8.1 The LinkDelay Class

The LinkDelay../ns-2/delay.cc is derived from the base Connector../ns-2/connector.h. Its definition is in ~ns/delay.cc, and is briefly excerpted below:

        class LinkDelay : public Connector {
                void recv(Packet* p, Handler*);
                void send(Packet* p, Handler*);
                void handle(Event* e);
                double delay();    /* line latency on this link /
                double bandwidth(); /* bandwidth on this link /
                inline double txtime(Packet* p) { /* time to send pkt p on this link /
                        hdr_cmn* hdr = (hdr_cmn*) p-\>access(off_cmn_);
                        return (hdr-\>size() * 8. / bandwidth_);

                double bandwidth_; /* bandwidth of underlying link (bits/sec) /
                double delay_;     /* line latency /
                int dynamic_;     /* indicates whether or not link is ~ /
                Event inTransit_;
                PacketQueue* itq_; /* internal packet queue for dynamic links /
                Packet* nextPacket_; /* to be delivered for a dynamic link. /
                Event intr_;
The []recv method../ns-2/delay.ccDelayLink::recv overrides the base class Connector../ns-2/connector.ccConnector::recv version. It is defined as follows:
        void LinkDelay::recv(Packet* p, Handler* h)
                double txt = txtime(p);
                Scheduler& s = Scheduler::instance();
                if (dynamic_) {
                        Event* e = (Event*)p;
                        e-\>time_ = s.clock() + txt + delay_; 
                } else {
                        s.schedule(target_, p, txt + delay_);
                /*XXX only need one intr_ since upstream object should
                 * block until it's handler is called
                 * This only holds if the link is not dynamic.  If it is, then
                 * the link itself will hold the packet, and call the upstream
                 * object at the appropriate time.  This second interrupt is
                 * called {\tt inTransit\_}, and is invoked through \fcn[]{schedule_next}
                s.schedule(h, &intr_, txt);
This object supports one instproc-like../ns-2/delay.ccLinkDelay::command, $object dynamic, to set its variable, dynamic_. This variable determines whether the link is dynamic or not (, prone to fail/recover at appropriate times). The internal behavior of the link in each case is different.

For ``non-dynamic'' links, this method operates by receiving a packet, $p$, and scheduling two events. Assume these two events are called $E_1$ and $E_2$, and that event $E_1$ is scheduled to occur before $E_2$. $E_1$ is scheduled to occur when the upstream node attached to this delay element has completed sending the current packet (which takes time equal to the packet size divided by the link bandwidth). $E_1$ is usually associated with a Queue object, and will cause it to (possibly) become unblocked (see section 7.1.1). $E_2$ represents the packet arrival event at the downstream neighbor of the delay element. Event $E_2$ occurs a number of seconds later than $E_1$ equal to the link delay.

Alternately, when the link is dynamic, and receives $p$, then it will schedule $E_1$ to possibly unblock the queue at the appropriate time. However, $E_2$ is scheduled only if $p$ is the only packet currently in transit. Otherwise, there is at least one packet in transit on the link that must be delivered before $p$ at $E_2$. Therefore, packet $p$ is held in the object's inTransit queue, itq_. When the packet just before $p$ in transit on the link is delivered at the neighbor node, the DelayLink object will schedule an event for itself to fire at $E_2$. At that appropriate time then, it's []handle method../ns-2/delay.ccLinkDelay::handle will directly send $p$ to its target. The object's internal []schedule_next method../ns-2/delay.hLinkDelay::schedule_next will schedule these events for packet sin transit at the appropriate time.

Tom Henderson 2011-11-05