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 #ifndef lint
00059 static const char rcsid[] =
00060 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/queue/rio.cc,v 1.11 2002/03/21 01:42:36 johnh Exp $ (LBL)";
00061 #endif
00062
00063 #include "rio.h"
00064 #include "tclcl.h"
00065 #include "packet.h"
00066 #include "random.h"
00067 #include "flags.h"
00068 #include "delay.h"
00069 #include "template.h"
00070 #include "red.h"
00071
00072 static class RIOClass : public TclClass {
00073 public:
00074 RIOClass() : TclClass("Queue/RED/RIO") {}
00075 TclObject* create(int, const char*const*) {
00076 return (new RIOQueue);
00077 }
00078 } class_rio;
00079
00080 RIOQueue::RIOQueue() : in_len_(0), in_bcount_(0), in_idle_(1)
00081 {
00082 bind("in_thresh_", &edp_in_.th_min);
00083 bind("in_maxthresh_", &edp_in_.th_max);
00084 bind("out_thresh_", &edp_out_.th_min);
00085 bind("out_maxthresh_", &edp_out_.th_max);
00086 bind("in_linterm_", &edp_in_.max_p_inv);
00087
00088
00089
00090 bind_bool("in_gentle_",&edp_in_.gentle);
00091 bind_bool("out_gentle_",&edp_out_.gentle);
00092
00093 bind("in_ave_", &edv_in_.v_ave);
00094 bind("out_ave_", &edv_out_.v_ave);
00095 bind("in_prob1_", &edv_in_.v_prob1);
00096 bind("out_prob1_", &edv_out_.v_prob1);
00097 bind("priority_method_", &priority_method_);
00098
00099
00100
00101
00102
00103 }
00104
00105 void RIOQueue::reset()
00106 {
00107
00108
00109
00110
00111
00112 if (qib_) {
00113 edp_in_.th_min *= edp_.mean_pktsize;
00114 edp_in_.th_max *= edp_.mean_pktsize;
00115
00116 edp_out_.th_min *= edp_.mean_pktsize;
00117 edp_out_.th_max *= edp_.mean_pktsize;
00118 }
00119
00120
00121 if (edp_.gentle) {
00122 edp_in_.gentle = true;
00123 edp_out_.gentle = true;
00124 }
00125 if (edp_in_.gentle) {
00126 edv_in_.v_c = ( 1.0 - 1 / edp_in_.max_p_inv ) / edp_in_.th_max;
00127 edv_in_.v_d = 2 / edp_in_.max_p_inv - 1.0;
00128 }
00129 if (edp_out_.gentle) {
00130 edv_out_.v_c = ( 1.0 - 1 / edp_.max_p_inv ) / edp_out_.th_max;
00131 edv_out_.v_d = 2 / edp_.max_p_inv - 1.0;
00132 }
00133
00134
00135 edv_in_.v_ave = 0.0;
00136 edv_in_.v_slope = 0.0;
00137 edv_in_.drops = 0;
00138 edv_in_.count = 0;
00139 edv_in_.count_bytes = 0;
00140 edv_in_.old = 0;
00141 edv_in_.v_a = 1 / (edp_in_.th_max - edp_in_.th_min);
00142 edv_in_.v_b = - edp_in_.th_min / (edp_in_.th_max - edp_in_.th_min);
00143
00144
00145 edv_out_.v_ave = 0.0;
00146 edv_out_.v_slope = 0.0;
00147 edv_out_.drops = 0;
00148 edv_out_.count = 0;
00149 edv_out_.count_bytes = 0;
00150 edv_out_.old = 0;
00151 edv_out_.v_a = 1 / (edp_out_.th_max - edp_out_.th_min);
00152 edv_out_.v_b = - edp_out_.th_min / (edp_out_.th_max - edp_out_.th_min);
00153
00154 in_idle_ = 1;
00155 if (&Scheduler::instance() == NULL) {
00156 in_idletime_ = 0.0;
00157 }
00158 REDQueue::reset();
00159 }
00160
00161
00162
00163
00164 Packet* RIOQueue::deque()
00165 {
00166 Packet *p;
00167 p = REDQueue::deque();
00168
00169 if (p != 0) {
00170 hdr_flags* hf = hdr_flags::access(p);
00171 if (hf->pri_) {
00172
00173 in_idle_ = 0;
00174 in_bcount_ -= hdr_cmn::access(p)->size();
00175 --in_len_;
00176 }
00177 } else {
00178 in_idle_ = 1;
00179 }
00180 return (p);
00181 }
00182
00183
00184
00185
00186 int
00187 RIOQueue::drop_in_early(Packet* pkt)
00188 {
00189 hdr_cmn* ch = hdr_cmn::access(pkt);
00190
00191 edv_in_.v_prob1 = REDQueue::calculate_p(edv_in_.v_ave, edp_in_.th_max,
00192 edp_in_.gentle, edv_in_.v_a, edv_in_.v_b, edv_in_.v_c,
00193 edv_in_.v_d, edp_in_.max_p_inv);
00194 edv_in_.v_prob = REDQueue::modify_p(edv_in_.v_prob1, edv_in_.count,
00195 edv_in_.count_bytes, edp_.bytes, edp_.mean_pktsize, edp_.wait,
00196 ch->size());
00197
00198
00199 double u = Random::uniform();
00200 if (u <= edv_in_.v_prob) {
00201
00202 edv_in_.count = 0;
00203 edv_in_.count_bytes = 0;
00204 hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));
00205 if (edp_.setbit && hf->ect() &&
00206 edv_in_.v_ave < edp_in_.th_max) {
00207 hf->ce() = 1;
00208 return (0);
00209 } else {
00210 return (1);
00211 }
00212 }
00213 return (0);
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 int RIOQueue::drop_out_early(Packet* pkt)
00225 {
00226 hdr_cmn* ch = hdr_cmn::access(pkt);
00227
00228 edv_out_.v_prob1 = REDQueue::calculate_p(edv_.v_ave, edp_out_.th_max,
00229 edp_out_.gentle, edv_out_.v_a, edv_out_.v_b, edv_out_.v_c,
00230 edv_out_.v_d, edp_.max_p_inv);
00231 edv_out_.v_prob = REDQueue::modify_p(edv_out_.v_prob1, edv_out_.count,
00232 edv_out_.count_bytes, edp_.bytes, edp_.mean_pktsize, edp_.wait,
00233 ch->size());
00234
00235
00236 double u = Random::uniform();
00237 if (u <= edv_out_.v_prob) {
00238
00239 edv_out_.count = 0;
00240 edv_out_.count_bytes = 0;
00241 hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));
00242 if (edp_.setbit && hf->ecn_capable_ &&
00243 edv_.v_ave < edp_out_.th_max) {
00244 hf->ce() = 1;
00245 return (0);
00246 } else {
00247 return (1);
00248 }
00249 }
00250 return (0);
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 #define DTYPE_NONE 0
00271 #define DTYPE_FORCED 1
00272 #define DTYPE_UNFORCED 2
00273
00274 void RIOQueue::enque(Packet* pkt)
00275 {
00276
00277
00278 hdr_flags* hf = hdr_flags::access(pkt);
00279 hdr_ip* iph = hdr_ip::access(pkt);
00280 if (priority_method_ == 1) {
00281 hf->pri_ = iph->flowid();
00282 }
00283
00284
00285
00286 if (hf->pri_) {
00287
00288
00289
00290
00291
00292
00293
00294 int m = 0;
00295 int m_in = 0;
00296 double now = Scheduler::instance().clock();
00297
00298 if (in_idle_) {
00299 in_idle_ = 0;
00300 m_in = int(edp_.ptc * (now - idletime_));
00301 }
00302 if (idle_) {
00303 idle_ = 0;
00304 m = int(edp_.ptc * (now - idletime_));
00305 }
00306
00307
00308
00309
00310
00311
00312
00313 edv_.v_ave = REDQueue::estimator(qib_ ? q_->byteLength() : q_->length(), m + 1,
00314 edv_.v_ave, edp_.q_w);
00315 edv_in_.v_ave = REDQueue::estimator(qib_ ? in_bcount_ : in_len_,
00316 m_in + 1, edv_in_.v_ave, edp_.q_w);
00317
00318
00319
00320
00321
00322
00323
00324 hdr_cmn* ch = hdr_cmn::access(pkt);
00325 ++edv_.count;
00326 edv_.count_bytes += ch->size();
00327
00328
00329 ++edv_in_.count;
00330 edv_in_.count_bytes += ch->size();
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 register double in_qavg = edv_in_.v_ave;
00342 int droptype = DTYPE_NONE;
00343 int qlen = qib_ ? q_->byteLength() : q_->length();
00344 int in_qlen = qib_ ? in_bcount_ : in_len_;
00345 int qlim = qib_ ? (qlim_ * edp_.mean_pktsize) : qlim_;
00346
00347 curq_ = qlen;
00348
00349 if (in_qavg >= edp_in_.th_min && in_qlen > 1) {
00350 if ((!edp_in_.gentle && in_qavg >= edp_in_.th_max) ||
00351 (edp_in_.gentle && in_qavg >= 2 * edp_in_.th_max)) {
00352 droptype = DTYPE_FORCED;
00353 } else if (edv_in_.old == 0) {
00354
00355
00356
00357
00358
00359
00360 edv_in_.count = 1;
00361 edv_in_.count_bytes = ch->size();
00362 edv_in_.old = 1;
00363 } else if (drop_in_early(pkt)) {
00364 droptype = DTYPE_UNFORCED;
00365 }
00366 } else {
00367
00368 edv_in_.v_prob = 0.0;
00369 edv_in_.old = 0;
00370 }
00371 if (qlen >= qlim) {
00372
00373 droptype = DTYPE_FORCED;
00374 }
00375
00376 if (droptype == DTYPE_UNFORCED) {
00377
00378 Packet *pkt_to_drop = pickPacketForECN(pkt);
00379
00380
00381
00382
00383 if (pkt_to_drop != pkt) {
00384 q_->enque(pkt);
00385
00386 ++in_len_;
00387 in_bcount_ += ch->size();
00388 q_->remove(pkt_to_drop);
00389
00390 if (hdr_flags::access(pkt_to_drop)->pri_)
00391 {
00392 in_bcount_ -=
00393 hdr_cmn::access(pkt_to_drop)->size();
00394 --in_len_;
00395 }
00396 pkt = pkt_to_drop;
00397 }
00398
00399 if (de_drop_ != NULL)
00400 de_drop_->recv(pkt);
00401 else
00402 drop(pkt);
00403 } else {
00404
00405 q_->enque(pkt);
00406
00407 ++in_len_;
00408 in_bcount_ += ch->size();
00409
00410
00411 if (droptype == DTYPE_FORCED) {
00412
00413 pkt = pickPacketToDrop();
00414 q_->remove(pkt);
00415
00416 if (hdr_flags::access(pkt)->pri_) {
00417 in_bcount_ -= hdr_cmn::access(pkt)->size();
00418 --in_len_;
00419 }
00420 drop(pkt);
00421 if (!ns1_compat_) {
00422
00423 edv_.count = 0;
00424 edv_.count_bytes = 0;
00425 edv_in_.count = 0;
00426 edv_in_.count_bytes = 0;
00427 }
00428 }
00429 }
00430 }
00431
00432 else {
00433
00434
00435
00436
00437
00438
00439 hdr_cmn* ch = hdr_cmn::access(pkt);
00440 ++edv_.count;
00441 edv_.count_bytes += ch->size();
00442
00443
00444 ++edv_out_.count;
00445 edv_out_.count_bytes += ch->size();
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 register double qavg = edv_.v_ave;
00460
00461 int droptype = DTYPE_NONE;
00462 int qlen = qib_ ? q_->byteLength() : q_->length();
00463
00464
00465
00466 int qlim = qib_ ? (qlim_ * edp_.mean_pktsize) : qlim_;
00467
00468 curq_ = qlen;
00469
00470 if (qavg >= edp_out_.th_min && qlen > 1) {
00471 if (!edp_out_.gentle && qavg >= edp_out_.th_max ||
00472 (edp_out_.gentle && qavg >= 2 * edp_out_.th_max)) {
00473 droptype = DTYPE_FORCED;
00474 } else if (edv_out_.old == 0) {
00475
00476
00477
00478
00479
00480
00481 edv_out_.count = 1;
00482 edv_out_.count_bytes = ch->size();
00483 edv_out_.old = 1;
00484 } else if (drop_out_early(pkt)) {
00485 droptype = DTYPE_UNFORCED;
00486 }
00487 } else {
00488 edv_out_.v_prob = 0.0;
00489 edv_out_.old = 0;
00490 }
00491 if (qlen >= qlim) {
00492
00493 droptype = DTYPE_FORCED;
00494 }
00495
00496 if (droptype == DTYPE_UNFORCED) {
00497
00498 Packet *pkt_to_drop = pickPacketForECN(pkt);
00499
00500
00501
00502
00503 if (pkt_to_drop != pkt) {
00504 q_->enque(pkt);
00505
00506 q_->remove(pkt_to_drop);
00507
00508 if (hdr_flags::access(pkt_to_drop)->pri_)
00509 {
00510 in_bcount_ -=hdr_cmn::access(pkt_to_drop)->size();
00511 --in_len_;
00512 }
00513 pkt = pkt_to_drop;
00514 }
00515
00516 if (de_drop_ != NULL)
00517 de_drop_->recv(pkt);
00518 else
00519 drop(pkt);
00520 } else {
00521
00522 q_->enque(pkt);
00523
00524
00525
00526 if (droptype == DTYPE_FORCED) {
00527
00528 pkt = pickPacketToDrop();
00529 q_->remove(pkt);
00530
00531 if (hdr_flags::access(pkt)->pri_)
00532 {
00533 in_bcount_ -= hdr_cmn::access(pkt)->size();
00534 --in_len_;
00535 }
00536 drop(pkt);
00537 }
00538 }
00539 }
00540
00541 return;
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551 void
00552 RIOQueue::trace(TracedVar* v)
00553 {
00554 char wrk[500], *p;
00555
00556 if (((p = strstr(v->name(), "ave")) == NULL) &&
00557 ((p = strstr(v->name(), "in_ave")) == NULL) &&
00558 ((p = strstr(v->name(), "out_ave")) == NULL) &&
00559 ((p = strstr(v->name(), "prob")) == NULL) &&
00560 ((p = strstr(v->name(), "in_prob")) == NULL) &&
00561 ((p = strstr(v->name(), "out_prob")) == NULL) &&
00562 ((p = strstr(v->name(), "curq")) == NULL)) {
00563 fprintf(stderr, "RIO:unknown trace var %s\n",
00564 v->name());
00565 return;
00566 }
00567
00568 if (tchan_) {
00569 int n;
00570 double t = Scheduler::instance().clock();
00571
00572 if (*p == 'c') {
00573 sprintf(wrk, "Q %g %d", t, int(*((TracedInt*) v)));
00574 } else {
00575 sprintf(wrk, "%c %g %g", *p, t,
00576 double(*((TracedDouble*) v)));
00577 }
00578 n = strlen(wrk);
00579 wrk[n] = '\n';
00580 wrk[n+1] = 0;
00581 (void)Tcl_Write(tchan_, wrk, n+1);
00582 }
00583 return;
00584 }
00585
00586
00587 void RIOQueue::print_edp()
00588 {
00589 REDQueue::print_edp();
00590 printf("in_minth: %f, in_maxth: %f\n", edp_in_.th_min, edp_in_.th_max);
00591 printf("out_minth: %f, out_maxth: %f\n",
00592 edp_out_.th_min, edp_out_.th_max);
00593 printf("qlim: %d, in_idletime: %f\n", qlim_, in_idletime_);
00594 printf("=========\n");
00595 }
00596
00597 void RIOQueue::print_edv()
00598 {
00599 REDQueue::print_edv();
00600 printf("in_v_a: %f, in_v_b: %f\n", edv_in_.v_a, edv_in_.v_b);
00601 printf("out_v_a: %f, out_v_b: %f\n", edv_out_.v_a, edv_out_.v_b);
00602 }