tcp-full.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 
00003 /*
00004  * Copyright (c) Intel Corporation 2001. All rights reserved.
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *   http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * Copyright (c) 1997, 1998 The Regents of the University of California.
00020  * All rights reserved.
00021  * 
00022  * Redistribution and use in source and binary forms, with or without
00023  * modification, are permitted provided that the following conditions
00024  * are met:
00025  * 1. Redistributions of source code must retain the above copyright
00026  *    notice, this list of conditions and the following disclaimer.
00027  * 2. Redistributions in binary form must reproduce the above copyright
00028  *    notice, this list of conditions and the following disclaimer in the
00029  *    documentation and/or other materials provided with the distribution.
00030  * 3. All advertising materials mentioning features or use of this software
00031  *    must display the following acknowledgement:
00032  *  This product includes software developed by the Network Research
00033  *  Group at Lawrence Berkeley National Laboratory.
00034  * 4. Neither the name of the University nor of the Laboratory may be used
00035  *    to endorse or promote products derived from this software without
00036  *    specific prior written permission.
00037  * 
00038  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00039  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00040  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00041  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00042  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00043  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00044  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00045  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00046  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00047  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00048  * SUCH DAMAGE.
00049  */
00050 
00051 /*
00052  * Full-TCP : A two-way TCP very similar to the 4.4BSD version of Reno TCP.
00053  * This version also includes variants Tahoe, NewReno, and SACK.
00054  *
00055  * This code below has received a fairly major restructuring (Aug. 2001).
00056  * The ReassemblyQueue structure is now removed to a separate module and
00057  * entirely re-written.
00058  * Also, the SACK functionality has been re-written (almost) entirely.
00059  * -KF [kfall@intel.com]
00060  *
00061  * This code below was motivated in part by code contributed by
00062  * Kathie Nichols (nichols@baynetworks.com).  The code below is based primarily
00063  * on the 4.4BSD TCP implementation. -KF [kfall@ee.lbl.gov]
00064  *
00065  * Kathie Nichols and Van Jacobson have contributed significant bug fixes,
00066  * especially with respect to the the handling of sequence numbers during
00067  * connection establishment/clearin.  Additional fixes have followed
00068  * theirs.
00069  *
00070  * Fixes for gensack() and ReassemblyQueue::add() contributed by Richard 
00071  * Mortier <Richard.Mortier@cl.cam.ac.uk>
00072  *
00073  * Some warnings and comments:
00074  *  this version of TCP will not work correctly if the sequence number
00075  *  goes above 2147483648 due to sequence number wrap
00076  *
00077  *  this version of TCP by default sends data at the beginning of a
00078  *  connection in the "typical" way... That is,
00079  *      A   ------> SYN ------> B
00080  *      A   <----- SYN+ACK ---- B
00081  *      A   ------> ACK ------> B
00082  *      A   ------> data -----> B
00083  *
00084  *  there is no dynamic receiver's advertised window.   The advertised
00085  *  window is simulated by simply telling the sender a bound on the window
00086  *  size (wnd_).
00087  *
00088  *  in real TCP, a user process performing a read (via PRU_RCVD)
00089  *      calls tcp_output each time to (possibly) send a window
00090  *      update.  Here we don't have a user process, so we simulate
00091  *      a user process always ready to consume all the receive buffer
00092  *
00093  * Notes:
00094  *  wnd_, wnd_init_, cwnd_, ssthresh_ are in segment units
00095  *  sequence and ack numbers are in byte units
00096  *
00097  * Futures:
00098  *      there are different existing TCPs with respect to how
00099  *      ack's are handled on connection startup.  Some delay
00100  *      the ack for the first segment, which can cause connections
00101  *      to take longer to start up than if we be sure to ack it quickly.
00102  *
00103  *      some TCPs arrange for immediate ACK generation if the incoming segment
00104  *      contains the PUSH bit
00105  *
00106  *
00107  */
00108 
00109 #ifndef lint
00110 static const char rcsid[] =
00111     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-full.cc,v 1.118 2005/08/02 04:02:58 tomh Exp $ (LBL)";
00112 #endif
00113 
00114 #include "ip.h"
00115 #include "tcp-full.h"
00116 #include "flags.h"
00117 #include "random.h"
00118 #include "template.h"
00119 
00120 #ifndef TRUE
00121 #define TRUE    1
00122 #endif
00123 
00124 #ifndef FALSE
00125 #define FALSE   0
00126 #endif
00127 
00128 /*
00129  * Tcl Linkage for the following:
00130  *  Agent/TCP/FullTcp, Agent/TCP/FullTcp/Tahoe,
00131  *  Agent/TCP/FullTcp/Newreno, Agent/TCP/FullTcp/Sack
00132  *
00133  * See tcl/lib/ns-default.tcl for init methods for
00134  *  Tahoe, Newreno, and Sack
00135  */
00136 
00137 static class FullTcpClass : public TclClass { 
00138 public:
00139     FullTcpClass() : TclClass("Agent/TCP/FullTcp") {}
00140     TclObject* create(int, const char*const*) { 
00141         return (new FullTcpAgent());
00142     }
00143 } class_full;
00144 
00145 static class TahoeFullTcpClass : public TclClass { 
00146 public:
00147     TahoeFullTcpClass() : TclClass("Agent/TCP/FullTcp/Tahoe") {}
00148     TclObject* create(int, const char*const*) { 
00149         // ns-default sets reno_fastrecov_ to false
00150         return (new TahoeFullTcpAgent());
00151     }
00152 } class_tahoe_full;
00153 
00154 static class NewRenoFullTcpClass : public TclClass { 
00155 public:
00156     NewRenoFullTcpClass() : TclClass("Agent/TCP/FullTcp/Newreno") {}
00157     TclObject* create(int, const char*const*) { 
00158         // ns-default sets open_cwnd_on_pack_ to false
00159         return (new NewRenoFullTcpAgent());
00160     }
00161 } class_newreno_full;
00162 
00163 static class SackFullTcpClass : public TclClass { 
00164 public:
00165     SackFullTcpClass() : TclClass("Agent/TCP/FullTcp/Sack") {}
00166     TclObject* create(int, const char*const*) { 
00167         // ns-default sets reno_fastrecov_ to false
00168         // ns-default sets open_cwnd_on_pack_ to false
00169         return (new SackFullTcpAgent());
00170     }
00171 } class_sack_full;
00172 
00173 /*
00174  * Delayed-binding variable linkage
00175  */
00176 
00177 void
00178 FullTcpAgent::delay_bind_init_all()
00179 {
00180         delay_bind_init_one("segsperack_");
00181         delay_bind_init_one("segsize_");
00182         delay_bind_init_one("tcprexmtthresh_");
00183         delay_bind_init_one("iss_");
00184         delay_bind_init_one("nodelay_");
00185         delay_bind_init_one("data_on_syn_");
00186         delay_bind_init_one("dupseg_fix_");
00187         delay_bind_init_one("dupack_reset_");
00188         delay_bind_init_one("close_on_empty_");
00189         delay_bind_init_one("signal_on_empty_");
00190         delay_bind_init_one("interval_");
00191         delay_bind_init_one("ts_option_size_");
00192         delay_bind_init_one("reno_fastrecov_");
00193         delay_bind_init_one("pipectrl_");
00194         delay_bind_init_one("open_cwnd_on_pack_");
00195         delay_bind_init_one("halfclose_");
00196         delay_bind_init_one("nopredict_");
00197         delay_bind_init_one("spa_thresh_");
00198 
00199     TcpAgent::delay_bind_init_all();
00200        
00201         reset();
00202 }
00203 
00204 int
00205 FullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
00206 {
00207         if (delay_bind(varName, localName, "segsperack_", &segs_per_ack_, tracer)) return TCL_OK;
00208         if (delay_bind(varName, localName, "segsize_", &maxseg_, tracer)) return TCL_OK;
00209         if (delay_bind(varName, localName, "tcprexmtthresh_", &tcprexmtthresh_, tracer)) return TCL_OK;
00210         if (delay_bind(varName, localName, "iss_", &iss_, tracer)) return TCL_OK;
00211         if (delay_bind(varName, localName, "spa_thresh_", &spa_thresh_, tracer)) return TCL_OK;
00212         if (delay_bind_bool(varName, localName, "nodelay_", &nodelay_, tracer)) return TCL_OK;
00213         if (delay_bind_bool(varName, localName, "data_on_syn_", &data_on_syn_, tracer)) return TCL_OK;
00214         if (delay_bind_bool(varName, localName, "dupseg_fix_", &dupseg_fix_, tracer)) return TCL_OK;
00215         if (delay_bind_bool(varName, localName, "dupack_reset_", &dupack_reset_, tracer)) return TCL_OK;
00216         if (delay_bind_bool(varName, localName, "close_on_empty_", &close_on_empty_, tracer)) return TCL_OK;
00217         if (delay_bind_bool(varName, localName, "signal_on_empty_", &signal_on_empty_, tracer)) return TCL_OK;
00218         if (delay_bind_time(varName, localName, "interval_", &delack_interval_, tracer)) return TCL_OK;
00219         if (delay_bind(varName, localName, "ts_option_size_", &ts_option_size_, tracer)) return TCL_OK;
00220         if (delay_bind_bool(varName, localName, "reno_fastrecov_", &reno_fastrecov_, tracer)) return TCL_OK;
00221         if (delay_bind_bool(varName, localName, "pipectrl_", &pipectrl_, tracer)) return TCL_OK;
00222         if (delay_bind_bool(varName, localName, "open_cwnd_on_pack_", &open_cwnd_on_pack_, tracer)) return TCL_OK;
00223         if (delay_bind_bool(varName, localName, "halfclose_", &halfclose_, tracer)) return TCL_OK;
00224         if (delay_bind_bool(varName, localName, "nopredict_", &nopredict_, tracer)) return TCL_OK;
00225 
00226         return TcpAgent::delay_bind_dispatch(varName, localName, tracer);
00227 }
00228 
00229 void
00230 SackFullTcpAgent::delay_bind_init_all()
00231 {
00232         delay_bind_init_one("clear_on_timeout_");
00233         delay_bind_init_one("sack_rtx_cthresh_");
00234         delay_bind_init_one("sack_rtx_bthresh_");
00235         delay_bind_init_one("sack_block_size_");
00236         delay_bind_init_one("sack_option_size_");
00237         delay_bind_init_one("max_sack_blocks_");
00238         delay_bind_init_one("sack_rtx_threshmode_");
00239     FullTcpAgent::delay_bind_init_all();
00240 }
00241 
00242 int
00243 SackFullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
00244 {
00245         if (delay_bind_bool(varName, localName, "clear_on_timeout_", &clear_on_timeout_, tracer)) return TCL_OK;
00246         if (delay_bind(varName, localName, "sack_rtx_cthresh_", &sack_rtx_cthresh_, tracer)) return TCL_OK;
00247         if (delay_bind(varName, localName, "sack_rtx_bthresh_", &sack_rtx_bthresh_, tracer)) return TCL_OK;
00248         if (delay_bind(varName, localName, "sack_rtx_threshmode_", &sack_rtx_threshmode_, tracer)) return TCL_OK;
00249         if (delay_bind(varName, localName, "sack_block_size_", &sack_block_size_, tracer)) return TCL_OK;
00250         if (delay_bind(varName, localName, "sack_option_size_", &sack_option_size_, tracer)) return TCL_OK;
00251         if (delay_bind(varName, localName, "max_sack_blocks_", &max_sack_blocks_, tracer)) return TCL_OK;
00252         return FullTcpAgent::delay_bind_dispatch(varName, localName, tracer);
00253 }
00254 
00255 int
00256 FullTcpAgent::command(int argc, const char*const* argv)
00257 {
00258     // would like to have some "connect" primitive
00259     // here, but the problem is that we get called before
00260     // the simulation is running and we want to send a SYN.
00261     // Because no routing exists yet, this fails.
00262     // Instead, see code in advance().
00263     //
00264     // listen can happen any time because it just changes state_
00265     //
00266     // close is designed to happen at some point after the
00267     // simulation is running (using an ns 'at' command)
00268 
00269     if (argc == 2) {
00270         if (strcmp(argv[1], "listen") == 0) {
00271             // just a state transition
00272             listen();
00273             return (TCL_OK);
00274         }
00275         if (strcmp(argv[1], "close") == 0) {
00276             usrclosed();
00277             return (TCL_OK);
00278         }
00279     }
00280     if (argc == 3) {
00281         if (strcmp(argv[1], "advance") == 0) {
00282             advanceby(atoi(argv[2]));
00283             return (TCL_OK);
00284         }
00285         if (strcmp(argv[1], "advanceby") == 0) {
00286             advanceby(atoi(argv[2]));
00287             return (TCL_OK);
00288         }
00289         if (strcmp(argv[1], "advance-bytes") == 0) {
00290             advance_bytes(atoi(argv[2]));
00291             return (TCL_OK);
00292         }
00293     }
00294     if (argc == 4) {
00295         if (strcmp(argv[1], "sendmsg") == 0) {
00296             sendmsg(atoi(argv[2]), argv[3]);
00297             return (TCL_OK);
00298         }
00299     }
00300     return (TcpAgent::command(argc, argv));
00301 }
00302 
00303 /*
00304  * "User Interface" Functions for Full TCP
00305  *  advanceby(number of packets)
00306  *  advance_bytes(number of bytes)
00307  *  sendmsg(int bytes, char* buf)
00308  *  listen
00309  *  close
00310  */
00311 
00312 /*
00313  * the 'advance' interface to the regular tcp is in packet
00314  * units.  Here we scale this to bytes for full tcp.
00315  *
00316  * 'advance' is normally called by an "application" (i.e. data source)
00317  * to signal that there is something to send
00318  *
00319  * 'curseq_' is the sequence number of the last byte provided
00320  * by the application.  In the case where no data has been supplied
00321  * by the application, curseq_ is the iss_.
00322  */
00323 void
00324 FullTcpAgent::advanceby(int np)
00325 {
00326     // XXX hack:
00327     //  because np is in packets and a data source
00328     //  may pass a *huge* number as a way to tell us
00329     //  to go forever, just look for the huge number
00330     //  and if it's there, pre-divide it
00331     if (np >= 0x10000000)
00332         np /= maxseg_;
00333 
00334     advance_bytes(np * maxseg_);
00335     return;
00336 }
00337 
00338 /*
00339  * the byte-oriented interface: advance_bytes(int nbytes)
00340  */
00341 
00342 void
00343 FullTcpAgent::advance_bytes(int nb)
00344 {
00345 
00346     //
00347     // state-specific operations:
00348     //  if CLOSED or LISTEN, reset and try a new active open/connect
00349     //  if ESTABLISHED, queue and try to send more
00350     //  if SYN_SENT or SYN_RCVD, just queue
00351     //  if above ESTABLISHED, we are closing, so don't allow
00352     //
00353 
00354     switch (state_) {
00355 
00356     case TCPS_CLOSED:
00357     case TCPS_LISTEN:
00358                 reset();
00359                 curseq_ = iss_ + nb;
00360                 connect();              // initiate new connection
00361         break;
00362 
00363     case TCPS_ESTABLISHED:
00364     case TCPS_SYN_SENT:
00365     case TCPS_SYN_RECEIVED:
00366                 if (curseq_ < iss_) 
00367                         curseq_ = iss_; 
00368                 curseq_ += nb;
00369         break;
00370 
00371     default:
00372         fprintf(stderr,
00373         "%f: FullTcpAgent::advance(%s): cannot advance while in state %s\n",
00374          now(), name(), statestr(state_));
00375 
00376     }
00377 
00378     if (state_ == TCPS_ESTABLISHED)
00379         send_much(0, REASON_NORMAL, maxburst_);
00380 
00381     return;
00382 }
00383 
00384 /*
00385  * If MSG_EOF is set, by setting close_on_empty_ to TRUE, we ensure that
00386  * a FIN will be sent when the send buffer emptys.
00387  * If DAT_EOF is set, the callback function done_data is called
00388  * when the send buffer empty
00389  * 
00390  * When (in the future?) FullTcpAgent implements T/TCP, avoidance of 3-way 
00391  * handshake can be handled in this function.
00392  */
00393 void
00394 FullTcpAgent::sendmsg(int nbytes, const char *flags)
00395 {
00396     if (flags && strcmp(flags, "MSG_EOF") == 0) 
00397         close_on_empty_ = TRUE; 
00398     if (flags && strcmp(flags, "DAT_EOF") == 0) 
00399         signal_on_empty_ = TRUE;    
00400 
00401     if (nbytes == -1) {
00402         infinite_send_ = TRUE;
00403         advance_bytes(0);
00404     } else
00405         advance_bytes(nbytes);
00406 }
00407 
00408 /*
00409  * do an active open
00410  * (in real TCP, see tcp_usrreq, case PRU_CONNECT)
00411  */
00412 void
00413 FullTcpAgent::connect()
00414 {
00415     newstate(TCPS_SYN_SENT);    // sending a SYN now
00416     sent(iss_, foutput(iss_, REASON_NORMAL));
00417     return;
00418 }
00419 
00420 /*
00421  * be a passive opener
00422  * (in real TCP, see tcp_usrreq, case PRU_LISTEN)
00423  * (for simulation, make this peer's ptype ACKs)
00424  */
00425 void
00426 FullTcpAgent::listen()
00427 {
00428     newstate(TCPS_LISTEN);
00429     type_ = PT_ACK; // instead of PT_TCP
00430 }
00431 
00432 
00433 /*
00434 * This function is invoked when the sender buffer is empty. It in turn
00435 * invokes the Tcl done_data procedure that was registered with TCP.
00436 */
00437  
00438 void
00439 FullTcpAgent::bufferempty()
00440 {
00441     signal_on_empty_=FALSE;
00442     Tcl::instance().evalf("%s done_data", this->name());
00443 }
00444 
00445 
00446 /*
00447  * called when user/application performs 'close'
00448  */
00449 
00450 void
00451 FullTcpAgent::usrclosed()
00452 {
00453     curseq_ = maxseq_ - 1;  // now, no more data
00454     infinite_send_ = FALSE; // stop infinite send
00455 
00456     switch (state_) {
00457     case TCPS_CLOSED:
00458     case TCPS_LISTEN:
00459         cancel_timers();
00460         newstate(TCPS_CLOSED);
00461         finish();
00462         break;
00463     case TCPS_SYN_SENT:
00464         newstate(TCPS_CLOSED);
00465         /* fall through */
00466     case TCPS_LAST_ACK:
00467         flags_ |= TF_NEEDFIN;
00468         send_much(1, REASON_NORMAL, maxburst_);
00469         break;
00470     case TCPS_SYN_RECEIVED:
00471     case TCPS_ESTABLISHED:
00472         newstate(TCPS_FIN_WAIT_1);
00473         flags_ |= TF_NEEDFIN;
00474         send_much(1, REASON_NORMAL, maxburst_);
00475         break;
00476     case TCPS_CLOSE_WAIT:
00477         newstate(TCPS_LAST_ACK);
00478         flags_ |= TF_NEEDFIN;
00479         send_much(1, REASON_NORMAL, maxburst_);
00480         break;
00481     case TCPS_FIN_WAIT_1:
00482     case TCPS_FIN_WAIT_2:
00483     case TCPS_CLOSING:
00484         /* usr asked for a close more than once [?] */
00485         fprintf(stderr,
00486           "%f FullTcpAgent(%s): app close in bad state %s\n",
00487           now(), name(), statestr(state_));
00488         break;
00489     default:
00490         fprintf(stderr,
00491           "%f FullTcpAgent(%s): app close in unknown state %s\n",
00492           now(), name(), statestr(state_));
00493     }
00494 
00495     return;
00496 }
00497 
00498 /*
00499  * Utility type functions
00500  */
00501 
00502 void
00503 FullTcpAgent::cancel_timers()
00504 {
00505 
00506     // cancel: rtx, burstsend, delsnd
00507     TcpAgent::cancel_timers();      
00508     // cancel: delack
00509     delack_timer_.force_cancel();
00510 }
00511 
00512 void
00513 FullTcpAgent::newstate(int state)
00514 {
00515 //printf("%f(%s): state changed from %s to %s\n",
00516 //now(), name(), statestr(state_), statestr(state));
00517 
00518     state_ = state;
00519 }
00520 
00521 void
00522 FullTcpAgent::prpkt(Packet *pkt)
00523 {
00524     hdr_tcp *tcph = hdr_tcp::access(pkt);   // TCP header
00525     hdr_cmn *th = hdr_cmn::access(pkt); // common header (size, etc)
00526     //hdr_flags *fh = hdr_flags::access(pkt);   // flags (CWR, CE, bits)
00527     hdr_ip* iph = hdr_ip::access(pkt);
00528     int datalen = th->size() - tcph->hlen(); // # payload bytes
00529 
00530     fprintf(stdout, " [%d:%d.%d>%d.%d] (hlen:%d, dlen:%d, seq:%d, ack:%d, flags:0x%x (%s), salen:%d, reason:0x%x)\n",
00531         th->uid(),
00532         iph->saddr(), iph->sport(),
00533         iph->daddr(), iph->dport(),
00534         tcph->hlen(),
00535         datalen,
00536         tcph->seqno(),
00537         tcph->ackno(),
00538         tcph->flags(), flagstr(tcph->flags()),
00539         tcph->sa_length(),
00540         tcph->reason());
00541 }
00542 
00543 char *
00544 FullTcpAgent::flagstr(int hflags)
00545 {
00546     // update this if tcp header flags change
00547     static char *flagstrs[28] = {
00548         "<null>", "<FIN>", "<SYN>", "<SYN,FIN>",    // 0-3
00549         "<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>", // 4-7
00550         "<PSH>", "<PSH,FIN>", "<PSH,SYN>", "<PSH,SYN,FIN>", // 0x08-0x0b
00551         /* do not use <??, in next line because that's an ANSI trigraph */
00552         "<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>",     // 0x0c-0x0f
00553         "<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>", // 0x10-0x13
00554         "<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>", // 0x14-0x17
00555         "<PSH,ACK>", "<PSH,ACK,FIN>", "<PSH,ACK,SYN>", "<PSH,ACK,SYN,FIN>", // 0x18-0x1b
00556     };
00557     if (hflags < 0 || (hflags > 28)) {
00558         /* Added strings for CWR and ECE  -M. Weigle 6/27/02 */
00559         if (hflags == 72) 
00560             return ("<ECE,PSH>");
00561         else if (hflags == 80)
00562             return ("<ECE,ACK>");
00563         else if (hflags == 88) 
00564             return ("<ECE,PSH,ACK>");
00565         else if (hflags == 152) 
00566             return ("<CWR,PSH,ACK>");
00567         else if (hflags == 153)
00568             return ("<CWR,PSH,ACK,FIN>");
00569         else
00570             return ("<invalid>");
00571     }
00572     return (flagstrs[hflags]);
00573 }
00574 
00575 char *
00576 FullTcpAgent::statestr(int state)
00577 {
00578     static char *statestrs[TCP_NSTATES] = {
00579         "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD",
00580         "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
00581         "LAST_ACK", "FIN_WAIT_2"
00582     };
00583     if (state < 0 || (state >= TCP_NSTATES))
00584         return ("INVALID");
00585     return (statestrs[state]);
00586 }
00587 
00588 void
00589 DelAckTimer::expire(Event *) {
00590         a_->timeout(TCP_TIMER_DELACK);
00591 }
00592 
00593 /*
00594  * reset to starting point, don't set state_ here,
00595  * because our starting point might be LISTEN rather
00596  * than CLOSED if we're a passive opener
00597  */
00598 void
00599 FullTcpAgent::reset()
00600 {
00601     cancel_timers();    // cancel timers first
00602         TcpAgent::reset();  // resets most variables
00603     rq_.clear();        // clear reassembly queue
00604     rtt_init();     // zero rtt, srtt, backoff
00605 
00606     last_ack_sent_ = -1;
00607     rcv_nxt_ = -1;
00608     pipe_ = 0;
00609     rtxbytes_ = 0;
00610     flags_ = 0;
00611     t_seqno_ = iss_;
00612     maxseq_ = -1;
00613     irs_ = -1;
00614     last_send_time_ = -1.0;
00615     if (ts_option_)
00616         recent_ = recent_age_ = 0.0;
00617     else
00618         recent_ = recent_age_ = -1.0;
00619 
00620     fastrecov_ = FALSE;
00621 }
00622 
00623 /*
00624  * This function is invoked when the connection is done. It in turn
00625  * invokes the Tcl finish procedure that was registered with TCP.
00626  * This function mimics tcp_close()
00627  */
00628 
00629 void
00630 FullTcpAgent::finish()
00631 {
00632     Tcl::instance().evalf("%s done", this->name());
00633 }
00634 /*
00635  * headersize:
00636  *  how big is an IP+TCP header in bytes; include options such as ts
00637  * this function should be virtual so others (e.g. SACK) can override
00638  */
00639 int
00640 FullTcpAgent::headersize()
00641 {
00642     int total = tcpip_base_hdr_size_;
00643     if (total < 1) {
00644         fprintf(stderr,
00645             "%f: FullTcpAgent(%s): warning: tcpip hdr size is only %d bytes\n",
00646             now(), name(), tcpip_base_hdr_size_);
00647     }
00648 
00649     if (ts_option_)
00650         total += ts_option_size_;
00651 
00652     return (total);
00653 }
00654 
00655 /*
00656  * flags that are completely dependent on the tcp state
00657  * these are used for the next outgoing packet in foutput()
00658  * (in real TCP, see tcp_fsm.h, the "tcp_outflags" array)
00659  */
00660 int
00661 FullTcpAgent::outflags()
00662 {
00663     // in real TCP an RST is added in the CLOSED state
00664     static int tcp_outflags[TCP_NSTATES] = {
00665         TH_ACK,             /* 0, CLOSED */  
00666         0,                      /* 1, LISTEN */ 
00667         TH_SYN,                 /* 2, SYN_SENT */
00668         TH_SYN|TH_ACK,          /* 3, SYN_RECEIVED */
00669         TH_ACK,                 /* 4, ESTABLISHED */
00670         TH_ACK,                 /* 5, CLOSE_WAIT */
00671         TH_FIN|TH_ACK,          /* 6, FIN_WAIT_1 */
00672         TH_FIN|TH_ACK,          /* 7, CLOSING */
00673         TH_FIN|TH_ACK,          /* 8, LAST_ACK */
00674         TH_ACK,                 /* 9, FIN_WAIT_2 */
00675         /* 10, TIME_WAIT --- not used in simulator */
00676     };
00677 
00678     if (state_ < 0 || (state_ >= TCP_NSTATES)) {
00679         fprintf(stderr, "%f FullTcpAgent(%s): invalid state %d\n",
00680             now(), name(), state_);
00681         return (0x0);
00682     }
00683 
00684     return (tcp_outflags[state_]);
00685 }
00686 
00687 /*
00688  * reaass() -- extract the appropriate fields from the packet
00689  *  and pass this info the ReassemblyQueue add routine
00690  *
00691  * returns the TCP header flags representing the "or" of
00692  *  the flags contained in the adjacent sequence # blocks
00693  */
00694 
00695 int
00696 FullTcpAgent::reass(Packet* pkt)
00697 {  
00698         hdr_tcp *tcph =  hdr_tcp::access(pkt);
00699         hdr_cmn *th = hdr_cmn::access(pkt);
00700    
00701         int start = tcph->seqno();
00702         int end = start + th->size() - tcph->hlen();
00703         int tiflags = tcph->flags();
00704     int fillshole = (start == rcv_nxt_);
00705     int flags;
00706    
00707     // end contains the seq of the last byte of
00708     // in the packet plus one
00709 
00710     if (start == end && (tiflags & TH_FIN) == 0) {
00711         fprintf(stderr, "%f: FullTcpAgent(%s)::reass() -- bad condition - adding non-FIN zero-len seg\n",
00712             now(), name());
00713         abort();
00714     }
00715 
00716     flags = rq_.add(start, end, tiflags, 0);
00717 
00718     //present:
00719     //
00720     // If we've never received a SYN (unlikely)
00721     // or this is an out of order addition, no reason to coalesce
00722     //
00723 
00724     if (TCPS_HAVERCVDSYN(state_) == 0 || !fillshole) {
00725         return (0x00);
00726     }
00727     //
00728     // If we get some data in SYN_RECVD, no need to present to user yet
00729     //
00730     if (state_ == TCPS_SYN_RECEIVED && (end > start))
00731         return (0x00);
00732 
00733     // clear out data that has been passed, up to rcv_nxt_,
00734     // collects flags
00735 
00736     flags |= rq_.cleartonxt();
00737 
00738         return (flags);
00739 }
00740 
00741 /*
00742  * utility function to set rcv_next_ during inital exchange of seq #s
00743  */
00744 
00745 int
00746 FullTcpAgent::rcvseqinit(int seq, int dlen)
00747 {
00748     return (seq + dlen + 1);
00749 }
00750 
00751 /*
00752  * build a header with the timestamp option if asked
00753  */
00754 int
00755 FullTcpAgent::build_options(hdr_tcp* tcph)
00756 {
00757     int total = 0;
00758     if (ts_option_) {
00759         tcph->ts() = now();
00760         tcph->ts_echo() = recent_;
00761         total += ts_option_size_;
00762     } else {
00763         tcph->ts() = tcph->ts_echo() = -1.0;
00764     }
00765     return (total);
00766 }
00767 
00768 /*
00769  * pack() -- is the ACK a partial ACK? (not past recover_)
00770  */
00771 
00772 int
00773 FullTcpAgent::pack(Packet *pkt)
00774 {
00775     hdr_tcp *tcph = hdr_tcp::access(pkt);
00776     /* Added check for fast recovery.  -M. Weigle 5/2/02 */
00777     return (fastrecov_ && tcph->ackno() >= highest_ack_ &&
00778         tcph->ackno() < recover_);
00779 }
00780 
00781 /*
00782  * baseline reno TCP exists fast recovery on a partial ACK
00783  */
00784 
00785 void
00786 FullTcpAgent::pack_action(Packet*)
00787 {
00788     if (reno_fastrecov_ && fastrecov_ && cwnd_ > double(ssthresh_)) {
00789         cwnd_ = double(ssthresh_); // retract window if inflated
00790     }
00791     fastrecov_ = FALSE;
00792 //printf("%f: EXITED FAST RECOVERY\n", now());
00793     dupacks_ = 0;
00794 }
00795 
00796 /*
00797  * ack_action -- same as partial ACK action for base Reno TCP
00798  */
00799 
00800 void
00801 FullTcpAgent::ack_action(Packet* p)
00802 {
00803     FullTcpAgent::pack_action(p);
00804 }
00805 
00806 
00807 /*
00808  * sendpacket: 
00809  *  allocate a packet, fill in header fields, and send
00810  *  also keeps stats on # of data pkts, acks, re-xmits, etc
00811  *
00812  * fill in packet fields.  Agent::allocpkt() fills
00813  * in most of the network layer fields for us.
00814  * So fill in tcp hdr and adjust the packet size.
00815  *
00816  * Also, set the size of the tcp header.
00817  */
00818 void
00819 FullTcpAgent::sendpacket(int seqno, int ackno, int pflags, int datalen, int reason)
00820 {
00821         Packet* p = allocpkt();
00822         hdr_tcp *tcph = hdr_tcp::access(p);
00823     hdr_flags *fh = hdr_flags::access(p);
00824 
00825     /* build basic header w/options */
00826 
00827         tcph->seqno() = seqno;
00828         tcph->ackno() = ackno;
00829         tcph->flags() = pflags;
00830         tcph->reason() |= reason; // make tcph->reason look like ns1 pkt->flags?
00831     tcph->sa_length() = 0;    // may be increased by build_options()
00832         tcph->hlen() = tcpip_base_hdr_size_;
00833     tcph->hlen() += build_options(tcph);
00834 
00835     /*
00836      * Explicit Congestion Notification (ECN) related:
00837      * Bits in header:
00838      *  ECT (EC Capable Transport),
00839      *  ECNECHO (ECHO of ECN Notification generated at router),
00840      *  CWR (Congestion Window Reduced from RFC 2481)
00841      * States in TCP:
00842      *  ecn_: I am supposed to do ECN if my peer does
00843      *  ect_: I am doing ECN (ecn_ should be T and peer does ECN)
00844      */
00845 
00846     // set ect on data packets (not syn or ack packets)
00847     if ( datalen > 0 && ecn_ ){
00848         fh->ect() = ect_;   // on after mutual agreement on ECT
00849     }
00850     else {
00851         /* Set ect() to 0.  -M. Weigle 1/19/05 */
00852         fh->ect() = 0;
00853     }
00854 
00855         // fill in CWR and ECE bits which don't actually sit in
00856         // the tcp_flags but in hdr_flags
00857         if ( pflags & TH_ECE) {
00858                 fh->ecnecho() = 1;
00859         } else {
00860                 fh->ecnecho() = 0;
00861         }
00862         if ( pflags & TH_CWR ) {
00863                 fh->cong_action() = 1;
00864         }
00865     else {
00866         /* Set cong_action() to 0  -M. Weigle 1/19/05 */
00867         fh->cong_action() = 0;
00868     }
00869 
00870     /* actual size is data length plus header length */
00871 
00872         hdr_cmn *ch = hdr_cmn::access(p);
00873         ch->size() = datalen + tcph->hlen();
00874 
00875         if (datalen <= 0)
00876                 ++nackpack_;
00877         else {
00878                 ++ndatapack_;
00879                 ndatabytes_ += datalen;
00880         last_send_time_ = now();    // time of last data
00881         }
00882         if (reason == REASON_TIMEOUT || reason == REASON_DUPACK || reason == REASON_SACK) {
00883                 ++nrexmitpack_;
00884                 nrexmitbytes_ += datalen;
00885         }
00886 
00887     last_ack_sent_ = ackno;
00888 
00889 //if (state_ != TCPS_ESTABLISHED) {
00890 //printf("%f(%s)[state:%s]: sending pkt ", now(), name(), statestr(state_));
00891 //prpkt(p);
00892 //}
00893 
00894     send(p, 0);
00895 
00896     return;
00897 }
00898 
00899 //
00900 // reset_rtx_timer: called during a retransmission timeout
00901 // to perform exponential backoff.  Also, note that because
00902 // we have performed a retransmission, our rtt timer is now
00903 // invalidated (indicate this by setting rtt_active_ false)
00904 //
00905 void
00906 FullTcpAgent::reset_rtx_timer(int /* mild */)
00907 {
00908     // cancel old timer, set a new one
00909     /* if there is no outstanding data, don't back off rtx timer *
00910      * (Fix from T. Kelly.) */
00911     if (!(highest_ack_ == maxseq_ && restart_bugfix_)) {
00912             rtt_backoff();      // double current timeout
00913     }
00914         set_rtx_timer();    // set new timer
00915         rtt_active_ = FALSE;    // no timing during this window
00916 }
00917 
00918 /*
00919  * see if we should send a segment, and if so, send it
00920  *  (may be ACK or data)
00921  * return the number of data bytes sent (count a SYN or FIN as 1 each)
00922  *
00923  * simulator var, desc (name in real TCP)
00924  * --------------------------------------
00925  * maxseq_, largest seq# we've sent plus one (snd_max)
00926  * flags_, flags regarding our internal state (t_state)
00927  * pflags, a local used to build up the tcp header flags (flags)
00928  * curseq_, is the highest sequence number given to us by "application"
00929  * highest_ack_, the highest ACK we've seen for our data (snd_una-1)
00930  * seqno, the next seq# we're going to send (snd_nxt)
00931  */
00932 int
00933 FullTcpAgent::foutput(int seqno, int reason)
00934 {
00935     // if maxseg_ not set, set it appropriately
00936     // Q: how can this happen?
00937 
00938     if (maxseg_ == 0) 
00939         maxseg_ = size_ - headersize();
00940     else
00941         size_ =  maxseg_ + headersize();
00942 
00943     int is_retransmit = (seqno < maxseq_);
00944     int quiet = (highest_ack_ == maxseq_);
00945     int pflags = outflags();
00946     int syn = (seqno == iss_);
00947     int emptying_buffer = FALSE;
00948     int buffered_bytes = (infinite_send_) ? TCP_MAXSEQ :
00949                 curseq_ - highest_ack_ + 1;
00950 
00951     int win = window() * maxseg_;   // window (in bytes)
00952     int off = seqno - highest_ack_; // offset of seg in window
00953     int datalen;
00954     //int amtsent = 0;
00955 
00956     // be careful if we have not received any ACK yet
00957     if (highest_ack_ < 0) {
00958         if (!infinite_send_)
00959             buffered_bytes = curseq_ - iss_;;
00960         off = seqno - iss_;
00961     }
00962 
00963     if (syn && !data_on_syn_)
00964         datalen = 0;
00965     else if (pipectrl_)
00966         datalen = buffered_bytes - off;
00967     else
00968         datalen = min(buffered_bytes, win) - off;
00969 
00970         if ((signal_on_empty_) && (!buffered_bytes) && (!syn))
00971                     bufferempty();
00972 
00973     //
00974     // in real TCP datalen (len) could be < 0 if there was window
00975     // shrinkage, or if a FIN has been sent and neither ACKd nor
00976     // retransmitted.  Only this 2nd case concerns us here...
00977     //
00978     if (datalen < 0) {
00979         datalen = 0;
00980     } else if (datalen > maxseg_) {
00981         datalen = maxseg_;
00982     }
00983 
00984 
00985     //
00986     // this is an option that causes us to slow-start if we've
00987     // been idle for a "long" time, where long means a rto or longer
00988     // the slow-start is a sort that does not set ssthresh
00989     //
00990 
00991     if (slow_start_restart_ && quiet && datalen > 0) {
00992         if (idle_restart()) {
00993             slowdown(CLOSE_CWND_INIT);
00994         }
00995     }
00996 
00997     //
00998     // see if sending this packet will empty the send buffer
00999     // a dataless SYN packet counts also
01000     //
01001 
01002     if (!infinite_send_ && ((seqno + datalen) > curseq_ || 
01003         (syn && datalen == 0))) {
01004         emptying_buffer = TRUE;
01005         //
01006         // if not a retransmission, notify application that 
01007         // everything has been sent out at least once.
01008         //
01009         if (!syn) {
01010             idle();
01011             if (close_on_empty_ && quiet) {
01012                 flags_ |= TF_NEEDCLOSE;
01013             }
01014         }
01015         pflags |= TH_PUSH;
01016         //
01017         // if close_on_empty set, we are finished
01018         // with this connection; close it
01019         //
01020     } else  {
01021         /* not emptying buffer, so can't be FIN */
01022         pflags &= ~TH_FIN;
01023     }
01024     if (infinite_send_ && (syn && datalen == 0))
01025         pflags |= TH_PUSH;  // set PUSH for dataless SYN
01026 
01027     /* sender SWS avoidance (Nagle) */
01028 
01029     if (datalen > 0) {
01030         // if full-sized segment, ok
01031         if (datalen == maxseg_)
01032             goto send;
01033         // if Nagle disabled and buffer clearing, ok
01034         if ((quiet || nodelay_)  && emptying_buffer)
01035             goto send;
01036         // if a retransmission
01037         if (is_retransmit)
01038             goto send;
01039         // if big "enough", ok...
01040         //  (this is not a likely case, and would
01041         //  only happen for tiny windows)
01042         if (datalen >= ((wnd_ * maxseg_) / 2.0))
01043             goto send;
01044     }
01045 
01046     if (need_send())
01047         goto send;
01048 
01049     /*
01050      * send now if a control packet or we owe peer an ACK
01051      * TF_ACKNOW can be set during connection establishment and
01052      * to generate acks for out-of-order data
01053      */
01054 
01055     if ((flags_ & (TF_ACKNOW|TF_NEEDCLOSE)) ||
01056         (pflags & (TH_SYN|TH_FIN))) {
01057         goto send;
01058     }
01059 
01060         /*      
01061          * No reason to send a segment, just return.
01062          */      
01063     return 0;
01064 
01065 send:
01066 
01067     // is a syn or fin?
01068 
01069     syn = (pflags & TH_SYN) ? 1 : 0;
01070     int fin = (pflags & TH_FIN) ? 1 : 0;
01071 
01072         /* setup ECN syn and ECN SYN+ACK packet headers */
01073         if (ecn_ && syn && !(pflags & TH_ACK)){
01074                 pflags |= TH_ECE;
01075                 pflags |= TH_CWR;
01076         }
01077         if (ecn_ && syn && (pflags & TH_ACK)){
01078                 pflags |= TH_ECE;
01079                 pflags &= ~TH_CWR;
01080         }
01081     else if (ecn_ && ect_ && cong_action_ && 
01082                  (!is_retransmit || SetCWRonRetransmit_)) 
01083         /* 
01084          * Don't set CWR for a retranmitted SYN+ACK (has ecn_ 
01085          * and cong_action_ set) or on any retransmits.
01086          * -M. Weigle 6/19/02
01087          */
01088         /* set CWR if necessary */
01089         pflags |= TH_CWR;
01090 
01091     /* moved from sendpacket()  -M. Weigle 6/19/02 */
01092     //
01093     // although CWR bit is ordinarily associated with ECN,
01094     // it has utility within the simulator for traces. Thus, set
01095     // it even if we aren't doing ECN
01096     //
01097     if (datalen > 0 && cong_action_ && !is_retransmit) {
01098         pflags |= TH_CWR;
01099     }
01100   
01101         /* set ECE if necessary */
01102         if (ecn_ && ect_ && recent_ce_ ) pflags |= TH_ECE;
01103 
01104         /* 
01105          * Tack on the FIN flag to the data segment if close_on_empty_
01106          * was previously set-- avoids sending a separate FIN
01107          */ 
01108         if (flags_ & TF_NEEDCLOSE) {
01109                 flags_ &= ~TF_NEEDCLOSE;
01110                 if (state_ <= TCPS_ESTABLISHED && state_ != TCPS_CLOSED)
01111                 {
01112                     pflags |=TH_FIN;
01113                     fin = 1;  /* FIN consumes sequence number */
01114                     newstate(TCPS_FIN_WAIT_1);
01115                 }
01116         }
01117     sendpacket(seqno, rcv_nxt_, pflags, datalen, reason);
01118 
01119         /*      
01120          * Data sent (as far as we can tell).
01121          * Any pending ACK has now been sent.
01122          */      
01123     flags_ &= ~(TF_ACKNOW|TF_DELACK);
01124 
01125     /*
01126      * if we have reacted to congestion recently, the
01127      * slowdown() procedure will have set cong_action_ and
01128      * sendpacket will have copied that to the outgoing pkt
01129      * CWR field. If that packet contains data, then
01130      * it will be reliably delivered, so we are free to turn off the
01131      * cong_action_ state now  If only a pure ACK, we keep the state
01132      * around until we actually send a segment
01133      */
01134 
01135     int reliable = datalen + syn + fin; // seq #'s reliably sent
01136     /* 
01137      * Don't reset cong_action_ until we send new data.
01138      * -M. Weigle 6/19/02
01139      */
01140     if (cong_action_ && reliable > 0 && !is_retransmit)
01141         cong_action_ = FALSE;
01142 
01143     // highest: greatest sequence number sent + 1
01144     //  and adjusted for SYNs and FINs which use up one number
01145 
01146     int highest = seqno + reliable;
01147     if (highest > maxseq_) {
01148         maxseq_ = highest;
01149         //
01150         // if we are using conventional RTT estimation,
01151         // establish timing on this segment
01152         //
01153         if (!ts_option_ && rtt_active_ == FALSE) {
01154             rtt_active_ = TRUE; // set timer
01155             rtt_seq_ = seqno;   // timed seq #
01156             rtt_ts_ = now();    // when set
01157         }
01158     }
01159 
01160     /*
01161      * Set retransmit timer if not currently set,
01162      * and not doing an ack or a keep-alive probe.
01163      * Initial value for retransmit timer is smoothed
01164      * round-trip time + 2 * round-trip time variance.
01165      * Future values are rtt + 4 * rttvar.
01166      */
01167     if (rtx_timer_.status() != TIMER_PENDING && reliable) {
01168         set_rtx_timer();  // no timer pending, schedule one
01169     }
01170 
01171     return (reliable);
01172 }
01173 
01174 /*
01175  *
01176  * send_much: send as much data as we are allowed to.  This is
01177  * controlled by the "pipectrl_" variable.  If pipectrl_ is set
01178  * to FALSE, then we are working as a normal window-based TCP and
01179  * we are allowed to send whatever the window allows.
01180  * If pipectrl_ is set to TRUE, then we are allowed to send whatever
01181  * pipe_ allows us to send.  One tricky part is to make sure we
01182  * do not overshoot the receiver's advertised window if we are
01183  * in (pipectrl_ == TRUE) mode.
01184  */
01185   
01186 void
01187 FullTcpAgent::send_much(int force, int reason, int maxburst)
01188 {
01189     int npackets = 0;   // sent so far
01190 
01191 //if ((int(t_seqno_)) > 1)
01192 //printf("%f: send_much(f:%d, win:%d, pipectrl:%d, pipe:%d, t_seqno:%d, topwin:%d, maxseq_:%d\n",
01193 //now(), force, win, pipectrl_, pipe_, int(t_seqno_), topwin, int(maxseq_));
01194 
01195     if (!force && (delsnd_timer_.status() == TIMER_PENDING))
01196         return;
01197 
01198     while (1) {
01199 
01200         /*
01201          * note that if output decides to not actually send
01202          * (e.g. because of Nagle), then if we don't break out
01203          * of this loop, we can loop forever at the same
01204          * simulated time instant
01205          */
01206         int amt;
01207         int seq = nxt_tseq();
01208         if (!force && !send_allowed(seq))
01209             break;
01210         // Q: does this need to be here too?
01211         if (!force && overhead_ != 0 &&
01212             (delsnd_timer_.status() != TIMER_PENDING)) {
01213             delsnd_timer_.resched(Random::uniform(overhead_));
01214             return;
01215         }
01216         if ((amt = foutput(seq, reason)) <= 0)
01217             break;
01218         if ((outflags() & TH_FIN))
01219             --amt;  // don't count FINs
01220         sent(seq, amt);
01221         force = 0;
01222 
01223         if ((outflags() & (TH_SYN|TH_FIN)) ||
01224             (maxburst && ++npackets >= maxburst))
01225             break;
01226     }
01227     return;
01228 }
01229 
01230 /*
01231  * base TCP: we are allowed to send a sequence number if it
01232  * is in the window
01233  */
01234 int
01235 FullTcpAgent::send_allowed(int seq)
01236 {
01237         int win = window() * maxseg_;
01238         int topwin = curseq_; // 1 seq number past the last byte we can send
01239 
01240         if ((topwin > highest_ack_ + win) || infinite_send_)
01241                 topwin = highest_ack_ + win; 
01242 
01243     return (seq < topwin);
01244 }
01245 /*
01246  * Process an ACK
01247  *  this version of the routine doesn't necessarily
01248  *  require the ack to be one which advances the ack number
01249  *
01250  * if this ACKs a rtt estimate
01251  *  indicate we are not timing
01252  *  reset the exponential timer backoff (gamma)
01253  * update rtt estimate
01254  * cancel retrans timer if everything is sent and ACK'd, else set it
01255  * advance the ack number if appropriate
01256  * update segment to send next if appropriate
01257  */
01258 void
01259 FullTcpAgent::newack(Packet* pkt)
01260 {
01261     hdr_tcp *tcph = hdr_tcp::access(pkt);
01262 
01263     register int ackno = tcph->ackno();
01264     int progress = (ackno > highest_ack_);
01265 
01266     if (ackno == maxseq_) {
01267         cancel_rtx_timer(); // all data ACKd
01268     } else if (progress) {
01269         set_rtx_timer();
01270     }
01271 
01272     // advance the ack number if this is for new data
01273     if (progress)
01274         highest_ack_ = ackno;
01275 
01276     // if we have suffered a retransmit timeout, t_seqno_
01277     // will have been reset to highest_ ack.  If the
01278     // receiver has cached some data above t_seqno_, the
01279     // new-ack value could (should) jump forward.  We must
01280     // update t_seqno_ here, otherwise we would be doing
01281     // go-back-n.
01282 
01283     if (t_seqno_ < highest_ack_)
01284         t_seqno_ = highest_ack_; // seq# to send next
01285 
01286         /*
01287          * Update RTT only if it's OK to do so from info in the flags header.
01288          * This is needed for protocols in which intermediate agents
01289          * in the network intersperse acks (e.g., ack-reconstructors) for
01290          * various reasons (without violating e2e semantics).
01291          */
01292         hdr_flags *fh = hdr_flags::access(pkt);
01293 
01294     if (!fh->no_ts_) {
01295                 if (ts_option_) {
01296             recent_age_ = now();
01297             recent_ = tcph->ts();
01298             rtt_update(now() - tcph->ts_echo());
01299             if (ts_resetRTO_ && (!ect_ || !ecn_backoff_ ||
01300                    !hdr_flags::access(pkt)->ecnecho())) { 
01301                 // From Andrei Gurtov
01302                 //
01303                             // Don't end backoff if still in ECN-Echo with
01304                             // a congestion window of 1 packet.
01305                 t_backoff_ = 1;
01306             }
01307         } else if (rtt_active_ && ackno > rtt_seq_) {
01308             // got an RTT sample, record it
01309             // "t_backoff_ = 1;" deleted by T. Kelly.
01310             rtt_active_ = FALSE;
01311             rtt_update(now() - rtt_ts_);
01312                 }
01313 
01314         if (!ect_ || !ecn_backoff_ ||
01315             !hdr_flags::access(pkt)->ecnecho()) {
01316             /*
01317              * Don't end backoff if still in ECN-Echo with
01318              * a congestion window of 1 packet.
01319              * Fix from T. Kelly.
01320              */
01321             t_backoff_ = 1;
01322             ecn_backoff_ = 0;
01323         }
01324         }
01325     return;
01326 }
01327 
01328 /*
01329  * this is the simulated form of the header prediction
01330  * predicate.  While not really necessary for a simulation, it
01331  * follows the code base more closely and can sometimes help to reveal
01332  * odd behavior caused by the implementation structure..
01333  *
01334  * Here's the comment from the real TCP:
01335  *
01336  * Header prediction: check for the two common cases
01337  * of a uni-directional data xfer.  If the packet has
01338  * no control flags, is in-sequence, the window didn't
01339  * change and we're not retransmitting, it's a
01340  * candidate.  If the length is zero and the ack moved
01341  * forward, we're the sender side of the xfer.  Just
01342  * free the data acked & wake any higher level process
01343  * that was blocked waiting for space.  If the length
01344  * is non-zero and the ack didn't move, we're the
01345  * receiver side.  If we're getting packets in-order
01346  * (the reassembly queue is empty), add the data to
01347  * the socket buffer and note that we need a delayed ack.
01348  * Make sure that the hidden state-flags are also off.
01349  * Since we check for TCPS_ESTABLISHED above, it can only
01350  * be TF_NEEDSYN.
01351  */
01352 
01353 int
01354 FullTcpAgent::predict_ok(Packet* pkt)
01355 {
01356     hdr_tcp *tcph = hdr_tcp::access(pkt);
01357         hdr_flags *fh = hdr_flags::access(pkt);
01358 
01359     /* not the fastest way to do this, but perhaps clearest */
01360 
01361     int p1 = (state_ == TCPS_ESTABLISHED);      // ready
01362     int p2 = ((tcph->flags() & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK); // ACK
01363     int p3 = ((flags_ & TF_NEEDFIN) == 0);      // don't need fin
01364     int p4 = (!ts_option_ || fh->no_ts_ || (tcph->ts() >= recent_)); // tsok
01365     int p5 = (tcph->seqno() == rcv_nxt_);       // in-order data
01366     int p6 = (t_seqno_ == maxseq_);         // not re-xmit
01367     int p7 = (!ecn_ || fh->ecnecho() == 0);     // no ECN
01368     int p8 = (tcph->sa_length() == 0);      // no SACK info
01369 
01370     return (p1 && p2 && p3 && p4 && p5 && p6 && p7 && p8);
01371 }
01372 
01373 /*
01374  * fast_retransmit using the given seqno
01375  *  perform fast RTX, set recover_, set last_cwnd_action
01376  */
01377 
01378 int
01379 FullTcpAgent::fast_retransmit(int seq)
01380 {
01381     // we are now going to fast-retransmit and willtrace that event
01382     trace_event("FAST_RETX");
01383     
01384     recover_ = maxseq_; // recovery target
01385     last_cwnd_action_ = CWND_ACTION_DUPACK;
01386     return(foutput(seq, REASON_DUPACK));    // send one pkt
01387 }
01388 
01389 /*
01390  * real tcp determines if the remote
01391  * side should receive a window update/ACK from us, and often
01392  * results in sending an update every 2 segments, thereby
01393  * giving the familiar 2-packets-per-ack behavior of TCP.
01394  * Here, we don't advertise any windows, so we just see if
01395  * there's at least 'segs_per_ack_' pkts not yet acked
01396  *
01397  * also, provide for a segs-per-ack "threshold" where
01398  * we generate 1-ack-per-seg until enough stuff
01399  * (spa_thresh_ bytes) has been received from the other side
01400  * This idea came from vj/kmn in BayTcp.  Added 8/21/01.
01401  */
01402 
01403 int
01404 FullTcpAgent::need_send()
01405 {
01406     if (flags_ & TF_ACKNOW)
01407         return TRUE;
01408 
01409     int spa = (spa_thresh_ > 0 && ((rcv_nxt_ - irs_)  < spa_thresh_)) ?
01410         1 : segs_per_ack_;
01411         
01412     return ((rcv_nxt_ - last_ack_sent_) >= (spa * maxseg_));
01413 }
01414 
01415 /*
01416  * determine whether enough time has elapsed in order to
01417  * conclude a "restart" is necessary (e.g. a slow-start)
01418  *
01419  * for now, keep track of this similarly to how rtt_update() does
01420  */
01421 
01422 int
01423 FullTcpAgent::idle_restart()
01424 {
01425     if (last_send_time_ < 0.0) {
01426         // last_send_time_ isn't set up yet, we shouldn't
01427         // do the idle_restart
01428         return (0);
01429     }
01430 
01431     double tao = now() - last_send_time_;
01432     if (!ts_option_) {
01433                 double tickoff = fmod(last_send_time_ + boot_time_,
01434             tcp_tick_);
01435                 tao = int((tao + tickoff) / tcp_tick_) * tcp_tick_;
01436     }
01437 
01438     return (tao > t_rtxcur_);  // verify this CHECKME
01439 }
01440 
01441 /*
01442  * tcp-full's version of set_initial_window()... over-rides
01443  * the one in tcp.cc
01444  */
01445 void
01446 FullTcpAgent::set_initial_window()
01447 {
01448     syn_ = TRUE;    // full-tcp always models SYN exchange
01449     TcpAgent::set_initial_window();
01450 }       
01451 
01452 /*
01453  * main reception path - 
01454  * called from the agent that handles the data path below in its muxing mode
01455  * advance() is called when connection is established with size sent from
01456  * user/application agent
01457  *
01458  * This is a fairly complex function.  It operates generally as follows:
01459  *  do header prediction for simple cases (pure ACKS or data)
01460  *  if in LISTEN and we get a SYN, begin initializing connection
01461  *  if in SYN_SENT and we get an ACK, complete connection init
01462  *  trim any redundant data from received dataful segment
01463  *  deal with ACKS:
01464  *      if in SYN_RCVD, complete connection init then go on
01465  *      see if ACK is old or at the current highest_ack
01466  *      if at current high, is the threshold reached or not
01467  *      if so, maybe do fast rtx... otherwise drop or inflate win
01468  *  deal with incoming data
01469  *  deal with FIN bit on in arriving packet
01470  */
01471 void
01472 FullTcpAgent::recv(Packet *pkt, Handler*)
01473 {
01474     hdr_tcp *tcph = hdr_tcp::access(pkt);   // TCP header
01475     hdr_cmn *th = hdr_cmn::access(pkt); // common header (size, etc)
01476     hdr_flags *fh = hdr_flags::access(pkt); // flags (CWR, CE, bits)
01477 
01478     int needoutput = FALSE;
01479     int ourfinisacked = FALSE;
01480     int dupseg = FALSE;         // recv'd dup data segment
01481     int todrop = 0;             // duplicate DATA cnt in seg
01482 
01483     last_state_ = state_;
01484 
01485     int datalen = th->size() - tcph->hlen(); // # payload bytes
01486     int ackno = tcph->ackno();       // ack # from packet
01487     int tiflags = tcph->flags() ;        // tcp flags from packet
01488 
01489 //if (state_ != TCPS_ESTABLISHED || (tiflags&(TH_SYN|TH_FIN))) {
01490 //fprintf(stdout, "%f(%s)in state %s recv'd this packet: ", now(), name(), statestr(state_));
01491 //prpkt(pkt);
01492 //}
01493 
01494     /* 
01495      * Acknowledge FIN from passive closer even in TCPS_CLOSED state
01496      * (since we lack TIME_WAIT state and RST packets,
01497      * the loss of the FIN packet from the passive closer will make that
01498      * endpoint retransmit the FIN forever)
01499      * -F. Hernandez-Campos 8/6/00
01500      */
01501     if ( (state_ == TCPS_CLOSED) && (tiflags & TH_FIN) ) {
01502         goto dropafterack;
01503     }
01504 
01505     /*
01506      * Don't expect to see anything while closed
01507      */
01508 
01509     if (state_ == TCPS_CLOSED) {
01510         fprintf(stderr, "%f: FullTcp(%s): recv'd pkt in CLOSED state: ",
01511             now(), name());
01512         prpkt(pkt);
01513         goto drop;
01514     }
01515 
01516         /*
01517          * Process options if not in LISTEN state,
01518          * else do it below
01519          */
01520 
01521     if (state_ != TCPS_LISTEN)
01522         dooptions(pkt);
01523 
01524     /*
01525      * if we are using delayed-ACK timers and
01526      * no delayed-ACK timer is set, set one.
01527      * They are set to fire every 'interval_' secs, starting
01528      * at time t0 = (0.0 + k * interval_) for some k such
01529      * that t0 > now
01530      */
01531 
01532     if (delack_interval_ > 0.0 &&
01533         (delack_timer_.status() != TIMER_PENDING)) {
01534         int last = int(now() / delack_interval_);
01535         delack_timer_.resched(delack_interval_ * (last + 1.0) - now());
01536     }
01537 
01538     /*
01539      * sanity check for ECN: shouldn't be seeing a CE bit if
01540      * ECT wasn't set on the packet first.  If we see this, we
01541      * probably have a misbehaving router...
01542      */
01543 
01544     if (fh->ce() && !fh->ect()) {
01545         fprintf(stderr,
01546         "%f: FullTcpAgent::recv(%s): warning: CE bit on, but ECT false!\n",
01547         now(), name());
01548     }
01549 
01550     /*
01551      * Try header prediction: in seq data or in seq pure ACK
01552      *  with no funny business
01553      */
01554 
01555     if (!nopredict_ && predict_ok(pkt)) {
01556                 /*
01557                  * If last ACK falls within this segment's sequence numbers,
01558                  * record the timestamp.
01559          * See RFC1323 (now RFC1323 bis)
01560                  */
01561                 if (ts_option_ && !fh->no_ts_ &&
01562             tcph->seqno() <= last_ack_sent_) {
01563             /*
01564              * this is the case where the ts value is newer than
01565              * the last one we've seen, and the seq # is the one
01566              * we expect [seqno == last_ack_sent_] or older
01567              */
01568             recent_age_ = now();
01569             recent_ = tcph->ts();
01570                 }
01571 
01572         //
01573         // generate a stream of ecnecho bits until we see a true
01574         // cong_action bit
01575         //
01576         if (ecn_) {
01577             if (fh->ce() && fh->ect()) {
01578                 // no CWR from peer yet... arrange to
01579                 // keep sending ECNECHO
01580                 recent_ce_ = TRUE;
01581             } else if (fh->cwr()) {
01582                 // got CWR response from peer.. stop
01583                 // sending ECNECHO bits
01584                 recent_ce_ = FALSE;
01585             }
01586         }
01587 
01588         // Header predication basically looks to see
01589         // if the incoming packet is an expected pure ACK
01590         // or an expected data segment
01591 
01592         if (datalen == 0) {
01593             // check for a received pure ACK in the correct range..
01594             // also checks to see if we are wnd_ limited
01595             // (we don't change cwnd at all below), plus
01596             // not being in fast recovery and not a partial ack.
01597             // If we are in fast
01598             // recovery, go below so we can remember to deflate
01599             // the window if we need to
01600             if (ackno > highest_ack_ && ackno < maxseq_ &&
01601                 cwnd_ >= wnd_ && !fastrecov_) {
01602                 newack(pkt);    // update timers,  highest_ack_
01603                 send_much(0, REASON_NORMAL, maxburst_);
01604                 Packet::free(pkt);
01605                 return;
01606             }
01607         } else if (ackno == highest_ack_ && rq_.empty()) {
01608             // check for pure incoming segment
01609             // the next data segment we're awaiting, and
01610             // that there's nothing sitting in the reassem-
01611             // bly queue
01612             //  give to "application" here
01613             //  note: DELACK is inspected only by
01614             //  tcp_fasttimo() in real tcp.  Every 200 ms
01615             //  this routine scans all tcpcb's looking for
01616             //  DELACK segments and when it finds them
01617             //  changes DELACK to ACKNOW and calls tcp_output()
01618             rcv_nxt_ += datalen;
01619             flags_ |= TF_DELACK;
01620             recvBytes(datalen); // notify application of "delivery"
01621             //
01622             // special code here to simulate the operation
01623             // of a receiver who always consumes data,
01624             // resulting in a call to tcp_output
01625             Packet::free(pkt);
01626             if (need_send())
01627                 send_much(1, REASON_NORMAL, maxburst_);
01628             return;
01629         }
01630     } /* header prediction */
01631 
01632 
01633     //
01634     // header prediction failed
01635     // (e.g. pure ACK out of valid range, SACK present, etc)...
01636     // do slow path processing
01637 
01638     //
01639     // the following switch does special things for these states:
01640     //  TCPS_LISTEN, TCPS_SYN_SENT
01641     //
01642 
01643     switch (state_) {
01644 
01645         /*
01646          * If the segment contains an ACK then it is bad and do reset.
01647          * If it does not contain a SYN then it is not interesting; drop it.
01648          * Otherwise initialize tp->rcv_nxt, and tp->irs, iss is already
01649      * selected, and send a segment:
01650          *     <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
01651          * Initialize tp->snd_nxt to tp->iss.
01652          * Enter SYN_RECEIVED state, and process any other fields of this
01653          * segment in this state.
01654          */
01655 
01656     case TCPS_LISTEN:   /* awaiting peer's SYN */
01657 
01658         if (tiflags & TH_ACK) {
01659                 fprintf(stderr,
01660                     "%f: FullTcpAgent(%s): warning: recv'd ACK while in LISTEN: ",
01661                 now(), name());
01662             prpkt(pkt);
01663             // don't want ACKs in LISTEN
01664             goto dropwithreset;
01665         }
01666         if ((tiflags & TH_SYN) == 0) {
01667                 fprintf(stderr,
01668                     "%f: FullTcpAgent(%s): warning: recv'd NON-SYN while in LISTEN\n",
01669                 now(), name());
01670             prpkt(pkt);
01671             // any non-SYN is discarded
01672             goto drop;
01673         }
01674 
01675         /*
01676          * must by a SYN (no ACK) at this point...
01677          * in real tcp we would bump the iss counter here also
01678          */
01679         dooptions(pkt);
01680         irs_ = tcph->seqno();
01681         t_seqno_ = iss_; /* tcp_sendseqinit() macro in real tcp */
01682         rcv_nxt_ = rcvseqinit(irs_, datalen);
01683         flags_ |= TF_ACKNOW;
01684 
01685         // check for a ECN-SYN with ECE|CWR
01686         if (ecn_ && fh->ecnecho() && fh->cong_action()) {
01687 
01688             ect_ = TRUE;
01689         }
01690 
01691 
01692         if (fid_ == 0) {
01693             // XXX: sort of hack... If we do not
01694             // have a special flow ID, pick up that
01695             // of the sender (active opener)
01696             hdr_ip* iph = hdr_ip::access(pkt);
01697             fid_ = iph->flowid();
01698         }
01699 
01700         newstate(TCPS_SYN_RECEIVED);
01701         goto trimthenstep6;
01702 
01703         /*
01704          * If the state is SYN_SENT:
01705          *      if seg contains an ACK, but not for our SYN, drop the input.
01706          *      if seg does not contain SYN, then drop it.
01707          * Otherwise this is an acceptable SYN segment
01708          *      initialize tp->rcv_nxt and tp->irs
01709          *      if seg contains ack then advance tp->snd_una
01710          *      if SYN has been acked change to ESTABLISHED else SYN_RCVD state
01711          *      arrange for segment to be acked (eventually)
01712          *      continue processing rest of data/controls, beginning with URG
01713          */
01714 
01715     case TCPS_SYN_SENT: /* we sent SYN, expecting SYN+ACK (or SYN) */
01716 
01717         /* drop if it's a SYN+ACK and the ack field is bad */
01718         if ((tiflags & TH_ACK) &&
01719             ((ackno <= iss_) || (ackno > maxseq_))) {
01720             // not an ACK for our SYN, discard
01721             fprintf(stderr,
01722                 "%f: FullTcpAgent::recv(%s): bad ACK for our SYN: ",
01723                     now(), name());
01724             prpkt(pkt);
01725             goto dropwithreset;
01726         }
01727 
01728         if ((tiflags & TH_SYN) == 0) {
01729             fprintf(stderr,
01730                 "%f: FullTcpAgent::recv(%s): no SYN for our SYN: ",
01731                     now(), name());
01732             prpkt(pkt);
01733             goto drop;
01734         }
01735 
01736         /* looks like an ok SYN or SYN+ACK */
01737 #ifdef notdef
01738 cancel_rtx_timer(); // cancel timer on our 1st SYN [does this belong!?]
01739 #endif
01740         irs_ = tcph->seqno();   // get initial recv'd seq #
01741         rcv_nxt_ = rcvseqinit(irs_, datalen);
01742 
01743         if (tiflags & TH_ACK) {
01744             // SYN+ACK (our SYN was acked)
01745             // CHECKME
01746                         // Check ECN-SYN+ACK packet
01747                         if (ecn_ && fh->ecnecho() && !fh->cong_action())
01748                                 ect_ = TRUE;
01749             highest_ack_ = ackno;
01750             cwnd_ = initial_window();
01751 
01752 #ifdef notdef
01753 /*
01754  * if we didn't have to retransmit the SYN,
01755  * use its rtt as our initial srtt & rtt var.
01756  */
01757 if (t_rtt_) {
01758     double tao = now() - tcph->ts();
01759     rtt_update(tao);
01760 }
01761 #endif
01762 
01763             /*
01764              * if there's data, delay ACK; if there's also a FIN
01765              * ACKNOW will be turned on later.
01766              */
01767             if (datalen > 0) {
01768                 flags_ |= TF_DELACK;    // data there: wait
01769             } else {
01770                 flags_ |= TF_ACKNOW;    // ACK peer's SYN
01771             }
01772 
01773                         /*
01774                          * Received <SYN,ACK> in SYN_SENT[*] state.
01775                          * Transitions:
01776                          *      SYN_SENT  --> ESTABLISHED
01777                          *      SYN_SENT* --> FIN_WAIT_1
01778                          */
01779 
01780             if (flags_ & TF_NEEDFIN) {
01781                 newstate(TCPS_FIN_WAIT_1);
01782                 flags_ &= ~TF_NEEDFIN;
01783                 tiflags &= ~TH_SYN;
01784             } else {
01785                 newstate(TCPS_ESTABLISHED);
01786             }
01787 
01788             // special to ns:
01789             //  generate pure ACK here.
01790             //  this simulates the ordinary connection establishment
01791             //  where the ACK of the peer's SYN+ACK contains
01792             //  no data.  This is typically caused by the way
01793             //  the connect() socket call works in which the
01794             //  entire 3-way handshake occurs prior to the app
01795             //  being able to issue a write() [which actually
01796             //  causes the segment to be sent].
01797             sendpacket(t_seqno_, rcv_nxt_, TH_ACK, 0, 0);
01798         } else {
01799             // Check ECN-SYN packet
01800                         if (ecn_ && fh->ecnecho() && fh->cong_action())
01801                                 ect_ = TRUE;
01802 
01803             // SYN (no ACK) (simultaneous active opens)
01804             flags_ |= TF_ACKNOW;
01805             cancel_rtx_timer();
01806             newstate(TCPS_SYN_RECEIVED);
01807             /*
01808              * decrement t_seqno_: we are sending a
01809              * 2nd SYN (this time in the form of a
01810              * SYN+ACK, so t_seqno_ will have been
01811              * advanced to 2... reduce this
01812              */
01813             t_seqno_--; // CHECKME
01814         }
01815 
01816 trimthenstep6:
01817         /*
01818          * advance the seq# to correspond to first data byte
01819          */
01820         tcph->seqno()++;
01821 
01822         if (tiflags & TH_ACK)
01823             goto process_ACK;
01824 
01825         goto step6;
01826 
01827     case TCPS_LAST_ACK:
01828         /* 
01829          * The only way we're in LAST_ACK is if we've already
01830          * received a FIN, so ignore all retranmitted FINS.
01831          * -M. Weigle 7/23/02
01832          */
01833         if (tiflags & TH_FIN) {
01834             goto drop;
01835         }
01836         break;
01837     case TCPS_CLOSING:
01838         break;
01839     } /* end switch(state_) */
01840 
01841         /*
01842          * States other than LISTEN or SYN_SENT.
01843          * First check timestamp, if present.
01844          * Then check that at least some bytes of segment are within
01845          * receive window.  If segment begins before rcv_nxt,
01846          * drop leading data (and SYN); if nothing left, just ack.
01847          *
01848          * RFC 1323 PAWS: If we have a timestamp reply on this segment
01849          * and it's less than ts_recent, drop it.
01850          */
01851 
01852     if (ts_option_ && !fh->no_ts_ && recent_ && tcph->ts() < recent_) {
01853         if ((now() - recent_age_) > TCP_PAWS_IDLE) {
01854             /*
01855              * this is basically impossible in the simulator,
01856              * but here it is...
01857              */
01858                         /*
01859                          * Invalidate ts_recent.  If this segment updates
01860                          * ts_recent, the age will be reset later and ts_recent
01861                          * will get a valid value.  If it does not, setting
01862                          * ts_recent to zero will at least satisfy the
01863                          * requirement that zero be placed in the timestamp
01864                          * echo reply when ts_recent isn't valid.  The
01865                          * age isn't reset until we get a valid ts_recent
01866                          * because we don't want out-of-order segments to be
01867                          * dropped when ts_recent is old.
01868                          */
01869             recent_ = 0.0;
01870         } else {
01871             fprintf(stderr, "%f: FullTcpAgent(%s): dropped pkt due to bad ts\n",
01872                 now(), name());
01873             goto dropafterack;
01874         }
01875     }
01876 
01877     // check for redundant data at head/tail of segment
01878     //  note that the 4.4bsd [Net/3] code has
01879     //  a bug here which can cause us to ignore the
01880     //  perfectly good ACKs on duplicate segments.  The
01881     //  fix is described in (Stevens, Vol2, p. 959-960).
01882     //  This code is based on that correction.
01883     //
01884     // In addition, it has a modification so that duplicate segments
01885     // with dup acks don't trigger a fast retransmit when dupseg_fix_
01886     // is enabled.
01887     //
01888     // Yet one more modification: make sure that if the received
01889     //  segment had datalen=0 and wasn't a SYN or FIN that
01890     //  we don't turn on the ACKNOW status bit.  If we were to
01891     //  allow ACKNOW to be turned on, normal pure ACKs that happen
01892     //  to have seq #s below rcv_nxt can trigger an ACK war by
01893     //  forcing us to ACK the pure ACKs
01894     //
01895     // Update: if we have a dataless FIN, don't really want to
01896     // do anything with it.  In particular, would like to
01897     // avoid ACKing an incoming FIN+ACK while in CLOSING
01898     //
01899     todrop = rcv_nxt_ - tcph->seqno();  // how much overlap?
01900 
01901     if (todrop > 0 && ((tiflags & (TH_SYN)) || datalen > 0)) {
01902 //printf("%f(%s): trim 1..todrop:%d, dlen:%d\n",now(), name(), todrop, datalen);
01903         if (tiflags & TH_SYN) {
01904             tiflags &= ~TH_SYN;
01905             tcph->seqno()++;
01906             th->size()--;   // XXX Must decrease packet size too!!
01907                     // Q: Why?.. this is only a SYN
01908             todrop--;
01909         }
01910         //
01911         // see Stevens, vol 2, p. 960 for this check;
01912         // this check is to see if we are dropping
01913         // more than this segment (i.e. the whole pkt + a FIN),
01914         // or just the whole packet (no FIN)
01915         //
01916         if ((todrop > datalen) ||
01917             (todrop == datalen && ((tiflags & TH_FIN) == 0))) {
01918 //printf("%f(%s): trim 2..todrop:%d, dlen:%d\n",now(), name(), todrop, datalen);
01919                         /*
01920                          * Any valid FIN must be to the left of the window.
01921                          * At this point the FIN must be a duplicate or out
01922                          * of sequence; drop it.
01923                          */
01924 
01925             tiflags &= ~TH_FIN;
01926 
01927             /*
01928              * Send an ACK to resynchronize and drop any data.
01929              * But keep on processing for RST or ACK.
01930              */
01931 
01932             flags_ |= TF_ACKNOW;
01933             todrop = datalen;
01934             dupseg = TRUE;  // *completely* duplicate
01935 
01936         }
01937 
01938         /*
01939          * Trim duplicate data from the front of the packet
01940          */
01941 
01942         tcph->seqno() += todrop;
01943         th->size() -= todrop;   // XXX Must decrease size too!!
01944                     // why? [kf]..prob when put in RQ
01945         datalen -= todrop;
01946 
01947     } /* data trim */
01948 
01949     /*
01950      * If we are doing timstamps and this packet has one, and
01951      * If last ACK falls within this segment's sequence numbers,
01952      * record the timestamp.
01953      * See RFC1323 (now RFC1323 bis)
01954      */
01955     if (ts_option_ && !fh->no_ts_ && tcph->seqno() <= last_ack_sent_) {
01956         /*
01957          * this is the case where the ts value is newer than
01958          * the last one we've seen, and the seq # is the one we expect
01959          * [seqno == last_ack_sent_] or older
01960          */
01961         recent_age_ = now();
01962         recent_ = tcph->ts();
01963     }
01964 
01965     if (tiflags & TH_SYN) {
01966         fprintf(stderr,
01967             "%f: FullTcpAgent::recv(%s) received unexpected SYN (state:%d): ",
01968                 now(), name(), state_);
01969         prpkt(pkt);
01970         goto dropwithreset;
01971     }
01972 
01973     if ((tiflags & TH_ACK) == 0) {
01974         /*
01975          * Added check for state != SYN_RECEIVED.  We will receive a 
01976          * duplicate SYN in SYN_RECEIVED when our SYN/ACK was dropped.
01977          * We should just ignore the duplicate SYN (our timeout for 
01978          * resending the SYN/ACK is about the same as the client's 
01979          * timeout for resending the SYN), but give no error message. 
01980          * -M. Weigle 07/24/01
01981          */
01982         if (state_ != TCPS_SYN_RECEIVED) {
01983             fprintf(stderr, "%f: FullTcpAgent::recv(%s) got packet lacking ACK (state:%d): ",
01984                 now(), name(), state_);
01985             prpkt(pkt);
01986             goto drop;
01987         }
01988     }
01989 
01990     /*
01991      * Ack processing.
01992      */
01993 
01994     switch (state_) {
01995     case TCPS_SYN_RECEIVED: /* want ACK for our SYN+ACK */
01996         if (ackno < highest_ack_ || ackno > maxseq_) {
01997             // not in useful range
01998                 fprintf(stderr,
01999                     "%f: FullTcpAgent(%s): ack(%d) not in range while in SYN_RECEIVED: ",
02000                 now(), name(), ackno);
02001             prpkt(pkt);
02002             goto dropwithreset;
02003         }
02004                 /*
02005                  * Make transitions:
02006                  *      SYN-RECEIVED  -> ESTABLISHED
02007                  *      SYN-RECEIVED* -> FIN-WAIT-1
02008                  */
02009                 if (flags_ & TF_NEEDFIN) {
02010             newstate(TCPS_FIN_WAIT_1);
02011                         flags_ &= ~TF_NEEDFIN;
02012                 } else {
02013                         newstate(TCPS_ESTABLISHED);
02014                 }
02015         cwnd_ = initial_window();
02016         /* fall into ... */
02017 
02018         /*
02019          * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
02020          * ACKs.  If the ack is in the range
02021          *      tp->snd_una < ti->ti_ack <= tp->snd_max
02022          * then advance tp->snd_una to ti->ti_ack and drop
02023          * data from the retransmission queue.
02024      *
02025      * note that state TIME_WAIT isn't used
02026      * in the simulator
02027          */
02028 
02029         case TCPS_ESTABLISHED:
02030         case TCPS_FIN_WAIT_1:
02031         case TCPS_FIN_WAIT_2:
02032     case TCPS_CLOSE_WAIT:
02033         case TCPS_CLOSING:
02034         case TCPS_LAST_ACK:
02035 
02036         //
02037         // look for ECNs in ACKs, react as necessary
02038         //
02039 
02040         if (fh->ecnecho() && (!ecn_ || !ect_)) {
02041             fprintf(stderr,
02042                 "%f: FullTcp(%s): warning, recvd ecnecho but I am not ECN capable!\n",
02043                 now(), name());
02044         }
02045 
02046                 //
02047                 // generate a stream of ecnecho bits until we see a true
02048                 // cong_action bit
02049                 // 
02050                 if (ecn_) {
02051                         if (fh->ce() && fh->ect())
02052                                 recent_ce_ = TRUE;
02053                         else if (fh->cwr())
02054                                 recent_ce_ = FALSE;
02055                 }
02056 
02057         //
02058         // If ESTABLISHED or starting to close, process SACKS
02059         //
02060 
02061         if (state_ >= TCPS_ESTABLISHED && tcph->sa_length() > 0) {
02062             process_sack(tcph);
02063         }
02064 
02065         //
02066         // ACK indicates packet left the network
02067         //  try not to be fooled by data
02068         //
02069 
02070         if (fastrecov_ && (datalen == 0 || ackno > highest_ack_))
02071             pipe_ -= maxseg_;
02072 
02073         // look for dup ACKs (dup ack numbers, no data)
02074         //
02075         // do fast retransmit/recovery if at/past thresh
02076         if (ackno <= highest_ack_) {
02077             // a pure ACK which doesn't advance highest_ack_
02078             if (datalen == 0 && (!dupseg_fix_ || !dupseg)) {
02079 
02080                                 /*
02081                                  * If we have outstanding data
02082                                  * this is a completely
02083                                  * duplicate ack,
02084                                  * the ack is the biggest we've
02085                                  * seen and we've seen exactly our rexmt
02086                                  * threshhold of them, assume a packet
02087                                  * has been dropped and retransmit it.
02088                                  *
02089                                  * We know we're losing at the current
02090                                  * window size so do congestion avoidance.
02091                                  *
02092                                  * Dup acks mean that packets have left the
02093                                  * network (they're now cached at the receiver)
02094                                  * so bump cwnd by the amount in the receiver
02095                                  * to keep a constant cwnd packets in the
02096                                  * network.
02097                                  */
02098 
02099                 if ((rtx_timer_.status() != TIMER_PENDING) ||
02100                     ackno < highest_ack_) {
02101                     // Q: significance of timer not pending?
02102                     // ACK below highest_ack_
02103                     oldack();
02104                 } else if (++dupacks_ == tcprexmtthresh_) {
02105                     // ACK at highest_ack_ AND meets threshold
02106                     //trace_event("FAST_RECOVERY");
02107 
02108                     dupack_action(); // maybe fast rexmt
02109                     goto drop;
02110 
02111                 } else if (dupacks_ > tcprexmtthresh_) {
02112                     // ACK at highest_ack_ AND above threshole
02113                     //trace_event("FAST_RECOVERY");
02114                     extra_ack();
02115 
02116                     // send whatever window allows
02117                     send_much(0, REASON_DUPACK, maxburst_);
02118                     goto drop;
02119                 }
02120             } else {
02121                 // non zero-length [dataful] segment
02122                 // with a dup ack (normal for dataful segs)
02123                 // (or window changed in real TCP).
02124                 if (dupack_reset_) {
02125                     dupacks_ = 0;
02126                     fastrecov_ = FALSE;
02127                 }
02128             }
02129             break;  /* take us to "step6" */
02130         } /* end of dup/old acks */
02131 
02132         /*
02133          * we've finished the fast retransmit/recovery period
02134          * (i.e. received an ACK which advances highest_ack_)
02135          * The ACK may be "good" or "partial"
02136          */
02137 
02138 process_ACK:
02139 
02140         if (ackno > maxseq_) {
02141             // ack more than we sent(!?)
02142             fprintf(stderr,
02143                 "%f: FullTcpAgent::recv(%s) too-big ACK (maxseq:%d): ",
02144                 now(), name(), int(maxseq_));
02145             prpkt(pkt);
02146             goto dropafterack;
02147         }
02148 
02149                 /*
02150                  * If we have a timestamp reply, update smoothed
02151                  * round trip time.  If no timestamp is present but
02152                  * transmit timer is running and timed sequence
02153                  * number was acked, update smoothed round trip time.
02154                  * Since we now have an rtt measurement, cancel the
02155                  * timer backoff (cf., Phil Karn's retransmit alg.).
02156                  * Recompute the initial retransmit timer.
02157          *
02158                  * If all outstanding data is acked, stop retransmit
02159                  * If there is more data to be acked, restart retransmit
02160                  * timer, using current (possibly backed-off) value.
02161                  */
02162         newack(pkt);    // handle timers, update highest_ack_
02163 
02164         /*
02165          * if this is a partial ACK, invoke whatever we should
02166          * note that newack() must be called before the action
02167          * functions, as some of them depend on side-effects
02168          * of newack()
02169          */
02170 
02171         int partial = pack(pkt);
02172 
02173         if (partial)
02174             pack_action(pkt);
02175         else
02176             ack_action(pkt);
02177 
02178         /*
02179          * if this is an ACK with an ECN indication, handle this
02180          * but not if it is a syn packet
02181          */
02182 
02183         if (fh->ecnecho() && !(tiflags&TH_SYN) )
02184         if (fh->ecnecho()) {
02185             // Note from Sally: In one-way TCP,
02186             // ecn() is called before newack()...
02187             ecn(highest_ack_);  // updated by newack(), above
02188             // "set_rtx_timer();" from T. Kelly.
02189             if (cwnd_ < 1)
02190                 set_rtx_timer();
02191         }
02192         // CHECKME: handling of rtx timer
02193         if (ackno == maxseq_) {
02194             needoutput = TRUE;
02195         }
02196 
02197         /*
02198          * If no data (only SYN) was ACK'd,
02199          *    skip rest of ACK processing.
02200          */
02201         if (ackno == (highest_ack_ + 1))
02202             goto step6;
02203 
02204         // if we are delaying initial cwnd growth (probably due to
02205         // large initial windows), then only open cwnd if data has
02206         // been received
02207         // Q: check when this happens
02208                 /*
02209                  * When new data is acked, open the congestion window.
02210                  * If the window gives us less than ssthresh packets
02211                  * in flight, open exponentially (maxseg per packet).
02212                  * Otherwise open about linearly: maxseg per window
02213                  * (maxseg^2 / cwnd per packet).
02214                  */
02215         if ((!delay_growth_ || (rcv_nxt_ > 0)) &&
02216             last_state_ == TCPS_ESTABLISHED) {
02217             if (!partial || open_cwnd_on_pack_)
02218               if (!ect_ || !hdr_flags::access(pkt)->ecnecho())
02219                 opencwnd();
02220         }
02221 
02222         if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {
02223             ourfinisacked = TRUE;
02224         }
02225 
02226         //
02227         // special additional processing when our state
02228         // is one of the closing states:
02229         //  FIN_WAIT_1, CLOSING, LAST_ACK
02230 
02231         switch (state_) {
02232                 /*
02233                  * In FIN_WAIT_1 STATE in addition to the processing
02234                  * for the ESTABLISHED state if our FIN is now acknowledged
02235                  * then enter FIN_WAIT_2.
02236                  */
02237         case TCPS_FIN_WAIT_1:   /* doing active close */
02238             if (ourfinisacked) {
02239                 // got the ACK, now await incoming FIN
02240                 newstate(TCPS_FIN_WAIT_2);
02241                 cancel_timers();
02242                 needoutput = FALSE;
02243             }
02244             break;
02245 
02246                 /*
02247                  * In CLOSING STATE in addition to the processing for
02248                  * the ESTABLISHED state if the ACK acknowledges our FIN
02249                  * then enter the TIME-WAIT state, otherwise ignore
02250                  * the segment.
02251                  */
02252         case TCPS_CLOSING:  /* simultaneous active close */;
02253             if (ourfinisacked) {
02254                 newstate(TCPS_CLOSED);
02255                 cancel_timers();
02256             }
02257             break;
02258                 /*
02259                  * In LAST_ACK, we may still be waiting for data to drain
02260                  * and/or to be acked, as well as for the ack of our FIN.
02261                  * If our FIN is now acknowledged,
02262                  * enter the closed state and return.
02263                  */
02264         case TCPS_LAST_ACK: /* passive close */
02265             // K: added state change here
02266             if (ourfinisacked) {
02267                 newstate(TCPS_CLOSED);
02268                 finish(); // cancels timers, erc
02269                 reset(); // for connection re-use (bug fix from ns-users list)
02270                 goto drop;
02271             } else {
02272                 // should be a FIN we've seen
02273                                 fprintf(stderr,
02274                                 "%f: FullTcpAgent(%s)::received non-ACK (state:%d): ",
02275                                         now(), name(), state_);
02276                 prpkt(pkt);
02277                         }
02278             break;
02279 
02280         /* no case for TIME_WAIT in simulator */
02281         }  // inner state_ switch (closing states)
02282     } // outer state_ switch (ack processing)
02283 
02284 step6:
02285 
02286     /*
02287      * Processing of incoming DATAful segments.
02288      *  Code above has already trimmed redundant data.
02289      *
02290      * real TCP handles window updates and URG data here also
02291      */
02292 
02293 /* dodata: this label is in the "real" code.. here only for reference */
02294 
02295     if ((datalen > 0 || (tiflags & TH_FIN)) &&
02296         TCPS_HAVERCVDFIN(state_) == 0) {
02297 
02298         //
02299         // the following 'if' implements the "real" TCP
02300         // TCP_REASS macro
02301         //
02302 
02303         if (tcph->seqno() == rcv_nxt_ && rq_.empty()) {
02304             // got the in-order packet we were looking
02305             // for, nobody is in the reassembly queue,
02306             // so this is the common case...
02307             // note: in "real" TCP we must also be in
02308             // ESTABLISHED state to come here, because
02309             // data arriving before ESTABLISHED is
02310             // queued in the reassembly queue.  Since we
02311             // don't really have a process anyhow, just
02312             // accept the data here as-is (i.e. don't
02313             // require being in ESTABLISHED state)
02314             flags_ |= TF_DELACK;
02315             rcv_nxt_ += datalen;
02316             tiflags = tcph->flags() & TH_FIN;
02317 
02318             // give to "application" here
02319             // in "real" TCP, this is sbappend() + sorwakeup()
02320             if (datalen)
02321                 recvBytes(datalen); // notify app. of "delivery"
02322             needoutput = need_send();
02323         } else {
02324             // see the "tcp_reass" function:
02325             // not the one we want next (or it
02326             // is but there's stuff on the reass queue);
02327             // do whatever we need to do for out-of-order
02328             // segments or hole-fills.  Also,
02329             // send an ACK (or SACK) to the other side right now.
02330             // Note that we may have just a FIN here (datalen = 0)
02331             int rcv_nxt_old_ = rcv_nxt_; // notify app. if changes
02332             tiflags = reass(pkt);
02333             if (rcv_nxt_ > rcv_nxt_old_) {
02334                 // if rcv_nxt_ has advanced, must have
02335                 // been a hole fill.  In this case, there
02336                 // is something to give to application
02337                 recvBytes(rcv_nxt_ - rcv_nxt_old_);
02338             }
02339             flags_ |= TF_ACKNOW;
02340 
02341             if (tiflags & TH_PUSH) {
02342                 //
02343                 // ???: does this belong here
02344                 // K: APPLICATION recv
02345                 needoutput = need_send();
02346             }
02347         }
02348     } else {
02349         /*
02350          * we're closing down or this is a pure ACK that
02351          * wasn't handled by the header prediction part above
02352          * (e.g. because cwnd < wnd)
02353          */
02354         // K: this is deleted
02355         tiflags &= ~TH_FIN;
02356     }
02357 
02358     /*
02359      * if FIN is received, ACK the FIN
02360      * (let user know if we could do so)
02361      */
02362 
02363     if (tiflags & TH_FIN) {
02364         if (TCPS_HAVERCVDFIN(state_) == 0) {
02365             flags_ |= TF_ACKNOW;
02366             rcv_nxt_++;
02367         }
02368         switch (state_) {
02369                 /*
02370                  * In SYN_RECEIVED and ESTABLISHED STATES
02371                  * enter the CLOSE_WAIT state.
02372          * (passive close)
02373                  */
02374                 case TCPS_SYN_RECEIVED:
02375                 case TCPS_ESTABLISHED:
02376             newstate(TCPS_CLOSE_WAIT);
02377                         break;
02378 
02379                 /*
02380                  * If still in FIN_WAIT_1 STATE FIN has not been acked so
02381                  * enter the CLOSING state.
02382          * (simultaneous close)
02383                  */
02384                 case TCPS_FIN_WAIT_1:
02385             newstate(TCPS_CLOSING);
02386                         break;
02387                 /*
02388                  * In FIN_WAIT_2 state enter the TIME_WAIT state,
02389                  * starting the time-wait timer, turning off the other
02390                  * standard timers.
02391          * (in the simulator, just go to CLOSED)
02392          * (completion of active close)
02393                  */
02394                 case TCPS_FIN_WAIT_2:
02395                         newstate(TCPS_CLOSED);
02396             cancel_timers();
02397                         break;
02398         }
02399     } /* end of if FIN bit on */
02400 
02401     if (needoutput || (flags_ & TF_ACKNOW))
02402         send_much(1, REASON_NORMAL, maxburst_);
02403     else if (curseq_ >= highest_ack_ || infinite_send_)
02404         send_much(0, REASON_NORMAL, maxburst_);
02405     // K: which state to return to when nothing left?
02406 
02407     if (!halfclose_ && state_ == TCPS_CLOSE_WAIT && highest_ack_ == maxseq_)
02408         usrclosed();
02409 
02410     Packet::free(pkt);
02411 
02412     // haoboy: Is here the place for done{} of active close? 
02413     // It cannot be put in the switch above because we might need to do
02414     // send_much() (an ACK)
02415     if (state_ == TCPS_CLOSED) 
02416         Tcl::instance().evalf("%s done", this->name());
02417 
02418     return;
02419 
02420     //
02421     // various ways of dropping (some also ACK, some also RST)
02422     //
02423 
02424 dropafterack:
02425     flags_ |= TF_ACKNOW;
02426     send_much(1, REASON_NORMAL, maxburst_);
02427     goto drop;
02428 
02429 dropwithreset:
02430     /* we should be sending an RST here, but can't in simulator */
02431     if (tiflags & TH_ACK) {
02432         sendpacket(ackno, 0, 0x0, 0, REASON_NORMAL);
02433     } else {
02434         int ack = tcph->seqno() + datalen;
02435         if (tiflags & TH_SYN)
02436             ack--;
02437         sendpacket(0, ack, TH_ACK, 0, REASON_NORMAL);
02438     }
02439 drop:
02440     Packet::free(pkt);
02441     return;
02442 }
02443 /*  
02444  * Dupack-action: what to do on a DUP ACK.  After the initial check
02445  * of 'recover' below, this function implements the following truth
02446  * table:
02447  *  
02448  *      bugfix  ecn     last-cwnd == ecn        action  
02449  *  
02450  *      0       0       0                       full_reno_action
02451  *      0       0       1                       full_reno_action [impossible]
02452  *      0       1       0                       full_reno_action
02453  *      0       1       1                       1/2 window, return 
02454  *      1       0       0                       nothing 
02455  *      1       0       1                       nothing         [impossible]
02456  *      1       1       0                       nothing 
02457  *      1       1       1                       1/2 window, return
02458  */ 
02459     
02460 void
02461 FullTcpAgent::dupack_action()
02462 {   
02463 
02464         int recovered = (highest_ack_ > recover_);
02465 
02466     fastrecov_ = TRUE;
02467     rtxbytes_ = 0;
02468 
02469         if (recovered || (!bug_fix_ && !ecn_) ||
02470         // Q: is last_cwnd_action == dupack enough to trigger?
02471         // probably not.  may need to fix 1-way reno model as well
02472         last_cwnd_action_ == CWND_ACTION_DUPACK) {
02473                 goto full_reno_action;
02474         }       
02475     
02476         if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
02477                 slowdown(CLOSE_CWND_HALF);
02478         cancel_rtx_timer();
02479         rtt_active_ = FALSE;
02480         (void)fast_retransmit(highest_ack_);
02481                 return; 
02482         }      
02483     
02484         if (bug_fix_) {
02485                 /*
02486                  * The line below, for "bug_fix_" true, avoids
02487                  * problems with multiple fast retransmits in one
02488                  * window of data.
02489                  */      
02490                 return;  
02491         }
02492     
02493 full_reno_action:    
02494         slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
02495     cancel_rtx_timer();
02496     rtt_active_ = FALSE;
02497     recover_ = maxseq_;
02498     (void)fast_retransmit(highest_ack_);
02499     // we measure cwnd in packets,
02500     // so don't scale by maxseg_
02501     // as real TCP does
02502     cwnd_ = double(ssthresh_) + double(dupacks_);
02503         return;
02504 }
02505 
02506 void
02507 FullTcpAgent::timeout_action()
02508 {
02509     recover_ = maxseq_;
02510 
02511     if (cwnd_ < 1.0) {
02512         fprintf(stderr,
02513         "%f: FullTcpAgent(%s):: resetting cwnd from %f to 1\n",
02514          now(), name(), double(cwnd_));
02515         cwnd_ = 1.0;
02516     }
02517 
02518     if (last_cwnd_action_ == CWND_ACTION_ECN) {
02519         slowdown(CLOSE_CWND_ONE);
02520     } else {
02521         slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_RESTART);
02522         last_cwnd_action_ = CWND_ACTION_TIMEOUT;
02523     }
02524     reset_rtx_timer(1);
02525     t_seqno_ = (highest_ack_ < 0) ? iss_ : int(highest_ack_);
02526     fastrecov_ = FALSE;
02527     dupacks_ = 0;
02528 }
02529 /*
02530  * deal with timers going off.
02531  * 2 types for now:
02532  *  retransmission timer (rtx_timer_)
02533  *  delayed ack timer (delack_timer_)
02534  *  delayed send (randomization) timer (delsnd_timer_)
02535  *
02536  * real TCP initializes the RTO as 6 sec
02537  *  (A + 2D, where A=0, D=3), [Stevens p. 305]
02538  * and thereafter uses
02539  *  (A + 4D, where A and D are dynamic estimates)
02540  *
02541  * note that in the simulator t_srtt_, t_rttvar_ and t_rtt_
02542  * are all measured in 'tcp_tick_'-second units
02543  */
02544 
02545 void
02546 FullTcpAgent::timeout(int tno)
02547 {
02548 
02549     /*
02550      * Due to F. Hernandez-Campos' fix in recv(), we may send an ACK
02551      * while in the CLOSED state.  -M. Weigle 7/24/01
02552      */
02553     if (state_ == TCPS_LISTEN) {
02554         // shouldn't be getting timeouts here
02555         fprintf(stderr, "%f: FullTcpAgent(%s): unexpected timeout %d in state %s\n",
02556             now(), name(), tno, statestr(state_));
02557         return;
02558     }
02559 
02560     switch (tno) {
02561 
02562     case TCP_TIMER_RTX:
02563                 /* retransmit timer */
02564                 ++nrexmit_;
02565                 timeout_action();
02566         /* fall thru */
02567     case TCP_TIMER_DELSND:
02568         /* for phase effects */
02569                 send_much(1, PF_TIMEOUT, maxburst_);
02570         break;
02571 
02572     case TCP_TIMER_DELACK:
02573                 if (flags_ & TF_DELACK) {
02574                         flags_ &= ~TF_DELACK;
02575                         flags_ |= TF_ACKNOW;
02576                         send_much(1, REASON_NORMAL, 0);
02577                 }
02578                 delack_timer_.resched(delack_interval_);
02579         break;
02580     default:
02581         fprintf(stderr, "%f: FullTcpAgent(%s) Unknown Timeout type %d\n",
02582             now(), name(), tno);
02583     }
02584     return;
02585 }
02586 
02587 void
02588 FullTcpAgent::dooptions(Packet* pkt)
02589 {
02590     // interesting options: timestamps (here),
02591     //  CC, CCNEW, CCECHO (future work perhaps?)
02592 
02593         hdr_flags *fh = hdr_flags::access(pkt);
02594     hdr_tcp *tcph = hdr_tcp::access(pkt);
02595 
02596     if (ts_option_ && !fh->no_ts_) {
02597         if (tcph->ts() < 0.0) {
02598             fprintf(stderr,
02599                 "%f: FullTcpAgent(%s) warning: ts_option enabled in this TCP, but appears to be disabled in peer\n",
02600                 now(), name());
02601         } else if (tcph->flags() & TH_SYN) {
02602             flags_ |= TF_RCVD_TSTMP;
02603             recent_ = tcph->ts();
02604             recent_age_ = now();
02605         }
02606     }
02607 
02608     return;
02609 }
02610 
02611 //
02612 // this shouldn't ever happen
02613 //
02614 void
02615 FullTcpAgent::process_sack(hdr_tcp*)
02616 {
02617     fprintf(stderr, "%f: FullTcpAgent(%s) Non-SACK capable FullTcpAgent received a SACK\n",
02618         now(), name());
02619     return;
02620 }
02621 
02622 
02623 /*
02624  * ****** Tahoe ******
02625  *
02626  * for TCP Tahoe, we force a slow-start as the dup ack
02627  * action.  Also, no window inflation due to multiple dup
02628  * acks.  The latter is arranged by setting reno_fastrecov_
02629  * false [which is performed by the Tcl init function for Tahoe in
02630  * ns-default.tcl].
02631  */
02632 
02633 /* 
02634  * Tahoe
02635  * Dupack-action: what to do on a DUP ACK.  After the initial check
02636  * of 'recover' below, this function implements the following truth
02637  * table:
02638  * 
02639  *      bugfix  ecn     last-cwnd == ecn        action  
02640  * 
02641  *      0       0       0                       full_tahoe_action
02642  *      0       0       1                       full_tahoe_action [impossible]
02643  *      0       1       0                       full_tahoe_action
02644  *      0       1       1                       1/2 window, return
02645  *      1       0       0                       nothing 
02646  *      1       0       1                       nothing         [impossible]
02647  *      1       1       0                       nothing 
02648  *      1       1       1                       1/2 window, return
02649  */
02650 
02651 void
02652 TahoeFullTcpAgent::dupack_action()
02653 {  
02654         int recovered = (highest_ack_ > recover_);
02655 
02656     fastrecov_ = TRUE;
02657     rtxbytes_ = 0;
02658 
02659         if (recovered || (!bug_fix_ && !ecn_) ||
02660         // Q: is last_cwnd_action dupack enough?
02661             last_cwnd_action_ == CWND_ACTION_DUPACK) {
02662                 goto full_tahoe_action;
02663         }
02664    
02665         if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
02666         // slow start on ECN
02667         last_cwnd_action_ = CWND_ACTION_DUPACK;
02668                 slowdown(CLOSE_CWND_ONE);
02669         set_rtx_timer();
02670                 rtt_active_ = FALSE;
02671         t_seqno_ = highest_ack_;
02672                 return; 
02673         }
02674    
02675         if (bug_fix_) {
02676                 /*
02677                  * The line below, for "bug_fix_" true, avoids
02678                  * problems with multiple fast retransmits in one
02679                  * window of data.
02680                  */      
02681                 return;  
02682         }
02683    
02684 full_tahoe_action:
02685     // slow-start and reset ssthresh
02686     trace_event("FAST_RETX");
02687     recover_ = maxseq_;
02688     last_cwnd_action_ = CWND_ACTION_DUPACK;
02689         slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_ONE);   // cwnd->1
02690     set_rtx_timer();
02691         rtt_active_ = FALSE;
02692     t_seqno_ = highest_ack_;
02693     send_much(0, REASON_NORMAL, 0);
02694         return; 
02695 }  
02696 
02697 /*
02698  * ****** Newreno ******
02699  *
02700  * for NewReno, a partial ACK does not exit fast recovery,
02701  * and does not reset the dup ACK counter (which might trigger fast
02702  * retransmits we don't want).  In addition, the number of packets
02703  * sent in response to an ACK is limited to recov_maxburst_ during
02704  * recovery periods.
02705  */
02706 
02707 NewRenoFullTcpAgent::NewRenoFullTcpAgent() : save_maxburst_(-1)
02708 {
02709     bind("recov_maxburst_", &recov_maxburst_);
02710 }
02711 
02712 void
02713 NewRenoFullTcpAgent::pack_action(Packet*)
02714 {
02715     (void)fast_retransmit(highest_ack_);
02716     cwnd_ = double(ssthresh_);
02717     if (save_maxburst_ < 0) {
02718         save_maxburst_ = maxburst_;
02719         maxburst_ = recov_maxburst_;
02720     }
02721     return;
02722 }
02723 
02724 void
02725 NewRenoFullTcpAgent::ack_action(Packet* p)
02726 {
02727     if (save_maxburst_ >= 0) {
02728         maxburst_ = save_maxburst_;
02729         save_maxburst_ = -1;
02730     }
02731     FullTcpAgent::ack_action(p);
02732     return;
02733 }
02734 
02735 /*
02736  *
02737  * ****** SACK ******
02738  *
02739  * for Sack, receiver part must report SACK data
02740  * sender part maintains a 'scoreboard' (sq_) that
02741  * records what it hears from receiver
02742  * sender fills holes during recovery and obeys
02743  * "pipe" style control until recovery is complete
02744  */
02745 
02746 void
02747 SackFullTcpAgent::reset()
02748 {
02749     sq_.clear();            // no SACK blocks
02750     /* Fixed typo.  -M. Weigle 6/17/02 */
02751     sack_min_ = h_seqno_ = -1;  // no left edge of SACK blocks
02752     FullTcpAgent::reset();
02753 }
02754 
02755 
02756 int
02757 SackFullTcpAgent::hdrsize(int nsackblocks)
02758 {
02759     int total = FullTcpAgent::headersize();
02760     // use base header size plus SACK option size
02761         if (nsackblocks > 0) {
02762                 total += ((nsackblocks * sack_block_size_)
02763                         + sack_option_size_);
02764     }
02765     return (total);
02766 }
02767 
02768 void
02769 SackFullTcpAgent::dupack_action()
02770 {
02771 
02772         int recovered = (highest_ack_ > recover_);
02773 
02774     fastrecov_ = TRUE;
02775     rtxbytes_ = 0;
02776     pipe_ = maxseq_ - highest_ack_ - sq_.total();
02777 
02778 //printf("%f: SACK DUPACK-ACTION:pipe_:%d, sq-total:%d, bugfix:%d, cwnd:%d, highest_ack:%d, recover_:%d\n",
02779 //now(), pipe_, sq_.total(), bug_fix_, int(cwnd_), int(highest_ack_), recover_);
02780 
02781         if (recovered || (!bug_fix_ && !ecn_)) {
02782                 goto full_sack_action;
02783         }           
02784 
02785         if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
02786         /* 
02787          * Received ECN notification and 3 DUPACKs in same 
02788          * window. Don't cut cwnd again, but retransmit lost
02789          * packet.   -M. Weigle  6/19/02
02790          */
02791         last_cwnd_action_ = CWND_ACTION_DUPACK;
02792         cancel_rtx_timer();
02793         rtt_active_ = FALSE;
02794         int amt = fast_retransmit(highest_ack_);
02795         pipectrl_ = TRUE;
02796         h_seqno_ = highest_ack_ + amt;
02797         send_much(0, REASON_DUPACK, maxburst_);
02798         return; 
02799     }
02800    
02801         if (bug_fix_) {
02802                 /*                              
02803                  * The line below, for "bug_fix_" true, avoids
02804                  * problems with multiple fast retransmits in one
02805                  * window of data.
02806                  */      
02807 
02808 //printf("%f: SACK DUPACK-ACTION BUGFIX RETURN:pipe_:%d, sq-total:%d, bugfix:%d, cwnd:%d\n",
02809 //now(), pipe_, sq_.total(), bug_fix_, int(cwnd_));
02810                 return;  
02811         }
02812    
02813 full_sack_action:                               
02814     trace_event("FAST_RECOVERY");
02815         slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
02816         cancel_rtx_timer();
02817         rtt_active_ = FALSE;
02818 
02819     // these initiate SACK-style "pipe" recovery
02820     pipectrl_ = TRUE;
02821     recover_ = maxseq_; // where I am when recovery starts
02822 
02823     int amt = fast_retransmit(highest_ack_);
02824     h_seqno_ = highest_ack_ + amt;
02825 
02826 //printf("%f: FAST-RTX seq:%d, h_seqno_ is now:%d, pipe:%d, cwnd:%d, recover:%d\n",
02827 //now(), int(highest_ack_), h_seqno_, pipe_, int(cwnd_), recover_);
02828 
02829     send_much(0, REASON_DUPACK, maxburst_);
02830 
02831         return;
02832 }
02833 
02834 void
02835 SackFullTcpAgent::pack_action(Packet* p)
02836 {
02837     if (!sq_.empty() && sack_min_ < highest_ack_) {
02838         sack_min_ = highest_ack_;
02839         sq_.cleartonxt();
02840     }
02841     pipe_ -= maxseg_;   // see comment in tcp-sack1.cc
02842     if (h_seqno_ < highest_ack_)
02843         h_seqno_ = highest_ack_;
02844 }
02845 
02846 void
02847 SackFullTcpAgent::ack_action(Packet* p)
02848 {
02849 //printf("%f: EXITING fast recovery, recover:%d\n",
02850 //now(), recover_);
02851     fastrecov_ = pipectrl_ = FALSE;
02852         if (!sq_.empty() && sack_min_ < highest_ack_) {
02853                 sack_min_ = highest_ack_;
02854                 sq_.cleartonxt();
02855         }
02856     dupacks_ = 0;
02857 
02858     /* 
02859      * Update h_seqno_ on new ACK (same as for partial ACKS)
02860      * -M. Weigle 6/3/05
02861      */
02862     if (h_seqno_ < highest_ack_)
02863         h_seqno_ = highest_ack_;
02864 }
02865 
02866 //
02867 // receiver side: if there are things in the reassembly queue,
02868 // build the appropriate SACK blocks to carry in the SACK
02869 //
02870 int
02871 SackFullTcpAgent::build_options(hdr_tcp* tcph)
02872 {
02873     int total = FullTcpAgent::build_options(tcph);
02874 
02875         if (!rq_.empty()) {
02876                 int nblk = rq_.gensack(&tcph->sa_left(0), max_sack_blocks_);
02877                 tcph->sa_length() = nblk;
02878         total += (nblk * sack_block_size_) + sack_option_size_;
02879         } else {
02880                 tcph->sa_length() = 0;
02881         }
02882     return (total);
02883 }
02884 
02885 void
02886 SackFullTcpAgent::timeout_action()
02887 {
02888     FullTcpAgent::timeout_action();
02889 
02890     //
02891     // original SACK spec says the sender is
02892     // supposed to clear out its knowledge of what
02893     // the receiver has in the case of a timeout
02894     // (on the chance the receiver has renig'd).
02895     // Here, this happens when clear_on_timeout_ is
02896     // enabled.
02897     //
02898 
02899     if (clear_on_timeout_) {
02900         sq_.clear();
02901         sack_min_ = highest_ack_;
02902     }
02903 
02904     return;
02905 }
02906 
02907 void
02908 SackFullTcpAgent::process_sack(hdr_tcp* tcph)
02909 {
02910     //
02911     // Figure out how many sack blocks are
02912     // in the pkt.  Insert each block range
02913     // into the scoreboard
02914     //
02915 
02916     if (max_sack_blocks_ <= 0) {
02917         fprintf(stderr,
02918             "%f: FullTcpAgent(%s) warning: received SACK block but I am not SACK enabled\n",
02919             now(), name());
02920         return;
02921     }   
02922 
02923     int slen = tcph->sa_length(), i;
02924     for (i = 0; i < slen; ++i) {
02925         /* Added check for FIN   -M. Weigle 5/21/02 */
02926         if ((tcph->flags() & TH_FIN == 0) && 
02927             tcph->sa_left(i) >= tcph->sa_right(i)) {
02928             fprintf(stderr,
02929                 "%f: FullTcpAgent(%s) warning: received illegal SACK block [%d,%d]\n",
02930                 now(), name(), tcph->sa_left(i), tcph->sa_right(i));
02931             continue;
02932         }
02933         sq_.add(tcph->sa_left(i), tcph->sa_right(i), 0);  
02934     }
02935 
02936     return;
02937 }
02938 
02939 int
02940 SackFullTcpAgent::send_allowed(int seq)
02941 {
02942     // not in pipe control, so use regular control
02943     if (!pipectrl_)
02944         return (FullTcpAgent::send_allowed(seq));
02945 
02946     // don't overshoot receiver's advertised window
02947     int topawin = highest_ack_ + int(wnd_) * maxseg_;
02948     if (seq >= topawin) {
02949 //printf("%f: SEND(%d) NOT ALLOWED DUE TO AWIN:%d, pipe:%d, cwnd:%d\n",
02950 //now(), seq, topawin, pipe_, int(cwnd_));
02951         return FALSE;
02952     }
02953 
02954     /*
02955      * If not in ESTABLISHED, don't send anything we don't have
02956      *   -M. Weigle 7/18/02
02957      */
02958     if (state_ != TCPS_ESTABLISHED && seq > curseq_)
02959         return FALSE;
02960 
02961     // don't overshoot cwnd_
02962     int cwin = int(cwnd_) * maxseg_;
02963     return (pipe_ < cwin);
02964 }
02965 
02966 
02967 //
02968 // Calculate the next seq# to send by send_much.  If we are recovering and
02969 // we have learned about data cached at the receiver via a SACK,
02970 // we may want something other than new data (t_seqno)
02971 //
02972 
02973 int
02974 SackFullTcpAgent::nxt_tseq()
02975 {
02976 
02977     int in_recovery = (highest_ack_ < recover_);
02978     int seq = h_seqno_;
02979 
02980     if (!in_recovery) {
02981 //if (int(t_seqno_) > 1)
02982 //printf("%f: non-recovery nxt_tseq called w/t_seqno:%d\n",
02983 //now(), int(t_seqno_));
02984 //sq_.dumplist();
02985         return (t_seqno_);
02986     }
02987 
02988     int fcnt;   // following count-- the
02989             // count field in the block
02990             // after the seq# we are about
02991             // to send
02992     int fbytes; // fcnt in bytes
02993 
02994 //if (int(t_seqno_) > 1)
02995 //printf("%f: recovery nxt_tseq called w/t_seqno:%d, seq:%d, mode:%d\n",
02996 //now(), int(t_seqno_), seq, sack_rtx_threshmode_);
02997 //sq_.dumplist();
02998 
02999     while ((seq = sq_.nexthole(seq, fcnt, fbytes)) > 0) {
03000         // if we have a following block
03001         // with a large enough count
03002         // we should use the seq# we get
03003         // from nexthole()
03004         if (sack_rtx_threshmode_ == 0 ||
03005             (sack_rtx_threshmode_ == 1 && fcnt >= sack_rtx_cthresh_) ||
03006             (sack_rtx_threshmode_ == 2 && fbytes >= sack_rtx_bthresh_) ||
03007             (sack_rtx_threshmode_ == 3 && (fcnt >= sack_rtx_cthresh_ || fbytes >= sack_rtx_bthresh_)) ||
03008             (sack_rtx_threshmode_ == 4 && (fcnt >= sack_rtx_cthresh_ && fbytes >= sack_rtx_bthresh_))) {
03009 
03010 //if (int(t_seqno_) > 1)
03011 //printf("%f: nxt_tseq<hole> returning %d\n",
03012 //now(), int(seq));
03013             // adjust h_seqno, as we may have
03014             // been "jumped ahead" by learning
03015             // about a filled hole
03016             if (seq > h_seqno_)
03017                 h_seqno_ = seq;
03018             return (seq);
03019         } else if (fcnt <= 0)
03020             break;
03021         else {
03022             seq += maxseg_;
03023         }
03024     }
03025 //if (int(t_seqno_) > 1)
03026 //printf("%f: nxt_tseq<top> returning %d\n",
03027 //now(), int(t_seqno_));
03028     return (t_seqno_);
03029 }

Generated on Tue Mar 6 16:47:52 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6