Public Member Functions | Protected Member Functions | Protected Attributes

tcp_old::TCPBaseAlg Class Reference

#include <TCPBaseAlg_old.h>

Inheritance diagram for tcp_old::TCPBaseAlg:
tcp_old::TCPAlgorithm tcp_old::TCPNoCongestionControl tcp_old::TCPTahoeRenoFamily tcp_old::TCPReno tcp_old::TCPTahoe

List of all members.

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

Detailed Description

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.


Constructor & Destructor Documentation

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;
}


Member Function Documentation

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().

{
    conn->sendAck();
}

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().

{
    // FIXME TBD finish (currently Persist Timer never gets scheduled)
    conn->sendProbe();
}

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.

{
    tcpEV << "ACK acks something not yet sent, sending immediate ACK\n";
    conn->sendAck();
}

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.

{
    tcpEV << "Out-of-order segment, sending immediate ACK\n";
    conn->sendAck();
}

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);
}


Member Data Documentation

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().

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().


The documentation for this class was generated from the following files: