A Discrete-Event Network Simulator
API
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 "ns3/data-rate.h"
45 #include "ns3/object.h"
46 #include "tcp-socket-base.h"
47 #include "tcp-l4-protocol.h"
48 #include "ipv4-end-point.h"
49 #include "ipv6-end-point.h"
50 #include "ipv6-l3-protocol.h"
51 #include "tcp-tx-buffer.h"
52 #include "tcp-rx-buffer.h"
53 #include "rtt-estimator.h"
54 #include "tcp-header.h"
55 #include "tcp-option-winscale.h"
56 #include "tcp-option-ts.h"
58 #include "tcp-option-sack.h"
59 #include "tcp-congestion-ops.h"
60 #include "tcp-recovery-ops.h"
61 #include "ns3/tcp-rate-ops.h"
62 
63 #include <math.h>
64 #include <algorithm>
65 
66 namespace ns3 {
67 
68 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase");
69 
70 NS_OBJECT_ENSURE_REGISTERED (TcpSocketBase);
71 
72 TypeId
74 {
75  static TypeId tid = TypeId ("ns3::TcpSocketBase")
76  .SetParent<TcpSocket> ()
77  .SetGroupName ("Internet")
78  .AddConstructor<TcpSocketBase> ()
79 // .AddAttribute ("TcpState", "State in TCP state machine",
80 // TypeId::ATTR_GET,
81 // EnumValue (CLOSED),
82 // MakeEnumAccessor (&TcpSocketBase::m_state),
83 // MakeEnumChecker (CLOSED, "Closed"))
84  .AddAttribute ("MaxSegLifetime",
85  "Maximum segment lifetime in seconds, use for TIME_WAIT state transition to CLOSED state",
86  DoubleValue (120), /* RFC793 says MSL=2 minutes*/
88  MakeDoubleChecker<double> (0))
89  .AddAttribute ("MaxWindowSize", "Max size of advertised window",
90  UintegerValue (65535),
92  MakeUintegerChecker<uint16_t> ())
93  .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
94  CallbackValue (),
97  .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
98  CallbackValue (),
101  .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option",
102  BooleanValue (true),
105  .AddAttribute ("Sack", "Enable or disable Sack option",
106  BooleanValue (true),
109  .AddAttribute ("Timestamp", "Enable or disable Timestamp option",
110  BooleanValue (true),
113  .AddAttribute ("MinRto",
114  "Minimum retransmit timeout value",
115  TimeValue (Seconds (1.0)), // RFC 6298 says min RTO=1 sec, but Linux uses 200ms.
116  // See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
119  MakeTimeChecker ())
120  .AddAttribute ("ClockGranularity",
121  "Clock Granularity used in RTO calculations",
122  TimeValue (MilliSeconds (1)), // RFC6298 suggest to use fine clock granularity
125  MakeTimeChecker ())
126  .AddAttribute ("TxBuffer",
127  "TCP Tx buffer",
128  PointerValue (),
130  MakePointerChecker<TcpTxBuffer> ())
131  .AddAttribute ("RxBuffer",
132  "TCP Rx buffer",
133  PointerValue (),
135  MakePointerChecker<TcpRxBuffer> ())
136  .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit",
137  UintegerValue (3),
140  MakeUintegerChecker<uint32_t> ())
141  .AddAttribute ("LimitedTransmit", "Enable limited transmit",
142  BooleanValue (true),
145  .AddAttribute ("UseEcn", "Parameter to set ECN functionality",
149  TcpSocketState::On, "On",
150  TcpSocketState::AcceptOnly, "AcceptOnly"))
151  .AddTraceSource ("RTO",
152  "Retransmission timeout",
154  "ns3::TracedValueCallback::Time")
155  .AddTraceSource ("RTT",
156  "Last RTT sample",
158  "ns3::TracedValueCallback::Time")
159  .AddTraceSource ("NextTxSequence",
160  "Next sequence number to send (SND.NXT)",
162  "ns3::SequenceNumber32TracedValueCallback")
163  .AddTraceSource ("HighestSequence",
164  "Highest sequence number ever sent in socket's life time",
166  "ns3::TracedValueCallback::SequenceNumber32")
167  .AddTraceSource ("State",
168  "TCP state",
170  "ns3::TcpStatesTracedValueCallback")
171  .AddTraceSource ("CongState",
172  "TCP Congestion machine state",
174  "ns3::TcpSocketState::TcpCongStatesTracedValueCallback")
175  .AddTraceSource ("EcnState",
176  "Trace ECN state change of socket",
178  "ns3::TcpSocketState::EcnStatesTracedValueCallback")
179  .AddTraceSource ("AdvWND",
180  "Advertised Window Size",
182  "ns3::TracedValueCallback::Uint32")
183  .AddTraceSource ("RWND",
184  "Remote side's flow control window",
186  "ns3::TracedValueCallback::Uint32")
187  .AddTraceSource ("BytesInFlight",
188  "Socket estimation of bytes in flight",
190  "ns3::TracedValueCallback::Uint32")
191  .AddTraceSource ("HighestRxSequence",
192  "Highest sequence number received from peer",
194  "ns3::TracedValueCallback::SequenceNumber32")
195  .AddTraceSource ("HighestRxAck",
196  "Highest ack received from peer",
198  "ns3::TracedValueCallback::SequenceNumber32")
199  .AddTraceSource ("PacingRate",
200  "The current TCP pacing rate",
202  "ns3::TracedValueCallback::DataRate")
203  .AddTraceSource ("CongestionWindow",
204  "The TCP connection's congestion window",
206  "ns3::TracedValueCallback::Uint32")
207  .AddTraceSource ("CongestionWindowInflated",
208  "The TCP connection's congestion window inflates as in older RFC",
210  "ns3::TracedValueCallback::Uint32")
211  .AddTraceSource ("SlowStartThreshold",
212  "TCP slow start threshold (bytes)",
214  "ns3::TracedValueCallback::Uint32")
215  .AddTraceSource ("Tx",
216  "Send tcp packet to IP protocol",
218  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
219  .AddTraceSource ("Rx",
220  "Receive tcp packet from IP protocol",
222  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
223  .AddTraceSource ("EcnEchoSeq",
224  "Sequence of last received ECN Echo",
226  "ns3::SequenceNumber32TracedValueCallback")
227  .AddTraceSource ("EcnCeSeq",
228  "Sequence of last received CE ",
230  "ns3::SequenceNumber32TracedValueCallback")
231  .AddTraceSource ("EcnCwrSeq",
232  "Sequence of last received CWR",
234  "ns3::SequenceNumber32TracedValueCallback")
235  ;
236  return tid;
237 }
238 
239 TypeId
241 {
242  return TcpSocketBase::GetTypeId ();
243 }
244 
246  : TcpSocket ()
247 {
248  NS_LOG_FUNCTION (this);
249  m_txBuffer = CreateObject<TcpTxBuffer> ();
250  m_txBuffer->SetRWndCallback (MakeCallback (&TcpSocketBase::GetRWnd, this));
251  m_tcb = CreateObject<TcpSocketState> ();
252  m_rateOps = CreateObject <TcpRateLinux> ();
253 
254  m_tcb->m_rxBuffer = CreateObject<TcpRxBuffer> ();
255 
258 
260 
261  bool ok;
262 
263  ok = m_tcb->TraceConnectWithoutContext ("PacingRate",
265  NS_ASSERT (ok == true);
266 
267  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
269  NS_ASSERT (ok == true);
270 
271  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindowInflated",
273  NS_ASSERT (ok == true);
274 
275  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
277  NS_ASSERT (ok == true);
278 
279  ok = m_tcb->TraceConnectWithoutContext ("CongState",
281  NS_ASSERT (ok == true);
282 
283  ok = m_tcb->TraceConnectWithoutContext ("EcnState",
285  NS_ASSERT (ok == true);
286 
287  ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
289  NS_ASSERT (ok == true);
290 
291  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
293  NS_ASSERT (ok == true);
294 
295  ok = m_tcb->TraceConnectWithoutContext ("BytesInFlight",
297  NS_ASSERT (ok == true);
298 
299  ok = m_tcb->TraceConnectWithoutContext ("RTT",
301  NS_ASSERT (ok == true);
302 }
303 
305  : TcpSocket (sock),
306  //copy object::m_tid and socket::callbacks
307  m_dupAckCount (sock.m_dupAckCount),
308  m_delAckCount (0),
309  m_delAckMaxCount (sock.m_delAckMaxCount),
310  m_noDelay (sock.m_noDelay),
311  m_synCount (sock.m_synCount),
312  m_synRetries (sock.m_synRetries),
313  m_dataRetrCount (sock.m_dataRetrCount),
314  m_dataRetries (sock.m_dataRetries),
315  m_rto (sock.m_rto),
316  m_minRto (sock.m_minRto),
317  m_clockGranularity (sock.m_clockGranularity),
318  m_delAckTimeout (sock.m_delAckTimeout),
319  m_persistTimeout (sock.m_persistTimeout),
320  m_cnTimeout (sock.m_cnTimeout),
321  m_endPoint (nullptr),
322  m_endPoint6 (nullptr),
323  m_node (sock.m_node),
324  m_tcp (sock.m_tcp),
325  m_state (sock.m_state),
326  m_errno (sock.m_errno),
327  m_closeNotified (sock.m_closeNotified),
328  m_closeOnEmpty (sock.m_closeOnEmpty),
329  m_shutdownSend (sock.m_shutdownSend),
330  m_shutdownRecv (sock.m_shutdownRecv),
331  m_connected (sock.m_connected),
332  m_msl (sock.m_msl),
333  m_maxWinSize (sock.m_maxWinSize),
334  m_bytesAckedNotProcessed (sock.m_bytesAckedNotProcessed),
335  m_rWnd (sock.m_rWnd),
336  m_highRxMark (sock.m_highRxMark),
337  m_highRxAckMark (sock.m_highRxAckMark),
338  m_sackEnabled (sock.m_sackEnabled),
339  m_winScalingEnabled (sock.m_winScalingEnabled),
340  m_rcvWindShift (sock.m_rcvWindShift),
341  m_sndWindShift (sock.m_sndWindShift),
342  m_timestampEnabled (sock.m_timestampEnabled),
343  m_timestampToEcho (sock.m_timestampToEcho),
344  m_recover (sock.m_recover),
345  m_recoverActive (sock.m_recoverActive),
346  m_retxThresh (sock.m_retxThresh),
347  m_limitedTx (sock.m_limitedTx),
348  m_isFirstPartialAck (sock.m_isFirstPartialAck),
349  m_txTrace (sock.m_txTrace),
350  m_rxTrace (sock.m_rxTrace),
351  m_pacingTimer (Timer::CANCEL_ON_DESTROY),
352  m_ecnEchoSeq (sock.m_ecnEchoSeq),
353  m_ecnCESeq (sock.m_ecnCESeq),
354  m_ecnCWRSeq (sock.m_ecnCWRSeq)
355 {
356  NS_LOG_FUNCTION (this);
357  NS_LOG_LOGIC ("Invoked the copy constructor");
358  // Copy the rtt estimator if it is set
359  if (sock.m_rtt)
360  {
361  m_rtt = sock.m_rtt->Copy ();
362  }
363  // Reset all callbacks to null
364  Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
365  Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr<Socket>, const Address &> ();
366  Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t> ();
367  SetConnectCallback (vPS, vPS);
368  SetDataSentCallback (vPSUI);
369  SetSendCallback (vPSUI);
370  SetRecvCallback (vPS);
372  m_txBuffer->SetRWndCallback (MakeCallback (&TcpSocketBase::GetRWnd, this));
373  m_tcb = CopyObject (sock.m_tcb);
375 
378 
379  if (sock.m_congestionControl)
380  {
382  m_congestionControl->Init (m_tcb);
383  }
384 
385  if (sock.m_recoveryOps)
386  {
387  m_recoveryOps = sock.m_recoveryOps->Fork ();
388  }
389 
390  m_rateOps = CreateObject <TcpRateLinux> ();
392  {
394  }
395 
396  bool ok;
397 
398  ok = m_tcb->TraceConnectWithoutContext ("PacingRate",
400 
401  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
403  NS_ASSERT (ok == true);
404 
405  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindowInflated",
407  NS_ASSERT (ok == true);
408 
409  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
411  NS_ASSERT (ok == true);
412 
413  ok = m_tcb->TraceConnectWithoutContext ("CongState",
415  NS_ASSERT (ok == true);
416 
417  ok = m_tcb->TraceConnectWithoutContext ("EcnState",
419  NS_ASSERT (ok == true);
420 
421  ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
423  NS_ASSERT (ok == true);
424 
425  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
427  NS_ASSERT (ok == true);
428 
429  ok = m_tcb->TraceConnectWithoutContext ("BytesInFlight",
431  NS_ASSERT (ok == true);
432 
433  ok = m_tcb->TraceConnectWithoutContext ("RTT",
435  NS_ASSERT (ok == true);
436 }
437 
439 {
440  NS_LOG_FUNCTION (this);
441  m_node = nullptr;
442  if (m_endPoint != nullptr)
443  {
444  NS_ASSERT (m_tcp != nullptr);
445  /*
446  * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
447  * DestroyCallback is set to TcpSocketBase::Destroy. If we called
448  * m_tcp->DeAllocate, it will destroy its Ipv4EndpointDemux::DeAllocate,
449  * which in turn destroys my m_endPoint, and in turn invokes
450  * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
451  */
452  NS_ASSERT (m_endPoint != nullptr);
453  m_tcp->DeAllocate (m_endPoint);
454  NS_ASSERT (m_endPoint == nullptr);
455  }
456  if (m_endPoint6 != nullptr)
457  {
458  NS_ASSERT (m_tcp != nullptr);
459  NS_ASSERT (m_endPoint6 != nullptr);
460  m_tcp->DeAllocate (m_endPoint6);
461  NS_ASSERT (m_endPoint6 == nullptr);
462  }
463  m_tcp = 0;
464  CancelAllTimers ();
465 }
466 
467 /* Associate a node with this TCP socket */
468 void
470 {
471  m_node = node;
472 }
473 
474 /* Associate the L4 protocol (e.g. mux/demux) with this socket */
475 void
477 {
478  m_tcp = tcp;
479 }
480 
481 /* Set an RTT estimator with this socket */
482 void
484 {
485  m_rtt = rtt;
486 }
487 
488 /* Inherit from Socket class: Returns error code */
491 {
492  return m_errno;
493 }
494 
495 /* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
498 {
499  return NS3_SOCK_STREAM;
500 }
501 
502 /* Inherit from Socket class: Returns associated node */
503 Ptr<Node>
505 {
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  {
517  m_errno = ERROR_ADDRNOTAVAIL;
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  {
533  m_errno = ERROR_ADDRNOTAVAIL;
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);
548  {
550  Ipv4Address ipv4 = transport.GetIpv4 ();
551  uint16_t port = transport.GetPort ();
552  SetIpTos (transport.GetTos ());
553  if (ipv4 == Ipv4Address::GetAny () && port == 0)
554  {
555  m_endPoint = m_tcp->Allocate ();
556  }
557  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
558  {
559  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (), port);
560  }
561  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
562  {
563  m_endPoint = m_tcp->Allocate (ipv4);
564  }
565  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
566  {
567  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (), ipv4, port);
568  }
569  if (0 == m_endPoint)
570  {
572  return -1;
573  }
574  }
576  {
578  Ipv6Address ipv6 = transport.GetIpv6 ();
579  uint16_t port = transport.GetPort ();
580  if (ipv6 == Ipv6Address::GetAny () && port == 0)
581  {
582  m_endPoint6 = m_tcp->Allocate6 ();
583  }
584  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
585  {
586  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (), port);
587  }
588  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
589  {
590  m_endPoint6 = m_tcp->Allocate6 (ipv6);
591  }
592  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
593  {
594  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (), ipv6, port);
595  }
596  if (0 == m_endPoint6)
597  {
599  return -1;
600  }
601  }
602  else
603  {
604  m_errno = ERROR_INVAL;
605  return -1;
606  }
607 
608  m_tcp->AddSocket (this);
609 
610  NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
611 
612  return SetupCallback ();
613 }
614 
615 void
617 {
618  NS_ABORT_MSG_UNLESS ( (m_state == CLOSED) || threshold == m_tcb->m_initialSsThresh,
619  "TcpSocketBase::SetSSThresh() cannot change initial ssThresh after connection started.");
620 
621  m_tcb->m_initialSsThresh = threshold;
622 }
623 
624 uint32_t
626 {
627  return m_tcb->m_initialSsThresh;
628 }
629 
630 void
632 {
634  "TcpSocketBase::SetInitialCwnd() cannot change initial cwnd after connection started.");
635 
636  m_tcb->m_initialCWnd = cwnd;
637 }
638 
639 uint32_t
641 {
642  return m_tcb->m_initialCWnd;
643 }
644 
645 /* Inherit from Socket class: Initiate connection to a remote address:port */
646 int
648 {
649  NS_LOG_FUNCTION (this << address);
650 
651  // If haven't do so, Bind() this socket first
653  {
654  if (m_endPoint == nullptr)
655  {
656  if (Bind () == -1)
657  {
658  NS_ASSERT (m_endPoint == nullptr);
659  return -1; // Bind() failed
660  }
661  NS_ASSERT (m_endPoint != nullptr);
662  }
664  m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
665  SetIpTos (transport.GetTos ());
666  m_endPoint6 = nullptr;
667 
668  // Get the appropriate local address and port number from the routing protocol and set up endpoint
669  if (SetupEndpoint () != 0)
670  {
671  NS_LOG_ERROR ("Route to destination does not exist ?!");
672  return -1;
673  }
674  }
676  {
677  // If we are operating on a v4-mapped address, translate the address to
678  // a v4 address and re-call this function
680  Ipv6Address v6Addr = transport.GetIpv6 ();
681  if (v6Addr.IsIpv4MappedAddress () == true)
682  {
683  Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
684  return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
685  }
686 
687  if (m_endPoint6 == nullptr)
688  {
689  if (Bind6 () == -1)
690  {
691  NS_ASSERT (m_endPoint6 == nullptr);
692  return -1; // Bind() failed
693  }
694  NS_ASSERT (m_endPoint6 != nullptr);
695  }
696  m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
697  m_endPoint = nullptr;
698 
699  // Get the appropriate local address and port number from the routing protocol and set up endpoint
700  if (SetupEndpoint6 () != 0)
701  {
702  NS_LOG_ERROR ("Route to destination does not exist ?!");
703  return -1;
704  }
705  }
706  else
707  {
708  m_errno = ERROR_INVAL;
709  return -1;
710  }
711 
712  // Re-initialize parameters in case this socket is being reused after CLOSE
713  m_rtt->Reset ();
716 
717  // DoConnect() will do state-checking and send a SYN packet
718  return DoConnect ();
719 }
720 
721 /* Inherit from Socket class: Listen on the endpoint for an incoming connection */
722 int
724 {
725  NS_LOG_FUNCTION (this);
726 
727  // Linux quits EINVAL if we're not in CLOSED state, so match what they do
728  if (m_state != CLOSED)
729  {
730  m_errno = ERROR_INVAL;
731  return -1;
732  }
733  // In other cases, set the state to LISTEN and done
734  NS_LOG_DEBUG ("CLOSED -> LISTEN");
735  m_state = LISTEN;
736  return 0;
737 }
738 
739 /* Inherit from Socket class: Kill this socket and signal the peer (if any) */
740 int
742 {
743  NS_LOG_FUNCTION (this);
747  if (m_tcb->m_rxBuffer->Size () != 0)
748  {
749  NS_LOG_WARN ("Socket " << this << " << unread rx data during close. Sending reset." <<
750  "This is probably due to a bad sink application; check its code");
751  SendRST ();
752  return 0;
753  }
754 
755  if (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
756  { // App close with pending data must wait until all data transmitted
757  if (m_closeOnEmpty == false)
758  {
759  m_closeOnEmpty = true;
760  NS_LOG_INFO ("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
761  }
762  return 0;
763  }
764  return DoClose ();
765 }
766 
767 /* Inherit from Socket class: Signal a termination of send */
768 int
770 {
771  NS_LOG_FUNCTION (this);
772 
773  //this prevents data from being added to the buffer
774  m_shutdownSend = true;
775  m_closeOnEmpty = true;
776  //if buffer is already empty, send a fin now
777  //otherwise fin will go when buffer empties.
778  if (m_txBuffer->Size () == 0)
779  {
780  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
781  {
782  NS_LOG_INFO ("Empty tx buffer, send fin");
784 
785  if (m_state == ESTABLISHED)
786  { // On active close: I am the first one to send FIN
787  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
789  }
790  else
791  { // On passive close: Peer sent me FIN already
792  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
793  m_state = LAST_ACK;
794  }
795  }
796  }
797 
798  return 0;
799 }
800 
801 /* Inherit from Socket class: Signal a termination of receive */
802 int
804 {
805  NS_LOG_FUNCTION (this);
806  m_shutdownRecv = true;
807  return 0;
808 }
809 
810 /* Inherit from Socket class: Send a packet. Parameter flags is not used.
811  Packet has no TCP header. Invoked by upper-layer application */
812 int
813 TcpSocketBase::Send (Ptr<Packet> p, uint32_t flags)
814 {
815  NS_LOG_FUNCTION (this << p);
816  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Send()");
818  {
819  // Store the packet into Tx buffer
820  if (!m_txBuffer->Add (p))
821  { // TxBuffer overflow, send failed
822  m_errno = ERROR_MSGSIZE;
823  return -1;
824  }
825  if (m_shutdownSend)
826  {
827  m_errno = ERROR_SHUTDOWN;
828  return -1;
829  }
830 
832  m_txBuffer->TailSequence (), m_tcb->m_nextTxSequence,
833  m_txBuffer->GetLost (), m_txBuffer->GetRetransmitsCount ());
834 
835  // Submit the data to lower layers
836  NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpStateName[m_state]);
837  if ((m_state == ESTABLISHED || m_state == CLOSE_WAIT) && AvailableWindow () > 0)
838  { // Try to send the data out: Add a little step to allow the application
839  // to fill the buffer
841  {
844  this, m_connected);
845  }
846  }
847  return p->GetSize ();
848  }
849  else
850  { // Connection not established yet
851  m_errno = ERROR_NOTCONN;
852  return -1; // Send failure
853  }
854 }
855 
856 /* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
857 int
859 {
860  NS_UNUSED (address);
861  return Send (p, flags); // SendTo() and Send() are the same
862 }
863 
864 /* Inherit from Socket class: Return data to upper-layer application. Parameter flags
865  is not used. Data is returned as a packet of size no larger than maxSize */
867 TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
868 {
869  NS_LOG_FUNCTION (this);
870  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()");
871  if (m_tcb->m_rxBuffer->Size () == 0 && m_state == CLOSE_WAIT)
872  {
873  return Create<Packet> (); // Send EOF on connection close
874  }
875  Ptr<Packet> outPacket = m_tcb->m_rxBuffer->Extract (maxSize);
876  return outPacket;
877 }
878 
879 /* Inherit from Socket class: Recv and return the remote's address */
881 TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
882 {
883  NS_LOG_FUNCTION (this << maxSize << flags);
884  Ptr<Packet> packet = Recv (maxSize, flags);
885  // Null packet means no data to read, and an empty packet indicates EOF
886  if (packet != nullptr && packet->GetSize () != 0)
887  {
888  if (m_endPoint != nullptr)
889  {
891  }
892  else if (m_endPoint6 != nullptr)
893  {
895  }
896  else
897  {
898  fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
899  }
900  }
901  return packet;
902 }
903 
904 /* Inherit from Socket class: Get the max number of bytes an app can send */
905 uint32_t
907 {
908  NS_LOG_FUNCTION (this);
909  return m_txBuffer->Available ();
910 }
911 
912 /* Inherit from Socket class: Get the max number of bytes an app can read */
913 uint32_t
915 {
916  NS_LOG_FUNCTION (this);
917  return m_tcb->m_rxBuffer->Available ();
918 }
919 
920 /* Inherit from Socket class: Return local address:port */
921 int
923 {
924  NS_LOG_FUNCTION (this);
925  if (m_endPoint != nullptr)
926  {
928  }
929  else if (m_endPoint6 != nullptr)
930  {
932  }
933  else
934  { // It is possible to call this method on a socket without a name
935  // in which case, behavior is unspecified
936  // Should this return an InetSocketAddress or an Inet6SocketAddress?
938  }
939  return 0;
940 }
941 
942 int
944 {
945  NS_LOG_FUNCTION (this << address);
946 
947  if (!m_endPoint && !m_endPoint6)
948  {
949  m_errno = ERROR_NOTCONN;
950  return -1;
951  }
952 
953  if (m_endPoint)
954  {
956  m_endPoint->GetPeerPort ());
957  }
958  else if (m_endPoint6)
959  {
962  }
963  else
964  {
965  NS_ASSERT (false);
966  }
967 
968  return 0;
969 }
970 
971 /* Inherit from Socket class: Bind this socket to the specified NetDevice */
972 void
974 {
975  NS_LOG_FUNCTION (netdevice);
976  Socket::BindToNetDevice (netdevice); // Includes sanity check
977  if (m_endPoint != nullptr)
978  {
979  m_endPoint->BindToNetDevice (netdevice);
980  }
981 
982  if (m_endPoint6 != nullptr)
983  {
984  m_endPoint6->BindToNetDevice (netdevice);
985  }
986 
987  return;
988 }
989 
990 /* Clean up after Bind. Set up callback functions in the end-point. */
991 int
993 {
994  NS_LOG_FUNCTION (this);
995 
996  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
997  {
998  return -1;
999  }
1000  if (m_endPoint != nullptr)
1001  {
1005  }
1006  if (m_endPoint6 != nullptr)
1007  {
1011  }
1012 
1013  return 0;
1014 }
1015 
1016 /* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
1017 int
1019 {
1020  NS_LOG_FUNCTION (this);
1021 
1022  // A new connection is allowed only if this socket does not have a connection
1023  if (m_state == CLOSED || m_state == LISTEN || m_state == SYN_SENT || m_state == LAST_ACK || m_state == CLOSE_WAIT)
1024  { // send a SYN packet and change state into SYN_SENT
1025  // send a SYN packet with ECE and CWR flags set if sender is ECN capable
1027  {
1029  }
1030  else
1031  {
1033  }
1034  NS_LOG_DEBUG (TcpStateName[m_state] << " -> SYN_SENT");
1035  m_state = SYN_SENT;
1036  m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; // because sender is not yet aware about receiver's ECN capability
1037  }
1038  else if (m_state != TIME_WAIT)
1039  { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
1040  // exists. We send RST, tear down everything, and close this socket.
1041  SendRST ();
1042  CloseAndNotify ();
1043  }
1044  return 0;
1045 }
1046 
1047 /* Do the action to close the socket. Usually send a packet with appropriate
1048  flags depended on the current m_state. */
1049 int
1051 {
1052  NS_LOG_FUNCTION (this);
1053  switch (m_state)
1054  {
1055  case SYN_RCVD:
1056  case ESTABLISHED:
1057  // send FIN to close the peer
1059  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
1060  m_state = FIN_WAIT_1;
1061  break;
1062  case CLOSE_WAIT:
1063  // send FIN+ACK to close the peer
1065  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
1066  m_state = LAST_ACK;
1067  break;
1068  case SYN_SENT:
1069  case CLOSING:
1070  // Send RST if application closes in SYN_SENT and CLOSING
1071  SendRST ();
1072  CloseAndNotify ();
1073  break;
1074  case LISTEN:
1075  // In this state, move to CLOSED and tear down the end point
1076  CloseAndNotify ();
1077  break;
1078  case LAST_ACK:
1079  case CLOSED:
1080  case FIN_WAIT_1:
1081  case FIN_WAIT_2:
1082  case TIME_WAIT:
1083  default: /* mute compiler */
1084  // Do nothing in these five states
1085  break;
1086  }
1087  return 0;
1088 }
1089 
1090 /* Peacefully close the socket by notifying the upper layer and deallocate end point */
1091 void
1093 {
1094  NS_LOG_FUNCTION (this);
1095 
1096  if (!m_closeNotified)
1097  {
1098  NotifyNormalClose ();
1099  m_closeNotified = true;
1100  }
1101  if (m_lastAckEvent.IsRunning ())
1102  {
1104  }
1105  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSED");
1106  m_state = CLOSED;
1107  DeallocateEndPoint ();
1108 }
1109 
1110 
1111 /* Tell if a sequence number range is out side the range that my rx buffer can
1112  accpet */
1113 bool
1115 {
1116  if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
1117  { // Rx buffer in these states are not initialized.
1118  return false;
1119  }
1120  if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
1121  { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
1122  // sequence number must equals to m_rxBuffer->NextRxSequence ()
1123  return (m_tcb->m_rxBuffer->NextRxSequence () != head);
1124  }
1125 
1126  // In all other cases, check if the sequence number is in range
1127  return (tail < m_tcb->m_rxBuffer->NextRxSequence () || m_tcb->m_rxBuffer->MaxRxSequence () <= head);
1128 }
1129 
1130 /* Function called by the L3 protocol when it received a packet to pass on to
1131  the TCP. This function is registered as the "RxCallback" function in
1132  SetupCallback(), which invoked by Bind(), and CompleteFork() */
1133 void
1135  Ptr<Ipv4Interface> incomingInterface)
1136 {
1137  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1138  m_endPoint->GetPeerAddress () <<
1139  ":" << m_endPoint->GetPeerPort () <<
1140  " to " << m_endPoint->GetLocalAddress () <<
1141  ":" << m_endPoint->GetLocalPort ());
1142 
1143  Address fromAddress = InetSocketAddress (header.GetSource (), port);
1144  Address toAddress = InetSocketAddress (header.GetDestination (),
1145  m_endPoint->GetLocalPort ());
1146 
1147  TcpHeader tcpHeader;
1148  uint32_t bytesRemoved = packet->PeekHeader (tcpHeader);
1149 
1150  if (!IsValidTcpSegment (tcpHeader.GetSequenceNumber (), bytesRemoved,
1151  packet->GetSize () - bytesRemoved))
1152  {
1153  return;
1154  }
1155 
1156  if (header.GetEcn() == Ipv4Header::ECN_CE && m_ecnCESeq < tcpHeader.GetSequenceNumber ())
1157  {
1158  NS_LOG_INFO ("Received CE flag is valid");
1159  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_CE_RCVD");
1160  m_ecnCESeq = tcpHeader.GetSequenceNumber ();
1163  }
1165  {
1167  }
1168 
1169  DoForwardUp (packet, fromAddress, toAddress);
1170 }
1171 
1172 void
1174  Ptr<Ipv6Interface> incomingInterface)
1175 {
1176  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1178  ":" << m_endPoint6->GetPeerPort () <<
1179  " to " << m_endPoint6->GetLocalAddress () <<
1180  ":" << m_endPoint6->GetLocalPort ());
1181 
1182  Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port);
1183  Address toAddress = Inet6SocketAddress (header.GetDestinationAddress (),
1185 
1186  TcpHeader tcpHeader;
1187  uint32_t bytesRemoved = packet->PeekHeader (tcpHeader);
1188 
1189  if (!IsValidTcpSegment (tcpHeader.GetSequenceNumber (), bytesRemoved,
1190  packet->GetSize () - bytesRemoved))
1191  {
1192  return;
1193  }
1194 
1195  if (header.GetEcn() == Ipv6Header::ECN_CE && m_ecnCESeq < tcpHeader.GetSequenceNumber ())
1196  {
1197  NS_LOG_INFO ("Received CE flag is valid");
1198  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_CE_RCVD");
1199  m_ecnCESeq = tcpHeader.GetSequenceNumber ();
1202  }
1203  else if (header.GetEcn() != Ipv6Header::ECN_NotECT)
1204  {
1206  }
1207 
1208  DoForwardUp (packet, fromAddress, toAddress);
1209 }
1210 
1211 void
1212 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1213  uint8_t icmpType, uint8_t icmpCode,
1214  uint32_t icmpInfo)
1215 {
1216  NS_LOG_FUNCTION (this << icmpSource << static_cast<uint32_t> (icmpTtl) <<
1217  static_cast<uint32_t> (icmpType) <<
1218  static_cast<uint32_t> (icmpCode) << icmpInfo);
1219  if (!m_icmpCallback.IsNull ())
1220  {
1221  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1222  }
1223 }
1224 
1225 void
1226 TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1227  uint8_t icmpType, uint8_t icmpCode,
1228  uint32_t icmpInfo)
1229 {
1230  NS_LOG_FUNCTION (this << icmpSource << static_cast<uint32_t> (icmpTtl) <<
1231  static_cast<uint32_t> (icmpType) <<
1232  static_cast<uint32_t> (icmpCode) << icmpInfo);
1233  if (!m_icmpCallback6.IsNull ())
1234  {
1235  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1236  }
1237 }
1238 
1239 bool
1240 TcpSocketBase::IsValidTcpSegment (const SequenceNumber32 seq, const uint32_t tcpHeaderSize,
1241  const uint32_t tcpPayloadSize)
1242 {
1243  if (tcpHeaderSize == 0 || tcpHeaderSize > 60)
1244  {
1245  NS_LOG_ERROR ("Bytes removed: " << tcpHeaderSize << " invalid");
1246  return false; // Discard invalid packet
1247  }
1248  else if (tcpPayloadSize > 0 && OutOfRange (seq, seq + tcpPayloadSize))
1249  {
1250  // Discard fully out of range data packets
1251  NS_LOG_WARN ("At state " << TcpStateName[m_state] <<
1252  " received packet of seq [" << seq <<
1253  ":" << seq + tcpPayloadSize <<
1254  ") out of range [" << m_tcb->m_rxBuffer->NextRxSequence () << ":" <<
1255  m_tcb->m_rxBuffer->MaxRxSequence () << ")");
1256  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
1258  return false;
1259  }
1260  return true;
1261 }
1262 
1263 void
1264 TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress,
1265  const Address &toAddress)
1266 {
1267  // in case the packet still has a priority tag attached, remove it
1268  SocketPriorityTag priorityTag;
1269  packet->RemovePacketTag (priorityTag);
1270 
1271  // Peel off TCP header
1272  TcpHeader tcpHeader;
1273  packet->RemoveHeader (tcpHeader);
1274  SequenceNumber32 seq = tcpHeader.GetSequenceNumber ();
1275 
1276  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
1277  {
1278  // Check if the sender has responded to ECN echo by reducing the Congestion Window
1279  if (tcpHeader.GetFlags () & TcpHeader::CWR )
1280  {
1281  // Check if a packet with CE bit set is received. If there is no CE bit set, then change the state to ECN_IDLE to
1282  // stop sending ECN Echo messages. If there is CE bit set, the packet should continue sending ECN Echo messages
1283  //
1285  {
1288  }
1289  }
1290  }
1291 
1292  m_rxTrace (packet, tcpHeader, this);
1293 
1294  if (tcpHeader.GetFlags () & TcpHeader::SYN)
1295  {
1296  /* The window field in a segment where the SYN bit is set (i.e., a <SYN>
1297  * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be
1298  * saved anyway..
1299  */
1300  m_rWnd = tcpHeader.GetWindowSize ();
1301 
1303  {
1305  }
1306  else
1307  {
1308  m_winScalingEnabled = false;
1309  }
1310 
1312  {
1314  }
1315  else
1316  {
1317  m_sackEnabled = false;
1318  m_txBuffer->SetSackEnabled (false);
1319  }
1320 
1321  // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end
1322  if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled)
1323  {
1325  tcpHeader.GetSequenceNumber ());
1326  }
1327  else
1328  {
1329  m_timestampEnabled = false;
1330  }
1331 
1332  // Initialize cWnd and ssThresh
1336 
1337  if (tcpHeader.GetFlags () & TcpHeader::ACK)
1338  {
1339  EstimateRtt (tcpHeader);
1340  m_highRxAckMark = tcpHeader.GetAckNumber ();
1341  }
1342  }
1343  else if (tcpHeader.GetFlags () & TcpHeader::ACK)
1344  {
1345  NS_ASSERT (!(tcpHeader.GetFlags () & TcpHeader::SYN));
1346  if (m_timestampEnabled)
1347  {
1348  if (!tcpHeader.HasOption (TcpOption::TS))
1349  {
1350  // Ignoring segment without TS, RFC 7323
1351  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1352  " received packet of seq [" << seq <<
1353  ":" << seq + packet->GetSize () <<
1354  ") without TS option. Silently discard it");
1355  return;
1356  }
1357  else
1358  {
1360  tcpHeader.GetSequenceNumber ());
1361  }
1362  }
1363 
1364  EstimateRtt (tcpHeader);
1365  UpdateWindowSize (tcpHeader);
1366  }
1367 
1368 
1369  if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ())
1370  { // Zero window: Enter persist state to send 1 byte to probe
1371  NS_LOG_LOGIC (this << " Enter zerowindow persist state");
1372  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1373  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1374  m_retxEvent.Cancel ();
1375  NS_LOG_LOGIC ("Schedule persist timeout at time " <<
1376  Simulator::Now ().GetSeconds () << " to expire at time " <<
1377  (Simulator::Now () + m_persistTimeout).GetSeconds ());
1380  }
1381 
1382  // TCP state machine code in different process functions
1383  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1384  switch (m_state)
1385  {
1386  case ESTABLISHED:
1387  ProcessEstablished (packet, tcpHeader);
1388  break;
1389  case LISTEN:
1390  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
1391  break;
1392  case TIME_WAIT:
1393  // Do nothing
1394  break;
1395  case CLOSED:
1396  // Send RST if the incoming packet is not a RST
1397  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1398  { // Since m_endPoint is not configured yet, we cannot use SendRST here
1399  TcpHeader h;
1400  Ptr<Packet> p = Create<Packet> ();
1403  h.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
1404  h.SetSourcePort (tcpHeader.GetDestinationPort ());
1405  h.SetDestinationPort (tcpHeader.GetSourcePort ());
1407  AddOptions (h);
1408  m_txTrace (p, h, this);
1409  m_tcp->SendPacket (p, h, toAddress, fromAddress, m_boundnetdevice);
1410  }
1411  break;
1412  case SYN_SENT:
1413  ProcessSynSent (packet, tcpHeader);
1414  break;
1415  case SYN_RCVD:
1416  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1417  break;
1418  case FIN_WAIT_1:
1419  case FIN_WAIT_2:
1420  case CLOSE_WAIT:
1421  ProcessWait (packet, tcpHeader);
1422  break;
1423  case CLOSING:
1424  ProcessClosing (packet, tcpHeader);
1425  break;
1426  case LAST_ACK:
1427  ProcessLastAck (packet, tcpHeader);
1428  break;
1429  default: // mute compiler
1430  break;
1431  }
1432 
1433  if (m_rWnd.Get () != 0 && m_persistEvent.IsRunning ())
1434  { // persist probes end, the other end has increased the window
1436  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
1438 
1440  }
1441 }
1442 
1443 /* Received a packet upon ESTABLISHED state. This function is mimicking the
1444  role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1445 void
1447 {
1448  NS_LOG_FUNCTION (this << tcpHeader);
1449 
1450  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
1451  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
1452 
1453  // Different flags are different events
1454  if (tcpflags == TcpHeader::ACK)
1455  {
1456  if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ())
1457  {
1458  // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be ignored.
1459  // Pag. 72 RFC 793
1460  NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1461  " SND.UNA = " << m_txBuffer->HeadSequence ());
1462 
1463  // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation]
1464  }
1465  else if (tcpHeader.GetAckNumber () > m_tcb->m_highTxMark)
1466  {
1467  // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then
1468  // send an ACK, drop the segment, and return.
1469  // Pag. 72 RFC 793
1470  NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1471  " HighTxMark = " << m_tcb->m_highTxMark);
1472 
1473  // Receiver sets ECE flags when it receives a packet with CE bit on or sender hasn’t responded to ECN echo sent by receiver
1475  {
1477  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
1479  }
1480  else
1481  {
1483  }
1484  }
1485  else
1486  {
1487  // SND.UNA < SEG.ACK =< HighTxMark
1488  // Pag. 72 RFC 793
1489  ReceivedAck (packet, tcpHeader);
1490  }
1491  }
1492  else if (tcpflags == TcpHeader::SYN)
1493  { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1494  // respond with a SYN+ACK. But it is not a legal state transition as of
1495  // RFC793. Thus this is ignored.
1496  }
1497  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1498  { // No action for received SYN+ACK, it is probably a duplicated packet
1499  }
1500  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1501  { // Received FIN or FIN+ACK, bring down this socket nicely
1502  PeerClose (packet, tcpHeader);
1503  }
1504  else if (tcpflags == 0)
1505  { // No flags means there is only data
1506  ReceivedData (packet, tcpHeader);
1507  if (m_tcb->m_rxBuffer->Finished ())
1508  {
1509  PeerClose (packet, tcpHeader);
1510  }
1511  }
1512  else
1513  { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1514  if (tcpflags != TcpHeader::RST)
1515  { // this must be an invalid flag, send reset
1516  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
1517  SendRST ();
1518  }
1519  CloseAndNotify ();
1520  }
1521 }
1522 
1523 bool
1525 {
1526  NS_LOG_FUNCTION (this << static_cast<uint32_t> (kind));
1527 
1528  switch (kind)
1529  {
1530  case TcpOption::TS:
1531  return m_timestampEnabled;
1532  case TcpOption::WINSCALE:
1533  return m_winScalingEnabled;
1535  case TcpOption::SACK:
1536  return m_sackEnabled;
1537  default:
1538  break;
1539  }
1540  return false;
1541 }
1542 
1543 void
1544 TcpSocketBase::ReadOptions (const TcpHeader &tcpHeader, uint32_t *bytesSacked)
1545 {
1546  NS_LOG_FUNCTION (this << tcpHeader);
1547  TcpHeader::TcpOptionList::const_iterator it;
1548  const TcpHeader::TcpOptionList options = tcpHeader.GetOptionList ();
1549 
1550  for (it = options.begin (); it != options.end (); ++it)
1551  {
1552  const Ptr<const TcpOption> option = (*it);
1553 
1554  // Check only for ACK options here
1555  switch (option->GetKind ())
1556  {
1557  case TcpOption::SACK:
1558  *bytesSacked = ProcessOptionSack (option);
1559  break;
1560  default:
1561  continue;
1562  }
1563  }
1564 }
1565 
1566 void
1567 TcpSocketBase::EnterRecovery (uint32_t currentDelivered)
1568 {
1569  NS_LOG_FUNCTION (this);
1571 
1573  " -> CA_RECOVERY");
1574 
1575  if (!m_sackEnabled)
1576  {
1577  // One segment has left the network, PLUS the head is lost
1578  m_txBuffer->AddRenoSack ();
1579  m_txBuffer->MarkHeadAsLost ();
1580  }
1581  else
1582  {
1583  if (!m_txBuffer->IsLost (m_txBuffer->HeadSequence ()))
1584  {
1585  // We received 3 dupacks, but the head is not marked as lost
1586  // (received less than 3 SACK block ahead).
1587  // Manually set it as lost.
1588  m_txBuffer->MarkHeadAsLost ();
1589  }
1590  }
1591 
1592  // RFC 6675, point (4):
1593  // (4) Invoke fast retransmit and enter loss recovery as follows:
1594  // (4.1) RecoveryPoint = HighData
1596  m_recoverActive = true;
1597 
1598  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_RECOVERY);
1600 
1601  // (4.2) ssthresh = cwnd = (FlightSize / 2)
1602  // If SACK is not enabled, still consider the head as 'in flight' for
1603  // compatibility with old ns-3 versions
1604  uint32_t bytesInFlight = m_sackEnabled ? BytesInFlight () : BytesInFlight () + m_tcb->m_segmentSize;
1605  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, bytesInFlight);
1606 
1607  if (!m_congestionControl->HasCongControl ())
1608  {
1609  m_recoveryOps->EnterRecovery (m_tcb, m_dupAckCount, UnAckDataCount (), currentDelivered);
1610  NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." <<
1611  "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
1612  m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover <<
1613  " calculated in flight: " << bytesInFlight);
1614  }
1615 
1616 
1617  // (4.3) Retransmit the first data segment presumed dropped
1618  DoRetransmit ();
1619  // (4.4) Run SetPipe ()
1620  // (4.5) Proceed to step (C)
1621  // these steps are done after the ProcessAck function (SendPendingData)
1622 }
1623 
1624 void
1625 TcpSocketBase::DupAck (uint32_t currentDelivered)
1626 {
1627  NS_LOG_FUNCTION (this);
1628  // NOTE: We do not count the DupAcks received in CA_LOSS, because we
1629  // don't know if they are generated by a spurious retransmission or because
1630  // of a real packet loss. With SACK, it is easy to know, but we do not consider
1631  // dupacks. Without SACK, there are some euristics in the RFC 6582, but
1632  // for now, we do not implement it, leading to ignoring the dupacks.
1634  {
1635  return;
1636  }
1637 
1638  // RFC 6675, Section 5, 3rd paragraph:
1639  // If the incoming ACK is a duplicate acknowledgment per the definition
1640  // in Section 2 (regardless of its status as a cumulative
1641  // acknowledgment), and the TCP is not currently in loss recovery
1642  // the TCP MUST increase DupAcks by one ...
1644  {
1645  ++m_dupAckCount;
1646  }
1647 
1649  {
1650  // From Open we go Disorder
1651  NS_ASSERT_MSG (m_dupAckCount == 1, "From OPEN->DISORDER but with " <<
1652  m_dupAckCount << " dup ACKs");
1653 
1654  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_DISORDER);
1656 
1657  NS_LOG_DEBUG ("CA_OPEN -> CA_DISORDER");
1658  }
1659 
1661  {
1662  if (!m_sackEnabled)
1663  {
1664  // If we are in recovery and we receive a dupack, one segment
1665  // has left the network. This is equivalent to a SACK of one block.
1666  m_txBuffer->AddRenoSack ();
1667  }
1668  if (!m_congestionControl->HasCongControl ())
1669  {
1670  m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
1671  NS_LOG_INFO (m_dupAckCount << " Dupack received in fast recovery mode."
1672  "Increase cwnd to " << m_tcb->m_cWnd);
1673  }
1674  }
1676  {
1677  // m_dupackCount should not exceed its threshold in CA_DISORDER state
1678  // when m_recoverActive has not been set. When recovery point
1679  // have been set after timeout, the sender could enter into CA_DISORDER
1680  // after receiving new ACK smaller than m_recover. After that, m_dupackCount
1681  // can be equal and larger than m_retxThresh and we should avoid entering
1682  // CA_RECOVERY and reducing sending rate again.
1684 
1685  // RFC 6675, Section 5, continuing:
1686  // ... and take the following steps:
1687  // (1) If DupAcks >= DupThresh, go to step (4).
1688  // Sequence number comparison (m_highRxAckMark >= m_recover) will take
1689  // effect only when m_recover has been set. Hence, we can avoid to use
1690  // m_recover in the last congestion event and fail to enter
1691  // CA_RECOVERY when sequence number is advanced significantly since
1692  // the last congestion event, which could be common for
1693  // bandwidth-greedy application in high speed and reliable network
1694  // (such as datacenter network) whose sending rate is constrainted by
1695  // TCP socket buffer size at receiver side.
1697  {
1698  EnterRecovery (currentDelivered);
1700  }
1701  // (2) If DupAcks < DupThresh but IsLost (HighACK + 1) returns true
1702  // (indicating at least three segments have arrived above the current
1703  // cumulative acknowledgment point, which is taken to indicate loss)
1704  // go to step (4).
1705  else if (m_txBuffer->IsLost (m_highRxAckMark + m_tcb->m_segmentSize))
1706  {
1707  EnterRecovery (currentDelivered);
1709  }
1710  else
1711  {
1712  // (3) The TCP MAY transmit previously unsent data segments as per
1713  // Limited Transmit [RFC5681] ...except that the number of octets
1714  // which may be sent is governed by pipe and cwnd as follows:
1715  //
1716  // (3.1) Set HighRxt to HighACK.
1717  // Not clear in RFC. We don't do this here, since we still have
1718  // to retransmit the segment.
1719 
1720  if (!m_sackEnabled && m_limitedTx)
1721  {
1722  m_txBuffer->AddRenoSack ();
1723 
1724  // In limited transmit, cwnd Infl is not updated.
1725  }
1726  }
1727  }
1728 }
1729 
1730 /* Process the newly received ACK */
1731 void
1733 {
1734  NS_LOG_FUNCTION (this << tcpHeader);
1735 
1736  NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK));
1737  NS_ASSERT (m_tcb->m_segmentSize > 0);
1738 
1739  // RFC 6675, Section 5, 1st paragraph:
1740  // Upon the receipt of any ACK containing SACK information, the
1741  // scoreboard MUST be updated via the Update () routine (done in ReadOptions)
1742  uint32_t bytesSacked = 0;
1743  uint64_t previousDelivered = m_rateOps->GetConnectionRate ().m_delivered;
1744  ReadOptions (tcpHeader, &bytesSacked);
1745 
1746  SequenceNumber32 ackNumber = tcpHeader.GetAckNumber ();
1747  SequenceNumber32 oldHeadSequence = m_txBuffer->HeadSequence ();
1748 
1749  if (ackNumber < oldHeadSequence)
1750  {
1751  NS_LOG_DEBUG ("Possibly received a stale ACK (ack number < head sequence)");
1752  // If there is any data piggybacked, store it into m_rxBuffer
1753  if (packet->GetSize () > 0)
1754  {
1755  ReceivedData (packet, tcpHeader);
1756  }
1757  return;
1758  }
1759  if ((ackNumber > oldHeadSequence) && (ackNumber < m_recover)
1761  {
1762  uint32_t segAcked = (ackNumber - oldHeadSequence)/m_tcb->m_segmentSize;
1763  for (uint32_t i = 0; i < segAcked; i++)
1764  {
1765  if (m_txBuffer->IsRetransmittedDataAcked (ackNumber - (i * m_tcb->m_segmentSize)))
1766  {
1767  m_tcb->m_isRetransDataAcked = true;
1768  NS_LOG_DEBUG ("Ack Number " << ackNumber <<
1769  "is ACK of retransmitted packet.");
1770  }
1771  }
1772  }
1773 
1774  m_txBuffer->DiscardUpTo (ackNumber, MakeCallback (&TcpRateOps::SkbDelivered, m_rateOps));
1775 
1776  uint32_t currentDelivered = static_cast<uint32_t> (m_rateOps->GetConnectionRate ().m_delivered - previousDelivered);
1777 
1778  if (ackNumber > oldHeadSequence && (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED) && (tcpHeader.GetFlags () & TcpHeader::ECE))
1779  {
1780  if (m_ecnEchoSeq < ackNumber)
1781  {
1782  NS_LOG_INFO ("Received ECN Echo is valid");
1783  m_ecnEchoSeq = ackNumber;
1784  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_ECE_RCVD");
1786  }
1787  }
1788  else if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && !(tcpHeader.GetFlags () & TcpHeader::ECE))
1789  {
1791  }
1792 
1793  // Update bytes in flight before processing the ACK for proper calculation of congestion window
1794  NS_LOG_INFO ("Update bytes in flight before processing the ACK.");
1795  BytesInFlight ();
1796 
1797  // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation
1798  // are inside the function ProcessAck
1799  ProcessAck (ackNumber, (bytesSacked > 0), currentDelivered, oldHeadSequence);
1800  m_tcb->m_isRetransDataAcked = false;
1801 
1802  if (m_congestionControl->HasCongControl ())
1803  {
1804  uint32_t previousLost = m_txBuffer->GetLost ();
1805  uint32_t priorInFlight = m_tcb->m_bytesInFlight.Get ();
1806  uint32_t currentLost = m_txBuffer->GetLost ();
1807  uint32_t lost = (currentLost > previousLost) ?
1808  currentLost - previousLost :
1809  previousLost - currentLost;
1810  auto rateSample = m_rateOps->GenerateSample (currentDelivered, lost,
1811  false, priorInFlight, m_tcb->m_minRtt);
1812  auto rateConn = m_rateOps->GetConnectionRate ();
1813  m_congestionControl->CongControl(m_tcb, rateConn, rateSample);
1814  }
1815 
1816  // If there is any data piggybacked, store it into m_rxBuffer
1817  if (packet->GetSize () > 0)
1818  {
1819  ReceivedData (packet, tcpHeader);
1820  }
1821 
1822  // RFC 6675, Section 5, point (C), try to send more data. NB: (C) is implemented
1823  // inside SendPendingData
1825 }
1826 
1827 void
1828 TcpSocketBase::ProcessAck(const SequenceNumber32 &ackNumber, bool scoreboardUpdated,
1829  uint32_t currentDelivered, const SequenceNumber32 &oldHeadSequence)
1830 {
1831  NS_LOG_FUNCTION (this << ackNumber << scoreboardUpdated);
1832  // RFC 6675, Section 5, 2nd paragraph:
1833  // If the incoming ACK is a cumulative acknowledgment, the TCP MUST
1834  // reset DupAcks to zero.
1835  bool exitedFastRecovery = false;
1836  uint32_t oldDupAckCount = m_dupAckCount; // remember the old value
1837  m_tcb->m_lastAckedSeq = ackNumber; // Update lastAckedSeq
1838  uint32_t bytesAcked = 0;
1839 
1840  /* In RFC 5681 the definition of duplicate acknowledgment was strict:
1841  *
1842  * (a) the receiver of the ACK has outstanding data,
1843  * (b) the incoming acknowledgment carries no data,
1844  * (c) the SYN and FIN bits are both off,
1845  * (d) the acknowledgment number is equal to the greatest acknowledgment
1846  * received on the given connection (TCP.UNA from [RFC793]),
1847  * (e) the advertised window in the incoming acknowledgment equals the
1848  * advertised window in the last incoming acknowledgment.
1849  *
1850  * With RFC 6675, this definition has been reduced:
1851  *
1852  * (a) the ACK is carrying a SACK block that identifies previously
1853  * unacknowledged and un-SACKed octets between HighACK (TCP.UNA) and
1854  * HighData (m_highTxMark)
1855  */
1856 
1857  bool isDupack = m_sackEnabled ?
1858  scoreboardUpdated
1859  : ackNumber == oldHeadSequence &&
1860  ackNumber < m_tcb->m_highTxMark;
1861 
1862  NS_LOG_DEBUG ("ACK of " << ackNumber <<
1863  " SND.UNA=" << oldHeadSequence <<
1864  " SND.NXT=" << m_tcb->m_nextTxSequence <<
1865  " in state: " << TcpSocketState::TcpCongStateName[m_tcb->m_congState] <<
1866  " with m_recover: " << m_recover);
1867 
1868  // RFC 6675, Section 5, 3rd paragraph:
1869  // If the incoming ACK is a duplicate acknowledgment per the definition
1870  // in Section 2 (regardless of its status as a cumulative
1871  // acknowledgment), and the TCP is not currently in loss recovery
1872  if (isDupack)
1873  {
1874  // loss recovery check is done inside this function thanks to
1875  // the congestion state machine
1876  DupAck (currentDelivered);
1877  }
1878 
1879  if (ackNumber == oldHeadSequence
1880  && ackNumber == m_tcb->m_highTxMark)
1881  {
1882  // Dupack, but the ACK is precisely equal to the nextTxSequence
1883  return;
1884  }
1885  else if (ackNumber == oldHeadSequence
1886  && ackNumber > m_tcb->m_highTxMark)
1887  {
1888  // ACK of the FIN bit ... nextTxSequence is not updated since we
1889  // don't have anything to transmit
1890  NS_LOG_DEBUG ("Update nextTxSequence manually to " << ackNumber);
1891  m_tcb->m_nextTxSequence = ackNumber;
1892  }
1893  else if (ackNumber == oldHeadSequence)
1894  {
1895  // DupAck. Artificially call PktsAcked: after all, one segment has been ACKed.
1896  m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
1897  }
1898  else if (ackNumber > oldHeadSequence)
1899  {
1900  // Please remember that, with SACK, we can enter here even if we
1901  // received a dupack.
1902  bytesAcked = ackNumber - oldHeadSequence;
1903  uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
1904  m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize;
1905  bytesAcked -= bytesAcked % m_tcb->m_segmentSize;
1906 
1908  {
1909  segsAcked += 1;
1910  bytesAcked += m_tcb->m_segmentSize;
1912  }
1913 
1914  // Dupack count is reset to eventually fast-retransmit after 3 dupacks.
1915  // Any SACK-ed segment will be cleaned up by DiscardUpTo.
1916  // In the case that we advanced SND.UNA, but the ack contains SACK blocks,
1917  // we do not reset. At the third one we will retransmit.
1918  // If we are already in recovery, this check is useless since dupAcks
1919  // are not considered in this phase. When from Recovery we go back
1920  // to open, then dupAckCount is reset anyway.
1921  if (!isDupack)
1922  {
1923  m_dupAckCount = 0;
1924  }
1925 
1926  // RFC 6675, Section 5, part (B)
1927  // (B) Upon receipt of an ACK that does not cover RecoveryPoint, the
1928  // following actions MUST be taken:
1929  //
1930  // (B.1) Use Update () to record the new SACK information conveyed
1931  // by the incoming ACK.
1932  // (B.2) Use SetPipe () to re-calculate the number of octets still
1933  // in the network.
1934  //
1935  // (B.1) is done at the beginning, while (B.2) is delayed to part (C) while
1936  // trying to transmit with SendPendingData. We are not allowed to exit
1937  // the CA_RECOVERY phase. Just process this partial ack (RFC 5681)
1938  if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1939  {
1940  if (!m_sackEnabled)
1941  {
1942  // Manually set the head as lost, it will be retransmitted.
1943  NS_LOG_INFO ("Partial ACK. Manually setting head as lost");
1944  m_txBuffer->MarkHeadAsLost ();
1945  }
1946 
1947  // Before retransmitting the packet perform DoRecovery and check if
1948  // there is available window
1949  if (!m_congestionControl->HasCongControl () && segsAcked >= 1)
1950  {
1951  m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
1952  }
1953 
1954  // If the packet is already retransmitted do not retransmit it
1955  if (!m_txBuffer->IsRetransmittedDataAcked (ackNumber + m_tcb->m_segmentSize))
1956  {
1957  DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
1958  m_tcb->m_cWndInfl = SafeSubtraction (m_tcb->m_cWndInfl, bytesAcked);
1959  }
1960 
1961  // This partial ACK acknowledge the fact that one segment has been
1962  // previously lost and now successfully received. All others have
1963  // been processed when they come under the form of dupACKs
1964  m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
1965  NewAck (ackNumber, m_isFirstPartialAck);
1966 
1967  if (m_isFirstPartialAck)
1968  {
1969  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
1970  " and this is the first (RTO will be reset);"
1971  " cwnd set to " << m_tcb->m_cWnd <<
1972  " recover seq: " << m_recover <<
1973  " dupAck count: " << m_dupAckCount);
1974  m_isFirstPartialAck = false;
1975  }
1976  else
1977  {
1978  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
1979  " and this is NOT the first (RTO will not be reset)"
1980  " cwnd set to " << m_tcb->m_cWnd <<
1981  " recover seq: " << m_recover <<
1982  " dupAck count: " << m_dupAckCount);
1983  }
1984  }
1985  // From RFC 6675 section 5.1
1986  // In addition, a new recovery phase (as described in Section 5) MUST NOT
1987  // be initiated until HighACK is greater than or equal to the new value
1988  // of RecoveryPoint.
1989  else if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_LOSS)
1990  {
1991  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
1992  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
1993 
1994  NS_LOG_DEBUG (" Cong Control Called, cWnd=" << m_tcb->m_cWnd <<
1995  " ssTh=" << m_tcb->m_ssThresh);
1996  if (!m_sackEnabled)
1997  {
1998  NS_ASSERT_MSG (m_txBuffer->GetSacked () == 0,
1999  "Some segment got dup-acked in CA_LOSS state: " <<
2000  m_txBuffer->GetSacked ());
2001  }
2002  NewAck (ackNumber, true);
2003  }
2004  else
2005  {
2007  {
2008  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2009  }
2011  {
2012  if (segsAcked >= oldDupAckCount)
2013  {
2014  m_congestionControl->PktsAcked (m_tcb, segsAcked - oldDupAckCount, m_tcb->m_lastRtt);
2015  }
2016 
2017  if (!isDupack)
2018  {
2019  // The network reorder packets. Linux changes the counting lost
2020  // packet algorithm from FACK to NewReno. We simply go back in Open.
2021  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2023  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
2024  ackNumber << " exiting CA_DISORDER -> CA_OPEN");
2025  }
2026  else
2027  {
2028  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
2029  ackNumber << " but still in CA_DISORDER");
2030  }
2031  }
2032  // RFC 6675, Section 5:
2033  // Once a TCP is in the loss recovery phase, the following procedure
2034  // MUST be used for each arriving ACK:
2035  // (A) An incoming cumulative ACK for a sequence number greater than
2036  // RecoveryPoint signals the end of loss recovery, and the loss
2037  // recovery phase MUST be terminated. Any information contained in
2038  // the scoreboard for sequence numbers greater than the new value of
2039  // HighACK SHOULD NOT be cleared when leaving the loss recovery
2040  // phase.
2042  {
2043  m_isFirstPartialAck = true;
2044 
2045  // Recalculate the segs acked, that are from m_recover to ackNumber
2046  // (which are the ones we have not passed to PktsAcked and that
2047  // can increase cWnd)
2048  // TODO: check consistency for dynamic segment size
2049  segsAcked = static_cast<uint32_t>(ackNumber - oldHeadSequence) / m_tcb->m_segmentSize;
2050  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2052  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2054  exitedFastRecovery = true;
2055  m_dupAckCount = 0; // From recovery to open, reset dupack
2056 
2057  NS_LOG_DEBUG (segsAcked << " segments acked in CA_RECOVER, ack of " <<
2058  ackNumber << ", exiting CA_RECOVERY -> CA_OPEN");
2059  }
2061  {
2062  m_isFirstPartialAck = true;
2063 
2064  // Recalculate the segs acked, that are from m_recover to ackNumber
2065  // (which are the ones we have not passed to PktsAcked and that
2066  // can increase cWnd)
2067  segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
2068 
2069  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2070 
2071  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2073  NS_LOG_DEBUG (segsAcked << " segments acked in CA_LOSS, ack of" <<
2074  ackNumber << ", exiting CA_LOSS -> CA_OPEN");
2075  }
2076 
2077  if (ackNumber >= m_recover)
2078  {
2079  // All lost segments in the congestion event have been
2080  // retransmitted successfully. The recovery point (m_recover)
2081  // should be deactivated.
2082  m_recoverActive = false;
2083  }
2084 
2085  if (exitedFastRecovery)
2086  {
2087  NewAck (ackNumber, true);
2088  m_recoveryOps->ExitRecovery (m_tcb);
2089  NS_LOG_DEBUG ("Leaving Fast Recovery; BytesInFlight() = " <<
2090  BytesInFlight () << "; cWnd = " << m_tcb->m_cWnd);
2091  }
2093  {
2094  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
2095 
2097 
2098  NS_LOG_LOGIC ("Congestion control called: " <<
2099  " cWnd: " << m_tcb->m_cWnd <<
2100  " ssTh: " << m_tcb->m_ssThresh <<
2101  " segsAcked: " << segsAcked);
2102 
2103  NewAck (ackNumber, true);
2104  }
2105  }
2106  }
2107  // Update the pacing rate, since m_congestionControl->IncreaseWindow() or
2108  // m_congestionControl->PktsAcked () may change m_tcb->m_cWnd
2109  // Make sure that control reaches the end of this function and there is no
2110  // return in between
2111  UpdatePacingRate ();
2112 }
2113 
2114 /* Received a packet upon LISTEN state. */
2115 void
2117  const Address& fromAddress, const Address& toAddress)
2118 {
2119  NS_LOG_FUNCTION (this << tcpHeader);
2120 
2121  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2122  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2123 
2124  // Fork a socket if received a SYN. Do nothing otherwise.
2125  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
2126  if (tcpflags != TcpHeader::SYN)
2127  {
2128  return;
2129  }
2130 
2131  // Call socket's notify function to let the server app know we got a SYN
2132  // If the server app refuses the connection, do nothing
2133  if (!NotifyConnectionRequest (fromAddress))
2134  {
2135  return;
2136  }
2137  // Clone the socket, simulate fork
2138  Ptr<TcpSocketBase> newSock = Fork ();
2139  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
2141  packet, tcpHeader, fromAddress, toAddress);
2142 }
2143 
2144 /* Received a packet upon SYN_SENT */
2145 void
2147 {
2148  NS_LOG_FUNCTION (this << tcpHeader);
2149 
2150  // Extract the flags. PSH and URG are disregarded.
2151  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2152 
2153  if (tcpflags == 0)
2154  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
2155  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2156  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2158  m_state = ESTABLISHED;
2159  m_connected = true;
2160  m_retxEvent.Cancel ();
2162  ReceivedData (packet, tcpHeader);
2164  }
2165  else if (tcpflags & TcpHeader::ACK && !(tcpflags & TcpHeader::SYN))
2166  { // Ignore ACK in SYN_SENT
2167  }
2168  else if (tcpflags & TcpHeader::SYN && !(tcpflags & TcpHeader::ACK))
2169  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
2170  NS_LOG_DEBUG ("SYN_SENT -> SYN_RCVD");
2171  m_state = SYN_RCVD;
2173  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2174  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if the traffic is ECN capable and
2175  * sender has sent ECN SYN packet
2176  */
2177 
2179  {
2180  NS_LOG_INFO ("Received ECN SYN packet");
2184  }
2185  else
2186  {
2189  }
2190  }
2191  else if (tcpflags & (TcpHeader::SYN | TcpHeader::ACK)
2192  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
2193  { // Handshake completed
2194  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2195  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2197  m_state = ESTABLISHED;
2198  m_connected = true;
2199  m_retxEvent.Cancel ();
2200  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2202  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2203  // Before sending packets, update the pacing rate based on RTT measurement so far
2204  UpdatePacingRate ();
2206 
2207  /* Check if we received an ECN SYN-ACK packet. Change the ECN state of sender to ECN_IDLE if receiver has sent an ECN SYN-ACK
2208  * packet and the traffic is ECN Capable
2209  */
2211  {
2212  NS_LOG_INFO ("Received ECN SYN-ACK packet.");
2215  }
2216  else
2217  {
2219  }
2222  // Always respond to first data packet to speed up the connection.
2223  // Remove to get the behaviour of old NS-3 code.
2225  }
2226  else
2227  { // Other in-sequence input
2228  if (!(tcpflags & TcpHeader::RST))
2229  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
2230  NS_LOG_LOGIC ("Illegal flag combination " << TcpHeader::FlagsToString (tcpHeader.GetFlags ()) <<
2231  " received in SYN_SENT. Reset packet is sent.");
2232  SendRST ();
2233  }
2234  CloseAndNotify ();
2235  }
2236 }
2237 
2238 /* Received a packet upon SYN_RCVD */
2239 void
2241  const Address& fromAddress, const Address& toAddress)
2242 {
2243  NS_UNUSED (toAddress);
2244  NS_LOG_FUNCTION (this << tcpHeader);
2245 
2246  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2247  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2248 
2249  if (tcpflags == 0
2250  || (tcpflags == TcpHeader::ACK
2251  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
2252  { // If it is bare data, accept it and move to ESTABLISHED state. This is
2253  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
2254  // handshake is completed nicely.
2255  NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED");
2256  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2258  m_state = ESTABLISHED;
2259  m_connected = true;
2260  m_retxEvent.Cancel ();
2262  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2263  if (m_endPoint)
2264  {
2265  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2266  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2267  }
2268  else if (m_endPoint6)
2269  {
2270  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2271  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2272  }
2273  // Always respond to first data packet to speed up the connection.
2274  // Remove to get the behaviour of old NS-3 code.
2276  NotifyNewConnectionCreated (this, fromAddress);
2277  ReceivedAck (packet, tcpHeader);
2278  // Update the pacing rate based on RTT measurement so far
2279  UpdatePacingRate ();
2280  // As this connection is established, the socket is available to send data now
2281  if (GetTxAvailable () > 0)
2282  {
2284  }
2285  }
2286  else if (tcpflags == TcpHeader::SYN)
2287  { // Probably the peer lost my SYN+ACK
2288  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2289  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2290  * packet and the traffic is ECN Capable
2291  */
2293  {
2294  NS_LOG_INFO ("Received ECN SYN packet");
2298  }
2299  else
2300  {
2303  }
2304  }
2305  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2306  {
2307  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2308  { // In-sequence FIN before connection complete. Set up connection and close.
2309  m_connected = true;
2310  m_retxEvent.Cancel ();
2312  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2313  if (m_endPoint)
2314  {
2315  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2316  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2317  }
2318  else if (m_endPoint6)
2319  {
2320  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2321  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2322  }
2323  NotifyNewConnectionCreated (this, fromAddress);
2324  PeerClose (packet, tcpHeader);
2325  }
2326  }
2327  else
2328  { // Other in-sequence input
2329  if (tcpflags != TcpHeader::RST)
2330  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
2331  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2332  " received. Reset packet is sent.");
2333  if (m_endPoint)
2334  {
2335  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2336  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2337  }
2338  else if (m_endPoint6)
2339  {
2340  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2341  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2342  }
2343  SendRST ();
2344  }
2345  CloseAndNotify ();
2346  }
2347 }
2348 
2349 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
2350 void
2352 {
2353  NS_LOG_FUNCTION (this << tcpHeader);
2354 
2355  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2356  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2357 
2358  if (packet->GetSize () > 0 && !(tcpflags & TcpHeader::ACK))
2359  { // Bare data, accept it
2360  ReceivedData (packet, tcpHeader);
2361  }
2362  else if (tcpflags == TcpHeader::ACK)
2363  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
2364  ReceivedAck (packet, tcpHeader);
2365  if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
2366  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2367  { // This ACK corresponds to the FIN sent
2368  NS_LOG_DEBUG ("FIN_WAIT_1 -> FIN_WAIT_2");
2369  m_state = FIN_WAIT_2;
2370  }
2371  }
2372  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2373  { // Got FIN, respond with ACK and move to next state
2374  if (tcpflags & TcpHeader::ACK)
2375  { // Process the ACK first
2376  ReceivedAck (packet, tcpHeader);
2377  }
2378  m_tcb->m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
2379  }
2380  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
2381  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
2382  return;
2383  }
2384  else
2385  { // This is a RST or bad flags
2386  if (tcpflags != TcpHeader::RST)
2387  {
2388  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2389  " received. Reset packet is sent.");
2390  SendRST ();
2391  }
2392  CloseAndNotify ();
2393  return;
2394  }
2395 
2396  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
2397  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_tcb->m_rxBuffer->Finished ())
2398  {
2399  if (m_state == FIN_WAIT_1)
2400  {
2401  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2402  m_state = CLOSING;
2403  if (m_txBuffer->Size () == 0
2404  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2405  { // This ACK corresponds to the FIN sent
2406  TimeWait ();
2407  }
2408  }
2409  else if (m_state == FIN_WAIT_2)
2410  {
2411  TimeWait ();
2412  }
2414  if (!m_shutdownRecv)
2415  {
2416  NotifyDataRecv ();
2417  }
2418  }
2419 }
2420 
2421 /* Received a packet upon CLOSING */
2422 void
2424 {
2425  NS_LOG_FUNCTION (this << tcpHeader);
2426 
2427  // Extract the flags. PSH and URG are disregarded.
2428  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2429 
2430  if (tcpflags == TcpHeader::ACK)
2431  {
2432  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2433  { // This ACK corresponds to the FIN sent
2434  TimeWait ();
2435  }
2436  }
2437  else
2438  { // CLOSING state means simultaneous close, i.e. no one is sending data to
2439  // anyone. If anything other than ACK is received, respond with a reset.
2440  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2441  { // FIN from the peer as well. We can close immediately.
2443  }
2444  else if (tcpflags != TcpHeader::RST)
2445  { // Receive of SYN or SYN+ACK or bad flags or pure data
2446  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2447  SendRST ();
2448  }
2449  CloseAndNotify ();
2450  }
2451 }
2452 
2453 /* Received a packet upon LAST_ACK */
2454 void
2456 {
2457  NS_LOG_FUNCTION (this << tcpHeader);
2458 
2459  // Extract the flags. PSH and URG are disregarded.
2460  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2461 
2462  if (tcpflags == 0)
2463  {
2464  ReceivedData (packet, tcpHeader);
2465  }
2466  else if (tcpflags == TcpHeader::ACK)
2467  {
2468  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2469  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
2470  CloseAndNotify ();
2471  }
2472  }
2473  else if (tcpflags == TcpHeader::FIN)
2474  { // Received FIN again, the peer probably lost the FIN+ACK
2476  }
2477  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2478  {
2479  CloseAndNotify ();
2480  }
2481  else
2482  { // Received a SYN or SYN+ACK or bad flags
2483  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2484  SendRST ();
2485  CloseAndNotify ();
2486  }
2487 }
2488 
2489 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
2490 void
2492 {
2493  NS_LOG_FUNCTION (this << tcpHeader);
2494 
2495  // Ignore all out of range packets
2496  if (tcpHeader.GetSequenceNumber () < m_tcb->m_rxBuffer->NextRxSequence ()
2497  || tcpHeader.GetSequenceNumber () > m_tcb->m_rxBuffer->MaxRxSequence ())
2498  {
2499  return;
2500  }
2501  // For any case, remember the FIN position in rx buffer first
2502  m_tcb->m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2503  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2504  // If there is any piggybacked data, process it
2505  if (p->GetSize ())
2506  {
2507  ReceivedData (p, tcpHeader);
2508  }
2509  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2510  if (!m_tcb->m_rxBuffer->Finished ())
2511  {
2512  return;
2513  }
2514 
2515  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2516  if (m_state == FIN_WAIT_1)
2517  {
2518  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2519  m_state = CLOSING;
2520  return;
2521  }
2522 
2523  DoPeerClose (); // Change state, respond with ACK
2524 }
2525 
2526 /* Received a in-sequence FIN. Close down this socket. */
2527 void
2529 {
2532 
2533  // Move the state to CLOSE_WAIT
2534  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSE_WAIT");
2535  m_state = CLOSE_WAIT;
2536 
2537  if (!m_closeNotified)
2538  {
2539  // The normal behaviour for an application is that, when the peer sent a in-sequence
2540  // FIN, the app should prepare to close. The app has two choices at this point: either
2541  // respond with ShutdownSend() call to declare that it has nothing more to send and
2542  // the socket can be closed immediately; or remember the peer's close request, wait
2543  // until all its existing data are pushed into the TCP socket, then call Close()
2544  // explicitly.
2545  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
2546  NotifyNormalClose ();
2547  m_closeNotified = true;
2548  }
2549  if (m_shutdownSend)
2550  { // The application declares that it would not sent any more, close this socket
2551  Close ();
2552  }
2553  else
2554  { // Need to ack, the application will close later
2556  }
2557  if (m_state == LAST_ACK)
2558  {
2559  m_dataRetrCount = m_dataRetries; // prevent endless FINs
2560  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
2561  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
2563  }
2564 }
2565 
2566 /* Kill this socket. This is a callback function configured to m_endpoint in
2567  SetupCallback(), invoked when the endpoint is destroyed. */
2568 void
2570 {
2571  NS_LOG_FUNCTION (this);
2572  m_endPoint = nullptr;
2573  if (m_tcp != nullptr)
2574  {
2575  m_tcp->RemoveSocket (this);
2576  }
2577  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2578  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2579  CancelAllTimers ();
2580 }
2581 
2582 /* Kill this socket. This is a callback function configured to m_endpoint in
2583  SetupCallback(), invoked when the endpoint is destroyed. */
2584 void
2586 {
2587  NS_LOG_FUNCTION (this);
2588  m_endPoint6 = nullptr;
2589  if (m_tcp != nullptr)
2590  {
2591  m_tcp->RemoveSocket (this);
2592  }
2593  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2594  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2595  CancelAllTimers ();
2596 }
2597 
2598 /* Send an empty packet with specified TCP flags */
2599 void
2601 {
2602  NS_LOG_FUNCTION (this << static_cast<uint32_t> (flags));
2603 
2604  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
2605  {
2606  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
2607  return;
2608  }
2609 
2610  Ptr<Packet> p = Create<Packet> ();
2611  TcpHeader header;
2613 
2614  if (flags & TcpHeader::FIN)
2615  {
2616  flags |= TcpHeader::ACK;
2617  }
2618  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2619  {
2620  ++s;
2621  }
2622 
2623  AddSocketTags (p);
2624 
2625  header.SetFlags (flags);
2626  header.SetSequenceNumber (s);
2627  header.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
2628  if (m_endPoint != nullptr)
2629  {
2630  header.SetSourcePort (m_endPoint->GetLocalPort ());
2631  header.SetDestinationPort (m_endPoint->GetPeerPort ());
2632  }
2633  else
2634  {
2635  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2636  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
2637  }
2638  AddOptions (header);
2639 
2640  // RFC 6298, clause 2.4
2641  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2642 
2643  uint16_t windowSize = AdvertisedWindowSize ();
2644  bool hasSyn = flags & TcpHeader::SYN;
2645  bool hasFin = flags & TcpHeader::FIN;
2646  bool isAck = flags == TcpHeader::ACK;
2647  if (hasSyn)
2648  {
2649  if (m_winScalingEnabled)
2650  { // The window scaling option is set only on SYN packets
2651  AddOptionWScale (header);
2652  }
2653 
2654  if (m_sackEnabled)
2655  {
2656  AddOptionSackPermitted (header);
2657  }
2658 
2659  if (m_synCount == 0)
2660  { // No more connection retries, give up
2661  NS_LOG_LOGIC ("Connection failed.");
2662  m_rtt->Reset (); //According to recommendation -> RFC 6298
2664  m_state = CLOSED;
2665  DeallocateEndPoint ();
2666  return;
2667  }
2668  else
2669  { // Exponential backoff of connection time out
2670  int backoffCount = 0x1 << (m_synRetries - m_synCount);
2671  m_rto = m_cnTimeout * backoffCount;
2672  m_synCount--;
2673  }
2674 
2675  if (m_synRetries - 1 == m_synCount)
2676  {
2677  UpdateRttHistory (s, 0, false);
2678  }
2679  else
2680  { // This is SYN retransmission
2681  UpdateRttHistory (s, 0, true);
2682  }
2683 
2684  windowSize = AdvertisedWindowSize (false);
2685  }
2686  header.SetWindowSize (windowSize);
2687 
2688  if (flags & TcpHeader::ACK)
2689  { // If sending an ACK, cancel the delay ACK as well
2690  m_delAckEvent.Cancel ();
2691  m_delAckCount = 0;
2692  if (m_highTxAck < header.GetAckNumber ())
2693  {
2694  m_highTxAck = header.GetAckNumber ();
2695  }
2696  if (m_sackEnabled && m_tcb->m_rxBuffer->GetSackListSize () > 0)
2697  {
2698  AddOptionSack (header);
2699  }
2700  NS_LOG_INFO ("Sending a pure ACK, acking seq " << m_tcb->m_rxBuffer->NextRxSequence ());
2701  }
2702 
2703  m_txTrace (p, header, this);
2704 
2705  if (m_endPoint != nullptr)
2706  {
2707  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2709  }
2710  else
2711  {
2712  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2714  }
2715 
2716 
2717  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
2718  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2719  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
2720  << Simulator::Now ().GetSeconds () << " to expire at time "
2721  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2723  }
2724 }
2725 
2726 /* This function closes the endpoint completely. Called upon RST_TX action. */
2727 void
2729 {
2730  NS_LOG_FUNCTION (this);
2732  NotifyErrorClose ();
2733  DeallocateEndPoint ();
2734 }
2735 
2736 /* Deallocate the end point and cancel all the timers */
2737 void
2739 {
2740  if (m_endPoint != nullptr)
2741  {
2742  CancelAllTimers ();
2743  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
2744  m_tcp->DeAllocate (m_endPoint);
2745  m_endPoint = nullptr;
2746  m_tcp->RemoveSocket (this);
2747  }
2748  else if (m_endPoint6 != nullptr)
2749  {
2750  CancelAllTimers ();
2751  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
2752  m_tcp->DeAllocate (m_endPoint6);
2753  m_endPoint6 = nullptr;
2754  m_tcp->RemoveSocket (this);
2755  }
2756 }
2757 
2758 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2759 int
2761 {
2762  NS_LOG_FUNCTION (this);
2763  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
2764  NS_ASSERT (ipv4 != nullptr);
2765  if (ipv4->GetRoutingProtocol () == nullptr)
2766  {
2767  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
2768  }
2769  // Create a dummy packet, then ask the routing function for the best output
2770  // interface's address
2771  Ipv4Header header;
2773  Socket::SocketErrno errno_;
2774  Ptr<Ipv4Route> route;
2776  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2777  if (route == 0)
2778  {
2779  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
2780  NS_LOG_ERROR (errno_);
2781  m_errno = errno_;
2782  return -1;
2783  }
2784  NS_LOG_LOGIC ("Route exists");
2785  m_endPoint->SetLocalAddress (route->GetSource ());
2786  return 0;
2787 }
2788 
2789 int
2791 {
2792  NS_LOG_FUNCTION (this);
2794  NS_ASSERT (ipv6 != nullptr);
2795  if (ipv6->GetRoutingProtocol () == nullptr)
2796  {
2797  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
2798  }
2799  // Create a dummy packet, then ask the routing function for the best output
2800  // interface's address
2801  Ipv6Header header;
2803  Socket::SocketErrno errno_;
2804  Ptr<Ipv6Route> route;
2806  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2807  if (route == nullptr)
2808  {
2809  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
2810  NS_LOG_ERROR (errno_);
2811  m_errno = errno_;
2812  return -1;
2813  }
2814  NS_LOG_LOGIC ("Route exists");
2815  m_endPoint6->SetLocalAddress (route->GetSource ());
2816  return 0;
2817 }
2818 
2819 /* This function is called only if a SYN received in LISTEN state. After
2820  TcpSocketBase cloned, allocate a new end point to handle the incoming
2821  connection and send a SYN+ACK to complete the handshake. */
2822 void
2824  const Address& fromAddress, const Address& toAddress)
2825 {
2826  NS_LOG_FUNCTION (this << p << h << fromAddress << toAddress);
2827  NS_UNUSED (p);
2828  // Get port and address from peer (connecting host)
2829  if (InetSocketAddress::IsMatchingType (toAddress))
2830  {
2831  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (),
2832  InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
2833  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
2834  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2835  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2836  m_endPoint6 = nullptr;
2837  }
2838  else if (Inet6SocketAddress::IsMatchingType (toAddress))
2839  {
2840  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (),
2841  Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
2842  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
2843  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2844  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2845  m_endPoint = nullptr;
2846  }
2847  m_tcp->AddSocket (this);
2848 
2849  // Change the cloned socket from LISTEN state to SYN_RCVD
2850  NS_LOG_DEBUG ("LISTEN -> SYN_RCVD");
2851  m_state = SYN_RCVD;
2854  SetupCallback ();
2855  // Set the sequence number and send SYN+ACK
2856  m_tcb->m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
2857 
2858  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2859  * packet and the traffic is ECN Capable
2860  */
2863  {
2867  }
2868  else
2869  {
2872  }
2873 }
2874 
2875 void
2877 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
2878  // be called as a scheduled event
2880  // The if-block below was moved from ProcessSynSent() to here because we need
2881  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
2882  // reflect the behaviour in the real world.
2883  if (GetTxAvailable () > 0)
2884  {
2886  }
2887 }
2888 
2889 void
2891 {
2892  /*
2893  * Add tags for each socket option.
2894  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2895  * if both options are set. Once the packet got to layer three, only
2896  * the corresponding tags will be read.
2897  */
2898  if (GetIpTos ())
2899  {
2900  SocketIpTosTag ipTosTag;
2902  {
2904  }
2905  else
2906  {
2907  // Set the last received ipTos
2908  ipTosTag.SetTos (GetIpTos ());
2909  }
2910  p->AddPacketTag (ipTosTag);
2911  }
2912  else
2913  {
2915  {
2916  SocketIpTosTag ipTosTag;
2918  p->AddPacketTag (ipTosTag);
2919  }
2920  }
2921 
2922  if (IsManualIpv6Tclass ())
2923  {
2924  SocketIpv6TclassTag ipTclassTag;
2926  {
2928  }
2929  else
2930  {
2931  // Set the last received ipTos
2932  ipTclassTag.SetTclass (GetIpv6Tclass ());
2933  }
2934  p->AddPacketTag (ipTclassTag);
2935  }
2936  else
2937  {
2939  {
2940  SocketIpv6TclassTag ipTclassTag;
2942  p->AddPacketTag (ipTclassTag);
2943  }
2944  }
2945 
2946  if (IsManualIpTtl ())
2947  {
2948  SocketIpTtlTag ipTtlTag;
2949  ipTtlTag.SetTtl (GetIpTtl ());
2950  p->AddPacketTag (ipTtlTag);
2951  }
2952 
2953  if (IsManualIpv6HopLimit ())
2954  {
2955  SocketIpv6HopLimitTag ipHopLimitTag;
2956  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
2957  p->AddPacketTag (ipHopLimitTag);
2958  }
2959 
2960  uint8_t priority = GetPriority ();
2961  if (priority)
2962  {
2963  SocketPriorityTag priorityTag;
2964  priorityTag.SetPriority (priority);
2965  p->ReplacePacketTag (priorityTag);
2966  }
2967 }
2968 
2969 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
2970  TCP header, and send to TcpL4Protocol */
2971 uint32_t
2972 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
2973 {
2974  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
2975 
2976  bool isStartOfTransmission = BytesInFlight () == 0U;
2977  TcpTxItem *outItem = m_txBuffer->CopyFromSequence (maxSize, seq);
2978 
2979  m_rateOps->SkbSent(outItem, isStartOfTransmission);
2980 
2981  bool isRetransmission = outItem->IsRetrans ();
2982  Ptr<Packet> p = outItem->GetPacketCopy ();
2983  uint32_t sz = p->GetSize (); // Size of packet
2984  uint8_t flags = withAck ? TcpHeader::ACK : 0;
2985  uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
2986 
2987  // TCP sender should not send data out of the window advertised by the
2988  // peer when it is not retransmission.
2989  NS_ASSERT (isRetransmission || ((m_highRxAckMark + SequenceNumber32 (m_rWnd)) >= (seq + SequenceNumber32 (maxSize))));
2990 
2991  if (IsPacingEnabled ())
2992  {
2993  NS_LOG_INFO ("Pacing is enabled");
2994  if (m_pacingTimer.IsExpired ())
2995  {
2996  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_pacingRate);
2997  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
2998  m_pacingTimer.Schedule (m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
2999  }
3000  else
3001  {
3002  NS_LOG_INFO ("Timer is already in running state");
3003  }
3004  }
3005  else
3006  {
3007  NS_LOG_INFO ("Pacing is disabled");
3008  }
3009 
3010  if (withAck)
3011  {
3012  m_delAckEvent.Cancel ();
3013  m_delAckCount = 0;
3014  }
3015 
3016  // Sender should reduce the Congestion Window as a response to receiver's ECN Echo notification only once per window
3017  if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && m_ecnEchoSeq.Get() > m_ecnCWRSeq.Get () && !isRetransmission)
3018  {
3019  NS_LOG_INFO ("Backoff mechanism by reducing CWND by half because we've received ECN Echo");
3020  m_congestionControl->ReduceCwnd (m_tcb);
3023  UpdatePacingRate ();
3024  flags |= TcpHeader::CWR;
3025  m_ecnCWRSeq = seq;
3026  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_CWR_SENT");
3028  NS_LOG_INFO ("CWR flags set");
3029  }
3030 
3031  AddSocketTags (p);
3032 
3033  if (m_closeOnEmpty && (remainingData == 0))
3034  {
3035  flags |= TcpHeader::FIN;
3036  if (m_state == ESTABLISHED)
3037  { // On active close: I am the first one to send FIN
3038  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
3039  m_state = FIN_WAIT_1;
3040  }
3041  else if (m_state == CLOSE_WAIT)
3042  { // On passive close: Peer sent me FIN already
3043  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
3044  m_state = LAST_ACK;
3045  }
3046  }
3047  TcpHeader header;
3048  header.SetFlags (flags);
3049  header.SetSequenceNumber (seq);
3050  header.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
3051  if (m_endPoint)
3052  {
3053  header.SetSourcePort (m_endPoint->GetLocalPort ());
3055  }
3056  else
3057  {
3058  header.SetSourcePort (m_endPoint6->GetLocalPort ());
3060  }
3061  header.SetWindowSize (AdvertisedWindowSize ());
3062  AddOptions (header);
3063 
3064  if (m_retxEvent.IsExpired ())
3065  {
3066  // Schedules retransmit timeout. m_rto should be already doubled.
3067 
3068  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
3069  Simulator::Now ().GetSeconds () << " to expire at time " <<
3070  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
3072  }
3073 
3074  m_txTrace (p, header, this);
3075 
3076  if (m_endPoint)
3077  {
3078  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
3080  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
3081  remainingData << " via TcpL4Protocol to " << m_endPoint->GetPeerAddress () <<
3082  ". Header " << header);
3083  }
3084  else
3085  {
3086  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
3088  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
3089  remainingData << " via TcpL4Protocol to " << m_endPoint6->GetPeerAddress () <<
3090  ". Header " << header);
3091  }
3092 
3093  UpdateRttHistory (seq, sz, isRetransmission);
3094 
3095  // Update bytes sent during recovery phase
3097  {
3098  m_recoveryOps->UpdateBytesSent (sz);
3099  }
3100 
3101  // Notify the application of the data being sent unless this is a retransmit
3102  if (!isRetransmission)
3103  {
3105  (seq + sz - m_tcb->m_highTxMark.Get ()));
3106  }
3107  // Update highTxMark
3108  m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ());
3109  return sz;
3110 }
3111 
3112 void
3114  bool isRetransmission)
3115 {
3116  NS_LOG_FUNCTION (this);
3117 
3118  // update the history of sequence numbers used to calculate the RTT
3119  if (isRetransmission == false)
3120  { // This is the next expected one, just log at end
3121  m_history.push_back (RttHistory (seq, sz, Simulator::Now ()));
3122  }
3123  else
3124  { // This is a retransmit, find in list and mark as re-tx
3125  for (std::deque<RttHistory>::iterator i = m_history.begin (); i != m_history.end (); ++i)
3126  {
3127  if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
3128  { // Found it
3129  i->retx = true;
3130  i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
3131  break;
3132  }
3133  }
3134  }
3135 }
3136 
3137 // Note that this function did not implement the PSH flag
3138 uint32_t
3140 {
3141  NS_LOG_FUNCTION (this << withAck);
3142  if (m_txBuffer->Size () == 0)
3143  {
3144  return false; // Nothing to send
3145  }
3146  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
3147  {
3148  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
3149  return false; // Is this the right way to handle this condition?
3150  }
3151 
3152  uint32_t nPacketsSent = 0;
3153  uint32_t availableWindow = AvailableWindow ();
3154 
3155  // RFC 6675, Section (C)
3156  // If cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more
3157  // segments as follows:
3158  // (NOTE: We check > 0, and do the checks for segmentSize in the following
3159  // else branch to control silly window syndrome and Nagle)
3160  while (availableWindow > 0)
3161  {
3162  if (IsPacingEnabled ())
3163  {
3164  NS_LOG_INFO ("Pacing is enabled");
3165  if (m_pacingTimer.IsRunning ())
3166  {
3167  NS_LOG_INFO ("Skipping Packet due to pacing" << m_pacingTimer.GetDelayLeft ());
3168  break;
3169  }
3170  NS_LOG_INFO ("Timer is not running");
3171  }
3172 
3175  {
3176  NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit");
3177  break;
3178  }
3179  // (C.1) The scoreboard MUST be queried via NextSeg () for the
3180  // sequence number range of the next segment to transmit (if
3181  // any), and the given segment sent. If NextSeg () returns
3182  // failure (no data to send), return without sending anything
3183  // (i.e., terminate steps C.1 -- C.5).
3184  SequenceNumber32 next;
3185  SequenceNumber32 nextHigh;
3186  bool enableRule3 = m_sackEnabled && m_tcb->m_congState == TcpSocketState::CA_RECOVERY;
3187  if (!m_txBuffer->NextSeg (&next, &nextHigh, enableRule3))
3188  {
3189  NS_LOG_INFO ("no valid seq to transmit, or no data available");
3190  break;
3191  }
3192  else
3193  {
3194  // It's time to transmit, but before do silly window and Nagle's check
3195  uint32_t availableData = m_txBuffer->SizeFromSequence (next);
3196 
3197  // If there's less app data than the full window, ask the app for more
3198  // data before trying to send
3199  if (availableData < availableWindow)
3200  {
3202  }
3203 
3204  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
3205  // but continue if we don't have data
3206  if (availableWindow < m_tcb->m_segmentSize && availableData > availableWindow)
3207  {
3208  NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
3209  break; // No more
3210  }
3211  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
3212  // in the buffer and the amount of data to send is less than one segment
3213  if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_segmentSize)
3214  {
3215  NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next <<
3216  ", SFS: " << m_txBuffer->SizeFromSequence (next) <<
3217  ". Wait to send.");
3218  break;
3219  }
3220 
3221  uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize);
3222  // NextSeg () may have further constrained the segment size
3223  uint32_t maxSizeToSend = static_cast<uint32_t> (nextHigh - next);
3224  s = std::min (s, maxSizeToSend);
3225 
3226  // (C.2) If any of the data octets sent in (C.1) are below HighData,
3227  // HighRxt MUST be set to the highest sequence number of the
3228  // retransmitted segment unless NextSeg () rule (4) was
3229  // invoked for this retransmission.
3230  // (C.3) If any of the data octets sent in (C.1) are above HighData,
3231  // HighData must be updated to reflect the transmission of
3232  // previously unsent data.
3233  //
3234  // These steps are done in m_txBuffer with the tags.
3235  if (m_tcb->m_nextTxSequence != next)
3236  {
3237  m_tcb->m_nextTxSequence = next;
3238  }
3239  if (m_tcb->m_bytesInFlight.Get () == 0)
3240  {
3242  }
3243  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck);
3244 
3245  NS_LOG_LOGIC (" rxwin " << m_rWnd <<
3246  " segsize " << m_tcb->m_segmentSize <<
3247  " highestRxAck " << m_txBuffer->HeadSequence () <<
3248  " pd->Size " << m_txBuffer->Size () <<
3249  " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence));
3250 
3251  NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd <<
3252  " total unAck: " << UnAckDataCount () <<
3253  " sent seq " << m_tcb->m_nextTxSequence <<
3254  " size " << sz);
3255  m_tcb->m_nextTxSequence += sz;
3256  ++nPacketsSent;
3257  if (IsPacingEnabled ())
3258  {
3259  NS_LOG_INFO ("Pacing is enabled");
3260  if (m_pacingTimer.IsExpired ())
3261  {
3262  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_pacingRate);
3263  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3264  m_pacingTimer.Schedule (m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3265  break;
3266  }
3267  }
3268  }
3269 
3270  // (C.4) The estimate of the amount of data outstanding in the
3271  // network must be updated by incrementing pipe by the number
3272  // of octets transmitted in (C.1).
3273  //
3274  // Done in BytesInFlight, inside AvailableWindow.
3275  availableWindow = AvailableWindow ();
3276 
3277  // (C.5) If cwnd - pipe >= 1 SMSS, return to (C.1)
3278  // loop again!
3279  }
3280 
3281  if (nPacketsSent > 0)
3282  {
3283  if (!m_sackEnabled)
3284  {
3285  if (!m_limitedTx)
3286  {
3287  // We can't transmit in CA_DISORDER without limitedTx active
3289  }
3290  }
3291 
3292  NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments");
3293  }
3294  else
3295  {
3296  NS_LOG_DEBUG ("SendPendingData no segments sent");
3297  }
3298  return nPacketsSent;
3299 }
3300 
3301 uint32_t
3303 {
3304  return m_tcb->m_highTxMark - m_txBuffer->HeadSequence ();
3305 }
3306 
3307 uint32_t
3309 {
3310  uint32_t bytesInFlight = m_txBuffer->BytesInFlight ();
3311  // Ugly, but we are not modifying the state; m_bytesInFlight is used
3312  // only for tracing purpose.
3313  m_tcb->m_bytesInFlight = bytesInFlight;
3314 
3315  NS_LOG_DEBUG ("Returning calculated bytesInFlight: " << bytesInFlight);
3316  return bytesInFlight;
3317 }
3318 
3319 uint32_t
3321 {
3322  return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
3323 }
3324 
3325 uint32_t
3327 {
3328  uint32_t win = Window (); // Number of bytes allowed to be outstanding
3329  uint32_t inflight = BytesInFlight (); // Number of outstanding bytes
3330  return (inflight > win) ? 0 : win - inflight;
3331 }
3332 
3333 uint16_t
3335 {
3336  NS_LOG_FUNCTION (this << scale);
3337  uint32_t w;
3338 
3339  // We don't want to advertise 0 after a FIN is received. So, we just use
3340  // the previous value of the advWnd.
3341  if (m_tcb->m_rxBuffer->GotFin ())
3342  {
3343  w = m_advWnd;
3344  }
3345  else
3346  {
3347  NS_ASSERT_MSG (m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence () >= 0,
3348  "Unexpected sequence number values");
3349  w = static_cast<uint32_t> (m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence ());
3350  }
3351 
3352  // Ugly, but we are not modifying the state, that variable
3353  // is used only for tracing purpose.
3354  if (w != m_advWnd)
3355  {
3356  const_cast<TcpSocketBase*> (this)->m_advWnd = w;
3357  }
3358  if (scale)
3359  {
3360  w >>= m_rcvWindShift;
3361  }
3362  if (w > m_maxWinSize)
3363  {
3364  w = m_maxWinSize;
3365  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
3366  }
3367  NS_LOG_LOGIC ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
3368  return static_cast<uint16_t> (w);
3369 }
3370 
3371 // Receipt of new packet, put into Rx buffer
3372 void
3374 {
3375  NS_LOG_FUNCTION (this << tcpHeader);
3376  NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () <<
3377  " pkt size=" << p->GetSize () );
3378 
3379  // Put into Rx buffer
3380  SequenceNumber32 expectedSeq = m_tcb->m_rxBuffer->NextRxSequence ();
3381  if (!m_tcb->m_rxBuffer->Add (p, tcpHeader))
3382  { // Insert failed: No data or RX buffer full
3384  {
3386  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3388  }
3389  else
3390  {
3392  }
3393  return;
3394  }
3395  // Notify app to receive if necessary
3396  if (expectedSeq < m_tcb->m_rxBuffer->NextRxSequence ())
3397  { // NextRxSeq advanced, we have something to send to the app
3398  if (!m_shutdownRecv)
3399  {
3400  NotifyDataRecv ();
3401  }
3402  // Handle exceptions
3403  if (m_closeNotified)
3404  {
3405  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
3406  }
3407  // If we received FIN before and now completed all "holes" in rx buffer,
3408  // invoke peer close procedure
3409  if (m_tcb->m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
3410  {
3411  DoPeerClose ();
3412  return;
3413  }
3414  }
3415  // Now send a new ACK packet acknowledging all received and delivered data
3416  if (m_tcb->m_rxBuffer->Size () > m_tcb->m_rxBuffer->Available () || m_tcb->m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
3417  { // A gap exists in the buffer, or we filled a gap: Always ACK
3420  {
3422  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3424  }
3425  else
3426  {
3428  }
3429  }
3430  else
3431  { // In-sequence packet: ACK if delayed ack count allows
3433  {
3434  m_delAckEvent.Cancel ();
3435  m_delAckCount = 0;
3438  {
3439  NS_LOG_DEBUG("Congestion algo " << m_congestionControl->GetName ());
3441  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3443  }
3444  else
3445  {
3447  }
3448  }
3449  else if (!m_delAckEvent.IsExpired ())
3450  {
3452  }
3453  else if (m_delAckEvent.IsExpired ())
3454  {
3458  NS_LOG_LOGIC (this << " scheduled delayed ACK at " <<
3459  (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
3460  }
3461  }
3462 }
3463 
3471 void
3473 {
3474  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber ();
3475  Time m = Time (0.0);
3476 
3477  // An ack has been received, calculate rtt and log this measurement
3478  // Note we use a linear search (O(n)) for this since for the common
3479  // case the ack'ed packet will be at the head of the list
3480  if (!m_history.empty ())
3481  {
3482  RttHistory& h = m_history.front ();
3483  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
3484  { // Ok to use this sample
3485  if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
3486  {
3488  ts = DynamicCast<const TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
3489  m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
3490  }
3491  else
3492  {
3493  m = Simulator::Now () - h.time; // Elapsed time
3494  }
3495  }
3496  }
3497 
3498  // Now delete all ack history with seq <= ack
3499  while (!m_history.empty ())
3500  {
3501  RttHistory& h = m_history.front ();
3502  if ((h.seq + SequenceNumber32 (h.count)) > ackSeq)
3503  {
3504  break; // Done removing
3505  }
3506  m_history.pop_front (); // Remove
3507  }
3508 
3509  if (!m.IsZero ())
3510  {
3511  m_rtt->Measurement (m); // Log the measurement
3512  // RFC 6298, clause 2.4
3513  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3514  m_tcb->m_lastRtt = m_rtt->GetEstimate ();
3516  NS_LOG_INFO (this << m_tcb->m_lastRtt << m_tcb->m_minRtt);
3517  }
3518 }
3519 
3520 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
3521 // when the three-way handshake completed. This cancels retransmission timer
3522 // and advances Tx window
3523 void
3524 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO)
3525 {
3526  NS_LOG_FUNCTION (this << ack);
3527 
3528  // Reset the data retransmission count. We got a new ACK!
3530 
3531  if (m_state != SYN_RCVD && resetRTO)
3532  { // Set RTO unless the ACK is received in SYN_RCVD state
3533  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3534  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3535  m_retxEvent.Cancel ();
3536  // On receiving a "New" ack we restart retransmission timer .. RFC 6298
3537  // RFC 6298, clause 2.4
3538  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3539 
3540  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
3541  Simulator::Now ().GetSeconds () << " to expire at time " <<
3542  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
3544  }
3545 
3546  // Note the highest ACK and tell app to send more
3547  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
3548  " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
3549 
3550  if (GetTxAvailable () > 0)
3551  {
3553  }
3554  if (ack > m_tcb->m_nextTxSequence)
3555  {
3556  m_tcb->m_nextTxSequence = ack; // If advanced
3557  }
3558  if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
3559  { // No retransmit timer if no data to retransmit
3560  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3561  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3562  m_retxEvent.Cancel ();
3563  }
3564 }
3565 
3566 // Retransmit timeout
3567 void
3569 {
3570  NS_LOG_FUNCTION (this);
3571  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
3572  // If erroneous timeout in closed/timed-wait state, just return
3573  if (m_state == CLOSED || m_state == TIME_WAIT)
3574  {
3575  return;
3576  }
3577 
3578  if (m_state == SYN_SENT)
3579  {
3580  NS_ASSERT (m_synCount > 0);
3582  {
3584  }
3585  else
3586  {
3588  }
3589  return;
3590  }
3591 
3592  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3593  if (m_txBuffer->Size () == 0)
3594  {
3595  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3596  { // Must have lost FIN, re-send
3598  }
3599  return;
3600  }
3601 
3602  NS_LOG_DEBUG ("Checking if Connection is Established");
3603  // If all data are received (non-closing socket and nothing to send), just return
3604  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark && m_txBuffer->Size () == 0)
3605  {
3606  NS_LOG_DEBUG ("Already Sent full data" << m_txBuffer->HeadSequence () << " " << m_tcb->m_highTxMark);
3607  return;
3608  }
3609 
3610  if (m_dataRetrCount == 0)
3611  {
3612  NS_LOG_INFO ("No more data retries available. Dropping connection");
3613  NotifyErrorClose ();
3614  DeallocateEndPoint ();
3615  return;
3616  }
3617  else
3618  {
3619  --m_dataRetrCount;
3620  }
3621 
3622  uint32_t inFlightBeforeRto = BytesInFlight ();
3623  bool resetSack = !m_sackEnabled; // Reset SACK information if SACK is not enabled.
3624  // The information in the TcpTxBuffer is guessed, in this case.
3625 
3626  // Reset dupAckCount
3627  m_dupAckCount = 0;
3628  if (!m_sackEnabled)
3629  {
3630  m_txBuffer->ResetRenoSack ();
3631  }
3632 
3633  // From RFC 6675, Section 5.1
3634  // [RFC2018] suggests that a TCP sender SHOULD expunge the SACK
3635  // information gathered from a receiver upon a retransmission timeout
3636  // (RTO) "since the timeout might indicate that the data receiver has
3637  // reneged." Additionally, a TCP sender MUST "ignore prior SACK
3638  // information in determining which data to retransmit."
3639  // It has been suggested that, as long as robust tests for
3640  // reneging are present, an implementation can retain and use SACK
3641  // information across a timeout event [Errata1610].
3642  // The head of the sent list will not be marked as sacked, therefore
3643  // will be retransmitted, if the receiver renegotiate the SACK blocks
3644  // that we received.
3645  m_txBuffer->SetSentListLost (resetSack);
3646 
3647  // From RFC 6675, Section 5.1
3648  // If an RTO occurs during loss recovery as specified in this document,
3649  // RecoveryPoint MUST be set to HighData. Further, the new value of
3650  // RecoveryPoint MUST be preserved and the loss recovery algorithm
3651  // outlined in this document MUST be terminated.
3653  m_recoverActive = true;
3654 
3655  // RFC 6298, clause 2.5, double the timer
3656  Time doubledRto = m_rto + m_rto;
3657  m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
3658 
3659  // Empty RTT history
3660  m_history.clear ();
3661 
3662  // Please don't reset highTxMark, it is used for retransmission detection
3663 
3664  // When a TCP sender detects segment loss using the retransmission timer
3665  // and the given segment has not yet been resent by way of the
3666  // retransmission timer, decrease ssThresh
3667  if (m_tcb->m_congState != TcpSocketState::CA_LOSS || !m_txBuffer->IsHeadRetransmitted ())
3668  {
3669  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, inFlightBeforeRto);
3670  }
3671 
3672  // Cwnd set to 1 MSS
3674  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS);
3678 
3679  m_pacingTimer.Cancel ();
3680 
3681  NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
3682  m_tcb->m_ssThresh << ", restart from seqnum " <<
3683  m_txBuffer->HeadSequence () << " doubled rto to " <<
3684  m_rto.Get ().GetSeconds () << " s");
3685 
3686  NS_ASSERT_MSG (BytesInFlight () == 0, "There are some bytes in flight after an RTO: " <<
3687  BytesInFlight ());
3688 
3690 
3692  "In flight (" << BytesInFlight () <<
3693  ") there is more than one segment (" << m_tcb->m_segmentSize << ")");
3694 }
3695 
3696 void
3698 {
3699  m_delAckCount = 0;
3702  {
3705  }
3706  else
3707  {
3709  }
3710 }
3711 
3712 void
3714 {
3715  NS_LOG_FUNCTION (this);
3716 
3718  if (m_state == LAST_ACK)
3719  {
3720  if (m_dataRetrCount == 0)
3721  {
3722  NS_LOG_INFO ("LAST-ACK: No more data retries available. Dropping connection");
3723  NotifyErrorClose ();
3724  DeallocateEndPoint ();
3725  return;
3726  }
3727  m_dataRetrCount--;
3729  NS_LOG_LOGIC ("TcpSocketBase " << this << " rescheduling LATO1");
3730  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
3732  }
3733 }
3734 
3735 // Send 1-byte data to probe for the window size at the receiver when
3736 // the local knowledge tells that the receiver has zero window size
3737 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
3738 void
3740 {
3741  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
3742  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
3743  Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence)->GetPacketCopy ();
3744  m_txBuffer->ResetLastSegmentSent ();
3745  TcpHeader tcpHeader;
3747  tcpHeader.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
3748  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
3749  if (m_endPoint != nullptr)
3750  {
3751  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
3752  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
3753  }
3754  else
3755  {
3756  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
3757  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
3758  }
3759  AddOptions (tcpHeader);
3760  //Send a packet tag for setting ECT bits in IP header
3762  {
3763  SocketIpTosTag ipTosTag;
3764  ipTosTag.SetTos (MarkEcnCodePoint (0, m_tcb->m_ectCodePoint));
3765  p->AddPacketTag (ipTosTag);
3766 
3767  SocketIpv6TclassTag ipTclassTag;
3768  ipTclassTag.SetTclass (MarkEcnCodePoint (0, m_tcb->m_ectCodePoint));
3769  p->AddPacketTag (ipTclassTag);
3770  }
3771  m_txTrace (p, tcpHeader, this);
3772 
3773  if (m_endPoint != nullptr)
3774  {
3775  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
3777  }
3778  else
3779  {
3780  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
3782  }
3783 
3784  NS_LOG_LOGIC ("Schedule persist timeout at time "
3785  << Simulator::Now ().GetSeconds () << " to expire at time "
3786  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
3788 }
3789 
3790 void
3792 {
3793  NS_LOG_FUNCTION (this);
3794  bool res;
3795  SequenceNumber32 seq;
3796  SequenceNumber32 seqHigh;
3797  uint32_t maxSizeToSend;
3798 
3799  // Find the first segment marked as lost and not retransmitted. With Reno,
3800  // that should be the head
3801  res = m_txBuffer->NextSeg (&seq, &seqHigh, false);
3802  if (!res)
3803  {
3804  // We have already retransmitted the head. However, we still received
3805  // three dupacks, or the RTO expired, but no data to transmit.
3806  // Therefore, re-send again the head.
3807  seq = m_txBuffer->HeadSequence ();
3808  maxSizeToSend = m_tcb->m_segmentSize;
3809  }
3810  else
3811  {
3812  // NextSeg() may constrain the segment size when res is true
3813  maxSizeToSend = static_cast<uint32_t> (seqHigh - seq);
3814  }
3815  NS_ASSERT (m_sackEnabled || seq == m_txBuffer->HeadSequence ());
3816 
3817  NS_LOG_INFO ("Retransmitting " << seq);
3818  // Update the trace and retransmit the segment
3819  m_tcb->m_nextTxSequence = seq;
3820  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, maxSizeToSend, true);
3821 
3822  NS_ASSERT (sz > 0);
3823 }
3824 
3825 void
3827 {
3828  m_retxEvent.Cancel ();
3830  m_delAckEvent.Cancel ();
3834  m_pacingTimer.Cancel ();
3835 }
3836 
3837 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
3838 void
3840 {
3841  NS_LOG_DEBUG (TcpStateName[m_state] << " -> TIME_WAIT");
3842  m_state = TIME_WAIT;
3843  CancelAllTimers ();
3844  if (!m_closeNotified)
3845  {
3846  // Technically the connection is not fully closed, but we notify now
3847  // because an implementation (real socket) would behave as if closed.
3848  // Notify normal close when entering TIME_WAIT or leaving LAST_ACK.
3849  NotifyNormalClose ();
3850  m_closeNotified = true;
3851  }
3852  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
3853  // according to RFC793, p.28
3856 }
3857 
3858 /* Below are the attribute get/set functions */
3859 
3860 void
3862 {
3863  NS_LOG_FUNCTION (this << size);
3864  m_txBuffer->SetMaxBufferSize (size);
3865 }
3866 
3867 uint32_t
3869 {
3870  return m_txBuffer->MaxBufferSize ();
3871 }
3872 
3873 void
3875 {
3876  NS_LOG_FUNCTION (this << size);
3877  uint32_t oldSize = GetRcvBufSize ();
3878 
3879  m_tcb->m_rxBuffer->SetMaxBufferSize (size);
3880 
3881  /* The size has (manually) increased. Actively inform the other end to prevent
3882  * stale zero-window states.
3883  */
3884  if (oldSize < size && m_connected)
3885  {
3887  {
3889  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3891  }
3892  else
3893  {
3895  }
3896  }
3897 }
3898 
3899 uint32_t
3901 {
3902  return m_tcb->m_rxBuffer->MaxBufferSize ();
3903 }
3904 
3905 void
3907 {
3908  NS_LOG_FUNCTION (this << size);
3909  m_tcb->m_segmentSize = size;
3910  m_txBuffer->SetSegmentSize (size);
3911 
3912  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
3913 }
3914 
3915 uint32_t
3917 {
3918  return m_tcb->m_segmentSize;
3919 }
3920 
3921 void
3923 {
3924  NS_LOG_FUNCTION (this << timeout);
3925  m_cnTimeout = timeout;
3926 }
3927 
3928 Time
3930 {
3931  return m_cnTimeout;
3932 }
3933 
3934 void
3936 {
3937  NS_LOG_FUNCTION (this << count);
3938  m_synRetries = count;
3939 }
3940 
3941 uint32_t
3943 {
3944  return m_synRetries;
3945 }
3946 
3947 void
3949 {
3950  NS_LOG_FUNCTION (this << retries);
3951  m_dataRetries = retries;
3952 }
3953 
3954 uint32_t
3956 {
3957  NS_LOG_FUNCTION (this);
3958  return m_dataRetries;
3959 }
3960 
3961 void
3963 {
3964  NS_LOG_FUNCTION (this << timeout);
3966 }
3967 
3968 Time
3970 {
3971  return m_delAckTimeout;
3972 }
3973 
3974 void
3976 {
3977  NS_LOG_FUNCTION (this << count);
3978  m_delAckMaxCount = count;
3979 }
3980 
3981 uint32_t
3983 {
3984  return m_delAckMaxCount;
3985 }
3986 
3987 void
3989 {
3990  NS_LOG_FUNCTION (this << noDelay);
3991  m_noDelay = noDelay;
3992 }
3993 
3994 bool
3996 {
3997  return m_noDelay;
3998 }
3999 
4000 void
4002 {
4003  NS_LOG_FUNCTION (this << timeout);
4005 }
4006 
4007 Time
4009 {
4010  return m_persistTimeout;
4011 }
4012 
4013 bool
4015 {
4016  // Broadcast is not implemented. Return true only if allowBroadcast==false
4017  return (!allowBroadcast);
4018 }
4019 
4020 bool
4022 {
4023  return false;
4024 }
4025 
4026 void
4028 {
4029  NS_LOG_FUNCTION (this << header);
4030 
4031  if (m_timestampEnabled)
4032  {
4033  AddOptionTimestamp (header);
4034  }
4035 }
4036 
4037 void
4039 {
4040  NS_LOG_FUNCTION (this << option);
4041 
4042  Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
4043 
4044  // In naming, we do the contrary of RFC 1323. The received scaling factor
4045  // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
4046  m_sndWindShift = ws->GetScale ();
4047 
4048  if (m_sndWindShift > 14)
4049  {
4050  NS_LOG_WARN ("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
4051  m_sndWindShift = 14;
4052  }
4053 
4054  NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
4055  static_cast<int> (m_sndWindShift));
4056 }
4057 
4058 uint8_t
4060 {
4061  NS_LOG_FUNCTION (this);
4062  uint32_t maxSpace = m_tcb->m_rxBuffer->MaxBufferSize ();
4063  uint8_t scale = 0;
4064 
4065  while (maxSpace > m_maxWinSize)
4066  {
4067  maxSpace = maxSpace >> 1;
4068  ++scale;
4069  }
4070 
4071  if (scale > 14)
4072  {
4073  NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
4074  scale = 14;
4075  }
4076 
4077  NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
4078  static_cast<int> (scale) << " for buffer size " << m_tcb->m_rxBuffer->MaxBufferSize ());
4079  return scale;
4080 }
4081 
4082 void
4084 {
4085  NS_LOG_FUNCTION (this << header);
4086  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
4087 
4088  Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
4089 
4090  // In naming, we do the contrary of RFC 1323. The sended scaling factor
4091  // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
4092 
4094  option->SetScale (m_rcvWindShift);
4095 
4096  header.AppendOption (option);
4097 
4098  NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
4099  static_cast<int> (m_rcvWindShift));
4100 }
4101 
4102 uint32_t
4104 {
4105  NS_LOG_FUNCTION (this << option);
4106 
4107  Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option);
4108  return m_txBuffer->Update (s->GetSackList (), MakeCallback (&TcpRateOps::SkbDelivered, m_rateOps));
4109 }
4110 
4111 void
4113 {
4114  NS_LOG_FUNCTION (this << option);
4115 
4116  Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted> (option);
4117 
4118  NS_ASSERT (m_sackEnabled == true);
4119  NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s);
4120 }
4121 
4122 void
4124 {
4125  NS_LOG_FUNCTION (this << header);
4126  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
4127 
4128  Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> ();
4129  header.AppendOption (option);
4130  NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED");
4131 }
4132 
4133 void
4135 {
4136  NS_LOG_FUNCTION (this << header);
4137 
4138  // Calculate the number of SACK blocks allowed in this packet
4139  uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength ();
4140  uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8;
4141 
4142  TcpOptionSack::SackList sackList = m_tcb->m_rxBuffer->GetSackList ();
4143  if (allowedSackBlocks == 0 || sackList.empty ())
4144  {
4145  NS_LOG_LOGIC ("No space available or sack list empty, not adding sack blocks");
4146  return;
4147  }
4148 
4149  // Append the allowed number of SACK blocks
4150  Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> ();
4151  TcpOptionSack::SackList::iterator i;
4152  for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i)
4153  {
4154  option->AddSackBlock (*i);
4155  allowedSackBlocks--;
4156  }
4157 
4158  header.AppendOption (option);
4159  NS_LOG_INFO (m_node->GetId () << " Add option SACK " << *option);
4160 }
4161 
4162 void
4164  const SequenceNumber32 &seq)
4165 {
4166  NS_LOG_FUNCTION (this << option);
4167 
4168  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
4169 
4170  // This is valid only when no overflow occurs. It happens
4171  // when a connection last longer than 50 days.
4172  if (m_tcb->m_rcvTimestampValue > ts->GetTimestamp ())
4173  {
4174  // Do not save a smaller timestamp (probably there is reordering)
4175  return;
4176  }
4177 
4178  m_tcb->m_rcvTimestampValue = ts->GetTimestamp ();
4179  m_tcb->m_rcvTimestampEchoReply = ts->GetEcho ();
4180 
4181  if (seq == m_tcb->m_rxBuffer->NextRxSequence () && seq <= m_highTxAck)
4182  {
4183  m_timestampToEcho = ts->GetTimestamp ();
4184  }
4185 
4186  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
4187  m_timestampToEcho << " and Echo=" << ts->GetEcho ());
4188 }
4189 
4190 void
4192 {
4193  NS_LOG_FUNCTION (this << header);
4194 
4195  Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
4196 
4197  option->SetTimestamp (TcpOptionTS::NowToTsValue ());
4198  option->SetEcho (m_timestampToEcho);
4199 
4200  header.AppendOption (option);
4201  NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
4202  option->GetTimestamp () << " echo=" << m_timestampToEcho);
4203 }
4204 
4206 {
4207  NS_LOG_FUNCTION (this << header);
4208  // If the connection is not established, the window size is always
4209  // updated
4210  uint32_t receivedWindow = header.GetWindowSize ();
4211  receivedWindow <<= m_sndWindShift;
4212  NS_LOG_INFO ("Received (scaled) window is " << receivedWindow << " bytes");
4213  if (m_state < ESTABLISHED)
4214  {
4215  m_rWnd = receivedWindow;
4216  NS_LOG_LOGIC ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
4217  return;
4218  }
4219 
4220  // Test for conditions that allow updating of the window
4221  // 1) segment contains new data (advancing the right edge of the receive
4222  // buffer),
4223  // 2) segment does not contain new data but the segment acks new data
4224  // (highest sequence number acked advances), or
4225  // 3) the advertised window is larger than the current send window
4226  bool update = false;
4227  if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
4228  {
4229  // right edge of the send window is increased (window update)
4230  update = true;
4231  }
4232  if (header.GetAckNumber () > m_highRxAckMark)
4233  {
4234  m_highRxAckMark = header.GetAckNumber ();
4235  update = true;
4236  }
4237  if (header.GetSequenceNumber () > m_highRxMark)
4238  {
4239  m_highRxMark = header.GetSequenceNumber ();
4240  update = true;
4241  }
4242  if (update == true)
4243  {
4244  m_rWnd = receivedWindow;
4245  NS_LOG_LOGIC ("updating rWnd to " << m_rWnd);
4246  }
4247 }
4248 
4249 void
4251 {
4252  NS_LOG_FUNCTION (this << minRto);
4253  m_minRto = minRto;
4254 }
4255 
4256 Time
4258 {
4259  return m_minRto;
4260 }
4261 
4262 void
4264 {
4265  NS_LOG_FUNCTION (this << clockGranularity);
4266  m_clockGranularity = clockGranularity;
4267 }
4268 
4269 Time
4271 {
4272  return m_clockGranularity;
4273 }
4274 
4277 {
4278  return m_txBuffer;
4279 }
4280 
4283 {
4284  return m_tcb->m_rxBuffer;
4285 }
4286 
4287 void
4288 TcpSocketBase::SetRetxThresh (uint32_t retxThresh)
4289 {
4290  m_retxThresh = retxThresh;
4291  m_txBuffer->SetDupAckThresh (retxThresh);
4292 }
4293 
4294 void
4296 {
4297  m_pacingRateTrace (oldValue, newValue);
4298 }
4299 
4300 void
4301 TcpSocketBase::UpdateCwnd (uint32_t oldValue, uint32_t newValue)
4302 {
4303  m_cWndTrace (oldValue, newValue);
4304 }
4305 
4306 void
4307 TcpSocketBase::UpdateCwndInfl (uint32_t oldValue, uint32_t newValue)
4308 {
4309  m_cWndInflTrace (oldValue, newValue);
4310 }
4311 
4312 void
4313 TcpSocketBase::UpdateSsThresh (uint32_t oldValue, uint32_t newValue)
4314 {
4315  m_ssThTrace (oldValue, newValue);
4316 }
4317 
4318 void
4321 {
4322  m_congStateTrace (oldValue, newValue);
4323 }
4324 
4325  void
4327  TcpSocketState::EcnState_t newValue)
4328 {
4329  m_ecnStateTrace (oldValue, newValue);
4330 }
4331 
4332 void
4334  SequenceNumber32 newValue)
4335 
4336 {
4337  m_nextTxSequenceTrace (oldValue, newValue);
4338 }
4339 
4340 void
4342 {
4343  m_highTxMarkTrace (oldValue, newValue);
4344 }
4345 
4346 void
4347 TcpSocketBase::UpdateBytesInFlight (uint32_t oldValue, uint32_t newValue)
4348 {
4349  m_bytesInFlightTrace (oldValue, newValue);
4350 }
4351 
4352 void
4353 TcpSocketBase::UpdateRtt (Time oldValue, Time newValue)
4354 {
4355  m_lastRttTrace (oldValue, newValue);
4356 }
4357 
4358 void
4360 {
4361  NS_LOG_FUNCTION (this << algo);
4362  m_congestionControl = algo;
4363  m_congestionControl->Init (m_tcb);
4364 }
4365 
4366 void
4368 {
4369  NS_LOG_FUNCTION (this << recovery);
4370  m_recoveryOps = recovery;
4371 }
4372 
4375 {
4376  return CopyObject<TcpSocketBase> (this);
4377 }
4378 
4379 uint32_t
4380 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b)
4381 {
4382  if (a > b)
4383  {
4384  return a-b;
4385  }
4386 
4387  return 0;
4388 }
4389 
4390 void
4392 {
4393  NS_LOG_FUNCTION (this);
4394  NS_LOG_INFO ("Performing Pacing");
4396 }
4397 
4398 bool
4400 {
4401  if (!m_tcb->m_pacing)
4402  {
4403  return false;
4404  }
4405  else
4406  {
4408  {
4409  return true;
4410  }
4411  SequenceNumber32 highTxMark = m_tcb->m_highTxMark; // cast traced value
4412  if (highTxMark.GetValue () > (GetInitialCwnd () * m_tcb->m_segmentSize))
4413  {
4414  return true;
4415  }
4416  }
4417  return false;
4418 }
4419 
4420 void
4422 {
4423  NS_LOG_FUNCTION (this << m_tcb);
4424 
4425  // According to Linux, set base pacing rate to (cwnd * mss) / srtt
4426  //
4427  // In (early) slow start, multiply base by the slow start factor.
4428  // In late slow start and congestion avoidance, multiply base by
4429  // the congestion avoidance factor.
4430  // Comment from Linux code regarding early/late slow start:
4431  // Normal Slow Start condition is (tp->snd_cwnd < tp->snd_ssthresh)
4432  // If snd_cwnd >= (tp->snd_ssthresh / 2), we are approaching
4433  // end of slow start and should slow down.
4434 
4435  // Similar to Linux, do not update pacing rate here if the
4436  // congestion control implements TcpCongestionOps::CongControl ()
4437  if (m_congestionControl->HasCongControl () || !m_tcb->m_pacing) return;
4438 
4439  double factor;
4440  if (m_tcb->m_cWnd < m_tcb->m_ssThresh/2)
4441  {
4442  NS_LOG_DEBUG ("Pacing according to slow start factor; " << m_tcb->m_cWnd << " " << m_tcb->m_ssThresh);
4443  factor = static_cast<double> (m_tcb->m_pacingSsRatio)/100;
4444  }
4445  else
4446  {
4447  NS_LOG_DEBUG ("Pacing according to congestion avoidance factor; " << m_tcb->m_cWnd << " " << m_tcb->m_ssThresh);
4448  factor = static_cast<double> (m_tcb->m_pacingCaRatio)/100;
4449  }
4450  Time lastRtt = m_tcb->m_lastRtt.Get (); // Get underlying Time value
4451  NS_LOG_DEBUG ("Last RTT is " << lastRtt.GetSeconds ());
4452 
4453  // Multiply by 8 to convert from bytes per second to bits per second
4454  DataRate pacingRate ((std::max (m_tcb->m_cWnd, m_tcb->m_bytesInFlight) * 8 * factor) / lastRtt.GetSeconds ());
4455  if (pacingRate < m_tcb->m_maxPacingRate)
4456  {
4457  NS_LOG_DEBUG ("Pacing rate updated to: " << pacingRate);
4458  m_tcb->m_pacingRate = pacingRate;
4459  }
4460  else
4461  {
4462  NS_LOG_DEBUG ("Pacing capped by max pacing rate: " << m_tcb->m_maxPacingRate);
4464  }
4465 }
4466 
4467 void
4469 {
4470  NS_LOG_FUNCTION (this << pacing);
4471  m_tcb->m_pacing = pacing;
4472 }
4473 
4474 void
4476 {
4477  NS_LOG_FUNCTION (this << paceWindow);
4478  m_tcb->m_paceInitialWindow = paceWindow;
4479 }
4480 
4481 void
4483 {
4484  NS_LOG_FUNCTION (this << useEcn);
4485  m_tcb->m_useEcn = useEcn;
4486 }
4487 
4488 uint32_t
4490 {
4491  return m_rWnd.Get ();
4492 }
4493 
4496 {
4497  return m_highRxAckMark.Get ();
4498 }
4499 
4500 
4501 //RttHistory methods
4503  : seq (s),
4504  count (c),
4505  time (t),
4506  retx (false)
4507 {
4508 }
4509 
4511  : seq (h.seq),
4512  count (h.count),
4513  time (h.time),
4514  retx (h.retx)
4515 {
4516 }
4517 
4518 } // 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:204
Ipv6Address GetLocalAddress()
Get the local address.
uint32_t m_rcvTimestampValue
Receiver Timestamp value.
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:280
log2() macro definition; to deal with Bug 1467.
void SetTclass(uint8_t tclass)
Set the tag&#39;s Tclass.
Definition: socket.cc:900
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
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
void ProcessListen(Ptr< Packet > packet, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Received a packet upon LISTEN state.
TracedValue< uint32_t > m_advWnd
Advertised Window size.
virtual void SetInitialCwnd(uint32_t cwnd)
Set the initial Congestion Window.
const TcpOptionList & GetOptionList(void) const
Get the list of option in this header.
Definition: tcp-header.cc:489
virtual int Listen(void)
Listen for incoming connections.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Packet header for IPv6.
Definition: ipv6-header.h:34
an Inet address class
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
static Ipv4Address GetAny(void)
UseEcn_t
Parameter value related to ECN enable/disable functionality similar to sysctl for tcp_ecn...
virtual bool GetTcpNoDelay(void) const
Check if Nagle&#39;s algorithm is enabled or not.
#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.
Ipv4Address GetIpv4MappedAddress() const
Return the Ipv4 address.
Last ACK received had ECE bit set in TCP header.
Normal state, no dubious events.
uint32_t m_dataRetries
Number of data retransmission attempts.
Connection established.
Definition: tcp-socket.h:71
virtual void SetInitialSSThresh(uint32_t threshold)
Set the initial Slow Start Threshold.
AttributeValue implementation for Boolean.
Definition: boolean.h:36
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
Callback template class.
Definition: callback.h:1278
bool IsIpv4MappedAddress() const
If the address is an IPv4-mapped address.
bool m_noDelay
Set to true to disable Nagle&#39;s algorithm.
CWND was reduced, we are fast-retransmitting.
uint32_t GetId(void) const
Definition: node.cc:109
In all the respects it is "Open", but requires a bit more attention.
virtual 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.
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer...
Definition: socket.h:1163
virtual Time GetPersistTimeout(void) const
Get the timeout for persistent connection.
A simple virtual Timer class.
Definition: timer.h:73
(abstract) base class of all TcpSockets
Definition: tcp-socket.h:47
Ipv4EndPoint * m_endPoint
the IPv4 endpoint
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
static Time ElapsedTimeFromTsValue(uint32_t echoTime)
Estimate the Time elapsed from a TS echo value.
bool m_pacing
Pacing status.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
TracedCallback< DataRate, DataRate > m_pacingRateTrace
Callback pointer for pacing rate trace chaining.
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
virtual ~TcpSocketBase(void)
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
uint32_t m_dataRetrCount
Count of remaining data retransmission attempts.
uint32_t m_synRetries
Number of connection attempts.
#define min(a, b)
Definition: 80211b.c:42
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.
uint32_t m_initialSsThresh
Initial Slow Start Threshold value.
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:85
uint8_t GetMaxOptionLength() const
Get maximum option length.
Definition: tcp-header.cc:167
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
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.
uint32_t m_rcvTimestampEchoReply
Sender Timestamp echoed by the receiver.
void ProcessOptionSackPermitted(const Ptr< const TcpOption > option)
Read the SACK PERMITTED option.
uint8_t GetTos(void) const
virtual void SetPersistTimeout(Time timeout)
Set the timeout for persistent connection.
static const char *const EcnStateName[TcpSocketState::ECN_CWR_SENT+1]
Literal names of ECN states for use in log messages.
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
EventId m_timewaitEvent
TIME_WAIT expiration event: Move this socket to CLOSED state.
void UpdateEcnState(TcpSocketState::EcnState_t oldValue, TcpSocketState::EcnState_t newValue)
Callback function to hook to EcnState state.
std::list< SackBlock > SackList
SACK list definition.
uint32_t GetRetxThresh(void) const
Get the retransmission threshold (dup ack threshold for a fast retransmit)
void NotifyConnectionFailed(void)
Notify through the callback (if set) that the connection has not been established due to an error...
Definition: socket.cc:227
virtual uint32_t GetSndBufSize(void) const
Get the send buffer size.
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.
uint8_t MarkEcnCodePoint(const uint8_t tos, const TcpSocketState::EcnCodePoint_t codePoint) const
mark ECN code point
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
void ProcessOptionTimestamp(const Ptr< const TcpOption > option, const SequenceNumber32 &seq)
Process the timestamp option from other side.
void SetUseEcn(TcpSocketState::UseEcn_t useEcn)
Set ECN mode of use on the socket.
TracedValue< EcnState_t > m_ecnState
Current ECN State, represented as combination of EcnState values.
Both sides have shutdown but we still have data we have to finish sending.
Definition: tcp-socket.h:81
virtual Time GetDelAckTimeout(void) const
Get the time to delay an ACK.
#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.
Time GetDelayLeft(void) const
Definition: timer.cc:87
virtual uint32_t GetDelAckMaxCount(void) const
Get the number of packet to fire an ACK before delay timeout.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Ptr< TcpSocketState > m_tcb
Congestion control information.
virtual void ProcessAck(const SequenceNumber32 &ackNumber, bool scoreboardUpdated, uint32_t currentDelivered, const SequenceNumber32 &oldHeadSequence)
Process a received ack.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1286
bool m_winScalingEnabled
Window Scale option enabled (RFC 7323)
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
bool m_timestampEnabled
Timestamp option enabled.
Timer m_pacingTimer
Pacing Event.
uint16_t m_maxWinSize
Maximum window size to advertise.
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
bool retx
True if this has been retransmitted.
virtual void NewAck(SequenceNumber32 const &seq, bool resetRTO)
Update buffers w.r.t.
uint32_t m_segmentSize
Segment size.
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:281
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
Time m_cnTimeout
Timeout for connection retry.
uint32_t m_initialCWnd
Initial cWnd value.
Ptr< TcpRxBuffer > m_rxBuffer
Rx buffer (reordering buffer)
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:802
virtual Time GetConnTimeout(void) const
Get the connection timeout.
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:80
void SetTos(uint8_t tos)
Set the tag&#39;s TOS.
Definition: socket.cc:785
TracedValue< SequenceNumber32 > m_ecnCESeq
Sequence number of the last received Congestion Experienced.
std::list< Ptr< const TcpOption > > TcpOptionList
List of TcpOption.
Definition: tcp-header.h:50
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received an ACK packet.
ns3::Time timeout
void AddSocketTags(const Ptr< Packet > &p) const
Add Tags for the Socket.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:1115
virtual uint32_t GetInitialSSThresh(void) const
Get the initial Slow Start Threshold.
bool m_isRetransDataAcked
Retransmitted data is ACKed if true.
virtual uint32_t BytesInFlight(void) const
Return total bytes in flight.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
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
TracedCallback< TcpSocketState::EcnState_t, TcpSocketState::EcnState_t > m_ecnStateTrace
Callback pointer for ECN state trace chaining.
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.
TracedValue< TcpStates_t > m_state
TCP state.
Time GetMinRto(void) const
Get the Minimum RTO.
uint32_t m_delAckMaxCount
Number of packet to fire an ACK before delay timeout.
bool m_paceInitialWindow
Enable/Disable pacing for the initial window.
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:65
Receiver sends an ACK with ECE bit set in TCP header.
uint16_t port
Definition: dsdv-manet.cc:45
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:1937
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 uint8_t GetIpTtl(void) const
Query the value of IP Time to Live field of this socket.
Definition: socket.cc:520
SequenceNumber32 m_recover
Previous highest Tx seqnum for fast recovery (set it to initial seq number)
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.
bool IsRetrans(void) const
Is the item retransmitted?
Definition: tcp-tx-item.cc:74
Class for representing data rates.
Definition: data-rate.h:88
virtual bool GetAllowBroadcast(void) const
Query whether broadcast datagram transmissions are allowed.
Last packet received had CE bit set in IP header.
virtual uint32_t GetRcvBufSize(void) const
Get the receive buffer size.
Ptr< NetDevice > GetBoundNetDevice()
Returns socket&#39;s bound NetDevice, if any.
Definition: socket.cc:351
Packet header for IPv4.
Definition: ipv4-header.h:33
void SetLocalAddress(Ipv6Address addr)
Set the local address.
virtual void CalculateAppLimited(uint32_t cWnd, uint32_t in_flight, uint32_t segmentSize, const SequenceNumber32 &tailSeq, const SequenceNumber32 &nextTx, const uint32_t lostOut, const uint32_t retransOut)=0
If a gap is detected between sends, it means we are app-limited.
Callback< void, uint8_t > m_sendEmptyPacketCallback
void UpdateBytesInFlight(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState bytes inflight.
virtual enum SocketType GetSocketType(void) const
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:94
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:218
void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Ptr< TcpRateOps > m_rateOps
Rate operations.
Ptr< TcpRxBuffer > GetRxBuffer(void) const
Get a pointer to the Rx buffer.
Item that encloses the application packet and some flags for it.
Definition: tcp-tx-item.h:32
bool CheckNoEcn(uint8_t tos) const
Checks if TOS has no ECN codepoints.
TracedValue< uint32_t > m_cWndInfl
Inflated congestion window trace (used only for backward compatibility purpose)
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.
bool IsTcpOptionEnabled(uint8_t kind) const
Return true if the specified option is enabled.
virtual uint32_t GetSegSize(void) const
Get the segment size.
virtual void EstimateRtt(const TcpHeader &tcpHeader)
Take into account the packet for RTT estimation.
virtual int GetSockName(Address &address) const
Get socket address.
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:227
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
Hold variables of type enum.
Definition: enum.h:54
Time time
Time this one was sent.
void ReadOptions(const TcpHeader &tcpHeader, uint32_t *bytesSacked)
Read TCP options before Ack processing.
#define max(a, b)
Definition: 80211b.c:43
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.
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:300
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:588
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&#39;s TTL.
Definition: socket.cc:604
AttributeValue implementation for Time.
Definition: nstime.h:1342
void Schedule(void)
Schedule a new event using the currently-configured delay, function, and arguments.
Definition: timer.cc:158
bool OutOfRange(SequenceNumber32 head, SequenceNumber32 tail) const
Check if a sequence number range is within the rx window.
TracedValue< DataRate > m_pacingRate
Current Pacing rate.
uint16_t GetLocalPort()
Get the local port.
bool IsPacingEnabled(void) const
Return true if packets in the current window should be paced.
virtual uint32_t Window(void) const
Return the max possible number of unacked bytes.
void UpdateWindowSize(const TcpHeader &header)
Update the receiver window (RWND) based on the value of the window field in the header.
void SetFunction(FN fn)
Definition: timer.h:278
Ptr< const AttributeChecker > MakeCallbackChecker(void)
Definition: callback.cc:74
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.
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: enum.h:203
void SetPacingStatus(bool pacing)
Enable or disable pacing.
std::deque< RttHistory > m_history
List of sent packet.
virtual enum SocketErrno GetErrno(void) const
Get last error number.
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:970
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:1981
Ipv4Address GetLocalAddress(void)
Get the local address.
indicates whether the socket has a priority set.
Definition: socket.h:1307
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:230
An Inet6 address class.
void SetRetxThresh(uint32_t retxThresh)
Set the retransmission threshold (dup ack threshold for a fast retransmit)
virtual void SetTcpNoDelay(bool noDelay)
Enable/Disable Nagle&#39;s algorithm.
Ptr< TcpRecoveryOps > m_recoveryOps
Recovery Algorithm.
RttHistory(SequenceNumber32 s, uint32_t c, Time t)
Constructor - builds an RttHistory with the given parameters.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
void NotifyPacingPerformed(void)
Notify Pacing.
EcnMode_t m_ecnMode
ECN mode.
void UpdateCongState(TcpSocketState::TcpCongState_t oldValue, TcpSocketState::TcpCongState_t newValue)
Callback function to hook to TcpSocketState congestion state.
virtual void SkbDelivered(TcpTxItem *skb)=0
Update the Rate information after an item is received.
SequenceNumber32 m_lastAckedSeq
Last sequence ACKed.
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
ECN is enabled but currently there is no action pertaining to ECE or CWR to be taken.
virtual uint32_t GetRxAvailable(void) const
Return number of bytes which can be returned from one or multiple calls to Recv.
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:511
friend Ptr< T > CopyObject(Ptr< T > object)
Copy an Object.
Definition: object.h:528
UseEcn_t m_useEcn
Socket ECN capability.
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)
int SetupCallback(void)
Common part of the two Bind(), i.e.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
TracedValue< uint32_t > m_bytesInFlight
Bytes in flight.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
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&#39;s Hop Limit.
Definition: socket.cc:665
void SetRecoveryAlgorithm(Ptr< TcpRecoveryOps > recovery)
Install a recovery algorithm on this socket.
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.
Ptr< TcpTxBuffer > GetTxBuffer(void) const
Get a pointer to the Tx buffer.
uint32_t GetRWnd(void) const
Get the current value of the receiver&#39;s offered window (RCV.WND)
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.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void SetPaceInitialWindow(bool paceWindow)
Enable or disable pacing of the initial window.
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
virtual uint32_t GetTxAvailable(void) const
Returns the number of bytes which can be sent in a single call to Send.
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.
Ptr< const TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:495
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:293
void AddOptions(TcpHeader &tcpHeader)
Add options to TcpHeader.
ECN functionality as described in RFC 8257.
void UpdateNextTxSequence(SequenceNumber32 oldValue, SequenceNumber32 newValue)
Callback function to hook to TcpSocketState next tx sequence.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t m_dupAckCount
Dupack counter.
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
void UpdateRtt(Time oldValue, Time newValue)
Callback function to hook to TcpSocketState rtt.
Ptr< Node > m_node
the associated node
Hold objects of type Ptr<T>.
Definition: pointer.h:36
virtual uint32_t AvailableWindow(void) const
Return unfilled portion of window.
address
Definition: first.py:44
Generic "sequence number" class.
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.
void TimeWait(void)
Move from CLOSING or FIN_WAIT_2 to TIME_WAIT state.
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:371
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
virtual void SetNode(Ptr< Node > node)
Set the associated node.
virtual uint32_t GetDataRetries(void) const
Get the number of data transmission retries before giving up.
EcnType GetEcn(void) const
Definition: ipv6-header.cc:262
TracedCallback< uint32_t, uint32_t > m_bytesInFlightTrace
Callback pointer for bytesInFlight trace chaining.
uint32_t ProcessOptionSack(const Ptr< const TcpOption > option)
Read the SACK option.
void AddOptionSackPermitted(TcpHeader &header)
Add the SACK PERMITTED option to the header.
uint16_t GetPort(void) const
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
bool m_recoverActive
Whether "m_recover" has been set/activated It is used to avoid comparing with the old m_recover value...
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1354
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:83
SequenceNumber32 GetHighRxAck(void) const
Get the current value of the receiver&#39;s highest (in-sequence) sequence number acked.
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:161
virtual int Close(void)
Close a socket.
void UpdateCwndInfl(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState inflated congestion window.
TracedValue< SequenceNumber32 > m_ecnCWRSeq
Sequence number of the last sent CWR.
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:1343
Our side has shutdown after remote has shutdown.
Definition: tcp-socket.h:75
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer information (address and port).
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
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:72
Sent a connection request, waiting for ack.
Definition: tcp-socket.h:68
virtual void SetRtt(Ptr< RttEstimator > rtt)
Set the associated RTT estimator.
virtual TypeId GetInstanceTypeId() const
Get the instance TypeId.
double m_msl
Max segment lifetime.
virtual void ReTxTimeout(void)
An RTO event happened.
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., ACK.
Time m_delAckTimeout
Time to delay an ACK.
virtual int GetPeerName(Address &address) const
Get the peer address of a connected socket.
TracedValue< uint32_t > m_cWnd
Congestion window.
Socket is finished.
Definition: tcp-socket.h:66
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:67
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:495
uint64_t m_delivered
The total amount of data in bytes delivered so far.
Definition: tcp-rate-ops.h:163
bool IsRunning(void) const
Definition: timer.cc:127
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
#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:88
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.
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:383
static Time FromDouble(double value, enum Unit unit)
Create a Time equal to value in unit unit.
Definition: nstime.h:480
virtual void SetDelAckTimeout(Time timeout)
Set the time to delay an ACK.
EcnCodePoint_t m_ectCodePoint
ECT code point to use.
void DeallocateEndPoint(void)
Deallocate m_endPoint and m_endPoint6.
Describes an IPv6 address.
Definition: ipv6-address.h:49
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
Sender has reduced the congestion window, and sent a packet with CWR bit set in TCP header...
void ProcessEstablished(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon ESTABLISHED state.
virtual const TcpRateConnection & GetConnectionRate()=0
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:1076
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
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
uint16_t m_pacingSsRatio
SS pacing ratio.
TracedValue< Time > m_rto
Retransmit timeout.
Helper class to store RTT measurements.
Ptr< Packet > GetPacketCopy(void) const
Get a copy of the Packet underlying this item.
Definition: tcp-tx-item.cc:80
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
uint16_t GetLocalPort(void)
Get the local port.
uint8_t m_rcvWindShift
Window shift to apply to outgoing segments.
virtual uint16_t AdvertisedWindowSize(bool scale=true) const
The amount of Rx window announced to the peer.
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:545
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
TracedValue< Time > m_lastRtt
Last RTT sample collected.
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:78
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
CWND was reduced due to RTO timeout or SACK reneging.
virtual uint8_t GetKind(void) const =0
Get the ‘kind’ (as in RFC 793) of this option.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
void DupAck(uint32_t currentDelivered)
Dupack management.
T Get(void) const
Get the underlying value.
Definition: traced-value.h:229
TracedValue< SequenceNumber32 > m_ecnEchoSeq
Sequence number of the last received ECN Echo.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1278
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
void Cancel(void)
Cancel the currently-running event if there is one.
Definition: timer.cc:109
bool m_sackEnabled
RFC SACK option enabled.
Time m_minRtt
Minimum RTT observed throughout the connection.
uint16_t m_pacingCaRatio
CA pacing ratio.
Ipv4Address GetPeerAddress(void)
Get the peer address.
Enable only when the peer endpoint is ECN capable.
uint32_t m_timestampToEcho
Timestamp to echo.
uint32_t m_synCount
Count of remaining connection retries.
void UpdatePacingRateTrace(DataRate oldValue, DataRate newValue)
Callback function to hook to TcpSocketState pacing rate.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void AddOptionSack(TcpHeader &header)
Add the SACK option to the header.
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv6Header, uint16_t, Ptr< Ipv6Interface > > callback)
Set the reception callback.
virtual const TcpRateSample & GenerateSample(uint32_t delivered, uint32_t lost, bool is_sack_reneg, uint32_t priorInFlight, const Time &minRtt)=0
Generate a TcpRateSample to feed a congestion avoidance algorithm.
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.
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:161
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
TracedValue< SequenceNumber32 > m_highTxMark
Highest seqno ever sent, regardless of ReTx.
void ProcessLastAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon LAST_ACK.
TracedCallback< Time, Time > m_lastRttTrace
Callback pointer for RTT trace chaining.
void UpdateSsThresh(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState slow start threshold.
first transmit when no packets in flight
virtual void SetSegSize(uint32_t size)
Set the segment size.
void ProcessClosing(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon CLOSING.
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
Time GetClockGranularity(void) const
Get the Clock Granularity (used in RTO calcs).
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:472
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:463
Received a connection request, sent ack, waiting for final ack in three-way handshake.
Definition: tcp-socket.h:69
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
second
Definition: nstime.h:115
virtual uint32_t GetInitialCwnd(void) const
Get the initial Congestion Window.
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.
virtual void SetRcvBufSize(uint32_t size)
Set the receive buffer size.
virtual Ptr< Node > GetNode(void) const
Return the node this socket is associated with.
bool m_shutdownRecv
Receive no longer allowed.
TracedCallback< uint32_t, uint32_t > m_ssThTrace
Callback pointer for ssTh trace chaining.
EventId m_sendPendingDataEvent
micro-delay event to send pending data
bool IsValidTcpSegment(const SequenceNumber32 seq, const uint32_t tcpHeaderSize, const uint32_t tcpPayloadSize)
Checks whether the given TCP segment is valid or not.
uint16_t GetPort(void) const
Get the port.
uint32_t SendPendingData(bool withAck=false)
Send as much pending data as possible according to the Tx window.
DataRate m_maxPacingRate
Max Pacing rate.
virtual void DelAckTimeout(void)
Action upon delay ACK timeout, i.e.
Ipv4Address GetSource(void) const
Definition: ipv4-route.cc:56
virtual void LastAckTimeout(void)
Timeout at LAST_ACK, close the connection.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
uint8_t CalculateWScale() const
Calculate window scale value based on receive buffer space.
void SetPriority(uint8_t priority)
Set the tag&#39;s priority.
Definition: socket.cc:842
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
uint32_t m_bytesAckedNotProcessed
Bytes acked, but not processed.
bool IsExpired(void) const
Definition: timer.cc:121
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:1261
TracedCallback< uint32_t, uint32_t > m_cWndInflTrace
Callback pointer for cWndInfl trace chaining.
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
bool IsManualIpTtl(void) const
Checks if the socket has a specific IPv4 TTL set.
Definition: socket.cc:377
uint8_t GetIpTos(void) const
Query the value of IP Type of Service of this socket.
Definition: socket.cc:453
void EnterRecovery(uint32_t currentDelivered)
Enter the CA_RECOVERY, and retransmit the head.
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
void SetIpTos(uint8_t ipTos)
Manually set IP Type of Service field.
Definition: socket.cc:437
EventId m_delAckEvent
Delayed ACK timeout event.
received CE marked IP packet.
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 uint32_t UnAckDataCount(void) const
Return count of number of unacked bytes.
virtual Ptr< TcpSocketBase > Fork(void)
Call CopyObject<> to clone me.
EcnType GetEcn(void) const
Definition: ipv4-header.cc:167
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:923
Time m_clockGranularity
Clock Granularity used in RTO calcs.
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
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
void UpdatePacingRate(void)
Dynamically update the pacing rate.
void DoRetransmit(void)
Retransmit the first segment marked as lost, without considering available window nor pacing...
bool m_closeOnEmpty
Close socket upon tx buffer emptied.
TracedCallback< Ptr< const Packet >, const TcpHeader &, Ptr< const TcpSocketBase > > m_txTrace
Trace of transmitted packets.
uint8_t GetPriority(void) const
Query the priority value of this socket.
Definition: socket.cc:396
void AddOptionWScale(TcpHeader &header)
Add the window scale option to the header.
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 information (address and port).
Ipv4Address GetIpv4(void) const
int SetupEndpoint(void)
Configure the endpoint to a local address.
virtual void SkbSent(TcpTxItem *skb, bool isStartOfTransmission)=0
Put the rate information inside the sent skb.
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.
EcnState_t
Definition of the Ecn state machine.
ECT set, but not CE marked.
Time m_persistTimeout
Time between sending 1-byte probes.