tfrc.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:19k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1999  International Computer Science Institute
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  * This product includes software developed by ACIRI, the AT&T 
  17.  *      Center for Internet Research at ICSI (the International Computer
  18.  *      Science Institute).
  19.  * 4. Neither the name of ACIRI nor of ICSI may be used
  20.  *    to endorse or promote products derived from this software without
  21.  *    specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY ICSI AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL ICSI OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  */
  35. #include <stdlib.h>
  36. #include <sys/types.h>
  37. #include <math.h>
  38.  
  39. #include "tfrc.h"
  40. #include "formula.h"
  41. #include "flags.h"
  42. int hdr_tfrc::offset_;
  43. int hdr_tfrc_ack::offset_;
  44. static class TFRCHeaderClass : public PacketHeaderClass {
  45. public:
  46. TFRCHeaderClass() : PacketHeaderClass("PacketHeader/TFRC",
  47.       sizeof(hdr_tfrc)) {
  48. bind_offset(&hdr_tfrc::offset_);
  49. }
  50. } class_tfrchdr;
  51. static class TFRC_ACKHeaderClass : public PacketHeaderClass {
  52. public:
  53. TFRC_ACKHeaderClass() : PacketHeaderClass("PacketHeader/TFRC_ACK",
  54.   sizeof(hdr_tfrc_ack)) {
  55. bind_offset(&hdr_tfrc_ack::offset_);
  56. }
  57. } class_tfrc_ackhdr;
  58. static class TfrcClass : public TclClass {
  59. public:
  60.    TfrcClass() : TclClass("Agent/TFRC") {}
  61.    TclObject* create(int, const char*const*) {
  62.      return (new TfrcAgent());
  63.    }
  64. } class_tfrc;
  65. TfrcAgent::TfrcAgent() : Agent(PT_TFRC), send_timer_(this), 
  66.  NoFeedbacktimer_(this), rate_(0), oldrate_(0), maxrate_(0)
  67. {
  68. bind("packetSize_", &size_);
  69. bind("rate_", &rate_);
  70. bind("df_", &df_);
  71. bind("tcp_tick_", &tcp_tick_);
  72. bind("ndatapack_", &ndatapack_);
  73. bind("ndatabytes_", &ndatabytes_);
  74. bind("true_loss_rate_", &true_loss_rate_);
  75. bind("srtt_init_", &srtt_init_);
  76. bind("rttvar_init_", &rttvar_init_);
  77. bind("rtxcur_init_", &rtxcur_init_);
  78. bind("rttvar_exp_", &rttvar_exp_);
  79. bind("T_SRTT_BITS", &T_SRTT_BITS);
  80. bind("T_RTTVAR_BITS", &T_RTTVAR_BITS);
  81. bind("InitRate_", &InitRate_);
  82. bind("overhead_", &overhead_);
  83. bind("ssmult_", &ssmult_);
  84. bind("bval_", &bval_);
  85. bind("ca_", &ca_);
  86. bind_bool("printStatus_", &printStatus_);
  87. bind_bool("conservative_", &conservative_);
  88. bind_bool("ecn_", &ecn_);
  89. bind("minrto_", &minrto_);
  90. bind("maxHeavyRounds_", &maxHeavyRounds_);
  91. bind("SndrType_", &SndrType_); 
  92. bind("scmult_", &scmult_);
  93. bind_bool("oldCode_", &oldCode_);
  94. bind("rate_init_", &rate_init_);
  95. // bind("standard_", &standard_);
  96. bind("rate_init_option_", &rate_init_option_);
  97. bind_bool("slow_increase_", &slow_increase_); 
  98. bind_bool("voip_", &voip_);
  99. bind("voip_max_pkt_rate_", &voip_max_pkt_rate_);
  100. bind("fsize_", &fsize_);
  101. bind_bool("useHeaders_", &useHeaders_);
  102. bind_bool("idleFix_", &idleFix_);
  103. bind("headersize_", &headersize_);
  104. seqno_ = -1;
  105. maxseq_ = 0;
  106. datalimited_ = 0;
  107. lastlimited_ = 0.0;
  108. last_pkt_time_ = 0.0;
  109. bind("maxqueue_", &maxqueue_);
  110. maxqueue_ = MAXSEQ;
  111. }
  112. /*
  113.  * Must convert bytes into packets. 
  114.  * If nbytes == -1, this corresponds to infinite send.  We approximate
  115.  * infinite by a very large number (MAXSEQ).
  116.  * For simplicity, when bytes are converted to packets, fractional packets 
  117.  * are always rounded up.  
  118.  */
  119. void TfrcAgent::sendmsg(int nbytes, const char* /*flags*/)
  120. {
  121.         if (nbytes == -1 && maxseq_ < MAXSEQ)
  122. advanceby(MAXSEQ - maxseq_);
  123.         else if (size_ > 0) {
  124. int npkts = int(nbytes/size_);
  125. npkts += (nbytes%size_ ? 1 : 0);
  126. // maxqueue was added by Tom Phelan, to control the
  127. //   transmit queue from the application.
  128. if ((maxseq_ - seqno_) < maxqueue_) {
  129. advanceby(npkts);
  130. }
  131. }
  132. }
  133. void TfrcAgent::advanceby(int delta)
  134. {
  135.    maxseq_ += delta;
  136. if (seqno_ == -1) {
  137. // if no packets hve been sent so far, call start. 
  138.    start(); 
  139. } else if (datalimited_ && maxseq_ > seqno_) {
  140. // We were data-limited - send a packet now!
  141. // The old code always waited for a timer to expire!!
  142. datalimited_ = 0;
  143. lastlimited_ = Scheduler::instance().clock();
  144. all_idle_ = 0;
  145. if (!oldCode_) {
  146. sendpkt();
  147. }
  148. }
  149. int TfrcAgent::command(int argc, const char*const* argv)
  150. {
  151. if (argc==2) {
  152. // are we an infinite sender?
  153. if ( (strcmp(argv[1],"start")==0) && (SndrType_ == 0)) {
  154. start();
  155. return TCL_OK;
  156. }
  157. if (strcmp(argv[1],"stop")==0) {
  158. stop();
  159. return TCL_OK;
  160. }
  161. }
  162.    if ((argc == 3) && (SndrType_ == 1)) {
  163. // or do we need an FTP type app? 
  164.      if (strcmp(argv[1], "advance") == 0) {
  165.              int newseq = atoi(argv[2]);
  166. // THIS ISN"T USED.
  167. // newseq: new sequence
  168. // seqno_: next sequence to be sent
  169. // maxseq_: max seq_  produced by app so far.
  170.              if (newseq > maxseq_)
  171.                   advanceby(newseq - maxseq_);
  172.              return (TCL_OK);
  173.      }
  174.      if (strcmp(argv[1], "advanceby") == 0) {
  175.        advanceby(atoi(argv[2]));
  176.        return (TCL_OK);
  177.      }
  178. }
  179. return (Agent::command(argc, argv));
  180. }
  181. void TfrcAgent::start()
  182. {
  183. seqno_=0;
  184. rate_ = InitRate_;
  185. delta_ = 0;
  186. oldrate_ = rate_;  
  187. rate_change_ = SLOW_START;
  188. UrgentFlag = 1;
  189. rtt_=0;  
  190. sqrtrtt_=1;
  191. rttcur_=1;
  192. tzero_ = 0;
  193. last_change_=0;
  194. maxrate_ = 0; 
  195. ss_maxrate_ = 0;
  196. ndatapack_=0;
  197. ndatabytes_ = 0;
  198. true_loss_rate_ = 0;
  199. active_ = 1; 
  200. round_id = 0;
  201. heavyrounds_ = 0;
  202. t_srtt_ = int(srtt_init_/tcp_tick_) << T_SRTT_BITS;
  203. t_rttvar_ = int(rttvar_init_/tcp_tick_) << T_RTTVAR_BITS;
  204. t_rtxcur_ = rtxcur_init_;
  205. rcvrate = 0 ;
  206. all_idle_ = 0;
  207. first_pkt_rcvd = 0 ;
  208. // send the first packet
  209. sendpkt();
  210. // ... at initial rate
  211. send_timer_.resched(size_/rate_);
  212. // ... and start timer so we can cut rate 
  213. // in half if we do not get feedback
  214. NoFeedbacktimer_.resched(2*size_/rate_); 
  215. }
  216. void TfrcAgent::stop()
  217. {
  218. active_ = 0;
  219. if (idleFix_) 
  220.   datalimited_ = 1;
  221. send_timer_.force_cancel();
  222. }
  223. void TfrcAgent::nextpkt()
  224. {
  225. double next = -1;
  226. double xrate = -1; 
  227. if (SndrType_ == 0) {
  228. sendpkt();
  229. }
  230. else {
  231. if (maxseq_ > seqno_) {
  232. sendpkt();
  233. } else
  234. datalimited_ = 1;
  235. if (debug_) {
  236.   double now = Scheduler::instance().clock();
  237. printf("Time: %5.2f Datalimited now.n", now);
  238. }
  239. }
  240. // If slow_increase_ is set, then during slow start, we increase rate
  241. // slowly - by amount delta per packet 
  242. if (slow_increase_ && round_id > 2 && (rate_change_ == SLOW_START) 
  243.        && (oldrate_+SMALLFLOAT< rate_)) {
  244. oldrate_ = oldrate_ + delta_;
  245. xrate = oldrate_;
  246. } else {
  247. if (ca_) {
  248. if (debug_) printf("SQRT: now: %5.2f factor: %5.2fn", Scheduler::instance().clock(), sqrtrtt_/sqrt(rttcur_));
  249. xrate = rate_ * sqrtrtt_/sqrt(rttcur_);
  250. } else
  251. xrate = rate_;
  252. }
  253. if (xrate > SMALLFLOAT) {
  254. next = size_/xrate;
  255. if (voip_) {
  256.         double min_interval = 1.0/voip_max_pkt_rate_;
  257.      if (next < min_interval)
  258. next = min_interval;
  259. }
  260. //
  261. // randomize between next*(1 +/- woverhead_) 
  262. //
  263. next = next*(2*overhead_*Random::uniform()-overhead_+1);
  264. if (next > SMALLFLOAT)
  265. send_timer_.resched(next);
  266.                 else 
  267. send_timer_.resched(SMALLFLOAT);
  268. }
  269. }
  270. void TfrcAgent::update_rtt (double tao, double now) 
  271. {
  272. /* the TCP update */
  273. t_rtt_ = int((now-tao) /tcp_tick_ + 0.5);
  274. if (t_rtt_==0) t_rtt_=1;
  275. if (t_srtt_ != 0) {
  276. register short rtt_delta;
  277. rtt_delta = t_rtt_ - (t_srtt_ >> T_SRTT_BITS);    
  278. if ((t_srtt_ += rtt_delta) <= 0)    
  279. t_srtt_ = 1;
  280. if (rtt_delta < 0)
  281. rtt_delta = -rtt_delta;
  282.    rtt_delta -= (t_rttvar_ >> T_RTTVAR_BITS);
  283.    if ((t_rttvar_ += rtt_delta) <= 0)  
  284. t_rttvar_ = 1;
  285. } else {
  286. t_srtt_ = t_rtt_ << T_SRTT_BITS;
  287. t_rttvar_ = t_rtt_ << (T_RTTVAR_BITS-1);
  288. }
  289. t_rtxcur_ = (((t_rttvar_ << (rttvar_exp_ + (T_SRTT_BITS - T_RTTVAR_BITS))) + t_srtt_)  >> T_SRTT_BITS ) * tcp_tick_;
  290. tzero_=t_rtxcur_;
  291.   if (tzero_ < minrto_) 
  292.    tzero_ = minrto_;
  293. /* fine grained RTT estimate for use in the equation */
  294. if (rtt_ > 0) {
  295. rtt_ = df_*rtt_ + ((1-df_)*(now - tao));
  296. sqrtrtt_ = df_*sqrtrtt_ + ((1-df_)*sqrt(now - tao));
  297. } else {
  298. rtt_ = now - tao;
  299. sqrtrtt_ = sqrt(now - tao);
  300. }
  301. rttcur_ = now - tao;
  302. }
  303. /*
  304.  * Receive a status report from the receiver.
  305.  */
  306. void TfrcAgent::recv(Packet *pkt, Handler *)
  307. {
  308. double now = Scheduler::instance().clock();
  309. hdr_tfrc_ack *nck = hdr_tfrc_ack::access(pkt);
  310. //double ts = nck->timestamp_echo;
  311. double ts = nck->timestamp_echo + nck->timestamp_offset;
  312. double rate_since_last_report = nck->rate_since_last_report;
  313. // double NumFeedback_ = nck->NumFeedback_;
  314. double flost = nck->flost; 
  315. int losses = nck->losses;
  316. true_loss_rate_ = nck->true_loss;
  317. round_id ++ ;
  318. UrgentFlag = 0;
  319. if (round_id > 1 && rate_since_last_report > 0) {
  320. /* compute the max rate for slow-start as two times rcv rate */ 
  321. ss_maxrate_ = 2*rate_since_last_report*size_;
  322. if (conservative_) { 
  323. if (losses >= 1) {
  324. /* there was a loss in the most recent RTT */
  325. if (debug_) printf("time: %5.2f losses: %d rate %5.2fn", 
  326.   now, losses, rate_since_last_report);
  327. maxrate_ = rate_since_last_report*size_;
  328. } else { 
  329. /* there was no loss in the most recent RTT */
  330. maxrate_ = scmult_*rate_since_last_report*size_;
  331. }
  332. if (debug_) printf("time: %5.2f losses: %d rate %5.2f maxrate: %5.2fn", now, losses, rate_since_last_report, maxrate_);
  333. } else 
  334. maxrate_ = 2*rate_since_last_report*size_;
  335. } else {
  336. ss_maxrate_ = 0;
  337. maxrate_ = 0; 
  338. }
  339. /* update the round trip time */
  340. update_rtt (ts, now);
  341. /* .. and estimate of fair rate */
  342. if (voip_ != 1) {
  343. // From RFC 3714:
  344. // The voip flow gets to send at the same rate as
  345. //  a TCP flow with 1460-byte packets.
  346. fsize_ = size_;
  347. }
  348. rcvrate = p_to_b(flost, rtt_, tzero_, fsize_, bval_);
  349. // rcvrate is in bytes per second, based on fairness with a    
  350. // TCP connection with the same packet size size_.       
  351. if (voip_) {
  352. // Subtract the bandwidth used by headers.
  353. double temp = rcvrate*(size_/(1.0*headersize_+size_));
  354. rcvrate = temp;
  355. }
  356. /* if we get no more feedback for some time, cut rate in half */
  357. double t = 2*rtt_ ; 
  358. if (t < 2*size_/rate_) 
  359. t = 2*size_/rate_ ; 
  360. NoFeedbacktimer_.resched(t);
  361. /* if we are in slow start and we just saw a loss */
  362. /* then come out of slow start */
  363. if (first_pkt_rcvd == 0) {
  364. first_pkt_rcvd = 1 ; 
  365. slowstart();
  366. nextpkt();
  367. }
  368. else {
  369. if (rate_change_ == SLOW_START) {
  370. if (flost > 0) {
  371. rate_change_ = OUT_OF_SLOW_START;
  372. oldrate_ = rate_ = rcvrate;
  373. }
  374. else {
  375. slowstart();
  376. nextpkt();
  377. }
  378. }
  379. else {
  380. if (rcvrate>rate_) 
  381. increase_rate(flost);
  382. else 
  383. decrease_rate ();
  384. }
  385. }
  386. if (printStatus_) {
  387. printf("time: %5.2f rate: %5.2fn", now, rate_);
  388. double packetrate = rate_ * rtt_ / size_;
  389. printf("time: %5.2f packetrate: %5.2fn", now, packetrate);
  390. double maxrate = maxrate_ * rtt_ / size_;
  391. printf("time: %5.2f maxrate: %5.2fn", now, maxrate);
  392. }
  393. Packet::free(pkt);
  394. }
  395. /*
  396.  * Calculate initial sending rate from RFC 3390.
  397.  */
  398. double TfrcAgent::rfc3390(int size)
  399. {
  400.         if (size_ <= 1095) {
  401.                 return (4.0);
  402.         } else if (size_ < 2190) {
  403.                 return (3.0);
  404.         } else {
  405.                 return (2.0);
  406.         }
  407. }
  408. /*
  409.  * Used in setting the initial rate.
  410.  * This is from TcpAgent::initial_wnd().
  411.  */
  412. double TfrcAgent::initial_rate()
  413. {
  414.         if (rate_init_option_ == 1) {
  415. // init_option = 1: static initial rate of rate_init_
  416.                 return (rate_init_);
  417.         }
  418.         else if (rate_init_option_ == 2) {
  419.                 // do initial rate according to RFC 3390.
  420. return (rfc3390(size_));
  421.         }
  422.         // XXX what should we return here???
  423.         fprintf(stderr, "Wrong number of rate_init_option_ %dn",
  424.                 rate_init_option_);
  425.         abort();
  426.         return (2.0); // XXX make msvc happy.
  427. }
  428. // ss_maxrate_ = 2*rate_since_last_report*size_;
  429. // rate_: the rate set from the last pass through slowstart()
  430. void TfrcAgent::slowstart () 
  431. {
  432. double now = Scheduler::instance().clock(); 
  433. double initrate = initial_rate()*size_/rtt_;
  434. // If slow_increase_ is set to true, delta is used so that 
  435. //  the rate increases slowly to new value over an RTT. 
  436. if (debug_) printf("SlowStart: round_id: %d rate: %5.2f ss_maxrate_: %5.2fn", round_id, rate_, ss_maxrate_);
  437. if (round_id <=1 || (round_id == 2 && initial_rate() > 1)) {
  438. // We don't have a good rate report yet, so keep to  
  439. //   the initial rate.      
  440. oldrate_ = rate_;
  441. if (rate_ < initrate) rate_ = initrate;
  442. delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
  443. last_change_=now;
  444. } else if (ss_maxrate_ > 0) {
  445. if (idleFix_ && (datalimited_ || lastlimited_ > now - 1.5*rtt_)
  446.      && ss_maxrate_ < initrate) {
  447. // Datalimited recently, and maxrate is small.
  448. // Don't be limited by maxrate to less that initrate.
  449. oldrate_ = rate_;
  450. if (rate_ < initrate) rate_ = initrate;
  451. delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
  452. last_change_=now;
  453. } else if (rate_ < ss_maxrate_ && 
  454.                     now - last_change_ > rtt_) {
  455. // Not limited by maxrate, and time to increase.
  456. // Multiply the rate by ssmult_, if maxrate allows.
  457. oldrate_ = rate_;
  458. if (ssmult_*rate_ > ss_maxrate_) 
  459. rate_ = ss_maxrate_;
  460. else rate_ = ssmult_*rate_;
  461. if (rate_ < size_/rtt_) 
  462. rate_ = size_/rtt_; 
  463. delta_ = (rate_ - oldrate_)/(rate_*rtt_/size_);
  464. last_change_=now;
  465. } else if (rate_ > ss_maxrate_) {
  466. // Limited by maxrate.  
  467. rate_ = oldrate_ = ss_maxrate_/2.0;
  468. delta_ = 0;
  469. last_change_=now;
  470. } else {
  471. // If we get here, ss_maxrate <= 0, so the receive rate is 0.
  472. // We should go back to a very small sending rate!!!
  473. oldrate_ = rate_;
  474. rate_ = size_/rtt_; 
  475. delta_ = 0;
  476.          last_change_=now;
  477. }
  478. if (debug_) printf("SlowStart: now: %5.2f rate: %5.2f delta: %5.2fn", now, rate_, delta_);
  479. if (printStatus_) {
  480. double rate = rate_ * rtt_ / size_;
  481.    printf("SlowStart: now: %5.2f rate: %5.2f ss_maxrate: %5.2f delta: %5.2fn", now, rate, ss_maxrate_, delta_);
  482. }
  483. }
  484. void TfrcAgent::increase_rate (double p)
  485. {               
  486.         double now = Scheduler::instance().clock();
  487.         double maximumrate;
  488. double mult = (now-last_change_)/rtt_ ;
  489. if (mult > 2) mult = 2 ;
  490. rate_ = rate_ + (size_/rtt_)*mult ;
  491. if (datalimited_ || lastlimited_ > now - 1.5*rtt_) {
  492. // Modified by Sally on 3/10/2006
  493. // If the sender has been datalimited, rate should be
  494. //   at least the initial rate, when increasing rate.
  495. double init_rate = initial_rate()*size_/rtt_;
  496.     maximumrate = (maxrate_>init_rate)?maxrate_:init_rate ;
  497.         } else {
  498.     maximumrate = (maxrate_>size_/rtt_)?maxrate_:size_/rtt_ ;
  499. }
  500. maximumrate = (maximumrate>rcvrate)?rcvrate:maximumrate;
  501. rate_ = (rate_ > maximumrate)?maximumrate:rate_ ;
  502.         rate_change_ = CONG_AVOID;  
  503.         last_change_ = now;
  504. heavyrounds_ = 0;
  505. if (debug_) printf("Increase: now: %5.2f rate: %5.2f lastlimited: %5.2f rtt: %5.2fn", now, rate_, lastlimited_, rtt_);
  506. if (printStatus_) {
  507. double rate = rate_ * rtt_ / size_;
  508. printf("Increase: now: %5.2f rate: %5.2f lastlimited: %5.2f rtt: %5.2fn", now, rate, lastlimited_, rtt_);
  509. }
  510. }       
  511. void TfrcAgent::decrease_rate () 
  512. {
  513. double now = Scheduler::instance().clock(); 
  514. rate_ = rcvrate;
  515. double maximumrate = (maxrate_>size_/rtt_)?maxrate_:size_/rtt_ ;
  516. // Allow sending rate to be greater than maximumrate
  517. //   (which is by default twice the receiving rate)
  518. //   for at most maxHeavyRounds_ rounds.
  519. if (rate_ > maximumrate)
  520. heavyrounds_++;
  521. else
  522. heavyrounds_ = 0;
  523. if (heavyrounds_ > maxHeavyRounds_) {
  524. rate_ = (rate_ > maximumrate)?maximumrate:rate_ ;
  525. }
  526. rate_change_ = RATE_DECREASE;
  527. last_change_ = now;
  528. if (debug_) printf("Decrease: now: %5.2f rate: %5.2f rtt: %5.2fn", now, rate_, rtt_);
  529. if (printStatus_) {
  530. double rate = rate_ * rtt_ / size_;
  531. printf("Decrease: now: %5.2f rate: %5.2f rtt: %5.2fn", now, rate, rtt_);
  532. }
  533. }
  534. void TfrcAgent::sendpkt()
  535. {
  536. if (active_) {
  537. double now = Scheduler::instance().clock(); 
  538. Packet* p = allocpkt();
  539. hdr_tfrc *tfrch = hdr_tfrc::access(p);
  540. hdr_flags* hf = hdr_flags::access(p);
  541. if (ecn_) {
  542. hf->ect() = 1;  // ECN-capable transport
  543. }
  544. tfrch->seqno=seqno_++;
  545. tfrch->timestamp=Scheduler::instance().clock();
  546. tfrch->rtt=rtt_;
  547. tfrch->tzero=tzero_;
  548. tfrch->rate=rate_;
  549. tfrch->psize=size_;
  550. tfrch->fsize=fsize_;
  551. tfrch->UrgentFlag=UrgentFlag;
  552. tfrch->round_id=round_id;
  553. ndatapack_++;
  554. ndatabytes_ += size_;
  555. if (useHeaders_ == true) {
  556. hdr_cmn::access(p)->size() += headersize_;
  557. }
  558. last_pkt_time_ = now;
  559. send(p, 0);
  560. }
  561. }
  562. /*
  563.  * RFC 3448:
  564.  * "If the sender has been idle since this nofeedback timer was set and
  565.  * X_recv is less than four packets per round-trip time, then X_recv
  566.  * should not be halved in response to the timer expiration.  This
  567.  * ensures that the allowed sending rate is never reduced to less than
  568.  * two packets per round-trip time as a result of an idle period."
  569.  */
  570.  
  571. void TfrcAgent::reduce_rate_on_no_feedback()
  572. {
  573. double now = Scheduler::instance().clock();
  574. if (rate_change_ != SLOW_START)
  575. // "if" statement added by Sally on 9/25/06,
  576. // so that an idle report doesn't kick us out of
  577. // slow-start!
  578. rate_change_ = RATE_DECREASE; 
  579. if (oldCode_ || (!all_idle_ && !datalimited_)) {
  580. // if we are not datalimited
  581. rate_*=0.5;
  582. } else if ((datalimited_ || all_idle_) && rate_init_option_ == 1) { 
  583. // all_idle_: the sender has been datalimited since the 
  584. //    timer was set
  585. //  Don't reduce rate below rate_init_ * size_/rtt_.
  586.                 if (rate_ > 2.0 * rate_init_ * size_/rtt_ ) {
  587.                         rate_*=0.5;
  588.                 } 
  589. } else if ((datalimited_ || all_idle_) && rate_init_option_ == 2) {
  590.                 // Don't reduce rate below the RFC3390 rate.
  591.                 if (rate_ > 2.0 * rfc3390(size_) * size_/rtt_ ) {
  592.                         rate_*=0.5;
  593.                 } else if ( rate_ > rfc3390(size_) * size_/rtt_ ) {
  594.                         rate_ = rfc3390(size_) * size_/rtt_;
  595.                 }
  596.         }
  597. if (debug_) printf("NO FEEDBACK: time: %5.2f rate: %5.2f all_idle: %dn", now, rate_, all_idle_);
  598. UrgentFlag = 1;
  599. round_id ++ ;
  600. double t = 2*rtt_ ; 
  601. // Set the nofeedback timer.
  602. if (t < 2*size_/rate_) 
  603. t = 2*size_/rate_ ; 
  604. NoFeedbacktimer_.resched(t);
  605. if (datalimited_) {
  606. all_idle_ = 1;
  607. if (debug_) printf("Time: %5.2f Datalimited now.n", now);
  608. }
  609. nextpkt();
  610. }
  611. void TfrcSendTimer::expire(Event *) {
  612.    a_->nextpkt();
  613. }
  614. void TfrcNoFeedbackTimer::expire(Event *) {
  615. a_->reduce_rate_on_no_feedback ();
  616. // TODO: if the first (SYN) packet was dropped, then don't use
  617. //   the larger initial rates from RFC 3390:
  618.         // if (highest_ack_ == -1 && wnd_init_option_ == 2)
  619. //     wnd_init_option_ = 1;
  620. }