Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

srr.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1991-1994 Regents of the University of California.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *      This product includes software developed by the University of
00016  *      California, Berkeley and the Network Research Group at
00017  *      Lawrence Berkeley Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  */
00035 
00036  /*
00037  * SRR means Smoothed Round Robin. 
00038  * as compared with the DRR provided in NS, 
00039  * this version now can:
00040  * 1, assign multi flows to a queue
00041  * 2, assign same quantum to different queue
00042  * 3, use the flowid information in the packet to disdinguish 
00043  *    different packets.
00044  * 4, it has  a Weight Spread Sequence. the WSS with MAXWSSORDER is stored statically in the memory
00045  * 5, it has the Weight Matrix. the WM can be adjusted in the processing of SRR
00046  *
00047  * for details about SRR, see:  
00048  * " SRR: An O(1) Time Complexity Scheduler for Flows in Multi-Service Packet Networks", Chuanxiong Guo, sigcomm'01.
00049  */
00050 // Ported by xuanc, 1/20/02
00051 
00052 #include "config.h"   // for string.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 //for debug 
00064 #ifndef DEBUG_SRR
00065 //#define DEBUG_SRR
00066 #endif // DEBUG_SRR
00067 
00068 // this struct is the basic element for the Weight Matrix
00069 struct wm_node
00070 {
00071         int queueid; // the queue the node belongs to 
00072         int weight;  // the weight of the node
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;   //total packets in this Queue
00085         int bcount; //count of bytes in each flow to find the max flow;
00086         int deficitCounter; // concept borrowed from DRR 
00087         int turn;    // whether the queue is on service or not 
00088         int queueid; // mark the id of this packet queue
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_; // 0 if p == tail_
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_ ;   //total number of flows allowed
00130         int blimit_;                    //total number of bytes allowed across all flows
00131         int bytecnt;                    //cumulative sum of bytes across all flows
00132         int pktcnt;                             // cumulative sum of packets across all flows
00133         int flwcnt;                             //total number of active flows
00134 
00135         int last_queueid;               // the id of the previously served queue
00136         int last_size;                  // the length of the last send packet
00137         
00138         PacketSRR srr[MAXFLOW]; //pointer to the entire srr struct
00139 
00140         int f2q[MAXFLOW];               // flow to queue mapping
00141         int private_rate[MAXFLOW];      // bandwidth for each queue
00142         int mtu_;                                       // it is used to mark the quantum adding to 
00143                                                                 // each queue
00144         int granularity_;                       // the min rate that can be allocated to a queue
00145         int maxRate;
00146         int minRate; 
00147 
00148         class WSS wss;    // wss deals with the Weight Spread Sequence.
00149                                 
00150         /*
00151          * wmHead[0] according to the least important weight,
00152          * wmHead[maxColumn] according to the most important weight
00153          */
00154         struct wm_node wmHead[MAXWSSORDER];             // each column of WM has a head
00155         struct wm_node wmTail[MAXWSSORDER];             // each column of WM has a tail 
00156         struct wm_node *pwmCurr;                                // points to the current scanning position
00157 
00158         struct wm_node *pRowHead[MAXFLOW];
00159         struct wm_node *pRowTail[MAXFLOW];
00160 
00161 
00162         int wmEmptyFlag;                                                // 0: WM is not empty, 1:WM is empty
00163 
00164         int maxColumn;          // the max column number of the WM, so there are total 
00165                                                 // maxColumn+1 columns, the column number is numbered from 0 to 
00166                                                 // maxColumn from left to right.
00167         int currMaxColumn;      // the current max number of the column
00168         
00169         int min_quantum;
00170 
00171         inline PacketSRR *getMaxflow () { //returns flow with max bytes 
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         //returns queuelength in packets
00194         inline int length () {
00195                 return pktcnt;
00196         }
00197 
00198         //returns queuelength in bytes
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;             //1000 bytes quantum at default setting
00222         granularity_ = 1000;    //default to 1K bit/s  
00223 
00224         last_queueid = -1; // -1 means that SRR does not have a previous deque operation        
00225         last_size = 0;
00226 
00227         flwcnt = 0;  // init 
00228         bytecnt = 0;
00229         pktcnt = 0;
00230         min_quantum = 1000;
00231 
00232         pwmCurr = 0; // at first, pwmCurr points to NULL
00233 
00234         for(i=0; i<MAXFLOW; i++)
00235         {
00236                 private_rate[i] = granularity_; //default quantum value for each flow
00237                 f2q[i]=0;                // default queue id for all the flow
00238                                          // or it will not works right at the default config
00239         }
00240 
00241         maxRate = 100000000; //100Mbps
00242         minRate = 1000; //1kbps 
00243 
00244         // init the WM double queues here too.
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; // it is empty at first
00258         wss.init(MAXWSSORDER); // create the Weight Spread Sequence
00259 
00260         currMaxColumn = -1;
00261         maxColumn=0;
00262         
00263         // allow the TCL scripts to change the following values
00264         bind("maxqueuenumber_",&maxqueuenumber_);  //it is the max queuenumber set in the TCL script
00265         bind("mtu_", &mtu_);      // set the Max Transfer Unit of the output link
00266         bind("granularity_", &granularity_); // set the rate allocation granularity of the 
00267                                 // all the flows. 
00268         bind("blimit_",&blimit_);
00269 }
00270 
00271 
00272 // enque and deque are two interface functions that provided by 
00273 // NS 
00274 void SRR::enque(Packet* pkt)
00275 {
00276         PacketSRR *q;
00277         //PacketSRR *remq;
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();          //get the flowid
00285         queueid= f2q[flowid];   // get the corresponding queue id
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 // we drop packets from the longest queue
00299 /*      if( bytecnt+ ch->size() > blimit_){
00300 
00301                 drop(pkt);
00302                 return;
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                         //add to the WM
00325                         // adjust currMaxColumn
00326                         // if it is a first active flow, put the pwmPtr
00327                         // all the above works are done in add_to_WM
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 //      static int dcnt = 0;
00347 
00348 //      if(dcnt <20){   
00349 //      printf(" in dequeue: %lf \n",  Scheduler::instance().clock() ); 
00350 //      dcnt++;
00351 //      }
00352 #ifdef DEBUG_SRR
00353 printf("  in deque\n");
00354 #endif
00355 
00356         if(last_queueid>=0){
00357 //printf("last size=%d\n ", last_size);
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                                 // delete the queue from SRR
00368                                 del_from_WM(last_queueid, private_rate[last_queueid]/granularity_ );
00369                         }
00370 
00371         }       
00372 
00373 assert(pktcnt>=0);
00374         if (pktcnt==0) {
00375         //      fprintf (stderr,"No active flow\n");
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 //printf("pktcnt=%d\n", pktcnt);
00386 
00387         while (!pkt) {
00388 
00389                 if(pwmCurr->queueid==-1){ // it should never happen
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]; // get the corresponding queue id
00409 
00410 assert(queueid== pwmCurr->queueid);
00411         
00412                 if (!pP->turn) {
00413                         pP->deficitCounter+= mtu_; // each queue shares the same quantum!
00414                                         // this is the difference between DRR!
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 //                      pP->bcount -= ch->size();
00426 //                      --pP->pkts;
00427 //                      --pktcnt;
00428 //                      bytecnt -= ch->size();
00429 //                      if (pP->pkts == 0) {
00430 //                              pP->turn=0;
00431 //                              pP->deficitCounter=0;
00432 
00433                                 // delete the queue from SRR
00434 //                              del_from_WM(queueid, private_rate[queueid]/granularity_ );
00435                                 //getNextNode();
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                         // pwmCurr should be adjusted.
00449                         getNextNode( );
00450                         pkt=0;
00451                 }
00452         }
00453         return 0;    // not reached
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 // weight is the queues rate/granularity.
00474 int SRR::add_to_WM(int queueid, int weight)
00475 {
00476         struct wm_node *pNode;
00477         int i;
00478         //int j=maxColumn;
00479         //int temp=weight;
00480         //int flag=0;
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         // add to the WM
00497         // adjust currMaxColumn
00498         // if it is a first active flow, put the pwmPtr
00499 
00500         
00501         for(i=maxColumn; i>=0; i--)
00502         {
00503 
00504                 if (weight & (1<<i) )
00505                 {  
00506                         // 
00507                         // add to queueid= i; wmHead[queueid], wmTail[queueid]
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; // adjust the current max column number
00544                         
00545                         if(wmEmptyFlag == 1)
00546                         {
00547                                 wmEmptyFlag=0;
00548                                 if(pwmCurr == NULL) // we should let it points to the correct place.
00549                                         pwmCurr=pNode;
00550                         }
00551 
00552                 }
00553         }
00554         
00555         if (  old_colno < currMaxColumn )
00556         {
00557                 if(old_colno >= 0){
00558         //      if(old_colno > 0){
00559                         int pc = wss.get_ptr () + 1;
00560                         pc = pc << (currMaxColumn - old_colno);
00561                         wss.set_ptr ( pc -1);
00562                 //      printf("set_ptr in add_to_wm: ptr:%d\n", pc-1);
00563                 //      printf("old column no: %d %d\n", old_colno, currMaxColumn);
00564                 }
00565         }
00566 
00567         //printf("in add_to_wm: k:%d, j:%d\n", currMaxColumn, old_colno);       
00568         ++flwcnt;
00569         return 0;
00570 }
00571 
00572 
00573 //remove the wm_node from the links and free the memory
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)  // we adjust pwmCurr before we delete the row
00583         { 
00584                 if (pwmCurr->next != &wmTail[pwmCurr->weight])
00585                         pwmCurr = pwmCurr->next ;
00586                 else pwmCurr = NULL;
00587         }
00588 
00589         /*
00590         for(i=0;i<=currMaxColumn;i++) // travel all double links, and delete the node whose id is queueid
00591         { 
00592                 pNode=wmHead[i].next;
00593 
00594                 while(pNode!=&wmTail[i]){
00595                         if(pNode->queueid==queueid){ //yes, we get one.
00596                                 //remove it from the link, and free the node.
00597                                 (pNode->prev)->next=pNode->next;
00598                                 (pNode->next)->prev=pNode->prev;
00599                                 free(pNode);
00600 
00601                                 break;
00602                         }
00603                         else
00604                                 pNode=pNode->next;
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 // we should adjust currMaxColumn, 
00623 //and if currMaxColumn becomes less, we should also adjust WSS's pointer
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                 // it is empty now.
00639 #ifdef DEBUG_SRR
00640 //printf("WM empty\n");
00641 #endif
00642                 wmEmptyFlag=1;
00643                 currMaxColumn=-1;
00644                 pwmCurr=NULL;
00645                 last_queueid=-1;
00646                 wss.set_ptr (0); // reset the WSS sequence pointer to 0;
00647                 goto rr;
00648         } else if ( currMaxColumn < old_colno)
00649         {
00650                 int pc = wss.get_ptr () +1;
00651                 //printf("pc = %d \n", pc);
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                 //printf("set_ptr in del_from__wm: ptr:%d\n", tmpc-1);
00662                 //printf("k:%d j:%d\n", currMaxColumn, old_colno);
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                 // try to point pwmCurr to the right place.
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 /* should be checked:
00687  * whether it returns nothing when the WM is empty
00688  */
00689 struct wm_node *SRR::getNextNode(){
00690   //struct wm_node *pNode;
00691   int queueid;
00692   int weight;
00693   int wss_term;
00694   int temp;
00695 
00696 
00697         if(bytecnt==0){
00698                 //      printf("getNextNode, pwmCurr = NULL, wmEmptyFlag=%d\n", wmEmptyFlag);
00699                 return NULL;
00700         }
00701 
00702         queueid=pwmCurr->queueid;
00703         weight= pwmCurr->weight;
00704 
00705         if(pwmCurr->next != &wmTail[weight]){ // not the tail 
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                 // wss_term according to currMaxColumn+1-wss_term queue
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  *Allows one to change 
00744  *      blimit_  
00745  *      maxqueuenumber_ 
00746  *      mtu_
00747  *      granularity_
00748  *      for a particular srrQ :
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                         //clear();
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                         /*if(private_rate[queue]%granularity_)
00814                                 success++;*/
00815                         temp=getOrder(success);  //now we have the order of the WSS
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)){ //the order of max band flow is too big!
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 

Generated on Tue Apr 20 12:14:33 2004 for NS2.26SourcesOriginal by doxygen 1.3.3