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 #ifndef lint
00073 static const char rcsid[] =
00074 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/baytcp/tcp-full-bay.cc,v 1.4 2001/07/19 17:57:02 haldar Exp $ (LBL)";
00075 #endif
00076
00077 #include "tclcl.h"
00078 #include "ip.h"
00079 #include "tcp-full-bay.h"
00080 #include "flags.h"
00081 #include "random.h"
00082 #include "template.h"
00083
00084 #define TRUE 1
00085 #define FALSE 0
00086
00087 static class BayFullTcpClass : public TclClass {
00088 public:
00089 BayFullTcpClass() : TclClass("Agent/TCP/BayFullTcp") {}
00090 TclObject* create(int, const char*const*) {
00091 return (new BayFullTcpAgent());
00092 }
00093 } class_bayfull;
00094
00095 static class TahoeBayFullTcpClass : public TclClass {
00096 public:
00097 TahoeBayFullTcpClass() : TclClass("Agent/TCP/BayFullTcp/Tahoe") {}
00098 TclObject* create(int, const char*const*) {
00099
00100
00101
00102 fprintf(stderr,"Tahoe, NewReno or Sack flavors are NOT available for BayTCP!! Use BayFullTcp only, which actually implements Reno.\n");
00103
00104 exit(1);
00105 }
00106 } class_tahoe_bayfull;
00107
00108 static class NewRenoBayFullTcpClass : public TclClass {
00109 public:
00110 NewRenoBayFullTcpClass() : TclClass("Agent/TCP/BayFullTcp/Newreno") {}
00111 TclObject* create(int, const char*const*) {
00112
00113
00114
00115 fprintf(stderr,"Tahoe, NewReno or Sack flavors are NOT available for BayFullTCP!! Use BayFullTcp only, which actually implements Reno.\n");
00116 exit(1);
00117 }
00118 } class_newreno_bayfull;
00119
00120 static class SackBayFullTcpClass : public TclClass {
00121 public:
00122 SackBayFullTcpClass() : TclClass("Agent/TCP/BayFullTcp/Sack") {}
00123 TclObject* create(int, const char*const*) {
00124
00125 fprintf(stderr,"Tahoe, NewReno or Sack flavors are NOT available for BayFullTCP!! Use BayFullTcp only, which actually implements Reno.\n");
00126 exit(1);
00127 }
00128 } class_sack_bayfull;
00129
00130
00131
00132
00133
00134
00135 BayFullTcpAgent::BayFullTcpAgent() : flags_(0),
00136 state_(TCPS_CLOSED), rq_(rcv_nxt_), last_ack_sent_(0), app_(0),
00137 delack_timer_(this)
00138 {
00139 bind("segsperack_", &segs_per_ack_);
00140 bind("segsize_", &maxseg_);
00141 bind("tcprexmtthresh_", &tcprexmtthresh_);
00142 bind("iss_", &iss_);
00143 bind_bool("nodelay_", &nodelay_);
00144 bind_bool("data_on_syn_",&data_on_syn_);
00145 bind_bool("dupseg_fix_", &dupseg_fix_);
00146 bind_bool("dupack_reset_", &dupack_reset_);
00147 bind("interval_", &delack_interval_);
00148 }
00149
00150 void
00151 BayFullTcpAgent::delay_bind_init_all()
00152 {
00153 TcpAgent::delay_bind_init_all();
00154 reset();
00155 }
00156
00157 int
00158 BayFullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
00159 {
00160 return TcpAgent::delay_bind_dispatch(varName, localName, tracer);
00161 }
00162
00163
00164
00165
00166
00167
00168 void
00169 BayFullTcpAgent::reset()
00170 {
00171 TcpAgent::reset();
00172 highest_ack_ = 0;
00173 last_ack_sent_ = 0;
00174 rcv_nxt_ = 0;
00175 flags_ = 0;
00176 t_seqno_ = iss_;
00177 close_on_empty_ = 0;
00178 switch_spa_thresh_ = 0;
00179 first_data_ = 0;
00180 }
00181
00182 void
00183 BayFullTcpAgent::reinit()
00184 {
00185 cancel_rtx_timeout();
00186 rtt_init();
00187 cwnd_ = wnd_init_;
00188 last_ack_ = highest_ack_ = 0;
00189 ssthresh_ = int(wnd_);
00190 awnd_ = wnd_init_ / 2.0;
00191 recover_ = 0;
00192 recover_cause_ = 0;
00193
00194 last_ack_sent_ = 0;
00195 rcv_nxt_ = 0;
00196 flags_ = 0;
00197 t_seqno_ = maxseq_ = iss_;
00198 switch_spa_thresh_ = 0;
00199
00200
00201
00202
00203
00204 rq_.clear();
00205 first_data_ = 0;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214 int
00215 BayFullTcpAgent::headersize()
00216 {
00217 return (TCPIP_BASE_PKTSIZE);
00218 }
00219
00220
00221
00222
00223
00224 BayFullTcpAgent::~BayFullTcpAgent()
00225 {
00226
00227
00228
00229
00230
00231
00232
00233 rq_.clear();
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 void
00246 BayFullTcpAgent::advance(int np)
00247 {
00248
00249
00250
00251
00252
00253 if (np >= 0x10000000)
00254 np /= maxseg_;
00255
00256 curseq_ += (np * maxseg_);
00257
00258
00259
00260
00261
00262
00263
00264
00265 if (state_ > TCPS_ESTABLISHED) {
00266 fprintf(stderr,
00267 "%f: BayFullTcpAgent::advance(%s): cannot advance while in state %d\n",
00268 now(), name(), state_);
00269 return;
00270 } else if (state_ == TCPS_CLOSED) {
00271 connect();
00272 } else if (state_ == TCPS_ESTABLISHED)
00273 send_much(0, REASON_NORMAL, 0);
00274 return;
00275 }
00276
00277
00278
00279 int
00280 BayFullTcpAgent::advance(int n, int close_flag)
00281 {
00282 close_on_empty_ = close_flag;
00283
00284
00285
00286
00287
00288
00289
00290
00291 if (state_ > TCPS_ESTABLISHED) {
00292 return 0;
00293 } else if (state_ == TCPS_CLOSED) {
00294 curseq_ = iss_ + n;
00295 reinit();
00296 connect();
00297 }
00298 else if (state_ == TCPS_ESTABLISHED)
00299 curseq_ += n;
00300 else
00301 return 0;
00302 return 1;
00303 }
00304
00305
00306
00307
00308 int BayFullTcpAgent::outflags()
00309 {
00310 int flags = 0;
00311 if ((state_ != TCPS_LISTEN) && (state_ != TCPS_SYN_SENT))
00312 flags |= TH_ACK;
00313
00314 if ((state_ == TCPS_SYN_SENT) || (state_ == TCPS_SYN_RECEIVED))
00315 flags |= TH_SYN;
00316
00317 if ((state_ == TCPS_FIN_WAIT_1) || (state_ == TCPS_LAST_ACK))
00318 flags |= TH_FIN;
00319
00320 return (flags);
00321 }
00322
00323 void BayFullTcpAgent::sendpacket(int seqno, int ackno, int pflags, int datalen,
00324 int reason)
00325 {
00326 Packet* p = allocpkt();
00327 hdr_tcp *tcph = hdr_tcp::access(p);
00328 hdr_cmn *th = hdr_cmn::access(p);
00329 tcph->seqno() = seqno;
00330 tcph->ackno() = ackno;
00331 tcph->flags() = pflags;
00332 tcph->hlen() = headersize();
00333 tcph->ts() = now();
00334
00335 tcph->reason() |= reason;
00336 th->size() = datalen + headersize();
00337 if (datalen <= 0)
00338 ++nackpack_;
00339 else {
00340 ++ndatapack_;
00341 ndatabytes_ += datalen;
00342 }
00343 if (reason == REASON_TIMEOUT || reason == REASON_DUPACK) {
00344 ++nrexmitpack_;
00345 nrexmitbytes_ += datalen;
00346 }
00347 send(p, 0);
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 void BayFullTcpAgent::output(int seqno, int reason)
00365 {
00366 int is_retransmit = (seqno < maxseq_);
00367 int idle = (highest_ack_ == maxseq_);
00368
00369
00370 int buffered_bytes = (curseq_ + iss_) - seqno;
00371 int datalen = min(buffered_bytes, (highest_ack_ + (window() * maxseg_)) - seqno);
00372 int pflags = outflags();
00373 int emptying_buffer = 0;
00374
00375 if((pflags & TH_SYN) || datalen <= 0)
00376 datalen = 0;
00377 else if(datalen > maxseg_) {
00378 datalen = maxseg_;
00379 } else if(datalen == buffered_bytes) {
00380 emptying_buffer = 1;
00381 pflags |= TH_PUSH;
00382
00383 if(close_on_empty_) {
00384 pflags |= TH_FIN;
00385 state_ = TCPS_FIN_WAIT_1;
00386 }
00387 }
00388
00389
00390
00391
00392 if (datalen > 0 && !emptying_buffer)
00393 pflags &= ~TH_FIN;
00394
00395
00396
00397 if (datalen > 0) {
00398
00399 if (datalen == maxseg_)
00400 goto send;
00401
00402 if ((idle || nodelay_) && emptying_buffer)
00403 goto send;
00404
00405 if (is_retransmit)
00406 goto send;
00407
00408
00409
00410 if (datalen >= ((wnd_ * maxseg_) / 2.0))
00411 goto send;
00412 }
00413
00414 if (need_send())
00415 goto send;
00416
00417
00418
00419
00420
00421
00422
00423 if ((flags_ & TF_ACKNOW) || (pflags & (TH_SYN|TH_FIN|TH_PUSH)))
00424 goto send;
00425
00426 return;
00427
00428 send:
00429
00430 if (pflags & TH_FIN) {
00431 if (flags_ & TF_SENTFIN) {
00432
00433
00434
00435 if (seqno >= maxseq_)
00436 --seqno;
00437 } else {
00438 flags_ |= TF_SENTFIN;
00439 ++t_seqno_;
00440 }
00441 }
00442
00443 if((pflags & TH_SYN)) {
00444 if ((flags_ & TF_SENTSYN) == 0) {
00445 flags_ |= TF_SENTSYN;
00446 ++t_seqno_;
00447 }
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 sendpacket(seqno, rcv_nxt_, pflags, datalen, reason);
00457 last_ack_sent_ = rcv_nxt_;
00458 flags_ &= ~(TF_ACKNOW|TF_DELACK);
00459
00460 t_seqno_ += datalen;
00461 if (t_seqno_ > maxseq_) {
00462 maxseq_ = t_seqno_;
00463
00464
00465
00466
00467 if (rtt_active_ == FALSE) {
00468 rtt_active_ = TRUE;
00469 rtt_seq_ = seqno;
00470 }
00471 }
00472
00473
00474
00475
00476
00477
00478
00479 if (!(rtx_timer_.status() == TIMER_PENDING) && (t_seqno_ > highest_ack_)) {
00480 set_rtx_timer();
00481 }
00482 }
00483
00484
00485
00486
00487
00488 void BayFullTcpAgent::send_much(int force, int reason, int maxburst)
00489 {
00490
00491
00492
00493
00494
00495
00496
00497 int win = window() * maxseg_;
00498 int npackets = 0;
00499 int topwin = curseq_ + iss_;
00500 if (topwin > highest_ack_ + win)
00501 topwin = highest_ack_ + win;
00502
00503 if (!force && (delsnd_timer_.status() == TIMER_PENDING))
00504 return;
00505
00506 while (force || (t_seqno_ < topwin)) {
00507 if (overhead_ != 0 && !(delsnd_timer_.status() == TIMER_PENDING)) {
00508 delsnd_timer_.resched(Random::uniform(overhead_));
00509 return;
00510 }
00511 output(t_seqno_, reason);
00512 force = 0;
00513 if (outflags() & TH_SYN)
00514 break;
00515 if (maxburst && ++npackets >= maxburst)
00516 break;
00517 }
00518 }
00519
00520 void BayFullTcpAgent::cancel_rtx_timeout()
00521 {
00522 if (rtx_timer_.status() == TIMER_PENDING) {
00523 rtx_timer_.cancel();
00524 }
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 void BayFullTcpAgent::newack(Packet* pkt)
00541 {
00542 hdr_tcp *tcph = hdr_tcp::access(pkt);
00543
00544 register int ackno = tcph->ackno();
00545
00546
00547
00548 if (rtt_active_ && ackno >= rtt_seq_) {
00549
00550 rtt_active_ = FALSE;
00551 t_backoff_ = 1;
00552 }
00553
00554
00555 double tao = now() - tcph->ts();
00556 rtt_update(tao);
00557
00558 if (ackno >= maxseq_)
00559 cancel_rtx_timeout();
00560 else {
00561 if (ackno > highest_ack_) {
00562 set_rtx_timer();
00563 }
00564 }
00565
00566
00567 if (ackno > highest_ack_)
00568 highest_ack_ = ackno;
00569
00570 if (t_seqno_ < highest_ack_)
00571 t_seqno_ = highest_ack_;
00572 }
00573
00574
00575
00576
00577 int BayFullTcpAgent::predict_ok(Packet* )
00578 {
00579 return 0;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589 void BayFullTcpAgent::fast_retransmit(int seq)
00590 {
00591 rtt_backoff();
00592 int onxt = t_seqno_;
00593 recover_ = maxseq_;
00594 recover_cause_ = REASON_DUPACK;
00595 output(seq, REASON_DUPACK);
00596 t_seqno_ = onxt;
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 int BayFullTcpAgent::need_send()
00611 {
00612
00613 if(flags_ & TF_ACKNOW)
00614 return 1;
00615 if(rcv_nxt_ < switch_spa_thresh_)
00616 return ((rcv_nxt_ - last_ack_sent_) >= 1);
00617 return ((rcv_nxt_ - last_ack_sent_) >= (segs_per_ack_ * maxseg_));
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 void BayFullTcpAgent::timeout(int tno)
00636 {
00637 if(state_ == TCPS_CLOSED || state_ == TCPS_LISTEN)
00638 return;
00639
00640 if (tno == TCP_TIMER_RTX) {
00641 ++nrexmit_;
00642 recover_ = maxseq_;
00643 recover_cause_ = REASON_TIMEOUT;
00644 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_RESTART);
00645
00646
00647
00648
00649
00650
00651 reset_rtx_timer(1);
00652 t_seqno_ = highest_ack_;
00653 dupacks_ = 0;
00654 send_much(1, REASON_TIMEOUT);
00655 } else if (tno == TCP_TIMER_DELSND) {
00656
00657
00658
00659
00660 send_much(1, PF_TIMEOUT);
00661 } else if (tno == TCP_TIMER_DELACK) {
00662 if (flags_ & TF_DELACK) {
00663 flags_ &= ~TF_DELACK;
00664 flags_ |= TF_ACKNOW;
00665 send_much(1, REASON_NORMAL, 0);
00666 }
00667 delack_timer_.resched(delack_interval_);
00668 } else {
00669 fprintf(stderr, "%f: (%s) UNKNOWN TIMEOUT %d\n",
00670 now(), name(), tno);
00671 }
00672 }
00673
00674
00675
00676
00677
00678 void BayDelAckTimer::expire(Event *) {
00679 a_->timeout(TCP_TIMER_DELACK);
00680 }
00681
00682
00683
00684
00685
00686
00687
00688 void BayFullTcpAgent::recv(Packet *pkt, Handler*)
00689 {
00690 hdr_tcp *tcph = hdr_tcp::access(pkt);
00691 hdr_cmn *th = hdr_cmn::access(pkt);
00692 hdr_ip *iph = hdr_ip::access(pkt);
00693 int needoutput = 0;
00694 int ourfinisacked = 0;
00695 int todrop = 0;
00696 int dupseg = FALSE;
00697
00698 #ifdef notdef
00699 if (trace_)
00700 plot();
00701 #endif
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 if (!(delack_timer_.status() == TIMER_PENDING)) {
00713 double now = Scheduler::instance().clock();
00714 int last = int(now / delack_interval_);
00715 delack_timer_.resched(delack_interval_ * (last + 1.0) - now);
00716
00717 }
00718
00719 int datalen = th->size() - tcph->hlen();
00720 int ackno = tcph->ackno();
00721
00722
00723
00724 int tiflags = tcph->flags() ;
00725
00726 switch (state_) {
00727 case TCPS_LISTEN:
00728 if (tiflags & TH_ACK) {
00729 if (tiflags & TH_FIN) {
00730 sendpacket(tcph->ackno(), tcph->seqno()+1,
00731 TH_ACK, 0, REASON_NORMAL);
00732 goto drop;
00733 }
00734
00735
00736
00737
00738
00739 goto drop;
00740 }
00741 if ((tiflags & TH_SYN) == 0) {
00742
00743 fprintf(stderr,
00744 "%f: BayFullTcpAgent::recv(%s): got a non-SYN while in LISTEN\n",
00745 now(), name());
00746 goto drop;
00747 }
00748 flags_ |= TF_ACKNOW;
00749 state_ = TCPS_SYN_RECEIVED;
00750 rcv_nxt_ = tcph->seqno() + 1;
00751 t_seqno_ = iss_;
00752
00753 switch_spa_thresh_ = rcv_nxt_ + (16 * 1024);
00754 goto step6;
00755 case TCPS_SYN_SENT:
00756 if ((tiflags & TH_ACK) && (ackno > maxseq_)) {
00757
00758
00759
00760
00761 goto drop;
00762 }
00763 if ((tiflags & TH_SYN) == 0) {
00764
00765 fprintf(stderr,
00766 "%f: BayFullTcpAgent::recv(%s): no SYN for our SYN(%d)\n",
00767 now(), name(), int(maxseq_));
00768 goto drop;
00769 }
00770 rcv_nxt_ = tcph->seqno()+1;
00771
00772 switch_spa_thresh_ = rcv_nxt_ + (16 * 1024);
00773 cancel_rtx_timeout();
00774 flags_ |= TF_ACKNOW;
00775 if (tiflags & TH_ACK) {
00776
00777
00778 newack(pkt);
00779 state_ = TCPS_ESTABLISHED;
00780 } else {
00781
00782 state_ = TCPS_SYN_RECEIVED;
00783 }
00784 goto step6;
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 todrop = rcv_nxt_ - tcph->seqno();
00799 if (todrop > 0) {
00800
00801 if (tiflags & TH_SYN) {
00802 t_seqno_ = highest_ack_;
00803 if ((tiflags & TH_ACK) == 0)
00804 goto dropafterack;
00805 tiflags &= ~TH_SYN;
00806 }
00807 if (todrop > datalen ||
00808 (todrop == datalen && ((tiflags & TH_FIN) == 0))) {
00809
00810
00811
00812
00813
00814 tiflags &= ~TH_FIN;
00815
00816
00817
00818
00819
00820 flags_ |= TF_ACKNOW;
00821 todrop = datalen;
00822 dupseg = TRUE;
00823 }
00824 tcph->seqno() += todrop;
00825 datalen -= todrop;
00826 }
00827
00828 if (tiflags & TH_SYN) {
00829 fprintf(stderr,
00830 "%f: %d.%d>%d.%d BayFullTcpAgent::recv(%s) received unexpected SYN (state:%d)\n",
00831 now(),
00832 iph->saddr(), iph->sport(),
00833 iph->daddr(), iph->dport(),
00834 name(), state_);
00835 goto drop;
00836 }
00837
00838 if ((tiflags & (TH_SYN|TH_ACK)) == 0) {
00839 fprintf(stderr, "%f: %d.%d>%d.%d BayFullTcpAgent::recv(%s) got packet lacking ACK (seq %d)\n",
00840 now(),
00841 iph->saddr(), iph->sport(),
00842 iph->daddr(), iph->dport(),
00843 name(), tcph->seqno());
00844 goto drop;
00845 }
00846
00847
00848
00849
00850
00851 switch (state_) {
00852 case TCPS_SYN_RECEIVED:
00853 if (ackno < highest_ack_ || ackno > maxseq_) {
00854
00855 goto drop;
00856 }
00857 state_ = TCPS_ESTABLISHED;
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 case TCPS_ESTABLISHED:
00872 case TCPS_FIN_WAIT_1:
00873 case TCPS_FIN_WAIT_2:
00874 case TCPS_CLOSING:
00875 case TCPS_LAST_ACK:
00876
00877
00878
00879
00880 if (ackno <= highest_ack_) {
00881
00882 if (datalen == 0 && (!dupseg_fix_ || !dupseg)) {
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 if (!(rtx_timer_.status() == TIMER_PENDING) ||
00903 ackno != highest_ack_) {
00904
00905 dupacks_ = 0;
00906 } else if (bug_fix_ &&
00907 highest_ack_ == recover_ &&
00908 recover_cause_ == REASON_TIMEOUT) {
00909
00910 dupacks_ = 0;
00911 } else if (++dupacks_ == tcprexmtthresh_) {
00912 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
00913 cancel_rtx_timeout();
00914 rtt_active_ = FALSE;
00915 fast_retransmit(ackno);
00916
00917
00918
00919 cwnd_ = ssthresh_ + dupacks_;
00920 goto drop;
00921 } else if (dupacks_ > tcprexmtthresh_) {
00922
00923
00924
00925 cwnd_++;
00926 send_much(0, REASON_NORMAL, 0);
00927 goto drop;
00928 }
00929 } else {
00930
00931
00932 if (dupack_reset_)
00933 dupacks_ = 0;
00934 }
00935 break;
00936 }
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 if (dupacks_ >= tcprexmtthresh_ && cwnd_ > ssthresh_) {
00948
00949
00950
00951 cwnd_ = (maxseq_ - ackno + maxseg_ - 1)
00952 / maxseg_ + 2;
00953 }
00954 dupacks_ = 0;
00955 if (ackno > maxseq_) {
00956
00957 fprintf(stderr,
00958 "%f: BayFullTcpAgent::recv(%s) too-big ACK (ack: %d, maxseq:%d)\n",
00959 now(), name(), int(ackno), int(maxseq_));
00960 goto dropafterack;
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976 newack(pkt);
00977 if (state_ == TCPS_ESTABLISHED && ackno < maxseq_)
00978 needoutput = 1;
00979
00980
00981
00982
00983 if(first_data_)
00984 opencwnd();
00985
00986 if ((state_ == TCPS_FIN_WAIT_1 || state_ == TCPS_FIN_WAIT_2
00987 || state_ == TCPS_LAST_ACK || state_ == TCPS_CLOSING)
00988 && ackno >= (curseq_ + iss_))
00989 ourfinisacked = 1;
00990 else
00991 ourfinisacked = 0;
00992
00993
00994 switch (state_) {
00995
00996
00997
00998
00999
01000 case TCPS_FIN_WAIT_1:
01001 if (ourfinisacked)
01002 state_ = TCPS_FIN_WAIT_2;
01003 break;
01004
01005
01006
01007
01008
01009
01010
01011 case TCPS_CLOSING: ;
01012 if (ourfinisacked)
01013 state_ = TCPS_CLOSED;
01014 break;
01015
01016
01017
01018
01019
01020
01021 case TCPS_LAST_ACK:
01022 if (ourfinisacked) {
01023 state_ = TCPS_CLOSED;
01024
01025
01026
01027
01028
01029 goto drop;
01030 } else {
01031 fprintf(stderr,
01032 "%f: %d.%d>%d.%d BayFullTcpAgent::recv(%s) received non-ACK (state:%d)\n",
01033 now(),
01034 iph->saddr(), iph->sport(),
01035 iph->daddr(), iph->dport(),
01036 name(), state_);
01037 }
01038
01039
01040 }
01041 }
01042
01043 step6:
01044
01045
01046
01047
01048
01049
01050
01051 if (datalen > 0 || (tiflags & TH_FIN)) {
01052 first_data_ = 1;
01053
01054 if (tcph->seqno() == rcv_nxt_ && rq_.empty()) {
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 tiflags &= TH_FIN;
01066 if (tiflags) {
01067 ++rcv_nxt_;
01068 }
01069 flags_ |= TF_DELACK;
01070 rcv_nxt_ += datalen;
01071
01072
01073
01074
01075
01076
01077
01078
01079 if(datalen && app_ && (tcph->flags() & TH_PUSH)) {
01080
01081 app_->recv(pkt,this,DATA_PUSH);
01082
01083 }
01084 needoutput = need_send();
01085 } else {
01086
01087
01088
01089
01090
01091 tiflags = rq_.add(pkt);
01092 if (tiflags & TH_PUSH) {
01093 if (app_ != NULL )
01094 app_->recv(pkt,this,DATA_PUSH);
01095 needoutput = need_send();
01096 } else
01097 flags_ |= TF_ACKNOW;
01098
01099 switch_spa_thresh_ = rcv_nxt_ + (16 * 1024);
01100 }
01101 }
01102
01103
01104
01105
01106
01107
01108 if (tiflags & TH_FIN) {
01109 flags_ |= TF_ACKNOW;
01110 rq_.clear();
01111 switch (state_) {
01112
01113
01114
01115
01116
01117
01118 case TCPS_SYN_RECEIVED:
01119 case TCPS_ESTABLISHED:
01120 state_ = TCPS_LAST_ACK;
01121 break;
01122
01123
01124
01125
01126
01127
01128 case TCPS_FIN_WAIT_1:
01129 state_ = TCPS_CLOSING;
01130 break;
01131
01132
01133
01134
01135
01136
01137
01138 case TCPS_FIN_WAIT_2:
01139 state_ = TCPS_CLOSED;
01140 cancel_rtx_timeout();
01141 break;
01142 }
01143 }
01144
01145 if (needoutput || (flags_ & TF_ACKNOW))
01146 send_much(1, REASON_NORMAL, 0);
01147 else if ((curseq_ + iss_) > highest_ack_)
01148 send_much(0, REASON_NORMAL, 0);
01149
01150
01151
01152
01153
01154 if(state_ == TCPS_CLOSED) {
01155 if(close_on_empty_) {
01156 reinit();
01157 curseq_ = iss_;
01158 state_ = TCPS_LISTEN;
01159 } else {
01160 if (app_ != NULL )
01161 app_->recv(pkt,this,CONNECTION_END);
01162 }
01163 }
01164 Packet::free(pkt);
01165 return;
01166
01167 dropafterack:
01168 flags_ |= TF_ACKNOW;
01169 send_much(1, REASON_NORMAL, 0);
01170 drop:
01171 Packet::free(pkt);
01172 return;
01173 }
01174
01175 void BayFullTcpAgent::reset_rtx_timer(int )
01176 {
01177
01178
01179 rtt_backoff();
01180 set_rtx_timer();
01181 rtt_active_ = FALSE;
01182 }
01183
01184
01185
01186
01187
01188
01189 void BayFullTcpAgent::connect()
01190 {
01191 state_ = TCPS_SYN_SENT;
01192
01193 if (!data_on_syn_) {
01194
01195 int cur = curseq_;
01196 curseq_ = iss_;
01197 output(iss_, REASON_NORMAL);
01198 curseq_ = cur + 1;
01199 return;
01200 }
01201 output(iss_, REASON_NORMAL);
01202 return;
01203 }
01204
01205
01206
01207
01208
01209
01210 void BayFullTcpAgent::listen()
01211 {
01212 state_ = TCPS_LISTEN;
01213 type_ = PT_TCP;
01214
01215 }
01216
01217
01218
01219
01220
01221 void BayFullTcpAgent::usrclosed()
01222 {
01223
01224 switch (state_) {
01225 case TCPS_CLOSED:
01226 case TCPS_LISTEN:
01227 case TCPS_SYN_SENT:
01228 state_ = TCPS_CLOSED;
01229 break;
01230 case TCPS_SYN_RECEIVED:
01231 case TCPS_ESTABLISHED:
01232 state_ = TCPS_FIN_WAIT_1;
01233 send_much(1, REASON_NORMAL, 0);
01234 break;
01235 }
01236 return;
01237 }
01238
01239 int BayFullTcpAgent::command(int argc, const char*const* argv)
01240 {
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252 Tcl& tcl = Tcl::instance();
01253
01254 if (argc == 2) {
01255 if (strcmp(argv[1], "listen") == 0) {
01256
01257 listen();
01258 return (TCL_OK);
01259 }
01260 if (strcmp(argv[1], "close") == 0) {
01261 usrclosed();
01262 return (TCL_OK);
01263 }
01264 }
01265 if (argc == 3) {
01266 if (strcmp(argv[1], "advance") == 0) {
01267 advance(atoi(argv[2]));
01268 return (TCL_OK);
01269 }
01270
01271
01272 if (strcmp(argv[1], "attach-application") == 0) {
01273 app_ = (BayTcpAppAgent *)TclObject::lookup(argv[2]);
01274 if (app_ == 0) {
01275 tcl.resultf("no such agent %s", argv[2]);
01276 return(TCL_ERROR);
01277 }
01278 return(TCL_OK);
01279 }
01280
01281 if (strcmp(argv[1], "initial-window") == 0) {
01282 wnd_init_ = atoi(argv[2]);
01283 cwnd_ = wnd_init_;
01284 awnd_ = wnd_init_ /2.0;
01285 return(TCL_OK);
01286 }
01287
01288 }
01289 return (TcpAgent::command(argc, argv));
01290 }
01291
01292
01293
01294 void BayReassemblyQueue::clear()
01295 {
01296 seginfo* p;
01297 seginfo* n;
01298 for (p = head_; p != NULL; p = n) {
01299 n = p->next_;
01300 delete p;
01301 }
01302 head_ = tail_ = NULL;
01303 return;
01304 }
01305
01306
01307
01308
01309
01310
01311 int BayReassemblyQueue::add(Packet* pkt)
01312 {
01313 hdr_tcp *tcph = hdr_tcp::access(pkt);
01314 hdr_cmn *th = hdr_cmn::access(pkt);
01315
01316 int start = tcph->seqno();
01317 int end = start + th->size() - tcph->hlen();
01318 int tiflags = tcph->flags();
01319 seginfo *q, *p, *n;
01320
01321 if (head_ == NULL) {
01322
01323 tail_ = head_ = new seginfo;
01324 head_->prev_ = NULL;
01325 head_->next_ = NULL;
01326 head_->startseq_ = start;
01327 head_->endseq_ = end;
01328 head_->flags_ = tiflags;
01329 } else {
01330 p = NULL;
01331 n = new seginfo;
01332 n->startseq_ = start;
01333 n->endseq_ = end;
01334 n->flags_ = tiflags;
01335 if (tail_->endseq_ <= start) {
01336
01337 p = tail_;
01338 goto endfast;
01339 }
01340
01341 q = head_;
01342
01343 while (q != NULL && (end > q->startseq_))
01344 q = q->next_;
01345
01346 if (q == NULL)
01347 p = tail_;
01348 else
01349 p = q->prev_;
01350
01351 if (p == NULL) {
01352
01353 n->next_ = head_;
01354 n->prev_ = NULL;
01355 head_->prev_ = n;
01356 head_ = n;
01357 } else {
01358 endfast:
01359
01360 n->next_ = p->next_;
01361 if (p->next_)
01362 p->next_->prev_ = n;
01363 p->next_ = n;
01364 n->prev_ = p;
01365 if (p == tail_)
01366 tail_ = n;
01367 }
01368 }
01369
01370
01371
01372
01373
01374 if (head_->startseq_ > rcv_nxt_)
01375 return 0;
01376
01377 tiflags = 0;
01378 p = head_;
01379 while (p != NULL) {
01380
01381
01382 rcv_nxt_ = p->endseq_;
01383 tiflags |= p->flags_;
01384 q = p;
01385 if (q->prev_)
01386 q->prev_->next_ = q->next_;
01387 else
01388 head_ = q->next_;
01389 if (q->next_)
01390 q->next_->prev_ = q->prev_;
01391 else
01392 tail_ = q->prev_;
01393 if (q->next_ && (q->endseq_ < q->next_->startseq_)) {
01394 delete q;
01395 break;
01396 }
01397 p = p->next_;
01398 delete q;
01399 }
01400 return (tiflags);
01401 }