dsred.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2000 Nortel Networks
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 Nortel Networks.
00016  * 4. The name of the Nortel Networks may not be used
00017  *    to endorse or promote products derived from this software without
00018  *    specific prior written permission.
00019  * 
00020  * THIS SOFTWARE IS PROVIDED BY NORTEL AND CONTRIBUTORS ``AS IS'' AND
00021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023  * ARE DISCLAIMED.  IN NO EVENT SHALL NORTEL OR CONTRIBUTORS BE LIABLE
00024  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00025  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00026  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00027  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00029  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * Developed by: Farhan Shallwani, Jeremy Ethridge
00033  *               Peter Pieda, and Mandeep Baines
00034  * Maintainer: Peter Pieda <ppieda@nortelnetworks.com>
00035  */
00036 
00037 #include <stdio.h>
00038 #include "ip.h"
00039 #include "dsred.h"
00040 #include "delay.h"
00041 #include "random.h"
00042 #include "flags.h"
00043 #include "tcp.h"
00044 #include "dsredq.h"
00045 
00046 
00047 /*------------------------------------------------------------------------------
00048 dsREDClass declaration. 
00049     Links the new class in the TCL heirarchy.  See "Notes And Documentation for 
00050 ns-2."
00051 ------------------------------------------------------------------------------*/
00052 static class dsREDClass : public TclClass {
00053 public:
00054     dsREDClass() : TclClass("Queue/dsRED") {}
00055     TclObject* create(int, const char*const*) {
00056         return (new dsREDQueue);
00057     }
00058 } class_dsred;
00059 
00060 
00061 /*------------------------------------------------------------------------------
00062 dsREDQueue() Constructor.
00063     Initializes the queue.  Note that the default value assigned to numQueues 
00064 in tcl/lib/ns-default.tcl must be no greater than MAX_QUEUES (the physical 
00065 queue array size).
00066 ------------------------------------------------------------------------------*/
00067 dsREDQueue::dsREDQueue() : de_drop_(NULL), link_(NULL)   {
00068   bind("numQueues_", &numQueues_);
00069   bind_bool("ecn_", &ecn_);
00070   int i;
00071   
00072   numPrec = MAX_PREC;
00073   schedMode = schedModeRR;
00074   
00075   for(i=0;i<MAX_QUEUES;i++){
00076     queueMaxRate[i] = 0;
00077     queueWeight[i]=1;
00078   }
00079   
00080   queuesDone = MAX_QUEUES;
00081   phbEntries = 0;       // Number of entries in PHB table
00082   
00083   reset();
00084 }
00085 
00086 // RED queues initilization
00087 void dsREDQueue::reset() {
00088   int i;
00089   
00090   qToDq = 0;        // q to be dequed, initialized to 0 
00091   
00092   for(i=0;i<MAX_QUEUES;i++){
00093     queueAvgRate[i] = 0.0;
00094     queueArrTime[i] = 0.0;
00095     slicecount[i]=0;
00096     pktcount[i]=0;
00097     wirrTemp[i]=0;
00098     wirrqDone[i]=0;
00099   }
00100   
00101   stats.drops = 0;
00102   stats.edrops = 0;
00103   stats.pkts = 0;
00104   
00105   for(i=0;i<MAX_CP;i++){
00106     stats.drops_CP[i]=0;
00107     stats.edrops_CP[i]=0;
00108     stats.pkts_CP[i]=0;
00109   }
00110   
00111   for (i = 0; i < MAX_QUEUES; i++)
00112     redq_[i].qlim = limit();
00113   
00114   // Compute the "packet time constant" if we know the
00115   // link bandwidth.  The ptc is the max number of (avg sized)
00116   // pkts per second which can be placed on the link.
00117   if (link_)
00118     for (int i = 0; i < MAX_QUEUES; i++)
00119       redq_[i].setPTC(link_->bandwidth());
00120   
00121   Queue::reset();
00122 }
00123 
00124 
00125 /*-----------------------------------------------------------------------------
00126 void edrop(Packet* pkt)
00127     This method is used so that flowmonitor can monitor early drops.
00128 -----------------------------------------------------------------------------*/
00129 void dsREDQueue::edrop(Packet* p)
00130 {
00131 
00132     if (de_drop_ != 0){
00133         de_drop_->recv(p);
00134     }
00135     else {
00136         drop(p);
00137     }
00138 }
00139 
00140 /*-----------------------------------------------------------------------------
00141 void applyTSWMeter(int q_id, int pkt_size)
00142 Update the average rate for a physical Q (indicated by q_id).
00143 Pre: policy's variables avgRate, arrivalTime, and winLen hold valid values;
00144   pkt_size specifies the bytes just dequeued (0 means no packet dequeued).
00145 Post: Adjusts policy's TSW state variables avgRate and arrivalTime 
00146   (also called tFront) according to the bytes sent.
00147 Note: See the paper "Explicit Allocation of Best effor Delivery Service" (David
00148   Clark and Wenjia Fang), Section 3.3, for a description of the TSW Tagger.
00149 -----------------------------------------------------------------------------*/
00150 void dsREDQueue::applyTSWMeter(int q_id, int pkt_size) {
00151   double now, bytesInTSW, newBytes;
00152   double winLen = 1.0;
00153 
00154   bytesInTSW = queueAvgRate[q_id] * winLen;
00155 
00156   // Modified by xuanc(xuanc@isi.edu) Oct 18, 2001, 
00157   // referring to the patch contributed by 
00158   // Sergio Andreozzi <sergio.andreozzi@lut.fi>
00159   newBytes = bytesInTSW + pkt_size;
00160 
00161   // Calculate the average rate (SW)
00162   now = Scheduler::instance().clock();
00163   queueAvgRate[q_id] = newBytes / (now - queueArrTime[q_id] + winLen);
00164   queueArrTime[q_id] = now;
00165 }
00166 
00167 
00168 /*-----------------------------------------------------------------------------
00169 void enque(Packet* pkt) 
00170     The following method outlines the enquing mechanism for a Diffserv router.
00171 This method is not used by the inheriting classes; it only serves as an 
00172 outline.
00173 -----------------------------------------------------------------------------*/
00174 void dsREDQueue::enque(Packet* pkt) {
00175   int codePt, eq_id, prec;
00176   hdr_ip* iph = hdr_ip::access(pkt);
00177   //extracting the marking done by the edge router
00178   codePt = iph->prio(); 
00179   int ecn = 0;
00180   
00181   //looking up queue and prec numbers for that codept
00182   lookupPHBTable(codePt, &eq_id, &prec);    
00183 
00184   // code added for ECN support
00185   //hdr_flags* hf = (hdr_flags*)(pkt->access(off_flags_));
00186   // Changed for the latest version instead of 2.1b6
00187   hdr_flags* hf = hdr_flags::access(pkt);
00188 
00189   if (ecn_ && hf->ect()) ecn = 1;
00190   
00191   stats.pkts_CP[codePt]++;
00192   stats.pkts++;
00193   
00194   switch(redq_[eq_id].enque(pkt, prec, ecn)) {
00195   case PKT_ENQUEUED:
00196     break;
00197   case PKT_DROPPED:
00198     stats.drops_CP[codePt]++;
00199     stats.drops++;
00200     drop(pkt);
00201          break;
00202   case PKT_EDROPPED:
00203     stats.edrops_CP[codePt]++;
00204     stats.edrops++;
00205     edrop(pkt);
00206     break;
00207   case PKT_MARKED:
00208     hf->ce() = 1;   // mark Congestion Experienced bit      
00209     break;          
00210   default:
00211     break;
00212   }
00213 }
00214 
00215 // Dequing mechanism for both edge and core router.
00216 Packet* dsREDQueue::deque() {
00217   Packet *p = NULL;
00218   int queue, prec;
00219   hdr_ip* iph;
00220   int fid;
00221   int dq_id;
00222 
00223   // Select queue to deque under the scheduling scheme specified.
00224   dq_id = selectQueueToDeque();
00225   
00226   // Dequeue a packet from the underlying queue:
00227   if (dq_id < numQueues_) 
00228     p = redq_[dq_id].deque();
00229   
00230   if (p) { 
00231     iph= hdr_ip::access(p);
00232     fid = iph->flowid()/32;
00233     pktcount[dq_id]+=1;
00234     
00235     // update the average rate for pri-queue
00236     // Modified by xuanc(xuanc@isi.edu) Oct 18, 2001, 
00237     // referring to the patch contributed by 
00238     // Sergio Andreozzi <sergio.andreozzi@lut.fi>
00239     // When there is a packet dequeued, 
00240     // update the average rate of each queue ()
00241     if (schedMode==schedModePRI) 
00242       for (int i=0;i<numQueues_;i++) 
00243     if (queueMaxRate[i]) 
00244       applyTSWMeter(i, (i == dq_id) ? hdr_cmn::access(p)->size() : 0); 
00245 
00246     // Get the precedence level (or virtual queue id)
00247     // for the packet dequeued.
00248     lookupPHBTable(getCodePt(p), &queue, &prec);
00249     
00250     // decrement virtual queue length
00251     // Previously in updateREDStateVar, moved by xuanc (12/03/01)
00252     //redq_[dq_id].qParam_[prec].qlen--;    
00253     redq_[dq_id].updateVREDLen(prec);   
00254     // update state variables for that "virtual" queue
00255     redq_[dq_id].updateREDStateVar(prec);
00256   }
00257   
00258   // Return the dequed packet:  
00259   return(p);
00260 }
00261 
00262 //    Extracts the code point marking from packet header.
00263 int dsREDQueue::getCodePt(Packet *p) {
00264   hdr_ip* iph = hdr_ip::access(p);
00265   return(iph->prio());
00266 }
00267 
00268 // Reutrn the id of physical queue to be dequeued
00269 int dsREDQueue::selectQueueToDeque() {
00270   // If the queue to be dequed has no elements, 
00271   // look for the next queue in line
00272   int i = 0;
00273   
00274   // Round-Robin
00275   if(schedMode==schedModeRR){
00276     //printf("RR\n");
00277     qToDq = ((qToDq + 1) % numQueues_);
00278     while ((i < numQueues_) && (redq_[qToDq].getRealLength() == 0)) {
00279       qToDq = ((qToDq + 1) % numQueues_);           
00280       i++;
00281     }
00282   } else if (schedMode==schedModeWRR) { // Weighted Round Robin
00283     if(wirrTemp[qToDq]<=0){
00284       qToDq = ((qToDq + 1) % numQueues_);
00285       wirrTemp[qToDq] = queueWeight[qToDq] - 1;
00286     } else {
00287       wirrTemp[qToDq] = wirrTemp[qToDq] -1;
00288     }           
00289     while ((i < numQueues_) && (redq_[qToDq].getRealLength() == 0)) {
00290       wirrTemp[qToDq] = 0;
00291       qToDq = ((qToDq + 1) % numQueues_);
00292       wirrTemp[qToDq] = queueWeight[qToDq] - 1;
00293       i++;
00294     }
00295   } else if (schedMode==schedModeWIRR) {
00296     qToDq = ((qToDq + 1) % numQueues_);
00297     while ((i<numQueues_) && ((redq_[qToDq].getRealLength()==0) || (wirrqDone[qToDq]))) {
00298       if (!wirrqDone[qToDq]) {
00299     queuesDone++;
00300     wirrqDone[qToDq]=1;
00301       }
00302       qToDq = ((qToDq + 1) % numQueues_);
00303       i++;
00304     }
00305     
00306     if (wirrTemp[qToDq] == 1) {
00307       queuesDone +=1;
00308       wirrqDone[qToDq]=1;
00309     }
00310     wirrTemp[qToDq]-=1;
00311     if(queuesDone >= numQueues_) {
00312       queuesDone = 0;
00313       for(i=0;i<numQueues_;i++) {
00314     wirrTemp[i] = queueWeight[i];
00315     wirrqDone[i]=0;
00316       }     
00317     }
00318   } else if (schedMode==schedModePRI) {
00319     // Find the queue with highest priority, which satisfies:
00320     // 1. nozero queue length; and either
00321     // 2.1. has no MaxRate specified; or
00322     // 2.2. has MaxRate specified and 
00323     //          its average rate is not beyond that limit.
00324     i = 0;
00325     while (i < numQueues_ && 
00326        (redq_[i].getRealLength() == 0 ||
00327         (queueMaxRate[i] && queueAvgRate[i]>queueMaxRate[i]))){
00328       i++;
00329     }
00330     qToDq = i;
00331 
00332     // If no queue satisfies the condition above,
00333     // find the Queue with highest priority, 
00334     // which has packet to dequeue.
00335     // NOTE: the high priority queue can still have its packet dequeued
00336     //       even if its average rate has beyond the MAX rate specified!
00337     //       Ideally, a NO_PACKET_TO_DEQUEUE should be returned.
00338     if (i == numQueues_) {
00339       i = qToDq = 0;
00340       while ((i < numQueues_) && (redq_[qToDq].getRealLength() == 0)) {
00341     qToDq = ((qToDq + 1) % numQueues_);
00342     i++;
00343       }
00344     }
00345   }
00346   return(qToDq);
00347 }   
00348 
00349 /*-----------------------------------------------------------------------------
00350 void lookupPHBTable(int codePt, int* queue, int* prec)
00351     Assigns the queue and prec parameters values corresponding to a given code 
00352 point.  The code point is assumed to be present in the PHB table.  If it is 
00353 not, an error message is outputted and queue and prec are undefined.
00354 -----------------------------------------------------------------------------*/
00355 void dsREDQueue::lookupPHBTable(int codePt, int* queue, int* prec) {
00356   for (int i = 0; i < phbEntries; i++) {
00357     if (phb_[i].codePt_ == codePt) {
00358       *queue = phb_[i].queue_;
00359       *prec = phb_[i].prec_;
00360       return;
00361     }
00362   }
00363   // quiet the compiler
00364   *queue = 0;
00365   *prec = 0;
00366   printf("ERROR: No match found for code point %d in PHB Table.\n", codePt);
00367   assert (false);
00368 }
00369 
00370 /*-----------------------------------------------------------------------------
00371 void addPHBEntry(int codePt, int queue, int prec)
00372     Add a PHB table entry.  (Each entry maps a code point to a queue-precedence
00373 pair.)
00374 -----------------------------------------------------------------------------*/
00375 void dsREDQueue::addPHBEntry(int codePt, int queue, int prec) {
00376   if (phbEntries == MAX_CP) {
00377     printf("ERROR: PHB Table size limit exceeded.\n");
00378   } else {
00379     phb_[phbEntries].codePt_ = codePt;
00380     phb_[phbEntries].queue_ = queue;
00381     phb_[phbEntries].prec_ = prec;
00382     stats.valid_CP[codePt] = 1;
00383     phbEntries++;
00384   }
00385 }
00386 
00387 /*-----------------------------------------------------------------------------
00388 void addPHBEntry(int codePt, int queue, int prec)
00389     Add a PHB table entry.  (Each entry maps a code point to a queue-precedence
00390 pair.)
00391 -----------------------------------------------------------------------------*/
00392 double dsREDQueue::getStat(int argc, const char*const* argv) {
00393 
00394     if (argc == 3) {
00395         if (strcmp(argv[2], "drops") == 0)
00396          return (stats.drops*1.0);
00397         if (strcmp(argv[2], "edrops") == 0)
00398          return (stats.edrops*1.0);
00399         if (strcmp(argv[2], "pkts") == 0)
00400          return (stats.pkts*1.0);
00401    }
00402     if (argc == 4) {
00403         if (strcmp(argv[2], "drops") == 0)
00404          return (stats.drops_CP[atoi(argv[3])]*1.0);
00405         if (strcmp(argv[2], "edrops") == 0)
00406          return (stats.edrops_CP[atoi(argv[3])]*1.0);
00407         if (strcmp(argv[2], "pkts") == 0)
00408          return (stats.pkts_CP[atoi(argv[3])]*1.0);
00409     }
00410     return -1.0;
00411 }
00412 
00413 
00414 /*------------------------------------------------------------------------------
00415 void setNumPrec(int prec) 
00416     Sets the current number of drop precendences.  The number of precedences is
00417 the number of virtual queues per physical queue.
00418 ------------------------------------------------------------------------------*/
00419 void dsREDQueue::setNumPrec(int prec) {
00420     int i;
00421 
00422     if (prec > MAX_PREC) {
00423         printf("ERROR: Cannot declare more than %d prcedence levels (as defined by MAX_PREC)\n",MAX_PREC);
00424     } else {
00425         numPrec = prec;
00426 
00427         for (i = 0; i < MAX_QUEUES; i++)
00428             redq_[i].numPrec = numPrec;
00429     }
00430 }
00431 
00432 /*------------------------------------------------------------------------------
00433 void setMREDMode(const char* mode)
00434    sets up the average queue accounting mode.
00435 ----------------------------------------------------------------------------*/
00436 void dsREDQueue::setMREDMode(const char* mode, const char* queue) {
00437   int i;
00438   mredModeType tempMode;
00439   
00440   if (strcmp(mode, "RIO-C") == 0)
00441     tempMode = rio_c;
00442   else if (strcmp(mode, "RIO-D") == 0)
00443     tempMode = rio_d;
00444   else if (strcmp(mode, "WRED") == 0)
00445     tempMode = wred;
00446   else if (strcmp(mode, "DROP") == 0)
00447     tempMode = dropTail;
00448   else {
00449     printf("Error: MRED mode %s does not exist\n",mode);
00450     return;
00451   }
00452   
00453   if (!queue)
00454     for (i = 0; i < MAX_QUEUES; i++)
00455       redq_[i].mredMode = tempMode;
00456   else
00457     redq_[atoi(queue)].mredMode = tempMode;
00458 }
00459 
00460 
00461 /*------------------------------------------------------------------------------
00462 void printPHBTable()
00463     Prints the PHB Table, with one entry per line.
00464 ------------------------------------------------------------------------------*/
00465 void dsREDQueue::printPHBTable() {
00466    printf("PHB Table:\n");
00467    for (int i = 0; i < phbEntries; i++)
00468       printf("Code Point %d is associated with Queue %d, Precedence %d\n", phb_[i].codePt_, phb_[i].queue_, phb_[i].prec_);
00469    printf("\n");
00470 }
00471 
00472 
00473 /*------------------------------------------------------------------------------
00474 void printStats()
00475     An output method that may be altered to assist debugging.
00476 ------------------------------------------------------------------------------*/
00477 void dsREDQueue::printStats() {
00478     printf("\nPackets Statistics\n");
00479     printf("=======================================\n");
00480     printf(" CP  TotPkts   TxPkts   ldrops   edrops\n");
00481     printf(" --  -------   ------   ------   ------\n");
00482     printf("All %8ld %8ld %8ld %8ld\n",stats.pkts,stats.pkts-stats.drops-stats.edrops,stats.drops,stats.edrops);
00483     for (int i = 0; i < MAX_CP; i++)
00484         if (stats.pkts_CP[i] != 0)
00485             printf("%3d %8ld %8ld %8ld %8ld\n",i,stats.pkts_CP[i],stats.pkts_CP[i]-stats.drops_CP[i]-stats.edrops_CP[i],stats.drops_CP[i],stats.edrops_CP[i]);
00486 
00487 }
00488 
00489 
00490 void dsREDQueue::printWRRcount() {
00491    int i;
00492    for (i = 0; i < numQueues_; i++){
00493       printf("%d: %d %d %d.\n", i, slicecount[i],pktcount[i],queueWeight[i]);
00494    }
00495 }
00496 
00497 
00498 /*------------------------------------------------------------------------------
00499 void setSchedularMode(int schedtype)
00500    sets up the schedular mode.
00501 ----------------------------------------------------------------------------*/
00502 void dsREDQueue::setSchedularMode(const char* schedtype) {
00503     if (strcmp(schedtype, "RR") == 0)
00504     schedMode = schedModeRR;
00505     else if (strcmp(schedtype, "WRR") == 0)
00506         schedMode = schedModeWRR;
00507     else if (strcmp(schedtype, "WIRR") == 0)
00508         schedMode = schedModeWIRR;
00509     else if (strcmp(schedtype, "PRI") == 0)
00510         schedMode = schedModePRI;
00511     else
00512         printf("Error: Scheduler type %s does not exist\n",schedtype);
00513 }
00514 
00515 
00516 /*------------------------------------------------------------------------------
00517 void addQueueWeights(int queueNum, int weight)
00518    An input method to set the individual Queue Weights.
00519 ----------------------------------------------------------------------------*/
00520 void dsREDQueue::addQueueWeights(int queueNum, int weight) {
00521   if(queueNum < MAX_QUEUES){
00522     queueWeight[queueNum]=weight;
00523   } else {
00524     printf("The queue number is out of range.\n");
00525   }
00526 }
00527 
00528 //Set the individual Queue Max Rates for Priority Queueing.
00529 void dsREDQueue::addQueueRate(int queueNum, int rate) {
00530   if(queueNum < MAX_QUEUES){
00531     // Convert to BYTE/SECOND
00532     queueMaxRate[queueNum]=(double)rate/8.0;
00533   } else {
00534     printf("The queue number is out of range.\n");
00535   }
00536 }
00537 
00538 /*-----------------------------------------------------------------------------
00539 int command(int argc, const char*const* argv)
00540     Commands from the ns file are interpreted through this interface.
00541 -----------------------------------------------------------------------------*/
00542 int dsREDQueue::command(int argc, const char*const* argv) {
00543   if (strcmp(argv[1], "configQ") == 0) {
00544     // modification to set the parameter q_w by Thilo
00545     redq_[atoi(argv[2])].config(atoi(argv[3]), argc, argv);
00546     return(TCL_OK);
00547   }
00548   if (strcmp(argv[1], "addPHBEntry") == 0) {
00549     addPHBEntry(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
00550     return (TCL_OK);
00551   }
00552   if (strcmp(argv[1], "meanPktSize") == 0) {
00553     for (int i = 0; i < MAX_QUEUES; i++)
00554       redq_[i].setMPS(atoi(argv[2]));
00555     return(TCL_OK);
00556   }
00557   if (strcmp(argv[1], "setNumPrec") == 0) {
00558     setNumPrec(atoi(argv[2]));
00559     return(TCL_OK);
00560   }
00561   if (strcmp(argv[1], "getAverage") == 0) {
00562     Tcl& tcl = Tcl::instance();
00563     tcl.resultf("%f", redq_[atoi(argv[2])].getWeightedLength());
00564     return(TCL_OK);
00565   }
00566   if (strcmp(argv[1], "getStat") == 0) {
00567     Tcl& tcl = Tcl::instance();
00568     tcl.resultf("%f", getStat(argc,argv));
00569     return(TCL_OK);
00570   }
00571   if (strcmp(argv[1], "getCurrent") == 0) {
00572     Tcl& tcl = Tcl::instance();
00573     tcl.resultf("%f", redq_[atoi(argv[2])].getRealLength()*1.0);
00574     return(TCL_OK);
00575   }
00576   if (strcmp(argv[1], "printStats") == 0) {
00577     printStats();
00578     return (TCL_OK);
00579   }
00580   if (strcmp(argv[1], "printWRRcount") == 0) {
00581     printWRRcount();
00582     return (TCL_OK);
00583   }
00584   if (strcmp(argv[1], "printPHBTable") == 0) {
00585     printPHBTable();
00586     return (TCL_OK);
00587   }
00588   if (strcmp(argv[1], "link") == 0) {
00589     Tcl& tcl = Tcl::instance();
00590     LinkDelay* del = (LinkDelay*) TclObject::lookup(argv[2]);
00591     if (del == 0) {
00592       tcl.resultf("RED: no LinkDelay object %s",
00593           argv[2]);
00594       return(TCL_ERROR);
00595     }
00596     link_ = del;
00597     return (TCL_OK);
00598   }
00599   if (strcmp(argv[1], "early-drop-target") == 0) {
00600     Tcl& tcl = Tcl::instance();
00601     NsObject* p = (NsObject*)TclObject::lookup(argv[2]);
00602     if (p == 0) {
00603       tcl.resultf("no object %s", argv[2]);
00604       return (TCL_ERROR);
00605     }
00606     de_drop_ = p;
00607     return (TCL_OK);
00608   }
00609   if (strcmp(argv[1], "setSchedularMode") == 0) {
00610     setSchedularMode(argv[2]);
00611     return(TCL_OK);
00612   }
00613   if (strcmp(argv[1], "setMREDMode") == 0) {
00614     if (argc == 3)
00615       setMREDMode(argv[2],0);
00616     else
00617       setMREDMode(argv[2],argv[3]);
00618     return(TCL_OK);
00619   }
00620   if (strcmp(argv[1], "addQueueWeights") == 0) {
00621     addQueueWeights(atoi(argv[2]), atoi(argv[3]));
00622     return(TCL_OK);
00623   }
00624   if (strcmp(argv[1], "addQueueRate") == 0) {
00625     addQueueRate(atoi(argv[2]), atoi(argv[3]));
00626     return(TCL_OK);
00627   }
00628   // Returns the weighted RED queue length for one virtual queue in packets
00629   // Added by Thilo
00630   if (strcmp(argv[1], "getAverageV") == 0) {
00631     Tcl& tcl = Tcl::instance();
00632     tcl.resultf("%f",
00633         redq_[atoi(argv[2])].getWeightedLength_v(atoi(argv[3])));
00634     return(TCL_OK);
00635   } 
00636   // Returns the length of one virtual queue, in packets 
00637   // Added by Thilo
00638   if (strcmp(argv[1], "getCurrentV") == 0) {
00639     Tcl& tcl = Tcl::instance();
00640     tcl.resultf("%f",
00641         redq_[atoi(argv[2])].getRealLength_v(atoi(argv[3]))*1.0);
00642     return(TCL_OK);
00643   }
00644 
00645   return(Queue::command(argc, argv));
00646 }
00647 
00648 

Generated on Tue Mar 6 16:47:44 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6