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 #include <stdlib.h>
00037 #include <sys/types.h>
00038 #include <math.h>
00039
00040 #include "tfrc.h"
00041 #include "formula.h"
00042 #include "flags.h"
00043
00044 int hdr_tfrc::offset_;
00045 int hdr_tfrc_ack::offset_;
00046
00047 static class TFRCHeaderClass : public PacketHeaderClass {
00048 public:
00049 TFRCHeaderClass() : PacketHeaderClass("PacketHeader/TFRC",
00050 sizeof(hdr_tfrc)) {
00051 bind_offset(&hdr_tfrc::offset_);
00052 }
00053 } class_tfrchdr;
00054
00055 static class TFRC_ACKHeaderClass : public PacketHeaderClass {
00056 public:
00057 TFRC_ACKHeaderClass() : PacketHeaderClass("PacketHeader/TFRC_ACK",
00058 sizeof(hdr_tfrc_ack)) {
00059 bind_offset(&hdr_tfrc_ack::offset_);
00060 }
00061 } class_tfrc_ackhdr;
00062
00063 static class TfrcClass : public TclClass {
00064 public:
00065 TfrcClass() : TclClass("Agent/TFRC") {}
00066 TclObject* create(int, const char*const*) {
00067 return (new TfrcAgent());
00068 }
00069 } class_tfrc;
00070
00071
00072 TfrcAgent::TfrcAgent() : Agent(PT_TFRC), send_timer_(this),
00073 NoFeedbacktimer_(this), rate_(0), oldrate_(0), maxrate_(0)
00074 {
00075 bind("packetSize_", &size_);
00076 bind("rate_", &rate_);
00077 bind("df_", &df_);
00078 bind("tcp_tick_", &tcp_tick_);
00079 bind("ndatapack_", &ndatapack_);
00080 bind("ndatabytes_", &ndatabytes_);
00081 bind("true_loss_rate_", &true_loss_rate_);
00082 bind("srtt_init_", &srtt_init_);
00083 bind("rttvar_init_", &rttvar_init_);
00084 bind("rtxcur_init_", &rtxcur_init_);
00085 bind("rttvar_exp_", &rttvar_exp_);
00086 bind("T_SRTT_BITS", &T_SRTT_BITS);
00087 bind("T_RTTVAR_BITS", &T_RTTVAR_BITS);
00088 bind("InitRate_", &InitRate_);
00089 bind("overhead_", &overhead_);
00090 bind("ssmult_", &ssmult_);
00091 bind("bval_", &bval_);
00092 bind("ca_", &ca_);
00093 bind_bool("printStatus_", &printStatus_);
00094 bind_bool("conservative_", &conservative_);
00095 bind_bool("ecn_", &ecn_);
00096 bind("minrto_", &minrto_);
00097 bind("maxHeavyRounds_", &maxHeavyRounds_);
00098 bind("SndrType_", &SndrType_);
00099 bind("scmult_", &scmult_);
00100 bind_bool("oldCode_", &oldCode_);
00101 bind("rate_init_", &rate_init_);
00102 bind("rate_init_option_", &rate_init_option_);
00103 bind_bool("slow_increase_", &slow_increase_);
00104 bind_bool("ss_changes_", &ss_changes_);
00105 bind_bool("voip_", &voip_);
00106 bind("voip_max_pkt_rate_", &voip_max_pkt_rate_);
00107 bind("fsize_", &fsize_);
00108 bind_bool("useHeaders_", &useHeaders_);
00109 bind("headersize_", &headersize_);
00110 seqno_ = -1;
00111 maxseq_ = 0;
00112 datalimited_ = 0;
00113 last_pkt_time_ = 0.0;
00114 bind("maxqueue_", &maxqueue_);
00115 maxqueue_ = MAXSEQ;
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125 void TfrcAgent::sendmsg(int nbytes, const char* )
00126 {
00127 if (nbytes == -1 && maxseq_ < MAXSEQ)
00128 advanceby(MAXSEQ - maxseq_);
00129 else if (size_ > 0) {
00130 int npkts = int(nbytes/size_);
00131 npkts += (nbytes%size_ ? 1 : 0);
00132
00133
00134 if ((maxseq_ - seqno_) < maxqueue_) {
00135 advanceby(npkts);
00136 }
00137 }
00138 }
00139
00140
00141 void TfrcAgent::advanceby(int delta)
00142 {
00143 maxseq_ += delta;
00144
00145 if (seqno_ == -1) {
00146
00147 start();
00148 } else if (datalimited_ && maxseq_ > seqno_) {
00149
00150
00151 datalimited_ = 0;
00152 if (!oldCode_) {
00153 sendpkt();
00154 }
00155 }
00156 }
00157
00158 int TfrcAgent::command(int argc, const char*const* argv)
00159 {
00160 if (argc==2) {
00161
00162 if ( (strcmp(argv[1],"start")==0) && (SndrType_ == 0)) {
00163 start();
00164 return TCL_OK;
00165 }
00166 if (strcmp(argv[1],"stop")==0) {
00167 stop();
00168 return TCL_OK;
00169 }
00170 }
00171 if ((argc == 3) && (SndrType_ == 1)) {
00172
00173 if (strcmp(argv[1], "advance") == 0) {
00174 int newseq = atoi(argv[2]);
00175
00176
00177
00178
00179 if (newseq > maxseq_)
00180 advanceby(newseq - maxseq_);
00181 return (TCL_OK);
00182 }
00183 if (strcmp(argv[1], "advanceby") == 0) {
00184 advanceby(atoi(argv[2]));
00185 return (TCL_OK);
00186 }
00187 }
00188 return (Agent::command(argc, argv));
00189 }
00190
00191 void TfrcAgent::start()
00192 {
00193 seqno_=0;
00194 rate_ = InitRate_;
00195 delta_ = 0;
00196 oldrate_ = rate_;
00197 rate_change_ = SLOW_START;
00198 UrgentFlag = 1;
00199 rtt_=0;
00200 sqrtrtt_=1;
00201 rttcur_=1;
00202 tzero_ = 0;
00203 last_change_=0;
00204 maxrate_ = 0;
00205 ss_maxrate_ = 0;
00206 ndatapack_=0;
00207 ndatabytes_ = 0;
00208 true_loss_rate_ = 0;
00209 active_ = 1;
00210 round_id = 0;
00211 heavyrounds_ = 0;
00212 t_srtt_ = int(srtt_init_/tcp_tick_) << T_SRTT_BITS;
00213 t_rttvar_ = int(rttvar_init_/tcp_tick_) << T_RTTVAR_BITS;
00214 t_rtxcur_ = rtxcur_init_;
00215 rcvrate = 0 ;
00216
00217 first_pkt_rcvd = 0 ;
00218
00219 sendpkt();
00220
00221 send_timer_.resched(size_/rate_);
00222
00223
00224 NoFeedbacktimer_.resched(2*size_/rate_);
00225 }
00226
00227 void TfrcAgent::stop()
00228 {
00229 active_ = 0;
00230 send_timer_.force_cancel();
00231 }
00232
00233 void TfrcAgent::nextpkt()
00234 {
00235 double next = -1;
00236 double xrate = -1;
00237
00238 if (SndrType_ == 0) {
00239 sendpkt();
00240 }
00241 else {
00242 if (maxseq_ > seqno_) {
00243 sendpkt();
00244 } else
00245 datalimited_ = 1;
00246 }
00247
00248
00249
00250 if (slow_increase_ && (!ss_changes_ || round_id > 2)
00251 && (rate_change_ == SLOW_START)
00252 && (oldrate_+SMALLFLOAT< rate_)) {
00253 oldrate_ = oldrate_ + delta_;
00254 xrate = oldrate_;
00255 } else {
00256 if (ca_)
00257 xrate = rate_ * sqrtrtt_/sqrt(rttcur_);
00258 else
00259 xrate = rate_;
00260 }
00261 if (xrate > SMALLFLOAT) {
00262 next = size_/xrate;
00263 if (voip_) {
00264 double min_interval = 1.0/voip_max_pkt_rate_;
00265 if (next < min_interval)
00266 next = min_interval;
00267 }
00268
00269
00270
00271 next = next*(2*overhead_*Random::uniform()-overhead_+1);
00272 if (next > SMALLFLOAT)
00273 send_timer_.resched(next);
00274 }
00275 }
00276
00277 void TfrcAgent::update_rtt (double tao, double now)
00278 {
00279
00280 t_rtt_ = int((now-tao) /tcp_tick_ + 0.5);
00281 if (t_rtt_==0) t_rtt_=1;
00282 if (t_srtt_ != 0) {
00283 register short rtt_delta;
00284 rtt_delta = t_rtt_ - (t_srtt_ >> T_SRTT_BITS);
00285 if ((t_srtt_ += rtt_delta) <= 0)
00286 t_srtt_ = 1;
00287 if (rtt_delta < 0)
00288 rtt_delta = -rtt_delta;
00289 rtt_delta -= (t_rttvar_ >> T_RTTVAR_BITS);
00290 if ((t_rttvar_ += rtt_delta) <= 0)
00291 t_rttvar_ = 1;
00292 } else {
00293 t_srtt_ = t_rtt_ << T_SRTT_BITS;
00294 t_rttvar_ = t_rtt_ << (T_RTTVAR_BITS-1);
00295 }
00296 t_rtxcur_ = (((t_rttvar_ << (rttvar_exp_ + (T_SRTT_BITS - T_RTTVAR_BITS))) + t_srtt_) >> T_SRTT_BITS ) * tcp_tick_;
00297 tzero_=t_rtxcur_;
00298 if (tzero_ < minrto_)
00299 tzero_ = minrto_;
00300
00301
00302 if (rtt_ > 0) {
00303 rtt_ = df_*rtt_ + ((1-df_)*(now - tao));
00304 sqrtrtt_ = df_*sqrtrtt_ + ((1-df_)*sqrt(now - tao));
00305 } else {
00306 rtt_ = now - tao;
00307 sqrtrtt_ = sqrt(now - tao);
00308 }
00309 rttcur_ = now - tao;
00310 }
00311
00312
00313
00314
00315 void TfrcAgent::recv(Packet *pkt, Handler *)
00316 {
00317 double now = Scheduler::instance().clock();
00318 hdr_tfrc_ack *nck = hdr_tfrc_ack::access(pkt);
00319
00320 double ts = nck->timestamp_echo + nck->timestamp_offset;
00321 double rate_since_last_report = nck->rate_since_last_report;
00322
00323 double flost = nck->flost;
00324 int losses = nck->losses;
00325 true_loss_rate_ = nck->true_loss;
00326
00327 round_id ++ ;
00328 UrgentFlag = 0;
00329
00330 if (rate_since_last_report > 0) {
00331
00332 ss_maxrate_ = 2*rate_since_last_report*size_;
00333 if (conservative_) {
00334 if (losses >= 1) {
00335
00336 if (debug_) printf("time: %5.2f losses: %d rate %5.2f\n",
00337 now, losses, rate_since_last_report);
00338 maxrate_ = rate_since_last_report*size_;
00339 } else {
00340
00341 maxrate_ = scmult_*rate_since_last_report*size_;
00342 }
00343 if (debug_) printf("time: %5.2f losses: %d rate %5.2f maxrate: %5.2f\n", now, losses, rate_since_last_report, maxrate_);
00344 } else
00345 maxrate_ = 2*rate_since_last_report*size_;
00346 } else {
00347 ss_maxrate_ = 0;
00348 maxrate_ = 0;
00349 }
00350
00351
00352
00353 update_rtt (ts, now);
00354
00355
00356 if (voip_ != 1) {
00357
00358
00359
00360 fsize_ = size_;
00361 }
00362 rcvrate = p_to_b(flost, rtt_, tzero_, fsize_, bval_);
00363
00364
00365 if (voip_) {
00366
00367 double temp = rcvrate*(size_/(1.0*headersize_+size_));
00368 rcvrate = temp;
00369 }
00370
00371
00372 double t = 2*rtt_ ;
00373 if (t < 2*size_/rate_)
00374 t = 2*size_/rate_ ;
00375 NoFeedbacktimer_.resched(t);
00376
00377
00378
00379
00380 if (first_pkt_rcvd == 0) {
00381 first_pkt_rcvd = 1 ;
00382 slowstart();
00383 nextpkt();
00384 }
00385 else {
00386 if (rate_change_ == SLOW_START) {
00387 if (flost > 0) {
00388 rate_change_ = OUT_OF_SLOW_START;
00389 oldrate_ = rate_ = rcvrate;
00390 }
00391 else {
00392 slowstart();
00393 nextpkt();
00394 }
00395 }
00396 else {
00397 if (rcvrate>rate_)
00398 increase_rate(flost);
00399 else
00400 decrease_rate ();
00401 }
00402 }
00403 if (printStatus_) {
00404 printf("time: %5.2f rate: %5.2f\n", now, rate_);
00405 double packetrate = rate_ * rtt_ / size_;
00406 printf("time: %5.2f packetrate: %5.2f\n", now, packetrate);
00407 }
00408 Packet::free(pkt);
00409 }
00410
00411
00412
00413
00414
00415 double TfrcAgent::initial_rate()
00416 {
00417 if (rate_init_option_ == 1) {
00418
00419 return (rate_init_);
00420 }
00421 else if (rate_init_option_ == 2) {
00422
00423 if (size_ <= 1095) {
00424 return (4.0);
00425 } else if (size_ < 2190) {
00426 return (3.0);
00427 } else {
00428 return (2.0);
00429 }
00430 }
00431
00432 fprintf(stderr, "Wrong number of rate_init_option_ %d\n",
00433 rate_init_option_);
00434 abort();
00435 return (2.0);
00436 }
00437
00438
00439
00440
00441
00442 void TfrcAgent::slowstart ()
00443 {
00444 double now = Scheduler::instance().clock();
00445
00446 if (round_id <= 1) {
00447
00448
00449 oldrate_ = rate_;
00450 rate_ = initial_rate()*size_/rtt_;
00451
00452
00453 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00454 last_change_ = now;
00455 } else if (!ss_changes_ && rate_+SMALLFLOAT< size_/rtt_) {
00456 oldrate_ = rate_;
00457 rate_ = size_/rtt_;
00458 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00459 last_change_ = now;
00460 } else if (ss_maxrate_ > 0) {
00461
00462
00463 if (ssmult_*rate_ < ss_maxrate_ && now - last_change_ > rtt_) {
00464
00465 if (ss_changes_) oldrate_ = rate_;
00466 rate_ = ssmult_*rate_;
00467 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00468 last_change_=now;
00469 } else if (oldrate_ > ss_maxrate_) {
00470
00471
00472 rate_ = oldrate_ = 0.5*ss_maxrate_;
00473 delta_ = 0;
00474 last_change_ = now;
00475 } else if ((!ss_changes_ || round_id > 2)
00476 && rate_ > ss_maxrate_) {
00477
00478
00479 if (ss_changes_) oldrate_ = rate_;
00480 rate_ = ss_maxrate_;
00481 delta_ = (rate_ - oldrate_)/ (rate_*rtt_/size_);
00482 last_change_ = now;
00483 } else {
00484
00485 if (now - last_change_ > rtt_) {
00486 if (ss_changes_) oldrate_ = rate_;
00487 rate_ = ss_maxrate_;
00488 delta_ = (rate_ - oldrate_)/ (rate_*rtt_/size_);
00489 last_change_=now;
00490 }
00491 }
00492 } else {
00493
00494
00495
00496 if (ss_changes_) oldrate_ = rate_;
00497 if (ss_changes_) rate_ = size_/rtt_; else rate_ = ssmult_*rate_;
00498 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00499 last_change_=now;
00500 }
00501
00502 }
00503
00504 void TfrcAgent::increase_rate (double p)
00505 {
00506 double now = Scheduler::instance().clock();
00507
00508 double mult = (now-last_change_)/rtt_ ;
00509 if (mult > 2) mult = 2 ;
00510
00511 rate_ = rate_ + (size_/rtt_)*mult ;
00512 double maximumrate = (maxrate_>size_/rtt_)?maxrate_:size_/rtt_ ;
00513 maximumrate = (maximumrate>rcvrate)?rcvrate:maximumrate;
00514 rate_ = (rate_ > maximumrate)?maximumrate:rate_ ;
00515
00516 rate_change_ = CONG_AVOID;
00517 last_change_ = now;
00518 heavyrounds_ = 0;
00519 }
00520
00521 void TfrcAgent::decrease_rate ()
00522 {
00523 double now = Scheduler::instance().clock();
00524 rate_ = rcvrate;
00525 double maximumrate = (maxrate_>size_/rtt_)?maxrate_:size_/rtt_ ;
00526
00527
00528
00529
00530 if (rate_ > maximumrate)
00531 heavyrounds_++;
00532 else
00533 heavyrounds_ = 0;
00534 if (heavyrounds_ > maxHeavyRounds_) {
00535 rate_ = (rate_ > maximumrate)?maximumrate:rate_ ;
00536 }
00537
00538 rate_change_ = RATE_DECREASE;
00539 last_change_ = now;
00540 }
00541
00542 void TfrcAgent::sendpkt()
00543 {
00544 if (active_) {
00545 double now = Scheduler::instance().clock();
00546 Packet* p = allocpkt();
00547 hdr_tfrc *tfrch = hdr_tfrc::access(p);
00548 hdr_flags* hf = hdr_flags::access(p);
00549 if (ecn_) {
00550 hf->ect() = 1;
00551 }
00552 tfrch->seqno=seqno_++;
00553 tfrch->timestamp=Scheduler::instance().clock();
00554 tfrch->rtt=rtt_;
00555 tfrch->tzero=tzero_;
00556 tfrch->rate=rate_;
00557 tfrch->psize=size_;
00558 tfrch->fsize=fsize_;
00559 tfrch->UrgentFlag=UrgentFlag;
00560 tfrch->round_id=round_id;
00561 ndatapack_++;
00562 ndatabytes_ += size_;
00563 if (useHeaders_ == true) {
00564 hdr_cmn::access(p)->size() += headersize_;
00565 }
00566 last_pkt_time_ = now;
00567 send(p, 0);
00568 }
00569 }
00570
00571 void TfrcAgent::reduce_rate_on_no_feedback()
00572 {
00573 rate_change_ = RATE_DECREASE;
00574 if (oldCode_ || !datalimited_ || rate_ > 4.0 * size_/rtt_ ) {
00575
00576
00577 rate_*=0.5;
00578 }
00579 UrgentFlag = 1;
00580 round_id ++ ;
00581 double t = 2*rtt_ ;
00582 if (t < 2*size_/rate_)
00583 t = 2*size_/rate_ ;
00584 NoFeedbacktimer_.resched(t);
00585 nextpkt();
00586 }
00587
00588 void TfrcSendTimer::expire(Event *) {
00589 a_->nextpkt();
00590 }
00591
00592 void TfrcNoFeedbackTimer::expire(Event *) {
00593 a_->reduce_rate_on_no_feedback ();
00594
00595
00596
00597
00598
00599 }