|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2004 Andras Varga 00003 // Copyright (C) 2009-2010 Thomas Reschka 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public License 00016 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 #include "TCPBaseAlg.h" 00020 #include "TCP.h" 00021 #include "TCPSACKRexmitQueue.h" 00022 00023 00024 // 00025 // Some constants below. MIN_REXMIT_TIMEOUT is the minimum allowed retransmit 00026 // interval. It is currently one second but e.g. a FreeBSD kernel comment says 00027 // it "will ultimately be reduced to 3 ticks for algorithmic stability, 00028 // leaving the 200ms variance to deal with delayed-acks, protocol overheads. 00029 // A 1 second minimum badly breaks throughput on any network faster then 00030 // a modem that has minor but continuous packet loss unrelated to congestion, 00031 // such as on a wireless network." 00032 // 00033 // RFC 1122, page 95: 00034 // "A TCP SHOULD implement a delayed ACK, but an ACK should not 00035 // be excessively delayed; in particular, the delay MUST be 00036 // less than 0.5 seconds, and in a stream of full-sized 00037 // segments there SHOULD be an ACK for at least every second 00038 // segment." 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 //#define MIN_REXMIT_TIMEOUT 0.6 // 600ms (3 ticks) 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; // will be set to SMSS when connection is established 00057 00058 rtseq = 0; 00059 rtseq_sendtime = 0; 00060 00061 // Jacobson's alg: srtt must be initialized to 0, rttvar to a value which 00062 // will yield rto = 3s initially. 00063 srtt = 0; 00064 rttvar = 3.0/4.0; 00065 00066 numRtos = 0; 00067 00068 // RFC 3782, page 4: 00069 // "The algorithm specified in this document uses a variable "recover", 00070 // whose initial value is the initial send sequence number." 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 // TBD add others too 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 // Note: don't delete "state" here, it'll be deleted from TCPConnection 00105 00106 // cancel and delete timers 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 // delete statistics objects 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 // initialize cwnd (we may learn SMSS during connection setup) 00151 00152 // RFC 3390, page 2: "The upper bound for the initial window is given more precisely in 00153 // (1): 00154 // 00155 // min (4*MSS, max (2*MSS, 4380 bytes)) (1) 00156 // 00157 // Note: Sending a 1500 byte packet indicates a maximum segment size 00158 // (MSS) of 1460 bytes (assuming no IP or TCP options). Therefore, 00159 // limiting the initial window's MSS to 4380 bytes allows the sender to 00160 // transmit three segments initially in the common case when using 1500 00161 // byte packets. 00162 // 00163 // Equivalently, the upper bound for the initial window size is based on 00164 // the MSS, as follows: 00165 // 00166 // If (MSS <= 1095 bytes) 00167 // then win <= 4 * MSS; 00168 // If (1095 bytes < MSS < 2190 bytes) 00169 // then win <= 4380; 00170 // If (2190 bytes <= MSS) 00171 // then win <= 2 * MSS; 00172 // 00173 // This increased initial window is optional: a TCP MAY start with a 00174 // larger initial window. However, we expect that most general-purpose 00175 // TCP implementations would choose to use the larger initial congestion 00176 // window given in equation (1) above. 00177 // 00178 // This upper bound for the initial window size represents a change from 00179 // RFC 2581 [RFC2581], which specified that the congestion window be 00180 // initialized to one or two segments. 00181 // (...) 00182 // If the SYN or SYN/ACK is 00183 // lost, the initial window used by a sender after a correctly 00184 // transmitted SYN MUST be one segment consisting of MSS bytes." 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 // RFC 2001, page 3: 00191 // " 1. Initialization for a given connection sets cwnd to one segment 00192 // and ssthresh to 65535 bytes." 00193 else 00194 state->snd_cwnd = state->snd_mss; // RFC 2001 00195 00196 if (active) 00197 { 00198 // finish connection setup with ACK (possibly piggybacked on data) 00199 tcpEV << "Completing connection setup by sending ACK (possibly piggybacked on data)\n"; 00200 if (!sendData()) // FIXME TODO - This condition is never true because the buffer is empty (at this time) therefore the first ACK is never piggyback on data 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 // For any state if the retransmission timeout expires on a segment in 00233 // the retransmission queue, send the segment at the front of the 00234 // retransmission queue again, reinitialize the retransmission timer, 00235 // and return. 00236 //" 00237 // Also: abort connection after max 12 retries. 00238 // 00239 // However, retransmission is actually more complicated than that 00240 // in RFC 793 above, we'll leave it to subclasses (e.g. TCPTahoe, TCPReno). 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; // TBD maybe rather introduce a TCP_E_TIMEDOUT event 00247 return; 00248 } 00249 00250 tcpEV << "Performing retransmission #" << state->rexmit_count 00251 << "; increasing RTO from " << state->rexmit_timeout << "s "; 00252 00253 // 00254 // Karn's algorithm is implemented below: 00255 // (1) don't measure RTT for retransmitted packets. 00256 // (2) RTO should be doubled after retransmission ("exponential back-off") 00257 // 00258 00259 // restart the retransmission timer with twice the latest RTO value, or with the max, whichever is smaller 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 // cancel round-trip time measurement 00268 state->rtseq_sendtime = 0; 00269 00270 state->numRtos++; 00271 if (numRtosVector) 00272 numRtosVector->record(state->numRtos); 00273 00274 // if sacked_enabled reset sack related flags 00275 if (state->sack_enabled) 00276 { 00277 conn->rexmitQueue->resetSackedBit(); 00278 conn->rexmitQueue->resetRexmittedBit(); 00279 00280 // RFC 3517, page 8: "If an RTO occurs during loss recovery as specified in this document, 00281 // RecoveryPoint MUST be set to HighData. Further, the new value of 00282 // RecoveryPoint MUST be preserved and the loss recovery algorithm 00283 // outlined in this document MUST be terminated. In addition, a new 00284 // recovery phase (as described in section 5) MUST NOT be initiated 00285 // until HighACK is greater than or equal to the new value of 00286 // RecoveryPoint." 00287 if (state->lossRecovery) 00288 { 00289 state->recoveryPoint = state->snd_max; // HighData = 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 // Leave congestion window management and actual retransmission to 00299 // subclasses (e.g. TCPTahoe, TCPReno). 00300 // 00301 // That is, subclasses will redefine this method, call us, then perform 00302 // window adjustments and do the retransmission as they like. 00303 // 00304 } 00305 00306 void TCPBaseAlg::processPersistTimer(TCPEventCode& event) 00307 { 00308 // setup and restart the PERSIST timer 00309 // FIXME Calculation of PERSIST timer is not as simple as done here! 00310 // It depends on RTT calculations and is bounded to 5-60 seconds. 00311 // This simplified PERSIST timer calculation generates values 00312 // as presented in [Stevens, W.R.: TCP/IP Illustrated, Volume 1, chapter 22.2] 00313 // (5, 5, 6, 12, 24, 48, 60, 60, 60...) 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; // 1.5 is a factor for typical LAN connection [Stevens, W.R.: TCP/IP Ill. Vol. 1, chapter 22.2] 00319 00320 // PERSIST timer is bounded to 5-60 seconds 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 // sending persist probe 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 // TBD 00340 // RFC 1122, page 102: 00341 // "A "keep-alive" mechanism periodically probes the other 00342 // end of a connection when the connection is otherwise 00343 // idle, even when there is no data to be sent. The TCP 00344 // specification does not include a keep-alive mechanism 00345 // because it could: (1) cause perfectly good connections 00346 // to break during transient Internet failures; (2) 00347 // consume unnecessary bandwidth ("if no one is using the 00348 // connection, who cares if it is still good?"); and (3) 00349 // cost money for an Internet path that charges for 00350 // packets." 00351 } 00352 00353 void TCPBaseAlg::startRexmitTimer() 00354 { 00355 // start counting retransmissions for this seq number. 00356 // Note: state->rexmit_timeout is set from rttMeasurementComplete(). 00357 state->rexmit_count = 0; 00358 00359 // schedule timer 00360 conn->scheduleTimeout(rexmitTimer, state->rexmit_timeout); 00361 } 00362 00363 void TCPBaseAlg::rttMeasurementComplete(simtime_t tSent, simtime_t tAcked) 00364 { 00365 // 00366 // Jacobson's algorithm for estimating RTT and adaptively setting RTO. 00367 // 00368 // Note: this implementation calculates in doubles. An impl. which uses 00369 // 500ms ticks is available from old tcpmodule.cc:calcRetransTimer(). 00370 // 00371 00372 // update smoothed RTT estimate (srtt) and variance (rttvar) 00373 const double g = 0.125; // 1/8; (1-alpha) where alpha=7/8; 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 // assign RTO (here: rexmit_timeout) a new value 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 // record statistics 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 // Note: The TS option is using uint32 values (ms precision) therefore we convert the current simTime also to a uint32 value (ms precision) 00406 // and then convert back to simtime_t to use rttMeasurementComplete() to update srtt and rttvar 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 // Nagle's algorithm: when a TCP connection has outstanding data that has not 00417 // yet been acknowledged, small segments cannot be sent until the outstanding 00418 // data is acknowledged. (In this case, small amounts of data are collected 00419 // by TCP and sent in a single segment.) 00420 // 00421 // FIXME there's also something like this: can still send if 00422 // "b) a segment that can be sent is at least half the size of 00423 // the largest window ever advertised by the receiver" 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 // RFC 2581, pages 7 and 8: "When TCP has not received a segment for 00430 // more than one retransmission timeout, cwnd is reduced to the value 00431 // of the restart window (RW) before transmission begins. 00432 // For the purposes of this standard, we define RW = IW. 00433 // (...) 00434 // Using the last time a segment was received to determine whether or 00435 // not to decrease cwnd fails to deflate cwnd in the common case of 00436 // persistent HTTP connections [HTH98]. 00437 // (...) 00438 // Therefore, a TCP SHOULD set cwnd to no more than RW before beginning 00439 // transmission if the TCP has not sent data in an interval exceeding 00440 // the retransmission timeout." 00441 if (!conn->isSendQueueEmpty()) // do we have any data to send? 00442 { 00443 if ((simTime() - state->time_last_data_sent) > state->rexmit_timeout) 00444 { 00445 // RFC 5681, page 11: "For the purposes of this standard, we define RW = min(IW,cwnd)." 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 // Send window is effectively the minimum of the congestion window (cwnd) 00456 // and the advertised window (snd_wnd). 00457 // 00458 return conn->sendData(fullSegmentsOnly, state->snd_cwnd); 00459 } 00460 00461 void TCPBaseAlg::sendCommandInvoked() 00462 { 00463 // try sending 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 // If we send a data segment already (with the updated seqNo) there is no need to send an additional ACK 00477 if (state->full_sized_segment_counter == 0 && !state->ack_now && state->last_ack_sent == state->rcv_nxt && !delayedAckTimer->isScheduled()) // ackSent? 00478 { 00479 // tcpEV << "ACK has already been sent (possibly piggybacked on data)\n"; 00480 } 00481 else 00482 { 00483 // RFC 2581, page 6: 00484 // "3.2 Fast Retransmit/Fast Recovery 00485 // (...) 00486 // In addition, a TCP receiver SHOULD send an immediate ACK 00487 // when the incoming segment fills in all or part of a gap in the 00488 // sequence space." 00489 if (state->lossRecovery) 00490 state->ack_now = true; // although not mentioned in [Stevens, W.R.: TCP/IP Illustrated, Volume 2, page 861] seems like we have to set ack_now 00491 00492 if (!state->delayed_acks_enabled) // delayed ACK disabled 00493 { 00494 tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", (delayed ACK disabled) sending ACK now\n"; 00495 conn->sendAck(); 00496 } 00497 else // delayed ACK enabled 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 // RFC 1122, page 96: "in a stream of full-sized segments there SHOULD be an ACK for at least every second segment." 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()) // schedule delayed ACK timer if not already running 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 // if round-trip time measurement is running, check if rtseq has been acked 00525 if (state->rtseq_sendtime!=0 && seqLess(state->rtseq, state->snd_una)) 00526 { 00527 // print value 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()); // update RTT variables with new value 00532 00533 // measurement finished 00534 state->rtseq_sendtime = 0; 00535 } 00536 } 00537 00538 // 00539 // handling of retransmission timer: if the ACK is for the last segment sent 00540 // (no data in flight), cancel the timer, otherwise restart the timer 00541 // with the current RTO value. 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 // handling of PERSIST timer: 00564 // If data sender received a zero-sized window, check retransmission timer. 00565 // If retransmission timer is not scheduled, start PERSIST timer if not already 00566 // running. 00567 // 00568 // If data sender received a non zero-sized window, check PERSIST timer. 00569 // If PERSIST timer is scheduled, cancel PERSIST timer. 00570 // 00571 if (state->snd_wnd==0) // received zero-sized window? 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 // received non zero-sized window? 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 // Leave congestion window management and possible sending data to 00607 // subclasses (e.g. TCPTahoe, TCPReno). 00608 // 00609 // That is, subclasses will redefine this method, call us, then perform 00610 // window adjustments and send data (if there's room in the window). 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) // DUPTRESH = 3 00620 conn->sendOneNewSegment(fullSegmentsOnly, state->snd_cwnd); // RFC 3042 00621 00622 // 00623 // Leave to subclasses (e.g. TCPTahoe, TCPReno) whatever they want to do 00624 // on duplicate Acks. 00625 // 00626 // That is, subclasses will redefine this method, call us, then perform 00627 // whatever action they want to do on dupAcks (e.g. retransmitting one segment). 00628 // 00629 } 00630 00631 void TCPBaseAlg::receivedAckForDataNotYetSent(uint32 seq) 00632 { 00633 // Note: In this case no immediate ACK will be send because not mentioned 00634 // in [Stevens, W.R.: TCP/IP Illustrated, Volume 2, page 861]. 00635 // To force immediate ACK use: 00636 // state->ack_now = true; 00637 // tcpEV << "ACK acks something not yet sent, sending immediate ACK\n"; 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; // reset counter 00645 state->ack_now = false; // reset flag 00646 state->last_ack_sent = state->rcv_nxt; // update last_ack_sent, needed for TS option 00647 // if delayed ACK timer is running, cancel it 00648 if (delayedAckTimer->isScheduled()) 00649 cancelEvent(delayedAckTimer); 00650 } 00651 00652 void TCPBaseAlg::dataSent(uint32 fromseq) 00653 { 00654 // if retransmission timer not running, schedule it 00655 if (!rexmitTimer->isScheduled()) 00656 { 00657 tcpEV << "Starting REXMIT timer\n"; 00658 startRexmitTimer(); 00659 } 00660 00661 if (!state->ts_enabled) 00662 { 00663 // start round-trip time measurement (if not already running) 00664 if (state->rtseq_sendtime==0) 00665 { 00666 // remember this sequence number and when it was sent 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 }