#include <TCPBaseAlg_old.h>
Public Member Functions | |
TCPBaseAlg () | |
virtual | ~TCPBaseAlg () |
virtual void | initialize () |
virtual void | established (bool active) |
virtual void | connectionClosed () |
virtual void | processTimer (cMessage *timer, TCPEventCode &event) |
virtual void | sendCommandInvoked () |
virtual void | receivedOutOfOrderSegment () |
virtual void | receiveSeqChanged () |
virtual void | receivedDataAck (uint32 firstSeqAcked) |
virtual void | receivedDuplicateAck () |
virtual void | receivedAckForDataNotYetSent (uint32 seq) |
virtual void | ackSent () |
virtual void | dataSent (uint32 fromseq) |
virtual void | restartRexmitTimer () |
Protected Member Functions | |
virtual void | startRexmitTimer () |
virtual void | rttMeasurementComplete (simtime_t tSent, simtime_t tAcked) |
virtual bool | sendData () |
cMessage * | cancelEvent (cMessage *msg) |
Process REXMIT, PERSIST, DELAYED-ACK and KEEP-ALIVE timers | |
virtual void | processRexmitTimer (TCPEventCode &event) |
virtual void | processPersistTimer (TCPEventCode &event) |
virtual void | processDelayedAckTimer (TCPEventCode &event) |
virtual void | processKeepAliveTimer (TCPEventCode &event) |
Protected Attributes | |
TCPBaseAlgStateVariables *& | state |
cMessage * | rexmitTimer |
cMessage * | persistTimer |
cMessage * | delayedAckTimer |
cMessage * | keepAliveTimer |
cOutVector * | cwndVector |
cOutVector * | ssthreshVector |
cOutVector * | rttVector |
cOutVector * | srttVector |
cOutVector * | rttvarVector |
cOutVector * | rtoVector |
Includes basic TCP algorithms: adaptive retransmission, persist timer, keep-alive, delayed acks -- EXCLUDING congestion control. Congestion control is implemented in subclasses such as TCPTahoeAlg or TCPRenoAlg.
Implements:
To be done:
Note: currently the timers and time calculations are done in double and NOT in Unix (200ms or 500ms) ticks. It's possible to write another TCPAlgorithm which uses ticks (or rather, factor out timer handling to separate methods, and redefine only those).
Congestion window is set to MSS when the connection is established, and not touched after that. Subclasses may redefine any of the virtual functions here to add their congestion control code.
Definition at line 89 of file TCPBaseAlg_old.h.
TCPBaseAlg::TCPBaseAlg | ( | ) |
Ctor.
Definition at line 90 of file old/flavours/TCPBaseAlg.cc.
: TCPAlgorithm(), state((TCPBaseAlgStateVariables *&)TCPAlgorithm::state) { rexmitTimer = persistTimer = delayedAckTimer = keepAliveTimer = NULL; cwndVector = ssthreshVector = rttVector = srttVector = rttvarVector = rtoVector = NULL; }
TCPBaseAlg::~TCPBaseAlg | ( | ) | [virtual] |
Virtual dtor.
Definition at line 97 of file old/flavours/TCPBaseAlg.cc.
{ // Note: don't delete "state" here, it'll be deleted from TCPConnection // cancel and delete timers if (rexmitTimer) delete cancelEvent(rexmitTimer); if (persistTimer) delete cancelEvent(persistTimer); if (delayedAckTimer) delete cancelEvent(delayedAckTimer); if (keepAliveTimer) delete cancelEvent(keepAliveTimer); // delete statistics objects delete cwndVector; delete ssthreshVector; delete rttVector; delete srttVector; delete rttvarVector; delete rtoVector; }
void TCPBaseAlg::ackSent | ( | ) | [virtual] |
Called after we sent an ACK. This hook can be used to cancel the delayed-ACK timer.
Implements tcp_old::TCPAlgorithm.
Definition at line 425 of file old/flavours/TCPBaseAlg.cc.
{ state->last_ack_sent = state->rcv_nxt; // if delayed ACK timer is running, cancel it if (delayedAckTimer->isScheduled()) cancelEvent(delayedAckTimer); }
cMessage* tcp_old::TCPBaseAlg::cancelEvent | ( | cMessage * | msg | ) | [inline, protected] |
Utility function
Definition at line 133 of file TCPBaseAlg_old.h.
Referenced by ackSent(), connectionClosed(), receivedDataAck(), restartRexmitTimer(), and ~TCPBaseAlg().
{return conn->getTcpMain()->cancelEvent(msg);}
void TCPBaseAlg::connectionClosed | ( | ) | [virtual] |
Called when the connection closes, it should cancel all running timers.
Implements tcp_old::TCPAlgorithm.
Definition at line 157 of file old/flavours/TCPBaseAlg.cc.
void TCPBaseAlg::dataSent | ( | uint32 | fromseq | ) | [virtual] |
Called after we sent data. This hook can be used to schedule the retransmission timer, to start round-trip time measurement, etc. The argument is the seqno of the first byte sent.
Implements tcp_old::TCPAlgorithm.
Definition at line 433 of file old/flavours/TCPBaseAlg.cc.
{ // if retransmission timer not running, schedule it if (!rexmitTimer->isScheduled()) { tcpEV << "Starting REXMIT timer\n"; startRexmitTimer(); } // start round-trip time measurement (if not already running) if (state->rtseq_sendtime==0) { // remember this sequence number and when it was sent state->rtseq = fromseq; state->rtseq_sendtime = simTime(); tcpEV << "Starting rtt measurement on seq=" << state->rtseq << "\n"; } }
void TCPBaseAlg::established | ( | bool | active | ) | [virtual] |
Called when the connection is going to ESTABLISHED from SYN_SENT or SYN_RCVD. This is a place to initialize some variables (e.g. set cwnd to the MSS learned during connection setup). If we are on the active side, here we also have to finish the 3-way connection setup procedure by sending an ACK, possibly piggybacked on data.
Implements tcp_old::TCPAlgorithm.
Definition at line 141 of file old/flavours/TCPBaseAlg.cc.
{ // initialize cwnd (we may learn MSS during connection setup -- // this (MSS TCP option) is not implemented yet though) state->snd_cwnd = state->snd_mss; if (cwndVector) cwndVector->record(state->snd_cwnd); if (active) { // finish connection setup with ACK (possibly piggybacked on data) tcpEV << "Completing connection setup by sending ACK (possibly piggybacked on data)\n"; if (!sendData()) conn->sendAck(); } }
void TCPBaseAlg::initialize | ( | ) | [virtual] |
Create timers, etc.
Reimplemented from tcp_old::TCPAlgorithm.
Reimplemented in tcp_old::TCPNoCongestionControl.
Definition at line 116 of file old/flavours/TCPBaseAlg.cc.
{ TCPAlgorithm::initialize(); rexmitTimer = new cMessage("REXMIT"); persistTimer = new cMessage("PERSIST"); delayedAckTimer = new cMessage("DELAYEDACK"); keepAliveTimer = new cMessage("KEEPALIVE"); rexmitTimer->setContextPointer(conn); persistTimer->setContextPointer(conn); delayedAckTimer->setContextPointer(conn); keepAliveTimer->setContextPointer(conn); if (conn->getTcpMain()->recordStatistics) { cwndVector = new cOutVector("cwnd"); ssthreshVector = new cOutVector("ssthresh"); rttVector = new cOutVector("measured RTT"); srttVector = new cOutVector("smoothed RTT"); rttvarVector = new cOutVector("RTTVAR"); rtoVector = new cOutVector("RTO"); } }
void TCPBaseAlg::processDelayedAckTimer | ( | TCPEventCode & | event | ) | [protected, virtual] |
Definition at line 235 of file old/flavours/TCPBaseAlg.cc.
Referenced by processTimer().
void TCPBaseAlg::processKeepAliveTimer | ( | TCPEventCode & | event | ) | [protected, virtual] |
Definition at line 240 of file old/flavours/TCPBaseAlg.cc.
Referenced by processTimer().
{
// FIXME TBD
}
void TCPBaseAlg::processPersistTimer | ( | TCPEventCode & | event | ) | [protected, virtual] |
Definition at line 229 of file old/flavours/TCPBaseAlg.cc.
Referenced by processTimer().
void TCPBaseAlg::processRexmitTimer | ( | TCPEventCode & | event | ) | [protected, virtual] |
Reimplemented in tcp_old::TCPNoCongestionControl, tcp_old::TCPReno, and tcp_old::TCPTahoe.
Definition at line 179 of file old/flavours/TCPBaseAlg.cc.
Referenced by processTimer().
{ //" // For any state if the retransmission timeout expires on a segment in // the retransmission queue, send the segment at the front of the // retransmission queue again, reinitialize the retransmission timer, // and return. //" // Also: abort connection after max 12 retries. // // However, retransmission is actually more complicated than that // in RFC 793 above, we'll leave it to subclasses (e.g. TCPTahoe, TCPReno). // if (++state->rexmit_count > MAX_REXMIT_COUNT) { tcpEV << "Retransmission count exceeds " << MAX_REXMIT_COUNT << ", aborting connection\n"; conn->signalConnectionTimeout(); event = TCP_E_ABORT; // TBD maybe rather introduce a TCP_E_TIMEDOUT event return; } tcpEV << "Performing retransmission #" << state->rexmit_count << "; increasing RTO from " << state->rexmit_timeout << "s "; // // Karn's algorithm is implemented below: // (1) don't measure RTT for retransmitted packets. // (2) RTO should be doubled after retransmission ("exponential back-off") // // restart the retransmission timer with twice the latest RTO value, or with the max, whichever is smaller state->rexmit_timeout += state->rexmit_timeout; if (state->rexmit_timeout > MAX_REXMIT_TIMEOUT) state->rexmit_timeout = MAX_REXMIT_TIMEOUT; conn->scheduleTimeout(rexmitTimer, state->rexmit_timeout); tcpEV << " to " << state->rexmit_timeout << "s, and cancelling RTT measurement\n"; // cancel round-trip time measurement state->rtseq_sendtime = 0; // // Leave congestion window management and actual retransmission to // subclasses (e.g. TCPTahoe, TCPReno). // // That is, subclasses will redefine this method, call us, then perform // window adjustments and do the retransmission as they like. // }
void TCPBaseAlg::processTimer | ( | cMessage * | timer, | |
TCPEventCode & | event | |||
) | [virtual] |
Process REXMIT, PERSIST, DELAYED-ACK and KEEP-ALIVE timers.
Implements tcp_old::TCPAlgorithm.
Definition at line 165 of file old/flavours/TCPBaseAlg.cc.
{ if (timer==rexmitTimer) processRexmitTimer(event); else if (timer==persistTimer) processPersistTimer(event); else if (timer==delayedAckTimer) processDelayedAckTimer(event); else if (timer==keepAliveTimer) processKeepAliveTimer(event); else throw cRuntimeError(timer, "unrecognized timer"); }
void TCPBaseAlg::receivedAckForDataNotYetSent | ( | uint32 | seq | ) | [virtual] |
Called after we received an ACK for data not yet sent. According to RFC 793 this function should send an ACK.
Implements tcp_old::TCPAlgorithm.
Definition at line 419 of file old/flavours/TCPBaseAlg.cc.
void TCPBaseAlg::receivedDataAck | ( | uint32 | firstSeqAcked | ) | [virtual] |
Called after we received an ACK which acked some data (that is, we could advance snd_una). At this point the state variables (snd_una, snd_wnd) have already been updated. The argument firstSeqAcked is the previous snd_una value, that is, the number of bytes acked is (snd_una-firstSeqAcked). The dupack counter still reflects the old value (needed for Reno and NewReno); it'll be reset to 0 after this call returns.
Implements tcp_old::TCPAlgorithm.
Reimplemented in tcp_old::TCPNoCongestionControl, tcp_old::TCPReno, and tcp_old::TCPTahoe.
Definition at line 355 of file old/flavours/TCPBaseAlg.cc.
{ // if round-trip time measurement is running, check if rtseq has been acked if (state->rtseq_sendtime!=0 && seqLess(state->rtseq, state->snd_una)) { // print value tcpEV << "Round-trip time measured on rtseq=" << state->rtseq << ": " << floor((simTime() - state->rtseq_sendtime)*1000+0.5) << "ms\n"; // update RTT variables with new value rttMeasurementComplete(state->rtseq_sendtime, simTime()); // measurement finished state->rtseq_sendtime = 0; } // // handling of retransmission timer: if the ACK is for the last segment sent // (no data in flight), cancel the timer, otherwise restart the timer // with the current RTO value. // if (state->snd_una==state->snd_max) { if (rexmitTimer->isScheduled()) { tcpEV << "ACK acks all outstanding segments, cancel REXMIT timer\n"; cancelEvent(rexmitTimer); } else { tcpEV << "There were no outstanding segments, nothing new in this ACK.\n"; } } else { tcpEV << "ACK acks some but not all outstanding segments (" << (state->snd_max - state->snd_una) << " bytes outstanding), " << "restarting REXMIT timer\n"; cancelEvent(rexmitTimer); startRexmitTimer(); } // // Leave congestion window management and possible sending data to // subclasses (e.g. TCPTahoe, TCPReno). // // That is, subclasses will redefine this method, call us, then perform // window adjustments and send data (if there's room in the window). // }
void TCPBaseAlg::receivedDuplicateAck | ( | ) | [virtual] |
Called after we received a duplicate ACK (that is: ackNo==snd_una, no data in segment, segment doesn't carry window update, and also, we have unacked data). The dupack counter got already updated when calling this method (i.e. dupack==1 on first duplicate ACK.)
Implements tcp_old::TCPAlgorithm.
Reimplemented in tcp_old::TCPReno, and tcp_old::TCPTahoe.
Definition at line 406 of file old/flavours/TCPBaseAlg.cc.
{ tcpEV << "Duplicate ACK #" << state->dupacks << "\n"; // // Leave to subclasses (e.g. TCPTahoe, TCPReno) whatever they want to do // on duplicate Acks. // // That is, subclasses will redefine this method, call us, then perform // whatever action they want to do on dupAcks (e.g. retransmitting one segment). // }
void TCPBaseAlg::receivedOutOfOrderSegment | ( | ) | [virtual] |
Called after receiving data which are in the window, but not at its left edge (seq!=rcv_nxt). This indicates that either segments got re-ordered in the way, or one segment was lost. RFC1122 and RFC2001 recommend sending an immediate ACK here (Fast Retransmit relies on that).
Implements tcp_old::TCPAlgorithm.
Definition at line 323 of file old/flavours/TCPBaseAlg.cc.
void TCPBaseAlg::receiveSeqChanged | ( | ) | [virtual] |
Called after rcv_nxt got advanced, either because we received in-sequence data ("text" in RFC 793 lingo) or a FIN. At this point, rcv_nxt has already been updated. This method should take care to send or schedule an ACK some time.
Implements tcp_old::TCPAlgorithm.
Definition at line 329 of file old/flavours/TCPBaseAlg.cc.
{ // If we send a data segment already (with the updated seqNo) there is no need to send an additional ACK if (state->last_ack_sent == state->rcv_nxt && !delayedAckTimer->isScheduled()) // ackSent? { // tcpEV << "ACK has already been sent (possibly piggybacked on data)\n"; } else { if (!state->delayed_acks_enabled) { tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", sending ACK now (delayed ACKs are disabled)\n"; conn->sendAck(); } else { // FIXME ACK should be generated for at least every second SMSS-sized segment! // schedule delayed ACK timer if not already running tcpEV << "rcv_nxt changed to " << state->rcv_nxt << ", scheduling ACK\n"; if (!delayedAckTimer->isScheduled()) conn->scheduleTimeout(delayedAckTimer, DELAYED_ACK_TIMEOUT); } } }
void TCPBaseAlg::restartRexmitTimer | ( | ) | [virtual] |
Restart REXMIT timer.
Implements tcp_old::TCPAlgorithm.
Definition at line 452 of file old/flavours/TCPBaseAlg.cc.
{ if (rexmitTimer->isScheduled()) cancelEvent(rexmitTimer); startRexmitTimer(); }
void TCPBaseAlg::rttMeasurementComplete | ( | simtime_t | tSent, | |
simtime_t | tAcked | |||
) | [protected, virtual] |
Update state vars with new measured RTT value. Passing two simtime_t's will allow rttMeasurementComplete() to do calculations in double or in 200ms/500ms ticks, as needed)
Definition at line 255 of file old/flavours/TCPBaseAlg.cc.
Referenced by receivedDataAck().
{ // // Jacobson's algorithm for estimating RTT and adaptively setting RTO. // // Note: this implementation calculates in doubles. An impl. which uses // 500ms ticks is available from old tcpmodule.cc:calcRetransTimer(). // // update smoothed RTT estimate (srtt) and variance (rttvar) const double g = 0.125; // 1/8; (1-alpha) where alpha=7/8; simtime_t newRTT = tAcked-tSent; simtime_t& srtt = state->srtt; simtime_t& rttvar = state->rttvar; simtime_t err = newRTT - srtt; srtt += g*err; rttvar += g*(fabs(err) - rttvar); // assign RTO (here: rexmit_timeout) a new value simtime_t rto = srtt + 4*rttvar; if (rto>MAX_REXMIT_TIMEOUT) rto = MAX_REXMIT_TIMEOUT; else if (rto<MIN_REXMIT_TIMEOUT) rto = MIN_REXMIT_TIMEOUT; state->rexmit_timeout = rto; // record statistics tcpEV << "Measured RTT=" << (newRTT*1000) << "ms, updated SRTT=" << (srtt*1000) << "ms, new RTO=" << (rto*1000) << "ms\n"; if (rttVector) rttVector->record(newRTT); if (srttVector) srttVector->record(srtt); if (rttvarVector) rttvarVector->record(rttvar); if (rtoVector) rtoVector->record(rto); }
void TCPBaseAlg::sendCommandInvoked | ( | ) | [virtual] |
Called after user sent TCP_C_SEND command to us.
Implements tcp_old::TCPAlgorithm.
Definition at line 317 of file old/flavours/TCPBaseAlg.cc.
{ // try sending sendData(); }
bool TCPBaseAlg::sendData | ( | ) | [protected, virtual] |
Send data, observing Nagle's algorithm and congestion window
Definition at line 294 of file old/flavours/TCPBaseAlg.cc.
Referenced by established(), tcp_old::TCPTahoe::receivedDataAck(), tcp_old::TCPReno::receivedDataAck(), tcp_old::TCPNoCongestionControl::receivedDataAck(), tcp_old::TCPReno::receivedDuplicateAck(), and sendCommandInvoked().
{ // // Nagle's algorithm: when a TCP connection has outstanding data that has not // yet been acknowledged, small segments cannot be sent until the outstanding // data is acknowledged. (In this case, small amounts of data are collected // by TCP and sent in a single segment.) // // FIXME there's also something like this: can still send if // "b) a segment that can be sent is at least half the size of // the largest window ever advertised by the receiver" bool fullSegmentsOnly = state->nagle_enabled && state->snd_una!=state->snd_max; if (fullSegmentsOnly) tcpEV << "Nagle is enabled and there's unacked data: only full segments will be sent\n"; // // Send window is effectively the minimum of the congestion window (cwnd) // and the advertised window (snd_wnd). // return conn->sendData(fullSegmentsOnly, state->snd_cwnd); }
void TCPBaseAlg::startRexmitTimer | ( | ) | [protected, virtual] |
Start REXMIT timer and initialize retransmission variables
Definition at line 245 of file old/flavours/TCPBaseAlg.cc.
Referenced by dataSent(), receivedDataAck(), and restartRexmitTimer().
{ // start counting retransmissions for this seq number. // Note: state->rexmit_timeout is set from rttMeasurementComplete(). state->rexmit_count = 0; // schedule timer conn->scheduleTimeout(rexmitTimer, state->rexmit_timeout); }
cOutVector* tcp_old::TCPBaseAlg::cwndVector [protected] |
Definition at line 99 of file TCPBaseAlg_old.h.
Referenced by established(), initialize(), tcp_old::TCPTahoe::processRexmitTimer(), tcp_old::TCPReno::processRexmitTimer(), tcp_old::TCPTahoe::receivedDataAck(), tcp_old::TCPReno::receivedDataAck(), tcp_old::TCPTahoe::receivedDuplicateAck(), tcp_old::TCPReno::receivedDuplicateAck(), TCPBaseAlg(), and ~TCPBaseAlg().
cMessage* tcp_old::TCPBaseAlg::delayedAckTimer [protected] |
Definition at line 96 of file TCPBaseAlg_old.h.
Referenced by ackSent(), connectionClosed(), initialize(), processTimer(), receiveSeqChanged(), TCPBaseAlg(), and ~TCPBaseAlg().
cMessage* tcp_old::TCPBaseAlg::keepAliveTimer [protected] |
Definition at line 97 of file TCPBaseAlg_old.h.
Referenced by connectionClosed(), initialize(), processTimer(), TCPBaseAlg(), and ~TCPBaseAlg().
cMessage* tcp_old::TCPBaseAlg::persistTimer [protected] |
Definition at line 95 of file TCPBaseAlg_old.h.
Referenced by connectionClosed(), initialize(), processTimer(), TCPBaseAlg(), and ~TCPBaseAlg().
cMessage* tcp_old::TCPBaseAlg::rexmitTimer [protected] |
Definition at line 94 of file TCPBaseAlg_old.h.
Referenced by connectionClosed(), dataSent(), initialize(), processRexmitTimer(), processTimer(), receivedDataAck(), restartRexmitTimer(), startRexmitTimer(), TCPBaseAlg(), and ~TCPBaseAlg().
cOutVector* tcp_old::TCPBaseAlg::rtoVector [protected] |
Definition at line 104 of file TCPBaseAlg_old.h.
Referenced by initialize(), rttMeasurementComplete(), TCPBaseAlg(), and ~TCPBaseAlg().
cOutVector* tcp_old::TCPBaseAlg::rttvarVector [protected] |
Definition at line 103 of file TCPBaseAlg_old.h.
Referenced by initialize(), rttMeasurementComplete(), TCPBaseAlg(), and ~TCPBaseAlg().
cOutVector* tcp_old::TCPBaseAlg::rttVector [protected] |
Definition at line 101 of file TCPBaseAlg_old.h.
Referenced by initialize(), rttMeasurementComplete(), TCPBaseAlg(), and ~TCPBaseAlg().
cOutVector* tcp_old::TCPBaseAlg::srttVector [protected] |
Definition at line 102 of file TCPBaseAlg_old.h.
Referenced by initialize(), rttMeasurementComplete(), TCPBaseAlg(), and ~TCPBaseAlg().
cOutVector* tcp_old::TCPBaseAlg::ssthreshVector [protected] |
Definition at line 100 of file TCPBaseAlg_old.h.
Referenced by initialize(), tcp_old::TCPTahoe::recalculateSlowStartThreshold(), tcp_old::TCPReno::recalculateSlowStartThreshold(), TCPBaseAlg(), and ~TCPBaseAlg().
TCPBaseAlgStateVariables*& tcp_old::TCPBaseAlg::state [protected] |
Reimplemented from tcp_old::TCPAlgorithm.
Reimplemented in tcp_old::TCPNoCongestionControl, tcp_old::TCPReno, tcp_old::TCPTahoe, and tcp_old::TCPTahoeRenoFamily.
Definition at line 92 of file TCPBaseAlg_old.h.
Referenced by ackSent(), dataSent(), established(), processRexmitTimer(), receivedDataAck(), receivedDuplicateAck(), receiveSeqChanged(), rttMeasurementComplete(), sendData(), and startRexmitTimer().