/* * inDirectChannel is used in this version */ #include #include #include #include "machine.h" #include "debug.h" #include "segments.hxx" #include "barrier.hxx" #include "random.hxx" #include "ssf.hxx" #include "ssf-root.hxx" // DMN ADDS FOR p4 INSTRUMENTATION #include "instrument.hxx" #define MIN_DELAY 10.0 #define SRC_TRANSMISSION_DELAY MIN_DELAY #define SRC_INTERARRIVAL_RATE 5 #define NUM_SRC 1 #define NUM_RUT 1 #define NUM_LNK 1 #define INFINITY 999; #define Q_LIM 60 #define DTYPE_NONE 0 /* ok, no drop */ #define DTYPE_FORCED 1 /* a "forced" drop */ #define DTYPE_UNFORCED 2 /* an "unforced" (random) drop */ #define min( x, y) ((x>y)? : y, x) FILE * arvl; FILE * dp; class Entity_Source; class Entity_Router; class Entity_MyRoot; class Entity_Link; class Entity_PacketQueue; // underlying FIFO queue class Entity_Queue; // base class for all kinds of queue class Event_Packet; class Entity_Classifier; class DropTail; // drop tail queue (there is the option to drop front) class REDQueue; struct edp; struct edv; class Event_Packet : public Event { public: enum PacketType { TCP=1, RTP=2, IPMcast=3 }; int ptype_; int uid_; /* currently uid_ is used to do routing */ int seqno_; Event_Packet * next_; Event_Packet(int type, int uid) { ptype_ = type; next_ = NULL; uid_ = uid; } ~Event_Packet() { } Event_Packet(const Event_Packet &); Event * eventCopy(); }; class Entity_Source : public Entity { private: char * name_; int myid_; Random * state_rng_; public: outChannel * outch_; Entity_Source(char * name, int myid); virtual ~Entity_Source(){ delete[] name_; delete state_rng_; //delete outch_; } void init() {}; void wrapup() {}; procedure void emit(); }; class Entity_Router : public Entity { public: char * name_; int myid_; inDirectChannel *inch_; // outChannel *outch; Entity_Classifier * demu_; Entity_Router(char * name, int myid); virtual ~Entity_Router() {;} void scan(Event * evt); }; class Entity_Link : public Entity { public: char * name_; int myid_; double service_rate_; inChannel *inch_; /* could be a set of channel */ outChannel * outch_; /* output Channel */ inChannel *intch_in_; /* internal channel between proc scan() and proc serve() */ outChannel *intch_out_; Entity_Queue * qu_; Entity_Link(char * name, int myid); virtual ~Entity_Link() {;} procedure void scan(); procedure void serve(); /* serve the queue */ double bandwidth() {return service_rate_; } }; class Entity_PacketQueue : public Entity { protected: Event_Packet * head_; Event_Packet ** tail_; int len_; // packet count public: Entity_PacketQueue() : head_(0), tail_(&head_), len_(0) {} inline int length() const { return (len_); } virtual inline void enque(Event_Packet* p) { *tail_ = p; tail_ = & p->next_; *tail_ = 0; ++len_; } virtual Event_Packet* deque() { Event_Packet* p = head_; if (p != 0) { --len_; head_ = p->next_; if (head_ == 0) tail_ = &head_; } return (p); } Event_Packet* lookup(int n) { for (Event_Packet* p = head_; p != 0; p = p->next_) { if (--n < 0) return (p); } return (0); } /* remove a specific packet, which must be in the queue */ virtual void remove(Event_Packet*); /* Remove a packet, located after a given packet. Either could be 0. */ void remove(Event_Packet *, Event_Packet *); inline Event_Packet* head() { return head_; } inline Event_Packet* tail() { return tail ? *tail_ : 0; } }; class Entity_Queue : public Entity { protected: Entity_Queue(int) ; void reset(); int qlim_; /* maximum allowed pkts in queue */ int blocked_; /* blocked now? */ int unblock_on_resume_; /* unblock q on idle? */ Entity_PacketQueue * pq_; /* pointer to actual packet queue * (maintained by the individual disciplines * like DropTail and RED). */ public: Entity_Link* link_; /* link contains the Entity_Queue */ virtual void enque(Event_Packet*) = 0; virtual Event_Packet* deque() = 0; void drop(Event_Packet*); void recv(Event_Packet*); void resume(); int blocked() const { return (blocked_ == 1); } void unblock() { blocked_ = 0; } void block() { blocked_ = 1; } int limit() { return qlim_; } int length() { return pq_->length(); } /* number of pkts currently in * underlying packet queue */ }; class DropTail : public Entity_Queue { public: DropTail(int lim) : Entity_Queue(lim) { q_ = new Entity_PacketQueue(); pq_ = q_; } void enque(Event_Packet*); Event_Packet* deque(); Entity_PacketQueue *q_; /* underlying FIFO queue */ int drop_front_; /* drop-from-front (rather than from tail) */ }; class Entity_Classifier : public Entity { // protected: public: void clear(int slot); int getnxt(); void alloc(int); outChannel** slot_; /* table that maps slot number to a NsObject */ int nslot_; int maxslot_; int offset_; // offset for Packet::access() int shift_; int mask_; //public: Entity_Classifier(); ~Entity_Classifier(); int maxslot() const { return maxslot_; } void install(int slot, outChannel *); inline outChannel * slot(int slot) { if ((slot >= 0) || (slot < nslot_)) return slot_[slot]; return 0; } outChannel * find(Event_Packet *const); virtual int classify(Event_Packet *const p) { int value = p->uid_; return (value >> shift_) & mask_; } }; /* * Early drop parameters, supplied by user */ struct edp { /* * User supplied. */ int mean_pktsize; /* avg pkt size */ int bytes; /* true if queue in bytes, false if packets */ int wait; /* true for waiting between dropped packets */ int setbit; /* true to set congestion indication bit */ double th_min; /* minimum threshold of average queue size */ double th_max; /* maximum threshold of average queue size */ double max_p_inv; /* 1/max_p, for max_p = maximum prob. */ double q_w; /* queue weight given to cur q size sample */ /* * Computed as a function of user supplied paramters. */ double ptc; /* packet time constant in packets/second */ edp() : mean_pktsize(500), bytes(0), wait(0), setbit(0), th_min(5), th_max(15), max_p_inv(30), q_w(0.002) {} }; /* * Early drop variables, maintained by RED */ struct edv { double v_ave; /* average queue size */ double v_prob1; /* prob. of packet drop before "count". */ double v_slope; /* used in computing average queue size */ double v_prob; /* prob. of packet drop */ double v_a; /* v_prob = v_a * v_ave + v_b */ double v_b; int count; /* # of packets since last drop */ int count_bytes; /* # of bytes since last drop */ int old; /* 0 when average queue first exceeds thresh */ edv() : v_ave(0.0), v_prob1(0.0), v_slope(0.0), v_prob(0.0), v_a(0.0), v_b(0.0), count(0), count_bytes(0), old(0) { } }; class REDQueue : public Entity_Queue { public: REDQueue(int); // protected: // int command(int argc, const char*const* argv); void enque(Event_Packet* pkt); virtual Event_Packet *pickPacketForECN(Event_Packet* pkt); virtual Event_Packet *pickPacketToDrop(); Event_Packet* deque(); void reset(); void run_estimator(int nqueued, int m); int drop_early(Event_Packet* pkt); int fifo_; /* fifo queue? */ Entity_PacketQueue *q_; /* underlying (usually) FIFO queue */ Random* ug_; /* random number generator used to decide ED */ int bcount_; /* byte count */ int qib_; /* bool: queue measured in bytes? */ // NsObject* de_drop_; /* drop_early target */ // Tcl_Channel tchan_; /* place to write trace records */ int curq_; /* current qlen seen by arrivals */ // void trace(TracedVar*); /* routine to write trace records */ /* * Static state. */ int drop_tail_; /* drop-tail */ int drop_front_; /* drop-from-front */ int drop_rand_; /* drop-tail, or drop random? */ edp edp_; /* early-drop params */ int doubleq_; /* for experiments with priority for small packets */ int dqthresh_; /* for experiments with priority for small packets */ /* * Dynamic state. */ int idle_; /* queue is idle? */ double idletime_; /* if so, since this time */ edv edv_; /* early-drop variables */ void print_edp(); // for debugging void print_edv(); // for debugging }; class Entity_MyRoot : public Root { public: char name[20]; Entity_Source **src; Entity_Router **router; Entity_Link **link; Entity_MyRoot(int ac, char **av, int id, int np, Time etime); virtual void init(); virtual void build(); virtual void wrapup(); };