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 #include <math.h>
00047 #include <sys/types.h>
00048 #include "config.h"
00049 #include "template.h"
00050 #include "random.h"
00051 #include "flags.h"
00052 #include "delay.h"
00053 #include "rem.h"
00054 #include <iostream>
00055
00056 static class REMClass : public TclClass {
00057 public:
00058 REMClass() : TclClass("Queue/REM") {}
00059 TclObject* create(int, const char*const*) {
00060 return (new REMQueue);
00061 }
00062 } class_rem;
00063
00064
00065 void REMQueue :: set_update_timer()
00066 {
00067 rem_timer_.resched(remp_.p_updtime);
00068 }
00069
00070 void REMQueue :: timeout()
00071 {
00072
00073 run_updaterule();
00074 set_update_timer();
00075 }
00076
00077
00078 void REMTimer :: expire (Event *e) {
00079 a_->timeout();
00080 }
00081
00082
00083
00084 REMQueue::REMQueue() : link_(NULL), tchan_(0), rem_timer_(this)
00085 {
00086 bind("gamma_", &remp_.p_gamma);
00087 bind("phi_", &remp_.p_phi);
00088 bind("inw_", &remp_.p_inw);
00089 bind("mean_pktsize_", &remp_.p_pktsize);
00090 bind("pupdtime_", &remp_.p_updtime);
00091 bind("pbo_", &remp_.p_bo);
00092 bind("prob_", &remv_.v_prob);
00093 bind("curq_", &curq_);
00094 bind("pmark_", &pmark_);
00095 bind_bool("markpkts_", &markpkts_);
00096 bind_bool("qib_", &qib_);
00097
00098 q_ = new PacketQueue();
00099 pq_ = q_;
00100 reset();
00101
00102 #ifdef notdef
00103 print_remp();
00104 print_remv();
00105 #endif
00106
00107 }
00108
00109 void REMQueue::reset()
00110 {
00111
00112
00113
00114
00115
00116
00117
00118
00119 if (link_)
00120 remp_.p_ptc = link_->bandwidth() / (8.0 * remp_.p_pktsize);
00121
00122 remv_.v_pl = 0.0;
00123 remv_.v_prob = 0.0;
00124 remv_.v_in = 0.0;
00125 remv_.v_ave = 0.0;
00126 remv_.v_count = 0.0;
00127
00128 remv_.v_pl1 = 0.0;
00129 remv_.v_pl2 = 0.0;
00130 remv_.v_in1 = 0.0;
00131 remv_.v_in2 = 0.0;
00132 pmark_ = 0.0;
00133 bcount_ = 0;
00134
00135
00136 set_update_timer();
00137 }
00138
00139
00140
00141
00142 void REMQueue::run_updaterule()
00143 {
00144
00145 double in, in_avg, nqueued, pl, pr;
00146
00147
00148
00149 pl = remv_.v_pl;
00150
00151
00152
00153
00154 in = remv_.v_count;
00155
00156
00157
00158
00159 in_avg = remv_.v_ave;
00160
00161 in_avg *= (1.0 - remp_.p_inw);
00162
00163 if (qib_) {
00164 in_avg += remp_.p_inw*in/remp_.p_pktsize;
00165 nqueued = bcount_/remp_.p_pktsize;
00166 }
00167 else {
00168 in_avg += remp_.p_inw*in;
00169 nqueued = q_ -> length();
00170 }
00171
00172
00173
00174
00175
00176 double c = remp_.p_updtime*remp_.p_ptc;
00177
00178 pl = pl + remp_.p_gamma*( in_avg + 0.1*(nqueued-remp_.p_bo) - c );
00179
00180 if ( pl < 0.0) {
00181 pl = 0.0;
00182 }
00183
00184 double pow1 = pow (remp_.p_phi, -pl);
00185 pr = 1.0-pow1;
00186
00187
00188 remv_.v_count = 0.0;
00189 remv_.v_ave = in_avg;
00190 remv_.v_pl = pl;
00191 remv_.v_prob = pr;
00192 }
00193
00194
00195
00196
00197
00198 Packet* REMQueue::deque()
00199 {
00200 Packet *p = q_->deque();
00201 if (p != 0) {
00202 bcount_ -= hdr_cmn::access(p)->size ();
00203 }
00204 if (markpkts_) {
00205 double u = Random::uniform();
00206 if (p!=0) {
00207 double pro = remv_.v_prob;
00208 if (qib_) {
00209 int size = hdr_cmn::access(p)->size ();
00210 pro = remv_.v_prob*size/remp_.p_pktsize;
00211 }
00212 if ( u <= pro ) {
00213 hdr_flags* hf = hdr_flags::access(p);
00214 if(hf->ect() == 1) {
00215 hf->ce() = 1;
00216 pmark_++;
00217 }
00218 }
00219 }
00220 }
00221 double qlen = qib_ ? bcount_ : q_->length();
00222 curq_ = (int) qlen;
00223 return (p);
00224 }
00225
00226
00227
00228
00229
00230
00231 void REMQueue::enque(Packet* pkt)
00232 {
00233 hdr_cmn* ch = hdr_cmn::access(pkt);
00234 double qlen;
00235
00236 if (qib_) {
00237 remv_.v_count += ch->size();
00238 }
00239 else {
00240 ++remv_.v_count;
00241 }
00242
00243 double qlim = qib_ ? (qlim_*remp_.p_pktsize) : qlim_ ;
00244
00245 q_ -> enque(pkt);
00246 bcount_ += ch->size();
00247
00248 qlen = qib_ ? bcount_ : q_->length();
00249
00250 if (qlen >= qlim) {
00251 q_->remove(pkt);
00252 bcount_ -= ch->size();
00253 drop(pkt);
00254 }
00255 else {
00256 if (!markpkts_) {
00257 double u = Random::uniform();
00258 double pro = remv_.v_prob;
00259 if (qib_) {
00260 pro = remv_.v_prob*ch->size()/remp_.p_pktsize;
00261 }
00262 if ( u <= pro ) {
00263 q_->remove(pkt);
00264 bcount_ -= ch->size();
00265 drop(pkt);
00266 }
00267 }
00268 }
00269 qlen = qib_ ? bcount_ : q_->length();
00270 curq_ = (int) qlen;
00271 }
00272
00273
00274 int REMQueue::command(int argc, const char*const* argv)
00275 {
00276
00277 Tcl& tcl = Tcl::instance();
00278 if (argc == 2) {
00279 if (strcmp(argv[1], "reset") == 0) {
00280 reset();
00281 return (TCL_OK);
00282 }
00283 } else if (argc == 3) {
00284
00285 if (strcmp(argv[1], "attach") == 0) {
00286 int mode;
00287 const char* id = argv[2];
00288 tchan_ = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);
00289 if (tchan_ == 0) {
00290 tcl.resultf("REM: trace: can't attach %s for writing", id);
00291 return (TCL_ERROR);
00292 }
00293 return (TCL_OK);
00294 }
00295
00296 if (strcmp(argv[1], "link") == 0) {
00297 LinkDelay* del = (LinkDelay*)TclObject::lookup(argv[2]);
00298 if (del == 0) {
00299 tcl.resultf("REM: no LinkDelay object %s",
00300 argv[2]);
00301 return(TCL_ERROR);
00302 }
00303
00304 link_ = del;
00305 remp_.p_ptc = link_->bandwidth() /
00306 (8. * remp_.p_pktsize);
00307
00308 return (TCL_OK);
00309 }
00310 if (!strcmp(argv[1], "packetqueue-attach")) {
00311 delete q_;
00312 if (!(q_ = (PacketQueue*) TclObject::lookup(argv[2])))
00313 return (TCL_ERROR);
00314 else {
00315 pq_ = q_;
00316 return (TCL_OK);
00317 }
00318 }
00319 }
00320 return (Queue::command(argc, argv));
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330 void
00331 REMQueue::trace(TracedVar* v)
00332 {
00333 char wrk[500], *p;
00334
00335 if (((p = strstr(v->name(), "ave")) == NULL) &&
00336 ((p = strstr(v->name(), "prob")) == NULL) &&
00337 ((p = strstr(v->name(), "curq")) == NULL)) {
00338 fprintf(stderr, "REM:unknown trace var %s\n",
00339 v->name());
00340 return;
00341 }
00342
00343 if (tchan_) {
00344 int n;
00345 double t = Scheduler::instance().clock();
00346 if (*p == 'c') {
00347 sprintf(wrk, "Q %g %d", t, int(*((TracedInt*) v)));
00348 } else {
00349 sprintf(wrk, "%c %g %g", *p, t,
00350 double(*((TracedDouble*) v)));
00351 }
00352 n = strlen(wrk);
00353 wrk[n] = '\n';
00354 wrk[n+1] = 0;
00355 (void)Tcl_Write(tchan_, wrk, n+1);
00356 }
00357 return;
00358 }
00359
00360
00361 void REMQueue::print_remp()
00362 {
00363 printf("=========\n");
00364 }
00365
00366 void REMQueue::print_remv()
00367 {
00368 printf("=========\n");
00369 }