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