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