tcp-full-bay.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:39k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 1997 The Regents of the University of California.
  3.  * All rights reserved.
  4.  * 
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *  This product includes software developed by the Network Research
  16.  *  Group at Lawrence Berkeley National Laboratory.
  17.  * 4. Neither the name of the University nor of the Laboratory may be used
  18.  *    to endorse or promote products derived from this software without
  19.  *    specific prior written permission.
  20.  * 
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33. /*
  34.  * This code below was motivated in part by code contributed by
  35.  * Kathie Nichols (nichols@com21.com).  The code below is based primarily
  36.  * on the 4.4BSD TCP implementation. -KF [kfall@ee.lbl.gov]
  37.  *
  38.  * Major revisions, 8/97, kmn (vj)
  39.  *
  40.  * Some Warnings:
  41.  * this version of TCP will not work correctly if the sequence number
  42.  * goes above 2147483648 due to sequence number wrap
  43.  *
  44.  * this version of TCP currently sends data on the 3rd segment of
  45.  * the initial 3-way handshake.  So, the typical sequence of events is
  46.  * A   ------> SYN ------> B
  47.  * A   <----- SYN+ACK ---- B
  48.  * A   ------> ACK+data -> B
  49.  * whereas many "real-world" TCPs don't send data until a 4th segment
  50.  *
  51.  * there is no dynamic receiver's advertised window.   The advertised
  52.  * window is simulated by simply telling the sender a bound on the window
  53.  * size (wnd_).
  54.  *
  55.  * in real TCP, a user process performing a read (via PRU_RCVD)
  56.  * calls tcp_output each time to (possibly) send a window
  57.  * update.  Here we don't have a user process, so we simulate
  58.  * a user process always ready to consume all the receive buffer
  59.  *
  60.  * Notes:
  61.  * wnd_, wnd_init_, cwnd_, ssthresh_ are in segment units
  62.  * sequence and ack numbers are in byte units
  63.  *
  64.  * Futures:
  65.  * there are different existing TCPs with respect to how
  66.  * ack's are handled on connection startup.  Some delay
  67.  * the ack for the first segment, which can cause connections
  68.  * to take longer to start up than if we be sure to ack it quickly.
  69.  */
  70. #ifndef lint
  71. static const char rcsid[] =
  72.     "@(#) $Header: /cvsroot/nsnam/ns-2/baytcp/tcp-full-bay.cc,v 1.6 2006/12/17 15:17:01 mweigle Exp $ (LBL)";
  73. #endif
  74. #include "tclcl.h"
  75. #include "ip.h"
  76. #include "tcp-full-bay.h"
  77. #include "flags.h"
  78. #include "random.h"
  79. #include "template.h"
  80. #define TRUE  1
  81. #define FALSE  0
  82. static class BayFullTcpClass : public TclClass { 
  83. public:
  84.     BayFullTcpClass() : TclClass("Agent/TCP/BayFullTcp") {}
  85.     TclObject* create(int, const char*const*) { 
  86.         return (new BayFullTcpAgent());
  87.     }
  88. } class_bayfull;
  89. static class TahoeBayFullTcpClass : public TclClass { 
  90. public:
  91. TahoeBayFullTcpClass() : TclClass("Agent/TCP/BayFullTcp/Tahoe") {}
  92.   TclObject* create(int, const char*const*) { 
  93.     // tcl lib code
  94.     // sets reno_fastrecov_ to false
  95.     //return (new BayFullTcpAgent());
  96.     fprintf(stderr,"Tahoe, NewReno or Sack flavors are NOT available for BayTCP!! Use BayFullTcp only, which actually implements Reno.n");
  97.     exit(1);
  98.     return NULL;
  99. }
  100. } class_tahoe_bayfull;
  101. static class NewRenoBayFullTcpClass : public TclClass { 
  102. public:
  103. NewRenoBayFullTcpClass() : TclClass("Agent/TCP/BayFullTcp/Newreno") {}
  104. TclObject* create(int, const char*const*) { 
  105.   // tcl lib code
  106.   // sets deflate_on_pack_ to false
  107.   //return (new BayFullTcpAgent());
  108.   fprintf(stderr,"Tahoe, NewReno or Sack flavors are NOT available for BayFullTCP!! Use BayFullTcp only, which actually implements Reno.n");
  109.   exit(1);
  110.   return NULL;
  111. }
  112. } class_newreno_bayfull;
  113. static class SackBayFullTcpClass : public TclClass { 
  114. public:
  115. SackBayFullTcpClass() : TclClass("Agent/TCP/BayFullTcp/Sack") {}
  116. TclObject* create(int, const char*const*) { 
  117.   //return (new BayFullTcpAgent());
  118.   fprintf(stderr,"Tahoe, NewReno or Sack flavors are NOT available for BayFullTCP!! Use BayFullTcp only, which actually implements Reno.n");
  119.   exit(1);
  120.   return NULL;
  121. }
  122. } class_sack_bayfull;
  123. /*
  124.  * Tcl bound variables:
  125.  * segsperack: for delayed ACKs, how many to wait before ACKing
  126.  * segsize: segment size to use when sending
  127.  */
  128. BayFullTcpAgent::BayFullTcpAgent() : flags_(0),
  129. state_(TCPS_CLOSED), rq_(rcv_nxt_), last_ack_sent_(0), app_(0),
  130. delack_timer_(this)
  131. {
  132. bind("segsperack_", &segs_per_ack_);
  133. bind("segsize_", &maxseg_);
  134. bind("tcprexmtthresh_", &tcprexmtthresh_);
  135. bind("iss_", &iss_);
  136. bind_bool("nodelay_", &nodelay_);
  137. bind_bool("data_on_syn_",&data_on_syn_);
  138. bind_bool("dupseg_fix_", &dupseg_fix_);
  139. bind_bool("dupack_reset_", &dupack_reset_);
  140. bind("interval_", &delack_interval_);
  141. }
  142. void
  143. BayFullTcpAgent::delay_bind_init_all()
  144. {
  145. TcpAgent::delay_bind_init_all();
  146.        reset();
  147. }
  148. int
  149. BayFullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
  150. {
  151.         return TcpAgent::delay_bind_dispatch(varName, localName, tracer);
  152. }
  153. /*
  154.  * reset to starting point, don't set state_ here,
  155.  * because our starting point might be LISTEN rather
  156.  * than CLOSED if we're a passive opener
  157.  */
  158. void
  159. BayFullTcpAgent::reset()
  160. {
  161. TcpAgent::reset();
  162. highest_ack_ = 0;
  163. last_ack_sent_ = 0;
  164. rcv_nxt_ = 0; //kmn
  165. flags_ = 0;
  166. t_seqno_ = iss_;
  167. close_on_empty_ = 0; //added 7/30/97 by kmn
  168. switch_spa_thresh_ = 0;
  169. first_data_ = 0; //don't open cwnd too early
  170. }
  171. void
  172. BayFullTcpAgent::reinit()
  173. {
  174. cancel_rtx_timeout();
  175. rtt_init();
  176. cwnd_ = wnd_init_;
  177. last_ack_ = highest_ack_ = 0;
  178. ssthresh_ = int(wnd_);
  179. awnd_ = wnd_init_ / 2.0;
  180. recover_ = 0;
  181. recover_cause_ = 0;
  182. last_ack_sent_ = 0;
  183. rcv_nxt_ = 0; //kmn
  184. flags_ = 0;
  185. t_seqno_ = maxseq_ = iss_;
  186. switch_spa_thresh_ = 0;
  187. /*
  188. for(int i =0; i < NTIMER; i++) {
  189. cancel(i);
  190. }
  191. */
  192. rq_.clear();
  193. first_data_ = 0; //don't open cwnd too early
  194. }
  195. /*
  196.  * headersize:
  197.  * how big is an IP+TCP header in bytes
  198.  * (for now, is the basic size, but may changes
  199.  *  in the future w/options; fix for sack)
  200.  */
  201. int
  202. BayFullTcpAgent::headersize()
  203. {
  204. return (TCPIP_BASE_PKTSIZE);
  205. }
  206. /*
  207.  * cancel any pending timers
  208.  * free up the reassembly queue if there's anything there
  209.  */
  210. BayFullTcpAgent::~BayFullTcpAgent()
  211. {
  212.   /*
  213.    * not required any more
  214. register i;
  215. for (i = 0; i < NTIMER; i++)
  216. if (pending_[i])
  217. cancel(i);
  218.   */
  219. rq_.clear();
  220. }
  221. /*
  222.  * the 'advance' interface to the regular tcp is in packet
  223.  * units.  Here we scale this to bytes for full tcp.
  224.  *
  225.  * 'advance' is normally called by an "application" (i.e. data source)
  226.  * to signal that there is something to send
  227.  *
  228.  * 'curseq_' is the last byte number provided by the application
  229.  */
  230. void
  231. BayFullTcpAgent::advance(int np)
  232. {
  233. // XXX hack:
  234. // because np is in packets and a data source
  235. // may pass a *huge* number as a way to tell us
  236. // to go forever, just look for the huge number
  237. // and if it's there, pre-divide it
  238. if (np >= 0x10000000)
  239. np /= maxseg_;
  240. curseq_ += (np * maxseg_);
  241. //
  242. // state-specific operations:
  243. // if CLOSED, do an active open/connect
  244. // if ESTABLISHED, just try to send more
  245. // if above ESTABLISHED, we are closing, so don't allow
  246. // if anything else (establishing), do nothing here
  247. //
  248. if (state_ > TCPS_ESTABLISHED) {
  249. fprintf(stderr,
  250.  "%f: BayFullTcpAgent::advance(%s): cannot advance while in state %dn",
  251.  now(), name(), state_);
  252. return;
  253. } else if (state_ == TCPS_CLOSED) {
  254. connect(); // initiate new connection
  255. } else if (state_ == TCPS_ESTABLISHED)
  256. send_much(0, REASON_NORMAL, 0);
  257. return;
  258. }
  259. /*
  260.  * added 7/30/97 by kmn to allow to pass bytes and set close_on_empty_
  261.  */
  262. int
  263. BayFullTcpAgent::advance(int n, int close_flag)
  264. {
  265. close_on_empty_ = close_flag;
  266. //
  267. // state-specific operations:
  268. // if CLOSED, do an active open/connect
  269. // if ESTABLISHED, just try to send more
  270. // if above ESTABLISHED, we are closing, so don't allow
  271. // if anything else (establishing), do nothing here
  272. //
  273. if (state_ > TCPS_ESTABLISHED) {
  274. return 0; //try again later, please
  275. } else if (state_ == TCPS_CLOSED) {
  276. curseq_ = iss_ + n;
  277. reinit();
  278. connect(); // initiate new connection
  279. }
  280. else if (state_ == TCPS_ESTABLISHED)
  281. curseq_ += n;
  282. else
  283. return 0;
  284. return 1;
  285. }
  286. /*
  287.  * flags that are completely dependent on the tcp state
  288.  * (in real TCP, see tcp_fsm.h, the "tcp_outflags" array)
  289.  */
  290. int BayFullTcpAgent::outflags()
  291. {
  292. int flags = 0;
  293. if ((state_ != TCPS_LISTEN) && (state_ != TCPS_SYN_SENT))
  294. flags |= TH_ACK;
  295. if ((state_ == TCPS_SYN_SENT) || (state_ == TCPS_SYN_RECEIVED))
  296. flags |= TH_SYN;
  297. if ((state_ == TCPS_FIN_WAIT_1) || (state_ == TCPS_LAST_ACK))
  298. flags |= TH_FIN;
  299. return (flags);
  300. }
  301. void BayFullTcpAgent::sendpacket(int seqno, int ackno, int pflags, int datalen,
  302.       int reason, Packet *p)
  303. {
  304. if (!p) p = allocpkt();
  305. hdr_tcp *tcph = hdr_tcp::access(p);
  306. hdr_cmn *th = hdr_cmn::access(p);
  307. tcph->seqno() = seqno;
  308. tcph->ackno() = ackno;
  309. tcph->flags() = pflags;
  310. tcph->hlen() = headersize();
  311. tcph->ts() = now();
  312.     /* Open issue:  should tcph->reason map to pkt->flags_ as in ns-1?? */
  313. tcph->reason() |= reason;
  314. th->size() = datalen + headersize();
  315. if (datalen <= 0)
  316. ++nackpack_;
  317. else {
  318. ++ndatapack_;
  319. ndatabytes_ += datalen;
  320. }
  321. if (reason == REASON_TIMEOUT || reason == REASON_DUPACK) {
  322. ++nrexmitpack_;
  323. nrexmitbytes_ += datalen;
  324. }
  325. send(p, 0);
  326. }
  327. /*
  328.  * see if we should send a segment, and if so, send it
  329.  * (may be ACK or data)
  330.  * 'maxseq_' is called 'snd_max' in "real" TCP
  331.  * and is the largest seq number we've sent
  332.  *
  333.  * maxseg_, largest seq# we've sent (snd_max)
  334.  * flags_, flags regarding our internal state (t_state)
  335.  * pflags, a local used to build up the tcp header flags (flags)
  336.  * curseq_, is the highest sequence number given to us by "application"
  337.  * highest_ack_, the highest ACK we've seen for our data (snd_una)
  338.  * seqno, the next seq# we're going to send (snd_nxt), this will
  339.  * update t_seqno_ (the last thing we sent)
  340.  */
  341. void BayFullTcpAgent::output(int seqno, int reason)
  342. {
  343. int is_retransmit = (seqno < maxseq_);
  344. int idle = (highest_ack_ == maxseq_);
  345. //kmn - changing all this for clarity 8/7/97
  346. int buffered_bytes = (curseq_ + iss_) - seqno;
  347. int datalen = min(buffered_bytes, (highest_ack_ + (window() * maxseg_)) - seqno);
  348. int pflags = outflags();
  349. int emptying_buffer = 0;
  350. if((pflags & TH_SYN) || datalen <= 0)
  351. datalen = 0;
  352. else if(datalen > maxseg_) {
  353. datalen = maxseg_;
  354. } else if(datalen == buffered_bytes) {
  355. emptying_buffer = 1;
  356. pflags |= TH_PUSH;
  357. //usrclosed() causes nested calls to output()
  358. if(close_on_empty_) {
  359. pflags |= TH_FIN;
  360. state_ = TCPS_FIN_WAIT_1;
  361. }
  362. }
  363. //end of kmn changes
  364. /* turn off FIN if there's really more to send */
  365. if (datalen > 0 && !emptying_buffer)
  366. pflags &= ~TH_FIN;
  367. /* sender SWS avoidance (Nagle) */
  368. if (datalen > 0) {
  369. // if full-sized segment, ok
  370. if (datalen == maxseg_)
  371. goto send;
  372. // if Nagle disabled and buffer clearing, ok
  373. if ((idle || nodelay_)  && emptying_buffer)
  374. goto send;
  375. // if a retransmission
  376. if (is_retransmit)
  377. goto send;
  378. // if big "enough", ok...
  379. // (this is not a likely case, and would
  380. // only happen for tiny windows)
  381. if (datalen >= ((wnd_ * maxseg_) / 2.0))
  382. goto send;
  383. }
  384. if (need_send())
  385. goto send;
  386. /*
  387.  * send now if a SYN or special flag "TF_ACKNOW" is set.
  388.  * TF_ACKNOW can be set during connection establishment and
  389.  * to generate acks for out-of-order data
  390.  * kmn 8/28 need to send if there's a push
  391.  */
  392. if ((flags_ & TF_ACKNOW) || (pflags & (TH_SYN|TH_FIN|TH_PUSH)))
  393. goto send;
  394. return; // no reason to send now
  395. send:
  396. //these changed by vj and kmn
  397. if (pflags & TH_FIN) {
  398. if (flags_ & TF_SENTFIN) {
  399. // don't allow seqno to advance past fin
  400. // (the ack generated by a discarded duplicate
  401. // may attempt to do this)
  402. if (seqno >= maxseq_)
  403. --seqno;
  404. } else {
  405. flags_ |= TF_SENTFIN;
  406. ++t_seqno_;
  407. }
  408. }
  409. if((pflags & TH_SYN)) {
  410. if ((flags_ & TF_SENTSYN) == 0) {
  411. flags_ |= TF_SENTSYN;
  412. ++t_seqno_;
  413. }
  414. }
  415. /*
  416.  * fill in packet fields.  Agent::allocpkt()
  417.  * has already filled most of the network layer
  418.  * fields for us.   So fill in tcp hdr and adjust
  419.  * the packet size.
  420.  */
  421. sendpacket(seqno, rcv_nxt_, pflags, datalen, reason);
  422. last_ack_sent_ = rcv_nxt_;
  423. flags_ &= ~(TF_ACKNOW|TF_DELACK);
  424. t_seqno_ += datalen; // update snd_nxt (t_seqno_)
  425. if (t_seqno_ > maxseq_) {
  426. maxseq_ = t_seqno_;  // largest seq# we've sent
  427. /*
  428.  * Time this transmission if not a retransmission and
  429.  * not currently timing anything.
  430.  */
  431. if (rtt_active_ == FALSE) {
  432. rtt_active_ = TRUE; // set timer
  433. rtt_seq_ = seqno;  // timed seq #
  434. }
  435. }
  436. /*
  437.  * Set retransmit timer if not currently set,
  438.  * and not doing an ack or a keep-alive probe.
  439.  * Initial value for retransmit timer is smoothed
  440.  * round-trip time + 2 * round-trip time variance.
  441.  * Future values are rtt + 4 * rttvar.
  442.  */
  443. if (!(rtx_timer_.status() == TIMER_PENDING) && (t_seqno_ > highest_ack_)) {
  444. set_rtx_timer();  // no timer pending, schedule one
  445. }
  446. }
  447. /*
  448.  * Try to send as much data as the window will allow.  The link layer will 
  449.  * do the buffering; we ask the application layer for the size of the packets.
  450.  */
  451. void BayFullTcpAgent::send_much(int force, int reason, int maxburst)
  452. {
  453. /*
  454.  * highest_ack is essentially "snd_una" in real TCP
  455.  *
  456.  * loop while we are in-window (seqno <= (highest_ack + win))
  457.  * and there is something to send (t_seqno_ < curseq_+iss_)
  458.  */
  459. int win = window() * maxseg_; // window() in pkts
  460. int npackets = 0;
  461. int topwin = curseq_ + iss_;
  462. if (topwin > highest_ack_ + win)
  463. topwin = highest_ack_ + win;
  464. if (!force && (delsnd_timer_.status() == TIMER_PENDING))
  465. return;
  466. while (force || (t_seqno_ < topwin)) {
  467. if (overhead_ != 0 && !(delsnd_timer_.status() == TIMER_PENDING)) {
  468. delsnd_timer_.resched(Random::uniform(overhead_));
  469. return;
  470. }
  471. output(t_seqno_, reason); // updates seqno for us
  472. force = 0;
  473. if (outflags() & TH_SYN)
  474. break;
  475. if (maxburst && ++npackets >= maxburst)
  476. break;
  477. }
  478. }
  479. void BayFullTcpAgent::cancel_rtx_timeout()
  480. {
  481. if (rtx_timer_.status() == TIMER_PENDING) {
  482. rtx_timer_.cancel();
  483. }
  484. }
  485. /*
  486.  * Process an ACK
  487.  * this version of the routine doesn't necessarily
  488.  * require the ack to be one which advances the ack number
  489.  *
  490.  * if this ACKs a rtt estimate
  491.  * indicate we are not timing
  492.  * reset the exponential timer backoff (gamma)
  493.  * update rtt estimate
  494.  * cancel retrans timer if everything is sent and ACK'd, else set it
  495.  * advance the ack number if appropriate
  496.  * update segment to send next if appropriate
  497.  */
  498. void BayFullTcpAgent::newack(Packet* pkt)
  499. {
  500.     hdr_tcp *tcph = hdr_tcp::access(pkt);
  501. register int ackno = tcph->ackno();
  502. // we were timing the segment and we
  503. // got an ACK for it
  504. if (rtt_active_ && ackno >= rtt_seq_) {
  505. /* got a rtt sample */
  506. rtt_active_ = FALSE; // no longer timing
  507. t_backoff_ = 1; // stop exp backoff
  508. }
  509. /* always with timestamp option */
  510. double tao = now() - tcph->ts();
  511. rtt_update(tao);
  512. if (ackno >= maxseq_)
  513. cancel_rtx_timeout();
  514. else {
  515. if (ackno > highest_ack_) {
  516. set_rtx_timer();
  517. }
  518. }
  519. // advance the ack number if this is for new data
  520. if (ackno > highest_ack_)
  521. highest_ack_ = ackno;
  522. // set up the next packet to send
  523. if (t_seqno_ < highest_ack_)
  524. t_seqno_ = highest_ack_; // thing to send next
  525. }
  526. /*
  527.  * nuked this stuff, but left in method - kmn
  528.  */
  529. int BayFullTcpAgent::predict_ok(Packet* )
  530. {
  531. return 0;
  532. }
  533. /*
  534.  * fast_retransmit using the given seqno
  535.  * perform a fast retransmit
  536.  * kludge t_seqno_ (snd_nxt) so we do the
  537.  * retransmit then continue from where we were
  538.  */
  539. void BayFullTcpAgent::fast_retransmit(int seq)
  540. {       
  541.         rtt_backoff();                  // bug fix by van to avoid spurious rtx
  542. int onxt = t_seqno_; // output() changes t_seqno_
  543. recover_ = maxseq_; // keep a copy of highest sent
  544. recover_cause_ = REASON_DUPACK; // why we started this recovery period
  545. output(seq, REASON_DUPACK); // send one pkt
  546. t_seqno_ = onxt;
  547. }
  548. /*
  549.  * real tcp determines if the remote
  550.  * side should receive a window update/ACK from us, and often
  551.  * results in sending an update every 2 segments, thereby
  552.  * giving the familiar 2-packets-per-ack behavior of TCP.
  553.  * Here, we don't advertise any windows, so we just see if
  554.  * there's at least 'segs_per_ack_' pkts not yet acked
  555.  */
  556.  /* kmn - adding code to switch from one seg per ack to set value
  557.   */
  558. int BayFullTcpAgent::need_send()
  559. {
  560. //first cut, send if anything to ack. Might need maxseg_
  561. if(flags_ & TF_ACKNOW)
  562. return 1;
  563. if(rcv_nxt_ < switch_spa_thresh_)
  564. return ((rcv_nxt_ - last_ack_sent_) >= 1);
  565. return ((rcv_nxt_ - last_ack_sent_) >= (segs_per_ack_ * maxseg_));
  566. }
  567. /*
  568.  * deal with timers going off.
  569.  * 2 types for now:
  570.  * retransmission timer (TCP_TIMER_RTX)
  571.  * delayed send (randomization) timer (TCP_TIMER_DELSND)
  572.  *
  573.  * real TCP initializes the RTO as 6 sec
  574.  * (  ^ 3sec, kmn )
  575.  * (A + 2D, where A=0, D=3), [Stevens p. 305]
  576.  * and thereafter uses
  577.  * (A + 4D, where A and D are dynamic estimates)
  578.  *
  579.  * note that in the simulator t_srtt_, t_rttvar_ and t_rtt_
  580.  * are all measured in 'tcp_tick_'-second units
  581.  */
  582. void BayFullTcpAgent::timeout(int tno)
  583. {
  584. if(state_ == TCPS_CLOSED || state_ == TCPS_LISTEN)
  585. return;
  586.         /* retransmit timer */
  587.         if (tno == TCP_TIMER_RTX) {
  588. ++nrexmit_;
  589. recover_ = maxseq_;
  590. recover_cause_ = REASON_TIMEOUT;
  591.                 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_RESTART);
  592. //changed 6/10/00 to look at rtx problem -kmn
  593. /* if(highest_ack_ == maxseq_)
  594. reset_rtx_timer(0,0);
  595. else
  596.                  reset_rtx_timer(0,1);
  597. */
  598.                 reset_rtx_timer(1);
  599. t_seqno_ = highest_ack_;
  600. dupacks_ = 0;
  601.                 send_much(1, REASON_TIMEOUT);
  602.         } else if (tno == TCP_TIMER_DELSND) {
  603.                 /*
  604.                  * delayed-send timer, with random overhead
  605.                  * to avoid phase effects
  606.                  */
  607.                 send_much(1, PF_TIMEOUT);
  608.         } else if (tno == TCP_TIMER_DELACK) {
  609. if (flags_ & TF_DELACK) {
  610. flags_ &= ~TF_DELACK;
  611. flags_ |= TF_ACKNOW;
  612. send_much(1, REASON_NORMAL, 0);
  613. }
  614. delack_timer_.resched(delack_interval_);
  615. } else {
  616. fprintf(stderr, "%f: (%s) UNKNOWN TIMEOUT %dn",
  617. now(), name(), tno);
  618. }
  619. }
  620. /*
  621.  * introduced kedar
  622.  */
  623. void BayDelAckTimer::expire(Event *) {
  624. a_->timeout(TCP_TIMER_DELACK);
  625. }
  626. /*
  627.  * main reception path - 
  628.  * called from the agent that handles the data path below in its muxing mode
  629.  * advance() is called when connection is established with size sent from
  630.  * user/application agent
  631.  */
  632. void BayFullTcpAgent::recv(Packet *pkt, Handler*)
  633. {
  634. hdr_tcp *tcph = hdr_tcp::access(pkt);
  635. hdr_cmn *th = hdr_cmn::access(pkt);
  636. hdr_ip *iph = hdr_ip::access(pkt);
  637. int needoutput = 0;
  638. int ourfinisacked = 0;
  639. int todrop = 0;
  640. int dupseg = FALSE;
  641. #ifdef notdef
  642. if (trace_)
  643. plot();
  644. #endif
  645. //
  646. // if no delayed-ACK timer is set, set one
  647. // they are set to fire every 'interval_' secs, starting
  648. // at time t0 = (0.0 + k * interval_) for some k such
  649. // that t0 > now
  650. //
  651. /*
  652. if (!pending_[TCP_TIMER_DELACK]) {
  653. */
  654. if (!(delack_timer_.status() == TIMER_PENDING)) {
  655. double now = Scheduler::instance().clock();
  656. int last = int(now / delack_interval_);
  657. delack_timer_.resched(delack_interval_ * (last + 1.0) - now);
  658. }
  659. int datalen = th->size() - tcph->hlen();
  660. int ackno = tcph->ackno(); // ack # from packet
  661. // nuked header prediction code that was here - kmn 8/5/97
  662. int tiflags = tcph->flags() ; // tcp flags from packet
  663. switch (state_) {
  664. case TCPS_LISTEN: /* awaiting peer's SYN */
  665. if (tiflags & TH_ACK) {
  666. if (tiflags & TH_FIN) {
  667. sendpacket(tcph->ackno(), tcph->seqno()+1,
  668.    TH_ACK, 0, REASON_NORMAL);
  669. goto drop;
  670. }
  671. // ACK shouldn't be on here
  672. // kmn - this can be from previous connection if reusing
  673. // fprintf(stderr,
  674. //     "%f: BayFullTcpAgent::recv(%s): got ACK(%d) while in LISTENn",
  675. // now(), name(), ackno);
  676. goto drop;
  677. }
  678. if ((tiflags & TH_SYN) == 0) {
  679. // we're looking for a SYN in return
  680. fprintf(stderr,
  681.     "%f: BayFullTcpAgent::recv(%s): got a non-SYN while in LISTENn",
  682. now(), name());
  683. goto drop;
  684. }
  685. flags_ |= TF_ACKNOW;
  686. state_ = TCPS_SYN_RECEIVED;
  687. rcv_nxt_ = tcph->seqno() + 1; //kmn
  688. t_seqno_ = iss_;
  689. //kmn - switch from one to set segs per ack
  690. switch_spa_thresh_ = rcv_nxt_ + (16 * 1024);
  691. goto step6;
  692. case TCPS_SYN_SENT: /* we sent SYN, expecting SYN+ACK */
  693. if ((tiflags & TH_ACK) && (ackno > maxseq_)) {
  694. // not an ACK for our SYN, discard
  695. // fprintf(stderr,
  696. //     "%f: BayFullTcpAgent::recv(%s): bad ACK (%d) for our SYN(%d)n",
  697. //         now(), name(), int(ackno), int(maxseq_));
  698. goto drop;
  699. }
  700. if ((tiflags & TH_SYN) == 0) {
  701. // we're looking for a SYN in return
  702. fprintf(stderr,
  703.     "%f: BayFullTcpAgent::recv(%s): no SYN for our SYN(%d)n",
  704.         now(), name(), int(maxseq_));
  705. goto drop;
  706. }
  707. rcv_nxt_ = tcph->seqno()+1; // initial expected seq#
  708. //kmn - switch from one to set segs per ack
  709. switch_spa_thresh_ = rcv_nxt_ + (16 * 1024);
  710. cancel_rtx_timeout(); // cancel timer on our 1st SYN
  711. flags_ |= TF_ACKNOW; // ACK peer's SYN
  712. if (tiflags & TH_ACK) {
  713. // got SYN+ACK (what we're expecting)
  714. // set up to ACK peer's SYN+ACK
  715. newack(pkt);
  716. state_ = TCPS_ESTABLISHED;
  717. } else {
  718. // simultaneous active opens
  719. state_ = TCPS_SYN_RECEIVED;
  720. }
  721. goto step6;
  722. }
  723. // check for redundant data at head/tail of segment
  724. // note that the 4.4bsd [Net/3] code has
  725. // a bug here which can cause us to ignore the
  726. // perfectly good ACKs on duplicate segments.  The
  727. // fix is described in (Stevens, Vol2, p. 959-960).
  728. // This code is based on that correction.
  729. //
  730. // In addition, it has a modification so that duplicate segments
  731. // with dup acks don't trigger a fast retransmit when dupseg_fix_
  732. // is enabled.
  733. //
  734. todrop = rcv_nxt_ - tcph->seqno();  // how much overlap?
  735. if (todrop > 0) {
  736. // segment is something we've seen (perhaps partially)
  737. if (tiflags & TH_SYN) {
  738. t_seqno_ = highest_ack_;
  739. if ((tiflags & TH_ACK) == 0)
  740. goto dropafterack;
  741. tiflags &= ~TH_SYN;
  742. }
  743. if (todrop > datalen ||
  744.     (todrop == datalen && ((tiflags & TH_FIN) == 0))) {
  745. /*
  746.  * Any valid FIN must be to the left of the window.
  747.  * At this point the FIN must be a duplicate or out
  748.  * of sequence; drop it.
  749.  */
  750. tiflags &= ~TH_FIN;
  751. /*
  752.  * Send an ACK to resynchronize and drop any data.
  753.  * But keep on processing for RST or ACK.
  754.  */
  755. flags_ |= TF_ACKNOW;
  756. todrop = datalen;
  757. dupseg = TRUE;
  758. }
  759. tcph->seqno() += todrop;
  760. datalen -= todrop;
  761. }
  762. if (tiflags & TH_SYN) {
  763. fprintf(stderr,
  764.     "%f: %d.%d>%d.%d BayFullTcpAgent::recv(%s) received unexpected SYN (state:%d)n",
  765.         now(),
  766. iph->saddr(), iph->sport(),
  767. iph->daddr(), iph->dport(),
  768.         name(), state_);
  769. goto drop;
  770. }
  771. if ((tiflags & (TH_SYN|TH_ACK)) == 0) {
  772. fprintf(stderr, "%f: %d.%d>%d.%d BayFullTcpAgent::recv(%s) got packet lacking ACK (seq %d)n",
  773. now(),
  774. iph->saddr(), iph->sport(),
  775. iph->daddr(), iph->dport(),
  776. name(), tcph->seqno());
  777. goto drop;
  778. }
  779. /*
  780.  * ACK processing
  781.  */
  782. switch (state_) {
  783. case TCPS_SYN_RECEIVED: /* got ACK for our SYN+ACK */
  784. if (ackno < highest_ack_ || ackno > maxseq_) {
  785. // not in useful range
  786. goto drop;
  787. }
  788. state_ = TCPS_ESTABLISHED;
  789. /* fall into ... */
  790.         /*
  791.          * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
  792.          * ACKs.  If the ack is in the range
  793.          *      tp->snd_una < ti->ti_ack <= tp->snd_max
  794.          * then advance tp->snd_una to ti->ti_ack and drop
  795.          * data from the retransmission queue.
  796.  *
  797.  * note that states CLOSE_WAIT and TIME_WAIT aren't used
  798.  * in the simulator
  799.          */
  800.         case TCPS_ESTABLISHED:
  801.         case TCPS_FIN_WAIT_1:
  802.         case TCPS_FIN_WAIT_2:
  803.         case TCPS_CLOSING:
  804.         case TCPS_LAST_ACK:
  805. // look for dup ACKs (dup ack numbers, no data)
  806. //
  807. // do fast retransmit/recovery if at/past thresh
  808. if (ackno <= highest_ack_) {
  809. // an ACK which doesn't advance highest_ack_
  810. if (datalen == 0 && (!dupseg_fix_ || !dupseg)) {
  811.                                 /*
  812.                                  * If we have outstanding data
  813.                                  * this is a completely
  814.                                  * duplicate ack,
  815.                                  * the ack is the biggest we've
  816.                                  * seen and we've seen exactly our rexmt
  817.                                  * threshhold of them, assume a packet
  818.                                  * has been dropped and retransmit it.
  819.                                  *
  820.                                  * We know we're losing at the current
  821.                                  * window size so do congestion avoidance.
  822.                                  *
  823.                                  * Dup acks mean that packets have left the
  824.                                  * network (they're now cached at the receiver)
  825.                                  * so bump cwnd by the amount in the receiver
  826.                                  * to keep a constant cwnd packets in the
  827.                                  * network.
  828.                                  */
  829.         if (!(rtx_timer_.status() == TIMER_PENDING) ||
  830.     ackno != highest_ack_) {
  831. // not timed, or re-ordered ACK
  832. dupacks_ = 0;
  833. } else if (bug_fix_ &&
  834.      highest_ack_ == recover_ &&
  835.      recover_cause_ == REASON_TIMEOUT) {
  836.   // doing timeout recovery not fastrxmit
  837.   dupacks_ = 0;
  838.    } else if (++dupacks_ == tcprexmtthresh_) {
  839. slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
  840. cancel_rtx_timeout();
  841. rtt_active_ = FALSE;
  842. fast_retransmit(ackno);
  843. // we measure cwnd in packets,
  844. // so don't scale by maxseg_
  845. // as real TCP does
  846. cwnd_ = ssthresh_ + dupacks_;
  847. goto drop;
  848. } else if (dupacks_ > tcprexmtthresh_) {
  849. // we just measure cwnd in packets,
  850. // so don't scale by maxset_ as real
  851. // tcp does
  852. cwnd_++; // fast recovery
  853. send_much(0, REASON_NORMAL, 0);
  854. goto drop;
  855. }
  856. } else {
  857. // non-zero length segment
  858. // (or window changed in real TCP).
  859. if (dupack_reset_)
  860. dupacks_ = 0;
  861. }
  862. break; /* take us to "step6" */
  863. }
  864. /*
  865.  * we've finished the fast retransmit/recovery period
  866.  * (i.e. received an ACK which advances highest_ack_)
  867.  */
  868.                 /*
  869.                  * If the congestion window was inflated to account
  870.                  * for the other side's cached packets, retract it.
  871.                  */
  872. if (dupacks_ >= tcprexmtthresh_ && cwnd_ > ssthresh_) {
  873. /*
  874.  * make sure we send at most 2 packets due to this ack
  875.  */
  876. cwnd_ = (maxseq_ - ackno + maxseg_ - 1)
  877.   / maxseg_ + 2;
  878. }
  879. dupacks_ = 0;
  880. if (ackno > maxseq_) {
  881. // ack more than we sent(!?)
  882. fprintf(stderr,
  883.     "%f: BayFullTcpAgent::recv(%s) too-big ACK (ack: %d, maxseq:%d)n",
  884. now(), name(), int(ackno), int(maxseq_));
  885. goto dropafterack;
  886. }
  887.                 /*
  888.                  * If we have a timestamp reply, update smoothed
  889.                  * round trip time.  If no timestamp is present but
  890.                  * transmit timer is running and timed sequence
  891.                  * number was acked, update smoothed round trip time.
  892.                  * Since we now have an rtt measurement, cancel the
  893.                  * timer backoff (cf., Phil Karn's retransmit alg.).
  894.                  * Recompute the initial retransmit timer.
  895.  *
  896.                  * If all outstanding data is acked, stop retransmit
  897.                  * If there is more data to be acked, restart retransmit
  898.                  * timer, using current (possibly backed-off) value.
  899.                  */
  900. newack(pkt);
  901. if (state_ == TCPS_ESTABLISHED && ackno < maxseq_)
  902. needoutput = 1;
  903. /* kmn - 8/12/97: don't want to do this on first
  904.  * data send, especially to compare IWs
  905.  * So added test.
  906.  */
  907. if(first_data_)
  908. opencwnd();
  909. // kmn - 8/15 added second test that is acking fin
  910. if ((state_ == TCPS_FIN_WAIT_1 || state_ == TCPS_FIN_WAIT_2
  911. || state_ == TCPS_LAST_ACK || state_ == TCPS_CLOSING)
  912. && ackno >= (curseq_ + iss_)) // && ackno == maxseq_)
  913. ourfinisacked = 1;
  914. else
  915. ourfinisacked = 0;
  916. // additional processing when we're in special states
  917. switch (state_) {
  918.                 /*
  919.                  * In FIN_WAIT_1 STATE in addition to the processing
  920.                  * for the ESTABLISHED state if our FIN is now acknowledged
  921.                  * then enter FIN_WAIT_2.
  922.                  */
  923. case TCPS_FIN_WAIT_1: /* doing active close */
  924. if (ourfinisacked)
  925. state_ = TCPS_FIN_WAIT_2;
  926. break;
  927.                 /*
  928.                  * In CLOSING STATE in addition to the processing for
  929.                  * the ESTABLISHED state if the ACK acknowledges our FIN
  930.                  * then enter the TIME-WAIT state, otherwise ignore
  931.                  * the segment.
  932.                  */
  933. case TCPS_CLOSING: /* simultaneous active close */;
  934. if (ourfinisacked)
  935. state_ = TCPS_CLOSED;
  936. break;
  937.                 /*
  938.                  * In LAST_ACK, we may still be waiting for data to drain
  939.                  * and/or to be acked, as well as for the ack of our FIN.
  940.                  * If our FIN is now acknowledged,
  941.                  * enter the closed state and return.
  942.                  */
  943. case TCPS_LAST_ACK: /* passive close */
  944. if (ourfinisacked) {
  945. state_ = TCPS_CLOSED; //kmn added 2 lines
  946. /*
  947. for(int i =0; i < NTIMER; i++) {
  948. cancel(i);
  949. }
  950. */
  951. goto drop;
  952. } else { //should be a FIN we've seen
  953. fprintf(stderr,
  954.      "%f: %d.%d>%d.%d BayFullTcpAgent::recv(%s) received non-ACK (state:%d)n",
  955.          now(),
  956. iph->saddr(), iph->sport(),
  957. iph->daddr(), iph->dport(),
  958.          name(), state_);
  959. }
  960. /* no case for TIME_WAIT in simulator */
  961. } // inner switch
  962. } // outer switch
  963. step6:
  964. /* real TCP handles window updates and URG data here */
  965. /* dodata: this label is in the "real" code.. here only for reference */
  966. /*
  967.  * DATA processing
  968.  * kmn - several changes here to talk to application agent
  969.  */
  970. if (datalen > 0 || (tiflags & TH_FIN)) {
  971. first_data_ = 1; //now seen first data
  972. // see the "TCP_REASS" macro for this code
  973. if (tcph->seqno() == rcv_nxt_ && rq_.empty()) {
  974. // got the in-order packet we were looking
  975. // for, nobody is in the reassembly queue,
  976. // so this is the common case...
  977. // note: in "real" TCP we must also be in
  978. // ESTABLISHED state to come here, because
  979. // data arriving before ESTABLISHED is
  980. // queued in the reassembly queue.  Since we
  981. // don't really have a process anyhow, just
  982. // accept the data here as-is (i.e. don't
  983. // require being in ESTABLISHED state)
  984. tiflags &= TH_FIN;
  985. if (tiflags) {
  986. ++rcv_nxt_;
  987. }
  988. flags_ |= TF_DELACK;
  989. rcv_nxt_ += datalen;
  990. // give to "application" here
  991. // added 7/30/97 by kmn to call application with
  992. // number of bytes since last push (if any)
  993. // the server is going to call advance before this
  994. // completes, so changed advance to not call
  995. // send_much if ESTABLISHED. curseq gets
  996. // checked below.
  997. //
  998. if(datalen && app_ && (tcph->flags() & TH_PUSH)) {
  999. //rcv_nxt_ - last_upcalled_bytes_;
  1000. app_->recv(pkt,this,DATA_PUSH);
  1001. //last_upcalled_bytes_ = rcv_nxt_;
  1002. }
  1003. needoutput = need_send();
  1004. } else {
  1005. // not the one we want next (or it
  1006. // is but there's stuff on the reass queue);
  1007. // do whatever we need to do for out-of-order
  1008. // segments or hole-fills.  Also,
  1009. // send an ACK to the other side right now.
  1010. tiflags = rq_.add(pkt);
  1011. if (tiflags & TH_PUSH) {
  1012.   if (app_ != NULL )
  1013.     app_->recv(pkt,this,DATA_PUSH);
  1014.   needoutput = need_send();
  1015. } else
  1016. flags_ |= TF_ACKNOW;
  1017. //reset for losses
  1018. switch_spa_thresh_ = rcv_nxt_ + (16 * 1024);
  1019. }
  1020. }
  1021. /*
  1022.  * if FIN is received, ACK the FIN
  1023.  * (let user know if we could do so)
  1024.  */
  1025. if (tiflags & TH_FIN) {
  1026. flags_ |= TF_ACKNOW;
  1027. rq_.clear(); // other side shutting down
  1028. switch (state_) {
  1029.                 /*
  1030.                  * In SYN_RECEIVED and ESTABLISHED STATES
  1031.                  * enter the CLOSE_WAIT state.
  1032.  * (in the simulator, go to LAST_ACK)
  1033.  * (passive close)
  1034.                  */
  1035.                 case TCPS_SYN_RECEIVED:
  1036.                 case TCPS_ESTABLISHED:
  1037.                         state_ = TCPS_LAST_ACK;
  1038.                         break;
  1039.                 /*
  1040.                  * If still in FIN_WAIT_1 STATE FIN has not been acked so
  1041.                  * enter the CLOSING state.
  1042.  * (simultaneous close)
  1043.                  */
  1044.                 case TCPS_FIN_WAIT_1:
  1045.                         state_ = TCPS_CLOSING;
  1046.                         break;
  1047.                 /*
  1048.                  * In FIN_WAIT_2 state enter the TIME_WAIT state,
  1049.                  * starting the time-wait timer, turning off the other
  1050.                  * standard timers.
  1051.  * (in the simulator, just go to CLOSED)
  1052.  * (active close)
  1053.                  */
  1054.                 case TCPS_FIN_WAIT_2:
  1055.                         state_ = TCPS_CLOSED;
  1056. cancel_rtx_timeout();
  1057.                         break;
  1058. }
  1059. }
  1060. if (needoutput || (flags_ & TF_ACKNOW))
  1061. send_much(1, REASON_NORMAL, 0);
  1062. else if ((curseq_ + iss_) > highest_ack_)
  1063. send_much(0, REASON_NORMAL, 0);
  1064. /* kmn -  ugh, egregious hack. Can tell it's a server
  1065.  * so it goes to listen state. Do something
  1066.  * else if this becomes more stable
  1067.  */
  1068.         if(state_ == TCPS_CLOSED) {
  1069. if(close_on_empty_) {
  1070. reinit();
  1071. curseq_ = iss_;
  1072. state_ = TCPS_LISTEN;
  1073. } else { /*"something else" - kmn 6/00 */
  1074.   if (app_ != NULL )
  1075.     app_->recv(pkt,this,CONNECTION_END);
  1076. }
  1077. }
  1078. Packet::free(pkt);
  1079. return;
  1080. dropafterack:
  1081. flags_ |= TF_ACKNOW;
  1082. send_much(1, REASON_NORMAL, 0);
  1083. drop:
  1084.     Packet::free(pkt);
  1085. return;
  1086. }
  1087. void BayFullTcpAgent::reset_rtx_timer(int )
  1088. {
  1089. // cancel old timer,
  1090. // set a new one
  1091.         rtt_backoff(); // double current timeout
  1092.         set_rtx_timer(); // set new timer
  1093.         rtt_active_ = FALSE;
  1094. }
  1095. /*
  1096.  * do an active open
  1097.  * (in real TCP, see tcp_usrreq, case PRU_CONNECT)
  1098.  */
  1099. void BayFullTcpAgent::connect()
  1100. {
  1101. state_ = TCPS_SYN_SENT; // sending a SYN now
  1102. if (!data_on_syn_) {
  1103. // force no data in this segment
  1104. int cur = curseq_;
  1105. curseq_ = iss_;
  1106. output(iss_, REASON_NORMAL);
  1107. curseq_ = cur + 1; //think I have to add in the syn here
  1108. return;
  1109. }
  1110. output(iss_, REASON_NORMAL);
  1111. return;
  1112. }
  1113. /*
  1114.  * be a passive opener
  1115.  * (in real TCP, see tcp_usrreq, case PRU_LISTEN)
  1116.  * (for simulation, make this peer's ptype ACKs)
  1117.  */
  1118. void BayFullTcpAgent::listen()
  1119. {
  1120. state_ = TCPS_LISTEN;
  1121. type_ = PT_TCP; //  changed by kmn 8/6/97
  1122. //type_ = PT_ACK; // instead of PT_TCP
  1123. }
  1124. /*
  1125.  * called when user/application performs 'close'
  1126.  */
  1127. void BayFullTcpAgent::usrclosed()
  1128. {
  1129. switch (state_) {
  1130. case TCPS_CLOSED:
  1131. case TCPS_LISTEN:
  1132. case TCPS_SYN_SENT:
  1133. state_ = TCPS_CLOSED;
  1134. break;
  1135. case TCPS_SYN_RECEIVED:
  1136. case TCPS_ESTABLISHED:
  1137. state_ = TCPS_FIN_WAIT_1;
  1138. send_much(1, REASON_NORMAL, 0);
  1139. break;
  1140. }
  1141. return;
  1142. }
  1143. int BayFullTcpAgent::command(int argc, const char*const* argv)
  1144. {
  1145. // would like to have some "connect" primitive
  1146. // here, but the problem is that we get called before
  1147. // the simulation is running and we want to send a SYN.
  1148. // Because no routing exists yet, this fails.
  1149. // Instead, see code in advance() above.
  1150. //
  1151. // listen can happen any time because it just changes state_
  1152. //
  1153. // close is designed to happen at some point after the
  1154. // simulation is running (using an ns 'at' command)
  1155.  Tcl& tcl = Tcl::instance();
  1156. if (argc == 2) {
  1157. if (strcmp(argv[1], "listen") == 0) {
  1158. // just a state transition
  1159. listen();
  1160. return (TCL_OK);
  1161. }
  1162. if (strcmp(argv[1], "close") == 0) {
  1163. usrclosed();
  1164. return (TCL_OK);
  1165. }
  1166. }
  1167. if (argc == 3) {
  1168. if (strcmp(argv[1], "advance") == 0) {
  1169. advance(atoi(argv[2]));
  1170. return (TCL_OK);
  1171. }
  1172. //added 7/31/97 by kmn to work with apps, specifically www
  1173. // probably should use a special type of agent...
  1174. if (strcmp(argv[1], "attach-application") == 0) { 
  1175. app_ = (BayTcpAppAgent *)TclObject::lookup(argv[2]); 
  1176. if (app_ == 0) {
  1177. tcl.resultf("no such agent %s", argv[2]);
  1178. return(TCL_ERROR);
  1179. }
  1180. return(TCL_OK);
  1181. }
  1182. //added by kmn 8/12/97
  1183. if (strcmp(argv[1], "initial-window") == 0) { 
  1184. wnd_init_ = atoi(argv[2]); 
  1185. cwnd_ = wnd_init_;
  1186. awnd_ = wnd_init_ /2.0;
  1187. return(TCL_OK);
  1188. }
  1189. }
  1190. return (TcpAgent::command(argc, argv));
  1191. }
  1192. /*
  1193.  * clear out reassembly queue
  1194.  */
  1195. void BayReassemblyQueue::clear()
  1196. {
  1197. seginfo* p;
  1198. seginfo* n;
  1199. for (p = head_; p != NULL; p = n) {
  1200. n = p->next_;
  1201. delete p;
  1202. }
  1203. head_ = tail_ = NULL;
  1204. return;
  1205. }
  1206. /*
  1207.  * add a packet to the reassembly queue..
  1208.  * will update BayFullTcpAgent::rcv_nxt_ by way of the
  1209.  * BayReassemblyQueue::rcv_nxt_ integer reference (an alias)
  1210.  */
  1211. int BayReassemblyQueue::add(Packet* pkt)
  1212. {
  1213.     hdr_tcp *tcph = hdr_tcp::access(pkt);
  1214.     hdr_cmn *th = hdr_cmn::access(pkt);
  1215. int start = tcph->seqno();
  1216. int end = start + th->size() - tcph->hlen();
  1217. int tiflags = tcph->flags();
  1218. seginfo *q, *p, *n;
  1219. if (head_ == NULL) {
  1220. // nobody there, just insert
  1221. tail_ = head_ = new seginfo;
  1222. head_->prev_ = NULL;
  1223. head_->next_ = NULL;
  1224. head_->startseq_ = start;
  1225. head_->endseq_ = end;
  1226. head_->flags_ = tiflags;
  1227. } else {
  1228. p = NULL;
  1229. n = new seginfo;
  1230. n->startseq_ = start;
  1231. n->endseq_ = end;
  1232. n->flags_ = tiflags;
  1233. if (tail_->endseq_ <= start) {
  1234. // common case of end of reass queue
  1235. p = tail_;
  1236. goto endfast;
  1237. }
  1238. q = head_;
  1239. // look for the segment after this one
  1240. while (q != NULL && (end > q->startseq_))
  1241. q = q->next_;
  1242. // set p to the segment before this one
  1243. if (q == NULL)
  1244. p = tail_;
  1245. else
  1246. p = q->prev_;
  1247. if (p == NULL) {
  1248. // insert at head
  1249. n->next_ = head_;
  1250. n->prev_ = NULL;
  1251. head_->prev_ = n;
  1252. head_ = n;
  1253. } else {
  1254. endfast:
  1255. // insert in the middle or end
  1256. n->next_ = p->next_;
  1257. if (p->next_)
  1258. p->next_->prev_ = n;
  1259. p->next_ = n;
  1260. n->prev_ = p;
  1261. if (p == tail_)
  1262. tail_ = n;
  1263. }
  1264. }
  1265. //
  1266. // look for a sequence of in-order segments and
  1267. // set rcv_nxt if we can
  1268. //
  1269. if (head_->startseq_ > rcv_nxt_)
  1270. return 0; // still awaiting a hole-fill
  1271. tiflags = 0;
  1272. p = head_;
  1273. while (p != NULL) {
  1274. // update rcv_nxt_ to highest in-seq thing
  1275. // and delete the entry from the reass queue
  1276. rcv_nxt_ = p->endseq_;
  1277. tiflags |= p->flags_;
  1278. q = p;
  1279. if (q->prev_)
  1280. q->prev_->next_ = q->next_;
  1281. else
  1282. head_ = q->next_;
  1283. if (q->next_)
  1284. q->next_->prev_ = q->prev_;
  1285. else
  1286. tail_ = q->prev_;
  1287. if (q->next_ && (q->endseq_ < q->next_->startseq_)) {
  1288. delete q;
  1289. break; // only the in-seq stuff
  1290. }
  1291. p = p->next_;
  1292. delete q;
  1293. }
  1294. return (tiflags);
  1295. }