📄 tfrc.cc
字号:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1999 International Computer Science Institute * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by ACIRI, the AT&T * Center for Internet Research at ICSI (the International Computer * Science Institute). * 4. Neither the name of ACIRI nor of ICSI may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY ICSI AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL ICSI OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <stdlib.h>#include <sys/types.h>#include <math.h> #include "tfrc.h"#include "formula.h"#include "flags.h"int hdr_tfrc::offset_;int hdr_tfrc_ack::offset_;static class TFRCHeaderClass : public PacketHeaderClass {public: TFRCHeaderClass() : PacketHeaderClass("PacketHeader/TFRC", sizeof(hdr_tfrc)) { bind_offset(&hdr_tfrc::offset_); }} class_tfrchdr;static class TFRC_ACKHeaderClass : public PacketHeaderClass {public: TFRC_ACKHeaderClass() : PacketHeaderClass("PacketHeader/TFRC_ACK", sizeof(hdr_tfrc_ack)) { bind_offset(&hdr_tfrc_ack::offset_); }} class_tfrc_ackhdr;static class TfrcClass : public TclClass {public: TfrcClass() : TclClass("Agent/TFRC") {} TclObject* create(int, const char*const*) { return (new TfrcAgent()); }} class_tfrc;TfrcAgent::TfrcAgent() : Agent(PT_TFRC), send_timer_(this), NoFeedbacktimer_(this), rate_(0), oldrate_(0), maxrate_(0){ bind("packetSize_", &size_); bind("rate_", &rate_); bind("df_", &df_); bind("tcp_tick_", &tcp_tick_); bind("ndatapack_", &ndatapack_); bind("ndatabytes_", &ndatabytes_); bind("true_loss_rate_", &true_loss_rate_); bind("srtt_init_", &srtt_init_); bind("rttvar_init_", &rttvar_init_); bind("rtxcur_init_", &rtxcur_init_); bind("rttvar_exp_", &rttvar_exp_); bind("T_SRTT_BITS", &T_SRTT_BITS); bind("T_RTTVAR_BITS", &T_RTTVAR_BITS); bind("InitRate_", &InitRate_); bind("overhead_", &overhead_); bind("ssmult_", &ssmult_); bind("bval_", &bval_); bind("ca_", &ca_); bind_bool("printStatus_", &printStatus_); bind_bool("conservative_", &conservative_); bind_bool("ecn_", &ecn_); bind("minrto_", &minrto_); bind("maxHeavyRounds_", &maxHeavyRounds_); bind("SndrType_", &SndrType_); bind("scmult_", &scmult_); bind_bool("oldCode_", &oldCode_); bind("rate_init_", &rate_init_); bind("rate_init_option_", &rate_init_option_); bind_bool("slow_increase_", &slow_increase_); bind_bool("ss_changes_", &ss_changes_); bind_bool("voip_", &voip_); bind("voip_max_pkt_rate_", &voip_max_pkt_rate_); bind("fsize_", &fsize_); bind_bool("useHeaders_", &useHeaders_); bind("headersize_", &headersize_); seqno_ = -1; maxseq_ = 0; datalimited_ = 0; last_pkt_time_ = 0.0; bind("maxqueue_", &maxqueue_); maxqueue_ = MAXSEQ;}/* * Must convert bytes into packets. * If nbytes == -1, this corresponds to infinite send. We approximate * infinite by a very large number (MAXSEQ). * For simplicity, when bytes are converted to packets, fractional packets * are always rounded up. */void TfrcAgent::sendmsg(int nbytes, const char* /*flags*/){ if (nbytes == -1 && maxseq_ < MAXSEQ) advanceby(MAXSEQ - maxseq_); else if (size_ > 0) { int npkts = int(nbytes/size_); npkts += (nbytes%size_ ? 1 : 0); // maxqueue was added by Tom Phelan, to control the // transmit queue from the application. if ((maxseq_ - seqno_) < maxqueue_) { advanceby(npkts); } }}void TfrcAgent::advanceby(int delta){ maxseq_ += delta; if (seqno_ == -1) { // if no packets hve been sent so far, call start. start(); } else if (datalimited_ && maxseq_ > seqno_) { // We were data-limited - send a packet now! // The old code always waited for a timer to expire!! datalimited_ = 0; if (!oldCode_) { sendpkt(); } }} int TfrcAgent::command(int argc, const char*const* argv){ if (argc==2) { // are we an infinite sender? if ( (strcmp(argv[1],"start")==0) && (SndrType_ == 0)) { start(); return TCL_OK; } if (strcmp(argv[1],"stop")==0) { stop(); return TCL_OK; } } if ((argc == 3) && (SndrType_ == 1)) { // or do we need an FTP type app? if (strcmp(argv[1], "advance") == 0) { int newseq = atoi(argv[2]); // THIS ISN"T USED. // newseq: new sequence // seqno_: next sequence to be sent // maxseq_: max seq_ produced by app so far. if (newseq > maxseq_) advanceby(newseq - maxseq_); return (TCL_OK); } if (strcmp(argv[1], "advanceby") == 0) { advanceby(atoi(argv[2])); return (TCL_OK); } } return (Agent::command(argc, argv));}void TfrcAgent::start(){ seqno_=0; rate_ = InitRate_; delta_ = 0; oldrate_ = rate_; rate_change_ = SLOW_START; UrgentFlag = 1; rtt_=0; sqrtrtt_=1; rttcur_=1; tzero_ = 0; last_change_=0; maxrate_ = 0; ss_maxrate_ = 0; ndatapack_=0; ndatabytes_ = 0; true_loss_rate_ = 0; active_ = 1; round_id = 0; heavyrounds_ = 0; t_srtt_ = int(srtt_init_/tcp_tick_) << T_SRTT_BITS; t_rttvar_ = int(rttvar_init_/tcp_tick_) << T_RTTVAR_BITS; t_rtxcur_ = rtxcur_init_; rcvrate = 0 ; first_pkt_rcvd = 0 ; // send the first packet sendpkt(); // ... at initial rate send_timer_.resched(size_/rate_); // ... and start timer so we can cut rate // in half if we do not get feedback NoFeedbacktimer_.resched(2*size_/rate_); }void TfrcAgent::stop(){ active_ = 0; send_timer_.force_cancel();}void TfrcAgent::nextpkt(){ double next = -1; double xrate = -1; if (SndrType_ == 0) { sendpkt(); } else { if (maxseq_ > seqno_) { sendpkt(); } else datalimited_ = 1; } // If slow_increase_ is set, then during slow start, we increase rate // slowly - by amount delta per packet if (slow_increase_ && (!ss_changes_ || round_id > 2) && (rate_change_ == SLOW_START) && (oldrate_+SMALLFLOAT< rate_)) { oldrate_ = oldrate_ + delta_; xrate = oldrate_; } else { if (ca_) xrate = rate_ * sqrtrtt_/sqrt(rttcur_); else xrate = rate_; } if (xrate > SMALLFLOAT) { next = size_/xrate; if (voip_) { double min_interval = 1.0/voip_max_pkt_rate_; if (next < min_interval) next = min_interval; } // // randomize between next*(1 +/- woverhead_) // next = next*(2*overhead_*Random::uniform()-overhead_+1); if (next > SMALLFLOAT) send_timer_.resched(next); }}void TfrcAgent::update_rtt (double tao, double now) { /* the TCP update */ t_rtt_ = int((now-tao) /tcp_tick_ + 0.5); if (t_rtt_==0) t_rtt_=1; if (t_srtt_ != 0) { register short rtt_delta; rtt_delta = t_rtt_ - (t_srtt_ >> T_SRTT_BITS); if ((t_srtt_ += rtt_delta) <= 0) t_srtt_ = 1; if (rtt_delta < 0) rtt_delta = -rtt_delta; rtt_delta -= (t_rttvar_ >> T_RTTVAR_BITS); if ((t_rttvar_ += rtt_delta) <= 0) t_rttvar_ = 1; } else { t_srtt_ = t_rtt_ << T_SRTT_BITS; t_rttvar_ = t_rtt_ << (T_RTTVAR_BITS-1); } t_rtxcur_ = (((t_rttvar_ << (rttvar_exp_ + (T_SRTT_BITS - T_RTTVAR_BITS))) + t_srtt_) >> T_SRTT_BITS ) * tcp_tick_; tzero_=t_rtxcur_; if (tzero_ < minrto_) tzero_ = minrto_;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -