📄 tfrc.cc
字号:
/* fine grained RTT estimate for use in the equation */ if (rtt_ > 0) { rtt_ = df_*rtt_ + ((1-df_)*(now - tao)); sqrtrtt_ = df_*sqrtrtt_ + ((1-df_)*sqrt(now - tao)); } else { rtt_ = now - tao; sqrtrtt_ = sqrt(now - tao); } rttcur_ = now - tao;}/* * Receive a status report from the receiver. */void TfrcAgent::recv(Packet *pkt, Handler *){ double now = Scheduler::instance().clock(); hdr_tfrc_ack *nck = hdr_tfrc_ack::access(pkt); //double ts = nck->timestamp_echo; double ts = nck->timestamp_echo + nck->timestamp_offset; double rate_since_last_report = nck->rate_since_last_report; // double NumFeedback_ = nck->NumFeedback_; double flost = nck->flost; int losses = nck->losses; true_loss_rate_ = nck->true_loss; round_id ++ ; UrgentFlag = 0; if (rate_since_last_report > 0) { /* compute the max rate for slow-start as two times rcv rate */ ss_maxrate_ = 2*rate_since_last_report*size_; if (conservative_) { if (losses >= 1) { /* there was a loss in the most recent RTT */ if (debug_) printf("time: %5.2f losses: %d rate %5.2f\n", now, losses, rate_since_last_report); maxrate_ = rate_since_last_report*size_; } else { /* there was no loss in the most recent RTT */ maxrate_ = scmult_*rate_since_last_report*size_; } if (debug_) printf("time: %5.2f losses: %d rate %5.2f maxrate: %5.2f\n", now, losses, rate_since_last_report, maxrate_); } else maxrate_ = 2*rate_since_last_report*size_; } else { ss_maxrate_ = 0; maxrate_ = 0; } /* update the round trip time */ update_rtt (ts, now); /* .. and estimate of fair rate */ if (voip_ != 1) { // From RFC 3714: // The voip flow gets to send at the same rate as // a TCP flow with 1460-byte packets. fsize_ = size_; } rcvrate = p_to_b(flost, rtt_, tzero_, fsize_, bval_); // rcvrate is in bytes per second, based on fairness with a // TCP connection with the same packet size size_. if (voip_) { // Subtract the bandwidth used by headers. double temp = rcvrate*(size_/(1.0*headersize_+size_)); rcvrate = temp; } /* if we get no more feedback for some time, cut rate in half */ double t = 2*rtt_ ; if (t < 2*size_/rate_) t = 2*size_/rate_ ; NoFeedbacktimer_.resched(t); /* if we are in slow start and we just saw a loss */ /* then come out of slow start */ if (first_pkt_rcvd == 0) { first_pkt_rcvd = 1 ; slowstart(); nextpkt(); } else { if (rate_change_ == SLOW_START) { if (flost > 0) { rate_change_ = OUT_OF_SLOW_START; oldrate_ = rate_ = rcvrate; } else { slowstart(); nextpkt(); } } else { if (rcvrate>rate_) increase_rate(flost); else decrease_rate (); } } if (printStatus_) { printf("time: %5.2f rate: %5.2f\n", now, rate_); double packetrate = rate_ * rtt_ / size_; printf("time: %5.2f packetrate: %5.2f\n", now, packetrate); } Packet::free(pkt);}/* * Used in setting the initial rate. * This is from TcpAgent::initial_wnd(). */double TfrcAgent::initial_rate(){ if (rate_init_option_ == 1) { // init_option = 1: static initial rate of rate_init_ return (rate_init_); } else if (rate_init_option_ == 2) { // do initial rate according to RFC 3390. if (size_ <= 1095) { return (4.0); } else if (size_ < 2190) { return (3.0); } else { return (2.0); } } // XXX what should we return here??? fprintf(stderr, "Wrong number of rate_init_option_ %d\n", rate_init_option_); abort(); return (2.0); // XXX make msvc happy.}// ss_maxrate_ = 2*rate_since_last_report*size_;// rate_: the rate set from the last pass through slowstart()// oldrate_: the rate the time before that.void TfrcAgent::slowstart () { double now = Scheduler::instance().clock(); if (round_id <= 1) { /* This is the first report, so */ /* change rate to initial rate.*/ oldrate_ = rate_; rate_ = initial_rate()*size_/rtt_; /* Compute delta so that if slow_increase_ is set to true, */ /* rate increases slowly to new value. */ delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_); last_change_ = now; } else if (!ss_changes_ && rate_+SMALLFLOAT< size_/rtt_) { oldrate_ = rate_; rate_ = size_/rtt_; delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_); last_change_ = now; } else if (ss_maxrate_ > 0) { /* Compute delta, so that if slow_increase_ is set, */ /* the rate increases slowly to its new value. */ if (ssmult_*rate_ < ss_maxrate_ && now - last_change_ > rtt_) { /* Multiply the rate by ssmult_. */ if (ss_changes_) oldrate_ = rate_; rate_ = ssmult_*rate_; delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_); last_change_=now; } else if (oldrate_ > ss_maxrate_) { // Time to reduce the sending rate, // to emulate ack-clocking. rate_ = oldrate_ = 0.5*ss_maxrate_; delta_ = 0; last_change_ = now; } else if ((!ss_changes_ || round_id > 2) && rate_ > ss_maxrate_) { // if round_id is 2, then ss_maxrate_ doesn't // reflect the slow-start sending rate yet. if (ss_changes_) oldrate_ = rate_; rate_ = ss_maxrate_; delta_ = (rate_ - oldrate_)/ (rate_*rtt_/size_); last_change_ = now; } else { // rate < ss_maxrate < ssmult_*rate_ if (now - last_change_ > rtt_) { if (ss_changes_) oldrate_ = rate_; rate_ = ss_maxrate_; delta_ = (rate_ - oldrate_)/ (rate_*rtt_/size_); last_change_=now; } } } else { // If we get here, ss_maxrate <= 0, so the receive rate is 0. // We should go back to a very small sending rate!!! // Changed by Sally on 10/20/2004. if (ss_changes_) oldrate_ = rate_; if (ss_changes_) rate_ = size_/rtt_; else rate_ = ssmult_*rate_; delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_); last_change_=now; } }void TfrcAgent::increase_rate (double p){ double now = Scheduler::instance().clock(); double mult = (now-last_change_)/rtt_ ; if (mult > 2) mult = 2 ; rate_ = rate_ + (size_/rtt_)*mult ; double maximumrate = (maxrate_>size_/rtt_)?maxrate_:size_/rtt_ ; maximumrate = (maximumrate>rcvrate)?rcvrate:maximumrate; rate_ = (rate_ > maximumrate)?maximumrate:rate_ ; rate_change_ = CONG_AVOID; last_change_ = now; heavyrounds_ = 0;} void TfrcAgent::decrease_rate () { double now = Scheduler::instance().clock(); rate_ = rcvrate; double maximumrate = (maxrate_>size_/rtt_)?maxrate_:size_/rtt_ ; // Allow sending rate to be greater than maximumrate // (which is by default twice the receiving rate) // for at most maxHeavyRounds_ rounds. if (rate_ > maximumrate) heavyrounds_++; else heavyrounds_ = 0; if (heavyrounds_ > maxHeavyRounds_) { rate_ = (rate_ > maximumrate)?maximumrate:rate_ ; } rate_change_ = RATE_DECREASE; last_change_ = now;}void TfrcAgent::sendpkt(){ if (active_) { double now = Scheduler::instance().clock(); Packet* p = allocpkt(); hdr_tfrc *tfrch = hdr_tfrc::access(p); hdr_flags* hf = hdr_flags::access(p); if (ecn_) { hf->ect() = 1; // ECN-capable transport } tfrch->seqno=seqno_++; tfrch->timestamp=Scheduler::instance().clock(); tfrch->rtt=rtt_; tfrch->tzero=tzero_; tfrch->rate=rate_; tfrch->psize=size_; tfrch->fsize=fsize_; tfrch->UrgentFlag=UrgentFlag; tfrch->round_id=round_id; ndatapack_++; ndatabytes_ += size_; if (useHeaders_ == true) { hdr_cmn::access(p)->size() += headersize_; } last_pkt_time_ = now; send(p, 0); }}void TfrcAgent::reduce_rate_on_no_feedback(){ rate_change_ = RATE_DECREASE; if (oldCode_ || !datalimited_ || rate_ > 4.0 * size_/rtt_ ) { // if we are not datalimited, // or the current rate is greater than four pkts per RTT rate_*=0.5; } UrgentFlag = 1; round_id ++ ; double t = 2*rtt_ ; if (t < 2*size_/rate_) t = 2*size_/rate_ ; NoFeedbacktimer_.resched(t); nextpkt();}void TfrcSendTimer::expire(Event *) { a_->nextpkt();}void TfrcNoFeedbackTimer::expire(Event *) { a_->reduce_rate_on_no_feedback (); // TODO: if the first (SYN) packet was dropped, then don't use // the larger initial rates from RFC 3390: // if (highest_ack_ == -1 && wnd_init_option_ == 2) // wnd_init_option_ = 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -