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