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

qsagent.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001 University of Southern California.
00003  * All rights reserved.                                            
00004  *                                                                
00005  * Redistribution and use in source and binary forms are permitted
00006  * provided that the above copyright notice and this paragraph are
00007  * duplicated in all such forms and that any documentation, advertising
00008  * materials, and other materials related to such distribution and use
00009  * acknowledge that the software was developed by the University of
00010  * Southern California, Information Sciences Institute.  The name of the
00011  * University may not be used to endorse or promote products derived from
00012  * this software without specific prior written permission.
00013  * 
00014  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
00015  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00016  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017  *
00018  **
00019  * Quick Start for TCP and IP.
00020  * A scheme for transport protocols to dynamically determine initial 
00021  * congestion window size.
00022  *
00023  * http://www.ietf.org/internet-drafts/draft-amit-quick-start-02.ps
00024  *
00025  * This implements the Quick Start Agent at each of network element "Agent/QSAgent"
00026  * qsagent.cc
00027  *
00028  * Srikanth Sundarrajan, 2002
00029  * sundarra@usc.edu
00030  */
00031 
00032 #include <assert.h>
00033 #include <math.h>
00034 #include <stdio.h>
00035 #include <signal.h>
00036 #include <float.h>
00037 
00038 #include "object.h"
00039 #include "agent.h"
00040 #include "packet.h"
00041 #include "ip.h"
00042 #include "classifier.h"
00043 #include "connector.h"
00044 #include "delay.h"
00045 #include "queue.h"
00046 #include "scheduler.h"
00047 #include "random.h"
00048 
00049 #include "hdr_qs.h"
00050 #include "qsagent.h"
00051 #include <fstream>
00052 
00053 static class QSAgentClass : public TclClass {
00054 public:
00055         QSAgentClass() : TclClass("Agent/QSAgent") {}
00056         TclObject* create(int, const char*const*) {
00057                 return (new QSAgent);
00058         }
00059 } class_QSAgent;
00060 
00061 QSAgent::QSAgent():Agent(PT_TCP), old_classifier_(NULL), qs_enabled_(1), 
00062     qs_timer_(this) 
00063 {
00064 
00065         prev_int_aggr_ = 0;
00066         aggr_approval_ = 0;
00067 
00068         bind("qs_enabled_", &qs_enabled_);
00069         bind("old_classifier_", &old_classifier_);
00070         bind("state_delay_", &state_delay_);
00071         bind("alloc_rate_", &alloc_rate_);
00072         bind("max_rate_", &max_rate_);
00073         bind("mss_", &mss_);
00074 
00075         qs_timer_.resched(state_delay_);
00076   
00077 }
00078 
00079 QSAgent::~QSAgent()
00080 {
00081 }
00082 
00083 int QSAgent::command(int argc, const char*const* argv)
00084 {
00085         return (Agent::command(argc,argv));
00086 }
00087 
00088 void QSAgent::recv(Packet* packet, Handler*)
00089 {
00090         int app_rate;
00091         double avail_bw, util;
00092         Classifier * pkt_target;
00093         Tcl& tcl = Tcl::instance();
00094         char qname[64], lname[64];
00095 
00096         hdr_qs *qsh =  hdr_qs::access(packet);
00097         hdr_ip *iph = hdr_ip::access(packet);
00098 
00099         if (old_classifier_)  
00100                 pkt_target = (Classifier *)TclObject::lookup(old_classifier_->name());
00101 
00102         if (qs_enabled_) {
00103                 /*if ((qsh->flag() == QS_REQUEST || qsh->flag() == QS_RESPONSE) && qsh->rate() > 0) 
00104                 printf("%d: got flag = %d, ttl1 = %d, ttl2 = %d, rate = %d\n", 
00105                 addr(), qsh->flag(), iph->ttl(), qsh->ttl(), qsh->rate());*/
00106                 if (qsh->flag() == QS_REQUEST && qsh->rate() > 0 && iph->daddr() != addr()) {
00107                         sprintf (qname, "[Simulator instance] get-queue %d %d", addr(), iph->daddr()); 
00108                         tcl.evalc (qname);
00109                         Queue * queue = (Queue *) TclObject::lookup(tcl.result());
00110 
00111                         sprintf (lname, "[Simulator instance] get-link %d %d", addr(), iph->daddr()); 
00112                         tcl.evalc (lname);
00113                         LinkDelay * link = (LinkDelay *) TclObject::lookup(tcl.result());
00114 
00115                         if (link != NULL && queue != NULL) {
00116                                 util = queue->utilization();
00117                                 avail_bw = link->bandwidth() / 8 * (1 - util) / mss_;
00118                                 avail_bw -= (prev_int_aggr_ + aggr_approval_);
00119                                 avail_bw *= alloc_rate_;
00120                                 printf("%d: requested = %d, available = %f\n", addr(), qsh->rate(), avail_bw);
00121                                 app_rate = (avail_bw < (double)qsh->rate()) ? (int) avail_bw : qsh->rate();
00122                                 app_rate = (app_rate < max_rate_) ? app_rate : max_rate_;
00123                                 if (app_rate > 0) {    
00124                                         aggr_approval_ += app_rate; // add approved to current bucket
00125                                         qsh->ttl() -= 1;
00126                                         qsh->rate() = app_rate; //update rate
00127                                 }
00128                                 else {
00129                                         qsh->rate() = 0; //disable quick start, not enough bandwidth
00130                                         qsh->flag() = QS_DISABLE;
00131                                 }
00132                         }
00133       }
00134   }
00135 
00136 #if 0   
00137   if (qs_enabled_) {
00138       /*if ((qsh->flag() == QS_REQUEST || qsh->flag() == QS_RESPONSE) && qsh->rate() > 0) 
00139           printf("%d: got flag = %d, ttl1 = %d, ttl2 = %d, rate = %d\n", 
00140               addr(), qsh->flag(), iph->ttl(), qsh->ttl(), qsh->rate());*/
00141       if (qsh->flag() == QS_REQUEST && qsh->rate() > 0 && iph->daddr() != addr()) {
00142           Connector * head = (Connector *) pkt_target->find(packet);
00143           if (head) {
00144               //printf("%d: got head %s %p\n", addr(), head->name(), head);
00145               Connector * enqT = (Connector *) head->target();
00146               if (enqT) {
00147                   //printf("%d: got enqT %s %p\n", addr(), enqT->name(), enqT);
00148                   Queue * queue = (Queue *) enqT->target();
00149                   if (queue) {
00150                       //printf("%d: got queue %s %p\n", addr(), queue->name(), queue);
00151                       Connector * deqT = (Connector *) queue->target();
00152                       if (deqT) {
00153                           //printf("%d: got deqT %s %p\n", addr(), deqT->name(), deqT);
00154                           LinkDelay * link = (LinkDelay *) deqT->target();
00155                           if (link) {
00156                                                           util = queue->utilization();
00157                               avail_bw = link->bandwidth() / 8 * (1 - util) / mss_;
00158                               avail_bw -= (prev_int_aggr_ + aggr_approval_);
00159                               avail_bw *= alloc_rate_;
00160                               printf("%d: requested = %d, available = %f\n", addr(), qsh->rate(), avail_bw);
00161                               app_rate = (avail_bw < (double)qsh->rate()) ? (int) avail_bw : qsh->rate();
00162                               app_rate = (app_rate < max_rate_) ? app_rate : max_rate_;
00163                               if (app_rate > 0) {    
00164                                   aggr_approval_ += app_rate; // add approved to current bucket
00165                                   qsh->ttl() -= 1;
00166                                   qsh->rate() = app_rate; //update rate
00167                               }
00168                               else {
00169                                   qsh->rate() = 0; //disable quick start, not enough bandwidth
00170                                   qsh->flag() = QS_DISABLE;
00171                               }
00172                           }
00173                       }
00174                   }
00175               }
00176           }
00177       }
00178   }
00179 #endif
00180 
00181         if (pkt_target) 
00182                 pkt_target->recv(packet, 0);
00183         else {
00184                 printf("%d, don't know what to do with the packet\n", addr()); // should never get here.
00185                 Packet::free(packet);
00186         }
00187 
00188         return;
00189   
00190 }
00191 
00192 void QSTimer::expire(Event *e) {
00193         
00194         qs_handle_->prev_int_aggr_ = qs_handle_->aggr_approval_;
00195         qs_handle_->aggr_approval_ = 0;
00196 
00197         this->resched(qs_handle_->state_delay_);
00198 
00199 }

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