Event-Driven Simulation: An Example of Scheduling-Dispatching Mechanism--Delayed Packet Reception
[ Table of Contents ] [ Previous Section ] [ Next Section ]
Note: The content in this series is extracted from the book, Introduction to Network Simulator NS2. You may have to read chapter 4 of the book for better understanding.
This post demonstrate one example of the scheduling-dispatching mechanism in NS2. The example here is delayed packet forwarding. Here, I will show you how to place a packet reception event in the simulation time line "t" seconds in future, and how to execute actions associated with the event when the Scheduler reaches that time.
An Example of Scheduling-Dispatching Mechanism--Delayed Packet Reception
View more presentations from Teerawat Issariyakul
In the next post, I'll talk about the mechanism where events are scheduled and dispatched (i.e., taking actions associated withe the events).
-------------- RELATED C++ PROGRAMS -----------------
Declaration of C++ Class LinkDelay
//~/ns/link/delay.h class LinkDelay : public Connector { public: LinkDelay(); void recv(Packet* p, Handler*); void send(Packet* p, Handler*); void handle(Event* e); double delay() { return delay_; } inline double txtime(Packet* p) { return (8. * hdr_cmn::access(p)->size() / bandwidth_); } double bandwidth() const { return bandwidth_; } void pktintran(int src, int group); protected: int command(int argc, const char*const* argv); void reset(); double bandwidth_; /* bandwidth of underlying link (bits/sec) */ double delay_; /* line latency */ Event intr_; int dynamic_; /* indicates whether or not link is ~ */ double latest_time_; /* latest scheduled packet time, for use * with avoidReordering_ */ PacketQueue* itq_; int total_[4]; int avoidReordering_; /* indicates whether or not to avoid * reordering when link bandwidth or delay * changes */ };
Function recv(p,h) of class LinkDelay
//~/ns/link/delay.cc void LinkDelay::recv(Packet* p, Handler* h) { double txt = txtime(p); Scheduler& s = Scheduler::instance(); if (dynamic_) { Event* e = (Event*)p; e->time_= txt + delay_; itq_->enque(p); // for convinience, use a queue to store packets in transit s.schedule(this, p, txt + delay_); } else if (avoidReordering_) { // code from Andrei Gurtov, to prevent reordering on // bandwidth or delay changes double now_ = Scheduler::instance().clock(); if (txt + delay_ < latest_time_ - now_ && latest_time_ > 0) { latest_time_+=txt; s.schedule(target_, p, latest_time_ - now_ ); } else { latest_time_ = now_ + txt + delay_; s.schedule(target_, p, txt + delay_); } } else { s.schedule(target_, p, txt + delay_); } s.schedule(h, &intr_, txt); }
Declaration of C++ Class Connector
//~/ns/common/connector.h class Connector : public NsObject { public: Connector(); inline NsObject* target() { return target_; } void target (NsObject *target) { target_ = target; } virtual void drop(Packet* p); void setDropTarget(NsObject *dt) {drop_ = dt; } protected: virtual void drop(Packet* p, const char *s); int command(int argc, const char*const* argv); void recv(Packet*, Handler* callback = 0); inline void send(Packet* p, Handler* h) { target_->recv(p, h); } NsObject* target_; NsObject* drop_; // drop target for this connector };
Function schedule(h,e,delay) of class Scheduler
//~/ns/common/scheduler.cc void Scheduler::schedule(Handler* h, Event* e, double delay) { // handler should ALWAYS be set... if it's not, it's a bug in the caller if (!h) { fprintf(stderr, "Scheduler: attempt to schedule an event with a NULL handler." " Don't DO that at time %f\n", clock_); abort(); }; if (e->uid_ > 0) { printf("Scheduler: Event UID not valid!\n\n"); abort(); } if (delay < 0) { // You probably don't want to do this // (it probably represents a bug in your simulation). fprintf(stderr, "warning: ns Scheduler::schedule: scheduling event\n\t" "with negative delay (%f) at time %f.\n", delay, clock_); } if (uid_ < 0) { fprintf(stderr, "Scheduler: UID space exhausted!\n"); abort(); } e->uid_ = uid_++; e->handler_ = h; double t = clock_ + delay; e->time_ = t; insert(e); }
Function dispatch(p,t) of class Scheduler
//~/ns/common/scheduler.cc void Scheduler::dispatch(Event* p, double t) { if (t < clock_) { fprintf(stderr, "ns: scheduler going backwards in time from %f to %f.\n", clock_, t); abort(); } clock_ = t; p->uid_ = -p->uid_; // being dispatched p->handler_->handle(p); // dispatch }
Function run() of class Scheduler
//~/ns/common/scheduler.cc Scheduler::run() { instance_ = this; Event *p; while (!halted_ && (p = deque())) { dispatch(p, p->time_); } }
Function run() of class Scheduler
//~/ns/common/object.cc void NsObject::handle(Event* e) { recv((Packet*)e); }
======================================================
T. Issaraiyakul and E. Hossain, “Introduction to Network Simulator NS2”, Springer 2009. Buy it now from Amazon:
You may also find lecture notes and other resource at the following website:http://www.ece.ubc.ca/~teerawat/NS2.htm