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 ("CongestionWindow",
200  "The TCP connection's congestion window",
202  "ns3::TracedValueCallback::Uint32")
203  .AddTraceSource ("CongestionWindowInflated",
204  "The TCP connection's congestion window inflates as in older RFC",
206  "ns3::TracedValueCallback::Uint32")
207  .AddTraceSource ("SlowStartThreshold",
208  "TCP slow start threshold (bytes)",
210  "ns3::TracedValueCallback::Uint32")
211  .AddTraceSource ("Tx",
212  "Send tcp packet to IP protocol",
214  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
215  .AddTraceSource ("Rx",
216  "Receive tcp packet from IP protocol",
218  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
219  .AddTraceSource ("EcnEchoSeq",
220  "Sequence of last received ECN Echo",
222  "ns3::SequenceNumber32TracedValueCallback")
223  .AddTraceSource ("EcnCeSeq",
224  "Sequence of last received CE ",
226  "ns3::SequenceNumber32TracedValueCallback")
227  .AddTraceSource ("EcnCwrSeq",
228  "Sequence of last received CWR",
230  "ns3::SequenceNumber32TracedValueCallback")
231  ;
232  return tid;
233 }
234 
235 TypeId
237 {
238  return TcpSocketBase::GetTypeId ();
239 }
240 
242  : TcpSocket ()
243 {
244  NS_LOG_FUNCTION (this);
245  m_txBuffer = CreateObject<TcpTxBuffer> ();
246  m_txBuffer->SetRWndCallback (MakeCallback (&TcpSocketBase::GetRWnd, this));
247  m_tcb = CreateObject<TcpSocketState> ();
248  m_rateOps = CreateObject <TcpRateLinux> ();
249 
250  m_tcb->m_rxBuffer = CreateObject<TcpRxBuffer> ();
251 
254 
256 
257  bool ok;
258 
259  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
261  NS_ASSERT (ok == true);
262 
263  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindowInflated",
265  NS_ASSERT (ok == true);
266 
267  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
269  NS_ASSERT (ok == true);
270 
271  ok = m_tcb->TraceConnectWithoutContext ("CongState",
273  NS_ASSERT (ok == true);
274 
275  ok = m_tcb->TraceConnectWithoutContext ("EcnState",
277  NS_ASSERT (ok == true);
278 
279  ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
281  NS_ASSERT (ok == true);
282 
283  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
285  NS_ASSERT (ok == true);
286 
287  ok = m_tcb->TraceConnectWithoutContext ("BytesInFlight",
289  NS_ASSERT (ok == true);
290 
291  ok = m_tcb->TraceConnectWithoutContext ("RTT",
293  NS_ASSERT (ok == true);
294 }
295 
297  : TcpSocket (sock),
298  //copy object::m_tid and socket::callbacks
299  m_dupAckCount (sock.m_dupAckCount),
300  m_delAckCount (0),
301  m_delAckMaxCount (sock.m_delAckMaxCount),
302  m_noDelay (sock.m_noDelay),
303  m_synCount (sock.m_synCount),
304  m_synRetries (sock.m_synRetries),
305  m_dataRetrCount (sock.m_dataRetrCount),
306  m_dataRetries (sock.m_dataRetries),
307  m_rto (sock.m_rto),
308  m_minRto (sock.m_minRto),
309  m_clockGranularity (sock.m_clockGranularity),
310  m_delAckTimeout (sock.m_delAckTimeout),
311  m_persistTimeout (sock.m_persistTimeout),
312  m_cnTimeout (sock.m_cnTimeout),
313  m_endPoint (nullptr),
314  m_endPoint6 (nullptr),
315  m_node (sock.m_node),
316  m_tcp (sock.m_tcp),
317  m_state (sock.m_state),
318  m_errno (sock.m_errno),
319  m_closeNotified (sock.m_closeNotified),
320  m_closeOnEmpty (sock.m_closeOnEmpty),
321  m_shutdownSend (sock.m_shutdownSend),
322  m_shutdownRecv (sock.m_shutdownRecv),
323  m_connected (sock.m_connected),
324  m_msl (sock.m_msl),
325  m_maxWinSize (sock.m_maxWinSize),
326  m_bytesAckedNotProcessed (sock.m_bytesAckedNotProcessed),
327  m_rWnd (sock.m_rWnd),
328  m_highRxMark (sock.m_highRxMark),
329  m_highRxAckMark (sock.m_highRxAckMark),
330  m_sackEnabled (sock.m_sackEnabled),
331  m_winScalingEnabled (sock.m_winScalingEnabled),
332  m_rcvWindShift (sock.m_rcvWindShift),
333  m_sndWindShift (sock.m_sndWindShift),
334  m_timestampEnabled (sock.m_timestampEnabled),
335  m_timestampToEcho (sock.m_timestampToEcho),
336  m_recover (sock.m_recover),
337  m_recoverActive (sock.m_recoverActive),
338  m_retxThresh (sock.m_retxThresh),
339  m_limitedTx (sock.m_limitedTx),
340  m_isFirstPartialAck (sock.m_isFirstPartialAck),
341  m_txTrace (sock.m_txTrace),
342  m_rxTrace (sock.m_rxTrace),
343  m_pacingTimer (Timer::CANCEL_ON_DESTROY),
344  m_ecnEchoSeq (sock.m_ecnEchoSeq),
345  m_ecnCESeq (sock.m_ecnCESeq),
346  m_ecnCWRSeq (sock.m_ecnCWRSeq)
347 {
348  NS_LOG_FUNCTION (this);
349  NS_LOG_LOGIC ("Invoked the copy constructor");
350  // Copy the rtt estimator if it is set
351  if (sock.m_rtt)
352  {
353  m_rtt = sock.m_rtt->Copy ();
354  }
355  // Reset all callbacks to null
356  Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
357  Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr<Socket>, const Address &> ();
358  Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t> ();
359  SetConnectCallback (vPS, vPS);
360  SetDataSentCallback (vPSUI);
361  SetSendCallback (vPSUI);
362  SetRecvCallback (vPS);
364  m_txBuffer->SetRWndCallback (MakeCallback (&TcpSocketBase::GetRWnd, this));
365  m_tcb = CopyObject (sock.m_tcb);
367 
370 
371  if (sock.m_congestionControl)
372  {
374  m_congestionControl->Init (m_tcb);
375  }
376 
377  if (sock.m_recoveryOps)
378  {
379  m_recoveryOps = sock.m_recoveryOps->Fork ();
380  }
381 
382  m_rateOps = CreateObject <TcpRateLinux> ();
384  {
386  }
387 
388  bool ok;
389 
390  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
392  NS_ASSERT (ok == true);
393 
394  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindowInflated",
396  NS_ASSERT (ok == true);
397 
398  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
400  NS_ASSERT (ok == true);
401 
402  ok = m_tcb->TraceConnectWithoutContext ("CongState",
404  NS_ASSERT (ok == true);
405 
406  ok = m_tcb->TraceConnectWithoutContext ("EcnState",
408  NS_ASSERT (ok == true);
409 
410  ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
412  NS_ASSERT (ok == true);
413 
414  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
416  NS_ASSERT (ok == true);
417 
418  ok = m_tcb->TraceConnectWithoutContext ("BytesInFlight",
420  NS_ASSERT (ok == true);
421 
422  ok = m_tcb->TraceConnectWithoutContext ("RTT",
424  NS_ASSERT (ok == true);
425 }
426 
428 {
429  NS_LOG_FUNCTION (this);
430  m_node = nullptr;
431  if (m_endPoint != nullptr)
432  {
433  NS_ASSERT (m_tcp != nullptr);
434  /*
435  * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
436  * DestroyCallback is set to TcpSocketBase::Destroy. If we called
437  * m_tcp->DeAllocate, it will destroy its Ipv4EndpointDemux::DeAllocate,
438  * which in turn destroys my m_endPoint, and in turn invokes
439  * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
440  */
441  NS_ASSERT (m_endPoint != nullptr);
442  m_tcp->DeAllocate (m_endPoint);
443  NS_ASSERT (m_endPoint == nullptr);
444  }
445  if (m_endPoint6 != nullptr)
446  {
447  NS_ASSERT (m_tcp != nullptr);
448  NS_ASSERT (m_endPoint6 != nullptr);
449  m_tcp->DeAllocate (m_endPoint6);
450  NS_ASSERT (m_endPoint6 == nullptr);
451  }
452  m_tcp = 0;
453  CancelAllTimers ();
454 }
455 
456 /* Associate a node with this TCP socket */
457 void
459 {
460  m_node = node;
461 }
462 
463 /* Associate the L4 protocol (e.g. mux/demux) with this socket */
464 void
466 {
467  m_tcp = tcp;
468 }
469 
470 /* Set an RTT estimator with this socket */
471 void
473 {
474  m_rtt = rtt;
475 }
476 
477 /* Inherit from Socket class: Returns error code */
480 {
481  return m_errno;
482 }
483 
484 /* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
487 {
488  return NS3_SOCK_STREAM;
489 }
490 
491 /* Inherit from Socket class: Returns associated node */
492 Ptr<Node>
494 {
495  return m_node;
496 }
497 
498 /* Inherit from Socket class: Bind socket to an end-point in TcpL4Protocol */
499 int
501 {
502  NS_LOG_FUNCTION (this);
503  m_endPoint = m_tcp->Allocate ();
504  if (0 == m_endPoint)
505  {
506  m_errno = ERROR_ADDRNOTAVAIL;
507  return -1;
508  }
509 
510  m_tcp->AddSocket (this);
511 
512  return SetupCallback ();
513 }
514 
515 int
517 {
518  NS_LOG_FUNCTION (this);
519  m_endPoint6 = m_tcp->Allocate6 ();
520  if (0 == m_endPoint6)
521  {
522  m_errno = ERROR_ADDRNOTAVAIL;
523  return -1;
524  }
525 
526  m_tcp->AddSocket (this);
527 
528  return SetupCallback ();
529 }
530 
531 /* Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
532 int
534 {
535  NS_LOG_FUNCTION (this << address);
537  {
539  Ipv4Address ipv4 = transport.GetIpv4 ();
540  uint16_t port = transport.GetPort ();
541  SetIpTos (transport.GetTos ());
542  if (ipv4 == Ipv4Address::GetAny () && port == 0)
543  {
544  m_endPoint = m_tcp->Allocate ();
545  }
546  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
547  {
548  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (), port);
549  }
550  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
551  {
552  m_endPoint = m_tcp->Allocate (ipv4);
553  }
554  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
555  {
556  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (), ipv4, port);
557  }
558  if (0 == m_endPoint)
559  {
561  return -1;
562  }
563  }
565  {
567  Ipv6Address ipv6 = transport.GetIpv6 ();
568  uint16_t port = transport.GetPort ();
569  if (ipv6 == Ipv6Address::GetAny () && port == 0)
570  {
571  m_endPoint6 = m_tcp->Allocate6 ();
572  }
573  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
574  {
575  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (), port);
576  }
577  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
578  {
579  m_endPoint6 = m_tcp->Allocate6 (ipv6);
580  }
581  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
582  {
583  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (), ipv6, port);
584  }
585  if (0 == m_endPoint6)
586  {
588  return -1;
589  }
590  }
591  else
592  {
593  m_errno = ERROR_INVAL;
594  return -1;
595  }
596 
597  m_tcp->AddSocket (this);
598 
599  NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
600 
601  return SetupCallback ();
602 }
603 
604 void
606 {
607  NS_ABORT_MSG_UNLESS ( (m_state == CLOSED) || threshold == m_tcb->m_initialSsThresh,
608  "TcpSocketBase::SetSSThresh() cannot change initial ssThresh after connection started.");
609 
610  m_tcb->m_initialSsThresh = threshold;
611 }
612 
613 uint32_t
615 {
616  return m_tcb->m_initialSsThresh;
617 }
618 
619 void
621 {
623  "TcpSocketBase::SetInitialCwnd() cannot change initial cwnd after connection started.");
624 
625  m_tcb->m_initialCWnd = cwnd;
626 }
627 
628 uint32_t
630 {
631  return m_tcb->m_initialCWnd;
632 }
633 
634 /* Inherit from Socket class: Initiate connection to a remote address:port */
635 int
637 {
638  NS_LOG_FUNCTION (this << address);
639 
640  // If haven't do so, Bind() this socket first
642  {
643  if (m_endPoint == nullptr)
644  {
645  if (Bind () == -1)
646  {
647  NS_ASSERT (m_endPoint == nullptr);
648  return -1; // Bind() failed
649  }
650  NS_ASSERT (m_endPoint != nullptr);
651  }
653  m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
654  SetIpTos (transport.GetTos ());
655  m_endPoint6 = nullptr;
656 
657  // Get the appropriate local address and port number from the routing protocol and set up endpoint
658  if (SetupEndpoint () != 0)
659  {
660  NS_LOG_ERROR ("Route to destination does not exist ?!");
661  return -1;
662  }
663  }
665  {
666  // If we are operating on a v4-mapped address, translate the address to
667  // a v4 address and re-call this function
669  Ipv6Address v6Addr = transport.GetIpv6 ();
670  if (v6Addr.IsIpv4MappedAddress () == true)
671  {
672  Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
673  return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
674  }
675 
676  if (m_endPoint6 == nullptr)
677  {
678  if (Bind6 () == -1)
679  {
680  NS_ASSERT (m_endPoint6 == nullptr);
681  return -1; // Bind() failed
682  }
683  NS_ASSERT (m_endPoint6 != nullptr);
684  }
685  m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
686  m_endPoint = nullptr;
687 
688  // Get the appropriate local address and port number from the routing protocol and set up endpoint
689  if (SetupEndpoint6 () != 0)
690  {
691  NS_LOG_ERROR ("Route to destination does not exist ?!");
692  return -1;
693  }
694  }
695  else
696  {
697  m_errno = ERROR_INVAL;
698  return -1;
699  }
700 
701  // Re-initialize parameters in case this socket is being reused after CLOSE
702  m_rtt->Reset ();
705 
706  // DoConnect() will do state-checking and send a SYN packet
707  return DoConnect ();
708 }
709 
710 /* Inherit from Socket class: Listen on the endpoint for an incoming connection */
711 int
713 {
714  NS_LOG_FUNCTION (this);
715 
716  // Linux quits EINVAL if we're not in CLOSED state, so match what they do
717  if (m_state != CLOSED)
718  {
719  m_errno = ERROR_INVAL;
720  return -1;
721  }
722  // In other cases, set the state to LISTEN and done
723  NS_LOG_DEBUG ("CLOSED -> LISTEN");
724  m_state = LISTEN;
725  return 0;
726 }
727 
728 /* Inherit from Socket class: Kill this socket and signal the peer (if any) */
729 int
731 {
732  NS_LOG_FUNCTION (this);
736  if (m_tcb->m_rxBuffer->Size () != 0)
737  {
738  NS_LOG_WARN ("Socket " << this << " << unread rx data during close. Sending reset." <<
739  "This is probably due to a bad sink application; check its code");
740  SendRST ();
741  return 0;
742  }
743 
744  if (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
745  { // App close with pending data must wait until all data transmitted
746  if (m_closeOnEmpty == false)
747  {
748  m_closeOnEmpty = true;
749  NS_LOG_INFO ("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
750  }
751  return 0;
752  }
753  return DoClose ();
754 }
755 
756 /* Inherit from Socket class: Signal a termination of send */
757 int
759 {
760  NS_LOG_FUNCTION (this);
761 
762  //this prevents data from being added to the buffer
763  m_shutdownSend = true;
764  m_closeOnEmpty = true;
765  //if buffer is already empty, send a fin now
766  //otherwise fin will go when buffer empties.
767  if (m_txBuffer->Size () == 0)
768  {
769  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
770  {
771  NS_LOG_INFO ("Empty tx buffer, send fin");
773 
774  if (m_state == ESTABLISHED)
775  { // On active close: I am the first one to send FIN
776  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
778  }
779  else
780  { // On passive close: Peer sent me FIN already
781  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
782  m_state = LAST_ACK;
783  }
784  }
785  }
786 
787  return 0;
788 }
789 
790 /* Inherit from Socket class: Signal a termination of receive */
791 int
793 {
794  NS_LOG_FUNCTION (this);
795  m_shutdownRecv = true;
796  return 0;
797 }
798 
799 /* Inherit from Socket class: Send a packet. Parameter flags is not used.
800  Packet has no TCP header. Invoked by upper-layer application */
801 int
802 TcpSocketBase::Send (Ptr<Packet> p, uint32_t flags)
803 {
804  NS_LOG_FUNCTION (this << p);
805  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Send()");
807  {
808  // Store the packet into Tx buffer
809  if (!m_txBuffer->Add (p))
810  { // TxBuffer overflow, send failed
811  m_errno = ERROR_MSGSIZE;
812  return -1;
813  }
814  if (m_shutdownSend)
815  {
816  m_errno = ERROR_SHUTDOWN;
817  return -1;
818  }
819 
821  m_txBuffer->TailSequence (), m_tcb->m_nextTxSequence,
822  m_txBuffer->GetLost (), m_txBuffer->GetRetransmitsCount ());
823 
824  // Submit the data to lower layers
825  NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpStateName[m_state]);
826  if ((m_state == ESTABLISHED || m_state == CLOSE_WAIT) && AvailableWindow () > 0)
827  { // Try to send the data out: Add a little step to allow the application
828  // to fill the buffer
830  {
833  this, m_connected);
834  }
835  }
836  return p->GetSize ();
837  }
838  else
839  { // Connection not established yet
840  m_errno = ERROR_NOTCONN;
841  return -1; // Send failure
842  }
843 }
844 
845 /* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
846 int
848 {
849  NS_UNUSED (address);
850  return Send (p, flags); // SendTo() and Send() are the same
851 }
852 
853 /* Inherit from Socket class: Return data to upper-layer application. Parameter flags
854  is not used. Data is returned as a packet of size no larger than maxSize */
856 TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
857 {
858  NS_LOG_FUNCTION (this);
859  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()");
860  if (m_tcb->m_rxBuffer->Size () == 0 && m_state == CLOSE_WAIT)
861  {
862  return Create<Packet> (); // Send EOF on connection close
863  }
864  Ptr<Packet> outPacket = m_tcb->m_rxBuffer->Extract (maxSize);
865  return outPacket;
866 }
867 
868 /* Inherit from Socket class: Recv and return the remote's address */
870 TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
871 {
872  NS_LOG_FUNCTION (this << maxSize << flags);
873  Ptr<Packet> packet = Recv (maxSize, flags);
874  // Null packet means no data to read, and an empty packet indicates EOF
875  if (packet != nullptr && packet->GetSize () != 0)
876  {
877  if (m_endPoint != nullptr)
878  {
880  }
881  else if (m_endPoint6 != nullptr)
882  {
884  }
885  else
886  {
887  fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
888  }
889  }
890  return packet;
891 }
892 
893 /* Inherit from Socket class: Get the max number of bytes an app can send */
894 uint32_t
896 {
897  NS_LOG_FUNCTION (this);
898  return m_txBuffer->Available ();
899 }
900 
901 /* Inherit from Socket class: Get the max number of bytes an app can read */
902 uint32_t
904 {
905  NS_LOG_FUNCTION (this);
906  return m_tcb->m_rxBuffer->Available ();
907 }
908 
909 /* Inherit from Socket class: Return local address:port */
910 int
912 {
913  NS_LOG_FUNCTION (this);
914  if (m_endPoint != nullptr)
915  {
917  }
918  else if (m_endPoint6 != nullptr)
919  {
921  }
922  else
923  { // It is possible to call this method on a socket without a name
924  // in which case, behavior is unspecified
925  // Should this return an InetSocketAddress or an Inet6SocketAddress?
927  }
928  return 0;
929 }
930 
931 int
933 {
934  NS_LOG_FUNCTION (this << address);
935 
936  if (!m_endPoint && !m_endPoint6)
937  {
938  m_errno = ERROR_NOTCONN;
939  return -1;
940  }
941 
942  if (m_endPoint)
943  {
945  m_endPoint->GetPeerPort ());
946  }
947  else if (m_endPoint6)
948  {
951  }
952  else
953  {
954  NS_ASSERT (false);
955  }
956 
957  return 0;
958 }
959 
960 /* Inherit from Socket class: Bind this socket to the specified NetDevice */
961 void
963 {
964  NS_LOG_FUNCTION (netdevice);
965  Socket::BindToNetDevice (netdevice); // Includes sanity check
966  if (m_endPoint != nullptr)
967  {
968  m_endPoint->BindToNetDevice (netdevice);
969  }
970 
971  if (m_endPoint6 != nullptr)
972  {
973  m_endPoint6->BindToNetDevice (netdevice);
974  }
975 
976  return;
977 }
978 
979 /* Clean up after Bind. Set up callback functions in the end-point. */
980 int
982 {
983  NS_LOG_FUNCTION (this);
984 
985  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
986  {
987  return -1;
988  }
989  if (m_endPoint != nullptr)
990  {
994  }
995  if (m_endPoint6 != nullptr)
996  {
1000  }
1001 
1002  return 0;
1003 }
1004 
1005 /* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
1006 int
1008 {
1009  NS_LOG_FUNCTION (this);
1010 
1011  // A new connection is allowed only if this socket does not have a connection
1012  if (m_state == CLOSED || m_state == LISTEN || m_state == SYN_SENT || m_state == LAST_ACK || m_state == CLOSE_WAIT)
1013  { // send a SYN packet and change state into SYN_SENT
1014  // send a SYN packet with ECE and CWR flags set if sender is ECN capable
1016  {
1018  }
1019  else
1020  {
1022  }
1023  NS_LOG_DEBUG (TcpStateName[m_state] << " -> SYN_SENT");
1024  m_state = SYN_SENT;
1025  m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; // because sender is not yet aware about receiver's ECN capability
1026  }
1027  else if (m_state != TIME_WAIT)
1028  { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
1029  // exists. We send RST, tear down everything, and close this socket.
1030  SendRST ();
1031  CloseAndNotify ();
1032  }
1033  return 0;
1034 }
1035 
1036 /* Do the action to close the socket. Usually send a packet with appropriate
1037  flags depended on the current m_state. */
1038 int
1040 {
1041  NS_LOG_FUNCTION (this);
1042  switch (m_state)
1043  {
1044  case SYN_RCVD:
1045  case ESTABLISHED:
1046  // send FIN to close the peer
1048  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
1049  m_state = FIN_WAIT_1;
1050  break;
1051  case CLOSE_WAIT:
1052  // send FIN+ACK to close the peer
1054  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
1055  m_state = LAST_ACK;
1056  break;
1057  case SYN_SENT:
1058  case CLOSING:
1059  // Send RST if application closes in SYN_SENT and CLOSING
1060  SendRST ();
1061  CloseAndNotify ();
1062  break;
1063  case LISTEN:
1064  // In this state, move to CLOSED and tear down the end point
1065  CloseAndNotify ();
1066  break;
1067  case LAST_ACK:
1068  case CLOSED:
1069  case FIN_WAIT_1:
1070  case FIN_WAIT_2:
1071  case TIME_WAIT:
1072  default: /* mute compiler */
1073  // Do nothing in these five states
1074  break;
1075  }
1076  return 0;
1077 }
1078 
1079 /* Peacefully close the socket by notifying the upper layer and deallocate end point */
1080 void
1082 {
1083  NS_LOG_FUNCTION (this);
1084 
1085  if (!m_closeNotified)
1086  {
1087  NotifyNormalClose ();
1088  m_closeNotified = true;
1089  }
1090  if (m_lastAckEvent.IsRunning ())
1091  {
1093  }
1094  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSED");
1095  m_state = CLOSED;
1096  DeallocateEndPoint ();
1097 }
1098 
1099 
1100 /* Tell if a sequence number range is out side the range that my rx buffer can
1101  accpet */
1102 bool
1104 {
1105  if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
1106  { // Rx buffer in these states are not initialized.
1107  return false;
1108  }
1109  if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
1110  { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
1111  // sequence number must equals to m_rxBuffer->NextRxSequence ()
1112  return (m_tcb->m_rxBuffer->NextRxSequence () != head);
1113  }
1114 
1115  // In all other cases, check if the sequence number is in range
1116  return (tail < m_tcb->m_rxBuffer->NextRxSequence () || m_tcb->m_rxBuffer->MaxRxSequence () <= head);
1117 }
1118 
1119 /* Function called by the L3 protocol when it received a packet to pass on to
1120  the TCP. This function is registered as the "RxCallback" function in
1121  SetupCallback(), which invoked by Bind(), and CompleteFork() */
1122 void
1124  Ptr<Ipv4Interface> incomingInterface)
1125 {
1126  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1127  m_endPoint->GetPeerAddress () <<
1128  ":" << m_endPoint->GetPeerPort () <<
1129  " to " << m_endPoint->GetLocalAddress () <<
1130  ":" << m_endPoint->GetLocalPort ());
1131 
1132  Address fromAddress = InetSocketAddress (header.GetSource (), port);
1133  Address toAddress = InetSocketAddress (header.GetDestination (),
1134  m_endPoint->GetLocalPort ());
1135 
1136  TcpHeader tcpHeader;
1137  uint32_t bytesRemoved = packet->PeekHeader (tcpHeader);
1138 
1139  if (!IsValidTcpSegment (tcpHeader.GetSequenceNumber (), bytesRemoved,
1140  packet->GetSize () - bytesRemoved))
1141  {
1142  return;
1143  }
1144 
1145  if (header.GetEcn() == Ipv4Header::ECN_CE && m_ecnCESeq < tcpHeader.GetSequenceNumber ())
1146  {
1147  NS_LOG_INFO ("Received CE flag is valid");
1148  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_CE_RCVD");
1149  m_ecnCESeq = tcpHeader.GetSequenceNumber ();
1152  }
1154  {
1156  }
1157 
1158  DoForwardUp (packet, fromAddress, toAddress);
1159 }
1160 
1161 void
1163  Ptr<Ipv6Interface> incomingInterface)
1164 {
1165  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1167  ":" << m_endPoint6->GetPeerPort () <<
1168  " to " << m_endPoint6->GetLocalAddress () <<
1169  ":" << m_endPoint6->GetLocalPort ());
1170 
1171  Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port);
1172  Address toAddress = Inet6SocketAddress (header.GetDestinationAddress (),
1174 
1175  TcpHeader tcpHeader;
1176  uint32_t bytesRemoved = packet->PeekHeader (tcpHeader);
1177 
1178  if (!IsValidTcpSegment (tcpHeader.GetSequenceNumber (), bytesRemoved,
1179  packet->GetSize () - bytesRemoved))
1180  {
1181  return;
1182  }
1183 
1184  if (header.GetEcn() == Ipv6Header::ECN_CE && m_ecnCESeq < tcpHeader.GetSequenceNumber ())
1185  {
1186  NS_LOG_INFO ("Received CE flag is valid");
1187  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_CE_RCVD");
1188  m_ecnCESeq = tcpHeader.GetSequenceNumber ();
1191  }
1192  else if (header.GetEcn() != Ipv6Header::ECN_NotECT)
1193  {
1195  }
1196 
1197  DoForwardUp (packet, fromAddress, toAddress);
1198 }
1199 
1200 void
1201 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1202  uint8_t icmpType, uint8_t icmpCode,
1203  uint32_t icmpInfo)
1204 {
1205  NS_LOG_FUNCTION (this << icmpSource << static_cast<uint32_t> (icmpTtl) <<
1206  static_cast<uint32_t> (icmpType) <<
1207  static_cast<uint32_t> (icmpCode) << icmpInfo);
1208  if (!m_icmpCallback.IsNull ())
1209  {
1210  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1211  }
1212 }
1213 
1214 void
1215 TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1216  uint8_t icmpType, uint8_t icmpCode,
1217  uint32_t icmpInfo)
1218 {
1219  NS_LOG_FUNCTION (this << icmpSource << static_cast<uint32_t> (icmpTtl) <<
1220  static_cast<uint32_t> (icmpType) <<
1221  static_cast<uint32_t> (icmpCode) << icmpInfo);
1222  if (!m_icmpCallback6.IsNull ())
1223  {
1224  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1225  }
1226 }
1227 
1228 bool
1229 TcpSocketBase::IsValidTcpSegment (const SequenceNumber32 seq, const uint32_t tcpHeaderSize,
1230  const uint32_t tcpPayloadSize)
1231 {
1232  if (tcpHeaderSize == 0 || tcpHeaderSize > 60)
1233  {
1234  NS_LOG_ERROR ("Bytes removed: " << tcpHeaderSize << " invalid");
1235  return false; // Discard invalid packet
1236  }
1237  else if (tcpPayloadSize > 0 && OutOfRange (seq, seq + tcpPayloadSize))
1238  {
1239  // Discard fully out of range data packets
1240  NS_LOG_WARN ("At state " << TcpStateName[m_state] <<
1241  " received packet of seq [" << seq <<
1242  ":" << seq + tcpPayloadSize <<
1243  ") out of range [" << m_tcb->m_rxBuffer->NextRxSequence () << ":" <<
1244  m_tcb->m_rxBuffer->MaxRxSequence () << ")");
1245  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
1247  return false;
1248  }
1249  return true;
1250 }
1251 
1252 void
1253 TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress,
1254  const Address &toAddress)
1255 {
1256  // in case the packet still has a priority tag attached, remove it
1257  SocketPriorityTag priorityTag;
1258  packet->RemovePacketTag (priorityTag);
1259 
1260  // Peel off TCP header
1261  TcpHeader tcpHeader;
1262  packet->RemoveHeader (tcpHeader);
1263  SequenceNumber32 seq = tcpHeader.GetSequenceNumber ();
1264 
1265  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
1266  {
1267  // Check if the sender has responded to ECN echo by reducing the Congestion Window
1268  if (tcpHeader.GetFlags () & TcpHeader::CWR )
1269  {
1270  // 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
1271  // stop sending ECN Echo messages. If there is CE bit set, the packet should continue sending ECN Echo messages
1272  //
1274  {
1277  }
1278  }
1279  }
1280 
1281  m_rxTrace (packet, tcpHeader, this);
1282 
1283  if (tcpHeader.GetFlags () & TcpHeader::SYN)
1284  {
1285  /* The window field in a segment where the SYN bit is set (i.e., a <SYN>
1286  * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be
1287  * saved anyway..
1288  */
1289  m_rWnd = tcpHeader.GetWindowSize ();
1290 
1292  {
1294  }
1295  else
1296  {
1297  m_winScalingEnabled = false;
1298  }
1299 
1301  {
1303  }
1304  else
1305  {
1306  m_sackEnabled = false;
1307  }
1308 
1309  // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end
1310  if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled)
1311  {
1313  tcpHeader.GetSequenceNumber ());
1314  }
1315  else
1316  {
1317  m_timestampEnabled = false;
1318  }
1319 
1320  // Initialize cWnd and ssThresh
1324 
1325  if (tcpHeader.GetFlags () & TcpHeader::ACK)
1326  {
1327  EstimateRtt (tcpHeader);
1328  m_highRxAckMark = tcpHeader.GetAckNumber ();
1329  }
1330  }
1331  else if (tcpHeader.GetFlags () & TcpHeader::ACK)
1332  {
1333  NS_ASSERT (!(tcpHeader.GetFlags () & TcpHeader::SYN));
1334  if (m_timestampEnabled)
1335  {
1336  if (!tcpHeader.HasOption (TcpOption::TS))
1337  {
1338  // Ignoring segment without TS, RFC 7323
1339  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1340  " received packet of seq [" << seq <<
1341  ":" << seq + packet->GetSize () <<
1342  ") without TS option. Silently discard it");
1343  return;
1344  }
1345  else
1346  {
1348  tcpHeader.GetSequenceNumber ());
1349  }
1350  }
1351 
1352  EstimateRtt (tcpHeader);
1353  UpdateWindowSize (tcpHeader);
1354  }
1355 
1356 
1357  if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ())
1358  { // Zero window: Enter persist state to send 1 byte to probe
1359  NS_LOG_LOGIC (this << " Enter zerowindow persist state");
1360  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1361  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1362  m_retxEvent.Cancel ();
1363  NS_LOG_LOGIC ("Schedule persist timeout at time " <<
1364  Simulator::Now ().GetSeconds () << " to expire at time " <<
1365  (Simulator::Now () + m_persistTimeout).GetSeconds ());
1368  }
1369 
1370  // TCP state machine code in different process functions
1371  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1372  switch (m_state)
1373  {
1374  case ESTABLISHED:
1375  ProcessEstablished (packet, tcpHeader);
1376  break;
1377  case LISTEN:
1378  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
1379  break;
1380  case TIME_WAIT:
1381  // Do nothing
1382  break;
1383  case CLOSED:
1384  // Send RST if the incoming packet is not a RST
1385  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1386  { // Since m_endPoint is not configured yet, we cannot use SendRST here
1387  TcpHeader h;
1388  Ptr<Packet> p = Create<Packet> ();
1391  h.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
1392  h.SetSourcePort (tcpHeader.GetDestinationPort ());
1393  h.SetDestinationPort (tcpHeader.GetSourcePort ());
1395  AddOptions (h);
1396  m_txTrace (p, h, this);
1397  m_tcp->SendPacket (p, h, toAddress, fromAddress, m_boundnetdevice);
1398  }
1399  break;
1400  case SYN_SENT:
1401  ProcessSynSent (packet, tcpHeader);
1402  break;
1403  case SYN_RCVD:
1404  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1405  break;
1406  case FIN_WAIT_1:
1407  case FIN_WAIT_2:
1408  case CLOSE_WAIT:
1409  ProcessWait (packet, tcpHeader);
1410  break;
1411  case CLOSING:
1412  ProcessClosing (packet, tcpHeader);
1413  break;
1414  case LAST_ACK:
1415  ProcessLastAck (packet, tcpHeader);
1416  break;
1417  default: // mute compiler
1418  break;
1419  }
1420 
1421  if (m_rWnd.Get () != 0 && m_persistEvent.IsRunning ())
1422  { // persist probes end, the other end has increased the window
1424  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
1426 
1428  }
1429 }
1430 
1431 /* Received a packet upon ESTABLISHED state. This function is mimicking the
1432  role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1433 void
1435 {
1436  NS_LOG_FUNCTION (this << tcpHeader);
1437 
1438  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
1439  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
1440 
1441  // Different flags are different events
1442  if (tcpflags == TcpHeader::ACK)
1443  {
1444  if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ())
1445  {
1446  // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be ignored.
1447  // Pag. 72 RFC 793
1448  NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1449  " SND.UNA = " << m_txBuffer->HeadSequence ());
1450 
1451  // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation]
1452  }
1453  else if (tcpHeader.GetAckNumber () > m_tcb->m_highTxMark)
1454  {
1455  // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then
1456  // send an ACK, drop the segment, and return.
1457  // Pag. 72 RFC 793
1458  NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1459  " HighTxMark = " << m_tcb->m_highTxMark);
1460 
1461  // Receiver sets ECE flags when it receives a packet with CE bit on or sender hasn’t responded to ECN echo sent by receiver
1463  {
1465  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
1467  }
1468  else
1469  {
1471  }
1472  }
1473  else
1474  {
1475  // SND.UNA < SEG.ACK =< HighTxMark
1476  // Pag. 72 RFC 793
1477  ReceivedAck (packet, tcpHeader);
1478  }
1479  }
1480  else if (tcpflags == TcpHeader::SYN)
1481  { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1482  // respond with a SYN+ACK. But it is not a legal state transition as of
1483  // RFC793. Thus this is ignored.
1484  }
1485  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1486  { // No action for received SYN+ACK, it is probably a duplicated packet
1487  }
1488  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1489  { // Received FIN or FIN+ACK, bring down this socket nicely
1490  PeerClose (packet, tcpHeader);
1491  }
1492  else if (tcpflags == 0)
1493  { // No flags means there is only data
1494  ReceivedData (packet, tcpHeader);
1495  if (m_tcb->m_rxBuffer->Finished ())
1496  {
1497  PeerClose (packet, tcpHeader);
1498  }
1499  }
1500  else
1501  { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1502  if (tcpflags != TcpHeader::RST)
1503  { // this must be an invalid flag, send reset
1504  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
1505  SendRST ();
1506  }
1507  CloseAndNotify ();
1508  }
1509 }
1510 
1511 bool
1513 {
1514  NS_LOG_FUNCTION (this << static_cast<uint32_t> (kind));
1515 
1516  switch (kind)
1517  {
1518  case TcpOption::TS:
1519  return m_timestampEnabled;
1520  case TcpOption::WINSCALE:
1521  return m_winScalingEnabled;
1523  case TcpOption::SACK:
1524  return m_sackEnabled;
1525  default:
1526  break;
1527  }
1528  return false;
1529 }
1530 
1531 void
1532 TcpSocketBase::ReadOptions (const TcpHeader &tcpHeader, uint32_t *bytesSacked)
1533 {
1534  NS_LOG_FUNCTION (this << tcpHeader);
1535  TcpHeader::TcpOptionList::const_iterator it;
1536  const TcpHeader::TcpOptionList options = tcpHeader.GetOptionList ();
1537 
1538  for (it = options.begin (); it != options.end (); ++it)
1539  {
1540  const Ptr<const TcpOption> option = (*it);
1541 
1542  // Check only for ACK options here
1543  switch (option->GetKind ())
1544  {
1545  case TcpOption::SACK:
1546  *bytesSacked = ProcessOptionSack (option);
1547  break;
1548  default:
1549  continue;
1550  }
1551  }
1552 }
1553 
1554 void
1555 TcpSocketBase::EnterRecovery (uint32_t currentDelivered)
1556 {
1557  NS_LOG_FUNCTION (this);
1559 
1561  " -> CA_RECOVERY");
1562 
1563  if (!m_sackEnabled)
1564  {
1565  // One segment has left the network, PLUS the head is lost
1566  m_txBuffer->AddRenoSack ();
1567  m_txBuffer->MarkHeadAsLost ();
1568  }
1569  else
1570  {
1571  if (!m_txBuffer->IsLost (m_txBuffer->HeadSequence ()))
1572  {
1573  // We received 3 dupacks, but the head is not marked as lost
1574  // (received less than 3 SACK block ahead).
1575  // Manually set it as lost.
1576  m_txBuffer->MarkHeadAsLost ();
1577  }
1578  }
1579 
1580  // RFC 6675, point (4):
1581  // (4) Invoke fast retransmit and enter loss recovery as follows:
1582  // (4.1) RecoveryPoint = HighData
1584  m_recoverActive = true;
1585 
1586  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_RECOVERY);
1588 
1589  // (4.2) ssthresh = cwnd = (FlightSize / 2)
1590  // If SACK is not enabled, still consider the head as 'in flight' for
1591  // compatibility with old ns-3 versions
1592  uint32_t bytesInFlight = m_sackEnabled ? BytesInFlight () : BytesInFlight () + m_tcb->m_segmentSize;
1593  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, bytesInFlight);
1594 
1595  if (!m_congestionControl->HasCongControl ())
1596  {
1597  m_recoveryOps->EnterRecovery (m_tcb, m_dupAckCount, UnAckDataCount (), currentDelivered);
1598  NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." <<
1599  "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
1600  m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover <<
1601  " calculated in flight: " << bytesInFlight);
1602  }
1603 
1604 
1605  // (4.3) Retransmit the first data segment presumed dropped
1606  DoRetransmit ();
1607  // (4.4) Run SetPipe ()
1608  // (4.5) Proceed to step (C)
1609  // these steps are done after the ProcessAck function (SendPendingData)
1610 }
1611 
1612 void
1613 TcpSocketBase::DupAck (uint32_t currentDelivered)
1614 {
1615  NS_LOG_FUNCTION (this);
1616  // NOTE: We do not count the DupAcks received in CA_LOSS, because we
1617  // don't know if they are generated by a spurious retransmission or because
1618  // of a real packet loss. With SACK, it is easy to know, but we do not consider
1619  // dupacks. Without SACK, there are some euristics in the RFC 6582, but
1620  // for now, we do not implement it, leading to ignoring the dupacks.
1622  {
1623  return;
1624  }
1625 
1626  // RFC 6675, Section 5, 3rd paragraph:
1627  // If the incoming ACK is a duplicate acknowledgment per the definition
1628  // in Section 2 (regardless of its status as a cumulative
1629  // acknowledgment), and the TCP is not currently in loss recovery
1630  // the TCP MUST increase DupAcks by one ...
1632  {
1633  ++m_dupAckCount;
1634  }
1635 
1637  {
1638  // From Open we go Disorder
1639  NS_ASSERT_MSG (m_dupAckCount == 1, "From OPEN->DISORDER but with " <<
1640  m_dupAckCount << " dup ACKs");
1641 
1642  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_DISORDER);
1644 
1645  NS_LOG_DEBUG ("CA_OPEN -> CA_DISORDER");
1646  }
1647 
1649  {
1650  if (!m_sackEnabled)
1651  {
1652  // If we are in recovery and we receive a dupack, one segment
1653  // has left the network. This is equivalent to a SACK of one block.
1654  m_txBuffer->AddRenoSack ();
1655  }
1656  if (!m_congestionControl->HasCongControl ())
1657  {
1658  m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
1659  NS_LOG_INFO (m_dupAckCount << " Dupack received in fast recovery mode."
1660  "Increase cwnd to " << m_tcb->m_cWnd);
1661  }
1662  }
1664  {
1665  // m_dupackCount should not exceed its threshold in CA_DISORDER state
1666  // when m_recoverActive has not been set. When recovery point
1667  // have been set after timeout, the sender could enter into CA_DISORDER
1668  // after receiving new ACK smaller than m_recover. After that, m_dupackCount
1669  // can be equal and larger than m_retxThresh and we should avoid entering
1670  // CA_RECOVERY and reducing sending rate again.
1672 
1673  // RFC 6675, Section 5, continuing:
1674  // ... and take the following steps:
1675  // (1) If DupAcks >= DupThresh, go to step (4).
1676  // Sequence number comparison (m_highRxAckMark >= m_recover) will take
1677  // effect only when m_recover has been set. Hence, we can avoid to use
1678  // m_recover in the last congestion event and fail to enter
1679  // CA_RECOVERY when sequence number is advanced significantly since
1680  // the last congestion event, which could be common for
1681  // bandwidth-greedy application in high speed and reliable network
1682  // (such as datacenter network) whose sending rate is constrainted by
1683  // TCP socket buffer size at receiver side.
1685  {
1686  EnterRecovery (currentDelivered);
1688  }
1689  // (2) If DupAcks < DupThresh but IsLost (HighACK + 1) returns true
1690  // (indicating at least three segments have arrived above the current
1691  // cumulative acknowledgment point, which is taken to indicate loss)
1692  // go to step (4).
1693  else if (m_txBuffer->IsLost (m_highRxAckMark + m_tcb->m_segmentSize))
1694  {
1695  EnterRecovery (currentDelivered);
1697  }
1698  else
1699  {
1700  // (3) The TCP MAY transmit previously unsent data segments as per
1701  // Limited Transmit [RFC5681] ...except that the number of octets
1702  // which may be sent is governed by pipe and cwnd as follows:
1703  //
1704  // (3.1) Set HighRxt to HighACK.
1705  // Not clear in RFC. We don't do this here, since we still have
1706  // to retransmit the segment.
1707 
1708  if (!m_sackEnabled && m_limitedTx)
1709  {
1710  m_txBuffer->AddRenoSack ();
1711 
1712  // In limited transmit, cwnd Infl is not updated.
1713  }
1714  }
1715  }
1716 }
1717 
1718 /* Process the newly received ACK */
1719 void
1721 {
1722  NS_LOG_FUNCTION (this << tcpHeader);
1723 
1724  NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK));
1725  NS_ASSERT (m_tcb->m_segmentSize > 0);
1726 
1727  // RFC 6675, Section 5, 1st paragraph:
1728  // Upon the receipt of any ACK containing SACK information, the
1729  // scoreboard MUST be updated via the Update () routine (done in ReadOptions)
1730  uint32_t bytesSacked = 0;
1731  uint64_t previousDelivered = m_rateOps->GetConnectionRate ().m_delivered;
1732  ReadOptions (tcpHeader, &bytesSacked);
1733 
1734  SequenceNumber32 ackNumber = tcpHeader.GetAckNumber ();
1735  SequenceNumber32 oldHeadSequence = m_txBuffer->HeadSequence ();
1736  m_txBuffer->DiscardUpTo (ackNumber, MakeCallback (&TcpRateOps::SkbDelivered, m_rateOps));
1737 
1738  uint32_t currentDelivered = static_cast<uint32_t> (m_rateOps->GetConnectionRate ().m_delivered - previousDelivered);
1739 
1740  if (ackNumber > oldHeadSequence && (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED) && (tcpHeader.GetFlags () & TcpHeader::ECE))
1741  {
1742  if (m_ecnEchoSeq < ackNumber)
1743  {
1744  NS_LOG_INFO ("Received ECN Echo is valid");
1745  m_ecnEchoSeq = ackNumber;
1746  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_ECE_RCVD");
1748  }
1749  }
1750  else if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && !(tcpHeader.GetFlags () & TcpHeader::ECE))
1751  {
1753  }
1754 
1755  // Update bytes in flight before processing the ACK for proper calculation of congestion window
1756  NS_LOG_INFO ("Update bytes in flight before processing the ACK.");
1757  BytesInFlight ();
1758 
1759  // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation
1760  // are inside the function ProcessAck
1761  ProcessAck (ackNumber, (bytesSacked > 0), currentDelivered, oldHeadSequence);
1762 
1763  if (m_congestionControl->HasCongControl ())
1764  {
1765  uint32_t previousLost = m_txBuffer->GetLost ();
1766  uint32_t priorInFlight = m_tcb->m_bytesInFlight.Get ();
1767  uint32_t currentLost = m_txBuffer->GetLost ();
1768  uint32_t lost = (currentLost > previousLost) ?
1769  currentLost - previousLost :
1770  previousLost - currentLost;
1771  auto rateSample = m_rateOps->GenerateSample (currentDelivered, lost,
1772  false, priorInFlight, m_tcb->m_minRtt);
1773  auto rateConn = m_rateOps->GetConnectionRate ();
1774  m_congestionControl->CongControl(m_tcb, rateConn, rateSample);
1775  }
1776 
1777  // If there is any data piggybacked, store it into m_rxBuffer
1778  if (packet->GetSize () > 0)
1779  {
1780  ReceivedData (packet, tcpHeader);
1781  }
1782 
1783  // RFC 6675, Section 5, point (C), try to send more data. NB: (C) is implemented
1784  // inside SendPendingData
1786 }
1787 
1788 void
1789 TcpSocketBase::ProcessAck(const SequenceNumber32 &ackNumber, bool scoreboardUpdated,
1790  uint32_t currentDelivered, const SequenceNumber32 &oldHeadSequence)
1791 {
1792  NS_LOG_FUNCTION (this << ackNumber << scoreboardUpdated);
1793  // RFC 6675, Section 5, 2nd paragraph:
1794  // If the incoming ACK is a cumulative acknowledgment, the TCP MUST
1795  // reset DupAcks to zero.
1796  bool exitedFastRecovery = false;
1797  uint32_t oldDupAckCount = m_dupAckCount; // remember the old value
1798  m_tcb->m_lastAckedSeq = ackNumber; // Update lastAckedSeq
1799  uint32_t bytesAcked = 0;
1800 
1801  /* In RFC 5681 the definition of duplicate acknowledgment was strict:
1802  *
1803  * (a) the receiver of the ACK has outstanding data,
1804  * (b) the incoming acknowledgment carries no data,
1805  * (c) the SYN and FIN bits are both off,
1806  * (d) the acknowledgment number is equal to the greatest acknowledgment
1807  * received on the given connection (TCP.UNA from [RFC793]),
1808  * (e) the advertised window in the incoming acknowledgment equals the
1809  * advertised window in the last incoming acknowledgment.
1810  *
1811  * With RFC 6675, this definition has been reduced:
1812  *
1813  * (a) the ACK is carrying a SACK block that identifies previously
1814  * unacknowledged and un-SACKed octets between HighACK (TCP.UNA) and
1815  * HighData (m_highTxMark)
1816  */
1817 
1818  bool isDupack = m_sackEnabled ?
1819  scoreboardUpdated
1820  : ackNumber == oldHeadSequence &&
1821  ackNumber < m_tcb->m_highTxMark;
1822 
1823  NS_LOG_DEBUG ("ACK of " << ackNumber <<
1824  " SND.UNA=" << oldHeadSequence <<
1825  " SND.NXT=" << m_tcb->m_nextTxSequence <<
1826  " in state: " << TcpSocketState::TcpCongStateName[m_tcb->m_congState] <<
1827  " with m_recover: " << m_recover);
1828 
1829  // RFC 6675, Section 5, 3rd paragraph:
1830  // If the incoming ACK is a duplicate acknowledgment per the definition
1831  // in Section 2 (regardless of its status as a cumulative
1832  // acknowledgment), and the TCP is not currently in loss recovery
1833  if (isDupack)
1834  {
1835  // loss recovery check is done inside this function thanks to
1836  // the congestion state machine
1837  DupAck (currentDelivered);
1838  }
1839 
1840  if (ackNumber == oldHeadSequence
1841  && ackNumber == m_tcb->m_highTxMark)
1842  {
1843  // Dupack, but the ACK is precisely equal to the nextTxSequence
1844  return;
1845  }
1846  else if (ackNumber == oldHeadSequence
1847  && ackNumber > m_tcb->m_highTxMark)
1848  {
1849  // ACK of the FIN bit ... nextTxSequence is not updated since we
1850  // don't have anything to transmit
1851  NS_LOG_DEBUG ("Update nextTxSequence manually to " << ackNumber);
1852  m_tcb->m_nextTxSequence = ackNumber;
1853  }
1854  else if (ackNumber == oldHeadSequence)
1855  {
1856  // DupAck. Artificially call PktsAcked: after all, one segment has been ACKed.
1857  m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
1858  }
1859  else if (ackNumber > oldHeadSequence)
1860  {
1861  // Please remember that, with SACK, we can enter here even if we
1862  // received a dupack.
1863  bytesAcked = ackNumber - oldHeadSequence;
1864  uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
1865  m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize;
1866  bytesAcked -= bytesAcked % m_tcb->m_segmentSize;
1867 
1869  {
1870  segsAcked += 1;
1871  bytesAcked += m_tcb->m_segmentSize;
1873  }
1874 
1875  // Dupack count is reset to eventually fast-retransmit after 3 dupacks.
1876  // Any SACK-ed segment will be cleaned up by DiscardUpTo.
1877  // In the case that we advanced SND.UNA, but the ack contains SACK blocks,
1878  // we do not reset. At the third one we will retransmit.
1879  // If we are already in recovery, this check is useless since dupAcks
1880  // are not considered in this phase. When from Recovery we go back
1881  // to open, then dupAckCount is reset anyway.
1882  if (!isDupack)
1883  {
1884  m_dupAckCount = 0;
1885  }
1886 
1887  // RFC 6675, Section 5, part (B)
1888  // (B) Upon receipt of an ACK that does not cover RecoveryPoint, the
1889  // following actions MUST be taken:
1890  //
1891  // (B.1) Use Update () to record the new SACK information conveyed
1892  // by the incoming ACK.
1893  // (B.2) Use SetPipe () to re-calculate the number of octets still
1894  // in the network.
1895  //
1896  // (B.1) is done at the beginning, while (B.2) is delayed to part (C) while
1897  // trying to transmit with SendPendingData. We are not allowed to exit
1898  // the CA_RECOVERY phase. Just process this partial ack (RFC 5681)
1899  if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1900  {
1901  if (!m_sackEnabled)
1902  {
1903  // Manually set the head as lost, it will be retransmitted.
1904  NS_LOG_INFO ("Partial ACK. Manually setting head as lost");
1905  m_txBuffer->MarkHeadAsLost ();
1906  }
1907  else
1908  {
1909  // We received a partial ACK, if we retransmitted this segment
1910  // probably is better to retransmit it
1911  m_txBuffer->DeleteRetransmittedFlagFromHead ();
1912  }
1913  DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
1914  m_tcb->m_cWndInfl = SafeSubtraction (m_tcb->m_cWndInfl, bytesAcked);
1915  if (!m_congestionControl->HasCongControl () && segsAcked >= 1)
1916  {
1917  m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
1918  }
1919 
1920  // This partial ACK acknowledge the fact that one segment has been
1921  // previously lost and now successfully received. All others have
1922  // been processed when they come under the form of dupACKs
1923  m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
1924  NewAck (ackNumber, m_isFirstPartialAck);
1925 
1926  if (m_isFirstPartialAck)
1927  {
1928  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
1929  " and this is the first (RTO will be reset);"
1930  " cwnd set to " << m_tcb->m_cWnd <<
1931  " recover seq: " << m_recover <<
1932  " dupAck count: " << m_dupAckCount);
1933  m_isFirstPartialAck = false;
1934  }
1935  else
1936  {
1937  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
1938  " and this is NOT the first (RTO will not be reset)"
1939  " cwnd set to " << m_tcb->m_cWnd <<
1940  " recover seq: " << m_recover <<
1941  " dupAck count: " << m_dupAckCount);
1942  }
1943  }
1944  // From RFC 6675 section 5.1
1945  // In addition, a new recovery phase (as described in Section 5) MUST NOT
1946  // be initiated until HighACK is greater than or equal to the new value
1947  // of RecoveryPoint.
1948  else if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_LOSS)
1949  {
1950  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
1951  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
1952 
1953  NS_LOG_DEBUG (" Cong Control Called, cWnd=" << m_tcb->m_cWnd <<
1954  " ssTh=" << m_tcb->m_ssThresh);
1955  if (!m_sackEnabled)
1956  {
1957  NS_ASSERT_MSG (m_txBuffer->GetSacked () == 0,
1958  "Some segment got dup-acked in CA_LOSS state: " <<
1959  m_txBuffer->GetSacked ());
1960  }
1961  NewAck (ackNumber, true);
1962  }
1963  else
1964  {
1966  {
1967  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
1968  }
1970  {
1971  if (segsAcked >= oldDupAckCount)
1972  {
1973  m_congestionControl->PktsAcked (m_tcb, segsAcked - oldDupAckCount, m_tcb->m_lastRtt);
1974  }
1975 
1976  if (!isDupack)
1977  {
1978  // The network reorder packets. Linux changes the counting lost
1979  // packet algorithm from FACK to NewReno. We simply go back in Open.
1980  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1982  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
1983  ackNumber << " exiting CA_DISORDER -> CA_OPEN");
1984  }
1985  else
1986  {
1987  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
1988  ackNumber << " but still in CA_DISORDER");
1989  }
1990  }
1991  // RFC 6675, Section 5:
1992  // Once a TCP is in the loss recovery phase, the following procedure
1993  // MUST be used for each arriving ACK:
1994  // (A) An incoming cumulative ACK for a sequence number greater than
1995  // RecoveryPoint signals the end of loss recovery, and the loss
1996  // recovery phase MUST be terminated. Any information contained in
1997  // the scoreboard for sequence numbers greater than the new value of
1998  // HighACK SHOULD NOT be cleared when leaving the loss recovery
1999  // phase.
2001  {
2002  m_isFirstPartialAck = true;
2003 
2004  // Recalculate the segs acked, that are from m_recover to ackNumber
2005  // (which are the ones we have not passed to PktsAcked and that
2006  // can increase cWnd)
2007  segsAcked = static_cast<uint32_t>(ackNumber - m_recover) / m_tcb->m_segmentSize;
2008  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2010  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2012  exitedFastRecovery = true;
2013  m_dupAckCount = 0; // From recovery to open, reset dupack
2014 
2015  NS_LOG_DEBUG (segsAcked << " segments acked in CA_RECOVER, ack of " <<
2016  ackNumber << ", exiting CA_RECOVERY -> CA_OPEN");
2017  }
2019  {
2020  m_isFirstPartialAck = true;
2021 
2022  // Recalculate the segs acked, that are from m_recover to ackNumber
2023  // (which are the ones we have not passed to PktsAcked and that
2024  // can increase cWnd)
2025  segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
2026 
2027  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2028 
2029  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2031  NS_LOG_DEBUG (segsAcked << " segments acked in CA_LOSS, ack of" <<
2032  ackNumber << ", exiting CA_LOSS -> CA_OPEN");
2033  }
2034 
2035  if (ackNumber >= m_recover)
2036  {
2037  // All lost segments in the congestion event have been
2038  // retransmitted successfully. The recovery point (m_recover)
2039  // should be deactivated.
2040  m_recoverActive = false;
2041  }
2042 
2043  if (exitedFastRecovery)
2044  {
2045  NewAck (ackNumber, true);
2046  m_recoveryOps->ExitRecovery (m_tcb);
2047  NS_LOG_DEBUG ("Leaving Fast Recovery; BytesInFlight() = " <<
2048  BytesInFlight () << "; cWnd = " << m_tcb->m_cWnd);
2049  }
2050  else
2051  {
2052  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
2053 
2055 
2056  NS_LOG_LOGIC ("Congestion control called: " <<
2057  " cWnd: " << m_tcb->m_cWnd <<
2058  " ssTh: " << m_tcb->m_ssThresh <<
2059  " segsAcked: " << segsAcked);
2060 
2061  NewAck (ackNumber, true);
2062  }
2063  }
2064  }
2065 }
2066 
2067 /* Received a packet upon LISTEN state. */
2068 void
2070  const Address& fromAddress, const Address& toAddress)
2071 {
2072  NS_LOG_FUNCTION (this << tcpHeader);
2073 
2074  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2075  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2076 
2077  // Fork a socket if received a SYN. Do nothing otherwise.
2078  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
2079  if (tcpflags != TcpHeader::SYN)
2080  {
2081  return;
2082  }
2083 
2084  // Call socket's notify function to let the server app know we got a SYN
2085  // If the server app refuses the connection, do nothing
2086  if (!NotifyConnectionRequest (fromAddress))
2087  {
2088  return;
2089  }
2090  // Clone the socket, simulate fork
2091  Ptr<TcpSocketBase> newSock = Fork ();
2092  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
2094  packet, tcpHeader, fromAddress, toAddress);
2095 }
2096 
2097 /* Received a packet upon SYN_SENT */
2098 void
2100 {
2101  NS_LOG_FUNCTION (this << tcpHeader);
2102 
2103  // Extract the flags. PSH and URG are disregarded.
2104  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2105 
2106  if (tcpflags == 0)
2107  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
2108  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2109  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2111  m_state = ESTABLISHED;
2112  m_connected = true;
2113  m_retxEvent.Cancel ();
2115  ReceivedData (packet, tcpHeader);
2117  }
2118  else if (tcpflags & TcpHeader::ACK && !(tcpflags & TcpHeader::SYN))
2119  { // Ignore ACK in SYN_SENT
2120  }
2121  else if (tcpflags & TcpHeader::SYN && !(tcpflags & TcpHeader::ACK))
2122  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
2123  NS_LOG_DEBUG ("SYN_SENT -> SYN_RCVD");
2124  m_state = SYN_RCVD;
2126  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2127  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if the traffic is ECN capable and
2128  * sender has sent ECN SYN packet
2129  */
2130 
2132  {
2133  NS_LOG_INFO ("Received ECN SYN packet");
2137  }
2138  else
2139  {
2142  }
2143  }
2144  else if (tcpflags & (TcpHeader::SYN | TcpHeader::ACK)
2145  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
2146  { // Handshake completed
2147  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2148  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2150  m_state = ESTABLISHED;
2151  m_connected = true;
2152  m_retxEvent.Cancel ();
2153  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2155  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2157 
2158  /* 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
2159  * packet and the traffic is ECN Capable
2160  */
2162  {
2163  NS_LOG_INFO ("Received ECN SYN-ACK packet.");
2166  }
2167  else
2168  {
2170  }
2173  // Always respond to first data packet to speed up the connection.
2174  // Remove to get the behaviour of old NS-3 code.
2176  }
2177  else
2178  { // Other in-sequence input
2179  if (!(tcpflags & TcpHeader::RST))
2180  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
2181  NS_LOG_LOGIC ("Illegal flag combination " << TcpHeader::FlagsToString (tcpHeader.GetFlags ()) <<
2182  " received in SYN_SENT. Reset packet is sent.");
2183  SendRST ();
2184  }
2185  CloseAndNotify ();
2186  }
2187 }
2188 
2189 /* Received a packet upon SYN_RCVD */
2190 void
2192  const Address& fromAddress, const Address& toAddress)
2193 {
2194  NS_UNUSED (toAddress);
2195  NS_LOG_FUNCTION (this << tcpHeader);
2196 
2197  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2198  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2199 
2200  if (tcpflags == 0
2201  || (tcpflags == TcpHeader::ACK
2202  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
2203  { // If it is bare data, accept it and move to ESTABLISHED state. This is
2204  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
2205  // handshake is completed nicely.
2206  NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED");
2207  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2209  m_state = ESTABLISHED;
2210  m_connected = true;
2211  m_retxEvent.Cancel ();
2213  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2214  if (m_endPoint)
2215  {
2216  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2217  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2218  }
2219  else if (m_endPoint6)
2220  {
2221  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2222  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2223  }
2224  // Always respond to first data packet to speed up the connection.
2225  // Remove to get the behaviour of old NS-3 code.
2227  NotifyNewConnectionCreated (this, fromAddress);
2228  ReceivedAck (packet, tcpHeader);
2229  // As this connection is established, the socket is available to send data now
2230  if (GetTxAvailable () > 0)
2231  {
2233  }
2234  }
2235  else if (tcpflags == TcpHeader::SYN)
2236  { // Probably the peer lost my SYN+ACK
2237  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2238  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2239  * packet and the traffic is ECN Capable
2240  */
2242  {
2243  NS_LOG_INFO ("Received ECN SYN packet");
2247  }
2248  else
2249  {
2252  }
2253  }
2254  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2255  {
2256  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2257  { // In-sequence FIN before connection complete. Set up connection and close.
2258  m_connected = true;
2259  m_retxEvent.Cancel ();
2261  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2262  if (m_endPoint)
2263  {
2264  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2265  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2266  }
2267  else if (m_endPoint6)
2268  {
2269  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2270  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2271  }
2272  NotifyNewConnectionCreated (this, fromAddress);
2273  PeerClose (packet, tcpHeader);
2274  }
2275  }
2276  else
2277  { // Other in-sequence input
2278  if (tcpflags != TcpHeader::RST)
2279  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
2280  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2281  " received. Reset packet is sent.");
2282  if (m_endPoint)
2283  {
2284  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2285  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2286  }
2287  else if (m_endPoint6)
2288  {
2289  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2290  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2291  }
2292  SendRST ();
2293  }
2294  CloseAndNotify ();
2295  }
2296 }
2297 
2298 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
2299 void
2301 {
2302  NS_LOG_FUNCTION (this << tcpHeader);
2303 
2304  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2305  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2306 
2307  if (packet->GetSize () > 0 && !(tcpflags & TcpHeader::ACK))
2308  { // Bare data, accept it
2309  ReceivedData (packet, tcpHeader);
2310  }
2311  else if (tcpflags == TcpHeader::ACK)
2312  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
2313  ReceivedAck (packet, tcpHeader);
2314  if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
2315  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2316  { // This ACK corresponds to the FIN sent
2317  NS_LOG_DEBUG ("FIN_WAIT_1 -> FIN_WAIT_2");
2318  m_state = FIN_WAIT_2;
2319  }
2320  }
2321  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2322  { // Got FIN, respond with ACK and move to next state
2323  if (tcpflags & TcpHeader::ACK)
2324  { // Process the ACK first
2325  ReceivedAck (packet, tcpHeader);
2326  }
2327  m_tcb->m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
2328  }
2329  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
2330  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
2331  return;
2332  }
2333  else
2334  { // This is a RST or bad flags
2335  if (tcpflags != TcpHeader::RST)
2336  {
2337  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2338  " received. Reset packet is sent.");
2339  SendRST ();
2340  }
2341  CloseAndNotify ();
2342  return;
2343  }
2344 
2345  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
2346  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_tcb->m_rxBuffer->Finished ())
2347  {
2348  if (m_state == FIN_WAIT_1)
2349  {
2350  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2351  m_state = CLOSING;
2352  if (m_txBuffer->Size () == 0
2353  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2354  { // This ACK corresponds to the FIN sent
2355  TimeWait ();
2356  }
2357  }
2358  else if (m_state == FIN_WAIT_2)
2359  {
2360  TimeWait ();
2361  }
2363  if (!m_shutdownRecv)
2364  {
2365  NotifyDataRecv ();
2366  }
2367  }
2368 }
2369 
2370 /* Received a packet upon CLOSING */
2371 void
2373 {
2374  NS_LOG_FUNCTION (this << tcpHeader);
2375 
2376  // Extract the flags. PSH and URG are disregarded.
2377  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2378 
2379  if (tcpflags == TcpHeader::ACK)
2380  {
2381  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2382  { // This ACK corresponds to the FIN sent
2383  TimeWait ();
2384  }
2385  }
2386  else
2387  { // CLOSING state means simultaneous close, i.e. no one is sending data to
2388  // anyone. If anything other than ACK is received, respond with a reset.
2389  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2390  { // FIN from the peer as well. We can close immediately.
2392  }
2393  else if (tcpflags != TcpHeader::RST)
2394  { // Receive of SYN or SYN+ACK or bad flags or pure data
2395  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2396  SendRST ();
2397  }
2398  CloseAndNotify ();
2399  }
2400 }
2401 
2402 /* Received a packet upon LAST_ACK */
2403 void
2405 {
2406  NS_LOG_FUNCTION (this << tcpHeader);
2407 
2408  // Extract the flags. PSH and URG are disregarded.
2409  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2410 
2411  if (tcpflags == 0)
2412  {
2413  ReceivedData (packet, tcpHeader);
2414  }
2415  else if (tcpflags == TcpHeader::ACK)
2416  {
2417  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2418  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
2419  CloseAndNotify ();
2420  }
2421  }
2422  else if (tcpflags == TcpHeader::FIN)
2423  { // Received FIN again, the peer probably lost the FIN+ACK
2425  }
2426  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2427  {
2428  CloseAndNotify ();
2429  }
2430  else
2431  { // Received a SYN or SYN+ACK or bad flags
2432  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2433  SendRST ();
2434  CloseAndNotify ();
2435  }
2436 }
2437 
2438 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
2439 void
2441 {
2442  NS_LOG_FUNCTION (this << tcpHeader);
2443 
2444  // Ignore all out of range packets
2445  if (tcpHeader.GetSequenceNumber () < m_tcb->m_rxBuffer->NextRxSequence ()
2446  || tcpHeader.GetSequenceNumber () > m_tcb->m_rxBuffer->MaxRxSequence ())
2447  {
2448  return;
2449  }
2450  // For any case, remember the FIN position in rx buffer first
2451  m_tcb->m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2452  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2453  // If there is any piggybacked data, process it
2454  if (p->GetSize ())
2455  {
2456  ReceivedData (p, tcpHeader);
2457  }
2458  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2459  if (!m_tcb->m_rxBuffer->Finished ())
2460  {
2461  return;
2462  }
2463 
2464  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2465  if (m_state == FIN_WAIT_1)
2466  {
2467  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2468  m_state = CLOSING;
2469  return;
2470  }
2471 
2472  DoPeerClose (); // Change state, respond with ACK
2473 }
2474 
2475 /* Received a in-sequence FIN. Close down this socket. */
2476 void
2478 {
2481 
2482  // Move the state to CLOSE_WAIT
2483  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSE_WAIT");
2484  m_state = CLOSE_WAIT;
2485 
2486  if (!m_closeNotified)
2487  {
2488  // The normal behaviour for an application is that, when the peer sent a in-sequence
2489  // FIN, the app should prepare to close. The app has two choices at this point: either
2490  // respond with ShutdownSend() call to declare that it has nothing more to send and
2491  // the socket can be closed immediately; or remember the peer's close request, wait
2492  // until all its existing data are pushed into the TCP socket, then call Close()
2493  // explicitly.
2494  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
2495  NotifyNormalClose ();
2496  m_closeNotified = true;
2497  }
2498  if (m_shutdownSend)
2499  { // The application declares that it would not sent any more, close this socket
2500  Close ();
2501  }
2502  else
2503  { // Need to ack, the application will close later
2505  }
2506  if (m_state == LAST_ACK)
2507  {
2508  m_dataRetrCount = m_dataRetries; // prevent endless FINs
2509  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
2510  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
2512  }
2513 }
2514 
2515 /* Kill this socket. This is a callback function configured to m_endpoint in
2516  SetupCallback(), invoked when the endpoint is destroyed. */
2517 void
2519 {
2520  NS_LOG_FUNCTION (this);
2521  m_endPoint = nullptr;
2522  if (m_tcp != nullptr)
2523  {
2524  m_tcp->RemoveSocket (this);
2525  }
2526  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2527  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2528  CancelAllTimers ();
2529 }
2530 
2531 /* Kill this socket. This is a callback function configured to m_endpoint in
2532  SetupCallback(), invoked when the endpoint is destroyed. */
2533 void
2535 {
2536  NS_LOG_FUNCTION (this);
2537  m_endPoint6 = nullptr;
2538  if (m_tcp != nullptr)
2539  {
2540  m_tcp->RemoveSocket (this);
2541  }
2542  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2543  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2544  CancelAllTimers ();
2545 }
2546 
2547 /* Send an empty packet with specified TCP flags */
2548 void
2550 {
2551  NS_LOG_FUNCTION (this << static_cast<uint32_t> (flags));
2552 
2553  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
2554  {
2555  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
2556  return;
2557  }
2558 
2559  Ptr<Packet> p = Create<Packet> ();
2560  TcpHeader header;
2562 
2563  if (flags & TcpHeader::FIN)
2564  {
2565  flags |= TcpHeader::ACK;
2566  }
2567  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2568  {
2569  ++s;
2570  }
2571 
2572  AddSocketTags (p);
2573 
2574  header.SetFlags (flags);
2575  header.SetSequenceNumber (s);
2576  header.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
2577  if (m_endPoint != nullptr)
2578  {
2579  header.SetSourcePort (m_endPoint->GetLocalPort ());
2580  header.SetDestinationPort (m_endPoint->GetPeerPort ());
2581  }
2582  else
2583  {
2584  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2585  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
2586  }
2587  AddOptions (header);
2588 
2589  // RFC 6298, clause 2.4
2590  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2591 
2592  uint16_t windowSize = AdvertisedWindowSize ();
2593  bool hasSyn = flags & TcpHeader::SYN;
2594  bool hasFin = flags & TcpHeader::FIN;
2595  bool isAck = flags == TcpHeader::ACK;
2596  if (hasSyn)
2597  {
2598  if (m_winScalingEnabled)
2599  { // The window scaling option is set only on SYN packets
2600  AddOptionWScale (header);
2601  }
2602 
2603  if (m_sackEnabled)
2604  {
2605  AddOptionSackPermitted (header);
2606  }
2607 
2608  if (m_synCount == 0)
2609  { // No more connection retries, give up
2610  NS_LOG_LOGIC ("Connection failed.");
2611  m_rtt->Reset (); //According to recommendation -> RFC 6298
2613  m_state = CLOSED;
2614  DeallocateEndPoint ();
2615  return;
2616  }
2617  else
2618  { // Exponential backoff of connection time out
2619  int backoffCount = 0x1 << (m_synRetries - m_synCount);
2620  m_rto = m_cnTimeout * backoffCount;
2621  m_synCount--;
2622  }
2623 
2624  if (m_synRetries - 1 == m_synCount)
2625  {
2626  UpdateRttHistory (s, 0, false);
2627  }
2628  else
2629  { // This is SYN retransmission
2630  UpdateRttHistory (s, 0, true);
2631  }
2632 
2633  windowSize = AdvertisedWindowSize (false);
2634  }
2635  header.SetWindowSize (windowSize);
2636 
2637  if (flags & TcpHeader::ACK)
2638  { // If sending an ACK, cancel the delay ACK as well
2639  m_delAckEvent.Cancel ();
2640  m_delAckCount = 0;
2641  if (m_highTxAck < header.GetAckNumber ())
2642  {
2643  m_highTxAck = header.GetAckNumber ();
2644  }
2645  if (m_sackEnabled && m_tcb->m_rxBuffer->GetSackListSize () > 0)
2646  {
2647  AddOptionSack (header);
2648  }
2649  NS_LOG_INFO ("Sending a pure ACK, acking seq " << m_tcb->m_rxBuffer->NextRxSequence ());
2650  }
2651 
2652  m_txTrace (p, header, this);
2653 
2654  if (m_endPoint != nullptr)
2655  {
2656  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2658  }
2659  else
2660  {
2661  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2663  }
2664 
2665 
2666  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
2667  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2668  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
2669  << Simulator::Now ().GetSeconds () << " to expire at time "
2670  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2672  }
2673 }
2674 
2675 /* This function closes the endpoint completely. Called upon RST_TX action. */
2676 void
2678 {
2679  NS_LOG_FUNCTION (this);
2681  NotifyErrorClose ();
2682  DeallocateEndPoint ();
2683 }
2684 
2685 /* Deallocate the end point and cancel all the timers */
2686 void
2688 {
2689  if (m_endPoint != nullptr)
2690  {
2691  CancelAllTimers ();
2692  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
2693  m_tcp->DeAllocate (m_endPoint);
2694  m_endPoint = nullptr;
2695  m_tcp->RemoveSocket (this);
2696  }
2697  else if (m_endPoint6 != nullptr)
2698  {
2699  CancelAllTimers ();
2700  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
2701  m_tcp->DeAllocate (m_endPoint6);
2702  m_endPoint6 = nullptr;
2703  m_tcp->RemoveSocket (this);
2704  }
2705 }
2706 
2707 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2708 int
2710 {
2711  NS_LOG_FUNCTION (this);
2712  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
2713  NS_ASSERT (ipv4 != nullptr);
2714  if (ipv4->GetRoutingProtocol () == nullptr)
2715  {
2716  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
2717  }
2718  // Create a dummy packet, then ask the routing function for the best output
2719  // interface's address
2720  Ipv4Header header;
2722  Socket::SocketErrno errno_;
2723  Ptr<Ipv4Route> route;
2725  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2726  if (route == 0)
2727  {
2728  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
2729  NS_LOG_ERROR (errno_);
2730  m_errno = errno_;
2731  return -1;
2732  }
2733  NS_LOG_LOGIC ("Route exists");
2734  m_endPoint->SetLocalAddress (route->GetSource ());
2735  return 0;
2736 }
2737 
2738 int
2740 {
2741  NS_LOG_FUNCTION (this);
2743  NS_ASSERT (ipv6 != nullptr);
2744  if (ipv6->GetRoutingProtocol () == nullptr)
2745  {
2746  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
2747  }
2748  // Create a dummy packet, then ask the routing function for the best output
2749  // interface's address
2750  Ipv6Header header;
2752  Socket::SocketErrno errno_;
2753  Ptr<Ipv6Route> route;
2755  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2756  if (route == nullptr)
2757  {
2758  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
2759  NS_LOG_ERROR (errno_);
2760  m_errno = errno_;
2761  return -1;
2762  }
2763  NS_LOG_LOGIC ("Route exists");
2764  m_endPoint6->SetLocalAddress (route->GetSource ());
2765  return 0;
2766 }
2767 
2768 /* This function is called only if a SYN received in LISTEN state. After
2769  TcpSocketBase cloned, allocate a new end point to handle the incoming
2770  connection and send a SYN+ACK to complete the handshake. */
2771 void
2773  const Address& fromAddress, const Address& toAddress)
2774 {
2775  NS_LOG_FUNCTION (this << p << h << fromAddress << toAddress);
2776  NS_UNUSED (p);
2777  // Get port and address from peer (connecting host)
2778  if (InetSocketAddress::IsMatchingType (toAddress))
2779  {
2780  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (),
2781  InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
2782  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
2783  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2784  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2785  m_endPoint6 = nullptr;
2786  }
2787  else if (Inet6SocketAddress::IsMatchingType (toAddress))
2788  {
2789  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (),
2790  Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
2791  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
2792  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2793  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2794  m_endPoint = nullptr;
2795  }
2796  m_tcp->AddSocket (this);
2797 
2798  // Change the cloned socket from LISTEN state to SYN_RCVD
2799  NS_LOG_DEBUG ("LISTEN -> SYN_RCVD");
2800  m_state = SYN_RCVD;
2803  SetupCallback ();
2804  // Set the sequence number and send SYN+ACK
2805  m_tcb->m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
2806 
2807  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2808  * packet and the traffic is ECN Capable
2809  */
2812  {
2816  }
2817  else
2818  {
2821  }
2822 }
2823 
2824 void
2826 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
2827  // be called as a scheduled event
2829  // The if-block below was moved from ProcessSynSent() to here because we need
2830  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
2831  // reflect the behaviour in the real world.
2832  if (GetTxAvailable () > 0)
2833  {
2835  }
2836 }
2837 
2838 void
2840 {
2841  /*
2842  * Add tags for each socket option.
2843  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2844  * if both options are set. Once the packet got to layer three, only
2845  * the corresponding tags will be read.
2846  */
2847  if (GetIpTos ())
2848  {
2849  SocketIpTosTag ipTosTag;
2851  {
2853  }
2854  else
2855  {
2856  // Set the last received ipTos
2857  ipTosTag.SetTos (GetIpTos ());
2858  }
2859  p->AddPacketTag (ipTosTag);
2860  }
2861  else
2862  {
2864  {
2865  SocketIpTosTag ipTosTag;
2867  p->AddPacketTag (ipTosTag);
2868  }
2869  }
2870 
2871  if (IsManualIpv6Tclass ())
2872  {
2873  SocketIpv6TclassTag ipTclassTag;
2875  {
2877  }
2878  else
2879  {
2880  // Set the last received ipTos
2881  ipTclassTag.SetTclass (GetIpv6Tclass ());
2882  }
2883  p->AddPacketTag (ipTclassTag);
2884  }
2885  else
2886  {
2888  {
2889  SocketIpv6TclassTag ipTclassTag;
2891  p->AddPacketTag (ipTclassTag);
2892  }
2893  }
2894 
2895  if (IsManualIpTtl ())
2896  {
2897  SocketIpTtlTag ipTtlTag;
2898  ipTtlTag.SetTtl (GetIpTtl ());
2899  p->AddPacketTag (ipTtlTag);
2900  }
2901 
2902  if (IsManualIpv6HopLimit ())
2903  {
2904  SocketIpv6HopLimitTag ipHopLimitTag;
2905  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
2906  p->AddPacketTag (ipHopLimitTag);
2907  }
2908 
2909  uint8_t priority = GetPriority ();
2910  if (priority)
2911  {
2912  SocketPriorityTag priorityTag;
2913  priorityTag.SetPriority (priority);
2914  p->ReplacePacketTag (priorityTag);
2915  }
2916 }
2917 
2918 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
2919  TCP header, and send to TcpL4Protocol */
2920 uint32_t
2921 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
2922 {
2923  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
2924 
2925  bool isStartOfTransmission = BytesInFlight () == 0U;
2926  TcpTxItem *outItem = m_txBuffer->CopyFromSequence (maxSize, seq);
2927 
2928  m_rateOps->SkbSent(outItem, isStartOfTransmission);
2929 
2930  bool isRetransmission = outItem->IsRetrans ();
2931  Ptr<Packet> p = outItem->GetPacketCopy ();
2932  uint32_t sz = p->GetSize (); // Size of packet
2933  uint8_t flags = withAck ? TcpHeader::ACK : 0;
2934  uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
2935 
2936  // TCP sender should not send data out of the window advertised by the
2937  // peer when it is not retransmission.
2938  NS_ASSERT (isRetransmission || ((m_highRxAckMark + SequenceNumber32 (m_rWnd)) >= (seq + SequenceNumber32 (maxSize))));
2939 
2940  if (m_tcb->m_pacing)
2941  {
2942  NS_LOG_INFO ("Pacing is enabled");
2943  if (m_pacingTimer.IsExpired ())
2944  {
2945  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_currentPacingRate);
2946  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_currentPacingRate.CalculateBytesTxTime (sz));
2948  }
2949  else
2950  {
2951  NS_LOG_INFO ("Timer is already in running state");
2952  }
2953  }
2954 
2955  if (withAck)
2956  {
2957  m_delAckEvent.Cancel ();
2958  m_delAckCount = 0;
2959  }
2960 
2961  // Sender should reduce the Congestion Window as a response to receiver's ECN Echo notification only once per window
2962  if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && m_ecnEchoSeq.Get() > m_ecnCWRSeq.Get () && !isRetransmission)
2963  {
2964  NS_LOG_INFO ("Backoff mechanism by reducing CWND by half because we've received ECN Echo");
2965  m_congestionControl->ReduceCwnd (m_tcb);
2968  flags |= TcpHeader::CWR;
2969  m_ecnCWRSeq = seq;
2970  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_CWR_SENT");
2972  NS_LOG_INFO ("CWR flags set");
2973  }
2974 
2975  AddSocketTags (p);
2976 
2977  if (m_closeOnEmpty && (remainingData == 0))
2978  {
2979  flags |= TcpHeader::FIN;
2980  if (m_state == ESTABLISHED)
2981  { // On active close: I am the first one to send FIN
2982  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
2983  m_state = FIN_WAIT_1;
2984  }
2985  else if (m_state == CLOSE_WAIT)
2986  { // On passive close: Peer sent me FIN already
2987  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
2988  m_state = LAST_ACK;
2989  }
2990  }
2991  TcpHeader header;
2992  header.SetFlags (flags);
2993  header.SetSequenceNumber (seq);
2994  header.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
2995  if (m_endPoint)
2996  {
2997  header.SetSourcePort (m_endPoint->GetLocalPort ());
2999  }
3000  else
3001  {
3002  header.SetSourcePort (m_endPoint6->GetLocalPort ());
3004  }
3005  header.SetWindowSize (AdvertisedWindowSize ());
3006  AddOptions (header);
3007 
3008  if (m_retxEvent.IsExpired ())
3009  {
3010  // Schedules retransmit timeout. m_rto should be already doubled.
3011 
3012  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
3013  Simulator::Now ().GetSeconds () << " to expire at time " <<
3014  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
3016  }
3017 
3018  m_txTrace (p, header, this);
3019 
3020  if (m_endPoint)
3021  {
3022  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
3024  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
3025  remainingData << " via TcpL4Protocol to " << m_endPoint->GetPeerAddress () <<
3026  ". Header " << header);
3027  }
3028  else
3029  {
3030  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
3032  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
3033  remainingData << " via TcpL4Protocol to " << m_endPoint6->GetPeerAddress () <<
3034  ". Header " << header);
3035  }
3036 
3037  UpdateRttHistory (seq, sz, isRetransmission);
3038 
3039  // Update bytes sent during recovery phase
3041  {
3042  m_recoveryOps->UpdateBytesSent (sz);
3043  }
3044 
3045  // Notify the application of the data being sent unless this is a retransmit
3046  if (!isRetransmission)
3047  {
3049  (seq + sz - m_tcb->m_highTxMark.Get ()));
3050  }
3051  // Update highTxMark
3052  m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ());
3053  return sz;
3054 }
3055 
3056 void
3058  bool isRetransmission)
3059 {
3060  NS_LOG_FUNCTION (this);
3061 
3062  // update the history of sequence numbers used to calculate the RTT
3063  if (isRetransmission == false)
3064  { // This is the next expected one, just log at end
3065  m_history.push_back (RttHistory (seq, sz, Simulator::Now ()));
3066  }
3067  else
3068  { // This is a retransmit, find in list and mark as re-tx
3069  for (std::deque<RttHistory>::iterator i = m_history.begin (); i != m_history.end (); ++i)
3070  {
3071  if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
3072  { // Found it
3073  i->retx = true;
3074  i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
3075  break;
3076  }
3077  }
3078  }
3079 }
3080 
3081 // Note that this function did not implement the PSH flag
3082 uint32_t
3084 {
3085  NS_LOG_FUNCTION (this << withAck);
3086  if (m_txBuffer->Size () == 0)
3087  {
3088  return false; // Nothing to send
3089  }
3090  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
3091  {
3092  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
3093  return false; // Is this the right way to handle this condition?
3094  }
3095 
3096  uint32_t nPacketsSent = 0;
3097  uint32_t availableWindow = AvailableWindow ();
3098 
3099  // RFC 6675, Section (C)
3100  // If cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more
3101  // segments as follows:
3102  // (NOTE: We check > 0, and do the checks for segmentSize in the following
3103  // else branch to control silly window syndrome and Nagle)
3104  while (availableWindow > 0)
3105  {
3106  if (m_tcb->m_pacing)
3107  {
3108  NS_LOG_INFO ("Pacing is enabled");
3109  if (m_pacingTimer.IsRunning ())
3110  {
3111  NS_LOG_INFO ("Skipping Packet due to pacing" << m_pacingTimer.GetDelayLeft ());
3112  break;
3113  }
3114  NS_LOG_INFO ("Timer is not running");
3115  }
3116 
3119  {
3120  NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit");
3121  break;
3122  }
3123  // (C.1) The scoreboard MUST be queried via NextSeg () for the
3124  // sequence number range of the next segment to transmit (if
3125  // any), and the given segment sent. If NextSeg () returns
3126  // failure (no data to send), return without sending anything
3127  // (i.e., terminate steps C.1 -- C.5).
3128  SequenceNumber32 next;
3129  SequenceNumber32 nextHigh;
3130  bool enableRule3 = m_sackEnabled && m_tcb->m_congState == TcpSocketState::CA_RECOVERY;
3131  if (!m_txBuffer->NextSeg (&next, &nextHigh, enableRule3))
3132  {
3133  NS_LOG_INFO ("no valid seq to transmit, or no data available");
3134  break;
3135  }
3136  else
3137  {
3138  // It's time to transmit, but before do silly window and Nagle's check
3139  uint32_t availableData = m_txBuffer->SizeFromSequence (next);
3140 
3141  // If there's less app data than the full window, ask the app for more
3142  // data before trying to send
3143  if (availableData < availableWindow)
3144  {
3146  }
3147 
3148  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
3149  // but continue if we don't have data
3150  if (availableWindow < m_tcb->m_segmentSize && availableData > availableWindow)
3151  {
3152  NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
3153  break; // No more
3154  }
3155  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
3156  // in the buffer and the amount of data to send is less than one segment
3157  if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_segmentSize)
3158  {
3159  NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next <<
3160  ", SFS: " << m_txBuffer->SizeFromSequence (next) <<
3161  ". Wait to send.");
3162  break;
3163  }
3164 
3165  uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize);
3166  // NextSeg () may have further constrained the segment size
3167  uint32_t maxSizeToSend = static_cast<uint32_t> (nextHigh - next);
3168  s = std::min (s, maxSizeToSend);
3169 
3170  // (C.2) If any of the data octets sent in (C.1) are below HighData,
3171  // HighRxt MUST be set to the highest sequence number of the
3172  // retransmitted segment unless NextSeg () rule (4) was
3173  // invoked for this retransmission.
3174  // (C.3) If any of the data octets sent in (C.1) are above HighData,
3175  // HighData must be updated to reflect the transmission of
3176  // previously unsent data.
3177  //
3178  // These steps are done in m_txBuffer with the tags.
3179  if (m_tcb->m_nextTxSequence != next)
3180  {
3181  m_tcb->m_nextTxSequence = next;
3182  }
3183  if (m_tcb->m_bytesInFlight.Get () == 0)
3184  {
3186  }
3187  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck);
3188  m_tcb->m_nextTxSequence += sz;
3189 
3190  NS_LOG_LOGIC (" rxwin " << m_rWnd <<
3191  " segsize " << m_tcb->m_segmentSize <<
3192  " highestRxAck " << m_txBuffer->HeadSequence () <<
3193  " pd->Size " << m_txBuffer->Size () <<
3194  " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence));
3195 
3196  NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd <<
3197  " total unAck: " << UnAckDataCount () <<
3198  " sent seq " << m_tcb->m_nextTxSequence <<
3199  " size " << sz);
3200  ++nPacketsSent;
3201  if (m_tcb->m_pacing)
3202  {
3203  NS_LOG_INFO ("Pacing is enabled");
3204  if (m_pacingTimer.IsExpired ())
3205  {
3206  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_currentPacingRate);
3207  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_currentPacingRate.CalculateBytesTxTime (sz));
3209  break;
3210  }
3211  }
3212  }
3213 
3214  // (C.4) The estimate of the amount of data outstanding in the
3215  // network must be updated by incrementing pipe by the number
3216  // of octets transmitted in (C.1).
3217  //
3218  // Done in BytesInFlight, inside AvailableWindow.
3219  availableWindow = AvailableWindow ();
3220 
3221  // (C.5) If cwnd - pipe >= 1 SMSS, return to (C.1)
3222  // loop again!
3223  }
3224 
3225  if (nPacketsSent > 0)
3226  {
3227  if (!m_sackEnabled)
3228  {
3229  if (!m_limitedTx)
3230  {
3231  // We can't transmit in CA_DISORDER without limitedTx active
3233  }
3234  }
3235 
3236  NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments");
3237  }
3238  else
3239  {
3240  NS_LOG_DEBUG ("SendPendingData no segments sent");
3241  }
3242  return nPacketsSent;
3243 }
3244 
3245 uint32_t
3247 {
3248  return m_tcb->m_highTxMark - m_txBuffer->HeadSequence ();
3249 }
3250 
3251 uint32_t
3253 {
3254  uint32_t bytesInFlight = m_txBuffer->BytesInFlight ();
3255  // Ugly, but we are not modifying the state; m_bytesInFlight is used
3256  // only for tracing purpose.
3257  m_tcb->m_bytesInFlight = bytesInFlight;
3258 
3259  NS_LOG_DEBUG ("Returning calculated bytesInFlight: " << bytesInFlight);
3260  return bytesInFlight;
3261 }
3262 
3263 uint32_t
3265 {
3266  return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
3267 }
3268 
3269 uint32_t
3271 {
3272  uint32_t win = Window (); // Number of bytes allowed to be outstanding
3273  uint32_t inflight = BytesInFlight (); // Number of outstanding bytes
3274  return (inflight > win) ? 0 : win - inflight;
3275 }
3276 
3277 uint16_t
3279 {
3280  NS_LOG_FUNCTION (this << scale);
3281  uint32_t w;
3282 
3283  // We don't want to advertise 0 after a FIN is received. So, we just use
3284  // the previous value of the advWnd.
3285  if (m_tcb->m_rxBuffer->GotFin ())
3286  {
3287  w = m_advWnd;
3288  }
3289  else
3290  {
3291  NS_ASSERT_MSG (m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence () >= 0,
3292  "Unexpected sequence number values");
3293  w = static_cast<uint32_t> (m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence ());
3294  }
3295 
3296  // Ugly, but we are not modifying the state, that variable
3297  // is used only for tracing purpose.
3298  if (w != m_advWnd)
3299  {
3300  const_cast<TcpSocketBase*> (this)->m_advWnd = w;
3301  }
3302  if (scale)
3303  {
3304  w >>= m_rcvWindShift;
3305  }
3306  if (w > m_maxWinSize)
3307  {
3308  w = m_maxWinSize;
3309  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
3310  }
3311  NS_LOG_LOGIC ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
3312  return static_cast<uint16_t> (w);
3313 }
3314 
3315 // Receipt of new packet, put into Rx buffer
3316 void
3318 {
3319  NS_LOG_FUNCTION (this << tcpHeader);
3320  NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () <<
3321  " pkt size=" << p->GetSize () );
3322 
3323  // Put into Rx buffer
3324  SequenceNumber32 expectedSeq = m_tcb->m_rxBuffer->NextRxSequence ();
3325  if (!m_tcb->m_rxBuffer->Add (p, tcpHeader))
3326  { // Insert failed: No data or RX buffer full
3328  {
3330  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3332  }
3333  else
3334  {
3336  }
3337  return;
3338  }
3339  // Notify app to receive if necessary
3340  if (expectedSeq < m_tcb->m_rxBuffer->NextRxSequence ())
3341  { // NextRxSeq advanced, we have something to send to the app
3342  if (!m_shutdownRecv)
3343  {
3344  NotifyDataRecv ();
3345  }
3346  // Handle exceptions
3347  if (m_closeNotified)
3348  {
3349  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
3350  }
3351  // If we received FIN before and now completed all "holes" in rx buffer,
3352  // invoke peer close procedure
3353  if (m_tcb->m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
3354  {
3355  DoPeerClose ();
3356  return;
3357  }
3358  }
3359  // Now send a new ACK packet acknowledging all received and delivered data
3360  if (m_tcb->m_rxBuffer->Size () > m_tcb->m_rxBuffer->Available () || m_tcb->m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
3361  { // A gap exists in the buffer, or we filled a gap: Always ACK
3364  {
3366  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3368  }
3369  else
3370  {
3372  }
3373  }
3374  else
3375  { // In-sequence packet: ACK if delayed ack count allows
3377  {
3378  m_delAckEvent.Cancel ();
3379  m_delAckCount = 0;
3382  {
3383  NS_LOG_DEBUG("Congestion algo " << m_congestionControl->GetName ());
3385  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3387  }
3388  else
3389  {
3391  }
3392  }
3393  else if (!m_delAckEvent.IsExpired ())
3394  {
3396  }
3397  else if (m_delAckEvent.IsExpired ())
3398  {
3402  NS_LOG_LOGIC (this << " scheduled delayed ACK at " <<
3403  (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
3404  }
3405  }
3406 }
3407 
3415 void
3417 {
3418  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber ();
3419  Time m = Time (0.0);
3420 
3421  // An ack has been received, calculate rtt and log this measurement
3422  // Note we use a linear search (O(n)) for this since for the common
3423  // case the ack'ed packet will be at the head of the list
3424  if (!m_history.empty ())
3425  {
3426  RttHistory& h = m_history.front ();
3427  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
3428  { // Ok to use this sample
3429  if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
3430  {
3432  ts = DynamicCast<const TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
3433  m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
3434  }
3435  else
3436  {
3437  m = Simulator::Now () - h.time; // Elapsed time
3438  }
3439  }
3440  }
3441 
3442  // Now delete all ack history with seq <= ack
3443  while (!m_history.empty ())
3444  {
3445  RttHistory& h = m_history.front ();
3446  if ((h.seq + SequenceNumber32 (h.count)) > ackSeq)
3447  {
3448  break; // Done removing
3449  }
3450  m_history.pop_front (); // Remove
3451  }
3452 
3453  if (!m.IsZero ())
3454  {
3455  m_rtt->Measurement (m); // Log the measurement
3456  // RFC 6298, clause 2.4
3457  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3458  m_tcb->m_lastRtt = m_rtt->GetEstimate ();
3460  NS_LOG_INFO (this << m_tcb->m_lastRtt << m_tcb->m_minRtt);
3461  }
3462 }
3463 
3464 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
3465 // when the three-way handshake completed. This cancels retransmission timer
3466 // and advances Tx window
3467 void
3468 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO)
3469 {
3470  NS_LOG_FUNCTION (this << ack);
3471 
3472  // Reset the data retransmission count. We got a new ACK!
3474 
3475  if (m_state != SYN_RCVD && resetRTO)
3476  { // Set RTO unless the ACK is received in SYN_RCVD state
3477  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3478  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3479  m_retxEvent.Cancel ();
3480  // On receiving a "New" ack we restart retransmission timer .. RFC 6298
3481  // RFC 6298, clause 2.4
3482  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3483 
3484  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
3485  Simulator::Now ().GetSeconds () << " to expire at time " <<
3486  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
3488  }
3489 
3490  // Note the highest ACK and tell app to send more
3491  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
3492  " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
3493 
3494  if (GetTxAvailable () > 0)
3495  {
3497  }
3498  if (ack > m_tcb->m_nextTxSequence)
3499  {
3500  m_tcb->m_nextTxSequence = ack; // If advanced
3501  }
3502  if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
3503  { // No retransmit timer if no data to retransmit
3504  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3505  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3506  m_retxEvent.Cancel ();
3507  }
3508 }
3509 
3510 // Retransmit timeout
3511 void
3513 {
3514  NS_LOG_FUNCTION (this);
3515  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
3516  // If erroneous timeout in closed/timed-wait state, just return
3517  if (m_state == CLOSED || m_state == TIME_WAIT)
3518  {
3519  return;
3520  }
3521 
3522  if (m_state == SYN_SENT)
3523  {
3524  NS_ASSERT (m_synCount > 0);
3526  {
3528  }
3529  else
3530  {
3532  }
3533  return;
3534  }
3535 
3536  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3537  if (m_txBuffer->Size () == 0)
3538  {
3539  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3540  { // Must have lost FIN, re-send
3542  }
3543  return;
3544  }
3545 
3546  NS_LOG_DEBUG ("Checking if Connection is Established");
3547  // If all data are received (non-closing socket and nothing to send), just return
3548  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark && m_txBuffer->Size () == 0)
3549  {
3550  NS_LOG_DEBUG ("Already Sent full data" << m_txBuffer->HeadSequence () << " " << m_tcb->m_highTxMark);
3551  return;
3552  }
3553 
3554  if (m_dataRetrCount == 0)
3555  {
3556  NS_LOG_INFO ("No more data retries available. Dropping connection");
3557  NotifyErrorClose ();
3558  DeallocateEndPoint ();
3559  return;
3560  }
3561  else
3562  {
3563  --m_dataRetrCount;
3564  }
3565 
3566  uint32_t inFlightBeforeRto = BytesInFlight ();
3567  bool resetSack = !m_sackEnabled; // Reset SACK information if SACK is not enabled.
3568  // The information in the TcpTxBuffer is guessed, in this case.
3569 
3570  // Reset dupAckCount
3571  m_dupAckCount = 0;
3572  if (!m_sackEnabled)
3573  {
3574  m_txBuffer->ResetRenoSack ();
3575  }
3576 
3577  // From RFC 6675, Section 5.1
3578  // [RFC2018] suggests that a TCP sender SHOULD expunge the SACK
3579  // information gathered from a receiver upon a retransmission timeout
3580  // (RTO) "since the timeout might indicate that the data receiver has
3581  // reneged." Additionally, a TCP sender MUST "ignore prior SACK
3582  // information in determining which data to retransmit."
3583  // It has been suggested that, as long as robust tests for
3584  // reneging are present, an implementation can retain and use SACK
3585  // information across a timeout event [Errata1610].
3586  // The head of the sent list will not be marked as sacked, therefore
3587  // will be retransmitted, if the receiver renegotiate the SACK blocks
3588  // that we received.
3589  m_txBuffer->SetSentListLost (resetSack);
3590 
3591  // From RFC 6675, Section 5.1
3592  // If an RTO occurs during loss recovery as specified in this document,
3593  // RecoveryPoint MUST be set to HighData. Further, the new value of
3594  // RecoveryPoint MUST be preserved and the loss recovery algorithm
3595  // outlined in this document MUST be terminated.
3597  m_recoverActive = true;
3598 
3599  // RFC 6298, clause 2.5, double the timer
3600  Time doubledRto = m_rto + m_rto;
3601  m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
3602 
3603  // Empty RTT history
3604  m_history.clear ();
3605 
3606  // Please don't reset highTxMark, it is used for retransmission detection
3607 
3608  // When a TCP sender detects segment loss using the retransmission timer
3609  // and the given segment has not yet been resent by way of the
3610  // retransmission timer, decrease ssThresh
3611  if (m_tcb->m_congState != TcpSocketState::CA_LOSS || !m_txBuffer->IsHeadRetransmitted ())
3612  {
3613  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, inFlightBeforeRto);
3614  }
3615 
3616  // Cwnd set to 1 MSS
3618  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS);
3622 
3623  m_pacingTimer.Cancel ();
3624 
3625  NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
3626  m_tcb->m_ssThresh << ", restart from seqnum " <<
3627  m_txBuffer->HeadSequence () << " doubled rto to " <<
3628  m_rto.Get ().GetSeconds () << " s");
3629 
3630  NS_ASSERT_MSG (BytesInFlight () == 0, "There are some bytes in flight after an RTO: " <<
3631  BytesInFlight ());
3632 
3634 
3636  "In flight (" << BytesInFlight () <<
3637  ") there is more than one segment (" << m_tcb->m_segmentSize << ")");
3638 }
3639 
3640 void
3642 {
3643  m_delAckCount = 0;
3646  {
3649  }
3650  else
3651  {
3653  }
3654 }
3655 
3656 void
3658 {
3659  NS_LOG_FUNCTION (this);
3660 
3662  if (m_state == LAST_ACK)
3663  {
3664  if (m_dataRetrCount == 0)
3665  {
3666  NS_LOG_INFO ("LAST-ACK: No more data retries available. Dropping connection");
3667  NotifyErrorClose ();
3668  DeallocateEndPoint ();
3669  return;
3670  }
3671  m_dataRetrCount--;
3673  NS_LOG_LOGIC ("TcpSocketBase " << this << " rescheduling LATO1");
3674  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
3676  }
3677 }
3678 
3679 // Send 1-byte data to probe for the window size at the receiver when
3680 // the local knowledge tells that the receiver has zero window size
3681 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
3682 void
3684 {
3685  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
3686  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
3687  Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence)->GetPacketCopy ();
3688  m_txBuffer->ResetLastSegmentSent ();
3689  TcpHeader tcpHeader;
3691  tcpHeader.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
3692  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
3693  if (m_endPoint != nullptr)
3694  {
3695  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
3696  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
3697  }
3698  else
3699  {
3700  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
3701  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
3702  }
3703  AddOptions (tcpHeader);
3704  //Send a packet tag for setting ECT bits in IP header
3706  {
3707  SocketIpTosTag ipTosTag;
3708  ipTosTag.SetTos (MarkEcnCodePoint (0, m_tcb->m_ectCodePoint));
3709  p->AddPacketTag (ipTosTag);
3710 
3711  SocketIpv6TclassTag ipTclassTag;
3712  ipTclassTag.SetTclass (MarkEcnCodePoint (0, m_tcb->m_ectCodePoint));
3713  p->AddPacketTag (ipTclassTag);
3714  }
3715  m_txTrace (p, tcpHeader, this);
3716 
3717  if (m_endPoint != nullptr)
3718  {
3719  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
3721  }
3722  else
3723  {
3724  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
3726  }
3727 
3728  NS_LOG_LOGIC ("Schedule persist timeout at time "
3729  << Simulator::Now ().GetSeconds () << " to expire at time "
3730  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
3732 }
3733 
3734 void
3736 {
3737  NS_LOG_FUNCTION (this);
3738  bool res;
3739  SequenceNumber32 seq;
3740  SequenceNumber32 seqHigh;
3741  uint32_t maxSizeToSend;
3742 
3743  // Find the first segment marked as lost and not retransmitted. With Reno,
3744  // that should be the head
3745  res = m_txBuffer->NextSeg (&seq, &seqHigh, false);
3746  if (!res)
3747  {
3748  // We have already retransmitted the head. However, we still received
3749  // three dupacks, or the RTO expired, but no data to transmit.
3750  // Therefore, re-send again the head.
3751  seq = m_txBuffer->HeadSequence ();
3752  maxSizeToSend = m_tcb->m_segmentSize;
3753  }
3754  else
3755  {
3756  // NextSeg() may constrain the segment size when res is true
3757  maxSizeToSend = static_cast<uint32_t> (seqHigh - seq);
3758  }
3759  NS_ASSERT (m_sackEnabled || seq == m_txBuffer->HeadSequence ());
3760 
3761  NS_LOG_INFO ("Retransmitting " << seq);
3762  // Update the trace and retransmit the segment
3763  m_tcb->m_nextTxSequence = seq;
3764  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, maxSizeToSend, true);
3765 
3766  NS_ASSERT (sz > 0);
3767 }
3768 
3769 void
3771 {
3772  m_retxEvent.Cancel ();
3774  m_delAckEvent.Cancel ();
3778  m_pacingTimer.Cancel ();
3779 }
3780 
3781 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
3782 void
3784 {
3785  NS_LOG_DEBUG (TcpStateName[m_state] << " -> TIME_WAIT");
3786  m_state = TIME_WAIT;
3787  CancelAllTimers ();
3788  if (!m_closeNotified)
3789  {
3790  // Technically the connection is not fully closed, but we notify now
3791  // because an implementation (real socket) would behave as if closed.
3792  // Notify normal close when entering TIME_WAIT or leaving LAST_ACK.
3793  NotifyNormalClose ();
3794  m_closeNotified = true;
3795  }
3796  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
3797  // according to RFC793, p.28
3800 }
3801 
3802 /* Below are the attribute get/set functions */
3803 
3804 void
3806 {
3807  NS_LOG_FUNCTION (this << size);
3808  m_txBuffer->SetMaxBufferSize (size);
3809 }
3810 
3811 uint32_t
3813 {
3814  return m_txBuffer->MaxBufferSize ();
3815 }
3816 
3817 void
3819 {
3820  NS_LOG_FUNCTION (this << size);
3821  uint32_t oldSize = GetRcvBufSize ();
3822 
3823  m_tcb->m_rxBuffer->SetMaxBufferSize (size);
3824 
3825  /* The size has (manually) increased. Actively inform the other end to prevent
3826  * stale zero-window states.
3827  */
3828  if (oldSize < size && m_connected)
3829  {
3831  {
3833  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3835  }
3836  else
3837  {
3839  }
3840  }
3841 }
3842 
3843 uint32_t
3845 {
3846  return m_tcb->m_rxBuffer->MaxBufferSize ();
3847 }
3848 
3849 void
3851 {
3852  NS_LOG_FUNCTION (this << size);
3853  m_tcb->m_segmentSize = size;
3854  m_txBuffer->SetSegmentSize (size);
3855 
3856  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
3857 }
3858 
3859 uint32_t
3861 {
3862  return m_tcb->m_segmentSize;
3863 }
3864 
3865 void
3867 {
3868  NS_LOG_FUNCTION (this << timeout);
3869  m_cnTimeout = timeout;
3870 }
3871 
3872 Time
3874 {
3875  return m_cnTimeout;
3876 }
3877 
3878 void
3880 {
3881  NS_LOG_FUNCTION (this << count);
3882  m_synRetries = count;
3883 }
3884 
3885 uint32_t
3887 {
3888  return m_synRetries;
3889 }
3890 
3891 void
3893 {
3894  NS_LOG_FUNCTION (this << retries);
3895  m_dataRetries = retries;
3896 }
3897 
3898 uint32_t
3900 {
3901  NS_LOG_FUNCTION (this);
3902  return m_dataRetries;
3903 }
3904 
3905 void
3907 {
3908  NS_LOG_FUNCTION (this << timeout);
3910 }
3911 
3912 Time
3914 {
3915  return m_delAckTimeout;
3916 }
3917 
3918 void
3920 {
3921  NS_LOG_FUNCTION (this << count);
3922  m_delAckMaxCount = count;
3923 }
3924 
3925 uint32_t
3927 {
3928  return m_delAckMaxCount;
3929 }
3930 
3931 void
3933 {
3934  NS_LOG_FUNCTION (this << noDelay);
3935  m_noDelay = noDelay;
3936 }
3937 
3938 bool
3940 {
3941  return m_noDelay;
3942 }
3943 
3944 void
3946 {
3947  NS_LOG_FUNCTION (this << timeout);
3949 }
3950 
3951 Time
3953 {
3954  return m_persistTimeout;
3955 }
3956 
3957 bool
3959 {
3960  // Broadcast is not implemented. Return true only if allowBroadcast==false
3961  return (!allowBroadcast);
3962 }
3963 
3964 bool
3966 {
3967  return false;
3968 }
3969 
3970 void
3972 {
3973  NS_LOG_FUNCTION (this << header);
3974 
3975  if (m_timestampEnabled)
3976  {
3977  AddOptionTimestamp (header);
3978  }
3979 }
3980 
3981 void
3983 {
3984  NS_LOG_FUNCTION (this << option);
3985 
3986  Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
3987 
3988  // In naming, we do the contrary of RFC 1323. The received scaling factor
3989  // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
3990  m_sndWindShift = ws->GetScale ();
3991 
3992  if (m_sndWindShift > 14)
3993  {
3994  NS_LOG_WARN ("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
3995  m_sndWindShift = 14;
3996  }
3997 
3998  NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
3999  static_cast<int> (m_sndWindShift));
4000 }
4001 
4002 uint8_t
4004 {
4005  NS_LOG_FUNCTION (this);
4006  uint32_t maxSpace = m_tcb->m_rxBuffer->MaxBufferSize ();
4007  uint8_t scale = 0;
4008 
4009  while (maxSpace > m_maxWinSize)
4010  {
4011  maxSpace = maxSpace >> 1;
4012  ++scale;
4013  }
4014 
4015  if (scale > 14)
4016  {
4017  NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
4018  scale = 14;
4019  }
4020 
4021  NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
4022  static_cast<int> (scale) << " for buffer size " << m_tcb->m_rxBuffer->MaxBufferSize ());
4023  return scale;
4024 }
4025 
4026 void
4028 {
4029  NS_LOG_FUNCTION (this << header);
4030  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
4031 
4032  Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
4033 
4034  // In naming, we do the contrary of RFC 1323. The sended scaling factor
4035  // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
4036 
4038  option->SetScale (m_rcvWindShift);
4039 
4040  header.AppendOption (option);
4041 
4042  NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
4043  static_cast<int> (m_rcvWindShift));
4044 }
4045 
4046 uint32_t
4048 {
4049  NS_LOG_FUNCTION (this << option);
4050 
4051  Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option);
4052  return m_txBuffer->Update (s->GetSackList (), MakeCallback (&TcpRateOps::SkbDelivered, m_rateOps));
4053 }
4054 
4055 void
4057 {
4058  NS_LOG_FUNCTION (this << option);
4059 
4060  Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted> (option);
4061 
4062  NS_ASSERT (m_sackEnabled == true);
4063  NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s);
4064 }
4065 
4066 void
4068 {
4069  NS_LOG_FUNCTION (this << header);
4070  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
4071 
4072  Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> ();
4073  header.AppendOption (option);
4074  NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED");
4075 }
4076 
4077 void
4079 {
4080  NS_LOG_FUNCTION (this << header);
4081 
4082  // Calculate the number of SACK blocks allowed in this packet
4083  uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength ();
4084  uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8;
4085 
4086  TcpOptionSack::SackList sackList = m_tcb->m_rxBuffer->GetSackList ();
4087  if (allowedSackBlocks == 0 || sackList.empty ())
4088  {
4089  NS_LOG_LOGIC ("No space available or sack list empty, not adding sack blocks");
4090  return;
4091  }
4092 
4093  // Append the allowed number of SACK blocks
4094  Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> ();
4095  TcpOptionSack::SackList::iterator i;
4096  for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i)
4097  {
4098  option->AddSackBlock (*i);
4099  allowedSackBlocks--;
4100  }
4101 
4102  header.AppendOption (option);
4103  NS_LOG_INFO (m_node->GetId () << " Add option SACK " << *option);
4104 }
4105 
4106 void
4108  const SequenceNumber32 &seq)
4109 {
4110  NS_LOG_FUNCTION (this << option);
4111 
4112  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
4113 
4114  // This is valid only when no overflow occurs. It happens
4115  // when a connection last longer than 50 days.
4116  if (m_tcb->m_rcvTimestampValue > ts->GetTimestamp ())
4117  {
4118  // Do not save a smaller timestamp (probably there is reordering)
4119  return;
4120  }
4121 
4122  m_tcb->m_rcvTimestampValue = ts->GetTimestamp ();
4123  m_tcb->m_rcvTimestampEchoReply = ts->GetEcho ();
4124 
4125  if (seq == m_tcb->m_rxBuffer->NextRxSequence () && seq <= m_highTxAck)
4126  {
4127  m_timestampToEcho = ts->GetTimestamp ();
4128  }
4129 
4130  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
4131  m_timestampToEcho << " and Echo=" << ts->GetEcho ());
4132 }
4133 
4134 void
4136 {
4137  NS_LOG_FUNCTION (this << header);
4138 
4139  Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
4140 
4141  option->SetTimestamp (TcpOptionTS::NowToTsValue ());
4142  option->SetEcho (m_timestampToEcho);
4143 
4144  header.AppendOption (option);
4145  NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
4146  option->GetTimestamp () << " echo=" << m_timestampToEcho);
4147 }
4148 
4150 {
4151  NS_LOG_FUNCTION (this << header);
4152  // If the connection is not established, the window size is always
4153  // updated
4154  uint32_t receivedWindow = header.GetWindowSize ();
4155  receivedWindow <<= m_sndWindShift;
4156  NS_LOG_INFO ("Received (scaled) window is " << receivedWindow << " bytes");
4157  if (m_state < ESTABLISHED)
4158  {
4159  m_rWnd = receivedWindow;
4160  NS_LOG_LOGIC ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
4161  return;
4162  }
4163 
4164  // Test for conditions that allow updating of the window
4165  // 1) segment contains new data (advancing the right edge of the receive
4166  // buffer),
4167  // 2) segment does not contain new data but the segment acks new data
4168  // (highest sequence number acked advances), or
4169  // 3) the advertised window is larger than the current send window
4170  bool update = false;
4171  if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
4172  {
4173  // right edge of the send window is increased (window update)
4174  update = true;
4175  }
4176  if (header.GetAckNumber () > m_highRxAckMark)
4177  {
4178  m_highRxAckMark = header.GetAckNumber ();
4179  update = true;
4180  }
4181  if (header.GetSequenceNumber () > m_highRxMark)
4182  {
4183  m_highRxMark = header.GetSequenceNumber ();
4184  update = true;
4185  }
4186  if (update == true)
4187  {
4188  m_rWnd = receivedWindow;
4189  NS_LOG_LOGIC ("updating rWnd to " << m_rWnd);
4190  }
4191 }
4192 
4193 void
4195 {
4196  NS_LOG_FUNCTION (this << minRto);
4197  m_minRto = minRto;
4198 }
4199 
4200 Time
4202 {
4203  return m_minRto;
4204 }
4205 
4206 void
4208 {
4209  NS_LOG_FUNCTION (this << clockGranularity);
4210  m_clockGranularity = clockGranularity;
4211 }
4212 
4213 Time
4215 {
4216  return m_clockGranularity;
4217 }
4218 
4221 {
4222  return m_txBuffer;
4223 }
4224 
4227 {
4228  return m_tcb->m_rxBuffer;
4229 }
4230 
4231 void
4232 TcpSocketBase::SetRetxThresh (uint32_t retxThresh)
4233 {
4234  m_retxThresh = retxThresh;
4235  m_txBuffer->SetDupAckThresh (retxThresh);
4236 }
4237 
4238 void
4239 TcpSocketBase::UpdateCwnd (uint32_t oldValue, uint32_t newValue)
4240 {
4241  m_cWndTrace (oldValue, newValue);
4242 }
4243 
4244 void
4245 TcpSocketBase::UpdateCwndInfl (uint32_t oldValue, uint32_t newValue)
4246 {
4247  m_cWndInflTrace (oldValue, newValue);
4248 }
4249 
4250 void
4251 TcpSocketBase::UpdateSsThresh (uint32_t oldValue, uint32_t newValue)
4252 {
4253  m_ssThTrace (oldValue, newValue);
4254 }
4255 
4256 void
4259 {
4260  m_congStateTrace (oldValue, newValue);
4261 }
4262 
4263  void
4265  TcpSocketState::EcnState_t newValue)
4266 {
4267  m_ecnStateTrace (oldValue, newValue);
4268 }
4269 
4270 void
4272  SequenceNumber32 newValue)
4273 
4274 {
4275  m_nextTxSequenceTrace (oldValue, newValue);
4276 }
4277 
4278 void
4280 {
4281  m_highTxMarkTrace (oldValue, newValue);
4282 }
4283 
4284 void
4285 TcpSocketBase::UpdateBytesInFlight (uint32_t oldValue, uint32_t newValue)
4286 {
4287  m_bytesInFlightTrace (oldValue, newValue);
4288 }
4289 
4290 void
4291 TcpSocketBase::UpdateRtt (Time oldValue, Time newValue)
4292 {
4293  m_lastRttTrace (oldValue, newValue);
4294 }
4295 
4296 void
4298 {
4299  NS_LOG_FUNCTION (this << algo);
4300  m_congestionControl = algo;
4301  m_congestionControl->Init (m_tcb);
4302 }
4303 
4304 void
4306 {
4307  NS_LOG_FUNCTION (this << recovery);
4308  m_recoveryOps = recovery;
4309 }
4310 
4313 {
4314  return CopyObject<TcpSocketBase> (this);
4315 }
4316 
4317 uint32_t
4318 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b)
4319 {
4320  if (a > b)
4321  {
4322  return a-b;
4323  }
4324 
4325  return 0;
4326 }
4327 
4328 void
4330 {
4331  NS_LOG_FUNCTION (this);
4332  NS_LOG_INFO ("Performing Pacing");
4334 }
4335 
4336 void
4338 {
4339  NS_LOG_FUNCTION (this << useEcn);
4340  m_tcb->m_useEcn = useEcn;
4341 }
4342 
4343 uint32_t
4345 {
4346  return m_rWnd.Get ();
4347 }
4348 
4351 {
4352  return m_highRxAckMark.Get ();
4353 }
4354 
4355 
4356 //RttHistory methods
4358  : seq (s),
4359  count (c),
4360  time (t),
4361  retx (false)
4362 {
4363 }
4364 
4366  : seq (h.seq),
4367  count (h.count),
4368  time (h.time),
4369  retx (h.retx)
4370 {
4371 }
4372 
4373 } // 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:102
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.
DataRate m_currentPacingRate
Current Pacing rate.
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
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
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
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:361
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:1070
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:162
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:743
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.
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 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
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
Definition: nstime.h:294
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:1124
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.
uint16_t GetLocalPort()
Get the local port.
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:225
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:877
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.
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
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.
Time TimeStep(uint64_t ts)
Definition: nstime.h:1119
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:1125
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.
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
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
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:462
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.
Ptr< const AttributeChecker > MakeEnumChecker(int v1, std::string n1, int v2, std::string n2, int v3, std::string n3, int v4, std::string n4, int v5, std::string n5, int v6, std::string n6, int v7, std::string n7, int v8, std::string n8, int v9, std::string n9, int v10, std::string n10, int v11, std::string n11, int v12, std::string n12, int v13, std::string n13, int v14, std::string n14, int v15, std::string n15, int v16, std::string n16, int v17, std::string n17, int v18, std::string n18, int v19, std::string n19, int v20, std::string n20, int v21, std::string n21, int v22, std::string n22)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.cc:180
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
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:863
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:870
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:1062
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.
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.
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.
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:449
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:114
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.
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
Time CalculateBytesTxTime(uint32_t bytes) const
Calculate transmission time.
Definition: data-rate.cc:229
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
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
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.