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
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 #ifndef lint
00114 static const char rcsid[] =
00115 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-full.cc,v 1.113 2002/07/24 04:34:18 tomh Exp $ (LBL)";
00116 #endif
00117
00118 #include "ip.h"
00119 #include "tcp-full.h"
00120 #include "flags.h"
00121 #include "random.h"
00122 #include "template.h"
00123
00124 #ifndef TRUE
00125 #define TRUE 1
00126 #endif
00127
00128 #ifndef FALSE
00129 #define FALSE 0
00130 #endif
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 static class FullTcpClass : public TclClass {
00142 public:
00143 FullTcpClass() : TclClass("Agent/TCP/FullTcp") {}
00144 TclObject* create(int, const char*const*) {
00145 return (new FullTcpAgent());
00146 }
00147 } class_full;
00148
00149 static class TahoeFullTcpClass : public TclClass {
00150 public:
00151 TahoeFullTcpClass() : TclClass("Agent/TCP/FullTcp/Tahoe") {}
00152 TclObject* create(int, const char*const*) {
00153
00154 return (new TahoeFullTcpAgent());
00155 }
00156 } class_tahoe_full;
00157
00158 static class NewRenoFullTcpClass : public TclClass {
00159 public:
00160 NewRenoFullTcpClass() : TclClass("Agent/TCP/FullTcp/Newreno") {}
00161 TclObject* create(int, const char*const*) {
00162
00163 return (new NewRenoFullTcpAgent());
00164 }
00165 } class_newreno_full;
00166
00167 static class SackFullTcpClass : public TclClass {
00168 public:
00169 SackFullTcpClass() : TclClass("Agent/TCP/FullTcp/Sack") {}
00170 TclObject* create(int, const char*const*) {
00171
00172
00173 return (new SackFullTcpAgent());
00174 }
00175 } class_sack_full;
00176
00177
00178
00179
00180
00181 void
00182 FullTcpAgent::delay_bind_init_all()
00183 {
00184 delay_bind_init_one("segsperack_");
00185 delay_bind_init_one("segsize_");
00186 delay_bind_init_one("tcprexmtthresh_");
00187 delay_bind_init_one("iss_");
00188 delay_bind_init_one("nodelay_");
00189 delay_bind_init_one("data_on_syn_");
00190 delay_bind_init_one("dupseg_fix_");
00191 delay_bind_init_one("dupack_reset_");
00192 delay_bind_init_one("close_on_empty_");
00193 delay_bind_init_one("signal_on_empty_");
00194 delay_bind_init_one("interval_");
00195 delay_bind_init_one("ts_option_size_");
00196 delay_bind_init_one("reno_fastrecov_");
00197 delay_bind_init_one("pipectrl_");
00198 delay_bind_init_one("open_cwnd_on_pack_");
00199 delay_bind_init_one("halfclose_");
00200 delay_bind_init_one("nopredict_");
00201 delay_bind_init_one("spa_thresh_");
00202
00203 TcpAgent::delay_bind_init_all();
00204
00205 reset();
00206 }
00207
00208 int
00209 FullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
00210 {
00211 if (delay_bind(varName, localName, "segsperack_", &segs_per_ack_, tracer)) return TCL_OK;
00212 if (delay_bind(varName, localName, "segsize_", &maxseg_, tracer)) return TCL_OK;
00213 if (delay_bind(varName, localName, "tcprexmtthresh_", &tcprexmtthresh_, tracer)) return TCL_OK;
00214 if (delay_bind(varName, localName, "iss_", &iss_, tracer)) return TCL_OK;
00215 if (delay_bind(varName, localName, "spa_thresh_", &spa_thresh_, tracer)) return TCL_OK;
00216 if (delay_bind_bool(varName, localName, "nodelay_", &nodelay_, tracer)) return TCL_OK;
00217 if (delay_bind_bool(varName, localName, "data_on_syn_", &data_on_syn_, tracer)) return TCL_OK;
00218 if (delay_bind_bool(varName, localName, "dupseg_fix_", &dupseg_fix_, tracer)) return TCL_OK;
00219 if (delay_bind_bool(varName, localName, "dupack_reset_", &dupack_reset_, tracer)) return TCL_OK;
00220 if (delay_bind_bool(varName, localName, "close_on_empty_", &close_on_empty_, tracer)) return TCL_OK;
00221 if (delay_bind_bool(varName, localName, "signal_on_empty_", &signal_on_empty_, tracer)) return TCL_OK;
00222 if (delay_bind_time(varName, localName, "interval_", &delack_interval_, tracer)) return TCL_OK;
00223 if (delay_bind(varName, localName, "ts_option_size_", &ts_option_size_, tracer)) return TCL_OK;
00224 if (delay_bind_bool(varName, localName, "reno_fastrecov_", &reno_fastrecov_, tracer)) return TCL_OK;
00225 if (delay_bind_bool(varName, localName, "pipectrl_", &pipectrl_, tracer)) return TCL_OK;
00226 if (delay_bind_bool(varName, localName, "open_cwnd_on_pack_", &open_cwnd_on_pack_, tracer)) return TCL_OK;
00227 if (delay_bind_bool(varName, localName, "halfclose_", &halfclose_, tracer)) return TCL_OK;
00228 if (delay_bind_bool(varName, localName, "nopredict_", &nopredict_, tracer)) return TCL_OK;
00229
00230 return TcpAgent::delay_bind_dispatch(varName, localName, tracer);
00231 }
00232
00233 void
00234 SackFullTcpAgent::delay_bind_init_all()
00235 {
00236 delay_bind_init_one("clear_on_timeout_");
00237 delay_bind_init_one("sack_rtx_cthresh_");
00238 delay_bind_init_one("sack_rtx_bthresh_");
00239 delay_bind_init_one("sack_block_size_");
00240 delay_bind_init_one("sack_option_size_");
00241 delay_bind_init_one("max_sack_blocks_");
00242 delay_bind_init_one("sack_rtx_threshmode_");
00243 FullTcpAgent::delay_bind_init_all();
00244 }
00245
00246 int
00247 SackFullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
00248 {
00249 if (delay_bind_bool(varName, localName, "clear_on_timeout_", &clear_on_timeout_, tracer)) return TCL_OK;
00250 if (delay_bind(varName, localName, "sack_rtx_cthresh_", &sack_rtx_cthresh_, tracer)) return TCL_OK;
00251 if (delay_bind(varName, localName, "sack_rtx_bthresh_", &sack_rtx_bthresh_, tracer)) return TCL_OK;
00252 if (delay_bind(varName, localName, "sack_rtx_threshmode_", &sack_rtx_threshmode_, tracer)) return TCL_OK;
00253 if (delay_bind(varName, localName, "sack_block_size_", &sack_block_size_, tracer)) return TCL_OK;
00254 if (delay_bind(varName, localName, "sack_option_size_", &sack_option_size_, tracer)) return TCL_OK;
00255 if (delay_bind(varName, localName, "max_sack_blocks_", &max_sack_blocks_, tracer)) return TCL_OK;
00256 return FullTcpAgent::delay_bind_dispatch(varName, localName, tracer);
00257 }
00258
00259 int
00260 FullTcpAgent::command(int argc, const char*const* argv)
00261 {
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 if (argc == 2) {
00274 if (strcmp(argv[1], "listen") == 0) {
00275
00276 listen();
00277 return (TCL_OK);
00278 }
00279 if (strcmp(argv[1], "close") == 0) {
00280 usrclosed();
00281 return (TCL_OK);
00282 }
00283 }
00284 if (argc == 3) {
00285 if (strcmp(argv[1], "advance") == 0) {
00286 advanceby(atoi(argv[2]));
00287 return (TCL_OK);
00288 }
00289 if (strcmp(argv[1], "advanceby") == 0) {
00290 advanceby(atoi(argv[2]));
00291 return (TCL_OK);
00292 }
00293 if (strcmp(argv[1], "advance-bytes") == 0) {
00294 advance_bytes(atoi(argv[2]));
00295 return (TCL_OK);
00296 }
00297 }
00298 if (argc == 4) {
00299 if (strcmp(argv[1], "sendmsg") == 0) {
00300 sendmsg(atoi(argv[2]), argv[3]);
00301 return (TCL_OK);
00302 }
00303 }
00304 return (TcpAgent::command(argc, argv));
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 void
00328 FullTcpAgent::advanceby(int np)
00329 {
00330
00331
00332
00333
00334
00335 if (np >= 0x10000000)
00336 np /= maxseg_;
00337
00338 advance_bytes(np * maxseg_);
00339 return;
00340 }
00341
00342
00343
00344
00345
00346 void
00347 FullTcpAgent::advance_bytes(int nb)
00348 {
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 switch (state_) {
00359
00360 case TCPS_CLOSED:
00361 case TCPS_LISTEN:
00362 reset();
00363 curseq_ = iss_ + nb;
00364 connect();
00365 break;
00366
00367 case TCPS_ESTABLISHED:
00368 case TCPS_SYN_SENT:
00369 case TCPS_SYN_RECEIVED:
00370 if (curseq_ < iss_)
00371 curseq_ = iss_;
00372 curseq_ += nb;
00373 break;
00374
00375 default:
00376 fprintf(stderr,
00377 "%f: FullTcpAgent::advance(%s): cannot advance while in state %s\n",
00378 now(), name(), statestr(state_));
00379
00380 }
00381
00382 if (state_ == TCPS_ESTABLISHED)
00383 send_much(0, REASON_NORMAL, maxburst_);
00384
00385 return;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 void
00398 FullTcpAgent::sendmsg(int nbytes, const char *flags)
00399 {
00400 if (flags && strcmp(flags, "MSG_EOF") == 0)
00401 close_on_empty_ = TRUE;
00402 if (flags && strcmp(flags, "DAT_EOF") == 0)
00403 signal_on_empty_ = TRUE;
00404
00405 if (nbytes == -1) {
00406 infinite_send_ = TRUE;
00407 advance_bytes(0);
00408 } else
00409 advance_bytes(nbytes);
00410 }
00411
00412
00413
00414
00415
00416 void
00417 FullTcpAgent::connect()
00418 {
00419 newstate(TCPS_SYN_SENT);
00420 sent(iss_, foutput(iss_, REASON_NORMAL));
00421 return;
00422 }
00423
00424
00425
00426
00427
00428
00429 void
00430 FullTcpAgent::listen()
00431 {
00432 newstate(TCPS_LISTEN);
00433 type_ = PT_ACK;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442 void
00443 FullTcpAgent::bufferempty()
00444 {
00445 signal_on_empty_=FALSE;
00446 Tcl::instance().evalf("%s done_data", this->name());
00447 }
00448
00449
00450
00451
00452
00453
00454 void
00455 FullTcpAgent::usrclosed()
00456 {
00457 curseq_ = maxseq_ - 1;
00458 infinite_send_ = FALSE;
00459
00460 switch (state_) {
00461 case TCPS_CLOSED:
00462 case TCPS_LISTEN:
00463 cancel_timers();
00464 newstate(TCPS_CLOSED);
00465 finish();
00466 break;
00467 case TCPS_SYN_SENT:
00468 newstate(TCPS_CLOSED);
00469
00470 case TCPS_LAST_ACK:
00471 flags_ |= TF_NEEDFIN;
00472 send_much(1, REASON_NORMAL, maxburst_);
00473 break;
00474 case TCPS_SYN_RECEIVED:
00475 case TCPS_ESTABLISHED:
00476 newstate(TCPS_FIN_WAIT_1);
00477 flags_ |= TF_NEEDFIN;
00478 send_much(1, REASON_NORMAL, maxburst_);
00479 break;
00480 case TCPS_CLOSE_WAIT:
00481 newstate(TCPS_LAST_ACK);
00482 flags_ |= TF_NEEDFIN;
00483 send_much(1, REASON_NORMAL, maxburst_);
00484 break;
00485 case TCPS_FIN_WAIT_1:
00486 case TCPS_FIN_WAIT_2:
00487 case TCPS_CLOSING:
00488
00489 fprintf(stderr,
00490 "%f FullTcpAgent(%s): app close in bad state %s\n",
00491 now(), name(), statestr(state_));
00492 break;
00493 default:
00494 fprintf(stderr,
00495 "%f FullTcpAgent(%s): app close in unknown state %s\n",
00496 now(), name(), statestr(state_));
00497 }
00498
00499 return;
00500 }
00501
00502
00503
00504
00505
00506 void
00507 FullTcpAgent::cancel_timers()
00508 {
00509
00510
00511 TcpAgent::cancel_timers();
00512
00513 delack_timer_.force_cancel();
00514 }
00515
00516 void
00517 FullTcpAgent::newstate(int state)
00518 {
00519
00520
00521
00522 state_ = state;
00523 }
00524
00525 void
00526 FullTcpAgent::prpkt(Packet *pkt)
00527 {
00528 hdr_tcp *tcph = hdr_tcp::access(pkt);
00529 hdr_cmn *th = hdr_cmn::access(pkt);
00530
00531 hdr_ip* iph = hdr_ip::access(pkt);
00532 int datalen = th->size() - tcph->hlen();
00533
00534 fprintf(stdout, " [%d:%d.%d>%d.%d] (hlen:%d, dlen:%d, seq:%d, ack:%d, flags:0x%x (%s), salen:%d, reason:0x%x)\n",
00535 th->uid(),
00536 iph->saddr(), iph->sport(),
00537 iph->daddr(), iph->dport(),
00538 tcph->hlen(),
00539 datalen,
00540 tcph->seqno(),
00541 tcph->ackno(),
00542 tcph->flags(), flagstr(tcph->flags()),
00543 tcph->sa_length(),
00544 tcph->reason());
00545 }
00546
00547 char *
00548 FullTcpAgent::flagstr(int hflags)
00549 {
00550
00551 static char *flagstrs[28] = {
00552 "<null>", "<FIN>", "<SYN>", "<SYN,FIN>",
00553 "<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>",
00554 "<PSH>", "<PSH,FIN>", "<PSH,SYN>", "<PSH,SYN,FIN>",
00555
00556 "<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>",
00557 "<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>",
00558 "<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>",
00559 "<PSH,ACK>", "<PSH,ACK,FIN>", "<PSH,ACK,SYN>", "<PSH,ACK,SYN,FIN>",
00560 };
00561 if (hflags < 0 || (hflags > 28))
00562 return ("<invalid>");
00563 return (flagstrs[hflags]);
00564 }
00565
00566 char *
00567 FullTcpAgent::statestr(int state)
00568 {
00569 static char *statestrs[TCP_NSTATES] = {
00570 "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD",
00571 "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
00572 "LAST_ACK", "FIN_WAIT_2"
00573 };
00574 if (state < 0 || (state >= TCP_NSTATES))
00575 return ("INVALID");
00576 return (statestrs[state]);
00577 }
00578
00579 void
00580 DelAckTimer::expire(Event *) {
00581 a_->timeout(TCP_TIMER_DELACK);
00582 }
00583
00584
00585
00586
00587
00588
00589 void
00590 FullTcpAgent::reset()
00591 {
00592 cancel_timers();
00593 TcpAgent::reset();
00594 rq_.clear();
00595 rtt_init();
00596
00597 last_ack_sent_ = -1;
00598 rcv_nxt_ = -1;
00599 pipe_ = 0;
00600 rtxbytes_ = 0;
00601 flags_ = 0;
00602 t_seqno_ = iss_;
00603 maxseq_ = -1;
00604 irs_ = -1;
00605 last_send_time_ = -1.0;
00606 if (ts_option_)
00607 recent_ = recent_age_ = 0.0;
00608 else
00609 recent_ = recent_age_ = -1.0;
00610
00611 fastrecov_ = FALSE;
00612 }
00613
00614
00615
00616
00617
00618
00619
00620 void
00621 FullTcpAgent::finish()
00622 {
00623 Tcl::instance().evalf("%s done", this->name());
00624 }
00625
00626
00627
00628
00629
00630 int
00631 FullTcpAgent::headersize()
00632 {
00633 int total = tcpip_base_hdr_size_;
00634 if (total < 1) {
00635 fprintf(stderr,
00636 "%f: FullTcpAgent(%s): warning: tcpip hdr size is only %d bytes\n",
00637 now(), name(), tcpip_base_hdr_size_);
00638 }
00639
00640 if (ts_option_)
00641 total += ts_option_size_;
00642
00643 return (total);
00644 }
00645
00646
00647
00648
00649
00650
00651 int
00652 FullTcpAgent::outflags()
00653 {
00654
00655 static int tcp_outflags[TCP_NSTATES] = {
00656 TH_ACK,
00657 0,
00658 TH_SYN,
00659 TH_SYN|TH_ACK,
00660 TH_ACK,
00661 TH_ACK,
00662 TH_FIN|TH_ACK,
00663 TH_FIN|TH_ACK,
00664 TH_FIN|TH_ACK,
00665 TH_ACK,
00666
00667 };
00668
00669 if (state_ < 0 || (state_ >= TCP_NSTATES)) {
00670 fprintf(stderr, "%f FullTcpAgent(%s): invalid state %d\n",
00671 now(), name(), state_);
00672 return (0x0);
00673 }
00674
00675 return (tcp_outflags[state_]);
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 int
00687 FullTcpAgent::reass(Packet* pkt)
00688 {
00689 hdr_tcp *tcph = hdr_tcp::access(pkt);
00690 hdr_cmn *th = hdr_cmn::access(pkt);
00691
00692 int start = tcph->seqno();
00693 int end = start + th->size() - tcph->hlen();
00694 int tiflags = tcph->flags();
00695 int fillshole = (start == rcv_nxt_);
00696 int flags;
00697
00698
00699
00700
00701 if (start == end && (tiflags & TH_FIN) == 0) {
00702 fprintf(stderr, "%f: FullTcpAgent(%s)::reass() -- bad condition - adding non-FIN zero-len seg\n",
00703 now(), name());
00704 abort();
00705 }
00706
00707 flags = rq_.add(start, end, tiflags, 0);
00708
00709
00710
00711
00712
00713
00714
00715 if (TCPS_HAVERCVDSYN(state_) == 0 || !fillshole) {
00716 return (0x00);
00717 }
00718
00719
00720
00721 if (state_ == TCPS_SYN_RECEIVED && (end > start))
00722 return (0x00);
00723
00724
00725
00726
00727 flags |= rq_.cleartonxt();
00728
00729 return (flags);
00730 }
00731
00732
00733
00734
00735
00736 int
00737 FullTcpAgent::rcvseqinit(int seq, int dlen)
00738 {
00739 return (seq + dlen + 1);
00740 }
00741
00742
00743
00744
00745 int
00746 FullTcpAgent::build_options(hdr_tcp* tcph)
00747 {
00748 int total = 0;
00749 if (ts_option_) {
00750 tcph->ts() = now();
00751 tcph->ts_echo() = recent_;
00752 total += ts_option_size_;
00753 } else {
00754 tcph->ts() = tcph->ts_echo() = -1.0;
00755 }
00756 return (total);
00757 }
00758
00759
00760
00761
00762
00763 int
00764 FullTcpAgent::pack(Packet *pkt)
00765 {
00766 hdr_tcp *tcph = hdr_tcp::access(pkt);
00767 return (tcph->ackno() >= highest_ack_ &&
00768 tcph->ackno() < recover_);
00769 }
00770
00771
00772
00773
00774
00775 void
00776 FullTcpAgent::pack_action(Packet*)
00777 {
00778 if (reno_fastrecov_ && fastrecov_ && cwnd_ > double(ssthresh_)) {
00779 cwnd_ = double(ssthresh_);
00780 }
00781 fastrecov_ = FALSE;
00782
00783 dupacks_ = 0;
00784 }
00785
00786
00787
00788
00789
00790 void
00791 FullTcpAgent::ack_action(Packet* p)
00792 {
00793 FullTcpAgent::pack_action(p);
00794 }
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 void
00809 FullTcpAgent::sendpacket(int seqno, int ackno, int pflags, int datalen, int reason)
00810 {
00811 Packet* p = allocpkt();
00812 hdr_tcp *tcph = hdr_tcp::access(p);
00813 hdr_flags *fh = hdr_flags::access(p);
00814
00815
00816
00817 tcph->seqno() = seqno;
00818 tcph->ackno() = ackno;
00819 tcph->flags() = pflags;
00820 tcph->reason() |= reason;
00821 tcph->sa_length() = 0;
00822 tcph->hlen() = tcpip_base_hdr_size_;
00823 tcph->hlen() += build_options(tcph);
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 if ( datalen > 0 && ecn_ ){
00838 fh->ect() = ect_;
00839 }
00840
00841
00842
00843 if ( pflags & TH_ECE) {
00844 fh->ecnecho() = 1;
00845 } else {
00846 fh->ecnecho() = 0;
00847 }
00848 if ( pflags & TH_CWR ) {
00849 fh->cong_action() = 1;
00850 }
00851
00852
00853
00854
00855
00856
00857 if ( datalen > 0 )
00858 fh->cwr() = cong_action_;
00859
00860
00861
00862 hdr_cmn *ch = hdr_cmn::access(p);
00863 ch->size() = datalen + tcph->hlen();
00864
00865 if (datalen <= 0)
00866 ++nackpack_;
00867 else {
00868 ++ndatapack_;
00869 ndatabytes_ += datalen;
00870 last_send_time_ = now();
00871 }
00872 if (reason == REASON_TIMEOUT || reason == REASON_DUPACK || reason == REASON_SACK) {
00873 ++nrexmitpack_;
00874 nrexmitbytes_ += datalen;
00875 }
00876
00877 last_ack_sent_ = ackno;
00878
00879
00880
00881
00882
00883
00884 send(p, 0);
00885
00886 return;
00887 }
00888
00889
00890
00891
00892
00893
00894
00895 void
00896 FullTcpAgent::reset_rtx_timer(int )
00897 {
00898
00899
00900
00901 if (!(highest_ack_ == maxseq_ && restart_bugfix_)) {
00902 rtt_backoff();
00903 }
00904 set_rtx_timer();
00905 rtt_active_ = FALSE;
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 int
00923 FullTcpAgent::foutput(int seqno, int reason)
00924 {
00925
00926
00927
00928 if (maxseg_ == 0)
00929 maxseg_ = size_ - headersize();
00930 else
00931 size_ = maxseg_ + headersize();
00932
00933 int is_retransmit = (seqno < maxseq_);
00934 int quiet = (highest_ack_ == maxseq_);
00935 int pflags = outflags();
00936 int syn = (seqno == iss_);
00937 int emptying_buffer = FALSE;
00938 int buffered_bytes = (infinite_send_) ? TCP_MAXSEQ :
00939 curseq_ - highest_ack_ + 1;
00940
00941 int win = window() * maxseg_;
00942 int off = seqno - highest_ack_;
00943 int datalen;
00944
00945
00946
00947 if (highest_ack_ < 0) {
00948 if (!infinite_send_)
00949 buffered_bytes = curseq_ - iss_;;
00950 off = seqno - iss_;
00951 }
00952
00953 if (syn && !data_on_syn_)
00954 datalen = 0;
00955 else if (pipectrl_)
00956 datalen = buffered_bytes - off;
00957 else
00958 datalen = min(buffered_bytes, win) - off;
00959
00960 if ((signal_on_empty_) && (!buffered_bytes) && (!syn))
00961 bufferempty();
00962
00963
00964
00965
00966
00967
00968 if (datalen < 0) {
00969 datalen = 0;
00970 } else if (datalen > maxseg_) {
00971 datalen = maxseg_;
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981 if (slow_start_restart_ && quiet && datalen > 0) {
00982 if (idle_restart()) {
00983 slowdown(CLOSE_CWND_INIT);
00984 }
00985 }
00986
00987
00988
00989
00990
00991
00992 if (!infinite_send_ && ((seqno + datalen) > curseq_ ||
00993 (syn && datalen == 0))) {
00994 emptying_buffer = TRUE;
00995
00996
00997
00998
00999 if (!syn) {
01000 idle();
01001 if (close_on_empty_ && quiet) {
01002 flags_ |= TF_NEEDCLOSE;
01003 }
01004 }
01005 pflags |= TH_PUSH;
01006
01007
01008
01009
01010 } else {
01011
01012 pflags &= ~TH_FIN;
01013 }
01014 if (infinite_send_ && (syn && datalen == 0))
01015 pflags |= TH_PUSH;
01016
01017
01018
01019 if (datalen > 0) {
01020
01021 if (datalen == maxseg_)
01022 goto send;
01023
01024 if ((quiet || nodelay_) && emptying_buffer)
01025 goto send;
01026
01027 if (is_retransmit)
01028 goto send;
01029
01030
01031
01032 if (datalen >= ((wnd_ * maxseg_) / 2.0))
01033 goto send;
01034 }
01035
01036 if (need_send())
01037 goto send;
01038
01039
01040
01041
01042
01043
01044
01045 if ((flags_ & (TF_ACKNOW|TF_NEEDCLOSE)) ||
01046 (pflags & (TH_SYN|TH_FIN))) {
01047 goto send;
01048 }
01049
01050
01051
01052
01053 return 0;
01054
01055 send:
01056
01057
01058
01059 syn = (pflags & TH_SYN) ? 1 : 0;
01060 int fin = (pflags & TH_FIN) ? 1 : 0;
01061
01062
01063 if (ecn_ && syn && !(pflags & TH_ACK)){
01064 pflags |= TH_ECE;
01065 pflags |= TH_CWR;
01066 }
01067 if (ecn_ && syn && (pflags & TH_ACK)){
01068 pflags |= TH_ECE;
01069 pflags &= ~TH_CWR;
01070 }
01071
01072
01073 if (ecn_ && ect_ && cong_action_) pflags |= TH_CWR;
01074
01075
01076 if (ecn_ && ect_ && recent_ce_ ) pflags |= TH_ECE;
01077
01078
01079
01080
01081
01082 if (flags_ & TF_NEEDCLOSE) {
01083 flags_ &= ~TF_NEEDCLOSE;
01084 if (state_ <= TCPS_ESTABLISHED && state_ != TCPS_CLOSED)
01085 {
01086 pflags |=TH_FIN;
01087 fin = 1;
01088 newstate(TCPS_FIN_WAIT_1);
01089 }
01090 }
01091 sendpacket(seqno, rcv_nxt_, pflags, datalen, reason);
01092
01093
01094
01095
01096
01097 flags_ &= ~(TF_ACKNOW|TF_DELACK);
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109 int reliable = datalen + syn + fin;
01110 if (cong_action_ && reliable > 0)
01111 cong_action_ = FALSE;
01112
01113
01114
01115
01116 int highest = seqno + reliable;
01117 if (highest > maxseq_) {
01118 maxseq_ = highest;
01119
01120
01121
01122
01123 if (!ts_option_ && rtt_active_ == FALSE) {
01124 rtt_active_ = TRUE;
01125 rtt_seq_ = seqno;
01126 rtt_ts_ = now();
01127 }
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137 if (rtx_timer_.status() != TIMER_PENDING && reliable) {
01138 set_rtx_timer();
01139 }
01140
01141 return (reliable);
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 void
01157 FullTcpAgent::send_much(int force, int reason, int maxburst)
01158 {
01159 int npackets = 0;
01160
01161
01162
01163
01164
01165 if (!force && (delsnd_timer_.status() == TIMER_PENDING))
01166 return;
01167
01168 while (1) {
01169
01170
01171
01172
01173
01174
01175
01176 int amt;
01177 int seq = nxt_tseq();
01178 if (!force && !send_allowed(seq))
01179 break;
01180
01181 if (!force && overhead_ != 0 &&
01182 (delsnd_timer_.status() != TIMER_PENDING)) {
01183 delsnd_timer_.resched(Random::uniform(overhead_));
01184 return;
01185 }
01186 if ((amt = foutput(seq, reason)) <= 0)
01187 break;
01188 if ((outflags() & TH_FIN))
01189 --amt;
01190 sent(seq, amt);
01191 force = 0;
01192
01193 if ((outflags() & (TH_SYN|TH_FIN)) ||
01194 (maxburst && ++npackets >= maxburst))
01195 break;
01196 }
01197 return;
01198 }
01199
01200
01201
01202
01203
01204 int
01205 FullTcpAgent::send_allowed(int seq)
01206 {
01207 int win = window() * maxseg_;
01208 int topwin = curseq_;
01209
01210 if ((topwin > highest_ack_ + win) || infinite_send_)
01211 topwin = highest_ack_ + win;
01212
01213 return (seq < topwin);
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228 void
01229 FullTcpAgent::newack(Packet* pkt)
01230 {
01231 hdr_tcp *tcph = hdr_tcp::access(pkt);
01232
01233 register int ackno = tcph->ackno();
01234 int progress = (ackno > highest_ack_);
01235
01236 if (ackno == maxseq_) {
01237 cancel_rtx_timer();
01238 } else if (progress) {
01239 set_rtx_timer();
01240 }
01241
01242
01243 if (progress)
01244 highest_ack_ = ackno;
01245
01246
01247
01248
01249
01250
01251
01252
01253 if (t_seqno_ < highest_ack_)
01254 t_seqno_ = highest_ack_;
01255
01256
01257
01258
01259
01260
01261
01262 hdr_flags *fh = hdr_flags::access(pkt);
01263
01264 if (!fh->no_ts_) {
01265 if (ts_option_) {
01266 recent_age_ = now();
01267 recent_ = tcph->ts();
01268 rtt_update(now() - tcph->ts_echo());
01269 } else if (rtt_active_ && ackno > rtt_seq_) {
01270
01271
01272 rtt_active_ = FALSE;
01273 rtt_update(now() - rtt_ts_);
01274 }
01275
01276 if (!ect_ || !ecn_backoff_ ||
01277 !hdr_flags::access(pkt)->ecnecho()) {
01278
01279
01280
01281
01282
01283 t_backoff_ = 1;
01284 ecn_backoff_ = 0;
01285 }
01286 }
01287 return;
01288 }
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315 int
01316 FullTcpAgent::predict_ok(Packet* pkt)
01317 {
01318 hdr_tcp *tcph = hdr_tcp::access(pkt);
01319 hdr_flags *fh = hdr_flags::access(pkt);
01320
01321
01322
01323 int p1 = (state_ == TCPS_ESTABLISHED);
01324 int p2 = ((tcph->flags() & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK);
01325 int p3 = ((flags_ & TF_NEEDFIN) == 0);
01326 int p4 = (!ts_option_ || fh->no_ts_ || (tcph->ts() >= recent_));
01327 int p5 = (tcph->seqno() == rcv_nxt_);
01328 int p6 = (t_seqno_ == maxseq_);
01329 int p7 = (!ecn_ || fh->ecnecho() == 0);
01330 int p8 = (tcph->sa_length() == 0);
01331
01332 return (p1 && p2 && p3 && p4 && p5 && p6 && p7 && p8);
01333 }
01334
01335
01336
01337
01338
01339
01340 int
01341 FullTcpAgent::fast_retransmit(int seq)
01342 {
01343
01344 trace_event("FAST_RETX");
01345
01346 recover_ = maxseq_;
01347 last_cwnd_action_ = CWND_ACTION_DUPACK;
01348 return(foutput(seq, REASON_DUPACK));
01349 }
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365 int
01366 FullTcpAgent::need_send()
01367 {
01368 if (flags_ & TF_ACKNOW)
01369 return TRUE;
01370
01371 int spa = (spa_thresh_ > 0 && ((rcv_nxt_ - irs_) < spa_thresh_)) ?
01372 1 : segs_per_ack_;
01373
01374 return ((rcv_nxt_ - last_ack_sent_) >= (spa * maxseg_));
01375 }
01376
01377
01378
01379
01380
01381
01382
01383
01384 int
01385 FullTcpAgent::idle_restart()
01386 {
01387 if (last_send_time_ < 0.0) {
01388
01389
01390 return (0);
01391 }
01392
01393 double tao = now() - last_send_time_;
01394 if (!ts_option_) {
01395 double tickoff = fmod(last_send_time_ + boot_time_,
01396 tcp_tick_);
01397 tao = int((tao + tickoff) / tcp_tick_) * tcp_tick_;
01398 }
01399
01400 return (tao > t_rtxcur_);
01401 }
01402
01403
01404
01405
01406
01407 void
01408 FullTcpAgent::set_initial_window()
01409 {
01410 syn_ = TRUE;
01411 TcpAgent::set_initial_window();
01412 }
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433 void
01434 FullTcpAgent::recv(Packet *pkt, Handler*)
01435 {
01436 hdr_tcp *tcph = hdr_tcp::access(pkt);
01437 hdr_cmn *th = hdr_cmn::access(pkt);
01438 hdr_flags *fh = hdr_flags::access(pkt);
01439
01440 int needoutput = FALSE;
01441 int ourfinisacked = FALSE;
01442 int dupseg = FALSE;
01443 int todrop = 0;
01444
01445 last_state_ = state_;
01446
01447 int datalen = th->size() - tcph->hlen();
01448 int ackno = tcph->ackno();
01449 int tiflags = tcph->flags() ;
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460 if (state_ == TCPS_CLOSED) {
01461 fprintf(stderr, "%f: FullTcp(%s): recv'd pkt in CLOSED state: ",
01462 now(), name());
01463 prpkt(pkt);
01464 goto drop;
01465 }
01466
01467
01468
01469
01470
01471
01472 if (state_ != TCPS_LISTEN)
01473 dooptions(pkt);
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483 if (delack_interval_ > 0.0 &&
01484 (delack_timer_.status() != TIMER_PENDING)) {
01485 int last = int(now() / delack_interval_);
01486 delack_timer_.resched(delack_interval_ * (last + 1.0) - now());
01487 }
01488
01489
01490
01491
01492
01493
01494
01495 if (fh->ce() && !fh->ect()) {
01496 fprintf(stderr,
01497 "%f: FullTcpAgent::recv(%s): warning: CE bit on, but ECT false!\n",
01498 now(), name());
01499 }
01500
01501
01502
01503
01504
01505
01506 if (!nopredict_ && predict_ok(pkt)) {
01507
01508
01509
01510
01511
01512 if (ts_option_ && !fh->no_ts_ &&
01513 tcph->seqno() <= last_ack_sent_) {
01514
01515
01516
01517
01518
01519 recent_age_ = now();
01520 recent_ = tcph->ts();
01521 }
01522
01523
01524
01525
01526
01527 if (ecn_) {
01528 if (fh->ce() && fh->ect()) {
01529
01530
01531 recent_ce_ = TRUE;
01532 } else if (fh->cwr()) {
01533
01534
01535 recent_ce_ = FALSE;
01536 }
01537 }
01538
01539
01540
01541
01542
01543 if (datalen == 0) {
01544
01545
01546
01547
01548
01549
01550
01551 if (ackno > highest_ack_ && ackno < maxseq_ &&
01552 cwnd_ >= wnd_ && !fastrecov_) {
01553 newack(pkt);
01554 send_much(0, REASON_NORMAL, maxburst_);
01555 Packet::free(pkt);
01556 return;
01557 }
01558 } else if (ackno == highest_ack_ && rq_.empty()) {
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569 rcv_nxt_ += datalen;
01570 flags_ |= TF_DELACK;
01571 recvBytes(datalen);
01572
01573
01574
01575
01576 Packet::free(pkt);
01577 if (need_send())
01578 send_much(1, REASON_NORMAL, maxburst_);
01579 return;
01580 }
01581 }
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594 switch (state_) {
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607 case TCPS_LISTEN:
01608
01609 if (tiflags & TH_ACK) {
01610 fprintf(stderr,
01611 "%f: FullTcpAgent(%s): warning: recv'd ACK while in LISTEN: ",
01612 now(), name());
01613 prpkt(pkt);
01614
01615 goto dropwithreset;
01616 }
01617 if ((tiflags & TH_SYN) == 0) {
01618 fprintf(stderr,
01619 "%f: FullTcpAgent(%s): warning: recv'd NON-SYN while in LISTEN\n",
01620 now(), name());
01621 prpkt(pkt);
01622
01623 goto drop;
01624 }
01625
01626
01627
01628
01629
01630 dooptions(pkt);
01631 irs_ = tcph->seqno();
01632 t_seqno_ = iss_;
01633 rcv_nxt_ = rcvseqinit(irs_, datalen);
01634 flags_ |= TF_ACKNOW;
01635
01636
01637 if (ecn_ && fh->ecnecho() && fh->cong_action()) {
01638
01639 ect_ = TRUE;
01640 }
01641
01642
01643 if (fid_ == 0) {
01644
01645
01646
01647 hdr_ip* iph = hdr_ip::access(pkt);
01648 fid_ = iph->flowid();
01649 }
01650
01651 newstate(TCPS_SYN_RECEIVED);
01652 goto trimthenstep6;
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666 case TCPS_SYN_SENT:
01667
01668
01669 if ((tiflags & TH_ACK) &&
01670 ((ackno <= iss_) || (ackno > maxseq_))) {
01671
01672 fprintf(stderr,
01673 "%f: FullTcpAgent::recv(%s): bad ACK for our SYN: ",
01674 now(), name());
01675 prpkt(pkt);
01676 goto dropwithreset;
01677 }
01678
01679 if ((tiflags & TH_SYN) == 0) {
01680 fprintf(stderr,
01681 "%f: FullTcpAgent::recv(%s): no SYN for our SYN: ",
01682 now(), name());
01683 prpkt(pkt);
01684 goto drop;
01685 }
01686
01687
01688 #ifdef notdef
01689 cancel_rtx_timer();
01690 #endif
01691 irs_ = tcph->seqno();
01692 rcv_nxt_ = rcvseqinit(irs_, datalen);
01693
01694 if (tiflags & TH_ACK) {
01695
01696
01697
01698 if (ecn_ && fh->ecnecho() && !fh->cong_action())
01699 ect_ = TRUE;
01700 highest_ack_ = ackno;
01701 cwnd_ = initial_window();
01702
01703 #ifdef notdef
01704
01705
01706
01707
01708 if (t_rtt_) {
01709 double tao = now() - tcph->ts();
01710 rtt_update(tao);
01711 }
01712 #endif
01713
01714
01715
01716
01717
01718 if (datalen > 0) {
01719 flags_ |= TF_DELACK;
01720 } else {
01721 flags_ |= TF_ACKNOW;
01722 }
01723
01724
01725
01726
01727
01728
01729
01730
01731 if (flags_ & TF_NEEDFIN) {
01732 newstate(TCPS_FIN_WAIT_1);
01733 flags_ &= ~TF_NEEDFIN;
01734 tiflags &= ~TH_SYN;
01735 } else {
01736 newstate(TCPS_ESTABLISHED);
01737 }
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748 sendpacket(t_seqno_, rcv_nxt_, TH_ACK, 0, 0);
01749 } else {
01750
01751 if (ecn_ && fh->ecnecho() && fh->cong_action())
01752 ect_ = TRUE;
01753
01754
01755 flags_ |= TF_ACKNOW;
01756 cancel_rtx_timer();
01757 newstate(TCPS_SYN_RECEIVED);
01758
01759
01760
01761
01762
01763
01764 t_seqno_--;
01765 }
01766
01767 trimthenstep6:
01768
01769
01770
01771 tcph->seqno()++;
01772
01773 if (tiflags & TH_ACK)
01774 goto process_ACK;
01775
01776 goto step6;
01777
01778 case TCPS_LAST_ACK:
01779 case TCPS_CLOSING:
01780 break;
01781 }
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794 if (ts_option_ && !fh->no_ts_ && recent_ && tcph->ts() < recent_) {
01795 if ((now() - recent_age_) > TCP_PAWS_IDLE) {
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 recent_ = 0.0;
01812 } else {
01813 fprintf(stderr, "%f: FullTcpAgent(%s): dropped pkt due to bad ts\n",
01814 now(), name());
01815 goto dropafterack;
01816 }
01817 }
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841 todrop = rcv_nxt_ - tcph->seqno();
01842
01843 if (todrop > 0 && ((tiflags & (TH_SYN)) || datalen > 0)) {
01844
01845 if (tiflags & TH_SYN) {
01846 tiflags &= ~TH_SYN;
01847 tcph->seqno()++;
01848 th->size()--;
01849
01850 todrop--;
01851 }
01852
01853
01854
01855
01856
01857
01858 if ((todrop > datalen) ||
01859 (todrop == datalen && ((tiflags & TH_FIN) == 0))) {
01860
01861
01862
01863
01864
01865
01866
01867 tiflags &= ~TH_FIN;
01868
01869
01870
01871
01872
01873
01874 flags_ |= TF_ACKNOW;
01875 todrop = datalen;
01876 dupseg = TRUE;
01877
01878 }
01879
01880
01881
01882
01883
01884 tcph->seqno() += todrop;
01885 th->size() -= todrop;
01886
01887 datalen -= todrop;
01888
01889 }
01890
01891
01892
01893
01894
01895
01896
01897 if (ts_option_ && !fh->no_ts_ && tcph->seqno() <= last_ack_sent_) {
01898
01899
01900
01901
01902
01903 recent_age_ = now();
01904 recent_ = tcph->ts();
01905 }
01906
01907 if (tiflags & TH_SYN) {
01908 fprintf(stderr,
01909 "%f: FullTcpAgent::recv(%s) received unexpected SYN (state:%d): ",
01910 now(), name(), state_);
01911 prpkt(pkt);
01912 goto dropwithreset;
01913 }
01914
01915 if ((tiflags & TH_ACK) == 0) {
01916 fprintf(stderr, "%f: FullTcpAgent::recv(%s) got packet lacking ACK (state:%d): ",
01917 now(), name(), state_);
01918 prpkt(pkt);
01919 goto drop;
01920 }
01921
01922
01923
01924
01925
01926 switch (state_) {
01927 case TCPS_SYN_RECEIVED:
01928 if (ackno < highest_ack_ || ackno > maxseq_) {
01929
01930 fprintf(stderr,
01931 "%f: FullTcpAgent(%s): ack(%d) not in range while in SYN_RECEIVED: ",
01932 now(), name(), ackno);
01933 prpkt(pkt);
01934 goto dropwithreset;
01935 }
01936
01937
01938
01939
01940
01941 if (flags_ & TF_NEEDFIN) {
01942 newstate(TCPS_FIN_WAIT_1);
01943 flags_ &= ~TF_NEEDFIN;
01944 } else {
01945 newstate(TCPS_ESTABLISHED);
01946 }
01947 cwnd_ = initial_window();
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961 case TCPS_ESTABLISHED:
01962 case TCPS_FIN_WAIT_1:
01963 case TCPS_FIN_WAIT_2:
01964 case TCPS_CLOSE_WAIT:
01965 case TCPS_CLOSING:
01966 case TCPS_LAST_ACK:
01967
01968
01969
01970
01971
01972 if (fh->ecnecho() && (!ecn_ || !ect_)) {
01973 fprintf(stderr,
01974 "%f: FullTcp(%s): warning, recvd ecnecho but I am not ECN capable!\n",
01975 now(), name());
01976 }
01977
01978
01979
01980
01981
01982 if (ecn_) {
01983 if (fh->ce() && fh->ect())
01984 recent_ce_ = TRUE;
01985 else if (fh->cwr())
01986 recent_ce_ = FALSE;
01987 }
01988
01989
01990
01991
01992
01993 if (state_ >= TCPS_ESTABLISHED && tcph->sa_length() > 0) {
01994 process_sack(tcph);
01995 }
01996
01997
01998
01999
02000
02001
02002 if (fastrecov_ && (datalen == 0 || ackno > highest_ack_))
02003 pipe_ -= maxseg_;
02004
02005
02006
02007
02008 if (ackno <= highest_ack_) {
02009
02010 if (datalen == 0 && (!dupseg_fix_ || !dupseg)) {
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031 if ((rtx_timer_.status() != TIMER_PENDING) ||
02032 ackno < highest_ack_) {
02033
02034
02035 oldack();
02036 } else if (++dupacks_ == tcprexmtthresh_) {
02037
02038
02039
02040 dupack_action();
02041 goto drop;
02042
02043 } else if (dupacks_ > tcprexmtthresh_) {
02044
02045
02046 extra_ack();
02047
02048
02049 send_much(0, REASON_DUPACK, maxburst_);
02050 goto drop;
02051 }
02052 } else {
02053
02054
02055
02056 if (dupack_reset_) {
02057 dupacks_ = 0;
02058 fastrecov_ = FALSE;
02059 }
02060 }
02061 break;
02062 }
02063
02064
02065
02066
02067
02068
02069
02070 process_ACK:
02071
02072 if (ackno > maxseq_) {
02073
02074 fprintf(stderr,
02075 "%f: FullTcpAgent::recv(%s) too-big ACK (maxseq:%d): ",
02076 now(), name(), int(maxseq_));
02077 prpkt(pkt);
02078 goto dropafterack;
02079 }
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094 newack(pkt);
02095
02096
02097
02098
02099
02100
02101
02102
02103 int partial = pack(pkt);
02104
02105 if (partial)
02106 pack_action(pkt);
02107 else
02108 ack_action(pkt);
02109
02110
02111
02112
02113
02114
02115 if (fh->ecnecho() && !(tiflags&TH_SYN) )
02116 if (fh->ecnecho()) {
02117
02118
02119 ecn(highest_ack_);
02120
02121 if (cwnd_ < 1)
02122 set_rtx_timer();
02123 }
02124
02125 if (ackno == maxseq_) {
02126 needoutput = TRUE;
02127 }
02128
02129
02130
02131
02132
02133 if (ackno == (highest_ack_ + 1))
02134 goto step6;
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147 if ((!delay_growth_ || (rcv_nxt_ > 0)) &&
02148 last_state_ == TCPS_ESTABLISHED) {
02149 if (!partial || open_cwnd_on_pack_)
02150 if (!ect_ || !hdr_flags::access(pkt)->ecnecho())
02151 opencwnd();
02152 }
02153
02154 if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {
02155 ourfinisacked = TRUE;
02156 }
02157
02158
02159
02160
02161
02162
02163 switch (state_) {
02164
02165
02166
02167
02168
02169 case TCPS_FIN_WAIT_1:
02170 if (ourfinisacked) {
02171
02172 newstate(TCPS_FIN_WAIT_2);
02173 cancel_timers();
02174 needoutput = FALSE;
02175 }
02176 break;
02177
02178
02179
02180
02181
02182
02183
02184 case TCPS_CLOSING: ;
02185 if (ourfinisacked) {
02186 newstate(TCPS_CLOSED);
02187 cancel_timers();
02188 }
02189 break;
02190
02191
02192
02193
02194
02195
02196 case TCPS_LAST_ACK:
02197
02198 if (ourfinisacked) {
02199 newstate(TCPS_CLOSED);
02200 finish();
02201 reset();
02202 goto drop;
02203 } else {
02204
02205 fprintf(stderr,
02206 "%f: FullTcpAgent(%s)::received non-ACK (state:%d): ",
02207 now(), name(), state_);
02208 prpkt(pkt);
02209 }
02210 break;
02211
02212
02213 }
02214 }
02215
02216 step6:
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227 if ((datalen > 0 || (tiflags & TH_FIN)) &&
02228 TCPS_HAVERCVDFIN(state_) == 0) {
02229
02230
02231
02232
02233
02234
02235 if (tcph->seqno() == rcv_nxt_ && rq_.empty()) {
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246 flags_ |= TF_DELACK;
02247 rcv_nxt_ += datalen;
02248 tiflags = tcph->flags() & TH_FIN;
02249
02250
02251
02252 if (datalen)
02253 recvBytes(datalen);
02254 needoutput = need_send();
02255 } else {
02256
02257
02258
02259
02260
02261
02262
02263 int rcv_nxt_old_ = rcv_nxt_;
02264 tiflags = reass(pkt);
02265 if (rcv_nxt_ > rcv_nxt_old_) {
02266
02267
02268
02269 recvBytes(rcv_nxt_ - rcv_nxt_old_);
02270 }
02271 flags_ |= TF_ACKNOW;
02272
02273 if (tiflags & TH_PUSH) {
02274
02275
02276
02277 needoutput = need_send();
02278 }
02279 }
02280 } else {
02281
02282
02283
02284
02285
02286
02287 tiflags &= ~TH_FIN;
02288 }
02289
02290
02291
02292
02293
02294
02295 if (tiflags & TH_FIN) {
02296 if (TCPS_HAVERCVDFIN(state_) == 0) {
02297 flags_ |= TF_ACKNOW;
02298 rcv_nxt_++;
02299 }
02300 switch (state_) {
02301
02302
02303
02304
02305
02306 case TCPS_SYN_RECEIVED:
02307 case TCPS_ESTABLISHED:
02308 newstate(TCPS_CLOSE_WAIT);
02309 break;
02310
02311
02312
02313
02314
02315
02316 case TCPS_FIN_WAIT_1:
02317 newstate(TCPS_CLOSING);
02318 break;
02319
02320
02321
02322
02323
02324
02325
02326 case TCPS_FIN_WAIT_2:
02327 newstate(TCPS_CLOSED);
02328 cancel_timers();
02329 break;
02330 }
02331 }
02332
02333 if (needoutput || (flags_ & TF_ACKNOW))
02334 send_much(1, REASON_NORMAL, maxburst_);
02335 else if (curseq_ >= highest_ack_ || infinite_send_)
02336 send_much(0, REASON_NORMAL, maxburst_);
02337
02338
02339 if (!halfclose_ && state_ == TCPS_CLOSE_WAIT && highest_ack_ == maxseq_)
02340 usrclosed();
02341
02342 Packet::free(pkt);
02343
02344
02345
02346
02347 if (state_ == TCPS_CLOSED)
02348 Tcl::instance().evalf("%s done", this->name());
02349
02350 return;
02351
02352
02353
02354
02355
02356 dropafterack:
02357 flags_ |= TF_ACKNOW;
02358 send_much(1, REASON_NORMAL, maxburst_);
02359 goto drop;
02360
02361 dropwithreset:
02362
02363 if (tiflags & TH_ACK) {
02364 sendpacket(ackno, 0, 0x0, 0, REASON_NORMAL);
02365 } else {
02366 int ack = tcph->seqno() + datalen;
02367 if (tiflags & TH_SYN)
02368 ack--;
02369 sendpacket(0, ack, TH_ACK, 0, REASON_NORMAL);
02370 }
02371 drop:
02372 Packet::free(pkt);
02373 return;
02374 }
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392 void
02393 FullTcpAgent::dupack_action()
02394 {
02395
02396 int recovered = (highest_ack_ > recover_);
02397
02398 fastrecov_ = TRUE;
02399 rtxbytes_ = 0;
02400
02401 if (recovered || (!bug_fix_ && !ecn_) ||
02402
02403
02404 last_cwnd_action_ == CWND_ACTION_DUPACK) {
02405 goto full_reno_action;
02406 }
02407
02408 if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
02409 slowdown(CLOSE_CWND_HALF);
02410 cancel_rtx_timer();
02411 rtt_active_ = FALSE;
02412 (void)fast_retransmit(highest_ack_);
02413 return;
02414 }
02415
02416 if (bug_fix_) {
02417
02418
02419
02420
02421
02422 return;
02423 }
02424
02425 full_reno_action:
02426 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
02427 cancel_rtx_timer();
02428 rtt_active_ = FALSE;
02429 recover_ = maxseq_;
02430 (void)fast_retransmit(highest_ack_);
02431
02432
02433
02434 cwnd_ = double(ssthresh_) + double(dupacks_);
02435 return;
02436 }
02437
02438 void
02439 FullTcpAgent::timeout_action()
02440 {
02441 recover_ = maxseq_;
02442
02443 if (cwnd_ < 1.0) {
02444 fprintf(stderr,
02445 "%f: FullTcpAgent(%s):: resetting cwnd from %f to 1\n",
02446 now(), name(), double(cwnd_));
02447 cwnd_ = 1.0;
02448 }
02449
02450 if (last_cwnd_action_ == CWND_ACTION_ECN) {
02451 slowdown(CLOSE_CWND_ONE);
02452 } else {
02453 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_RESTART);
02454 last_cwnd_action_ = CWND_ACTION_TIMEOUT;
02455 }
02456 reset_rtx_timer(1);
02457 t_seqno_ = (highest_ack_ < 0) ? iss_ : int(highest_ack_);
02458 fastrecov_ = FALSE;
02459 dupacks_ = 0;
02460 }
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477 void
02478 FullTcpAgent::timeout(int tno)
02479 {
02480
02481 if (state_ == TCPS_CLOSED || state_ == TCPS_LISTEN) {
02482
02483 fprintf(stderr, "%f: FullTcpAgent(%s): unexpected timeout %d in state %s\n",
02484 now(), name(), tno, statestr(state_));
02485 return;
02486 }
02487
02488 switch (tno) {
02489
02490 case TCP_TIMER_RTX:
02491
02492 ++nrexmit_;
02493 timeout_action();
02494
02495 case TCP_TIMER_DELSND:
02496
02497 send_much(1, PF_TIMEOUT, maxburst_);
02498 break;
02499
02500 case TCP_TIMER_DELACK:
02501 if (flags_ & TF_DELACK) {
02502 flags_ &= ~TF_DELACK;
02503 flags_ |= TF_ACKNOW;
02504 send_much(1, REASON_NORMAL, 0);
02505 }
02506 delack_timer_.resched(delack_interval_);
02507 break;
02508 default:
02509 fprintf(stderr, "%f: FullTcpAgent(%s) Unknown Timeout type %d\n",
02510 now(), name(), tno);
02511 }
02512 return;
02513 }
02514
02515 void
02516 FullTcpAgent::dooptions(Packet* pkt)
02517 {
02518
02519
02520
02521 hdr_flags *fh = hdr_flags::access(pkt);
02522 hdr_tcp *tcph = hdr_tcp::access(pkt);
02523
02524 if (ts_option_ && !fh->no_ts_) {
02525 if (tcph->ts() < 0.0) {
02526 fprintf(stderr,
02527 "%f: FullTcpAgent(%s) warning: ts_option enabled in this TCP, but appears to be disabled in peer\n",
02528 now(), name());
02529 } else if (tcph->flags() & TH_SYN) {
02530 flags_ |= TF_RCVD_TSTMP;
02531 recent_ = tcph->ts();
02532 recent_age_ = now();
02533 }
02534 }
02535
02536 return;
02537 }
02538
02539
02540
02541
02542 void
02543 FullTcpAgent::process_sack(hdr_tcp*)
02544 {
02545 fprintf(stderr, "%f: FullTcpAgent(%s) Non-SACK capable FullTcpAgent received a SACK\n",
02546 now(), name());
02547 return;
02548 }
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579 void
02580 TahoeFullTcpAgent::dupack_action()
02581 {
02582 int recovered = (highest_ack_ > recover_);
02583
02584 fastrecov_ = TRUE;
02585 rtxbytes_ = 0;
02586
02587 if (recovered || (!bug_fix_ && !ecn_) ||
02588
02589 last_cwnd_action_ == CWND_ACTION_DUPACK) {
02590 goto full_tahoe_action;
02591 }
02592
02593 if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
02594
02595 last_cwnd_action_ = CWND_ACTION_DUPACK;
02596 slowdown(CLOSE_CWND_ONE);
02597 set_rtx_timer();
02598 rtt_active_ = FALSE;
02599 t_seqno_ = highest_ack_;
02600 return;
02601 }
02602
02603 if (bug_fix_) {
02604
02605
02606
02607
02608
02609 return;
02610 }
02611
02612 full_tahoe_action:
02613
02614 trace_event("FAST_RETX");
02615 recover_ = maxseq_;
02616 last_cwnd_action_ = CWND_ACTION_DUPACK;
02617 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_ONE);
02618 set_rtx_timer();
02619 rtt_active_ = FALSE;
02620 t_seqno_ = highest_ack_;
02621 send_much(0, REASON_NORMAL, 0);
02622 return;
02623 }
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635 NewRenoFullTcpAgent::NewRenoFullTcpAgent() : save_maxburst_(-1)
02636 {
02637 bind("recov_maxburst_", &recov_maxburst_);
02638 }
02639
02640 void
02641 NewRenoFullTcpAgent::pack_action(Packet*)
02642 {
02643 (void)fast_retransmit(highest_ack_);
02644 cwnd_ = double(ssthresh_);
02645 if (save_maxburst_ < 0) {
02646 save_maxburst_ = maxburst_;
02647 maxburst_ = recov_maxburst_;
02648 }
02649 return;
02650 }
02651
02652 void
02653 NewRenoFullTcpAgent::ack_action(Packet* p)
02654 {
02655 if (save_maxburst_ >= 0) {
02656 maxburst_ = save_maxburst_;
02657 save_maxburst_ = -1;
02658 }
02659 FullTcpAgent::ack_action(p);
02660 return;
02661 }
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674 void
02675 SackFullTcpAgent::reset()
02676 {
02677 sq_.clear();
02678 sack_min_ = h_seqno_ -1;
02679 FullTcpAgent::reset();
02680 }
02681
02682
02683 int
02684 SackFullTcpAgent::hdrsize(int nsackblocks)
02685 {
02686 int total = FullTcpAgent::headersize();
02687
02688 if (nsackblocks > 0) {
02689 total += ((nsackblocks * sack_block_size_)
02690 + sack_option_size_);
02691 }
02692 return (total);
02693 }
02694
02695 void
02696 SackFullTcpAgent::dupack_action()
02697 {
02698
02699 int recovered = (highest_ack_ > recover_);
02700
02701 fastrecov_ = TRUE;
02702 rtxbytes_ = 0;
02703 pipe_ = maxseq_ - highest_ack_ - sq_.total();
02704
02705
02706
02707
02708 if (recovered || (!bug_fix_ && !ecn_)) {
02709 goto full_sack_action;
02710 }
02711
02712 if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
02713 last_cwnd_action_ = CWND_ACTION_DUPACK;
02714 cancel_rtx_timer();
02715 rtt_active_ = FALSE;
02716 send_much(1, REASON_DUPACK, maxburst_);
02717 return;
02718 }
02719
02720 if (bug_fix_) {
02721
02722
02723
02724
02725
02726
02727
02728
02729 return;
02730 }
02731
02732 full_sack_action:
02733 trace_event("FAST_RECOVERY");
02734 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
02735 cancel_rtx_timer();
02736 rtt_active_ = FALSE;
02737
02738
02739 pipectrl_ = TRUE;
02740 recover_ = maxseq_;
02741
02742 int amt = fast_retransmit(highest_ack_);
02743 h_seqno_ = highest_ack_ + amt;
02744
02745
02746
02747
02748 send_much(0, REASON_DUPACK, maxburst_);
02749
02750 return;
02751 }
02752
02753 void
02754 SackFullTcpAgent::pack_action(Packet* p)
02755 {
02756 if (!sq_.empty() && sack_min_ < highest_ack_) {
02757 sack_min_ = highest_ack_;
02758 sq_.cleartonxt();
02759 }
02760 pipe_ -= maxseg_;
02761 if (h_seqno_ < highest_ack_)
02762 h_seqno_ = highest_ack_;
02763 }
02764
02765 void
02766 SackFullTcpAgent::ack_action(Packet* p)
02767 {
02768
02769
02770 fastrecov_ = pipectrl_ = FALSE;
02771 if (!sq_.empty() && sack_min_ < highest_ack_) {
02772 sack_min_ = highest_ack_;
02773 sq_.cleartonxt();
02774 }
02775 dupacks_ = 0;
02776 }
02777
02778
02779
02780
02781
02782 int
02783 SackFullTcpAgent::build_options(hdr_tcp* tcph)
02784 {
02785 int total = FullTcpAgent::build_options(tcph);
02786
02787 if (!rq_.empty()) {
02788 int nblk = rq_.gensack(&tcph->sa_left(0), max_sack_blocks_);
02789 tcph->sa_length() = nblk;
02790 total += (nblk * sack_block_size_) + sack_option_size_;
02791 } else {
02792 tcph->sa_length() = 0;
02793 }
02794 return (total);
02795 }
02796
02797 void
02798 SackFullTcpAgent::timeout_action()
02799 {
02800 FullTcpAgent::timeout_action();
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811 if (clear_on_timeout_) {
02812 sq_.clear();
02813 sack_min_ = highest_ack_;
02814 }
02815
02816 return;
02817 }
02818
02819 void
02820 SackFullTcpAgent::process_sack(hdr_tcp* tcph)
02821 {
02822
02823
02824
02825
02826
02827
02828 if (max_sack_blocks_ <= 0) {
02829 fprintf(stderr,
02830 "%f: FullTcpAgent(%s) warning: received SACK block but I am not SACK enabled\n",
02831 now(), name());
02832 return;
02833 }
02834
02835 int slen = tcph->sa_length(), i;
02836 for (i = 0; i < slen; ++i) {
02837 if (tcph->sa_left(i) >= tcph->sa_right(i)) {
02838 fprintf(stderr,
02839 "%f: FullTcpAgent(%s) warning: received illegal SACK block [%d,%d]\n",
02840 now(), name(), tcph->sa_left(i), tcph->sa_right(i));
02841 continue;
02842 }
02843 sq_.add(tcph->sa_left(i), tcph->sa_right(i), 0);
02844 }
02845
02846 return;
02847 }
02848
02849 int
02850 SackFullTcpAgent::send_allowed(int seq)
02851 {
02852
02853 if (!pipectrl_)
02854 return (FullTcpAgent::send_allowed(seq));
02855
02856
02857 int topawin = highest_ack_ + int(wnd_) * maxseg_;
02858 if (seq >= topawin) {
02859
02860
02861 return FALSE;
02862 }
02863
02864
02865 int cwin = int(cwnd_) * maxseg_;
02866 return (pipe_ < cwin);
02867 }
02868
02869
02870
02871
02872
02873
02874
02875
02876 int
02877 SackFullTcpAgent::nxt_tseq()
02878 {
02879
02880 int in_recovery = (highest_ack_ < recover_);
02881 int seq = h_seqno_;
02882
02883 if (!in_recovery) {
02884
02885
02886
02887
02888 return (t_seqno_);
02889 }
02890
02891 int fcnt;
02892
02893
02894
02895 int fbytes;
02896
02897
02898
02899
02900
02901
02902 while ((seq = sq_.nexthole(seq, fcnt, fbytes)) > 0) {
02903
02904
02905
02906
02907 if (sack_rtx_threshmode_ == 0 ||
02908 (sack_rtx_threshmode_ == 1 && fcnt >= sack_rtx_cthresh_) ||
02909 (sack_rtx_threshmode_ == 2 && fbytes >= sack_rtx_bthresh_) ||
02910 (sack_rtx_threshmode_ == 3 && (fcnt >= sack_rtx_cthresh_ || fbytes >= sack_rtx_bthresh_)) ||
02911 (sack_rtx_threshmode_ == 4 && (fcnt >= sack_rtx_cthresh_ && fbytes >= sack_rtx_bthresh_))) {
02912
02913
02914
02915
02916
02917
02918
02919 if (seq > h_seqno_)
02920 h_seqno_ = seq;
02921 return (seq);
02922 } else if (fcnt <= 0)
02923 break;
02924 else {
02925 seq += maxseg_;
02926 }
02927 }
02928
02929
02930
02931 return (t_seqno_);
02932 }