flavours/TCPBaseAlg.cc

Go to the documentation of this file.
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 }