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