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  // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation
1702  // are inside the function ProcessAck
1703  ProcessAck (ackNumber, scoreboardUpdated, oldHeadSequence);
1704 
1705  // If there is any data piggybacked, store it into m_rxBuffer
1706  if (packet->GetSize () > 0)
1707  {
1708  ReceivedData (packet, tcpHeader);
1709  }
1710 
1711  // RFC 6675, Section 5, point (C), try to send more data. NB: (C) is implemented
1712  // inside SendPendingData
1714 }
1715 
1716 void
1717 TcpSocketBase::ProcessAck (const SequenceNumber32 &ackNumber, bool scoreboardUpdated,
1718  const SequenceNumber32 &oldHeadSequence)
1719 {
1720  NS_LOG_FUNCTION (this << ackNumber << scoreboardUpdated);
1721  // RFC 6675, Section 5, 2nd paragraph:
1722  // If the incoming ACK is a cumulative acknowledgment, the TCP MUST
1723  // reset DupAcks to zero.
1724  bool exitedFastRecovery = false;
1725  uint32_t oldDupAckCount = m_dupAckCount; // remember the old value
1726  m_tcb->m_lastAckedSeq = ackNumber; // Update lastAckedSeq
1727 
1728  /* In RFC 5681 the definition of duplicate acknowledgment was strict:
1729  *
1730  * (a) the receiver of the ACK has outstanding data,
1731  * (b) the incoming acknowledgment carries no data,
1732  * (c) the SYN and FIN bits are both off,
1733  * (d) the acknowledgment number is equal to the greatest acknowledgment
1734  * received on the given connection (TCP.UNA from [RFC793]),
1735  * (e) the advertised window in the incoming acknowledgment equals the
1736  * advertised window in the last incoming acknowledgment.
1737  *
1738  * With RFC 6675, this definition has been reduced:
1739  *
1740  * (a) the ACK is carrying a SACK block that identifies previously
1741  * unacknowledged and un-SACKed octets between HighACK (TCP.UNA) and
1742  * HighData (m_highTxMark)
1743  */
1744 
1745  bool isDupack = m_sackEnabled ?
1746  scoreboardUpdated
1747  : ackNumber == oldHeadSequence &&
1748  ackNumber < m_tcb->m_highTxMark;
1749 
1750  NS_LOG_DEBUG ("ACK of " << ackNumber <<
1751  " SND.UNA=" << oldHeadSequence <<
1752  " SND.NXT=" << m_tcb->m_nextTxSequence <<
1753  " in state: " << TcpSocketState::TcpCongStateName[m_tcb->m_congState] <<
1754  " with m_recover: " << m_recover);
1755 
1756  // RFC 6675, Section 5, 3rd paragraph:
1757  // If the incoming ACK is a duplicate acknowledgment per the definition
1758  // in Section 2 (regardless of its status as a cumulative
1759  // acknowledgment), and the TCP is not currently in loss recovery
1760  if (isDupack)
1761  {
1762  // loss recovery check is done inside this function thanks to
1763  // the congestion state machine
1764  DupAck ();
1765  }
1766 
1767  if (ackNumber == oldHeadSequence
1768  && ackNumber == m_tcb->m_highTxMark)
1769  {
1770  // Dupack, but the ACK is precisely equal to the nextTxSequence
1771  return;
1772  }
1773  else if (ackNumber == oldHeadSequence
1774  && ackNumber > m_tcb->m_highTxMark)
1775  {
1776  // ACK of the FIN bit ... nextTxSequence is not updated since we
1777  // don't have anything to transmit
1778  NS_LOG_DEBUG ("Update nextTxSequence manually to " << ackNumber);
1779  m_tcb->m_nextTxSequence = ackNumber;
1780  }
1781  else if (ackNumber == oldHeadSequence)
1782  {
1783  // DupAck. Artificially call PktsAcked: after all, one segment has been ACKed.
1784  m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
1785  }
1786  else if (ackNumber > oldHeadSequence)
1787  {
1788  // Please remember that, with SACK, we can enter here even if we
1789  // received a dupack.
1790  uint32_t bytesAcked = ackNumber - oldHeadSequence;
1791  uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
1792  m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize;
1793 
1795  {
1796  segsAcked += 1;
1798  }
1799 
1800  // Dupack count is reset to eventually fast-retransmit after 3 dupacks.
1801  // Any SACK-ed segment will be cleaned up by DiscardUpTo.
1802  // In the case that we advanced SND.UNA, but the ack contains SACK blocks,
1803  // we do not reset. At the third one we will retransmit.
1804  // If we are already in recovery, this check is useless since dupAcks
1805  // are not considered in this phase. When from Recovery we go back
1806  // to open, then dupAckCount is reset anyway.
1807  if (!isDupack)
1808  {
1809  m_dupAckCount = 0;
1810  }
1811 
1812  // RFC 6675, Section 5, part (B)
1813  // (B) Upon receipt of an ACK that does not cover RecoveryPoint, the
1814  // following actions MUST be taken:
1815  //
1816  // (B.1) Use Update () to record the new SACK information conveyed
1817  // by the incoming ACK.
1818  // (B.2) Use SetPipe () to re-calculate the number of octets still
1819  // in the network.
1820  //
1821  // (B.1) is done at the beginning, while (B.2) is delayed to part (C) while
1822  // trying to transmit with SendPendingData. We are not allowed to exit
1823  // the CA_RECOVERY phase. Just process this partial ack (RFC 5681)
1824  if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1825  {
1826  if (!m_sackEnabled)
1827  {
1828  // Manually set the head as lost, it will be retransmitted.
1829  NS_LOG_INFO ("Partial ACK. Manually setting head as lost");
1830  m_txBuffer->MarkHeadAsLost ();
1831  }
1832  else
1833  {
1834  // We received a partial ACK, if we retransmitted this segment
1835  // probably is better to retransmit it
1836  m_txBuffer->DeleteRetransmittedFlagFromHead ();
1837  }
1838  DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
1839  m_tcb->m_cWndInfl = SafeSubtraction (m_tcb->m_cWndInfl, bytesAcked);
1840  if (segsAcked >= 1)
1841  {
1842  m_recoveryOps->DoRecovery (m_tcb, bytesAcked, m_txBuffer->GetSacked ());
1843  }
1844 
1845  // This partial ACK acknowledge the fact that one segment has been
1846  // previously lost and now successfully received. All others have
1847  // been processed when they come under the form of dupACKs
1848  m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
1849  NewAck (ackNumber, m_isFirstPartialAck);
1850 
1851  if (m_isFirstPartialAck)
1852  {
1853  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
1854  " and this is the first (RTO will be reset);"
1855  " cwnd set to " << m_tcb->m_cWnd <<
1856  " recover seq: " << m_recover <<
1857  " dupAck count: " << m_dupAckCount);
1858  m_isFirstPartialAck = false;
1859  }
1860  else
1861  {
1862  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
1863  " and this is NOT the first (RTO will not be reset)"
1864  " cwnd set to " << m_tcb->m_cWnd <<
1865  " recover seq: " << m_recover <<
1866  " dupAck count: " << m_dupAckCount);
1867  }
1868  }
1869  // From RFC 6675 section 5.1
1870  // In addition, a new recovery phase (as described in Section 5) MUST NOT
1871  // be initiated until HighACK is greater than or equal to the new value
1872  // of RecoveryPoint.
1873  else if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_LOSS)
1874  {
1875  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
1876  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
1877 
1878  NS_LOG_DEBUG (" Cong Control Called, cWnd=" << m_tcb->m_cWnd <<
1879  " ssTh=" << m_tcb->m_ssThresh);
1880  if (!m_sackEnabled)
1881  {
1882  NS_ASSERT_MSG (m_txBuffer->GetSacked () == 0,
1883  "Some segment got dup-acked in CA_LOSS state: " <<
1884  m_txBuffer->GetSacked ());
1885  }
1886  NewAck (ackNumber, true);
1887  }
1888  else
1889  {
1891  {
1892  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
1893  }
1895  {
1896  if (segsAcked >= oldDupAckCount)
1897  {
1898  m_congestionControl->PktsAcked (m_tcb, segsAcked - oldDupAckCount, m_tcb->m_lastRtt);
1899  }
1900 
1901  if (!isDupack)
1902  {
1903  // The network reorder packets. Linux changes the counting lost
1904  // packet algorithm from FACK to NewReno. We simply go back in Open.
1905  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1907  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
1908  ackNumber << " exiting CA_DISORDER -> CA_OPEN");
1909  }
1910  else
1911  {
1912  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
1913  ackNumber << " but still in CA_DISORDER");
1914  }
1915  }
1916  // RFC 6675, Section 5:
1917  // Once a TCP is in the loss recovery phase, the following procedure
1918  // MUST be used for each arriving ACK:
1919  // (A) An incoming cumulative ACK for a sequence number greater than
1920  // RecoveryPoint signals the end of loss recovery, and the loss
1921  // recovery phase MUST be terminated. Any information contained in
1922  // the scoreboard for sequence numbers greater than the new value of
1923  // HighACK SHOULD NOT be cleared when leaving the loss recovery
1924  // phase.
1926  {
1927  m_isFirstPartialAck = true;
1928 
1929  // Recalculate the segs acked, that are from m_recover to ackNumber
1930  // (which are the ones we have not passed to PktsAcked and that
1931  // can increase cWnd)
1932  segsAcked = static_cast<uint32_t>(ackNumber - m_recover) / m_tcb->m_segmentSize;
1933  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
1935  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1937  exitedFastRecovery = true;
1938  m_dupAckCount = 0; // From recovery to open, reset dupack
1939 
1940  NS_LOG_DEBUG (segsAcked << " segments acked in CA_RECOVER, ack of " <<
1941  ackNumber << ", exiting CA_RECOVERY -> CA_OPEN");
1942  }
1944  {
1945  m_isFirstPartialAck = true;
1946 
1947  // Recalculate the segs acked, that are from m_recover to ackNumber
1948  // (which are the ones we have not passed to PktsAcked and that
1949  // can increase cWnd)
1950  segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
1951 
1952  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
1953 
1954  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1956  NS_LOG_DEBUG (segsAcked << " segments acked in CA_LOSS, ack of" <<
1957  ackNumber << ", exiting CA_LOSS -> CA_OPEN");
1958  }
1959 
1960  if (exitedFastRecovery)
1961  {
1962  NewAck (ackNumber, true);
1963  m_recoveryOps->ExitRecovery (m_tcb);
1964  NS_LOG_DEBUG ("Leaving Fast Recovery; BytesInFlight() = " <<
1965  BytesInFlight () << "; cWnd = " << m_tcb->m_cWnd);
1966  }
1967  else
1968  {
1969  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
1970 
1972 
1973  NS_LOG_LOGIC ("Congestion control called: " <<
1974  " cWnd: " << m_tcb->m_cWnd <<
1975  " ssTh: " << m_tcb->m_ssThresh <<
1976  " segsAcked: " << segsAcked);
1977 
1978  NewAck (ackNumber, true);
1979  }
1980  }
1981  }
1982 }
1983 
1984 /* Received a packet upon LISTEN state. */
1985 void
1987  const Address& fromAddress, const Address& toAddress)
1988 {
1989  NS_LOG_FUNCTION (this << tcpHeader);
1990 
1991  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
1992  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
1993 
1994  // Fork a socket if received a SYN. Do nothing otherwise.
1995  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
1996  if (tcpflags != TcpHeader::SYN)
1997  {
1998  return;
1999  }
2000 
2001  // Call socket's notify function to let the server app know we got a SYN
2002  // If the server app refuses the connection, do nothing
2003  if (!NotifyConnectionRequest (fromAddress))
2004  {
2005  return;
2006  }
2007  // Clone the socket, simulate fork
2008  Ptr<TcpSocketBase> newSock = Fork ();
2009  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
2011  packet, tcpHeader, fromAddress, toAddress);
2012 }
2013 
2014 /* Received a packet upon SYN_SENT */
2015 void
2017 {
2018  NS_LOG_FUNCTION (this << tcpHeader);
2019 
2020  // Extract the flags. PSH and URG are disregarded.
2021  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2022 
2023  if (tcpflags == 0)
2024  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
2025  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2026  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2027  m_state = ESTABLISHED;
2028  m_connected = true;
2029  m_retxEvent.Cancel ();
2031  ReceivedData (packet, tcpHeader);
2033  }
2034  else if (tcpflags & TcpHeader::ACK && !(tcpflags & TcpHeader::SYN))
2035  { // Ignore ACK in SYN_SENT
2036  }
2037  else if (tcpflags & TcpHeader::SYN && !(tcpflags & TcpHeader::ACK))
2038  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
2039  NS_LOG_DEBUG ("SYN_SENT -> SYN_RCVD");
2040  m_state = SYN_RCVD;
2042  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2043  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if the traffic is ECN capable and
2044  * sender has sent ECN SYN packet
2045  */
2046  if (m_ecnMode == EcnMode_t::ClassicEcn && (tcpflags & (TcpHeader::CWR | TcpHeader::ECE)) == (TcpHeader::CWR | TcpHeader::ECE))
2047  {
2048  NS_LOG_INFO ("Received ECN SYN packet");
2052  }
2053  else
2054  {
2057  }
2058  }
2059  else if (tcpflags & (TcpHeader::SYN | TcpHeader::ACK)
2060  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
2061  { // Handshake completed
2062  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2063  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2064  m_state = ESTABLISHED;
2065  m_connected = true;
2066  m_retxEvent.Cancel ();
2067  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2069  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2071 
2072  /* 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
2073  * packet and the traffic is ECN Capable
2074  */
2075  if (m_ecnMode == EcnMode_t::ClassicEcn && (tcpflags & (TcpHeader::CWR | TcpHeader::ECE)) == (TcpHeader::ECE))
2076  {
2077  NS_LOG_INFO ("Received ECN SYN-ACK packet.");
2080  }
2081  else
2082  {
2084  }
2087  // Always respond to first data packet to speed up the connection.
2088  // Remove to get the behaviour of old NS-3 code.
2090  }
2091  else
2092  { // Other in-sequence input
2093  if (!(tcpflags & TcpHeader::RST))
2094  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
2095  NS_LOG_LOGIC ("Illegal flag combination " << TcpHeader::FlagsToString (tcpHeader.GetFlags ()) <<
2096  " received in SYN_SENT. Reset packet is sent.");
2097  SendRST ();
2098  }
2099  CloseAndNotify ();
2100  }
2101 }
2102 
2103 /* Received a packet upon SYN_RCVD */
2104 void
2106  const Address& fromAddress, const Address& toAddress)
2107 {
2108  NS_UNUSED (toAddress);
2109  NS_LOG_FUNCTION (this << tcpHeader);
2110 
2111  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2112  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2113 
2114  if (tcpflags == 0
2115  || (tcpflags == TcpHeader::ACK
2116  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
2117  { // If it is bare data, accept it and move to ESTABLISHED state. This is
2118  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
2119  // handshake is completed nicely.
2120  NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED");
2121  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2122  m_state = ESTABLISHED;
2123  m_connected = true;
2124  m_retxEvent.Cancel ();
2126  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2127  if (m_endPoint)
2128  {
2129  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2130  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2131  }
2132  else if (m_endPoint6)
2133  {
2134  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2135  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2136  }
2137  // Always respond to first data packet to speed up the connection.
2138  // Remove to get the behaviour of old NS-3 code.
2140  NotifyNewConnectionCreated (this, fromAddress);
2141  ReceivedAck (packet, tcpHeader);
2142  // As this connection is established, the socket is available to send data now
2143  if (GetTxAvailable () > 0)
2144  {
2146  }
2147  }
2148  else if (tcpflags == TcpHeader::SYN)
2149  { // Probably the peer lost my SYN+ACK
2150  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2151  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2152  * packet and the traffic is ECN Capable
2153  */
2154  if (m_ecnMode == EcnMode_t::ClassicEcn && (tcpHeader.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) == (TcpHeader::CWR | TcpHeader::ECE))
2155  {
2156  NS_LOG_INFO ("Received ECN SYN packet");
2160  }
2161  else
2162  {
2165  }
2166  }
2167  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2168  {
2169  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
2170  { // In-sequence FIN before connection complete. Set up connection and close.
2171  m_connected = true;
2172  m_retxEvent.Cancel ();
2174  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2175  if (m_endPoint)
2176  {
2177  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2178  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2179  }
2180  else if (m_endPoint6)
2181  {
2182  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2183  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2184  }
2185  NotifyNewConnectionCreated (this, fromAddress);
2186  PeerClose (packet, tcpHeader);
2187  }
2188  }
2189  else
2190  { // Other in-sequence input
2191  if (tcpflags != TcpHeader::RST)
2192  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
2193  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2194  " received. Reset packet is sent.");
2195  if (m_endPoint)
2196  {
2197  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2198  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2199  }
2200  else if (m_endPoint6)
2201  {
2202  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2203  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2204  }
2205  SendRST ();
2206  }
2207  CloseAndNotify ();
2208  }
2209 }
2210 
2211 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
2212 void
2214 {
2215  NS_LOG_FUNCTION (this << tcpHeader);
2216 
2217  // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2218  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2219 
2220  if (packet->GetSize () > 0 && !(tcpflags & TcpHeader::ACK))
2221  { // Bare data, accept it
2222  ReceivedData (packet, tcpHeader);
2223  }
2224  else if (tcpflags == TcpHeader::ACK)
2225  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
2226  ReceivedAck (packet, tcpHeader);
2227  if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
2228  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2229  { // This ACK corresponds to the FIN sent
2230  NS_LOG_DEBUG ("FIN_WAIT_1 -> FIN_WAIT_2");
2231  m_state = FIN_WAIT_2;
2232  }
2233  }
2234  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2235  { // Got FIN, respond with ACK and move to next state
2236  if (tcpflags & TcpHeader::ACK)
2237  { // Process the ACK first
2238  ReceivedAck (packet, tcpHeader);
2239  }
2240  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
2241  }
2242  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
2243  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
2244  return;
2245  }
2246  else
2247  { // This is a RST or bad flags
2248  if (tcpflags != TcpHeader::RST)
2249  {
2250  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2251  " received. Reset packet is sent.");
2252  SendRST ();
2253  }
2254  CloseAndNotify ();
2255  return;
2256  }
2257 
2258  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
2259  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_rxBuffer->Finished ())
2260  {
2261  if (m_state == FIN_WAIT_1)
2262  {
2263  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2264  m_state = CLOSING;
2265  if (m_txBuffer->Size () == 0
2266  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2267  { // This ACK corresponds to the FIN sent
2268  TimeWait ();
2269  }
2270  }
2271  else if (m_state == FIN_WAIT_2)
2272  {
2273  TimeWait ();
2274  }
2276  if (!m_shutdownRecv)
2277  {
2278  NotifyDataRecv ();
2279  }
2280  }
2281 }
2282 
2283 /* Received a packet upon CLOSING */
2284 void
2286 {
2287  NS_LOG_FUNCTION (this << tcpHeader);
2288 
2289  // Extract the flags. PSH and URG are disregarded.
2290  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2291 
2292  if (tcpflags == TcpHeader::ACK)
2293  {
2294  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
2295  { // This ACK corresponds to the FIN sent
2296  TimeWait ();
2297  }
2298  }
2299  else
2300  { // CLOSING state means simultaneous close, i.e. no one is sending data to
2301  // anyone. If anything other than ACK is received, respond with a reset.
2302  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2303  { // FIN from the peer as well. We can close immediately.
2305  }
2306  else if (tcpflags != TcpHeader::RST)
2307  { // Receive of SYN or SYN+ACK or bad flags or pure data
2308  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2309  SendRST ();
2310  }
2311  CloseAndNotify ();
2312  }
2313 }
2314 
2315 /* Received a packet upon LAST_ACK */
2316 void
2318 {
2319  NS_LOG_FUNCTION (this << tcpHeader);
2320 
2321  // Extract the flags. PSH and URG are disregarded.
2322  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2323 
2324  if (tcpflags == 0)
2325  {
2326  ReceivedData (packet, tcpHeader);
2327  }
2328  else if (tcpflags == TcpHeader::ACK)
2329  {
2330  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
2331  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
2332  CloseAndNotify ();
2333  }
2334  }
2335  else if (tcpflags == TcpHeader::FIN)
2336  { // Received FIN again, the peer probably lost the FIN+ACK
2338  }
2339  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2340  {
2341  CloseAndNotify ();
2342  }
2343  else
2344  { // Received a SYN or SYN+ACK or bad flags
2345  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2346  SendRST ();
2347  CloseAndNotify ();
2348  }
2349 }
2350 
2351 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
2352 void
2354 {
2355  NS_LOG_FUNCTION (this << tcpHeader);
2356 
2357  // Ignore all out of range packets
2358  if (tcpHeader.GetSequenceNumber () < m_rxBuffer->NextRxSequence ()
2359  || tcpHeader.GetSequenceNumber () > m_rxBuffer->MaxRxSequence ())
2360  {
2361  return;
2362  }
2363  // For any case, remember the FIN position in rx buffer first
2364  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2365  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2366  // If there is any piggybacked data, process it
2367  if (p->GetSize ())
2368  {
2369  ReceivedData (p, tcpHeader);
2370  }
2371  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2372  if (!m_rxBuffer->Finished ())
2373  {
2374  return;
2375  }
2376 
2377  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2378  if (m_state == FIN_WAIT_1)
2379  {
2380  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2381  m_state = CLOSING;
2382  return;
2383  }
2384 
2385  DoPeerClose (); // Change state, respond with ACK
2386 }
2387 
2388 /* Received a in-sequence FIN. Close down this socket. */
2389 void
2391 {
2394 
2395  // Move the state to CLOSE_WAIT
2396  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSE_WAIT");
2397  m_state = CLOSE_WAIT;
2398 
2399  if (!m_closeNotified)
2400  {
2401  // The normal behaviour for an application is that, when the peer sent a in-sequence
2402  // FIN, the app should prepare to close. The app has two choices at this point: either
2403  // respond with ShutdownSend() call to declare that it has nothing more to send and
2404  // the socket can be closed immediately; or remember the peer's close request, wait
2405  // until all its existing data are pushed into the TCP socket, then call Close()
2406  // explicitly.
2407  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
2408  NotifyNormalClose ();
2409  m_closeNotified = true;
2410  }
2411  if (m_shutdownSend)
2412  { // The application declares that it would not sent any more, close this socket
2413  Close ();
2414  }
2415  else
2416  { // Need to ack, the application will close later
2418  }
2419  if (m_state == LAST_ACK)
2420  {
2421  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
2422  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
2424  }
2425 }
2426 
2427 /* Kill this socket. This is a callback function configured to m_endpoint in
2428  SetupCallback(), invoked when the endpoint is destroyed. */
2429 void
2431 {
2432  NS_LOG_FUNCTION (this);
2433  m_endPoint = nullptr;
2434  if (m_tcp != nullptr)
2435  {
2436  m_tcp->RemoveSocket (this);
2437  }
2438  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2439  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2440  CancelAllTimers ();
2441 }
2442 
2443 /* Kill this socket. This is a callback function configured to m_endpoint in
2444  SetupCallback(), invoked when the endpoint is destroyed. */
2445 void
2447 {
2448  NS_LOG_FUNCTION (this);
2449  m_endPoint6 = nullptr;
2450  if (m_tcp != nullptr)
2451  {
2452  m_tcp->RemoveSocket (this);
2453  }
2454  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2455  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2456  CancelAllTimers ();
2457 }
2458 
2459 /* Send an empty packet with specified TCP flags */
2460 void
2462 {
2463  NS_LOG_FUNCTION (this << static_cast<uint32_t> (flags));
2464 
2465  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
2466  {
2467  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
2468  return;
2469  }
2470 
2471  Ptr<Packet> p = Create<Packet> ();
2472  TcpHeader header;
2474 
2475  if (flags & TcpHeader::FIN)
2476  {
2477  flags |= TcpHeader::ACK;
2478  }
2479  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2480  {
2481  ++s;
2482  }
2483 
2484  AddSocketTags (p);
2485 
2486  header.SetFlags (flags);
2487  header.SetSequenceNumber (s);
2488  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2489  if (m_endPoint != nullptr)
2490  {
2491  header.SetSourcePort (m_endPoint->GetLocalPort ());
2492  header.SetDestinationPort (m_endPoint->GetPeerPort ());
2493  }
2494  else
2495  {
2496  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2497  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
2498  }
2499  AddOptions (header);
2500 
2501  // RFC 6298, clause 2.4
2502  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2503 
2504  uint16_t windowSize = AdvertisedWindowSize ();
2505  bool hasSyn = flags & TcpHeader::SYN;
2506  bool hasFin = flags & TcpHeader::FIN;
2507  bool isAck = flags == TcpHeader::ACK;
2508  if (hasSyn)
2509  {
2510  if (m_winScalingEnabled)
2511  { // The window scaling option is set only on SYN packets
2512  AddOptionWScale (header);
2513  }
2514 
2515  if (m_sackEnabled)
2516  {
2517  AddOptionSackPermitted (header);
2518  }
2519 
2520  if (m_synCount == 0)
2521  { // No more connection retries, give up
2522  NS_LOG_LOGIC ("Connection failed.");
2523  m_rtt->Reset (); //According to recommendation -> RFC 6298
2524  CloseAndNotify ();
2525  return;
2526  }
2527  else
2528  { // Exponential backoff of connection time out
2529  int backoffCount = 0x1 << (m_synRetries - m_synCount);
2530  m_rto = m_cnTimeout * backoffCount;
2531  m_synCount--;
2532  }
2533 
2534  if (m_synRetries - 1 == m_synCount)
2535  {
2536  UpdateRttHistory (s, 0, false);
2537  }
2538  else
2539  { // This is SYN retransmission
2540  UpdateRttHistory (s, 0, true);
2541  }
2542 
2543  windowSize = AdvertisedWindowSize (false);
2544  }
2545  header.SetWindowSize (windowSize);
2546 
2547  if (flags & TcpHeader::ACK)
2548  { // If sending an ACK, cancel the delay ACK as well
2549  m_delAckEvent.Cancel ();
2550  m_delAckCount = 0;
2551  if (m_highTxAck < header.GetAckNumber ())
2552  {
2553  m_highTxAck = header.GetAckNumber ();
2554  }
2555  if (m_sackEnabled && m_rxBuffer->GetSackListSize () > 0)
2556  {
2557  AddOptionSack (header);
2558  }
2559  NS_LOG_INFO ("Sending a pure ACK, acking seq " << m_rxBuffer->NextRxSequence ());
2560  }
2561 
2562  m_txTrace (p, header, this);
2563 
2564  if (m_endPoint != nullptr)
2565  {
2566  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2568  }
2569  else
2570  {
2571  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2573  }
2574 
2575 
2576  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
2577  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2578  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
2579  << Simulator::Now ().GetSeconds () << " to expire at time "
2580  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2582  }
2583 }
2584 
2585 /* This function closes the endpoint completely. Called upon RST_TX action. */
2586 void
2588 {
2589  NS_LOG_FUNCTION (this);
2591  NotifyErrorClose ();
2592  DeallocateEndPoint ();
2593 }
2594 
2595 /* Deallocate the end point and cancel all the timers */
2596 void
2598 {
2599  if (m_endPoint != nullptr)
2600  {
2601  CancelAllTimers ();
2602  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
2603  m_tcp->DeAllocate (m_endPoint);
2604  m_endPoint = nullptr;
2605  m_tcp->RemoveSocket (this);
2606  }
2607  else if (m_endPoint6 != nullptr)
2608  {
2609  CancelAllTimers ();
2610  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
2611  m_tcp->DeAllocate (m_endPoint6);
2612  m_endPoint6 = nullptr;
2613  m_tcp->RemoveSocket (this);
2614  }
2615 }
2616 
2617 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2618 int
2620 {
2621  NS_LOG_FUNCTION (this);
2622  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
2623  NS_ASSERT (ipv4 != nullptr);
2624  if (ipv4->GetRoutingProtocol () == nullptr)
2625  {
2626  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
2627  }
2628  // Create a dummy packet, then ask the routing function for the best output
2629  // interface's address
2630  Ipv4Header header;
2632  Socket::SocketErrno errno_;
2633  Ptr<Ipv4Route> route;
2635  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2636  if (route == 0)
2637  {
2638  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
2639  NS_LOG_ERROR (errno_);
2640  m_errno = errno_;
2641  return -1;
2642  }
2643  NS_LOG_LOGIC ("Route exists");
2644  m_endPoint->SetLocalAddress (route->GetSource ());
2645  return 0;
2646 }
2647 
2648 int
2650 {
2651  NS_LOG_FUNCTION (this);
2653  NS_ASSERT (ipv6 != nullptr);
2654  if (ipv6->GetRoutingProtocol () == nullptr)
2655  {
2656  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
2657  }
2658  // Create a dummy packet, then ask the routing function for the best output
2659  // interface's address
2660  Ipv6Header header;
2662  Socket::SocketErrno errno_;
2663  Ptr<Ipv6Route> route;
2665  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2666  if (route == nullptr)
2667  {
2668  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
2669  NS_LOG_ERROR (errno_);
2670  m_errno = errno_;
2671  return -1;
2672  }
2673  NS_LOG_LOGIC ("Route exists");
2674  m_endPoint6->SetLocalAddress (route->GetSource ());
2675  return 0;
2676 }
2677 
2678 /* This function is called only if a SYN received in LISTEN state. After
2679  TcpSocketBase cloned, allocate a new end point to handle the incoming
2680  connection and send a SYN+ACK to complete the handshake. */
2681 void
2683  const Address& fromAddress, const Address& toAddress)
2684 {
2685  NS_LOG_FUNCTION (this << p << h << fromAddress << toAddress);
2686  NS_UNUSED (p);
2687  // Get port and address from peer (connecting host)
2688  if (InetSocketAddress::IsMatchingType (toAddress))
2689  {
2690  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (),
2691  InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
2692  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
2693  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2694  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2695  m_endPoint6 = nullptr;
2696  }
2697  else if (Inet6SocketAddress::IsMatchingType (toAddress))
2698  {
2699  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (),
2700  Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
2701  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
2702  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2703  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2704  m_endPoint = nullptr;
2705  }
2706  m_tcp->AddSocket (this);
2707 
2708  // Change the cloned socket from LISTEN state to SYN_RCVD
2709  NS_LOG_DEBUG ("LISTEN -> SYN_RCVD");
2710  m_state = SYN_RCVD;
2713  SetupCallback ();
2714  // Set the sequence number and send SYN+ACK
2715  m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
2716 
2717  /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2718  * packet and the traffic is ECN Capable
2719  */
2720  if (m_ecnMode == EcnMode_t::ClassicEcn && (h.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) == (TcpHeader::CWR | TcpHeader::ECE))
2721  {
2725  }
2726  else
2727  {
2730  }
2731 }
2732 
2733 void
2735 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
2736  // be called as a scheduled event
2738  // The if-block below was moved from ProcessSynSent() to here because we need
2739  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
2740  // reflect the behaviour in the real world.
2741  if (GetTxAvailable () > 0)
2742  {
2744  }
2745 }
2746 
2747 void
2749 {
2750  /*
2751  * Add tags for each socket option.
2752  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2753  * if both options are set. Once the packet got to layer three, only
2754  * the corresponding tags will be read.
2755  */
2756  if (GetIpTos ())
2757  {
2758  SocketIpTosTag ipTosTag;
2760  {
2761  // Set ECT(0) if ECN is enabled with the last received ipTos
2762  ipTosTag.SetTos (MarkEcnEct0 (GetIpTos ()));
2763  }
2764  else
2765  {
2766  // Set the last received ipTos
2767  ipTosTag.SetTos (GetIpTos ());
2768  }
2769  p->AddPacketTag (ipTosTag);
2770  }
2771  else
2772  {
2774  {
2775  // Set ECT(0) if ECN is enabled and ipTos is 0
2776  SocketIpTosTag ipTosTag;
2777  ipTosTag.SetTos (MarkEcnEct0 (GetIpTos ()));
2778  p->AddPacketTag (ipTosTag);
2779  }
2780  }
2781 
2782  if (IsManualIpv6Tclass ())
2783  {
2784  SocketIpv6TclassTag ipTclassTag;
2786  {
2787  // Set ECT(0) if ECN is enabled with the last received ipTos
2788  ipTclassTag.SetTclass (MarkEcnEct0 (GetIpv6Tclass ()));
2789  }
2790  else
2791  {
2792  // Set the last received ipTos
2793  ipTclassTag.SetTclass (GetIpv6Tclass ());
2794  }
2795  p->AddPacketTag (ipTclassTag);
2796  }
2797  else
2798  {
2800  {
2801  // Set ECT(0) if ECN is enabled and ipTos is 0
2802  SocketIpv6TclassTag ipTclassTag;
2803  ipTclassTag.SetTclass (MarkEcnEct0 (GetIpv6Tclass ()));
2804  p->AddPacketTag (ipTclassTag);
2805  }
2806  }
2807 
2808  if (IsManualIpTtl ())
2809  {
2810  SocketIpTtlTag ipTtlTag;
2811  ipTtlTag.SetTtl (GetIpTtl ());
2812  p->AddPacketTag (ipTtlTag);
2813  }
2814 
2815  if (IsManualIpv6HopLimit ())
2816  {
2817  SocketIpv6HopLimitTag ipHopLimitTag;
2818  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
2819  p->AddPacketTag (ipHopLimitTag);
2820  }
2821 
2822  uint8_t priority = GetPriority ();
2823  if (priority)
2824  {
2825  SocketPriorityTag priorityTag;
2826  priorityTag.SetPriority (priority);
2827  p->ReplacePacketTag (priorityTag);
2828  }
2829 }
2830 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
2831  TCP header, and send to TcpL4Protocol */
2832 uint32_t
2833 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
2834 {
2835  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
2836 
2837  bool isRetransmission = false;
2838  if (seq != m_tcb->m_highTxMark)
2839  {
2840  isRetransmission = true;
2841  }
2842 
2843  Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq);
2844  uint32_t sz = p->GetSize (); // Size of packet
2845  uint8_t flags = withAck ? TcpHeader::ACK : 0;
2846  uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
2847 
2848  if (m_tcb->m_pacing)
2849  {
2850  NS_LOG_INFO ("Pacing is enabled");
2851  if (m_pacingTimer.IsExpired ())
2852  {
2853  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_currentPacingRate);
2854  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_currentPacingRate.CalculateBytesTxTime (sz));
2856  }
2857  else
2858  {
2859  NS_LOG_INFO ("Timer is already in running state");
2860  }
2861  }
2862 
2863  if (withAck)
2864  {
2865  m_delAckEvent.Cancel ();
2866  m_delAckCount = 0;
2867  }
2868 
2869  // Sender should reduce the Congestion Window as a response to receiver's ECN Echo notification only once per window
2870  if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && m_ecnEchoSeq.Get() > m_ecnCWRSeq.Get () && !isRetransmission)
2871  {
2872  NS_LOG_INFO ("Backoff mechanism by reducing CWND by half because we've received ECN Echo");
2876  flags |= TcpHeader::CWR;
2877  m_ecnCWRSeq = seq;
2878  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_CWR_SENT");
2880  NS_LOG_INFO ("CWR flags set");
2883  {
2884  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_CWR);
2886  }
2887  }
2888 
2889  AddSocketTags (p);
2890 
2891  if (m_closeOnEmpty && (remainingData == 0))
2892  {
2893  flags |= TcpHeader::FIN;
2894  if (m_state == ESTABLISHED)
2895  { // On active close: I am the first one to send FIN
2896  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
2897  m_state = FIN_WAIT_1;
2898  }
2899  else if (m_state == CLOSE_WAIT)
2900  { // On passive close: Peer sent me FIN already
2901  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
2902  m_state = LAST_ACK;
2903  }
2904  }
2905  TcpHeader header;
2906  header.SetFlags (flags);
2907  header.SetSequenceNumber (seq);
2908  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2909  if (m_endPoint)
2910  {
2911  header.SetSourcePort (m_endPoint->GetLocalPort ());
2913  }
2914  else
2915  {
2916  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2918  }
2919  header.SetWindowSize (AdvertisedWindowSize ());
2920  AddOptions (header);
2921 
2922  if (m_retxEvent.IsExpired ())
2923  {
2924  // Schedules retransmit timeout. m_rto should be already doubled.
2925 
2926  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
2927  Simulator::Now ().GetSeconds () << " to expire at time " <<
2928  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
2930  }
2931 
2932  m_txTrace (p, header, this);
2933 
2934  if (m_endPoint)
2935  {
2936  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2938  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
2939  remainingData << " via TcpL4Protocol to " << m_endPoint->GetPeerAddress () <<
2940  ". Header " << header);
2941  }
2942  else
2943  {
2944  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2946  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
2947  remainingData << " via TcpL4Protocol to " << m_endPoint6->GetPeerAddress () <<
2948  ". Header " << header);
2949  }
2950 
2951  UpdateRttHistory (seq, sz, isRetransmission);
2952 
2953  // Update bytes sent during recovery phase
2955  {
2956  m_recoveryOps->UpdateBytesSent (sz);
2957  }
2958 
2959  // Notify the application of the data being sent unless this is a retransmit
2960  if (seq + sz > m_tcb->m_highTxMark)
2961  {
2963  (seq + sz - m_tcb->m_highTxMark.Get ()));
2964  }
2965  // Update highTxMark
2966  m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ());
2967  return sz;
2968 }
2969 
2970 void
2972  bool isRetransmission)
2973 {
2974  NS_LOG_FUNCTION (this);
2975 
2976  // update the history of sequence numbers used to calculate the RTT
2977  if (isRetransmission == false)
2978  { // This is the next expected one, just log at end
2979  m_history.push_back (RttHistory (seq, sz, Simulator::Now ()));
2980  }
2981  else
2982  { // This is a retransmit, find in list and mark as re-tx
2983  for (std::deque<RttHistory>::iterator i = m_history.begin (); i != m_history.end (); ++i)
2984  {
2985  if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
2986  { // Found it
2987  i->retx = true;
2988  i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
2989  break;
2990  }
2991  }
2992  }
2993 }
2994 
2995 // Note that this function did not implement the PSH flag
2996 uint32_t
2998 {
2999  NS_LOG_FUNCTION (this << withAck);
3000  if (m_txBuffer->Size () == 0)
3001  {
3002  return false; // Nothing to send
3003  }
3004  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
3005  {
3006  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
3007  return false; // Is this the right way to handle this condition?
3008  }
3009 
3010  uint32_t nPacketsSent = 0;
3011  uint32_t availableWindow = AvailableWindow ();
3012 
3013  // RFC 6675, Section (C)
3014  // If cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more
3015  // segments as follows:
3016  // (NOTE: We check > 0, and do the checks for segmentSize in the following
3017  // else branch to control silly window syndrome and Nagle)
3018  while (availableWindow > 0)
3019  {
3020  if (m_tcb->m_pacing)
3021  {
3022  NS_LOG_INFO ("Pacing is enabled");
3023  if (m_pacingTimer.IsRunning ())
3024  {
3025  NS_LOG_INFO ("Skipping Packet due to pacing" << m_pacingTimer.GetDelayLeft ());
3026  break;
3027  }
3028  NS_LOG_INFO ("Timer is not running");
3029  }
3030 
3033  {
3034  NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit");
3035  break;
3036  }
3037  // (C.1) The scoreboard MUST be queried via NextSeg () for the
3038  // sequence number range of the next segment to transmit (if
3039  // any), and the given segment sent. If NextSeg () returns
3040  // failure (no data to send), return without sending anything
3041  // (i.e., terminate steps C.1 -- C.5).
3042  SequenceNumber32 next;
3043  bool enableRule3 = m_sackEnabled && m_tcb->m_congState == TcpSocketState::CA_RECOVERY;
3044  if (!m_txBuffer->NextSeg (&next, enableRule3))
3045  {
3046  NS_LOG_INFO ("no valid seq to transmit, or no data available");
3047  break;
3048  }
3049  else
3050  {
3051  // It's time to transmit, but before do silly window and Nagle's check
3052  uint32_t availableData = m_txBuffer->SizeFromSequence (next);
3053 
3054  // If there's less app data than the full window, ask the app for more
3055  // data before trying to send
3056  if (availableData < availableWindow)
3057  {
3059  }
3060 
3061  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
3062  // but continue if we don't have data
3063  if (availableWindow < m_tcb->m_segmentSize && availableData > availableWindow)
3064  {
3065  NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
3066  break; // No more
3067  }
3068  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
3069  // in the buffer and the amount of data to send is less than one segment
3070  if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_segmentSize)
3071  {
3072  NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next <<
3073  ", SFS: " << m_txBuffer->SizeFromSequence (next) <<
3074  ". Wait to send.");
3075  break;
3076  }
3077 
3078  uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize);
3079 
3080  // (C.2) If any of the data octets sent in (C.1) are below HighData,
3081  // HighRxt MUST be set to the highest sequence number of the
3082  // retransmitted segment unless NextSeg () rule (4) was
3083  // invoked for this retransmission.
3084  // (C.3) If any of the data octets sent in (C.1) are above HighData,
3085  // HighData must be updated to reflect the transmission of
3086  // previously unsent data.
3087  //
3088  // These steps are done in m_txBuffer with the tags.
3089  if (m_tcb->m_nextTxSequence != next)
3090  {
3091  m_tcb->m_nextTxSequence = next;
3092  }
3093  if (m_tcb->m_bytesInFlight.Get () == 0)
3094  {
3096  }
3097  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck);
3098  m_tcb->m_nextTxSequence += sz;
3099 
3100  NS_LOG_LOGIC (" rxwin " << m_rWnd <<
3101  " segsize " << m_tcb->m_segmentSize <<
3102  " highestRxAck " << m_txBuffer->HeadSequence () <<
3103  " pd->Size " << m_txBuffer->Size () <<
3104  " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence));
3105 
3106  NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd <<
3107  " total unAck: " << UnAckDataCount () <<
3108  " sent seq " << m_tcb->m_nextTxSequence <<
3109  " size " << sz);
3110  ++nPacketsSent;
3111  if (m_tcb->m_pacing)
3112  {
3113  NS_LOG_INFO ("Pacing is enabled");
3114  if (m_pacingTimer.IsExpired ())
3115  {
3116  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_currentPacingRate);
3117  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_currentPacingRate.CalculateBytesTxTime (sz));
3119  break;
3120  }
3121  }
3122  }
3123 
3124  // (C.4) The estimate of the amount of data outstanding in the
3125  // network must be updated by incrementing pipe by the number
3126  // of octets transmitted in (C.1).
3127  //
3128  // Done in BytesInFlight, inside AvailableWindow.
3129  availableWindow = AvailableWindow ();
3130 
3131  // (C.5) If cwnd - pipe >= 1 SMSS, return to (C.1)
3132  // loop again!
3133  }
3134 
3135  if (nPacketsSent > 0)
3136  {
3137  if (!m_sackEnabled)
3138  {
3139  if (!m_limitedTx)
3140  {
3141  // We can't transmit in CA_DISORDER without limitedTx active
3143  }
3144  }
3145 
3146  NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments");
3147  }
3148  else
3149  {
3150  NS_LOG_DEBUG ("SendPendingData no segments sent");
3151  }
3152  return nPacketsSent;
3153 }
3154 
3155 uint32_t
3157 {
3158  return m_tcb->m_highTxMark - m_txBuffer->HeadSequence ();
3159 }
3160 
3161 uint32_t
3163 {
3164  uint32_t bytesInFlight = m_txBuffer->BytesInFlight ();
3165  // Ugly, but we are not modifying the state; m_bytesInFlight is used
3166  // only for tracing purpose.
3167  m_tcb->m_bytesInFlight = bytesInFlight;
3168 
3169  NS_LOG_DEBUG ("Returning calculated bytesInFlight: " << bytesInFlight);
3170  return bytesInFlight;
3171 }
3172 
3173 uint32_t
3175 {
3176  return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
3177 }
3178 
3179 uint32_t
3181 {
3182  uint32_t win = Window (); // Number of bytes allowed to be outstanding
3183  uint32_t inflight = BytesInFlight (); // Number of outstanding bytes
3184  return (inflight > win) ? 0 : win - inflight;
3185 }
3186 
3187 uint16_t
3189 {
3190  NS_LOG_FUNCTION (this << scale);
3191  uint32_t w;
3192 
3193  // We don't want to advertise 0 after a FIN is received. So, we just use
3194  // the previous value of the advWnd.
3195  if (m_rxBuffer->GotFin ())
3196  {
3197  w = m_advWnd;
3198  }
3199  else
3200  {
3201  NS_ASSERT_MSG (m_rxBuffer->MaxRxSequence () - m_rxBuffer->NextRxSequence () >= 0,
3202  "Unexpected sequence number values");
3203  w = static_cast<uint32_t> (m_rxBuffer->MaxRxSequence () - m_rxBuffer->NextRxSequence ());
3204  }
3205 
3206  // Ugly, but we are not modifying the state, that variable
3207  // is used only for tracing purpose.
3208  if (w != m_advWnd)
3209  {
3210  const_cast<TcpSocketBase*> (this)->m_advWnd = w;
3211  }
3212  if (scale)
3213  {
3214  w >>= m_rcvWindShift;
3215  }
3216  if (w > m_maxWinSize)
3217  {
3218  w = m_maxWinSize;
3219  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
3220  }
3221  NS_LOG_LOGIC ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
3222  return static_cast<uint16_t> (w);
3223 }
3224 
3225 // Receipt of new packet, put into Rx buffer
3226 void
3228 {
3229  NS_LOG_FUNCTION (this << tcpHeader);
3230  NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () <<
3231  " pkt size=" << p->GetSize () );
3232 
3233  // Put into Rx buffer
3234  SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence ();
3235  if (!m_rxBuffer->Add (p, tcpHeader))
3236  { // Insert failed: No data or RX buffer full
3238  {
3240  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3242  }
3243  else
3244  {
3246  }
3247  return;
3248  }
3249  // Notify app to receive if necessary
3250  if (expectedSeq < m_rxBuffer->NextRxSequence ())
3251  { // NextRxSeq advanced, we have something to send to the app
3252  if (!m_shutdownRecv)
3253  {
3254  NotifyDataRecv ();
3255  }
3256  // Handle exceptions
3257  if (m_closeNotified)
3258  {
3259  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
3260  }
3261  // If we received FIN before and now completed all "holes" in rx buffer,
3262  // invoke peer close procedure
3263  if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
3264  {
3265  DoPeerClose ();
3266  return;
3267  }
3268  }
3269  // Now send a new ACK packet acknowledging all received and delivered data
3270  if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
3271  { // A gap exists in the buffer, or we filled a gap: Always ACK
3274  {
3276  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3278  }
3279  else
3280  {
3282  }
3283  }
3284  else
3285  { // In-sequence packet: ACK if delayed ack count allows
3287  {
3288  m_delAckEvent.Cancel ();
3289  m_delAckCount = 0;
3292  {
3293  NS_LOG_DEBUG("Congestion algo " << m_congestionControl->GetName ());
3295  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3297  }
3298  else
3299  {
3301  }
3302  }
3303  else if (m_delAckEvent.IsExpired ())
3304  {
3307  NS_LOG_LOGIC (this << " scheduled delayed ACK at " <<
3308  (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
3309  }
3310  }
3311 }
3312 
3320 void
3322 {
3323  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber ();
3324  Time m = Time (0.0);
3325 
3326  // An ack has been received, calculate rtt and log this measurement
3327  // Note we use a linear search (O(n)) for this since for the common
3328  // case the ack'ed packet will be at the head of the list
3329  if (!m_history.empty ())
3330  {
3331  RttHistory& h = m_history.front ();
3332  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
3333  { // Ok to use this sample
3334  if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
3335  {
3337  ts = DynamicCast<const TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
3338  m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
3339  }
3340  else
3341  {
3342  m = Simulator::Now () - h.time; // Elapsed time
3343  }
3344  }
3345  }
3346 
3347  // Now delete all ack history with seq <= ack
3348  while (!m_history.empty ())
3349  {
3350  RttHistory& h = m_history.front ();
3351  if ((h.seq + SequenceNumber32 (h.count)) > ackSeq)
3352  {
3353  break; // Done removing
3354  }
3355  m_history.pop_front (); // Remove
3356  }
3357 
3358  if (!m.IsZero ())
3359  {
3360  m_rtt->Measurement (m); // Log the measurement
3361  // RFC 6298, clause 2.4
3362  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3363  m_tcb->m_lastRtt = m_rtt->GetEstimate ();
3365  NS_LOG_INFO (this << m_tcb->m_lastRtt << m_tcb->m_minRtt);
3366  }
3367 }
3368 
3369 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
3370 // when the three-way handshake completed. This cancels retransmission timer
3371 // and advances Tx window
3372 void
3373 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO)
3374 {
3375  NS_LOG_FUNCTION (this << ack);
3376 
3377  // Reset the data retransmission count. We got a new ACK!
3379 
3380  if (m_state != SYN_RCVD && resetRTO)
3381  { // Set RTO unless the ACK is received in SYN_RCVD state
3382  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3383  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3384  m_retxEvent.Cancel ();
3385  // On receiving a "New" ack we restart retransmission timer .. RFC 6298
3386  // RFC 6298, clause 2.4
3387  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3388 
3389  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
3390  Simulator::Now ().GetSeconds () << " to expire at time " <<
3391  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
3393  }
3394 
3395  // Note the highest ACK and tell app to send more
3396  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
3397  " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
3398 
3399  if (GetTxAvailable () > 0)
3400  {
3402  }
3403  if (ack > m_tcb->m_nextTxSequence)
3404  {
3405  m_tcb->m_nextTxSequence = ack; // If advanced
3406  }
3407  if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
3408  { // No retransmit timer if no data to retransmit
3409  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3410  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3411  m_retxEvent.Cancel ();
3412  }
3413 }
3414 
3415 // Retransmit timeout
3416 void
3418 {
3419  NS_LOG_FUNCTION (this);
3420  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
3421  // If erroneous timeout in closed/timed-wait state, just return
3422  if (m_state == CLOSED || m_state == TIME_WAIT)
3423  {
3424  return;
3425  }
3426 
3427  if (m_state == SYN_SENT)
3428  {
3429  if (m_synCount > 0)
3430  {
3431  if (m_ecnMode == EcnMode_t::ClassicEcn)
3432  {
3434  }
3435  else
3436  {
3438  }
3440  }
3441  else
3442  {
3444  }
3445  return;
3446  }
3447 
3448  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3449  if (m_txBuffer->Size () == 0)
3450  {
3451  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3452  { // Must have lost FIN, re-send
3454  }
3455  return;
3456  }
3457 
3458  NS_LOG_DEBUG ("Checking if Connection is Established");
3459  // If all data are received (non-closing socket and nothing to send), just return
3460  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark && m_txBuffer->Size () == 0)
3461  {
3462  NS_LOG_DEBUG ("Already Sent full data" << m_txBuffer->HeadSequence () << " " << m_tcb->m_highTxMark);
3463  return;
3464  }
3465 
3466  if (m_dataRetrCount == 0)
3467  {
3468  NS_LOG_INFO ("No more data retries available. Dropping connection");
3469  NotifyErrorClose ();
3470  DeallocateEndPoint ();
3471  return;
3472  }
3473  else
3474  {
3475  --m_dataRetrCount;
3476  }
3477 
3478  uint32_t inFlightBeforeRto = BytesInFlight ();
3479  bool resetSack = !m_sackEnabled; // Reset SACK information if SACK is not enabled.
3480  // The information in the TcpTxBuffer is guessed, in this case.
3481 
3482  // Reset dupAckCount
3483  m_dupAckCount = 0;
3484  if (!m_sackEnabled)
3485  {
3486  m_txBuffer->ResetRenoSack ();
3487  }
3488 
3489  // From RFC 6675, Section 5.1
3490  // [RFC2018] suggests that a TCP sender SHOULD expunge the SACK
3491  // information gathered from a receiver upon a retransmission timeout
3492  // (RTO) "since the timeout might indicate that the data receiver has
3493  // reneged." Additionally, a TCP sender MUST "ignore prior SACK
3494  // information in determining which data to retransmit."
3495  // It has been suggested that, as long as robust tests for
3496  // reneging are present, an implementation can retain and use SACK
3497  // information across a timeout event [Errata1610].
3498  // The head of the sent list will not be marked as sacked, therefore
3499  // will be retransmitted, if the receiver renegotiate the SACK blocks
3500  // that we received.
3501  m_txBuffer->SetSentListLost (resetSack);
3502 
3503  // From RFC 6675, Section 5.1
3504  // If an RTO occurs during loss recovery as specified in this document,
3505  // RecoveryPoint MUST be set to HighData. Further, the new value of
3506  // RecoveryPoint MUST be preserved and the loss recovery algorithm
3507  // outlined in this document MUST be terminated.
3509 
3510  // RFC 6298, clause 2.5, double the timer
3511  Time doubledRto = m_rto + m_rto;
3512  m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
3513 
3514  // Empty RTT history
3515  m_history.clear ();
3516 
3517  // Please don't reset highTxMark, it is used for retransmission detection
3518 
3519  // When a TCP sender detects segment loss using the retransmission timer
3520  // and the given segment has not yet been resent by way of the
3521  // retransmission timer, decrease ssThresh
3522  if (m_tcb->m_congState != TcpSocketState::CA_LOSS || !m_txBuffer->IsHeadRetransmitted ())
3523  {
3524  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, inFlightBeforeRto);
3525  }
3526 
3527  // Cwnd set to 1 MSS
3531  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS);
3533 
3534  m_pacingTimer.Cancel ();
3535 
3536  NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
3537  m_tcb->m_ssThresh << ", restart from seqnum " <<
3538  m_txBuffer->HeadSequence () << " doubled rto to " <<
3539  m_rto.Get ().GetSeconds () << " s");
3540 
3541  NS_ASSERT_MSG (BytesInFlight () == 0, "There are some bytes in flight after an RTO: " <<
3542  BytesInFlight ());
3543 
3545 
3547  "In flight (" << BytesInFlight () <<
3548  ") there is more than one segment (" << m_tcb->m_segmentSize << ")");
3549 }
3550 
3551 void
3553 {
3554  m_delAckCount = 0;
3557  {
3560  }
3561  else
3562  {
3564  }
3565 }
3566 
3567 void
3569 {
3570  NS_LOG_FUNCTION (this);
3571 
3573  if (m_state == LAST_ACK)
3574  {
3575  CloseAndNotify ();
3576  }
3577  if (!m_closeNotified)
3578  {
3579  m_closeNotified = true;
3580  }
3581 }
3582 
3583 // Send 1-byte data to probe for the window size at the receiver when
3584 // the local knowledge tells that the receiver has zero window size
3585 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
3586 void
3588 {
3589  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
3590  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
3591  Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence);
3592  m_txBuffer->ResetLastSegmentSent ();
3593  TcpHeader tcpHeader;
3595  tcpHeader.SetAckNumber (m_rxBuffer->NextRxSequence ());
3596  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
3597  if (m_endPoint != nullptr)
3598  {
3599  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
3600  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
3601  }
3602  else
3603  {
3604  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
3605  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
3606  }
3607  AddOptions (tcpHeader);
3608  //Send a packet tag for setting ECT bits in IP header
3610  {
3611  SocketIpTosTag ipTosTag;
3612  ipTosTag.SetTos (MarkEcnEct0 (0));
3613  p->AddPacketTag (ipTosTag);
3614 
3615  SocketIpv6TclassTag ipTclassTag;
3616  ipTclassTag.SetTclass (MarkEcnEct0 (0));
3617  p->AddPacketTag (ipTclassTag);
3618  }
3619  m_txTrace (p, tcpHeader, this);
3620 
3621  if (m_endPoint != nullptr)
3622  {
3623  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
3625  }
3626  else
3627  {
3628  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
3630  }
3631 
3632  NS_LOG_LOGIC ("Schedule persist timeout at time "
3633  << Simulator::Now ().GetSeconds () << " to expire at time "
3634  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
3636 }
3637 
3638 void
3640 {
3641  NS_LOG_FUNCTION (this);
3642  bool res;
3643  SequenceNumber32 seq;
3644 
3645  // Find the first segment marked as lost and not retransmitted. With Reno,
3646  // that should be the head
3647  res = m_txBuffer->NextSeg (&seq, false);
3648  if (!res)
3649  {
3650  // We have already retransmitted the head. However, we still received
3651  // three dupacks, or the RTO expired, but no data to transmit.
3652  // Therefore, re-send again the head.
3653  seq = m_txBuffer->HeadSequence ();
3654  }
3655  NS_ASSERT (m_sackEnabled || seq == m_txBuffer->HeadSequence ());
3656 
3657  NS_LOG_INFO ("Retransmitting " << seq);
3658  // Update the trace and retransmit the segment
3659  m_tcb->m_nextTxSequence = seq;
3660  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, m_tcb->m_segmentSize, true);
3661 
3662  NS_ASSERT (sz > 0);
3663 }
3664 
3665 void
3667 {
3668  m_retxEvent.Cancel ();
3670  m_delAckEvent.Cancel ();
3674  m_pacingTimer.Cancel ();
3675 }
3676 
3677 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
3678 void
3680 {
3681  NS_LOG_DEBUG (TcpStateName[m_state] << " -> TIME_WAIT");
3682  m_state = TIME_WAIT;
3683  CancelAllTimers ();
3684  if (!m_closeNotified)
3685  {
3686  // Technically the connection is not fully closed, but we notify now
3687  // because an implementation (real socket) would behave as if closed.
3688  // Notify normal close when entering TIME_WAIT or leaving LAST_ACK.
3689  NotifyNormalClose ();
3690  m_closeNotified = true;
3691  }
3692  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
3693  // according to RFC793, p.28
3696 }
3697 
3698 /* Below are the attribute get/set functions */
3699 
3700 void
3702 {
3703  NS_LOG_FUNCTION (this << size);
3704  m_txBuffer->SetMaxBufferSize (size);
3705 }
3706 
3707 uint32_t
3709 {
3710  return m_txBuffer->MaxBufferSize ();
3711 }
3712 
3713 void
3715 {
3716  NS_LOG_FUNCTION (this << size);
3717  uint32_t oldSize = GetRcvBufSize ();
3718 
3719  m_rxBuffer->SetMaxBufferSize (size);
3720 
3721  /* The size has (manually) increased. Actively inform the other end to prevent
3722  * stale zero-window states.
3723  */
3724  if (oldSize < size && m_connected)
3725  {
3727  {
3729  NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3731  }
3732  else
3733  {
3735  }
3736  }
3737 }
3738 
3739 uint32_t
3741 {
3742  return m_rxBuffer->MaxBufferSize ();
3743 }
3744 
3745 void
3747 {
3748  NS_LOG_FUNCTION (this << size);
3749  m_tcb->m_segmentSize = size;
3750  m_txBuffer->SetSegmentSize (size);
3751 
3752  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
3753 }
3754 
3755 uint32_t
3757 {
3758  return m_tcb->m_segmentSize;
3759 }
3760 
3761 void
3763 {
3764  NS_LOG_FUNCTION (this << timeout);
3765  m_cnTimeout = timeout;
3766 }
3767 
3768 Time
3770 {
3771  return m_cnTimeout;
3772 }
3773 
3774 void
3776 {
3777  NS_LOG_FUNCTION (this << count);
3778  m_synRetries = count;
3779 }
3780 
3781 uint32_t
3783 {
3784  return m_synRetries;
3785 }
3786 
3787 void
3789 {
3790  NS_LOG_FUNCTION (this << retries);
3791  m_dataRetries = retries;
3792 }
3793 
3794 uint32_t
3796 {
3797  NS_LOG_FUNCTION (this);
3798  return m_dataRetries;
3799 }
3800 
3801 void
3803 {
3804  NS_LOG_FUNCTION (this << timeout);
3806 }
3807 
3808 Time
3810 {
3811  return m_delAckTimeout;
3812 }
3813 
3814 void
3816 {
3817  NS_LOG_FUNCTION (this << count);
3818  m_delAckMaxCount = count;
3819 }
3820 
3821 uint32_t
3823 {
3824  return m_delAckMaxCount;
3825 }
3826 
3827 void
3829 {
3830  NS_LOG_FUNCTION (this << noDelay);
3831  m_noDelay = noDelay;
3832 }
3833 
3834 bool
3836 {
3837  return m_noDelay;
3838 }
3839 
3840 void
3842 {
3843  NS_LOG_FUNCTION (this << timeout);
3845 }
3846 
3847 Time
3849 {
3850  return m_persistTimeout;
3851 }
3852 
3853 bool
3855 {
3856  // Broadcast is not implemented. Return true only if allowBroadcast==false
3857  return (!allowBroadcast);
3858 }
3859 
3860 bool
3862 {
3863  return false;
3864 }
3865 
3866 void
3868 {
3869  NS_LOG_FUNCTION (this << header);
3870 
3871  if (m_timestampEnabled)
3872  {
3873  AddOptionTimestamp (header);
3874  }
3875 }
3876 
3877 void
3879 {
3880  NS_LOG_FUNCTION (this << option);
3881 
3882  Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
3883 
3884  // In naming, we do the contrary of RFC 1323. The received scaling factor
3885  // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
3886  m_sndWindShift = ws->GetScale ();
3887 
3888  if (m_sndWindShift > 14)
3889  {
3890  NS_LOG_WARN ("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
3891  m_sndWindShift = 14;
3892  }
3893 
3894  NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
3895  static_cast<int> (m_sndWindShift));
3896 }
3897 
3898 uint8_t
3900 {
3901  NS_LOG_FUNCTION (this);
3902  uint32_t maxSpace = m_rxBuffer->MaxBufferSize ();
3903  uint8_t scale = 0;
3904 
3905  while (maxSpace > m_maxWinSize)
3906  {
3907  maxSpace = maxSpace >> 1;
3908  ++scale;
3909  }
3910 
3911  if (scale > 14)
3912  {
3913  NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
3914  scale = 14;
3915  }
3916 
3917  NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
3918  static_cast<int> (scale) << " for buffer size " << m_rxBuffer->MaxBufferSize ());
3919  return scale;
3920 }
3921 
3922 void
3924 {
3925  NS_LOG_FUNCTION (this << header);
3926  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
3927 
3928  Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
3929 
3930  // In naming, we do the contrary of RFC 1323. The sended scaling factor
3931  // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
3932 
3934  option->SetScale (m_rcvWindShift);
3935 
3936  header.AppendOption (option);
3937 
3938  NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
3939  static_cast<int> (m_rcvWindShift));
3940 }
3941 
3942 bool
3944 {
3945  NS_LOG_FUNCTION (this << option);
3946 
3947  Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option);
3948  TcpOptionSack::SackList list = s->GetSackList ();
3949  return m_txBuffer->Update (list);
3950 }
3951 
3952 void
3954 {
3955  NS_LOG_FUNCTION (this << option);
3956 
3957  Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted> (option);
3958 
3959  NS_ASSERT (m_sackEnabled == true);
3960  NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s);
3961 }
3962 
3963 void
3965 {
3966  NS_LOG_FUNCTION (this << header);
3967  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
3968 
3969  Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> ();
3970  header.AppendOption (option);
3971  NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED");
3972 }
3973 
3974 void
3976 {
3977  NS_LOG_FUNCTION (this << header);
3978 
3979  // Calculate the number of SACK blocks allowed in this packet
3980  uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength ();
3981  uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8;
3982 
3983  TcpOptionSack::SackList sackList = m_rxBuffer->GetSackList ();
3984  if (allowedSackBlocks == 0 || sackList.empty ())
3985  {
3986  NS_LOG_LOGIC ("No space available or sack list empty, not adding sack blocks");
3987  return;
3988  }
3989 
3990  // Append the allowed number of SACK blocks
3991  Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> ();
3992  TcpOptionSack::SackList::iterator i;
3993  for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i)
3994  {
3995  option->AddSackBlock (*i);
3996  allowedSackBlocks--;
3997  }
3998 
3999  header.AppendOption (option);
4000  NS_LOG_INFO (m_node->GetId () << " Add option SACK " << *option);
4001 }
4002 
4003 void
4005  const SequenceNumber32 &seq)
4006 {
4007  NS_LOG_FUNCTION (this << option);
4008 
4009  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
4010 
4011  // This is valid only when no overflow occurs. It happens
4012  // when a connection last longer than 50 days.
4013  if (m_tcb->m_rcvTimestampValue > ts->GetTimestamp ())
4014  {
4015  // Do not save a smaller timestamp (probably there is reordering)
4016  return;
4017  }
4018 
4019  m_tcb->m_rcvTimestampValue = ts->GetTimestamp ();
4020  m_tcb->m_rcvTimestampEchoReply = ts->GetEcho ();
4021 
4022  if (seq == m_rxBuffer->NextRxSequence () && seq <= m_highTxAck)
4023  {
4024  m_timestampToEcho = ts->GetTimestamp ();
4025  }
4026 
4027  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
4028  m_timestampToEcho << " and Echo=" << ts->GetEcho ());
4029 }
4030 
4031 void
4033 {
4034  NS_LOG_FUNCTION (this << header);
4035 
4036  Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
4037 
4038  option->SetTimestamp (TcpOptionTS::NowToTsValue ());
4039  option->SetEcho (m_timestampToEcho);
4040 
4041  header.AppendOption (option);
4042  NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
4043  option->GetTimestamp () << " echo=" << m_timestampToEcho);
4044 }
4045 
4047 {
4048  NS_LOG_FUNCTION (this << header);
4049  // If the connection is not established, the window size is always
4050  // updated
4051  uint32_t receivedWindow = header.GetWindowSize ();
4052  receivedWindow <<= m_sndWindShift;
4053  NS_LOG_INFO ("Received (scaled) window is " << receivedWindow << " bytes");
4054  if (m_state < ESTABLISHED)
4055  {
4056  m_rWnd = receivedWindow;
4057  NS_LOG_LOGIC ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
4058  return;
4059  }
4060 
4061  // Test for conditions that allow updating of the window
4062  // 1) segment contains new data (advancing the right edge of the receive
4063  // buffer),
4064  // 2) segment does not contain new data but the segment acks new data
4065  // (highest sequence number acked advances), or
4066  // 3) the advertised window is larger than the current send window
4067  bool update = false;
4068  if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
4069  {
4070  // right edge of the send window is increased (window update)
4071  update = true;
4072  }
4073  if (header.GetAckNumber () > m_highRxAckMark)
4074  {
4075  m_highRxAckMark = header.GetAckNumber ();
4076  update = true;
4077  }
4078  if (header.GetSequenceNumber () > m_highRxMark)
4079  {
4080  m_highRxMark = header.GetSequenceNumber ();
4081  update = true;
4082  }
4083  if (update == true)
4084  {
4085  m_rWnd = receivedWindow;
4086  NS_LOG_LOGIC ("updating rWnd to " << m_rWnd);
4087  }
4088 }
4089 
4090 void
4092 {
4093  NS_LOG_FUNCTION (this << minRto);
4094  m_minRto = minRto;
4095 }
4096 
4097 Time
4099 {
4100  return m_minRto;
4101 }
4102 
4103 void
4105 {
4106  NS_LOG_FUNCTION (this << clockGranularity);
4107  m_clockGranularity = clockGranularity;
4108 }
4109 
4110 Time
4112 {
4113  return m_clockGranularity;
4114 }
4115 
4118 {
4119  return m_txBuffer;
4120 }
4121 
4124 {
4125  return m_rxBuffer;
4126 }
4127 
4128 void
4129 TcpSocketBase::SetRetxThresh (uint32_t retxThresh)
4130 {
4131  m_retxThresh = retxThresh;
4132  m_txBuffer->SetDupAckThresh (retxThresh);
4133 }
4134 
4135 void
4136 TcpSocketBase::UpdateCwnd (uint32_t oldValue, uint32_t newValue)
4137 {
4138  m_cWndTrace (oldValue, newValue);
4139 }
4140 
4141 void
4142 TcpSocketBase::UpdateCwndInfl (uint32_t oldValue, uint32_t newValue)
4143 {
4144  m_cWndInflTrace (oldValue, newValue);
4145 }
4146 
4147 void
4148 TcpSocketBase::UpdateSsThresh (uint32_t oldValue, uint32_t newValue)
4149 {
4150  m_ssThTrace (oldValue, newValue);
4151 }
4152 
4153 void
4156 {
4157  m_congStateTrace (oldValue, newValue);
4158 }
4159 
4160  void
4162  TcpSocketState::EcnState_t newValue)
4163 {
4164  m_ecnStateTrace (oldValue, newValue);
4165 }
4166 
4167 void
4169  SequenceNumber32 newValue)
4170 
4171 {
4172  m_nextTxSequenceTrace (oldValue, newValue);
4173 }
4174 
4175 void
4177 {
4178  m_highTxMarkTrace (oldValue, newValue);
4179 }
4180 
4181 void
4182 TcpSocketBase::UpdateBytesInFlight (uint32_t oldValue, uint32_t newValue)
4183 {
4184  m_bytesInFlightTrace (oldValue, newValue);
4185 }
4186 
4187 void
4188 TcpSocketBase::UpdateRtt (Time oldValue, Time newValue)
4189 {
4190  m_lastRttTrace (oldValue, newValue);
4191 }
4192 
4193 void
4195 {
4196  NS_LOG_FUNCTION (this << algo);
4197  m_congestionControl = algo;
4198 }
4199 
4200 void
4202 {
4203  NS_LOG_FUNCTION (this << recovery);
4204  m_recoveryOps = recovery;
4205 }
4206 
4209 {
4210  return CopyObject<TcpSocketBase> (this);
4211 }
4212 
4213 uint32_t
4214 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b)
4215 {
4216  if (a > b)
4217  {
4218  return a-b;
4219  }
4220 
4221  return 0;
4222 }
4223 
4224 void
4226 {
4228  NS_LOG_INFO ("Performing Pacing");
4230 }
4231 
4232 void
4234 {
4235  NS_LOG_FUNCTION (this);
4236  m_ecnMode = ecnMode;
4237 }
4238 
4239 //RttHistory methods
4241  : seq (s),
4242  count (c),
4243  time (t),
4244  retx (false)
4245 {
4246 }
4247 
4249  : seq (h.seq),
4250  count (h.count),
4251  time (h.time),
4252  retx (h.retx)
4253 {
4254 }
4255 
4256 } // 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:258
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:831
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:202
Ptr< TcpSocketState > m_tcb
Congestion control information.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1022
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:278
#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:740
#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:1381
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:1076
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:866
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:1071
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:1570
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:1077
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:249
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:852
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:262
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:859
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:270
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:1014
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:254
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.