Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "TCPBaseAlg.h"
00020 #include "TCP.h"
00021 #include "TCPSACKRexmitQueue.h"
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #define DELAYED_ACK_TIMEOUT 0.2 // 200ms (RFC 1122: MUST be less than 0.5 seconds)
00041 #define MAX_REXMIT_COUNT 12 // 12 retries
00042 #define MIN_REXMIT_TIMEOUT 1.0 // 1s
00043
00044 #define MAX_REXMIT_TIMEOUT 240 // 2*MSL (RFC 1122)
00045 #define MIN_PERSIST_TIMEOUT 5 // 5s
00046 #define MAX_PERSIST_TIMEOUT 60 // 60s
00047
00048 TCPBaseAlgStateVariables::TCPBaseAlgStateVariables()
00049 {
00050 rexmit_count = 0;
00051 rexmit_timeout = 3.0;
00052
00053 persist_factor = 0;
00054 persist_timeout = 5.0;
00055
00056 snd_cwnd = 0;
00057
00058 rtseq = 0;
00059 rtseq_sendtime = 0;
00060
00061
00062
00063 srtt = 0;
00064 rttvar = 3.0/4.0;
00065
00066 numRtos = 0;
00067
00068
00069
00070
00071 recover = iss;
00072 firstPartialACK = false;
00073 }
00074
00075 std::string TCPBaseAlgStateVariables::info() const
00076 {
00077 std::stringstream out;
00078 out << TCPStateVariables::info();
00079 out << " snd_cwnd=" << snd_cwnd;
00080 out << " rto=" << rexmit_timeout;
00081 return out.str();
00082 }
00083
00084 std::string TCPBaseAlgStateVariables::detailedInfo() const
00085 {
00086 std::stringstream out;
00087 out << TCPStateVariables::detailedInfo();
00088 out << "snd_cwnd = " << snd_cwnd << "\n";
00089 out << "rto = " << rexmit_timeout << "\n";
00090 out << "persist_timeout = " << persist_timeout << "\n";
00091
00092 return out.str();
00093 }
00094
00095 TCPBaseAlg::TCPBaseAlg() : TCPAlgorithm(),
00096 state((TCPBaseAlgStateVariables *&)TCPAlgorithm::state)
00097 {
00098 rexmitTimer = persistTimer = delayedAckTimer = keepAliveTimer = NULL;
00099 cwndVector = ssthreshVector = rttVector = srttVector = rttvarVector = rtoVector = numRtosVector = NULL;
00100 }
00101
00102 TCPBaseAlg::~TCPBaseAlg()
00103 {
00104
00105
00106
00107 if (rexmitTimer) delete cancelEvent(rexmitTimer);
00108 if (persistTimer) delete cancelEvent(persistTimer);
00109 if (delayedAckTimer) delete cancelEvent(delayedAckTimer);
00110 if (keepAliveTimer) delete cancelEvent(keepAliveTimer);
00111
00112
00113 delete cwndVector;
00114 delete ssthreshVector;
00115 delete rttVector;
00116 delete srttVector;
00117 delete rttvarVector;
00118 delete rtoVector;
00119 delete numRtosVector;
00120 }
00121
00122 void TCPBaseAlg::initialize()
00123 {
00124 TCPAlgorithm::initialize();
00125
00126 rexmitTimer = new cMessage("REXMIT");
00127 persistTimer = new cMessage("PERSIST");
00128 delayedAckTimer = new cMessage("DELAYEDACK");
00129 keepAliveTimer = new cMessage("KEEPALIVE");
00130
00131 rexmitTimer->setContextPointer(conn);
00132 persistTimer->setContextPointer(conn);
00133 delayedAckTimer->setContextPointer(conn);
00134 keepAliveTimer->setContextPointer(conn);
00135
00136 if (conn->getTcpMain()->recordStatistics)
00137 {
00138 cwndVector = new cOutVector("cwnd");
00139 ssthreshVector = new cOutVector("ssthresh");
00140 rttVector = new cOutVector("measured RTT");
00141 srttVector = new cOutVector("smoothed RTT");
00142 rttvarVector = new cOutVector("RTTVAR");
00143 rtoVector = new cOutVector("RTO");
00144 numRtosVector = new cOutVector("numRTOs");
00145 }
00146 }
00147
00148 void TCPBaseAlg::established(bool active)
00149 {
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 if (state->increased_IW_enabled && state->syn_rexmit_count==0)
00186 {
00187 state->snd_cwnd = std::min(4 * state->snd_mss, std::max(2 * state->snd_mss, (uint32)4380));
00188 tcpEV << "Enabled Increased Initial Window, CWND is set to: " << state->snd_cwnd << "\n";
00189 }
00190
00191
00192
00193 else
00194 state->snd_cwnd = state->snd_mss;
00195
00196 if (active)
00197 {
00198
00199 tcpEV << "Completing connection setup by sending ACK (possibly piggybacked on data)\n";
00200 if (!sendData())
00201 conn->sendAck();
00202 }
00203 }
00204
00205 void TCPBaseAlg::connectionClosed()
00206 {
00207 cancelEvent(rexmitTimer);
00208 cancelEvent(persistTimer);
00209 cancelEvent(delayedAckTimer);
00210 cancelEvent(keepAliveTimer);
00211 }
00212
00213 void TCPBaseAlg::processTimer(cMessage *timer, TCPEventCode& event)
00214 {
00215 if (timer==rexmitTimer)
00216 processRexmitTimer(event);
00217 else if (timer==persistTimer)
00218 processPersistTimer(event);
00219 else if (timer==delayedAckTimer)
00220 processDelayedAckTimer(event);
00221 else if (timer==keepAliveTimer)
00222 processKeepAliveTimer(event);
00223 else
00224 throw cRuntimeError(timer, "unrecognized timer");
00225 }
00226
00227 void TCPBaseAlg::processRexmitTimer(TCPEventCode& event)
00228 {
00229 tcpEV << "TCB: " << state->info() << "\n";
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 if (++state->rexmit_count > MAX_REXMIT_COUNT)
00243 {
00244 tcpEV << "Retransmission count exceeds " << MAX_REXMIT_COUNT << ", aborting connection\n";
00245 conn->signalConnectionTimeout();
00246 event = TCP_E_ABORT;
00247 return;
00248 }
00249
00250 tcpEV << "Performing retransmission #" << state->rexmit_count
00251 << "; increasing RTO from " << state->rexmit_timeout << "s ";
00252
00253
00254
00255
00256
00257
00258
00259
00260 state->rexmit_timeout += state->rexmit_timeout;
00261 if (state->rexmit_timeout > MAX_REXMIT_TIMEOUT)
00262 state->rexmit_timeout = MAX_REXMIT_TIMEOUT;
00263 conn->scheduleTimeout(rexmitTimer, state->rexmit_timeout);
00264
00265 tcpEV << " to " << state->rexmit_timeout << "s, and cancelling RTT measurement\n";
00266
00267
00268 state->rtseq_sendtime = 0;
00269
00270 state->numRtos++;
00271 if (numRtosVector)
00272 numRtosVector->record(state->numRtos);
00273
00274
00275 if (state->sack_enabled)
00276 {
00277 conn->rexmitQueue->resetSackedBit();
00278 conn->rexmitQueue->resetRexmittedBit();
00279
00280
00281
00282
00283
00284
00285
00286
00287 if (state->lossRecovery)
00288 {
00289 state->recoveryPoint = state->snd_max;
00290 tcpEV << "Loss Recovery terminated.\n";
00291 state->lossRecovery = false;
00292 }
00293 }
00294
00295 state->time_last_data_sent = simTime();
00296
00297
00298
00299
00300
00301
00302
00303
00304 }
00305
00306 void TCPBaseAlg::processPersistTimer(TCPEventCode& event)
00307 {
00308
00309
00310
00311
00312
00313
00314 if (state->persist_factor == 0)
00315 state->persist_factor++;
00316 else if (state->persist_factor < 64)
00317 state->persist_factor = state->persist_factor*2;
00318 state->persist_timeout = state->persist_factor * 1.5;
00319
00320
00321 if (state->persist_timeout < MIN_PERSIST_TIMEOUT)
00322 state->rexmit_timeout = MIN_PERSIST_TIMEOUT;
00323 if (state->persist_timeout > MAX_PERSIST_TIMEOUT)
00324 state->rexmit_timeout = MAX_PERSIST_TIMEOUT;
00325 conn->scheduleTimeout(persistTimer, state->persist_timeout);
00326
00327
00328 conn->sendProbe();
00329 }
00330
00331 void TCPBaseAlg::processDelayedAckTimer(TCPEventCode& event)
00332 {
00333 state->ack_now = true;
00334 conn->sendAck();
00335 }
00336
00337 void TCPBaseAlg::processKeepAliveTimer(TCPEventCode& event)
00338 {
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 }
00352
00353 void TCPBaseAlg::startRexmitTimer()
00354 {
00355
00356
00357 state->rexmit_count = 0;
00358
00359
00360 conn->scheduleTimeout(rexmitTimer, state->rexmit_timeout);
00361 }
00362
00363 void TCPBaseAlg::rttMeasurementComplete(simtime_t tSent, simtime_t tAcked)
00364 {
00365
00366
00367
00368
00369
00370
00371
00372
00373 const double g = 0.125;
00374 simtime_t newRTT = tAcked-tSent;
00375
00376 simtime_t& srtt = state->srtt;
00377 simtime_t& rttvar = state->rttvar;
00378
00379 simtime_t err = newRTT - srtt;
00380
00381 srtt += g*err;
00382 rttvar += g*(fabs(err) - rttvar);
00383
00384
00385 simtime_t rto = srtt + 4*rttvar;
00386 if (rto>MAX_REXMIT_TIMEOUT)
00387 rto = MAX_REXMIT_TIMEOUT;
00388 else if (rto<MIN_REXMIT_TIMEOUT)
00389 rto = MIN_REXMIT_TIMEOUT;
00390
00391 state->rexmit_timeout = rto;
00392
00393
00394 tcpEV << "Measured RTT=" << (newRTT*1000) << "ms, updated SRTT=" << (srtt*1000)
00395 << "ms, new RTO=" << (rto*1000) << "ms\n";
00396 if (rttVector) rttVector->record(newRTT);
00397 if (srttVector) srttVector->record(srtt);
00398 if (rttvarVector) rttvarVector->record(rttvar);
00399 if (rtoVector) rtoVector->record(rto);
00400 }
00401
00402 void TCPBaseAlg::rttMeasurementCompleteUsingTS(uint32 echoedTS)
00403 {
00404 ASSERT (state->ts_enabled);
00405
00406
00407 uint32 now = conn->convertSimtimeToTS(simTime());
00408 simtime_t tSent = conn->convertTSToSimtime(echoedTS);
00409 simtime_t tAcked = conn->convertTSToSimtime(now);
00410 rttMeasurementComplete(tSent, tAcked);
00411 }
00412
00413 bool TCPBaseAlg::sendData()
00414 {
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 bool fullSegmentsOnly = state->nagle_enabled && state->snd_una!=state->snd_max;
00426 if (fullSegmentsOnly)
00427 tcpEV << "Nagle is enabled and there's unacked data: only full segments will be sent\n";
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 if (!conn->isSendQueueEmpty())
00442 {
00443 if ((simTime() - state->time_last_data_sent) > state->rexmit_timeout)
00444 {
00445
00446 if (state->increased_IW_enabled)
00447 state->snd_cwnd = std::min (std::min (4 * state->snd_mss, std::max(2 * state->snd_mss, (uint32)4380)), state->snd_cwnd);
00448 else
00449 state->snd_cwnd = state->snd_mss;
00450 tcpEV << "Restarting idle connection, CWND is set to: " << state->snd_cwnd << "\n";
00451 }
00452 }
00453
00454
00455
00456
00457
00458 return conn->sendData(fullSegmentsOnly, state->snd_cwnd);
00459 }
00460
00461 void TCPBaseAlg::sendCommandInvoked()
00462 {
00463
00464 sendData();
00465 }
00466
00467 void TCPBaseAlg::receivedOutOfOrderSegment()
00468 {
00469 state->ack_now = true;
00470 tcpEV << "Out-of-order segment, sending immediate ACK\n";
00471 conn->sendAck();
00472 }
00473
00474 void TCPBaseAlg::receiveSeqChanged()
00475 {
00476
00477 if (state->full_sized_segment_counter == 0 && !state->ack_now && state->last_ack_sent == state->rcv_nxt && !delayedAckTimer->isScheduled())
00478 {
00479
00480 }
00481 else
00482 {
00483
00484
00485
00486
00487
00488
00489 if (state->lossRecovery)
00490 state->ack_now = true;
00491
00492 if (!state->delayed_acks_enabled)
00493 {
00494 tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", (delayed ACK disabled) sending ACK now\n";
00495 conn->sendAck();
00496 }
00497 else
00498 {
00499 if (state->ack_now)
00500 {
00501 tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", (delayed ACK enabled, but ack_now is set) sending ACK now\n";
00502 conn->sendAck();
00503 }
00504
00505 else if (state->full_sized_segment_counter >= 2)
00506 {
00507 tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", (delayed ACK enabled, but full_sized_segment_counter=" << state->full_sized_segment_counter << ") sending ACK now\n";
00508 conn->sendAck();
00509 }
00510 else
00511 {
00512 tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", (delayed ACK enabled and full_sized_segment_counter=" << state->full_sized_segment_counter << ") scheduling ACK\n";
00513 if (!delayedAckTimer->isScheduled())
00514 conn->scheduleTimeout(delayedAckTimer, DELAYED_ACK_TIMEOUT);
00515 }
00516 }
00517 }
00518 }
00519
00520 void TCPBaseAlg::receivedDataAck(uint32 firstSeqAcked)
00521 {
00522 if (!state->ts_enabled)
00523 {
00524
00525 if (state->rtseq_sendtime!=0 && seqLess(state->rtseq, state->snd_una))
00526 {
00527
00528 tcpEV << "Round-trip time measured on rtseq=" << state->rtseq << ": "
00529 << floor((simTime() - state->rtseq_sendtime)*1000+0.5) << "ms\n";
00530
00531 rttMeasurementComplete(state->rtseq_sendtime, simTime());
00532
00533
00534 state->rtseq_sendtime = 0;
00535 }
00536 }
00537
00538
00539
00540
00541
00542
00543 if (state->snd_una==state->snd_max)
00544 {
00545 if (rexmitTimer->isScheduled())
00546 {
00547 tcpEV << "ACK acks all outstanding segments, cancel REXMIT timer\n";
00548 cancelEvent(rexmitTimer);
00549 }
00550 else
00551 tcpEV << "There were no outstanding segments, nothing new in this ACK.\n";
00552 }
00553 else
00554 {
00555 tcpEV << "ACK acks some but not all outstanding segments ("
00556 << (state->snd_max - state->snd_una) << " bytes outstanding), "
00557 << "restarting REXMIT timer\n";
00558 cancelEvent(rexmitTimer);
00559 startRexmitTimer();
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 if (state->snd_wnd==0)
00572 {
00573 if (rexmitTimer->isScheduled())
00574 {
00575 if (persistTimer->isScheduled())
00576 {
00577 tcpEV << "Received zero-sized window and REXMIT timer is running therefore PERSIST timer is canceled.\n";
00578 cancelEvent(persistTimer);
00579 state->persist_factor = 0;
00580 }
00581 else
00582 tcpEV << "Received zero-sized window and REXMIT timer is running therefore PERSIST timer is not started.\n";
00583 }
00584 else
00585 {
00586 if (!persistTimer->isScheduled())
00587 {
00588 tcpEV << "Received zero-sized window therefore PERSIST timer is started.\n";
00589 conn->scheduleTimeout(persistTimer, state->persist_timeout);
00590 }
00591 else
00592 tcpEV << "Received zero-sized window and PERSIST timer is already running.\n";
00593 }
00594 }
00595 else
00596 {
00597 if (persistTimer->isScheduled())
00598 {
00599 tcpEV << "Received non zero-sized window therefore PERSIST timer is canceled.\n";
00600 cancelEvent(persistTimer);
00601 state->persist_factor = 0;
00602 }
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612 }
00613
00614 void TCPBaseAlg::receivedDuplicateAck()
00615 {
00616 tcpEV << "Duplicate ACK #" << state->dupacks << "\n";
00617
00618 bool fullSegmentsOnly = state->nagle_enabled && state->snd_una!=state->snd_max;
00619 if (state->dupacks < DUPTHRESH && state->limited_transmit_enabled)
00620 conn->sendOneNewSegment(fullSegmentsOnly, state->snd_cwnd);
00621
00622
00623
00624
00625
00626
00627
00628
00629 }
00630
00631 void TCPBaseAlg::receivedAckForDataNotYetSent(uint32 seq)
00632 {
00633
00634
00635
00636
00637
00638 tcpEV << "ACK acks something not yet sent, sending ACK\n";
00639 conn->sendAck();
00640 }
00641
00642 void TCPBaseAlg::ackSent()
00643 {
00644 state->full_sized_segment_counter = 0;
00645 state->ack_now = false;
00646 state->last_ack_sent = state->rcv_nxt;
00647
00648 if (delayedAckTimer->isScheduled())
00649 cancelEvent(delayedAckTimer);
00650 }
00651
00652 void TCPBaseAlg::dataSent(uint32 fromseq)
00653 {
00654
00655 if (!rexmitTimer->isScheduled())
00656 {
00657 tcpEV << "Starting REXMIT timer\n";
00658 startRexmitTimer();
00659 }
00660
00661 if (!state->ts_enabled)
00662 {
00663
00664 if (state->rtseq_sendtime==0)
00665 {
00666
00667 state->rtseq = fromseq;
00668 state->rtseq_sendtime = simTime();
00669 tcpEV << "Starting rtt measurement on seq=" << state->rtseq << "\n";
00670 }
00671 }
00672
00673 state->time_last_data_sent = simTime();
00674 }
00675
00676 void TCPBaseAlg::restartRexmitTimer()
00677 {
00678 if (rexmitTimer->isScheduled())
00679 cancelEvent(rexmitTimer);
00680 startRexmitTimer();
00681 }