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

drr.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
00002  *
00003  * Copyright (c) Xerox Corporation 1997. All rights reserved.
00004  *  
00005  * License is granted to copy, to use, and to make and to use derivative
00006  * works for research and evaluation purposes, provided that Xerox is
00007  * acknowledged in all documentation pertaining to any such copy or derivative
00008  * work. Xerox grants no other licenses expressed or implied. The Xerox trade
00009  * name should not be used in any advertising without its written permission.
00010  *  
00011  * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
00012  * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
00013  * FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
00014  * express or implied warranty of any kind.
00015  *  
00016  * These notices must be retained in any copies of any part of this software.
00017  *
00018  * This file contributed by Sandeep Bajaj <bajaj@parc.xerox.com>, Mar 1997.
00019  *
00020  * $Header: /nfs/jade/vint/CVSROOT/ns-2/queue/drr.cc,v 1.10 2002/05/06 22:23:16 difa Exp $
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"   // for string.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;    //to detect collisions keep track of actual src address
00041         int bcount; //count of bytes in each flow to find the max flow;
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_ ; //total number of flows allowed
00082         int blimit_;    //total number of bytes allowed across all flows
00083         int quantum_;  //total number of bytes that a flow can send
00084         int mask_;     /*if set hashes on just the node address otherwise on 
00085                          node+port address*/
00086         int bytecnt ; //cumulative sum of bytes across all flows
00087         int pktcnt ; // cumulative sum of packets across all flows
00088         int flwcnt ; //total number of active flows
00089         PacketDRR *curr; //current active flow
00090         PacketDRR *drr ; //pointer to the entire drr struct
00091 
00092         inline PacketDRR *getMaxflow (PacketDRR *curr) { //returns flow with max pkts
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         //returns queuelength in packets
00105         inline int length () {
00106                 return pktcnt;
00107         }
00108 
00109         //returns queuelength in bytes
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         /*detect collisions here */
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                 //fprintf (stderr,"No active flow\n");
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;    // not reached
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  *Allows one to change blimit_ and bucket_ for a particular drrQ :
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; // modulo a large prime
00296 }

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