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