#include <tcp-full.h>
Inheritance diagram for SackFullTcpAgent:


Public Member Functions | |
| SackFullTcpAgent () | |
| ~SackFullTcpAgent () | |
| virtual void | recv (Packet *pkt, Handler *) |
| virtual void | recv (Packet *p, const char *s) |
| virtual void | timeout (int tno) |
| virtual void | close () |
| void | advanceby (int) |
| void | advance_bytes (int) |
| virtual void | sendmsg (int nbytes, const char *flags=0) |
| virtual void | sendmsg (int sz, AppData *, const char *flags=0) |
| virtual int & | size () |
| virtual int | command (int argc, const char *const *argv) |
| virtual void | connect (nsaddr_t dst) |
| virtual void | timeout_nonrtx (int tno) |
| void | trace (TracedVar *v) |
| void | recvOnly (Packet *) |
| void | send (Packet *p, Handler *h) |
| virtual void | send (int sz, AppData *data) |
| virtual void | send (int nbytes) |
| virtual void | sendto (int sz, AppData *, const char *flags, nsaddr_t dst) |
| virtual void | sendto (int nbytes, const char *flags, nsaddr_t dst) |
| virtual void | attachApp (Application *app) |
| nsaddr_t & | addr () |
| nsaddr_t & | port () |
| nsaddr_t & | daddr () |
| nsaddr_t & | dport () |
| void | set_pkttype (packet_t pkttype) |
| packet_t | get_pkttype () |
| NsObject * | target () |
| virtual void | drop (Packet *p) |
| int | isdebug () const |
| virtual void | debug (const char *fmt,...) |
Protected Member Functions | |
| virtual void | delay_bind_init_all () |
| virtual int | delay_bind_dispatch (const char *varName, const char *localName, TclObject *tracer) |
| virtual void | pack_action (Packet *) |
| virtual void | ack_action (Packet *) |
| virtual void | dupack_action () |
| virtual void | process_sack (hdr_tcp *) |
| virtual void | timeout_action () |
| virtual int | nxt_tseq () |
| virtual int | hdrsize (int nblks) |
| virtual int | send_allowed (int) |
| virtual void | sent (int seq, int amt) |
| int | build_options (hdr_tcp *) |
| void | reset () |
| void | sendpacket (int seqno, int ackno, int pflags, int datalen, int reason) |
| int | headersize () |
| int | outflags () |
| int | rcvseqinit (int, int) |
| int | predict_ok (Packet *) |
| int | idle_restart () |
| int | fast_retransmit (int) |
| double | now () |
| virtual void | newstate (int ns) |
| void | bufferempty () |
| void | finish () |
| void | reset_rtx_timer (int) |
| void | reset_rtx_timer (int mild, int backoff=1) |
| virtual void | send_much (int force, int reason, int maxburst=0) |
| virtual int | reass (Packet *) |
| virtual void | oldack () |
| virtual void | extra_ack () |
| void | connect () |
| void | listen () |
| void | usrclosed () |
| int | need_send () |
| int | foutput (int seqno, int reason=0) |
| void | newack (Packet *pkt) |
| int | pack (Packet *pkt) |
| void | dooptions (Packet *) |
| void | cancel_timers () |
| void | prpkt (Packet *) |
| char * | flagstr (int) |
| char * | statestr (int) |
| void | set_initial_window () |
| virtual int | window () |
| virtual double | windowd () |
| void | print_if_needed (double memb_time) |
| void | traceAll () |
| virtual void | traceVar (TracedVar *v) |
| virtual void | rtt_init () |
| virtual double | rtt_timeout () |
| virtual void | rtt_update (double tao) |
| virtual void | rtt_backoff () |
| virtual void | output (int seqno, int reason=0) |
| virtual void | newtimer (Packet *) |
| virtual void | send_one () |
| double | linear (double x, double x_1, double y_1, double x_2, double y_2) |
| void | opencwnd () |
| void | slowdown (int how) |
| void | ecn (int seqno) |
| double | initial_window () |
| void | tcp_eln (Packet *pkt) |
| void | reset_qoption () |
| void | rtt_counting () |
| int | network_limited () |
| double | limited_slow_start (double cwnd, double max_ssthresh, double increment) |
| virtual int | numdupacks (double cwnd) |
| virtual void | processQuickStart (Packet *pkt) |
| virtual void | endQuickStart () |
| virtual void | output_helper (Packet *) |
| virtual void | send_helper (int) |
| virtual void | send_idle_helper () |
| virtual void | recv_helper (Packet *) |
| virtual void | recv_newack_helper (Packet *) |
| virtual void | partialnewack_helper (Packet *) |
| virtual void | cancel_rtx_timer () |
| virtual void | set_rtx_timer () |
| double | increase_param () |
| double | decrease_param () |
| double | compute_p () |
| void | trace_event (char *eventtype) |
| void | closecwnd (int how) |
| void | quench (int how) |
| void | process_qoption_after_send () |
| void | process_qoption_after_ack (int seqno) |
| virtual void | recvBytes (int bytes) |
| virtual void | idle () |
| Packet * | allocpkt () const |
| Packet * | allocpkt (int) const |
| void | initpkt (Packet *) const |
| void | deleteAgentTrace () |
| void | addAgentTrace (const char *name) |
| void | monitorAgentTrace () |
| OldValue * | lookupOldValue (TracedVar *v) |
| void | insertOldValue (TracedVar *v, const char *value) |
| void | dumpTracedVars () |
| virtual void | drop (Packet *p, const char *s) |
| void | handle (Event *) |
Protected Attributes | |
| int | clear_on_timeout_ |
| int | sack_option_size_ |
| int | sack_block_size_ |
| int | max_sack_blocks_ |
| int | sack_rtx_bthresh_ |
| int | sack_rtx_cthresh_ |
| int | sack_rtx_threshmode_ |
| ReassemblyQueue | sq_ |
| int | sack_min_ |
| int | h_seqno_ |
| int | closed_ |
| int | ts_option_size_ |
| int | pipe_ |
| int | pipectrl_ |
| int | rtxbytes_ |
| int | open_cwnd_on_pack_ |
| int | segs_per_ack_ |
| int | spa_thresh_ |
| int | nodelay_ |
| int | fastrecov_ |
| int | deflate_on_pack_ |
| int | data_on_syn_ |
| double | last_send_time_ |
| int | close_on_empty_ |
| int | signal_on_empty_ |
| int | reno_fastrecov_ |
| int | infinite_send_ |
| int | tcprexmtthresh_ |
| int | iss_ |
| int | irs_ |
| int | dupseg_fix_ |
| int | dupack_reset_ |
| int | halfclose_ |
| int | nopredict_ |
| int | dsack_ |
| double | delack_interval_ |
| DelAckTimer | delack_timer_ |
| int | maxseg_ |
| int | flags_ |
| int | state_ |
| int | ect_ |
| int | recent_ce_ |
| int | last_state_ |
| int | rcv_nxt_ |
| ReassemblyQueue | rq_ |
| int | last_ack_sent_ |
| double | recent_ |
| double | recent_age_ |
| TracedInt | t_seqno_ |
| TracedInt | t_rtt_ |
| int | T_SRTT_BITS |
| TracedInt | t_srtt_ |
| int | srtt_init_ |
| int | T_RTTVAR_BITS |
| int | rttvar_exp_ |
| TracedInt | t_rttvar_ |
| int | rttvar_init_ |
| double | t_rtxcur_ |
| double | rtxcur_init_ |
| TracedInt | t_backoff_ |
| double | ts_peer_ |
| RtxTimer | rtx_timer_ |
| DelSndTimer | delsnd_timer_ |
| BurstSndTimer | burstsnd_timer_ |
| int | timerfix_ |
| int | rfc2988_ |
| double | boot_time_ |
| double | overhead_ |
| double | wnd_ |
| double | wnd_const_ |
| double | wnd_th_ |
| double | wnd_init_ |
| double | wnd_restart_ |
| double | tcp_tick_ |
| int | wnd_option_ |
| int | wnd_init_option_ |
| double | decrease_num_ |
| double | increase_num_ |
| double | k_parameter_ |
| double | l_parameter_ |
| int | precision_reduce_ |
| int | syn_ |
| int | delay_growth_ |
| int | tcpip_base_hdr_size_ |
| int | bug_fix_ |
| int | less_careful_ |
| int | ts_option_ |
| int | maxburst_ |
| int | maxcwnd_ |
| int | numdupacks_ |
| int | numdupacksFrac_ |
| double | maxrto_ |
| double | minrto_ |
| int | old_ecn_ |
| FILE * | plotfile_ |
| TracedInt | dupacks_ |
| TracedInt | curseq_ |
| int | last_ack_ |
| TracedInt | highest_ack_ |
| int | recover_ |
| int | last_cwnd_action_ |
| TracedDouble | cwnd_ |
| double | base_cwnd_ |
| double | awnd_ |
| TracedInt | ssthresh_ |
| int | count_ |
| double | fcnt_ |
| int | rtt_active_ |
| int | rtt_seq_ |
| double | rtt_ts_ |
| TracedInt | maxseq_ |
| int | ecn_ |
| int | cong_action_ |
| int | ecn_burst_ |
| int | ecn_backoff_ |
| int | eln_ |
| int | eln_rxmit_thresh_ |
| int | eln_last_rxmit_ |
| double | firstsent_ |
| double | lastreset_ |
| int | slow_start_restart_ |
| int | restart_bugfix_ |
| TracedInt | ndatapack_ |
| TracedInt | ndatabytes_ |
| TracedInt | nackpack_ |
| TracedInt | nrexmit_ |
| TracedInt | nrexmitpack_ |
| TracedInt | nrexmitbytes_ |
| TracedInt | necnresponses_ |
| TracedInt | ncwndcuts_ |
| int | trace_all_oneline_ |
| int | nam_tracevar_ |
| int | first_decrease_ |
| TracedInt | singledup_ |
| int | noFastRetrans_ |
| int | oldCode_ |
| int | useHeaders_ |
| int | low_window_ |
| int | high_window_ |
| double | high_p_ |
| double | high_decrease_ |
| int | max_ssthresh_ |
| double | cwnd_last_ |
| double | increase_last_ |
| double | cwnd_frac_ |
| int | rate_request_ |
| int | qs_enabled_ |
| int | qs_requested_ |
| int | qs_approved_ |
| int | ttl_diff_ |
| int | QOption_ |
| int | EnblRTTCtr_ |
| int | T_full |
| int | T_last |
| int | T_prev |
| int | T_start |
| int | RTT_count |
| int | RTT_prev |
| int | RTT_goodcount |
| int | F_counting |
| int | W_used |
| int | W_timed |
| int | F_full |
| int | Backoffs |
| int | control_increase_ |
| int | prev_highest_ack_ |
| ns_addr_t | here_ |
| ns_addr_t | dst_ |
| int | size_ |
| packet_t | type_ |
| int | fid_ |
| int | prio_ |
| int | defttl_ |
| Tcl_Channel | channel_ |
| char * | traceName_ |
| OldValue * | oldValueList_ |
| Application * | app_ |
| EventTrace * | et_ |
| NsObject * | target_ |
| NsObject * | drop_ |
| int | debug_ |
Static Protected Attributes | |
| int | uidcnt_ |
|
|
Definition at line 265 of file tcp-full.h. References h_seqno_, sack_min_, and sq_.
|
|
|
Definition at line 267 of file tcp-full.h. References ReassemblyQueue::clear(), and FullTcpAgent::rq_.
|
Here is the call graph for this function:

|
|
Reimplemented from FullTcpAgent. Definition at line 2766 of file tcp-full.cc. References ReassemblyQueue::cleartonxt(), TcpAgent::dupacks_, ReassemblyQueue::empty(), FALSE, FullTcpAgent::fastrecov_, TcpAgent::highest_ack_, FullTcpAgent::pipectrl_, sack_min_, and sq_.
02767 {
02768 //printf("%f: EXITING fast recovery, recover:%d\n",
02769 //now(), recover_);
02770 fastrecov_ = pipectrl_ = FALSE;
02771 if (!sq_.empty() && sack_min_ < highest_ack_) {
02772 sack_min_ = highest_ack_;
02773 sq_.cleartonxt();
02774 }
02775 dupacks_ = 0;
02776 }
|
Here is the call graph for this function:

|
|
Definition at line 326 of file agent.cc. References ns_addr_t::addr_, Agent::channel_, Scheduler::clock(), Agent::dst_, Agent::here_, Scheduler::instance(), TIME_FORMAT, and Agent::traceName_. Referenced by Agent::command().
00327 {
00328 char wrk[256];
00329 int n;
00330 double curTime = (&Scheduler::instance() == NULL ? 0 :
00331 Scheduler::instance().clock());
00332
00333 sprintf(wrk, "a -t "TIME_FORMAT" -s %d -d %d -n %s",
00334 curTime, here_.addr_, dst_.addr_, name);
00335 n = strlen(wrk);
00336 wrk[n] = '\n';
00337 wrk[n+1] = 0;
00338 if (channel_)
00339 (void)Tcl_Write(channel_, wrk, n+1);
00340 // keep agent trace name
00341 if (traceName_ != NULL)
00342 delete[] traceName_;
00343 traceName_ = new char[strlen(name)+1];
00344 strcpy(traceName_, name);
00345 }
|
Here is the call graph for this function:

|
|
|
Definition at line 347 of file tcp-full.cc. References FullTcpAgent::connect(), TcpAgent::curseq_, FullTcpAgent::iss_, TcpAgent::maxburst_, FullTcpAgent::now(), REASON_NORMAL, FullTcpAgent::reset(), FullTcpAgent::send_much(), FullTcpAgent::state_, FullTcpAgent::statestr(), TCPS_CLOSED, TCPS_ESTABLISHED, TCPS_LISTEN, TCPS_SYN_RECEIVED, and TCPS_SYN_SENT. Referenced by FullTcpAgent::advanceby(), FullTcpAgent::command(), and FullTcpAgent::sendmsg().
00348 {
00349
00350 //
00351 // state-specific operations:
00352 // if CLOSED or LISTEN, reset and try a new active open/connect
00353 // if ESTABLISHED, queue and try to send more
00354 // if SYN_SENT or SYN_RCVD, just queue
00355 // if above ESTABLISHED, we are closing, so don't allow
00356 //
00357
00358 switch (state_) {
00359
00360 case TCPS_CLOSED:
00361 case TCPS_LISTEN:
00362 reset();
00363 curseq_ = iss_ + nb;
00364 connect(); // initiate new connection
00365 break;
00366
00367 case TCPS_ESTABLISHED:
00368 case TCPS_SYN_SENT:
00369 case TCPS_SYN_RECEIVED:
00370 if (curseq_ < iss_)
00371 curseq_ = iss_;
00372 curseq_ += nb;
00373 break;
00374
00375 default:
00376 fprintf(stderr,
00377 "%f: FullTcpAgent::advance(%s): cannot advance while in state %s\n",
00378 now(), name(), statestr(state_));
00379
00380 }
00381
00382 if (state_ == TCPS_ESTABLISHED)
00383 send_much(0, REASON_NORMAL, maxburst_);
00384
00385 return;
00386 }
|
Here is the call graph for this function:

|
|
Reimplemented from TcpAgent. Definition at line 328 of file tcp-full.cc. References FullTcpAgent::advance_bytes(), and FullTcpAgent::maxseg_. Referenced by FullTcpAgent::command().
00329 {
00330 // XXX hack:
00331 // because np is in packets and a data source
00332 // may pass a *huge* number as a way to tell us
00333 // to go forever, just look for the huge number
00334 // and if it's there, pre-divide it
00335 if (np >= 0x10000000)
00336 np /= maxseg_;
00337
00338 advance_bytes(np * maxseg_);
00339 return;
00340 }
|
Here is the call graph for this function:

|
|
Definition at line 517 of file agent.cc. References Packet::allocdata(), and Agent::allocpkt().
|
Here is the call graph for this function:

|
Here is the call graph for this function:

|
|
Definition at line 372 of file agent.cc. References Agent::app_. Referenced by HttpMInvalCache::command(), Application::command(), TcpApp::TcpApp(), and TcpApp::~TcpApp().
00373 {
00374 app_ = app;
00375 }
|
|
|
Definition at line 443 of file tcp-full.cc. References FALSE, and FullTcpAgent::signal_on_empty_. Referenced by FullTcpAgent::foutput().
00444 {
00445 signal_on_empty_=FALSE;
00446 Tcl::instance().evalf("%s done_data", this->name());
00447 }
|
|
|
Reimplemented from FullTcpAgent. Definition at line 2783 of file tcp-full.cc. References FullTcpAgent::build_options(), ReassemblyQueue::empty(), ReassemblyQueue::gensack(), max_sack_blocks_, FullTcpAgent::rq_, hdr_tcp::sa_left(), hdr_tcp::sa_length(), sack_block_size_, and sack_option_size_.
02784 {
02785 int total = FullTcpAgent::build_options(tcph);
02786
02787 if (!rq_.empty()) {
02788 int nblk = rq_.gensack(&tcph->sa_left(0), max_sack_blocks_);
02789 tcph->sa_length() = nblk;
02790 total += (nblk * sack_block_size_) + sack_option_size_;
02791 } else {
02792 tcph->sa_length() = 0;
02793 }
02794 return (total);
02795 }
|
Here is the call graph for this function:

|
|
Reimplemented in TcpFsAgent, RenoTcpFsAgent, NewRenoTcpFsAgent, and TcpSessionAgent. Definition at line 242 of file tcp.h. References TimerHandler::force_cancel(), and TcpAgent::rtx_timer_. Referenced by dupack_action(), FullTcpAgent::dupack_action(), FullTcpAgent::newack(), TcpAgent::newtimer(), FullTcpAgent::recv(), and TcpAgent::recv_newack_helper().
00242 {
00243 rtx_timer_.force_cancel();
00244 }
|
Here is the call graph for this function:

|
|
Reimplemented from TcpAgent. Definition at line 507 of file tcp-full.cc. References TcpAgent::cancel_timers(), FullTcpAgent::delack_timer_, and TimerHandler::force_cancel(). Referenced by FullTcpAgent::recv(), FullTcpAgent::reset(), FullTcpAgent::usrclosed(), and FullTcpAgent::~FullTcpAgent().
00508 {
00509
00510 // cancel: rtx, burstsend, delsnd
00511 TcpAgent::cancel_timers();
00512 // cancel: delack
00513 delack_timer_.force_cancel();
00514 }
|
Here is the call graph for this function:

|
|
Reimplemented from Agent. Definition at line 128 of file tcp-full.h. References FullTcpAgent::usrclosed().
00128 { usrclosed(); }
|
Here is the call graph for this function:

|
|
Reimplemented in IntTcpAgent. Definition at line 1649 of file tcp.cc. References abort(), TcpAgent::count_, TcpAgent::cwnd_, TcpAgent::decrease_num_, TcpAgent::fcnt_, TcpAgent::ssthresh_, TcpAgent::window(), TcpAgent::wnd_init_, and TcpAgent::wnd_restart_. Referenced by TcpAgent::quench().
01650 {
01651 static int first_time = 1;
01652 if (first_time == 1) {
01653 fprintf(stderr, "the TcpAgent::closecwnd() function is now deprecated, please use the function slowdown() instead\n");
01654 }
01655 switch (how) {
01656 case 0:
01657 /* timeouts */
01658 ssthresh_ = int( window() / 2 );
01659 if (ssthresh_ < 2)
01660 ssthresh_ = 2;
01661 cwnd_ = int(wnd_restart_);
01662 break;
01663
01664 case 1:
01665 /* Reno dup acks, or after a recent congestion indication. */
01666 // cwnd_ = window()/2;
01667 cwnd_ = decrease_num_ * window();
01668 ssthresh_ = int(cwnd_);
01669 if (ssthresh_ < 2)
01670 ssthresh_ = 2;
01671 break;
01672
01673 case 2:
01674 /* Tahoe dup acks
01675 * after a recent congestion indication */
01676 cwnd_ = wnd_init_;
01677 break;
01678
01679 case 3:
01680 /* Retransmit timeout, but no outstanding data. */
01681 cwnd_ = int(wnd_init_);
01682 break;
01683 case 4:
01684 /* Tahoe dup acks */
01685 ssthresh_ = int( window() / 2 );
01686 if (ssthresh_ < 2)
01687 ssthresh_ = 2;
01688 cwnd_ = 1;
01689 break;
01690
01691 default:
01692 abort();
01693 }
01694 fcnt_ = 0.;
01695 count_ = 0;
01696 }
|
Here is the call graph for this function:

|
||||||||||||
|
Reimplemented from TcpAgent. Definition at line 260 of file tcp-full.cc. References FullTcpAgent::advance_bytes(), FullTcpAgent::advanceby(), TcpAgent::command(), FullTcpAgent::listen(), FullTcpAgent::sendmsg(), and FullTcpAgent::usrclosed().
00261 {
00262 // would like to have some "connect" primitive
00263 // here, but the problem is that we get called before
00264 // the simulation is running and we want to send a SYN.
00265 // Because no routing exists yet, this fails.
00266 // Instead, see code in advance().
00267 //
00268 // listen can happen any time because it just changes state_
00269 //
00270 // close is designed to happen at some point after the
00271 // simulation is running (using an ns 'at' command)
00272
00273 if (argc == 2) {
00274 if (strcmp(argv[1], "listen") == 0) {
00275 // just a state transition
00276 listen();
00277 return (TCL_OK);
00278 }
00279 if (strcmp(argv[1], "close") == 0) {
00280 usrclosed();
00281 return (TCL_OK);
00282 }
00283 }
00284 if (argc == 3) {
00285 if (strcmp(argv[1], "advance") == 0) {
00286 advanceby(atoi(argv[2]));
00287 return (TCL_OK);
00288 }
00289 if (strcmp(argv[1], "advanceby") == 0) {
00290 advanceby(atoi(argv[2]));
00291 return (TCL_OK);
00292 }
00293 if (strcmp(argv[1], "advance-bytes") == 0) {
00294 advance_bytes(atoi(argv[2]));
00295 return (TCL_OK);
00296 }
00297 }
00298 if (argc == 4) {
00299 if (strcmp(argv[1], "sendmsg") == 0) {
00300 sendmsg(atoi(argv[2]), argv[3]);
00301 return (TCL_OK);
00302 }
00303 }
00304 return (TcpAgent::command(argc, argv));
00305 }
|
Here is the call graph for this function:

|
|
Definition at line 897 of file tcp.cc. References TcpAgent::cwnd_, TcpAgent::high_p_, TcpAgent::high_window_, TcpAgent::linear(), and TcpAgent::low_window_. Referenced by TcpAgent::increase_param().
00898 {
00899 double p;
00900 double low_p = 1.5/(low_window_*low_window_);
00901 p = exp(linear(log(cwnd_), log(low_window_), log(low_p), log(high_window_), log(high_p_)));
00902 return p;
00903 }
|
Here is the call graph for this function:

|
|
Definition at line 389 of file agent.cc. Referenced by Agent::command().
00390 {
00391 /*
00392 dst_ = dst;
00393 */
00394 }
|
|
|
Definition at line 417 of file tcp-full.cc. References FullTcpAgent::foutput(), FullTcpAgent::iss_, FullTcpAgent::newstate(), REASON_NORMAL, FullTcpAgent::sent(), and TCPS_SYN_SENT. Referenced by FullTcpAgent::advance_bytes().
|
Here is the call graph for this function:

