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

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  * License is granted to copy, to use, and to make and to use derivative
00006  * works for research and evaluation purposes, provided that Xerox is
00007  * acknowledged in all documentation pertaining to any such copy or
00008  * derivative work. Xerox grants no other licenses expressed or
00009  * implied. The Xerox trade name should not be used in any advertising
00010  * without its written permission. 
00011  *
00012  * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
00013  * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
00014  * FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
00015  * express or implied warranty of any kind.
00016  *
00017  * These notices must be retained in any copies of any part of this
00018  * software. 
00019  */
00020 
00021 /* Token Bucket filter which has  3 parameters :
00022    a. Token Generation rate
00023    b. Token bucket depth
00024    c. Max. Queue Length (a finite length would allow this to be used as  policer as packets are dropped after queue gets full)
00025    */
00026 
00027 #include "connector.h" 
00028 #include "packet.h"
00029 #include "queue.h"
00030 #include "tbf.h"
00031 
00032 TBF::TBF() :tokens_(0),tbf_timer_(this), init_(1)
00033 {
00034         q_=new PacketQueue();
00035         bind_bw("rate_",&rate_);
00036         bind("bucket_",&bucket_);
00037         bind("qlen_",&qlen_);
00038 }
00039         
00040 TBF::~TBF()
00041 {
00042         if (q_->length() != 0) {
00043                 //Clear all pending timers
00044                 tbf_timer_.cancel();
00045                 //Free up the packetqueue
00046                 for (Packet *p=q_->head();p!=0;p=p->next_) 
00047                         Packet::free(p);
00048         }
00049         delete q_;
00050 }
00051 
00052 
00053 void TBF::recv(Packet *p, Handler *)
00054 {
00055         //start with a full bucket
00056         if (init_) {
00057                 tokens_=bucket_;
00058                 lastupdatetime_ = Scheduler::instance().clock();
00059                 init_=0;
00060         }
00061 
00062         
00063         hdr_cmn *ch=hdr_cmn::access(p);
00064 
00065         //enque packets appropriately if a non-zero q already exists
00066         if (q_->length() !=0) {
00067                 if (q_->length() < qlen_) {
00068                         q_->enque(p);
00069                         return;
00070                 }
00071 
00072                 drop(p);
00073                 return;
00074         }
00075 
00076         double tok;
00077         tok = getupdatedtokens();
00078 
00079         int pktsize = ch->size()<<3;
00080         if (tokens_ >=pktsize) {
00081                 target_->recv(p);
00082                 tokens_-=pktsize;
00083         }
00084         else {
00085                 
00086                 if (qlen_!=0) {
00087                         q_->enque(p);
00088                         tbf_timer_.resched((pktsize-tokens_)/rate_);
00089                 }
00090                 else {
00091                         drop(p);
00092                 }
00093         }
00094 }
00095 
00096 double TBF::getupdatedtokens(void)
00097 {
00098         double now=Scheduler::instance().clock();
00099         
00100         tokens_ += (now-lastupdatetime_)*rate_;
00101         if (tokens_ > bucket_)
00102                 tokens_=bucket_;
00103         lastupdatetime_ = Scheduler::instance().clock();
00104         return tokens_;
00105 }
00106 
00107 void TBF::timeout(int)
00108 {
00109         if (q_->length() == 0) {
00110                 fprintf (stderr,"ERROR in tbf\n");
00111                 abort();
00112         }
00113         
00114         Packet *p=q_->deque();
00115         double tok;
00116         tok = getupdatedtokens();
00117         hdr_cmn *ch=hdr_cmn::access(p);
00118         int pktsize = ch->size()<<3;
00119 
00120         //We simply send the packet here without checking if we have enough tokens
00121         //because the timer is supposed to fire at the right time
00122         target_->recv(p);
00123         tokens_-=pktsize;
00124 
00125         if (q_->length() !=0 ) {
00126                 p=q_->head();
00127                 hdr_cmn *ch=hdr_cmn::access(p);
00128                 pktsize = ch->size()<<3;
00129                 tbf_timer_.resched((pktsize-tokens_)/rate_);
00130         }
00131 }
00132 
00133 void TBF_Timer::expire(Event* /*e*/)
00134 {
00135         tbf_->timeout(0);
00136 }
00137 
00138 
00139 static class TBFClass : public TclClass {
00140 public:
00141         TBFClass() : TclClass ("TBF") {}
00142         TclObject* create(int,const char*const*) {
00143                 return (new TBF());
00144         }
00145 }class_tbf;

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