00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include <assert.h>
00062 #include <math.h>
00063 #include <stdio.h>
00064 #include <signal.h>
00065 #include <float.h>
00066
00067 #include "object.h"
00068 #include "agent.h"
00069 #include "packet.h"
00070 #include "ip.h"
00071 #include "classifier.h"
00072 #include "connector.h"
00073 #include "delay.h"
00074 #include "queue.h"
00075 #include "scheduler.h"
00076 #include "random.h"
00077
00078 #include "hdr_qs.h"
00079 #include "qsagent.h"
00080 #include <fstream>
00081
00082 static class QSAgentClass : public TclClass {
00083 public:
00084 QSAgentClass() : TclClass("Agent/QSAgent") {}
00085 TclObject* create(int, const char*const*) {
00086 return (new QSAgent);
00087 }
00088 } class_QSAgent;
00089
00090 int QSAgent::rate_function_ = 1;
00091
00092 QSAgent::QSAgent():Agent(PT_TCP), old_classifier_(NULL), qs_enabled_(1),
00093 qs_timer_(this)
00094 {
00095
00096 prev_int_aggr_ = 0;
00097 aggr_approval_ = 0;
00098
00099 bind("qs_enabled_", &qs_enabled_);
00100 bind("old_classifier_", &old_classifier_);
00101 bind("state_delay_", &state_delay_);
00102 bind("alloc_rate_", &alloc_rate_);
00103 bind("threshold_", &threshold_);
00104 bind("max_rate_", &max_rate_);
00105 bind("mss_", &mss_);
00106 bind("rate_function_", &rate_function_);
00107 bind("algorithm_", &algorithm_);
00108
00109 qs_timer_.resched(state_delay_);
00110
00111 }
00112
00113 QSAgent::~QSAgent()
00114 {
00115 }
00116
00117 int QSAgent::command(int argc, const char*const* argv)
00118 {
00119 return (Agent::command(argc,argv));
00120 }
00121
00122 void QSAgent::recv(Packet* packet, Handler*)
00123 {
00124 double app_rate;
00125
00126 Classifier * pkt_target;
00127 Tcl& tcl = Tcl::instance();
00128 char qname[64], lname[64];
00129
00130 hdr_qs *qsh = hdr_qs::access(packet);
00131 hdr_ip *iph = hdr_ip::access(packet);
00132
00133 assert (old_classifier_ != 0);
00134
00135 pkt_target = (Classifier *)TclObject::lookup(old_classifier_->name());
00136
00137 if (qs_enabled_) {
00138 if (qsh->flag() == QS_REQUEST && qsh->rate() > 0 && iph->daddr() != addr()) {
00139 sprintf (qname, "[Simulator instance] get-queue %d %d", addr(), iph->daddr());
00140 tcl.evalc (qname);
00141 Queue * queue = (Queue *) TclObject::lookup(tcl.result());
00142
00143 sprintf (lname, "[Simulator instance] get-link %d %d", addr(), iph->daddr());
00144 tcl.evalc (lname);
00145 LinkDelay * link = (LinkDelay *) TclObject::lookup(tcl.result());
00146
00147 if (link != NULL && queue != NULL) {
00148 app_rate = process(link, queue, hdr_qs::rate_to_Bps(qsh->rate()));
00149 if (app_rate > 0) {
00150 aggr_approval_ += app_rate;
00151 qsh->ttl() -= 1;
00152 qsh->rate() = hdr_qs::Bps_to_rate(app_rate);
00153 }
00154 else {
00155 qsh->rate() = 0;
00156 qsh->flag() = QS_DISABLE;
00157 }
00158 }
00159 }
00160 }
00161
00162 pkt_target->recv(packet, 0);
00163
00164 return;
00165
00166 }
00167
00168
00169 double QSAgent::process(LinkDelay *link, Queue *queue, double ratereq)
00170 {
00171 double util, avail_bw, app_rate, util_bw;
00172
00173
00174 if (algorithm_ == 1) {
00175
00176
00177 util = queue->utilization();
00178 avail_bw = link->bandwidth() / 8 * (1 - util);
00179 avail_bw -= (prev_int_aggr_ + aggr_approval_);
00180 avail_bw *= alloc_rate_;
00181 app_rate = (avail_bw < ratereq) ? (int) avail_bw : ratereq;
00182 app_rate = (app_rate < (max_rate_ * 1024)) ?
00183 app_rate : (max_rate_ * 1024);
00184 if (app_rate > 0) {
00185
00186 aggr_approval_ += app_rate;
00187 }
00188 } else if (algorithm_ == 2) {
00189
00190
00191
00192
00193
00194
00195
00196 util = queue->utilization();
00197 util_bw = link->bandwidth() / 8 * util;
00198 util_bw += (prev_int_aggr_ + aggr_approval_);
00199 if (util_bw < threshold_ * link->bandwidth() / 8) {
00200 app_rate = alloc_rate_ * link->bandwidth() / 8;
00201 if (ratereq < app_rate)
00202 app_rate = ratereq;
00203 } else {
00204 app_rate = 0;
00205 }
00206 aggr_approval_ += app_rate;
00207 } else if (algorithm_ == 3) {
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 util = queue->peak_utilization();
00221 util_bw = link->bandwidth() / 8 * util;
00222 util_bw += (prev_int_aggr_ + aggr_approval_);
00223 if (util_bw < threshold_ * link->bandwidth() / 8) {
00224 app_rate = alloc_rate_ * link->bandwidth() / 8
00225 - util_bw;
00226 if (ratereq < app_rate)
00227 app_rate = ratereq;
00228 if (app_rate < 0)
00229 app_rate = 0;
00230 } else {
00231 app_rate = 0;
00232 }
00233 aggr_approval_ += app_rate;
00234 } else if (algorithm_ == 4) {
00235
00236 app_rate = ratereq;
00237 } else {
00238 app_rate = 0;
00239 }
00240
00241 #ifdef QS_DEBUG
00242 printf("%d: requested = %f KBps, available = %f KBps, approved = %f KBps\n", addr(), ratereq/1024, free_bw/1024, app_rate/1024);
00243 #endif
00244
00245 return app_rate;
00246 }
00247
00248
00249 void QSTimer::expire(Event *e) {
00250
00251 qs_handle_->prev_int_aggr_ = qs_handle_->aggr_approval_;
00252 qs_handle_->aggr_approval_ = 0;
00253
00254 this->resched(qs_handle_->state_delay_);
00255
00256 }
00257
00258
00259
00260
00261
00262
00263