A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
tcp-socket-base.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007 Georgia Tech Research Corporation
4  * Copyright (c) 2010 Adrian Sai-wah Tam
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
20  */
21 
22 #define NS_LOG_APPEND_CONTEXT \
23  if (m_node) { std::clog << " [node " << m_node->GetId () << "] "; }
24 
25 #include "ns3/abort.h"
26 #include "ns3/node.h"
27 #include "ns3/inet-socket-address.h"
28 #include "ns3/inet6-socket-address.h"
29 #include "ns3/log.h"
30 #include "ns3/ipv4.h"
31 #include "ns3/ipv6.h"
32 #include "ns3/ipv4-interface-address.h"
33 #include "ns3/ipv4-route.h"
34 #include "ns3/ipv6-route.h"
35 #include "ns3/ipv4-routing-protocol.h"
36 #include "ns3/ipv6-routing-protocol.h"
37 #include "ns3/simulation-singleton.h"
38 #include "ns3/simulator.h"
39 #include "ns3/packet.h"
40 #include "ns3/uinteger.h"
41 #include "ns3/double.h"
42 #include "ns3/pointer.h"
43 #include "ns3/trace-source-accessor.h"
44 #include "tcp-socket-base.h"
45 #include "tcp-l4-protocol.h"
46 #include "ipv4-end-point.h"
47 #include "ipv6-end-point.h"
48 #include "ipv6-l3-protocol.h"
49 #include "tcp-header.h"
50 #include "tcp-option-winscale.h"
51 #include "tcp-option-ts.h"
52 #include "rtt-estimator.h"
53 #include "tcp-congestion-ops.h"
54 
55 #include <math.h>
56 #include <algorithm>
57 
58 namespace ns3 {
59 
60 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase");
61 
62 NS_OBJECT_ENSURE_REGISTERED (TcpSocketBase);
63 
64 TypeId
66 {
67  static TypeId tid = TypeId ("ns3::TcpSocketBase")
68  .SetParent<TcpSocket> ()
69  .SetGroupName ("Internet")
70  .AddConstructor<TcpSocketBase> ()
71 // .AddAttribute ("TcpState", "State in TCP state machine",
72 // TypeId::ATTR_GET,
73 // EnumValue (CLOSED),
74 // MakeEnumAccessor (&TcpSocketBase::m_state),
75 // MakeEnumChecker (CLOSED, "Closed"))
76  .AddAttribute ("MaxSegLifetime",
77  "Maximum segment lifetime in seconds, use for TIME_WAIT state transition to CLOSED state",
78  DoubleValue (120), /* RFC793 says MSL=2 minutes*/
80  MakeDoubleChecker<double> (0))
81  .AddAttribute ("MaxWindowSize", "Max size of advertised window",
82  UintegerValue (65535),
84  MakeUintegerChecker<uint16_t> ())
85  .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
86  CallbackValue (),
89  .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
90  CallbackValue (),
93  .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option",
94  BooleanValue (true),
97  .AddAttribute ("Timestamp", "Enable or disable Timestamp option",
98  BooleanValue (true),
101  .AddAttribute ("MinRto",
102  "Minimum retransmit timeout value",
103  TimeValue (Seconds (1.0)), // RFC 6298 says min RTO=1 sec, but Linux uses 200ms.
104  // See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
107  MakeTimeChecker ())
108  .AddAttribute ("ClockGranularity",
109  "Clock Granularity used in RTO calculations",
110  TimeValue (MilliSeconds (1)), // RFC6298 suggest to use fine clock granularity
113  MakeTimeChecker ())
114  .AddAttribute ("TxBuffer",
115  "TCP Tx buffer",
116  PointerValue (),
118  MakePointerChecker<TcpTxBuffer> ())
119  .AddAttribute ("RxBuffer",
120  "TCP Rx buffer",
121  PointerValue (),
123  MakePointerChecker<TcpRxBuffer> ())
124  .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit",
125  UintegerValue (3),
127  MakeUintegerChecker<uint32_t> ())
128  .AddAttribute ("LimitedTransmit", "Enable limited transmit",
129  BooleanValue (true),
132  .AddTraceSource ("RTO",
133  "Retransmission timeout",
135  "ns3::Time::TracedValueCallback")
136  .AddTraceSource ("RTT",
137  "Last RTT sample",
139  "ns3::Time::TracedValueCallback")
140  .AddTraceSource ("NextTxSequence",
141  "Next sequence number to send (SND.NXT)",
143  "ns3::SequenceNumber32TracedValueCallback")
144  .AddTraceSource ("HighestSequence",
145  "Highest sequence number ever sent in socket's life time",
147  "ns3::SequenceNumber32TracedValueCallback")
148  .AddTraceSource ("State",
149  "TCP state",
151  "ns3::TcpStatesTracedValueCallback")
152  .AddTraceSource ("CongState",
153  "TCP Congestion machine state",
155  "ns3::TcpSocketState::TcpCongStatesTracedValueCallback")
156  .AddTraceSource ("RWND",
157  "Remote side's flow control window",
159  "ns3::TracedValueCallback::Uint32")
160  .AddTraceSource ("BytesInFlight",
161  "Socket estimation of bytes in flight",
163  "ns3::TracedValueCallback::Uint32")
164  .AddTraceSource ("HighestRxSequence",
165  "Highest sequence number received from peer",
167  "ns3::SequenceNumber32TracedValueCallback")
168  .AddTraceSource ("HighestRxAck",
169  "Highest ack received from peer",
171  "ns3::SequenceNumber32TracedValueCallback")
172  .AddTraceSource ("CongestionWindow",
173  "The TCP connection's congestion window",
175  "ns3::TracedValueCallback::Uint32")
176  .AddTraceSource ("SlowStartThreshold",
177  "TCP slow start threshold (bytes)",
179  "ns3::TracedValueCallback::Uint32")
180  .AddTraceSource ("Tx",
181  "Send tcp packet to IP protocol",
183  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
184  .AddTraceSource ("Rx",
185  "Receive tcp packet from IP protocol",
187  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
188  ;
189  return tid;
190 }
191 
192 TypeId
194 {
195  return TcpSocketBase::GetTypeId ();
196 }
197 
198 
199 TypeId
201 {
202  static TypeId tid = TypeId ("ns3::TcpSocketState")
203  .SetParent<Object> ()
204  .SetGroupName ("Internet")
205  .AddConstructor <TcpSocketState> ()
206  .AddTraceSource ("CongestionWindow",
207  "The TCP connection's congestion window",
209  "ns3::TracedValue::Uint32Callback")
210  .AddTraceSource ("SlowStartThreshold",
211  "TCP slow start threshold (bytes)",
213  "ns3::TracedValue::Uint32Callback")
214  .AddTraceSource ("CongState",
215  "TCP Congestion machine state",
217  "ns3::TracedValue::TcpCongStatesTracedValueCallback")
218  .AddTraceSource ("HighestSequence",
219  "Highest sequence number received from peer",
221  "ns3::SequenceNumber32TracedValueCallback")
222  .AddTraceSource ("NextTxSequence",
223  "Next sequence number to send (SND.NXT)",
225  "ns3::SequenceNumber32TracedValueCallback")
226  ;
227  return tid;
228 }
229 
231  : Object (),
232  m_cWnd (0),
233  m_ssThresh (0),
234  m_initialCWnd (0),
235  m_initialSsThresh (0),
236  m_segmentSize (0),
237  m_lastAckedSeq (0),
238  m_congState (CA_OPEN),
239  m_highTxMark (0),
240  // Change m_nextTxSequence for non-zero initial sequence number
241  m_nextTxSequence (0)
242 {
243 }
244 
246  : Object (other),
247  m_cWnd (other.m_cWnd),
248  m_ssThresh (other.m_ssThresh),
249  m_initialCWnd (other.m_initialCWnd),
250  m_initialSsThresh (other.m_initialSsThresh),
251  m_segmentSize (other.m_segmentSize),
252  m_lastAckedSeq (other.m_lastAckedSeq),
253  m_congState (other.m_congState),
254  m_highTxMark (other.m_highTxMark),
255  m_nextTxSequence (other.m_nextTxSequence)
256 {
257 }
258 
259 const char* const
261 {
262  "CA_OPEN", "CA_DISORDER", "CA_CWR", "CA_RECOVERY", "CA_LOSS"
263 };
264 
266  : TcpSocket (),
267  m_retxEvent (),
268  m_lastAckEvent (),
269  m_delAckEvent (),
270  m_persistEvent (),
271  m_timewaitEvent (),
272  m_dupAckCount (0),
273  m_delAckCount (0),
274  m_delAckMaxCount (0),
275  m_noDelay (false),
276  m_synCount (0),
277  m_synRetries (0),
278  m_dataRetrCount (0),
279  m_dataRetries (0),
280  m_rto (Seconds (0.0)),
281  m_minRto (Time::Max ()),
282  m_clockGranularity (Seconds (0.001)),
283  m_lastRtt (Seconds (0.0)),
284  m_delAckTimeout (Seconds (0.0)),
285  m_persistTimeout (Seconds (0.0)),
286  m_cnTimeout (Seconds (0.0)),
287  m_endPoint (0),
288  m_endPoint6 (0),
289  m_node (0),
290  m_tcp (0),
291  m_rtt (0),
292  m_rxBuffer (0),
293  m_txBuffer (0),
294  m_state (CLOSED),
295  m_errno (ERROR_NOTERROR),
296  m_closeNotified (false),
297  m_closeOnEmpty (false),
298  m_shutdownSend (false),
299  m_shutdownRecv (false),
300  m_connected (false),
301  m_msl (0),
302  m_maxWinSize (0),
303  m_rWnd (0),
304  m_highRxMark (0),
305  m_highTxAck (0),
306  m_highRxAckMark (0),
307  m_bytesAckedNotProcessed (0),
308  m_bytesInFlight (0),
309  m_winScalingEnabled (false),
310  m_rcvWindShift (0),
311  m_sndWindShift (0),
312  m_timestampEnabled (true),
313  m_timestampToEcho (0),
314  m_sendPendingDataEvent (),
315  // Set m_recover to the initial sequence number
316  m_recover (0),
317  m_retxThresh (3),
318  m_limitedTx (false),
319  m_retransOut (0),
320  m_congestionControl (0),
321  m_isFirstPartialAck (true)
322 {
323  NS_LOG_FUNCTION (this);
324  m_rxBuffer = CreateObject<TcpRxBuffer> ();
325  m_txBuffer = CreateObject<TcpTxBuffer> ();
326  m_tcb = CreateObject<TcpSocketState> ();
327 
328  bool ok;
329 
330  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
332  NS_ASSERT (ok == true);
333 
334  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
336  NS_ASSERT (ok == true);
337 
338  ok = m_tcb->TraceConnectWithoutContext ("CongState",
340  NS_ASSERT (ok == true);
341 
342  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
344  NS_ASSERT (ok == true);
345 }
346 
348  : TcpSocket (sock),
349  //copy object::m_tid and socket::callbacks
350  m_dupAckCount (sock.m_dupAckCount),
351  m_delAckCount (0),
352  m_delAckMaxCount (sock.m_delAckMaxCount),
353  m_noDelay (sock.m_noDelay),
354  m_synCount (sock.m_synCount),
355  m_synRetries (sock.m_synRetries),
356  m_dataRetrCount (sock.m_dataRetrCount),
357  m_dataRetries (sock.m_dataRetries),
358  m_rto (sock.m_rto),
359  m_minRto (sock.m_minRto),
360  m_clockGranularity (sock.m_clockGranularity),
361  m_lastRtt (sock.m_lastRtt),
362  m_delAckTimeout (sock.m_delAckTimeout),
363  m_persistTimeout (sock.m_persistTimeout),
364  m_cnTimeout (sock.m_cnTimeout),
365  m_endPoint (0),
366  m_endPoint6 (0),
367  m_node (sock.m_node),
368  m_tcp (sock.m_tcp),
369  m_state (sock.m_state),
370  m_errno (sock.m_errno),
371  m_closeNotified (sock.m_closeNotified),
372  m_closeOnEmpty (sock.m_closeOnEmpty),
373  m_shutdownSend (sock.m_shutdownSend),
374  m_shutdownRecv (sock.m_shutdownRecv),
375  m_connected (sock.m_connected),
376  m_msl (sock.m_msl),
377  m_maxWinSize (sock.m_maxWinSize),
378  m_rWnd (sock.m_rWnd),
379  m_highRxMark (sock.m_highRxMark),
380  m_highRxAckMark (sock.m_highRxAckMark),
381  m_bytesAckedNotProcessed (sock.m_bytesAckedNotProcessed),
382  m_bytesInFlight (sock.m_bytesInFlight),
383  m_winScalingEnabled (sock.m_winScalingEnabled),
384  m_rcvWindShift (sock.m_rcvWindShift),
385  m_sndWindShift (sock.m_sndWindShift),
386  m_timestampEnabled (sock.m_timestampEnabled),
387  m_timestampToEcho (sock.m_timestampToEcho),
388  m_recover (sock.m_recover),
389  m_retxThresh (sock.m_retxThresh),
390  m_limitedTx (sock.m_limitedTx),
391  m_retransOut (sock.m_retransOut),
392  m_isFirstPartialAck (sock.m_isFirstPartialAck),
393  m_txTrace (sock.m_txTrace),
394  m_rxTrace (sock.m_rxTrace)
395 {
396  NS_LOG_FUNCTION (this);
397  NS_LOG_LOGIC ("Invoked the copy constructor");
398  // Copy the rtt estimator if it is set
399  if (sock.m_rtt)
400  {
401  m_rtt = sock.m_rtt->Copy ();
402  }
403  // Reset all callbacks to null
404  Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
405  Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr<Socket>, const Address &> ();
406  Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t> ();
407  SetConnectCallback (vPS, vPS);
408  SetDataSentCallback (vPSUI);
409  SetSendCallback (vPSUI);
410  SetRecvCallback (vPS);
413  m_tcb = CopyObject (sock.m_tcb);
414  if (sock.m_congestionControl)
415  {
417  }
418 
419  bool ok;
420 
421  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
423  NS_ASSERT (ok == true);
424 
425  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
427  NS_ASSERT (ok == true);
428 
429  ok = m_tcb->TraceConnectWithoutContext ("CongState",
431  NS_ASSERT (ok == true);
432 
433  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
435 }
436 
438 {
439  NS_LOG_FUNCTION (this);
440  m_node = 0;
441  if (m_endPoint != 0)
442  {
443  NS_ASSERT (m_tcp != 0);
444  /*
445  * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
446  * DestroyCallback is set to TcpSocketBase::Destroy. If we called
447  * m_tcp->DeAllocate, it wil destroy its Ipv4EndpointDemux::DeAllocate,
448  * which in turn destroys my m_endPoint, and in turn invokes
449  * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
450  */
451  NS_ASSERT (m_endPoint != 0);
452  m_tcp->DeAllocate (m_endPoint);
453  NS_ASSERT (m_endPoint == 0);
454  }
455  if (m_endPoint6 != 0)
456  {
457  NS_ASSERT (m_tcp != 0);
458  NS_ASSERT (m_endPoint6 != 0);
459  m_tcp->DeAllocate (m_endPoint6);
460  NS_ASSERT (m_endPoint6 == 0);
461  }
462  m_tcp = 0;
463  CancelAllTimers ();
464 }
465 
466 /* Associate a node with this TCP socket */
467 void
469 {
470  m_node = node;
471 }
472 
473 /* Associate the L4 protocol (e.g. mux/demux) with this socket */
474 void
476 {
477  m_tcp = tcp;
478 }
479 
480 /* Set an RTT estimator with this socket */
481 void
483 {
484  m_rtt = rtt;
485 }
486 
487 /* Inherit from Socket class: Returns error code */
490 {
491  return m_errno;
492 }
493 
494 /* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
497 {
498  return NS3_SOCK_STREAM;
499 }
500 
501 /* Inherit from Socket class: Returns associated node */
502 Ptr<Node>
504 {
506  return m_node;
507 }
508 
509 /* Inherit from Socket class: Bind socket to an end-point in TcpL4Protocol */
510 int
512 {
513  NS_LOG_FUNCTION (this);
514  m_endPoint = m_tcp->Allocate ();
515  if (0 == m_endPoint)
516  {
518  return -1;
519  }
520 
521  m_tcp->AddSocket (this);
522 
523  return SetupCallback ();
524 }
525 
526 int
528 {
529  NS_LOG_FUNCTION (this);
530  m_endPoint6 = m_tcp->Allocate6 ();
531  if (0 == m_endPoint6)
532  {
534  return -1;
535  }
536 
537  m_tcp->AddSocket (this);
538 
539  return SetupCallback ();
540 }
541 
542 /* Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
543 int
545 {
546  NS_LOG_FUNCTION (this << address);
547  if (InetSocketAddress::IsMatchingType (address))
548  {
550  Ipv4Address ipv4 = transport.GetIpv4 ();
551  uint16_t port = transport.GetPort ();
552  if (ipv4 == Ipv4Address::GetAny () && port == 0)
553  {
554  m_endPoint = m_tcp->Allocate ();
555  }
556  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
557  {
558  m_endPoint = m_tcp->Allocate (port);
559  }
560  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
561  {
562  m_endPoint = m_tcp->Allocate (ipv4);
563  }
564  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
565  {
566  m_endPoint = m_tcp->Allocate (ipv4, port);
567  }
568  if (0 == m_endPoint)
569  {
571  return -1;
572  }
573  }
574  else if (Inet6SocketAddress::IsMatchingType (address))
575  {
577  Ipv6Address ipv6 = transport.GetIpv6 ();
578  uint16_t port = transport.GetPort ();
579  if (ipv6 == Ipv6Address::GetAny () && port == 0)
580  {
581  m_endPoint6 = m_tcp->Allocate6 ();
582  }
583  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
584  {
585  m_endPoint6 = m_tcp->Allocate6 (port);
586  }
587  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
588  {
589  m_endPoint6 = m_tcp->Allocate6 (ipv6);
590  }
591  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
592  {
593  m_endPoint6 = m_tcp->Allocate6 (ipv6, port);
594  }
595  if (0 == m_endPoint6)
596  {
598  return -1;
599  }
600  }
601  else
602  {
604  return -1;
605  }
606 
607  m_tcp->AddSocket (this);
608 
609  NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
610 
611  return SetupCallback ();
612 }
613 
614 void
616 {
617  NS_ABORT_MSG_UNLESS ( (m_state == CLOSED) || threshold == m_tcb->m_initialSsThresh,
618  "TcpSocketBase::SetSSThresh() cannot change initial ssThresh after connection started.");
619 
620  m_tcb->m_initialSsThresh = threshold;
621 }
622 
623 uint32_t
625 {
626  return m_tcb->m_initialSsThresh;
627 }
628 
629 void
631 {
632  NS_ABORT_MSG_UNLESS ( (m_state == CLOSED) || cwnd == m_tcb->m_initialCWnd,
633  "TcpSocketBase::SetInitialCwnd() cannot change initial cwnd after connection started.");
634 
635  m_tcb->m_initialCWnd = cwnd;
636 }
637 
638 uint32_t
640 {
641  return m_tcb->m_initialCWnd;
642 }
643 
644 /* Inherit from Socket class: Initiate connection to a remote address:port */
645 int
647 {
648  NS_LOG_FUNCTION (this << address);
649 
650  // If haven't do so, Bind() this socket first
651  if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0)
652  {
653  if (m_endPoint == 0)
654  {
655  if (Bind () == -1)
656  {
657  NS_ASSERT (m_endPoint == 0);
658  return -1; // Bind() failed
659  }
660  NS_ASSERT (m_endPoint != 0);
661  }
663  m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
664  m_endPoint6 = 0;
665 
666  // Get the appropriate local address and port number from the routing protocol and set up endpoint
667  if (SetupEndpoint () != 0)
668  {
669  NS_LOG_ERROR ("Route to destination does not exist ?!");
670  return -1;
671  }
672  }
673  else if (Inet6SocketAddress::IsMatchingType (address) && m_endPoint == 0)
674  {
675  // If we are operating on a v4-mapped address, translate the address to
676  // a v4 address and re-call this function
678  Ipv6Address v6Addr = transport.GetIpv6 ();
679  if (v6Addr.IsIpv4MappedAddress () == true)
680  {
681  Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
682  return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
683  }
684 
685  if (m_endPoint6 == 0)
686  {
687  if (Bind6 () == -1)
688  {
689  NS_ASSERT (m_endPoint6 == 0);
690  return -1; // Bind() failed
691  }
692  NS_ASSERT (m_endPoint6 != 0);
693  }
694  m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
695  m_endPoint = 0;
696 
697  // Get the appropriate local address and port number from the routing protocol and set up endpoint
698  if (SetupEndpoint6 () != 0)
699  { // Route to destination does not exist
700  return -1;
701  }
702  }
703  else
704  {
706  return -1;
707  }
708 
709  // Re-initialize parameters in case this socket is being reused after CLOSE
710  m_rtt->Reset ();
713 
714  // DoConnect() will do state-checking and send a SYN packet
715  return DoConnect ();
716 }
717 
718 /* Inherit from Socket class: Listen on the endpoint for an incoming connection */
719 int
721 {
722  NS_LOG_FUNCTION (this);
723 
724  // Linux quits EINVAL if we're not in CLOSED state, so match what they do
725  if (m_state != CLOSED)
726  {
728  return -1;
729  }
730  // In other cases, set the state to LISTEN and done
731  NS_LOG_DEBUG ("CLOSED -> LISTEN");
732  m_state = LISTEN;
733  return 0;
734 }
735 
736 /* Inherit from Socket class: Kill this socket and signal the peer (if any) */
737 int
739 {
740  NS_LOG_FUNCTION (this);
744  if (m_rxBuffer->Size () != 0)
745  {
746  NS_LOG_WARN ("Socket " << this << " << unread rx data during close. Sending reset." <<
747  "This is probably due to a bad sink application; check its code");
748  SendRST ();
749  return 0;
750  }
751 
752  if (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
753  { // App close with pending data must wait until all data transmitted
754  if (m_closeOnEmpty == false)
755  {
756  m_closeOnEmpty = true;
757  NS_LOG_INFO ("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
758  }
759  return 0;
760  }
761  return DoClose ();
762 }
763 
764 /* Inherit from Socket class: Signal a termination of send */
765 int
767 {
768  NS_LOG_FUNCTION (this);
769 
770  //this prevents data from being added to the buffer
771  m_shutdownSend = true;
772  m_closeOnEmpty = true;
773  //if buffer is already empty, send a fin now
774  //otherwise fin will go when buffer empties.
775  if (m_txBuffer->Size () == 0)
776  {
777  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
778  {
779  NS_LOG_INFO ("Emtpy tx buffer, send fin");
781 
782  if (m_state == ESTABLISHED)
783  { // On active close: I am the first one to send FIN
784  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
786  }
787  else
788  { // On passive close: Peer sent me FIN already
789  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
790  m_state = LAST_ACK;
791  }
792  }
793  }
794 
795  return 0;
796 }
797 
798 /* Inherit from Socket class: Signal a termination of receive */
799 int
801 {
802  NS_LOG_FUNCTION (this);
803  m_shutdownRecv = true;
804  return 0;
805 }
806 
807 /* Inherit from Socket class: Send a packet. Parameter flags is not used.
808  Packet has no TCP header. Invoked by upper-layer application */
809 int
810 TcpSocketBase::Send (Ptr<Packet> p, uint32_t flags)
811 {
812  NS_LOG_FUNCTION (this << p);
813  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Send()");
815  {
816  // Store the packet into Tx buffer
817  if (!m_txBuffer->Add (p))
818  { // TxBuffer overflow, send failed
820  return -1;
821  }
822  if (m_shutdownSend)
823  {
825  return -1;
826  }
827  // Submit the data to lower layers
828  NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpStateName[m_state]);
829  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
830  { // Try to send the data out
832  {
835  this, m_connected);
836  }
837  }
838  return p->GetSize ();
839  }
840  else
841  { // Connection not established yet
843  return -1; // Send failure
844  }
845 }
846 
847 /* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
848 int
850 {
851  return Send (p, flags); // SendTo() and Send() are the same
852 }
853 
854 /* Inherit from Socket class: Return data to upper-layer application. Parameter flags
855  is not used. Data is returned as a packet of size no larger than maxSize */
857 TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
858 {
859  NS_LOG_FUNCTION (this);
860  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()");
861  if (m_rxBuffer->Size () == 0 && m_state == CLOSE_WAIT)
862  {
863  return Create<Packet> (); // Send EOF on connection close
864  }
865  Ptr<Packet> outPacket = m_rxBuffer->Extract (maxSize);
866  return outPacket;
867 }
868 
869 /* Inherit from Socket class: Recv and return the remote's address */
871 TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
872 {
873  NS_LOG_FUNCTION (this << maxSize << flags);
874  Ptr<Packet> packet = Recv (maxSize, flags);
875  // Null packet means no data to read, and an empty packet indicates EOF
876  if (packet != 0 && packet->GetSize () != 0)
877  {
878  if (m_endPoint != 0)
879  {
881  }
882  else if (m_endPoint6 != 0)
883  {
885  }
886  else
887  {
888  fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
889  }
890  }
891  return packet;
892 }
893 
894 /* Inherit from Socket class: Get the max number of bytes an app can send */
895 uint32_t
897 {
898  NS_LOG_FUNCTION (this);
899  return m_txBuffer->Available ();
900 }
901 
902 /* Inherit from Socket class: Get the max number of bytes an app can read */
903 uint32_t
905 {
906  NS_LOG_FUNCTION (this);
907  return m_rxBuffer->Available ();
908 }
909 
910 /* Inherit from Socket class: Return local address:port */
911 int
913 {
914  NS_LOG_FUNCTION (this);
915  if (m_endPoint != 0)
916  {
918  }
919  else if (m_endPoint6 != 0)
920  {
922  }
923  else
924  { // It is possible to call this method on a socket without a name
925  // in which case, behavior is unspecified
926  // Should this return an InetSocketAddress or an Inet6SocketAddress?
927  address = InetSocketAddress (Ipv4Address::GetZero (), 0);
928  }
929  return 0;
930 }
931 
932 int
934 {
935  NS_LOG_FUNCTION (this << address);
936 
937  if (!m_endPoint && !m_endPoint6)
938  {
940  return -1;
941  }
942 
943  if (m_endPoint)
944  {
946  m_endPoint->GetPeerPort ());
947  }
948  else if (m_endPoint6)
949  {
952  }
953  else
954  {
955  NS_ASSERT (false);
956  }
957 
958  return 0;
959 }
960 
961 /* Inherit from Socket class: Bind this socket to the specified NetDevice */
962 void
964 {
965  NS_LOG_FUNCTION (netdevice);
966  Socket::BindToNetDevice (netdevice); // Includes sanity check
967  if (m_endPoint == 0)
968  {
969  if (Bind () == -1)
970  {
971  NS_ASSERT (m_endPoint == 0);
972  return;
973  }
974  NS_ASSERT (m_endPoint != 0);
975  }
976  m_endPoint->BindToNetDevice (netdevice);
977 
978  if (m_endPoint6 == 0)
979  {
980  if (Bind6 () == -1)
981  {
982  NS_ASSERT (m_endPoint6 == 0);
983  return;
984  }
985  NS_ASSERT (m_endPoint6 != 0);
986  }
987  m_endPoint6->BindToNetDevice (netdevice);
988 
989  return;
990 }
991 
992 /* Clean up after Bind. Set up callback functions in the end-point. */
993 int
995 {
996  NS_LOG_FUNCTION (this);
997 
998  if (m_endPoint == 0 && m_endPoint6 == 0)
999  {
1000  return -1;
1001  }
1002  if (m_endPoint != 0)
1003  {
1007  }
1008  if (m_endPoint6 != 0)
1009  {
1013  }
1014 
1015  return 0;
1016 }
1017 
1018 /* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
1019 int
1021 {
1022  NS_LOG_FUNCTION (this);
1023 
1024  // A new connection is allowed only if this socket does not have a connection
1025  if (m_state == CLOSED || m_state == LISTEN || m_state == SYN_SENT || m_state == LAST_ACK || m_state == CLOSE_WAIT)
1026  { // send a SYN packet and change state into SYN_SENT
1028  NS_LOG_DEBUG (TcpStateName[m_state] << " -> SYN_SENT");
1029  m_state = SYN_SENT;
1030  }
1031  else if (m_state != TIME_WAIT)
1032  { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
1033  // exists. We send RST, tear down everything, and close this socket.
1034  SendRST ();
1035  CloseAndNotify ();
1036  }
1037  return 0;
1038 }
1039 
1040 /* Do the action to close the socket. Usually send a packet with appropriate
1041  flags depended on the current m_state. */
1042 int
1044 {
1045  NS_LOG_FUNCTION (this);
1046  switch (m_state)
1047  {
1048  case SYN_RCVD:
1049  case ESTABLISHED:
1050  // send FIN to close the peer
1052  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
1053  m_state = FIN_WAIT_1;
1054  break;
1055  case CLOSE_WAIT:
1056  // send FIN+ACK to close the peer
1058  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
1059  m_state = LAST_ACK;
1060  break;
1061  case SYN_SENT:
1062  case CLOSING:
1063  // Send RST if application closes in SYN_SENT and CLOSING
1064  SendRST ();
1065  CloseAndNotify ();
1066  break;
1067  case LISTEN:
1068  case LAST_ACK:
1069  // In these three states, move to CLOSED and tear down the end point
1070  CloseAndNotify ();
1071  break;
1072  case CLOSED:
1073  case FIN_WAIT_1:
1074  case FIN_WAIT_2:
1075  case TIME_WAIT:
1076  default: /* mute compiler */
1077  // Do nothing in these four states
1078  break;
1079  }
1080  return 0;
1081 }
1082 
1083 /* Peacefully close the socket by notifying the upper layer and deallocate end point */
1084 void
1086 {
1087  NS_LOG_FUNCTION (this);
1088 
1089  if (!m_closeNotified)
1090  {
1091  NotifyNormalClose ();
1092  m_closeNotified = true;
1093  }
1094 
1095  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSED");
1096  m_state = CLOSED;
1097  DeallocateEndPoint ();
1098 }
1099 
1100 
1101 /* Tell if a sequence number range is out side the range that my rx buffer can
1102  accpet */
1103 bool
1105 {
1106  if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
1107  { // Rx buffer in these states are not initialized.
1108  return false;
1109  }
1110  if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
1111  { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
1112  // sequence number must equals to m_rxBuffer->NextRxSequence ()
1113  return (m_rxBuffer->NextRxSequence () != head);
1114  }
1115 
1116  // In all other cases, check if the sequence number is in range
1117  return (tail < m_rxBuffer->NextRxSequence () || m_rxBuffer->MaxRxSequence () <= head);
1118 }
1119 
1120 /* Function called by the L3 protocol when it received a packet to pass on to
1121  the TCP. This function is registered as the "RxCallback" function in
1122  SetupCallback(), which invoked by Bind(), and CompleteFork() */
1123 void
1125  Ptr<Ipv4Interface> incomingInterface)
1126 {
1127  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1128  m_endPoint->GetPeerAddress () <<
1129  ":" << m_endPoint->GetPeerPort () <<
1130  " to " << m_endPoint->GetLocalAddress () <<
1131  ":" << m_endPoint->GetLocalPort ());
1132 
1133  Address fromAddress = InetSocketAddress (header.GetSource (), port);
1134  Address toAddress = InetSocketAddress (header.GetDestination (),
1135  m_endPoint->GetLocalPort ());
1136 
1137  DoForwardUp (packet, fromAddress, toAddress);
1138 }
1139 
1140 void
1142  Ptr<Ipv6Interface> incomingInterface)
1143 {
1144  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1146  ":" << m_endPoint6->GetPeerPort () <<
1147  " to " << m_endPoint6->GetLocalAddress () <<
1148  ":" << m_endPoint6->GetLocalPort ());
1149 
1150  Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port);
1151  Address toAddress = Inet6SocketAddress (header.GetDestinationAddress (),
1153 
1154  DoForwardUp (packet, fromAddress, toAddress);
1155 }
1156 
1157 void
1158 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1159  uint8_t icmpType, uint8_t icmpCode,
1160  uint32_t icmpInfo)
1161 {
1162  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1163  (uint32_t)icmpCode << icmpInfo);
1164  if (!m_icmpCallback.IsNull ())
1165  {
1166  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1167  }
1168 }
1169 
1170 void
1171 TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1172  uint8_t icmpType, uint8_t icmpCode,
1173  uint32_t icmpInfo)
1174 {
1175  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1176  (uint32_t)icmpCode << icmpInfo);
1177  if (!m_icmpCallback6.IsNull ())
1178  {
1179  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1180  }
1181 }
1182 
1183 void
1184 TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress,
1185  const Address &toAddress)
1186 {
1187  // Peel off TCP header and do validity checking
1188  TcpHeader tcpHeader;
1189  uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader);
1190  SequenceNumber32 seq = tcpHeader.GetSequenceNumber ();
1191  if (bytesRemoved == 0 || bytesRemoved > 60)
1192  {
1193  NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid");
1194  return; // Discard invalid packet
1195  }
1196  else if (packet->GetSize () > 0 && OutOfRange (seq, seq + packet->GetSize ()))
1197  {
1198  // Discard fully out of range data packets
1199  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1200  " received packet of seq [" << seq <<
1201  ":" << seq + packet->GetSize () <<
1202  ") out of range [" << m_rxBuffer->NextRxSequence () << ":" <<
1203  m_rxBuffer->MaxRxSequence () << ")");
1204  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
1205  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
1206  {
1208  }
1209  return;
1210  }
1211 
1212  m_rxTrace (packet, tcpHeader, this);
1213 
1214  if (tcpHeader.GetFlags () & TcpHeader::SYN)
1215  {
1216  /* The window field in a segment where the SYN bit is set (i.e., a <SYN>
1217  * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be
1218  * saved anyway..
1219  */
1220  m_rWnd = tcpHeader.GetWindowSize ();
1221 
1223  {
1225  }
1226  else
1227  {
1228  m_winScalingEnabled = false;
1229  }
1230 
1231  // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end
1232  if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled)
1233  {
1235  tcpHeader.GetSequenceNumber ());
1236  }
1237  else
1238  {
1239  m_timestampEnabled = false;
1240  }
1241 
1242  // Initialize cWnd and ssThresh
1243  m_tcb->m_cWnd = GetInitialCwnd () * GetSegSize ();
1244  m_tcb->m_ssThresh = GetInitialSSThresh ();
1245 
1246  if (tcpHeader.GetFlags () & TcpHeader::ACK)
1247  {
1248  EstimateRtt (tcpHeader);
1249  m_highRxAckMark = tcpHeader.GetAckNumber ();
1250  }
1251  }
1252  else if (tcpHeader.GetFlags () & TcpHeader::ACK)
1253  {
1254  NS_ASSERT (!(tcpHeader.GetFlags () & TcpHeader::SYN));
1255  if (m_timestampEnabled)
1256  {
1257  if (!tcpHeader.HasOption (TcpOption::TS))
1258  {
1259  // Ignoring segment without TS, RFC 7323
1260  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1261  " received packet of seq [" << seq <<
1262  ":" << seq + packet->GetSize () <<
1263  ") without TS option. Silently discard it");
1264  return;
1265  }
1266  else
1267  {
1269  tcpHeader.GetSequenceNumber ());
1270  }
1271  }
1272 
1273  EstimateRtt (tcpHeader);
1274  UpdateWindowSize (tcpHeader);
1275  }
1276 
1277 
1278  if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ())
1279  { // Zero window: Enter persist state to send 1 byte to probe
1280  NS_LOG_LOGIC (this << " Enter zerowindow persist state");
1281  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1282  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1283  m_retxEvent.Cancel ();
1284  NS_LOG_LOGIC ("Schedule persist timeout at time " <<
1285  Simulator::Now ().GetSeconds () << " to expire at time " <<
1286  (Simulator::Now () + m_persistTimeout).GetSeconds ());
1289  }
1290 
1291  // TCP state machine code in different process functions
1292  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1293  switch (m_state)
1294  {
1295  case ESTABLISHED:
1296  ProcessEstablished (packet, tcpHeader);
1297  break;
1298  case LISTEN:
1299  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
1300  break;
1301  case TIME_WAIT:
1302  // Do nothing
1303  break;
1304  case CLOSED:
1305  // Send RST if the incoming packet is not a RST
1306  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1307  { // Since m_endPoint is not configured yet, we cannot use SendRST here
1308  TcpHeader h;
1309  Ptr<Packet> p = Create<Packet> ();
1311  h.SetSequenceNumber (m_tcb->m_nextTxSequence);
1312  h.SetAckNumber (m_rxBuffer->NextRxSequence ());
1313  h.SetSourcePort (tcpHeader.GetDestinationPort ());
1314  h.SetDestinationPort (tcpHeader.GetSourcePort ());
1316  AddOptions (h);
1317  m_txTrace (p, h, this);
1318  m_tcp->SendPacket (p, h, toAddress, fromAddress, m_boundnetdevice);
1319  }
1320  break;
1321  case SYN_SENT:
1322  ProcessSynSent (packet, tcpHeader);
1323  break;
1324  case SYN_RCVD:
1325  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1326  break;
1327  case FIN_WAIT_1:
1328  case FIN_WAIT_2:
1329  case CLOSE_WAIT:
1330  ProcessWait (packet, tcpHeader);
1331  break;
1332  case CLOSING:
1333  ProcessClosing (packet, tcpHeader);
1334  break;
1335  case LAST_ACK:
1336  ProcessLastAck (packet, tcpHeader);
1337  break;
1338  default: // mute compiler
1339  break;
1340  }
1341 
1342  if (m_rWnd.Get () != 0 && m_persistEvent.IsRunning ())
1343  { // persist probes end, the other end has increased the window
1345  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
1347 
1348  // Try to send more data, since window has been updated
1350  {
1353  this, m_connected);
1354  }
1355  }
1356 }
1357 
1358 /* Received a packet upon ESTABLISHED state. This function is mimicking the
1359  role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1360 void
1362 {
1363  NS_LOG_FUNCTION (this << tcpHeader);
1364 
1365  // Extract the flags. PSH and URG are not honoured.
1366  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1367 
1368  // Different flags are different events
1369  if (tcpflags == TcpHeader::ACK)
1370  {
1371  if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ())
1372  {
1373  // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be ignored.
1374  // Pag. 72 RFC 793
1375  NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1376  " SND.UNA = " << m_txBuffer->HeadSequence ());
1377 
1378  // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation]
1379  }
1380  else if (tcpHeader.GetAckNumber () > m_tcb->m_highTxMark)
1381  {
1382  // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then
1383  // send an ACK, drop the segment, and return.
1384  // Pag. 72 RFC 793
1385  NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1386  " HighTxMark = " << m_tcb->m_highTxMark);
1387 
1389  }
1390  else
1391  {
1392  // SND.UNA < SEG.ACK =< HighTxMark
1393  // Pag. 72 RFC 793
1394  ReceivedAck (packet, tcpHeader);
1395  }
1396  }
1397  else if (tcpflags == TcpHeader::SYN)
1398  { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1399  // respond with a SYN+ACK. But it is not a legal state transition as of
1400  // RFC793. Thus this is ignored.
1401  }
1402  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1403  { // No action for received SYN+ACK, it is probably a duplicated packet
1404  }
1405  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1406  { // Received FIN or FIN+ACK, bring down this socket nicely
1407  PeerClose (packet, tcpHeader);
1408  }
1409  else if (tcpflags == 0)
1410  { // No flags means there is only data
1411  ReceivedData (packet, tcpHeader);
1412  if (m_rxBuffer->Finished ())
1413  {
1414  PeerClose (packet, tcpHeader);
1415  }
1416  }
1417  else
1418  { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1419  if (tcpflags != TcpHeader::RST)
1420  { // this must be an invalid flag, send reset
1421  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
1422  SendRST ();
1423  }
1424  CloseAndNotify ();
1425  }
1426 }
1427 
1428 /* Process the newly received ACK */
1429 void
1431 {
1432  NS_LOG_FUNCTION (this << tcpHeader);
1433 
1434  NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK));
1435  NS_ASSERT (m_tcb->m_segmentSize > 0);
1436 
1437  SequenceNumber32 ackNumber = tcpHeader.GetAckNumber ();
1438  uint32_t bytesAcked = ackNumber - m_txBuffer->HeadSequence ();
1439  uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
1440  m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize;
1441 
1442  if (m_bytesAckedNotProcessed >= m_tcb->m_segmentSize)
1443  {
1444  segsAcked += 1;
1445  m_bytesAckedNotProcessed -= m_tcb->m_segmentSize;
1446  }
1447 
1448  NS_LOG_LOGIC (" Bytes acked: " << bytesAcked <<
1449  " Segments acked: " << segsAcked <<
1450  " bytes left: " << m_bytesAckedNotProcessed);
1451 
1452  NS_LOG_DEBUG ("ACK of " << ackNumber <<
1453  " SND.UNA=" << m_txBuffer->HeadSequence () <<
1454  " SND.NXT=" << m_tcb->m_nextTxSequence);
1455 
1456  m_tcb->m_lastAckedSeq = ackNumber;
1457 
1458  if (ackNumber == m_txBuffer->HeadSequence ()
1459  && ackNumber < m_tcb->m_nextTxSequence
1460  && packet->GetSize () == 0)
1461  {
1462  // There is a DupAck
1463  ++m_dupAckCount;
1464 
1465  if (m_tcb->m_congState == TcpSocketState::CA_OPEN)
1466  {
1467  // From Open we go Disorder
1468  NS_ASSERT_MSG (m_dupAckCount == 1, "From OPEN->DISORDER but with " <<
1469  m_dupAckCount << " dup ACKs");
1470 
1471  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_DISORDER);
1472  m_tcb->m_congState = TcpSocketState::CA_DISORDER;
1473 
1474  if (m_limitedTx && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
1475  {
1476  // RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit
1477  NS_LOG_INFO ("Limited transmit");
1478  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, m_tcb->m_segmentSize, true);
1479  m_tcb->m_nextTxSequence += sz;
1480  }
1481 
1482  NS_LOG_DEBUG ("OPEN -> DISORDER");
1483  }
1484  else if (m_tcb->m_congState == TcpSocketState::CA_DISORDER)
1485  {
1487  {
1488  // triple duplicate ack triggers fast retransmit (RFC2582 sec.3 bullet #1)
1490  " -> RECOVERY");
1491  m_recover = m_tcb->m_highTxMark;
1492  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_RECOVERY);
1493  m_tcb->m_congState = TcpSocketState::CA_RECOVERY;
1494 
1495  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb,
1496  BytesInFlight ());
1497  m_tcb->m_cWnd = m_tcb->m_ssThresh + m_dupAckCount * m_tcb->m_segmentSize;
1498 
1499  NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." <<
1500  "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
1501  m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover);
1502  DoRetransmit ();
1503  }
1504  else if (m_limitedTx && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
1505  {
1506  // RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit
1507  NS_LOG_INFO ("Limited transmit");
1508  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, m_tcb->m_segmentSize, true);
1509  m_tcb->m_nextTxSequence += sz;
1510  }
1511  }
1512  else if (m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1513  { // Increase cwnd for every additional dupack (RFC2582, sec.3 bullet #3)
1514  m_tcb->m_cWnd += m_tcb->m_segmentSize;
1515  NS_LOG_INFO (m_dupAckCount << " Dupack received in fast recovery mode."
1516  "Increase cwnd to " << m_tcb->m_cWnd);
1518  }
1519 
1520  // Artificially call PktsAcked. After all, one segment has been ACKed.
1521  m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt);
1522  }
1523  else if (ackNumber == m_txBuffer->HeadSequence ()
1524  && ackNumber == m_tcb->m_nextTxSequence)
1525  {
1526  // Dupack, but the ACK is precisely equal to the nextTxSequence
1527  }
1528  else if (ackNumber > m_txBuffer->HeadSequence ())
1529  { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer
1530  bool callCongestionControl = true;
1531  bool resetRTO = true;
1532 
1533  /* The following switch is made because m_dupAckCount can be
1534  * "inflated" through out-of-order segments (e.g. from retransmission,
1535  * while segments have not been lost but are network-reordered). At
1536  * least one segment has been acked; in the luckiest case, an amount
1537  * equals to segsAcked-m_dupAckCount has not been processed.
1538  *
1539  * To be clear: segsAcked will be passed to PktsAcked, and it should take
1540  * in considerations the times that it has been already called, while newSegsAcked
1541  * will be passed to IncreaseCwnd, and it represents the amount of
1542  * segments that are allowed to increase the cWnd value.
1543  */
1544  uint32_t newSegsAcked = segsAcked;
1545  if (segsAcked > m_dupAckCount)
1546  {
1547  segsAcked -= m_dupAckCount;
1548  }
1549  else
1550  {
1551  segsAcked = 1;
1552  }
1553 
1554  if (m_tcb->m_congState == TcpSocketState::CA_OPEN)
1555  {
1556  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1557  }
1558  else if (m_tcb->m_congState == TcpSocketState::CA_DISORDER)
1559  {
1560  // The network reorder packets. Linux changes the counting lost
1561  // packet algorithm from FACK to NewReno. We simply go back in Open.
1562  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1563  m_tcb->m_congState = TcpSocketState::CA_OPEN;
1564  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1565  m_dupAckCount = 0;
1566  m_retransOut = 0;
1567 
1568  NS_LOG_DEBUG ("DISORDER -> OPEN");
1569  }
1570  else if (m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1571  {
1572  if (ackNumber < m_recover)
1573  {
1574  /* Partial ACK.
1575  * In case of partial ACK, retransmit the first unacknowledged
1576  * segment. Deflate the congestion window by the amount of new
1577  * data acknowledged by the Cumulative Acknowledgment field.
1578  * If the partial ACK acknowledges at least one SMSS of new data,
1579  * then add back SMSS bytes to the congestion window.
1580  * This artificially inflates the congestion window in order to
1581  * reflect the additional segment that has left the network.
1582  * Send a new segment if permitted by the new value of cwnd.
1583  * This "partial window deflation" attempts to ensure that, when
1584  * fast recovery eventually ends, approximately ssthresh amount
1585  * of data will be outstanding in the network. Do not exit the
1586  * fast recovery procedure (i.e., if any duplicate ACKs subsequently
1587  * arrive, execute step 4 of Section 3.2 of [RFC5681]).
1588  */
1589  m_tcb->m_cWnd = SafeSubtraction (m_tcb->m_cWnd, bytesAcked);
1590 
1591  if (segsAcked >= 1)
1592  {
1593  m_tcb->m_cWnd += m_tcb->m_segmentSize;
1594  }
1595 
1596  callCongestionControl = false; // No congestion control on cWnd show be invoked
1597  m_dupAckCount = SafeSubtraction (m_dupAckCount, segsAcked); // Update the dupAckCount
1598  m_retransOut = SafeSubtraction (m_retransOut, 1); // at least one retransmission
1599  // has reached the other side
1600  m_txBuffer->DiscardUpTo (ackNumber); //Bug 1850: retransmit before newack
1601  DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
1602 
1603  if (m_isFirstPartialAck)
1604  {
1605  m_isFirstPartialAck = false;
1606  }
1607  else
1608  {
1609  resetRTO = false;
1610  }
1611 
1612  /* This partial ACK acknowledge the fact that one segment has been
1613  * previously lost and now successfully received. All others have
1614  * been processed when they come under the form of dupACKs
1615  */
1616  m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt);
1617 
1618  NS_LOG_INFO ("Partial ACK for seq " << ackNumber <<
1619  " in fast recovery: cwnd set to " << m_tcb->m_cWnd <<
1620  " recover seq: " << m_recover <<
1621  " dupAck count: " << m_dupAckCount);
1622  }
1623  else if (ackNumber >= m_recover)
1624  { // Full ACK (RFC2582 sec.3 bullet #5 paragraph 2, option 1)
1625  m_tcb->m_cWnd = std::min (m_tcb->m_ssThresh.Get (),
1626  BytesInFlight () + m_tcb->m_segmentSize);
1627  m_isFirstPartialAck = true;
1628  m_dupAckCount = 0;
1629  m_retransOut = 0;
1630 
1631  /* This FULL ACK acknowledge the fact that one segment has been
1632  * previously lost and now successfully received. All others have
1633  * been processed when they come under the form of dupACKs,
1634  * except the (maybe) new ACKs which come from a new window
1635  */
1636  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1637  newSegsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
1638  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1639  m_tcb->m_congState = TcpSocketState::CA_OPEN;
1640 
1641  NS_LOG_INFO ("Received full ACK for seq " << ackNumber <<
1642  ". Leaving fast recovery with cwnd set to " << m_tcb->m_cWnd);
1643  NS_LOG_DEBUG ("RECOVERY -> OPEN");
1644  }
1645  }
1646  else if (m_tcb->m_congState == TcpSocketState::CA_LOSS)
1647  {
1648  // Go back in OPEN state
1649  m_isFirstPartialAck = true;
1650  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1651  m_dupAckCount = 0;
1652  m_retransOut = 0;
1653  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1654  m_tcb->m_congState = TcpSocketState::CA_OPEN;
1655  NS_LOG_DEBUG ("LOSS -> OPEN");
1656  }
1657 
1658  if (callCongestionControl)
1659  {
1660  m_congestionControl->IncreaseWindow (m_tcb, newSegsAcked);
1661 
1662  NS_LOG_LOGIC ("Congestion control called: " <<
1663  " cWnd: " << m_tcb->m_cWnd <<
1664  " ssTh: " << m_tcb->m_ssThresh);
1665  }
1666 
1667  // Reset the data retransmission count. We got a new ACK!
1669 
1670  if (m_isFirstPartialAck == false)
1671  {
1672  NS_ASSERT (m_tcb->m_congState == TcpSocketState::CA_RECOVERY);
1673  }
1674 
1675  NewAck (ackNumber, resetRTO);
1676 
1677  // Try to send more data
1679  {
1682  this, m_connected);
1683  }
1684  }
1685 
1686  // If there is any data piggybacked, store it into m_rxBuffer
1687  if (packet->GetSize () > 0)
1688  {
1689  ReceivedData (packet, tcpHeader);
1690  }
1691 }
1692 
1693 /* Received a packet upon LISTEN state. */
1694 void
1696  const Address& fromAddress, const Address& toAddress)
1697 {
1698  NS_LOG_FUNCTION (this << tcpHeader);
1699 
1700  // Extract the flags. PSH and URG are not honoured.
1701  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1702 
1703  // Fork a socket if received a SYN. Do nothing otherwise.
1704  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
1705  if (tcpflags != TcpHeader::SYN)
1706  {
1707  return;
1708  }
1709 
1710  // Call socket's notify function to let the server app know we got a SYN
1711  // If the server app refuses the connection, do nothing
1712  if (!NotifyConnectionRequest (fromAddress))
1713  {
1714  return;
1715  }
1716  // Clone the socket, simulate fork
1717  Ptr<TcpSocketBase> newSock = Fork ();
1718  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
1720  packet, tcpHeader, fromAddress, toAddress);
1721 }
1722 
1723 /* Received a packet upon SYN_SENT */
1724 void
1726 {
1727  NS_LOG_FUNCTION (this << tcpHeader);
1728 
1729  // Extract the flags. PSH and URG are not honoured.
1730  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1731 
1732  if (tcpflags == 0)
1733  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
1734  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
1735  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1736  m_state = ESTABLISHED;
1737  m_connected = true;
1738  m_retxEvent.Cancel ();
1740  ReceivedData (packet, tcpHeader);
1742  }
1743  else if (tcpflags == TcpHeader::ACK)
1744  { // Ignore ACK in SYN_SENT
1745  }
1746  else if (tcpflags == TcpHeader::SYN)
1747  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
1748  NS_LOG_DEBUG ("SYN_SENT -> SYN_RCVD");
1749  m_state = SYN_RCVD;
1751  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1753  }
1754  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK)
1755  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
1756  { // Handshake completed
1757  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
1758  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1759  m_state = ESTABLISHED;
1760  m_connected = true;
1761  m_retxEvent.Cancel ();
1762  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1763  m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence;
1764  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
1768  // Always respond to first data packet to speed up the connection.
1769  // Remove to get the behaviour of old NS-3 code.
1771  }
1772  else
1773  { // Other in-sequence input
1774  if (tcpflags != TcpHeader::RST)
1775  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
1776  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
1777  " received. Reset packet is sent.");
1778  SendRST ();
1779  }
1780  CloseAndNotify ();
1781  }
1782 }
1783 
1784 /* Received a packet upon SYN_RCVD */
1785 void
1787  const Address& fromAddress, const Address& toAddress)
1788 {
1789  NS_LOG_FUNCTION (this << tcpHeader);
1790 
1791  // Extract the flags. PSH and URG are not honoured.
1792  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1793 
1794  if (tcpflags == 0
1795  || (tcpflags == TcpHeader::ACK
1796  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
1797  { // If it is bare data, accept it and move to ESTABLISHED state. This is
1798  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
1799  // handshake is completed nicely.
1800  NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED");
1801  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1802  m_state = ESTABLISHED;
1803  m_connected = true;
1804  m_retxEvent.Cancel ();
1805  m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence;
1806  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
1807  if (m_endPoint)
1808  {
1809  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1810  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1811  }
1812  else if (m_endPoint6)
1813  {
1814  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1815  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1816  }
1817  // Always respond to first data packet to speed up the connection.
1818  // Remove to get the behaviour of old NS-3 code.
1820  ReceivedAck (packet, tcpHeader);
1821  NotifyNewConnectionCreated (this, fromAddress);
1822  // As this connection is established, the socket is available to send data now
1823  if (GetTxAvailable () > 0)
1824  {
1826  }
1827  }
1828  else if (tcpflags == TcpHeader::SYN)
1829  { // Probably the peer lost my SYN+ACK
1830  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1832  }
1833  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1834  {
1835  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
1836  { // In-sequence FIN before connection complete. Set up connection and close.
1837  m_connected = true;
1838  m_retxEvent.Cancel ();
1839  m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence;
1840  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
1841  if (m_endPoint)
1842  {
1843  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1844  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1845  }
1846  else if (m_endPoint6)
1847  {
1848  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1849  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1850  }
1851  PeerClose (packet, tcpHeader);
1852  }
1853  }
1854  else
1855  { // Other in-sequence input
1856  if (tcpflags != TcpHeader::RST)
1857  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
1858  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
1859  " received. Reset packet is sent.");
1860  if (m_endPoint)
1861  {
1862  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1863  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1864  }
1865  else if (m_endPoint6)
1866  {
1867  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1868  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1869  }
1870  SendRST ();
1871  }
1872  CloseAndNotify ();
1873  }
1874 }
1875 
1876 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
1877 void
1879 {
1880  NS_LOG_FUNCTION (this << tcpHeader);
1881 
1882  // Extract the flags. PSH and URG are not honoured.
1883  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1884 
1885  if (packet->GetSize () > 0 && tcpflags != TcpHeader::ACK)
1886  { // Bare data, accept it
1887  ReceivedData (packet, tcpHeader);
1888  }
1889  else if (tcpflags == TcpHeader::ACK)
1890  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
1891  ReceivedAck (packet, tcpHeader);
1892  if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
1893  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
1894  { // This ACK corresponds to the FIN sent
1895  NS_LOG_DEBUG ("FIN_WAIT_1 -> FIN_WAIT_2");
1896  m_state = FIN_WAIT_2;
1897  }
1898  }
1899  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1900  { // Got FIN, respond with ACK and move to next state
1901  if (tcpflags & TcpHeader::ACK)
1902  { // Process the ACK first
1903  ReceivedAck (packet, tcpHeader);
1904  }
1905  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
1906  }
1907  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1908  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
1909  return;
1910  }
1911  else
1912  { // This is a RST or bad flags
1913  if (tcpflags != TcpHeader::RST)
1914  {
1915  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
1916  " received. Reset packet is sent.");
1917  SendRST ();
1918  }
1919  CloseAndNotify ();
1920  return;
1921  }
1922 
1923  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
1924  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_rxBuffer->Finished ())
1925  {
1926  if (m_state == FIN_WAIT_1)
1927  {
1928  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
1929  m_state = CLOSING;
1930  if (m_txBuffer->Size () == 0
1931  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
1932  { // This ACK corresponds to the FIN sent
1933  TimeWait ();
1934  }
1935  }
1936  else if (m_state == FIN_WAIT_2)
1937  {
1938  TimeWait ();
1939  }
1941  if (!m_shutdownRecv)
1942  {
1943  NotifyDataRecv ();
1944  }
1945  }
1946 }
1947 
1948 /* Received a packet upon CLOSING */
1949 void
1951 {
1952  NS_LOG_FUNCTION (this << tcpHeader);
1953 
1954  // Extract the flags. PSH and URG are not honoured.
1955  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1956 
1957  if (tcpflags == TcpHeader::ACK)
1958  {
1959  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
1960  { // This ACK corresponds to the FIN sent
1961  TimeWait ();
1962  }
1963  }
1964  else
1965  { // CLOSING state means simultaneous close, i.e. no one is sending data to
1966  // anyone. If anything other than ACK is received, respond with a reset.
1967  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1968  { // FIN from the peer as well. We can close immediately.
1970  }
1971  else if (tcpflags != TcpHeader::RST)
1972  { // Receive of SYN or SYN+ACK or bad flags or pure data
1973  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
1974  SendRST ();
1975  }
1976  CloseAndNotify ();
1977  }
1978 }
1979 
1980 /* Received a packet upon LAST_ACK */
1981 void
1983 {
1984  NS_LOG_FUNCTION (this << tcpHeader);
1985 
1986  // Extract the flags. PSH and URG are not honoured.
1987  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1988 
1989  if (tcpflags == 0)
1990  {
1991  ReceivedData (packet, tcpHeader);
1992  }
1993  else if (tcpflags == TcpHeader::ACK)
1994  {
1995  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
1996  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
1997  CloseAndNotify ();
1998  }
1999  }
2000  else if (tcpflags == TcpHeader::FIN)
2001  { // Received FIN again, the peer probably lost the FIN+ACK
2003  }
2004  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2005  {
2006  CloseAndNotify ();
2007  }
2008  else
2009  { // Received a SYN or SYN+ACK or bad flags
2010  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2011  SendRST ();
2012  CloseAndNotify ();
2013  }
2014 }
2015 
2016 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
2017 void
2019 {
2020  NS_LOG_FUNCTION (this << tcpHeader);
2021 
2022  // Ignore all out of range packets
2023  if (tcpHeader.GetSequenceNumber () < m_rxBuffer->NextRxSequence ()
2024  || tcpHeader.GetSequenceNumber () > m_rxBuffer->MaxRxSequence ())
2025  {
2026  return;
2027  }
2028  // For any case, remember the FIN position in rx buffer first
2029  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2030  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2031  // If there is any piggybacked data, process it
2032  if (p->GetSize ())
2033  {
2034  ReceivedData (p, tcpHeader);
2035  }
2036  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2037  if (!m_rxBuffer->Finished ())
2038  {
2039  return;
2040  }
2041 
2042  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2043  if (m_state == FIN_WAIT_1)
2044  {
2045  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2046  m_state = CLOSING;
2047  return;
2048  }
2049 
2050  DoPeerClose (); // Change state, respond with ACK
2051 }
2052 
2053 /* Received a in-sequence FIN. Close down this socket. */
2054 void
2056 {
2058 
2059  // Move the state to CLOSE_WAIT
2060  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSE_WAIT");
2061  m_state = CLOSE_WAIT;
2062 
2063  if (!m_closeNotified)
2064  {
2065  // The normal behaviour for an application is that, when the peer sent a in-sequence
2066  // FIN, the app should prepare to close. The app has two choices at this point: either
2067  // respond with ShutdownSend() call to declare that it has nothing more to send and
2068  // the socket can be closed immediately; or remember the peer's close request, wait
2069  // until all its existing data are pushed into the TCP socket, then call Close()
2070  // explicitly.
2071  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
2072  NotifyNormalClose ();
2073  m_closeNotified = true;
2074  }
2075  if (m_shutdownSend)
2076  { // The application declares that it would not sent any more, close this socket
2077  Close ();
2078  }
2079  else
2080  { // Need to ack, the application will close later
2082  }
2083  if (m_state == LAST_ACK)
2084  {
2085  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
2086  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
2088  }
2089 }
2090 
2091 /* Kill this socket. This is a callback function configured to m_endpoint in
2092  SetupCallback(), invoked when the endpoint is destroyed. */
2093 void
2095 {
2096  NS_LOG_FUNCTION (this);
2097  m_endPoint = 0;
2098  if (m_tcp != 0)
2099  {
2100  m_tcp->RemoveSocket (this);
2101  }
2102  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2103  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2104  CancelAllTimers ();
2105 }
2106 
2107 /* Kill this socket. This is a callback function configured to m_endpoint in
2108  SetupCallback(), invoked when the endpoint is destroyed. */
2109 void
2111 {
2112  NS_LOG_FUNCTION (this);
2113  m_endPoint6 = 0;
2114  if (m_tcp != 0)
2115  {
2116  m_tcp->RemoveSocket (this);
2117  }
2118  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2119  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2120  CancelAllTimers ();
2121 }
2122 
2123 /* Send an empty packet with specified TCP flags */
2124 void
2126 {
2127  NS_LOG_FUNCTION (this << (uint32_t)flags);
2128  Ptr<Packet> p = Create<Packet> ();
2129  TcpHeader header;
2130  SequenceNumber32 s = m_tcb->m_nextTxSequence;
2131 
2132  /*
2133  * Add tags for each socket option.
2134  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2135  * if both options are set. Once the packet got to layer three, only
2136  * the corresponding tags will be read.
2137  */
2138  if (IsManualIpTos ())
2139  {
2140  SocketIpTosTag ipTosTag;
2141  ipTosTag.SetTos (GetIpTos ());
2142  p->AddPacketTag (ipTosTag);
2143  }
2144 
2145  if (IsManualIpv6Tclass ())
2146  {
2147  SocketIpv6TclassTag ipTclassTag;
2148  ipTclassTag.SetTclass (GetIpv6Tclass ());
2149  p->AddPacketTag (ipTclassTag);
2150  }
2151 
2152  if (IsManualIpTtl ())
2153  {
2154  SocketIpTtlTag ipTtlTag;
2155  ipTtlTag.SetTtl (GetIpTtl ());
2156  p->AddPacketTag (ipTtlTag);
2157  }
2158 
2159  if (IsManualIpv6HopLimit ())
2160  {
2161  SocketIpv6HopLimitTag ipHopLimitTag;
2162  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
2163  p->AddPacketTag (ipHopLimitTag);
2164  }
2165 
2166  if (m_endPoint == 0 && m_endPoint6 == 0)
2167  {
2168  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
2169  return;
2170  }
2171  if (flags & TcpHeader::FIN)
2172  {
2173  flags |= TcpHeader::ACK;
2174  }
2175  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2176  {
2177  ++s;
2178  }
2179 
2180  header.SetFlags (flags);
2181  header.SetSequenceNumber (s);
2182  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2183  if (m_endPoint != 0)
2184  {
2185  header.SetSourcePort (m_endPoint->GetLocalPort ());
2186  header.SetDestinationPort (m_endPoint->GetPeerPort ());
2187  }
2188  else
2189  {
2190  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2191  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
2192  }
2193  AddOptions (header);
2194 
2195  // RFC 6298, clause 2.4
2196  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2197 
2198  uint16_t windowSize = AdvertisedWindowSize ();
2199  bool hasSyn = flags & TcpHeader::SYN;
2200  bool hasFin = flags & TcpHeader::FIN;
2201  bool isAck = flags == TcpHeader::ACK;
2202  if (hasSyn)
2203  {
2204  if (m_winScalingEnabled)
2205  { // The window scaling option is set only on SYN packets
2206  AddOptionWScale (header);
2207  }
2208 
2209  if (m_synCount == 0)
2210  { // No more connection retries, give up
2211  NS_LOG_LOGIC ("Connection failed.");
2212  m_rtt->Reset (); //According to recommendation -> RFC 6298
2213  CloseAndNotify ();
2214  return;
2215  }
2216  else
2217  { // Exponential backoff of connection time out
2218  int backoffCount = 0x1 << (m_synRetries - m_synCount);
2219  m_rto = m_cnTimeout * backoffCount;
2220  m_synCount--;
2221  }
2222 
2223  if (m_synRetries - 1 == m_synCount)
2224  {
2225  UpdateRttHistory (s, 0, false);
2226  }
2227  else
2228  { // This is SYN retransmission
2229  UpdateRttHistory (s, 0, true);
2230  }
2231 
2232  windowSize = AdvertisedWindowSize (false);
2233  }
2234  header.SetWindowSize (windowSize);
2235 
2236  m_txTrace (p, header, this);
2237 
2238  if (m_endPoint != 0)
2239  {
2240  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2242  }
2243  else
2244  {
2245  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2247  }
2248 
2249  if (flags & TcpHeader::ACK)
2250  { // If sending an ACK, cancel the delay ACK as well
2251  m_delAckEvent.Cancel ();
2252  m_delAckCount = 0;
2253  if (m_highTxAck < header.GetAckNumber ())
2254  {
2255  m_highTxAck = header.GetAckNumber ();
2256  }
2257  }
2258  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
2259  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2260  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
2261  << Simulator::Now ().GetSeconds () << " to expire at time "
2262  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2264  }
2265 }
2266 
2267 /* This function closes the endpoint completely. Called upon RST_TX action. */
2268 void
2270 {
2271  NS_LOG_FUNCTION (this);
2273  NotifyErrorClose ();
2274  DeallocateEndPoint ();
2275 }
2276 
2277 /* Deallocate the end point and cancel all the timers */
2278 void
2280 {
2281  if (m_endPoint != 0)
2282  {
2283  CancelAllTimers ();
2284  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
2285  m_tcp->DeAllocate (m_endPoint);
2286  m_endPoint = 0;
2287  m_tcp->RemoveSocket (this);
2288  }
2289  else if (m_endPoint6 != 0)
2290  {
2291  CancelAllTimers ();
2292  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
2293  m_tcp->DeAllocate (m_endPoint6);
2294  m_endPoint6 = 0;
2295  m_tcp->RemoveSocket (this);
2296  }
2297 }
2298 
2299 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2300 int
2302 {
2303  NS_LOG_FUNCTION (this);
2304  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
2305  NS_ASSERT (ipv4 != 0);
2306  if (ipv4->GetRoutingProtocol () == 0)
2307  {
2308  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
2309  }
2310  // Create a dummy packet, then ask the routing function for the best output
2311  // interface's address
2312  Ipv4Header header;
2314  Socket::SocketErrno errno_;
2315  Ptr<Ipv4Route> route;
2317  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2318  if (route == 0)
2319  {
2320  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
2321  NS_LOG_ERROR (errno_);
2322  m_errno = errno_;
2323  return -1;
2324  }
2325  NS_LOG_LOGIC ("Route exists");
2326  m_endPoint->SetLocalAddress (route->GetSource ());
2327  return 0;
2328 }
2329 
2330 int
2332 {
2333  NS_LOG_FUNCTION (this);
2335  NS_ASSERT (ipv6 != 0);
2336  if (ipv6->GetRoutingProtocol () == 0)
2337  {
2338  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
2339  }
2340  // Create a dummy packet, then ask the routing function for the best output
2341  // interface's address
2342  Ipv6Header header;
2344  Socket::SocketErrno errno_;
2345  Ptr<Ipv6Route> route;
2347  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2348  if (route == 0)
2349  {
2350  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
2351  NS_LOG_ERROR (errno_);
2352  m_errno = errno_;
2353  return -1;
2354  }
2355  NS_LOG_LOGIC ("Route exists");
2356  m_endPoint6->SetLocalAddress (route->GetSource ());
2357  return 0;
2358 }
2359 
2360 /* This function is called only if a SYN received in LISTEN state. After
2361  TcpSocketBase cloned, allocate a new end point to handle the incoming
2362  connection and send a SYN+ACK to complete the handshake. */
2363 void
2365  const Address& fromAddress, const Address& toAddress)
2366 {
2367  // Get port and address from peer (connecting host)
2368  if (InetSocketAddress::IsMatchingType (toAddress))
2369  {
2370  m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
2371  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
2372  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2373  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2374  m_endPoint6 = 0;
2375  }
2376  else if (Inet6SocketAddress::IsMatchingType (toAddress))
2377  {
2378  m_endPoint6 = m_tcp->Allocate6 (Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
2379  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
2380  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2381  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2382  m_endPoint = 0;
2383  }
2384  m_tcp->AddSocket (this);
2385 
2386  // Change the cloned socket from LISTEN state to SYN_RCVD
2387  NS_LOG_DEBUG ("LISTEN -> SYN_RCVD");
2388  m_state = SYN_RCVD;
2391  SetupCallback ();
2392  // Set the sequence number and send SYN+ACK
2393  m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
2394 
2396 }
2397 
2398 void
2400 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
2401  // be called as a scheduled event
2403  // The if-block below was moved from ProcessSynSent() to here because we need
2404  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
2405  // reflect the behaviour in the real world.
2406  if (GetTxAvailable () > 0)
2407  {
2409  }
2410 }
2411 
2412 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
2413  TCP header, and send to TcpL4Protocol */
2414 uint32_t
2415 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
2416 {
2417  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
2418 
2419  bool isRetransmission = false;
2420  if (seq != m_tcb->m_highTxMark)
2421  {
2422  isRetransmission = true;
2423  }
2424 
2425  Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq);
2426  uint32_t sz = p->GetSize (); // Size of packet
2427  uint8_t flags = withAck ? TcpHeader::ACK : 0;
2428  uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
2429 
2430  if (withAck)
2431  {
2432  m_delAckEvent.Cancel ();
2433  m_delAckCount = 0;
2434  }
2435 
2436  /*
2437  * Add tags for each socket option.
2438  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2439  * if both options are set. Once the packet got to layer three, only
2440  * the corresponding tags will be read.
2441  */
2442  if (IsManualIpTos ())
2443  {
2444  SocketIpTosTag ipTosTag;
2445  ipTosTag.SetTos (GetIpTos ());
2446  p->AddPacketTag (ipTosTag);
2447  }
2448 
2449  if (IsManualIpv6Tclass ())
2450  {
2451  SocketIpv6TclassTag ipTclassTag;
2452  ipTclassTag.SetTclass (GetIpv6Tclass ());
2453  p->AddPacketTag (ipTclassTag);
2454  }
2455 
2456  if (IsManualIpTtl ())
2457  {
2458  SocketIpTtlTag ipTtlTag;
2459  ipTtlTag.SetTtl (GetIpTtl ());
2460  p->AddPacketTag (ipTtlTag);
2461  }
2462 
2463  if (IsManualIpv6HopLimit ())
2464  {
2465  SocketIpv6HopLimitTag ipHopLimitTag;
2466  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
2467  p->AddPacketTag (ipHopLimitTag);
2468  }
2469 
2470  if (m_closeOnEmpty && (remainingData == 0))
2471  {
2472  flags |= TcpHeader::FIN;
2473  if (m_state == ESTABLISHED)
2474  { // On active close: I am the first one to send FIN
2475  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
2476  m_state = FIN_WAIT_1;
2477  }
2478  else if (m_state == CLOSE_WAIT)
2479  { // On passive close: Peer sent me FIN already
2480  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
2481  m_state = LAST_ACK;
2482  }
2483  }
2484  TcpHeader header;
2485  header.SetFlags (flags);
2486  header.SetSequenceNumber (seq);
2487  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2488  if (m_endPoint)
2489  {
2490  header.SetSourcePort (m_endPoint->GetLocalPort ());
2492  }
2493  else
2494  {
2495  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2497  }
2498  header.SetWindowSize (AdvertisedWindowSize ());
2499  AddOptions (header);
2500 
2501  if (m_retxEvent.IsExpired ())
2502  {
2503  // Schedules retransmit timeout. If this is a retransmission, double the timer
2504 
2505  if (isRetransmission)
2506  { // This is a retransmit
2507  // RFC 6298, clause 2.5
2508  Time doubledRto = m_rto + m_rto;
2509  m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
2510  }
2511 
2512  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
2513  Simulator::Now ().GetSeconds () << " to expire at time " <<
2514  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
2516  }
2517 
2518  m_txTrace (p, header, this);
2519 
2520  if (m_endPoint)
2521  {
2522  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2524  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
2525  remainingData << " via TcpL4Protocol to " << m_endPoint->GetPeerAddress () <<
2526  ". Header " << header);
2527  }
2528  else
2529  {
2530  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2532  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
2533  remainingData << " via TcpL4Protocol to " << m_endPoint6->GetPeerAddress () <<
2534  ". Header " << header);
2535  }
2536 
2537  UpdateRttHistory (seq, sz, isRetransmission);
2538 
2539  // Notify the application of the data being sent unless this is a retransmit
2540  if (seq + sz > m_tcb->m_highTxMark)
2541  {
2543  (seq + sz - m_tcb->m_highTxMark.Get ()));
2544  }
2545  // Update highTxMark
2546  m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ());
2547  return sz;
2548 }
2549 
2550 void
2552  bool isRetransmission)
2553 {
2554  NS_LOG_FUNCTION (this);
2555 
2556  // update the history of sequence numbers used to calculate the RTT
2557  if (isRetransmission == false)
2558  { // This is the next expected one, just log at end
2559  m_history.push_back (RttHistory (seq, sz, Simulator::Now ()));
2560  }
2561  else
2562  { // This is a retransmit, find in list and mark as re-tx
2563  for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i)
2564  {
2565  if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
2566  { // Found it
2567  i->retx = true;
2568  i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
2569  break;
2570  }
2571  }
2572  }
2573 }
2574 
2575 /* Send as much pending data as possible according to the Tx window. Note that
2576  * this function did not implement the PSH flag
2577  */
2578 bool
2580 {
2581  NS_LOG_FUNCTION (this << withAck);
2582  if (m_txBuffer->Size () == 0)
2583  {
2584  return false; // Nothing to send
2585  }
2586  if (m_endPoint == 0 && m_endPoint6 == 0)
2587  {
2588  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
2589  return false; // Is this the right way to handle this condition?
2590  }
2591  uint32_t nPacketsSent = 0;
2592  while (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence))
2593  {
2594  uint32_t w = AvailableWindow (); // Get available window size
2595  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
2596  if (w < m_tcb->m_segmentSize && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > w)
2597  {
2598  NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
2599  break; // No more
2600  }
2601  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
2602  // in the buffer and the amount of data to send is less than one segment
2603  if (!m_noDelay && UnAckDataCount () > 0
2604  && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) < m_tcb->m_segmentSize)
2605  {
2606  NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send.");
2607  break;
2608  }
2609  NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" <<
2610  " w " << w <<
2611  " rxwin " << m_rWnd <<
2612  " segsize " << m_tcb->m_segmentSize <<
2613  " nextTxSeq " << m_tcb->m_nextTxSequence <<
2614  " highestRxAck " << m_txBuffer->HeadSequence () <<
2615  " pd->Size " << m_txBuffer->Size () <<
2616  " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence));
2617 
2618  NS_LOG_DEBUG ("Window: " << w <<
2619  " cWnd: " << m_tcb->m_cWnd <<
2620  " unAck: " << UnAckDataCount ());
2621 
2622  uint32_t s = std::min (w, m_tcb->m_segmentSize); // Send no more than window
2623  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck);
2624  nPacketsSent++; // Count sent this loop
2625  m_tcb->m_nextTxSequence += sz; // Advance next tx sequence
2626  }
2627  if (nPacketsSent > 0)
2628  {
2629  NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments");
2630  }
2631  return (nPacketsSent > 0);
2632 }
2633 
2634 uint32_t
2636 {
2637  NS_LOG_FUNCTION (this);
2638  return m_tcb->m_nextTxSequence.Get () - m_txBuffer->HeadSequence ();
2639 }
2640 
2641 uint32_t
2643 {
2644  NS_LOG_FUNCTION (this);
2645  // Previous (see bug 1783):
2646  // uint32_t bytesInFlight = m_highTxMark.Get () - m_txBuffer->HeadSequence ();
2647  // RFC 4898 page 23
2648  // PipeSize=SND.NXT-SND.UNA+(retransmits-dupacks)*CurMSS
2649 
2650  // flightSize == UnAckDataCount (), but we avoid the call to save log lines
2651  uint32_t flightSize = m_tcb->m_nextTxSequence.Get () - m_txBuffer->HeadSequence ();
2652  uint32_t duplicatedSize;
2653  uint32_t bytesInFlight;
2654 
2656  {
2657  duplicatedSize = (m_retransOut - m_dupAckCount)*m_tcb->m_segmentSize;
2658  bytesInFlight = flightSize + duplicatedSize;
2659  }
2660  else
2661  {
2662  duplicatedSize = (m_dupAckCount - m_retransOut)*m_tcb->m_segmentSize;
2663  bytesInFlight = duplicatedSize > flightSize ? 0 : flightSize - duplicatedSize;
2664  }
2665 
2666  // m_bytesInFlight is traced; avoid useless assignments which would fire
2667  // fruitlessly the callback
2668  if (m_bytesInFlight != bytesInFlight)
2669  {
2670  m_bytesInFlight = bytesInFlight;
2671  }
2672 
2673  return bytesInFlight;
2674 }
2675 
2676 uint32_t
2678 {
2679  NS_LOG_FUNCTION (this);
2680  return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
2681 }
2682 
2683 uint32_t
2685 {
2687  uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
2688  uint32_t win = Window (); // Number of bytes allowed to be outstanding
2689 
2690  NS_LOG_DEBUG ("UnAckCount=" << unack << ", Win=" << win);
2691  return (win < unack) ? 0 : (win - unack);
2692 }
2693 
2694 uint16_t
2696 {
2697  NS_LOG_FUNCTION (this << scale);
2698  uint32_t w = m_rxBuffer->MaxBufferSize ();
2699 
2700  if (scale)
2701  {
2702  w >>= m_rcvWindShift;
2703  }
2704  if (w > m_maxWinSize)
2705  {
2706  w = m_maxWinSize;
2707  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
2708  }
2709  NS_LOG_DEBUG ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
2710  return static_cast<uint16_t> (w);
2711 }
2712 
2713 // Receipt of new packet, put into Rx buffer
2714 void
2716 {
2717  NS_LOG_FUNCTION (this << tcpHeader);
2718  NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () <<
2719  " pkt size=" << p->GetSize () );
2720 
2721  // Put into Rx buffer
2722  SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence ();
2723  if (!m_rxBuffer->Add (p, tcpHeader))
2724  { // Insert failed: No data or RX buffer full
2726  return;
2727  }
2728  // Now send a new ACK packet acknowledging all received and delivered data
2729  if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
2730  { // A gap exists in the buffer, or we filled a gap: Always ACK
2732  }
2733  else
2734  { // In-sequence packet: ACK if delayed ack count allows
2736  {
2737  m_delAckEvent.Cancel ();
2738  m_delAckCount = 0;
2740  }
2741  else if (m_delAckEvent.IsExpired ())
2742  {
2745  NS_LOG_LOGIC (this << " scheduled delayed ACK at " <<
2746  (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
2747  }
2748  }
2749  // Notify app to receive if necessary
2750  if (expectedSeq < m_rxBuffer->NextRxSequence ())
2751  { // NextRxSeq advanced, we have something to send to the app
2752  if (!m_shutdownRecv)
2753  {
2754  NotifyDataRecv ();
2755  }
2756  // Handle exceptions
2757  if (m_closeNotified)
2758  {
2759  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
2760  }
2761  // If we received FIN before and now completed all "holes" in rx buffer,
2762  // invoke peer close procedure
2763  if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
2764  {
2765  DoPeerClose ();
2766  }
2767  }
2768 }
2769 
2777 void
2779 {
2780  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber ();
2781  Time m = Time (0.0);
2782 
2783  // An ack has been received, calculate rtt and log this measurement
2784  // Note we use a linear search (O(n)) for this since for the common
2785  // case the ack'ed packet will be at the head of the list
2786  if (!m_history.empty ())
2787  {
2788  RttHistory& h = m_history.front ();
2789  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
2790  { // Ok to use this sample
2791  if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
2792  {
2793  Ptr<TcpOptionTS> ts;
2794  ts = DynamicCast<TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
2795  m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
2796  }
2797  else
2798  {
2799  m = Simulator::Now () - h.time; // Elapsed time
2800  }
2801  }
2802  }
2803 
2804  // Now delete all ack history with seq <= ack
2805  while (!m_history.empty ())
2806  {
2807  RttHistory& h = m_history.front ();
2808  if ((h.seq + SequenceNumber32 (h.count)) > ackSeq)
2809  {
2810  break; // Done removing
2811  }
2812  m_history.pop_front (); // Remove
2813  }
2814 
2815  if (!m.IsZero ())
2816  {
2817  m_rtt->Measurement (m); // Log the measurement
2818  // RFC 6298, clause 2.4
2819  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2820  m_lastRtt = m_rtt->GetEstimate ();
2821  NS_LOG_FUNCTION (this << m_lastRtt);
2822  }
2823 }
2824 
2825 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
2826 // when the three-way handshake completed. This cancels retransmission timer
2827 // and advances Tx window
2828 void
2829 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO)
2830 {
2831  NS_LOG_FUNCTION (this << ack);
2832 
2833  if (m_state != SYN_RCVD && resetRTO)
2834  { // Set RTO unless the ACK is received in SYN_RCVD state
2835  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2836  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2837  m_retxEvent.Cancel ();
2838  // On receiving a "New" ack we restart retransmission timer .. RFC 6298
2839  // RFC 6298, clause 2.4
2840  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2841 
2842  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
2843  Simulator::Now ().GetSeconds () << " to expire at time " <<
2844  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2846  }
2847 
2848  // Note the highest ACK and tell app to send more
2849  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
2850  " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
2851  m_txBuffer->DiscardUpTo (ack);
2852  if (GetTxAvailable () > 0)
2853  {
2855  }
2856  if (ack > m_tcb->m_nextTxSequence)
2857  {
2858  m_tcb->m_nextTxSequence = ack; // If advanced
2859  }
2860  if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
2861  { // No retransmit timer if no data to retransmit
2862  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2863  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2864  m_retxEvent.Cancel ();
2865  }
2866 }
2867 
2868 // Retransmit timeout
2869 void
2871 {
2872  NS_LOG_FUNCTION (this);
2873  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
2874  // If erroneous timeout in closed/timed-wait state, just return
2875  if (m_state == CLOSED || m_state == TIME_WAIT)
2876  {
2877  return;
2878  }
2879  // If all data are received (non-closing socket and nothing to send), just return
2880  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark)
2881  {
2882  return;
2883  }
2884 
2885  m_recover = m_tcb->m_highTxMark;
2886  Retransmit ();
2887 }
2888 
2889 void
2891 {
2892  m_delAckCount = 0;
2894 }
2895 
2896 void
2898 {
2899  NS_LOG_FUNCTION (this);
2900 
2902  if (m_state == LAST_ACK)
2903  {
2904  CloseAndNotify ();
2905  }
2906  if (!m_closeNotified)
2907  {
2908  m_closeNotified = true;
2909  }
2910 }
2911 
2912 // Send 1-byte data to probe for the window size at the receiver when
2913 // the local knowledge tells that the receiver has zero window size
2914 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
2915 void
2917 {
2918  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
2919  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
2920  Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence);
2921  TcpHeader tcpHeader;
2922  tcpHeader.SetSequenceNumber (m_tcb->m_nextTxSequence);
2923  tcpHeader.SetAckNumber (m_rxBuffer->NextRxSequence ());
2924  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
2925  if (m_endPoint != 0)
2926  {
2927  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
2928  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
2929  }
2930  else
2931  {
2932  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
2933  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
2934  }
2935  AddOptions (tcpHeader);
2936 
2937  m_txTrace (p, tcpHeader, this);
2938 
2939  if (m_endPoint != 0)
2940  {
2941  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
2943  }
2944  else
2945  {
2946  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
2948  }
2949 
2950  NS_LOG_LOGIC ("Schedule persist timeout at time "
2951  << Simulator::Now ().GetSeconds () << " to expire at time "
2952  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
2954 }
2955 
2956 void
2958 {
2959  // If erroneous timeout in closed/timed-wait state, just return
2960  if (m_state == CLOSED || m_state == TIME_WAIT)
2961  {
2962  return;
2963  }
2964  // If all data are received (non-closing socket and nothing to send), just return
2965  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark)
2966  {
2967  return;
2968  }
2969 
2970  /*
2971  * When a TCP sender detects segment loss using the retransmission timer
2972  * and the given segment has not yet been resent by way of the
2973  * retransmission timer, the value of ssthresh MUST be set to no more
2974  * than the value given in equation (4):
2975  *
2976  * ssthresh = max (FlightSize / 2, 2*SMSS) (4)
2977  *
2978  * where, as discussed above, FlightSize is the amount of outstanding
2979  * data in the network.
2980  *
2981  * On the other hand, when a TCP sender detects segment loss using the
2982  * retransmission timer and the given segment has already been
2983  * retransmitted by way of the retransmission timer at least once, the
2984  * value of ssthresh is held constant.
2985  *
2986  * Conditions to decrement slow - start threshold are as follows:
2987  *
2988  * *) The TCP state should be less than disorder, which is nothing but open.
2989  * If we are entering into the loss state from the open state, we have not yet
2990  * reduced the slow - start threshold for the window of data. (Nat: Recovery?)
2991  * *) If we have entered the loss state with all the data pointed to by high_seq
2992  * acknowledged. Once again it means that in whatever state we are (other than
2993  * open state), all the data from the window that got us into the state, prior to
2994  * retransmission timer expiry, has been acknowledged. (Nat: How this can happen?)
2995  * *) If the above two conditions fail, we still have one more condition that can
2996  * demand reducing the slow - start threshold: If we are already in the loss state
2997  * and have not yet retransmitted anything. The condition may arise in case we
2998  * are not able to retransmit anything because of local congestion.
2999  */
3000 
3001  if (m_tcb->m_congState != TcpSocketState::CA_LOSS)
3002  {
3003  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS);
3004  m_tcb->m_congState = TcpSocketState::CA_LOSS;
3005  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, BytesInFlight ());
3006  m_tcb->m_cWnd = m_tcb->m_segmentSize;
3007  }
3008 
3009  m_tcb->m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack
3010  m_dupAckCount = 0;
3011 
3012  NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
3013  m_tcb->m_ssThresh << ", restart from seqnum " << m_tcb->m_nextTxSequence);
3014  DoRetransmit (); // Retransmit the packet
3015 }
3016 
3017 void
3019 {
3020  NS_LOG_FUNCTION (this);
3021  // Retransmit SYN packet
3022  if (m_state == SYN_SENT)
3023  {
3024  if (m_synCount > 0)
3025  {
3027  }
3028  else
3029  {
3031  }
3032  return;
3033  }
3034 
3035  if (m_dataRetrCount == 0)
3036  {
3037  NS_LOG_INFO ("No more data retries available. Dropping connection");
3038  NotifyErrorClose ();
3039  DeallocateEndPoint ();
3040  return;
3041  }
3042  else
3043  {
3044  --m_dataRetrCount;
3045  }
3046 
3047  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3048  if (m_txBuffer->Size () == 0)
3049  {
3050  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3051  { // Must have lost FIN, re-send
3053  }
3054  return;
3055  }
3056 
3057  // Retransmit a data packet: Call SendDataPacket
3058  uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_tcb->m_segmentSize, true);
3059  ++m_retransOut;
3060 
3061  // In case of RTO, advance m_tcb->m_nextTxSequence
3062  m_tcb->m_nextTxSequence = std::max (m_tcb->m_nextTxSequence.Get (), m_txBuffer->HeadSequence () + sz);
3063 
3064  NS_LOG_DEBUG ("retxing seq " << m_txBuffer->HeadSequence ());
3065 }
3066 
3067 void
3069 {
3070  m_retxEvent.Cancel ();
3072  m_delAckEvent.Cancel ();
3076 }
3077 
3078 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
3079 void
3081 {
3082  NS_LOG_DEBUG (TcpStateName[m_state] << " -> TIME_WAIT");
3083  m_state = TIME_WAIT;
3084  CancelAllTimers ();
3085  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
3086  // according to RFC793, p.28
3089 }
3090 
3091 /* Below are the attribute get/set functions */
3092 
3093 void
3095 {
3096  NS_LOG_FUNCTION (this << size);
3097  m_txBuffer->SetMaxBufferSize (size);
3098 }
3099 
3100 uint32_t
3102 {
3103  return m_txBuffer->MaxBufferSize ();
3104 }
3105 
3106 void
3108 {
3109  NS_LOG_FUNCTION (this << size);
3110  uint32_t oldSize = GetRcvBufSize ();
3111 
3112  m_rxBuffer->SetMaxBufferSize (size);
3113 
3114  /* The size has (manually) increased. Actively inform the other end to prevent
3115  * stale zero-window states.
3116  */
3117  if (oldSize < size && m_connected)
3118  {
3120  }
3121 }
3122 
3123 uint32_t
3125 {
3126  return m_rxBuffer->MaxBufferSize ();
3127 }
3128 
3129 void
3131 {
3132  NS_LOG_FUNCTION (this << size);
3133  m_tcb->m_segmentSize = size;
3134 
3135  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
3136 }
3137 
3138 uint32_t
3140 {
3141  return m_tcb->m_segmentSize;
3142 }
3143 
3144 void
3146 {
3147  NS_LOG_FUNCTION (this << timeout);
3148  m_cnTimeout = timeout;
3149 }
3150 
3151 Time
3153 {
3154  return m_cnTimeout;
3155 }
3156 
3157 void
3159 {
3160  NS_LOG_FUNCTION (this << count);
3161  m_synRetries = count;
3162 }
3163 
3164 uint32_t
3166 {
3167  return m_synRetries;
3168 }
3169 
3170 void
3172 {
3173  NS_LOG_FUNCTION (this << retries);
3174  m_dataRetries = retries;
3175 }
3176 
3177 uint32_t
3179 {
3180  NS_LOG_FUNCTION (this);
3181  return m_dataRetries;
3182 }
3183 
3184 void
3186 {
3187  NS_LOG_FUNCTION (this << timeout);
3189 }
3190 
3191 Time
3193 {
3194  return m_delAckTimeout;
3195 }
3196 
3197 void
3199 {
3200  NS_LOG_FUNCTION (this << count);
3201  m_delAckMaxCount = count;
3202 }
3203 
3204 uint32_t
3206 {
3207  return m_delAckMaxCount;
3208 }
3209 
3210 void
3212 {
3213  NS_LOG_FUNCTION (this << noDelay);
3214  m_noDelay = noDelay;
3215 }
3216 
3217 bool
3219 {
3220  return m_noDelay;
3221 }
3222 
3223 void
3225 {
3226  NS_LOG_FUNCTION (this << timeout);
3228 }
3229 
3230 Time
3232 {
3233  return m_persistTimeout;
3234 }
3235 
3236 bool
3238 {
3239  // Broadcast is not implemented. Return true only if allowBroadcast==false
3240  return (!allowBroadcast);
3241 }
3242 
3243 bool
3245 {
3246  return false;
3247 }
3248 
3249 void
3251 {
3252  NS_LOG_FUNCTION (this << header);
3253 
3254  if (m_timestampEnabled)
3255  {
3256  AddOptionTimestamp (header);
3257  }
3258 }
3259 
3260 void
3262 {
3263  NS_LOG_FUNCTION (this << option);
3264 
3265  Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
3266 
3267  // In naming, we do the contrary of RFC 1323. The received scaling factor
3268  // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
3269  m_sndWindShift = ws->GetScale ();
3270 
3271  if (m_sndWindShift > 14)
3272  {
3273  NS_LOG_WARN ("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
3274  m_sndWindShift = 14;
3275  }
3276 
3277  NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
3278  static_cast<int> (m_sndWindShift));
3279 }
3280 
3281 uint8_t
3283 {
3284  NS_LOG_FUNCTION (this);
3285  uint32_t maxSpace = m_rxBuffer->MaxBufferSize ();
3286  uint8_t scale = 0;
3287 
3288  while (maxSpace > m_maxWinSize)
3289  {
3290  maxSpace = maxSpace >> 1;
3291  ++scale;
3292  }
3293 
3294  if (scale > 14)
3295  {
3296  NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
3297  scale = 14;
3298  }
3299 
3300  NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
3301  static_cast<int> (scale) << " for buffer size " << m_rxBuffer->MaxBufferSize ());
3302  return scale;
3303 }
3304 
3305 void
3307 {
3308  NS_LOG_FUNCTION (this << header);
3309  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
3310 
3311  Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
3312 
3313  // In naming, we do the contrary of RFC 1323. The sended scaling factor
3314  // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
3315 
3317  option->SetScale (m_rcvWindShift);
3318 
3319  header.AppendOption (option);
3320 
3321  NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
3322  static_cast<int> (m_rcvWindShift));
3323 }
3324 
3325 void
3327  const SequenceNumber32 &seq)
3328 {
3329  NS_LOG_FUNCTION (this << option);
3330 
3331  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
3332 
3333  if (seq == m_rxBuffer->NextRxSequence () && seq <= m_highTxAck)
3334  {
3335  m_timestampToEcho = ts->GetTimestamp ();
3336  }
3337 
3338  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
3339  m_timestampToEcho << " and Echo=" << ts->GetEcho ());
3340 }
3341 
3342 void
3344 {
3345  NS_LOG_FUNCTION (this << header);
3346 
3347  Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
3348 
3349  option->SetTimestamp (TcpOptionTS::NowToTsValue ());
3350  option->SetEcho (m_timestampToEcho);
3351 
3352  header.AppendOption (option);
3353  NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
3354  option->GetTimestamp () << " echo=" << m_timestampToEcho);
3355 }
3356 
3358 {
3359  NS_LOG_FUNCTION (this << header);
3360  // If the connection is not established, the window size is always
3361  // updated
3362  uint32_t receivedWindow = header.GetWindowSize ();
3363  receivedWindow <<= m_sndWindShift;
3364  NS_LOG_INFO ("Received (scaled) window is " << receivedWindow << " bytes");
3365  if (m_state < ESTABLISHED)
3366  {
3367  m_rWnd = receivedWindow;
3368  NS_LOG_LOGIC ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
3369  return;
3370  }
3371 
3372  // Test for conditions that allow updating of the window
3373  // 1) segment contains new data (advancing the right edge of the receive
3374  // buffer),
3375  // 2) segment does not contain new data but the segment acks new data
3376  // (highest sequence number acked advances), or
3377  // 3) the advertised window is larger than the current send window
3378  bool update = false;
3379  if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
3380  {
3381  // right edge of the send window is increased (window update)
3382  update = true;
3383  }
3384  if (header.GetAckNumber () > m_highRxAckMark)
3385  {
3386  m_highRxAckMark = header.GetAckNumber ();
3387  update = true;
3388  }
3389  if (header.GetSequenceNumber () > m_highRxMark)
3390  {
3391  m_highRxMark = header.GetSequenceNumber ();
3392  update = true;
3393  }
3394  if (update == true)
3395  {
3396  m_rWnd = receivedWindow;
3397  NS_LOG_LOGIC ("updating rWnd to " << m_rWnd);
3398  }
3399 }
3400 
3401 void
3403 {
3404  NS_LOG_FUNCTION (this << minRto);
3405  m_minRto = minRto;
3406 }
3407 
3408 Time
3410 {
3411  return m_minRto;
3412 }
3413 
3414 void
3416 {
3417  NS_LOG_FUNCTION (this << clockGranularity);
3418  m_clockGranularity = clockGranularity;
3419 }
3420 
3421 Time
3423 {
3424  return m_clockGranularity;
3425 }
3426 
3429 {
3430  return m_txBuffer;
3431 }
3432 
3435 {
3436  return m_rxBuffer;
3437 }
3438 
3439 void
3440 TcpSocketBase::UpdateCwnd (uint32_t oldValue, uint32_t newValue)
3441 {
3442  m_cWndTrace (oldValue, newValue);
3443 }
3444 
3445 void
3446 TcpSocketBase::UpdateSsThresh (uint32_t oldValue, uint32_t newValue)
3447 {
3448  m_ssThTrace (oldValue, newValue);
3449 }
3450 
3451 void
3454 {
3455  m_congStateTrace (oldValue, newValue);
3456 }
3457 
3458 void
3460  SequenceNumber32 newValue)
3461 
3462 {
3463  m_nextTxSequenceTrace (oldValue, newValue);
3464 }
3465 
3466 void
3468 {
3469  m_highTxMarkTrace (oldValue, newValue);
3470 }
3471 
3472 void
3474 {
3475  NS_LOG_FUNCTION (this << algo);
3476  m_congestionControl = algo;
3477 }
3478 
3481 {
3482  return CopyObject<TcpSocketBase> (this);
3483 }
3484 
3485 uint32_t
3486 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b)
3487 {
3488  if (a > b)
3489  {
3490  return a-b;
3491  }
3492 
3493  return 0;
3494 }
3495 
3496 //RttHistory methods
3498  : seq (s),
3499  count (c),
3500  time (t),
3501  retx (false)
3502 {
3503 }
3504 
3506  : seq (h.seq),
3507  count (h.count),
3508  time (h.time),
3509  retx (h.retx)
3510 {
3511 }
3512 
3513 } // namespace ns3
TracedCallback< SequenceNumber32, SequenceNumber32 > m_highTxMarkTrace
Callback pointer for high tx mark chaining.
void SetCongestionControlAlgorithm(Ptr< TcpCongestionOps > algo)
Install a congestion control algorithm on this socket.
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:232
Ipv6Address GetLocalAddress()
Get the local address.
void PeerClose(Ptr< Packet > p, const TcpHeader &tcpHeader)
Received a FIN from peer, notify rx buffer.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
TracedValue< uint32_t > m_bytesInFlight
Bytes in flight.
Custom version of log2() to deal with Bug 1467.
void SetTclass(uint8_t tclass)
Set the tag's Tclass.
Definition: socket.cc:793
static std::string FlagsToString(uint8_t flags, const std::string &delimiter="|")
Converts an integer into a human readable list of Tcp flags.
Definition: tcp-header.cc:55
bool m_limitedTx
perform limited transmit
void ProcessListen(Ptr< Packet > packet, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Received a packet upon LISTEN state.
virtual void SetInitialCwnd(uint32_t cwnd)
Set the initial Congestion Window.
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
virtual int Listen(void)
Listen for incoming connections.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
bool IsManualIpTtl(void) const
Checks if the socket has a specific IPv4 TTL set.
Definition: socket.cc:383
Introspection did not find any typical Config paths.
Definition: ipv6-header.h:33
an Inet address class
virtual int GetSockName(Address &address) const
Get socket address.
Ipv4Address GetIpv4(void) const
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
static Ipv4Address GetAny(void)
virtual uint32_t Window(void) const
Return the max possible number of unacked bytes.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void ProcessWait(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon CLOSE_WAIT, FIN_WAIT_1, FIN_WAIT_2.
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
Normal state, no dubious events.
uint32_t m_dataRetries
Number of data retransmission attempts.
Connection established.
Definition: tcp-socket.h:70
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
virtual void SetInitialSSThresh(uint32_t threshold)
Set the initial Slow Start Threshold.
AttributeValue implementation for Boolean.
Definition: boolean.h:34
virtual uint8_t GetIpTtl(void) const
Query the value of IP Time to Live field of this socket.
Definition: socket.cc:471
Callback template class.
Definition: callback.h:1176
bool m_noDelay
Set to true to disable Nagle's algorithm.
virtual uint32_t GetSegSize(void) const
Get the segment size.
CWND was reduced, we are fast-retransmitting.
In all the respects it is "Open", but requires a bit more attention.
Time GetClockGranularity(void) const
Get the Clock Granularity (used in RTO calcs).
uint8_t GetIpTos(void) const
Query the value of IP Type of Service of this socket.
Definition: socket.cc:404
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer...
Definition: socket.h:1053
uint32_t SendDataPacket(SequenceNumber32 seq, uint32_t maxSize, bool withAck)
Extract at most maxSize bytes from the TxBuffer at sequence seq, add the TCP header, and send to TcpL4Protocol.
(abstract) base class of all TcpSockets
Definition: tcp-socket.h:46
Ipv4EndPoint * m_endPoint
the IPv4 endpoint
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
static Time ElapsedTimeFromTsValue(uint32_t echoTime)
Estimate the Time elapsed from a TS echo value.
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
virtual ~TcpSocketBase(void)
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:455
uint32_t m_dataRetrCount
Count of remaining data retransmission attempts.
TracedValue< Time > m_lastRtt
Last RTT sample collected.
uint32_t m_synRetries
Number of connection attempts.
#define min(a, b)
Definition: 80211b.c:44
void NotifyDataRecv(void)
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:305
TracedValue< SequenceNumber32 > m_highRxAckMark
Highest ack received.
virtual int ShutdownRecv(void)
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv4Header, uint16_t, Ptr< Ipv4Interface > > callback)
Set the reception callback.
TcpSocketBase(void)
Create an unbound TCP socket.
void SetClockGranularity(Time clockGranularity)
Sets the Clock Granularity (used in RTO calcs).
EventId m_retxEvent
Retransmission event.
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:175
IPv6 layer implementation.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:81
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
void ForwardUp6(Ptr< Packet > packet, Ipv6Header header, uint16_t port, Ptr< Ipv6Interface > incomingInterface)
Called by the L3 protocol when it received a packet to pass on to TCP.
bool IsZero(void) const
Definition: nstime.h:274
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:824
virtual void SetPersistTimeout(Time timeout)
Set the timout for persistent connection.
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
virtual bool GetAllowBroadcast(void) const
Query whether broadcast datagram transmissions are allowed.
EventId m_timewaitEvent
TIME_WAIT expiration event: Move this socket to CLOSED state.
void NotifyConnectionFailed(void)
Notify through the callback (if set) that the connection has not been established due to an error...
Definition: socket.cc:227
static const char *const TcpCongStateName[TcpSocketState::CA_LAST_STATE]
Literal names of TCP states for use in log messages.
static TypeId GetTypeId(void)
Get the type ID.
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
void ProcessOptionTimestamp(const Ptr< const TcpOption > option, const SequenceNumber32 &seq)
Process the timestamp option from other side.
Both sides have shutdown but we still have data we have to finish sending.
Definition: tcp-socket.h:80
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
void UpdateHighTxMark(SequenceNumber32 oldValue, SequenceNumber32 newValue)
Callback function to hook to TcpSocketState high tx mark.
void SendRST(void)
Send reset and tear down this socket.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Ptr< TcpSocketState > m_tcb
Congestion control informations.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:903
bool m_winScalingEnabled
Window Scale option enabled (RFC 7323)
bool m_timestampEnabled
Timestamp option enabled.
uint16_t m_maxWinSize
Maximum window size to advertise.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
bool retx
True if this has been retransmitted.
virtual void NewAck(SequenceNumber32 const &seq, bool resetRTO)
Update buffers w.r.t.
bool IsManualIpTos(void) const
Checks if the socket has a specific IPv4 ToS set.
Definition: socket.cc:371
Callback< void, Ipv4Address, uint8_t, uint8_t, uint8_t, uint32_t > m_icmpCallback
ICMP callback.
void CancelAllTimers(void)
Cancel all timer when endpoint is deleted.
uint32_t count
Number of bytes sent.
void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:496
Time m_cnTimeout
Timeout for connection retry.
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
Data structure that records the congestion state of a connection.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
EventId m_lastAckEvent
Last ACK timeout event.
void ConnectionSucceeded(void)
Schedule-friendly wrapper for Socket::NotifyConnectionSucceeded()
All buffered data sent, waiting for remote to shutdown.
Definition: tcp-socket.h:79
void SetTos(uint8_t tos)
Set the tag's TOS.
Definition: socket.cc:736
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received an ACK packet.
ns3::Time timeout
T Get(void) const
Get the underlying value.
Definition: traced-value.h:217
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:1005
virtual uint32_t GetDataRetries(void) const
Get the number of data transmission retries before giving up.
virtual Time GetPersistTimeout(void) const
Get the timout for persistent connection.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
void DoPeerClose(void)
FIN is in sequence, notify app and respond with a FIN.
bool NotifyConnectionRequest(const Address &from)
Notify through the callback (if set) that an incoming connection is being requested by a remote host...
Definition: socket.cc:257
virtual void PersistTimeout(void)
Send 1 byte probe to get an updated window size.
virtual void SetSynRetries(uint32_t count)
Set the number of connection retries before giving up.
Ptr< TcpTxBuffer > GetTxBuffer(void) const
Get a pointer to the Tx buffer.
TracedValue< TcpStates_t > m_state
TCP state.
uint32_t m_delAckMaxCount
Number of packet to fire an ACK before delay timeout.
uint8_t CalculateWScale() const
Calculate window scale value based on receive buffer space.
uint16_t port
Definition: dsdv-manet.cc:44
a polymophic address class
Definition: address.h:90
void SetMinRto(Time minRto)
Sets the Minimum RTO.
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
uint16_t GetPeerPort()
Get the peer port.
AttributeValue implementation for Callback.
Definition: callback.h:1880
virtual uint32_t GetRcvBufSize(void) const
Get the receive buffer size.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
uint32_t m_delAckCount
Delayed ACK counter.
virtual bool GetTcpNoDelay(void) const
Check if Nagle's algorithm is enabled or not.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
SequenceNumber32 m_recover
Previous highest Tx seqnum for fast recovery.
void ForwardIcmp6(Ipv6Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Called by the L3 protocol when it received an ICMPv6 packet to pass on to TCP.
virtual int Bind(void)
Allocate a local IPv4 endpoint for this socket.
virtual int GetPeerName(Address &address) const
Get the peer address of a connected socket.
virtual void Retransmit(void)
Halving cwnd and call DoRetransmit()
Packet header for IPv4.
Definition: ipv4-header.h:31
void SetLocalAddress(Ipv6Address addr)
Set the local address.
bool AppendOption(Ptr< TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:460
virtual void SetDataRetries(uint32_t retries)
Set the number of data transmission retries before giving up.
Ptr< TcpCongestionOps > m_congestionControl
Congestion control.
static const char *const TcpStateName[TcpSocket::LAST_STATE]
Literal names of TCP states for use in log messages.
Definition: tcp-socket.h:93
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:197
void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send data to a specified peer.
void UpdateCwnd(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState congestion window.
virtual void EstimateRtt(const TcpHeader &tcpHeader)
Take into account the packet for RTT estimation.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: pointer.h:220
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1221
Time time
Time this one was sent.
#define max(a, b)
Definition: 80211b.c:45
virtual void UpdateRttHistory(const SequenceNumber32 &seq, uint32_t sz, bool isRetransmission)
Update the RTT history, when we send TCP segments.
Ptr< TcpTxBuffer > m_txBuffer
Tx buffer.
void ForwardUp(Ptr< Packet > packet, Ipv4Header header, uint16_t port, Ptr< Ipv4Interface > incomingInterface)
Called by the L3 protocol when it received a packet to pass on to TCP.
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition: socket.cc:555
AttributeValue implementation for Time.
Definition: nstime.h:957
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
virtual uint32_t GetSndBufSize(void) const
Get the send buffer size.
virtual enum SocketType GetSocketType(void) const
uint16_t GetLocalPort()
Get the local port.
virtual uint16_t AdvertisedWindowSize(bool scale=true) const
The amount of Rx window announced to the peer.
void UpdateWindowSize(const TcpHeader &header)
Update the receiver window (RWND) based on the value of the window field in the header.
void AddOptionTimestamp(TcpHeader &header)
Add the timestamp option to the header.
Hold an unsigned integer type.
Definition: uinteger.h:44
SequenceNumber32 m_highTxAck
Highest ack sent.
TracedCallback< uint32_t, uint32_t > m_cWndTrace
Callback pointer for cWnd trace chaining.
Ipv6EndPoint * m_endPoint6
the IPv6 endpoint
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
virtual uint32_t GetSynRetries(void) const
Get the number of connection retries before giving up.
bool OutOfRange(SequenceNumber32 head, SequenceNumber32 tail) const
Check if a sequence number range is within the rx window.
virtual bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
Ptr< const AttributeAccessor > MakeCallbackAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: callback.h:1922
Ipv4Address GetLocalAddress(void)
Get the local address.
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:209
An Inet6 address class.
virtual void SetTcpNoDelay(bool noDelay)
Enable/Disable Nagle's algorithm.
RttHistory(SequenceNumber32 s, uint32_t c, Time t)
Constructor - builds an RttHistory with the given parameters.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
void UpdateCongState(TcpSocketState::TcpCongState_t oldValue, TcpSocketState::TcpCongState_t newValue)
Callback function to hook to TcpSocketState congestion state.
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:377
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:285
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:128
enum SocketErrno m_errno
Socket error code.
Ipv4Address GetSource(void) const
Definition: ipv4-route.cc:56
friend Ptr< T > CopyObject(Ptr< T > object)
Copy an Object.
Definition: object.h:490
A base class for implementation of a stream socket using TCP.
Ptr< RttEstimator > m_rtt
Round trip time estimator.
bool m_closeNotified
Told app to close socket.
void ProcessSynSent(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon SYN_SENT.
static uint32_t SafeSubtraction(uint32_t a, uint32_t b)
Performs a safe subtraction between a and b (a-b)
Ptr< TcpRxBuffer > m_rxBuffer
Rx buffer (reordering buffer)
int SetupCallback(void)
Common part of the two Bind(), i.e.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
virtual void SetTcp(Ptr< TcpL4Protocol > tcp)
Set the associated TCP L4 protocol.
bool m_isFirstPartialAck
First partial ACK during RECOVERY.
Ptr< TcpL4Protocol > m_tcp
the associated TCP L4 protocol
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:616
TracedValue< uint32_t > m_ssThresh
Slow start threshold.
void ProcessSynRcvd(Ptr< Packet > packet, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Received a packet upon SYN_RCVD.
virtual int ShutdownSend(void)
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:95
void NotifyConnectionSucceeded(void)
Notify through the callback (if set) that the connection has been established.
Definition: socket.cc:217
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:113
uint32_t m_retxThresh
Fast Retransmit threshold.
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
TcpCongState_t
Definition of the Congestion state machine.
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:389
virtual void SetDelAckMaxCount(uint32_t count)
Set the number of packet to fire an ACK before delay timeout.
void NotifyNormalClose(void)
Notify through the callback (if set) that the connection has been closed.
Definition: socket.cc:237
int DoConnect(void)
Perform the real connection tasks: Send SYN if allowed, RST if invalid.
virtual void CompleteFork(Ptr< Packet > p, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Complete a connection by forking the socket.
virtual void AddOptions(TcpHeader &tcpHeader)
Add options to TcpHeader.
void UpdateNextTxSequence(SequenceNumber32 oldValue, SequenceNumber32 newValue)
Callback function to hook to TcpSocketState next tx sequence.
uint32_t m_dupAckCount
Dupack counter.
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Used only in debug messages.
Ptr< Node > m_node
the associated node
Hold objects of type Ptr<T>.
Definition: pointer.h:36
void NotifyNewConnectionCreated(Ptr< Socket > socket, const Address &from)
Notify through the callback (if set) that a new connection has been created.
Definition: socket.cc:275
TracedValue< TcpCongState_t > m_congState
State in the Congestion state machine.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
void TimeWait(void)
Move from CLOSING or FIN_WAIT_2 to TIME_WAIT state.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
virtual void SetNode(Ptr< Node > node)
Set the associated node.
void SetIcmpCallback(Callback< void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t > callback)
Set the ICMP callback.
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
virtual uint32_t UnAckDataCount(void) const
Return count of number of unacked bytes.
virtual uint32_t BytesInFlight(void)
Return total bytes in flight.
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1198
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:446
void Destroy(void)
Kill this socket by zeroing its attributes (IPv4)
Timeout to catch resent junk before entering closed, can only be entered from FIN_WAIT2 or CLOSING...
Definition: tcp-socket.h:82
static TypeId GetTypeId(void)
Get the type ID.
virtual uint32_t GetInitialSSThresh(void) const
Get the initial Slow Start Threshold.
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
Time TimeStep(uint64_t ts)
Definition: nstime.h:952
static EventId ScheduleNow(MEM mem_ptr, OBJ obj)
Schedule an event to expire Now.
Definition: simulator.h:1384
virtual int Close(void)
Close a socket.
static Ipv4Address GetZero(void)
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: nstime.h:958
Our side has shutdown after remote has shutdown.
Definition: tcp-socket.h:74
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer informations (address and port).
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:121
Remote side has shutdown and is waiting for us to finish writing our data and to shutdown (we have to...
Definition: tcp-socket.h:71
Sent a connection request, waiting for ack.
Definition: tcp-socket.h:67
virtual void SetRtt(Ptr< RttEstimator > rtt)
Set the associated RTT estimator.
double m_msl
Max segment lifetime.
virtual void ReTxTimeout(void)
Call Retransmit() upon RTO event.
Ptr< const AttributeChecker > MakeCallbackChecker(void)
Definition: callback.cc:75
static uint32_t NowToTsValue()
Return an uint32_t value which represent "now".
Time m_minRto
minimum value of the Retransmit timeout
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:330
virtual void SendEmptyPacket(uint8_t flags)
Send a empty packet that carries a flag, e.g.
Time m_delAckTimeout
Time to delay an ACK.
TracedValue< uint32_t > m_cWnd
Congestion window.
Socket is finished.
Definition: tcp-socket.h:65
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call) ...
Definition: socket.cc:114
Listening for a connection.
Definition: tcp-socket.h:66
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
void SetLocalAddress(Ipv4Address address)
Set the local address.
virtual void SetSndBufSize(uint32_t size)
Set the send buffer size.
virtual TypeId GetInstanceTypeId() const
Get the instance TypeId.
Ptr< TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:486
static Time FromDouble(double value, enum Unit unit)
Create a Time equal to value in unit unit.
Definition: nstime.h:442
virtual void SetDelAckTimeout(Time timeout)
Set the time to delay an ACK.
void DeallocateEndPoint(void)
Deallocate m_endPoint and m_endPoint6.
Ptr< TcpRxBuffer > GetRxBuffer(void) const
Get a pointer to the Rx buffer.
Describes an IPv6 address.
Definition: ipv6-address.h:48
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
Time GetMinRto(void) const
Get the Minimum RTO.
void ProcessEstablished(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon ESTABLISHED state.
void ProcessOptionWScale(const Ptr< const TcpOption > option)
Read and parse the Window scale option.
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:967
bool m_connected
Connection established.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
uint32_t GetId(void) const
Definition: node.cc:107
TracedValue< Time > m_rto
Retransmit timeout.
Helper class to store RTT measurements.
uint16_t GetLocalPort(void)
Get the local port.
uint8_t m_rcvWindShift
Window shift to apply to outgoing segments.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:228
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
Ipv6Address GetPeerAddress()
Get the peer address.
int DoClose(void)
Close a socket by sending RST, FIN, or FIN+ACK, depend on the current state.
SequenceNumber32 seq
First sequence number in packet sent.
Our side has shutdown, waiting to complete transmission of remaining buffered data.
Definition: tcp-socket.h:77
CWND was reduced due to RTO timeout or SACK reneging.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
RttHistory_t m_history
List of sent packet.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:895
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
virtual uint32_t GetInitialCwnd(void) const
Get the initial Congestion Window.
Ipv4Address GetPeerAddress(void)
Get the peer address.
uint32_t m_timestampToEcho
Timestamp to echo.
uint32_t m_synCount
Count of remaining connection retries.
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv6Header, uint16_t, Ptr< Ipv6Interface > > callback)
Set the reception callback.
static bool IsMatchingType(const Address &addr)
If the address match.
uint16_t GetPeerPort(void)
Get the peer port.
TracedValue< SequenceNumber32 > m_highRxMark
Highest seqno received.
uint16_t GetPort(void) const
Get the port.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
virtual enum SocketErrno GetErrno(void) const
Get last error number.
TracedValue< SequenceNumber32 > m_highTxMark
Highest seqno ever sent, regardless of ReTx.
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
void ProcessLastAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon LAST_ACK.
Ipv4Address GetIpv4MappedAddress() const
Return the Ipv4 address.
void UpdateSsThresh(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState slow start threshold.
virtual void SetSegSize(uint32_t size)
Set the segment size.
void ProcessClosing(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon CLOSING.
Received a connection request, sent ack, waiting for final ack in three-way handshake.
Definition: tcp-socket.h:68
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:220
uint16_t GetPort(void) const
second
Definition: nstime.h:114
virtual void ReceivedData(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Recv of a data, put into buffer, call L7 to get it if necessary.
void SetConnectCallback(Callback< void, Ptr< Socket > > connectionSucceeded, Callback< void, Ptr< Socket > > connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:84
void CloseAndNotify(void)
Peacefully close the socket by notifying the upper layer and deallocate end point.
Callback< void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t > m_icmpCallback6
ICMPv6 callback.
A base class which provides memory management and object aggregation.
Definition: object.h:87
tuple address
Definition: first.py:37
virtual Ptr< Node > GetNode(void) const
Return the node this socket is associated with.
virtual void SetRcvBufSize(uint32_t size)
Set the receive buffer size.
bool m_shutdownRecv
Receive no longer allowed.
uint32_t m_retransOut
Number of retransmission in this window.
virtual Time GetDelAckTimeout(void) const
Get the time to delay an ACK.
TracedCallback< uint32_t, uint32_t > m_ssThTrace
Callback pointer for ssTh trace chaining.
EventId m_sendPendingDataEvent
micro-delay event to send pending data
virtual void DelAckTimeout(void)
Action upon delay ACK timeout, i.e.
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:502
virtual void LastAckTimeout(void)
Timeout at LAST_ACK, close the connection.
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Definition: double.h:41
uint32_t m_bytesAckedNotProcessed
Bytes acked, but not processed.
virtual int Bind6(void)
Allocate a local IPv6 endpoint for this socket.
TracedCallback< SequenceNumber32, SequenceNumber32 > m_nextTxSequenceTrace
Callback pointer for next tx sequence chaining.
indicates whether the socket has IP_TOS set.
Definition: socket.h:1151
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
void SetIcmpCallback(Callback< void, Ipv4Address, uint8_t, uint8_t, uint8_t, uint32_t > callback)
Set the ICMP callback.
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
bool IsIpv4MappedAddress() const
If the address is an IPv4-mapped address.
EventId m_delAckEvent
Delayed ACK timeout event.
a unique identifier for an interface.
Definition: type-id.h:58
uint8_t m_sndWindShift
Window shift to apply to incoming segments.
bool m_shutdownSend
Send no longer allowed.
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:105
virtual Ptr< TcpSocketBase > Fork(void)
Call CopyObject<> to clone me.
int SetupEndpoint6(void)
Configure the endpoint v6 to a local address.
void NotifySend(uint32_t spaceAvailable)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:295
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:827
Time m_clockGranularity
Clock Granularity used in RTO calcs.
bool SendPendingData(bool withAck=false)
Send as much pending data as possible according to the Tx window.
void ForwardIcmp(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Called by the L3 protocol when it received an ICMP packet to pass on to TCP.
TracedValue< uint32_t > m_rWnd
Receiver window (RCV.WND in RFC793)
TracedCallback< Ptr< const Packet >, const TcpHeader &, Ptr< const TcpSocketBase > > m_rxTrace
Trace of received packets.
virtual void DoForwardUp(Ptr< Packet > packet, const Address &fromAddress, const Address &toAddress)
Called by TcpSocketBase::ForwardUp{,6}().
static bool IsMatchingType(const Address &address)
void NotifyErrorClose(void)
Notify through the callback (if set) that the connection has been closed due to an error...
Definition: socket.cc:247
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
virtual void DoRetransmit(void)
Retransmit the oldest packet.
bool m_closeOnEmpty
Close socket upon tx buffer emptied.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:719
TracedCallback< Ptr< const Packet >, const TcpHeader &, Ptr< const TcpSocketBase > > m_txTrace
Trace of transmitted packets.
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
void AddOptionWScale(TcpHeader &header)
Add the window scale option to the header.
virtual uint32_t GetDelAckMaxCount(void) const
Get the number of packet to fire an ACK before delay timeout.
virtual void SetConnTimeout(Time timeout)
Set the connection timeout.
EventId m_persistEvent
Persist event: Send 1 byte to probe for a non-zero Rx window.
void SetPeer(Ipv6Address addr, uint16_t port)
Set the peer informations (address and port).
int SetupEndpoint(void)
Configure the endpoint to a local address.
virtual Time GetConnTimeout(void) const
Get the connection timeout.
TracedCallback< TcpSocketState::TcpCongState_t, TcpSocketState::TcpCongState_t > m_congStateTrace
Callback pointer for congestion state trace chaining.
void Destroy6(void)
Kill this socket by zeroing its attributes (IPv6)
TracedValue< SequenceNumber32 > m_nextTxSequence
Next seqnum to be sent (SND.NXT), ReTx pushes it back.
virtual uint32_t AvailableWindow(void) const
Return unfilled portion of window.
Time m_persistTimeout
Time between sending 1-byte probes.
virtual uint32_t GetTxAvailable(void) const
Returns the number of bytes which can be sent in a single call to Send.
virtual uint32_t GetRxAvailable(void) const
Return number of bytes which can be returned from one or multiple calls to Recv.