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