tbf.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  * This program is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU General Public License as published by the
00007  * Free Software Foundation; either version 2 of the License, or (at your
00008  * option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License along
00016  * with this program; if not, write to the Free Software Foundation, Inc.,
00017  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  *
00019  * Linking this file statically or dynamically with other modules is making
00020  * a combined work based on this file.  Thus, the terms and conditions of
00021  * the GNU General Public License cover the whole combination.
00022  *
00023  * In addition, as a special exception, the copyright holders of this file
00024  * give you permission to combine this file with free software programs or
00025  * libraries that are released under the GNU LGPL and with code included in
00026  * the standard release of ns-2 under the Apache 2.0 license or under
00027  * otherwise-compatible licenses with advertising requirements (or modified
00028  * versions of such code, with unchanged license).  You may copy and
00029  * distribute such a system following the terms of the GNU GPL for this
00030  * file and the licenses of the other code concerned, provided that you
00031  * include the source code of that other code when and as the GNU GPL
00032  * requires distribution of source code.
00033  *
00034  * Note that people who make modified versions of this file are not
00035  * obligated to grant this special exception for their modified versions;
00036  * it is their choice whether to do so.  The GNU General Public License
00037  * gives permission to release a modified version without this exception;
00038  * this exception also makes it possible to release a modified version
00039  * which carries forward this exception.
00040  */
00041 
00042 /* Token Bucket filter which has  3 parameters :
00043    a. Token Generation rate
00044    b. Token bucket depth
00045    c. Max. Queue Length (a finite length would allow this to be used as  policer as packets are dropped after queue gets full)
00046    */
00047 
00048 #include "connector.h" 
00049 #include "packet.h"
00050 #include "queue.h"
00051 #include "tbf.h"
00052 
00053 TBF::TBF() :tokens_(0),tbf_timer_(this), init_(1)
00054 {
00055     q_=new PacketQueue();
00056     bind_bw("rate_",&rate_);
00057     bind("bucket_",&bucket_);
00058     bind("qlen_",&qlen_);
00059 }
00060     
00061 TBF::~TBF()
00062 {
00063     if (q_->length() != 0) {
00064         //Clear all pending timers
00065         tbf_timer_.cancel();
00066         //Free up the packetqueue
00067         for (Packet *p=q_->head();p!=0;p=p->next_) 
00068             Packet::free(p);
00069     }
00070     delete q_;
00071 }
00072 
00073 
00074 void TBF::recv(Packet *p, Handler *)
00075 {
00076     //start with a full bucket
00077     if (init_) {
00078         tokens_=bucket_;
00079         lastupdatetime_ = Scheduler::instance().clock();
00080         init_=0;
00081     }
00082 
00083     
00084     hdr_cmn *ch=hdr_cmn::access(p);
00085 
00086     //enque packets appropriately if a non-zero q already exists
00087     if (q_->length() !=0) {
00088         if (q_->length() < qlen_) {
00089             q_->enque(p);
00090             return;
00091         }
00092 
00093         drop(p);
00094         return;
00095     }
00096 
00097     double tok;
00098     tok = getupdatedtokens();
00099 
00100     int pktsize = ch->size()<<3;
00101     if (tokens_ >=pktsize) {
00102         target_->recv(p);
00103         tokens_-=pktsize;
00104     }
00105     else {
00106         
00107         if (qlen_!=0) {
00108             q_->enque(p);
00109             tbf_timer_.resched((pktsize-tokens_)/rate_);
00110         }
00111         else {
00112             drop(p);
00113         }
00114     }
00115 }
00116 
00117 double TBF::getupdatedtokens(void)
00118 {
00119     double now=Scheduler::instance().clock();
00120     
00121     tokens_ += (now-lastupdatetime_)*rate_;
00122     if (tokens_ > bucket_)
00123         tokens_=bucket_;
00124     lastupdatetime_ = Scheduler::instance().clock();
00125     return tokens_;
00126 }
00127 
00128 void TBF::timeout(int)
00129 {
00130     if (q_->length() == 0) {
00131         fprintf (stderr,"ERROR in tbf\n");
00132         abort();
00133     }
00134     
00135     Packet *p=q_->deque();
00136     double tok;
00137     tok = getupdatedtokens();
00138     hdr_cmn *ch=hdr_cmn::access(p);
00139     int pktsize = ch->size()<<3;
00140 
00141     //We simply send the packet here without checking if we have enough tokens
00142     //because the timer is supposed to fire at the right time
00143     target_->recv(p);
00144     tokens_-=pktsize;
00145 
00146     if (q_->length() !=0 ) {
00147         p=q_->head();
00148         hdr_cmn *ch=hdr_cmn::access(p);
00149         pktsize = ch->size()<<3;
00150         tbf_timer_.resched((pktsize-tokens_)/rate_);
00151     }
00152 }
00153 
00154 void TBF_Timer::expire(Event* /*e*/)
00155 {
00156     tbf_->timeout(0);
00157 }
00158 
00159 
00160 static class TBFClass : public TclClass {
00161 public:
00162     TBFClass() : TclClass ("TBF") {}
00163     TclObject* create(int,const char*const*) {
00164         return (new TBF());
00165     }
00166 }class_tbf;

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