00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef lint
00024 static const char rcsid[] =
00025 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/queue/drr.cc,v 1.10 2002/05/06 22:23:16 difa Exp $ (Xerox)";
00026 #endif
00027
00028 #include "config.h"
00029 #include <stdlib.h>
00030 #include "queue.h"
00031
00032 class PacketDRR;
00033 class DRR;
00034
00035 class PacketDRR : public PacketQueue {
00036 PacketDRR(): pkts(0),src(-1),bcount(0),prev(0),next(0),deficitCounter(0),turn(0) {}
00037 friend class DRR;
00038 protected :
00039 int pkts;
00040 int src;
00041 int bcount;
00042 PacketDRR *prev;
00043 PacketDRR *next;
00044 int deficitCounter;
00045 int turn;
00046 inline PacketDRR * activate(PacketDRR *head) {
00047 if (head) {
00048 this->prev = head->prev;
00049 this->next = head;
00050 head->prev->next = this;
00051 head->prev = this;
00052 return head;
00053 }
00054 this->prev = this;
00055 this->next = this;
00056 return this;
00057 }
00058 inline PacketDRR * idle(PacketDRR *head) {
00059 if (head == this) {
00060 if (this->next == this)
00061 return 0;
00062 this->next->prev = this->prev;
00063 this->prev->next = this->next;
00064 return this->next;
00065 }
00066 this->next->prev = this->prev;
00067 this->prev->next = this->next;
00068 return head;
00069 }
00070 };
00071
00072 class DRR : public Queue {
00073 public :
00074 DRR();
00075 virtual int command(int argc, const char*const* argv);
00076 Packet *deque(void);
00077 void enque(Packet *pkt);
00078 int hash(Packet *pkt);
00079 void clear();
00080 protected:
00081 int buckets_ ;
00082 int blimit_;
00083 int quantum_;
00084 int mask_;
00085
00086 int bytecnt ;
00087 int pktcnt ;
00088 int flwcnt ;
00089 PacketDRR *curr;
00090 PacketDRR *drr ;
00091
00092 inline PacketDRR *getMaxflow (PacketDRR *curr) {
00093 int i;
00094 PacketDRR *tmp;
00095 PacketDRR *maxflow=curr;
00096 for (i=0,tmp=curr; i < flwcnt; i++,tmp=tmp->next) {
00097 if (maxflow->bcount < tmp->bcount)
00098 maxflow=tmp;
00099 }
00100 return maxflow;
00101 }
00102
00103 public:
00104
00105 inline int length () {
00106 return pktcnt;
00107 }
00108
00109
00110 inline int blength () {
00111 return bytecnt;
00112 }
00113 };
00114
00115 static class DRRClass : public TclClass {
00116 public:
00117 DRRClass() : TclClass("Queue/DRR") {}
00118 TclObject* create(int, const char*const*) {
00119 return (new DRR);
00120 }
00121 } class_drr;
00122
00123 DRR::DRR()
00124 {
00125 buckets_=16;
00126 quantum_=250;
00127 drr=0;
00128 curr=0;
00129 flwcnt=0;
00130 bytecnt=0;
00131 pktcnt=0;
00132 mask_=0;
00133 bind("buckets_",&buckets_);
00134 bind("blimit_",&blimit_);
00135 bind("quantum_",&quantum_);
00136 bind("mask_",&mask_);
00137 }
00138
00139 void DRR::enque(Packet* pkt)
00140 {
00141 PacketDRR *q,*remq;
00142 int which;
00143
00144 hdr_cmn *ch= hdr_cmn::access(pkt);
00145 hdr_ip *iph = hdr_ip::access(pkt);
00146 if (!drr)
00147 drr=new PacketDRR[buckets_];
00148 which= hash(pkt) % buckets_;
00149 q=&drr[which];
00150
00151
00152 int compare=(!mask_ ? ((int)iph->saddr()) : ((int)iph->saddr()&0xfff0));
00153 if (q->src ==-1)
00154 q->src=compare;
00155 else
00156 if (q->src != compare)
00157 fprintf(stderr,"Collisions between %d and %d src addresses\n",q->src,(int)iph->saddr());
00158
00159 q->enque(pkt);
00160 ++q->pkts;
00161 ++pktcnt;
00162 q->bcount += ch->size();
00163 bytecnt +=ch->size();
00164
00165
00166 if (q->pkts==1)
00167 {
00168 curr = q->activate(curr);
00169 q->deficitCounter=0;
00170 ++flwcnt;
00171 }
00172 while (bytecnt > blimit_) {
00173 Packet *p;
00174 hdr_cmn *remch;
00175 hdr_ip *remiph;
00176 remq=getMaxflow(curr);
00177 p=remq->deque();
00178 remch=hdr_cmn::access(p);
00179 remiph=hdr_ip::access(p);
00180 remq->bcount -= remch->size();
00181 bytecnt -= remch->size();
00182 drop(p);
00183 --remq->pkts;
00184 --pktcnt;
00185 if (remq->pkts==0) {
00186 curr=remq->idle(curr);
00187 --flwcnt;
00188 }
00189 }
00190 }
00191
00192 Packet *DRR::deque(void)
00193 {
00194 hdr_cmn *ch;
00195 hdr_ip *iph;
00196 Packet *pkt=0;
00197 if (bytecnt==0) {
00198
00199 return(0);
00200 }
00201
00202 while (!pkt) {
00203 if (!curr->turn) {
00204 curr->deficitCounter+=quantum_;
00205 curr->turn=1;
00206 }
00207
00208 pkt=curr->lookup(0);
00209 ch=hdr_cmn::access(pkt);
00210 iph=hdr_ip::access(pkt);
00211 if (curr->deficitCounter >= ch->size()) {
00212 curr->deficitCounter -= ch->size();
00213 pkt=curr->deque();
00214 curr->bcount -= ch->size();
00215 --curr->pkts;
00216 --pktcnt;
00217 bytecnt -= ch->size();
00218 if (curr->pkts == 0) {
00219 curr->turn=0;
00220 --flwcnt;
00221 curr->deficitCounter=0;
00222 curr=curr->idle(curr);
00223 }
00224 return pkt;
00225 }
00226 else {
00227 curr->turn=0;
00228 curr=curr->next;
00229 pkt=0;
00230 }
00231 }
00232 return 0;
00233 }
00234
00235 void DRR::clear()
00236 {
00237 PacketDRR *q =drr;
00238 int i = buckets_;
00239
00240 if (!q)
00241 return;
00242 while (i--) {
00243 if (q->pkts) {
00244 fprintf(stderr, "Changing non-empty bucket from drr\n");
00245 exit(1);
00246 }
00247 ++q;
00248 }
00249 delete[](drr);
00250 drr = 0;
00251 }
00252
00253
00254
00255
00256
00257
00258 int DRR::command(int argc, const char*const* argv)
00259 {
00260 if (argc==3) {
00261 if (strcmp(argv[1], "blimit") == 0) {
00262 blimit_ = atoi(argv[2]);
00263 if (bytecnt > blimit_)
00264 {
00265 fprintf (stderr,"More packets in buffer than the new limit");
00266 exit (1);
00267 }
00268 return (TCL_OK);
00269 }
00270 if (strcmp(argv[1], "buckets") == 0) {
00271 clear();
00272 buckets_ = atoi(argv[2]);
00273 return (TCL_OK);
00274 }
00275 if (strcmp(argv[1],"quantum") == 0) {
00276 quantum_ = atoi(argv[2]);
00277 return (TCL_OK);
00278 }
00279 if (strcmp(argv[1],"mask")==0) {
00280 mask_= atoi(argv[2]);
00281 return (TCL_OK);
00282 }
00283 }
00284 return (Queue::command(argc, argv));
00285 }
00286
00287 int DRR::hash(Packet* pkt)
00288 {
00289 hdr_ip *iph=hdr_ip::access(pkt);
00290 int i;
00291 if (mask_)
00292 i = (int)iph->saddr() & (0xfff0);
00293 else
00294 i = (int)iph->saddr();
00295 return ((i + (i >> 8) + ~(i>>4)) % ((2<<23)-1))+1;
00296 }