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("srtt_init_", &srtt_init_);
00081 bind("rttvar_init_", &rttvar_init_);
00082 bind("rtxcur_init_", &rtxcur_init_);
00083 bind("rttvar_exp_", &rttvar_exp_);
00084 bind("T_SRTT_BITS", &T_SRTT_BITS);
00085 bind("T_RTTVAR_BITS", &T_RTTVAR_BITS);
00086 bind("InitRate_", &InitRate_);
00087 bind("overhead_", &overhead_);
00088 bind("ssmult_", &ssmult_);
00089 bind("bval_", &bval_);
00090 bind("ca_", &ca_);
00091 bind_bool("printStatus_", &printStatus_);
00092 bind_bool("conservative_", &conservative_);
00093 bind_bool("ecn_", &ecn_);
00094 bind("maxHeavyRounds_", &maxHeavyRounds_);
00095 bind("SndrType_", &SndrType_);
00096 bind("scmult_", &scmult_);
00097 bind_bool("oldCode_", &oldCode_);
00098 seqno_ = -1;
00099 maxseq_ = 0;
00100 datalimited_ = 0;
00101 last_pkt_time_ = 0.0;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111 void TfrcAgent::sendmsg(int nbytes, const char* )
00112 {
00113 if (nbytes == -1 && maxseq_ < MAXSEQ)
00114 advanceby(MAXSEQ - maxseq_);
00115 else if (size_ > 0) {
00116 int npkts = int(nbytes/size_);
00117 npkts += (nbytes%size_ ? 1 : 0);
00118
00119
00120 advanceby(npkts);
00121 }
00122 }
00123
00124
00125 void TfrcAgent::advanceby(int delta)
00126 {
00127 maxseq_ += delta;
00128
00129 if (seqno_ == -1) {
00130
00131 start();
00132 } else if (datalimited_ && maxseq_ > seqno_) {
00133
00134
00135 datalimited_ = 0;
00136 if (!oldCode_) {
00137 sendpkt();
00138 }
00139 }
00140 }
00141
00142 int TfrcAgent::command(int argc, const char*const* argv)
00143 {
00144 if (argc==2) {
00145
00146 if ( (strcmp(argv[1],"start")==0) && (SndrType_ == 0)) {
00147 start();
00148 return TCL_OK;
00149 }
00150 if (strcmp(argv[1],"stop")==0) {
00151 stop();
00152 return TCL_OK;
00153 }
00154 }
00155 if ((argc == 3) && (SndrType_ == 1)) {
00156
00157 if (strcmp(argv[1], "advance") == 0) {
00158 int newseq = atoi(argv[2]);
00159
00160
00161
00162
00163 if (newseq > maxseq_)
00164 advanceby(newseq - maxseq_);
00165 return (TCL_OK);
00166 }
00167 if (strcmp(argv[1], "advanceby") == 0) {
00168 advanceby(atoi(argv[2]));
00169 return (TCL_OK);
00170 }
00171 }
00172 return (Agent::command(argc, argv));
00173 }
00174
00175 void TfrcAgent::start()
00176 {
00177 seqno_=0;
00178 rate_ = InitRate_;
00179 delta_ = 0;
00180 oldrate_ = rate_;
00181 rate_change_ = SLOW_START;
00182 UrgentFlag = 1;
00183 rtt_=0;
00184 sqrtrtt_=1;
00185 rttcur_=1;
00186 tzero_ = 0;
00187 last_change_=0;
00188 maxrate_ = 0;
00189 ss_maxrate_ = 0;
00190 ndatapack_=0;
00191 active_ = 1;
00192 round_id = 0;
00193 heavyrounds_ = 0;
00194 t_srtt_ = int(srtt_init_/tcp_tick_) << T_SRTT_BITS;
00195 t_rttvar_ = int(rttvar_init_/tcp_tick_) << T_RTTVAR_BITS;
00196 t_rtxcur_ = rtxcur_init_;
00197 rcvrate = 0 ;
00198
00199 first_pkt_rcvd = 0 ;
00200
00201 sendpkt();
00202
00203 send_timer_.resched(size_/rate_);
00204
00205
00206 NoFeedbacktimer_.resched(2*size_/rate_);
00207 }
00208
00209 void TfrcAgent::stop()
00210 {
00211 active_ = 0;
00212 send_timer_.force_cancel();
00213 }
00214
00215 void TfrcAgent::nextpkt()
00216 {
00217 double next = -1;
00218 double xrate = -1;
00219
00220 if (SndrType_ == 0) {
00221 sendpkt();
00222 }
00223 else {
00224 if (maxseq_ > seqno_) {
00225 sendpkt();
00226 } else
00227 datalimited_ = 1;
00228 }
00229
00230
00231
00232 if ((rate_change_ == SLOW_START) && (oldrate_+SMALLFLOAT< rate_)) {
00233 oldrate_ = oldrate_ + delta_;
00234 xrate = oldrate_;
00235 }
00236 else {
00237 if (ca_)
00238 xrate = rate_ * sqrtrtt_/sqrt(rttcur_);
00239 else
00240 xrate = rate_;
00241 }
00242 if (xrate > SMALLFLOAT) {
00243 next = size_/xrate;
00244
00245
00246
00247 next = next*(2*overhead_*Random::uniform()-overhead_+1);
00248 if (next > SMALLFLOAT)
00249 send_timer_.resched(next);
00250 }
00251 }
00252
00253 void TfrcAgent::update_rtt (double tao, double now)
00254 {
00255
00256 t_rtt_ = int((now-tao) /tcp_tick_ + 0.5);
00257 if (t_rtt_==0) t_rtt_=1;
00258 if (t_srtt_ != 0) {
00259 register short delta;
00260 delta = t_rtt_ - (t_srtt_ >> T_SRTT_BITS);
00261 if ((t_srtt_ += delta) <= 0)
00262 t_srtt_ = 1;
00263 if (delta < 0)
00264 delta = -delta;
00265 delta -= (t_rttvar_ >> T_RTTVAR_BITS);
00266 if ((t_rttvar_ += delta) <= 0)
00267 t_rttvar_ = 1;
00268 } else {
00269 t_srtt_ = t_rtt_ << T_SRTT_BITS;
00270 t_rttvar_ = t_rtt_ << (T_RTTVAR_BITS-1);
00271 }
00272 t_rtxcur_ = (((t_rttvar_ << (rttvar_exp_ + (T_SRTT_BITS - T_RTTVAR_BITS))) + t_srtt_) >> T_SRTT_BITS ) * tcp_tick_;
00273 tzero_=t_rtxcur_;
00274
00275
00276 if (rtt_ > 0) {
00277 rtt_ = df_*rtt_ + ((1-df_)*(now - tao));
00278 sqrtrtt_ = df_*sqrtrtt_ + ((1-df_)*sqrt(now - tao));
00279 } else {
00280 rtt_ = now - tao;
00281 sqrtrtt_ = sqrt(now - tao);
00282 }
00283 rttcur_ = now - tao;
00284 }
00285
00286
00287
00288
00289 void TfrcAgent::recv(Packet *pkt, Handler *)
00290 {
00291 double now = Scheduler::instance().clock();
00292 hdr_tfrc_ack *nck = hdr_tfrc_ack::access(pkt);
00293 double ts = nck->timestamp_echo;
00294 double rate_since_last_report = nck->rate_since_last_report;
00295
00296 double flost = nck->flost;
00297 int losses = nck->losses;
00298
00299 round_id ++ ;
00300 UrgentFlag = 0;
00301
00302 if (rate_since_last_report > 0) {
00303
00304 ss_maxrate_ = 2*rate_since_last_report*size_;
00305 if (conservative_) {
00306 if (losses >= 1) {
00307
00308 if (debug_) printf("time: %5.2f losses: %d rate %5.2f\n",
00309 now, losses, rate_since_last_report);
00310 maxrate_ = rate_since_last_report*size_;
00311 } else {
00312
00313 maxrate_ = scmult_*rate_since_last_report*size_;
00314 }
00315 if (debug_) printf("time: %5.2f losses: %d rate %5.2f maxrate: %5.2f\n", now, losses, rate_since_last_report, maxrate_);
00316 } else
00317 maxrate_ = 2*rate_since_last_report*size_;
00318 } else {
00319 ss_maxrate_ = 0;
00320 maxrate_ = 0;
00321 }
00322
00323
00324
00325 update_rtt (ts, now);
00326
00327
00328 rcvrate = p_to_b(flost, rtt_, tzero_, size_, bval_);
00329
00330
00331 double t = 2*rtt_ ;
00332 if (t < 2*size_/rate_)
00333 t = 2*size_/rate_ ;
00334 NoFeedbacktimer_.resched(t);
00335
00336
00337
00338
00339 if (first_pkt_rcvd == 0) {
00340 first_pkt_rcvd = 1 ;
00341 slowstart ();
00342 nextpkt();
00343 }
00344 else {
00345 if (rate_change_ == SLOW_START) {
00346 if (flost > 0) {
00347 rate_change_ = OUT_OF_SLOW_START;
00348 oldrate_ = rate_ = rcvrate;
00349 }
00350 else {
00351 slowstart ();
00352 nextpkt();
00353 }
00354 }
00355 else {
00356 if (rcvrate>rate_)
00357 increase_rate(flost);
00358 else
00359 decrease_rate ();
00360 }
00361 }
00362 if (printStatus_) {
00363 printf("time: %5.2f rate: %5.2f\n", now, rate_);
00364 double packetrate = rate_ * rtt_ / size_;
00365 printf("time: %5.2f packetrate: %5.2f\n", now, packetrate);
00366 }
00367 Packet::free(pkt);
00368 }
00369
00370 void TfrcAgent::slowstart ()
00371 {
00372 double now = Scheduler::instance().clock();
00373
00374 if (rate_+SMALLFLOAT< size_/rtt_ ) {
00375
00376
00377 oldrate_ = rate_;
00378 rate_ = size_/rtt_;
00379 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00380 last_change_ = now;
00381 } else {
00382
00383
00384 if (ss_maxrate_ > 0) {
00385 if (ssmult_*rate_ < ss_maxrate_ && now - last_change_ > rtt_) {
00386 rate_ = ssmult_*rate_;
00387 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00388 last_change_=now;
00389 } else {
00390 if ( (oldrate_ > ss_maxrate_) || (rate_ > ss_maxrate_)) {
00391 if (oldrate_ > ss_maxrate_) {
00392 delta_ = 0;
00393 rate_ = oldrate_ = 0.5*ss_maxrate_;
00394 last_change_ = now;
00395 } else {
00396 rate_ = ss_maxrate_;
00397 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00398 last_change_ = now;
00399 }
00400 } else {
00401 if (now - last_change_ > rtt_) {
00402 rate_ = ss_maxrate_;
00403 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00404 last_change_=now;
00405 }
00406 }
00407 }
00408 } else {
00409 rate_ = ssmult_*rate_;
00410 delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
00411 last_change_=now;
00412 }
00413 }
00414 }
00415
00416 void TfrcAgent::increase_rate (double p)
00417 {
00418 double now = Scheduler::instance().clock();
00419
00420 double mult = (now-last_change_)/rtt_ ;
00421 if (mult > 2) mult = 2 ;
00422
00423 rate_ = rate_ + (size_/rtt_)*mult ;
00424 double maximumrate = (maxrate_>size_/rtt_)?maxrate_:size_/rtt_ ;
00425 maximumrate = (maximumrate>rcvrate)?rcvrate:maximumrate;
00426 rate_ = (rate_ > maximumrate)?maximumrate:rate_ ;
00427
00428 rate_change_ = CONG_AVOID;
00429 last_change_ = now;
00430 heavyrounds_ = 0;
00431 }
00432
00433 void TfrcAgent::decrease_rate ()
00434 {
00435 double now = Scheduler::instance().clock();
00436 rate_ = rcvrate;
00437 double maximumrate = (maxrate_>size_/rtt_)?maxrate_:size_/rtt_ ;
00438
00439
00440
00441
00442 if (rate_ > maximumrate)
00443 heavyrounds_++;
00444 else
00445 heavyrounds_ = 0;
00446 if (heavyrounds_ > maxHeavyRounds_) {
00447 rate_ = (rate_ > maximumrate)?maximumrate:rate_ ;
00448 }
00449
00450 rate_change_ = RATE_DECREASE;
00451 last_change_ = now;
00452 }
00453
00454 void TfrcAgent::sendpkt()
00455 {
00456 if (active_) {
00457 Packet* p = allocpkt();
00458 hdr_tfrc *tfrch = hdr_tfrc::access(p);
00459 hdr_flags* hf = hdr_flags::access(p);
00460 if (ecn_) {
00461 hf->ect() = 1;
00462 }
00463 tfrch->seqno=seqno_++;
00464 tfrch->timestamp=Scheduler::instance().clock();
00465 tfrch->rtt=rtt_;
00466 tfrch->tzero=tzero_;
00467 tfrch->rate=rate_;
00468 tfrch->psize=size_;
00469 tfrch->UrgentFlag=UrgentFlag;
00470 tfrch->round_id=round_id;
00471 ndatapack_++;
00472 double now = Scheduler::instance().clock();
00473 last_pkt_time_ = now;
00474 send(p, 0);
00475 }
00476 }
00477
00478 void TfrcAgent::reduce_rate_on_no_feedback()
00479 {
00480 rate_change_ = RATE_DECREASE;
00481 if (oldCode_ || !datalimited_ || rate_ > 4.0 * size_/rtt_ ) {
00482
00483
00484 rate_*=0.5;
00485 }
00486 UrgentFlag = 1;
00487 round_id ++ ;
00488 double t = 2*rtt_ ;
00489 if (t < 2*size_/rate_)
00490 t = 2*size_/rate_ ;
00491 NoFeedbacktimer_.resched(t);
00492 nextpkt();
00493 }
00494
00495 void TfrcSendTimer::expire(Event *) {
00496 a_->nextpkt();
00497 }
00498
00499 void TfrcNoFeedbackTimer::expire(Event *) {
00500 a_->reduce_rate_on_no_feedback ();
00501 }