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 #include "TCPBaseAlg_old.h"
00019 #include "TCP_old.h"
00020
00021 using namespace tcp_old;
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #define DELAYED_ACK_TIMEOUT 0.2 // 200ms
00033 #define MAX_REXMIT_COUNT 12 // 12 retries
00034 #define MIN_REXMIT_TIMEOUT 1.0 // 1s
00035
00036 #define MAX_REXMIT_TIMEOUT 240 // 2*MSL (RFC1122)
00037
00038
00039
00040 TCPBaseAlgStateVariables::TCPBaseAlgStateVariables()
00041 {
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 delayed_acks_enabled = false;
00054
00055 nagle_enabled = true;
00056
00057 rexmit_count = 0;
00058 rexmit_timeout = 3.0;
00059
00060 snd_cwnd = 0;
00061
00062 rtseq = 0;
00063 rtseq_sendtime = 0;
00064
00065
00066
00067 srtt = 0;
00068 rttvar = 3.0/4.0;
00069 }
00070
00071 std::string TCPBaseAlgStateVariables::info() const
00072 {
00073 std::stringstream out;
00074 out << TCPStateVariables::info();
00075 out << " snd_cwnd=" << snd_cwnd;
00076 out << " rto=" << rexmit_timeout;
00077 return out.str();
00078 }
00079
00080 std::string TCPBaseAlgStateVariables::detailedInfo() const
00081 {
00082 std::stringstream out;
00083 out << TCPStateVariables::detailedInfo();
00084 out << "snd_cwnd = " << snd_cwnd << "\n";
00085 out << "rto = " << rexmit_timeout << "\n";
00086
00087 return out.str();
00088 }
00089
00090 TCPBaseAlg::TCPBaseAlg() : TCPAlgorithm(),
00091 state((TCPBaseAlgStateVariables *&)TCPAlgorithm::state)
00092 {
00093 rexmitTimer = persistTimer = delayedAckTimer = keepAliveTimer = NULL;
00094 cwndVector = ssthreshVector = rttVector = srttVector = rttvarVector = rtoVector = NULL;
00095 }
00096
00097 TCPBaseAlg::~TCPBaseAlg()
00098 {
00099
00100
00101
00102 if (rexmitTimer) delete cancelEvent(rexmitTimer);
00103 if (persistTimer) delete cancelEvent(persistTimer);
00104 if (delayedAckTimer) delete cancelEvent(delayedAckTimer);
00105 if (keepAliveTimer) delete cancelEvent(keepAliveTimer);
00106
00107
00108 delete cwndVector;
00109 delete ssthreshVector;
00110 delete rttVector;
00111 delete srttVector;
00112 delete rttvarVector;
00113 delete rtoVector;
00114 }
00115
00116 void TCPBaseAlg::initialize()
00117 {
00118 TCPAlgorithm::initialize();
00119
00120 rexmitTimer = new cMessage("REXMIT");
00121 persistTimer = new cMessage("PERSIST");
00122 delayedAckTimer = new cMessage("DELAYEDACK");
00123 keepAliveTimer = new cMessage("KEEPALIVE");
00124
00125 rexmitTimer->setContextPointer(conn);
00126 persistTimer->setContextPointer(conn);
00127 delayedAckTimer->setContextPointer(conn);
00128 keepAliveTimer->setContextPointer(conn);
00129
00130 if (conn->getTcpMain()->recordStatistics)
00131 {
00132 cwndVector = new cOutVector("cwnd");
00133 ssthreshVector = new cOutVector("ssthresh");
00134 rttVector = new cOutVector("measured RTT");
00135 srttVector = new cOutVector("smoothed RTT");
00136 rttvarVector = new cOutVector("RTTVAR");
00137 rtoVector = new cOutVector("RTO");
00138 }
00139 }
00140
00141 void TCPBaseAlg::established(bool active)
00142 {
00143
00144
00145 state->snd_cwnd = state->snd_mss;
00146 if (cwndVector) cwndVector->record(state->snd_cwnd);
00147
00148 if (active)
00149 {
00150
00151 tcpEV << "Completing connection setup by sending ACK (possibly piggybacked on data)\n";
00152 if (!sendData())
00153 conn->sendAck();
00154 }
00155 }
00156
00157 void TCPBaseAlg::connectionClosed()
00158 {
00159 cancelEvent(rexmitTimer);
00160 cancelEvent(persistTimer);
00161 cancelEvent(delayedAckTimer);
00162 cancelEvent(keepAliveTimer);
00163 }
00164
00165 void TCPBaseAlg::processTimer(cMessage *timer, TCPEventCode& event)
00166 {
00167 if (timer==rexmitTimer)
00168 processRexmitTimer(event);
00169 else if (timer==persistTimer)
00170 processPersistTimer(event);
00171 else if (timer==delayedAckTimer)
00172 processDelayedAckTimer(event);
00173 else if (timer==keepAliveTimer)
00174 processKeepAliveTimer(event);
00175 else
00176 throw cRuntimeError(timer, "unrecognized timer");
00177 }
00178
00179 void TCPBaseAlg::processRexmitTimer(TCPEventCode& event)
00180 {
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 if (++state->rexmit_count > MAX_REXMIT_COUNT)
00193 {
00194 tcpEV << "Retransmission count exceeds " << MAX_REXMIT_COUNT << ", aborting connection\n";
00195 conn->signalConnectionTimeout();
00196 event = TCP_E_ABORT;
00197 return;
00198 }
00199
00200 tcpEV << "Performing retransmission #" << state->rexmit_count
00201 << "; increasing RTO from " << state->rexmit_timeout << "s ";
00202
00203
00204
00205
00206
00207
00208
00209
00210 state->rexmit_timeout += state->rexmit_timeout;
00211 if (state->rexmit_timeout > MAX_REXMIT_TIMEOUT)
00212 state->rexmit_timeout = MAX_REXMIT_TIMEOUT;
00213 conn->scheduleTimeout(rexmitTimer, state->rexmit_timeout);
00214
00215 tcpEV << " to " << state->rexmit_timeout << "s, and cancelling RTT measurement\n";
00216
00217
00218 state->rtseq_sendtime = 0;
00219
00220
00221
00222
00223
00224
00225
00226
00227 }
00228
00229 void TCPBaseAlg::processPersistTimer(TCPEventCode& event)
00230 {
00231
00232 conn->sendProbe();
00233 }
00234
00235 void TCPBaseAlg::processDelayedAckTimer(TCPEventCode& event)
00236 {
00237 conn->sendAck();
00238 }
00239
00240 void TCPBaseAlg::processKeepAliveTimer(TCPEventCode& event)
00241 {
00242
00243 }
00244
00245 void TCPBaseAlg::startRexmitTimer()
00246 {
00247
00248
00249 state->rexmit_count = 0;
00250
00251
00252 conn->scheduleTimeout(rexmitTimer, state->rexmit_timeout);
00253 }
00254
00255 void TCPBaseAlg::rttMeasurementComplete(simtime_t tSent, simtime_t tAcked)
00256 {
00257
00258
00259
00260
00261
00262
00263
00264
00265 const double g = 0.125;
00266 simtime_t newRTT = tAcked-tSent;
00267
00268 simtime_t& srtt = state->srtt;
00269 simtime_t& rttvar = state->rttvar;
00270
00271 simtime_t err = newRTT - srtt;
00272
00273 srtt += g*err;
00274 rttvar += g*(fabs(err) - rttvar);
00275
00276
00277 simtime_t rto = srtt + 4*rttvar;
00278 if (rto>MAX_REXMIT_TIMEOUT)
00279 rto = MAX_REXMIT_TIMEOUT;
00280 else if (rto<MIN_REXMIT_TIMEOUT)
00281 rto = MIN_REXMIT_TIMEOUT;
00282
00283 state->rexmit_timeout = rto;
00284
00285
00286 tcpEV << "Measured RTT=" << (newRTT*1000) << "ms, updated SRTT=" << (srtt*1000)
00287 << "ms, new RTO=" << (rto*1000) << "ms\n";
00288 if (rttVector) rttVector->record(newRTT);
00289 if (srttVector) srttVector->record(srtt);
00290 if (rttvarVector) rttvarVector->record(rttvar);
00291 if (rtoVector) rtoVector->record(rto);
00292 }
00293
00294 bool TCPBaseAlg::sendData()
00295 {
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 bool fullSegmentsOnly = state->nagle_enabled && state->snd_una!=state->snd_max;
00307 if (fullSegmentsOnly)
00308 tcpEV << "Nagle is enabled and there's unacked data: only full segments will be sent\n";
00309
00310
00311
00312
00313
00314 return conn->sendData(fullSegmentsOnly, state->snd_cwnd);
00315 }
00316
00317 void TCPBaseAlg::sendCommandInvoked()
00318 {
00319
00320 sendData();
00321 }
00322
00323 void TCPBaseAlg::receivedOutOfOrderSegment()
00324 {
00325 tcpEV << "Out-of-order segment, sending immediate ACK\n";
00326 conn->sendAck();
00327 }
00328
00329 void TCPBaseAlg::receiveSeqChanged()
00330 {
00331
00332 if (state->last_ack_sent == state->rcv_nxt && !delayedAckTimer->isScheduled())
00333 {
00334
00335 }
00336 else
00337 {
00338
00339 if (!state->delayed_acks_enabled)
00340 {
00341 tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", sending ACK now (delayed ACKs are disabled)\n";
00342 conn->sendAck();
00343 }
00344 else
00345 {
00346
00347
00348 tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", scheduling ACK\n";
00349 if (!delayedAckTimer->isScheduled())
00350 conn->scheduleTimeout(delayedAckTimer, DELAYED_ACK_TIMEOUT);
00351 }
00352 }
00353 }
00354
00355 void TCPBaseAlg::receivedDataAck(uint32 firstSeqAcked)
00356 {
00357
00358 if (state->rtseq_sendtime!=0 && seqLess(state->rtseq, state->snd_una))
00359 {
00360
00361 tcpEV << "Round-trip time measured on rtseq=" << state->rtseq << ": "
00362 << floor((simTime() - state->rtseq_sendtime)*1000+0.5) << "ms\n";
00363
00364
00365 rttMeasurementComplete(state->rtseq_sendtime, simTime());
00366
00367
00368 state->rtseq_sendtime = 0;
00369 }
00370
00371
00372
00373
00374
00375
00376 if (state->snd_una==state->snd_max)
00377 {
00378 if (rexmitTimer->isScheduled())
00379 {
00380 tcpEV << "ACK acks all outstanding segments, cancel REXMIT timer\n";
00381 cancelEvent(rexmitTimer);
00382 }
00383 else
00384 {
00385 tcpEV << "There were no outstanding segments, nothing new in this ACK.\n";
00386 }
00387 }
00388 else
00389 {
00390 tcpEV << "ACK acks some but not all outstanding segments ("
00391 << (state->snd_max - state->snd_una) << " bytes outstanding), "
00392 << "restarting REXMIT timer\n";
00393 cancelEvent(rexmitTimer);
00394 startRexmitTimer();
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404 }
00405
00406 void TCPBaseAlg::receivedDuplicateAck()
00407 {
00408 tcpEV << "Duplicate ACK #" << state->dupacks << "\n";
00409
00410
00411
00412
00413
00414
00415
00416
00417 }
00418
00419 void TCPBaseAlg::receivedAckForDataNotYetSent(uint32 seq)
00420 {
00421 tcpEV << "ACK acks something not yet sent, sending immediate ACK\n";
00422 conn->sendAck();
00423 }
00424
00425 void TCPBaseAlg::ackSent()
00426 {
00427 state->last_ack_sent = state->rcv_nxt;
00428
00429 if (delayedAckTimer->isScheduled())
00430 cancelEvent(delayedAckTimer);
00431 }
00432
00433 void TCPBaseAlg::dataSent(uint32 fromseq)
00434 {
00435
00436 if (!rexmitTimer->isScheduled())
00437 {
00438 tcpEV << "Starting REXMIT timer\n";
00439 startRexmitTimer();
00440 }
00441
00442
00443 if (state->rtseq_sendtime==0)
00444 {
00445
00446 state->rtseq = fromseq;
00447 state->rtseq_sendtime = simTime();
00448 tcpEV << "Starting rtt measurement on seq=" << state->rtseq << "\n";
00449 }
00450 }
00451
00452 void TCPBaseAlg::restartRexmitTimer()
00453 {
00454 if (rexmitTimer->isScheduled())
00455 cancelEvent(rexmitTimer);
00456 startRexmitTimer();
00457 }
00458
00459