|
|
||||||||||||
|
Definition at line 102 of file object.cc. References NsObject::debug_.
00103 {
00104 if (!debug_)
00105 return;
00106 va_list ap;
00107 va_start(ap, fmt);
00108 vprintf(fmt, ap);
00109 }
|
|
|
Definition at line 908 of file tcp.cc. References TcpAgent::cwnd_, TcpAgent::high_decrease_, TcpAgent::high_window_, TcpAgent::linear(), and TcpAgent::low_window_. Referenced by TcpAgent::increase_param(), and TcpAgent::slowdown().
00909 {
00910 double decrease;
00911 decrease = linear(log(cwnd_), log(low_window_), 0.5, log(high_window_), high_decrease_);
00912 return decrease;
00913 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Reimplemented from FullTcpAgent. Definition at line 247 of file tcp-full.cc. References clear_on_timeout_, FullTcpAgent::delay_bind_dispatch(), max_sack_blocks_, sack_block_size_, sack_option_size_, sack_rtx_bthresh_, sack_rtx_cthresh_, and sack_rtx_threshmode_.
00248 {
00249 if (delay_bind_bool(varName, localName, "clear_on_timeout_", &clear_on_timeout_, tracer)) return TCL_OK;
00250 if (delay_bind(varName, localName, "sack_rtx_cthresh_", &sack_rtx_cthresh_, tracer)) return TCL_OK;
00251 if (delay_bind(varName, localName, "sack_rtx_bthresh_", &sack_rtx_bthresh_, tracer)) return TCL_OK;
00252 if (delay_bind(varName, localName, "sack_rtx_threshmode_", &sack_rtx_threshmode_, tracer)) return TCL_OK;
00253 if (delay_bind(varName, localName, "sack_block_size_", &sack_block_size_, tracer)) return TCL_OK;
00254 if (delay_bind(varName, localName, "sack_option_size_", &sack_option_size_, tracer)) return TCL_OK;
00255 if (delay_bind(varName, localName, "max_sack_blocks_", &max_sack_blocks_, tracer)) return TCL_OK;
00256 return FullTcpAgent::delay_bind_dispatch(varName, localName, tracer);
00257 }
|
Here is the call graph for this function:

|
|
Reimplemented from FullTcpAgent. Definition at line 234 of file tcp-full.cc. References FullTcpAgent::delay_bind_init_all().
00235 {
00236 delay_bind_init_one("clear_on_timeout_");
00237 delay_bind_init_one("sack_rtx_cthresh_");
00238 delay_bind_init_one("sack_rtx_bthresh_");
00239 delay_bind_init_one("sack_block_size_");
00240 delay_bind_init_one("sack_option_size_");
00241 delay_bind_init_one("max_sack_blocks_");
00242 delay_bind_init_one("sack_rtx_threshmode_");
00243 FullTcpAgent::delay_bind_init_all();
00244 }
|
Here is the call graph for this function:

|
|
Definition at line 222 of file agent.cc. References ns_addr_t::addr_, Agent::dst_, Agent::flushAVar(), Agent::here_, Scheduler::instance(), TIME_FORMAT, and Agent::traceName_. Referenced by Agent::command().
00223 {
00224 char wrk[256];
00225
00226 // XXX we don't know InstVar outside of Tcl! Is there any
00227 // tracedvars hidden in InstVar? If so, shall we have a tclclInt.h?
00228 TracedVar* var = tracedvar_;
00229 for ( ; var != 0; var = var->next_)
00230 flushAVar(var);
00231
00232 // we need to flush all var values to trace file,
00233 // so nam can do backtracing
00234 sprintf(wrk, "a -t "TIME_FORMAT" -s %d -d %d -n %s -x",
00235 Scheduler::instance().clock(), here_.addr_,
00236 dst_.addr_, traceName_);
00237 if (traceName_ != NULL)
00238 delete[] traceName_;
00239 traceName_ = NULL;
00240 }
|
Here is the call graph for this function:

|
|
Definition at line 2516 of file tcp-full.cc. References hdr_tcp::access(), hdr_flags::access(), hdr_tcp::flags(), FullTcpAgent::flags_, hdr_flags::no_ts_, FullTcpAgent::now(), FullTcpAgent::recent_, FullTcpAgent::recent_age_, TF_RCVD_TSTMP, TH_SYN, hdr_tcp::ts(), and TcpAgent::ts_option_. Referenced by FullTcpAgent::recv().
02517 {
02518 // interesting options: timestamps (here),
02519 // CC, CCNEW, CCECHO (future work perhaps?)
02520
02521 hdr_flags *fh = hdr_flags::access(pkt);
02522 hdr_tcp *tcph = hdr_tcp::access(pkt);
02523
02524 if (ts_option_ && !fh->no_ts_) {
02525 if (tcph->ts() < 0.0) {
02526 fprintf(stderr,
02527 "%f: FullTcpAgent(%s) warning: ts_option enabled in this TCP, but appears to be disabled in peer\n",
02528 now(), name());
02529 } else if (tcph->flags() & TH_SYN) {
02530 flags_ |= TF_RCVD_TSTMP;
02531 recent_ = tcph->ts();
02532 recent_age_ = now();
02533 }
02534 }
02535
02536 return;
02537 }
|
Here is the call graph for this function:

|
|
Definition at line 99 of file agent.h. References Agent::dst_, nsaddr_t, and ns_addr_t::port_. Referenced by DSDV_Agent::lost_link(), TcpAsymSink::recv(), CtrMcastEncap::recv(), IntTcpAgent::rxmit_last(), IntTcpAgent::send_one(), rtProtoDV::sendpkt(), TcpAgent::trace_event(), TcpAgent::traceAll(), TcpAsymAgent::traceAll(), TcpAgent::traceVar(), TcpSessionAgent::traceVar(), and TcpAsymAgent::traceVar().
|
|
||||||||||||
|
Definition at line 114 of file connector.cc. References Connector::drop_, Packet::free(), and NsObject::recv().
00115 {
00116 if (drop_ != 0)
00117 drop_->recv(p, s);
00118 else
00119 Packet::free(p);
00120 }
|
Here is the call graph for this function:

|
Here is the call graph for this function:

|
|
|
|
|
Reimplemented from FullTcpAgent. Definition at line 2696 of file tcp-full.cc. References TcpAgent::bug_fix_, TcpAgent::cancel_rtx_timer(), CLOSE_CWND_HALF, CLOSE_SSTHRESH_HALF, CWND_ACTION_DUPACK, CWND_ACTION_ECN, TcpAgent::ecn_, FALSE, FullTcpAgent::fast_retransmit(), FullTcpAgent::fastrecov_, h_seqno_, TcpAgent::highest_ack_, TcpAgent::last_cwnd_action_, TcpAgent::maxburst_, TcpAgent::maxseq_, FullTcpAgent::pipe_, FullTcpAgent::pipectrl_, REASON_DUPACK, TcpAgent::recover_, TcpAgent::rtt_active_, FullTcpAgent::rtxbytes_, FullTcpAgent::send_much(), TcpAgent::slowdown(), sq_, ReassemblyQueue::total(), TcpAgent::trace_event(), and TRUE.
02697 {
02698
02699 int recovered = (highest_ack_ > recover_);
02700
02701 fastrecov_ = TRUE;
02702 rtxbytes_ = 0;
02703 pipe_ = maxseq_ - highest_ack_ - sq_.total();
02704
02705 //printf("%f: SACK DUPACK-ACTION:pipe_:%d, sq-total:%d, bugfix:%d, cwnd:%d, highest_ack:%d, recover_:%d\n",
02706 //now(), pipe_, sq_.total(), bug_fix_, int(cwnd_), int(highest_ack_), recover_);
02707
02708 if (recovered || (!bug_fix_ && !ecn_)) {
02709 goto full_sack_action;
02710 }
02711
02712 if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {
02713 last_cwnd_action_ = CWND_ACTION_DUPACK;
02714 cancel_rtx_timer();
02715 rtt_active_ = FALSE;
02716 send_much(1, REASON_DUPACK, maxburst_);
02717 return;
02718 }
02719
02720 if (bug_fix_) {
02721 /*
02722 * The line below, for "bug_fix_" true, avoids
02723 * problems with multiple fast retransmits in one
02724 * window of data.
02725 */
02726
02727 //printf("%f: SACK DUPACK-ACTION BUGFIX RETURN:pipe_:%d, sq-total:%d, bugfix:%d, cwnd:%d\n",
02728 //now(), pipe_, sq_.total(), bug_fix_, int(cwnd_));
02729 return;
02730 }
02731
02732 full_sack_action:
02733 trace_event("FAST_RECOVERY");
02734 slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
02735 cancel_rtx_timer();
02736 rtt_active_ = FALSE;
02737
02738 // these initiate SACK-style "pipe" recovery
02739 pipectrl_ = TRUE;
02740 recover_ = maxseq_; // where I am when recovery starts
02741
02742 int amt = fast_retransmit(highest_ack_);
02743 h_seqno_ = highest_ack_ + amt;
02744
02745 //printf("%f: FAST-RTX seq:%d, h_seqno_ is now:%d, pipe:%d, cwnd:%d, recover:%d\n",
02746 //now(), int(highest_ack_), h_seqno_, pipe_, int(cwnd_), recover_);
02747
02748 send_much(0, REASON_DUPACK, maxburst_);
02749
02750 return;
02751 }
|
Here is the call graph for this function:

|
|
Definition at line 1232 of file tcp.cc. References CLOSE_CWND_HALF, CLOSE_SSTHRESH_HALF, TcpAgent::cwnd_, CWND_ACTION_ECN, CWND_ACTION_TIMEOUT, TcpAgent::ecn_backoff_, TcpAgent::last_cwnd_action_, TcpAgent::maxseq_, TcpAgent::necnresponses_, TcpAgent::recover_, TcpAgent::rtt_backoff(), and TcpAgent::slowdown(). Referenced by TcpAgent::recv(), VegasTcpAgent::recv(), Sack1TcpAgent::recv(), RFC793eduTcpAgent::recv(), RenoTcpAgent::recv(), NewRenoTcpAgent::recv(), FullTcpAgent::recv(), and FackTcpAgent::recv().
01233 {
01234 if (seqno > recover_ ||
01235 last_cwnd_action_ == CWND_ACTION_TIMEOUT) {
01236 recover_ = maxseq_;
01237 last_cwnd_action_ = CWND_ACTION_ECN;
01238 if (cwnd_ <= 1.0) {
01239 if (ecn_backoff_)
01240 rtt_backoff();
01241 else ecn_backoff_ = 1;
01242 } else ecn_backoff_ = 0;
01243 slowdown(CLOSE_CWND_HALF|CLOSE_SSTHRESH_HALF);
01244 ++necnresponses_ ;
01245 // added by sylvia to count number of ecn responses
01246 }
01247 }
|
Here is the call graph for this function:

|
|
Definition at line 1402 of file tcp.cc. References TcpAgent::cwnd_, TcpAgent::initial_window(), TcpAgent::last_ack_, TcpAgent::maxseq_, and TcpAgent::qs_approved_. Referenced by TcpAgent::recv(), Sack1TcpAgent::recv(), RenoTcpAgent::recv(), and NewRenoTcpAgent::recv().
01403 {
01404 qs_approved_ = 0;
01405 int new_cwnd = maxseq_ - last_ack_;
01406 if (new_cwnd > 1 && new_cwnd < cwnd_) {
01407 cwnd_ = new_cwnd;
01408 if (cwnd_ < initial_window())
01409 cwnd_ = initial_window();
01410 }
01411 }
|
Here is the call graph for this function:

|
|
Definition at line 202 of file tcp-full.h. References TcpAgent::cwnd_, and FullTcpAgent::reno_fastrecov_. Referenced by FullTcpAgent::recv().
00202 { // dup ACKs after threshold
00203 if (reno_fastrecov_)
00204 cwnd_++;
00205 }
|
|
|
Definition at line 1341 of file tcp-full.cc. References CWND_ACTION_DUPACK, FullTcpAgent::foutput(), TcpAgent::last_cwnd_action_, TcpAgent::maxseq_, REASON_DUPACK, TcpAgent::recover_, and TcpAgent::trace_event(). Referenced by dupack_action(), FullTcpAgent::dupack_action(), and NewRenoFullTcpAgent::pack_action().
01342 {
01343 // we are now going to fast-retransmit and willtrace that event
01344 trace_event("FAST_RETX");
01345
01346 recover_ = maxseq_; // recovery target
01347 last_cwnd_action_ = CWND_ACTION_DUPACK;
01348 return(foutput(seq, REASON_DUPACK)); // send one pkt
01349 }
|
Here is the call graph for this function:

|
|
Reimplemented from TcpAgent. Definition at line 621 of file tcp-full.cc. Referenced by FullTcpAgent::recv(), and FullTcpAgent::usrclosed().
00622 {
00623 Tcl::instance().evalf("%s done", this->name());
00624 }
|
|
|
Definition at line 548 of file tcp-full.cc. Referenced by FullTcpAgent::prpkt().
00549 {
00550 // update this if tcp header flags change
00551 static char *flagstrs[28] = {
00552 "<null>", "<FIN>", "<SYN>", "<SYN,FIN>", // 0-3
00553 "<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>", // 4-7
00554 "<PSH>", "<PSH,FIN>", "<PSH,SYN>", "<PSH,SYN,FIN>", // 0x08-0x0b
00555 /* do not use <??, in next line because that's an ANSI trigraph */
00556 "<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>", // 0x0c-0x0f
00557 "<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>", // 0x10-0x13
00558 "<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>", // 0x14-0x17
00559 "<PSH,ACK>", "<PSH,ACK,FIN>", "<PSH,ACK,SYN>", "<PSH,ACK,SYN,FIN>", // 0x18-0x1b
00560 };
00561 if (hflags < 0 || (hflags > 28))
00562 return ("<invalid>");
00563 return (flagstrs[hflags]);
00564 }
|
|
||||||||||||
|
Definition at line 923 of file tcp-full.cc. References FullTcpAgent::bufferempty(), CLOSE_CWND_INIT, FullTcpAgent::close_on_empty_, TcpAgent::cong_action_, TcpAgent::curseq_, FullTcpAgent::data_on_syn_, TcpAgent::ecn_, FullTcpAgent::ect_, FALSE, FullTcpAgent::flags_, FullTcpAgent::headersize(), TcpAgent::highest_ack_, Agent::idle(), FullTcpAgent::idle_restart(), FullTcpAgent::infinite_send_, FullTcpAgent::iss_, FullTcpAgent::maxseg_, TcpAgent::maxseq_, min, FullTcpAgent::need_send(), FullTcpAgent::newstate(), FullTcpAgent::nodelay_, FullTcpAgent::now(), FullTcpAgent::outflags(), FullTcpAgent::pipectrl_, FullTcpAgent::rcv_nxt_, FullTcpAgent::recent_ce_, TcpAgent::rtt_active_, TcpAgent::rtt_seq_, TcpAgent::rtt_ts_, TcpAgent::rtx_timer_, Agent::send(), FullTcpAgent::sendpacket(), TcpAgent::set_rtx_timer(), FullTcpAgent::signal_on_empty_, Agent::size_, TcpAgent::slow_start_restart_, TcpAgent::slowdown(), FullTcpAgent::state_, TimerHandler::status(), TCP_MAXSEQ, TCPS_CLOSED, TCPS_ESTABLISHED, TCPS_FIN_WAIT_1, TF_ACKNOW, TF_DELACK, TF_NEEDCLOSE, TH_ACK, TH_CWR, TH_ECE, TH_FIN, TH_PUSH, TH_SYN, TIMER_PENDING, TRUE, TcpAgent::ts_option_, TcpAgent::window(), and TcpAgent::wnd_. Referenced by FullTcpAgent::connect(), FullTcpAgent::fast_retransmit(), and FullTcpAgent::send_much().
00924 {
00925 // if maxseg_ not set, set it appropriately
00926 // Q: how can this happen?
00927
00928 if (maxseg_ == 0)
00929 maxseg_ = size_ - headersize();
00930 else
00931 size_ = maxseg_ + headersize();
00932
00933 int is_retransmit = (seqno < maxseq_);
00934 int quiet = (highest_ack_ == maxseq_);
00935 int pflags = outflags();
00936 int syn = (seqno == iss_);
00937 int emptying_buffer = FALSE;
00938 int buffered_bytes = (infinite_send_) ? TCP_MAXSEQ :
00939 curseq_ - highest_ack_ + 1;
00940
00941 int win = window() * maxseg_; // window (in bytes)
00942 int off = seqno - highest_ack_; // offset of seg in window
00943 int datalen;
00944 //int amtsent = 0;
00945
00946 // be careful if we have not received any ACK yet
00947 if (highest_ack_ < 0) {
00948 if (!infinite_send_)
00949 buffered_bytes = curseq_ - iss_;;
00950 off = seqno - iss_;
00951 }
00952
00953 if (syn && !data_on_syn_)
00954 datalen = 0;
00955 else if (pipectrl_)
00956 datalen = buffered_bytes - off;
00957 else
00958 datalen = min(buffered_bytes, win) - off;
00959
00960 if ((signal_on_empty_) && (!buffered_bytes) && (!syn))
00961 bufferempty();
00962
00963 //
00964 // in real TCP datalen (len) could be < 0 if there was window
00965 // shrinkage, or if a FIN has been sent and neither ACKd nor
00966 // retransmitted. Only this 2nd case concerns us here...
00967 //
00968 if (datalen < 0) {
00969 datalen = 0;
00970 } else if (datalen > maxseg_) {
00971 datalen = maxseg_;
00972 }
00973
00974
00975 //
00976 // this is an option that causes us to slow-start if we've
00977 // been idle for a "long" time, where long means a rto or longer
00978 // the slow-start is a sort that does not set ssthresh
00979 //
00980
00981 if (slow_start_restart_ && quiet && datalen > 0) {
00982 if (idle_restart()) {
00983 slowdown(CLOSE_CWND_INIT);
00984 }
00985 }
00986
00987 //
00988 // see if sending this packet will empty the send buffer
00989 // a dataless SYN packet counts also
00990 //
00991
00992 if (!infinite_send_ && ((seqno + datalen) > curseq_ ||
00993 (syn && datalen == 0))) {
00994 emptying_buffer = TRUE;
00995 //
00996 // if not a retransmission, notify application that
00997 // everything has been sent out at least once.
00998 //
00999 if (!syn) {
01000 idle();
01001 if (close_on_empty_ && quiet) {
01002 flags_ |= TF_NEEDCLOSE;
01003 }
01004 }
01005 pflags |= TH_PUSH;
01006 //
01007 // if close_on_empty set, we are finished
01008 // with this connection; close it
01009 //
01010 } else {
01011 /* not emptying buffer, so can't be FIN */
01012 pflags &= ~TH_FIN;
01013 }
01014 if (infinite_send_ && (syn && datalen == 0))
01015 pflags |= TH_PUSH; // set PUSH for dataless SYN
01016
01017 /* sender SWS avoidance (Nagle) */
01018
01019 if (datalen > 0) {
01020 // if full-sized segment, ok
01021 if (datalen == maxseg_)
01022 goto send;
01023 // if Nagle disabled and buffer clearing, ok
01024 if ((quiet || nodelay_) && emptying_buffer)
01025 goto send;
01026 // if a retransmission
01027 if (is_retransmit)
01028 goto send;
01029 // if big "enough", ok...
01030 // (this is not a likely case, and would
01031 // only happen for tiny windows)
01032 if (datalen >= ((wnd_ * maxseg_) / 2.0))
01033 goto send;
01034 }
01035
01036 if (need_send())
01037 goto send;
01038
01039 /*
01040 * send now if a control packet or we owe peer an ACK
01041 * TF_ACKNOW can be set during connection establishment and
01042 * to generate acks for out-of-order data
01043 */
01044
01045 if ((flags_ & (TF_ACKNOW|TF_NEEDCLOSE)) ||
01046 (pflags & (TH_SYN|TH_FIN))) {
01047 goto send;
01048 }
01049
01050 /*
01051 * No reason to send a segment, just return.
01052 */
01053 return 0;
01054
01055 send:
01056
01057 // is a syn or fin?
01058
01059 syn = (pflags & TH_SYN) ? 1 : 0;
01060 int fin = (pflags & TH_FIN) ? 1 : 0;
01061
01062 /* setup ECN syn and ECN SYN+ACK packet headers */
01063 if (ecn_ && syn && !(pflags & TH_ACK)){
01064 pflags |= TH_ECE;
01065 pflags |= TH_CWR;
01066 }
01067 if (ecn_ && syn && (pflags & TH_ACK)){
01068 pflags |= TH_ECE;
01069 pflags &= ~TH_CWR;
01070 }
01071
01072 /* set CWR if necessary */
01073 if (ecn_ && ect_ && cong_action_) pflags |= TH_CWR;
01074
01075 /* set ECE if necessary */
01076 if (ecn_ && ect_ && recent_ce_ ) pflags |= TH_ECE;
01077
01078 /*
01079 * Tack on the FIN flag to the data segment if close_on_empty_
01080 * was previously set-- avoids sending a separate FIN
01081 */
01082 if (flags_ & TF_NEEDCLOSE) {
01083 flags_ &= ~TF_NEEDCLOSE;
01084 if (state_ <= TCPS_ESTABLISHED && state_ != TCPS_CLOSED)
01085 {
01086 pflags |=TH_FIN;
01087 fin = 1; /* FIN consumes sequence number */
01088 newstate(TCPS_FIN_WAIT_1);
01089 }
01090 }
01091 sendpacket(seqno, rcv_nxt_, pflags, datalen, reason);
01092
01093 /*
01094 * Data sent (as far as we can tell).
01095 * Any pending ACK has now been sent.
01096 */
01097 flags_ &= ~(TF_ACKNOW|TF_DELACK);
01098
01099 /*
01100 * if we have reacted to congestion recently, the
01101 * slowdown() procedure will have set cong_action_ and
01102 * sendpacket will have copied that to the outgoing pkt
01103 * CWR field. If that packet contains data, then
01104 * it will be reliably delivered, so we are free to turn off the
01105 * cong_action_ state now If only a pure ACK, we keep the state
01106 * around until we actually send a segment
01107 */
01108
01109 int reliable = datalen + syn + fin; // seq #'s reliably sent
01110 if (cong_action_ && reliable > 0)
01111 cong_action_ = FALSE;
01112
01113 // highest: greatest sequence number sent + 1
01114 // and adjusted for SYNs and FINs which use up one number
01115
01116 int highest = seqno + reliable;
01117 if (highest > maxseq_) {
01118 maxseq_ = highest;
01119 //
01120 // if we are using conventional RTT estimation,
01121 // establish timing on this segment
01122 //
01123 if (!ts_option_ && rtt_active_ == FALSE) {
01124 rtt_active_ = TRUE; // set timer
01125 rtt_seq_ = seqno; // timed seq #
01126 rtt_ts_ = now(); // when set
01127 }
01128 }
01129
01130 /*
01131 * Set retransmit timer if not currently set,
01132 * and not doing an ack or a keep-alive probe.
01133 * Initial value for retransmit timer is smoothed
01134 * round-trip time + 2 * round-trip time variance.
01135 * Future values are rtt + 4 * rttvar.
01136 */
01137 if (rtx_timer_.status() != TIMER_PENDING && reliable) {
01138 set_rtx_timer(); // no timer pending, schedule one
01139 }
01140
01141 return (reliable);
01142 }
|
Here is the call graph for this function:

|
|
Definition at line 101 of file agent.h. References packet_t, and Agent::type_. Referenced by CBR_Traffic::init().
00101 { return type_; }
|
|
|
Implements Handler. Reimplemented in LinkDelay, LL, AckRecons, and Snoop. Definition at line 91 of file object.cc. References NsObject::recv().
|
Here is the call graph for this function:

|
|
Definition at line 2684 of file tcp-full.cc. References FullTcpAgent::headersize(), sack_block_size_, and sack_option_size_.
02685 {
02686 int total = FullTcpAgent::headersize();
02687 // use base header size plus SACK option size
02688 if (nsackblocks > 0) {
02689 total += ((nsackblocks * sack_block_size_)
02690 + sack_option_size_);
02691 }
02692 return (total);
02693 }
|
Here is the call graph for this function:

|
|
Reimplemented from TcpAgent. Definition at line 631 of file tcp-full.cc. References FullTcpAgent::now(), TcpAgent::tcpip_base_hdr_size_, TcpAgent::ts_option_, and FullTcpAgent::ts_option_size_. Referenced by FullTcpAgent::foutput(), and hdrsize().
00632 {
00633 int total = tcpip_base_hdr_size_;
00634 if (total < 1) {
00635 fprintf(stderr,
00636 "%f: FullTcpAgent(%s): warning: tcpip hdr size is only %d bytes\n",
00637 now(), name(), tcpip_base_hdr_size_);
00638 }
00639
00640 if (ts_option_)
00641 total += ts_option_size_;
00642
00643 return (total);
00644 }
|
Here is the call graph for this function:

|
|
Definition at line 363 of file agent.cc. References Agent::app_, and Application::resume(). Referenced by FullTcpAgent::foutput(), TcpAgent::output(), VegasTcpAgent::output(), RFC793eduTcpAgent::output(), QSNewRenoTcpAgent::output(), IntTcpAgent::output(), BayFullTcpAgent::output(), UdpAgent::sendmsg(), SA_Agent::sendmsg(), and RTPAgent::sendmsg().
|
Here is the call graph for this function:

|
|
Definition at line 1385 of file tcp-full.cc. References TcpAgent::boot_time_, FullTcpAgent::last_send_time_, FullTcpAgent::now(), TcpAgent::t_rtxcur_, TcpAgent::tcp_tick_, and TcpAgent::ts_option_. Referenced by FullTcpAgent::foutput().
01386 {
01387 if (last_send_time_ < 0.0) {
01388 // last_send_time_ isn't set up yet, we shouldn't
01389 // do the idle_restart
01390 return (0);
01391 }
01392
01393 double tao = now() - last_send_time_;
01394 if (!ts_option_) {
01395 double tickoff = fmod(last_send_time_ + boot_time_,
01396 tcp_tick_);
01397 tao = int((tao + tickoff) / tcp_tick_) * tcp_tick_;
01398 }
01399
01400 return (tao > t_rtxcur_); // verify this CHECKME
01401 }
|
Here is the call graph for this function:

|
|
Definition at line 918 of file tcp.cc. References TcpAgent::compute_p(), TcpAgent::cwnd_, TcpAgent::cwnd_frac_, TcpAgent::cwnd_last_, TcpAgent::decrease_param(), TcpAgent::increase_last_, and TcpAgent::low_window_. Referenced by TcpAgent::opencwnd().
00919 {
00920 double increase, decrease, p, answer;
00921 /* extending the slow-start for high-speed TCP */
00922
00923 /* for highspeed TCP -- from Sylvia Ratnasamy, */
00924 /* modifications by Sally Floyd and Evandro de Souza */
00925 // p ranges from 1.5/W^2 at congestion window low_window_, to
00926 // high_p_ at congestion window high_window_, on a log-log scale.
00927 // The decrease factor ranges from 0.5 to high_decrease
00928 // as the window ranges from low_window to high_window,
00929 // as the log of the window.
00930 // For an efficient implementation, this would just be looked up
00931 // in a table, with the increase and decrease being a function of the
00932 // congestion window.
00933
00934 if (cwnd_ <= low_window_) {
00935 answer = 1 / cwnd_;
00936 return answer;
00937 } else if (cwnd_ >= cwnd_last_ && cwnd_ < cwnd_frac_ * cwnd_last_ ) {
00938 answer = increase_last_ / cwnd_;
00939 return answer;
00940 } else {
00941 p = compute_p();
00942 decrease = decrease_param();
00943 increase = (cwnd_ * cwnd_ *2.0* decrease * p)/(2.0 - decrease);
00944 // double max_increase = 157.8;
00945 // if (increase > max_increase) {
00946 // increase = max_increase;
00947 // }
00948 answer = increase / cwnd_;
00949 cwnd_last_ = cwnd_;
00950 increase_last_ = increase;
00951 return answer;
00952 }
00953 }
|
Here is the call graph for this function:

|
|
Definition at line 1301 of file tcp.cc. References abort(), Agent::size_, TcpAgent::wnd_init_, and TcpAgent::wnd_init_option_. Referenced by TcpAgent::endQuickStart(), TcpAgent::processQuickStart(), TcpAgent::recv(), VegasTcpAgent::recv(), Sack1TcpAgent::recv(), RFC793eduTcpAgent::recv(), RenoTcpAgent::recv(), QSNewRenoTcpAgent::recv(), NewRenoTcpAgent::recv(), FullTcpAgent::recv(), TcpAgent::set_initial_window(), and QSNewRenoTcpAgent::timeout().
01302 {
01303 //
01304 // init_option = 1: static iw of wnd_init_
01305 //
01306 if (wnd_init_option_ == 1) {
01307 return (wnd_init_);
01308 }
01309 else if (wnd_init_option_ == 2) {
01310 // do iw according to Internet draft
01311 if (size_ <= 1095) {
01312 return (4.0);
01313 } else if (size_ < 2190) {
01314 return (3.0);
01315 } else {
01316 return (2.0);
01317 }
01318 }
01319 // XXX what should we return here???
01320 fprintf(stderr, "Wrong number of wnd_init_option_ %d\n",
01321 wnd_init_option_);
01322 abort();
01323 return (2.0); // XXX make msvc happy.
01324 }
|
Here is the call graph for this function:

|
|
Definition at line 446 of file agent.cc. References hdr_nv::access(), hdr_flags::access(), hdr_ip::access(), hdr_cmn::access(), ns_addr_t::addr_, Scheduler::clock(), hdr_flags::cong_action_, hdr_ip::daddr(), Agent::defttl_, hdr_cmn::direction(), hdr_ip::dport(), Agent::dst_, hdr_flags::ecn_, hdr_flags::ecn_capable_, hdr_flags::ecn_to_echo_, hdr_flags::eln_, hdr_cmn::error(), Agent::fid_, hdr_ip::flowid(), hdr_flags::fs_, NixNode::GetNixVector(), NixNode::GetNodeObject(), hdr_nv::h_used, Agent::here_, hdr_cmn::iface(), Scheduler::instance(), hdr_flags::no_ts_, hdr_cmn::NONE, hdr_nv::nv(), hdr_ip::offset(), hdr_nv::offset(), ns_addr_t::port_, hdr_flags::pri_, hdr_ip::prio(), Agent::prio_, hdr_cmn::ptype(), NixVec::Reset(), hdr_ip::saddr(), hdr_cmn::size(), Agent::size_, hdr_ip::sport(), hdr_cmn::timestamp(), hdr_ip::ttl(), Agent::type_, hdr_cmn::uid(), and Agent::uidcnt_. Referenced by Agent::allocpkt(), and PingResponder::recv().
00447 {
00448 hdr_cmn* ch = hdr_cmn::access(p);
00449 ch->uid() = uidcnt_++;
00450 ch->ptype() = type_;
00451 ch->size() = size_;
00452 ch->timestamp() = Scheduler::instance().clock();
00453 ch->iface() = UNKN_IFACE.value(); // from packet.h (agent is local)
00454 ch->direction() = hdr_cmn::NONE;
00455
00456 ch->error() = 0; /* pkt not corrupt to start with */
00457
00458 hdr_ip* iph = hdr_ip::access(p);
00459 iph->saddr() = here_.addr_;
00460 iph->sport() = here_.port_;
00461 iph->daddr() = dst_.addr_;
00462 iph->dport() = dst_.port_;
00463
00464 //DEBUG
00465 //if (dst_ != -1)
00466 // printf("pl break\n");
00467
00468 iph->flowid() = fid_;
00469 iph->prio() = prio_;
00470 iph->ttl() = defttl_;
00471
00472 hdr_flags* hf = hdr_flags::access(p);
00473 hf->ecn_capable_ = 0;
00474 hf->ecn_ = 0;
00475 hf->eln_ = 0;
00476 hf->ecn_to_echo_ = 0;
00477 hf->fs_ = 0;
00478 hf->no_ts_ = 0;
00479 hf->pri_ = 0;
00480 hf->cong_action_ = 0;
00481 #ifdef HAVE_STL
00482
00483 hdr_nv* nv = hdr_nv::access(p);
00484 if (0)
00485 printf("Off hdr_nv %d, ip_hdr %d myaddr %ld\n",
00486 hdr_nv::offset(), hdr_ip::offset(), here_.addr_);
00487 NixNode* pNixNode = NixNode::GetNodeObject(here_.addr_);
00488 if (0)
00489 printf("Node Object %p\n", pNixNode);
00490 if (pNixNode) {
00491 // If we get non-null, indicates nixvector routing in use
00492 // Delete any left over nv in the packet
00493 // Get a nixvector to the target (may create new)
00494 NixVec* pNv = pNixNode->GetNixVector(dst_.addr_);
00495 pNv->Reset();
00496 nv->nv() = pNv; // And set the nixvec in the packet
00497 nv->h_used = 0; // And reset used portion to 0
00498 }
00499 #endif //HAVE_STL
00500 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 250 of file agent.cc. References min, OldValue::next_, Agent::oldValueList_, TRACEVAR_MAXVALUELENGTH, OldValue::val_, and OldValue::var_. Referenced by Agent::trace().
00251 {
00252 OldValue *p = new OldValue;
00253 assert(p != NULL);
00254 strncpy(p->val_, value, min(strlen(value)+1, TRACEVAR_MAXVALUELENGTH));
00255 p->var_ = v;
00256 p->next_ = NULL;
00257 if (oldValueList_ == NULL)
00258 oldValueList_ = p;
00259 else {
00260 p->next_ = oldValueList_;
00261 oldValueList_ = p;
00262 }
00263 }
|
|
|
Definition at line 61 of file object.h. References NsObject::debug_.
00061 { return debug_; }
|
|
||||||||||||||||
|
Definition at line 872 of file tcp.cc. Referenced by TcpAgent::opencwnd().
00873 {
00874 int round = int(cwnd / (double(max_ssthresh)/2.0));
00875 double increment1 = 1.0/(double(round));
00876 if (increment < increment1)
00877 increment = increment1;
00878 return increment;
00879 }
|
|
||||||||||||||||||||||||
|
Definition at line 860 of file tcp.cc. Referenced by TcpAgent::compute_p(), and TcpAgent::decrease_param().
00861 {
00862 // The y coordinate factor ranges from y_1 to y_2
00863 // as the x coordinate ranges from x_1 to x_2.
00864 double y = y_1 + ((y_2 - y_1) * ((x - x_1)/(x_2-x_1)));
00865 return y;
00866 }
|
|
|
Reimplemented from Agent. Definition at line 430 of file tcp-full.cc. References FullTcpAgent::newstate(), PT_ACK, TCPS_LISTEN, and Agent::type_. Referenced by FullTcpAgent::command().
|
Here is the call graph for this function:

|
|
Definition at line 242 of file agent.cc. References OldValue::next_, Agent::oldValueList_, and OldValue::var_. Referenced by Agent::trace().
00243 {
00244 OldValue *p = oldValueList_;
00245 while ((p != NULL) && (p->var_ != v))
00246 p = p->next_;
00247 return p;
00248 }
|
|
|
Definition at line 310 of file agent.cc. References ns_addr_t::addr_, Agent::channel_, Scheduler::clock(), Agent::here_, Scheduler::instance(), TIME_FORMAT, and Agent::traceName_. Referenced by Agent::command().
00311 {
00312 char wrk[256];
00313 int n;
00314 double curTime = (&Scheduler::instance() == NULL ? 0 :
00315 Scheduler::instance().clock());
00316
00317 sprintf(wrk, "v -t "TIME_FORMAT" -e monitor_agent %d %s",
00318 curTime, here_.addr_, traceName_);
00319 n = strlen(wrk);
00320 wrk[n] = '\n';
00321 wrk[n+1] = 0;
00322 if (channel_)
00323 (void)Tcl_Write(channel_, wrk, n+1);
00324 }
|
Here is the call graph for this function:

|
|
Definition at line 1366 of file tcp-full.cc. References FullTcpAgent::flags_, FullTcpAgent::irs_, FullTcpAgent::last_ack_sent_, FullTcpAgent::maxseg_, FullTcpAgent::rcv_nxt_, FullTcpAgent::segs_per_ack_, FullTcpAgent::spa_thresh_, TF_ACKNOW, and TRUE. Referenced by FullTcpAgent::foutput(), and FullTcpAgent::recv().
01367 {
01368 if (flags_ & TF_ACKNOW)
01369 return TRUE;
01370
01371 int spa = (spa_thresh_ > 0 && ((rcv_nxt_ - irs_) < spa_thresh_)) ?
01372 1 : segs_per_ack_;
01373
01374 return ((rcv_nxt_ - last_ack_sent_) >= (spa * maxseg_));
01375 }
|
|
|
Definition at line 1253 of file tcp.cc. References TcpAgent::prev_highest_ack_, TcpAgent::t_seqno_, and TcpAgent::window(). Referenced by TcpAgent::recv_newack_helper().
01253 {
01254 int win = window () ;
01255 if (t_seqno_ > (prev_highest_ack_ + win))
01256 return 1;
01257 else
01258 return 0;
01259 }
|
Here is the call graph for this function:

|
|
Reimplemented from TcpAgent. Definition at line 1229 of file tcp-full.cc. References hdr_flags::access(), hdr_tcp::access(), hdr_tcp::ackno(), TcpAgent::cancel_rtx_timer(), TcpAgent::ecn_backoff_, hdr_flags::ecnecho(), FullTcpAgent::ect_, FALSE, TcpAgent::highest_ack_, TcpAgent::maxseq_, hdr_flags::no_ts_, FullTcpAgent::now(), FullTcpAgent::recent_, FullTcpAgent::recent_age_, TcpAgent::rtt_active_, TcpAgent::rtt_seq_, TcpAgent::rtt_ts_, TcpAgent::rtt_update(), TcpAgent::set_rtx_timer(), TcpAgent::t_backoff_, TcpAgent::t_seqno_, hdr_tcp::ts(), hdr_tcp::ts_echo(), and TcpAgent::ts_option_. Referenced by FullTcpAgent::recv().
01230 {
01231 hdr_tcp *tcph = hdr_tcp::access(pkt);
01232
01233 register int ackno = tcph->ackno();
01234 int progress = (ackno > highest_ack_);
01235
01236 if (ackno == maxseq_) {
01237 cancel_rtx_timer(); // all data ACKd
01238 } else if (progress) {
01239 set_rtx_timer();
01240 }
01241
01242 // advance the ack number if this is for new data
01243 if (progress)
01244 highest_ack_ = ackno;
01245
01246 // if we have suffered a retransmit timeout, t_seqno_
01247 // will have been reset to highest_ ack. If the
01248 // receiver has cached some data above t_seqno_, the
01249 // new-ack value could (should) jump forward. We must
01250 // update t_seqno_ here, otherwise we would be doing
01251 // go-back-n.
01252
01253 if (t_seqno_ < highest_ack_)
01254 t_seqno_ = highest_ack_; // seq# to send next
01255
01256 /*
01257 * Update RTT only if it's OK to do so from info in the flags header.
01258 * This is needed for protocols in which intermediate agents
01259 * in the network intersperse acks (e.g., ack-reconstructors) for
01260 * various reasons (without violating e2e semantics).
01261 */
01262 hdr_flags *fh = hdr_flags::access(pkt);
01263
01264 if (!fh->no_ts_) {
01265 if (ts_option_) {
01266 recent_age_ = now();
01267 recent_ = tcph->ts();
01268 rtt_update(now() - tcph->ts_echo());
01269 } else if (rtt_active_ && ackno > rtt_seq_) {
01270 // got an RTT sample, record it
01271 // "t_backoff_ = 1;" deleted by T. Kelly.
01272 rtt_active_ = FALSE;
01273 rtt_update(now() - rtt_ts_);
01274 }
01275
01276 if (!ect_ || !ecn_backoff_ ||
01277 !hdr_flags::access(pkt)->ecnecho()) {
01278 /*
01279 * Don't end backoff if still in ECN-Echo with
01280 * a congestion window of 1 packet.
01281 * Fix from T. Kelly.
01282 */
01283 t_backoff_ = 1;
01284 ecn_backoff_ = 0;
01285 }
01286 }
01287 return;
01288 }
|
Here is the call graph for this function:

|
|
Definition at line 517 of file tcp-full.cc. References FullTcpAgent::state_. Referenced by FullTcpAgent::connect(), FullTcpAgent::foutput(), FullTcpAgent::listen(), FullTcpAgent::recv(), and FullTcpAgent::usrclosed().
00518 {
00519 //printf("%f(%s): state changed from %s to %s\n",
00520 //now(), name(), statestr(state_), statestr(state));
00521
00522 state_ = state;
00523 }
|
|
|
Definition at line 838 of file tcp.cc. References hdr_tcp::access(), TcpAgent::cancel_rtx_timer(), TcpAgent::cwnd_, TcpAgent::maxseq_, hdr_tcp::seqno(), TcpAgent::set_rtx_timer(), and TcpAgent::t_seqno_. Referenced by TcpAgent::newack(), SackRHTcpAgent::newack(), RFC793eduTcpAgent::newack(), FackTcpAgent::oldack(), NewRenoTcpAgent::partialnewack_helper(), and Sack1TcpAgent::recv().
00839 {
00840 hdr_tcp *tcph = hdr_tcp::access(pkt);
00841 /*
00842 * t_seqno_, the next packet to send, is reset (decreased)
00843 * to highest_ack_ + 1 after a timeout,
00844 * so we also have to check maxseq_, the highest seqno sent.
00845 * In addition, if the packet sent after the timeout has
00846 * the ECN bit set, then the returning ACK caused cwnd_ to
00847 * be decreased to less than one, and we can't send another
00848 * packet until the retransmit timer again expires.
00849 * So we have to check for "cwnd_ < 1" as well.
00850 */
00851 if (t_seqno_ > tcph->seqno() || tcph->seqno() < maxseq_ || cwnd_ < 1)
00852 set_rtx_timer();
00853 else
00854 cancel_rtx_timer();
00855 }
|
Here is the call graph for this function:

|
|
Definition at line 170 of file tcp-full.h. References Scheduler::clock(), and Scheduler::instance(). Referenced by FullTcpAgent::advance_bytes(), FullTcpAgent::build_options(), FullTcpAgent::dooptions(), FullTcpAgent::foutput(), FullTcpAgent::headersize(), FullTcpAgent::idle_restart(), FullTcpAgent::newack(), FullTcpAgent::outflags(), process_sack(), FullTcpAgent::process_sack(), FullTcpAgent::reass(), FullTcpAgent::recv(), FullTcpAgent::sendpacket(), FullTcpAgent::timeout(), FullTcpAgent::timeout_action(), and FullTcpAgent::usrclosed().
00170 { return Scheduler::instance().clock(); }
|
Here is the call graph for this function:

|
|
Definition at line 884 of file tcp.cc. References TcpAgent::numdupacks_, and TcpAgent::numdupacksFrac_. Referenced by Sack1TcpAgent::dupack_action(), and Sack1TcpAgent::recv().
00885 {
00886 int cwndfraction = (int) cwnd/numdupacksFrac_;
00887 if (numdupacks_ > cwndfraction) {
00888 return numdupacks_;
00889 } else {
00890 return cwndfraction;
00891 }
00892 }
|
|
|
Reimplemented from FullTcpAgent. Definition at line 2877 of file tcp-full.cc. References h_seqno_, TcpAgent::highest_ack_, FullTcpAgent::maxseg_, ReassemblyQueue::nexthole(), TcpAgent::recover_, sack_rtx_bthresh_, sack_rtx_cthresh_, sack_rtx_threshmode_, sq_, and TcpAgent::t_seqno_.
02878 {
02879
02880 int in_recovery = (highest_ack_ < recover_);
02881 int seq = h_seqno_;
02882
02883 if (!in_recovery) {
02884 //if (int(t_seqno_) > 1)
02885 //printf("%f: non-recovery nxt_tseq called w/t_seqno:%d\n",
02886 //now(), int(t_seqno_));
02887 //sq_.dumplist();
02888 return (t_seqno_);
02889 }
02890
02891 int fcnt; // following count-- the
02892 // count field in the block
02893 // after the seq# we are about
02894 // to send
02895 int fbytes; // fcnt in bytes
02896
02897 //if (int(t_seqno_) > 1)
02898 //printf("%f: recovery nxt_tseq called w/t_seqno:%d, seq:%d, mode:%d\n",
02899 //now(), int(t_seqno_), seq, sack_rtx_threshmode_);
02900 //sq_.dumplist();
02901
02902 while ((seq = sq_.nexthole(seq, fcnt, fbytes)) > 0) {
02903 // if we have a following block
02904 // with a large enough count
02905 // we should use the seq# we get
02906 // from nexthole()
02907 if (sack_rtx_threshmode_ == 0 ||
02908 (sack_rtx_threshmode_ == 1 && fcnt >= sack_rtx_cthresh_) ||
02909 (sack_rtx_threshmode_ == 2 && fbytes >= sack_rtx_bthresh_) ||
02910 (sack_rtx_threshmode_ == 3 && (fcnt >= sack_rtx_cthresh_ || fbytes >= sack_rtx_bthresh_)) ||
02911 (sack_rtx_threshmode_ == 4 && (fcnt >= sack_rtx_cthresh_ && fbytes >= sack_rtx_bthresh_))) {
02912
02913 //if (int(t_seqno_) > 1)
02914 //printf("%f: nxt_tseq<hole> returning %d\n",
02915 //now(), int(seq));
02916 // adjust h_seqno, as we may have
02917 // been "jumped ahead" by learning
02918 // about a filled hole
02919 if (seq > h_seqno_)
02920 h_seqno_ = seq;
02921 return (seq);
02922 } else if (fcnt <= 0)
02923 break;
02924 else {
02925 seq += maxseg_;
02926 }
02927 }
02928 //if (int(t_seqno_) > 1)
02929 //printf("%f: nxt_tseq<top> returning %d\n",
02930 //now(), int(t_seqno_));
02931 return (t_seqno_);
02932 }
|
Here is the call graph for this function:

|
|
Definition at line 198 of file tcp-full.h. References TcpAgent::dupacks_. Referenced by FullTcpAgent::recv().
00198 { // what to do on old ack
00199 dupacks_ = 0;
00200 }
|
|
|
Reimplemented in FackTcpAgent, IntTcpAgent, and RFC793eduTcpAgent. Definition at line 958 of file tcp.cc. References abort(), TcpAgent::awnd_, TcpAgent::count_, TcpAgent::cwnd_, CWND_ACTION_TIMEOUT, TcpAgent::fcnt_, TcpAgent::increase_num_, TcpAgent::increase_param(), TcpAgent::k_parameter_, TcpAgent::last_cwnd_action_, TcpAgent::limited_slow_start(), TcpAgent::max_ssthresh_, TcpAgent::maxcwnd_, pow(), TcpAgent::ssthresh_, TcpAgent::t_srtt_, TcpAgent::T_SRTT_BITS, TcpAgent::tcp_tick_, TcpAgent::wnd_const_, and TcpAgent::wnd_option_. Referenced by FackTcpAgent::opencwnd(), TcpSessionAgent::recv(), SackRHTcpAgent::recv(), FullTcpAgent::recv(), BayFullTcpAgent::recv(), TcpAgent::recv_newack_helper(), VegasTcpAgent::recv_newack_helper(), TcpFsAgent::recv_newack_helper(), and TcpAsymAgent::recv_newack_helper().
00959 {
00960 double increment;
00961 if (cwnd_ < ssthresh_) {
00962 /* slow-start (exponential) */
00963 cwnd_ += 1;
00964 } else {
00965 /* linear */
00966 double f;
00967 switch (wnd_option_) {
00968 case 0:
00969 if (++count_ >= cwnd_) {
00970 count_ = 0;
00971 ++cwnd_;
00972 }
00973 break;
00974
00975 case 1:
00976 /* This is the standard algorithm. */
00977 increment = increase_num_ / cwnd_;
00978 if ((last_cwnd_action_ == 0 ||
00979 last_cwnd_action_ == CWND_ACTION_TIMEOUT)
00980 && max_ssthresh_ > 0) {
00981 increment = limited_slow_start(cwnd_,
00982 max_ssthresh_, increment);
00983 }
00984 cwnd_ += increment;
00985 break;
00986
00987 case 2:
00988 /* These are window increase algorithms
00989 * for experimental purposes only. */
00990 f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;
00991 f *= f;
00992 f *= wnd_const_;
00993 f += fcnt_;
00994 if (f > cwnd_) {
00995 fcnt_ = 0;
00996 ++cwnd_;
00997 } else
00998 fcnt_ = f;
00999 break;
01000
01001 case 3:
01002 f = awnd_;
01003 f *= f;
01004 f *= wnd_const_;
01005 f += fcnt_;
01006 if (f > cwnd_) {
01007 fcnt_ = 0;
01008 ++cwnd_;
01009 } else
01010 fcnt_ = f;
01011 break;
01012
01013 case 4:
01014 f = awnd_;
01015 f *= wnd_const_;
01016 f += fcnt_;
01017 if (f > cwnd_) {
01018 fcnt_ = 0;
01019 ++cwnd_;
01020 } else
01021 fcnt_ = f;
01022 break;
01023 case 5:
01024 f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;
01025 f *= wnd_const_;
01026 f += fcnt_;
01027 if (f > cwnd_) {
01028 fcnt_ = 0;
01029 ++cwnd_;
01030 } else
01031 fcnt_ = f;
01032 break;
01033 case 6:
01034 /* binomial controls */
01035 cwnd_ += increase_num_ / (cwnd_*pow(cwnd_,k_parameter_));
01036 break;
01037 case 8:
01038 /* high-speed TCP */
01039 increment = increase_param();
01040 if ((last_cwnd_action_ == 0 ||
01041 last_cwnd_action_ == CWND_ACTION_TIMEOUT)
01042 && max_ssthresh_ > 0) {
01043 increment = limited_slow_start(cwnd_,
01044 max_ssthresh_, increment);
01045 }
01046 cwnd_ += increment;
01047 break;
01048 default:
01049 #ifdef notdef
01050 /*XXX*/
01051 error("illegal window option %d", wnd_option_);
01052 #endif
01053 abort();
01054 }
01055 }
01056 // if maxcwnd_ is set (nonzero), make it the cwnd limit
01057 if (maxcwnd_ && (int(cwnd_) > maxcwnd_))
01058 cwnd_ = maxcwnd_;
01059
01060 return;
01061 }
|
Here is the call graph for this function:

|
|
Definition at line 652 of file tcp-full.cc. References FullTcpAgent::now(), FullTcpAgent::state_, TCP_NSTATES, TH_ACK, TH_FIN, and TH_SYN. Referenced by FullTcpAgent::foutput(), and FullTcpAgent::send_much().
00653 {
00654 // in real TCP an RST is added in the CLOSED state
00655 static int tcp_outflags[TCP_NSTATES] = {
00656 TH_ACK, /* 0, CLOSED */
00657 0, /* 1, LISTEN */
00658 TH_SYN, /* 2, SYN_SENT */
00659 TH_SYN|TH_ACK, /* 3, SYN_RECEIVED */
00660 TH_ACK, /* 4, ESTABLISHED */
00661 TH_ACK, /* 5, CLOSE_WAIT */
00662 TH_FIN|TH_ACK, /* 6, FIN_WAIT_1 */
00663 TH_FIN|TH_ACK, /* 7, CLOSING */
00664 TH_FIN|TH_ACK, /* 8, LAST_ACK */
00665 TH_ACK, /* 9, FIN_WAIT_2 */
00666 /* 10, TIME_WAIT --- not used in simulator */
00667 };
00668
00669 if (state_ < 0 || (state_ >= TCP_NSTATES)) {
00670 fprintf(stderr, "%f FullTcpAgent(%s): invalid state %d\n",
00671 now(), name(), state_);
00672 return (0x0);
00673 }
00674
00675 return (tcp_outflags[state_]);
00676 }
|
Here is the call graph for this function:

|
||||||||||||
Here is the call graph for this function:

|
|
Reimplemented in NewRenoTcpAsymFsAgent, TcpAsymAgent, TcpRenoAsymAgent, NewRenoTcpAsymAgent, TcpFsAgent, RenoTcpFsAgent, NewRenoTcpFsAgent, and IntTcpAgent. Definition at line 226 of file tcp.h. Referenced by TcpAgent::output(), RFC793eduTcpAgent::output(), and QSNewRenoTcpAgent::output().
00226 { return; }
|
|
|
Definition at line 764 of file tcp-full.cc. References hdr_tcp::access(), hdr_tcp::ackno(), TcpAgent::highest_ack_, and TcpAgent::recover_. Referenced by FullTcpAgent::recv().
00765 {
00766 hdr_tcp *tcph = hdr_tcp::access(pkt);
00767 return (tcph->ackno() >= highest_ack_ &&
00768 tcph->ackno() < recover_);
00769 }
|
Here is the call graph for this function:

|
|
Reimplemented from FullTcpAgent. Definition at line 2754 of file tcp-full.cc. References ReassemblyQueue::cleartonxt(), ReassemblyQueue::empty(), h_seqno_, TcpAgent::highest_ack_, FullTcpAgent::maxseg_, FullTcpAgent::pipe_, sack_min_, and sq_.
02755 {
02756 if (!sq_.empty() && sack_min_ < highest_ack_) {
02757 sack_min_ = highest_ack_;
02758 sq_.cleartonxt();
02759 }
02760 pipe_ -= maxseg_; // see comment in tcp-sack1.cc
02761 if (h_seqno_ < highest_ack_)
02762 h_seqno_ = highest_ack_;
02763 }
|
Here is the call graph for this function:

|
|
Reimplemented in NewRenoTcpAsymFsAgent, TcpFsAgent, NewRenoTcpFsAgent, and NewRenoTcpAgent. Definition at line 231 of file tcp.h.
00231 {};
|
|
|
Definition at line 97 of file agent.h. References Agent::here_, nsaddr_t, and ns_addr_t::port_. Referenced by LmsAgent::pkt2agent(), TcpAsymSink::recv(), MIPBSAgent::recv(), LmsAgent::recv(), HttpInvalAgent::recv(), CtrMcastEncap::recv(), IntTcpAgent::rxmit_last(), IntTcpAgent::send_one(), LmsReceiver::send_refresh(), IcmpAgent::sendredirect(), TcpAgent::trace_event(), TcpAgent::traceAll(), TcpAsymAgent::traceAll(), TcpAgent::traceVar(), TcpSessionAgent::traceVar(), and TcpAsymAgent::traceVar().
|
|
|
Definition at line 1316 of file tcp-full.cc. References hdr_flags::access(), hdr_tcp::access(), TcpAgent::ecn_, hdr_flags::ecnecho(), hdr_tcp::flags(), FullTcpAgent::flags_, TcpAgent::maxseq_, hdr_flags::no_ts_, p1, p2, p3, FullTcpAgent::rcv_nxt_, FullTcpAgent::recent_, hdr_tcp::sa_length(), hdr_tcp::seqno(), FullTcpAgent::state_, TcpAgent::t_seqno_, TCPS_ESTABLISHED, TF_NEEDFIN, TH_ACK, TH_FIN, TH_SYN, hdr_tcp::ts(), and TcpAgent::ts_option_. Referenced by FullTcpAgent::recv().
01317 {
01318 hdr_tcp *tcph = hdr_tcp::access(pkt);
01319 hdr_flags *fh = hdr_flags::access(pkt);
01320
01321 /* not the fastest way to do this, but perhaps clearest */
01322
01323 int p1 = (state_ == TCPS_ESTABLISHED); // ready
01324 int p2 = ((tcph->flags() & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK); // ACK
01325 int p3 = ((flags_ & TF_NEEDFIN) == 0); // don't need fin
01326 int p4 = (!ts_option_ || fh->no_ts_ || (tcph->ts() >= recent_)); // tsok
01327 int p5 = (tcph->seqno() == rcv_nxt_); // in-order data
01328 int p6 = (t_seqno_ == maxseq_); // not re-xmit
01329 int p7 = (!ecn_ || fh->ecnecho() == 0); // no ECN
01330 int p8 = (tcph->sa_length() == 0); // no SACK info
01331
01332 return (p1 && p2 && p3 && p4 && p5 && p6 && p7 && p8);
01333 }
|
Here is the call graph for this function:

|
|
|
|
|
Definition at line 1806 of file tcp.cc. References TcpAgent::dupacks_, TcpAgent::F_counting, TcpAgent::numdupacks_, TcpAgent::RTT_count, and TcpAgent::W_timed. Referenced by TcpAgent::recv().
01807 {
01808 if (F_counting == 1) {
01809 if (seqno >= W_timed) {
01810 RTT_count ++ ;
01811 F_counting = 0 ;
01812 }
01813 else {
01814 if (dupacks_ == numdupacks_)
01815 RTT_count ++ ;
01816 }
01817 }
01818 }
|
|
|
Definition at line 1702 of file tcp.cc. References Scheduler::clock(), CLOSE_CWND_HALF_WAY, TcpAgent::curseq_, CWND_HALF_WITH_MIN, TcpAgent::EnblRTTCtr_, TcpAgent::highest_ack_, Scheduler::instance(), TcpAgent::rtt_counting(), TcpAgent::slowdown(), TcpAgent::T_last, TcpAgent::T_prev, TcpAgent::t_rtxcur_, TcpAgent::t_seqno_, TcpAgent::tcp_tick_, THREE_QUARTER_SSTHRESH, TcpAgent::W_used, and TcpAgent::window(). Referenced by TcpAgent::send_much(), Sack1TcpAgent::send_much(), and TcpAgent::send_one().
01703 {
01704 int tcp_now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);
01705 int rto = (int)(t_rtxcur_/tcp_tick_) ;
01706 /*double ct = Scheduler::instance().clock();*/
01707
01708 if (!EnblRTTCtr_) {
01709 if (tcp_now - T_last >= rto) {
01710 // The sender has been idle.
01711 slowdown(THREE_QUARTER_SSTHRESH) ;
01712 for (int i = 0 ; i < (tcp_now - T_last)/rto; i ++) {
01713 slowdown(CWND_HALF_WITH_MIN);
01714 }
01715 T_prev = tcp_now ;
01716 W_used = 0 ;
01717 }
01718 T_last = tcp_now ;
01719 if (t_seqno_ == highest_ack_+ window()) {
01720 T_prev = tcp_now ;
01721 W_used = 0 ;
01722 }
01723 else if (t_seqno_ == curseq_-1) {
01724 // The sender has no more data to send.
01725 int tmp = t_seqno_ - highest_ack_ ;
01726 if (tmp > W_used)
01727 W_used = tmp ;
01728 if (tcp_now - T_prev >= rto) {
01729 // The sender has been application-limited.
01730 slowdown(THREE_QUARTER_SSTHRESH);
01731 slowdown(CLOSE_CWND_HALF_WAY);
01732 T_prev = tcp_now ;
01733 W_used = 0 ;
01734 }
01735 }
01736 } else {
01737 rtt_counting();
01738 }
01739 }
|
Here is the call graph for this function:

|
|
Reimplemented from FullTcpAgent. Definition at line 2820 of file tcp-full.cc. References ReassemblyQueue::add(), max_sack_blocks_, FullTcpAgent::now(), hdr_tcp::sa_left(), hdr_tcp::sa_length(), hdr_tcp::sa_right(), and sq_.
02821 {
02822 //
02823 // Figure out how many sack blocks are
02824 // in the pkt. Insert each block range
02825 // into the scoreboard
02826 //
02827
02828 if (max_sack_blocks_ <= 0) {
02829 fprintf(stderr,
02830 "%f: FullTcpAgent(%s) warning: received SACK block but I am not SACK enabled\n",
02831 now(), name());
02832 return;
02833 }
02834
02835 int slen = tcph->sa_length(), i;
02836 for (i = 0; i < slen; ++i) {
02837 if (tcph->sa_left(i) >= tcph->sa_right(i)) {
02838 fprintf(stderr,
02839 "%f: FullTcpAgent(%s) warning: received illegal SACK block [%d,%d]\n",
02840 now(), name(), tcph->sa_left(i), tcph->sa_right(i));
02841 continue;
02842 }
02843 sq_.add(tcph->sa_left(i), tcph->sa_right(i), 0);
02844 }
02845
02846 return;
02847 }
|
Here is the call graph for this function:

|
|
Definition at line 1413 of file tcp.cc. References hdr_qs::access(), hdr_tcp::access(), Scheduler::clock(), hdr_qs::flag(), TcpAgent::initial_window(), Scheduler::instance(), TcpAgent::qs_approved_, TcpAgent::qs_requested_, QS_RESPONSE, hdr_qs::rate(), hdr_tcp::ts_echo(), hdr_qs::ttl(), TcpAgent::ttl_diff_, TcpAgent::wnd_init_, and TcpAgent::wnd_init_option_. Referenced by TcpAgent::recv(), Sack1TcpAgent::recv(), RenoTcpAgent::recv(), and NewRenoTcpAgent::recv().
01414 {
01415 // QuickStart code from Srikanth Sundarrajan.
01416 hdr_tcp *tcph = hdr_tcp::access(pkt);
01417 hdr_qs *qsh = hdr_qs::access(pkt);
01418 double now = Scheduler::instance().clock();
01419 int app_rate;
01420
01421 // printf("flag: %d ttl: %d ttl_diff: %d rate: %d\n", qsh->flag(),
01422 // qsh->ttl(), ttl_diff_, qsh->rate());
01423 qs_requested_ = 0;
01424 qs_approved_ = 0;
01425 if (qsh->flag() == QS_RESPONSE && qsh->ttl() == ttl_diff_ &&
01426 qsh->rate() > 0) {
01427 app_rate = (int) (qsh->rate() * (now - tcph->ts_echo())) ;
01428 printf("Quick Start approved, rate %d, window %d\n",
01429 qsh->rate(), app_rate);
01430 if (app_rate > initial_window()) {
01431 wnd_init_option_ = 1;
01432 wnd_init_ = app_rate;
01433 qs_approved_ = 1;
01434 }
01435 } else { // Quick Start rejected
01436 printf("Quick Start rejected\n");
01437 }
01438
01439 }
|
Here is the call graph for this function:

|
|
Definition at line 526 of file tcp-full.cc. References hdr_ip::access(), hdr_cmn::access(), hdr_tcp::access(), hdr_tcp::ackno(), hdr_ip::daddr(), hdr_ip::dport(), hdr_tcp::flags(), FullTcpAgent::flagstr(), hdr_tcp::hlen(), hdr_tcp::reason(), hdr_tcp::sa_length(), hdr_ip::saddr(), hdr_tcp::seqno(), hdr_cmn::size(), hdr_ip::sport(), and hdr_cmn::uid(). Referenced by FullTcpAgent::recv().
00527 {
00528 hdr_tcp *tcph = hdr_tcp::access(pkt); // TCP header
00529 hdr_cmn *th = hdr_cmn::access(pkt); // common header (size, etc)
00530 //hdr_flags *fh = hdr_flags::access(pkt); // flags (CWR, CE, bits)
00531 hdr_ip* iph = hdr_ip::access(pkt);
00532 int datalen = th->size() - tcph->hlen(); // # payload bytes
00533
00534 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",
00535 th->uid(),
00536 iph->saddr(), iph->sport(),
00537 iph->daddr(), iph->dport(),
00538 tcph->hlen(),
00539 datalen,
00540 tcph->seqno(),
00541 tcph->ackno(),
00542 tcph->flags(), flagstr(tcph->flags()),
00543 tcph->sa_length(),
00544 tcph->reason());
00545 }
|
Here is the call graph for this function:

|
|
Reimplemented in CorresHost. Definition at line 1637 of file tcp.cc. References TcpAgent::closecwnd(), CWND_ACTION_ECN, TcpAgent::highest_ack_, TcpAgent::last_cwnd_action_, TcpAgent::maxseq_, and TcpAgent::recover_.
01638 {
01639 if (highest_ack_ >= recover_) {
01640 recover_ = maxseq_;
01641 last_cwnd_action_ = CWND_ACTION_ECN;
01642 closecwnd(how);
01643 }
01644 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 737 of file tcp-full.cc. Referenced by FullTcpAgent::recv().
00738 {
00739 return (seq + dlen + 1);
00740 }
|
|
|
Definition at line 687 of file tcp-full.cc. References abort(), hdr_cmn::access(), hdr_tcp::access(), ReassemblyQueue::add(), ReassemblyQueue::cleartonxt(), hdr_tcp::flags(), hdr_tcp::hlen(), FullTcpAgent::now(), FullTcpAgent::rcv_nxt_, FullTcpAgent::rq_, hdr_tcp::seqno(), hdr_cmn::size(), FullTcpAgent::state_, TCPS_HAVERCVDSYN, TCPS_SYN_RECEIVED, and TH_FIN. Referenced by FullTcpAgent::recv().
00688 {
00689 hdr_tcp *tcph = hdr_tcp::access(pkt);
00690 hdr_cmn *th = hdr_cmn::access(pkt);
00691
00692 int start = tcph->seqno();
00693 int end = start + th->size() - tcph->hlen();
00694 int tiflags = tcph->flags();
00695 int fillshole = (start == rcv_nxt_);
00696 int flags;
00697
00698 // end contains the seq of the last byte of
00699 // in the packet plus one
00700
00701 if (start == end && (tiflags & TH_FIN) == 0) {
00702 fprintf(stderr, "%f: FullTcpAgent(%s)::reass() -- bad condition - adding non-FIN zero-len seg\n",
00703 now(), name());
00704 abort();
00705 }
00706
00707 flags = rq_.add(start, end, tiflags, 0);
00708
00709 //present:
00710 //
00711 // If we've never received a SYN (unlikely)
00712 // or this is an out of order addition, no reason to coalesce
00713 //
00714
00715 if (TCPS_HAVERCVDSYN(state_) == 0 || !fillshole) {
00716 return (0x00);
00717 }
00718 //
00719 // If we get some data in SYN_RECVD, no need to present to user yet
00720 //
00721 if (state_ == TCPS_SYN_RECEIVED && (end > start))
00722 return (0x00);
00723
00724 // clear out data that has been passed, up to rcv_nxt_,
00725 // collects flags
00726
00727 flags |= rq_.cleartonxt();
00728
00729 return (flags);
00730 }
|
Here is the call graph for this function:

|
||||||||||||
|
Reimplemented in CMUTrace. Definition at line 96 of file object.cc. References Packet::free().
00097 {
00098 Packet::free(p);
00099 }
|
Here is the call graph for this function:

|
||||||||||||
|
Reimplemented from TcpAgent. Definition at line 1434 of file tcp-full.cc. References hdr_ip::access(), hdr_flags::access(), hdr_cmn::access(), hdr_tcp::access(), FullTcpAgent::ack_action(), hdr_tcp::ackno(), TcpAgent::cancel_rtx_timer(), FullTcpAgent::cancel_timers(), hdr_flags::ce(), hdr_flags::cong_action(), TcpAgent::curseq_, TcpAgent::cwnd_, hdr_flags::cwr(), FullTcpAgent::delack_interval_, FullTcpAgent::delack_timer_, TcpAgent::delay_growth_, FullTcpAgent::dooptions(), Connector::drop(), FullTcpAgent::dupack_action(), FullTcpAgent::dupack_reset_, TcpAgent::dupacks_, FullTcpAgent::dupseg_fix_, TcpAgent::ecn(), TcpAgent::ecn_, hdr_flags::ecnecho(), hdr_flags::ect(), FullTcpAgent::ect_, ReassemblyQueue::empty(), FullTcpAgent::extra_ack(), FALSE, FullTcpAgent::fastrecov_, Agent::fid_, FullTcpAgent::finish(), hdr_tcp::flags(), FullTcpAgent::flags_, hdr_ip::flowid(), Packet::free(), FullTcpAgent::halfclose_, TcpAgent::highest_ack_, hdr_tcp::hlen(), FullTcpAgent::infinite_send_, TcpAgent::initial_window(), FullTcpAgent::irs_, FullTcpAgent::iss_, FullTcpAgent::last_ack_sent_, FullTcpAgent::last_state_, TcpAgent::maxburst_, FullTcpAgent::maxseg_, TcpAgent::maxseq_, FullTcpAgent::need_send(), FullTcpAgent::newack(), FullTcpAgent::newstate(), hdr_flags::no_ts_, FullTcpAgent::nopredict_, FullTcpAgent::now(), FullTcpAgent::oldack(), FullTcpAgent::open_cwnd_on_pack_, TcpAgent::opencwnd(), FullTcpAgent::pack(), FullTcpAgent::pack_action(), FullTcpAgent::pipe_, FullTcpAgent::predict_ok(), FullTcpAgent::process_sack(), FullTcpAgent::prpkt(), FullTcpAgent::rcv_nxt_, FullTcpAgent::rcvseqinit(), REASON_DUPACK, REASON_NORMAL, FullTcpAgent::reass(), FullTcpAgent::recent_, FullTcpAgent::recent_age_, FullTcpAgent::recent_ce_, Agent::recvBytes(), TimerHandler::resched(), FullTcpAgent::reset(), FullTcpAgent::rq_, TcpAgent::rtt_update(), TcpAgent::rtx_timer_, hdr_tcp::sa_length(), FullTcpAgent::send_much(), FullTcpAgent::sendpacket(), hdr_tcp::seqno(), TcpAgent::set_rtx_timer(), hdr_cmn::size(), FullTcpAgent::state_, TimerHandler::status(), TcpAgent::t_rtt_, TcpAgent::t_seqno_, TCP_PAWS_IDLE, FullTcpAgent::tcprexmtthresh_, TCPS_CLOSE_WAIT, TCPS_CLOSED, TCPS_CLOSING, TCPS_ESTABLISHED, TCPS_FIN_WAIT_1, TCPS_FIN_WAIT_2, TCPS_HAVERCVDFIN, TCPS_LAST_ACK, TCPS_LISTEN, TCPS_SYN_RECEIVED, TCPS_SYN_SENT, TF_ACKNOW, TF_DELACK, TF_NEEDFIN, TH_ACK, TH_FIN, TH_PUSH, TH_SYN, TIMER_PENDING, TRUE, hdr_tcp::ts(), TcpAgent::ts_option_, FullTcpAgent::usrclosed(), and TcpAgent::wnd_.
01435 {
01436 hdr_tcp *tcph = hdr_tcp::access(pkt); // TCP header
01437 hdr_cmn *th = hdr_cmn::access(pkt); // common header (size, etc)
01438 hdr_flags *fh = hdr_flags::access(pkt); // flags (CWR, CE, bits)
01439
01440 int needoutput = FALSE;
01441 int ourfinisacked = FALSE;
01442 int dupseg = FALSE; // recv'd dup data segment
01443 int todrop = 0; // duplicate DATA cnt in seg
01444
01445 last_state_ = state_;
01446
01447 int datalen = th->size() - tcph->hlen(); // # payload bytes
01448 int ackno = tcph->ackno(); // ack # from packet
01449 int tiflags = tcph->flags() ; // tcp flags from packet
01450
01451 //if (state_ != TCPS_ESTABLISHED || (tiflags&(TH_SYN|TH_FIN))) {
01452 //fprintf(stdout, "%f(%s)in state %s recv'd this packet: ", now(), name(), statestr(state_));
01453 //prpkt(pkt);
01454 //}
01455
01456 /*
01457 * Don't expect to see anything while closed
01458 */
01459
01460 if (state_ == TCPS_CLOSED) {
01461 fprintf(stderr, "%f: FullTcp(%s): recv'd pkt in CLOSED state: ",
01462 now(), name());
01463 prpkt(pkt);
01464 goto drop;
01465 }
01466
01467 /*
01468 * Process options if not in LISTEN state,
01469 * else do it below
01470 */
01471
01472 if (state_ != TCPS_LISTEN)
01473 dooptions(pkt);
01474
01475 /*
01476 * if we are using delayed-ACK timers and
01477 * no delayed-ACK timer is set, set one.
01478 * They are set to fire every 'interval_' secs, starting
01479 * at time t0 = (0.0 + k * interval_) for some k such
01480 * that t0 > now
01481 */
01482
01483 if (delack_interval_ > 0.0 &&
01484 (delack_timer_.status() != TIMER_PENDING)) {
01485 int last = int(now() / delack_interval_);
01486 delack_timer_.resched(delack_interval_ * (last + 1.0) - now());
01487 }
01488
01489 /*
01490 * sanity check for ECN: shouldn't be seeing a CE bit if
01491 * ECT wasn't set on the packet first. If we see this, we
01492 * probably have a misbehaving router...
01493 */
01494
01495 if (fh->ce() && !fh->ect()) {
01496 fprintf(stderr,
01497 "%f: FullTcpAgent::recv(%s): warning: CE bit on, but ECT false!\n",
01498 now(), name());
01499 }
01500
01501 /*
01502 * Try header prediction: in seq data or in seq pure ACK
01503 * with no funny business
01504 */
01505
01506 if (!nopredict_ && predict_ok(pkt)) {
01507 /*
01508 * If last ACK falls within this segment's sequence numbers,
01509 * record the timestamp.
01510 * See RFC1323 (now RFC1323 bis)
01511 */
01512 if (ts_option_ && !fh->no_ts_ &&
01513 tcph->seqno() <= last_ack_sent_) {
01514 /*
01515 * this is the case where the ts value is newer than
01516 * the last one we've seen, and the seq # is the one
01517 * we expect [seqno == last_ack_sent_] or older
01518 */
01519 recent_age_ = now();
01520 recent_ = tcph->ts();
01521 }
01522
01523 //
01524 // generate a stream of ecnecho bits until we see a true
01525 // cong_action bit
01526 //
01527 if (ecn_) {
01528 if (fh->ce() && fh->ect()) {
01529 // no CWR from peer yet... arrange to
01530 // keep sending ECNECHO
01531 recent_ce_ = TRUE;
01532 } else if (fh->cwr()) {
01533 // got CWR response from peer.. stop
01534 // sending ECNECHO bits
01535 recent_ce_ = FALSE;
01536 }
01537 }
01538
01539 // Header predication basically looks to see
01540 // if the incoming packet is an expected pure ACK
01541 // or an expected data segment
01542
01543 if (datalen == 0) {
01544 // check for a received pure ACK in the correct range..
01545 // also checks to see if we are wnd_ limited
01546 // (we don't change cwnd at all below), plus
01547 // not being in fast recovery and not a partial ack.
01548 // If we are in fast
01549 // recovery, go below so we can remember to deflate
01550 // the window if we need to
01551 if (ackno > highest_ack_ && ackno < maxseq_ &&
01552 cwnd_ >= wnd_ && !fastrecov_) {
01553 newack(pkt); // update timers, highest_ack_
01554 send_much(0, REASON_NORMAL, maxburst_);
01555 Packet::free(pkt);
01556 return;
01557 }
01558 } else if (ackno == highest_ack_ && rq_.empty()) {
01559 // check for pure incoming segment
01560 // the next data segment we're awaiting, and
01561 // that there's nothing sitting in the reassem-
01562 // bly queue
01563 // give to "application" here
01564 // note: DELACK is inspected only by
01565 // tcp_fasttimo() in real tcp. Every 200 ms
01566 // this routine scans all tcpcb's looking for
01567 // DELACK segments and when it finds them
01568 // changes DELACK to ACKNOW and calls tcp_output()
01569 rcv_nxt_ += datalen;
01570 flags_ |= TF_DELACK;
01571 recvBytes(datalen); // notify application of "delivery"
01572 //
01573 // special code here to simulate the operation
01574 // of a receiver who always consumes data,
01575 // resulting in a call to tcp_output
01576 Packet::free(pkt);
01577 if (need_send())
01578 send_much(1, REASON_NORMAL, maxburst_);
01579 return;
01580 }
01581 } /* header prediction */
01582
01583
01584 //
01585 // header prediction failed
01586 // (e.g. pure ACK out of valid range, SACK present, etc)...
01587 // do slow path processing
01588
01589 //
01590 // the following switch does special things for these states:
01591 // TCPS_LISTEN, TCPS_SYN_SENT
01592 //
01593
01594 switch (state_) {
01595
01596 /*
01597 * If the segment contains an ACK then it is bad and do reset.
01598 * If it does not contain a SYN then it is not interesting; drop it.
01599 * Otherwise initialize tp->rcv_nxt, and tp->irs, iss is already
01600 * selected, and send a segment:
01601 * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
01602 * Initialize tp->snd_nxt to tp->iss.
01603 * Enter SYN_RECEIVED state, and process any other fields of this
01604 * segment in this state.
01605 */
01606
01607 case TCPS_LISTEN: /* awaiting peer's SYN */
01608
01609 if (tiflags & TH_ACK) {
01610 fprintf(stderr,
01611 "%f: FullTcpAgent(%s): warning: recv'd ACK while in LISTEN: ",
01612 now(), name());
01613 prpkt(pkt);
01614 // don't want ACKs in LISTEN
01615 goto dropwithreset;
01616 }
01617 if ((tiflags & TH_SYN) == 0) {
01618 fprintf(stderr,
01619 "%f: FullTcpAgent(%s): warning: recv'd NON-SYN while in LISTEN\n",
01620 now(), name());
01621 prpkt(pkt);
01622 // any non-SYN is discarded
01623 goto drop;
01624 }
01625
01626 /*
01627 * must by a SYN (no ACK) at this point...
01628 * in real tcp we would bump the iss counter here also
01629 */
01630 dooptions(pkt);
01631 irs_ = tcph->seqno();
01632 t_seqno_ = iss_; /* tcp_sendseqinit() macro in real tcp */
01633 rcv_nxt_ = rcvseqinit(irs_, datalen);
01634 flags_ |= TF_ACKNOW;
01635
01636 // check for a ECN-SYN with ECE|CWR
01637 if (ecn_ && fh->ecnecho() && fh->cong_action()) {
01638
01639 ect_ = TRUE;
01640 }
01641
01642
01643 if (fid_ == 0) {
01644 // XXX: sort of hack... If we do not
01645 // have a special flow ID, pick up that
01646 // of the sender (active opener)
01647 hdr_ip* iph = hdr_ip::access(pkt);
01648 fid_ = iph->flowid();
01649 }
01650
01651 newstate(TCPS_SYN_RECEIVED);
01652 goto trimthenstep6;
01653
01654 /*
01655 * If the state is SYN_SENT:
01656 * if seg contains an ACK, but not for our SYN, drop the input.
01657 * if seg does not contain SYN, then drop it.
01658 * Otherwise this is an acceptable SYN segment
01659 * initialize tp->rcv_nxt and tp->irs
01660 * if seg contains ack then advance tp->snd_una
01661 * if SYN has been acked change to ESTABLISHED else SYN_RCVD state
01662 * arrange for segment to be acked (eventually)
01663 * continue processing rest of data/controls, beginning with URG
01664 */
01665
01666 case TCPS_SYN_SENT: /* we sent SYN, expecting SYN+ACK (or SYN) */
01667
01668 /* drop if it's a SYN+ACK and the ack field is bad */
01669 if ((tiflags & TH_ACK) &&
01670 ((ackno <= iss_) || (ackno > maxseq_))) {
01671 // not an ACK for our SYN, discard
01672 fprintf(stderr,
01673 "%f: FullTcpAgent::recv(%s): bad ACK for our SYN: ",
01674 now(), name());
01675 prpkt(pkt);
01676 goto dropwithreset;
01677 }
01678
01679 if ((tiflags & TH_SYN) == 0) {
01680 fprintf(stderr,
01681 "%f: FullTcpAgent::recv(%s): no SYN for our SYN: ",
01682 now(), name());
01683 prpkt(pkt);
01684 goto drop;
01685 }
01686
01687 /* looks like an ok SYN or SYN+ACK */
01688 #ifdef notdef
01689 cancel_rtx_timer(); // cancel timer on our 1st SYN [does this belong!?]
01690 #endif
01691 irs_ = tcph->seqno(); // get initial recv'd seq #
01692 rcv_nxt_ = rcvseqinit(irs_, datalen);
01693
01694 if (tiflags & TH_ACK) {
01695 // SYN+ACK (our SYN was acked)
01696 // CHECKME
01697 // Check ECN-SYN+ACK packet
01698 if (ecn_ && fh->ecnecho() && !fh->cong_action())
01699 ect_ = TRUE;
01700 highest_ack_ = ackno;
01701 cwnd_ = initial_window();
01702
01703 #ifdef notdef
01704 /*
01705 * if we didn't have to retransmit the SYN,
01706 * use its rtt as our initial srtt & rtt var.
01707 */
01708 if (t_rtt_) {
01709 double tao = now() - tcph->ts();
01710 rtt_update(tao);
01711 }
01712 #endif
01713
01714 /*
01715 * if there's data, delay ACK; if there's also a FIN
01716 * ACKNOW will be turned on later.
01717 */
01718 if (datalen > 0) {
01719 flags_ |= TF_DELACK; // data there: wait
01720 } else {
01721 flags_ |= TF_ACKNOW; // ACK peer's SYN
01722 }
01723
01724 /*
01725 * Received <SYN,ACK> in SYN_SENT[*] state.
01726 * Transitions:
01727 * SYN_SENT --> ESTABLISHED
01728 * SYN_SENT* --> FIN_WAIT_1
01729 */
01730
01731 if (flags_ & TF_NEEDFIN) {
01732 newstate(TCPS_FIN_WAIT_1);
01733 flags_ &= ~TF_NEEDFIN;
01734 tiflags &= ~TH_SYN;
01735 } else {
01736 newstate(TCPS_ESTABLISHED);
01737 }
01738
01739 // special to ns:
01740 // generate pure ACK here.
01741 // this simulates the ordinary connection establishment
01742 // where the ACK of the peer's SYN+ACK contains
01743 // no data. This is typically caused by the way
01744 // the connect() socket call works in which the
01745 // entire 3-way handshake occurs prior to the app
01746 // being able to issue a write() [which actually
01747 // causes the segment to be sent].
01748 sendpacket(t_seqno_, rcv_nxt_, TH_ACK, 0, 0);
01749 } else {
01750 // Check ECN-SYN packet
01751 if (ecn_ && fh->ecnecho() && fh->cong_action())
01752 ect_ = TRUE;
01753
01754 // SYN (no ACK) (simultaneous active opens)
01755 flags_ |= TF_ACKNOW;
01756 cancel_rtx_timer();
01757 newstate(TCPS_SYN_RECEIVED);
01758 /*
01759 * decrement t_seqno_: we are sending a
01760 * 2nd SYN (this time in the form of a
01761 * SYN+ACK, so t_seqno_ will have been
01762 * advanced to 2... reduce this
01763 */
01764 t_seqno_--; // CHECKME
01765 }
01766
01767 trimthenstep6:
01768 /*
01769 * advance the seq# to correspond to first data byte
01770 */
01771 tcph->seqno()++;
01772
01773 if (tiflags & TH_ACK)
01774 goto process_ACK;
01775
01776 goto step6;
01777
01778 case TCPS_LAST_ACK:
01779 case TCPS_CLOSING:
01780 break;
01781 } /* end switch(state_) */
01782
01783 /*
01784 * States other than LISTEN or SYN_SENT.
01785 * First check timestamp, if present.
01786 * Then check that at least some bytes of segment are within
01787 * receive window. If segment begins before rcv_nxt,
01788 * drop leading data (and SYN); if nothing left, just ack.
01789 *
01790 * RFC 1323 PAWS: If we have a timestamp reply on this segment
01791 * and it's less than ts_recent, drop it.
01792 */
01793
01794 if (ts_option_ && !fh->no_ts_ && recent_ && tcph->ts() < recent_) {
01795 if ((now() - recent_age_) > TCP_PAWS_IDLE) {
01796 /*
01797 * this is basically impossible in the simulator,
01798 * but here it is...
01799 */
01800 /*
01801 * Invalidate ts_recent. If this segment updates
01802 * ts_recent, the age will be reset later and ts_recent
01803 * will get a valid value. If it does not, setting
01804 * ts_recent to zero will at least satisfy the
01805 * requirement that zero be placed in the timestamp
01806 * echo reply when ts_recent isn't valid. The
01807 * age isn't reset until we get a valid ts_recent
01808 * because we don't want out-of-order segments to be
01809 * dropped when ts_recent is old.
01810 */
01811 recent_ = 0.0;
01812 } else {
01813 fprintf(stderr, "%f: FullTcpAgent(%s): dropped pkt due to bad ts\n",
01814 now(), name());
01815 goto dropafterack;
01816 }
01817 }
01818
01819 // check for redundant data at head/tail of segment
01820 // note that the 4.4bsd [Net/3] code has
01821 // a bug here which can cause us to ignore the
01822 // perfectly good ACKs on duplicate segments. The
01823 // fix is described in (Stevens, Vol2, p. 959-960).
01824 // This code is based on that correction.
01825 //
01826 // In addition, it has a modification so that duplicate segments
01827 // with dup acks don't trigger a fast retransmit when dupseg_fix_
01828 // is enabled.
01829 //
01830 // Yet one more modification: make sure that if the received
01831 // segment had datalen=0 and wasn't a SYN or FIN that
01832 // we don't turn on the ACKNOW status bit. If we were to
01833 // allow ACKNOW to be turned on, normal pure ACKs that happen
01834 // to have seq #s below rcv_nxt can trigger an ACK war by
01835 // forcing us to ACK the pure ACKs
01836 //
01837 // Update: if we have a dataless FIN, don't really want to
01838 // do anything with it. In particular, would like to
01839 // avoid ACKing an incoming FIN+ACK while in CLOSING
01840 //
01841 todrop = rcv_nxt_ - tcph->seqno(); // how much overlap?
01842
01843 if (todrop > 0 && ((tiflags & (TH_SYN)) || datalen > 0)) {
01844 //printf("%f(%s): trim 1..todrop:%d, dlen:%d\n",now(), name(), todrop, datalen);
01845 if (tiflags & TH_SYN) {
01846 tiflags &= ~TH_SYN;
01847 tcph->seqno()++;
01848 th->size()--; // XXX Must decrease packet size too!!
01849 // Q: Why?.. this is only a SYN
01850 todrop--;
01851 }
01852 //
01853 // see Stevens, vol 2, p. 960 for this check;
01854 // this check is to see if we are dropping
01855 // more than this segment (i.e. the whole pkt + a FIN),
01856 // or just the whole packet (no FIN)
01857 //
01858 if ((todrop > datalen) ||
01859 (todrop == datalen && ((tiflags & TH_FIN) == 0))) {
01860 //printf("%f(%s): trim 2..todrop:%d, dlen:%d\n",now(), name(), todrop, datalen);
01861 /*
01862 * Any valid FIN must be to the left of the window.
01863 * At this point the FIN must be a duplicate or out
01864 * of sequence; drop it.
01865 */
01866
01867 tiflags &= ~TH_FIN;
01868
01869 /*
01870 * Send an ACK to resynchronize and drop any data.
01871 * But keep on processing for RST or ACK.
01872 */
01873
01874 flags_ |= TF_ACKNOW;
01875 todrop = datalen;
01876 dupseg = TRUE; // *completely* duplicate
01877
01878 }
01879
01880 /*
01881 * Trim duplicate data from the front of the packet
01882 */
01883
01884 tcph->seqno() += todrop;
01885 th->size() -= todrop; // XXX Must decrease size too!!
01886 // why? [kf]..prob when put in RQ
01887 datalen -= todrop;
01888
01889 } /* data trim */
01890
01891 /*
01892 * If we are doing timstamps and this packet has one, and
01893 * If last ACK falls within this segment's sequence numbers,
01894 * record the timestamp.
01895 * See RFC1323 (now RFC1323 bis)
01896 */
01897 if (ts_option_ && !fh->no_ts_ && tcph->seqno() <= last_ack_sent_) {
01898 /*
01899 * this is the case where the ts value is newer than
01900 * the last one we've seen, and the seq # is the one we expect
01901 * [seqno == last_ack_sent_] or older
01902 */
01903 recent_age_ = now();
01904 recent_ = tcph->ts();
01905 }
01906
01907 if (tiflags & TH_SYN) {
01908 fprintf(stderr,
01909 "%f: FullTcpAgent::recv(%s) received unexpected SYN (state:%d): ",
01910 now(), name(), state_);
01911 prpkt(pkt);
01912 goto dropwithreset;
01913 }
01914
01915 if ((tiflags & TH_ACK) == 0) {
01916 fprintf(stderr, "%f: FullTcpAgent::recv(%s) got packet lacking ACK (state:%d): ",
01917 now(), name(), state_);
01918 prpkt(pkt);
01919 goto drop;
01920 }
01921
01922 /*
01923 * Ack processing.
01924 */
01925
01926 switch (state_) {
01927 case TCPS_SYN_RECEIVED: /* want ACK for our SYN+ACK */
01928 if (ackno < highest_ack_ || ackno > maxseq_) {
01929 // not in useful range
01930 fprintf(stderr,
01931 "%f: FullTcpAgent(%s): ack(%d) not in range while in SYN_RECEIVED: ",
01932 now(), name(), ackno);
01933 prpkt(pkt);
01934 goto dropwithreset;
01935 }
01936 /*
01937 * Make transitions:
01938 * SYN-RECEIVED -> ESTABLISHED
01939 * SYN-RECEIVED* -> FIN-WAIT-1
01940 */
01941 if (flags_ & TF_NEEDFIN) {
01942 newstate(TCPS_FIN_WAIT_1);
01943 flags_ &= ~TF_NEEDFIN;
01944 } else {
01945 newstate(TCPS_ESTABLISHED);
01946 }
01947 cwnd_ = initial_window();
01948 /* fall into ... */
01949
01950 /*
01951 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
01952 * ACKs. If the ack is in the range
01953 * tp->snd_una < ti->ti_ack <= tp->snd_max
01954 * then advance tp->snd_una to ti->ti_ack and drop
01955 * data from the retransmission queue.
01956 *
01957 * note that state TIME_WAIT isn't used
01958 * in the simulator
01959 */
01960
01961 case TCPS_ESTABLISHED:
01962 case TCPS_FIN_WAIT_1:
01963 case TCPS_FIN_WAIT_2:
01964 case TCPS_CLOSE_WAIT:
01965 case TCPS_CLOSING:
01966 case TCPS_LAST_ACK:
01967
01968 //
01969 // look for ECNs in ACKs, react as necessary
01970 //
01971
01972 if (fh->ecnecho() && (!ecn_ || !ect_)) {
01973 fprintf(stderr,
01974 "%f: FullTcp(%s): warning, recvd ecnecho but I am not ECN capable!\n",
01975 now(), name());
01976 }
01977
01978 //
01979 // generate a stream of ecnecho bits until we see a true
01980 // cong_action bit
01981 //
01982 if (ecn_) {
01983 if (fh->ce() && fh->ect())
01984 recent_ce_ = TRUE;
01985 else if (fh->cwr())
01986 recent_ce_ = FALSE;
01987 }
01988
01989 //
01990 // If ESTABLISHED or starting to close, process SACKS
01991 //
01992
01993 if (state_ >= TCPS_ESTABLISHED && tcph->sa_length() > 0) {
01994 process_sack(tcph);
01995 }
01996
01997 //
01998 // ACK indicates packet left the network
01999 // try not to be fooled by data
02000 //
02001
02002 if (fastrecov_ && (datalen == 0 || ackno > highest_ack_))
02003 pipe_ -= maxseg_;
02004
02005 // look for dup ACKs (dup ack numbers, no data)
02006 //
02007 // do fast retransmit/recovery if at/past thresh
02008 if (ackno <= highest_ack_) {
02009 // a pure ACK which doesn't advance highest_ack_
02010 if (datalen == 0 && (!dupseg_fix_ || !dupseg)) {
02011
02012 /*
02013 * If we have outstanding data
02014 * this is a completely
02015 * duplicate ack,
02016 * the ack is the biggest we've
02017 * seen and we've seen exactly our rexmt
02018 * threshhold of them, assume a packet
02019 * has been dropped and retransmit it.
02020 *
02021 * We know we're losing at the current
02022 * window size so do congestion avoidance.
02023 *
02024 * Dup acks mean that packets have left the
02025 * network (they're now cached at the receiver)
02026 * so bump cwnd by the amount in the receiver
02027 * to keep a constant cwnd packets in the
02028 * network.
02029 */
02030
02031 if ((rtx_timer_.status() != TIMER_PENDING) ||
02032 ackno < highest_ack_) {
02033 // Q: significance of timer not pending?
02034 // ACK below highest_ack_
02035 oldack();
02036 } else if (++dupacks_ == tcprexmtthresh_) {
02037 // ACK at highest_ack_ AND meets threshold
02038 //trace_event("FAST_RECOVERY");
02039
02040 dupack_action(); // maybe fast rexmt
02041 goto drop;
02042
02043 } else if (dupacks_ > tcprexmtthresh_) {
02044 // ACK at highest_ack_ AND above threshole
02045 //trace_event("FAST_RECOVERY");
02046 extra_ack();
02047
02048 // send whatever window allows
02049 send_much(0, REASON_DUPACK, maxburst_);
02050 goto drop;
02051 }
02052 } else {
02053 // non zero-length [dataful] segment
02054 // with a dup ack (normal for dataful segs)
02055 // (or window changed in real TCP).
02056 if (dupack_reset_) {
02057 dupacks_ = 0;
02058 fastrecov_ = FALSE;
02059 }
02060 }
02061 break; /* take us to "step6" */
02062 } /* end of dup/old acks */
02063
02064 /*
02065 * we've finished the fast retransmit/recovery period
02066 * (i.e. received an ACK which advances highest_ack_)
02067 * The ACK may be "good" or "partial"
02068 */
02069
02070 process_ACK:
02071
02072 if (ackno > maxseq_) {
02073 // ack more than we sent(!?)
02074 fprintf(stderr,
02075 "%f: FullTcpAgent::recv(%s) too-big ACK (maxseq:%d): ",
02076 now(), name(), int(maxseq_));
02077 prpkt(pkt);
02078 goto dropafterack;
02079 }
02080
02081 /*
02082 * If we have a timestamp reply, update smoothed
02083 * round trip time. If no timestamp is present but
02084 * transmit timer is running and timed sequence
02085 * number was acked, update smoothed round trip time.
02086 * Since we now have an rtt measurement, cancel the
02087 * timer backoff (cf., Phil Karn's retransmit alg.).
02088 * Recompute the initial retransmit timer.
02089 *
02090 * If all outstanding data is acked, stop retransmit
02091 * If there is more data to be acked, restart retransmit
02092 * timer, using current (possibly backed-off) value.
02093 */
02094 newack(pkt); // handle timers, update highest_ack_
02095
02096 /*
02097 * if this is a partial ACK, invoke whatever we should
02098 * note that newack() must be called before the action
02099 * functions, as some of them depend on side-effects
02100 * of newack()
02101 */
02102
02103 int partial = pack(pkt);
02104
02105 if (partial)
02106 pack_action(pkt);
02107 else
02108 ack_action(pkt);
02109
02110 /*
02111 * if this is an ACK with an ECN indication, handle this
02112 * but not if it is a syn packet
02113 */
02114
02115 if (fh->ecnecho() && !(tiflags&TH_SYN) )
02116 if (fh->ecnecho()) {
02117 // Note from Sally: In one-way TCP,
02118 // ecn() is called before newack()...
02119 ecn(highest_ack_); // updated by newack(), above
02120 // "set_rtx_timer();" from T. Kelly.
02121 if (cwnd_ < 1)
02122 set_rtx_timer();
02123 }
02124 // CHECKME: handling of rtx timer
02125 if (ackno == maxseq_) {
02126 needoutput = TRUE;
02127 }
02128
02129 /*
02130 * If no data (only SYN) was ACK'd,
02131 * skip rest of ACK processing.
02132 */
02133 if (ackno == (highest_ack_ + 1))
02134 goto step6;
02135
02136 // if we are delaying initial cwnd growth (probably due to
02137 // large initial windows), then only open cwnd if data has
02138 // been received
02139 // Q: check when this happens
02140 /*
02141 * When new data is acked, open the congestion window.
02142 * If the window gives us less than ssthresh packets
02143 * in flight, open exponentially (maxseg per packet).
02144 * Otherwise open about linearly: maxseg per window
02145 * (maxseg^2 / cwnd per packet).
02146 */
02147 if ((!delay_growth_ || (rcv_nxt_ > 0)) &&
02148 last_state_ == TCPS_ESTABLISHED) {
02149 if (!partial || open_cwnd_on_pack_)
02150 if (!ect_ || !hdr_flags::access(pkt)->ecnecho())
02151 opencwnd();
02152 }
02153
02154 if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {
02155 ourfinisacked = TRUE;
02156 }
02157
02158 //
02159 // special additional processing when our state
02160 // is one of the closing states:
02161 // FIN_WAIT_1, CLOSING, LAST_ACK
02162
02163 switch (state_) {
02164 /*
02165 * In FIN_WAIT_1 STATE in addition to the processing
02166 * for the ESTABLISHED state if our FIN is now acknowledged
02167 * then enter FIN_WAIT_2.
02168 */
02169 case TCPS_FIN_WAIT_1: /* doing active close */
02170 if (ourfinisacked) {
02171 // got the ACK, now await incoming FIN
02172 newstate(TCPS_FIN_WAIT_2);
02173 cancel_timers();
02174 needoutput = FALSE;
02175 }
02176 break;
02177
02178 /*
02179 * In CLOSING STATE in addition to the processing for
02180 * the ESTABLISHED state if the ACK acknowledges our FIN
02181 * then enter the TIME-WAIT state, otherwise ignore
02182 * the segment.
02183 */
02184 case TCPS_CLOSING: /* simultaneous active close */;
02185 if (ourfinisacked) {
02186 newstate(TCPS_CLOSED);
02187 cancel_timers();
02188 }
02189 break;
02190 /*
02191 * In LAST_ACK, we may still be waiting for data to drain
02192 * and/or to be acked, as well as for the ack of our FIN.
02193 * If our FIN is now acknowledged,
02194 * enter the closed state and return.
02195 */
02196 case TCPS_LAST_ACK: /* passive close */
02197 // K: added state change here
02198 if (ourfinisacked) {
02199 newstate(TCPS_CLOSED);
02200 finish(); // cancels timers, erc
02201 reset(); // for connection re-use (bug fix from ns-users list)
02202 goto drop;
02203 } else {
02204 // should be a FIN we've seen
02205 fprintf(stderr,
02206 "%f: FullTcpAgent(%s)::received non-ACK (state:%d): ",
02207 now(), name(), state_);
02208 prpkt(pkt);
02209 }
02210 break;
02211
02212 /* no case for TIME_WAIT in simulator */
02213 } // inner state_ switch (closing states)
02214 } // outer state_ switch (ack processing)
02215
02216 step6:
02217
02218 /*
02219 * Processing of incoming DATAful segments.
02220 * Code above has already trimmed redundant data.
02221 *
02222 * real TCP handles window updates and URG data here also
02223 */
02224
02225 /* dodata: this label is in the "real" code.. here only for reference */
02226
02227 if ((datalen > 0 || (tiflags & TH_FIN)) &&
02228 TCPS_HAVERCVDFIN(state_) == 0) {
02229
02230 //
02231 // the following 'if' implements the "real" TCP
02232 // TCP_REASS macro
02233 //
02234
02235 if (tcph->seqno() == rcv_nxt_ && rq_.empty()) {
02236 // got the in-order packet we were looking
02237 // for, nobody is in the reassembly queue,
02238 // so this is the common case...
02239 // note: in "real" TCP we must also be in
02240 // ESTABLISHED state to come here, because
02241 // data arriving before ESTABLISHED is
02242 // queued in the reassembly queue. Since we
02243 // don't really have a process anyhow, just
02244 // accept the data here as-is (i.e. don't
02245 // require being in ESTABLISHED state)
02246 flags_ |= TF_DELACK;
02247 rcv_nxt_ += datalen;
02248 tiflags = tcph->flags() & TH_FIN;
02249
02250 // give to "application" here
02251 // in "real" TCP, this is sbappend() + sorwakeup()
02252 if (datalen)
02253 recvBytes(datalen); // notify app. of "delivery"
02254 needoutput = need_send();
02255 } else {
02256 // see the "tcp_reass" function:
02257 // not the one we want next (or it
02258 // is but there's stuff on the reass queue);
02259 // do whatever we need to do for out-of-order
02260 // segments or hole-fills. Also,
02261 // send an ACK (or SACK) to the other side right now.
02262 // Note that we may have just a FIN here (datalen = 0)
02263 int rcv_nxt_old_ = rcv_nxt_; // notify app. if changes
02264 tiflags = reass(pkt);
02265 if (rcv_nxt_ > rcv_nxt_old_) {
02266 // if rcv_nxt_ has advanced, must have
02267 // been a hole fill. In this case, there
02268 // is something to give to application
02269 recvBytes(rcv_nxt_ - rcv_nxt_old_);
02270 }
02271 flags_ |= TF_ACKNOW;
02272
02273 if (tiflags & TH_PUSH) {
02274 //
02275 // ???: does this belong here
02276 // K: APPLICATION recv
02277 needoutput = need_send();
02278 }
02279 }
02280 } else {
02281 /*
02282 * we're closing down or this is a pure ACK that
02283 * wasn't handled by the header prediction part above
02284 * (e.g. because cwnd < wnd)
02285 */
02286 // K: this is deleted
02287 tiflags &= ~TH_FIN;
02288 }
02289
02290 /*
02291 * if FIN is received, ACK the FIN
02292 * (let user know if we could do so)
02293 */
02294
02295 if (tiflags & TH_FIN) {
02296 if (TCPS_HAVERCVDFIN(state_) == 0) {
02297 flags_ |= TF_ACKNOW;
02298 rcv_nxt_++;
02299 }
02300 switch (state_) {
02301 /*
02302 * In SYN_RECEIVED and ESTABLISHED STATES
02303 * enter the CLOSE_WAIT state.
02304 * (passive close)
02305 */
02306 case TCPS_SYN_RECEIVED:
02307 case TCPS_ESTABLISHED:
02308 newstate(TCPS_CLOSE_WAIT);
02309 break;
02310
02311 /*
02312 * If still in FIN_WAIT_1 STATE FIN has not been acked so
02313 * enter the CLOSING state.
02314 * (simultaneous close)
02315 */
02316 case TCPS_FIN_WAIT_1:
02317 newstate(TCPS_CLOSING);
02318 break;
02319 /*
02320 * In FIN_WAIT_2 state enter the TIME_WAIT state,
02321 * starting the time-wait timer, turning off the other
02322 * standard timers.
02323 * (in the simulator, just go to CLOSED)
02324 * (completion of active close)
02325 */
02326 case TCPS_FIN_WAIT_2:
02327 newstate(TCPS_CLOSED);
02328 cancel_timers();
02329 break;
02330 }
02331 } /* end of if FIN bit on */
02332
02333 if (needoutput || (flags_ & TF_ACKNOW))
02334 send_much(1, REASON_NORMAL, maxburst_);
02335 else if (curseq_ >= highest_ack_ || infinite_send_)
02336 send_much(0, REASON_NORMAL, maxburst_);
02337 // K: which state to return to when nothing left?
02338
02339 if (!halfclose_ && state_ == TCPS_CLOSE_WAIT && highest_ack_ == maxseq_)
02340 usrclosed();
02341
02342 Packet::free(pkt);
02343
02344 // haoboy: Is here the place for done{} of active close?
02345 // It cannot be put in the switch above because we might need to do
02346 // send_much() (an ACK)
02347 if (state_ == TCPS_CLOSED)
02348 Tcl::instance().evalf("%s done", this->name());
02349
02350 return;
02351
02352 //
02353 // various ways of dropping (some also ACK, some also RST)
02354 //
02355
02356 dropafterack:
02357 flags_ |= TF_ACKNOW;
02358 send_much(1, REASON_NORMAL, maxburst_);
02359 goto drop;
02360
02361 dropwithreset:
02362 /* we should be sending an RST here, but can't in simulator */
02363 if (tiflags & TH_ACK) {
02364 sendpacket(ackno, 0, 0x0, 0, REASON_NORMAL);
02365 } else {
02366 int ack = tcph->seqno() + datalen;
02367 if (tiflags & TH_SYN)
02368 ack--;
02369 sendpacket(0, ack, TH_ACK, 0, REASON_NORMAL);
02370 }
02371 drop:
02372 Packet::free(pkt);
02373 return;
02374 }
|
Here is the call graph for this function:
