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 Mar 6 16:47:45 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6