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