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
00047
00048
00049
00050
00051
00052 #include "config.h"
00053 #include <stdlib.h>
00054 #include "queue.h"
00055 #include <math.h>
00056 #include <assert.h>
00057
00058 #define MAXFLOW 100 // this version supports up to 1024 flows and queues.
00059 #define MAXQUEUE 100 // if you want more, you can change it.
00060 #define MAXWSSORDER 16 // a 16th WSS needs pow(2, 16) space
00061
00062
00063
00064 #ifndef DEBUG_SRR
00065
00066 #endif // DEBUG_SRR
00067
00068
00069 struct wm_node
00070 {
00071 int queueid;
00072 int weight;
00073 struct wm_node *next;
00074 struct wm_node *prev;
00075 struct wm_node *sibling;
00076 };
00077
00078 #include "wss.h"
00079
00080 class PacketSRR {
00081 PacketSRR(): pkts(0),bcount(0),deficitCounter(0),turn(0),head_(0), tail_(0), len_(0) {}
00082 friend class SRR;
00083 protected:
00084 int pkts;
00085 int bcount;
00086 int deficitCounter;
00087 int turn;
00088 int queueid;
00089
00090 Packet *head_, *tail_;
00091 int len_;
00092
00093 inline void enque(Packet* p) {
00094
00095 if (!tail_) head_= tail_= p;
00096 else {
00097 tail_->next_= p;
00098 tail_= p;
00099 }
00100 tail_->next_= 0;
00101 ++len_;
00102 }
00103 inline Packet* deque() {
00104 if (!head_) return 0;
00105 Packet* p = head_;
00106 head_= p->next_;
00107 if (p == tail_) head_= tail_= 0;
00108 --len_;
00109 return p;
00110 }
00111 Packet* lookup(int n) {
00112 for (Packet* p = head_; p != 0; p = p->next_) {
00113 if (--n < 0)
00114 return (p);
00115 }
00116 return (0);
00117 }
00118 };
00119
00120 class SRR : public Queue {
00121 public :
00122 SRR();
00123 virtual int command(int argc, const char*const* argv);
00124 Packet *deque(void);
00125 void enque(Packet *pkt);
00126 void clear();
00127
00128 public:
00129 int maxqueuenumber_ ;
00130 int blimit_;
00131 int bytecnt;
00132 int pktcnt;
00133 int flwcnt;
00134
00135 int last_queueid;
00136 int last_size;
00137
00138 PacketSRR srr[MAXFLOW];
00139
00140 int f2q[MAXFLOW];
00141 int private_rate[MAXFLOW];
00142 int mtu_;
00143
00144 int granularity_;
00145 int maxRate;
00146 int minRate;
00147
00148 class WSS wss;
00149
00150
00151
00152
00153
00154 struct wm_node wmHead[MAXWSSORDER];
00155 struct wm_node wmTail[MAXWSSORDER];
00156 struct wm_node *pwmCurr;
00157
00158 struct wm_node *pRowHead[MAXFLOW];
00159 struct wm_node *pRowTail[MAXFLOW];
00160
00161
00162 int wmEmptyFlag;
00163
00164 int maxColumn;
00165
00166
00167 int currMaxColumn;
00168
00169 int min_quantum;
00170
00171 inline PacketSRR *getMaxflow () {
00172 int j,i;
00173 PacketSRR *tmp=0;
00174 PacketSRR *maxflow=0;
00175
00176
00177 int bcount=0;
00178
00179 for (i=0;i<maxqueuenumber_;i++) {
00180 tmp=&srr[i];
00181 if (tmp->bcount > bcount){
00182 bcount= tmp->bcount;
00183 maxflow=tmp;j=i;
00184 }
00185 }
00186 if(maxflow==0){
00187 fprintf(stderr, "getMaxflow, err");
00188 exit(1);
00189 }
00190 return maxflow;
00191 }
00192
00193
00194 inline int length () {
00195 return pktcnt;
00196 }
00197
00198
00199 inline int blength () {
00200 return bytecnt;
00201 }
00202
00203 int add_to_WM(int queueid, int weight);
00204 int del_from_WM(int queueid, int weight);
00205 struct wm_node * getNextNode( );
00206 };
00207
00208 static class SRRClass : public TclClass {
00209 public:
00210 SRRClass() : TclClass("Queue/SRR") {}
00211 TclObject* create(int, const char*const*) {
00212 return (new SRR);
00213 }
00214 } class_srr;
00215
00216 SRR::SRR()
00217 { int i;
00218
00219 maxqueuenumber_ = 10;
00220 blimit_ = 25000;
00221 mtu_= 1000;
00222 granularity_ = 1000;
00223
00224 last_queueid = -1;
00225 last_size = 0;
00226
00227 flwcnt = 0;
00228 bytecnt = 0;
00229 pktcnt = 0;
00230 min_quantum = 1000;
00231
00232 pwmCurr = 0;
00233
00234 for(i=0; i<MAXFLOW; i++)
00235 {
00236 private_rate[i] = granularity_;
00237 f2q[i]=0;
00238
00239 }
00240
00241 maxRate = 100000000;
00242 minRate = 1000;
00243
00244
00245 for(i=0;i<MAXWSSORDER;i++){
00246 wmHead[i].prev=NULL;
00247 wmHead[i].next=&wmTail[i];
00248 wmTail[i].prev=&wmHead[i];
00249 wmTail[i].next=NULL;
00250 wmHead[i].queueid=wmTail[i].queueid=-1;
00251 wmHead[i].weight=wmHead[i].weight=i;
00252 }
00253
00254 for (i=0;i<MAXFLOW; i++)
00255 pRowHead[i]= pRowTail[i] = NULL;
00256
00257 wmEmptyFlag=1;
00258 wss.init(MAXWSSORDER);
00259
00260 currMaxColumn = -1;
00261 maxColumn=0;
00262
00263
00264 bind("maxqueuenumber_",&maxqueuenumber_);
00265 bind("mtu_", &mtu_);
00266 bind("granularity_", &granularity_);
00267
00268 bind("blimit_",&blimit_);
00269 }
00270
00271
00272
00273
00274 void SRR::enque(Packet* pkt)
00275 {
00276 PacketSRR *q;
00277
00278 int flowid, queueid;
00279 int weight;
00280
00281 hdr_cmn *ch=hdr_cmn::access(pkt);
00282 hdr_ip *iph = hdr_ip::access(pkt);
00283
00284 flowid= iph->flowid();
00285 queueid= f2q[flowid];
00286
00287 if(queueid > maxqueuenumber_)
00288 {
00289 fprintf(stderr, "queueid too big\n");
00290 exit(1);
00291 }
00292
00293 #ifdef DEBUG_SRR
00294 printf(" in enque\n"); fflush(0);
00295 #endif
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 q=&srr[queueid];
00307
00308 if(q->pkts==qlim_){
00309
00310 drop(pkt);
00311 return;
00312 }
00313
00314 q->enque(pkt);
00315
00316 ++q->pkts;
00317 ++pktcnt;
00318 q->bcount += ch->size();
00319 bytecnt +=ch->size();
00320
00321
00322 if (q->pkts==1)
00323 {
00324
00325
00326
00327
00328 weight= private_rate[queueid];
00329 weight/=granularity_;
00330
00331 add_to_WM(queueid, weight);
00332
00333 q->deficitCounter=0;
00334 }
00335
00336 }
00337
00338 Packet *SRR::deque(void)
00339 {
00340 hdr_cmn *ch;
00341 hdr_ip *iph;
00342 Packet *pkt=0;
00343 int flowid;
00344 int queueid;
00345 PacketSRR *pP;
00346
00347
00348
00349
00350
00351
00352 #ifdef DEBUG_SRR
00353 printf(" in deque\n");
00354 #endif
00355
00356 if(last_queueid>=0){
00357
00358 srr[last_queueid].bcount -= last_size;
00359 srr[last_queueid].pkts-=1;
00360 --pktcnt;
00361 bytecnt -= last_size;
00362
00363 if (srr[last_queueid].pkts == 0) {
00364 srr[last_queueid].turn=0;
00365 srr[last_queueid].deficitCounter=0;
00366
00367
00368 del_from_WM(last_queueid, private_rate[last_queueid]/granularity_ );
00369 }
00370
00371 }
00372
00373 assert(pktcnt>=0);
00374 if (pktcnt==0) {
00375
00376 last_queueid=-1;
00377 return(0);
00378 }
00379
00380 if(pwmCurr == NULL){
00381 printf("wrong, pwmCurr is NULL\n");
00382 exit(0);
00383 }
00384
00385
00386
00387 while (!pkt) {
00388
00389 if(pwmCurr->queueid==-1){
00390
00391 fprintf(stderr,"pwmCurr points to head or tail\n");
00392 fprintf(stderr, "weight:%d", pwmCurr->weight);
00393 exit(0);
00394 }
00395 pP=&srr[pwmCurr->queueid];
00396
00397 pkt=pP->lookup(0);
00398
00399 if(pkt==0){
00400 fprintf(stderr, "wrong place, should never be here\n");
00401 exit(2);
00402
00403 }
00404
00405 iph = hdr_ip::access(pkt);
00406
00407 flowid=iph->flowid();
00408 queueid= f2q[flowid];
00409
00410 assert(queueid== pwmCurr->queueid);
00411
00412 if (!pP->turn) {
00413 pP->deficitCounter+= mtu_;
00414
00415 pP->turn=1;
00416 }
00417
00418 ch=hdr_cmn::access(pkt);
00419
00420 if (pP->deficitCounter >= ch->size()) {
00421 pP->deficitCounter -= (ch->size());
00422 pkt=pP->deque();
00423 last_size=ch->size( );
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 #ifdef DEBUG_SRR
00439 printf("deque a packet, id=%d, size=%d\n", queueid, last_size);
00440 #endif
00441 last_queueid=queueid;
00442
00443 return pkt;
00444 }
00445 else {
00446 pP->turn=0;
00447
00448
00449 getNextNode( );
00450 pkt=0;
00451 }
00452 }
00453 return 0;
00454 }
00455
00456 void SRR::clear()
00457 {
00458 PacketSRR *q =srr;
00459 int i = maxqueuenumber_;
00460
00461 if (!q)
00462 return;
00463 while (i--) {
00464 if (q->pkts) {
00465 fprintf(stderr, "Changing non-empty flow from srr\n");
00466 exit(1);
00467 }
00468 ++q;
00469 }
00470 }
00471
00472
00473
00474 int SRR::add_to_WM(int queueid, int weight)
00475 {
00476 struct wm_node *pNode;
00477 int i;
00478
00479
00480
00481
00482 int old_colno = currMaxColumn;
00483
00484 if(weight==0)
00485 {
00486 fprintf(stderr, "add_to_WM: weight should not be zero");
00487 exit(1);
00488 }
00489
00490 if(weight > ( (1<<(maxColumn+1))-1) )
00491 {
00492 fprintf(stderr, "add_to_WM: weight too big");
00493 exit(1);
00494 }
00495
00496
00497
00498
00499
00500
00501 for(i=maxColumn; i>=0; i--)
00502 {
00503
00504 if (weight & (1<<i) )
00505 {
00506
00507
00508 pNode=(struct wm_node*)malloc(sizeof(struct wm_node));
00509
00510 if(pNode==NULL)
00511 {
00512 fprintf(stderr, "no memeory to create WM node");
00513 exit(2);
00514 }
00515
00516
00517 pNode->queueid = queueid;
00518 pNode->weight = i;
00519 pNode->sibling = NULL;
00520
00521 if(pRowTail[queueid] == NULL){
00522 pRowHead[queueid]= pRowTail[queueid] = pNode;
00523 }else{
00524 pRowTail[queueid]->sibling = pNode;
00525 pRowTail[queueid] = pNode;
00526 }
00527
00528 if( pwmCurr && (pwmCurr->weight == i) ){
00529 pNode-> prev = pwmCurr->prev;
00530 pNode-> next = pwmCurr;
00531 (pwmCurr->prev)->next = pNode;
00532 pwmCurr->prev = pNode;
00533
00534 }else {
00535
00536 pNode->prev = wmTail[i].prev;
00537 pNode->next = &wmTail[i];
00538 (wmTail[i].prev)->next = pNode;
00539 wmTail[i].prev = pNode;
00540 }
00541
00542 if(currMaxColumn < i)
00543 currMaxColumn = i;
00544
00545 if(wmEmptyFlag == 1)
00546 {
00547 wmEmptyFlag=0;
00548 if(pwmCurr == NULL)
00549 pwmCurr=pNode;
00550 }
00551
00552 }
00553 }
00554
00555 if ( old_colno < currMaxColumn )
00556 {
00557 if(old_colno >= 0){
00558
00559 int pc = wss.get_ptr () + 1;
00560 pc = pc << (currMaxColumn - old_colno);
00561 wss.set_ptr ( pc -1);
00562
00563
00564 }
00565 }
00566
00567
00568 ++flwcnt;
00569 return 0;
00570 }
00571
00572
00573
00574 int SRR::del_from_WM(int queueid, int weight)
00575 {
00576 struct wm_node *pNode, *pNode2;
00577 int i;
00578 int wss_term;
00579 int temp;
00580
00581
00582 if(pwmCurr->queueid==queueid)
00583 {
00584 if (pwmCurr->next != &wmTail[pwmCurr->weight])
00585 pwmCurr = pwmCurr->next ;
00586 else pwmCurr = NULL;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 pNode = pRowHead[queueid];
00611 while (pNode){
00612 (pNode->prev)->next=pNode->next;
00613 (pNode->next)->prev=pNode->prev;
00614
00615 pNode2= pNode;
00616 pNode = pNode->sibling;
00617 free(pNode2);
00618 }
00619
00620 pRowHead[queueid] = pRowTail[queueid] = NULL;
00621
00622
00623
00624
00625 int old_colno = currMaxColumn;
00626
00627 for(i=currMaxColumn;i>=0;i--)
00628 {
00629 if(wmHead[i].next != &wmTail[i])
00630 {
00631 currMaxColumn=i;
00632 break;
00633 }
00634 }
00635
00636 if(i<0)
00637 {
00638
00639 #ifdef DEBUG_SRR
00640
00641 #endif
00642 wmEmptyFlag=1;
00643 currMaxColumn=-1;
00644 pwmCurr=NULL;
00645 last_queueid=-1;
00646 wss.set_ptr (0);
00647 goto rr;
00648 } else if ( currMaxColumn < old_colno)
00649 {
00650 int pc = wss.get_ptr () +1;
00651
00652 int mul = 1 << (old_colno - currMaxColumn );
00653 int tmpc = pc / mul;
00654 if (pc % mul){
00655 tmpc += 1;
00656 if (tmpc > ((1<<(currMaxColumn+1) )- 1) )
00657 tmpc = 1;
00658
00659 }
00660 wss.set_ptr (tmpc -1);
00661
00662
00663
00664 }
00665 if (pwmCurr == NULL){
00666 loop:
00667 wss_term=wss.get(currMaxColumn+1);
00668 wss.inc_ptr (currMaxColumn+1 );
00669 temp = currMaxColumn+1-wss_term;
00670
00671
00672 if( wmHead[temp].next != &wmTail[temp])
00673 {
00674 pwmCurr=wmHead[temp].next;
00675
00676 }else
00677 goto loop;
00678 }
00679
00680 rr:
00681 --flwcnt;
00682 return 0;
00683 }
00684
00685
00686
00687
00688
00689 struct wm_node *SRR::getNextNode(){
00690
00691 int queueid;
00692 int weight;
00693 int wss_term;
00694 int temp;
00695
00696
00697 if(bytecnt==0){
00698
00699 return NULL;
00700 }
00701
00702 queueid=pwmCurr->queueid;
00703 weight= pwmCurr->weight;
00704
00705 if(pwmCurr->next != &wmTail[weight]){
00706 pwmCurr=pwmCurr ->next;
00707 } else{
00708 if (currMaxColumn==-1){
00709 fprintf(stderr, "getNextNode, empty WM");
00710 exit(0);
00711 }
00712
00713 again:
00714 wss_term=wss.get(currMaxColumn+1);
00715 wss.inc_ptr (currMaxColumn+1 );
00716
00717 temp = currMaxColumn+1-wss_term;
00718
00719
00720 if( wmHead[temp].next != &wmTail[temp]) {
00721 pwmCurr=wmHead[temp].next;
00722
00723 }else
00724 goto again;
00725
00726
00727 }
00728
00729 return pwmCurr;
00730 }
00731
00732
00733 int getOrder(int i){
00734 int order=0;
00735
00736 while( (1 << order)<= i)
00737 order++;
00738 return (order-1);
00739 }
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752 int SRR::command(int argc, const char*const* argv)
00753 {
00754
00755
00756 if (argc==3) {
00757
00758 if (strcmp(argv[1], "blimit") == 0) {
00759 blimit_ = atoi(argv[2]);
00760 if (bytecnt > blimit_)
00761 {
00762 fprintf (stderr,"More packets in buffer than the new limit");
00763 exit (1);
00764 }
00765 return (TCL_OK);
00766 }
00767 if (strcmp(argv[1], "maxqueuenumber") == 0) {
00768
00769 maxqueuenumber_ = atoi(argv[2]);
00770 return (TCL_OK);
00771 }
00772 if (strcmp(argv[1],"mtu")==0) {
00773 mtu_= atoi(argv[2]);
00774 return (TCL_OK);
00775 }
00776 if (strcmp(argv[1], "granularity")==0) {
00777 granularity_ = atoi(argv[2]);
00778 return (TCL_OK);
00779 }
00780 }
00781
00782 if (argc == 4) {
00783 if(!strcmp(argv[1],"setrate")) {
00784 int rate;
00785 int queue,success=0;
00786 int temp;
00787
00788 success += sscanf(argv[2],"%d",&queue);
00789 success += sscanf(argv[3],"%d",&rate);
00790
00791 if(success!=2){
00792 fprintf(stderr, "SRR setrate ??"); exit(0);
00793 exit(1);
00794 }
00795
00796 if ( queue>MAXQUEUE ) {
00797 fprintf(stderr,"queue id out of range"); exit(0);
00798 }
00799 min_quantum= min_quantum<rate ? min_quantum:rate;
00800 private_rate[queue]=rate;
00801
00802
00803 if(private_rate[queue]<minRate)
00804 private_rate[queue]=minRate;
00805 if(private_rate[queue]>maxRate){
00806 fprintf(stderr, "Rate too hight!\n");
00807 exit(1);
00808 }
00809
00810
00811 success=private_rate[queue]/granularity_;
00812 if(success==0) success=1;
00813
00814
00815 temp=getOrder(success);
00816 if(maxColumn<temp){
00817 maxColumn=temp;
00818
00819 }
00820
00821 #ifdef DEBUG_SRR
00822 printf("maxColumn=%d\n", maxColumn), fflush(0);
00823 #endif
00824 if(maxColumn>(MAXWSSORDER-1)){
00825 fprintf(stderr, "granularity too small or band too big!");
00826 exit(2);
00827 }
00828
00829 return (TCL_OK);
00830 }
00831
00832 else if(!strcmp(argv[1],"setqueue")) {
00833 int queue,flow,success=0;
00834 success += sscanf(argv[2],"%d",&flow);
00835 success += sscanf(argv[3],"%d",&queue);
00836 if(success==2) {
00837 if ( !(queue<MAXQUEUE) ) {
00838 fprintf(stderr,"queue id out of range");exit(1);
00839 }
00840 if ( !(flow<MAXFLOW) ) {
00841 fprintf(stderr,"flow id out of range"); exit(1);
00842 }
00843
00844 f2q[flow]=queue;
00845
00846 return TCL_OK;
00847 }
00848 }
00849 }
00850 return (Queue::command(argc, argv));
00851 }
00852
00853