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