ns2--tcp-full.cc

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2.  
  3. /*
  4. * Copyright (c) Intel Corporation 2001. All rights reserved.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17.  
  18. /*
  19. * Copyright (c) 1997, 1998 The Regents of the University of California.
  20. * All rights reserved.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the above copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. All advertising materials mentioning features or use of this software
  31. * must display the following acknowledgement:
  32. * This product includes software developed by the Network Research
  33. * Group at Lawrence Berkeley National Laboratory.
  34. * 4. Neither the name of the University nor of the Laboratory may be used
  35. * to endorse or promote products derived from this software without
  36. * specific prior written permission.
  37. *
  38. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  39. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  40. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  41. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  42. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  43. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  44. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  45. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  46. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  47. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  48. * SUCH DAMAGE.
  49. */
  50.  
  51. /*
  52. *
  53. * Full-TCP : A two-way TCP very similar to the 4.4BSD version of Reno TCP.
  54. * This version also includes variants Tahoe, NewReno, and SACK.
  55. *
  56. * This code below has received a fairly major restructuring (Aug. 2001).
  57. * The ReassemblyQueue structure is now removed to a separate module and
  58. * entirely re-written.
  59. * Also, the SACK functionality has been re-written (almost) entirely.
  60. * -KF [kfall@intel.com]
  61. *
  62. * This code below was motivated in part by code contributed by
  63. * Kathie Nichols (nichols@baynetworks.com). The code below is based primarily
  64. * on the 4.4BSD TCP implementation. -KF [kfall@ee.lbl.gov]
  65. *
  66. * Kathie Nichols and Van Jacobson have contributed significant bug fixes,
  67. * especially with respect to the the handling of sequence numbers during
  68. * connection establishment/clearin. Additional fixes have followed
  69. * theirs.
  70. *
  71. * Fixes for gensack() and ReassemblyQueue::add() contributed by Richard
  72. * Mortier <Richard.Mortier@cl.cam.ac.uk>
  73. *
  74. * Some warnings and comments:
  75. * this version of TCP will not work correctly if the sequence number
  76. * goes above 2147483648 due to sequence number wrap
  77. *
  78. * this version of TCP by default sends data at the beginning of a
  79. * connection in the "typical" way... That is,
  80. * A ------> SYN ------> B
  81. * A <----- SYN+ACK ---- B
  82. * A ------> ACK ------> B
  83. * A ------> data -----> B
  84. *
  85. * there is no dynamic receiver's advertised window. The advertised
  86. * window is simulated by simply telling the sender a bound on the window
  87. * size (wnd_).
  88. *
  89. * in real TCP, a user process performing a read (via PRU_RCVD)
  90. * calls tcp_output each time to (possibly) send a window
  91. * update. Here we don't have a user process, so we simulate
  92. * a user process always ready to consume all the receive buffer
  93. *
  94. * Notes:
  95. * wnd_, wnd_init_, cwnd_, ssthresh_ are in segment units
  96. * sequence and ack numbers are in byte units
  97. *
  98. * Futures:
  99. * there are different existing TCPs with respect to how
  100. * ack's are handled on connection startup. Some delay
  101. * the ack for the first segment, which can cause connections
  102. * to take longer to start up than if we be sure to ack it quickly.
  103. *
  104. * some TCPs arrange for immediate ACK generation if the incoming segment
  105. * contains the PUSH bit
  106. *
  107. *
  108. */
  109.  
  110. #ifndef lint
  111. static const char rcsid[] =
  112. "@(#) $Header: /cvsroot/nsnam/ns-2/tcp/tcp-full.cc,v 1.130 2010/03/08 05:54:54 tom_henderson Exp $ (LBL)";
  113. #endif
  114.  
  115. #include "ip.h"
  116. #include "tcp-full.h"
  117. #include "flags.h"
  118. #include "random.h"
  119. #include "template.h"
  120.  
  121. #ifndef TRUE
  122. #define TRUE 1
  123. #endif
  124.  
  125. #ifndef FALSE
  126. #define FALSE 0
  127. #endif
  128.  
  129. /*
  130. * Tcl Linkage for the following:
  131. * Agent/TCP/FullTcp, Agent/TCP/FullTcp/Tahoe,
  132. * Agent/TCP/FullTcp/Newreno, Agent/TCP/FullTcp/Sack
  133. *
  134. * See tcl/lib/ns-default.tcl for init methods for
  135. * Tahoe, Newreno, and Sack
  136. */
  137.  
  138. static class FullTcpClass : public TclClass {
  139. public:
  140. FullTcpClass() : TclClass("Agent/TCP/FullTcp") {}
  141. TclObject* create(int, const char*const*) {
  142. return (new FullTcpAgent());
  143. }
  144. } class_full;
  145.  
  146. static class TahoeFullTcpClass : public TclClass {
  147. public:
  148. TahoeFullTcpClass() : TclClass("Agent/TCP/FullTcp/Tahoe") {}
  149. TclObject* create(int, const char*const*) {
  150. // ns-default sets reno_fastrecov_ to false
  151. return (new TahoeFullTcpAgent());
  152. }
  153. } class_tahoe_full;
  154.  
  155. static class NewRenoFullTcpClass : public TclClass {
  156. public:
  157. NewRenoFullTcpClass() : TclClass("Agent/TCP/FullTcp/Newreno") {}
  158. TclObject* create(int, const char*const*) {
  159. // ns-default sets open_cwnd_on_pack_ to false
  160. return (new NewRenoFullTcpAgent());
  161. }
  162. } class_newreno_full;
  163.  
  164. static class SackFullTcpClass : public TclClass {
  165. public:
  166. SackFullTcpClass() : TclClass("Agent/TCP/FullTcp/Sack") {}
  167. TclObject* create(int, const char*const*) {
  168. // ns-default sets reno_fastrecov_ to false
  169. // ns-default sets open_cwnd_on_pack_ to false
  170. return (new SackFullTcpAgent());
  171. }
  172. } class_sack_full;
  173.  
  174. /*
  175. * Delayed-binding variable linkage
  176. */
  177.  
  178. void
  179. FullTcpAgent::delay_bind_init_all()
  180. {
  181. delay_bind_init_one("segsperack_");
  182. delay_bind_init_one("segsize_");
  183. delay_bind_init_one("tcprexmtthresh_");
  184. delay_bind_init_one("iss_");
  185. delay_bind_init_one("nodelay_");
  186. delay_bind_init_one("data_on_syn_");
  187. delay_bind_init_one("dupseg_fix_");
  188. delay_bind_init_one("dupack_reset_");
  189. delay_bind_init_one("close_on_empty_");
  190. delay_bind_init_one("signal_on_empty_");
  191. delay_bind_init_one("interval_");
  192. delay_bind_init_one("ts_option_size_");
  193. delay_bind_init_one("reno_fastrecov_");
  194. delay_bind_init_one("pipectrl_");
  195. delay_bind_init_one("open_cwnd_on_pack_");
  196. delay_bind_init_one("halfclose_");
  197. delay_bind_init_one("nopredict_");
  198. delay_bind_init_one("ecn_syn_");
  199. delay_bind_init_one("ecn_syn_wait_");
  200. delay_bind_init_one("debug_");
  201. delay_bind_init_one("spa_thresh_");
  202.  
  203. TcpAgent::delay_bind_init_all();
  204.  
  205. reset();
  206. }
  207.  
  208. int
  209. FullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
  210. {
  211. if (delay_bind(varName, localName, "segsperack_", &segs_per_ack_, tracer)) return TCL_OK;
  212. if (delay_bind(varName, localName, "segsize_", &maxseg_, tracer)) return TCL_OK;
  213. if (delay_bind(varName, localName, "tcprexmtthresh_", &tcprexmtthresh_, tracer)) return TCL_OK;
  214. if (delay_bind(varName, localName, "iss_", &iss_, tracer)) return TCL_OK;
  215. if (delay_bind(varName, localName, "spa_thresh_", &spa_thresh_, tracer)) return TCL_OK;
  216. if (delay_bind_bool(varName, localName, "nodelay_", &nodelay_, tracer)) return TCL_OK;
  217. if (delay_bind_bool(varName, localName, "data_on_syn_", &data_on_syn_, tracer)) return TCL_OK;
  218. if (delay_bind_bool(varName, localName, "dupseg_fix_", &dupseg_fix_, tracer)) return TCL_OK;
  219. if (delay_bind_bool(varName, localName, "dupack_reset_", &dupack_reset_, tracer)) return TCL_OK;
  220. if (delay_bind_bool(varName, localName, "close_on_empty_", &close_on_empty_, tracer)) return TCL_OK;
  221. if (delay_bind_bool(varName, localName, "signal_on_empty_", &signal_on_empty_, tracer)) return TCL_OK;
  222. if (delay_bind_time(varName, localName, "interval_", &delack_interval_, tracer)) return TCL_OK;
  223. if (delay_bind(varName, localName, "ts_option_size_", &ts_option_size_, tracer)) return TCL_OK;
  224. if (delay_bind_bool(varName, localName, "reno_fastrecov_", &reno_fastrecov_, tracer)) return TCL_OK;
  225. if (delay_bind_bool(varName, localName, "pipectrl_", &pipectrl_, tracer)) return TCL_OK;
  226. if (delay_bind_bool(varName, localName, "open_cwnd_on_pack_", &open_cwnd_on_pack_, tracer)) return TCL_OK;
  227. if (delay_bind_bool(varName, localName, "halfclose_", &halfclose_, tracer)) return TCL_OK;
  228. if (delay_bind_bool(varName, localName, "nopredict_", &nopredict_, tracer)) return TCL_OK;
  229. if (delay_bind_bool(varName, localName, "ecn_syn_", &ecn_syn_, tracer)) return TCL_OK;
  230. if (delay_bind(varName, localName, "ecn_syn_wait_", &ecn_syn_wait_, tracer)) return TCL_OK;
  231. if (delay_bind_bool(varName, localName, "debug_", &debug_, tracer)) return TCL_OK;
  232.  
  233. return TcpAgent::delay_bind_dispatch(varName, localName, tracer);
  234. }
  235.  
  236. void
  237. SackFullTcpAgent::delay_bind_init_all()
  238. {
  239. delay_bind_init_one("clear_on_timeout_");
  240. delay_bind_init_one("sack_rtx_cthresh_");
  241. delay_bind_init_one("sack_rtx_bthresh_");
  242. delay_bind_init_one("sack_block_size_");
  243. delay_bind_init_one("sack_option_size_");
  244. delay_bind_init_one("max_sack_blocks_");
  245. delay_bind_init_one("sack_rtx_threshmode_");
  246. FullTcpAgent::delay_bind_init_all();
  247. }
  248.  
  249. int
  250. SackFullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
  251. {
  252. if (delay_bind_bool(varName, localName, "clear_on_timeout_", &clear_on_timeout_, tracer)) return TCL_OK;
  253. if (delay_bind(varName, localName, "sack_rtx_cthresh_", &sack_rtx_cthresh_, tracer)) return TCL_OK;
  254. if (delay_bind(varName, localName, "sack_rtx_bthresh_", &sack_rtx_bthresh_, tracer)) return TCL_OK;
  255. if (delay_bind(varName, localName, "sack_rtx_threshmode_", &sack_rtx_threshmode_, tracer)) return TCL_OK;
  256. if (delay_bind(varName, localName, "sack_block_size_", &sack_block_size_, tracer)) return TCL_OK;
  257. if (delay_bind(varName, localName, "sack_option_size_", &sack_option_size_, tracer)) return TCL_OK;
  258. if (delay_bind(varName, localName, "max_sack_blocks_", &max_sack_blocks_, tracer)) return TCL_OK;
  259. return FullTcpAgent::delay_bind_dispatch(varName, localName, tracer);
  260. }
  261.  
  262. int
  263. FullTcpAgent::command(int argc, const char*const* argv)
  264. {
  265. // would like to have some "connect" primitive
  266. // here, but the problem is that we get called before
  267. // the simulation is running and we want to send a SYN.
  268. // Because no routing exists yet, this fails.
  269. // Instead, see code in advance().
  270. //
  271. // listen can happen any time because it just changes state_
  272. //
  273. // close is designed to happen at some point after the
  274. // simulation is running (using an ns 'at' command)
  275.  
  276. if (argc == ) {
  277. if (strcmp(argv[], "listen") == ) {
  278. // just a state transition
  279. listen();
  280. return (TCL_OK);
  281. }
  282. if (strcmp(argv[], "close") == ) {
  283. usrclosed();
  284. return (TCL_OK);
  285. }
  286. }
  287. if (argc == ) {
  288. if (strcmp(argv[], "advance") == ) {
  289. advanceby(atoi(argv[]));
  290. return (TCL_OK);
  291. }
  292. if (strcmp(argv[], "advanceby") == ) {
  293. advanceby(atoi(argv[]));
  294. return (TCL_OK);
  295. }
  296. if (strcmp(argv[], "advance-bytes") == ) {
  297. advance_bytes(atoi(argv[]));
  298. return (TCL_OK);
  299. }
  300. }
  301. if (argc == ) {
  302. if (strcmp(argv[], "sendmsg") == ) {
  303. sendmsg(atoi(argv[]), argv[]);
  304. return (TCL_OK);
  305. }
  306. }
  307. return (TcpAgent::command(argc, argv));
  308. }
  309.  
  310. /*
  311. * "User Interface" Functions for Full TCP
  312. * advanceby(number of packets)
  313. * advance_bytes(number of bytes)
  314. * sendmsg(int bytes, char* buf)
  315. * listen
  316. * close
  317. */
  318.  
  319. /*
  320. * the 'advance' interface to the regular tcp is in packet
  321. * units. Here we scale this to bytes for full tcp.
  322. *
  323. * 'advance' is normally called by an "application" (i.e. data source)
  324. * to signal that there is something to send
  325. *
  326. * 'curseq_' is the sequence number of the last byte provided
  327. * by the application. In the case where no data has been supplied
  328. * by the application, curseq_ is the iss_.
  329. */
  330. void
  331. FullTcpAgent::advanceby(int np)
  332. {
  333. // XXX hack:
  334. // because np is in packets and a data source
  335. // may pass a *huge* number as a way to tell us
  336. // to go forever, just look for the huge number
  337. // and if it's there, pre-divide it
  338. if (np >= 0x10000000)
  339. np /= maxseg_;
  340.  
  341. advance_bytes(np * maxseg_);
  342. return;
  343. }
  344.  
  345. /*
  346. * the byte-oriented interface: advance_bytes(int nbytes)
  347. */
  348.  
  349. void
  350. FullTcpAgent::advance_bytes(int nb)
  351. {
  352.  
  353. //
  354. // state-specific operations:
  355. // if CLOSED or LISTEN, reset and try a new active open/connect
  356. // if ESTABLISHED, queue and try to send more
  357. // if SYN_SENT or SYN_RCVD, just queue
  358. // if above ESTABLISHED, we are closing, so don't allow
  359. //
  360.  
  361. switch (state_) {
  362.  
  363. case TCPS_CLOSED:
  364. case TCPS_LISTEN:
  365. reset();
  366. curseq_ = iss_ + nb;
  367. connect(); // initiate new connection
  368. break;
  369.  
  370. case TCPS_ESTABLISHED:
  371. case TCPS_SYN_SENT:
  372. case TCPS_SYN_RECEIVED:
  373. if (curseq_ < iss_)
  374. curseq_ = iss_;
  375. curseq_ += nb;
  376. break;
  377.  
  378. default:
  379. if (debug_)
  380. fprintf(stderr, "%f: FullTcpAgent::advance(%s): cannot advance while in state %s\n",
  381. now(), name(), statestr(state_));
  382.  
  383. }
  384.  
  385. if (state_ == TCPS_ESTABLISHED)
  386. send_much(, REASON_NORMAL, maxburst_);
  387.  
  388. return;
  389. }
  390.  
  391. /*
  392. * If MSG_EOF is set, by setting close_on_empty_ to TRUE, we ensure that
  393. * a FIN will be sent when the send buffer emptys.
  394. * If DAT_EOF is set, the callback function done_data is called
  395. * when the send buffer empty
  396. *
  397. * When (in the future?) FullTcpAgent implements T/TCP, avoidance of 3-way
  398. * handshake can be handled in this function.
  399. */
  400. void
  401. FullTcpAgent::sendmsg(int nbytes, const char *flags)
  402. {
  403. if (flags && strcmp(flags, "MSG_EOF") == )
  404. close_on_empty_ = TRUE;
  405. if (flags && strcmp(flags, "DAT_EOF") == )
  406. signal_on_empty_ = TRUE;
  407.  
  408. if (nbytes == -) {
  409. infinite_send_ = TRUE;
  410. advance_bytes();
  411. } else
  412. advance_bytes(nbytes);
  413. }
  414.  
  415. /*
  416. * do an active open
  417. * (in real TCP, see tcp_usrreq, case PRU_CONNECT)
  418. */
  419. void
  420. FullTcpAgent::connect()
  421. {
  422. newstate(TCPS_SYN_SENT); // sending a SYN now
  423. sent(iss_, foutput(iss_, REASON_NORMAL));
  424. return;
  425. }
  426.  
  427. /*
  428. * be a passive opener
  429. * (in real TCP, see tcp_usrreq, case PRU_LISTEN)
  430. * (for simulation, make this peer's ptype ACKs)
  431. */
  432. void
  433. FullTcpAgent::listen()
  434. {
  435. newstate(TCPS_LISTEN);
  436. type_ = PT_ACK; // instead of PT_TCP
  437. }
  438.  
  439. /*
  440. * This function is invoked when the sender buffer is empty. It in turn
  441. * invokes the Tcl done_data procedure that was registered with TCP.
  442. */
  443.  
  444. void
  445. FullTcpAgent::bufferempty()
  446. {
  447. signal_on_empty_=FALSE;
  448. Tcl::instance().evalf("%s done_data", this->name());
  449. }
  450.  
  451. /*
  452. * called when user/application performs 'close'
  453. */
  454.  
  455. void
  456. FullTcpAgent::usrclosed()
  457. {
  458. curseq_ = maxseq_ - ; // now, no more data
  459. infinite_send_ = FALSE; // stop infinite send
  460.  
  461. switch (state_) {
  462. case TCPS_CLOSED:
  463. case TCPS_LISTEN:
  464. cancel_timers();
  465. newstate(TCPS_CLOSED);
  466. finish();
  467. break;
  468. case TCPS_SYN_SENT:
  469. newstate(TCPS_CLOSED);
  470. /* fall through */
  471. case TCPS_LAST_ACK:
  472. flags_ |= TF_NEEDFIN;
  473. send_much(, REASON_NORMAL, maxburst_);
  474. break;
  475. case TCPS_SYN_RECEIVED:
  476. case TCPS_ESTABLISHED:
  477. newstate(TCPS_FIN_WAIT_1);
  478. flags_ |= TF_NEEDFIN;
  479. send_much(, REASON_NORMAL, maxburst_);
  480. break;
  481. case TCPS_CLOSE_WAIT:
  482. newstate(TCPS_LAST_ACK);
  483. flags_ |= TF_NEEDFIN;
  484. send_much(, REASON_NORMAL, maxburst_);
  485. break;
  486. case TCPS_FIN_WAIT_1:
  487. case TCPS_FIN_WAIT_2:
  488. case TCPS_CLOSING:
  489. /* usr asked for a close more than once [?] */
  490. if (debug_)
  491. fprintf(stderr,
  492. "%f FullTcpAgent(%s): app close in bad state %s\n",
  493. now(), name(), statestr(state_));
  494. break;
  495. default:
  496. if (debug_)
  497. fprintf(stderr,
  498. "%f FullTcpAgent(%s): app close in unknown state %s\n",
  499. now(), name(), statestr(state_));
  500. }
  501.  
  502. return;
  503. }
  504.  
  505. /*
  506. * Utility type functions
  507. */
  508.  
  509. void
  510. FullTcpAgent::cancel_timers()
  511. {
  512.  
  513. // cancel: rtx, burstsend, delsnd
  514. TcpAgent::cancel_timers();
  515. // cancel: delack
  516. delack_timer_.force_cancel();
  517. }
  518.  
  519. void
  520. FullTcpAgent::newstate(int state)
  521. {
  522. //printf("%f(%s): state changed from %s to %s\n",
  523. //now(), name(), statestr(state_), statestr(state));
  524.  
  525. state_ = state;
  526. }
  527.  
  528. void
  529. FullTcpAgent::prpkt(Packet *pkt)
  530. {
  531. hdr_tcp *tcph = hdr_tcp::access(pkt); // TCP header
  532. hdr_cmn *th = hdr_cmn::access(pkt); // common header (size, etc)
  533. //hdr_flags *fh = hdr_flags::access(pkt); // flags (CWR, CE, bits)
  534. hdr_ip* iph = hdr_ip::access(pkt);
  535. int datalen = th->size() - tcph->hlen(); // # payload bytes
  536.  
  537. 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",
  538. th->uid(),
  539. iph->saddr(), iph->sport(),
  540. iph->daddr(), iph->dport(),
  541. tcph->hlen(),
  542. datalen,
  543. tcph->seqno(),
  544. tcph->ackno(),
  545. tcph->flags(), flagstr(tcph->flags()),
  546. tcph->sa_length(),
  547. tcph->reason());
  548. }
  549.  
  550. char *
  551. FullTcpAgent::flagstr(int hflags)
  552. {
  553. // update this if tcp header flags change
  554. static char *flagstrs[] = {
  555. "<null>", "<FIN>", "<SYN>", "<SYN,FIN>", // 0-3
  556. "<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>", // 4-7
  557. "<PSH>", "<PSH,FIN>", "<PSH,SYN>", "<PSH,SYN,FIN>", // 0x08-0x0b
  558. /* do not use <??, in next line because that's an ANSI trigraph */
  559. "<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>", // 0x0c-0x0f
  560. "<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>", // 0x10-0x13
  561. "<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>", // 0x14-0x17
  562. "<PSH,ACK>", "<PSH,ACK,FIN>", "<PSH,ACK,SYN>", "<PSH,ACK,SYN,FIN>", // 0x18-0x1b
  563. };
  564. if (hflags < || (hflags > )) {
  565. /* Added strings for CWR and ECE -M. Weigle 6/27/02 */
  566. if (hflags == )
  567. return ("<ECE,PSH>");
  568. else if (hflags == )
  569. return ("<ECE,ACK>");
  570. else if (hflags == )
  571. return ("<ECE,PSH,ACK>");
  572. else if (hflags == )
  573. return ("<CWR,PSH,ACK>");
  574. else if (hflags == )
  575. return ("<CWR,PSH,ACK,FIN>");
  576. else
  577. return ("<invalid>");
  578. }
  579. return (flagstrs[hflags]);
  580. }
  581.  
  582. char *
  583. FullTcpAgent::statestr(int state)
  584. {
  585. static char *statestrs[TCP_NSTATES] = {
  586. "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD",
  587. "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
  588. "LAST_ACK", "FIN_WAIT_2"
  589. };
  590. if (state < || (state >= TCP_NSTATES))
  591. return ("INVALID");
  592. return (statestrs[state]);
  593. }
  594.  
  595. void
  596. DelAckTimer::expire(Event *) {
  597. a_->timeout(TCP_TIMER_DELACK);
  598. }
  599.  
  600. /*
  601. * reset to starting point, don't set state_ here,
  602. * because our starting point might be LISTEN rather
  603. * than CLOSED if we're a passive opener
  604. */
  605. void
  606. FullTcpAgent::reset()
  607. {
  608. cancel_timers(); // cancel timers first
  609. TcpAgent::reset(); // resets most variables
  610. rq_.clear(); // clear reassembly queue
  611. rtt_init(); // zero rtt, srtt, backoff
  612.  
  613. last_ack_sent_ = -;
  614. rcv_nxt_ = -;
  615. pipe_ = ;
  616. rtxbytes_ = ;
  617. flags_ = ;
  618. t_seqno_ = iss_;
  619. maxseq_ = -;
  620. irs_ = -;
  621. last_send_time_ = -1.0;
  622. if (ts_option_)
  623. recent_ = recent_age_ = 0.0;
  624. else
  625. recent_ = recent_age_ = -1.0;
  626.  
  627. fastrecov_ = FALSE;
  628.  
  629. closed_ = ;
  630. close_on_empty_ = FALSE;
  631.  
  632. if (ecn_syn_)
  633. ecn_syn_next_ = ;
  634. else
  635. ecn_syn_next_ = ;
  636.  
  637. }
  638.  
  639. /*
  640. * This function is invoked when the connection is done. It in turn
  641. * invokes the Tcl finish procedure that was registered with TCP.
  642. * This function mimics tcp_close()
  643. */
  644.  
  645. void
  646. FullTcpAgent::finish()
  647. {
  648. Tcl::instance().evalf("%s done", this->name());
  649. }
  650. /*
  651. * headersize:
  652. * how big is an IP+TCP header in bytes; include options such as ts
  653. * this function should be virtual so others (e.g. SACK) can override
  654. */
  655. int
  656. FullTcpAgent::headersize()
  657. {
  658. int total = tcpip_base_hdr_size_;
  659. if (total < ) {
  660. fprintf(stderr,
  661. "%f: FullTcpAgent(%s): warning: tcpip hdr size is only %d bytes\n",
  662. now(), name(), tcpip_base_hdr_size_);
  663. }
  664.  
  665. if (ts_option_)
  666. total += ts_option_size_;
  667.  
  668. return (total);
  669. }
  670.  
  671. /*
  672. * flags that are completely dependent on the tcp state
  673. * these are used for the next outgoing packet in foutput()
  674. * (in real TCP, see tcp_fsm.h, the "tcp_outflags" array)
  675. */
  676. int
  677. FullTcpAgent::outflags()
  678. {
  679. // in real TCP an RST is added in the CLOSED state
  680. static int tcp_outflags[TCP_NSTATES] = {
  681. TH_ACK, /* 0, CLOSED */
  682. , /* 1, LISTEN */
  683. TH_SYN, /* 2, SYN_SENT */
  684. TH_SYN|TH_ACK, /* 3, SYN_RECEIVED */
  685. TH_ACK, /* 4, ESTABLISHED */
  686. TH_ACK, /* 5, CLOSE_WAIT */
  687. TH_FIN|TH_ACK, /* 6, FIN_WAIT_1 */
  688. TH_FIN|TH_ACK, /* 7, CLOSING */
  689. TH_FIN|TH_ACK, /* 8, LAST_ACK */
  690. TH_ACK, /* 9, FIN_WAIT_2 */
  691. /* 10, TIME_WAIT --- not used in simulator */
  692. };
  693.  
  694. if (state_ < || (state_ >= TCP_NSTATES)) {
  695. fprintf(stderr, "%f FullTcpAgent(%s): invalid state %d\n",
  696. now(), name(), state_);
  697. return (0x0);
  698. }
  699.  
  700. return (tcp_outflags[state_]);
  701. }
  702.  
  703. /*
  704. * reaass() -- extract the appropriate fields from the packet
  705. * and pass this info the ReassemblyQueue add routine
  706. *
  707. * returns the TCP header flags representing the "or" of
  708. * the flags contained in the adjacent sequence # blocks
  709. */
  710.  
  711. int
  712. FullTcpAgent::reass(Packet* pkt)
  713. {
  714. hdr_tcp *tcph = hdr_tcp::access(pkt);
  715. hdr_cmn *th = hdr_cmn::access(pkt);
  716.  
  717. int start = tcph->seqno();
  718. int end = start + th->size() - tcph->hlen();
  719. int tiflags = tcph->flags();
  720. int fillshole = (start == rcv_nxt_);
  721. int flags;
  722.  
  723. // end contains the seq of the last byte of
  724. // in the packet plus one
  725.  
  726. if (start == end && (tiflags & TH_FIN) == ) {
  727. fprintf(stderr, "%f: FullTcpAgent(%s)::reass() -- bad condition - adding non-FIN zero-len seg\n",
  728. now(), name());
  729. abort();
  730. }
  731.  
  732. flags = rq_.add(start, end, tiflags, );
  733.  
  734. //present:
  735. //
  736. // If we've never received a SYN (unlikely)
  737. // or this is an out of order addition, no reason to coalesce
  738. //
  739.  
  740. if (TCPS_HAVERCVDSYN(state_) == || !fillshole) {
  741. return (0x00);
  742. }
  743. //
  744. // If we get some data in SYN_RECVD, no need to present to user yet
  745. //
  746. if (state_ == TCPS_SYN_RECEIVED && (end > start))
  747. return (0x00);
  748.  
  749. // clear out data that has been passed, up to rcv_nxt_,
  750. // collects flags
  751.  
  752. flags |= rq_.cleartonxt();
  753.  
  754. return (flags);
  755. }
  756.  
  757. /*
  758. * utility function to set rcv_next_ during inital exchange of seq #s
  759. */
  760.  
  761. int
  762. FullTcpAgent::rcvseqinit(int seq, int dlen)
  763. {
  764. return (seq + dlen + );
  765. }
  766.  
  767. /*
  768. * build a header with the timestamp option if asked
  769. */
  770. int
  771. FullTcpAgent::build_options(hdr_tcp* tcph)
  772. {
  773. int total = ;
  774. if (ts_option_) {
  775. tcph->ts() = now();
  776. tcph->ts_echo() = recent_;
  777. total += ts_option_size_;
  778. } else {
  779. tcph->ts() = tcph->ts_echo() = -1.0;
  780. }
  781. return (total);
  782. }
  783.  
  784. /*
  785. * pack() -- is the ACK a partial ACK? (not past recover_)
  786. */
  787.  
  788. int
  789. FullTcpAgent::pack(Packet *pkt)
  790. {
  791. hdr_tcp *tcph = hdr_tcp::access(pkt);
  792. /* Added check for fast recovery. -M. Weigle 5/2/02 */
  793. return (fastrecov_ && tcph->ackno() >= highest_ack_ &&
  794. tcph->ackno() < recover_);
  795. }
  796.  
  797. /*
  798. * baseline reno TCP exists fast recovery on a partial ACK
  799. */
  800.  
  801. void
  802. FullTcpAgent::pack_action(Packet*)
  803. {
  804. if (reno_fastrecov_ && fastrecov_ && cwnd_ > double(ssthresh_)) {
  805. cwnd_ = double(ssthresh_); // retract window if inflated
  806. }
  807. fastrecov_ = FALSE;
  808. //printf("%f: EXITED FAST RECOVERY\n", now());
  809. dupacks_ = ;
  810. }
  811.  
  812. /*
  813. * ack_action -- same as partial ACK action for base Reno TCP
  814. */
  815.  
  816. void
  817. FullTcpAgent::ack_action(Packet* p)
  818. {
  819. FullTcpAgent::pack_action(p);
  820. }
  821.  
  822. /*
  823. * sendpacket:
  824. * allocate a packet, fill in header fields, and send
  825. * also keeps stats on # of data pkts, acks, re-xmits, etc
  826. *
  827. * fill in packet fields. Agent::allocpkt() fills
  828. * in most of the network layer fields for us.
  829. * So fill in tcp hdr and adjust the packet size.
  830. *
  831. * Also, set the size of the tcp header.
  832. */
  833. void
  834. FullTcpAgent::sendpacket(int seqno, int ackno, int pflags, int datalen, int reason, Packet *p)
  835. {
  836. if (!p) p = allocpkt();
  837. hdr_tcp *tcph = hdr_tcp::access(p);
  838. hdr_flags *fh = hdr_flags::access(p);
  839.  
  840. /* build basic header w/options */
  841.  
  842. tcph->seqno() = seqno;
  843. tcph->ackno() = ackno;
  844. tcph->flags() = pflags;
  845. tcph->reason() |= reason; // make tcph->reason look like ns1 pkt->flags?
  846. tcph->sa_length() = ; // may be increased by build_options()
  847. tcph->hlen() = tcpip_base_hdr_size_;
  848. tcph->hlen() += build_options(tcph);
  849.  
  850. /*
  851. * Explicit Congestion Notification (ECN) related:
  852. * Bits in header:
  853. * ECT (EC Capable Transport),
  854. * ECNECHO (ECHO of ECN Notification generated at router),
  855. * CWR (Congestion Window Reduced from RFC 2481)
  856. * States in TCP:
  857. * ecn_: I am supposed to do ECN if my peer does
  858. * ect_: I am doing ECN (ecn_ should be T and peer does ECN)
  859. */
  860.  
  861. if (datalen > && ecn_ ){
  862. // set ect on data packets
  863. fh->ect() = ect_; // on after mutual agreement on ECT
  864. } else if (ecn_ && ecn_syn_ && ecn_syn_next_ && (pflags & TH_SYN) && (pflags & TH_ACK)) {
  865. // set ect on syn/ack packet, if syn packet was negotiating ECT
  866. fh->ect() = ect_;
  867. } else {
  868. /* Set ect() to 0. -M. Weigle 1/19/05 */
  869. fh->ect() = ;
  870. }
  871. if (ecn_ && ect_ && recent_ce_ ) {
  872. // This is needed here for the ACK in a SYN, SYN/ACK, ACK
  873. // sequence.
  874. pflags |= TH_ECE;
  875. }
  876. // fill in CWR and ECE bits which don't actually sit in
  877. // the tcp_flags but in hdr_flags
  878. if ( pflags & TH_ECE) {
  879. fh->ecnecho() = ;
  880. } else {
  881. fh->ecnecho() = ;
  882. }
  883. if ( pflags & TH_CWR ) {
  884. fh->cong_action() = ;
  885. }
  886. else {
  887. /* Set cong_action() to 0 -M. Weigle 1/19/05 */
  888. fh->cong_action() = ;
  889. }
  890.  
  891. /* actual size is data length plus header length */
  892.  
  893. hdr_cmn *ch = hdr_cmn::access(p);
  894. ch->size() = datalen + tcph->hlen();
  895.  
  896. if (datalen <= )
  897. ++nackpack_;
  898. else {
  899. ++ndatapack_;
  900. ndatabytes_ += datalen;
  901. last_send_time_ = now(); // time of last data
  902. }
  903. if (reason == REASON_TIMEOUT || reason == REASON_DUPACK || reason == REASON_SACK) {
  904. ++nrexmitpack_;
  905. nrexmitbytes_ += datalen;
  906. }
  907.  
  908. last_ack_sent_ = ackno;
  909.  
  910. //if (state_ != TCPS_ESTABLISHED) {
  911. //printf("%f(%s)[state:%s]: sending pkt ", now(), name(), statestr(state_));
  912. //prpkt(p);
  913. //}
  914.  
  915. send(p, );
  916.  
  917. return;
  918. }
  919.  
  920. //
  921. // reset_rtx_timer: called during a retransmission timeout
  922. // to perform exponential backoff. Also, note that because
  923. // we have performed a retransmission, our rtt timer is now
  924. // invalidated (indicate this by setting rtt_active_ false)
  925. //
  926. void
  927. FullTcpAgent::reset_rtx_timer(int /* mild */)
  928. {
  929. // cancel old timer, set a new one
  930. /* if there is no outstanding data, don't back off rtx timer *
  931. * (Fix from T. Kelly.) */
  932. if (!(highest_ack_ == maxseq_ && restart_bugfix_)) {
  933. rtt_backoff(); // double current timeout
  934. }
  935. set_rtx_timer(); // set new timer
  936. rtt_active_ = FALSE; // no timing during this window
  937. }
  938.  
  939. /*
  940. * see if we should send a segment, and if so, send it
  941. * (may be ACK or data)
  942. * return the number of data bytes sent (count a SYN or FIN as 1 each)
  943. *
  944. * simulator var, desc (name in real TCP)
  945. * --------------------------------------
  946. * maxseq_, largest seq# we've sent plus one (snd_max)
  947. * flags_, flags regarding our internal state (t_state)
  948. * pflags, a local used to build up the tcp header flags (flags)
  949. * curseq_, is the highest sequence number given to us by "application"
  950. * highest_ack_, the highest ACK we've seen for our data (snd_una-1)
  951. * seqno, the next seq# we're going to send (snd_nxt)
  952. */
  953. int
  954. FullTcpAgent::foutput(int seqno, int reason)
  955. {
  956. // if maxseg_ not set, set it appropriately
  957. // Q: how can this happen?
  958.  
  959. if (maxseg_ == )
  960. maxseg_ = size_ - headersize();
  961. else
  962. size_ = maxseg_ + headersize();
  963.  
  964. int is_retransmit = (seqno < maxseq_);
  965. int quiet = (highest_ack_ == maxseq_);
  966. int pflags = outflags();
  967. int syn = (seqno == iss_);
  968. int emptying_buffer = FALSE;
  969. int buffered_bytes = (infinite_send_) ? TCP_MAXSEQ :
  970. curseq_ - highest_ack_ + ;
  971.  
  972. int win = window() * maxseg_; // window (in bytes)
  973. int off = seqno - highest_ack_; // offset of seg in window
  974. int datalen;
  975. //int amtsent = 0;
  976.  
  977. // be careful if we have not received any ACK yet
  978. if (highest_ack_ < ) {
  979. if (!infinite_send_)
  980. buffered_bytes = curseq_ - iss_;;
  981. off = seqno - iss_;
  982. }
  983.  
  984. if (syn && !data_on_syn_)
  985. datalen = ;
  986. else if (pipectrl_)
  987. datalen = buffered_bytes - off;
  988. else
  989. datalen = min(buffered_bytes, win) - off;
  990.  
  991. if ((signal_on_empty_) && (!buffered_bytes) && (!syn))
  992. bufferempty();
  993.  
  994. //
  995. // in real TCP datalen (len) could be < 0 if there was window
  996. // shrinkage, or if a FIN has been sent and neither ACKd nor
  997. // retransmitted. Only this 2nd case concerns us here...
  998. //
  999. if (datalen < ) {
  1000. datalen = ;
  1001. } else if (datalen > maxseg_) {
  1002. datalen = maxseg_;
  1003. }
  1004.  
  1005. //
  1006. // this is an option that causes us to slow-start if we've
  1007. // been idle for a "long" time, where long means a rto or longer
  1008. // the slow-start is a sort that does not set ssthresh
  1009. //
  1010.  
  1011. if (slow_start_restart_ && quiet && datalen > ) {
  1012. if (idle_restart()) {
  1013. slowdown(CLOSE_CWND_INIT);
  1014. }
  1015. }
  1016.  
  1017. //
  1018. // see if sending this packet will empty the send buffer
  1019. // a dataless SYN packet counts also
  1020. //
  1021.  
  1022. if (!infinite_send_ && ((seqno + datalen) > curseq_ ||
  1023. (syn && datalen == ))) {
  1024. emptying_buffer = TRUE;
  1025. //
  1026. // if not a retransmission, notify application that
  1027. // everything has been sent out at least once.
  1028. //
  1029. if (!syn) {
  1030. idle();
  1031. if (close_on_empty_ && quiet) {
  1032. flags_ |= TF_NEEDCLOSE;
  1033. }
  1034. }
  1035. pflags |= TH_PUSH;
  1036. //
  1037. // if close_on_empty set, we are finished
  1038. // with this connection; close it
  1039. //
  1040. } else {
  1041. /* not emptying buffer, so can't be FIN */
  1042. pflags &= ~TH_FIN;
  1043. }
  1044. if (infinite_send_ && (syn && datalen == ))
  1045. pflags |= TH_PUSH; // set PUSH for dataless SYN
  1046.  
  1047. /* sender SWS avoidance (Nagle) */
  1048.  
  1049. if (datalen > ) {
  1050. // if full-sized segment, ok
  1051. if (datalen == maxseg_)
  1052. goto send;
  1053. // if Nagle disabled and buffer clearing, ok
  1054. if ((quiet || nodelay_) && emptying_buffer)
  1055. goto send;
  1056. // if a retransmission
  1057. if (is_retransmit)
  1058. goto send;
  1059. // if big "enough", ok...
  1060. // (this is not a likely case, and would
  1061. // only happen for tiny windows)
  1062. if (datalen >= ((wnd_ * maxseg_) / 2.0))
  1063. goto send;
  1064. }
  1065.  
  1066. if (need_send())
  1067. goto send;
  1068.  
  1069. /*
  1070. * send now if a control packet or we owe peer an ACK
  1071. * TF_ACKNOW can be set during connection establishment and
  1072. * to generate acks for out-of-order data
  1073. */
  1074.  
  1075. if ((flags_ & (TF_ACKNOW|TF_NEEDCLOSE)) ||
  1076. (pflags & (TH_SYN|TH_FIN))) {
  1077. goto send;
  1078. }
  1079.  
  1080. /*
  1081. * No reason to send a segment, just return.
  1082. */
  1083. return ;
  1084.  
  1085. send:
  1086.  
  1087. // is a syn or fin?
  1088.  
  1089. syn = (pflags & TH_SYN) ? : ;
  1090. int fin = (pflags & TH_FIN) ? : ;
  1091.  
  1092. /* setup ECN syn and ECN SYN+ACK packet headers */
  1093. if (ecn_ && syn && !(pflags & TH_ACK)){
  1094. pflags |= TH_ECE;
  1095. pflags |= TH_CWR;
  1096. }
  1097. if (ecn_ && syn && (pflags & TH_ACK)){
  1098. pflags |= TH_ECE;
  1099. pflags &= ~TH_CWR;
  1100. }
  1101. else if (ecn_ && ect_ && cong_action_ &&
  1102. (!is_retransmit || SetCWRonRetransmit_)) {
  1103. /*
  1104. * Don't set CWR for a retranmitted SYN+ACK (has ecn_
  1105. * and cong_action_ set).
  1106. * -M. Weigle 6/19/02
  1107. *
  1108. * SetCWRonRetransmit_ was changed to true,
  1109. * allowing CWR on retransmitted data packets.
  1110. * See test ecn_burstyEcn_reno_full
  1111. * in test-suite-ecn-full.tcl.
  1112. * - Sally Floyd, 6/5/08.
  1113. */
  1114. /* set CWR if necessary */
  1115. pflags |= TH_CWR;
  1116. /* Turn cong_action_ off: Added 6/5/08, Sally Floyd. */
  1117. cong_action_ = FALSE;
  1118. }
  1119.  
  1120. /* moved from sendpacket() -M. Weigle 6/19/02 */
  1121. //
  1122. // although CWR bit is ordinarily associated with ECN,
  1123. // it has utility within the simulator for traces. Thus, set
  1124. // it even if we aren't doing ECN
  1125. //
  1126. if (datalen > && cong_action_ && !is_retransmit) {
  1127. pflags |= TH_CWR;
  1128. }
  1129.  
  1130. /* set ECE if necessary */
  1131. if (ecn_ && ect_ && recent_ce_ ) {
  1132. pflags |= TH_ECE;
  1133. }
  1134.  
  1135. /*
  1136. * Tack on the FIN flag to the data segment if close_on_empty_
  1137. * was previously set-- avoids sending a separate FIN
  1138. */
  1139. if (flags_ & TF_NEEDCLOSE) {
  1140. flags_ &= ~TF_NEEDCLOSE;
  1141. if (state_ <= TCPS_ESTABLISHED && state_ != TCPS_CLOSED)
  1142. {
  1143. pflags |=TH_FIN;
  1144. fin = ; /* FIN consumes sequence number */
  1145. newstate(TCPS_FIN_WAIT_1);
  1146. }
  1147. }
  1148. sendpacket(seqno, rcv_nxt_, pflags, datalen, reason);
  1149.  
  1150. /*
  1151. * Data sent (as far as we can tell).
  1152. * Any pending ACK has now been sent.
  1153. */
  1154. flags_ &= ~(TF_ACKNOW|TF_DELACK);
  1155.  
  1156. /*
  1157. * if we have reacted to congestion recently, the
  1158. * slowdown() procedure will have set cong_action_ and
  1159. * sendpacket will have copied that to the outgoing pkt
  1160. * CWR field. If that packet contains data, then
  1161. * it will be reliably delivered, so we are free to turn off the
  1162. * cong_action_ state now If only a pure ACK, we keep the state
  1163. * around until we actually send a segment
  1164. */
  1165.  
  1166. int reliable = datalen + syn + fin; // seq #'s reliably sent
  1167. /*
  1168. * Don't reset cong_action_ until we send new data.
  1169. * -M. Weigle 6/19/02
  1170. */
  1171. if (cong_action_ && reliable > && !is_retransmit)
  1172. cong_action_ = FALSE;
  1173.  
  1174. // highest: greatest sequence number sent + 1
  1175. // and adjusted for SYNs and FINs which use up one number
  1176.  
  1177. int highest = seqno + reliable;
  1178. if (highest > maxseq_) {
  1179. maxseq_ = highest;
  1180. //
  1181. // if we are using conventional RTT estimation,
  1182. // establish timing on this segment
  1183. //
  1184. if (!ts_option_ && rtt_active_ == FALSE) {
  1185. rtt_active_ = TRUE; // set timer
  1186. rtt_seq_ = seqno; // timed seq #
  1187. rtt_ts_ = now(); // when set
  1188. }
  1189. }
  1190.  
  1191. /*
  1192. * Set retransmit timer if not currently set,
  1193. * and not doing an ack or a keep-alive probe.
  1194. * Initial value for retransmit timer is smoothed
  1195. * round-trip time + 2 * round-trip time variance.
  1196. * Future values are rtt + 4 * rttvar.
  1197. */
  1198. if (rtx_timer_.status() != TIMER_PENDING && reliable) {
  1199. set_rtx_timer(); // no timer pending, schedule one
  1200. }
  1201.  
  1202. return (reliable);
  1203. }
  1204.  
  1205. /*
  1206. *
  1207. * send_much: send as much data as we are allowed to. This is
  1208. * controlled by the "pipectrl_" variable. If pipectrl_ is set
  1209. * to FALSE, then we are working as a normal window-based TCP and
  1210. * we are allowed to send whatever the window allows.
  1211. * If pipectrl_ is set to TRUE, then we are allowed to send whatever
  1212. * pipe_ allows us to send. One tricky part is to make sure we
  1213. * do not overshoot the receiver's advertised window if we are
  1214. * in (pipectrl_ == TRUE) mode.
  1215. */
  1216.  
  1217. void
  1218. FullTcpAgent::send_much(int force, int reason, int maxburst)
  1219. {
  1220. int npackets = ; // sent so far
  1221.  
  1222. //if ((int(t_seqno_)) > 1)
  1223. //printf("%f: send_much(f:%d, win:%d, pipectrl:%d, pipe:%d, t_seqno:%d, topwin:%d, maxseq_:%d\n",
  1224. //now(), force, win, pipectrl_, pipe_, int(t_seqno_), topwin, int(maxseq_));
  1225.  
  1226. if (!force && (delsnd_timer_.status() == TIMER_PENDING))
  1227. return;
  1228.  
  1229. while () {
  1230.  
  1231. /*
  1232. * note that if output decides to not actually send
  1233. * (e.g. because of Nagle), then if we don't break out
  1234. * of this loop, we can loop forever at the same
  1235. * simulated time instant
  1236. */
  1237. int amt;
  1238. int seq = nxt_tseq();
  1239. if (!force && !send_allowed(seq))
  1240. break;
  1241. // Q: does this need to be here too?
  1242. if (!force && overhead_ != &&
  1243. (delsnd_timer_.status() != TIMER_PENDING)) {
  1244. delsnd_timer_.resched(Random::uniform(overhead_));
  1245. return;
  1246. }
  1247. if ((amt = foutput(seq, reason)) <= )
  1248. break;
  1249. if ((outflags() & TH_FIN))
  1250. --amt; // don't count FINs
  1251. sent(seq, amt);
  1252. force = ;
  1253.  
  1254. if ((outflags() & (TH_SYN|TH_FIN)) ||
  1255. (maxburst && ++npackets >= maxburst))
  1256. break;
  1257. }
  1258. return;
  1259. }
  1260.  
  1261. /*
  1262. * base TCP: we are allowed to send a sequence number if it
  1263. * is in the window
  1264. */
  1265. int
  1266. FullTcpAgent::send_allowed(int seq)
  1267. {
  1268. int win = window() * maxseg_;
  1269. int topwin = curseq_; // 1 seq number past the last byte we can send
  1270.  
  1271. if ((topwin > highest_ack_ + win) || infinite_send_)
  1272. topwin = highest_ack_ + win;
  1273.  
  1274. return (seq < topwin);
  1275. }
  1276. /*
  1277. * Process an ACK
  1278. * this version of the routine doesn't necessarily
  1279. * require the ack to be one which advances the ack number
  1280. *
  1281. * if this ACKs a rtt estimate
  1282. * indicate we are not timing
  1283. * reset the exponential timer backoff (gamma)
  1284. * update rtt estimate
  1285. * cancel retrans timer if everything is sent and ACK'd, else set it
  1286. * advance the ack number if appropriate
  1287. * update segment to send next if appropriate
  1288. */
  1289. void
  1290. FullTcpAgent::newack(Packet* pkt)
  1291. {
  1292. hdr_tcp *tcph = hdr_tcp::access(pkt);
  1293.  
  1294. register int ackno = tcph->ackno();
  1295. int progress = (ackno > highest_ack_);
  1296.  
  1297. if (ackno == maxseq_) {
  1298. cancel_rtx_timer(); // all data ACKd
  1299. } else if (progress) {
  1300. set_rtx_timer();
  1301. }
  1302.  
  1303. // advance the ack number if this is for new data
  1304. if (progress)
  1305. highest_ack_ = ackno;
  1306.  
  1307. // if we have suffered a retransmit timeout, t_seqno_
  1308. // will have been reset to highest_ ack. If the
  1309. // receiver has cached some data above t_seqno_, the
  1310. // new-ack value could (should) jump forward. We must
  1311. // update t_seqno_ here, otherwise we would be doing
  1312. // go-back-n.
  1313.  
  1314. if (t_seqno_ < highest_ack_)
  1315. t_seqno_ = highest_ack_; // seq# to send next
  1316.  
  1317. /*
  1318. * Update RTT only if it's OK to do so from info in the flags header.
  1319. * This is needed for protocols in which intermediate agents
  1320.  
  1321. * in the network intersperse acks (e.g., ack-reconstructors) for
  1322. * various reasons (without violating e2e semantics).
  1323. */
  1324. hdr_flags *fh = hdr_flags::access(pkt);
  1325.  
  1326. if (!fh->no_ts_) {
  1327. if (ts_option_) {
  1328. recent_age_ = now();
  1329. recent_ = tcph->ts();
  1330. rtt_update(now() - tcph->ts_echo());
  1331. if (ts_resetRTO_ && (!ect_ || !ecn_backoff_ ||
  1332. !hdr_flags::access(pkt)->ecnecho())) {
  1333. // From Andrei Gurtov
  1334. //
  1335. // Don't end backoff if still in ECN-Echo with
  1336. // a congestion window of 1 packet.
  1337. t_backoff_ = ;
  1338. }
  1339. } else if (rtt_active_ && ackno > rtt_seq_) {
  1340. // got an RTT sample, record it
  1341. // "t_backoff_ = 1;" deleted by T. Kelly.
  1342. rtt_active_ = FALSE;
  1343. rtt_update(now() - rtt_ts_);
  1344. }
  1345. if (!ect_ || !ecn_backoff_ ||
  1346. !hdr_flags::access(pkt)->ecnecho()) {
  1347. /*
  1348. * Don't end backoff if still in ECN-Echo with
  1349. * a congestion window of 1 packet.
  1350. * Fix from T. Kelly.
  1351. */
  1352. t_backoff_ = ;
  1353. ecn_backoff_ = ;
  1354. }
  1355.  
  1356. }
  1357. return;
  1358. }
  1359.  
  1360. /*
  1361. * this is the simulated form of the header prediction
  1362. * predicate. While not really necessary for a simulation, it
  1363. * follows the code base more closely and can sometimes help to reveal
  1364. * odd behavior caused by the implementation structure..
  1365. *
  1366. * Here's the comment from the real TCP:
  1367. *
  1368. * Header prediction: check for the two common cases
  1369. * of a uni-directional data xfer. If the packet has
  1370. * no control flags, is in-sequence, the window didn't
  1371. * change and we're not retransmitting, it's a
  1372. * candidate. If the length is zero and the ack moved
  1373. * forward, we're the sender side of the xfer. Just
  1374. * free the data acked & wake any higher level process
  1375. * that was blocked waiting for space. If the length
  1376. * is non-zero and the ack didn't move, we're the
  1377. * receiver side. If we're getting packets in-order
  1378. * (the reassembly queue is empty), add the data to
  1379. * the socket buffer and note that we need a delayed ack.
  1380. * Make sure that the hidden state-flags are also off.
  1381. * Since we check for TCPS_ESTABLISHED above, it can only
  1382. * be TF_NEEDSYN.
  1383. */
  1384.  
  1385. int
  1386. FullTcpAgent::predict_ok(Packet* pkt)
  1387. {
  1388. hdr_tcp *tcph = hdr_tcp::access(pkt);
  1389. hdr_flags *fh = hdr_flags::access(pkt);
  1390.  
  1391. /* not the fastest way to do this, but perhaps clearest */
  1392.  
  1393. int p1 = (state_ == TCPS_ESTABLISHED); // ready
  1394. int p2 = ((tcph->flags() & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK); // ACK
  1395. int p3 = ((flags_ & TF_NEEDFIN) == ); // don't need fin
  1396. int p4 = (!ts_option_ || fh->no_ts_ || (tcph->ts() >= recent_)); // tsok
  1397. int p5 = (tcph->seqno() == rcv_nxt_); // in-order data
  1398. int p6 = (t_seqno_ == maxseq_); // not re-xmit
  1399. int p7 = (!ecn_ || fh->ecnecho() == ); // no ECN
  1400. int p8 = (tcph->sa_length() == ); // no SACK info
  1401.  
  1402. return (p1 && p2 && p3 && p4 && p5 && p6 && p7 && p8);
  1403. }
  1404.  
  1405. /*
  1406. * fast_retransmit using the given seqno
  1407. * perform fast RTX, set recover_, set last_cwnd_action
  1408. */
  1409.  
  1410. int
  1411. FullTcpAgent::fast_retransmit(int seq)
  1412. {
  1413. // we are now going to fast-retransmit and willtrace that event
  1414. trace_event("FAST_RETX");
  1415.  
  1416. recover_ = maxseq_; // recovery target
  1417. last_cwnd_action_ = CWND_ACTION_DUPACK;
  1418. return(foutput(seq, REASON_DUPACK)); // send one pkt
  1419. }
  1420.  
  1421. /*
  1422. * real tcp determines if the remote
  1423. * side should receive a window update/ACK from us, and often
  1424. * results in sending an update every 2 segments, thereby
  1425. * giving the familiar 2-packets-per-ack behavior of TCP.
  1426. * Here, we don't advertise any windows, so we just see if
  1427. * there's at least 'segs_per_ack_' pkts not yet acked
  1428. *
  1429. * also, provide for a segs-per-ack "threshold" where
  1430. * we generate 1-ack-per-seg until enough stuff
  1431. * (spa_thresh_ bytes) has been received from the other side
  1432. * This idea came from vj/kmn in BayTcp. Added 8/21/01.
  1433. */
  1434.  
  1435. int
  1436. FullTcpAgent::need_send()
  1437. {
  1438. if (flags_ & TF_ACKNOW)
  1439. return TRUE;
  1440.  
  1441. int spa = (spa_thresh_ > && ((rcv_nxt_ - irs_) < spa_thresh_)) ?
  1442. : segs_per_ack_;
  1443.  
  1444. return ((rcv_nxt_ - last_ack_sent_) >= (spa * maxseg_));
  1445. }
  1446.  
  1447. /*
  1448. * determine whether enough time has elapsed in order to
  1449. * conclude a "restart" is necessary (e.g. a slow-start)
  1450. *
  1451. * for now, keep track of this similarly to how rtt_update() does
  1452. */
  1453.  
  1454. int
  1455. FullTcpAgent::idle_restart()
  1456. {
  1457. if (last_send_time_ < 0.0) {
  1458. // last_send_time_ isn't set up yet, we shouldn't
  1459. // do the idle_restart
  1460. return ();
  1461. }
  1462.  
  1463. double tao = now() - last_send_time_;
  1464. if (!ts_option_) {
  1465. double tickoff = fmod(last_send_time_ + boot_time_,
  1466. tcp_tick_);
  1467. tao = int((tao + tickoff) / tcp_tick_) * tcp_tick_;
  1468. }
  1469.  
  1470. return (tao > t_rtxcur_); // verify this CHECKME
  1471. }
  1472.  
  1473. /*
  1474. * tcp-full's version of set_initial_window()... over-rides
  1475. * the one in tcp.cc
  1476. */
  1477. void
  1478. FullTcpAgent::set_initial_window()
  1479. {
  1480. syn_ = TRUE; // full-tcp always models SYN exchange
  1481. TcpAgent::set_initial_window();
  1482. }
  1483.  
  1484. /*
  1485. * main reception path -
  1486. * called from the agent that handles the data path below in its muxing mode
  1487. * advance() is called when connection is established with size sent from
  1488. * user/application agent
  1489. *
  1490. * This is a fairly complex function. It operates generally as follows:
  1491. * do header prediction for simple cases (pure ACKS or data)
  1492. * if in LISTEN and we get a SYN, begin initializing connection
  1493. * if in SYN_SENT and we get an ACK, complete connection init
  1494. * trim any redundant data from received dataful segment
  1495. * deal with ACKS:
  1496. * if in SYN_RCVD, complete connection init then go on
  1497. * see if ACK is old or at the current highest_ack
  1498. * if at current high, is the threshold reached or not
  1499. * if so, maybe do fast rtx... otherwise drop or inflate win
  1500. * deal with incoming data
  1501. * deal with FIN bit on in arriving packet
  1502. */
  1503. void
  1504. FullTcpAgent::recv(Packet *pkt, Handler*)
  1505. {
  1506. hdr_tcp *tcph = hdr_tcp::access(pkt); // TCP header
  1507. hdr_cmn *th = hdr_cmn::access(pkt); // common header (size, etc)
  1508. hdr_flags *fh = hdr_flags::access(pkt); // flags (CWR, CE, bits)
  1509.  
  1510. int needoutput = FALSE;
  1511. int ourfinisacked = FALSE;
  1512. int dupseg = FALSE; // recv'd dup data segment
  1513. int todrop = ; // duplicate DATA cnt in seg
  1514.  
  1515. last_state_ = state_;
  1516.  
  1517. int datalen = th->size() - tcph->hlen(); // # payload bytes
  1518. int ackno = tcph->ackno(); // ack # from packet
  1519. int tiflags = tcph->flags() ; // tcp flags from packet
  1520.  
  1521. //if (state_ != TCPS_ESTABLISHED || (tiflags&(TH_SYN|TH_FIN))) {
  1522. //fprintf(stdout, "%f(%s)in state %s recv'd this packet: ", now(), name(), statestr(state_));
  1523. //prpkt(pkt);
  1524. //}
  1525.  
  1526. /*
  1527. * Acknowledge FIN from passive closer even in TCPS_CLOSED state
  1528. * (since we lack TIME_WAIT state and RST packets,
  1529. * the loss of the FIN packet from the passive closer will make that
  1530. * endpoint retransmit the FIN forever)
  1531. * -F. Hernandez-Campos 8/6/00
  1532. */
  1533. if ( (state_ == TCPS_CLOSED) && (tiflags & TH_FIN) ) {
  1534. goto dropafterack;
  1535. }
  1536.  
  1537. /*
  1538. * Don't expect to see anything while closed
  1539. */
  1540.  
  1541. if (state_ == TCPS_CLOSED) {
  1542. if (debug_) {
  1543. fprintf(stderr, "%f: FullTcp(%s): recv'd pkt in CLOSED state: ",
  1544. now(), name());
  1545. prpkt(pkt);
  1546. }
  1547. goto drop;
  1548. }
  1549.  
  1550. /*
  1551. * Process options if not in LISTEN state,
  1552. * else do it below
  1553. */
  1554. if (state_ != TCPS_LISTEN)
  1555. dooptions(pkt);
  1556.  
  1557. /*
  1558. * if we are using delayed-ACK timers and
  1559. * no delayed-ACK timer is set, set one.
  1560. * They are set to fire every 'interval_' secs, starting
  1561. * at time t0 = (0.0 + k * interval_) for some k such
  1562. * that t0 > now
  1563. */
  1564. if (delack_interval_ > 0.0 &&
  1565. (delack_timer_.status() != TIMER_PENDING)) {
  1566. int last = int(now() / delack_interval_);
  1567. delack_timer_.resched(delack_interval_ * (last + 1.0) - now());
  1568. }
  1569.  
  1570. /*
  1571. * Try header prediction: in seq data or in seq pure ACK
  1572. * with no funny business
  1573. */
  1574. if (!nopredict_ && predict_ok(pkt)) {
  1575. /*
  1576. * If last ACK falls within this segment's sequence numbers,
  1577. * record the timestamp.
  1578. * See RFC1323 (now RFC1323 bis)
  1579. */
  1580. if (ts_option_ && !fh->no_ts_ &&
  1581. tcph->seqno() <= last_ack_sent_) {
  1582. /*
  1583. * this is the case where the ts value is newer than
  1584. * the last one we've seen, and the seq # is the one
  1585. * we expect [seqno == last_ack_sent_] or older
  1586. */
  1587. recent_age_ = now();
  1588. recent_ = tcph->ts();
  1589. }
  1590.  
  1591. //
  1592. // generate a stream of ecnecho bits until we see a true
  1593. // cong_action bit
  1594. //
  1595.  
  1596. if (ecn_) {
  1597. if (fh->ce() && fh->ect()) {
  1598. // no CWR from peer yet... arrange to
  1599. // keep sending ECNECHO
  1600. recent_ce_ = TRUE;
  1601. } else if (fh->cwr()) {
  1602. // got CWR response from peer.. stop
  1603. // sending ECNECHO bits
  1604. recent_ce_ = FALSE;
  1605. }
  1606. }
  1607.  
  1608. // Header predication basically looks to see
  1609. // if the incoming packet is an expected pure ACK
  1610. // or an expected data segment
  1611.  
  1612. if (datalen == ) {
  1613. // check for a received pure ACK in the correct range..
  1614. // also checks to see if we are wnd_ limited
  1615. // (we don't change cwnd at all below), plus
  1616. // not being in fast recovery and not a partial ack.
  1617. // If we are in fast
  1618. // recovery, go below so we can remember to deflate
  1619. // the window if we need to
  1620. if (ackno > highest_ack_ && ackno < maxseq_ &&
  1621. cwnd_ >= wnd_ && !fastrecov_) {
  1622. newack(pkt); // update timers, highest_ack_
  1623. send_much(, REASON_NORMAL, maxburst_);
  1624. Packet::free(pkt);
  1625. return;
  1626. }
  1627. } else if (ackno == highest_ack_ && rq_.empty()) {
  1628. // check for pure incoming segment
  1629. // the next data segment we're awaiting, and
  1630. // that there's nothing sitting in the reassem-
  1631. // bly queue
  1632. // give to "application" here
  1633. // note: DELACK is inspected only by
  1634. // tcp_fasttimo() in real tcp. Every 200 ms
  1635. // this routine scans all tcpcb's looking for
  1636. // DELACK segments and when it finds them
  1637. // changes DELACK to ACKNOW and calls tcp_output()
  1638. rcv_nxt_ += datalen;
  1639. flags_ |= TF_DELACK;
  1640. recvBytes(datalen); // notify application of "delivery"
  1641. //
  1642. // special code here to simulate the operation
  1643. // of a receiver who always consumes data,
  1644. // resulting in a call to tcp_output
  1645. Packet::free(pkt);
  1646. if (need_send())
  1647. send_much(, REASON_NORMAL, maxburst_);
  1648. return;
  1649. }
  1650. } /* header prediction */
  1651.  
  1652. //
  1653. // header prediction failed
  1654. // (e.g. pure ACK out of valid range, SACK present, etc)...
  1655. // do slow path processing
  1656.  
  1657. //
  1658. // the following switch does special things for these states:
  1659. // TCPS_LISTEN, TCPS_SYN_SENT
  1660. //
  1661.  
  1662. switch (state_) {
  1663.  
  1664. /*
  1665. * If the segment contains an ACK then it is bad and do reset.
  1666. * If it does not contain a SYN then it is not interesting; drop it.
  1667. * Otherwise initialize tp->rcv_nxt, and tp->irs, iss is already
  1668. * selected, and send a segment:
  1669. * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
  1670. * Initialize tp->snd_nxt to tp->iss.
  1671. * Enter SYN_RECEIVED state, and process any other fields of this
  1672. * segment in this state.
  1673. */
  1674.  
  1675. case TCPS_LISTEN: /* awaiting peer's SYN */
  1676.  
  1677. if (tiflags & TH_ACK) {
  1678. if (debug_) {
  1679. fprintf(stderr,
  1680. "%f: FullTcpAgent(%s): warning: recv'd ACK while in LISTEN: ",
  1681. now(), name());
  1682. prpkt(pkt);
  1683. }
  1684. // don't want ACKs in LISTEN
  1685. goto dropwithreset;
  1686. }
  1687. if ((tiflags & TH_SYN) == ) {
  1688. if (debug_) {
  1689. fprintf(stderr, "%f: FullTcpAgent(%s): warning: recv'd NON-SYN while in LISTEN\n",
  1690. now(), name());
  1691. prpkt(pkt);
  1692. }
  1693. // any non-SYN is discarded
  1694. goto drop;
  1695. }
  1696.  
  1697. /*
  1698. * must by a SYN (no ACK) at this point...
  1699. * in real tcp we would bump the iss counter here also
  1700. */
  1701. dooptions(pkt);
  1702. irs_ = tcph->seqno();
  1703. t_seqno_ = iss_; /* tcp_sendseqinit() macro in real tcp */
  1704. rcv_nxt_ = rcvseqinit(irs_, datalen);
  1705. flags_ |= TF_ACKNOW;
  1706.  
  1707. // check for a ECN-SYN with ECE|CWR
  1708. if (ecn_ && fh->ecnecho() && fh->cong_action()) {
  1709. ect_ = TRUE;
  1710. }
  1711.  
  1712. if (fid_ == ) {
  1713. // XXX: sort of hack... If we do not
  1714. // have a special flow ID, pick up that
  1715. // of the sender (active opener)
  1716. hdr_ip* iph = hdr_ip::access(pkt);
  1717. fid_ = iph->flowid();
  1718. }
  1719.  
  1720. newstate(TCPS_SYN_RECEIVED);
  1721. goto trimthenstep6;
  1722.  
  1723. /*
  1724. * If the state is SYN_SENT:
  1725. * if seg contains an ACK, but not for our SYN, drop the input.
  1726. * if seg does not contain SYN, then drop it.
  1727. * Otherwise this is an acceptable SYN segment
  1728. * initialize tp->rcv_nxt and tp->irs
  1729. * if seg contains ack then advance tp->snd_una
  1730. * if SYN has been acked change to ESTABLISHED else SYN_RCVD state
  1731. * arrange for segment to be acked (eventually)
  1732. * continue processing rest of data/controls, beginning with URG
  1733. */
  1734.  
  1735. case TCPS_SYN_SENT: /* we sent SYN, expecting SYN+ACK (or SYN) */
  1736.  
  1737. /* drop if it's a SYN+ACK and the ack field is bad */
  1738. if ((tiflags & TH_ACK) &&
  1739. ((ackno <= iss_) || (ackno > maxseq_))) {
  1740. // not an ACK for our SYN, discard
  1741. if (debug_) {
  1742. fprintf(stderr, "%f: FullTcpAgent::recv(%s): bad ACK for our SYN: ",
  1743. now(), name());
  1744. prpkt(pkt);
  1745. }
  1746. goto dropwithreset;
  1747. }
  1748.  
  1749. if ((tiflags & TH_SYN) == ) {
  1750. if (debug_) {
  1751. fprintf(stderr, "%f: FullTcpAgent::recv(%s): no SYN for our SYN: ",
  1752. now(), name());
  1753. prpkt(pkt);
  1754. }
  1755. goto drop;
  1756. }
  1757.  
  1758. /* looks like an ok SYN or SYN+ACK */
  1759. // If ecn_syn_wait is set to 2:
  1760. // Check if CE-marked SYN/ACK packet, then just send an ACK
  1761. // packet with ECE set, and drop the SYN/ACK packet.
  1762. // Don't update TCP state.
  1763. if (tiflags & TH_ACK)
  1764. {
  1765. if (ecn_ && fh->ecnecho() && !fh->cong_action() && ecn_syn_wait_ == )
  1766. // if SYN/ACK packet and ecn_syn_wait_ == 2
  1767. {
  1768. if ( fh->ce() )
  1769. // If SYN/ACK packet is CE-marked
  1770. {
  1771. //cancel_rtx_timer();
  1772. //newack(pkt);
  1773. set_rtx_timer();
  1774. sendpacket(t_seqno_, rcv_nxt_, TH_ACK|TH_ECE, , );
  1775. goto drop;
  1776. }
  1777. }
  1778. }
  1779.  
  1780. #ifdef notdef
  1781. cancel_rtx_timer(); // cancel timer on our 1st SYN [does this belong!?]
  1782. #endif
  1783. irs_ = tcph->seqno(); // get initial recv'd seq #
  1784. rcv_nxt_ = rcvseqinit(irs_, datalen);
  1785.  
  1786. if (tiflags & TH_ACK) {
  1787. // SYN+ACK (our SYN was acked)
  1788. if (ecn_ && fh->ecnecho() && !fh->cong_action()) {
  1789. ect_ = TRUE;
  1790. if ( fh->ce() )
  1791. recent_ce_ = TRUE;
  1792. }
  1793. highest_ack_ = ackno;
  1794. cwnd_ = initial_window();
  1795.  
  1796. #ifdef notdef
  1797. /*
  1798. * if we didn't have to retransmit the SYN,
  1799. * use its rtt as our initial srtt & rtt var.
  1800. */
  1801. if (t_rtt_) {
  1802. double tao = now() - tcph->ts();
  1803. rtt_update(tao);
  1804. }
  1805. #endif
  1806.  
  1807. /*
  1808. * if there's data, delay ACK; if there's also a FIN
  1809. * ACKNOW will be turned on later.
  1810. */
  1811. if (datalen > ) {
  1812. flags_ |= TF_DELACK; // data there: wait
  1813. } else {
  1814. flags_ |= TF_ACKNOW; // ACK peer's SYN
  1815. }
  1816.  
  1817. /*
  1818. * Received <SYN,ACK> in SYN_SENT[*] state.
  1819. * Transitions:
  1820. * SYN_SENT --> ESTABLISHED
  1821. * SYN_SENT* --> FIN_WAIT_1
  1822. */
  1823.  
  1824. if (flags_ & TF_NEEDFIN) {
  1825. newstate(TCPS_FIN_WAIT_1);
  1826. flags_ &= ~TF_NEEDFIN;
  1827. tiflags &= ~TH_SYN;
  1828. } else {
  1829. newstate(TCPS_ESTABLISHED);
  1830. }
  1831.  
  1832. // special to ns:
  1833. // generate pure ACK here.
  1834. // this simulates the ordinary connection establishment
  1835. // where the ACK of the peer's SYN+ACK contains
  1836. // no data. This is typically caused by the way
  1837. // the connect() socket call works in which the
  1838. // entire 3-way handshake occurs prior to the app
  1839. // being able to issue a write() [which actually
  1840. // causes the segment to be sent].
  1841. sendpacket(t_seqno_, rcv_nxt_, TH_ACK, , );
  1842. } else {
  1843. // Check ECN-SYN packet
  1844. if (ecn_ && fh->ecnecho() && fh->cong_action())
  1845. ect_ = TRUE;
  1846.  
  1847. // SYN (no ACK) (simultaneous active opens)
  1848. flags_ |= TF_ACKNOW;
  1849. cancel_rtx_timer();
  1850. newstate(TCPS_SYN_RECEIVED);
  1851. /*
  1852. * decrement t_seqno_: we are sending a
  1853. * 2nd SYN (this time in the form of a
  1854. * SYN+ACK, so t_seqno_ will have been
  1855. * advanced to 2... reduce this
  1856. */
  1857. t_seqno_--; // CHECKME
  1858. }
  1859.  
  1860. trimthenstep6:
  1861. /*
  1862. * advance the seq# to correspond to first data byte
  1863. */
  1864. tcph->seqno()++;
  1865.  
  1866. if (tiflags & TH_ACK)
  1867. goto process_ACK;
  1868.  
  1869. goto step6;
  1870.  
  1871. case TCPS_LAST_ACK:
  1872. /*
  1873. * The only way we're in LAST_ACK is if we've already
  1874. * received a FIN, so ignore all retranmitted FINS.
  1875. * -M. Weigle 7/23/02
  1876. */
  1877. if (tiflags & TH_FIN) {
  1878. goto drop;
  1879. }
  1880. break;
  1881. case TCPS_CLOSING:
  1882. break;
  1883. } /* end switch(state_) */
  1884.  
  1885. /*
  1886. * States other than LISTEN or SYN_SENT.
  1887. * First check timestamp, if present.
  1888. * Then check that at least some bytes of segment are within
  1889. * receive window. If segment begins before rcv_nxt,
  1890. * drop leading data (and SYN); if nothing left, just ack.
  1891. *
  1892. * RFC 1323 PAWS: If we have a timestamp reply on this segment
  1893. * and it's less than ts_recent, drop it.
  1894. */
  1895.  
  1896. if (ts_option_ && !fh->no_ts_ && recent_ && tcph->ts() < recent_) {
  1897. if ((now() - recent_age_) > TCP_PAWS_IDLE) {
  1898. /*
  1899. * this is basically impossible in the simulator,
  1900. * but here it is...
  1901. */
  1902. /*
  1903. * Invalidate ts_recent. If this segment updates
  1904. * ts_recent, the age will be reset later and ts_recent
  1905. * will get a valid value. If it does not, setting
  1906. * ts_recent to zero will at least satisfy the
  1907. * requirement that zero be placed in the timestamp
  1908. * echo reply when ts_recent isn't valid. The
  1909. * age isn't reset until we get a valid ts_recent
  1910. * because we don't want out-of-order segments to be
  1911. * dropped when ts_recent is old.
  1912. */
  1913. recent_ = 0.0;
  1914. } else {
  1915. fprintf(stderr, "%f: FullTcpAgent(%s): dropped pkt due to bad ts\n",
  1916. now(), name());
  1917. goto dropafterack;
  1918. }
  1919. }
  1920.  
  1921. // check for redundant data at head/tail of segment
  1922. // note that the 4.4bsd [Net/3] code has
  1923. // a bug here which can cause us to ignore the
  1924. // perfectly good ACKs on duplicate segments. The
  1925. // fix is described in (Stevens, Vol2, p. 959-960).
  1926. // This code is based on that correction.
  1927. //
  1928. // In addition, it has a modification so that duplicate segments
  1929. // with dup acks don't trigger a fast retransmit when dupseg_fix_
  1930. // is enabled.
  1931. //
  1932. // Yet one more modification: make sure that if the received
  1933. // segment had datalen=0 and wasn't a SYN or FIN that
  1934. // we don't turn on the ACKNOW status bit. If we were to
  1935. // allow ACKNOW to be turned on, normal pure ACKs that happen
  1936. // to have seq #s below rcv_nxt can trigger an ACK war by
  1937. // forcing us to ACK the pure ACKs
  1938. //
  1939. // Update: if we have a dataless FIN, don't really want to
  1940. // do anything with it. In particular, would like to
  1941. // avoid ACKing an incoming FIN+ACK while in CLOSING
  1942. //
  1943. todrop = rcv_nxt_ - tcph->seqno(); // how much overlap?
  1944.  
  1945. if (todrop > && ((tiflags & (TH_SYN)) || datalen > )) {
  1946. //printf("%f(%s): trim 1..todrop:%d, dlen:%d\n",now(), name(), todrop, datalen);
  1947. if (tiflags & TH_SYN) {
  1948. tiflags &= ~TH_SYN;
  1949. tcph->seqno()++;
  1950. th->size()--; // XXX Must decrease packet size too!!
  1951. // Q: Why?.. this is only a SYN
  1952. todrop--;
  1953. }
  1954. //
  1955. // see Stevens, vol 2, p. 960 for this check;
  1956. // this check is to see if we are dropping
  1957. // more than this segment (i.e. the whole pkt + a FIN),
  1958. // or just the whole packet (no FIN)
  1959. //
  1960. if ((todrop > datalen) ||
  1961. (todrop == datalen && ((tiflags & TH_FIN) == ))) {
  1962. //printf("%f(%s): trim 2..todrop:%d, dlen:%d\n",now(), name(), todrop, datalen);
  1963. /*
  1964. * Any valid FIN must be to the left of the window.
  1965. * At this point the FIN must be a duplicate or out
  1966. * of sequence; drop it.
  1967. */
  1968.  
  1969. tiflags &= ~TH_FIN;
  1970.  
  1971. /*
  1972. * Send an ACK to resynchronize and drop any data.
  1973. * But keep on processing for RST or ACK.
  1974. */
  1975.  
  1976. flags_ |= TF_ACKNOW;
  1977. todrop = datalen;
  1978. dupseg = TRUE; // *completely* duplicate
  1979.  
  1980. }
  1981.  
  1982. /*
  1983. * Trim duplicate data from the front of the packet
  1984. */
  1985.  
  1986. tcph->seqno() += todrop;
  1987. th->size() -= todrop; // XXX Must decrease size too!!
  1988. // why? [kf]..prob when put in RQ
  1989. datalen -= todrop;
  1990.  
  1991. } /* data trim */
  1992.  
  1993. /*
  1994. * If we are doing timstamps and this packet has one, and
  1995. * If last ACK falls within this segment's sequence numbers,
  1996. * record the timestamp.
  1997. * See RFC1323 (now RFC1323 bis)
  1998. */
  1999. if (ts_option_ && !fh->no_ts_ && tcph->seqno() <= last_ack_sent_) {
  2000. /*
  2001. * this is the case where the ts value is newer than
  2002. * the last one we've seen, and the seq # is the one we expect
  2003. * [seqno == last_ack_sent_] or older
  2004. */
  2005. recent_age_ = now();
  2006. recent_ = tcph->ts();
  2007. }
  2008.  
  2009. if (tiflags & TH_SYN) {
  2010. if (debug_) {
  2011. fprintf(stderr, "%f: FullTcpAgent::recv(%s) received unexpected SYN (state:%d): ",
  2012. now(), name(), state_);
  2013. prpkt(pkt);
  2014. }
  2015. goto dropwithreset;
  2016. }
  2017.  
  2018. if ((tiflags & TH_ACK) == ) {
  2019. /*
  2020. * Added check for state != SYN_RECEIVED. We will receive a
  2021. * duplicate SYN in SYN_RECEIVED when our SYN/ACK was dropped.
  2022. * We should just ignore the duplicate SYN (our timeout for
  2023. * resending the SYN/ACK is about the same as the client's
  2024. * timeout for resending the SYN), but give no error message.
  2025. * -M. Weigle 07/24/01
  2026. */
  2027. if (state_ != TCPS_SYN_RECEIVED) {
  2028. if (debug_) {
  2029. fprintf(stderr, "%f: FullTcpAgent::recv(%s) got packet lacking ACK (state:%d): ",
  2030. now(), name(), state_);
  2031. prpkt(pkt);
  2032. }
  2033. }
  2034. goto drop;
  2035. }
  2036.  
  2037. /*
  2038. * Ack processing.
  2039. */
  2040.  
  2041. switch (state_) {
  2042. case TCPS_SYN_RECEIVED: /* want ACK for our SYN+ACK */
  2043. if (ackno < highest_ack_ || ackno > maxseq_) {
  2044. // not in useful range
  2045. if (debug_) {
  2046. fprintf(stderr, "%f: FullTcpAgent(%s): ack(%d) not in range while in SYN_RECEIVED: ",
  2047. now(), name(), ackno);
  2048. prpkt(pkt);
  2049. }
  2050. goto dropwithreset;
  2051. }
  2052.  
  2053. if (ecn_ && ect_ && ecn_syn_ && fh->ecnecho() && ecn_syn_wait_ == )
  2054. {
  2055. // The SYN/ACK packet was ECN-marked.
  2056. // Reset the rtx timer, send another SYN/ACK packet
  2057. // immediately, and drop the ACK packet.
  2058. // Do not move to TCPS_ESTB state or update TCP variables.
  2059. cancel_rtx_timer();
  2060. ecn_syn_next_ = ;
  2061. foutput(iss_, REASON_NORMAL);
  2062. wnd_init_option_ = ;
  2063. wnd_init_ = ;
  2064. goto drop;
  2065. }
  2066. if (ecn_ && ect_ && ecn_syn_ && fh->ecnecho() && ecn_syn_wait_ < ) {
  2067. // The SYN/ACK packet was ECN-marked.
  2068. if (ecn_syn_wait_ == ) {
  2069. // A timer will be called in ecn().
  2070. cwnd_ = ;
  2071. use_rtt_ = ; //KK, wait for timeout() period
  2072. } else {
  2073. // Congestion window will be halved in ecn().
  2074. cwnd_ = ;
  2075. }
  2076. } else {
  2077. cwnd_ = initial_window();
  2078. }
  2079.  
  2080. /*
  2081. * Make transitions:
  2082. * SYN-RECEIVED -> ESTABLISHED
  2083. * SYN-RECEIVED* -> FIN-WAIT-1
  2084. */
  2085. if (flags_ & TF_NEEDFIN) {
  2086. newstate(TCPS_FIN_WAIT_1);
  2087. flags_ &= ~TF_NEEDFIN;
  2088. } else {
  2089. newstate(TCPS_ESTABLISHED);
  2090. }
  2091.  
  2092. /* fall into ... */
  2093.  
  2094. /*
  2095. * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
  2096. * ACKs. If the ack is in the range
  2097. * tp->snd_una < ti->ti_ack <= tp->snd_max
  2098. * then advance tp->snd_una to ti->ti_ack and drop
  2099. * data from the retransmission queue.
  2100. *
  2101. * note that state TIME_WAIT isn't used
  2102. * in the simulator
  2103. */
  2104.  
  2105. case TCPS_ESTABLISHED:
  2106. case TCPS_FIN_WAIT_1:
  2107. case TCPS_FIN_WAIT_2:
  2108. case TCPS_CLOSE_WAIT:
  2109. case TCPS_CLOSING:
  2110. case TCPS_LAST_ACK:
  2111.  
  2112. //
  2113. // look for ECNs in ACKs, react as necessary
  2114. //
  2115.  
  2116. if (fh->ecnecho() && (!ecn_ || !ect_)) {
  2117. fprintf(stderr,
  2118. "%f: FullTcp(%s): warning, recvd ecnecho but I am not ECN capable!\n",
  2119. now(), name());
  2120. }
  2121.  
  2122. //
  2123. // generate a stream of ecnecho bits until we see a true
  2124. // cong_action bit
  2125. //
  2126. if (ecn_) {
  2127. if (fh->ce() && fh->ect())
  2128. recent_ce_ = TRUE;
  2129. else if (fh->cwr())
  2130. recent_ce_ = FALSE;
  2131. }
  2132.  
  2133. //
  2134. // If ESTABLISHED or starting to close, process SACKS
  2135. //
  2136.  
  2137. if (state_ >= TCPS_ESTABLISHED && tcph->sa_length() > ) {
  2138. process_sack(tcph);
  2139. }
  2140.  
  2141. //
  2142. // ACK indicates packet left the network
  2143. // try not to be fooled by data
  2144. //
  2145.  
  2146. if (fastrecov_ && (datalen == || ackno > highest_ack_))
  2147. pipe_ -= maxseg_;
  2148.  
  2149. // look for dup ACKs (dup ack numbers, no data)
  2150. //
  2151. // do fast retransmit/recovery if at/past thresh
  2152. if (ackno <= highest_ack_) {
  2153. // a pure ACK which doesn't advance highest_ack_
  2154. if (datalen == && (!dupseg_fix_ || !dupseg)) {
  2155.  
  2156. /*
  2157. * If we have outstanding data
  2158. * this is a completely
  2159. * duplicate ack,
  2160. * the ack is the biggest we've
  2161. * seen and we've seen exactly our rexmt
  2162. * threshhold of them, assume a packet
  2163. * has been dropped and retransmit it.
  2164. *
  2165. * We know we're losing at the current
  2166. * window size so do congestion avoidance.
  2167. *
  2168. * Dup acks mean that packets have left the
  2169. * network (they're now cached at the receiver)
  2170. * so bump cwnd by the amount in the receiver
  2171. * to keep a constant cwnd packets in the
  2172. * network.
  2173. */
  2174.  
  2175. if ((rtx_timer_.status() != TIMER_PENDING) ||
  2176. ackno < highest_ack_) {
  2177. // Q: significance of timer not pending?
  2178. // ACK below highest_ack_
  2179. oldack();
  2180. } else if (++dupacks_ == tcprexmtthresh_) {
  2181. // ACK at highest_ack_ AND meets threshold
  2182. //trace_event("FAST_RECOVERY");
  2183. dupack_action(); // maybe fast rexmt
  2184. goto drop;
  2185.  
  2186. } else if (dupacks_ > tcprexmtthresh_) {
  2187. // ACK at highest_ack_ AND above threshole
  2188. //trace_event("FAST_RECOVERY");
  2189. extra_ack();
  2190.  
  2191. // send whatever window allows
  2192. send_much(, REASON_DUPACK, maxburst_);
  2193. goto drop;
  2194. }
  2195. } else {
  2196. // non zero-length [dataful] segment
  2197. // with a dup ack (normal for dataful segs)
  2198. // (or window changed in real TCP).
  2199. if (dupack_reset_) {
  2200. dupacks_ = ;
  2201. fastrecov_ = FALSE;
  2202. }
  2203. }
  2204. break; /* take us to "step6" */
  2205. } /* end of dup/old acks */
  2206.  
  2207. /*
  2208. * we've finished the fast retransmit/recovery period
  2209. * (i.e. received an ACK which advances highest_ack_)
  2210. * The ACK may be "good" or "partial"
  2211. */
  2212.  
  2213. process_ACK:
  2214.  
  2215. if (ackno > maxseq_) {
  2216. // ack more than we sent(!?)
  2217. if (debug_) {
  2218. fprintf(stderr, "%f: FullTcpAgent::recv(%s) too-big ACK (maxseq:%d): ",
  2219. now(), name(), int(maxseq_));
  2220. prpkt(pkt);
  2221. }
  2222. goto dropafterack;
  2223. }
  2224.  
  2225. /*
  2226. * If we have a timestamp reply, update smoothed
  2227. * round trip time. If no timestamp is present but
  2228. * transmit timer is running and timed sequence
  2229. * number was acked, update smoothed round trip time.
  2230. * Since we now have an rtt measurement, cancel the
  2231. * timer backoff (cf., Phil Karn's retransmit alg.).
  2232. * Recompute the initial retransmit timer.
  2233. *
  2234. * If all outstanding data is acked, stop retransmit
  2235. * If there is more data to be acked, restart retransmit
  2236. * timer, using current (possibly backed-off) value.
  2237. */
  2238. newack(pkt); // handle timers, update highest_ack_
  2239.  
  2240. /*
  2241. * if this is a partial ACK, invoke whatever we should
  2242. * note that newack() must be called before the action
  2243. * functions, as some of them depend on side-effects
  2244. * of newack()
  2245. */
  2246.  
  2247. int partial = pack(pkt);
  2248.  
  2249. if (partial)
  2250. pack_action(pkt);
  2251. else
  2252. ack_action(pkt);
  2253.  
  2254. /*
  2255. * if this is an ACK with an ECN indication, handle this
  2256. * but not if it is a syn packet
  2257. */
  2258. if (fh->ecnecho() && !(tiflags&TH_SYN) )
  2259. if (fh->ecnecho()) {
  2260. // Note from Sally: In one-way TCP,
  2261. // ecn() is called before newack()...
  2262. ecn(highest_ack_); // updated by newack(), above
  2263. // "set_rtx_timer();" from T. Kelly.
  2264. if (cwnd_ < )
  2265. set_rtx_timer();
  2266. }
  2267. // CHECKME: handling of rtx timer
  2268. if (ackno == maxseq_) {
  2269. needoutput = TRUE;
  2270. }
  2271.  
  2272. /*
  2273. * If no data (only SYN) was ACK'd,
  2274. * skip rest of ACK processing.
  2275. */
  2276. if (ackno == (highest_ack_ + ))
  2277. goto step6;
  2278.  
  2279. // if we are delaying initial cwnd growth (probably due to
  2280. // large initial windows), then only open cwnd if data has
  2281. // been received
  2282. // Q: check when this happens
  2283. /*
  2284. * When new data is acked, open the congestion window.
  2285. * If the window gives us less than ssthresh packets
  2286. * in flight, open exponentially (maxseg per packet).
  2287. * Otherwise open about linearly: maxseg per window
  2288. * (maxseg^2 / cwnd per packet).
  2289. */
  2290. if ((!delay_growth_ || (rcv_nxt_ > )) &&
  2291. last_state_ == TCPS_ESTABLISHED) {
  2292. if (!partial || open_cwnd_on_pack_) {
  2293. if (!ect_ || !hdr_flags::access(pkt)->ecnecho())
  2294. opencwnd();
  2295. }
  2296. }
  2297.  
  2298. if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {
  2299. ourfinisacked = TRUE;
  2300. }
  2301.  
  2302. //
  2303. // special additional processing when our state
  2304. // is one of the closing states:
  2305. // FIN_WAIT_1, CLOSING, LAST_ACK
  2306.  
  2307. switch (state_) {
  2308. /*
  2309. * In FIN_WAIT_1 STATE in addition to the processing
  2310. * for the ESTABLISHED state if our FIN is now acknowledged
  2311. * then enter FIN_WAIT_2.
  2312. */
  2313. case TCPS_FIN_WAIT_1: /* doing active close */
  2314. if (ourfinisacked) {
  2315. // got the ACK, now await incoming FIN
  2316. newstate(TCPS_FIN_WAIT_2);
  2317. cancel_timers();
  2318. needoutput = FALSE;
  2319. }
  2320. break;
  2321.  
  2322. /*
  2323. * In CLOSING STATE in addition to the processing for
  2324. * the ESTABLISHED state if the ACK acknowledges our FIN
  2325. * then enter the TIME-WAIT state, otherwise ignore
  2326. * the segment.
  2327. */
  2328. case TCPS_CLOSING: /* simultaneous active close */;
  2329. if (ourfinisacked) {
  2330. newstate(TCPS_CLOSED);
  2331. cancel_timers();
  2332. }
  2333. break;
  2334. /*
  2335. * In LAST_ACK, we may still be waiting for data to drain
  2336. * and/or to be acked, as well as for the ack of our FIN.
  2337. * If our FIN is now acknowledged,
  2338. * enter the closed state and return.
  2339. */
  2340. case TCPS_LAST_ACK: /* passive close */
  2341. // K: added state change here
  2342. if (ourfinisacked) {
  2343. newstate(TCPS_CLOSED);
  2344. finish(); // cancels timers, erc
  2345. reset(); // for connection re-use (bug fix from ns-users list)
  2346. goto drop;
  2347. } else {
  2348. // should be a FIN we've seen
  2349. if (debug_) {
  2350. fprintf(stderr, "%f: FullTcpAgent(%s)::received non-ACK (state:%d): ",
  2351. now(), name(), state_);
  2352. prpkt(pkt);
  2353. }
  2354. }
  2355. break;
  2356.  
  2357. /* no case for TIME_WAIT in simulator */
  2358. } // inner state_ switch (closing states)
  2359. } // outer state_ switch (ack processing)
  2360.  
  2361. step6:
  2362.  
  2363. /*
  2364. * Processing of incoming DATAful segments.
  2365. * Code above has already trimmed redundant data.
  2366. *
  2367. * real TCP handles window updates and URG data here also
  2368. */
  2369.  
  2370. /* dodata: this label is in the "real" code.. here only for reference */
  2371.  
  2372. if ((datalen > || (tiflags & TH_FIN)) &&
  2373. TCPS_HAVERCVDFIN(state_) == ) {
  2374.  
  2375. //
  2376. // the following 'if' implements the "real" TCP
  2377. // TCP_REASS macro
  2378. //
  2379.  
  2380. if (tcph->seqno() == rcv_nxt_ && rq_.empty()) {
  2381. // got the in-order packet we were looking
  2382. // for, nobody is in the reassembly queue,
  2383. // so this is the common case...
  2384. // note: in "real" TCP we must also be in
  2385. // ESTABLISHED state to come here, because
  2386. // data arriving before ESTABLISHED is
  2387. // queued in the reassembly queue. Since we
  2388. // don't really have a process anyhow, just
  2389. // accept the data here as-is (i.e. don't
  2390. // require being in ESTABLISHED state)
  2391. flags_ |= TF_DELACK;
  2392. rcv_nxt_ += datalen;
  2393. tiflags = tcph->flags() & TH_FIN;
  2394.  
  2395. // give to "application" here
  2396. // in "real" TCP, this is sbappend() + sorwakeup()
  2397. if (datalen)
  2398. recvBytes(datalen); // notify app. of "delivery"
  2399. needoutput = need_send();
  2400. } else {
  2401. // see the "tcp_reass" function:
  2402. // not the one we want next (or it
  2403. // is but there's stuff on the reass queue);
  2404. // do whatever we need to do for out-of-order
  2405. // segments or hole-fills. Also,
  2406. // send an ACK (or SACK) to the other side right now.
  2407. // Note that we may have just a FIN here (datalen = 0)
  2408. int rcv_nxt_old_ = rcv_nxt_; // notify app. if changes
  2409. tiflags = reass(pkt);
  2410. if (rcv_nxt_ > rcv_nxt_old_) {
  2411. // if rcv_nxt_ has advanced, must have
  2412. // been a hole fill. In this case, there
  2413. // is something to give to application
  2414. recvBytes(rcv_nxt_ - rcv_nxt_old_);
  2415. }
  2416. flags_ |= TF_ACKNOW;
  2417.  
  2418. if (tiflags & TH_PUSH) {
  2419. //
  2420. // ???: does this belong here
  2421. // K: APPLICATION recv
  2422. needoutput = need_send();
  2423. }
  2424. }
  2425. } else {
  2426. /*
  2427. * we're closing down or this is a pure ACK that
  2428. * wasn't handled by the header prediction part above
  2429. * (e.g. because cwnd < wnd)
  2430. */
  2431. // K: this is deleted
  2432. tiflags &= ~TH_FIN;
  2433. }
  2434.  
  2435. /*
  2436. * if FIN is received, ACK the FIN
  2437. * (let user know if we could do so)
  2438. */
  2439.  
  2440. if (tiflags & TH_FIN) {
  2441. if (TCPS_HAVERCVDFIN(state_) == ) {
  2442. flags_ |= TF_ACKNOW;
  2443. rcv_nxt_++;
  2444. }
  2445. switch (state_) {
  2446. /*
  2447. * In SYN_RECEIVED and ESTABLISHED STATES
  2448. * enter the CLOSE_WAIT state.
  2449. * (passive close)
  2450. */
  2451. case TCPS_SYN_RECEIVED:
  2452. case TCPS_ESTABLISHED:
  2453. newstate(TCPS_CLOSE_WAIT);
  2454. break;
  2455.  
  2456. /*
  2457. * If still in FIN_WAIT_1 STATE FIN has not been acked so
  2458. * enter the CLOSING state.
  2459. * (simultaneous close)
  2460. */
  2461. case TCPS_FIN_WAIT_1:
  2462. newstate(TCPS_CLOSING);
  2463. break;
  2464. /*
  2465. * In FIN_WAIT_2 state enter the TIME_WAIT state,
  2466. * starting the time-wait timer, turning off the other
  2467. * standard timers.
  2468. * (in the simulator, just go to CLOSED)
  2469. * (completion of active close)
  2470. */
  2471. case TCPS_FIN_WAIT_2:
  2472. newstate(TCPS_CLOSED);
  2473. cancel_timers();
  2474. break;
  2475. }
  2476. } /* end of if FIN bit on */
  2477.  
  2478. if (needoutput || (flags_ & TF_ACKNOW))
  2479. send_much(, REASON_NORMAL, maxburst_);
  2480. else if (curseq_ >= highest_ack_ || infinite_send_)
  2481. send_much(, REASON_NORMAL, maxburst_);
  2482. // K: which state to return to when nothing left?
  2483.  
  2484. if (!halfclose_ && state_ == TCPS_CLOSE_WAIT && highest_ack_ == maxseq_)
  2485. usrclosed();
  2486.  
  2487. Packet::free(pkt);
  2488.  
  2489. // haoboy: Is here the place for done{} of active close?
  2490. // It cannot be put in the switch above because we might need to do
  2491. // send_much() (an ACK)
  2492. if (state_ == TCPS_CLOSED)
  2493. Tcl::instance().evalf("%s done", this->name());
  2494.  
  2495. return;
  2496.  
  2497. //
  2498. // various ways of dropping (some also ACK, some also RST)
  2499. //
  2500.  
  2501. dropafterack:
  2502. flags_ |= TF_ACKNOW;
  2503. send_much(, REASON_NORMAL, maxburst_);
  2504. goto drop;
  2505.  
  2506. dropwithreset:
  2507. /* we should be sending an RST here, but can't in simulator */
  2508. if (tiflags & TH_ACK) {
  2509. sendpacket(ackno, , 0x0, , REASON_NORMAL);
  2510. } else {
  2511. int ack = tcph->seqno() + datalen;
  2512. if (tiflags & TH_SYN)
  2513. ack--;
  2514. sendpacket(, ack, TH_ACK, , REASON_NORMAL);
  2515. }
  2516. drop:
  2517. Packet::free(pkt);
  2518. return;
  2519. }
  2520.  
  2521. /*
  2522. * Dupack-action: what to do on a DUP ACK. After the initial check
  2523. * of 'recover' below, this function implements the following truth
  2524. * table:
  2525. *
  2526. * bugfix ecn last-cwnd == ecn action
  2527. *
  2528. * 0 0 0 full_reno_action
  2529. * 0 0 1 full_reno_action [impossible]
  2530. * 0 1 0 full_reno_action
  2531. * 0 1 1 1/2 window, return
  2532. * 1 0 0 nothing
  2533. * 1 0 1 nothing [impossible]
  2534. * 1 1 0 nothing
  2535. * 1 1 1 1/2 window, return
  2536. */
  2537.  
  2538. void
  2539. FullTcpAgent::dupack_action()
  2540. {
  2541.  
  2542. int recovered = (highest_ack_ > recover_);
  2543.  
  2544. fastrecov_ = TRUE;
  2545. rtxbytes_ = ;
  2546.  
  2547. if (recovered || (!bug_fix_ && !ecn_)
  2548. || (last_cwnd_action_ == CWND_ACTION_DUPACK)
  2549. || ( highest_ack_ == )) {
  2550. goto full_reno_action;
  2551. }
  2552.  
  2553. if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
  2554. slowdown(CLOSE_CWND_HALF);
  2555. cancel_rtx_timer();
  2556. rtt_active_ = FALSE;
  2557. (void)fast_retransmit(highest_ack_);
  2558. return;
  2559. }
  2560.  
  2561. if (bug_fix_) {
  2562. /*
  2563. * The line below, for "bug_fix_" true, avoids
  2564. * problems with multiple fast retransmits in one
  2565. * window of data.
  2566. */
  2567. return;
  2568. }
  2569.  
  2570. full_reno_action:
  2571. slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
  2572. cancel_rtx_timer();
  2573. rtt_active_ = FALSE;
  2574. recover_ = maxseq_;
  2575. (void)fast_retransmit(highest_ack_);
  2576. // we measure cwnd in packets,
  2577. // so don't scale by maxseg_
  2578. // as real TCP does
  2579. cwnd_ = double(ssthresh_) + double(dupacks_);
  2580. return;
  2581. }
  2582.  
  2583. void
  2584. FullTcpAgent::timeout_action()
  2585. {
  2586. recover_ = maxseq_;
  2587.  
  2588. if (cwnd_ < 1.0) {
  2589. if (debug_) {
  2590. fprintf(stderr, "%f: FullTcpAgent(%s):: resetting cwnd from %f to 1\n",
  2591. now(), name(), double(cwnd_));
  2592. }
  2593. cwnd_ = 1.0;
  2594. }
  2595.  
  2596. if (last_cwnd_action_ == CWND_ACTION_ECN) {
  2597. slowdown(CLOSE_CWND_ONE);
  2598. } else {
  2599. slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_RESTART);
  2600. last_cwnd_action_ = CWND_ACTION_TIMEOUT;
  2601. }
  2602. reset_rtx_timer();
  2603. t_seqno_ = (highest_ack_ < ) ? iss_ : int(highest_ack_);
  2604. fastrecov_ = FALSE;
  2605. dupacks_ = ;
  2606. }
  2607. /*
  2608. * deal with timers going off.
  2609. * 2 types for now:
  2610. * retransmission timer (rtx_timer_)
  2611. * delayed ack timer (delack_timer_)
  2612. * delayed send (randomization) timer (delsnd_timer_)
  2613. *
  2614. * real TCP initializes the RTO as 6 sec
  2615. * (A + 2D, where A=0, D=3), [Stevens p. 305]
  2616. * and thereafter uses
  2617. * (A + 4D, where A and D are dynamic estimates)
  2618. *
  2619. * note that in the simulator t_srtt_, t_rttvar_ and t_rtt_
  2620. * are all measured in 'tcp_tick_'-second units
  2621. */
  2622.  
  2623. void
  2624. FullTcpAgent::timeout(int tno)
  2625. {
  2626.  
  2627. /*
  2628. * Due to F. Hernandez-Campos' fix in recv(), we may send an ACK
  2629. * while in the CLOSED state. -M. Weigle 7/24/01
  2630. */
  2631. if (state_ == TCPS_LISTEN) {
  2632. // shouldn't be getting timeouts here
  2633. if (debug_) {
  2634. fprintf(stderr, "%f: FullTcpAgent(%s): unexpected timeout %d in state %s\n",
  2635. now(), name(), tno, statestr(state_));
  2636. }
  2637. return;
  2638. }
  2639.  
  2640. switch (tno) {
  2641.  
  2642. case TCP_TIMER_RTX:
  2643. /* retransmit timer */
  2644. ++nrexmit_;
  2645. timeout_action();
  2646. /* fall thru */
  2647. case TCP_TIMER_DELSND:
  2648. /* for phase effects */
  2649. send_much(, PF_TIMEOUT, maxburst_);
  2650. break;
  2651.  
  2652. case TCP_TIMER_DELACK:
  2653. if (flags_ & TF_DELACK) {
  2654. flags_ &= ~TF_DELACK;
  2655. flags_ |= TF_ACKNOW;
  2656. send_much(, REASON_NORMAL, );
  2657. }
  2658. delack_timer_.resched(delack_interval_);
  2659. break;
  2660. default:
  2661. fprintf(stderr, "%f: FullTcpAgent(%s) Unknown Timeout type %d\n",
  2662. now(), name(), tno);
  2663. }
  2664. return;
  2665. }
  2666.  
  2667. void
  2668. FullTcpAgent::dooptions(Packet* pkt)
  2669. {
  2670. // interesting options: timestamps (here),
  2671. // CC, CCNEW, CCECHO (future work perhaps?)
  2672.  
  2673. hdr_flags *fh = hdr_flags::access(pkt);
  2674. hdr_tcp *tcph = hdr_tcp::access(pkt);
  2675.  
  2676. if (ts_option_ && !fh->no_ts_) {
  2677. if (tcph->ts() < 0.0) {
  2678. fprintf(stderr,
  2679. "%f: FullTcpAgent(%s) warning: ts_option enabled in this TCP, but appears to be disabled in peer\n",
  2680. now(), name());
  2681. } else if (tcph->flags() & TH_SYN) {
  2682. flags_ |= TF_RCVD_TSTMP;
  2683. recent_ = tcph->ts();
  2684. recent_age_ = now();
  2685. }
  2686. }
  2687.  
  2688. return;
  2689. }
  2690.  
  2691. //
  2692. // this shouldn't ever happen
  2693. //
  2694. void
  2695. FullTcpAgent::process_sack(hdr_tcp*)
  2696. {
  2697. fprintf(stderr, "%f: FullTcpAgent(%s) Non-SACK capable FullTcpAgent received a SACK\n",
  2698. now(), name());
  2699. return;
  2700. }
  2701.  
  2702. /*
  2703. * ****** Tahoe ******
  2704. *
  2705. * for TCP Tahoe, we force a slow-start as the dup ack
  2706. * action. Also, no window inflation due to multiple dup
  2707. * acks. The latter is arranged by setting reno_fastrecov_
  2708. * false [which is performed by the Tcl init function for Tahoe in
  2709. * ns-default.tcl].
  2710. */
  2711.  
  2712. /*
  2713. * Tahoe
  2714. * Dupack-action: what to do on a DUP ACK. After the initial check
  2715. * of 'recover' below, this function implements the following truth
  2716. * table:
  2717. *
  2718. * bugfix ecn last-cwnd == ecn action
  2719. *
  2720. * 0 0 0 full_tahoe_action
  2721. * 0 0 1 full_tahoe_action [impossible]
  2722. * 0 1 0 full_tahoe_action
  2723. * 0 1 1 1/2 window, return
  2724. * 1 0 0 nothing
  2725. * 1 0 1 nothing [impossible]
  2726. * 1 1 0 nothing
  2727. * 1 1 1 1/2 window, return
  2728. */
  2729.  
  2730. void
  2731. TahoeFullTcpAgent::dupack_action()
  2732. {
  2733. int recovered = (highest_ack_ > recover_);
  2734.  
  2735. fastrecov_ = TRUE;
  2736. rtxbytes_ = ;
  2737.  
  2738. if (recovered || (!bug_fix_ && !ecn_) || highest_ack_ == ) {
  2739. goto full_tahoe_action;
  2740. }
  2741.  
  2742. if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
  2743. // slow start on ECN
  2744. last_cwnd_action_ = CWND_ACTION_DUPACK;
  2745. slowdown(CLOSE_CWND_ONE);
  2746. set_rtx_timer();
  2747. rtt_active_ = FALSE;
  2748. t_seqno_ = highest_ack_;
  2749. return;
  2750. }
  2751.  
  2752. if (bug_fix_) {
  2753. /*
  2754. * The line below, for "bug_fix_" true, avoids
  2755. * problems with multiple fast retransmits in one
  2756. * window of data.
  2757. */
  2758. return;
  2759. }
  2760.  
  2761. full_tahoe_action:
  2762. // slow-start and reset ssthresh
  2763. trace_event("FAST_RETX");
  2764. recover_ = maxseq_;
  2765. last_cwnd_action_ = CWND_ACTION_DUPACK;
  2766. slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_ONE); // cwnd->1
  2767. set_rtx_timer();
  2768. rtt_active_ = FALSE;
  2769. t_seqno_ = highest_ack_;
  2770. send_much(, REASON_NORMAL, );
  2771. return;
  2772. }
  2773.  
  2774. /*
  2775. * ****** Newreno ******
  2776. *
  2777. * for NewReno, a partial ACK does not exit fast recovery,
  2778. * and does not reset the dup ACK counter (which might trigger fast
  2779. * retransmits we don't want). In addition, the number of packets
  2780. * sent in response to an ACK is limited to recov_maxburst_ during
  2781. * recovery periods.
  2782. */
  2783.  
  2784. NewRenoFullTcpAgent::NewRenoFullTcpAgent() : save_maxburst_(-)
  2785. {
  2786. bind("recov_maxburst_", &recov_maxburst_);
  2787. }
  2788.  
  2789. void
  2790. NewRenoFullTcpAgent::pack_action(Packet*)
  2791. {
  2792. (void)fast_retransmit(highest_ack_);
  2793. cwnd_ = double(ssthresh_);
  2794. if (save_maxburst_ < ) {
  2795. save_maxburst_ = maxburst_;
  2796. maxburst_ = recov_maxburst_;
  2797. }
  2798. return;
  2799. }
  2800.  
  2801. void
  2802. NewRenoFullTcpAgent::ack_action(Packet* p)
  2803. {
  2804. if (save_maxburst_ >= ) {
  2805. maxburst_ = save_maxburst_;
  2806. save_maxburst_ = -;
  2807. }
  2808. FullTcpAgent::ack_action(p);
  2809. return;
  2810. }
  2811.  
  2812. /*
  2813. *
  2814. * ****** SACK ******
  2815. *
  2816. * for Sack, receiver part must report SACK data
  2817. * sender part maintains a 'scoreboard' (sq_) that
  2818. * records what it hears from receiver
  2819. * sender fills holes during recovery and obeys
  2820. * "pipe" style control until recovery is complete
  2821. */
  2822.  
  2823. void
  2824. SackFullTcpAgent::reset()
  2825. {
  2826. sq_.clear(); // no SACK blocks
  2827. /* Fixed typo. -M. Weigle 6/17/02 */
  2828. sack_min_ = h_seqno_ = -; // no left edge of SACK blocks
  2829. FullTcpAgent::reset();
  2830. }
  2831.  
  2832. int
  2833. SackFullTcpAgent::hdrsize(int nsackblocks)
  2834. {
  2835. int total = FullTcpAgent::headersize();
  2836. // use base header size plus SACK option size
  2837. if (nsackblocks > ) {
  2838. total += ((nsackblocks * sack_block_size_)
  2839. + sack_option_size_);
  2840. }
  2841. return (total);
  2842. }
  2843.  
  2844. void
  2845. SackFullTcpAgent::dupack_action()
  2846. {
  2847.  
  2848. int recovered = (highest_ack_ > recover_);
  2849.  
  2850. fastrecov_ = TRUE;
  2851. rtxbytes_ = ;
  2852. pipe_ = maxseq_ - highest_ack_ - sq_.total();
  2853.  
  2854. //printf("%f: SACK DUPACK-ACTION:pipe_:%d, sq-total:%d, bugfix:%d, cwnd:%d, highest_ack:%d, recover_:%d\n",
  2855. //now(), pipe_, sq_.total(), bug_fix_, int(cwnd_), int(highest_ack_), recover_);
  2856.  
  2857. if (recovered || (!bug_fix_ && !ecn_)) {
  2858. goto full_sack_action;
  2859. }
  2860.  
  2861. if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
  2862. /*
  2863. * Received ECN notification and 3 DUPACKs in same
  2864. * window. Don't cut cwnd again, but retransmit lost
  2865. * packet. -M. Weigle 6/19/02
  2866. */
  2867. last_cwnd_action_ = CWND_ACTION_DUPACK;
  2868. cancel_rtx_timer();
  2869. rtt_active_ = FALSE;
  2870. int amt = fast_retransmit(highest_ack_);
  2871. pipectrl_ = TRUE;
  2872. h_seqno_ = highest_ack_ + amt;
  2873. send_much(, REASON_DUPACK, maxburst_);
  2874. return;
  2875. }
  2876.  
  2877. if (bug_fix_) {
  2878. /*
  2879. * The line below, for "bug_fix_" true, avoids
  2880. * problems with multiple fast retransmits in one
  2881. * window of data.
  2882. */
  2883.  
  2884. //printf("%f: SACK DUPACK-ACTION BUGFIX RETURN:pipe_:%d, sq-total:%d, bugfix:%d, cwnd:%d\n",
  2885. //now(), pipe_, sq_.total(), bug_fix_, int(cwnd_));
  2886. return;
  2887. }
  2888.  
  2889. full_sack_action:
  2890. trace_event("FAST_RECOVERY");
  2891. slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
  2892. cancel_rtx_timer();
  2893. rtt_active_ = FALSE;
  2894.  
  2895. // these initiate SACK-style "pipe" recovery
  2896. pipectrl_ = TRUE;
  2897. recover_ = maxseq_; // where I am when recovery starts
  2898.  
  2899. int amt = fast_retransmit(highest_ack_);
  2900. h_seqno_ = highest_ack_ + amt;
  2901.  
  2902. //printf("%f: FAST-RTX seq:%d, h_seqno_ is now:%d, pipe:%d, cwnd:%d, recover:%d\n",
  2903. //now(), int(highest_ack_), h_seqno_, pipe_, int(cwnd_), recover_);
  2904.  
  2905. send_much(, REASON_DUPACK, maxburst_);
  2906.  
  2907. return;
  2908. }
  2909.  
  2910. void
  2911. SackFullTcpAgent::pack_action(Packet*)
  2912. {
  2913. if (!sq_.empty() && sack_min_ < highest_ack_) {
  2914. sack_min_ = highest_ack_;
  2915. sq_.cleartonxt();
  2916. }
  2917. pipe_ -= maxseg_; // see comment in tcp-sack1.cc
  2918. if (h_seqno_ < highest_ack_)
  2919. h_seqno_ = highest_ack_;
  2920. }
  2921.  
  2922. void
  2923. SackFullTcpAgent::ack_action(Packet*)
  2924. {
  2925. //printf("%f: EXITING fast recovery, recover:%d\n",
  2926. //now(), recover_);
  2927. fastrecov_ = pipectrl_ = FALSE;
  2928. if (!sq_.empty() && sack_min_ < highest_ack_) {
  2929. sack_min_ = highest_ack_;
  2930. sq_.cleartonxt();
  2931. }
  2932. dupacks_ = ;
  2933.  
  2934. /*
  2935. * Update h_seqno_ on new ACK (same as for partial ACKS)
  2936. * -M. Weigle 6/3/05
  2937. */
  2938. if (h_seqno_ < highest_ack_)
  2939. h_seqno_ = highest_ack_;
  2940. }
  2941.  
  2942. //
  2943. // receiver side: if there are things in the reassembly queue,
  2944. // build the appropriate SACK blocks to carry in the SACK
  2945. //
  2946. int
  2947. SackFullTcpAgent::build_options(hdr_tcp* tcph)
  2948. {
  2949. int total = FullTcpAgent::build_options(tcph);
  2950.  
  2951. if (!rq_.empty()) {
  2952. int nblk = rq_.gensack(&tcph->sa_left(), max_sack_blocks_);
  2953. tcph->sa_length() = nblk;
  2954. total += (nblk * sack_block_size_) + sack_option_size_;
  2955. } else {
  2956. tcph->sa_length() = ;
  2957. }
  2958. return (total);
  2959. }
  2960.  
  2961. void
  2962. SackFullTcpAgent::timeout_action()
  2963. {
  2964. FullTcpAgent::timeout_action();
  2965.  
  2966. //
  2967. // original SACK spec says the sender is
  2968. // supposed to clear out its knowledge of what
  2969. // the receiver has in the case of a timeout
  2970. // (on the chance the receiver has renig'd).
  2971. // Here, this happens when clear_on_timeout_ is
  2972. // enabled.
  2973. //
  2974.  
  2975. if (clear_on_timeout_) {
  2976. sq_.clear();
  2977. sack_min_ = highest_ack_;
  2978. }
  2979.  
  2980. return;
  2981. }
  2982.  
  2983. void
  2984. SackFullTcpAgent::process_sack(hdr_tcp* tcph)
  2985. {
  2986. //
  2987. // Figure out how many sack blocks are
  2988. // in the pkt. Insert each block range
  2989. // into the scoreboard
  2990. //
  2991.  
  2992. if (max_sack_blocks_ <= ) {
  2993. fprintf(stderr,
  2994. "%f: FullTcpAgent(%s) warning: received SACK block but I am not SACK enabled\n",
  2995. now(), name());
  2996. return;
  2997. }
  2998.  
  2999. int slen = tcph->sa_length(), i;
  3000. for (i = ; i < slen; ++i) {
  3001. /* Added check for FIN -M. Weigle 5/21/02 */
  3002. if (((tcph->flags() & TH_FIN) == ) &&
  3003. tcph->sa_left(i) >= tcph->sa_right(i)) {
  3004. fprintf(stderr,
  3005. "%f: FullTcpAgent(%s) warning: received illegal SACK block [%d,%d]\n",
  3006. now(), name(), tcph->sa_left(i), tcph->sa_right(i));
  3007. continue;
  3008. }
  3009. sq_.add(tcph->sa_left(i), tcph->sa_right(i), );
  3010. }
  3011.  
  3012. return;
  3013. }
  3014.  
  3015. int
  3016. SackFullTcpAgent::send_allowed(int seq)
  3017. {
  3018. // not in pipe control, so use regular control
  3019. if (!pipectrl_)
  3020. return (FullTcpAgent::send_allowed(seq));
  3021.  
  3022. // don't overshoot receiver's advertised window
  3023. int topawin = highest_ack_ + int(wnd_) * maxseg_;
  3024. if (seq >= topawin) {
  3025. //printf("%f: SEND(%d) NOT ALLOWED DUE TO AWIN:%d, pipe:%d, cwnd:%d\n",
  3026. //now(), seq, topawin, pipe_, int(cwnd_));
  3027. return FALSE;
  3028. }
  3029.  
  3030. /*
  3031. * If not in ESTABLISHED, don't send anything we don't have
  3032. * -M. Weigle 7/18/02
  3033. */
  3034. if (state_ != TCPS_ESTABLISHED && seq > curseq_)
  3035. return FALSE;
  3036.  
  3037. // don't overshoot cwnd_
  3038. int cwin = int(cwnd_) * maxseg_;
  3039. return (pipe_ < cwin);
  3040. }
  3041.  
  3042. //
  3043. // Calculate the next seq# to send by send_much. If we are recovering and
  3044. // we have learned about data cached at the receiver via a SACK,
  3045. // we may want something other than new data (t_seqno)
  3046. //
  3047.  
  3048. int
  3049. SackFullTcpAgent::nxt_tseq()
  3050. {
  3051.  
  3052. int in_recovery = (highest_ack_ < recover_);
  3053. int seq = h_seqno_;
  3054.  
  3055. if (!in_recovery) {
  3056. //if (int(t_seqno_) > 1)
  3057. //printf("%f: non-recovery nxt_tseq called w/t_seqno:%d\n",
  3058. //now(), int(t_seqno_));
  3059. //sq_.dumplist();
  3060. return (t_seqno_);
  3061. }
  3062.  
  3063. int fcnt; // following count-- the
  3064. // count field in the block
  3065. // after the seq# we are about
  3066. // to send
  3067. int fbytes; // fcnt in bytes
  3068.  
  3069. //if (int(t_seqno_) > 1)
  3070. //printf("%f: recovery nxt_tseq called w/t_seqno:%d, seq:%d, mode:%d\n",
  3071. //now(), int(t_seqno_), seq, sack_rtx_threshmode_);
  3072. //sq_.dumplist();
  3073.  
  3074. while ((seq = sq_.nexthole(seq, fcnt, fbytes)) > ) {
  3075. // if we have a following block
  3076. // with a large enough count
  3077. // we should use the seq# we get
  3078. // from nexthole()
  3079. if (sack_rtx_threshmode_ == ||
  3080. (sack_rtx_threshmode_ == && fcnt >= sack_rtx_cthresh_) ||
  3081. (sack_rtx_threshmode_ == && fbytes >= sack_rtx_bthresh_) ||
  3082. (sack_rtx_threshmode_ == && (fcnt >= sack_rtx_cthresh_ || fbytes >= sack_rtx_bthresh_)) ||
  3083. (sack_rtx_threshmode_ == && (fcnt >= sack_rtx_cthresh_ && fbytes >= sack_rtx_bthresh_))) {
  3084.  
  3085. //if (int(t_seqno_) > 1)
  3086. //printf("%f: nxt_tseq<hole> returning %d\n",
  3087. //now(), int(seq));
  3088. // adjust h_seqno, as we may have
  3089. // been "jumped ahead" by learning
  3090. // about a filled hole
  3091. if (seq > h_seqno_)
  3092. h_seqno_ = seq;
  3093. return (seq);
  3094. } else if (fcnt <= )
  3095. break;
  3096. else {
  3097. seq += maxseg_;
  3098. }
  3099. }
  3100. //if (int(t_seqno_) > 1)
  3101. //printf("%f: nxt_tseq<top> returning %d\n",
  3102. //now(), int(t_seqno_));
  3103. return (t_seqno_);
  3104. }

