11.1.2 Example: Tcp retransmission timer

TCP is an example of an agent which requires timers. There are three timers defined in the basic Tahoe TCP agent defined in tcp.cc:

        rtx_timer_;      /*  Retransmission timer /
        delsnd_timer_;   /*  Delays sending of packets by a small random amount of time, /
                        /* to avoid phase effects /
        burstsnd_timer_;   /* Helps TCP to stagger the transmission of a large window /
                                /* into several smaller bursts /
In ~ns/tcp.h, three classes are derived from the base class TimerHandlertcp.h:
        class RtxTimer : public TimerHandler {
        public:
            RtxTimer(TcpAgent *a) : TimerHandler() { a_ = a; }
        protected:                   
            virtual void expire(Event *e);
            TcpAgent *a_;
        };  
            
        class DelSndTimer : public TimerHandler {
        public:
            DelSndTimer(TcpAgent *a) : TimerHandler() { a_ = a; }
        protected:
            virtual void expire(Event *e);
            TcpAgent *a_;
        };      
    
        class BurstSndTimer : public TimerHandler {
        public: 
            BurstSndTimer(TcpAgent *a) : TimerHandler() { a_ = a; }
        protected:
            virtual void expire(Event *e); 
            TcpAgent *a_;
        };
In the constructor for TcpAgent../ns-2/tcp.ccTcpAgent::TcpAgent in tcp.cc, each of these timers is initialized with the this pointer, which is assigned to the pointer a_.
        TcpAgent::TcpAgent() : Agent(PT_TCP), rtt_active_(0), rtt_seq_(-1), 
            \ldots
            rtx_timer_(this), delsnd_timer_(this), burstsnd_timer_(this)
        {
            \ldots
        }
In the following, we will focus only on the retransmission timer. Various helper methods may be defined to schedule timer events; ,
        /*
         *Set retransmit timer using current rtt estimate.  By calling \fcn[]{resched}
         *it does not matter whether the timer was already running.
         */
        void TcpAgent::set_rtx_timer()
        {
            rtx_timer_.resched(rtt_timeout());
        }

        /*
         * Set new retransmission timer if not all outstanding
         * data has been acked.  Otherwise, if a timer is still
         * outstanding, cancel it.
         */
        void TcpAgent::newtimer(Packet* pkt)
        {
            hdr_tcp *tcph = (hdr_tcp*)pkt-\>access(off_tcp_);
            if (t_seqno_ \> tcph-\>seqno())
                set_rtx_timer();
            else if (rtx_timer_.status() == TIMER_PENDING)
                rtx_timer_.cancel();
        }
In the above code, the []set_rtx_timer method reschedules the retransmission timer by calling []rtx_timer_.resched. Note that if it is unclear whether or not the timer is already running, calling []resched eliminates the need to explicitly cancel the timer. In the second function, examples are given of the use of the []status and cancel methods.

Finally, the expire method for class RtxTimer must be defined. In this case, expire calls the timeout method for TcpAgent. This is possible because []timeout is a public member function; if it were not, then RtxTimer would have had to have been declared a friend class of TcpAgent.

void TcpAgent::timeout(int tno)
{                     
    /* retransmit timer */
    if (tno == TCP_TIMER_RTX) {
        if (highest_ack_ == maxseq_ && !slow_start_restart_) {
            /*
             * TCP option:
             * If no outstanding data, then don't do anything.
             */
            return;  
        };
        recover_ = maxseq_;
        recover_cause_ = 2;
        closecwnd(0);
        reset_rtx_timer(0,1);
        send_much(0, TCP_REASON_TIMEOUT, maxburst_); 
    } else {
        /* 
         * delayed-send timer, with random overhead
         * to avoid phase effects  
         */     
        send_much(1, TCP_REASON_TIMEOUT, maxburst_);
    }           
}           
            
void RtxTimer::expire(Event *e) {
    a_-\>timeout(TCP_TIMER_RTX);
}

The various TCP agents contain additional examples of timers.

Tom Henderson 2011-11-05