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  m_tcb->m_lastAckedSackedBytes = currentDelivered;
1815 
1816  if (m_tcb->m_congState == TcpSocketState::CA_CWR && (ackNumber > m_recover))
1817  {
1818  // Recovery is over after the window exceeds m_recover
1819  // (although it may be re-entered below if ECE is still set)
1822  if (!m_congestionControl->HasCongControl ())
1823  {
1824  m_tcb->m_cWnd = m_tcb->m_ssThresh.Get ();
1825  m_recoveryOps->ExitRecovery (m_tcb);
1827  }
1828  }
1829 
1830  if (ackNumber > oldHeadSequence && (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED) && (tcpHeader.GetFlags () & TcpHeader::ECE))
1831  {
1832  if (m_ecnEchoSeq < ackNumber)
1833  {
1834  NS_LOG_INFO ("Received ECN Echo is valid");
1835  m_ecnEchoSeq = ackNumber;
1836  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_ECE_RCVD");
1839  {
1840  EnterCwr (currentDelivered);
1841  }
1842  }
1843  }
1844  else if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && !(tcpHeader.GetFlags () & TcpHeader::ECE))
1845  {
1847  }
1848 
1849  // Update bytes in flight before processing the ACK for proper calculation of congestion window
1850  NS_LOG_INFO ("Update bytes in flight before processing the ACK.");
1851  BytesInFlight ();
1852 
1853  // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation
1854  // are inside the function ProcessAck
1855  ProcessAck (ackNumber, (bytesSacked > 0), currentDelivered, oldHeadSequence);
1856  m_tcb->m_isRetransDataAcked = false;
1857 
1858  if (m_congestionControl->HasCongControl ())
1859  {
1860  uint32_t currentLost = m_txBuffer->GetLost ();
1861  uint32_t lost = (currentLost > previousLost) ?
1862  currentLost - previousLost :
1863  previousLost - currentLost;
1864  auto rateSample = m_rateOps->GenerateSample (currentDelivered, lost,
1865  false, priorInFlight, m_tcb->m_minRtt);
1866  auto rateConn = m_rateOps->GetConnectionRate ();
1867  m_congestionControl->CongControl(m_tcb, rateConn, rateSample);
1868  }
1869 
1870  // If there is any data piggybacked, store it into m_rxBuffer
1871  if (packet->GetSize () > 0)
1872  {
1873  ReceivedData (packet, tcpHeader);
1874  }
1875 
1876  // RFC 6675, Section 5, point (C), try to send more data. NB: (C) is implemented
1877  // inside SendPendingData
1879 }
1880 
1881 void
1882 TcpSocketBase::ProcessAck(const SequenceNumber32 &ackNumber, bool scoreboardUpdated,
1883  uint32_t currentDelivered, const SequenceNumber32 &oldHeadSequence)
1884 {
1885  NS_LOG_FUNCTION (this << ackNumber << scoreboardUpdated);
1886  // RFC 6675, Section 5, 2nd paragraph:
1887  // If the incoming ACK is a cumulative acknowledgment, the TCP MUST
1888  // reset DupAcks to zero.
1889  bool exitedFastRecovery = false;
1890  uint32_t oldDupAckCount = m_dupAckCount; // remember the old value
1891  m_tcb->m_lastAckedSeq = ackNumber; // Update lastAckedSeq
1892  uint32_t bytesAcked = 0;
1893 
1894  /* In RFC 5681 the definition of duplicate acknowledgment was strict:
1895  *
1896  * (a) the receiver of the ACK has outstanding data,
1897  * (b) the incoming acknowledgment carries no data,
1898  * (c) the SYN and FIN bits are both off,
1899  * (d) the acknowledgment number is equal to the greatest acknowledgment
1900  * received on the given connection (TCP.UNA from [RFC793]),
1901  * (e) the advertised window in the incoming acknowledgment equals the
1902  * advertised window in the last incoming acknowledgment.
1903  *
1904  * With RFC 6675, this definition has been reduced:
1905  *
1906  * (a) the ACK is carrying a SACK block that identifies previously
1907  * unacknowledged and un-SACKed octets between HighACK (TCP.UNA) and
1908  * HighData (m_highTxMark)
1909  */
1910 
1911  bool isDupack = m_sackEnabled ?
1912  scoreboardUpdated
1913  : ackNumber == oldHeadSequence &&
1914  ackNumber < m_tcb->m_highTxMark;
1915 
1916  NS_LOG_DEBUG ("ACK of " << ackNumber <<
1917  " SND.UNA=" << oldHeadSequence <<
1918  " SND.NXT=" << m_tcb->m_nextTxSequence <<
1919  " in state: " << TcpSocketState::TcpCongStateName[m_tcb->m_congState] <<
1920  " with m_recover: " << m_recover);
1921 
1922  // RFC 6675, Section 5, 3rd paragraph:
1923  // If the incoming ACK is a duplicate acknowledgment per the definition
1924  // in Section 2 (regardless of its status as a cumulative
1925  // acknowledgment), and the TCP is not currently in loss recovery
1926  if (isDupack)
1927  {
1928  // loss recovery check is done inside this function thanks to
1929  // the congestion state machine
1930  DupAck (currentDelivered);
1931  }
1932 
1933  if (ackNumber == oldHeadSequence
1934  && ackNumber == m_tcb->m_highTxMark)
1935  {
1936  // Dupack, but the ACK is precisely equal to the nextTxSequence
1937  return;
1938  }
1939  else if (ackNumber == oldHeadSequence
1940  && ackNumber > m_tcb->m_highTxMark)
1941  {
1942  // ACK of the FIN bit ... nextTxSequence is not updated since we
1943  // don't have anything to transmit
1944  NS_LOG_DEBUG ("Update nextTxSequence manually to " << ackNumber);
1945  m_tcb->m_nextTxSequence = ackNumber;
1946  }
1947  else if (ackNumber == oldHeadSequence)
1948  {
1949  // DupAck. Artificially call PktsAcked: after all, one segment has been ACKed.
1950  m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
1951  }
1952  else if (ackNumber > oldHeadSequence)
1953  {
1954  // Please remember that, with SACK, we can enter here even if we
1955  // received a dupack.
1956  bytesAcked = ackNumber - oldHeadSequence;
1957  uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
1958  m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize;
1959  bytesAcked -= bytesAcked % m_tcb->m_segmentSize;
1960 
1962  {
1963  segsAcked += 1;
1964  bytesAcked += m_tcb->m_segmentSize;
1966  }
1967 
1968  // Dupack count is reset to eventually fast-retransmit after 3 dupacks.
1969  // Any SACK-ed segment will be cleaned up by DiscardUpTo.
1970  // In the case that we advanced SND.UNA, but the ack contains SACK blocks,
1971  // we do not reset. At the third one we will retransmit.
1972  // If we are already in recovery, this check is useless since dupAcks
1973  // are not considered in this phase. When from Recovery we go back
1974  // to open, then dupAckCount is reset anyway.
1975  if (!isDupack)
1976  {
1977  m_dupAckCount = 0;
1978  }
1979 
1980  // RFC 6675, Section 5, part (B)
1981  // (B) Upon receipt of an ACK that does not cover RecoveryPoint, the
1982  // following actions MUST be taken:
1983  //
1984  // (B.1) Use Update () to record the new SACK information conveyed
1985  // by the incoming ACK.
1986  // (B.2) Use SetPipe () to re-calculate the number of octets still
1987  // in the network.
1988  //
1989  // (B.1) is done at the beginning, while (B.2) is delayed to part (C) while
1990  // trying to transmit with SendPendingData. We are not allowed to exit
1991  // the CA_RECOVERY phase. Just process this partial ack (RFC 5681)
1992  if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1993  {
1994  if (!m_sackEnabled)
1995  {
1996  // Manually set the head as lost, it will be retransmitted.
1997  NS_LOG_INFO ("Partial ACK. Manually setting head as lost");
1998  m_txBuffer->MarkHeadAsLost ();
1999  }
2000 
2001  // Before retransmitting the packet perform DoRecovery and check if
2002  // there is available window
2003  if (!m_congestionControl->HasCongControl () && segsAcked >= 1)
2004  {
2005  m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
2006  }
2007 
2008  // If the packet is already retransmitted do not retransmit it
2009  if (!m_txBuffer->IsRetransmittedDataAcked (ackNumber + m_tcb->m_segmentSize))
2010  {
2011  DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
2012  m_tcb->m_cWndInfl = SafeSubtraction (m_tcb->m_cWndInfl, bytesAcked);
2013  }
2014 
2015  // This partial ACK acknowledge the fact that one segment has been
2016  // previously lost and now successfully received. All others have
2017  // been processed when they come under the form of dupACKs
2018  m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
2019  NewAck (ackNumber, m_isFirstPartialAck);
2020 
2021  if (m_isFirstPartialAck)
2022  {
2023  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
2024  " and this is the first (RTO will be reset);"
2025  " cwnd set to " << m_tcb->m_cWnd <<
2026  " recover seq: " << m_recover <<
2027  " dupAck count: " << m_dupAckCount);
2028  m_isFirstPartialAck = false;
2029  }
2030  else
2031  {
2032  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
2033  " and this is NOT the first (RTO will not be reset)"
2034  " cwnd set to " << m_tcb->m_cWnd <<
2035  " recover seq: " << m_recover <<
2036  " dupAck count: " << m_dupAckCount);
2037  }
2038  }
2039  // From RFC 6675 section 5.1
2040  // In addition, a new recovery phase (as described in Section 5) MUST NOT
2041  // be initiated until HighACK is greater than or equal to the new value
2042  // of RecoveryPoint.
2043  else if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_LOSS)
2044  {
2045  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2046  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
2047 
2048  NS_LOG_DEBUG (" Cong Control Called, cWnd=" << m_tcb->m_cWnd <<
2049  " ssTh=" << m_tcb->m_ssThresh);
2050  if (!m_sackEnabled)
2051  {
2052  NS_ASSERT_MSG (m_txBuffer->GetSacked () == 0,
2053  "Some segment got dup-acked in CA_LOSS state: " <<
2054  m_txBuffer->GetSacked ());
2055  }
2056  NewAck (ackNumber, true);
2057  }
2059  {
2060  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2061  // TODO: need to check behavior if marking is compounded by loss
2062  // and/or packet reordering
2063  if (!m_congestionControl->HasCongControl () && segsAcked >= 1)
2064  {
2065  m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
2066  }
2067  NewAck (ackNumber, true);
2068  }
2069  else
2070  {
2072  {
2073  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2074  }
2076  {
2077  if (segsAcked >= oldDupAckCount)
2078  {
2079  m_congestionControl->PktsAcked (m_tcb, segsAcked - oldDupAckCount, m_tcb->m_lastRtt);
2080  }
2081 
2082  if (!isDupack)
2083  {
2084  // The network reorder packets. Linux changes the counting lost
2085  // packet algorithm from FACK to NewReno. We simply go back in Open.
2086  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2088  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
2089  ackNumber << " exiting CA_DISORDER -> CA_OPEN");
2090  }
2091  else
2092  {
2093  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
2094  ackNumber << " but still in CA_DISORDER");
2095  }
2096  }
2097  // RFC 6675, Section 5:
2098  // Once a TCP is in the loss recovery phase, the following procedure
2099  // MUST be used for each arriving ACK:
2100  // (A) An incoming cumulative ACK for a sequence number greater than
2101  // RecoveryPoint signals the end of loss recovery, and the loss
2102  // recovery phase MUST be terminated. Any information contained in
2103  // the scoreboard for sequence numbers greater than the new value of
2104  // HighACK SHOULD NOT be cleared when leaving the loss recovery
2105  // phase.
2107  {
2108  m_isFirstPartialAck = true;
2109 
2110  // Recalculate the segs acked, that are from m_recover to ackNumber
2111  // (which are the ones we have not passed to PktsAcked and that
2112  // can increase cWnd)
2113  // TODO: check consistency for dynamic segment size
2114  segsAcked = static_cast<uint32_t>(ackNumber - oldHeadSequence) / m_tcb->m_segmentSize;
2115  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2117  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2119  exitedFastRecovery = true;
2120  m_dupAckCount = 0; // From recovery to open, reset dupack
2121 
2122  NS_LOG_DEBUG (segsAcked << " segments acked in CA_RECOVER, ack of " <<
2123  ackNumber << ", exiting CA_RECOVERY -> CA_OPEN");
2124  }
2126  {
2127  m_isFirstPartialAck = true;
2128 
2129  // Recalculate the segs acked, that are from m_recover to ackNumber
2130  // (which are the ones we have not passed to PktsAcked and that
2131  // can increase cWnd)
2132  segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
2133 
2134  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2135 
2136  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2138  NS_LOG_DEBUG (segsAcked << " segments acked in CA_LOSS, ack of" <<
2139  ackNumber << ", exiting CA_LOSS -> CA_OPEN");
2140  }
2141 
2142  if (ackNumber >= m_recover)
2143  {
2144  // All lost segments in the congestion event have been
2145  // retransmitted successfully. The recovery point (m_recover)
2146  // should be deactivated.
2147  m_recoverActive = false;
2148  }
2149 
2150  if (exitedFastRecovery)
2151  {
2152  NewAck (ackNumber, true);
2153  m_tcb->m_cWnd = m_tcb->m_ssThresh.Get ();
2154  m_recoveryOps->ExitRecovery (m_tcb);
2155  NS_LOG_DEBUG ("Leaving Fast Recovery; BytesInFlight() = " <<
2156  BytesInFlight () << "; cWnd = " << m_tcb->m_cWnd);
2157  }
2159  {
2160  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
2161 
2163 
2164  NS_LOG_LOGIC ("Congestion control called: " <<
2165  " cWnd: " << m_tcb->m_cWnd <<
2166  " ssTh: " << m_tcb->m_ssThresh <<
2167  " segsAcked: " << segsAcked);
2168 
2169  NewAck (ackNumber, true);
2170  }
2171  }
2172  }
2173  // Update the pacing rate, since m_congestionControl->IncreaseWindow() or
2174  // m_congestionControl->PktsAcked () may change m_tcb->m_cWnd
2175  // Make sure that control reaches the end of this function and there is no
2176  // return in between
2177  UpdatePacingRate ();
2178 }
2179 
2180 /* Received a packet upon LISTEN state. */
2181 void
2183  const Address& fromAddress, const Address& toAddress)
2184 {
2185  NS_LOG_FUNCTION (this << tcpHeader);
2186 
2187  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2188  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2189 
2190  // Fork a socket if received a SYN. Do nothing otherwise.
2191  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
2192  if (tcpflags != TcpHeader::SYN)
2193  {
2194  return;
2195  }
2196 
2197  // Call socket's notify function to let the server app know we got a SYN
2198  // If the server app refuses the connection, do nothing
2199  if (!NotifyConnectionRequest (fromAddress))
2200  {
2201  return;
2202  }
2203  // Clone the socket, simulate fork
2204  Ptr<TcpSocketBase> newSock = Fork ();
2205  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
2207  packet, tcpHeader, fromAddress, toAddress);
2208 }
2209 
2210 /* Received a packet upon SYN_SENT */
2211 void
2213 {
2214  NS_LOG_FUNCTION (this << tcpHeader);
2215 
2216  // Extract the flags. PSH and URG are disregarded.
2217  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2218 
2219  if (tcpflags == 0)
2220  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
2221  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2222  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2224  m_state = ESTABLISHED;
2225  m_connected = true;
2226  m_retxEvent.Cancel ();
2228  ReceivedData (packet, tcpHeader);
2230  }
2231  else if (tcpflags & TcpHeader::ACK && !(tcpflags & TcpHeader::SYN))
2232  { // Ignore ACK in SYN_SENT
2233  }
2234  else if (tcpflags & TcpHeader::SYN && !(tcpflags & TcpHeader::ACK))
2235  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
2236  NS_LOG_DEBUG ("SYN_SENT -> SYN_RCVD");
2237  m_state = SYN_RCVD;
2239  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2240  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if the traffic is ECN capable and
2241  * sender has sent ECN SYN packet
2242  */
2243 
2245  {
2246  NS_LOG_INFO ("Received ECN SYN packet");
2250  }
2251  else
2252  {
2255  }
2256  }
2257  else if (tcpflags & (TcpHeader::SYN | TcpHeader::ACK)
2258  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
2259  { // Handshake completed
2260  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2261  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2263  m_state = ESTABLISHED;
2264  m_connected = true;
2265  m_retxEvent.Cancel ();
2266  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2268  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2269  // Before sending packets, update the pacing rate based on RTT measurement so far
2270  UpdatePacingRate ();
2272 
2273  /* 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
2274  * packet and the traffic is ECN Capable
2275  */
2277  {
2278  NS_LOG_INFO ("Received ECN SYN-ACK packet.");
2281  }
2282  else
2283  {
2285  }
2288  // Always respond to first data packet to speed up the connection.
2289  // Remove to get the behaviour of old NS-3 code.
2291  }
2292  else
2293  { // Other in-sequence input
2294  if (!(tcpflags & TcpHeader::RST))
2295  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
2296  NS_LOG_LOGIC ("Illegal flag combination " << TcpHeader::FlagsToString (tcpHeader.GetFlags ()) <<
2297  " received in SYN_SENT. Reset packet is sent.");
2298  SendRST ();
2299  }
2300  CloseAndNotify ();
2301  }
2302 }
2303 
2304 /* Received a packet upon SYN_RCVD */
2305 void
2307  const Address& fromAddress, const Address& toAddress)
2308 {
2309  NS_UNUSED (toAddress);
2310  NS_LOG_FUNCTION (this << tcpHeader);
2311 
2312  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2313  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2314 
2315  if (tcpflags == 0
2316  || (tcpflags == TcpHeader::ACK
2317  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
2318  { // If it is bare data, accept it and move to ESTABLISHED state. This is
2319  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
2320  // handshake is completed nicely.
2321  NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED");
2322  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2324  m_state = ESTABLISHED;
2325  m_connected = true;
2326  m_retxEvent.Cancel ();
2328  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2329  if (m_endPoint)
2330  {
2331  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2332  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2333  }
2334  else if (m_endPoint6)
2335  {
2336  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2337  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2338  }
2339  // Always respond to first data packet to speed up the connection.
2340  // Remove to get the behaviour of old NS-3 code.
2342  NotifyNewConnectionCreated (this, fromAddress);
2343  ReceivedAck (packet, tcpHeader);
2344  // Update the pacing rate based on RTT measurement so far
2345  UpdatePacingRate ();
2346  // As this connection is established, the socket is available to send data now
2347  if (GetTxAvailable () > 0)
2348  {
2350  }
2351  }
2352  else if (tcpflags == TcpHeader::SYN)
2353  { // Probably the peer lost my SYN+ACK
2354  m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2355  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2356  * packet and the traffic is ECN Capable
2357  */
2359  {
2360  NS_LOG_INFO ("Received ECN SYN packet");
2364  }
2365  else
2366  {
2369  }
2370  }
2371  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2372  {
2373  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2374  { // In-sequence FIN before connection complete. Set up connection and close.
2375  m_connected = true;
2376  m_retxEvent.Cancel ();
2378  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2379  if (m_endPoint)
2380  {
2381  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2382  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2383  }
2384  else if (m_endPoint6)
2385  {
2386  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2387  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2388  }
2389  NotifyNewConnectionCreated (this, fromAddress);
2390  PeerClose (packet, tcpHeader);
2391  }
2392  }
2393  else
2394  { // Other in-sequence input
2395  if (tcpflags != TcpHeader::RST)
2396  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
2397  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2398  " received. Reset packet is sent.");
2399  if (m_endPoint)
2400  {
2401  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2402  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2403  }
2404  else if (m_endPoint6)
2405  {
2406  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2407  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2408  }
2409  SendRST ();
2410  }
2411  CloseAndNotify ();
2412  }
2413 }
2414 
2415 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
2416 void
2418 {
2419  NS_LOG_FUNCTION (this << tcpHeader);
2420 
2421  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2422  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2423 
2424  if (packet->GetSize () > 0 && !(tcpflags & TcpHeader::ACK))
2425  { // Bare data, accept it
2426  ReceivedData (packet, tcpHeader);
2427  }
2428  else if (tcpflags == TcpHeader::ACK)
2429  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
2430  ReceivedAck (packet, tcpHeader);
2431  if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
2432  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2433  { // This ACK corresponds to the FIN sent
2434  NS_LOG_DEBUG ("FIN_WAIT_1 -> FIN_WAIT_2");
2435  m_state = FIN_WAIT_2;
2436  }
2437  }
2438  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2439  { // Got FIN, respond with ACK and move to next state
2440  if (tcpflags & TcpHeader::ACK)
2441  { // Process the ACK first
2442  ReceivedAck (packet, tcpHeader);
2443  }
2444  m_tcb->m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
2445  }
2446  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
2447  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
2448  return;
2449  }
2450  else
2451  { // This is a RST or bad flags
2452  if (tcpflags != TcpHeader::RST)
2453  {
2454  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2455  " received. Reset packet is sent.");
2456  SendRST ();
2457  }
2458  CloseAndNotify ();
2459  return;
2460  }
2461 
2462  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
2463  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_tcb->m_rxBuffer->Finished ())
2464  {
2465  if (m_state == FIN_WAIT_1)
2466  {
2467  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2468  m_state = CLOSING;
2469  if (m_txBuffer->Size () == 0
2470  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2471  { // This ACK corresponds to the FIN sent
2472  TimeWait ();
2473  }
2474  }
2475  else if (m_state == FIN_WAIT_2)
2476  {
2477  TimeWait ();
2478  }
2480  if (!m_shutdownRecv)
2481  {
2482  NotifyDataRecv ();
2483  }
2484  }
2485 }
2486 
2487 /* Received a packet upon CLOSING */
2488 void
2490 {
2491  NS_LOG_FUNCTION (this << tcpHeader);
2492 
2493  // Extract the flags. PSH and URG are disregarded.
2494  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2495 
2496  if (tcpflags == TcpHeader::ACK)
2497  {
2498  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2499  { // This ACK corresponds to the FIN sent
2500  TimeWait ();
2501  }
2502  }
2503  else
2504  { // CLOSING state means simultaneous close, i.e. no one is sending data to
2505  // anyone. If anything other than ACK is received, respond with a reset.
2506  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2507  { // FIN from the peer as well. We can close immediately.
2509  }
2510  else if (tcpflags != TcpHeader::RST)
2511  { // Receive of SYN or SYN+ACK or bad flags or pure data
2512  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2513  SendRST ();
2514  }
2515  CloseAndNotify ();
2516  }
2517 }
2518 
2519 /* Received a packet upon LAST_ACK */
2520 void
2522 {
2523  NS_LOG_FUNCTION (this << tcpHeader);
2524 
2525  // Extract the flags. PSH and URG are disregarded.
2526  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2527 
2528  if (tcpflags == 0)
2529  {
2530  ReceivedData (packet, tcpHeader);
2531  }
2532  else if (tcpflags == TcpHeader::ACK)
2533  {
2534  if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2535  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
2536  CloseAndNotify ();
2537  }
2538  }
2539  else if (tcpflags == TcpHeader::FIN)
2540  { // Received FIN again, the peer probably lost the FIN+ACK
2542  }
2543  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2544  {
2545  CloseAndNotify ();
2546  }
2547  else
2548  { // Received a SYN or SYN+ACK or bad flags
2549  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2550  SendRST ();
2551  CloseAndNotify ();
2552  }
2553 }
2554 
2555 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
2556 void
2558 {
2559  NS_LOG_FUNCTION (this << tcpHeader);
2560 
2561  // Ignore all out of range packets
2562  if (tcpHeader.GetSequenceNumber () < m_tcb->m_rxBuffer->NextRxSequence ()
2563  || tcpHeader.GetSequenceNumber () > m_tcb->m_rxBuffer->MaxRxSequence ())
2564  {
2565  return;
2566  }
2567  // For any case, remember the FIN position in rx buffer first
2568  m_tcb->m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2569  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2570  // If there is any piggybacked data, process it
2571  if (p->GetSize ())
2572  {
2573  ReceivedData (p, tcpHeader);
2574  }
2575  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2576  if (!m_tcb->m_rxBuffer->Finished ())
2577  {
2578  return;
2579  }
2580 
2581  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2582  if (m_state == FIN_WAIT_1)
2583  {
2584  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2585  m_state = CLOSING;
2586  return;
2587  }
2588 
2589  DoPeerClose (); // Change state, respond with ACK
2590 }
2591 
2592 /* Received a in-sequence FIN. Close down this socket. */
2593 void
2595 {
2598 
2599  // Move the state to CLOSE_WAIT
2600  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSE_WAIT");
2601  m_state = CLOSE_WAIT;
2602 
2603  if (!m_closeNotified)
2604  {
2605  // The normal behaviour for an application is that, when the peer sent a in-sequence
2606  // FIN, the app should prepare to close. The app has two choices at this point: either
2607  // respond with ShutdownSend() call to declare that it has nothing more to send and
2608  // the socket can be closed immediately; or remember the peer's close request, wait
2609  // until all its existing data are pushed into the TCP socket, then call Close()
2610  // explicitly.
2611  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
2612  NotifyNormalClose ();
2613  m_closeNotified = true;
2614  }
2615  if (m_shutdownSend)
2616  { // The application declares that it would not sent any more, close this socket
2617  Close ();
2618  }
2619  else
2620  { // Need to ack, the application will close later
2622  }
2623  if (m_state == LAST_ACK)
2624  {
2625  m_dataRetrCount = m_dataRetries; // prevent endless FINs
2626  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
2627  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
2629  }
2630 }
2631 
2632 /* Kill this socket. This is a callback function configured to m_endpoint in
2633  SetupCallback(), invoked when the endpoint is destroyed. */
2634 void
2636 {
2637  NS_LOG_FUNCTION (this);
2638  m_endPoint = nullptr;
2639  if (m_tcp != nullptr)
2640  {
2641  m_tcp->RemoveSocket (this);
2642  }
2643  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2644  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2645  CancelAllTimers ();
2646 }
2647 
2648 /* Kill this socket. This is a callback function configured to m_endpoint in
2649  SetupCallback(), invoked when the endpoint is destroyed. */
2650 void
2652 {
2653  NS_LOG_FUNCTION (this);
2654  m_endPoint6 = nullptr;
2655  if (m_tcp != nullptr)
2656  {
2657  m_tcp->RemoveSocket (this);
2658  }
2659  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2660  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2661  CancelAllTimers ();
2662 }
2663 
2664 /* Send an empty packet with specified TCP flags */
2665 void
2667 {
2668  NS_LOG_FUNCTION (this << static_cast<uint32_t> (flags));
2669 
2670  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
2671  {
2672  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
2673  return;
2674  }
2675 
2676  Ptr<Packet> p = Create<Packet> ();
2677  TcpHeader header;
2679 
2680  if (flags & TcpHeader::FIN)
2681  {
2682  flags |= TcpHeader::ACK;
2683  }
2684  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2685  {
2686  ++s;
2687  }
2688 
2689  AddSocketTags (p);
2690 
2691  header.SetFlags (flags);
2692  header.SetSequenceNumber (s);
2693  header.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
2694  if (m_endPoint != nullptr)
2695  {
2696  header.SetSourcePort (m_endPoint->GetLocalPort ());
2697  header.SetDestinationPort (m_endPoint->GetPeerPort ());
2698  }
2699  else
2700  {
2701  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2702  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
2703  }
2704  AddOptions (header);
2705 
2706  // RFC 6298, clause 2.4
2707  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2708 
2709  uint16_t windowSize = AdvertisedWindowSize ();
2710  bool hasSyn = flags & TcpHeader::SYN;
2711  bool hasFin = flags & TcpHeader::FIN;
2712  bool isAck = flags == TcpHeader::ACK;
2713  if (hasSyn)
2714  {
2715  if (m_winScalingEnabled)
2716  { // The window scaling option is set only on SYN packets
2717  AddOptionWScale (header);
2718  }
2719 
2720  if (m_sackEnabled)
2721  {
2722  AddOptionSackPermitted (header);
2723  }
2724 
2725  if (m_synCount == 0)
2726  { // No more connection retries, give up
2727  NS_LOG_LOGIC ("Connection failed.");
2728  m_rtt->Reset (); //According to recommendation -> RFC 6298
2730  m_state = CLOSED;
2731  DeallocateEndPoint ();
2732  return;
2733  }
2734  else
2735  { // Exponential backoff of connection time out
2736  int backoffCount = 0x1 << (m_synRetries - m_synCount);
2737  m_rto = m_cnTimeout * backoffCount;
2738  m_synCount--;
2739  }
2740 
2741  if (m_synRetries - 1 == m_synCount)
2742  {
2743  UpdateRttHistory (s, 0, false);
2744  }
2745  else
2746  { // This is SYN retransmission
2747  UpdateRttHistory (s, 0, true);
2748  }
2749 
2750  windowSize = AdvertisedWindowSize (false);
2751  }
2752  header.SetWindowSize (windowSize);
2753 
2754  if (flags & TcpHeader::ACK)
2755  { // If sending an ACK, cancel the delay ACK as well
2756  m_delAckEvent.Cancel ();
2757  m_delAckCount = 0;
2758  if (m_highTxAck < header.GetAckNumber ())
2759  {
2760  m_highTxAck = header.GetAckNumber ();
2761  }
2762  if (m_sackEnabled && m_tcb->m_rxBuffer->GetSackListSize () > 0)
2763  {
2764  AddOptionSack (header);
2765  }
2766  NS_LOG_INFO ("Sending a pure ACK, acking seq " << m_tcb->m_rxBuffer->NextRxSequence ());
2767  }
2768 
2769  m_txTrace (p, header, this);
2770 
2771  if (m_endPoint != nullptr)
2772  {
2773  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2775  }
2776  else
2777  {
2778  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2780  }
2781 
2782 
2783  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
2784  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2785  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
2786  << Simulator::Now ().GetSeconds () << " to expire at time "
2787  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2789  }
2790 }
2791 
2792 /* This function closes the endpoint completely. Called upon RST_TX action. */
2793 void
2795 {
2796  NS_LOG_FUNCTION (this);
2798  NotifyErrorClose ();
2799  DeallocateEndPoint ();
2800 }
2801 
2802 /* Deallocate the end point and cancel all the timers */
2803 void
2805 {
2806  if (m_endPoint != nullptr)
2807  {
2808  CancelAllTimers ();
2809  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
2810  m_tcp->DeAllocate (m_endPoint);
2811  m_endPoint = nullptr;
2812  m_tcp->RemoveSocket (this);
2813  }
2814  else if (m_endPoint6 != nullptr)
2815  {
2816  CancelAllTimers ();
2817  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
2818  m_tcp->DeAllocate (m_endPoint6);
2819  m_endPoint6 = nullptr;
2820  m_tcp->RemoveSocket (this);
2821  }
2822 }
2823 
2824 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2825 int
2827 {
2828  NS_LOG_FUNCTION (this);
2829  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
2830  NS_ASSERT (ipv4 != nullptr);
2831  if (ipv4->GetRoutingProtocol () == nullptr)
2832  {
2833  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
2834  }
2835  // Create a dummy packet, then ask the routing function for the best output
2836  // interface's address
2837  Ipv4Header header;
2839  Socket::SocketErrno errno_;
2840  Ptr<Ipv4Route> route;
2842  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2843  if (route == 0)
2844  {
2845  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
2846  NS_LOG_ERROR (errno_);
2847  m_errno = errno_;
2848  return -1;
2849  }
2850  NS_LOG_LOGIC ("Route exists");
2851  m_endPoint->SetLocalAddress (route->GetSource ());
2852  return 0;
2853 }
2854 
2855 int
2857 {
2858  NS_LOG_FUNCTION (this);
2860  NS_ASSERT (ipv6 != nullptr);
2861  if (ipv6->GetRoutingProtocol () == nullptr)
2862  {
2863  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
2864  }
2865  // Create a dummy packet, then ask the routing function for the best output
2866  // interface's address
2867  Ipv6Header header;
2869  Socket::SocketErrno errno_;
2870  Ptr<Ipv6Route> route;
2872  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2873  if (route == nullptr)
2874  {
2875  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
2876  NS_LOG_ERROR (errno_);
2877  m_errno = errno_;
2878  return -1;
2879  }
2880  NS_LOG_LOGIC ("Route exists");
2881  m_endPoint6->SetLocalAddress (route->GetSource ());
2882  return 0;
2883 }
2884 
2885 /* This function is called only if a SYN received in LISTEN state. After
2886  TcpSocketBase cloned, allocate a new end point to handle the incoming
2887  connection and send a SYN+ACK to complete the handshake. */
2888 void
2890  const Address& fromAddress, const Address& toAddress)
2891 {
2892  NS_LOG_FUNCTION (this << p << h << fromAddress << toAddress);
2893  NS_UNUSED (p);
2894  // Get port and address from peer (connecting host)
2895  if (InetSocketAddress::IsMatchingType (toAddress))
2896  {
2897  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (),
2898  InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
2899  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
2900  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2901  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2902  m_endPoint6 = nullptr;
2903  }
2904  else if (Inet6SocketAddress::IsMatchingType (toAddress))
2905  {
2906  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (),
2907  Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
2908  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
2909  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2910  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2911  m_endPoint = nullptr;
2912  }
2913  m_tcp->AddSocket (this);
2914 
2915  // Change the cloned socket from LISTEN state to SYN_RCVD
2916  NS_LOG_DEBUG ("LISTEN -> SYN_RCVD");
2917  m_state = SYN_RCVD;
2920  SetupCallback ();
2921  // Set the sequence number and send SYN+ACK
2922  m_tcb->m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
2923 
2924  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2925  * packet and the traffic is ECN Capable
2926  */
2929  {
2933  }
2934  else
2935  {
2938  }
2939 }
2940 
2941 void
2943 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
2944  // be called as a scheduled event
2946  // The if-block below was moved from ProcessSynSent() to here because we need
2947  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
2948  // reflect the behaviour in the real world.
2949  if (GetTxAvailable () > 0)
2950  {
2952  }
2953 }
2954 
2955 void
2957 {
2958  /*
2959  * Add tags for each socket option.
2960  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2961  * if both options are set. Once the packet got to layer three, only
2962  * the corresponding tags will be read.
2963  */
2964  if (GetIpTos ())
2965  {
2966  SocketIpTosTag ipTosTag;
2968  {
2970  }
2971  else
2972  {
2973  // Set the last received ipTos
2974  ipTosTag.SetTos (GetIpTos ());
2975  }
2976  p->AddPacketTag (ipTosTag);
2977  }
2978  else
2979  {
2981  {
2982  SocketIpTosTag ipTosTag;
2984  p->AddPacketTag (ipTosTag);
2985  }
2986  }
2987 
2988  if (IsManualIpv6Tclass ())
2989  {
2990  SocketIpv6TclassTag ipTclassTag;
2992  {
2994  }
2995  else
2996  {
2997  // Set the last received ipTos
2998  ipTclassTag.SetTclass (GetIpv6Tclass ());
2999  }
3000  p->AddPacketTag (ipTclassTag);
3001  }
3002  else
3003  {
3005  {
3006  SocketIpv6TclassTag ipTclassTag;
3008  p->AddPacketTag (ipTclassTag);
3009  }
3010  }
3011 
3012  if (IsManualIpTtl ())
3013  {
3014  SocketIpTtlTag ipTtlTag;
3015  ipTtlTag.SetTtl (GetIpTtl ());
3016  p->AddPacketTag (ipTtlTag);
3017  }
3018 
3019  if (IsManualIpv6HopLimit ())
3020  {
3021  SocketIpv6HopLimitTag ipHopLimitTag;
3022  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
3023  p->AddPacketTag (ipHopLimitTag);
3024  }
3025 
3026  uint8_t priority = GetPriority ();
3027  if (priority)
3028  {
3029  SocketPriorityTag priorityTag;
3030  priorityTag.SetPriority (priority);
3031  p->ReplacePacketTag (priorityTag);
3032  }
3033 }
3034 
3035 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
3036  TCP header, and send to TcpL4Protocol */
3037 uint32_t
3038 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
3039 {
3040  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
3041 
3042  bool isStartOfTransmission = BytesInFlight () == 0U;
3043  TcpTxItem *outItem = m_txBuffer->CopyFromSequence (maxSize, seq);
3044 
3045  m_rateOps->SkbSent(outItem, isStartOfTransmission);
3046 
3047  bool isRetransmission = outItem->IsRetrans ();
3048  Ptr<Packet> p = outItem->GetPacketCopy ();
3049  uint32_t sz = p->GetSize (); // Size of packet
3050  uint8_t flags = withAck ? TcpHeader::ACK : 0;
3051  uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
3052 
3053  // TCP sender should not send data out of the window advertised by the
3054  // peer when it is not retransmission.
3055  NS_ASSERT (isRetransmission || ((m_highRxAckMark + SequenceNumber32 (m_rWnd)) >= (seq + SequenceNumber32 (maxSize))));
3056 
3057  if (IsPacingEnabled ())
3058  {
3059  NS_LOG_INFO ("Pacing is enabled");
3060  if (m_pacingTimer.IsExpired ())
3061  {
3062  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_pacingRate);
3063  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3064  m_pacingTimer.Schedule (m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3065  }
3066  else
3067  {
3068  NS_LOG_INFO ("Timer is already in running state");
3069  }
3070  }
3071  else
3072  {
3073  NS_LOG_INFO ("Pacing is disabled");
3074  }
3075 
3076  if (withAck)
3077  {
3078  m_delAckEvent.Cancel ();
3079  m_delAckCount = 0;
3080  }
3081 
3082  if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && m_ecnEchoSeq.Get() > m_ecnCWRSeq.Get () && !isRetransmission)
3083  {
3084  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_CWR_SENT");
3086  m_ecnCWRSeq = seq;
3087  flags |= TcpHeader::CWR;
3088  NS_LOG_INFO ("CWR flags set");
3089  }
3090 
3091  AddSocketTags (p);
3092 
3093  if (m_closeOnEmpty && (remainingData == 0))
3094  {
3095  flags |= TcpHeader::FIN;
3096  if (m_state == ESTABLISHED)
3097  { // On active close: I am the first one to send FIN
3098  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
3099  m_state = FIN_WAIT_1;
3100  }
3101  else if (m_state == CLOSE_WAIT)
3102  { // On passive close: Peer sent me FIN already
3103  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
3104  m_state = LAST_ACK;
3105  }
3106  }
3107  TcpHeader header;
3108  header.SetFlags (flags);
3109  header.SetSequenceNumber (seq);
3110  header.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
3111  if (m_endPoint)
3112  {
3113  header.SetSourcePort (m_endPoint->GetLocalPort ());
3115  }
3116  else
3117  {
3118  header.SetSourcePort (m_endPoint6->GetLocalPort ());
3120  }
3121  header.SetWindowSize (AdvertisedWindowSize ());
3122  AddOptions (header);
3123 
3124  if (m_retxEvent.IsExpired ())
3125  {
3126  // Schedules retransmit timeout. m_rto should be already doubled.
3127 
3128  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
3129  Simulator::Now ().GetSeconds () << " to expire at time " <<
3130  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
3132  }
3133 
3134  m_txTrace (p, header, this);
3135 
3136  if (m_endPoint)
3137  {
3138  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
3140  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
3141  remainingData << " via TcpL4Protocol to " << m_endPoint->GetPeerAddress () <<
3142  ". Header " << header);
3143  }
3144  else
3145  {
3146  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
3148  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
3149  remainingData << " via TcpL4Protocol to " << m_endPoint6->GetPeerAddress () <<
3150  ". Header " << header);
3151  }
3152 
3153  UpdateRttHistory (seq, sz, isRetransmission);
3154 
3155  // Update bytes sent during recovery phase
3157  {
3158  m_recoveryOps->UpdateBytesSent (sz);
3159  }
3160 
3161  // Notify the application of the data being sent unless this is a retransmit
3162  if (!isRetransmission)
3163  {
3165  (seq + sz - m_tcb->m_highTxMark.Get ()));
3166  }
3167  // Update highTxMark
3168  m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ());
3169  return sz;
3170 }
3171 
3172 void
3174  bool isRetransmission)
3175 {
3176  NS_LOG_FUNCTION (this);
3177 
3178  // update the history of sequence numbers used to calculate the RTT
3179  if (isRetransmission == false)
3180  { // This is the next expected one, just log at end
3181  m_history.push_back (RttHistory (seq, sz, Simulator::Now ()));
3182  }
3183  else
3184  { // This is a retransmit, find in list and mark as re-tx
3185  for (std::deque<RttHistory>::iterator i = m_history.begin (); i != m_history.end (); ++i)
3186  {
3187  if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
3188  { // Found it
3189  i->retx = true;
3190  i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
3191  break;
3192  }
3193  }
3194  }
3195 }
3196 
3197 // Note that this function did not implement the PSH flag
3198 uint32_t
3200 {
3201  NS_LOG_FUNCTION (this << withAck);
3202  if (m_txBuffer->Size () == 0)
3203  {
3204  return false; // Nothing to send
3205  }
3206  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
3207  {
3208  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
3209  return false; // Is this the right way to handle this condition?
3210  }
3211 
3212  uint32_t nPacketsSent = 0;
3213  uint32_t availableWindow = AvailableWindow ();
3214 
3215  // RFC 6675, Section (C)
3216  // If cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more
3217  // segments as follows:
3218  // (NOTE: We check > 0, and do the checks for segmentSize in the following
3219  // else branch to control silly window syndrome and Nagle)
3220  while (availableWindow > 0)
3221  {
3222  if (IsPacingEnabled ())
3223  {
3224  NS_LOG_INFO ("Pacing is enabled");
3225  if (m_pacingTimer.IsRunning ())
3226  {
3227  NS_LOG_INFO ("Skipping Packet due to pacing" << m_pacingTimer.GetDelayLeft ());
3228  break;
3229  }
3230  NS_LOG_INFO ("Timer is not running");
3231  }
3232 
3235  {
3236  NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit");
3237  break;
3238  }
3239  // (C.1) The scoreboard MUST be queried via NextSeg () for the
3240  // sequence number range of the next segment to transmit (if
3241  // any), and the given segment sent. If NextSeg () returns
3242  // failure (no data to send), return without sending anything
3243  // (i.e., terminate steps C.1 -- C.5).
3244  SequenceNumber32 next;
3245  SequenceNumber32 nextHigh;
3246  bool enableRule3 = m_sackEnabled && m_tcb->m_congState == TcpSocketState::CA_RECOVERY;
3247  if (!m_txBuffer->NextSeg (&next, &nextHigh, enableRule3))
3248  {
3249  NS_LOG_INFO ("no valid seq to transmit, or no data available");
3250  break;
3251  }
3252  else
3253  {
3254  // It's time to transmit, but before do silly window and Nagle's check
3255  uint32_t availableData = m_txBuffer->SizeFromSequence (next);
3256 
3257  // If there's less app data than the full window, ask the app for more
3258  // data before trying to send
3259  if (availableData < availableWindow)
3260  {
3262  }
3263 
3264  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
3265  // but continue if we don't have data
3266  if (availableWindow < m_tcb->m_segmentSize && availableData > availableWindow)
3267  {
3268  NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
3269  break; // No more
3270  }
3271  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
3272  // in the buffer and the amount of data to send is less than one segment
3273  if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_segmentSize)
3274  {
3275  NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next <<
3276  ", SFS: " << m_txBuffer->SizeFromSequence (next) <<
3277  ". Wait to send.");
3278  break;
3279  }
3280 
3281  uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize);
3282  // NextSeg () may have further constrained the segment size
3283  uint32_t maxSizeToSend = static_cast<uint32_t> (nextHigh - next);
3284  s = std::min (s, maxSizeToSend);
3285 
3286  // (C.2) If any of the data octets sent in (C.1) are below HighData,
3287  // HighRxt MUST be set to the highest sequence number of the
3288  // retransmitted segment unless NextSeg () rule (4) was
3289  // invoked for this retransmission.
3290  // (C.3) If any of the data octets sent in (C.1) are above HighData,
3291  // HighData must be updated to reflect the transmission of
3292  // previously unsent data.
3293  //
3294  // These steps are done in m_txBuffer with the tags.
3295  if (m_tcb->m_nextTxSequence != next)
3296  {
3297  m_tcb->m_nextTxSequence = next;
3298  }
3299  if (m_tcb->m_bytesInFlight.Get () == 0)
3300  {
3302  }
3303  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck);
3304 
3305  NS_LOG_LOGIC (" rxwin " << m_rWnd <<
3306  " segsize " << m_tcb->m_segmentSize <<
3307  " highestRxAck " << m_txBuffer->HeadSequence () <<
3308  " pd->Size " << m_txBuffer->Size () <<
3309  " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence));
3310 
3311  NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd <<
3312  " total unAck: " << UnAckDataCount () <<
3313  " sent seq " << m_tcb->m_nextTxSequence <<
3314  " size " << sz);
3315  m_tcb->m_nextTxSequence += sz;
3316  ++nPacketsSent;
3317  if (IsPacingEnabled ())
3318  {
3319  NS_LOG_INFO ("Pacing is enabled");
3320  if (m_pacingTimer.IsExpired ())
3321  {
3322  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_pacingRate);
3323  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3324  m_pacingTimer.Schedule (m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3325  break;
3326  }
3327  }
3328  }
3329 
3330  // (C.4) The estimate of the amount of data outstanding in the
3331  // network must be updated by incrementing pipe by the number
3332  // of octets transmitted in (C.1).
3333  //
3334  // Done in BytesInFlight, inside AvailableWindow.
3335  availableWindow = AvailableWindow ();
3336 
3337  // (C.5) If cwnd - pipe >= 1 SMSS, return to (C.1)
3338  // loop again!
3339  }
3340 
3341  if (nPacketsSent > 0)
3342  {
3343  if (!m_sackEnabled)
3344  {
3345  if (!m_limitedTx)
3346  {
3347  // We can't transmit in CA_DISORDER without limitedTx active
3349  }
3350  }
3351 
3352  NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments");
3353  }
3354  else
3355  {
3356  NS_LOG_DEBUG ("SendPendingData no segments sent");
3357  }
3358  return nPacketsSent;
3359 }
3360 
3361 uint32_t
3363 {
3364  return m_tcb->m_highTxMark - m_txBuffer->HeadSequence ();
3365 }
3366 
3367 uint32_t
3369 {
3370  uint32_t bytesInFlight = m_txBuffer->BytesInFlight ();
3371  // Ugly, but we are not modifying the state; m_bytesInFlight is used
3372  // only for tracing purpose.
3373  m_tcb->m_bytesInFlight = bytesInFlight;
3374 
3375  NS_LOG_DEBUG ("Returning calculated bytesInFlight: " << bytesInFlight);
3376  return bytesInFlight;
3377 }
3378 
3379 uint32_t
3381 {
3382  return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
3383 }
3384 
3385 uint32_t
3387 {
3388  uint32_t win = Window (); // Number of bytes allowed to be outstanding
3389  uint32_t inflight = BytesInFlight (); // Number of outstanding bytes
3390  return (inflight > win) ? 0 : win - inflight;
3391 }
3392 
3393 uint16_t
3395 {
3396  NS_LOG_FUNCTION (this << scale);
3397  uint32_t w;
3398 
3399  // We don't want to advertise 0 after a FIN is received. So, we just use
3400  // the previous value of the advWnd.
3401  if (m_tcb->m_rxBuffer->GotFin ())
3402  {
3403  w = m_advWnd;
3404  }
3405  else
3406  {
3407  NS_ASSERT_MSG (m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence () >= 0,
3408  "Unexpected sequence number values");
3409  w = static_cast<uint32_t> (m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence ());
3410  }
3411 
3412  // Ugly, but we are not modifying the state, that variable
3413  // is used only for tracing purpose.
3414  if (w != m_advWnd)
3415  {
3416  const_cast<TcpSocketBase*> (this)->m_advWnd = w;
3417  }
3418  if (scale)
3419  {
3420  w >>= m_rcvWindShift;
3421  }
3422  if (w > m_maxWinSize)
3423  {
3424  w = m_maxWinSize;
3425  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
3426  }
3427  NS_LOG_LOGIC ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
3428  return static_cast<uint16_t> (w);
3429 }
3430 
3431 // Receipt of new packet, put into Rx buffer
3432 void
3434 {
3435  NS_LOG_FUNCTION (this << tcpHeader);
3436  NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () <<
3437  " pkt size=" << p->GetSize () );
3438 
3439  // Put into Rx buffer
3440  SequenceNumber32 expectedSeq = m_tcb->m_rxBuffer->NextRxSequence ();
3441  if (!m_tcb->m_rxBuffer->Add (p, tcpHeader))
3442  { // Insert failed: No data or RX buffer full
3444  {
3446  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3448  }
3449  else
3450  {
3452  }
3453  return;
3454  }
3455  // Notify app to receive if necessary
3456  if (expectedSeq < m_tcb->m_rxBuffer->NextRxSequence ())
3457  { // NextRxSeq advanced, we have something to send to the app
3458  if (!m_shutdownRecv)
3459  {
3460  NotifyDataRecv ();
3461  }
3462  // Handle exceptions
3463  if (m_closeNotified)
3464  {
3465  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
3466  }
3467  // If we received FIN before and now completed all "holes" in rx buffer,
3468  // invoke peer close procedure
3469  if (m_tcb->m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
3470  {
3471  DoPeerClose ();
3472  return;
3473  }
3474  }
3475  // Now send a new ACK packet acknowledging all received and delivered data
3476  if (m_tcb->m_rxBuffer->Size () > m_tcb->m_rxBuffer->Available () || m_tcb->m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
3477  { // A gap exists in the buffer, or we filled a gap: Always ACK
3480  {
3482  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3484  }
3485  else
3486  {
3488  }
3489  }
3490  else
3491  { // In-sequence packet: ACK if delayed ack count allows
3493  {
3494  m_delAckEvent.Cancel ();
3495  m_delAckCount = 0;
3498  {
3499  NS_LOG_DEBUG("Congestion algo " << m_congestionControl->GetName ());
3501  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3503  }
3504  else
3505  {
3507  }
3508  }
3509  else if (!m_delAckEvent.IsExpired ())
3510  {
3512  }
3513  else if (m_delAckEvent.IsExpired ())
3514  {
3518  NS_LOG_LOGIC (this << " scheduled delayed ACK at " <<
3519  (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
3520  }
3521  }
3522 }
3523 
3524 void
3526 {
3527  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber ();
3528  Time m = Time (0.0);
3529 
3530  // An ack has been received, calculate rtt and log this measurement
3531  // Note we use a linear search (O(n)) for this since for the common
3532  // case the ack'ed packet will be at the head of the list
3533  if (!m_history.empty ())
3534  {
3535  RttHistory& h = m_history.front ();
3536  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
3537  { // Ok to use this sample
3538  if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
3539  {
3541  ts = DynamicCast<const TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
3542  m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
3543  if (m.IsZero ())
3544  {
3545  NS_LOG_LOGIC ("TcpSocketBase::EstimateRtt - RTT calculated from TcpOption::TS is zero, approximating to 1us.");
3546  m = MicroSeconds (1);
3547  }
3548  }
3549  else
3550  {
3551  m = Simulator::Now () - h.time; // Elapsed time
3552  }
3553  }
3554  }
3555 
3556  // Now delete all ack history with seq <= ack
3557  while (!m_history.empty ())
3558  {
3559  RttHistory& h = m_history.front ();
3560  if ((h.seq + SequenceNumber32 (h.count)) > ackSeq)
3561  {
3562  break; // Done removing
3563  }
3564  m_history.pop_front (); // Remove
3565  }
3566 
3567  if (!m.IsZero ())
3568  {
3569  m_rtt->Measurement (m); // Log the measurement
3570  // RFC 6298, clause 2.4
3571  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3572  m_tcb->m_lastRtt = m_rtt->GetEstimate ();
3574  NS_LOG_INFO (this << m_tcb->m_lastRtt << m_tcb->m_minRtt);
3575  }
3576 }
3577 
3578 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
3579 // when the three-way handshake completed. This cancels retransmission timer
3580 // and advances Tx window
3581 void
3582 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO)
3583 {
3584  NS_LOG_FUNCTION (this << ack);
3585 
3586  // Reset the data retransmission count. We got a new ACK!
3588 
3589  if (m_state != SYN_RCVD && resetRTO)
3590  { // Set RTO unless the ACK is received in SYN_RCVD state
3591  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3592  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3593  m_retxEvent.Cancel ();
3594  // On receiving a "New" ack we restart retransmission timer .. RFC 6298
3595  // RFC 6298, clause 2.4
3596  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3597 
3598  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
3599  Simulator::Now ().GetSeconds () << " to expire at time " <<
3600  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
3602  }
3603 
3604  // Note the highest ACK and tell app to send more
3605  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
3606  " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
3607 
3608  if (GetTxAvailable () > 0)
3609  {
3611  }
3612  if (ack > m_tcb->m_nextTxSequence)
3613  {
3614  m_tcb->m_nextTxSequence = ack; // If advanced
3615  }
3616  if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
3617  { // No retransmit timer if no data to retransmit
3618  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3619  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3620  m_retxEvent.Cancel ();
3621  }
3622 }
3623 
3624 // Retransmit timeout
3625 void
3627 {
3628  NS_LOG_FUNCTION (this);
3629  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
3630  // If erroneous timeout in closed/timed-wait state, just return
3631  if (m_state == CLOSED || m_state == TIME_WAIT)
3632  {
3633  return;
3634  }
3635 
3636  if (m_state == SYN_SENT)
3637  {
3638  NS_ASSERT (m_synCount > 0);
3640  {
3642  }
3643  else
3644  {
3646  }
3647  return;
3648  }
3649 
3650  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3651  if (m_txBuffer->Size () == 0)
3652  {
3653  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3654  { // Must have lost FIN, re-send
3656  }
3657  return;
3658  }
3659 
3660  NS_LOG_DEBUG ("Checking if Connection is Established");
3661  // If all data are received (non-closing socket and nothing to send), just return
3662  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark && m_txBuffer->Size () == 0)
3663  {
3664  NS_LOG_DEBUG ("Already Sent full data" << m_txBuffer->HeadSequence () << " " << m_tcb->m_highTxMark);
3665  return;
3666  }
3667 
3668  if (m_dataRetrCount == 0)
3669  {
3670  NS_LOG_INFO ("No more data retries available. Dropping connection");
3671  NotifyErrorClose ();
3672  DeallocateEndPoint ();
3673  return;
3674  }
3675  else
3676  {
3677  --m_dataRetrCount;
3678  }
3679 
3680  uint32_t inFlightBeforeRto = BytesInFlight ();
3681  bool resetSack = !m_sackEnabled; // Reset SACK information if SACK is not enabled.
3682  // The information in the TcpTxBuffer is guessed, in this case.
3683 
3684  // Reset dupAckCount
3685  m_dupAckCount = 0;
3686  if (!m_sackEnabled)
3687  {
3688  m_txBuffer->ResetRenoSack ();
3689  }
3690 
3691  // From RFC 6675, Section 5.1
3692  // [RFC2018] suggests that a TCP sender SHOULD expunge the SACK
3693  // information gathered from a receiver upon a retransmission timeout
3694  // (RTO) "since the timeout might indicate that the data receiver has
3695  // reneged." Additionally, a TCP sender MUST "ignore prior SACK
3696  // information in determining which data to retransmit."
3697  // It has been suggested that, as long as robust tests for
3698  // reneging are present, an implementation can retain and use SACK
3699  // information across a timeout event [Errata1610].
3700  // The head of the sent list will not be marked as sacked, therefore
3701  // will be retransmitted, if the receiver renegotiate the SACK blocks
3702  // that we received.
3703  m_txBuffer->SetSentListLost (resetSack);
3704 
3705  // From RFC 6675, Section 5.1
3706  // If an RTO occurs during loss recovery as specified in this document,
3707  // RecoveryPoint MUST be set to HighData. Further, the new value of
3708  // RecoveryPoint MUST be preserved and the loss recovery algorithm
3709  // outlined in this document MUST be terminated.
3711  m_recoverActive = true;
3712 
3713  // RFC 6298, clause 2.5, double the timer
3714  Time doubledRto = m_rto + m_rto;
3715  m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
3716 
3717  // Empty RTT history
3718  m_history.clear ();
3719 
3720  // Please don't reset highTxMark, it is used for retransmission detection
3721 
3722  // When a TCP sender detects segment loss using the retransmission timer
3723  // and the given segment has not yet been resent by way of the
3724  // retransmission timer, decrease ssThresh
3725  if (m_tcb->m_congState != TcpSocketState::CA_LOSS || !m_txBuffer->IsHeadRetransmitted ())
3726  {
3727  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, inFlightBeforeRto);
3728  }
3729 
3730  // Cwnd set to 1 MSS
3732  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS);
3736 
3737  m_pacingTimer.Cancel ();
3738 
3739  NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
3740  m_tcb->m_ssThresh << ", restart from seqnum " <<
3741  m_txBuffer->HeadSequence () << " doubled rto to " <<
3742  m_rto.Get ().GetSeconds () << " s");
3743 
3744  NS_ASSERT_MSG (BytesInFlight () == 0, "There are some bytes in flight after an RTO: " <<
3745  BytesInFlight ());
3746 
3748 
3750  "In flight (" << BytesInFlight () <<
3751  ") there is more than one segment (" << m_tcb->m_segmentSize << ")");
3752 }
3753 
3754 void
3756 {
3757  m_delAckCount = 0;
3760  {
3763  }
3764  else
3765  {
3767  }
3768 }
3769 
3770 void
3772 {
3773  NS_LOG_FUNCTION (this);
3774 
3776  if (m_state == LAST_ACK)
3777  {
3778  if (m_dataRetrCount == 0)
3779  {
3780  NS_LOG_INFO ("LAST-ACK: No more data retries available. Dropping connection");
3781  NotifyErrorClose ();
3782  DeallocateEndPoint ();
3783  return;
3784  }
3785  m_dataRetrCount--;
3787  NS_LOG_LOGIC ("TcpSocketBase " << this << " rescheduling LATO1");
3788  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
3790  }
3791 }
3792 
3793 // Send 1-byte data to probe for the window size at the receiver when
3794 // the local knowledge tells that the receiver has zero window size
3795 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
3796 void
3798 {
3799  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
3800  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
3801  Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence)->GetPacketCopy ();
3802  m_txBuffer->ResetLastSegmentSent ();
3803  TcpHeader tcpHeader;
3805  tcpHeader.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
3806  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
3807  if (m_endPoint != nullptr)
3808  {
3809  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
3810  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
3811  }
3812  else
3813  {
3814  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
3815  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
3816  }
3817  AddOptions (tcpHeader);
3818  //Send a packet tag for setting ECT bits in IP header
3820  {
3821  SocketIpTosTag ipTosTag;
3822  ipTosTag.SetTos (MarkEcnCodePoint (0, m_tcb->m_ectCodePoint));
3823  p->AddPacketTag (ipTosTag);
3824 
3825  SocketIpv6TclassTag ipTclassTag;
3826  ipTclassTag.SetTclass (MarkEcnCodePoint (0, m_tcb->m_ectCodePoint));
3827  p->AddPacketTag (ipTclassTag);
3828  }
3829  m_txTrace (p, tcpHeader, this);
3830 
3831  if (m_endPoint != nullptr)
3832  {
3833  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
3835  }
3836  else
3837  {
3838  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
3840  }
3841 
3842  NS_LOG_LOGIC ("Schedule persist timeout at time "
3843  << Simulator::Now ().GetSeconds () << " to expire at time "
3844  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
3846 }
3847 
3848 void
3850 {
3851  NS_LOG_FUNCTION (this);
3852  bool res;
3853  SequenceNumber32 seq;
3854  SequenceNumber32 seqHigh;
3855  uint32_t maxSizeToSend;
3856 
3857  // Find the first segment marked as lost and not retransmitted. With Reno,
3858  // that should be the head
3859  res = m_txBuffer->NextSeg (&seq, &seqHigh, false);
3860  if (!res)
3861  {
3862  // We have already retransmitted the head. However, we still received
3863  // three dupacks, or the RTO expired, but no data to transmit.
3864  // Therefore, re-send again the head.
3865  seq = m_txBuffer->HeadSequence ();
3866  maxSizeToSend = m_tcb->m_segmentSize;
3867  }
3868  else
3869  {
3870  // NextSeg() may constrain the segment size when res is true
3871  maxSizeToSend = static_cast<uint32_t> (seqHigh - seq);
3872  }
3873  NS_ASSERT (m_sackEnabled || seq == m_txBuffer->HeadSequence ());
3874 
3875  NS_LOG_INFO ("Retransmitting " << seq);
3876  // Update the trace and retransmit the segment
3877  m_tcb->m_nextTxSequence = seq;
3878  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, maxSizeToSend, true);
3879 
3880  NS_ASSERT (sz > 0);
3881 }
3882 
3883 void
3885 {
3886  m_retxEvent.Cancel ();
3888  m_delAckEvent.Cancel ();
3892  m_pacingTimer.Cancel ();
3893 }
3894 
3895 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
3896 void
3898 {
3899  NS_LOG_DEBUG (TcpStateName[m_state] << " -> TIME_WAIT");
3900  m_state = TIME_WAIT;
3901  CancelAllTimers ();
3902  if (!m_closeNotified)
3903  {
3904  // Technically the connection is not fully closed, but we notify now
3905  // because an implementation (real socket) would behave as if closed.
3906  // Notify normal close when entering TIME_WAIT or leaving LAST_ACK.
3907  NotifyNormalClose ();
3908  m_closeNotified = true;
3909  }
3910  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
3911  // according to RFC793, p.28
3914 }
3915 
3916 /* Below are the attribute get/set functions */
3917 
3918 void
3920 {
3921  NS_LOG_FUNCTION (this << size);
3922  m_txBuffer->SetMaxBufferSize (size);
3923 }
3924 
3925 uint32_t
3927 {
3928  return m_txBuffer->MaxBufferSize ();
3929 }
3930 
3931 void
3933 {
3934  NS_LOG_FUNCTION (this << size);
3935  uint32_t oldSize = GetRcvBufSize ();
3936 
3937  m_tcb->m_rxBuffer->SetMaxBufferSize (size);
3938 
3939  /* The size has (manually) increased. Actively inform the other end to prevent
3940  * stale zero-window states.
3941  */
3942  if (oldSize < size && m_connected)
3943  {
3945  {
3947  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3949  }
3950  else
3951  {
3953  }
3954  }
3955 }
3956 
3957 uint32_t
3959 {
3960  return m_tcb->m_rxBuffer->MaxBufferSize ();
3961 }
3962 
3963 void
3965 {
3966  NS_LOG_FUNCTION (this << size);
3967  m_tcb->m_segmentSize = size;
3968  m_txBuffer->SetSegmentSize (size);
3969 
3970  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
3971 }
3972 
3973 uint32_t
3975 {
3976  return m_tcb->m_segmentSize;
3977 }
3978 
3979 void
3981 {
3982  NS_LOG_FUNCTION (this << timeout);
3983  m_cnTimeout = timeout;
3984 }
3985 
3986 Time
3988 {
3989  return m_cnTimeout;
3990 }
3991 
3992 void
3994 {
3995  NS_LOG_FUNCTION (this << count);
3996  m_synRetries = count;
3997 }
3998 
3999 uint32_t
4001 {
4002  return m_synRetries;
4003 }
4004 
4005 void
4007 {
4008  NS_LOG_FUNCTION (this << retries);
4009  m_dataRetries = retries;
4010 }
4011 
4012 uint32_t
4014 {
4015  NS_LOG_FUNCTION (this);
4016  return m_dataRetries;
4017 }
4018 
4019 void
4021 {
4022  NS_LOG_FUNCTION (this << timeout);
4024 }
4025 
4026 Time
4028 {
4029  return m_delAckTimeout;
4030 }
4031 
4032 void
4034 {
4035  NS_LOG_FUNCTION (this << count);
4036  m_delAckMaxCount = count;
4037 }
4038 
4039 uint32_t
4041 {
4042  return m_delAckMaxCount;
4043 }
4044 
4045 void
4047 {
4048  NS_LOG_FUNCTION (this << noDelay);
4049  m_noDelay = noDelay;
4050 }
4051 
4052 bool
4054 {
4055  return m_noDelay;
4056 }
4057 
4058 void
4060 {
4061  NS_LOG_FUNCTION (this << timeout);
4063 }
4064 
4065 Time
4067 {
4068  return m_persistTimeout;
4069 }
4070 
4071 bool
4073 {
4074  // Broadcast is not implemented. Return true only if allowBroadcast==false
4075  return (!allowBroadcast);
4076 }
4077 
4078 bool
4080 {
4081  return false;
4082 }
4083 
4084 void
4086 {
4087  NS_LOG_FUNCTION (this << header);
4088 
4089  if (m_timestampEnabled)
4090  {
4091  AddOptionTimestamp (header);
4092  }
4093 }
4094 
4095 void
4097 {
4098  NS_LOG_FUNCTION (this << option);
4099 
4100  Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
4101 
4102  // In naming, we do the contrary of RFC 1323. The received scaling factor
4103  // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
4104  m_sndWindShift = ws->GetScale ();
4105 
4106  if (m_sndWindShift > 14)
4107  {
4108  NS_LOG_WARN ("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
4109  m_sndWindShift = 14;
4110  }
4111 
4112  NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
4113  static_cast<int> (m_sndWindShift));
4114 }
4115 
4116 uint8_t
4118 {
4119  NS_LOG_FUNCTION (this);
4120  uint32_t maxSpace = m_tcb->m_rxBuffer->MaxBufferSize ();
4121  uint8_t scale = 0;
4122 
4123  while (maxSpace > m_maxWinSize)
4124  {
4125  maxSpace = maxSpace >> 1;
4126  ++scale;
4127  }
4128 
4129  if (scale > 14)
4130  {
4131  NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
4132  scale = 14;
4133  }
4134 
4135  NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
4136  static_cast<int> (scale) << " for buffer size " << m_tcb->m_rxBuffer->MaxBufferSize ());
4137  return scale;
4138 }
4139 
4140 void
4142 {
4143  NS_LOG_FUNCTION (this << header);
4144  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
4145 
4146  Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
4147 
4148  // In naming, we do the contrary of RFC 1323. The sended scaling factor
4149  // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
4150 
4152  option->SetScale (m_rcvWindShift);
4153 
4154  header.AppendOption (option);
4155 
4156  NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
4157  static_cast<int> (m_rcvWindShift));
4158 }
4159 
4160 uint32_t
4162 {
4163  NS_LOG_FUNCTION (this << option);
4164 
4165  Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option);
4166  return m_txBuffer->Update (s->GetSackList (), MakeCallback (&TcpRateOps::SkbDelivered, m_rateOps));
4167 }
4168 
4169 void
4171 {
4172  NS_LOG_FUNCTION (this << option);
4173 
4174  Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted> (option);
4175 
4176  NS_ASSERT (m_sackEnabled == true);
4177  NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s);
4178 }
4179 
4180 void
4182 {
4183  NS_LOG_FUNCTION (this << header);
4184  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
4185 
4186  Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> ();
4187  header.AppendOption (option);
4188  NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED");
4189 }
4190 
4191 void
4193 {
4194  NS_LOG_FUNCTION (this << header);
4195 
4196  // Calculate the number of SACK blocks allowed in this packet
4197  uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength ();
4198  uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8;
4199 
4200  TcpOptionSack::SackList sackList = m_tcb->m_rxBuffer->GetSackList ();
4201  if (allowedSackBlocks == 0 || sackList.empty ())
4202  {
4203  NS_LOG_LOGIC ("No space available or sack list empty, not adding sack blocks");
4204  return;
4205  }
4206 
4207  // Append the allowed number of SACK blocks
4208  Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> ();
4209  TcpOptionSack::SackList::iterator i;
4210  for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i)
4211  {
4212  option->AddSackBlock (*i);
4213  allowedSackBlocks--;
4214  }
4215 
4216  header.AppendOption (option);
4217  NS_LOG_INFO (m_node->GetId () << " Add option SACK " << *option);
4218 }
4219 
4220 void
4222  const SequenceNumber32 &seq)
4223 {
4224  NS_LOG_FUNCTION (this << option);
4225 
4226  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
4227 
4228  // This is valid only when no overflow occurs. It happens
4229  // when a connection last longer than 50 days.
4230  if (m_tcb->m_rcvTimestampValue > ts->GetTimestamp ())
4231  {
4232  // Do not save a smaller timestamp (probably there is reordering)
4233  return;
4234  }
4235 
4236  m_tcb->m_rcvTimestampValue = ts->GetTimestamp ();
4237  m_tcb->m_rcvTimestampEchoReply = ts->GetEcho ();
4238 
4239  if (seq == m_tcb->m_rxBuffer->NextRxSequence () && seq <= m_highTxAck)
4240  {
4241  m_timestampToEcho = ts->GetTimestamp ();
4242  }
4243 
4244  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
4245  m_timestampToEcho << " and Echo=" << ts->GetEcho ());
4246 }
4247 
4248 void
4250 {
4251  NS_LOG_FUNCTION (this << header);
4252 
4253  Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
4254 
4255  option->SetTimestamp (TcpOptionTS::NowToTsValue ());
4256  option->SetEcho (m_timestampToEcho);
4257 
4258  header.AppendOption (option);
4259  NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
4260  option->GetTimestamp () << " echo=" << m_timestampToEcho);
4261 }
4262 
4264 {
4265  NS_LOG_FUNCTION (this << header);
4266  // If the connection is not established, the window size is always
4267  // updated
4268  uint32_t receivedWindow = header.GetWindowSize ();
4269  receivedWindow <<= m_sndWindShift;
4270  NS_LOG_INFO ("Received (scaled) window is " << receivedWindow << " bytes");
4271  if (m_state < ESTABLISHED)
4272  {
4273  m_rWnd = receivedWindow;
4274  NS_LOG_LOGIC ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
4275  return;
4276  }
4277 
4278  // Test for conditions that allow updating of the window
4279  // 1) segment contains new data (advancing the right edge of the receive
4280  // buffer),
4281  // 2) segment does not contain new data but the segment acks new data
4282  // (highest sequence number acked advances), or
4283  // 3) the advertised window is larger than the current send window
4284  bool update = false;
4285  if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
4286  {
4287  // right edge of the send window is increased (window update)
4288  update = true;
4289  }
4290  if (header.GetAckNumber () > m_highRxAckMark)
4291  {
4292  m_highRxAckMark = header.GetAckNumber ();
4293  update = true;
4294  }
4295  if (header.GetSequenceNumber () > m_highRxMark)
4296  {
4297  m_highRxMark = header.GetSequenceNumber ();
4298  update = true;
4299  }
4300  if (update == true)
4301  {
4302  m_rWnd = receivedWindow;
4303  NS_LOG_LOGIC ("updating rWnd to " << m_rWnd);
4304  }
4305 }
4306 
4307 void
4309 {
4310  NS_LOG_FUNCTION (this << minRto);
4311  m_minRto = minRto;
4312 }
4313 
4314 Time
4316 {
4317  return m_minRto;
4318 }
4319 
4320 void
4322 {
4323  NS_LOG_FUNCTION (this << clockGranularity);
4324  m_clockGranularity = clockGranularity;
4325 }
4326 
4327 Time
4329 {
4330  return m_clockGranularity;
4331 }
4332 
4335 {
4336  return m_txBuffer;
4337 }
4338 
4341 {
4342  return m_tcb->m_rxBuffer;
4343 }
4344 
4345 void
4346 TcpSocketBase::SetRetxThresh (uint32_t retxThresh)
4347 {
4348  m_retxThresh = retxThresh;
4349  m_txBuffer->SetDupAckThresh (retxThresh);
4350 }
4351 
4352 void
4354 {
4355  m_pacingRateTrace (oldValue, newValue);
4356 }
4357 
4358 void
4359 TcpSocketBase::UpdateCwnd (uint32_t oldValue, uint32_t newValue)
4360 {
4361  m_cWndTrace (oldValue, newValue);
4362 }
4363 
4364 void
4365 TcpSocketBase::UpdateCwndInfl (uint32_t oldValue, uint32_t newValue)
4366 {
4367  m_cWndInflTrace (oldValue, newValue);
4368 }
4369 
4370 void
4371 TcpSocketBase::UpdateSsThresh (uint32_t oldValue, uint32_t newValue)
4372 {
4373  m_ssThTrace (oldValue, newValue);
4374 }
4375 
4376 void
4379 {
4380  m_congStateTrace (oldValue, newValue);
4381 }
4382 
4383  void
4385  TcpSocketState::EcnState_t newValue)
4386 {
4387  m_ecnStateTrace (oldValue, newValue);
4388 }
4389 
4390 void
4392  SequenceNumber32 newValue)
4393 
4394 {
4395  m_nextTxSequenceTrace (oldValue, newValue);
4396 }
4397 
4398 void
4400 {
4401  m_highTxMarkTrace (oldValue, newValue);
4402 }
4403 
4404 void
4405 TcpSocketBase::UpdateBytesInFlight (uint32_t oldValue, uint32_t newValue)
4406 {
4407  m_bytesInFlightTrace (oldValue, newValue);
4408 }
4409 
4410 void
4411 TcpSocketBase::UpdateRtt (Time oldValue, Time newValue)
4412 {
4413  m_lastRttTrace (oldValue, newValue);
4414 }
4415 
4416 void
4418 {
4419  NS_LOG_FUNCTION (this << algo);
4420  m_congestionControl = algo;
4421  m_congestionControl->Init (m_tcb);
4422 }
4423 
4424 void
4426 {
4427  NS_LOG_FUNCTION (this << recovery);
4428  m_recoveryOps = recovery;
4429 }
4430 
4433 {
4434  return CopyObject<TcpSocketBase> (this);
4435 }
4436 
4437 uint32_t
4438 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b)
4439 {
4440  if (a > b)
4441  {
4442  return a-b;
4443  }
4444 
4445  return 0;
4446 }
4447 
4448 void
4450 {
4451  NS_LOG_FUNCTION (this);
4452  NS_LOG_INFO ("Performing Pacing");
4454 }
4455 
4456 bool
4458 {
4459  if (!m_tcb->m_pacing)
4460  {
4461  return false;
4462  }
4463  else
4464  {
4466  {
4467  return true;
4468  }
4469  SequenceNumber32 highTxMark = m_tcb->m_highTxMark; // cast traced value
4470  if (highTxMark.GetValue () > (GetInitialCwnd () * m_tcb->m_segmentSize))
4471  {
4472  return true;
4473  }
4474  }
4475  return false;
4476 }
4477 
4478 void
4480 {
4481  NS_LOG_FUNCTION (this << m_tcb);
4482 
4483  // According to Linux, set base pacing rate to (cwnd * mss) / srtt
4484  //
4485  // In (early) slow start, multiply base by the slow start factor.
4486  // In late slow start and congestion avoidance, multiply base by
4487  // the congestion avoidance factor.
4488  // Comment from Linux code regarding early/late slow start:
4489  // Normal Slow Start condition is (tp->snd_cwnd < tp->snd_ssthresh)
4490  // If snd_cwnd >= (tp->snd_ssthresh / 2), we are approaching
4491  // end of slow start and should slow down.
4492 
4493  // Similar to Linux, do not update pacing rate here if the
4494  // congestion control implements TcpCongestionOps::CongControl ()
4495  if (m_congestionControl->HasCongControl () || !m_tcb->m_pacing) return;
4496 
4497  double factor;
4498  if (m_tcb->m_cWnd < m_tcb->m_ssThresh/2)
4499  {
4500  NS_LOG_DEBUG ("Pacing according to slow start factor; " << m_tcb->m_cWnd << " " << m_tcb->m_ssThresh);
4501  factor = static_cast<double> (m_tcb->m_pacingSsRatio)/100;
4502  }
4503  else
4504  {
4505  NS_LOG_DEBUG ("Pacing according to congestion avoidance factor; " << m_tcb->m_cWnd << " " << m_tcb->m_ssThresh);
4506  factor = static_cast<double> (m_tcb->m_pacingCaRatio)/100;
4507  }
4508  Time lastRtt = m_tcb->m_lastRtt.Get (); // Get underlying Time value
4509  NS_LOG_DEBUG ("Last RTT is " << lastRtt.GetSeconds ());
4510 
4511  // Multiply by 8 to convert from bytes per second to bits per second
4512  DataRate pacingRate ((std::max (m_tcb->m_cWnd, m_tcb->m_bytesInFlight) * 8 * factor) / lastRtt.GetSeconds ());
4513  if (pacingRate < m_tcb->m_maxPacingRate)
4514  {
4515  NS_LOG_DEBUG ("Pacing rate updated to: " << pacingRate);
4516  m_tcb->m_pacingRate = pacingRate;
4517  }
4518  else
4519  {
4520  NS_LOG_DEBUG ("Pacing capped by max pacing rate: " << m_tcb->m_maxPacingRate);
4522  }
4523 }
4524 
4525 void
4527 {
4528  NS_LOG_FUNCTION (this << pacing);
4529  m_tcb->m_pacing = pacing;
4530 }
4531 
4532 void
4534 {
4535  NS_LOG_FUNCTION (this << paceWindow);
4536  m_tcb->m_paceInitialWindow = paceWindow;
4537 }
4538 
4539 void
4541 {
4542  NS_LOG_FUNCTION (this << useEcn);
4543  m_tcb->m_useEcn = useEcn;
4544 }
4545 
4546 uint32_t
4548 {
4549  return m_rWnd.Get ();
4550 }
4551 
4554 {
4555  return m_highRxAckMark.Get ();
4556 }
4557 
4558 
4559 //RttHistory methods
4561  : seq (s),
4562  count (c),
4563  time (t),
4564  retx (false)
4565 {
4566 }
4567 
4569  : seq (h.seq),
4570  count (h.count),
4571  time (h.time),
4572  retx (h.retx)
4573 {
4574 }
4575 
4576 } // 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
uint32_t m_lastAckedSackedBytes
The number of bytes acked and sacked as indicated by the current ACK received.
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:1164
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:1116
virtual uint32_t GetInitialSSThresh(void) const
Get the initial Slow Start Threshold.
bool m_isRetransDataAcked
Retransmitted data is ACKed if true.
virtual uint32_t BytesInFlight(void) const
Return total bytes in flight.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
void DoPeerClose(void)
FIN is in sequence, notify app and respond with a FIN.
bool NotifyConnectionRequest(const Address &from)
Notify through the callback (if set) that an incoming connection is being requested by a remote host...
Definition: socket.cc:257
TracedCallback< TcpSocketState::EcnState_t, TcpSocketState::EcnState_t > m_ecnStateTrace
Callback pointer for ECN state trace chaining.
virtual void PersistTimeout(void)
Send 1 byte probe to get an updated window size.
virtual void SetSynRetries(uint32_t count)
Set the number of connection retries before giving up.
TracedValue< TcpStates_t > m_state
TCP state.
Time GetMinRto(void) const
Get the Minimum RTO.
uint32_t m_delAckMaxCount
Number of packet to fire an ACK before delay timeout.
bool m_paceInitialWindow
Enable/Disable pacing for the initial window.
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:65
Receiver sends an ACK with ECE bit set in TCP header.
uint16_t port
Definition: dsdv-manet.cc:45
a polymophic address class
Definition: address.h:90
void SetMinRto(Time minRto)
Sets the Minimum RTO.
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
uint16_t GetPeerPort()
Get the peer port.
AttributeValue implementation for Callback.
Definition: callback.h:1937
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
uint32_t m_delAckCount
Delayed ACK counter.
virtual uint8_t GetIpTtl(void) const
Query the value of IP Time to Live field of this socket.
Definition: socket.cc:520
SequenceNumber32 m_recover
Previous highest Tx seqnum for fast recovery (set it to initial seq number)
void ForwardIcmp6(Ipv6Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Called by the L3 protocol when it received an ICMPv6 packet to pass on to TCP.
virtual int Bind(void)
Allocate a local IPv4 endpoint for this socket.
bool IsRetrans(void) const
Is the item retransmitted?
Definition: tcp-tx-item.cc:74
Class for representing data rates.
Definition: data-rate.h:88
virtual bool GetAllowBroadcast(void) const
Query whether broadcast datagram transmissions are allowed.
Last packet received had CE bit set in IP header.
virtual uint32_t GetRcvBufSize(void) const
Get the receive buffer size.
Ptr< NetDevice > GetBoundNetDevice()
Returns socket&#39;s bound NetDevice, if any.
Definition: socket.cc:351
Packet header for IPv4.
Definition: ipv4-header.h:33
void SetLocalAddress(Ipv6Address addr)
Set the local address.
virtual void CalculateAppLimited(uint32_t cWnd, uint32_t in_flight, uint32_t segmentSize, const SequenceNumber32 &tailSeq, const SequenceNumber32 &nextTx, const uint32_t lostOut, const uint32_t retransOut)=0
If a gap is detected between sends, it means we are app-limited.
Callback< void, uint8_t > m_sendEmptyPacketCallback
Callback to send an empty packet.
void UpdateBytesInFlight(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState bytes inflight.
virtual enum SocketType GetSocketType(void) const
virtual void SetDataRetries(uint32_t retries)
Set the number of data transmission retries before giving up.
Ptr< TcpCongestionOps > m_congestionControl
Congestion control.
static const char *const TcpStateName[TcpSocket::LAST_STATE]
Literal names of TCP states for use in log messages.
Definition: tcp-socket.h:94
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:218
void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Ptr< TcpRateOps > m_rateOps
Rate operations.
Ptr< TcpRxBuffer > GetRxBuffer(void) const
Get a pointer to the Rx buffer.
Item that encloses the application packet and some flags for it.
Definition: tcp-tx-item.h:32
bool CheckNoEcn(uint8_t tos) const
Checks if TOS has no ECN codepoints.
TracedValue< uint32_t > m_cWndInfl
Inflated congestion window trace (used only for backward compatibility purpose)
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send data to a specified peer.
void UpdateCwnd(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState congestion window.
bool IsTcpOptionEnabled(uint8_t kind) const
Return true if the specified option is enabled.
virtual uint32_t GetSegSize(void) const
Get the segment size.
virtual void EstimateRtt(const TcpHeader &tcpHeader)
Take into account the packet for RTT estimation.
virtual int GetSockName(Address &address) const
Get socket address.
cWnd was reduced due to some congestion notification event, such as ECN, ICMP source quench...
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: pointer.h:227
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
Hold variables of type enum.
Definition: enum.h:54
Time time
Time this one was sent.
void ReadOptions(const TcpHeader &tcpHeader, uint32_t *bytesSacked)
Read TCP options before Ack processing.
#define max(a, b)
Definition: 80211b.c:43
virtual void UpdateRttHistory(const SequenceNumber32 &seq, uint32_t sz, bool isRetransmission)
Update the RTT history, when we send TCP segments.
Ptr< TcpTxBuffer > m_txBuffer
Tx buffer.
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:301
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:588
void ForwardUp(Ptr< Packet > packet, Ipv4Header header, uint16_t port, Ptr< Ipv4Interface > incomingInterface)
Called by the L3 protocol when it received a packet to pass on to TCP.
void SetTtl(uint8_t ttl)
Set the tag&#39;s TTL.
Definition: socket.cc:604
AttributeValue implementation for Time.
Definition: nstime.h:1353
void Schedule(void)
Schedule a new event using the currently-configured delay, function, and arguments.
Definition: timer.cc:158
bool OutOfRange(SequenceNumber32 head, SequenceNumber32 tail) const
Check if a sequence number range is within the rx window.
TracedValue< DataRate > m_pacingRate
Current Pacing rate.
uint16_t GetLocalPort()
Get the local port.
bool IsPacingEnabled(void) const
Return true if packets in the current window should be paced.
virtual uint32_t Window(void) const
Return the max possible number of unacked bytes.
void UpdateWindowSize(const TcpHeader &header)
Update the receiver window (RWND) based on the value of the window field in the header.
void SetFunction(FN fn)
Definition: timer.h:278
Ptr< const AttributeChecker > MakeCallbackChecker(void)
Definition: callback.cc:74
void AddOptionTimestamp(TcpHeader &header)
Add the timestamp option to the header.
Hold an unsigned integer type.
Definition: uinteger.h:44
SequenceNumber32 m_highTxAck
Highest ack sent.
TracedCallback< uint32_t, uint32_t > m_cWndTrace
Callback pointer for cWnd trace chaining.
Ipv6EndPoint * m_endPoint6
the IPv6 endpoint
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
virtual uint32_t GetSynRetries(void) const
Get the number of connection retries before giving up.
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: enum.h:203
void SetPacingStatus(bool pacing)
Enable or disable pacing.
std::deque< RttHistory > m_history
List of sent packet.
virtual enum SocketErrno GetErrno(void) const
Get last error number.
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:970
virtual bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
Ptr< const AttributeAccessor > MakeCallbackAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: callback.h:1981
Ipv4Address GetLocalAddress(void)
Get the local address.
indicates whether the socket has a priority set.
Definition: socket.h:1308
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:230
An Inet6 address class.
void SetRetxThresh(uint32_t retxThresh)
Set the retransmission threshold (dup ack threshold for a fast retransmit)
virtual void SetTcpNoDelay(bool noDelay)
Enable/Disable Nagle&#39;s algorithm.
Ptr< TcpRecoveryOps > m_recoveryOps
Recovery Algorithm.
RttHistory(SequenceNumber32 s, uint32_t c, Time t)
Constructor - builds an RttHistory with the given parameters.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
void NotifyPacingPerformed(void)
Notify Pacing.
EcnMode_t m_ecnMode
ECN mode.
void UpdateCongState(TcpSocketState::TcpCongState_t oldValue, TcpSocketState::TcpCongState_t newValue)
Callback function to hook to TcpSocketState congestion state.
virtual void SkbDelivered(TcpTxItem *skb)=0
Update the Rate information after an item is received.
SequenceNumber32 m_lastAckedSeq
Last sequence ACKed.
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:285
ECN is enabled but currently there is no action pertaining to ECE or CWR to be taken.
virtual uint32_t GetRxAvailable(void) const
Return number of bytes which can be returned from one or multiple calls to Recv.
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:511
friend Ptr< T > CopyObject(Ptr< T > object)
Copy an Object.
Definition: object.h:541
UseEcn_t m_useEcn
Socket ECN capability.
A base class for implementation of a stream socket using TCP.
Ptr< RttEstimator > m_rtt
Round trip time estimator.
bool m_closeNotified
Told app to close socket.
void ProcessSynSent(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon SYN_SENT.
static uint32_t SafeSubtraction(uint32_t a, uint32_t b)
Performs a safe subtraction between a and b (a-b)
int SetupCallback(void)
Common part of the two Bind(), i.e.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
TracedValue< uint32_t > m_bytesInFlight
Bytes in flight.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
virtual void SetTcp(Ptr< TcpL4Protocol > tcp)
Set the associated TCP L4 protocol.
bool m_isFirstPartialAck
First partial ACK during RECOVERY.
Ptr< TcpL4Protocol > m_tcp
the associated TCP L4 protocol
void SetHopLimit(uint8_t hopLimit)
Set the tag&#39;s Hop Limit.
Definition: socket.cc:665
void SetRecoveryAlgorithm(Ptr< TcpRecoveryOps > recovery)
Install a recovery algorithm on this socket.
TracedValue< uint32_t > m_ssThresh
Slow start threshold.
void ProcessSynRcvd(Ptr< Packet > packet, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Received a packet upon SYN_RCVD.
Ptr< TcpTxBuffer > GetTxBuffer(void) const
Get a pointer to the Tx buffer.
uint32_t GetRWnd(void) const
Get the current value of the receiver&#39;s offered window (RCV.WND)
virtual int ShutdownSend(void)
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:95
void NotifyConnectionSucceeded(void)
Notify through the callback (if set) that the connection has been established.
Definition: socket.cc:217
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:113
uint32_t m_retxThresh
Fast Retransmit threshold.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
TcpCongState_t
Definition of the Congestion state machine.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void SetPaceInitialWindow(bool paceWindow)
Enable or disable pacing of the initial window.
virtual void SetDelAckMaxCount(uint32_t count)
Set the number of packet to fire an ACK before delay timeout.
void NotifyNormalClose(void)
Notify through the callback (if set) that the connection has been closed.
Definition: socket.cc:237
virtual uint32_t GetTxAvailable(void) const
Returns the number of bytes which can be sent in a single call to Send.
int DoConnect(void)
Perform the real connection tasks: Send SYN if allowed, RST if invalid.
virtual void CompleteFork(Ptr< Packet > p, const TcpHeader &tcpHeader, const Address &fromAddress, const Address &toAddress)
Complete a connection by forking the socket.
Ptr< const TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:495
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:293
void AddOptions(TcpHeader &tcpHeader)
Add options to TcpHeader.
ECN functionality as described in RFC 8257.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
void UpdateNextTxSequence(SequenceNumber32 oldValue, SequenceNumber32 newValue)
Callback function to hook to TcpSocketState next tx sequence.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t m_dupAckCount
Dupack counter.
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
void UpdateRtt(Time oldValue, Time newValue)
Callback function to hook to TcpSocketState rtt.
Ptr< Node > m_node
the associated node
Hold objects of type Ptr<T>.
Definition: pointer.h:36
virtual uint32_t AvailableWindow(void) const
Return unfilled portion of window.
address
Definition: first.py:44
Generic "sequence number" class.
void NotifyNewConnectionCreated(Ptr< Socket > socket, const Address &from)
Notify through the callback (if set) that a new connection has been created.
Definition: socket.cc:275
TracedValue< TcpCongState_t > m_congState
State in the Congestion state machine.
void TimeWait(void)
Move from CLOSING or FIN_WAIT_2 to TIME_WAIT state.
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:371
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
virtual void SetNode(Ptr< Node > node)
Set the associated node.
virtual uint32_t GetDataRetries(void) const
Get the number of data transmission retries before giving up.
EcnType GetEcn(void) const
Definition: ipv6-header.cc:262
TracedCallback< uint32_t, uint32_t > m_bytesInFlightTrace
Callback pointer for bytesInFlight trace chaining.
uint32_t ProcessOptionSack(const Ptr< const TcpOption > option)
Read the SACK option.
void AddOptionSackPermitted(TcpHeader &header)
Add the SACK PERMITTED option to the header.
uint16_t GetPort(void) const
void SetIcmpCallback(Callback< void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t > callback)
Set the ICMP callback.
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
bool m_recoverActive
Whether "m_recover" has been set/activated It is used to avoid comparing with the old m_recover value...
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1355
void Destroy(void)
Kill this socket by zeroing its attributes (IPv4)
Timeout to catch resent junk before entering closed, can only be entered from FIN_WAIT2 or CLOSING...
Definition: tcp-socket.h:83
SequenceNumber32 GetHighRxAck(void) const
Get the current value of the receiver&#39;s highest (in-sequence) sequence number acked.
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
void EnterCwr(uint32_t currentDelivered)
Enter CA_CWR state upon receipt of an ECN Echo.
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:161
virtual int Close(void)
Close a socket.
void UpdateCwndInfl(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState inflated congestion window.
TracedValue< SequenceNumber32 > m_ecnCWRSeq
Sequence number of the last sent CWR.
static Ipv4Address GetZero(void)
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: nstime.h:1354
Our side has shutdown after remote has shutdown.
Definition: tcp-socket.h:75
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer information (address and port).
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:121
Remote side has shutdown and is waiting for us to finish writing our data and to shutdown (we have to...
Definition: tcp-socket.h:72
Sent a connection request, waiting for ack.
Definition: tcp-socket.h:68
virtual void SetRtt(Ptr< RttEstimator > rtt)
Set the associated RTT estimator.
virtual TypeId GetInstanceTypeId() const
Get the instance TypeId.
double m_msl
Max segment lifetime.
virtual void ReTxTimeout(void)
An RTO event happened.
static uint32_t NowToTsValue()
Return an uint32_t value which represent "now".
Time m_minRto
minimum value of the Retransmit timeout
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:330
virtual void SendEmptyPacket(uint8_t flags)
Send a empty packet that carries a flag, e.g., ACK.
Time m_delAckTimeout
Time to delay an ACK.
virtual int GetPeerName(Address &address) const
Get the peer address of a connected socket.
TracedValue< uint32_t > m_cWnd
Congestion window.
Socket is finished.
Definition: tcp-socket.h:66
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call) ...
Definition: socket.cc:114
Listening for a connection.
Definition: tcp-socket.h:67
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:495
uint64_t m_delivered
The total amount of data in bytes delivered so far.
Definition: tcp-rate-ops.h:164
bool IsRunning(void) const
Definition: timer.cc:127
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
void SetLocalAddress(Ipv4Address address)
Set the local address.
virtual void SetSndBufSize(uint32_t size)
Set the send buffer size.
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:383
static Time FromDouble(double value, enum Unit unit)
Create a Time equal to value in unit unit.
Definition: nstime.h:481
virtual void SetDelAckTimeout(Time timeout)
Set the time to delay an ACK.
EcnCodePoint_t m_ectCodePoint
ECT code point to use.
void DeallocateEndPoint(void)
Deallocate m_endPoint and m_endPoint6.
Describes an IPv6 address.
Definition: ipv6-address.h:49
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
Sender has reduced the congestion window, and sent a packet with CWR bit set in TCP header...
void ProcessEstablished(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon ESTABLISHED state.
virtual const TcpRateConnection & GetConnectionRate()=0
void ProcessOptionWScale(const Ptr< const TcpOption > option)
Read and parse the Window scale option.
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:1077
bool m_connected
Connection established.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
uint16_t m_pacingSsRatio
SS pacing ratio.
TracedValue< Time > m_rto
Retransmit timeout.
Helper class to store RTT measurements.
Ptr< Packet > GetPacketCopy(void) const
Get a copy of the Packet underlying this item.
Definition: tcp-tx-item.cc:80
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
uint16_t GetLocalPort(void)
Get the local port.
uint8_t m_rcvWindShift
Window shift to apply to outgoing segments.
virtual uint16_t AdvertisedWindowSize(bool scale=true) const
The amount of Rx window announced to the peer.
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:545
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
TracedValue< Time > m_lastRtt
Last RTT sample collected.
Ipv6Address GetPeerAddress()
Get the peer address.
int DoClose(void)
Close a socket by sending RST, FIN, or FIN+ACK, depend on the current state.
SequenceNumber32 seq
First sequence number in packet sent.
Our side has shutdown, waiting to complete transmission of remaining buffered data.
Definition: tcp-socket.h:78
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
CWND was reduced due to RTO timeout or SACK reneging.
virtual uint8_t GetKind(void) const =0
Get the ‘kind’ (as in RFC 793) of this option.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
void DupAck(uint32_t currentDelivered)
Dupack management.
T Get(void) const
Get the underlying value.
Definition: traced-value.h:229
TracedValue< SequenceNumber32 > m_ecnEchoSeq
Sequence number of the last received ECN Echo.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
void Cancel(void)
Cancel the currently-running event if there is one.
Definition: timer.cc:109
bool m_sackEnabled
RFC SACK option enabled.
Time m_minRtt
Minimum RTT observed throughout the connection.
uint16_t m_pacingCaRatio
CA pacing ratio.
Ipv4Address GetPeerAddress(void)
Get the peer address.
Enable only when the peer endpoint is ECN capable.
uint32_t m_timestampToEcho
Timestamp to echo.
uint32_t m_synCount
Count of remaining connection retries.
void UpdatePacingRateTrace(DataRate oldValue, DataRate newValue)
Callback function to hook to TcpSocketState pacing rate.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void AddOptionSack(TcpHeader &header)
Add the SACK option to the header.
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv6Header, uint16_t, Ptr< Ipv6Interface > > callback)
Set the reception callback.
virtual const TcpRateSample & GenerateSample(uint32_t delivered, uint32_t lost, bool is_sack_reneg, uint32_t priorInFlight, const Time &minRtt)=0
Generate a TcpRateSample to feed a congestion avoidance algorithm.
static bool IsMatchingType(const Address &addr)
If the address match.
uint16_t GetPeerPort(void)
Get the peer port.
TracedValue< SequenceNumber32 > m_highRxMark
Highest seqno received.
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:161
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
TracedValue< SequenceNumber32 > m_highTxMark
Highest seqno ever sent, regardless of ReTx.
void ProcessLastAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon LAST_ACK.
TracedCallback< Time, Time > m_lastRttTrace
Callback pointer for RTT trace chaining.
void UpdateSsThresh(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState slow start threshold.
first transmit when no packets in flight
virtual void SetSegSize(uint32_t size)
Set the segment size.
void ProcessClosing(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon CLOSING.
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
Time GetClockGranularity(void) const
Get the Clock Granularity (used in RTO calcs).
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:463
Received a connection request, sent ack, waiting for final ack in three-way handshake.
Definition: tcp-socket.h:69
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
second
Definition: nstime.h:115
virtual uint32_t GetInitialCwnd(void) const
Get the initial Congestion Window.
virtual void ReceivedData(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Recv of a data, put into buffer, call L7 to get it if necessary.
void SetConnectCallback(Callback< void, Ptr< Socket > > connectionSucceeded, Callback< void, Ptr< Socket > > connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:84
void CloseAndNotify(void)
Peacefully close the socket by notifying the upper layer and deallocate end point.
Callback< void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t > m_icmpCallback6
ICMPv6 callback.
virtual void SetRcvBufSize(uint32_t size)
Set the receive buffer size.
virtual Ptr< Node > GetNode(void) const
Return the node this socket is associated with.
bool m_shutdownRecv
Receive no longer allowed.
TracedCallback< uint32_t, uint32_t > m_ssThTrace
Callback pointer for ssTh trace chaining.
EventId m_sendPendingDataEvent
micro-delay event to send pending data
bool IsValidTcpSegment(const SequenceNumber32 seq, const uint32_t tcpHeaderSize, const uint32_t tcpPayloadSize)
Checks whether the given TCP segment is valid or not.
uint16_t GetPort(void) const
Get the port.
uint32_t SendPendingData(bool withAck=false)
Send as much pending data as possible according to the Tx window.
DataRate m_maxPacingRate
Max Pacing rate.
virtual void DelAckTimeout(void)
Action upon delay ACK timeout, i.e.
Ipv4Address GetSource(void) const
Definition: ipv4-route.cc:56
virtual void LastAckTimeout(void)
Timeout at LAST_ACK, close the connection.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
uint8_t CalculateWScale() const
Calculate window scale value based on receive buffer space.
void SetPriority(uint8_t priority)
Set the tag&#39;s priority.
Definition: socket.cc:842
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
uint32_t m_bytesAckedNotProcessed
Bytes acked, but not processed.
bool IsExpired(void) const
Definition: timer.cc:121
virtual int Bind6(void)
Allocate a local IPv6 endpoint for this socket.
TracedCallback< SequenceNumber32, SequenceNumber32 > m_nextTxSequenceTrace
Callback pointer for next tx sequence chaining.
indicates whether the socket has IP_TOS set.
Definition: socket.h:1262
TracedCallback< uint32_t, uint32_t > m_cWndInflTrace
Callback pointer for cWndInfl trace chaining.
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
bool IsManualIpTtl(void) const
Checks if the socket has a specific IPv4 TTL set.
Definition: socket.cc:377
uint8_t GetIpTos(void) const
Query the value of IP Type of Service of this socket.
Definition: socket.cc:453
void EnterRecovery(uint32_t currentDelivered)
Enter the CA_RECOVERY, and retransmit the head.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
void SetIcmpCallback(Callback< void, Ipv4Address, uint8_t, uint8_t, uint8_t, uint32_t > callback)
Set the ICMP callback.
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
void SetIpTos(uint8_t ipTos)
Manually set IP Type of Service field.
Definition: socket.cc:437
EventId m_delAckEvent
Delayed ACK timeout event.
received CE marked IP packet.
a unique identifier for an interface.
Definition: type-id.h:58
uint8_t m_sndWindShift
Window shift to apply to incoming segments.
bool m_shutdownSend
Send no longer allowed.
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:105
virtual uint32_t UnAckDataCount(void) const
Return count of number of unacked bytes.
virtual Ptr< TcpSocketBase > Fork(void)
Call CopyObject<> to clone me.
EcnType GetEcn(void) const
Definition: ipv4-header.cc:167
int SetupEndpoint6(void)
Configure the endpoint v6 to a local address.
void NotifySend(uint32_t spaceAvailable)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:295
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
Time m_clockGranularity
Clock Granularity used in RTO calcs.
void ForwardIcmp(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Called by the L3 protocol when it received an ICMP packet to pass on to TCP.
TracedValue< uint32_t > m_rWnd
Receiver window (RCV.WND in RFC793)
TracedCallback< Ptr< const Packet >, const TcpHeader &, Ptr< const TcpSocketBase > > m_rxTrace
Trace of received packets.
virtual void DoForwardUp(Ptr< Packet > packet, const Address &fromAddress, const Address &toAddress)
Called by TcpSocketBase::ForwardUp{,6}().
static bool IsMatchingType(const Address &address)
void NotifyErrorClose(void)
Notify through the callback (if set) that the connection has been closed due to an error...
Definition: socket.cc:247
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
void UpdatePacingRate(void)
Dynamically update the pacing rate.
void DoRetransmit(void)
Retransmit the first segment marked as lost, without considering available window nor pacing...
bool m_closeOnEmpty
Close socket upon tx buffer emptied.
TracedCallback< Ptr< const Packet >, const TcpHeader &, Ptr< const TcpSocketBase > > m_txTrace
Trace of transmitted packets.
uint8_t GetPriority(void) const
Query the priority value of this socket.
Definition: socket.cc:396
void AddOptionWScale(TcpHeader &header)
Add the window scale option to the header.
virtual void SetConnTimeout(Time timeout)
Set the connection timeout.
EventId m_persistEvent
Persist event: Send 1 byte to probe for a non-zero Rx window.
void SetPeer(Ipv6Address addr, uint16_t port)
Set the peer information (address and port).
Ipv4Address GetIpv4(void) const
int SetupEndpoint(void)
Configure the endpoint to a local address.
virtual void SkbSent(TcpTxItem *skb, bool isStartOfTransmission)=0
Put the rate information inside the sent skb.
TracedCallback< TcpSocketState::TcpCongState_t, TcpSocketState::TcpCongState_t > m_congStateTrace
Callback pointer for congestion state trace chaining.
void Destroy6(void)
Kill this socket by zeroing its attributes (IPv6)
TracedValue< SequenceNumber32 > m_nextTxSequence
Next seqnum to be sent (SND.NXT), ReTx pushes it back.
EcnState_t
Definition of the Ecn state machine.
Time m_persistTimeout
Time between sending 1-byte probes.