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

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   printf("ERROR: No match found for code point %d in PHB Table.\n", codePt);
00364 }
00365 
00366 /*-----------------------------------------------------------------------------
00367 void addPHBEntry(int codePt, int queue, int prec)
00368     Add a PHB table entry.  (Each entry maps a code point to a queue-precedence
00369 pair.)
00370 -----------------------------------------------------------------------------*/
00371 void dsREDQueue::addPHBEntry(int codePt, int queue, int prec) {
00372   if (phbEntries == MAX_CP) {
00373     printf("ERROR: PHB Table size limit exceeded.\n");
00374   } else {
00375     phb_[phbEntries].codePt_ = codePt;
00376     phb_[phbEntries].queue_ = queue;
00377     phb_[phbEntries].prec_ = prec;
00378     stats.valid_CP[codePt] = 1;
00379     phbEntries++;
00380   }
00381 }
00382 
00383 /*-----------------------------------------------------------------------------
00384 void addPHBEntry(int codePt, int queue, int prec)
00385     Add a PHB table entry.  (Each entry maps a code point to a queue-precedence
00386 pair.)
00387 -----------------------------------------------------------------------------*/
00388 double dsREDQueue::getStat(int argc, const char*const* argv) {
00389 
00390         if (argc == 3) {
00391                 if (strcmp(argv[2], "drops") == 0)
00392          return (stats.drops*1.0);
00393                 if (strcmp(argv[2], "edrops") == 0)
00394          return (stats.edrops*1.0);
00395                 if (strcmp(argv[2], "pkts") == 0)
00396          return (stats.pkts*1.0);
00397    }
00398         if (argc == 4) {
00399                 if (strcmp(argv[2], "drops") == 0)
00400          return (stats.drops_CP[atoi(argv[3])]*1.0);
00401                 if (strcmp(argv[2], "edrops") == 0)
00402          return (stats.edrops_CP[atoi(argv[3])]*1.0);
00403                 if (strcmp(argv[2], "pkts") == 0)
00404          return (stats.pkts_CP[atoi(argv[3])]*1.0);
00405         }
00406         return -1.0;
00407 }
00408 
00409 
00410 /*------------------------------------------------------------------------------
00411 void setNumPrec(int prec) 
00412     Sets the current number of drop precendences.  The number of precedences is
00413 the number of virtual queues per physical queue.
00414 ------------------------------------------------------------------------------*/
00415 void dsREDQueue::setNumPrec(int prec) {
00416         int i;
00417 
00418         if (prec > MAX_PREC) {
00419                 printf("ERROR: Cannot declare more than %d prcedence levels (as defined by MAX_PREC)\n",MAX_PREC);
00420         } else {
00421                 numPrec = prec;
00422 
00423                 for (i = 0; i < MAX_QUEUES; i++)
00424                         redq_[i].numPrec = numPrec;
00425         }
00426 }
00427 
00428 /*------------------------------------------------------------------------------
00429 void setMREDMode(const char* mode)
00430    sets up the average queue accounting mode.
00431 ----------------------------------------------------------------------------*/
00432 void dsREDQueue::setMREDMode(const char* mode, const char* queue) {
00433   int i;
00434   mredModeType tempMode;
00435   
00436   if (strcmp(mode, "RIO-C") == 0)
00437     tempMode = rio_c;
00438   else if (strcmp(mode, "RIO-D") == 0)
00439     tempMode = rio_d;
00440   else if (strcmp(mode, "WRED") == 0)
00441     tempMode = wred;
00442   else if (strcmp(mode, "DROP") == 0)
00443     tempMode = dropTail;
00444   else {
00445     printf("Error: MRED mode %s does not exist\n",mode);
00446     return;
00447   }
00448   
00449   if (!queue)
00450     for (i = 0; i < MAX_QUEUES; i++)
00451       redq_[i].mredMode = tempMode;
00452   else
00453     redq_[atoi(queue)].mredMode = tempMode;
00454 }
00455 
00456 
00457 /*------------------------------------------------------------------------------
00458 void printPHBTable()
00459     Prints the PHB Table, with one entry per line.
00460 ------------------------------------------------------------------------------*/
00461 void dsREDQueue::printPHBTable() {
00462    printf("PHB Table:\n");
00463    for (int i = 0; i < phbEntries; i++)
00464       printf("Code Point %d is associated with Queue %d, Precedence %d\n", phb_[i].codePt_, phb_[i].queue_, phb_[i].prec_);
00465    printf("\n");
00466 }
00467 
00468 
00469 /*------------------------------------------------------------------------------
00470 void printStats()
00471     An output method that may be altered to assist debugging.
00472 ------------------------------------------------------------------------------*/
00473 void dsREDQueue::printStats() {
00474         printf("\nPackets Statistics\n");
00475         printf("=======================================\n");
00476         printf(" CP  TotPkts   TxPkts   ldrops   edrops\n");
00477         printf(" --  -------   ------   ------   ------\n");
00478         printf("All %8ld %8ld %8ld %8ld\n",stats.pkts,stats.pkts-stats.drops-stats.edrops,stats.drops,stats.edrops);
00479         for (int i = 0; i < MAX_CP; i++)
00480                 if (stats.pkts_CP[i] != 0)
00481                         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]);
00482 
00483 }
00484 
00485 
00486 void dsREDQueue::printWRRcount() {
00487    int i;
00488    for (i = 0; i < numQueues_; i++){
00489       printf("%d: %d %d %d.\n", i, slicecount[i],pktcount[i],queueWeight[i]);
00490    }
00491 }
00492 
00493 
00494 /*------------------------------------------------------------------------------
00495 void setSchedularMode(int schedtype)
00496    sets up the schedular mode.
00497 ----------------------------------------------------------------------------*/
00498 void dsREDQueue::setSchedularMode(const char* schedtype) {
00499         if (strcmp(schedtype, "RR") == 0)
00500         schedMode = schedModeRR;
00501         else if (strcmp(schedtype, "WRR") == 0)
00502                 schedMode = schedModeWRR;
00503         else if (strcmp(schedtype, "WIRR") == 0)
00504                 schedMode = schedModeWIRR;
00505         else if (strcmp(schedtype, "PRI") == 0)
00506                 schedMode = schedModePRI;
00507         else
00508                 printf("Error: Scheduler type %s does not exist\n",schedtype);
00509 }
00510 
00511 
00512 /*------------------------------------------------------------------------------
00513 void addQueueWeights(int queueNum, int weight)
00514    An input method to set the individual Queue Weights.
00515 ----------------------------------------------------------------------------*/
00516 void dsREDQueue::addQueueWeights(int queueNum, int weight) {
00517   if(queueNum < MAX_QUEUES){
00518     queueWeight[queueNum]=weight;
00519   } else {
00520     printf("The queue number is out of range.\n");
00521   }
00522 }
00523 
00524 //Set the individual Queue Max Rates for Priority Queueing.
00525 void dsREDQueue::addQueueRate(int queueNum, int rate) {
00526   if(queueNum < MAX_QUEUES){
00527     // Convert to BYTE/SECOND
00528     queueMaxRate[queueNum]=(double)rate/8.0;
00529   } else {
00530     printf("The queue number is out of range.\n");
00531   }
00532 }
00533 
00534 /*-----------------------------------------------------------------------------
00535 int command(int argc, const char*const* argv)
00536     Commands from the ns file are interpreted through this interface.
00537 -----------------------------------------------------------------------------*/
00538 int dsREDQueue::command(int argc, const char*const* argv) {
00539   if (strcmp(argv[1], "configQ") == 0) {
00540     // modification to set the parameter q_w by Thilo
00541     redq_[atoi(argv[2])].config(atoi(argv[3]), argc, argv);
00542     return(TCL_OK);
00543   }
00544   if (strcmp(argv[1], "addPHBEntry") == 0) {
00545     addPHBEntry(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
00546     return (TCL_OK);
00547   }
00548   if (strcmp(argv[1], "meanPktSize") == 0) {
00549     for (int i = 0; i < MAX_QUEUES; i++)
00550       redq_[i].setMPS(atoi(argv[2]));
00551     return(TCL_OK);
00552   }
00553   if (strcmp(argv[1], "setNumPrec") == 0) {
00554     setNumPrec(atoi(argv[2]));
00555     return(TCL_OK);
00556   }
00557   if (strcmp(argv[1], "getAverage") == 0) {
00558     Tcl& tcl = Tcl::instance();
00559     tcl.resultf("%f", redq_[atoi(argv[2])].getWeightedLength());
00560     return(TCL_OK);
00561   }
00562   if (strcmp(argv[1], "getStat") == 0) {
00563     Tcl& tcl = Tcl::instance();
00564     tcl.resultf("%f", getStat(argc,argv));
00565     return(TCL_OK);
00566   }
00567   if (strcmp(argv[1], "getCurrent") == 0) {
00568     Tcl& tcl = Tcl::instance();
00569     tcl.resultf("%f", redq_[atoi(argv[2])].getRealLength()*1.0);
00570     return(TCL_OK);
00571   }
00572   if (strcmp(argv[1], "printStats") == 0) {
00573     printStats();
00574     return (TCL_OK);
00575   }
00576   if (strcmp(argv[1], "printWRRcount") == 0) {
00577     printWRRcount();
00578     return (TCL_OK);
00579   }
00580   if (strcmp(argv[1], "printPHBTable") == 0) {
00581     printPHBTable();
00582     return (TCL_OK);
00583   }
00584   if (strcmp(argv[1], "link") == 0) {
00585     Tcl& tcl = Tcl::instance();
00586     LinkDelay* del = (LinkDelay*) TclObject::lookup(argv[2]);
00587     if (del == 0) {
00588       tcl.resultf("RED: no LinkDelay object %s",
00589                   argv[2]);
00590       return(TCL_ERROR);
00591     }
00592     link_ = del;
00593     return (TCL_OK);
00594   }
00595   if (strcmp(argv[1], "early-drop-target") == 0) {
00596     Tcl& tcl = Tcl::instance();
00597     NsObject* p = (NsObject*)TclObject::lookup(argv[2]);
00598     if (p == 0) {
00599       tcl.resultf("no object %s", argv[2]);
00600       return (TCL_ERROR);
00601     }
00602     de_drop_ = p;
00603     return (TCL_OK);
00604   }
00605   if (strcmp(argv[1], "setSchedularMode") == 0) {
00606     setSchedularMode(argv[2]);
00607     return(TCL_OK);
00608   }
00609   if (strcmp(argv[1], "setMREDMode") == 0) {
00610     if (argc == 3)
00611       setMREDMode(argv[2],0);
00612     else
00613       setMREDMode(argv[2],argv[3]);
00614     return(TCL_OK);
00615   }
00616   if (strcmp(argv[1], "addQueueWeights") == 0) {
00617     addQueueWeights(atoi(argv[2]), atoi(argv[3]));
00618     return(TCL_OK);
00619   }
00620   if (strcmp(argv[1], "addQueueRate") == 0) {
00621     addQueueRate(atoi(argv[2]), atoi(argv[3]));
00622     return(TCL_OK);
00623   }
00624   // Returns the weighted RED queue length for one virtual queue in packets
00625   // Added by Thilo
00626   if (strcmp(argv[1], "getAverageV") == 0) {
00627     Tcl& tcl = Tcl::instance();
00628     tcl.resultf("%f",
00629                 redq_[atoi(argv[2])].getWeightedLength_v(atoi(argv[3])));
00630     return(TCL_OK);
00631   } 
00632   // Returns the length of one virtual queue, in packets 
00633   // Added by Thilo
00634   if (strcmp(argv[1], "getCurrentV") == 0) {
00635     Tcl& tcl = Tcl::instance();
00636     tcl.resultf("%f",
00637                 redq_[atoi(argv[2])].getRealLength_v(atoi(argv[3]))*1.0);
00638     return(TCL_OK);
00639   }
00640 
00641   return(Queue::command(argc, argv));
00642 }
00643 
00644 

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