tcp-full.cc的更多相关文章

  1. 现代互联网的TCP拥塞控制(CC)算法评谈

    动机 写这篇文章本质上的动机是因为前天发了一个朋友圈,见最后的写在最后,但实际上,我早就想总结总结TCP拥塞控制算法点点滴滴了,上周总结了一张图,这周接着那些,写点文字. 前些天,Linux中国微信公 ...

  2. TCP的.cc文件代码解释(中文)

    #ifndef lint static const char rcsid[] =     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp ...

  3. (转)TCP注册端口号大全

    分类: 网络与安全 cisco-sccp 2000/tcp Cisco SCCPcisco-sccp 2000/udp Cisco SCCp# Dan Wing <dwing&cisco ...

  4. TCP三次握手那些事

    临近5月,春招和实习招聘逐渐进入尾声.本文主要讨论面试中经常提问的TCP连接的机制,附带一些扩展知识. 参加面试的时候,过半的面试官都会问TCP相关问题,而最常见的问题就是:讲一下TCP三次握手(四次 ...

  5. 网络-05-端口号-F5-负载均衡设-linux端口详解大全--TCP注册端口号大全备

    [root@test1:Standby] config # [root@test1:Standby] config # [root@test1:Standby] config # [root@test ...

  6. TCP常用网络和木马使用端口对照表,常用和不常用端口一览表

    [开始-运行- CMD , 输入 netstat -an 然后回车就可以查看端口] 端口: 服务:Reserved 说明:通常用于分析操作系统.这一方法能够工作是因为在一些系统中“”是无效端口,当你试 ...

  7. 要开始恶补Layer4-7 TCP/IP相关的姿势了,今天立个Flag

    今天开区域销售会,被老板K了一顿大的!(:/手动委屈:) 说产品出来这么久,怎么没看到你们的跟接触客户的使用报告记录,一年快到头了,试用客户才个位数?你们了解自己的产品吗,然后轮着上去一个个做功能演示 ...

  8. 【转】虚拟机VMware与主机共享文件介绍

    from: http://www.cnblogs.com/kerrycode/p/3818095.html 写的比较详细,但是vm版本较旧. 2:通过共享文件夹功能 虚拟机VMware提供了在宿主机与 ...

  9. linux查看端口及端口详解

    今天现场查看了TCP端口的占用情况,如下图   红色部分是IP,现场那边问我是不是我的程序占用了tcp的链接,,我远程登陆现场查看了一下,这种类型的tcp链接占用了400多个,,后边查了一下资料,说E ...

随机推荐

  1. vue 深度响应初步了解(检测data对象数据变化)

    当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为 getter/se ...

  2. 卸载Windows,安装纯Linux

    操作步骤 下载安装一键GHOST优盘版 参考帮助文档,安装U盘启动 重启电脑,F12进入模式选择界面,选择USB device 选择DOS 工具 进入Disk Genius 删除掉除主分区(0)外的其 ...

  3. 《大数据日知录》读书笔记-ch3大数据常用的算法与数据结构

    布隆过滤器(bloom filter,BF): 二进制向量数据结构,时空效率很好,尤其是空间效率极高.作用:检测某个元素在某个巨量集合中存在. 构造: 查询: 不会发生漏判(false negativ ...

  4. Http请求响应模型

    主要用到以下四个部分: Client   API   DB   API 场景:登录 1.Client发起请求到API接口层 1.1用户在客户端输入登录信息,点击登录,发送请求 2.API接受用户发起的 ...

  5. 【Nginx】关于域名转发proxy_pass

    在配置nginx的时候,有一个需求,访问m.XXX.com的时候,需要实际访问www.YYY.com/m,并且域名不能发生变化. 达成这个需求有两种做法: 第一种就是301跳转,使用rewrite来跳 ...

  6. poj 1284 Primitive Roots(未完)

    Primitive Roots Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3155   Accepted: 1817 D ...

  7. SpringMVC的json交互

    一.注解说明 1.@RequestBody  作用:@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内 ...

  8. bzoj 5252: [2018多省省队联测]林克卡特树

    Description 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做& ...

  9. Js的小技巧

    感谢好友破狼提供的这篇好文章,也感谢写这些知识点的作者们和将他们整理到一起的作者.这是github上的一篇文章,在这里本兽也就只做翻译,由于本兽英语水平和编程能力都不咋地,如有不好的地方也请多理解体谅 ...

  10. 判断网站域名是否被GFW(墙)过滤屏蔽了

    GFW:Greate Firewall Of China中国防火长城: 描述: 1.今天所属的一个域名被告诉不能访问了,赶紧自己测试了一下,发现可以,然后对方试了下说是不行,然后仔细按对方说的一步步操 ...