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

gk.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:4; tab-width:4; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1994 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *  This product includes software developed by the Computer Systems
00017  *  Engineering Group at 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 /* Marking scheme proposed by Gibbens and Kelly in "Resource pricing
00036    and the evolution of Internet"
00037 
00038    Central Idea:
00039    ------------
00040 
00041    The link maintains a virtual queue with the same arrivals as the
00042    real queue. However, the capacity of the virtual queue is smaller
00043    than the capacity of the real queue, i.e., set the capacity of the
00044    virtual queue, ctilde = ecnlim_ * c_. The buffer is also scaled by
00045    the same factor, i,e B_{vq} = ecnlim_ * qlim_. 
00046 
00047    When the VQ drops a packet, mark ALL the packets in the real queue
00048    as well as all the INCOMING packets till the VQ becomes empty
00049    again.
00050 
00051    Variables:
00052    ----------
00053 
00054    ecnlim_ : Fraction of the buffer size and the capacity that the VQ
00055              has.
00056          
00057    mark_flag: Indicates that the VQ overflowed and that all outgoing
00058               packets has to be marked.
00059 
00060 */ 
00061 
00062 
00063 #include "flags.h"
00064 #include "delay.h"
00065 #include "gk.h"
00066 #include "math.h"
00067 
00068 static class GKClass : public TclClass {
00069 public:
00070         GKClass() : TclClass("Queue/GK") {}
00071         TclObject* create(int argc, const char*const* argv) {
00072                 if (argc==5)
00073                         return (new GK(argv[4]));
00074                 else
00075                         return (new GK("Drop"));
00076         }       
00077 } class_gk;
00078 
00079 GK::GK(const char * trace):link_(NULL), EDTrace(NULL), tchan_(0)
00080 {
00081         q_ = new PacketQueue;
00082         pq_ = q_;
00083         bind_bool("drop_front_", &drop_front_);
00084         bind("ecnlim_", &ecnlim_); 
00085         bind("mean_pktsize_", &mean_pktsize_); 
00086         bind("curq_", &curq_); 
00087         vq_len = 0.0;
00088         prev_time = 0.0;
00089         mark_flag = 0;
00090 }
00091 
00092 int GK::command(int argc, const char*const* argv) {
00093         Tcl& tcl = Tcl::instance();
00094   if (argc == 3) {
00095           if (strcmp(argv[1], "link") == 0) {
00096                   LinkDelay* del = (LinkDelay*)TclObject::lookup(argv[2]);
00097                   if (del == 0) {
00098                           return(TCL_ERROR);
00099                   }
00100                   // set capacity now
00101                         link_ = del;
00102                   c_ = del->bandwidth();
00103                         c_ = c_ / (8.0 * mean_pktsize_);
00104                   return (TCL_OK);
00105           }
00106           if (!strcmp(argv[1], "packetqueue-attach")) {
00107                   delete q_;
00108                   if (!(q_ = (PacketQueue*) TclObject::lookup(argv[2])))
00109                           return (TCL_ERROR);
00110                   else {
00111                           pq_ = q_;
00112                           return (TCL_OK);
00113                   }
00114           }
00115                 // attach a file for variable tracing
00116                 if (strcmp(argv[1], "attach") == 0) {
00117                         int mode;
00118                         const char* id = argv[2];
00119                         tchan_ = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);
00120                         if (tchan_ == 0) {
00121                                 tcl.resultf("Vq: trace: can't attach %s for writing", id);
00122                                 return (TCL_ERROR);
00123                         }
00124                         return (TCL_OK);
00125                 }
00126   }
00127   return Queue::command(argc, argv);
00128 }
00129 
00130 void GK::enque(Packet* p)
00131 {
00132   q_->enque(p);
00133          
00134   curr_time = Scheduler::instance().clock();
00135   /*Whenever a packet is enqueued, the actual length of the
00136     virtual queue is determined */
00137  
00138   if(curr_time > prev_time){
00139           deque_vq();
00140   }
00141   /* Add the packet to the VQ */
00142   vq_len = vq_len + 1.0;
00143 
00144   /* If the VQ overflows, set flag so that all packets may be marked
00145          till the VQ hits zero again. */
00146   if(vq_len > (ecnlim_ * qlim_)){
00147           mark_flag = 1; // Indicates that all outgoing packets has to be marked
00148           vq_len = vq_len - 1.0;
00149   }
00150   
00151   if (q_->length() >= qlim_) {
00152                 if (drop_front_) { /* remove from head of queue */
00153                 Packet *pp = q_->deque();
00154                 drop(pp);
00155                 } else {
00156                 q_->remove(p);
00157                 drop(p);
00158                 }
00159   }
00160         curq_ = q_->length(); 
00161 }
00162 
00163 Packet* GK::deque()
00164 {
00165   /* Check the status of the virtual queue. We do this to update the
00166          mark_flag.  */
00167   curr_time = Scheduler::instance().clock();
00168   deque_vq();
00169 
00170   /* If the Real queue has packets and the mark_flag is set, mark the
00171          outgoing packet. */
00172   if((q_->length() > 0) && (mark_flag == 1)){
00173         Packet *pp = q_->deque();
00174         hdr_flags* hf = hdr_flags::access(pp);
00175         if(hf->ect() == 1)  // ECN capable flow
00176                 hf->ce() = 1; // Mark the TCP Flow;
00177         return pp;
00178   }
00179   else return q_->deque();
00180 }
00181 
00182 /* This procedure updates the VQ */
00183 void GK::deque_vq(){
00184   if(vq_len > 0.0){ 
00185         vq_len = vq_len - (ecnlim_ * c_ * (curr_time - prev_time));
00186         prev_time = curr_time;
00187         
00188         /* If the VQ hits zero, unset mark_flag */
00189         if(vq_len <= 0.0){
00190           vq_len = 0.0;
00191           mark_flag = 0;
00192         }
00193   }
00194 }
00195 
00196 /*
00197  * Routine called by TracedVar facility when variables change values.
00198  * Currently used to trace value of 
00199  * the instantaneous queue size seen by arriving packets.
00200  * Note that the tracing of each var must be enabled in tcl to work.
00201  */
00202 
00203 void GK::trace(TracedVar* v)
00204 {
00205         char wrk[500], *p;
00206 
00207         if ((p = strstr(v->name(), "curq")) == NULL) {
00208                 fprintf(stderr, "Vq:unknown trace var %s\n", v->name());
00209                 return;
00210         }
00211 
00212         if (tchan_) {
00213                 int n;
00214                 double t = Scheduler::instance().clock();
00215                 // XXX: be compatible with nsv1 RED trace entries
00216                 if (*p == 'c') {
00217                         sprintf(wrk, "Q %g %d", t, int(*((TracedInt*) v)));
00218                 } else {
00219                         sprintf(wrk, "%c %g %g", *p, t, double(*((TracedDouble*) v)));
00220                 }
00221                 n = strlen(wrk);
00222                 wrk[n] = '\n'; 
00223                 wrk[n+1] = 0;
00224                 (void)Tcl_Write(tchan_, wrk, n+1);
00225         }
00226         return; 
00227 }

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