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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1991-1997 Regents of the University of California.
  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 the Computer Systems
  17.  * Engineering Group at Lawrence Berkeley Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34. #ifndef lint
  35. static const char rcsid[] =
  36.     "@(#) $Header: /cvsroot/nsnam/ns-2/tcp/tcp.cc,v 1.179 2007/12/04 19:59:35 seashadow Exp $ (LBL)";
  37. #endif
  38. #include <stdlib.h>
  39. #include <math.h>
  40. #include <sys/types.h>
  41. #include "ip.h"
  42. #include "tcp.h"
  43. #include "flags.h"
  44. #include "random.h"
  45. #include "basetrace.h"
  46. #include "hdr_qs.h"
  47. int hdr_tcp::offset_;
  48. static class TCPHeaderClass : public PacketHeaderClass {
  49. public:
  50.         TCPHeaderClass() : PacketHeaderClass("PacketHeader/TCP",
  51.      sizeof(hdr_tcp)) {
  52. bind_offset(&hdr_tcp::offset_);
  53. }
  54. } class_tcphdr;
  55. static class TcpClass : public TclClass {
  56. public:
  57. TcpClass() : TclClass("Agent/TCP") {}
  58. TclObject* create(int , const char*const*) {
  59. return (new TcpAgent());
  60. }
  61. } class_tcp;
  62. TcpAgent::TcpAgent() 
  63. : Agent(PT_TCP), 
  64.   t_seqno_(0), dupacks_(0), curseq_(0), highest_ack_(0), 
  65.           cwnd_(0), ssthresh_(0), maxseq_(0), count_(0), 
  66.           rtt_active_(0), rtt_seq_(-1), rtt_ts_(0.0), 
  67.           lastreset_(0.0), closed_(0), t_rtt_(0), t_srtt_(0), t_rttvar_(0), 
  68.   t_backoff_(0), ts_peer_(0), ts_echo_(0), tss(NULL), tss_size_(100), 
  69.   rtx_timer_(this), delsnd_timer_(this), burstsnd_timer_(this), 
  70.   first_decrease_(1), fcnt_(0), nrexmit_(0), restart_bugfix_(1), 
  71.           cong_action_(0), ecn_burst_(0), ecn_backoff_(0), ect_(0), 
  72.           use_rtt_(0), qs_requested_(0), qs_approved_(0),
  73.   qs_window_(0), qs_cwnd_(0), frto_(0)
  74. {
  75. #ifdef TCP_DELAY_BIND_ALL
  76.         // defined since Dec 1999.
  77. #else /* ! TCP_DELAY_BIND_ALL */
  78. bind("t_seqno_", &t_seqno_);
  79. bind("rtt_", &t_rtt_);
  80. bind("srtt_", &t_srtt_);
  81. bind("rttvar_", &t_rttvar_);
  82. bind("backoff_", &t_backoff_);
  83. bind("dupacks_", &dupacks_);
  84. bind("seqno_", &curseq_);
  85. bind("ack_", &highest_ack_);
  86. bind("cwnd_", &cwnd_);
  87. bind("ssthresh_", &ssthresh_);
  88. bind("maxseq_", &maxseq_);
  89.         bind("ndatapack_", &ndatapack_);
  90.         bind("ndatabytes_", &ndatabytes_);
  91.         bind("nackpack_", &nackpack_);
  92.         bind("nrexmit_", &nrexmit_);
  93.         bind("nrexmitpack_", &nrexmitpack_);
  94.         bind("nrexmitbytes_", &nrexmitbytes_);
  95.         bind("necnresponses_", &necnresponses_);
  96.         bind("ncwndcuts_", &ncwndcuts_);
  97. bind("ncwndcuts1_", &ncwndcuts1_);
  98. #endif /* TCP_DELAY_BIND_ALL */
  99. }
  100. void
  101. TcpAgent::delay_bind_init_all()
  102. {
  103.         // Defaults for bound variables should be set in ns-default.tcl.
  104.         delay_bind_init_one("window_");
  105.         delay_bind_init_one("windowInit_");
  106.         delay_bind_init_one("windowInitOption_");
  107.         delay_bind_init_one("syn_");
  108.         delay_bind_init_one("max_connects_");
  109.         delay_bind_init_one("windowOption_");
  110.         delay_bind_init_one("windowConstant_");
  111.         delay_bind_init_one("windowThresh_");
  112.         delay_bind_init_one("delay_growth_");
  113.         delay_bind_init_one("overhead_");
  114.         delay_bind_init_one("tcpTick_");
  115.         delay_bind_init_one("ecn_");
  116.         delay_bind_init_one("SetCWRonRetransmit_");
  117.         delay_bind_init_one("old_ecn_");
  118.         delay_bind_init_one("bugfix_ss_");
  119.         delay_bind_init_one("eln_");
  120.         delay_bind_init_one("eln_rxmit_thresh_");
  121.         delay_bind_init_one("packetSize_");
  122.         delay_bind_init_one("tcpip_base_hdr_size_");
  123. delay_bind_init_one("ts_option_size_");
  124.         delay_bind_init_one("bugFix_");
  125. delay_bind_init_one("bugFix_ack_");
  126. delay_bind_init_one("bugFix_ts_");
  127. delay_bind_init_one("lessCareful_");
  128.         delay_bind_init_one("slow_start_restart_");
  129.         delay_bind_init_one("restart_bugfix_");
  130.         delay_bind_init_one("timestamps_");
  131. delay_bind_init_one("ts_resetRTO_");
  132.         delay_bind_init_one("maxburst_");
  133. delay_bind_init_one("aggressive_maxburst_");
  134.         delay_bind_init_one("maxcwnd_");
  135. delay_bind_init_one("numdupacks_");
  136. delay_bind_init_one("numdupacksFrac_");
  137. delay_bind_init_one("exitFastRetrans_");
  138.         delay_bind_init_one("maxrto_");
  139. delay_bind_init_one("minrto_");
  140.         delay_bind_init_one("srtt_init_");
  141.         delay_bind_init_one("rttvar_init_");
  142.         delay_bind_init_one("rtxcur_init_");
  143.         delay_bind_init_one("T_SRTT_BITS");
  144.         delay_bind_init_one("T_RTTVAR_BITS");
  145.         delay_bind_init_one("rttvar_exp_");
  146.         delay_bind_init_one("awnd_");
  147.         delay_bind_init_one("decrease_num_");
  148.         delay_bind_init_one("increase_num_");
  149. delay_bind_init_one("k_parameter_");
  150. delay_bind_init_one("l_parameter_");
  151.         delay_bind_init_one("trace_all_oneline_");
  152.         delay_bind_init_one("nam_tracevar_");
  153.         delay_bind_init_one("QOption_");
  154.         delay_bind_init_one("EnblRTTCtr_");
  155.         delay_bind_init_one("control_increase_");
  156. delay_bind_init_one("noFastRetrans_");
  157. delay_bind_init_one("precisionReduce_");
  158. delay_bind_init_one("oldCode_");
  159. delay_bind_init_one("useHeaders_");
  160. delay_bind_init_one("low_window_");
  161. delay_bind_init_one("high_window_");
  162. delay_bind_init_one("high_p_");
  163. delay_bind_init_one("high_decrease_");
  164. delay_bind_init_one("max_ssthresh_");
  165. delay_bind_init_one("cwnd_range_");
  166. delay_bind_init_one("timerfix_");
  167. delay_bind_init_one("rfc2988_");
  168. delay_bind_init_one("singledup_");
  169. delay_bind_init_one("LimTransmitFix_");
  170. delay_bind_init_one("rate_request_");
  171. delay_bind_init_one("qs_enabled_");
  172. delay_bind_init_one("tcp_qs_recovery_");
  173. delay_bind_init_one("qs_request_mode_");
  174. delay_bind_init_one("qs_thresh_");
  175. delay_bind_init_one("qs_rtt_");
  176. delay_bind_init_one("print_request_");
  177. delay_bind_init_one("frto_enabled_");
  178. delay_bind_init_one("sfrto_enabled_");
  179. delay_bind_init_one("spurious_response_");
  180. #ifdef TCP_DELAY_BIND_ALL
  181. // out because delay-bound tracevars aren't yet supported
  182.         delay_bind_init_one("t_seqno_");
  183.         delay_bind_init_one("rtt_");
  184.         delay_bind_init_one("srtt_");
  185.         delay_bind_init_one("rttvar_");
  186.         delay_bind_init_one("backoff_");
  187.         delay_bind_init_one("dupacks_");
  188.         delay_bind_init_one("seqno_");
  189.         delay_bind_init_one("ack_");
  190.         delay_bind_init_one("cwnd_");
  191.         delay_bind_init_one("ssthresh_");
  192.         delay_bind_init_one("maxseq_");
  193.         delay_bind_init_one("ndatapack_");
  194.         delay_bind_init_one("ndatabytes_");
  195.         delay_bind_init_one("nackpack_");
  196.         delay_bind_init_one("nrexmit_");
  197.         delay_bind_init_one("nrexmitpack_");
  198.         delay_bind_init_one("nrexmitbytes_");
  199.         delay_bind_init_one("necnresponses_");
  200.         delay_bind_init_one("ncwndcuts_");
  201. delay_bind_init_one("ncwndcuts1_");
  202. #endif /* TCP_DELAY_BIND_ALL */
  203. Agent::delay_bind_init_all();
  204.         reset();
  205. }
  206. int
  207. TcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
  208. {
  209.         if (delay_bind(varName, localName, "window_", &wnd_, tracer)) return TCL_OK;
  210.         if (delay_bind(varName, localName, "windowInit_", &wnd_init_, tracer)) return TCL_OK;
  211.         if (delay_bind(varName, localName, "windowInitOption_", &wnd_init_option_, tracer)) return TCL_OK;
  212.         if (delay_bind_bool(varName, localName, "syn_", &syn_, tracer)) return TCL_OK;
  213.         if (delay_bind(varName, localName, "max_connects_", &max_connects_, tracer)) return TCL_OK;
  214.         if (delay_bind(varName, localName, "windowOption_", &wnd_option_ , tracer)) return TCL_OK;
  215.         if (delay_bind(varName, localName, "windowConstant_",  &wnd_const_, tracer)) return TCL_OK;
  216.         if (delay_bind(varName, localName, "windowThresh_", &wnd_th_ , tracer)) return TCL_OK;
  217.         if (delay_bind_bool(varName, localName, "delay_growth_", &delay_growth_ , tracer)) return TCL_OK;
  218.         if (delay_bind(varName, localName, "overhead_", &overhead_, tracer)) return TCL_OK;
  219.         if (delay_bind(varName, localName, "tcpTick_", &tcp_tick_, tracer)) return TCL_OK;
  220.         if (delay_bind_bool(varName, localName, "ecn_", &ecn_, tracer)) return TCL_OK;
  221.         if (delay_bind_bool(varName, localName, "SetCWRonRetransmit_", &SetCWRonRetransmit_, tracer)) return TCL_OK;
  222.         if (delay_bind_bool(varName, localName, "old_ecn_", &old_ecn_ , tracer)) return TCL_OK;
  223.         if (delay_bind_bool(varName, localName, "bugfix_ss_", &bugfix_ss_ , tracer)) return TCL_OK;
  224.         if (delay_bind(varName, localName, "eln_", &eln_ , tracer)) return TCL_OK;
  225.         if (delay_bind(varName, localName, "eln_rxmit_thresh_", &eln_rxmit_thresh_ , tracer)) return TCL_OK;
  226.         if (delay_bind(varName, localName, "packetSize_", &size_ , tracer)) return TCL_OK;
  227.         if (delay_bind(varName, localName, "tcpip_base_hdr_size_", &tcpip_base_hdr_size_, tracer)) return TCL_OK;
  228. if (delay_bind(varName, localName, "ts_option_size_", &ts_option_size_, tracer)) return TCL_OK;
  229.         if (delay_bind_bool(varName, localName, "bugFix_", &bug_fix_ , tracer)) return TCL_OK;
  230. if (delay_bind_bool(varName, localName, "bugFix_ack_", &bugfix_ack_, tracer)) return TCL_OK;
  231. if (delay_bind_bool(varName, localName, "bugFix_ts_", &bugfix_ts_ , tracer)) return TCL_OK;
  232.         if (delay_bind_bool(varName, localName, "lessCareful_", &less_careful_ , tracer)) return TCL_OK;
  233.         if (delay_bind_bool(varName, localName, "timestamps_", &ts_option_ , tracer)) return TCL_OK;
  234.         if (delay_bind_bool(varName, localName, "ts_resetRTO_", &ts_resetRTO_, tracer)) return TCL_OK;
  235.         if (delay_bind_bool(varName, localName, "slow_start_restart_", &slow_start_restart_ , tracer)) return TCL_OK;
  236.         if (delay_bind_bool(varName, localName, "restart_bugfix_", &restart_bugfix_ , tracer)) return TCL_OK;
  237.         if (delay_bind(varName, localName, "maxburst_", &maxburst_ , tracer)) return TCL_OK;
  238.         if (delay_bind_bool(varName, localName, "aggressive_maxburst_", &aggressive_maxburst_ , tracer)) return TCL_OK;
  239.         if (delay_bind(varName, localName, "maxcwnd_", &maxcwnd_ , tracer)) return TCL_OK;
  240. if (delay_bind(varName, localName, "numdupacks_", &numdupacks_, tracer)) return TCL_OK;
  241. if (delay_bind(varName, localName, "numdupacksFrac_", &numdupacksFrac_, tracer)) return TCL_OK;
  242. if (delay_bind_bool(varName, localName, "exitFastRetrans_", &exitFastRetrans_, tracer)) return TCL_OK;
  243.         if (delay_bind(varName, localName, "maxrto_", &maxrto_ , tracer)) return TCL_OK;
  244. if (delay_bind(varName, localName, "minrto_", &minrto_ , tracer)) return TCL_OK;
  245.         if (delay_bind(varName, localName, "srtt_init_", &srtt_init_ , tracer)) return TCL_OK;
  246.         if (delay_bind(varName, localName, "rttvar_init_", &rttvar_init_ , tracer)) return TCL_OK;
  247.         if (delay_bind(varName, localName, "rtxcur_init_", &rtxcur_init_ , tracer)) return TCL_OK;
  248.         if (delay_bind(varName, localName, "T_SRTT_BITS", &T_SRTT_BITS , tracer)) return TCL_OK;
  249.         if (delay_bind(varName, localName, "T_RTTVAR_BITS", &T_RTTVAR_BITS , tracer)) return TCL_OK;
  250.         if (delay_bind(varName, localName, "rttvar_exp_", &rttvar_exp_ , tracer)) return TCL_OK;
  251.         if (delay_bind(varName, localName, "awnd_", &awnd_ , tracer)) return TCL_OK;
  252.         if (delay_bind(varName, localName, "decrease_num_", &decrease_num_, tracer)) return TCL_OK;
  253.         if (delay_bind(varName, localName, "increase_num_", &increase_num_, tracer)) return TCL_OK;
  254. if (delay_bind(varName, localName, "k_parameter_", &k_parameter_, tracer)) return TCL_OK;
  255.         if (delay_bind(varName, localName, "l_parameter_", &l_parameter_, tracer)) return TCL_OK;
  256.         if (delay_bind_bool(varName, localName, "trace_all_oneline_", &trace_all_oneline_ , tracer)) return TCL_OK;
  257.         if (delay_bind_bool(varName, localName, "nam_tracevar_", &nam_tracevar_ , tracer)) return TCL_OK;
  258.         if (delay_bind(varName, localName, "QOption_", &QOption_ , tracer)) return TCL_OK;
  259.         if (delay_bind(varName, localName, "EnblRTTCtr_", &EnblRTTCtr_ , tracer)) return TCL_OK;
  260.         if (delay_bind(varName, localName, "control_increase_", &control_increase_ , tracer)) return TCL_OK;
  261.         if (delay_bind_bool(varName, localName, "noFastRetrans_", &noFastRetrans_, tracer)) return TCL_OK;
  262.         if (delay_bind_bool(varName, localName, "precisionReduce_", &precision_reduce_, tracer)) return TCL_OK;
  263. if (delay_bind_bool(varName, localName, "oldCode_", &oldCode_, tracer)) return TCL_OK;
  264. if (delay_bind_bool(varName, localName, "useHeaders_", &useHeaders_, tracer)) return TCL_OK;
  265. if (delay_bind(varName, localName, "low_window_", &low_window_, tracer)) return TCL_OK;
  266. if (delay_bind(varName, localName, "high_window_", &high_window_, tracer)) return TCL_OK;
  267. if (delay_bind(varName, localName, "high_p_", &high_p_, tracer)) return TCL_OK;
  268. if (delay_bind(varName, localName, "high_decrease_", &high_decrease_, tracer)) return TCL_OK;
  269. if (delay_bind(varName, localName, "max_ssthresh_", &max_ssthresh_, tracer)) return TCL_OK;
  270. if (delay_bind(varName, localName, "cwnd_range_", &cwnd_range_, tracer)) return TCL_OK;
  271. if (delay_bind_bool(varName, localName, "timerfix_", &timerfix_, tracer)) return TCL_OK;
  272. if (delay_bind_bool(varName, localName, "rfc2988_", &rfc2988_, tracer)) return TCL_OK;
  273.         if (delay_bind(varName, localName, "singledup_", &singledup_ , tracer)) return TCL_OK;
  274.         if (delay_bind_bool(varName, localName, "LimTransmitFix_", &LimTransmitFix_ , tracer)) return TCL_OK;
  275.         if (delay_bind(varName, localName, "rate_request_", &rate_request_ , tracer)) return TCL_OK;
  276.         if (delay_bind_bool(varName, localName, "qs_enabled_", &qs_enabled_ , tracer)) return TCL_OK;
  277. if (delay_bind_bool(varName, localName, "tcp_qs_recovery_", &tcp_qs_recovery_, tracer)) return TCL_OK;
  278. if (delay_bind(varName, localName, "qs_request_mode_", &qs_request_mode_, tracer)) return TCL_OK;
  279. if (delay_bind(varName, localName, "qs_thresh_", &qs_thresh_, tracer)) return TCL_OK;
  280. if (delay_bind(varName, localName, "qs_rtt_", &qs_rtt_, tracer)) return TCL_OK;
  281. if (delay_bind_bool(varName, localName, "print_request_", &print_request_, tracer)) return TCL_OK;
  282. if (delay_bind_bool(varName, localName, "frto_enabled_", &frto_enabled_, tracer)) return TCL_OK;
  283. if (delay_bind_bool(varName, localName, "sfrto_enabled_", &sfrto_enabled_, tracer)) return TCL_OK;
  284. if (delay_bind_bool(varName, localName, "spurious_response_", &spurious_response_, tracer)) return TCL_OK;
  285. #ifdef TCP_DELAY_BIND_ALL
  286. // not if (delay-bound delay-bound tracevars aren't yet supported
  287.         if (delay_bind(varName, localName, "t_seqno_", &t_seqno_ , tracer)) return TCL_OK;
  288.         if (delay_bind(varName, localName, "rtt_", &t_rtt_ , tracer)) return TCL_OK;
  289.         if (delay_bind(varName, localName, "srtt_", &t_srtt_ , tracer)) return TCL_OK;
  290.         if (delay_bind(varName, localName, "rttvar_", &t_rttvar_ , tracer)) return TCL_OK;
  291.         if (delay_bind(varName, localName, "backoff_", &t_backoff_ , tracer)) return TCL_OK;
  292.         if (delay_bind(varName, localName, "dupacks_", &dupacks_ , tracer)) return TCL_OK;
  293.         if (delay_bind(varName, localName, "seqno_", &curseq_ , tracer)) return TCL_OK;
  294.         if (delay_bind(varName, localName, "ack_", &highest_ack_ , tracer)) return TCL_OK;
  295.         if (delay_bind(varName, localName, "cwnd_", &cwnd_ , tracer)) return TCL_OK;
  296.         if (delay_bind(varName, localName, "ssthresh_", &ssthresh_ , tracer)) return TCL_OK;
  297.         if (delay_bind(varName, localName, "maxseq_", &maxseq_ , tracer)) return TCL_OK;
  298.         if (delay_bind(varName, localName, "ndatapack_", &ndatapack_ , tracer)) return TCL_OK;
  299.         if (delay_bind(varName, localName, "ndatabytes_", &ndatabytes_ , tracer)) return TCL_OK;
  300.         if (delay_bind(varName, localName, "nackpack_", &nackpack_ , tracer)) return TCL_OK;
  301.         if (delay_bind(varName, localName, "nrexmit_", &nrexmit_ , tracer)) return TCL_OK;
  302.         if (delay_bind(varName, localName, "nrexmitpack_", &nrexmitpack_ , tracer)) return TCL_OK;
  303.         if (delay_bind(varName, localName, "nrexmitbytes_", &nrexmitbytes_ , tracer)) return TCL_OK;
  304.         if (delay_bind(varName, localName, "necnresponses_", &necnresponses_ , tracer)) return TCL_OK;
  305.         if (delay_bind(varName, localName, "ncwndcuts_", &ncwndcuts_ , tracer)) return TCL_OK;
  306.   if (delay_bind(varName, localName, "ncwndcuts1_", &ncwndcuts1_ , tracer)) return TCL_OK;
  307. #endif
  308.         return Agent::delay_bind_dispatch(varName, localName, tracer);
  309. }
  310. #define TCP_WRK_SIZE 512
  311. /* Print out all the traced variables whenever any one is changed */
  312. void
  313. TcpAgent::traceAll() {
  314. if (!channel_)
  315. return;
  316. double curtime;
  317. Scheduler& s = Scheduler::instance();
  318. char wrk[TCP_WRK_SIZE];
  319. curtime = &s ? s.clock() : 0;
  320. snprintf(wrk, TCP_WRK_SIZE,
  321.  "time: %-8.5f saddr: %-2d sport: %-2d daddr: %-2d dport:"
  322.  " %-2d maxseq: %-4d hiack: %-4d seqno: %-4d cwnd: %-6.3f"
  323.  " ssthresh: %-3d dupacks: %-2d rtt: %-6.3f srtt: %-6.3f"
  324.  " rttvar: %-6.3f bkoff: %-dn", curtime, addr(), port(),
  325.  daddr(), dport(), int(maxseq_), int(highest_ack_),
  326.  int(t_seqno_), double(cwnd_), int(ssthresh_),
  327.  int(dupacks_), int(t_rtt_)*tcp_tick_, 
  328.  (int(t_srtt_) >> T_SRTT_BITS)*tcp_tick_, 
  329.  int(t_rttvar_)*tcp_tick_/4.0, int(t_backoff_)); 
  330. (void)Tcl_Write(channel_, wrk, -1);
  331. }
  332. /* Print out just the variable that is modified */
  333. void
  334. TcpAgent::traceVar(TracedVar* v) 
  335. {
  336. if (!channel_)
  337. return;
  338. double curtime;
  339. Scheduler& s = Scheduler::instance();
  340. char wrk[TCP_WRK_SIZE];
  341. curtime = &s ? s.clock() : 0;
  342. // XXX comparing addresses is faster than comparing names
  343. if (v == &cwnd_)
  344. snprintf(wrk, TCP_WRK_SIZE,
  345.  "%-8.5f %-2d %-2d %-2d %-2d %s %-6.3fn",
  346.  curtime, addr(), port(), daddr(), dport(),
  347.  v->name(), double(*((TracedDouble*) v))); 
  348.   else if (v == &t_rtt_)
  349. snprintf(wrk, TCP_WRK_SIZE,
  350.  "%-8.5f %-2d %-2d %-2d %-2d %s %-6.3fn",
  351.  curtime, addr(), port(), daddr(), dport(),
  352.  v->name(), int(*((TracedInt*) v))*tcp_tick_); 
  353. else if (v == &t_srtt_)
  354. snprintf(wrk, TCP_WRK_SIZE,
  355.  "%-8.5f %-2d %-2d %-2d %-2d %s %-6.3fn",
  356.  curtime, addr(), port(), daddr(), dport(),
  357.  v->name(), 
  358.  (int(*((TracedInt*) v)) >> T_SRTT_BITS)*tcp_tick_); 
  359. else if (v == &t_rttvar_)
  360. snprintf(wrk, TCP_WRK_SIZE,
  361.  "%-8.5f %-2d %-2d %-2d %-2d %s %-6.3fn",
  362.  curtime, addr(), port(), daddr(), dport(),
  363.  v->name(), 
  364.  int(*((TracedInt*) v))*tcp_tick_/4.0); 
  365. else
  366. snprintf(wrk, TCP_WRK_SIZE,
  367.  "%-8.5f %-2d %-2d %-2d %-2d %s %dn",
  368.  curtime, addr(), port(), daddr(), dport(),
  369.  v->name(), int(*((TracedInt*) v))); 
  370. (void)Tcl_Write(channel_, wrk, -1);
  371. }
  372. void
  373. TcpAgent::trace(TracedVar* v) 
  374. {
  375. if (nam_tracevar_) {
  376. Agent::trace(v);
  377. } else if (trace_all_oneline_)
  378. traceAll();
  379. else 
  380. traceVar(v);
  381. }
  382. //
  383. // in 1-way TCP, syn_ indicates we are modeling
  384. // a SYN exchange at the beginning.  If this is true
  385. // and we are delaying growth, then use an initial
  386. // window of one.  If not, we do whatever initial_window()
  387. // says to do.
  388. //
  389. void
  390. TcpAgent::set_initial_window()
  391. {
  392. if (syn_ && delay_growth_) {
  393. cwnd_ = 1.0; 
  394. syn_connects_ = 0;
  395. } else
  396. cwnd_ = initial_window();
  397. }
  398. void
  399. TcpAgent::reset_qoption()
  400. {
  401. int now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
  402. T_start = now ; 
  403. RTT_count = 0 ; 
  404. RTT_prev = 0 ; 
  405. RTT_goodcount = 1 ; 
  406. F_counting = 0 ; 
  407. W_timed = -1 ; 
  408. F_full = 0 ;
  409. Backoffs = 0 ; 
  410. }
  411. void
  412. TcpAgent::reset()
  413. {
  414. rtt_init();
  415. rtt_seq_ = -1;
  416. /*XXX lookup variables */
  417. dupacks_ = 0;
  418. curseq_ = 0;
  419. set_initial_window();
  420. t_seqno_ = 0;
  421. maxseq_ = -1;
  422. last_ack_ = -1;
  423. highest_ack_ = -1;
  424. //highest_ack_ = 1;
  425. ssthresh_ = int(wnd_);
  426. if (max_ssthresh_ > 0 && max_ssthresh_ < ssthresh_) 
  427. ssthresh_ = max_ssthresh_;
  428. wnd_restart_ = 1.;
  429. awnd_ = wnd_init_ / 2.0;
  430. recover_ = 0;
  431. closed_ = 0;
  432. last_cwnd_action_ = 0;
  433. boot_time_ = Random::uniform(tcp_tick_);
  434. first_decrease_ = 1;
  435. /* W.N.: for removing packets from previous incarnations */
  436. lastreset_ = Scheduler::instance().clock();
  437. /* Now these variables will be reset 
  438.    - Debojyoti Dutta 12th Oct'2000 */
  439.  
  440. ndatapack_ = 0;
  441. ndatabytes_ = 0;
  442. nackpack_ = 0;
  443. nrexmitbytes_ = 0;
  444. nrexmit_ = 0;
  445. nrexmitpack_ = 0;
  446. necnresponses_ = 0;
  447. ncwndcuts_ = 0;
  448. ncwndcuts1_ = 0;
  449. if (control_increase_) {
  450. prev_highest_ack_ = highest_ack_ ; 
  451. }
  452. if (wnd_option_ == 8) {
  453. // HighSpeed TCP
  454. hstcp_.low_p = 1.5/(low_window_*low_window_);
  455. double highLowWin = log(high_window_)-log(low_window_);
  456. double highLowP = log(high_p_) - log(hstcp_.low_p);
  457. hstcp_.dec1 = 
  458.    0.5 - log(low_window_) * (high_decrease_ - 0.5)/highLowWin;
  459. hstcp_.dec2 = (high_decrease_ - 0.5)/highLowWin;
  460.          hstcp_.p1 = 
  461.   log(hstcp_.low_p) - log(low_window_) * highLowP/highLowWin;
  462. hstcp_.p2 = highLowP/highLowWin;
  463. }
  464. if (QOption_) {
  465. int now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
  466. T_last = now ; 
  467. T_prev = now ; 
  468. W_used = 0 ;
  469. if (EnblRTTCtr_) {
  470. reset_qoption();
  471. }
  472. }
  473. }
  474. /*
  475.  * Initialize variables for the retransmit timer.
  476.  */
  477. void TcpAgent::rtt_init()
  478. {
  479. t_rtt_ = 0;
  480. t_srtt_ = int(srtt_init_ / tcp_tick_) << T_SRTT_BITS;
  481. t_rttvar_ = int(rttvar_init_ / tcp_tick_) << T_RTTVAR_BITS;
  482. t_rtxcur_ = rtxcur_init_;
  483. t_backoff_ = 1;
  484. }
  485. double TcpAgent::rtt_timeout()
  486. {
  487. double timeout;
  488. if (rfc2988_) {
  489. // Correction from Tom Kelly to be RFC2988-compliant, by
  490. // clamping minrto_ before applying t_backoff_.
  491. if (t_rtxcur_ < minrto_ && !use_rtt_)
  492. timeout = minrto_ * t_backoff_;
  493. else
  494. timeout = t_rtxcur_ * t_backoff_;
  495. } else {
  496. // only of interest for backwards compatibility
  497. timeout = t_rtxcur_ * t_backoff_;
  498. if (timeout < minrto_)
  499. timeout = minrto_;
  500. }
  501. if (timeout > maxrto_)
  502. timeout = maxrto_;
  503.         if (timeout < 2.0 * tcp_tick_) {
  504. if (timeout < 0) {
  505. fprintf(stderr, "TcpAgent: negative RTO!  (%f)n",
  506. timeout);
  507. exit(1);
  508. } else if (use_rtt_ && timeout < tcp_tick_)
  509. timeout = tcp_tick_;
  510. else
  511. timeout = 2.0 * tcp_tick_;
  512. }
  513. use_rtt_ = 0;
  514. return (timeout);
  515. }
  516. /* This has been modified to use the tahoe code. */
  517. void TcpAgent::rtt_update(double tao)
  518. {
  519. double now = Scheduler::instance().clock();
  520. if (ts_option_)
  521. t_rtt_ = int(tao /tcp_tick_ + 0.5);
  522. else {
  523. double sendtime = now - tao;
  524. sendtime += boot_time_;
  525. double tickoff = fmod(sendtime, tcp_tick_);
  526. t_rtt_ = int((tao + tickoff) / tcp_tick_);
  527. }
  528. if (t_rtt_ < 1)
  529. t_rtt_ = 1;
  530. //
  531. // t_srtt_ has 3 bits to the right of the binary point
  532. // t_rttvar_ has 2
  533.         // Thus "t_srtt_ >> T_SRTT_BITS" is the actual srtt, 
  534.    //   and "t_srtt_" is 8*srtt.
  535. // Similarly, "t_rttvar_ >> T_RTTVAR_BITS" is the actual rttvar,
  536. //   and "t_rttvar_" is 4*rttvar.
  537. //
  538.         if (t_srtt_ != 0) {
  539. register short delta;
  540. delta = t_rtt_ - (t_srtt_ >> T_SRTT_BITS); // d = (m - a0)
  541. if ((t_srtt_ += delta) <= 0) // a1 = 7/8 a0 + 1/8 m
  542. t_srtt_ = 1;
  543. if (delta < 0)
  544. delta = -delta;
  545. delta -= (t_rttvar_ >> T_RTTVAR_BITS);
  546. if ((t_rttvar_ += delta) <= 0) // var1 = 3/4 var0 + 1/4 |d|
  547. t_rttvar_ = 1;
  548. } else {
  549. t_srtt_ = t_rtt_ << T_SRTT_BITS; // srtt = rtt
  550. t_rttvar_ = t_rtt_ << (T_RTTVAR_BITS-1); // rttvar = rtt / 2
  551. }
  552. //
  553. // Current retransmit value is 
  554. //    (unscaled) smoothed round trip estimate
  555. //    plus 2^rttvar_exp_ times (unscaled) rttvar. 
  556. //
  557. t_rtxcur_ = (((t_rttvar_ << (rttvar_exp_ + (T_SRTT_BITS - T_RTTVAR_BITS))) +
  558. t_srtt_)  >> T_SRTT_BITS ) * tcp_tick_;
  559. return;
  560. }
  561. void TcpAgent::rtt_backoff()
  562. {
  563. if (t_backoff_ < 64 || rfc2988_)
  564.          t_backoff_ <<= 1;
  565.         // RFC2988 allows a maximum for the backed-off RTO of 60 seconds.
  566.         // This is applied by maxrto_.
  567. if (t_backoff_ > 8) {
  568. /*
  569.  * If backed off this far, clobber the srtt
  570.  * value, storing it in the mean deviation
  571.  * instead.
  572.  */
  573. t_rttvar_ += (t_srtt_ >> T_SRTT_BITS);
  574. t_srtt_ = 0;
  575. }
  576. }
  577. /*
  578.  * headersize:
  579.  *      how big is an IP+TCP header in bytes; include options such as ts
  580.  * this function should be virtual so others (e.g. SACK) can override
  581.  */
  582. int TcpAgent::headersize()
  583. {
  584.         int total = tcpip_base_hdr_size_;
  585. if (total < 1) {
  586. fprintf(stderr,
  587.   "TcpAgent(%s): warning: tcpip hdr size is only %d bytesn",
  588.   name(), tcpip_base_hdr_size_);
  589. }
  590. if (ts_option_)
  591. total += ts_option_size_;
  592.         return (total);
  593. }
  594. void TcpAgent::output(int seqno, int reason)
  595. {
  596. int force_set_rtx_timer = 0;
  597. Packet* p = allocpkt();
  598. hdr_tcp *tcph = hdr_tcp::access(p);
  599. hdr_flags* hf = hdr_flags::access(p);
  600. hdr_ip *iph = hdr_ip::access(p);
  601. int databytes = hdr_cmn::access(p)->size();
  602. tcph->seqno() = seqno;
  603. tcph->ts() = Scheduler::instance().clock();
  604. int is_retransmit = (seqno < maxseq_);
  605.  
  606. // Mark packet for diagnosis purposes if we are in Quick-Start Phase
  607. if (qs_approved_) {
  608. hf->qs() = 1;
  609. }
  610.  
  611.         // store timestamps, with bugfix_ts_.  From Andrei Gurtov. 
  612. // (A real TCP would use scoreboard for this.)
  613.         if (bugfix_ts_ && tss==NULL) {
  614.                 tss = (double*) calloc(tss_size_, sizeof(double));
  615.                 if (tss==NULL) exit(1);
  616.         }
  617.         //dynamically grow the timestamp array if it's getting full
  618.         if (bugfix_ts_ && ((seqno - highest_ack_) > tss_size_* 0.9)) {
  619.                 double *ntss;
  620.                 ntss = (double*) calloc(tss_size_*2, sizeof(double));
  621.                 printf("%p resizing timestamp tablen", this);
  622.                 if (ntss == NULL) exit(1);
  623.                 for (int i=0; i<tss_size_; i++)
  624.                         ntss[(highest_ack_ + i) % (tss_size_ * 2)] =
  625.                                 tss[(highest_ack_ + i) % tss_size_];
  626.                 free(tss);
  627.                 tss_size_ *= 2;
  628.                 tss = ntss;
  629.         }
  630.  
  631.         if (tss!=NULL)
  632.                 tss[seqno % tss_size_] = tcph->ts(); 
  633. tcph->ts_echo() = ts_peer_;
  634. tcph->reason() = reason;
  635. tcph->last_rtt() = int(int(t_rtt_)*tcp_tick_*1000);
  636. if (ecn_) {
  637. hf->ect() = 1; // ECN-capable transport
  638. }
  639. if (cong_action_ && (!is_retransmit || SetCWRonRetransmit_)) {
  640. hf->cong_action() = TRUE;  // Congestion action.
  641. cong_action_ = FALSE;
  642.         }
  643. /* Check if this is the initial SYN packet. */
  644. if (seqno == 0) {
  645. if (syn_) {
  646. databytes = 0;
  647. curseq_ += 1;
  648. hdr_cmn::access(p)->size() = tcpip_base_hdr_size_;
  649. ++syn_connects_;
  650. //fprintf(stderr, "TCPAgent: syn_connects_ %d max_connects_ %dn",
  651. // syn_connects_, max_connects_);
  652. if (max_connects_ > 0 &&
  653.                                syn_connects_ > max_connects_) {
  654.       // Abort the connection.
  655.       // What is the best way to abort the connection?
  656.       curseq_ = 0;
  657.                       rtx_timer_.resched(10000);
  658.                               return;
  659.                         }
  660. }
  661. if (ecn_) {
  662. hf->ecnecho() = 1;
  663. // hf->cong_action() = 1;
  664. hf->ect() = 0;
  665. }
  666. if (qs_enabled_) {
  667. hdr_qs *qsh = hdr_qs::access(p);
  668. // dataout is kilobytes queued for sending
  669. int dataout = (curseq_ - maxseq_ - 1) * (size_ + headersize()) / 1024;
  670. int qs_rr = rate_request_;
  671. if (qs_request_mode_ == 1 && qs_rtt_ > 0) {
  672. // PS: Avoid making unnecessary QS requests
  673. // use a rough estimation of RTT in qs_rtt_
  674. // to calculate the desired rate from dataout.
  675. // printf("dataout %d qs_rr %d qs_rtt_ %dn",
  676. // dataout, qs_rr, qs_rtt_);
  677. if (dataout * 1000 / qs_rtt_ < qs_rr) {
  678. qs_rr = dataout * 1000 / qs_rtt_;
  679. }
  680. // printf("request %dn", qs_rr);
  681. // qs_thresh_ is minimum number of unsent
  682. // segments needed to activate QS request
  683. // printf("curseq_ %d maxseq_ %d qs_thresh_ %dn",
  684. //  int(curseq_), int(maxseq_), qs_thresh_);
  685. if ((curseq_ - maxseq_ - 1) < qs_thresh_) {
  686. qs_rr = 0;
  687. }
  688.      if (qs_rr > 0) {
  689. if (print_request_) 
  690. printf("QS request (before encoding): %d KBpsn", qs_rr);
  691. // QuickStart code from Srikanth Sundarrajan.
  692. qsh->flag() = QS_REQUEST;
  693. qsh->ttl() = Random::integer(256);
  694. ttl_diff_ = (iph->ttl() - qsh->ttl()) % 256;
  695. qsh->rate() = hdr_qs::Bps_to_rate(qs_rr * 1024);
  696. qs_requested_ = 1;
  697.      } else {
  698. qsh->flag() = QS_DISABLE;
  699. }
  700. }
  701. }
  702. else if (useHeaders_ == true) {
  703. hdr_cmn::access(p)->size() += headersize();
  704. }
  705.         hdr_cmn::access(p)->size();
  706. /* if no outstanding data, be sure to set rtx timer again */
  707. if (highest_ack_ == maxseq_)
  708. force_set_rtx_timer = 1;
  709. /* call helper function to fill in additional fields */
  710. output_helper(p);
  711.         ++ndatapack_;
  712.         ndatabytes_ += databytes;
  713. send(p, 0);
  714. if (seqno == curseq_ && seqno > maxseq_)
  715. idle();  // Tell application I have sent everything so far
  716. if (seqno > maxseq_) {
  717. maxseq_ = seqno;
  718. if (!rtt_active_) {
  719. rtt_active_ = 1;
  720. if (seqno > rtt_seq_) {
  721. rtt_seq_ = seqno;
  722. rtt_ts_ = Scheduler::instance().clock();
  723. }
  724. }
  725. } else {
  726.          ++nrexmitpack_;
  727. nrexmitbytes_ += databytes;
  728. }
  729. if (!(rtx_timer_.status() == TIMER_PENDING) || force_set_rtx_timer)
  730. /* No timer pending.  Schedule one. */
  731. set_rtx_timer();
  732. }
  733. /*
  734.  * Must convert bytes into packets for one-way TCPs.
  735.  * If nbytes == -1, this corresponds to infinite send.  We approximate
  736.  * infinite by a very large number (TCP_MAXSEQ).
  737.  */
  738. void TcpAgent::sendmsg(int nbytes, const char* /*flags*/)
  739. {
  740. if (nbytes == -1 && curseq_ <= TCP_MAXSEQ)
  741. curseq_ = TCP_MAXSEQ; 
  742. else
  743. curseq_ += (nbytes/size_ + (nbytes%size_ ? 1 : 0));
  744. send_much(0, 0, maxburst_);
  745. }
  746. void TcpAgent::advanceby(int delta)
  747. {
  748.   curseq_ += delta;
  749. if (delta > 0)
  750. closed_ = 0;
  751. send_much(0, 0, maxburst_); 
  752. }
  753. int TcpAgent::command(int argc, const char*const* argv)
  754. {
  755. if (argc == 3) {
  756. if (strcmp(argv[1], "advance") == 0) {
  757. int newseq = atoi(argv[2]);
  758. if (newseq > maxseq_)
  759. advanceby(newseq - curseq_);
  760. else
  761. advanceby(maxseq_ - curseq_);
  762. return (TCL_OK);
  763. }
  764. if (strcmp(argv[1], "advanceby") == 0) {
  765. advanceby(atoi(argv[2]));
  766. return (TCL_OK);
  767. }
  768. if (strcmp(argv[1], "eventtrace") == 0) {
  769. et_ = (EventTrace *)TclObject::lookup(argv[2]);
  770. return (TCL_OK);
  771. }
  772. /*
  773.  * Curtis Villamizar's trick to transfer tcp connection
  774.  * parameters to emulate http persistent connections.
  775.  *
  776.  * Another way to do the same thing is to open one tcp
  777.  * object and use start/stop/maxpkts_ or advanceby to control
  778.  * how much data is sent in each burst.
  779.  * With a single connection, slow_start_restart_
  780.  * should be configured as desired.
  781.  *
  782.  * This implementation (persist) may not correctly
  783.  * emulate pure-BSD-based systems which close cwnd
  784.  * after the connection goes idle (slow-start
  785.  * restart).  See appendix C in
  786.  * Jacobson and Karels ``Congestion
  787.  * Avoidance and Control'' at
  788.  * <ftp://ftp.ee.lbl.gov/papers/congavoid.ps.Z>
  789.  * (*not* the original
  790.  * '88 paper) for why BSD does this.  See
  791.  * ``Performance Interactions Between P-HTTP and TCP
  792.  * Implementations'' in CCR 27(2) for descriptions of
  793.  * what other systems do the same.
  794.  *
  795.  */
  796. if (strcmp(argv[1], "persist") == 0) {
  797. TcpAgent *other
  798.   = (TcpAgent*)TclObject::lookup(argv[2]);
  799. cwnd_ = other->cwnd_;
  800. awnd_ = other->awnd_;
  801. ssthresh_ = other->ssthresh_;
  802. t_rtt_ = other->t_rtt_;
  803. t_srtt_ = other->t_srtt_;
  804. t_rttvar_ = other->t_rttvar_;
  805. t_backoff_ = other->t_backoff_;
  806. return (TCL_OK);
  807. }
  808. }
  809. return (Agent::command(argc, argv));
  810. }
  811. /*
  812.  * Returns the window size adjusted to allow <num> segments past recovery
  813.  * point to be transmitted on next ack.
  814.  */
  815. int TcpAgent::force_wnd(int num)
  816. {
  817. return recover_ + num - (int)highest_ack_;
  818. }
  819. int TcpAgent::window()
  820. {
  821.         /*
  822.          * If F-RTO is enabled and first ack has come in, temporarily open
  823.          * window for sending two segments.
  824.  * The F-RTO code is from Pasi Sarolahti.  F-RTO is an algorithm
  825.  * for detecting spurious retransmission timeouts.
  826.          */
  827.         if (frto_ == 2) {
  828.                 return (force_wnd(2) < wnd_ ?
  829.                         force_wnd(2) : (int)wnd_);
  830.         } else {
  831. return (cwnd_ < wnd_ ? (int)cwnd_ : (int)wnd_);
  832.         }
  833. }
  834. double TcpAgent::windowd()
  835. {
  836. return (cwnd_ < wnd_ ? (double)cwnd_ : (double)wnd_);
  837. }
  838. /*
  839.  * Try to send as much data as the window will allow.  The link layer will 
  840.  * do the buffering; we ask the application layer for the size of the packets.
  841.  */
  842. void TcpAgent::send_much(int force, int reason, int maxburst)
  843. {
  844. send_idle_helper();
  845. int win = window();
  846. int npackets = 0;
  847. if (!force && delsnd_timer_.status() == TIMER_PENDING)
  848. return;
  849. /* Save time when first packet was sent, for newreno  --Allman */
  850. if (t_seqno_ == 0)
  851. firstsent_ = Scheduler::instance().clock();
  852. if (burstsnd_timer_.status() == TIMER_PENDING)
  853. return;
  854. while (t_seqno_ <= highest_ack_ + win && t_seqno_ < curseq_) {
  855. if (overhead_ == 0 || force || qs_approved_) {
  856. output(t_seqno_, reason);
  857. npackets++;
  858. if (QOption_)
  859. process_qoption_after_send () ; 
  860. t_seqno_ ++ ;
  861. if (qs_approved_ == 1) {
  862. // delay = effective RTT / window
  863. double delay = (double) t_rtt_ * tcp_tick_ / win;
  864. if (overhead_) { 
  865. delsnd_timer_.resched(delay + Random::uniform(overhead_));
  866. } else {
  867. delsnd_timer_.resched(delay);
  868. }
  869. return;
  870. }
  871. } else if (!(delsnd_timer_.status() == TIMER_PENDING)) {
  872. /*
  873.  * Set a delayed send timeout.
  874.  */
  875. delsnd_timer_.resched(Random::uniform(overhead_));
  876. return;
  877. }
  878. win = window();
  879. if (maxburst && npackets == maxburst)
  880. break;
  881. }
  882. /* call helper function */
  883. send_helper(maxburst);
  884. }
  885. /*
  886.  * We got a timeout or too many duplicate acks.  Clear the retransmit timer.  
  887.  * Resume the sequence one past the last packet acked.  
  888.  * "mild" is 0 for timeouts and Tahoe dup acks, 1 for Reno dup acks.
  889.  * "backoff" is 1 if the timer should be backed off, 0 otherwise.
  890.  */
  891. void TcpAgent::reset_rtx_timer(int mild, int backoff)
  892. {
  893. if (backoff)
  894. rtt_backoff();
  895. set_rtx_timer();
  896. if (!mild)
  897. t_seqno_ = highest_ack_ + 1;
  898. rtt_active_ = 0;
  899. }
  900. /*
  901.  * Set retransmit timer using current rtt estimate.  By calling resched(), 
  902.  * it does not matter whether the timer was already running.
  903.  */
  904. void TcpAgent::set_rtx_timer()
  905. {
  906. rtx_timer_.resched(rtt_timeout());
  907. }
  908. /*
  909.  * Set new retransmission timer if not all outstanding
  910.  * or available data acked, or if we are unable to send because 
  911.  * cwnd is less than one (as when the ECN bit is set when cwnd was 1).
  912.  * Otherwise, if a timer is still outstanding, cancel it.
  913.  */
  914. void TcpAgent::newtimer(Packet* pkt)
  915. {
  916. hdr_tcp *tcph = hdr_tcp::access(pkt);
  917. /*
  918.  * t_seqno_, the next packet to send, is reset (decreased) 
  919.  *   to highest_ack_ + 1 after a timeout,
  920.  *   so we also have to check maxseq_, the highest seqno sent.
  921.  * In addition, if the packet sent after the timeout has
  922.  *   the ECN bit set, then the returning ACK caused cwnd_ to
  923.  *   be decreased to less than one, and we can't send another
  924.  *   packet until the retransmit timer again expires.
  925.  *   So we have to check for "cwnd_ < 1" as well.
  926.  */
  927. if (t_seqno_ > tcph->seqno() || tcph->seqno() < maxseq_ || cwnd_ < 1) 
  928. set_rtx_timer();
  929. else
  930. cancel_rtx_timer();
  931. }
  932. /*
  933.  * for experimental, high-speed TCP
  934.  */
  935. double TcpAgent::linear(double x, double x_1, double y_1, double x_2, double y_2)
  936. {
  937. // The y coordinate factor ranges from y_1 to y_2
  938. //  as the x coordinate ranges from x_1 to x_2.
  939. double y = y_1 + ((y_2 - y_1) * ((x - x_1)/(x_2-x_1)));
  940. return y;
  941. }
  942. /*
  943.  * Limited Slow-Start for large congestion windows.
  944.  * This should only be called when max_ssthresh_ is non-zero.
  945.  */
  946. double TcpAgent::limited_slow_start(double cwnd, int max_ssthresh, double increment)
  947. {
  948.         if (max_ssthresh <= 0) {
  949.    return increment;
  950. } else {
  951.                 double increment1 = 0.0;
  952. int round = int(cwnd / (double(max_ssthresh)/2.0));
  953. if (round > 0) {
  954.    increment1 = 1.0/double(round); 
  955. if (increment < increment1) {
  956.    return increment1;
  957. } else {
  958.    return increment;
  959. }
  960. }
  961. }
  962. /*
  963.  * For retrieving numdupacks_.
  964.  */
  965. int TcpAgent::numdupacks(double cwnd)
  966. {
  967.         int cwndfraction = (int) cwnd/numdupacksFrac_;
  968. if (numdupacks_ > cwndfraction) {
  969.    return numdupacks_;
  970.         } else {
  971.    return cwndfraction;
  972. }
  973. }
  974. /*
  975.  * Calculating the decrease parameter for highspeed TCP.
  976.  */
  977. double TcpAgent::decrease_param()
  978. {
  979. double decrease;
  980. // OLD:
  981. // decrease = linear(log(cwnd_), log(low_window_), 0.5, log(high_window_), high_decrease_);
  982. // NEW (but equivalent):
  983.         decrease = hstcp_.dec1 + log(cwnd_) * hstcp_.dec2;  
  984. return decrease;
  985. }
  986. /*
  987.  * Calculating the increase parameter for highspeed TCP.
  988.  */
  989. double TcpAgent::increase_param()
  990. {
  991. double increase, decrease, p, answer;
  992. /* extending the slow-start for high-speed TCP */
  993. /* for highspeed TCP -- from Sylvia Ratnasamy, */
  994. /* modifications by Sally Floyd and Evandro de Souza */
  995.   // p ranges from 1.5/W^2 at congestion window low_window_, to
  996. //    high_p_ at congestion window high_window_, on a log-log scale.
  997.         // The decrease factor ranges from 0.5 to high_decrease
  998. //  as the window ranges from low_window to high_window, 
  999. //  as the log of the window. 
  1000. // For an efficient implementation, this would just be looked up
  1001. //   in a table, with the increase and decrease being a function of the
  1002. //   congestion window.
  1003.        if (cwnd_ <= low_window_) { 
  1004. answer = 1 / cwnd_;
  1005.         return answer; 
  1006.        } else if (cwnd_ >= hstcp_.cwnd_last_ && 
  1007.       cwnd_ < hstcp_.cwnd_last_ + cwnd_range_) {
  1008.       // cwnd_range_ can be set to 0 to be disabled,
  1009.       //  or can be set from 1 to 100 
  1010.         answer = hstcp_.increase_last_ / cwnd_;
  1011.                return answer;
  1012.        } else { 
  1013. // OLD:
  1014.   // p = exp(linear(log(cwnd_), log(low_window_), log(hstcp_.low_p), log(high_window_), log(high_p_)));
  1015. // NEW, but equivalent:
  1016.          p = exp(hstcp_.p1 + log(cwnd_) * hstcp_.p2);  
  1017.          decrease = decrease_param();
  1018. // OLD:
  1019. // increase = cwnd_*cwnd_*p *(2.0*decrease)/(2.0 - decrease); 
  1020. // NEW, but equivalent:
  1021. increase = cwnd_ * cwnd_ * p /(1/decrease - 0.5);
  1022. // if (increase > max_increase) { 
  1023. // increase = max_increase;
  1024. // } 
  1025. answer = increase / cwnd_;
  1026. hstcp_.cwnd_last_ = cwnd_;
  1027. hstcp_.increase_last_ = increase;
  1028.         return answer;
  1029. }       
  1030. }
  1031. /*
  1032.  * open up the congestion window
  1033.  */
  1034. void TcpAgent::opencwnd()
  1035. {
  1036. double increment;
  1037. if (cwnd_ < ssthresh_) {
  1038. /* slow-start (exponential) */
  1039. cwnd_ += 1;
  1040. } else {
  1041. /* linear */
  1042. double f;
  1043. switch (wnd_option_) {
  1044. case 0:
  1045. if (++count_ >= cwnd_) {
  1046. count_ = 0;
  1047. ++cwnd_;
  1048. }
  1049. break;
  1050. case 1:
  1051. /* This is the standard algorithm. */
  1052. increment = increase_num_ / cwnd_;
  1053. if ((last_cwnd_action_ == 0 ||
  1054.   last_cwnd_action_ == CWND_ACTION_TIMEOUT) 
  1055.   && max_ssthresh_ > 0) {
  1056. increment = limited_slow_start(cwnd_,
  1057.   max_ssthresh_, increment);
  1058. }
  1059. cwnd_ += increment;
  1060. break;
  1061. case 2:
  1062. /* These are window increase algorithms
  1063.  * for experimental purposes only. */
  1064. /* This is the Constant-Rate increase algorithm 
  1065.                          *  from the 1991 paper by S. Floyd on "Connections  
  1066.  *  with Multiple Congested Gateways". 
  1067.  *  The window is increased by roughly 
  1068.  *  wnd_const_*RTT^2 packets per round-trip time.  */
  1069. f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;
  1070. f *= f;
  1071. f *= wnd_const_;
  1072. /* f = wnd_const_ * RTT^2 */
  1073. f += fcnt_;
  1074. if (f > cwnd_) {
  1075. fcnt_ = 0;
  1076. ++cwnd_;
  1077. } else
  1078. fcnt_ = f;
  1079. break;
  1080. case 3:
  1081. /* The window is increased by roughly 
  1082.  *  awnd_^2 * wnd_const_ packets per RTT,
  1083.  *  for awnd_ the average congestion window. */
  1084. f = awnd_;
  1085. f *= f;
  1086. f *= wnd_const_;
  1087. f += fcnt_;
  1088. if (f > cwnd_) {
  1089. fcnt_ = 0;
  1090. ++cwnd_;
  1091. } else
  1092. fcnt_ = f;
  1093. break;
  1094.                 case 4:
  1095. /* The window is increased by roughly 
  1096.  *  awnd_ * wnd_const_ packets per RTT,
  1097.  *  for awnd_ the average congestion window. */
  1098.                         f = awnd_;
  1099.                         f *= wnd_const_;
  1100.                         f += fcnt_;
  1101.                         if (f > cwnd_) {
  1102.                                 fcnt_ = 0;
  1103.                                 ++cwnd_;
  1104.                         } else
  1105.                                 fcnt_ = f;
  1106.                         break;
  1107. case 5:
  1108. /* The window is increased by roughly wnd_const_*RTT 
  1109.  *  packets per round-trip time, as discussed in
  1110.  *  the 1992 paper by S. Floyd on "On Traffic 
  1111.  *  Phase Effects in Packet-Switched Gateways". */
  1112.                         f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;
  1113.                         f *= wnd_const_;
  1114.                         f += fcnt_;
  1115.                         if (f > cwnd_) {
  1116.                                 fcnt_ = 0;
  1117.                                 ++cwnd_;
  1118.                         } else
  1119.                                 fcnt_ = f;
  1120.                         break;
  1121.                 case 6:
  1122.                         /* binomial controls */ 
  1123.                         cwnd_ += increase_num_ / (cwnd_*pow(cwnd_,k_parameter_));                
  1124.                         break; 
  1125.   case 8: 
  1126. /* high-speed TCP, RFC 3649 */
  1127. increment = increase_param();
  1128. if ((last_cwnd_action_ == 0 ||
  1129.   last_cwnd_action_ == CWND_ACTION_TIMEOUT) 
  1130.   && max_ssthresh_ > 0) {
  1131. increment = limited_slow_start(cwnd_,
  1132.   max_ssthresh_, increment);
  1133. }
  1134. cwnd_ += increment;
  1135.                         break;
  1136. default:
  1137. #ifdef notdef
  1138. /*XXX*/
  1139. error("illegal window option %d", wnd_option_);
  1140. #endif
  1141. abort();
  1142. }
  1143. }
  1144. // if maxcwnd_ is set (nonzero), make it the cwnd limit
  1145. if (maxcwnd_ && (int(cwnd_) > maxcwnd_))
  1146. cwnd_ = maxcwnd_;
  1147. return;
  1148. }
  1149. void
  1150. TcpAgent::slowdown(int how)
  1151. {
  1152. double decrease;  /* added for highspeed - sylvia */
  1153. double win, halfwin, decreasewin;
  1154. int slowstart = 0;
  1155. ++ncwndcuts_;
  1156. if (!(how & TCP_IDLE) && !(how & NO_OUTSTANDING_DATA)){
  1157. ++ncwndcuts1_; 
  1158. }
  1159. // we are in slowstart for sure if cwnd < ssthresh
  1160. if (cwnd_ < ssthresh_) 
  1161. slowstart = 1;
  1162.         if (precision_reduce_) {
  1163. halfwin = windowd() / 2;
  1164.                 if (wnd_option_ == 6) {         
  1165.                         /* binomial controls */
  1166.                         decreasewin = windowd() - (1.0-decrease_num_)*pow(windowd(),l_parameter_);
  1167.                 } else if (wnd_option_ == 8 && (cwnd_ > low_window_)) { 
  1168.                         /* experimental highspeed TCP */
  1169. decrease = decrease_param();
  1170. //if (decrease < 0.1) 
  1171. // decrease = 0.1;
  1172. decrease_num_ = decrease;
  1173.                         decreasewin = windowd() - (decrease * windowd());
  1174.                 } else {
  1175.   decreasewin = decrease_num_ * windowd();
  1176. }
  1177. win = windowd();
  1178. } else  {
  1179. int temp;
  1180. temp = (int)(window() / 2);
  1181. halfwin = (double) temp;
  1182.                 if (wnd_option_ == 6) {
  1183.                         /* binomial controls */
  1184.                         temp = (int)(window() - (1.0-decrease_num_)*pow(window(),l_parameter_));
  1185.                 } else if ((wnd_option_ == 8) && (cwnd_ > low_window_)) { 
  1186.                         /* experimental highspeed TCP */
  1187. decrease = decrease_param();
  1188. //if (decrease < 0.1)
  1189.                         //       decrease = 0.1;
  1190. decrease_num_ = decrease;
  1191.                         temp = (int)(windowd() - (decrease * windowd()));
  1192.                 } else {
  1193.   temp = (int)(decrease_num_ * window());
  1194. }
  1195. decreasewin = (double) temp;
  1196. win = (double) window();
  1197. }
  1198. if (how & CLOSE_SSTHRESH_HALF)
  1199. // For the first decrease, decrease by half
  1200. // even for non-standard values of decrease_num_.
  1201. if (first_decrease_ == 1 || slowstart ||
  1202. last_cwnd_action_ == CWND_ACTION_TIMEOUT) {
  1203. // Do we really want halfwin instead of decreasewin
  1204. // after a timeout?
  1205. ssthresh_ = (int) halfwin;
  1206. } else {
  1207. ssthresh_ = (int) decreasewin;
  1208. }
  1209.         else if (how & THREE_QUARTER_SSTHRESH)
  1210. if (ssthresh_ < 3*cwnd_/4)
  1211. ssthresh_  = (int)(3*cwnd_/4);
  1212. if (how & CLOSE_CWND_HALF)
  1213. // For the first decrease, decrease by half
  1214. // even for non-standard values of decrease_num_.
  1215. if (first_decrease_ == 1 || slowstart || decrease_num_ == 0.5) {
  1216. cwnd_ = halfwin;
  1217. } else cwnd_ = decreasewin;
  1218.         else if (how & CWND_HALF_WITH_MIN) {
  1219. // We have not thought about how non-standard TCPs, with
  1220. // non-standard values of decrease_num_, should respond
  1221. // after quiescent periods.
  1222.                 cwnd_ = decreasewin;
  1223.                 if (cwnd_ < 1)
  1224.                         cwnd_ = 1;
  1225. }
  1226. else if (how & CLOSE_CWND_RESTART) 
  1227. cwnd_ = int(wnd_restart_);
  1228. else if (how & CLOSE_CWND_INIT)
  1229. cwnd_ = int(wnd_init_);
  1230. else if (how & CLOSE_CWND_ONE)
  1231. cwnd_ = 1;
  1232. else if (how & CLOSE_CWND_HALF_WAY) {
  1233. // cwnd_ = win - (win - W_used)/2 ;
  1234. cwnd_ = W_used + decrease_num_ * (win - W_used);
  1235.                 if (cwnd_ < 1)
  1236.                         cwnd_ = 1;
  1237. }
  1238. if (ssthresh_ < 2)
  1239. ssthresh_ = 2;
  1240. if (how & (CLOSE_CWND_HALF|CLOSE_CWND_RESTART|CLOSE_CWND_INIT|CLOSE_CWND_ONE))
  1241. cong_action_ = TRUE;
  1242. fcnt_ = count_ = 0;
  1243. if (first_decrease_ == 1)
  1244. first_decrease_ = 0;
  1245. // for event tracing slow start
  1246. if (cwnd_ == 1 || slowstart) 
  1247. // Not sure if this is best way to capture slow_start
  1248. // This is probably tracing a superset of slowdowns of
  1249. // which all may not be slow_start's --Padma, 07/'01.
  1250. trace_event("SLOW_START");
  1251. }
  1252. /*
  1253.  * Process a packet that acks previously unacknowleged data.
  1254.  */
  1255. void TcpAgent::newack(Packet* pkt)
  1256. {
  1257. double now = Scheduler::instance().clock();
  1258. hdr_tcp *tcph = hdr_tcp::access(pkt);
  1259. /* 
  1260.  * Wouldn't it be better to set the timer *after*
  1261.  * updating the RTT, instead of *before*? 
  1262.  */
  1263. if (!timerfix_) newtimer(pkt);
  1264. dupacks_ = 0;
  1265. last_ack_ = tcph->seqno();
  1266. prev_highest_ack_ = highest_ack_ ;
  1267. highest_ack_ = last_ack_;
  1268. if (t_seqno_ < last_ack_ + 1)
  1269. t_seqno_ = last_ack_ + 1;
  1270. /* 
  1271.  * Update RTT only if it's OK to do so from info in the flags header.
  1272.  * This is needed for protocols in which intermediate agents
  1273.  * in the network intersperse acks (e.g., ack-reconstructors) for
  1274.  * various reasons (without violating e2e semantics).
  1275.  */
  1276. hdr_flags *fh = hdr_flags::access(pkt);
  1277. if (!fh->no_ts_) {
  1278. if (ts_option_) {
  1279. ts_echo_=tcph->ts_echo();
  1280. rtt_update(now - tcph->ts_echo());
  1281. if (ts_resetRTO_ && (!ect_ || !ecn_backoff_ ||
  1282.     !hdr_flags::access(pkt)->ecnecho())) { 
  1283. // From Andrei Gurtov
  1284. /* 
  1285.  * Don't end backoff if still in ECN-Echo with
  1286.    * a congestion window of 1 packet. 
  1287.  */
  1288. t_backoff_ = 1;
  1289. ecn_backoff_ = 0;
  1290. }
  1291. }
  1292. if (rtt_active_ && tcph->seqno() >= rtt_seq_) {
  1293. if (!ect_ || !ecn_backoff_ || 
  1294. !hdr_flags::access(pkt)->ecnecho()) {
  1295. /* 
  1296.  * Don't end backoff if still in ECN-Echo with
  1297.    * a congestion window of 1 packet. 
  1298.  */
  1299. t_backoff_ = 1;
  1300. ecn_backoff_ = 0;
  1301. }
  1302. rtt_active_ = 0;
  1303. if (!ts_option_)
  1304. rtt_update(now - rtt_ts_);
  1305. }
  1306. }
  1307. if (timerfix_) newtimer(pkt);
  1308. /* update average window */
  1309. awnd_ *= 1.0 - wnd_th_;
  1310. awnd_ += wnd_th_ * cwnd_;
  1311. }
  1312. /*
  1313.  * Respond either to a source quench or to a congestion indication bit.
  1314.  * This is done at most once a roundtrip time;  after a source quench,
  1315.  * another one will not be done until the last packet transmitted before
  1316.  * the previous source quench has been ACKed.
  1317.  *
  1318.  * Note that this procedure is called before "highest_ack_" is
  1319.  * updated to reflect the current ACK packet.  
  1320.  */
  1321. void TcpAgent::ecn(int seqno)
  1322. {
  1323. if (seqno > recover_ || 
  1324.       last_cwnd_action_ == CWND_ACTION_TIMEOUT) {
  1325. recover_ =  maxseq_;
  1326. last_cwnd_action_ = CWND_ACTION_ECN;
  1327. if (cwnd_ <= 1.0) {
  1328. if (ecn_backoff_) 
  1329. rtt_backoff();
  1330. else ecn_backoff_ = 1;
  1331. } else ecn_backoff_ = 0;
  1332. slowdown(CLOSE_CWND_HALF|CLOSE_SSTHRESH_HALF);
  1333. ++necnresponses_ ;
  1334. // added by sylvia to count number of ecn responses 
  1335. }
  1336. }
  1337. /*
  1338.  *  Is the connection limited by the network (instead of by a lack
  1339.  *    of data from the application?
  1340.  */
  1341. int TcpAgent::network_limited() {
  1342. int win = window () ;
  1343. if (t_seqno_ > (prev_highest_ack_ + win))
  1344. return 1;
  1345. else
  1346. return 0;
  1347. }
  1348. void TcpAgent::recv_newack_helper(Packet *pkt) {
  1349. //hdr_tcp *tcph = hdr_tcp::access(pkt);
  1350. newack(pkt);
  1351.         if (qs_window_ && highest_ack_ >= qs_window_) {
  1352.                 // All segments in the QS window have been acknowledged.
  1353.                 // We can exit the Quick-Start phase.
  1354.                 qs_window_ = 0;
  1355.         }
  1356. if (!ect_ || !hdr_flags::access(pkt)->ecnecho() ||
  1357. (old_ecn_ && ecn_burst_)) {
  1358. /* If "old_ecn", this is not the first ACK carrying ECN-Echo
  1359.  * after a period of ACKs without ECN-Echo.
  1360.  * Therefore, open the congestion window. */
  1361. /* if control option is set, and the sender is not
  1362.  window limited, then do not increase the window size */
  1363. if (!control_increase_ || 
  1364.    (control_increase_ && (network_limited() == 1))) 
  1365.        opencwnd();
  1366. }
  1367. if (ect_) {
  1368. if (!hdr_flags::access(pkt)->ecnecho())
  1369. ecn_backoff_ = 0;
  1370. if (!ecn_burst_ && hdr_flags::access(pkt)->ecnecho())
  1371. ecn_burst_ = TRUE;
  1372. else if (ecn_burst_ && ! hdr_flags::access(pkt)->ecnecho())
  1373. ecn_burst_ = FALSE;
  1374. }
  1375. if (!ect_ && hdr_flags::access(pkt)->ecnecho() &&
  1376. !hdr_flags::access(pkt)->cong_action())
  1377. ect_ = 1;
  1378. /* if the connection is done, call finish() */
  1379. if ((highest_ack_ >= curseq_-1) && !closed_) {
  1380. closed_ = 1;
  1381. finish();
  1382. }
  1383. if (QOption_ && curseq_ == highest_ack_ +1) {
  1384. cancel_rtx_timer();
  1385. }
  1386. if (frto_ == 1) {
  1387. /*
  1388.  * New ack after RTO. If F-RTO is enabled, try to transmit new
  1389.  * previously unsent segments.
  1390.  * If there are no new data or receiver window limits the
  1391.  * transmission, revert to traditional recovery.
  1392.  */
  1393. if (recover_ + 1 >= highest_ack_ + wnd_ ||
  1394.     recover_ + 1 >= curseq_) {
  1395. frto_ = 0;
  1396.   } else if (highest_ack_ == recover_) {
  1397.   /*
  1398.    * F-RTO step 2a) RTO retransmission fixes whole
  1399.  * window => cancel F-RTO
  1400.    */
  1401.   frto_ = 0;
  1402. } else {
  1403. t_seqno_ = recover_ + 1;
  1404. frto_ = 2;
  1405. }
  1406. } else if (frto_ == 2) {
  1407. /*
  1408.  * Second new ack after RTO. If F-RTO is enabled, RTO can be
  1409.  * declared spurious
  1410.  */
  1411. spurious_timeout();
  1412. }
  1413. }
  1414. /*
  1415.  * Set the initial window. 
  1416.  */
  1417. double
  1418. TcpAgent::initial_window()
  1419. {
  1420.         // If Quick-Start Request was approved, use that as a basis for
  1421.         // initial window
  1422.         if (qs_cwnd_) {
  1423.                 return (qs_cwnd_);
  1424.         }
  1425. //
  1426. // init_option = 1: static iw of wnd_init_
  1427. //
  1428. if (wnd_init_option_ == 1) {
  1429. return (wnd_init_);
  1430. }
  1431.         else if (wnd_init_option_ == 2) {
  1432. // do iw according to Internet draft
  1433.   if (size_ <= 1095) {
  1434. return (4.0);
  1435.   } else if (size_ < 2190) {
  1436. return (3.0);
  1437. } else {
  1438. return (2.0);
  1439. }
  1440. }
  1441. // XXX what should we return here???
  1442. fprintf(stderr, "Wrong number of wnd_init_option_ %dn", 
  1443. wnd_init_option_);
  1444. abort();
  1445. return (2.0); // XXX make msvc happy.
  1446. }
  1447. /*
  1448.  * Dupack-action: what to do on a DUP ACK.  After the initial check
  1449.  * of 'recover' below, this function implements the following truth
  1450.  * table:
  1451.  *
  1452.  * bugfix ecn last-cwnd == ecn action
  1453.  *
  1454.  * 0 0 0 tahoe_action
  1455.  * 0 0 1 tahoe_action [impossible]
  1456.  * 0 1 0 tahoe_action
  1457.  * 0 1 1 slow-start, return
  1458.  * 1 0 0 nothing
  1459.  * 1 0 1 nothing [impossible]
  1460.  * 1 1 0 nothing
  1461.  * 1 1 1 slow-start, return
  1462.  */
  1463. /* 
  1464.  * A first or second duplicate acknowledgement has arrived, and
  1465.  * singledup_ is enabled.
  1466.  * If the receiver's advertised window permits, and we are exceeding our
  1467.  * congestion window by less than numdupacks_, then send a new packet.
  1468.  */
  1469. void
  1470. TcpAgent::send_one()
  1471. {
  1472. if (t_seqno_ <= highest_ack_ + wnd_ && t_seqno_ < curseq_ &&
  1473. t_seqno_ <= highest_ack_ + cwnd_ + dupacks_ ) {
  1474. output(t_seqno_, 0);
  1475. if (QOption_)
  1476. process_qoption_after_send () ;
  1477. t_seqno_ ++ ;
  1478. // send_helper(); ??
  1479. }
  1480. return;
  1481. }
  1482. void
  1483. TcpAgent::dupack_action()
  1484. {
  1485. int recovered = (highest_ack_ > recover_);
  1486. if (recovered || (!bug_fix_ && !ecn_) || 
  1487. (bugfix_ss_ && highest_ack_ == 0)) {
  1488. // (highest_ack_ == 0) added to allow Fast Retransmit
  1489. //  when the first data packet is dropped.
  1490. //  Bug report from Mark Allman.
  1491. goto tahoe_action;
  1492. }
  1493. if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
  1494. last_cwnd_action_ = CWND_ACTION_DUPACK;
  1495. slowdown(CLOSE_CWND_ONE);
  1496. reset_rtx_timer(0,0);
  1497. return;
  1498. }
  1499. if (bug_fix_) {
  1500. /*
  1501.  * The line below, for "bug_fix_" true, avoids
  1502.  * problems with multiple fast retransmits in one
  1503.  * window of data. 
  1504.  */
  1505. return;
  1506. }
  1507. tahoe_action:
  1508.         recover_ = maxseq_;
  1509.         if (!lossQuickStart()) {
  1510. // we are now going to fast-retransmit and willtrace that event
  1511. trace_event("FAST_RETX");
  1512. last_cwnd_action_ = CWND_ACTION_DUPACK;
  1513. slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_ONE);
  1514. }
  1515. reset_rtx_timer(0,0);
  1516. return;
  1517. }
  1518. /*
  1519.  * When exiting QuickStart, reduce the congestion window to the
  1520.  *   size that was actually used.
  1521.  */
  1522. void TcpAgent::endQuickStart()
  1523. {
  1524. qs_approved_ = 0;
  1525.         qs_cwnd_ = 0;
  1526.         qs_window_ = maxseq_;
  1527. int new_cwnd = maxseq_ - last_ack_;
  1528. if (new_cwnd > 1 && new_cwnd < cwnd_) {
  1529.   cwnd_ = new_cwnd;
  1530. if (cwnd_ < initial_window()) 
  1531. cwnd_ = initial_window();
  1532. }
  1533. }
  1534. void TcpAgent::processQuickStart(Packet *pkt)
  1535. {
  1536. // QuickStart code from Srikanth Sundarrajan.
  1537. hdr_tcp *tcph = hdr_tcp::access(pkt);
  1538. hdr_qs *qsh = hdr_qs::access(pkt);
  1539. double now = Scheduler::instance().clock();
  1540. int app_rate;
  1541.         // printf("flag: %d ttl: %d ttl_diff: %d rate: %dn", qsh->flag(),
  1542. //     qsh->ttl(), ttl_diff_, qsh->rate());
  1543. qs_requested_ = 0;
  1544. qs_approved_ = 0;
  1545. if (qsh->flag() == QS_RESPONSE && qsh->ttl() == ttl_diff_ && 
  1546.             qsh->rate() > 0) {
  1547.                 app_rate = (int) ((hdr_qs::rate_to_Bps(qsh->rate()) *
  1548.                       (now - tcph->ts_echo())) / (size_ + headersize()));
  1549. if (print_request_) {
  1550.   double num1 = hdr_qs::rate_to_Bps(qsh->rate());
  1551.   double time = now - tcph->ts_echo();
  1552.   int size = size_ + headersize();
  1553.   printf("Quick Start request, rate: %g Bps, encoded rate: %dn", 
  1554.      num1, qsh->rate());
  1555.   printf("Quick Start request, window %d rtt: %4.2f pktsize: %dn",
  1556.      app_rate, time, size);
  1557. }
  1558.                 if (app_rate > initial_window()) {
  1559. qs_cwnd_ = app_rate;
  1560.                         qs_approved_ = 1;
  1561.                 }
  1562.         } else { // Quick Start rejected
  1563. #ifdef QS_DEBUG
  1564.                 printf("Quick Start rejectedn");
  1565. #endif
  1566.         }
  1567. }
  1568. /*
  1569.  * ACK has been received, hook from recv()
  1570.  */
  1571. void TcpAgent::recv_frto_helper(Packet *pkt)
  1572. {
  1573. hdr_tcp *tcph = hdr_tcp::access(pkt);
  1574. if (tcph->seqno() == last_ack_ && frto_ != 0) {
  1575. /*
  1576.  * Duplicate ACK while in F-RTO indicates that the
  1577.  * timeout was valid. Go to slow start retransmissions.
  1578.  */
  1579. t_seqno_ = highest_ack_ + 1;
  1580. cwnd_ = frto_;
  1581. frto_ = 0;
  1582. // Must zero dupacks (in order to trigger send_much at recv)
  1583. // dupacks is increased in recv after exiting this function
  1584. dupacks_ = -1;
  1585. }
  1586. }
  1587. /*
  1588.  * A spurious timeout has been detected. Do appropriate actions.
  1589.  */
  1590. void TcpAgent::spurious_timeout()
  1591. {
  1592. frto_ = 0;
  1593. switch (spurious_response_) {
  1594. case 1:
  1595. default:
  1596. /*
  1597.  * Full revert of congestion window
  1598.  * (FlightSize before last acknowledgment)
  1599.  */
  1600. cwnd_ = t_seqno_ - prev_highest_ack_;
  1601. break;
  1602.  
  1603. case 2:
  1604. /*
  1605.  * cwnd = reduced ssthresh (approx. half of the earlier pipe)
  1606.  */
  1607. cwnd_ = ssthresh_; break;
  1608. case 3:
  1609. /*
  1610.  * slow start, but without retransmissions
  1611.  */
  1612. cwnd_ = 1; break;
  1613. }
  1614. /*
  1615.  * Revert ssthresh to size before retransmission timeout
  1616.  */
  1617. ssthresh_ = pipe_prev_;
  1618. /* If timeout was spurious, bugfix is not needed */
  1619. recover_ = highest_ack_ - 1;
  1620. }
  1621. /*
  1622.  * Loss occurred in Quick-Start window.
  1623.  * If Quick-Start is enabled, packet loss in the QS phase, during slow-start,
  1624.  * should trigger slow start instead of the regular fast retransmit.
  1625.  * We use variable tcp_qs_recovery_ to toggle this behaviour on and off.
  1626.  * If tcp_qs_recovery_ is true, initiate slow start to probe for
  1627.  * a correct window size.
  1628.  *
  1629.  * Return value: non-zero if Quick-Start specific loss recovery took place
  1630.  */
  1631. int TcpAgent::lossQuickStart()
  1632. {
  1633.        if (qs_window_ && tcp_qs_recovery_) {
  1634.                 //recover_ = maxseq_;
  1635.                 //reset_rtx_timer(1,0);
  1636.                 slowdown(CLOSE_CWND_INIT);
  1637. // reset ssthresh to half of W-D/2?
  1638.                 qs_window_ = 0;
  1639.                 output(last_ack_ + 1, TCP_REASON_DUPACK);
  1640.                 return 1;
  1641.        }
  1642.        return 0;
  1643. }
  1644. /*
  1645.  * main reception path - should only see acks, otherwise the
  1646.  * network connections are misconfigured
  1647.  */
  1648. void TcpAgent::recv(Packet *pkt, Handler*)
  1649. {
  1650. hdr_tcp *tcph = hdr_tcp::access(pkt);
  1651. int valid_ack = 0;
  1652. if (qs_approved_ == 1 && tcph->seqno() > last_ack_) 
  1653. endQuickStart();
  1654. if (qs_requested_ == 1)
  1655. processQuickStart(pkt);
  1656. #ifdef notdef
  1657. if (pkt->type_ != PT_ACK) {
  1658. Tcl::instance().evalf("%s error "received non-ack"",
  1659.       name());
  1660. Packet::free(pkt);
  1661. return;
  1662. }
  1663. #endif
  1664. /* W.N.: check if this is from a previous incarnation */
  1665. if (tcph->ts() < lastreset_) {
  1666. // Remove packet and do nothing
  1667. Packet::free(pkt);
  1668. return;
  1669. }
  1670. ++nackpack_;
  1671. ts_peer_ = tcph->ts();
  1672. int ecnecho = hdr_flags::access(pkt)->ecnecho();
  1673. if (ecnecho && ecn_)
  1674. ecn(tcph->seqno());
  1675. recv_helper(pkt);
  1676. recv_frto_helper(pkt);
  1677. /* grow cwnd and check if the connection is done */ 
  1678. if (tcph->seqno() > last_ack_) {
  1679. recv_newack_helper(pkt);
  1680. if (last_ack_ == 0 && delay_growth_) { 
  1681. cwnd_ = initial_window();
  1682. }
  1683. } else if (tcph->seqno() == last_ack_) {
  1684.                 if (hdr_flags::access(pkt)->eln_ && eln_) {
  1685.                         tcp_eln(pkt);
  1686.                         return;
  1687.                 }
  1688. if (++dupacks_ == numdupacks_ && !noFastRetrans_) {
  1689. dupack_action();
  1690. } else if (dupacks_ < numdupacks_ && singledup_ ) {
  1691. send_one();
  1692. }
  1693. }
  1694. if (QOption_ && EnblRTTCtr_)
  1695. process_qoption_after_ack (tcph->seqno());
  1696. if (tcph->seqno() >= last_ack_)  
  1697. // Check if ACK is valid.  Suggestion by Mark Allman. 
  1698. valid_ack = 1;
  1699. Packet::free(pkt);
  1700. /*
  1701.  * Try to send more data.
  1702.  */
  1703. if (valid_ack || aggressive_maxburst_)
  1704. send_much(0, 0, maxburst_);
  1705. }
  1706. /*
  1707.  * Process timeout events other than rtx timeout. Having this as a separate 
  1708.  * function allows derived classes to make alterations/enhancements (e.g.,
  1709.  * response to new types of timeout events).
  1710.  */ 
  1711. void TcpAgent::timeout_nonrtx(int tno) 
  1712. {
  1713. if (tno == TCP_TIMER_DELSND)  {
  1714.  /*
  1715.   * delayed-send timer, with random overhead
  1716.   * to avoid phase effects
  1717.   */
  1718. send_much(1, TCP_REASON_TIMEOUT, maxburst_);
  1719. }
  1720. }
  1721. void TcpAgent::timeout(int tno)
  1722. {
  1723. /* retransmit timer */
  1724. if (tno == TCP_TIMER_RTX) {
  1725. // There has been a timeout - will trace this event
  1726. trace_event("TIMEOUT");
  1727. frto_ = 0;
  1728. // Set pipe_prev as per Eifel Response
  1729. pipe_prev_ = (window() > ssthresh_) ?
  1730. window() : (int)ssthresh_;
  1731.         if (cwnd_ < 1) cwnd_ = 1;
  1732. if (qs_approved_ == 1) qs_approved_ = 0;
  1733. if (highest_ack_ == maxseq_ && !slow_start_restart_) {
  1734. /*
  1735.  * TCP option:
  1736.  * If no outstanding data, then don't do anything.  
  1737.  */
  1738.  // Should this return be here?
  1739.  // What if CWND_ACTION_ECN and cwnd < 1?
  1740.  // return;
  1741. } else {
  1742. recover_ = maxseq_;
  1743. if (highest_ack_ == -1 && wnd_init_option_ == 2)
  1744. /* 
  1745.  * First packet dropped, so don't use larger
  1746.  * initial windows. 
  1747.  */
  1748. wnd_init_option_ = 1;
  1749.                         else if ((highest_ack_ == -1) &&
  1750.                                 (wnd_init_option_ == 1) && (wnd_init_ > 1)
  1751. && bugfix_ss_)
  1752.                                 /*
  1753.                                  * First packet dropped, so don't use larger
  1754.                                  * initial windows.  Bugfix from Mark Allman.
  1755.                                  */
  1756.                                 wnd_init_ = 1;
  1757. if (highest_ack_ == maxseq_ && restart_bugfix_)
  1758.        /* 
  1759. * if there is no outstanding data, don't cut 
  1760. * down ssthresh_.
  1761. */
  1762. slowdown(CLOSE_CWND_ONE|NO_OUTSTANDING_DATA);
  1763. else if (highest_ack_ < recover_ &&
  1764.   last_cwnd_action_ == CWND_ACTION_ECN) {
  1765.        /*
  1766. * if we are in recovery from a recent ECN,
  1767. * don't cut down ssthresh_.
  1768. */
  1769. slowdown(CLOSE_CWND_ONE);
  1770. if (frto_enabled_ || sfrto_enabled_) {
  1771. frto_ = 1;
  1772. }
  1773. }
  1774. else {
  1775. ++nrexmit_;
  1776. last_cwnd_action_ = CWND_ACTION_TIMEOUT;
  1777. slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_RESTART);
  1778. if (frto_enabled_ || sfrto_enabled_) {
  1779. frto_ = 1;
  1780. }
  1781. }
  1782. }
  1783. /* if there is no outstanding data, don't back off rtx timer */
  1784. if (highest_ack_ == maxseq_ && restart_bugfix_) {
  1785. reset_rtx_timer(0,0);
  1786. }
  1787. else {
  1788. reset_rtx_timer(0,1);
  1789. }
  1790. last_cwnd_action_ = CWND_ACTION_TIMEOUT;
  1791. send_much(0, TCP_REASON_TIMEOUT, maxburst_);
  1792. else {
  1793. timeout_nonrtx(tno);
  1794. }
  1795. }
  1796. /* 
  1797.  * Check if the packet (ack) has the ELN bit set, and if it does, and if the
  1798.  * last ELN-rxmitted packet is smaller than this one, then retransmit the
  1799.  * packet.  Do not adjust the cwnd when this happens.
  1800.  */
  1801. void TcpAgent::tcp_eln(Packet *pkt)
  1802. {
  1803.         //int eln_rxmit;
  1804.         hdr_tcp *tcph = hdr_tcp::access(pkt);
  1805.         int ack = tcph->seqno();
  1806.         if (++dupacks_ == eln_rxmit_thresh_ && ack > eln_last_rxmit_) {
  1807.                 /* Retransmit this packet */
  1808.                 output(last_ack_ + 1, TCP_REASON_DUPACK);
  1809.                 eln_last_rxmit_ = last_ack_+1;
  1810.         } else
  1811.                 send_much(0, 0, maxburst_);
  1812.         Packet::free(pkt);
  1813.         return;
  1814. }
  1815. /*
  1816.  * This function is invoked when the connection is done. It in turn
  1817.  * invokes the Tcl finish procedure that was registered with TCP.
  1818.  */
  1819. void TcpAgent::finish()
  1820. {
  1821. Tcl::instance().evalf("%s done", this->name());
  1822. }
  1823. void RtxTimer::expire(Event*)
  1824. {
  1825. a_->timeout(TCP_TIMER_RTX);
  1826. }
  1827. void DelSndTimer::expire(Event*)
  1828. {
  1829. a_->timeout(TCP_TIMER_DELSND);
  1830. }
  1831. void BurstSndTimer::expire(Event*)
  1832. {
  1833. a_->timeout(TCP_TIMER_BURSTSND);
  1834. }
  1835. /*
  1836.  * THE FOLLOWING FUNCTIONS ARE OBSOLETE, but REMAIN HERE
  1837.  * DUE TO OTHER PEOPLE's TCPs THAT MIGHT USE THEM
  1838.  *
  1839.  * These functions are now replaced by ecn() and slowdown(),
  1840.  * respectively.
  1841.  */
  1842. /*
  1843.  * Respond either to a source quench or to a congestion indication bit.
  1844.  * This is done at most once a roundtrip time;  after a source quench,
  1845.  * another one will not be done until the last packet transmitted before
  1846.  * the previous source quench has been ACKed.
  1847.  */
  1848. void TcpAgent::quench(int how)
  1849. {
  1850. if (highest_ack_ >= recover_) {
  1851. recover_ =  maxseq_;
  1852. last_cwnd_action_ = CWND_ACTION_ECN;
  1853. closecwnd(how);
  1854. }
  1855. }
  1856. /*
  1857.  * close down the congestion window
  1858.  */
  1859. void TcpAgent::closecwnd(int how)
  1860. {   
  1861. static int first_time = 1;
  1862. if (first_time == 1) {
  1863. fprintf(stderr, "the TcpAgent::closecwnd() function is now deprecated, please use the function slowdown() insteadn");
  1864. }
  1865. switch (how) {
  1866. case 0:
  1867. /* timeouts */
  1868. ssthresh_ = int( window() / 2 );
  1869. if (ssthresh_ < 2)
  1870. ssthresh_ = 2;
  1871. cwnd_ = int(wnd_restart_);
  1872. break;
  1873. case 1:
  1874. /* Reno dup acks, or after a recent congestion indication. */
  1875. // cwnd_ = window()/2;
  1876. cwnd_ = decrease_num_ * window();
  1877. ssthresh_ = int(cwnd_);
  1878. if (ssthresh_ < 2)
  1879. ssthresh_ = 2;
  1880. break;
  1881. case 2:
  1882. /* Tahoe dup acks  
  1883.  * after a recent congestion indication */
  1884. cwnd_ = wnd_init_;
  1885. break;
  1886. case 3:
  1887. /* Retransmit timeout, but no outstanding data. */ 
  1888. cwnd_ = int(wnd_init_);
  1889. break;
  1890. case 4:
  1891. /* Tahoe dup acks */
  1892. ssthresh_ = int( window() / 2 );
  1893. if (ssthresh_ < 2)
  1894. ssthresh_ = 2;
  1895. cwnd_ = 1;
  1896. break;
  1897. default:
  1898. abort();
  1899. }
  1900. fcnt_ = 0.;
  1901. count_ = 0;
  1902. }
  1903. /*
  1904.  * Check if the sender has been idle or application-limited for more
  1905.  * than an RTO, and if so, reduce the congestion window.
  1906.  */
  1907. void TcpAgent::process_qoption_after_send ()
  1908. {
  1909. int tcp_now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
  1910. int rto = (int)(t_rtxcur_/tcp_tick_) ; 
  1911. /*double ct = Scheduler::instance().clock();*/
  1912. if (!EnblRTTCtr_) {
  1913. if (tcp_now - T_last >= rto) {
  1914. // The sender has been idle.
  1915.   slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE) ;
  1916. for (int i = 0 ; i < (tcp_now - T_last)/rto; i ++) {
  1917. slowdown(CWND_HALF_WITH_MIN|TCP_IDLE);
  1918. }
  1919. T_prev = tcp_now ;
  1920. W_used = 0 ;
  1921. }
  1922. T_last = tcp_now ;
  1923. if (t_seqno_ == highest_ack_+ window()) {
  1924. T_prev = tcp_now ; 
  1925. W_used = 0 ; 
  1926. }
  1927. else if (t_seqno_ == curseq_-1) {
  1928. // The sender has no more data to send.
  1929. int tmp = t_seqno_ - highest_ack_ ;
  1930. if (tmp > W_used)
  1931. W_used = tmp ;
  1932. if (tcp_now - T_prev >= rto) {
  1933. // The sender has been application-limited.
  1934. slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE);
  1935. slowdown(CLOSE_CWND_HALF_WAY|TCP_IDLE);
  1936. T_prev = tcp_now ;
  1937. W_used = 0 ;
  1938. }
  1939. }
  1940. } else {
  1941. rtt_counting();
  1942. }
  1943. }
  1944. /*
  1945.  * Check if the sender has been idle or application-limited for more
  1946.  * than an RTO, and if so, reduce the congestion window, for a TCP sender
  1947.  * that "counts RTTs" by estimating the number of RTTs that fit into
  1948.  * a single clock tick.
  1949.  */
  1950. void
  1951. TcpAgent::rtt_counting()
  1952. {
  1953.         int tcp_now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
  1954. int rtt = (int(t_srtt_) >> T_SRTT_BITS) ;
  1955. if (rtt < 1) 
  1956. rtt = 1 ;
  1957. if (tcp_now - T_last >= 2*rtt) {
  1958. // The sender has been idle.
  1959. int RTTs ; 
  1960. RTTs = (tcp_now -T_last)*RTT_goodcount/(rtt*2) ; 
  1961. RTTs = RTTs - Backoffs ; 
  1962. Backoffs = 0 ; 
  1963. if (RTTs > 0) {
  1964. slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE) ;
  1965. for (int i = 0 ; i < RTTs ; i ++) {
  1966. slowdown(CWND_HALF_WITH_MIN|TCP_IDLE);
  1967. RTT_prev = RTT_count ; 
  1968. W_used = 0 ;
  1969. }
  1970. }
  1971. }
  1972. T_last = tcp_now ;
  1973. if (tcp_now - T_start >= 2*rtt) {
  1974. if ((RTT_count > RTT_goodcount) || (F_full == 1)) {
  1975. RTT_goodcount = RTT_count ; 
  1976. if (RTT_goodcount < 1) RTT_goodcount = 1 ; 
  1977. }
  1978. RTT_prev = RTT_prev - RTT_count ;
  1979. RTT_count = 0 ; 
  1980. T_start  = tcp_now ;
  1981. F_full = 0;
  1982. }
  1983. if (t_seqno_ == highest_ack_ + window()) {
  1984. W_used = 0 ; 
  1985. F_full = 1 ; 
  1986. RTT_prev = RTT_count ;
  1987. }
  1988. else if (t_seqno_ == curseq_-1) {
  1989. // The sender has no more data to send.
  1990. int tmp = t_seqno_ - highest_ack_ ;
  1991. if (tmp > W_used)
  1992. W_used = tmp ;
  1993. if (RTT_count - RTT_prev >= 2) {
  1994. // The sender has been application-limited.
  1995. slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE) ;
  1996. slowdown(CLOSE_CWND_HALF_WAY|TCP_IDLE);
  1997. RTT_prev = RTT_count ; 
  1998. Backoffs ++ ; 
  1999. W_used = 0;
  2000. }
  2001. }
  2002. if (F_counting == 0) {
  2003. W_timed = t_seqno_  ;
  2004. F_counting = 1 ;
  2005. }
  2006. }
  2007. void TcpAgent::process_qoption_after_ack (int seqno)
  2008. {
  2009. if (F_counting == 1) {
  2010. if (seqno >= W_timed) {
  2011. RTT_count ++ ; 
  2012. F_counting = 0 ; 
  2013. }
  2014. else {
  2015. if (dupacks_ == numdupacks_)
  2016. RTT_count ++ ;
  2017. }
  2018. }
  2019. }
  2020. void TcpAgent::trace_event(char *eventtype)
  2021. {
  2022. if (et_ == NULL) return;
  2023. int seqno = t_seqno_;
  2024. char *wrk = et_->buffer();
  2025. char *nwrk = et_->nbuffer();
  2026. if (wrk != 0)
  2027. sprintf(wrk,
  2028. "E "TIME_FORMAT" %d %d TCP %s %d %d %d",
  2029. et_->round(Scheduler::instance().clock()),   // time
  2030. addr(),                       // owner (src) node id
  2031. daddr(),                      // dst node id
  2032. eventtype,                    // event type
  2033. fid_,                         // flow-id
  2034. seqno,                        // current seqno
  2035. int(cwnd_)                         //cong. window
  2036. );
  2037. if (nwrk != 0)
  2038. sprintf(nwrk,
  2039. "E -t "TIME_FORMAT" -o TCP -e %s -s %d.%d -d %d.%d",
  2040. et_->round(Scheduler::instance().clock()),   // time
  2041. eventtype,                    // event type
  2042. addr(),                       // owner (src) node id
  2043. port(),                       // owner (src) port id
  2044. daddr(),                      // dst node id
  2045. dport()                       // dst port id
  2046. );
  2047. et_->trace();
  2048. }