00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef lint
00036 static const char rcsid[] =
00037 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp.cc,v 1.163 2005/06/21 01:48:24 sfloyd Exp $ (LBL)";
00038 #endif
00039
00040 #include <stdlib.h>
00041 #include <math.h>
00042 #include <sys/types.h>
00043 #include "ip.h"
00044 #include "tcp.h"
00045 #include "flags.h"
00046 #include "random.h"
00047 #include "basetrace.h"
00048 #include "hdr_qs.h"
00049
00050 int hdr_tcp::offset_;
00051
00052 static class TCPHeaderClass : public PacketHeaderClass {
00053 public:
00054 TCPHeaderClass() : PacketHeaderClass("PacketHeader/TCP",
00055 sizeof(hdr_tcp)) {
00056 bind_offset(&hdr_tcp::offset_);
00057 }
00058 } class_tcphdr;
00059
00060 static class TcpClass : public TclClass {
00061 public:
00062 TcpClass() : TclClass("Agent/TCP") {}
00063 TclObject* create(int , const char*const*) {
00064 return (new TcpAgent());
00065 }
00066 } class_tcp;
00067
00068 TcpAgent::TcpAgent()
00069 : Agent(PT_TCP),
00070 t_seqno_(0), t_rtt_(0), t_srtt_(0), t_rttvar_(0),
00071 t_backoff_(0), ts_peer_(0), ts_echo_(0),
00072 tss(NULL), tss_size_(100),
00073 rtx_timer_(this), delsnd_timer_(this), burstsnd_timer_(this),
00074 dupacks_(0), curseq_(0), highest_ack_(0), cwnd_(0), ssthresh_(0),
00075 maxseq_(0), count_(0), rtt_active_(0), rtt_seq_(-1), rtt_ts_(0.0),
00076 lastreset_(0.0), closed_(0), first_decrease_(1), fcnt_(0),
00077 nrexmit_(0), restart_bugfix_(1), cong_action_(0),
00078 ecn_burst_(0), ecn_backoff_(0), ect_(0),
00079 qs_requested_(0), qs_approved_(0),
00080 qs_window_(0), qs_cwnd_(0), frto_(0)
00081
00082 {
00083 #ifdef TCP_DELAY_BIND_ALL
00084 #else
00085
00086 bind("t_seqno_", &t_seqno_);
00087 bind("rtt_", &t_rtt_);
00088 bind("srtt_", &t_srtt_);
00089 bind("rttvar_", &t_rttvar_);
00090 bind("backoff_", &t_backoff_);
00091 bind("dupacks_", &dupacks_);
00092 bind("seqno_", &curseq_);
00093 bind("ack_", &highest_ack_);
00094 bind("cwnd_", &cwnd_);
00095 bind("ssthresh_", &ssthresh_);
00096 bind("maxseq_", &maxseq_);
00097 bind("ndatapack_", &ndatapack_);
00098 bind("ndatabytes_", &ndatabytes_);
00099 bind("nackpack_", &nackpack_);
00100 bind("nrexmit_", &nrexmit_);
00101 bind("nrexmitpack_", &nrexmitpack_);
00102 bind("nrexmitbytes_", &nrexmitbytes_);
00103 bind("necnresponses_", &necnresponses_);
00104 bind("ncwndcuts_", &ncwndcuts_);
00105 bind("ncwndcuts1_", &ncwndcuts1_);
00106 #endif
00107
00108 }
00109
00110 void
00111 TcpAgent::delay_bind_init_all()
00112 {
00113
00114
00115 delay_bind_init_one("window_");
00116 delay_bind_init_one("windowInit_");
00117 delay_bind_init_one("windowInitOption_");
00118
00119 delay_bind_init_one("syn_");
00120 delay_bind_init_one("windowOption_");
00121 delay_bind_init_one("windowConstant_");
00122 delay_bind_init_one("windowThresh_");
00123 delay_bind_init_one("delay_growth_");
00124 delay_bind_init_one("overhead_");
00125 delay_bind_init_one("tcpTick_");
00126 delay_bind_init_one("ecn_");
00127 delay_bind_init_one("SetCWRonRetransmit_");
00128 delay_bind_init_one("old_ecn_");
00129 delay_bind_init_one("eln_");
00130 delay_bind_init_one("eln_rxmit_thresh_");
00131 delay_bind_init_one("packetSize_");
00132 delay_bind_init_one("tcpip_base_hdr_size_");
00133 delay_bind_init_one("ts_option_size_");
00134 delay_bind_init_one("bugFix_");
00135 delay_bind_init_one("bugFix_ack_");
00136 delay_bind_init_one("bugFix_ts_");
00137 delay_bind_init_one("lessCareful_");
00138 delay_bind_init_one("slow_start_restart_");
00139 delay_bind_init_one("restart_bugfix_");
00140 delay_bind_init_one("timestamps_");
00141 delay_bind_init_one("ts_resetRTO_");
00142 delay_bind_init_one("maxburst_");
00143 delay_bind_init_one("aggressive_maxburst_");
00144 delay_bind_init_one("maxcwnd_");
00145 delay_bind_init_one("numdupacks_");
00146 delay_bind_init_one("numdupacksFrac_");
00147 delay_bind_init_one("exitFastRetrans_");
00148 delay_bind_init_one("maxrto_");
00149 delay_bind_init_one("minrto_");
00150 delay_bind_init_one("srtt_init_");
00151 delay_bind_init_one("rttvar_init_");
00152 delay_bind_init_one("rtxcur_init_");
00153 delay_bind_init_one("T_SRTT_BITS");
00154 delay_bind_init_one("T_RTTVAR_BITS");
00155 delay_bind_init_one("rttvar_exp_");
00156 delay_bind_init_one("awnd_");
00157 delay_bind_init_one("decrease_num_");
00158 delay_bind_init_one("increase_num_");
00159 delay_bind_init_one("k_parameter_");
00160 delay_bind_init_one("l_parameter_");
00161 delay_bind_init_one("trace_all_oneline_");
00162 delay_bind_init_one("nam_tracevar_");
00163
00164 delay_bind_init_one("QOption_");
00165 delay_bind_init_one("EnblRTTCtr_");
00166 delay_bind_init_one("control_increase_");
00167 delay_bind_init_one("noFastRetrans_");
00168 delay_bind_init_one("precisionReduce_");
00169 delay_bind_init_one("oldCode_");
00170 delay_bind_init_one("useHeaders_");
00171 delay_bind_init_one("low_window_");
00172 delay_bind_init_one("high_window_");
00173 delay_bind_init_one("high_p_");
00174 delay_bind_init_one("high_decrease_");
00175 delay_bind_init_one("max_ssthresh_");
00176 delay_bind_init_one("cwnd_range_");
00177 delay_bind_init_one("timerfix_");
00178 delay_bind_init_one("rfc2988_");
00179 delay_bind_init_one("singledup_");
00180 delay_bind_init_one("LimTransmitFix_");
00181 delay_bind_init_one("rate_request_");
00182 delay_bind_init_one("qs_enabled_");
00183 delay_bind_init_one("tcp_qs_recovery_");
00184 delay_bind_init_one("qs_request_mode_");
00185 delay_bind_init_one("qs_thresh_");
00186 delay_bind_init_one("qs_rtt_");
00187
00188 delay_bind_init_one("frto_enabled_");
00189 delay_bind_init_one("sfrto_enabled_");
00190 delay_bind_init_one("spurious_response_");
00191
00192 #ifdef TCP_DELAY_BIND_ALL
00193
00194 delay_bind_init_one("t_seqno_");
00195 delay_bind_init_one("rtt_");
00196 delay_bind_init_one("srtt_");
00197 delay_bind_init_one("rttvar_");
00198 delay_bind_init_one("backoff_");
00199 delay_bind_init_one("dupacks_");
00200 delay_bind_init_one("seqno_");
00201 delay_bind_init_one("ack_");
00202 delay_bind_init_one("cwnd_");
00203 delay_bind_init_one("ssthresh_");
00204 delay_bind_init_one("maxseq_");
00205 delay_bind_init_one("ndatapack_");
00206 delay_bind_init_one("ndatabytes_");
00207 delay_bind_init_one("nackpack_");
00208 delay_bind_init_one("nrexmit_");
00209 delay_bind_init_one("nrexmitpack_");
00210 delay_bind_init_one("nrexmitbytes_");
00211 delay_bind_init_one("necnresponses_");
00212 delay_bind_init_one("ncwndcuts_");
00213 delay_bind_init_one("ncwndcuts1_");
00214 #endif
00215
00216 Agent::delay_bind_init_all();
00217
00218 reset();
00219 }
00220
00221 int
00222 TcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
00223 {
00224 if (delay_bind(varName, localName, "window_", &wnd_, tracer)) return TCL_OK;
00225 if (delay_bind(varName, localName, "windowInit_", &wnd_init_, tracer)) return TCL_OK;
00226 if (delay_bind(varName, localName, "windowInitOption_", &wnd_init_option_, tracer)) return TCL_OK;
00227 if (delay_bind_bool(varName, localName, "syn_", &syn_, tracer)) return TCL_OK;
00228 if (delay_bind(varName, localName, "windowOption_", &wnd_option_ , tracer)) return TCL_OK;
00229 if (delay_bind(varName, localName, "windowConstant_", &wnd_const_, tracer)) return TCL_OK;
00230 if (delay_bind(varName, localName, "windowThresh_", &wnd_th_ , tracer)) return TCL_OK;
00231 if (delay_bind_bool(varName, localName, "delay_growth_", &delay_growth_ , tracer)) return TCL_OK;
00232 if (delay_bind(varName, localName, "overhead_", &overhead_, tracer)) return TCL_OK;
00233 if (delay_bind(varName, localName, "tcpTick_", &tcp_tick_, tracer)) return TCL_OK;
00234 if (delay_bind_bool(varName, localName, "ecn_", &ecn_, tracer)) return TCL_OK;
00235 if (delay_bind_bool(varName, localName, "SetCWRonRetransmit_", &SetCWRonRetransmit_, tracer)) return TCL_OK;
00236 if (delay_bind_bool(varName, localName, "old_ecn_", &old_ecn_ , tracer)) return TCL_OK;
00237 if (delay_bind(varName, localName, "eln_", &eln_ , tracer)) return TCL_OK;
00238 if (delay_bind(varName, localName, "eln_rxmit_thresh_", &eln_rxmit_thresh_ , tracer)) return TCL_OK;
00239 if (delay_bind(varName, localName, "packetSize_", &size_ , tracer)) return TCL_OK;
00240 if (delay_bind(varName, localName, "tcpip_base_hdr_size_", &tcpip_base_hdr_size_, tracer)) return TCL_OK;
00241 if (delay_bind(varName, localName, "ts_option_size_", &ts_option_size_, tracer)) return TCL_OK;
00242 if (delay_bind_bool(varName, localName, "bugFix_", &bug_fix_ , tracer)) return TCL_OK;
00243 if (delay_bind_bool(varName, localName, "bugFix_ack_", &bugfix_ack_, tracer)) return TCL_OK;
00244 if (delay_bind_bool(varName, localName, "bugFix_ts_", &bugfix_ts_ , tracer)) return TCL_OK;
00245 if (delay_bind_bool(varName, localName, "lessCareful_", &less_careful_ , tracer)) return TCL_OK;
00246 if (delay_bind_bool(varName, localName, "timestamps_", &ts_option_ , tracer)) return TCL_OK;
00247 if (delay_bind_bool(varName, localName, "ts_resetRTO_", &ts_resetRTO_, tracer)) return TCL_OK;
00248 if (delay_bind_bool(varName, localName, "slow_start_restart_", &slow_start_restart_ , tracer)) return TCL_OK;
00249 if (delay_bind_bool(varName, localName, "restart_bugfix_", &restart_bugfix_ , tracer)) return TCL_OK;
00250 if (delay_bind(varName, localName, "maxburst_", &maxburst_ , tracer)) return TCL_OK;
00251 if (delay_bind_bool(varName, localName, "aggressive_maxburst_", &aggressive_maxburst_ , tracer)) return TCL_OK;
00252 if (delay_bind(varName, localName, "maxcwnd_", &maxcwnd_ , tracer)) return TCL_OK;
00253 if (delay_bind(varName, localName, "numdupacks_", &numdupacks_, tracer)) return TCL_OK;
00254 if (delay_bind(varName, localName, "numdupacksFrac_", &numdupacksFrac_, tracer)) return TCL_OK;
00255 if (delay_bind_bool(varName, localName, "exitFastRetrans_", &exitFastRetrans_, tracer)) return TCL_OK;
00256 if (delay_bind(varName, localName, "maxrto_", &maxrto_ , tracer)) return TCL_OK;
00257 if (delay_bind(varName, localName, "minrto_", &minrto_ , tracer)) return TCL_OK;
00258 if (delay_bind(varName, localName, "srtt_init_", &srtt_init_ , tracer)) return TCL_OK;
00259 if (delay_bind(varName, localName, "rttvar_init_", &rttvar_init_ , tracer)) return TCL_OK;
00260 if (delay_bind(varName, localName, "rtxcur_init_", &rtxcur_init_ , tracer)) return TCL_OK;
00261 if (delay_bind(varName, localName, "T_SRTT_BITS", &T_SRTT_BITS , tracer)) return TCL_OK;
00262 if (delay_bind(varName, localName, "T_RTTVAR_BITS", &T_RTTVAR_BITS , tracer)) return TCL_OK;
00263 if (delay_bind(varName, localName, "rttvar_exp_", &rttvar_exp_ , tracer)) return TCL_OK;
00264 if (delay_bind(varName, localName, "awnd_", &awnd_ , tracer)) return TCL_OK;
00265 if (delay_bind(varName, localName, "decrease_num_", &decrease_num_, tracer)) return TCL_OK;
00266 if (delay_bind(varName, localName, "increase_num_", &increase_num_, tracer)) return TCL_OK;
00267 if (delay_bind(varName, localName, "k_parameter_", &k_parameter_, tracer)) return TCL_OK;
00268 if (delay_bind(varName, localName, "l_parameter_", &l_parameter_, tracer)) return TCL_OK;
00269
00270
00271 if (delay_bind_bool(varName, localName, "trace_all_oneline_", &trace_all_oneline_ , tracer)) return TCL_OK;
00272 if (delay_bind_bool(varName, localName, "nam_tracevar_", &nam_tracevar_ , tracer)) return TCL_OK;
00273 if (delay_bind(varName, localName, "QOption_", &QOption_ , tracer)) return TCL_OK;
00274 if (delay_bind(varName, localName, "EnblRTTCtr_", &EnblRTTCtr_ , tracer)) return TCL_OK;
00275 if (delay_bind(varName, localName, "control_increase_", &control_increase_ , tracer)) return TCL_OK;
00276 if (delay_bind_bool(varName, localName, "noFastRetrans_", &noFastRetrans_, tracer)) return TCL_OK;
00277 if (delay_bind_bool(varName, localName, "precisionReduce_", &precision_reduce_, tracer)) return TCL_OK;
00278 if (delay_bind_bool(varName, localName, "oldCode_", &oldCode_, tracer)) return TCL_OK;
00279 if (delay_bind_bool(varName, localName, "useHeaders_", &useHeaders_, tracer)) return TCL_OK;
00280 if (delay_bind(varName, localName, "low_window_", &low_window_, tracer)) return TCL_OK;
00281 if (delay_bind(varName, localName, "high_window_", &high_window_, tracer)) return TCL_OK;
00282 if (delay_bind(varName, localName, "high_p_", &high_p_, tracer)) return TCL_OK;
00283 if (delay_bind(varName, localName, "high_decrease_", &high_decrease_, tracer)) return TCL_OK;
00284 if (delay_bind(varName, localName, "max_ssthresh_", &max_ssthresh_, tracer)) return TCL_OK;
00285 if (delay_bind(varName, localName, "cwnd_range_", &cwnd_range_, tracer)) return TCL_OK;
00286 if (delay_bind_bool(varName, localName, "timerfix_", &timerfix_, tracer)) return TCL_OK;
00287 if (delay_bind_bool(varName, localName, "rfc2988_", &rfc2988_, tracer)) return TCL_OK;
00288 if (delay_bind(varName, localName, "singledup_", &singledup_ , tracer)) return TCL_OK;
00289 if (delay_bind_bool(varName, localName, "LimTransmitFix_", &LimTransmitFix_ , tracer)) return TCL_OK;
00290 if (delay_bind(varName, localName, "rate_request_", &rate_request_ , tracer)) return TCL_OK;
00291 if (delay_bind_bool(varName, localName, "qs_enabled_", &qs_enabled_ , tracer)) return TCL_OK;
00292 if (delay_bind_bool(varName, localName, "tcp_qs_recovery_", &tcp_qs_recovery_, tracer)) return TCL_OK;
00293
00294 if (delay_bind_bool(varName, localName, "frto_enabled_", &frto_enabled_, tracer)) return TCL_OK;
00295 if (delay_bind_bool(varName, localName, "sfrto_enabled_", &sfrto_enabled_, tracer)) return TCL_OK;
00296 if (delay_bind_bool(varName, localName, "spurious_response_", &spurious_response_, tracer)) return TCL_OK;
00297
00298
00299 #ifdef TCP_DELAY_BIND_ALL
00300
00301 if (delay_bind(varName, localName, "t_seqno_", &t_seqno_ , tracer)) return TCL_OK;
00302 if (delay_bind(varName, localName, "rtt_", &t_rtt_ , tracer)) return TCL_OK;
00303 if (delay_bind(varName, localName, "srtt_", &t_srtt_ , tracer)) return TCL_OK;
00304 if (delay_bind(varName, localName, "rttvar_", &t_rttvar_ , tracer)) return TCL_OK;
00305 if (delay_bind(varName, localName, "backoff_", &t_backoff_ , tracer)) return TCL_OK;
00306
00307 if (delay_bind(varName, localName, "dupacks_", &dupacks_ , tracer)) return TCL_OK;
00308 if (delay_bind(varName, localName, "seqno_", &curseq_ , tracer)) return TCL_OK;
00309 if (delay_bind(varName, localName, "ack_", &highest_ack_ , tracer)) return TCL_OK;
00310 if (delay_bind(varName, localName, "cwnd_", &cwnd_ , tracer)) return TCL_OK;
00311 if (delay_bind(varName, localName, "ssthresh_", &ssthresh_ , tracer)) return TCL_OK;
00312 if (delay_bind(varName, localName, "maxseq_", &maxseq_ , tracer)) return TCL_OK;
00313 if (delay_bind(varName, localName, "ndatapack_", &ndatapack_ , tracer)) return TCL_OK;
00314 if (delay_bind(varName, localName, "ndatabytes_", &ndatabytes_ , tracer)) return TCL_OK;
00315 if (delay_bind(varName, localName, "nackpack_", &nackpack_ , tracer)) return TCL_OK;
00316 if (delay_bind(varName, localName, "nrexmit_", &nrexmit_ , tracer)) return TCL_OK;
00317 if (delay_bind(varName, localName, "nrexmitpack_", &nrexmitpack_ , tracer)) return TCL_OK;
00318 if (delay_bind(varName, localName, "nrexmitbytes_", &nrexmitbytes_ , tracer)) return TCL_OK;
00319 if (delay_bind(varName, localName, "necnresponses_", &necnresponses_ , tracer)) return TCL_OK;
00320 if (delay_bind(varName, localName, "ncwndcuts_", &ncwndcuts_ , tracer)) return TCL_OK;
00321 if (delay_bind(varName, localName, "ncwndcuts1_", &ncwndcuts1_ , tracer)) return TCL_OK;
00322
00323 #endif
00324
00325 return Agent::delay_bind_dispatch(varName, localName, tracer);
00326 }
00327
00328 #define TCP_WRK_SIZE 512
00329
00330 void
00331 TcpAgent::traceAll() {
00332 if (!channel_)
00333 return;
00334
00335 double curtime;
00336 Scheduler& s = Scheduler::instance();
00337 char wrk[TCP_WRK_SIZE];
00338
00339 curtime = &s ? s.clock() : 0;
00340 snprintf(wrk, TCP_WRK_SIZE,
00341 "time: %-8.5f saddr: %-2d sport: %-2d daddr: %-2d dport:"
00342 " %-2d maxseq: %-4d hiack: %-4d seqno: %-4d cwnd: %-6.3f"
00343 " ssthresh: %-3d dupacks: %-2d rtt: %-6.3f srtt: %-6.3f"
00344 " rttvar: %-6.3f bkoff: %-d\n", curtime, addr(), port(),
00345 daddr(), dport(), int(maxseq_), int(highest_ack_),
00346 int(t_seqno_), double(cwnd_), int(ssthresh_),
00347 int(dupacks_), int(t_rtt_)*tcp_tick_,
00348 (int(t_srtt_) >> T_SRTT_BITS)*tcp_tick_,
00349 int(t_rttvar_)*tcp_tick_/4.0, int(t_backoff_));
00350 (void)Tcl_Write(channel_, wrk, -1);
00351 }
00352
00353
00354 void
00355 TcpAgent::traceVar(TracedVar* v)
00356 {
00357 if (!channel_)
00358 return;
00359
00360 double curtime;
00361 Scheduler& s = Scheduler::instance();
00362 char wrk[TCP_WRK_SIZE];
00363
00364 curtime = &s ? s.clock() : 0;
00365
00366
00367 if (v == &cwnd_)
00368 snprintf(wrk, TCP_WRK_SIZE,
00369 "%-8.5f %-2d %-2d %-2d %-2d %s %-6.3f\n",
00370 curtime, addr(), port(), daddr(), dport(),
00371 v->name(), double(*((TracedDouble*) v)));
00372 else if (v == &t_rtt_)
00373 snprintf(wrk, TCP_WRK_SIZE,
00374 "%-8.5f %-2d %-2d %-2d %-2d %s %-6.3f\n",
00375 curtime, addr(), port(), daddr(), dport(),
00376 v->name(), int(*((TracedInt*) v))*tcp_tick_);
00377 else if (v == &t_srtt_)
00378 snprintf(wrk, TCP_WRK_SIZE,
00379 "%-8.5f %-2d %-2d %-2d %-2d %s %-6.3f\n",
00380 curtime, addr(), port(), daddr(), dport(),
00381 v->name(),
00382 (int(*((TracedInt*) v)) >> T_SRTT_BITS)*tcp_tick_);
00383 else if (v == &t_rttvar_)
00384 snprintf(wrk, TCP_WRK_SIZE,
00385 "%-8.5f %-2d %-2d %-2d %-2d %s %-6.3f\n",
00386 curtime, addr(), port(), daddr(), dport(),
00387 v->name(),
00388 int(*((TracedInt*) v))*tcp_tick_/4.0);
00389 else
00390 snprintf(wrk, TCP_WRK_SIZE,
00391 "%-8.5f %-2d %-2d %-2d %-2d %s %d\n",
00392 curtime, addr(), port(), daddr(), dport(),
00393 v->name(), int(*((TracedInt*) v)));
00394
00395 (void)Tcl_Write(channel_, wrk, -1);
00396 }
00397
00398 void
00399 TcpAgent::trace(TracedVar* v)
00400 {
00401 if (nam_tracevar_) {
00402 Agent::trace(v);
00403 } else if (trace_all_oneline_)
00404 traceAll();
00405 else
00406 traceVar(v);
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 void
00418 TcpAgent::set_initial_window()
00419 {
00420 if (syn_ && delay_growth_)
00421 cwnd_ = 1.0;
00422 else
00423 cwnd_ = initial_window();
00424 }
00425
00426 void
00427 TcpAgent::reset_qoption()
00428 {
00429 int now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
00430
00431 T_start = now ;
00432 RTT_count = 0 ;
00433 RTT_prev = 0 ;
00434 RTT_goodcount = 1 ;
00435 F_counting = 0 ;
00436 W_timed = -1 ;
00437 F_full = 0 ;
00438 Backoffs = 0 ;
00439 }
00440
00441 void
00442 TcpAgent::reset()
00443 {
00444 rtt_init();
00445 rtt_seq_ = -1;
00446
00447 dupacks_ = 0;
00448 curseq_ = 0;
00449 set_initial_window();
00450
00451 t_seqno_ = 0;
00452 maxseq_ = -1;
00453 last_ack_ = -1;
00454 highest_ack_ = -1;
00455 ssthresh_ = int(wnd_);
00456 if (max_ssthresh_ > 0 && max_ssthresh_ < ssthresh_)
00457 ssthresh_ = max_ssthresh_;
00458 wnd_restart_ = 1.;
00459 awnd_ = wnd_init_ / 2.0;
00460 recover_ = 0;
00461 closed_ = 0;
00462 last_cwnd_action_ = 0;
00463 boot_time_ = Random::uniform(tcp_tick_);
00464 first_decrease_ = 1;
00465
00466 lastreset_ = Scheduler::instance().clock();
00467
00468
00469
00470
00471 ndatapack_ = 0;
00472 ndatabytes_ = 0;
00473 nackpack_ = 0;
00474 nrexmitbytes_ = 0;
00475 nrexmit_ = 0;
00476 nrexmitpack_ = 0;
00477 necnresponses_ = 0;
00478 ncwndcuts_ = 0;
00479 ncwndcuts1_ = 0;
00480
00481 if (control_increase_) {
00482 prev_highest_ack_ = highest_ack_ ;
00483 }
00484
00485 if (wnd_option_ == 8) {
00486
00487 hstcp_.low_p = 1.5/(low_window_*low_window_);
00488 double highLowWin = log(high_window_)-log(low_window_);
00489 double highLowP = log(high_p_) - log(hstcp_.low_p);
00490 hstcp_.dec1 =
00491 0.5 - log(low_window_) * (high_decrease_ - 0.5)/highLowWin;
00492 hstcp_.dec2 = (high_decrease_ - 0.5)/highLowWin;
00493 hstcp_.p1 =
00494 log(hstcp_.low_p) - log(low_window_) * highLowP/highLowWin;
00495 hstcp_.p2 = highLowP/highLowWin;
00496 }
00497
00498 if (QOption_) {
00499 int now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
00500 T_last = now ;
00501 T_prev = now ;
00502 W_used = 0 ;
00503 if (EnblRTTCtr_) {
00504 reset_qoption();
00505 }
00506 }
00507 }
00508
00509
00510
00511
00512 void TcpAgent::rtt_init()
00513 {
00514 t_rtt_ = 0;
00515 t_srtt_ = int(srtt_init_ / tcp_tick_) << T_SRTT_BITS;
00516 t_rttvar_ = int(rttvar_init_ / tcp_tick_) << T_RTTVAR_BITS;
00517 t_rtxcur_ = rtxcur_init_;
00518 t_backoff_ = 1;
00519 }
00520
00521 double TcpAgent::rtt_timeout()
00522 {
00523 double timeout;
00524 if (rfc2988_) {
00525
00526
00527 if (t_rtxcur_ < minrto_)
00528 timeout = minrto_ * t_backoff_;
00529 else
00530 timeout = t_rtxcur_ * t_backoff_;
00531 } else {
00532 timeout = t_rtxcur_ * t_backoff_;
00533 if (timeout < minrto_)
00534 timeout = minrto_;
00535 }
00536
00537 if (timeout > maxrto_)
00538 timeout = maxrto_;
00539
00540 if (timeout < 2.0 * tcp_tick_) {
00541 if (timeout < 0) {
00542 fprintf(stderr, "TcpAgent: negative RTO! (%f)\n",
00543 timeout);
00544 exit(1);
00545 }
00546 timeout = 2.0 * tcp_tick_;
00547 }
00548 return (timeout);
00549 }
00550
00551
00552
00553 void TcpAgent::rtt_update(double tao)
00554 {
00555 double now = Scheduler::instance().clock();
00556 if (ts_option_)
00557 t_rtt_ = int(tao /tcp_tick_ + 0.5);
00558 else {
00559 double sendtime = now - tao;
00560 sendtime += boot_time_;
00561 double tickoff = fmod(sendtime, tcp_tick_);
00562 t_rtt_ = int((tao + tickoff) / tcp_tick_);
00563 }
00564 if (t_rtt_ < 1)
00565 t_rtt_ = 1;
00566
00567
00568
00569
00570
00571
00572
00573
00574 if (t_srtt_ != 0) {
00575 register short delta;
00576 delta = t_rtt_ - (t_srtt_ >> T_SRTT_BITS);
00577 if ((t_srtt_ += delta) <= 0)
00578 t_srtt_ = 1;
00579 if (delta < 0)
00580 delta = -delta;
00581 delta -= (t_rttvar_ >> T_RTTVAR_BITS);
00582 if ((t_rttvar_ += delta) <= 0)
00583 t_rttvar_ = 1;
00584 } else {
00585 t_srtt_ = t_rtt_ << T_SRTT_BITS;
00586 t_rttvar_ = t_rtt_ << (T_RTTVAR_BITS-1);
00587 }
00588
00589
00590
00591
00592
00593 t_rtxcur_ = (((t_rttvar_ << (rttvar_exp_ + (T_SRTT_BITS - T_RTTVAR_BITS))) +
00594 t_srtt_) >> T_SRTT_BITS ) * tcp_tick_;
00595
00596 return;
00597 }
00598
00599 void TcpAgent::rtt_backoff()
00600 {
00601 if (t_backoff_ < 64)
00602 t_backoff_ <<= 1;
00603
00604 if (t_backoff_ > 8) {
00605
00606
00607
00608
00609
00610 t_rttvar_ += (t_srtt_ >> T_SRTT_BITS);
00611 t_srtt_ = 0;
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620 int TcpAgent::headersize()
00621 {
00622 int total = tcpip_base_hdr_size_;
00623 if (total < 1) {
00624 fprintf(stderr,
00625 "TcpAgent(%s): warning: tcpip hdr size is only %d bytes\n",
00626 name(), tcpip_base_hdr_size_);
00627 }
00628 if (ts_option_)
00629 total += ts_option_size_;
00630 return (total);
00631 }
00632
00633 void TcpAgent::output(int seqno, int reason)
00634 {
00635 int force_set_rtx_timer = 0;
00636 Packet* p = allocpkt();
00637 hdr_tcp *tcph = hdr_tcp::access(p);
00638 hdr_flags* hf = hdr_flags::access(p);
00639 hdr_ip *iph = hdr_ip::access(p);
00640 int databytes = hdr_cmn::access(p)->size();
00641 tcph->seqno() = seqno;
00642 tcph->ts() = Scheduler::instance().clock();
00643 int is_retransmit = (seqno < maxseq_);
00644
00645
00646 if (qs_approved_) {
00647 hf->qs() = 1;
00648 }
00649
00650
00651
00652 if (bugfix_ts_ && tss==NULL) {
00653 tss = (double*) calloc(tss_size_, sizeof(double));
00654 if (tss==NULL) exit(1);
00655 }
00656
00657 if (bugfix_ts_ && window() > tss_size_* 0.9) {
00658 double *ntss;
00659 ntss = (double*) calloc(tss_size_*2, sizeof(double));
00660 printf("resizing timestamp table\n");
00661 if (ntss == NULL) exit(1);
00662 for (int i=0; i<tss_size_; i++)
00663 ntss[(highest_ack_ + i) % (tss_size_ * 2)] =
00664 tss[(highest_ack_ + i) % tss_size_];
00665 free(tss);
00666 tss_size_ *= 2;
00667 tss = ntss;
00668 }
00669
00670 if (tss!=NULL)
00671 tss[seqno % tss_size_] = tcph->ts();
00672
00673 tcph->ts_echo() = ts_peer_;
00674 tcph->reason() = reason;
00675 tcph->last_rtt() = int(int(t_rtt_)*tcp_tick_*1000);
00676
00677 if (ecn_) {
00678 hf->ect() = 1;
00679 }
00680 if (cong_action_ && (!is_retransmit || SetCWRonRetransmit_)) {
00681 hf->cong_action() = TRUE;
00682 cong_action_ = FALSE;
00683 }
00684
00685 if (seqno == 0) {
00686 if (syn_) {
00687 databytes = 0;
00688 curseq_ += 1;
00689 hdr_cmn::access(p)->size() = tcpip_base_hdr_size_;
00690 }
00691 if (ecn_) {
00692 hf->ecnecho() = 1;
00693
00694 hf->ect() = 0;
00695 }
00696 if (qs_enabled_) {
00697 hdr_qs *qsh = hdr_qs::access(p);
00698
00699
00700 int dataout = (curseq_ - maxseq_ - 1) * (size_ + headersize()) / 1024;
00701 int qs_rr = rate_request_;
00702 if (qs_request_mode_ == 1) {
00703
00704
00705
00706 if (dataout * 1000 / qs_rtt_ < qs_rr) {
00707 qs_rr = dataout * 1000 / qs_rtt_;
00708 }
00709
00710
00711 if ((curseq_ - maxseq_ - 1) < qs_thresh_) {
00712 qs_rr = 0;
00713 }
00714 }
00715
00716 if (qs_rr > 0) {
00717
00718 qsh->flag() = QS_REQUEST;
00719 qsh->ttl() = Random::integer(256);
00720 ttl_diff_ = (iph->ttl() - qsh->ttl()) % 256;
00721 qsh->rate() = hdr_qs::Bps_to_rate(qs_rr * 1024);
00722 qs_requested_ = 1;
00723 } else {
00724 qsh->flag() = QS_DISABLE;
00725 }
00726 }
00727 }
00728 else if (useHeaders_ == true) {
00729 hdr_cmn::access(p)->size() += headersize();
00730 }
00731 hdr_cmn::access(p)->size();
00732
00733
00734 if (highest_ack_ == maxseq_)
00735 force_set_rtx_timer = 1;
00736
00737 output_helper(p);
00738
00739 ++ndatapack_;
00740 ndatabytes_ += databytes;
00741 send(p, 0);
00742 if (seqno == curseq_ && seqno > maxseq_)
00743 idle();
00744 if (seqno > maxseq_) {
00745 maxseq_ = seqno;
00746 if (!rtt_active_) {
00747 rtt_active_ = 1;
00748 if (seqno > rtt_seq_) {
00749 rtt_seq_ = seqno;
00750 rtt_ts_ = Scheduler::instance().clock();
00751 }
00752
00753 }
00754 } else {
00755 ++nrexmitpack_;
00756 nrexmitbytes_ += databytes;
00757 }
00758 if (!(rtx_timer_.status() == TIMER_PENDING) || force_set_rtx_timer)
00759
00760 set_rtx_timer();
00761 }
00762
00763
00764
00765
00766
00767
00768 void TcpAgent::sendmsg(int nbytes, const char* )
00769 {
00770 if (nbytes == -1 && curseq_ <= TCP_MAXSEQ)
00771 curseq_ = TCP_MAXSEQ;
00772 else
00773 curseq_ += (nbytes/size_ + (nbytes%size_ ? 1 : 0));
00774 send_much(0, 0, maxburst_);
00775 }
00776
00777 void TcpAgent::advanceby(int delta)
00778 {
00779 curseq_ += delta;
00780 if (delta > 0)
00781 closed_ = 0;
00782 send_much(0, 0, maxburst_);
00783 }
00784
00785
00786 int TcpAgent::command(int argc, const char*const* argv)
00787 {
00788 if (argc == 3) {
00789 if (strcmp(argv[1], "advance") == 0) {
00790 int newseq = atoi(argv[2]);
00791 if (newseq > maxseq_)
00792 advanceby(newseq - curseq_);
00793 else
00794 advanceby(maxseq_ - curseq_);
00795 return (TCL_OK);
00796 }
00797 if (strcmp(argv[1], "advanceby") == 0) {
00798 advanceby(atoi(argv[2]));
00799 return (TCL_OK);
00800 }
00801 if (strcmp(argv[1], "eventtrace") == 0) {
00802 et_ = (EventTrace *)TclObject::lookup(argv[2]);
00803 return (TCL_OK);
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 if (strcmp(argv[1], "persist") == 0) {
00830 TcpAgent *other
00831 = (TcpAgent*)TclObject::lookup(argv[2]);
00832 cwnd_ = other->cwnd_;
00833 awnd_ = other->awnd_;
00834 ssthresh_ = other->ssthresh_;
00835 t_rtt_ = other->t_rtt_;
00836 t_srtt_ = other->t_srtt_;
00837 t_rttvar_ = other->t_rttvar_;
00838 t_backoff_ = other->t_backoff_;
00839 return (TCL_OK);
00840 }
00841 }
00842 return (Agent::command(argc, argv));
00843 }
00844
00845
00846
00847
00848
00849 int TcpAgent::force_wnd(int num)
00850 {
00851 return recover_ + num - (int)highest_ack_;
00852 }
00853
00854 int TcpAgent::window()
00855 {
00856
00857
00858
00859
00860
00861
00862 if (frto_ == 2) {
00863 return (force_wnd(2) < wnd_ ?
00864 force_wnd(2) : (int)wnd_);
00865 } else {
00866 return (cwnd_ < wnd_ ? (int)cwnd_ : (int)wnd_);
00867 }
00868 }
00869
00870 double TcpAgent::windowd()
00871 {
00872 return (cwnd_ < wnd_ ? (double)cwnd_ : (double)wnd_);
00873 }
00874
00875
00876
00877
00878
00879 void TcpAgent::send_much(int force, int reason, int maxburst)
00880 {
00881 send_idle_helper();
00882 int win = window();
00883 int npackets = 0;
00884
00885 if (!force && delsnd_timer_.status() == TIMER_PENDING)
00886 return;
00887
00888 if (t_seqno_ == 0)
00889 firstsent_ = Scheduler::instance().clock();
00890
00891 if (burstsnd_timer_.status() == TIMER_PENDING)
00892 return;
00893 while (t_seqno_ <= highest_ack_ + win && t_seqno_ < curseq_) {
00894 if (overhead_ == 0 || force || qs_approved_) {
00895 output(t_seqno_, reason);
00896 npackets++;
00897 if (QOption_)
00898 process_qoption_after_send () ;
00899 t_seqno_ ++ ;
00900 if (qs_approved_ == 1) {
00901
00902 double delay = (double) t_rtt_ * tcp_tick_ / win;
00903 if (overhead_) {
00904 delsnd_timer_.resched(delay + Random::uniform(overhead_));
00905 } else {
00906 delsnd_timer_.resched(delay);
00907 }
00908 return;
00909 }
00910 } else if (!(delsnd_timer_.status() == TIMER_PENDING)) {
00911
00912
00913
00914 delsnd_timer_.resched(Random::uniform(overhead_));
00915 return;
00916 }
00917 win = window();
00918 if (maxburst && npackets == maxburst)
00919 break;
00920 }
00921
00922 send_helper(maxburst);
00923 }
00924
00925
00926
00927
00928
00929
00930
00931 void TcpAgent::reset_rtx_timer(int mild, int backoff)
00932 {
00933 if (backoff)
00934 rtt_backoff();
00935 set_rtx_timer();
00936 if (!mild)
00937 t_seqno_ = highest_ack_ + 1;
00938 rtt_active_ = 0;
00939 }
00940
00941
00942
00943
00944
00945 void TcpAgent::set_rtx_timer()
00946 {
00947 rtx_timer_.resched(rtt_timeout());
00948 }
00949
00950
00951
00952
00953
00954
00955
00956 void TcpAgent::newtimer(Packet* pkt)
00957 {
00958 hdr_tcp *tcph = hdr_tcp::access(pkt);
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969 if (t_seqno_ > tcph->seqno() || tcph->seqno() < maxseq_ || cwnd_ < 1)
00970 set_rtx_timer();
00971 else
00972 cancel_rtx_timer();
00973 }
00974
00975
00976
00977
00978 double TcpAgent::linear(double x, double x_1, double y_1, double x_2, double y_2)
00979 {
00980
00981
00982 double y = y_1 + ((y_2 - y_1) * ((x - x_1)/(x_2-x_1)));
00983 return y;
00984 }
00985
00986
00987
00988
00989
00990 double TcpAgent::limited_slow_start(double cwnd, double max_ssthresh, double increment)
00991 {
00992 int round = int(cwnd / (double(max_ssthresh)/2.0));
00993 double increment1 = 1.0/(double(round));
00994 if (increment < increment1)
00995 increment = increment1;
00996 return increment;
00997 }
00998
00999
01000
01001
01002 int TcpAgent::numdupacks(double cwnd)
01003 {
01004 int cwndfraction = (int) cwnd/numdupacksFrac_;
01005 if (numdupacks_ > cwndfraction) {
01006 return numdupacks_;
01007 } else {
01008 return cwndfraction;
01009 }
01010 }
01011
01012
01013
01014
01015 double TcpAgent::decrease_param()
01016 {
01017 double decrease;
01018
01019
01020
01021 decrease = hstcp_.dec1 + log(cwnd_) * hstcp_.dec2;
01022 return decrease;
01023 }
01024
01025
01026
01027
01028 double TcpAgent::increase_param()
01029 {
01030 double increase, decrease, p, answer;
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 if (cwnd_ <= low_window_) {
01045 answer = 1 / cwnd_;
01046 return answer;
01047 } else if (cwnd_ >= hstcp_.cwnd_last_ &&
01048 cwnd_ < hstcp_.cwnd_last_ + cwnd_range_) {
01049
01050
01051 answer = hstcp_.increase_last_ / cwnd_;
01052 return answer;
01053 } else {
01054
01055
01056
01057 p = exp(hstcp_.p1 + log(cwnd_) * hstcp_.p2);
01058 decrease = decrease_param();
01059
01060
01061
01062 increase = cwnd_ * cwnd_ * p /(1/decrease - 0.5);
01063
01064
01065
01066 answer = increase / cwnd_;
01067 hstcp_.cwnd_last_ = cwnd_;
01068 hstcp_.increase_last_ = increase;
01069 return answer;
01070 }
01071 }
01072
01073
01074
01075
01076 void TcpAgent::opencwnd()
01077 {
01078 double increment;
01079 if (cwnd_ < ssthresh_) {
01080
01081 cwnd_ += 1;
01082 } else {
01083
01084 double f;
01085 switch (wnd_option_) {
01086 case 0:
01087 if (++count_ >= cwnd_) {
01088 count_ = 0;
01089 ++cwnd_;
01090 }
01091 break;
01092
01093 case 1:
01094
01095 increment = increase_num_ / cwnd_;
01096 if ((last_cwnd_action_ == 0 ||
01097 last_cwnd_action_ == CWND_ACTION_TIMEOUT)
01098 && max_ssthresh_ > 0) {
01099 increment = limited_slow_start(cwnd_,
01100 max_ssthresh_, increment);
01101 }
01102 cwnd_ += increment;
01103 break;
01104
01105 case 2:
01106
01107
01108
01109
01110
01111
01112
01113 f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;
01114 f *= f;
01115 f *= wnd_const_;
01116
01117 f += fcnt_;
01118 if (f > cwnd_) {
01119 fcnt_ = 0;
01120 ++cwnd_;
01121 } else
01122 fcnt_ = f;
01123 break;
01124
01125 case 3:
01126
01127
01128
01129 f = awnd_;
01130 f *= f;
01131 f *= wnd_const_;
01132 f += fcnt_;
01133 if (f > cwnd_) {
01134 fcnt_ = 0;
01135 ++cwnd_;
01136 } else
01137 fcnt_ = f;
01138 break;
01139
01140 case 4:
01141
01142
01143
01144 f = awnd_;
01145 f *= wnd_const_;
01146 f += fcnt_;
01147 if (f > cwnd_) {
01148 fcnt_ = 0;
01149 ++cwnd_;
01150 } else
01151 fcnt_ = f;
01152 break;
01153 case 5:
01154
01155
01156
01157
01158 f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;
01159 f *= wnd_const_;
01160 f += fcnt_;
01161 if (f > cwnd_) {
01162 fcnt_ = 0;
01163 ++cwnd_;
01164 } else
01165 fcnt_ = f;
01166 break;
01167 case 6:
01168
01169 cwnd_ += increase_num_ / (cwnd_*pow(cwnd_,k_parameter_));
01170 break;
01171 case 8:
01172
01173 increment = increase_param();
01174 if ((last_cwnd_action_ == 0 ||
01175 last_cwnd_action_ == CWND_ACTION_TIMEOUT)
01176 && max_ssthresh_ > 0) {
01177 increment = limited_slow_start(cwnd_,
01178 max_ssthresh_, increment);
01179 }
01180 cwnd_ += increment;
01181 break;
01182 default:
01183 #ifdef notdef
01184
01185 error("illegal window option %d", wnd_option_);
01186 #endif
01187 abort();
01188 }
01189 }
01190
01191 if (maxcwnd_ && (int(cwnd_) > maxcwnd_))
01192 cwnd_ = maxcwnd_;
01193
01194 return;
01195 }
01196
01197 void
01198 TcpAgent::slowdown(int how)
01199 {
01200 double decrease;
01201 double win, halfwin, decreasewin;
01202 int slowstart = 0;
01203 ++ncwndcuts_;
01204 if (!(how & TCP_IDLE) && !(how & NO_OUTSTANDING_DATA)){
01205 ++ncwndcuts1_;
01206 }
01207
01208 if (cwnd_ < ssthresh_)
01209 slowstart = 1;
01210 if (precision_reduce_) {
01211 halfwin = windowd() / 2;
01212 if (wnd_option_ == 6) {
01213
01214 decreasewin = windowd() - (1.0-decrease_num_)*pow(windowd(),l_parameter_);
01215 } else if (wnd_option_ == 8 && (cwnd_ > low_window_)) {
01216
01217 decrease = decrease_param();
01218
01219
01220 decrease_num_ = decrease;
01221 decreasewin = windowd() - (decrease * windowd());
01222 } else {
01223 decreasewin = decrease_num_ * windowd();
01224 }
01225 win = windowd();
01226 } else {
01227 int temp;
01228 temp = (int)(window() / 2);
01229 halfwin = (double) temp;
01230 if (wnd_option_ == 6) {
01231
01232 temp = (int)(window() - (1.0-decrease_num_)*pow(window(),l_parameter_));
01233 } else if ((wnd_option_ == 8) && (cwnd_ > low_window_)) {
01234
01235 decrease = decrease_param();
01236
01237
01238 decrease_num_ = decrease;
01239 temp = (int)(windowd() - (decrease * windowd()));
01240 } else {
01241 temp = (int)(decrease_num_ * window());
01242 }
01243 decreasewin = (double) temp;
01244 win = (double) window();
01245 }
01246 if (how & CLOSE_SSTHRESH_HALF)
01247
01248
01249 if (first_decrease_ == 1 || slowstart ||
01250 last_cwnd_action_ == CWND_ACTION_TIMEOUT) {
01251
01252
01253 ssthresh_ = (int) halfwin;
01254 } else {
01255 ssthresh_ = (int) decreasewin;
01256 }
01257 else if (how & THREE_QUARTER_SSTHRESH)
01258 if (ssthresh_ < 3*cwnd_/4)
01259 ssthresh_ = (int)(3*cwnd_/4);
01260 if (how & CLOSE_CWND_HALF)
01261
01262
01263 if (first_decrease_ == 1 || slowstart || decrease_num_ == 0.5) {
01264 cwnd_ = halfwin;
01265 } else cwnd_ = decreasewin;
01266 else if (how & CWND_HALF_WITH_MIN) {
01267
01268
01269
01270 cwnd_ = decreasewin;
01271 if (cwnd_ < 1)
01272 cwnd_ = 1;
01273 }
01274 else if (how & CLOSE_CWND_RESTART)
01275 cwnd_ = int(wnd_restart_);
01276 else if (how & CLOSE_CWND_INIT)
01277 cwnd_ = int(wnd_init_);
01278 else if (how & CLOSE_CWND_ONE)
01279 cwnd_ = 1;
01280 else if (how & CLOSE_CWND_HALF_WAY) {
01281
01282 cwnd_ = W_used + decrease_num_ * (win - W_used);
01283 if (cwnd_ < 1)
01284 cwnd_ = 1;
01285 }
01286 if (ssthresh_ < 2)
01287 ssthresh_ = 2;
01288 if (how & (CLOSE_CWND_HALF|CLOSE_CWND_RESTART|CLOSE_CWND_INIT|CLOSE_CWND_ONE))
01289 cong_action_ = TRUE;
01290
01291 fcnt_ = count_ = 0;
01292 if (first_decrease_ == 1)
01293 first_decrease_ = 0;
01294
01295 if (cwnd_ == 1 || slowstart)
01296
01297
01298
01299 trace_event("SLOW_START");
01300
01301
01302
01303
01304 }
01305
01306
01307
01308
01309 void TcpAgent::newack(Packet* pkt)
01310 {
01311 double now = Scheduler::instance().clock();
01312 hdr_tcp *tcph = hdr_tcp::access(pkt);
01313
01314
01315
01316
01317 if (!timerfix_) newtimer(pkt);
01318 dupacks_ = 0;
01319 last_ack_ = tcph->seqno();
01320 prev_highest_ack_ = highest_ack_ ;
01321 highest_ack_ = last_ack_;
01322
01323 if (t_seqno_ < last_ack_ + 1)
01324 t_seqno_ = last_ack_ + 1;
01325
01326
01327
01328
01329
01330
01331 hdr_flags *fh = hdr_flags::access(pkt);
01332 if (!fh->no_ts_) {
01333 if (ts_option_) {
01334 ts_echo_=tcph->ts_echo();
01335 rtt_update(now - tcph->ts_echo());
01336 if (ts_resetRTO_ && (!ect_ || !ecn_backoff_ ||
01337 !hdr_flags::access(pkt)->ecnecho())) {
01338
01339
01340
01341
01342
01343 t_backoff_ = 1;
01344 ecn_backoff_ = 0;
01345 }
01346 }
01347 if (rtt_active_ && tcph->seqno() >= rtt_seq_) {
01348 if (!ect_ || !ecn_backoff_ ||
01349 !hdr_flags::access(pkt)->ecnecho()) {
01350
01351
01352
01353
01354 t_backoff_ = 1;
01355 ecn_backoff_ = 0;
01356 }
01357 rtt_active_ = 0;
01358 if (!ts_option_)
01359 rtt_update(now - rtt_ts_);
01360 }
01361 }
01362 if (timerfix_) newtimer(pkt);
01363
01364 awnd_ *= 1.0 - wnd_th_;
01365 awnd_ += wnd_th_ * cwnd_;
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378 void TcpAgent::ecn(int seqno)
01379 {
01380 if (seqno > recover_ ||
01381 last_cwnd_action_ == CWND_ACTION_TIMEOUT) {
01382 recover_ = maxseq_;
01383 last_cwnd_action_ = CWND_ACTION_ECN;
01384 if (cwnd_ <= 1.0) {
01385 if (ecn_backoff_)
01386 rtt_backoff();
01387 else ecn_backoff_ = 1;
01388 } else ecn_backoff_ = 0;
01389 slowdown(CLOSE_CWND_HALF|CLOSE_SSTHRESH_HALF);
01390 ++necnresponses_ ;
01391
01392 }
01393 }
01394
01395
01396
01397
01398
01399 int TcpAgent::network_limited() {
01400 int win = window () ;
01401 if (t_seqno_ > (prev_highest_ack_ + win))
01402 return 1;
01403 else
01404 return 0;
01405 }
01406
01407 void TcpAgent::recv_newack_helper(Packet *pkt) {
01408
01409 newack(pkt);
01410 if (qs_window_ && highest_ack_ >= qs_window_) {
01411
01412
01413 qs_window_ = 0;
01414 }
01415 if (!ect_ || !hdr_flags::access(pkt)->ecnecho() ||
01416 (old_ecn_ && ecn_burst_)) {
01417
01418
01419
01420
01421
01422
01423 if (!control_increase_ ||
01424 (control_increase_ && (network_limited() == 1)))
01425 opencwnd();
01426 }
01427 if (ect_) {
01428 if (!hdr_flags::access(pkt)->ecnecho())
01429 ecn_backoff_ = 0;
01430 if (!ecn_burst_ && hdr_flags::access(pkt)->ecnecho())
01431 ecn_burst_ = TRUE;
01432 else if (ecn_burst_ && ! hdr_flags::access(pkt)->ecnecho())
01433 ecn_burst_ = FALSE;
01434 }
01435 if (!ect_ && hdr_flags::access(pkt)->ecnecho() &&
01436 !hdr_flags::access(pkt)->cong_action())
01437 ect_ = 1;
01438
01439 if ((highest_ack_ >= curseq_-1) && !closed_) {
01440 closed_ = 1;
01441 finish();
01442 }
01443 if (QOption_ && curseq_ == highest_ack_ +1) {
01444 cancel_rtx_timer();
01445 }
01446 if (frto_ == 1) {
01447
01448
01449
01450
01451
01452
01453 if (recover_ + 1 >= highest_ack_ + wnd_ ||
01454 recover_ + 1 >= curseq_) {
01455 frto_ = 0;
01456 } else if (highest_ack_ == recover_) {
01457
01458
01459
01460
01461 frto_ = 0;
01462 } else {
01463 t_seqno_ = recover_ + 1;
01464 frto_ = 2;
01465 }
01466 } else if (frto_ == 2) {
01467
01468
01469
01470
01471 spurious_timeout();
01472 }
01473 }
01474
01475
01476
01477
01478 double
01479 TcpAgent::initial_window()
01480 {
01481
01482
01483 if (qs_cwnd_) {
01484 return (qs_cwnd_);
01485 }
01486
01487
01488
01489 if (wnd_init_option_ == 1) {
01490 return (wnd_init_);
01491 }
01492 else if (wnd_init_option_ == 2) {
01493
01494 if (size_ <= 1095) {
01495 return (4.0);
01496 } else if (size_ < 2190) {
01497 return (3.0);
01498 } else {
01499 return (2.0);
01500 }
01501 }
01502
01503 fprintf(stderr, "Wrong number of wnd_init_option_ %d\n",
01504 wnd_init_option_);
01505 abort();
01506 return (2.0);
01507 }
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532 void
01533 TcpAgent::send_one()
01534 {
01535 if (t_seqno_ <= highest_ack_ + wnd_ && t_seqno_ < curseq_ &&
01536 t_seqno_ <= highest_ack_ + cwnd_ + dupacks_ ) {
01537 output(t_seqno_, 0);
01538 if (QOption_)
01539 process_qoption_after_send () ;
01540 t_seqno_ ++ ;
01541
01542 }
01543 return;
01544 }
01545
01546 void
01547 TcpAgent::dupack_action()
01548 {
01549 int recovered = (highest_ack_ > recover_);
01550 if (recovered || (!bug_fix_ && !ecn_)) {
01551 goto tahoe_action;
01552 }
01553
01554 if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
01555 last_cwnd_action_ = CWND_ACTION_DUPACK;
01556 slowdown(CLOSE_CWND_ONE);
01557 reset_rtx_timer(0,0);
01558 return;
01559 }
01560
01561 if (bug_fix_) {
01562
01563
01564
01565
01566
01567 return;
01568 }
01569
01570 tahoe_action:
01571 recover_ = maxseq_;
01572 if (!lossQuickStart()) {
01573
01574 trace_event("FAST_RETX");
01575 last_cwnd_action_ = CWND_ACTION_DUPACK;
01576 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_ONE);
01577 }
01578 reset_rtx_timer(0,0);
01579 return;
01580 }
01581
01582
01583
01584
01585
01586 void TcpAgent::endQuickStart()
01587 {
01588 qs_approved_ = 0;
01589 qs_cwnd_ = 0;
01590 qs_window_ = maxseq_;
01591 int new_cwnd = maxseq_ - last_ack_;
01592 if (new_cwnd > 1 && new_cwnd < cwnd_) {
01593 cwnd_ = new_cwnd;
01594 if (cwnd_ < initial_window())
01595 cwnd_ = initial_window();
01596 }
01597 }
01598
01599 void TcpAgent::processQuickStart(Packet *pkt)
01600 {
01601
01602 hdr_tcp *tcph = hdr_tcp::access(pkt);
01603 hdr_qs *qsh = hdr_qs::access(pkt);
01604 double now = Scheduler::instance().clock();
01605 int app_rate;
01606
01607
01608
01609 qs_requested_ = 0;
01610 qs_approved_ = 0;
01611 if (qsh->flag() == QS_RESPONSE && qsh->ttl() == ttl_diff_ &&
01612 qsh->rate() > 0) {
01613 app_rate = (int) (hdr_qs::rate_to_Bps(qsh->rate()) *
01614 (now - tcph->ts_echo()) / (size_ + headersize()));
01615 #ifdef QS_DEBUG
01616 printf("Quick Start approved, rate %d, window %d\n",
01617 qsh->rate(), app_rate);
01618 #endif
01619 if (app_rate > initial_window()) {
01620 qs_cwnd_ = app_rate;
01621 qs_approved_ = 1;
01622 }
01623 } else {
01624 #ifdef QS_DEBUG
01625 printf("Quick Start rejected\n");
01626 #endif
01627 }
01628
01629 }
01630
01631
01632
01633
01634
01635
01636 void TcpAgent::recv_frto_helper(Packet *pkt)
01637 {
01638 hdr_tcp *tcph = hdr_tcp::access(pkt);
01639 if (tcph->seqno() == last_ack_ && frto_ != 0) {
01640
01641
01642
01643
01644 t_seqno_ = highest_ack_ + 1;
01645 cwnd_ = frto_;
01646 frto_ = 0;
01647
01648
01649
01650 dupacks_ = -1;
01651 }
01652 }
01653
01654
01655
01656
01657
01658 void TcpAgent::spurious_timeout()
01659 {
01660 frto_ = 0;
01661
01662 switch (spurious_response_) {
01663 case 1:
01664 default:
01665
01666
01667
01668
01669 cwnd_ = t_seqno_ - prev_highest_ack_;
01670 break;
01671
01672 case 2:
01673
01674
01675
01676 cwnd_ = ssthresh_; break;
01677 case 3:
01678
01679
01680
01681 cwnd_ = 1; break;
01682 }
01683
01684
01685
01686
01687 ssthresh_ = pipe_prev_;
01688
01689
01690 recover_ = highest_ack_ - 1;
01691 }
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705 int TcpAgent::lossQuickStart()
01706 {
01707 if (qs_window_ && tcp_qs_recovery_) {
01708
01709
01710 slowdown(CLOSE_CWND_INIT);
01711
01712 qs_window_ = 0;
01713 output(last_ack_ + 1, TCP_REASON_DUPACK);
01714 return 1;
01715 }
01716 return 0;
01717 }
01718
01719
01720
01721
01722
01723
01724
01725
01726 void TcpAgent::recv(Packet *pkt, Handler*)
01727 {
01728 hdr_tcp *tcph = hdr_tcp::access(pkt);
01729 int valid_ack = 0;
01730 if (qs_approved_ == 1 && tcph->seqno() > last_ack_)
01731 endQuickStart();
01732 if (qs_requested_ == 1)
01733 processQuickStart(pkt);
01734 #ifdef notdef
01735 if (pkt->type_ != PT_ACK) {
01736 Tcl::instance().evalf("%s error \"received non-ack\"",
01737 name());
01738 Packet::free(pkt);
01739 return;
01740 }
01741 #endif
01742
01743 if (tcph->ts() < lastreset_) {
01744
01745 Packet::free(pkt);
01746 return;
01747 }
01748 ++nackpack_;
01749 ts_peer_ = tcph->ts();
01750 int ecnecho = hdr_flags::access(pkt)->ecnecho();
01751 if (ecnecho && ecn_)
01752 ecn(tcph->seqno());
01753 recv_helper(pkt);
01754 recv_frto_helper(pkt);
01755
01756 if (tcph->seqno() > last_ack_) {
01757 recv_newack_helper(pkt);
01758 if (last_ack_ == 0 && delay_growth_) {
01759 cwnd_ = initial_window();
01760 }
01761 } else if (tcph->seqno() == last_ack_) {
01762 if (hdr_flags::access(pkt)->eln_ && eln_) {
01763 tcp_eln(pkt);
01764 return;
01765 }
01766 if (++dupacks_ == numdupacks_ && !noFastRetrans_) {
01767 dupack_action();
01768 } else if (dupacks_ < numdupacks_ && singledup_ ) {
01769 send_one();
01770 }
01771 }
01772
01773 if (QOption_ && EnblRTTCtr_)
01774 process_qoption_after_ack (tcph->seqno());
01775
01776 if (tcph->seqno() >= last_ack_)
01777
01778 valid_ack = 1;
01779 Packet::free(pkt);
01780
01781
01782
01783 if (valid_ack || aggressive_maxburst_)
01784 send_much(0, 0, maxburst_);
01785 }
01786
01787
01788
01789
01790
01791
01792 void TcpAgent::timeout_nonrtx(int tno)
01793 {
01794 if (tno == TCP_TIMER_DELSND) {
01795
01796
01797
01798
01799 send_much(1, TCP_REASON_TIMEOUT, maxburst_);
01800 }
01801 }
01802
01803 void TcpAgent::timeout(int tno)
01804 {
01805
01806 if (tno == TCP_TIMER_RTX) {
01807
01808
01809 trace_event("TIMEOUT");
01810
01811 frto_ = 0;
01812
01813 pipe_prev_ = (window() > ssthresh_) ?
01814 window() : (int)ssthresh_;
01815
01816 if (cwnd_ < 1) cwnd_ = 1;
01817 if (qs_approved_ == 1) qs_approved_ = 0;
01818 if (highest_ack_ == maxseq_ && !slow_start_restart_) {
01819
01820
01821
01822
01823
01824
01825
01826 } else {
01827 recover_ = maxseq_;
01828 if (highest_ack_ == -1 && wnd_init_option_ == 2)
01829
01830
01831
01832
01833 wnd_init_option_ = 1;
01834 if (highest_ack_ == maxseq_ && restart_bugfix_)
01835
01836
01837
01838
01839 slowdown(CLOSE_CWND_ONE|NO_OUTSTANDING_DATA);
01840 else if (highest_ack_ < recover_ &&
01841 last_cwnd_action_ == CWND_ACTION_ECN) {
01842
01843
01844
01845
01846 slowdown(CLOSE_CWND_ONE);
01847 if (frto_enabled_ || sfrto_enabled_) {
01848 frto_ = 1;
01849 }
01850 }
01851 else {
01852 ++nrexmit_;
01853 last_cwnd_action_ = CWND_ACTION_TIMEOUT;
01854 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_RESTART);
01855 if (frto_enabled_ || sfrto_enabled_) {
01856 frto_ = 1;
01857 }
01858 }
01859 }
01860
01861 if (highest_ack_ == maxseq_ && restart_bugfix_) {
01862 reset_rtx_timer(0,0);
01863 }
01864 else {
01865 reset_rtx_timer(0,1);
01866 }
01867 last_cwnd_action_ = CWND_ACTION_TIMEOUT;
01868 send_much(0, TCP_REASON_TIMEOUT, maxburst_);
01869 }
01870 else {
01871 timeout_nonrtx(tno);
01872 }
01873 }
01874
01875
01876
01877
01878
01879
01880 void TcpAgent::tcp_eln(Packet *pkt)
01881 {
01882
01883 hdr_tcp *tcph = hdr_tcp::access(pkt);
01884 int ack = tcph->seqno();
01885
01886 if (++dupacks_ == eln_rxmit_thresh_ && ack > eln_last_rxmit_) {
01887
01888 output(last_ack_ + 1, TCP_REASON_DUPACK);
01889 eln_last_rxmit_ = last_ack_+1;
01890 } else
01891 send_much(0, 0, maxburst_);
01892
01893 Packet::free(pkt);
01894 return;
01895 }
01896
01897
01898
01899
01900
01901 void TcpAgent::finish()
01902 {
01903 Tcl::instance().evalf("%s done", this->name());
01904 }
01905
01906 void RtxTimer::expire(Event*)
01907 {
01908 a_->timeout(TCP_TIMER_RTX);
01909 }
01910
01911 void DelSndTimer::expire(Event*)
01912 {
01913 a_->timeout(TCP_TIMER_DELSND);
01914 }
01915
01916 void BurstSndTimer::expire(Event*)
01917 {
01918 a_->timeout(TCP_TIMER_BURSTSND);
01919 }
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 void TcpAgent::quench(int how)
01936 {
01937 if (highest_ack_ >= recover_) {
01938 recover_ = maxseq_;
01939 last_cwnd_action_ = CWND_ACTION_ECN;
01940 closecwnd(how);
01941 }
01942 }
01943
01944
01945
01946
01947 void TcpAgent::closecwnd(int how)
01948 {
01949 static int first_time = 1;
01950 if (first_time == 1) {
01951 fprintf(stderr, "the TcpAgent::closecwnd() function is now deprecated, please use the function slowdown() instead\n");
01952 }
01953 switch (how) {
01954 case 0:
01955
01956 ssthresh_ = int( window() / 2 );
01957 if (ssthresh_ < 2)
01958 ssthresh_ = 2;
01959 cwnd_ = int(wnd_restart_);
01960 break;
01961
01962 case 1:
01963
01964
01965 cwnd_ = decrease_num_ * window();
01966 ssthresh_ = int(cwnd_);
01967 if (ssthresh_ < 2)
01968 ssthresh_ = 2;
01969 break;
01970
01971 case 2:
01972
01973
01974 cwnd_ = wnd_init_;
01975 break;
01976
01977 case 3:
01978
01979 cwnd_ = int(wnd_init_);
01980 break;
01981 case 4:
01982
01983 ssthresh_ = int( window() / 2 );
01984 if (ssthresh_ < 2)
01985 ssthresh_ = 2;
01986 cwnd_ = 1;
01987 break;
01988
01989 default:
01990 abort();
01991 }
01992 fcnt_ = 0.;
01993 count_ = 0;
01994 }
01995
01996
01997
01998
01999
02000 void TcpAgent::process_qoption_after_send ()
02001 {
02002 int tcp_now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
02003 int rto = (int)(t_rtxcur_/tcp_tick_) ;
02004
02005
02006 if (!EnblRTTCtr_) {
02007 if (tcp_now - T_last >= rto) {
02008
02009 slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE) ;
02010 for (int i = 0 ; i < (tcp_now - T_last)/rto; i ++) {
02011 slowdown(CWND_HALF_WITH_MIN|TCP_IDLE);
02012 }
02013 T_prev = tcp_now ;
02014 W_used = 0 ;
02015 }
02016 T_last = tcp_now ;
02017 if (t_seqno_ == highest_ack_+ window()) {
02018 T_prev = tcp_now ;
02019 W_used = 0 ;
02020 }
02021 else if (t_seqno_ == curseq_-1) {
02022
02023 int tmp = t_seqno_ - highest_ack_ ;
02024 if (tmp > W_used)
02025 W_used = tmp ;
02026 if (tcp_now - T_prev >= rto) {
02027
02028 slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE);
02029 slowdown(CLOSE_CWND_HALF_WAY|TCP_IDLE);
02030 T_prev = tcp_now ;
02031 W_used = 0 ;
02032 }
02033 }
02034 } else {
02035 rtt_counting();
02036 }
02037 }
02038
02039
02040
02041
02042
02043
02044
02045 void
02046 TcpAgent::rtt_counting()
02047 {
02048 int tcp_now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
02049 int rtt = (int(t_srtt_) >> T_SRTT_BITS) ;
02050
02051 if (rtt < 1)
02052 rtt = 1 ;
02053 if (tcp_now - T_last >= 2*rtt) {
02054
02055 int RTTs ;
02056 RTTs = (tcp_now -T_last)*RTT_goodcount/(rtt*2) ;
02057 RTTs = RTTs - Backoffs ;
02058 Backoffs = 0 ;
02059 if (RTTs > 0) {
02060 slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE) ;
02061 for (int i = 0 ; i < RTTs ; i ++) {
02062 slowdown(CWND_HALF_WITH_MIN|TCP_IDLE);
02063 RTT_prev = RTT_count ;
02064 W_used = 0 ;
02065 }
02066 }
02067 }
02068 T_last = tcp_now ;
02069 if (tcp_now - T_start >= 2*rtt) {
02070 if ((RTT_count > RTT_goodcount) || (F_full == 1)) {
02071 RTT_goodcount = RTT_count ;
02072 if (RTT_goodcount < 1) RTT_goodcount = 1 ;
02073 }
02074 RTT_prev = RTT_prev - RTT_count ;
02075 RTT_count = 0 ;
02076 T_start = tcp_now ;
02077 F_full = 0;
02078 }
02079 if (t_seqno_ == highest_ack_ + window()) {
02080 W_used = 0 ;
02081 F_full = 1 ;
02082 RTT_prev = RTT_count ;
02083 }
02084 else if (t_seqno_ == curseq_-1) {
02085
02086 int tmp = t_seqno_ - highest_ack_ ;
02087 if (tmp > W_used)
02088 W_used = tmp ;
02089 if (RTT_count - RTT_prev >= 2) {
02090
02091 slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE) ;
02092 slowdown(CLOSE_CWND_HALF_WAY|TCP_IDLE);
02093 RTT_prev = RTT_count ;
02094 Backoffs ++ ;
02095 W_used = 0;
02096 }
02097 }
02098 if (F_counting == 0) {
02099 W_timed = t_seqno_ ;
02100 F_counting = 1 ;
02101 }
02102 }
02103
02104 void TcpAgent::process_qoption_after_ack (int seqno)
02105 {
02106 if (F_counting == 1) {
02107 if (seqno >= W_timed) {
02108 RTT_count ++ ;
02109 F_counting = 0 ;
02110 }
02111 else {
02112 if (dupacks_ == numdupacks_)
02113 RTT_count ++ ;
02114 }
02115 }
02116 }
02117
02118 void TcpAgent::trace_event(char *eventtype)
02119 {
02120 if (et_ == NULL) return;
02121 int seqno = t_seqno_;
02122 char *wrk = et_->buffer();
02123 char *nwrk = et_->nbuffer();
02124 if (wrk != 0)
02125 sprintf(wrk,
02126 "E "TIME_FORMAT" %d %d TCP %s %d %d %d",
02127 et_->round(Scheduler::instance().clock()),
02128 addr(),
02129 daddr(),
02130 eventtype,
02131 fid_,
02132 seqno,
02133 int(cwnd_)
02134 );
02135
02136 if (nwrk != 0)
02137 sprintf(nwrk,
02138 "E -t "TIME_FORMAT" -o TCP -e %s -s %d.%d -d %d.%d",
02139 et_->round(Scheduler::instance().clock()),
02140 eventtype,
02141 addr(),
02142 port(),
02143 daddr(),
02144 dport()
02145 );
02146 et_->trace();
02147 }