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-header.h"
52 #include "tcp-option-winscale.h"
53 #include "tcp-option-ts.h"
55 #include "tcp-option-sack.h"
56 #include "tcp-congestion-ops.h"
57 
58 #include <math.h>
59 #include <algorithm>
60 
61 namespace ns3 {
62 
63 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase");
64 
65 NS_OBJECT_ENSURE_REGISTERED (TcpSocketBase);
66 
67 TypeId
69 {
70  static TypeId tid = TypeId ("ns3::TcpSocketBase")
71  .SetParent<TcpSocket> ()
72  .SetGroupName ("Internet")
73  .AddConstructor<TcpSocketBase> ()
74 // .AddAttribute ("TcpState", "State in TCP state machine",
75 // TypeId::ATTR_GET,
76 // EnumValue (CLOSED),
77 // MakeEnumAccessor (&TcpSocketBase::m_state),
78 // MakeEnumChecker (CLOSED, "Closed"))
79  .AddAttribute ("MaxSegLifetime",
80  "Maximum segment lifetime in seconds, use for TIME_WAIT state transition to CLOSED state",
81  DoubleValue (120), /* RFC793 says MSL=2 minutes*/
83  MakeDoubleChecker<double> (0))
84  .AddAttribute ("MaxWindowSize", "Max size of advertised window",
85  UintegerValue (65535),
87  MakeUintegerChecker<uint16_t> ())
88  .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
89  CallbackValue (),
92  .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
93  CallbackValue (),
96  .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option",
97  BooleanValue (true),
100  .AddAttribute ("Sack", "Enable or disable Sack option",
101  BooleanValue (true),
104  .AddAttribute ("Timestamp", "Enable or disable Timestamp option",
105  BooleanValue (true),
108  .AddAttribute ("MinRto",
109  "Minimum retransmit timeout value",
110  TimeValue (Seconds (1.0)), // RFC 6298 says min RTO=1 sec, but Linux uses 200ms.
111  // See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
114  MakeTimeChecker ())
115  .AddAttribute ("ClockGranularity",
116  "Clock Granularity used in RTO calculations",
117  TimeValue (MilliSeconds (1)), // RFC6298 suggest to use fine clock granularity
120  MakeTimeChecker ())
121  .AddAttribute ("TxBuffer",
122  "TCP Tx buffer",
123  PointerValue (),
125  MakePointerChecker<TcpTxBuffer> ())
126  .AddAttribute ("RxBuffer",
127  "TCP Rx buffer",
128  PointerValue (),
130  MakePointerChecker<TcpRxBuffer> ())
131  .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit",
132  UintegerValue (3),
135  MakeUintegerChecker<uint32_t> ())
136  .AddAttribute ("LimitedTransmit", "Enable limited transmit",
137  BooleanValue (true),
140  .AddTraceSource ("RTO",
141  "Retransmission timeout",
143  "ns3::TracedValueCallback::Time")
144  .AddTraceSource ("RTT",
145  "Last RTT sample",
147  "ns3::TracedValueCallback::Time")
148  .AddTraceSource ("NextTxSequence",
149  "Next sequence number to send (SND.NXT)",
151  "ns3::SequenceNumber32TracedValueCallback")
152  .AddTraceSource ("HighestSequence",
153  "Highest sequence number ever sent in socket's life time",
155  "ns3::TracedValueCallback::SequenceNumber32")
156  .AddTraceSource ("State",
157  "TCP state",
159  "ns3::TcpStatesTracedValueCallback")
160  .AddTraceSource ("CongState",
161  "TCP Congestion machine state",
163  "ns3::TcpSocketState::TcpCongStatesTracedValueCallback")
164  .AddTraceSource ("AdvWND",
165  "Advertised Window Size",
167  "ns3::TracedValueCallback::Uint32")
168  .AddTraceSource ("RWND",
169  "Remote side's flow control window",
171  "ns3::TracedValueCallback::Uint32")
172  .AddTraceSource ("BytesInFlight",
173  "Socket estimation of bytes in flight",
175  "ns3::TracedValueCallback::Uint32")
176  .AddTraceSource ("HighestRxSequence",
177  "Highest sequence number received from peer",
179  "ns3::TracedValueCallback::SequenceNumber32")
180  .AddTraceSource ("HighestRxAck",
181  "Highest ack received from peer",
183  "ns3::TracedValueCallback::SequenceNumber32")
184  .AddTraceSource ("CongestionWindow",
185  "The TCP connection's congestion window",
187  "ns3::TracedValueCallback::Uint32")
188  .AddTraceSource ("CongestionWindowInflated",
189  "The TCP connection's congestion window inflates as in older RFC",
191  "ns3::TracedValueCallback::Uint32")
192  .AddTraceSource ("SlowStartThreshold",
193  "TCP slow start threshold (bytes)",
195  "ns3::TracedValueCallback::Uint32")
196  .AddTraceSource ("Tx",
197  "Send tcp packet to IP protocol",
199  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
200  .AddTraceSource ("Rx",
201  "Receive tcp packet from IP protocol",
203  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
204  ;
205  return tid;
206 }
207 
208 TypeId
210 {
211  return TcpSocketBase::GetTypeId ();
212 }
213 
215 
216 TypeId
218 {
219  static TypeId tid = TypeId ("ns3::TcpSocketState")
220  .SetParent<Object> ()
221  .SetGroupName ("Internet")
222  .AddConstructor <TcpSocketState> ()
223  .AddAttribute ("EnablePacing", "Enable Pacing",
224  BooleanValue (false),
227  .AddAttribute ("MaxPacingRate", "Set Max Pacing Rate",
228  DataRateValue (DataRate ("4Gb/s")),
231  .AddTraceSource ("CongestionWindow",
232  "The TCP connection's congestion window",
234  "ns3::TracedValue::Uint32Callback")
235  .AddTraceSource ("SlowStartThreshold",
236  "TCP slow start threshold (bytes)",
238  "ns3::TracedValue::Uint32Callback")
239  .AddTraceSource ("CongState",
240  "TCP Congestion machine state",
242  "ns3::TracedValue::TcpCongStatesTracedValueCallback")
243  .AddTraceSource ("HighestSequence",
244  "Highest sequence number received from peer",
246  "ns3::SequenceNumber32TracedValueCallback")
247  .AddTraceSource ("NextTxSequence",
248  "Next sequence number to send (SND.NXT)",
250  "ns3::SequenceNumber32TracedValueCallback")
251  ;
252  return tid;
253 }
254 
256  : Object (other),
257  m_cWnd (other.m_cWnd),
258  m_ssThresh (other.m_ssThresh),
259  m_initialCWnd (other.m_initialCWnd),
260  m_initialSsThresh (other.m_initialSsThresh),
261  m_segmentSize (other.m_segmentSize),
262  m_lastAckedSeq (other.m_lastAckedSeq),
263  m_congState (other.m_congState),
264  m_highTxMark (other.m_highTxMark),
265  m_nextTxSequence (other.m_nextTxSequence),
266  m_rcvTimestampValue (other.m_rcvTimestampValue),
267  m_rcvTimestampEchoReply (other.m_rcvTimestampEchoReply),
268  m_pacing (other.m_pacing),
269  m_maxPacingRate (other.m_maxPacingRate),
270  m_currentPacingRate (other.m_currentPacingRate),
271  m_minRtt (other.m_minRtt)
272 {
273 }
274 
275 const char* const
277 {
278  "CA_OPEN", "CA_DISORDER", "CA_CWR", "CA_RECOVERY", "CA_LOSS"
279 };
280 
282  : TcpSocket ()
283 {
284  NS_LOG_FUNCTION (this);
285  m_rxBuffer = CreateObject<TcpRxBuffer> ();
286  m_txBuffer = CreateObject<TcpTxBuffer> ();
287  m_tcb = CreateObject<TcpSocketState> ();
288 
289  m_tcb->m_currentPacingRate = m_tcb->m_maxPacingRate;
291 
292  bool ok;
293 
294  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
296  NS_ASSERT (ok == true);
297 
298  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
300  NS_ASSERT (ok == true);
301 
302  ok = m_tcb->TraceConnectWithoutContext ("CongState",
304  NS_ASSERT (ok == true);
305 
306  ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
308  NS_ASSERT (ok == true);
309 
310  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
312  NS_ASSERT (ok == true);
313 }
314 
316  : TcpSocket (sock),
317  //copy object::m_tid and socket::callbacks
318  m_dupAckCount (sock.m_dupAckCount),
319  m_delAckCount (0),
320  m_delAckMaxCount (sock.m_delAckMaxCount),
321  m_noDelay (sock.m_noDelay),
322  m_synCount (sock.m_synCount),
323  m_synRetries (sock.m_synRetries),
324  m_dataRetrCount (sock.m_dataRetrCount),
325  m_dataRetries (sock.m_dataRetries),
326  m_rto (sock.m_rto),
327  m_minRto (sock.m_minRto),
328  m_lastRtt (sock.m_lastRtt),
329  m_clockGranularity (sock.m_clockGranularity),
330  m_delAckTimeout (sock.m_delAckTimeout),
331  m_persistTimeout (sock.m_persistTimeout),
332  m_cnTimeout (sock.m_cnTimeout),
333  m_endPoint (nullptr),
334  m_endPoint6 (nullptr),
335  m_node (sock.m_node),
336  m_tcp (sock.m_tcp),
337  m_state (sock.m_state),
338  m_errno (sock.m_errno),
339  m_closeNotified (sock.m_closeNotified),
340  m_closeOnEmpty (sock.m_closeOnEmpty),
341  m_shutdownSend (sock.m_shutdownSend),
342  m_shutdownRecv (sock.m_shutdownRecv),
343  m_connected (sock.m_connected),
344  m_msl (sock.m_msl),
345  m_maxWinSize (sock.m_maxWinSize),
346  m_bytesAckedNotProcessed (sock.m_bytesAckedNotProcessed),
347  m_rWnd (sock.m_rWnd),
348  m_highRxMark (sock.m_highRxMark),
349  m_highRxAckMark (sock.m_highRxAckMark),
350  m_bytesInFlight (sock.m_bytesInFlight),
351  m_sackEnabled (sock.m_sackEnabled),
352  m_winScalingEnabled (sock.m_winScalingEnabled),
353  m_rcvWindShift (sock.m_rcvWindShift),
354  m_sndWindShift (sock.m_sndWindShift),
355  m_timestampEnabled (sock.m_timestampEnabled),
356  m_timestampToEcho (sock.m_timestampToEcho),
357  m_recover (sock.m_recover),
358  m_retxThresh (sock.m_retxThresh),
359  m_limitedTx (sock.m_limitedTx),
360  m_isFirstPartialAck (sock.m_isFirstPartialAck),
361  m_txTrace (sock.m_txTrace),
362  m_rxTrace (sock.m_rxTrace),
363  m_pacingTimer (Timer::REMOVE_ON_DESTROY)
364 {
365  NS_LOG_FUNCTION (this);
366  NS_LOG_LOGIC ("Invoked the copy constructor");
367  // Copy the rtt estimator if it is set
368  if (sock.m_rtt)
369  {
370  m_rtt = sock.m_rtt->Copy ();
371  }
372  // Reset all callbacks to null
373  Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
374  Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr<Socket>, const Address &> ();
375  Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t> ();
376  SetConnectCallback (vPS, vPS);
377  SetDataSentCallback (vPSUI);
378  SetSendCallback (vPSUI);
379  SetRecvCallback (vPS);
382  m_tcb = CopyObject (sock.m_tcb);
383 
386 
387  if (sock.m_congestionControl)
388  {
390  }
391 
392  bool ok;
393 
394  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
396  NS_ASSERT (ok == true);
397 
398  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
400  NS_ASSERT (ok == true);
401 
402  ok = m_tcb->TraceConnectWithoutContext ("CongState",
404  NS_ASSERT (ok == true);
405 
406  ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
408  NS_ASSERT (ok == true);
409 
410  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
412  NS_ASSERT (ok == true);
413 }
414 
416 {
417  NS_LOG_FUNCTION (this);
418  m_node = nullptr;
419  if (m_endPoint != nullptr)
420  {
421  NS_ASSERT (m_tcp != nullptr);
422  /*
423  * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
424  * DestroyCallback is set to TcpSocketBase::Destroy. If we called
425  * m_tcp->DeAllocate, it wil destroy its Ipv4EndpointDemux::DeAllocate,
426  * which in turn destroys my m_endPoint, and in turn invokes
427  * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
428  */
429  NS_ASSERT (m_endPoint != nullptr);
430  m_tcp->DeAllocate (m_endPoint);
431  NS_ASSERT (m_endPoint == nullptr);
432  }
433  if (m_endPoint6 != nullptr)
434  {
435  NS_ASSERT (m_tcp != nullptr);
436  NS_ASSERT (m_endPoint6 != nullptr);
437  m_tcp->DeAllocate (m_endPoint6);
438  NS_ASSERT (m_endPoint6 == nullptr);
439  }
440  m_tcp = 0;
441  CancelAllTimers ();
442 }
443 
444 /* Associate a node with this TCP socket */
445 void
447 {
448  m_node = node;
449 }
450 
451 /* Associate the L4 protocol (e.g. mux/demux) with this socket */
452 void
454 {
455  m_tcp = tcp;
456 }
457 
458 /* Set an RTT estimator with this socket */
459 void
461 {
462  m_rtt = rtt;
463 }
464 
465 /* Inherit from Socket class: Returns error code */
468 {
469  return m_errno;
470 }
471 
472 /* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
475 {
476  return NS3_SOCK_STREAM;
477 }
478 
479 /* Inherit from Socket class: Returns associated node */
480 Ptr<Node>
482 {
483  return m_node;
484 }
485 
486 /* Inherit from Socket class: Bind socket to an end-point in TcpL4Protocol */
487 int
489 {
490  NS_LOG_FUNCTION (this);
491  m_endPoint = m_tcp->Allocate ();
492  if (0 == m_endPoint)
493  {
494  m_errno = ERROR_ADDRNOTAVAIL;
495  return -1;
496  }
497 
498  m_tcp->AddSocket (this);
499 
500  return SetupCallback ();
501 }
502 
503 int
505 {
506  NS_LOG_FUNCTION (this);
507  m_endPoint6 = m_tcp->Allocate6 ();
508  if (0 == m_endPoint6)
509  {
510  m_errno = ERROR_ADDRNOTAVAIL;
511  return -1;
512  }
513 
514  m_tcp->AddSocket (this);
515 
516  return SetupCallback ();
517 }
518 
519 /* Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
520 int
522 {
523  NS_LOG_FUNCTION (this << address);
524  if (InetSocketAddress::IsMatchingType (address))
525  {
527  Ipv4Address ipv4 = transport.GetIpv4 ();
528  uint16_t port = transport.GetPort ();
529  SetIpTos (transport.GetTos ());
530  if (ipv4 == Ipv4Address::GetAny () && port == 0)
531  {
532  m_endPoint = m_tcp->Allocate ();
533  }
534  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
535  {
536  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (), port);
537  }
538  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
539  {
540  m_endPoint = m_tcp->Allocate (ipv4);
541  }
542  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
543  {
544  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (), ipv4, port);
545  }
546  if (0 == m_endPoint)
547  {
548  m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
549  return -1;
550  }
551  }
552  else if (Inet6SocketAddress::IsMatchingType (address))
553  {
555  Ipv6Address ipv6 = transport.GetIpv6 ();
556  uint16_t port = transport.GetPort ();
557  if (ipv6 == Ipv6Address::GetAny () && port == 0)
558  {
559  m_endPoint6 = m_tcp->Allocate6 ();
560  }
561  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
562  {
563  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (), port);
564  }
565  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
566  {
567  m_endPoint6 = m_tcp->Allocate6 (ipv6);
568  }
569  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
570  {
571  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (), ipv6, port);
572  }
573  if (0 == m_endPoint6)
574  {
575  m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
576  return -1;
577  }
578  }
579  else
580  {
581  m_errno = ERROR_INVAL;
582  return -1;
583  }
584 
585  m_tcp->AddSocket (this);
586 
587  NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
588 
589  return SetupCallback ();
590 }
591 
592 void
594 {
595  NS_ABORT_MSG_UNLESS ( (m_state == CLOSED) || threshold == m_tcb->m_initialSsThresh,
596  "TcpSocketBase::SetSSThresh() cannot change initial ssThresh after connection started.");
597 
598  m_tcb->m_initialSsThresh = threshold;
599 }
600 
601 uint32_t
603 {
604  return m_tcb->m_initialSsThresh;
605 }
606 
607 void
609 {
611  "TcpSocketBase::SetInitialCwnd() cannot change initial cwnd after connection started.");
612 
613  m_tcb->m_initialCWnd = cwnd;
614 }
615 
616 uint32_t
618 {
619  return m_tcb->m_initialCWnd;
620 }
621 
622 /* Inherit from Socket class: Initiate connection to a remote address:port */
623 int
625 {
626  NS_LOG_FUNCTION (this << address);
627 
628  // If haven't do so, Bind() this socket first
629  if (InetSocketAddress::IsMatchingType (address))
630  {
631  if (m_endPoint == nullptr)
632  {
633  if (Bind () == -1)
634  {
635  NS_ASSERT (m_endPoint == nullptr);
636  return -1; // Bind() failed
637  }
638  NS_ASSERT (m_endPoint != nullptr);
639  }
641  m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
642  SetIpTos (transport.GetTos ());
643  m_endPoint6 = nullptr;
644 
645  // Get the appropriate local address and port number from the routing protocol and set up endpoint
646  if (SetupEndpoint () != 0)
647  {
648  NS_LOG_ERROR ("Route to destination does not exist ?!");
649  return -1;
650  }
651  }
652  else if (Inet6SocketAddress::IsMatchingType (address))
653  {
654  // If we are operating on a v4-mapped address, translate the address to
655  // a v4 address and re-call this function
657  Ipv6Address v6Addr = transport.GetIpv6 ();
658  if (v6Addr.IsIpv4MappedAddress () == true)
659  {
660  Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
661  return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
662  }
663 
664  if (m_endPoint6 == nullptr)
665  {
666  if (Bind6 () == -1)
667  {
668  NS_ASSERT (m_endPoint6 == nullptr);
669  return -1; // Bind() failed
670  }
671  NS_ASSERT (m_endPoint6 != nullptr);
672  }
673  m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
674  m_endPoint = nullptr;
675 
676  // Get the appropriate local address and port number from the routing protocol and set up endpoint
677  if (SetupEndpoint6 () != 0)
678  {
679  NS_LOG_ERROR ("Route to destination does not exist ?!");
680  return -1;
681  }
682  }
683  else
684  {
685  m_errno = ERROR_INVAL;
686  return -1;
687  }
688 
689  // Re-initialize parameters in case this socket is being reused after CLOSE
690  m_rtt->Reset ();
693 
694  // DoConnect() will do state-checking and send a SYN packet
695  return DoConnect ();
696 }
697 
698 /* Inherit from Socket class: Listen on the endpoint for an incoming connection */
699 int
701 {
702  NS_LOG_FUNCTION (this);
703 
704  // Linux quits EINVAL if we're not in CLOSED state, so match what they do
705  if (m_state != CLOSED)
706  {
707  m_errno = ERROR_INVAL;
708  return -1;
709  }
710  // In other cases, set the state to LISTEN and done
711  NS_LOG_DEBUG ("CLOSED -> LISTEN");
712  m_state = LISTEN;
713  return 0;
714 }
715 
716 /* Inherit from Socket class: Kill this socket and signal the peer (if any) */
717 int
719 {
720  NS_LOG_FUNCTION (this);
724  if (m_rxBuffer->Size () != 0)
725  {
726  NS_LOG_WARN ("Socket " << this << " << unread rx data during close. Sending reset." <<
727  "This is probably due to a bad sink application; check its code");
728  SendRST ();
729  return 0;
730  }
731 
732  if (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
733  { // App close with pending data must wait until all data transmitted
734  if (m_closeOnEmpty == false)
735  {
736  m_closeOnEmpty = true;
737  NS_LOG_INFO ("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
738  }
739  return 0;
740  }
741  return DoClose ();
742 }
743 
744 /* Inherit from Socket class: Signal a termination of send */
745 int
747 {
748  NS_LOG_FUNCTION (this);
749 
750  //this prevents data from being added to the buffer
751  m_shutdownSend = true;
752  m_closeOnEmpty = true;
753  //if buffer is already empty, send a fin now
754  //otherwise fin will go when buffer empties.
755  if (m_txBuffer->Size () == 0)
756  {
757  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
758  {
759  NS_LOG_INFO ("Emtpy tx buffer, send fin");
761 
762  if (m_state == ESTABLISHED)
763  { // On active close: I am the first one to send FIN
764  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
766  }
767  else
768  { // On passive close: Peer sent me FIN already
769  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
770  m_state = LAST_ACK;
771  }
772  }
773  }
774 
775  return 0;
776 }
777 
778 /* Inherit from Socket class: Signal a termination of receive */
779 int
781 {
782  NS_LOG_FUNCTION (this);
783  m_shutdownRecv = true;
784  return 0;
785 }
786 
787 /* Inherit from Socket class: Send a packet. Parameter flags is not used.
788  Packet has no TCP header. Invoked by upper-layer application */
789 int
790 TcpSocketBase::Send (Ptr<Packet> p, uint32_t flags)
791 {
792  NS_LOG_FUNCTION (this << p);
793  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Send()");
795  {
796  // Store the packet into Tx buffer
797  if (!m_txBuffer->Add (p))
798  { // TxBuffer overflow, send failed
799  m_errno = ERROR_MSGSIZE;
800  return -1;
801  }
802  if (m_shutdownSend)
803  {
804  m_errno = ERROR_SHUTDOWN;
805  return -1;
806  }
807  // Submit the data to lower layers
808  NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpStateName[m_state]);
809  if ((m_state == ESTABLISHED || m_state == CLOSE_WAIT) && AvailableWindow () > 0)
810  { // Try to send the data out: Add a little step to allow the application
811  // to fill the buffer
813  {
816  this, m_connected);
817  }
818  }
819  return p->GetSize ();
820  }
821  else
822  { // Connection not established yet
823  m_errno = ERROR_NOTCONN;
824  return -1; // Send failure
825  }
826 }
827 
828 /* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
829 int
831 {
832  NS_UNUSED (address);
833  return Send (p, flags); // SendTo() and Send() are the same
834 }
835 
836 /* Inherit from Socket class: Return data to upper-layer application. Parameter flags
837  is not used. Data is returned as a packet of size no larger than maxSize */
839 TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
840 {
841  NS_LOG_FUNCTION (this);
842  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()");
843  if (m_rxBuffer->Size () == 0 && m_state == CLOSE_WAIT)
844  {
845  return Create<Packet> (); // Send EOF on connection close
846  }
847  Ptr<Packet> outPacket = m_rxBuffer->Extract (maxSize);
848  return outPacket;
849 }
850 
851 /* Inherit from Socket class: Recv and return the remote's address */
853 TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
854 {
855  NS_LOG_FUNCTION (this << maxSize << flags);
856  Ptr<Packet> packet = Recv (maxSize, flags);
857  // Null packet means no data to read, and an empty packet indicates EOF
858  if (packet != nullptr && packet->GetSize () != 0)
859  {
860  if (m_endPoint != nullptr)
861  {
863  }
864  else if (m_endPoint6 != nullptr)
865  {
867  }
868  else
869  {
870  fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
871  }
872  }
873  return packet;
874 }
875 
876 /* Inherit from Socket class: Get the max number of bytes an app can send */
877 uint32_t
879 {
880  NS_LOG_FUNCTION (this);
881  return m_txBuffer->Available ();
882 }
883 
884 /* Inherit from Socket class: Get the max number of bytes an app can read */
885 uint32_t
887 {
888  NS_LOG_FUNCTION (this);
889  return m_rxBuffer->Available ();
890 }
891 
892 /* Inherit from Socket class: Return local address:port */
893 int
895 {
896  NS_LOG_FUNCTION (this);
897  if (m_endPoint != nullptr)
898  {
900  }
901  else if (m_endPoint6 != nullptr)
902  {
904  }
905  else
906  { // It is possible to call this method on a socket without a name
907  // in which case, behavior is unspecified
908  // Should this return an InetSocketAddress or an Inet6SocketAddress?
909  address = InetSocketAddress (Ipv4Address::GetZero (), 0);
910  }
911  return 0;
912 }
913 
914 int
916 {
917  NS_LOG_FUNCTION (this << address);
918 
919  if (!m_endPoint && !m_endPoint6)
920  {
921  m_errno = ERROR_NOTCONN;
922  return -1;
923  }
924 
925  if (m_endPoint)
926  {
928  m_endPoint->GetPeerPort ());
929  }
930  else if (m_endPoint6)
931  {
934  }
935  else
936  {
937  NS_ASSERT (false);
938  }
939 
940  return 0;
941 }
942 
943 /* Inherit from Socket class: Bind this socket to the specified NetDevice */
944 void
946 {
947  NS_LOG_FUNCTION (netdevice);
948  Socket::BindToNetDevice (netdevice); // Includes sanity check
949  if (m_endPoint != nullptr)
950  {
951  m_endPoint->BindToNetDevice (netdevice);
952  }
953 
954  if (m_endPoint6 != nullptr)
955  {
956  m_endPoint6->BindToNetDevice (netdevice);
957  }
958 
959  return;
960 }
961 
962 /* Clean up after Bind. Set up callback functions in the end-point. */
963 int
965 {
966  NS_LOG_FUNCTION (this);
967 
968  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
969  {
970  return -1;
971  }
972  if (m_endPoint != nullptr)
973  {
977  }
978  if (m_endPoint6 != nullptr)
979  {
983  }
984 
985  return 0;
986 }
987 
988 /* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
989 int
991 {
992  NS_LOG_FUNCTION (this);
993 
994  // A new connection is allowed only if this socket does not have a connection
996  { // send a SYN packet and change state into SYN_SENT
998  NS_LOG_DEBUG (TcpStateName[m_state] << " -> SYN_SENT");
999  m_state = SYN_SENT;
1000  }
1001  else if (m_state != TIME_WAIT)
1002  { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
1003  // exists. We send RST, tear down everything, and close this socket.
1004  SendRST ();
1005  CloseAndNotify ();
1006  }
1007  return 0;
1008 }
1009 
1010 /* Do the action to close the socket. Usually send a packet with appropriate
1011  flags depended on the current m_state. */
1012 int
1014 {
1015  NS_LOG_FUNCTION (this);
1016  switch (m_state)
1017  {
1018  case SYN_RCVD:
1019  case ESTABLISHED:
1020  // send FIN to close the peer
1022  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
1023  m_state = FIN_WAIT_1;
1024  break;
1025  case CLOSE_WAIT:
1026  // send FIN+ACK to close the peer
1028  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
1029  m_state = LAST_ACK;
1030  break;
1031  case SYN_SENT:
1032  case CLOSING:
1033  // Send RST if application closes in SYN_SENT and CLOSING
1034  SendRST ();
1035  CloseAndNotify ();
1036  break;
1037  case LISTEN:
1038  case LAST_ACK:
1039  // In these three states, move to CLOSED and tear down the end point
1040  CloseAndNotify ();
1041  break;
1042  case CLOSED:
1043  case FIN_WAIT_1:
1044  case FIN_WAIT_2:
1045  case TIME_WAIT:
1046  default: /* mute compiler */
1047  // Do nothing in these four states
1048  break;
1049  }
1050  return 0;
1051 }
1052 
1053 /* Peacefully close the socket by notifying the upper layer and deallocate end point */
1054 void
1056 {
1057  NS_LOG_FUNCTION (this);
1058 
1059  if (!m_closeNotified)
1060  {
1061  NotifyNormalClose ();
1062  m_closeNotified = true;
1063  }
1064 
1065  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSED");
1066  m_state = CLOSED;
1067  DeallocateEndPoint ();
1068 }
1069 
1070 
1071 /* Tell if a sequence number range is out side the range that my rx buffer can
1072  accpet */
1073 bool
1075 {
1076  if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
1077  { // Rx buffer in these states are not initialized.
1078  return false;
1079  }
1080  if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
1081  { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
1082  // sequence number must equals to m_rxBuffer->NextRxSequence ()
1083  return (m_rxBuffer->NextRxSequence () != head);
1084  }
1085 
1086  // In all other cases, check if the sequence number is in range
1087  return (tail < m_rxBuffer->NextRxSequence () || m_rxBuffer->MaxRxSequence () <= head);
1088 }
1089 
1090 /* Function called by the L3 protocol when it received a packet to pass on to
1091  the TCP. This function is registered as the "RxCallback" function in
1092  SetupCallback(), which invoked by Bind(), and CompleteFork() */
1093 void
1095  Ptr<Ipv4Interface> incomingInterface)
1096 {
1097  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1098  m_endPoint->GetPeerAddress () <<
1099  ":" << m_endPoint->GetPeerPort () <<
1100  " to " << m_endPoint->GetLocalAddress () <<
1101  ":" << m_endPoint->GetLocalPort ());
1102 
1103  Address fromAddress = InetSocketAddress (header.GetSource (), port);
1104  Address toAddress = InetSocketAddress (header.GetDestination (),
1105  m_endPoint->GetLocalPort ());
1106 
1107  DoForwardUp (packet, fromAddress, toAddress);
1108 }
1109 
1110 void
1112  Ptr<Ipv6Interface> incomingInterface)
1113 {
1114  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1116  ":" << m_endPoint6->GetPeerPort () <<
1117  " to " << m_endPoint6->GetLocalAddress () <<
1118  ":" << m_endPoint6->GetLocalPort ());
1119 
1120  Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port);
1121  Address toAddress = Inet6SocketAddress (header.GetDestinationAddress (),
1123 
1124  DoForwardUp (packet, fromAddress, toAddress);
1125 }
1126 
1127 void
1128 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1129  uint8_t icmpType, uint8_t icmpCode,
1130  uint32_t icmpInfo)
1131 {
1132  NS_LOG_FUNCTION (this << icmpSource << static_cast<uint32_t> (icmpTtl) <<
1133  static_cast<uint32_t> (icmpType) <<
1134  static_cast<uint32_t> (icmpCode) << icmpInfo);
1135  if (!m_icmpCallback.IsNull ())
1136  {
1137  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1138  }
1139 }
1140 
1141 void
1142 TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1143  uint8_t icmpType, uint8_t icmpCode,
1144  uint32_t icmpInfo)
1145 {
1146  NS_LOG_FUNCTION (this << icmpSource << static_cast<uint32_t> (icmpTtl) <<
1147  static_cast<uint32_t> (icmpType) <<
1148  static_cast<uint32_t> (icmpCode) << icmpInfo);
1149  if (!m_icmpCallback6.IsNull ())
1150  {
1151  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1152  }
1153 }
1154 
1155 void
1156 TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress,
1157  const Address &toAddress)
1158 {
1159  // in case the packet still has a priority tag attached, remove it
1160  SocketPriorityTag priorityTag;
1161  packet->RemovePacketTag (priorityTag);
1162 
1163  // Peel off TCP header and do validity checking
1164  TcpHeader tcpHeader;
1165  uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader);
1166  SequenceNumber32 seq = tcpHeader.GetSequenceNumber ();
1167  if (bytesRemoved == 0 || bytesRemoved > 60)
1168  {
1169  NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid");
1170  return; // Discard invalid packet
1171  }
1172  else if (packet->GetSize () > 0 && OutOfRange (seq, seq + packet->GetSize ()))
1173  {
1174  // Discard fully out of range data packets
1175  NS_LOG_WARN ("At state " << TcpStateName[m_state] <<
1176  " received packet of seq [" << seq <<
1177  ":" << seq + packet->GetSize () <<
1178  ") out of range [" << m_rxBuffer->NextRxSequence () << ":" <<
1179  m_rxBuffer->MaxRxSequence () << ")");
1180  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
1181  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
1182  {
1184  }
1185  return;
1186  }
1187 
1188  m_rxTrace (packet, tcpHeader, this);
1189 
1190  if (tcpHeader.GetFlags () & TcpHeader::SYN)
1191  {
1192  /* The window field in a segment where the SYN bit is set (i.e., a <SYN>
1193  * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be
1194  * saved anyway..
1195  */
1196  m_rWnd = tcpHeader.GetWindowSize ();
1197 
1199  {
1201  }
1202  else
1203  {
1204  m_winScalingEnabled = false;
1205  }
1206 
1208  {
1210  }
1211  else
1212  {
1213  m_sackEnabled = false;
1214  }
1215 
1216  // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end
1217  if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled)
1218  {
1220  tcpHeader.GetSequenceNumber ());
1221  }
1222  else
1223  {
1224  m_timestampEnabled = false;
1225  }
1226 
1227  // Initialize cWnd and ssThresh
1229  m_cWndInfl = m_tcb->m_cWnd;
1231 
1232  if (tcpHeader.GetFlags () & TcpHeader::ACK)
1233  {
1234  EstimateRtt (tcpHeader);
1235  m_highRxAckMark = tcpHeader.GetAckNumber ();
1236  }
1237  }
1238  else if (tcpHeader.GetFlags () & TcpHeader::ACK)
1239  {
1240  NS_ASSERT (!(tcpHeader.GetFlags () & TcpHeader::SYN));
1241  if (m_timestampEnabled)
1242  {
1243  if (!tcpHeader.HasOption (TcpOption::TS))
1244  {
1245  // Ignoring segment without TS, RFC 7323
1246  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1247  " received packet of seq [" << seq <<
1248  ":" << seq + packet->GetSize () <<
1249  ") without TS option. Silently discard it");
1250  return;
1251  }
1252  else
1253  {
1255  tcpHeader.GetSequenceNumber ());
1256  }
1257  }
1258 
1259  EstimateRtt (tcpHeader);
1260  UpdateWindowSize (tcpHeader);
1261  }
1262 
1263 
1264  if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ())
1265  { // Zero window: Enter persist state to send 1 byte to probe
1266  NS_LOG_LOGIC (this << " Enter zerowindow persist state");
1267  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1268  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1269  m_retxEvent.Cancel ();
1270  NS_LOG_LOGIC ("Schedule persist timeout at time " <<
1271  Simulator::Now ().GetSeconds () << " to expire at time " <<
1272  (Simulator::Now () + m_persistTimeout).GetSeconds ());
1275  }
1276 
1277  // TCP state machine code in different process functions
1278  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1279  switch (m_state)
1280  {
1281  case ESTABLISHED:
1282  ProcessEstablished (packet, tcpHeader);
1283  break;
1284  case LISTEN:
1285  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
1286  break;
1287  case TIME_WAIT:
1288  // Do nothing
1289  break;
1290  case CLOSED:
1291  // Send RST if the incoming packet is not a RST
1292  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1293  { // Since m_endPoint is not configured yet, we cannot use SendRST here
1294  TcpHeader h;
1295  Ptr<Packet> p = Create<Packet> ();
1298  h.SetAckNumber (m_rxBuffer->NextRxSequence ());
1299  h.SetSourcePort (tcpHeader.GetDestinationPort ());
1300  h.SetDestinationPort (tcpHeader.GetSourcePort ());
1302  AddOptions (h);
1303  m_txTrace (p, h, this);
1304  m_tcp->SendPacket (p, h, toAddress, fromAddress, m_boundnetdevice);
1305  }
1306  break;
1307  case SYN_SENT:
1308  ProcessSynSent (packet, tcpHeader);
1309  break;
1310  case SYN_RCVD:
1311  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1312  break;
1313  case FIN_WAIT_1:
1314  case FIN_WAIT_2:
1315  case CLOSE_WAIT:
1316  ProcessWait (packet, tcpHeader);
1317  break;
1318  case CLOSING:
1319  ProcessClosing (packet, tcpHeader);
1320  break;
1321  case LAST_ACK:
1322  ProcessLastAck (packet, tcpHeader);
1323  break;
1324  default: // mute compiler
1325  break;
1326  }
1327 
1328  if (m_rWnd.Get () != 0 && m_persistEvent.IsRunning ())
1329  { // persist probes end, the other end has increased the window
1331  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
1333 
1335  }
1336 }
1337 
1338 /* Received a packet upon ESTABLISHED state. This function is mimicking the
1339  role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1340 void
1342 {
1343  NS_LOG_FUNCTION (this << tcpHeader);
1344 
1345  // Extract the flags. PSH and URG are not honoured.
1346  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1347 
1348  // Different flags are different events
1349  if (tcpflags == TcpHeader::ACK)
1350  {
1351  if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ())
1352  {
1353  // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be ignored.
1354  // Pag. 72 RFC 793
1355  NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1356  " SND.UNA = " << m_txBuffer->HeadSequence ());
1357 
1358  // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation]
1359  }
1360  else if (tcpHeader.GetAckNumber () > m_tcb->m_highTxMark)
1361  {
1362  // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then
1363  // send an ACK, drop the segment, and return.
1364  // Pag. 72 RFC 793
1365  NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1366  " HighTxMark = " << m_tcb->m_highTxMark);
1367 
1369  }
1370  else
1371  {
1372  // SND.UNA < SEG.ACK =< HighTxMark
1373  // Pag. 72 RFC 793
1374  ReceivedAck (packet, tcpHeader);
1375  }
1376  }
1377  else if (tcpflags == TcpHeader::SYN)
1378  { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1379  // respond with a SYN+ACK. But it is not a legal state transition as of
1380  // RFC793. Thus this is ignored.
1381  }
1382  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1383  { // No action for received SYN+ACK, it is probably a duplicated packet
1384  }
1385  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1386  { // Received FIN or FIN+ACK, bring down this socket nicely
1387  PeerClose (packet, tcpHeader);
1388  }
1389  else if (tcpflags == 0)
1390  { // No flags means there is only data
1391  ReceivedData (packet, tcpHeader);
1392  if (m_rxBuffer->Finished ())
1393  {
1394  PeerClose (packet, tcpHeader);
1395  }
1396  }
1397  else
1398  { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1399  if (tcpflags != TcpHeader::RST)
1400  { // this must be an invalid flag, send reset
1401  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
1402  SendRST ();
1403  }
1404  CloseAndNotify ();
1405  }
1406 }
1407 
1408 bool
1410 {
1411  NS_LOG_FUNCTION (this << static_cast<uint32_t> (kind));
1412 
1413  switch (kind)
1414  {
1415  case TcpOption::TS:
1416  return m_timestampEnabled;
1417  case TcpOption::WINSCALE:
1418  return m_winScalingEnabled;
1420  case TcpOption::SACK:
1421  return m_sackEnabled;
1422  default:
1423  break;
1424  }
1425  return false;
1426 }
1427 
1428 void
1429 TcpSocketBase::ReadOptions (const TcpHeader &tcpHeader, bool &scoreboardUpdated)
1430 {
1431  NS_LOG_FUNCTION (this << tcpHeader);
1432  TcpHeader::TcpOptionList::const_iterator it;
1433  const TcpHeader::TcpOptionList options = tcpHeader.GetOptionList ();
1434 
1435  for (it = options.begin (); it != options.end (); ++it)
1436  {
1437  const Ptr<const TcpOption> option = (*it);
1438 
1439  // Check only for ACK options here
1440  switch (option->GetKind ())
1441  {
1442  case TcpOption::SACK:
1443  scoreboardUpdated = ProcessOptionSack (option);
1444  break;
1445  default:
1446  continue;
1447  }
1448  }
1449 }
1450 
1451 void
1453 {
1454  NS_LOG_FUNCTION (this);
1456 
1457  NS_LOG_DEBUG (TcpSocketState::TcpCongStateName[m_tcb->m_congState] <<
1458  " -> CA_RECOVERY");
1459 
1460  if (!m_sackEnabled)
1461  {
1462  // One segment has left the network, PLUS the head is lost
1463  m_txBuffer->AddRenoSack ();
1464  m_txBuffer->MarkHeadAsLost ();
1465  }
1466  else
1467  {
1468  if (! m_txBuffer->IsLost (m_txBuffer->HeadSequence ()))
1469  {
1470  // We received 3 dupacks, but the head is not marked as lost
1471  // (received less than 3 SACK block ahead).
1472  // Manually set it as lost.
1473  m_txBuffer->MarkHeadAsLost ();
1474  }
1475  }
1476 
1477  // RFC 6675, point (4):
1478  // (4) Invoke fast retransmit and enter loss recovery as follows:
1479  // (4.1) RecoveryPoint = HighData
1481 
1482  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_RECOVERY);
1484 
1485  // (4.2) ssthresh = cwnd = (FlightSize / 2)
1486  // If SACK is not enabled, still consider the head as 'in flight' for
1487  // compatibility with old ns-3 versions
1488  uint32_t bytesInFlight = m_sackEnabled ? BytesInFlight () : BytesInFlight () + m_tcb->m_segmentSize;
1489  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, bytesInFlight);
1492 
1493  NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." <<
1494  "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
1495  m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover <<
1496  " calculated in flight: " << bytesInFlight);
1497 
1498  // (4.3) Retransmit the first data segment presumed dropped
1499  DoRetransmit ();
1500  // (4.4) Run SetPipe ()
1501  // (4.5) Proceed to step (C)
1502  // these steps are done after the ProcessAck function (SendPendingData)
1503 }
1504 
1505 void
1507 {
1508  NS_LOG_FUNCTION (this);
1509  // NOTE: We do not count the DupAcks received in CA_LOSS, because we
1510  // don't know if they are generated by a spurious retransmission or because
1511  // of a real packet loss. With SACK, it is easy to know, but we do not consider
1512  // dupacks. Without SACK, there are some euristics in the RFC 6582, but
1513  // for now, we do not implement it, leading to ignoring the dupacks.
1515  {
1516  return;
1517  }
1518 
1519  // RFC 6675, Section 5, 3rd paragraph:
1520  // If the incoming ACK is a duplicate acknowledgment per the definition
1521  // in Section 2 (regardless of its status as a cumulative
1522  // acknowledgment), and the TCP is not currently in loss recovery
1523  // the TCP MUST increase DupAcks by one ...
1525  {
1526  ++m_dupAckCount;
1527  }
1528 
1530  {
1531  // If we are in recovery and we receive a dupack, one segment
1532  // has left the network. This is equivalent to a SACK of one block.
1533  m_txBuffer->AddRenoSack ();
1534 
1536  }
1537 
1539  {
1540  // From Open we go Disorder
1541  NS_ASSERT_MSG (m_dupAckCount == 1, "From OPEN->DISORDER but with " <<
1542  m_dupAckCount << " dup ACKs");
1543 
1544  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_DISORDER);
1546 
1547  NS_LOG_DEBUG ("CA_OPEN -> CA_DISORDER");
1548  }
1549 
1551  {
1552  // RFC 6675, Section 5, continuing:
1553  // ... and take the following steps:
1554  // (1) If DupAcks >= DupThresh, go to step (4).
1556  {
1557  EnterRecovery ();
1559  }
1560  // (2) If DupAcks < DupThresh but IsLost (HighACK + 1) returns true
1561  // (indicating at least three segments have arrived above the current
1562  // cumulative acknowledgment point, which is taken to indicate loss)
1563  // go to step (4).
1564  else if (m_txBuffer->IsLost (m_highRxAckMark + m_tcb->m_segmentSize))
1565  {
1566  EnterRecovery ();
1568  }
1569  else
1570  {
1571  // (3) The TCP MAY transmit previously unsent data segments as per
1572  // Limited Transmit [RFC5681] ...except that the number of octets
1573  // which may be sent is governed by pipe and cwnd as follows:
1574  //
1575  // (3.1) Set HighRxt to HighACK.
1576  // Not clear in RFC. We don't do this here, since we still have
1577  // to retransmit the segment.
1578 
1579  if (!m_sackEnabled && m_limitedTx)
1580  {
1581  m_txBuffer->AddRenoSack ();
1582 
1583  // In limited transmit, cwnd Infl is not updated.
1584  }
1585  }
1586  }
1587 }
1588 
1589 /* Process the newly received ACK */
1590 void
1592 {
1593  NS_LOG_FUNCTION (this << tcpHeader);
1594 
1595  NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK));
1596  NS_ASSERT (m_tcb->m_segmentSize > 0);
1597 
1598  // RFC 6675, Section 5, 1st paragraph:
1599  // Upon the receipt of any ACK containing SACK information, the
1600  // scoreboard MUST be updated via the Update () routine (done in ReadOptions)
1601  bool scoreboardUpdated = false;
1602  ReadOptions (tcpHeader, scoreboardUpdated);
1603 
1604  SequenceNumber32 ackNumber = tcpHeader.GetAckNumber ();
1605  SequenceNumber32 oldHeadSequence = m_txBuffer->HeadSequence ();
1606  m_txBuffer->DiscardUpTo (ackNumber);
1607 
1608  // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation
1609  // are inside the function ProcessAck
1610  ProcessAck (ackNumber, scoreboardUpdated, oldHeadSequence);
1611 
1612  // If there is any data piggybacked, store it into m_rxBuffer
1613  if (packet->GetSize () > 0)
1614  {
1615  ReceivedData (packet, tcpHeader);
1616  }
1617 
1618  // RFC 6675, Section 5, point (C), try to send more data. NB: (C) is implemented
1619  // inside SendPendingData
1621 }
1622 
1623 void
1624 TcpSocketBase::ProcessAck (const SequenceNumber32 &ackNumber, bool scoreboardUpdated,
1625  const SequenceNumber32 &oldHeadSequence)
1626 {
1627  NS_LOG_FUNCTION (this << ackNumber << scoreboardUpdated);
1628  // RFC 6675, Section 5, 2nd paragraph:
1629  // If the incoming ACK is a cumulative acknowledgment, the TCP MUST
1630  // reset DupAcks to zero.
1631  bool exitedFastRecovery = false;
1632  uint32_t oldDupAckCount = m_dupAckCount; // remember the old value
1633  m_tcb->m_lastAckedSeq = ackNumber; // Update lastAckedSeq
1634 
1635  /* In RFC 5681 the definition of duplicate acknowledgment was strict:
1636  *
1637  * (a) the receiver of the ACK has outstanding data,
1638  * (b) the incoming acknowledgment carries no data,
1639  * (c) the SYN and FIN bits are both off,
1640  * (d) the acknowledgment number is equal to the greatest acknowledgment
1641  * received on the given connection (TCP.UNA from [RFC793]),
1642  * (e) the advertised window in the incoming acknowledgment equals the
1643  * advertised window in the last incoming acknowledgment.
1644  *
1645  * With RFC 6675, this definition has been reduced:
1646  *
1647  * (a) the ACK is carrying a SACK block that identifies previously
1648  * unacknowledged and un-SACKed octets between HighACK (TCP.UNA) and
1649  * HighData (m_highTxMark)
1650  */
1651 
1652  bool isDupack = m_sackEnabled ?
1653  scoreboardUpdated
1654  : ackNumber == oldHeadSequence &&
1655  ackNumber < m_tcb->m_highTxMark;
1656 
1657  NS_LOG_DEBUG ("ACK of " << ackNumber <<
1658  " SND.UNA=" << oldHeadSequence <<
1659  " SND.NXT=" << m_tcb->m_nextTxSequence <<
1660  " in state: " << TcpSocketState::TcpCongStateName[m_tcb->m_congState] <<
1661  " with m_recover: " << m_recover);
1662 
1663  // RFC 6675, Section 5, 3rd paragraph:
1664  // If the incoming ACK is a duplicate acknowledgment per the definition
1665  // in Section 2 (regardless of its status as a cumulative
1666  // acknowledgment), and the TCP is not currently in loss recovery
1667  if (isDupack)
1668  {
1669  // loss recovery check is done inside this function thanks to
1670  // the congestion state machine
1671  DupAck ();
1672  }
1673 
1674  if (ackNumber == oldHeadSequence
1675  && ackNumber == m_tcb->m_highTxMark)
1676  {
1677  // Dupack, but the ACK is precisely equal to the nextTxSequence
1678  return;
1679  }
1680  else if (ackNumber == oldHeadSequence
1681  && ackNumber > m_tcb->m_highTxMark)
1682  {
1683  // ACK of the FIN bit ... nextTxSequence is not updated since we
1684  // don't have anything to transmit
1685  NS_LOG_DEBUG ("Update nextTxSequence manually to " << ackNumber);
1686  m_tcb->m_nextTxSequence = ackNumber;
1687  }
1688  else if (ackNumber == oldHeadSequence)
1689  {
1690  // DupAck. Artificially call PktsAcked: after all, one segment has been ACKed.
1691  m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt);
1692  }
1693  else if (ackNumber > oldHeadSequence)
1694  {
1695  // Please remember that, with SACK, we can enter here even if we
1696  // received a dupack.
1697  uint32_t bytesAcked = ackNumber - oldHeadSequence;
1698  uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
1699  m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize;
1700 
1702  {
1703  segsAcked += 1;
1705  }
1706 
1707  // Dupack count is reset to eventually fast-retransmit after 3 dupacks.
1708  // Any SACK-ed segment will be cleaned up by DiscardUpTo.
1709  // In the case that we advanced SND.UNA, but the ack contains SACK blocks,
1710  // we do not reset. At the third one we will retransmit.
1711  // If we are already in recovery, this check is useless since dupAcks
1712  // are not considered in this phase. When from Recovery we go back
1713  // to open, then dupAckCount is reset anyway.
1714  if (!isDupack)
1715  {
1716  m_dupAckCount = 0;
1717  }
1718 
1719  // RFC 6675, Section 5, part (B)
1720  // (B) Upon receipt of an ACK that does not cover RecoveryPoint, the
1721  // following actions MUST be taken:
1722  //
1723  // (B.1) Use Update () to record the new SACK information conveyed
1724  // by the incoming ACK.
1725  // (B.2) Use SetPipe () to re-calculate the number of octets still
1726  // in the network.
1727  //
1728  // (B.1) is done at the beginning, while (B.2) is delayed to part (C) while
1729  // trying to transmit with SendPendingData. We are not allowed to exit
1730  // the CA_RECOVERY phase. Just process this partial ack (RFC 5681)
1731  if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1732  {
1733  if (!m_sackEnabled)
1734  {
1735  // Manually set the head as lost, it will be retransmitted.
1736  NS_LOG_INFO ("Partial ACK. Manually setting head as lost");
1737  m_txBuffer->MarkHeadAsLost ();
1738  }
1739  else
1740  {
1741  // We received a partial ACK, if we retransmitted this segment
1742  // probably is better to retransmit it
1743  m_txBuffer->DeleteRetransmittedFlagFromHead ();
1744  }
1745  DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
1746  m_cWndInfl = SafeSubtraction (m_cWndInfl, bytesAcked);
1747  if (segsAcked >= 1)
1748  {
1750  }
1751 
1752  // This partial ACK acknowledge the fact that one segment has been
1753  // previously lost and now successfully received. All others have
1754  // been processed when they come under the form of dupACKs
1755  m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt);
1756  NewAck (ackNumber, m_isFirstPartialAck);
1757 
1758  if (m_isFirstPartialAck)
1759  {
1760  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
1761  " and this is the first (RTO will be reset);"
1762  " cwnd set to " << m_tcb->m_cWnd <<
1763  " recover seq: " << m_recover <<
1764  " dupAck count: " << m_dupAckCount);
1765  m_isFirstPartialAck = false;
1766  }
1767  else
1768  {
1769  NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
1770  " and this is NOT the first (RTO will not be reset)"
1771  " cwnd set to " << m_tcb->m_cWnd <<
1772  " recover seq: " << m_recover <<
1773  " dupAck count: " << m_dupAckCount);
1774  }
1775  }
1776  // From RFC 6675 section 5.1
1777  // In addition, a new recovery phase (as described in Section 5) MUST NOT
1778  // be initiated until HighACK is greater than or equal to the new value
1779  // of RecoveryPoint.
1780  else if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_LOSS)
1781  {
1782  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1783  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
1784 
1785  NS_LOG_DEBUG (" Cong Control Called, cWnd=" << m_tcb->m_cWnd <<
1786  " ssTh=" << m_tcb->m_ssThresh);
1787  if (!m_sackEnabled)
1788  {
1789  NS_ASSERT_MSG (m_txBuffer->GetSacked () == 0,
1790  "Some segment got dup-acked in CA_LOSS state: " <<
1791  m_txBuffer->GetSacked ());
1792  }
1793  NewAck (ackNumber, true);
1794  }
1795  else
1796  {
1798  {
1799  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1800  }
1802  {
1803  if (segsAcked >= oldDupAckCount)
1804  {
1805  m_congestionControl->PktsAcked (m_tcb, segsAcked - oldDupAckCount, m_lastRtt);
1806  }
1807 
1808  if (!isDupack)
1809  {
1810  // The network reorder packets. Linux changes the counting lost
1811  // packet algorithm from FACK to NewReno. We simply go back in Open.
1812  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1814  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
1815  ackNumber << " exiting CA_DISORDER -> CA_OPEN");
1816  }
1817  else
1818  {
1819  NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
1820  ackNumber << " but still in CA_DISORDER");
1821  }
1822  }
1823  // RFC 6675, Section 5:
1824  // Once a TCP is in the loss recovery phase, the following procedure
1825  // MUST be used for each arriving ACK:
1826  // (A) An incoming cumulative ACK for a sequence number greater than
1827  // RecoveryPoint signals the end of loss recovery, and the loss
1828  // recovery phase MUST be terminated. Any information contained in
1829  // the scoreboard for sequence numbers greater than the new value of
1830  // HighACK SHOULD NOT be cleared when leaving the loss recovery
1831  // phase.
1833  {
1834  m_isFirstPartialAck = true;
1835 
1836  // Recalculate the segs acked, that are from m_recover to ackNumber
1837  // (which are the ones we have not passed to PktsAcked and that
1838  // can increase cWnd)
1839  segsAcked = static_cast<uint32_t>(ackNumber - m_recover) / m_tcb->m_segmentSize;
1840  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1842  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1844  exitedFastRecovery = true;
1845  m_dupAckCount = 0; // From recovery to open, reset dupack
1846 
1847  NS_LOG_DEBUG (segsAcked << " segments acked in CA_RECOVER, ack of " <<
1848  ackNumber << ", exiting CA_RECOVERY -> CA_OPEN");
1849  }
1851  {
1852  m_isFirstPartialAck = true;
1853 
1854  // Recalculate the segs acked, that are from m_recover to ackNumber
1855  // (which are the ones we have not passed to PktsAcked and that
1856  // can increase cWnd)
1857  segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
1858 
1859  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1860 
1861  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1863  NS_LOG_DEBUG (segsAcked << " segments acked in CA_LOSS, ack of" <<
1864  ackNumber << ", exiting CA_LOSS -> CA_OPEN");
1865  }
1866 
1867  if (exitedFastRecovery)
1868  {
1869  NewAck (ackNumber, true);
1870  // Follow NewReno procedures to exit FR if SACK is disabled
1871  // (RFC2582 sec.3 bullet #5 paragraph 2, option 2)
1873  // For SACK connections, we maintain the cwnd = ssthresh. In fact,
1874  // this ACK was received in RECOVERY phase, not in OPEN. So we
1875  // are not allowed to increase the window
1876  NS_LOG_DEBUG ("Leaving Fast Recovery; BytesInFlight() = " <<
1877  BytesInFlight () << "; cWnd = " << m_tcb->m_cWnd);
1878  }
1879  else
1880  {
1881  m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
1882 
1883  m_cWndInfl = m_tcb->m_cWnd;
1884 
1885  NS_LOG_LOGIC ("Congestion control called: " <<
1886  " cWnd: " << m_tcb->m_cWnd <<
1887  " ssTh: " << m_tcb->m_ssThresh <<
1888  " segsAcked: " << segsAcked);
1889 
1890  NewAck (ackNumber, true);
1891  }
1892  }
1893  }
1894 }
1895 
1896 /* Received a packet upon LISTEN state. */
1897 void
1899  const Address& fromAddress, const Address& toAddress)
1900 {
1901  NS_LOG_FUNCTION (this << tcpHeader);
1902 
1903  // Extract the flags. PSH and URG are not honoured.
1904  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1905 
1906  // Fork a socket if received a SYN. Do nothing otherwise.
1907  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
1908  if (tcpflags != TcpHeader::SYN)
1909  {
1910  return;
1911  }
1912 
1913  // Call socket's notify function to let the server app know we got a SYN
1914  // If the server app refuses the connection, do nothing
1915  if (!NotifyConnectionRequest (fromAddress))
1916  {
1917  return;
1918  }
1919  // Clone the socket, simulate fork
1920  Ptr<TcpSocketBase> newSock = Fork ();
1921  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
1923  packet, tcpHeader, fromAddress, toAddress);
1924 }
1925 
1926 /* Received a packet upon SYN_SENT */
1927 void
1929 {
1930  NS_LOG_FUNCTION (this << tcpHeader);
1931 
1932  // Extract the flags. PSH and URG are not honoured.
1933  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1934 
1935  if (tcpflags == 0)
1936  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
1937  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
1938  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1939  m_state = ESTABLISHED;
1940  m_connected = true;
1941  m_retxEvent.Cancel ();
1943  ReceivedData (packet, tcpHeader);
1945  }
1946  else if (tcpflags == TcpHeader::ACK)
1947  { // Ignore ACK in SYN_SENT
1948  }
1949  else if (tcpflags == TcpHeader::SYN)
1950  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
1951  NS_LOG_DEBUG ("SYN_SENT -> SYN_RCVD");
1952  m_state = SYN_RCVD;
1954  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1956  }
1957  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK)
1958  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
1959  { // Handshake completed
1960  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
1961  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1962  m_state = ESTABLISHED;
1963  m_connected = true;
1964  m_retxEvent.Cancel ();
1965  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1967  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
1971  // Always respond to first data packet to speed up the connection.
1972  // Remove to get the behaviour of old NS-3 code.
1974  }
1975  else
1976  { // Other in-sequence input
1977  if (tcpflags != TcpHeader::RST)
1978  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
1979  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
1980  " received. Reset packet is sent.");
1981  SendRST ();
1982  }
1983  CloseAndNotify ();
1984  }
1985 }
1986 
1987 /* Received a packet upon SYN_RCVD */
1988 void
1990  const Address& fromAddress, const Address& toAddress)
1991 {
1992  NS_UNUSED (toAddress);
1993  NS_LOG_FUNCTION (this << tcpHeader);
1994 
1995  // Extract the flags. PSH and URG are not honoured.
1996  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1997 
1998  if (tcpflags == 0
1999  || (tcpflags == TcpHeader::ACK
2000  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
2001  { // If it is bare data, accept it and move to ESTABLISHED state. This is
2002  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
2003  // handshake is completed nicely.
2004  NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED");
2005  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2006  m_state = ESTABLISHED;
2007  m_connected = true;
2008  m_retxEvent.Cancel ();
2010  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2011  if (m_endPoint)
2012  {
2013  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2014  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2015  }
2016  else if (m_endPoint6)
2017  {
2018  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2019  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2020  }
2021  // Always respond to first data packet to speed up the connection.
2022  // Remove to get the behaviour of old NS-3 code.
2024  NotifyNewConnectionCreated (this, fromAddress);
2025  ReceivedAck (packet, tcpHeader);
2026  // As this connection is established, the socket is available to send data now
2027  if (GetTxAvailable () > 0)
2028  {
2030  }
2031  }
2032  else if (tcpflags == TcpHeader::SYN)
2033  { // Probably the peer lost my SYN+ACK
2034  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2036  }
2037  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2038  {
2039  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
2040  { // In-sequence FIN before connection complete. Set up connection and close.
2041  m_connected = true;
2042  m_retxEvent.Cancel ();
2044  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2045  if (m_endPoint)
2046  {
2047  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2048  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2049  }
2050  else if (m_endPoint6)
2051  {
2052  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2053  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2054  }
2055  NotifyNewConnectionCreated (this, fromAddress);
2056  PeerClose (packet, tcpHeader);
2057  }
2058  }
2059  else
2060  { // Other in-sequence input
2061  if (tcpflags != TcpHeader::RST)
2062  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
2063  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2064  " received. Reset packet is sent.");
2065  if (m_endPoint)
2066  {
2067  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2068  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2069  }
2070  else if (m_endPoint6)
2071  {
2072  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2073  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2074  }
2075  SendRST ();
2076  }
2077  CloseAndNotify ();
2078  }
2079 }
2080 
2081 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
2082 void
2084 {
2085  NS_LOG_FUNCTION (this << tcpHeader);
2086 
2087  // Extract the flags. PSH and URG are not honoured.
2088  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2089 
2090  if (packet->GetSize () > 0 && !(tcpflags & TcpHeader::ACK))
2091  { // Bare data, accept it
2092  ReceivedData (packet, tcpHeader);
2093  }
2094  else if (tcpflags == TcpHeader::ACK)
2095  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
2096  ReceivedAck (packet, tcpHeader);
2097  if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
2098  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2099  { // This ACK corresponds to the FIN sent
2100  NS_LOG_DEBUG ("FIN_WAIT_1 -> FIN_WAIT_2");
2101  m_state = FIN_WAIT_2;
2102  }
2103  }
2104  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2105  { // Got FIN, respond with ACK and move to next state
2106  if (tcpflags & TcpHeader::ACK)
2107  { // Process the ACK first
2108  ReceivedAck (packet, tcpHeader);
2109  }
2110  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
2111  }
2112  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
2113  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
2114  return;
2115  }
2116  else
2117  { // This is a RST or bad flags
2118  if (tcpflags != TcpHeader::RST)
2119  {
2120  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2121  " received. Reset packet is sent.");
2122  SendRST ();
2123  }
2124  CloseAndNotify ();
2125  return;
2126  }
2127 
2128  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
2129  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_rxBuffer->Finished ())
2130  {
2131  if (m_state == FIN_WAIT_1)
2132  {
2133  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2134  m_state = CLOSING;
2135  if (m_txBuffer->Size () == 0
2136  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2137  { // This ACK corresponds to the FIN sent
2138  TimeWait ();
2139  }
2140  }
2141  else if (m_state == FIN_WAIT_2)
2142  {
2143  TimeWait ();
2144  }
2146  if (!m_shutdownRecv)
2147  {
2148  NotifyDataRecv ();
2149  }
2150  }
2151 }
2152 
2153 /* Received a packet upon CLOSING */
2154 void
2156 {
2157  NS_LOG_FUNCTION (this << tcpHeader);
2158 
2159  // Extract the flags. PSH and URG are not honoured.
2160  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2161 
2162  if (tcpflags == TcpHeader::ACK)
2163  {
2164  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
2165  { // This ACK corresponds to the FIN sent
2166  TimeWait ();
2167  }
2168  }
2169  else
2170  { // CLOSING state means simultaneous close, i.e. no one is sending data to
2171  // anyone. If anything other than ACK is received, respond with a reset.
2172  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2173  { // FIN from the peer as well. We can close immediately.
2175  }
2176  else if (tcpflags != TcpHeader::RST)
2177  { // Receive of SYN or SYN+ACK or bad flags or pure data
2178  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2179  SendRST ();
2180  }
2181  CloseAndNotify ();
2182  }
2183 }
2184 
2185 /* Received a packet upon LAST_ACK */
2186 void
2188 {
2189  NS_LOG_FUNCTION (this << tcpHeader);
2190 
2191  // Extract the flags. PSH and URG are not honoured.
2192  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2193 
2194  if (tcpflags == 0)
2195  {
2196  ReceivedData (packet, tcpHeader);
2197  }
2198  else if (tcpflags == TcpHeader::ACK)
2199  {
2200  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
2201  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
2202  CloseAndNotify ();
2203  }
2204  }
2205  else if (tcpflags == TcpHeader::FIN)
2206  { // Received FIN again, the peer probably lost the FIN+ACK
2208  }
2209  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2210  {
2211  CloseAndNotify ();
2212  }
2213  else
2214  { // Received a SYN or SYN+ACK or bad flags
2215  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2216  SendRST ();
2217  CloseAndNotify ();
2218  }
2219 }
2220 
2221 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
2222 void
2224 {
2225  NS_LOG_FUNCTION (this << tcpHeader);
2226 
2227  // Ignore all out of range packets
2228  if (tcpHeader.GetSequenceNumber () < m_rxBuffer->NextRxSequence ()
2229  || tcpHeader.GetSequenceNumber () > m_rxBuffer->MaxRxSequence ())
2230  {
2231  return;
2232  }
2233  // For any case, remember the FIN position in rx buffer first
2234  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2235  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2236  // If there is any piggybacked data, process it
2237  if (p->GetSize ())
2238  {
2239  ReceivedData (p, tcpHeader);
2240  }
2241  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2242  if (!m_rxBuffer->Finished ())
2243  {
2244  return;
2245  }
2246 
2247  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2248  if (m_state == FIN_WAIT_1)
2249  {
2250  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2251  m_state = CLOSING;
2252  return;
2253  }
2254 
2255  DoPeerClose (); // Change state, respond with ACK
2256 }
2257 
2258 /* Received a in-sequence FIN. Close down this socket. */
2259 void
2261 {
2264 
2265  // Move the state to CLOSE_WAIT
2266  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSE_WAIT");
2267  m_state = CLOSE_WAIT;
2268 
2269  if (!m_closeNotified)
2270  {
2271  // The normal behaviour for an application is that, when the peer sent a in-sequence
2272  // FIN, the app should prepare to close. The app has two choices at this point: either
2273  // respond with ShutdownSend() call to declare that it has nothing more to send and
2274  // the socket can be closed immediately; or remember the peer's close request, wait
2275  // until all its existing data are pushed into the TCP socket, then call Close()
2276  // explicitly.
2277  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
2278  NotifyNormalClose ();
2279  m_closeNotified = true;
2280  }
2281  if (m_shutdownSend)
2282  { // The application declares that it would not sent any more, close this socket
2283  Close ();
2284  }
2285  else
2286  { // Need to ack, the application will close later
2288  }
2289  if (m_state == LAST_ACK)
2290  {
2291  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
2292  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
2294  }
2295 }
2296 
2297 /* Kill this socket. This is a callback function configured to m_endpoint in
2298  SetupCallback(), invoked when the endpoint is destroyed. */
2299 void
2301 {
2302  NS_LOG_FUNCTION (this);
2303  m_endPoint = nullptr;
2304  if (m_tcp != nullptr)
2305  {
2306  m_tcp->RemoveSocket (this);
2307  }
2308  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2309  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2310  CancelAllTimers ();
2311 }
2312 
2313 /* Kill this socket. This is a callback function configured to m_endpoint in
2314  SetupCallback(), invoked when the endpoint is destroyed. */
2315 void
2317 {
2318  NS_LOG_FUNCTION (this);
2319  m_endPoint6 = nullptr;
2320  if (m_tcp != nullptr)
2321  {
2322  m_tcp->RemoveSocket (this);
2323  }
2324  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2325  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2326  CancelAllTimers ();
2327 }
2328 
2329 /* Send an empty packet with specified TCP flags */
2330 void
2332 {
2333  NS_LOG_FUNCTION (this << static_cast<uint32_t> (flags));
2334 
2335  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
2336  {
2337  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
2338  return;
2339  }
2340 
2341  Ptr<Packet> p = Create<Packet> ();
2342  TcpHeader header;
2344 
2345  if (flags & TcpHeader::FIN)
2346  {
2347  flags |= TcpHeader::ACK;
2348  }
2349  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2350  {
2351  ++s;
2352  }
2353 
2354  AddSocketTags (p);
2355 
2356  header.SetFlags (flags);
2357  header.SetSequenceNumber (s);
2358  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2359  if (m_endPoint != nullptr)
2360  {
2361  header.SetSourcePort (m_endPoint->GetLocalPort ());
2362  header.SetDestinationPort (m_endPoint->GetPeerPort ());
2363  }
2364  else
2365  {
2366  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2367  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
2368  }
2369  AddOptions (header);
2370 
2371  // RFC 6298, clause 2.4
2372  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2373 
2374  uint16_t windowSize = AdvertisedWindowSize ();
2375  bool hasSyn = flags & TcpHeader::SYN;
2376  bool hasFin = flags & TcpHeader::FIN;
2377  bool isAck = flags == TcpHeader::ACK;
2378  if (hasSyn)
2379  {
2380  if (m_winScalingEnabled)
2381  { // The window scaling option is set only on SYN packets
2382  AddOptionWScale (header);
2383  }
2384 
2385  if (m_sackEnabled)
2386  {
2387  AddOptionSackPermitted (header);
2388  }
2389 
2390  if (m_synCount == 0)
2391  { // No more connection retries, give up
2392  NS_LOG_LOGIC ("Connection failed.");
2393  m_rtt->Reset (); //According to recommendation -> RFC 6298
2394  CloseAndNotify ();
2395  return;
2396  }
2397  else
2398  { // Exponential backoff of connection time out
2399  int backoffCount = 0x1 << (m_synRetries - m_synCount);
2400  m_rto = m_cnTimeout * backoffCount;
2401  m_synCount--;
2402  }
2403 
2404  if (m_synRetries - 1 == m_synCount)
2405  {
2406  UpdateRttHistory (s, 0, false);
2407  }
2408  else
2409  { // This is SYN retransmission
2410  UpdateRttHistory (s, 0, true);
2411  }
2412 
2413  windowSize = AdvertisedWindowSize (false);
2414  }
2415  header.SetWindowSize (windowSize);
2416 
2417  if (flags & TcpHeader::ACK)
2418  { // If sending an ACK, cancel the delay ACK as well
2419  m_delAckEvent.Cancel ();
2420  m_delAckCount = 0;
2421  if (m_highTxAck < header.GetAckNumber ())
2422  {
2423  m_highTxAck = header.GetAckNumber ();
2424  }
2425  if (m_sackEnabled && m_rxBuffer->GetSackListSize () > 0)
2426  {
2427  AddOptionSack (header);
2428  }
2429  NS_LOG_INFO ("Sending a pure ACK, acking seq " << m_rxBuffer->NextRxSequence ());
2430  }
2431 
2432  m_txTrace (p, header, this);
2433 
2434  if (m_endPoint != nullptr)
2435  {
2436  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2438  }
2439  else
2440  {
2441  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2443  }
2444 
2445 
2446  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
2447  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2448  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
2449  << Simulator::Now ().GetSeconds () << " to expire at time "
2450  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2452  }
2453 }
2454 
2455 /* This function closes the endpoint completely. Called upon RST_TX action. */
2456 void
2458 {
2459  NS_LOG_FUNCTION (this);
2461  NotifyErrorClose ();
2462  DeallocateEndPoint ();
2463 }
2464 
2465 /* Deallocate the end point and cancel all the timers */
2466 void
2468 {
2469  if (m_endPoint != nullptr)
2470  {
2471  CancelAllTimers ();
2472  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
2473  m_tcp->DeAllocate (m_endPoint);
2474  m_endPoint = nullptr;
2475  m_tcp->RemoveSocket (this);
2476  }
2477  else if (m_endPoint6 != nullptr)
2478  {
2479  CancelAllTimers ();
2480  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
2481  m_tcp->DeAllocate (m_endPoint6);
2482  m_endPoint6 = nullptr;
2483  m_tcp->RemoveSocket (this);
2484  }
2485 }
2486 
2487 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2488 int
2490 {
2491  NS_LOG_FUNCTION (this);
2492  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
2493  NS_ASSERT (ipv4 != nullptr);
2494  if (ipv4->GetRoutingProtocol () == nullptr)
2495  {
2496  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
2497  }
2498  // Create a dummy packet, then ask the routing function for the best output
2499  // interface's address
2500  Ipv4Header header;
2502  Socket::SocketErrno errno_;
2503  Ptr<Ipv4Route> route;
2505  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2506  if (route == 0)
2507  {
2508  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
2509  NS_LOG_ERROR (errno_);
2510  m_errno = errno_;
2511  return -1;
2512  }
2513  NS_LOG_LOGIC ("Route exists");
2514  m_endPoint->SetLocalAddress (route->GetSource ());
2515  return 0;
2516 }
2517 
2518 int
2520 {
2521  NS_LOG_FUNCTION (this);
2523  NS_ASSERT (ipv6 != nullptr);
2524  if (ipv6->GetRoutingProtocol () == nullptr)
2525  {
2526  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
2527  }
2528  // Create a dummy packet, then ask the routing function for the best output
2529  // interface's address
2530  Ipv6Header header;
2532  Socket::SocketErrno errno_;
2533  Ptr<Ipv6Route> route;
2535  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2536  if (route == nullptr)
2537  {
2538  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
2539  NS_LOG_ERROR (errno_);
2540  m_errno = errno_;
2541  return -1;
2542  }
2543  NS_LOG_LOGIC ("Route exists");
2544  m_endPoint6->SetLocalAddress (route->GetSource ());
2545  return 0;
2546 }
2547 
2548 /* This function is called only if a SYN received in LISTEN state. After
2549  TcpSocketBase cloned, allocate a new end point to handle the incoming
2550  connection and send a SYN+ACK to complete the handshake. */
2551 void
2553  const Address& fromAddress, const Address& toAddress)
2554 {
2555  NS_UNUSED (p);
2556  // Get port and address from peer (connecting host)
2557  if (InetSocketAddress::IsMatchingType (toAddress))
2558  {
2559  m_endPoint = m_tcp->Allocate (GetBoundNetDevice (),
2560  InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
2561  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
2562  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2563  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2564  m_endPoint6 = nullptr;
2565  }
2566  else if (Inet6SocketAddress::IsMatchingType (toAddress))
2567  {
2568  m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (),
2569  Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
2570  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
2571  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2572  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2573  m_endPoint = nullptr;
2574  }
2575  m_tcp->AddSocket (this);
2576 
2577  // Change the cloned socket from LISTEN state to SYN_RCVD
2578  NS_LOG_DEBUG ("LISTEN -> SYN_RCVD");
2579  m_state = SYN_RCVD;
2582  SetupCallback ();
2583  // Set the sequence number and send SYN+ACK
2584  m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
2585 
2587 }
2588 
2589 void
2591 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
2592  // be called as a scheduled event
2594  // The if-block below was moved from ProcessSynSent() to here because we need
2595  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
2596  // reflect the behaviour in the real world.
2597  if (GetTxAvailable () > 0)
2598  {
2600  }
2601 }
2602 
2603 void
2605 {
2606  /*
2607  * Add tags for each socket option.
2608  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2609  * if both options are set. Once the packet got to layer three, only
2610  * the corresponding tags will be read.
2611  */
2612  if (GetIpTos ())
2613  {
2614  SocketIpTosTag ipTosTag;
2615  ipTosTag.SetTos (GetIpTos ());
2616  p->AddPacketTag (ipTosTag);
2617  }
2618 
2619  if (IsManualIpv6Tclass ())
2620  {
2621  SocketIpv6TclassTag ipTclassTag;
2622  ipTclassTag.SetTclass (GetIpv6Tclass ());
2623  p->AddPacketTag (ipTclassTag);
2624  }
2625 
2626  if (IsManualIpTtl ())
2627  {
2628  SocketIpTtlTag ipTtlTag;
2629  ipTtlTag.SetTtl (GetIpTtl ());
2630  p->AddPacketTag (ipTtlTag);
2631  }
2632 
2633  if (IsManualIpv6HopLimit ())
2634  {
2635  SocketIpv6HopLimitTag ipHopLimitTag;
2636  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
2637  p->AddPacketTag (ipHopLimitTag);
2638  }
2639 
2640  uint8_t priority = GetPriority ();
2641  if (priority)
2642  {
2643  SocketPriorityTag priorityTag;
2644  priorityTag.SetPriority (priority);
2645  p->ReplacePacketTag (priorityTag);
2646  }
2647 }
2648 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
2649  TCP header, and send to TcpL4Protocol */
2650 uint32_t
2651 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
2652 {
2653  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
2654 
2655  bool isRetransmission = false;
2656  if (seq != m_tcb->m_highTxMark)
2657  {
2658  isRetransmission = true;
2659  }
2660 
2661  Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq);
2662  uint32_t sz = p->GetSize (); // Size of packet
2663  uint8_t flags = withAck ? TcpHeader::ACK : 0;
2664  uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
2665 
2666  if (m_tcb->m_pacing)
2667  {
2668  NS_LOG_INFO ("Pacing is enabled");
2669  if (m_pacingTimer.IsExpired ())
2670  {
2671  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_currentPacingRate);
2672  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_currentPacingRate.CalculateBytesTxTime (sz));
2674  }
2675  else
2676  {
2677  NS_LOG_INFO ("Timer is already in running state");
2678  }
2679  }
2680 
2681  if (withAck)
2682  {
2683  m_delAckEvent.Cancel ();
2684  m_delAckCount = 0;
2685  }
2686 
2687  AddSocketTags (p);
2688 
2689  if (m_closeOnEmpty && (remainingData == 0))
2690  {
2691  flags |= TcpHeader::FIN;
2692  if (m_state == ESTABLISHED)
2693  { // On active close: I am the first one to send FIN
2694  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
2695  m_state = FIN_WAIT_1;
2696  }
2697  else if (m_state == CLOSE_WAIT)
2698  { // On passive close: Peer sent me FIN already
2699  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
2700  m_state = LAST_ACK;
2701  }
2702  }
2703  TcpHeader header;
2704  header.SetFlags (flags);
2705  header.SetSequenceNumber (seq);
2706  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2707  if (m_endPoint)
2708  {
2709  header.SetSourcePort (m_endPoint->GetLocalPort ());
2711  }
2712  else
2713  {
2714  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2716  }
2717  header.SetWindowSize (AdvertisedWindowSize ());
2718  AddOptions (header);
2719 
2720  if (m_retxEvent.IsExpired ())
2721  {
2722  // Schedules retransmit timeout. m_rto should be already doubled.
2723 
2724  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
2725  Simulator::Now ().GetSeconds () << " to expire at time " <<
2726  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
2728  }
2729 
2730  m_txTrace (p, header, this);
2731 
2732  if (m_endPoint)
2733  {
2734  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2736  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
2737  remainingData << " via TcpL4Protocol to " << m_endPoint->GetPeerAddress () <<
2738  ". Header " << header);
2739  }
2740  else
2741  {
2742  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2744  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
2745  remainingData << " via TcpL4Protocol to " << m_endPoint6->GetPeerAddress () <<
2746  ". Header " << header);
2747  }
2748 
2749  UpdateRttHistory (seq, sz, isRetransmission);
2750 
2751  // Notify the application of the data being sent unless this is a retransmit
2752  if (seq + sz > m_tcb->m_highTxMark)
2753  {
2755  (seq + sz - m_tcb->m_highTxMark.Get ()));
2756  }
2757  // Update highTxMark
2758  m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ());
2759  return sz;
2760 }
2761 
2762 void
2764  bool isRetransmission)
2765 {
2766  NS_LOG_FUNCTION (this);
2767 
2768  // update the history of sequence numbers used to calculate the RTT
2769  if (isRetransmission == false)
2770  { // This is the next expected one, just log at end
2771  m_history.push_back (RttHistory (seq, sz, Simulator::Now ()));
2772  }
2773  else
2774  { // This is a retransmit, find in list and mark as re-tx
2775  for (std::deque<RttHistory>::iterator i = m_history.begin (); i != m_history.end (); ++i)
2776  {
2777  if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
2778  { // Found it
2779  i->retx = true;
2780  i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
2781  break;
2782  }
2783  }
2784  }
2785 }
2786 
2787 // Note that this function did not implement the PSH flag
2788 uint32_t
2790 {
2791  NS_LOG_FUNCTION (this << withAck);
2792  if (m_txBuffer->Size () == 0)
2793  {
2794  return false; // Nothing to send
2795  }
2796  if (m_endPoint == nullptr && m_endPoint6 == nullptr)
2797  {
2798  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
2799  return false; // Is this the right way to handle this condition?
2800  }
2801 
2802  uint32_t nPacketsSent = 0;
2803  uint32_t availableWindow = AvailableWindow ();
2804 
2805  // RFC 6675, Section (C)
2806  // If cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more
2807  // segments as follows:
2808  // (NOTE: We check > 0, and do the checks for segmentSize in the following
2809  // else branch to control silly window syndrome and Nagle)
2810  while (availableWindow > 0)
2811  {
2812  if (m_tcb->m_pacing)
2813  {
2814  NS_LOG_INFO ("Pacing is enabled");
2815  if (m_pacingTimer.IsRunning ())
2816  {
2817  NS_LOG_INFO ("Skipping Packet due to pacing" << m_pacingTimer.GetDelayLeft ());
2818  break;
2819  }
2820  NS_LOG_INFO ("Timer is not running");
2821  }
2822 
2825  {
2826  NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit");
2827  break;
2828  }
2829  // (C.1) The scoreboard MUST be queried via NextSeg () for the
2830  // sequence number range of the next segment to transmit (if
2831  // any), and the given segment sent. If NextSeg () returns
2832  // failure (no data to send), return without sending anything
2833  // (i.e., terminate steps C.1 -- C.5).
2834  SequenceNumber32 next;
2835  bool enableRule3 = m_sackEnabled && m_tcb->m_congState == TcpSocketState::CA_RECOVERY;
2836  if (!m_txBuffer->NextSeg (&next, enableRule3))
2837  {
2838  NS_LOG_INFO ("no valid seq to transmit, or no data available");
2839  break;
2840  }
2841  else
2842  {
2843  // It's time to transmit, but before do silly window and Nagle's check
2844  uint32_t availableData = m_txBuffer->SizeFromSequence (next);
2845 
2846  // If there's less app data than the full window, ask the app for more
2847  // data before trying to send
2848  if (availableData < availableWindow)
2849  {
2851  }
2852 
2853  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
2854  // but continue if we don't have data
2855  if (availableWindow < m_tcb->m_segmentSize && availableData > availableWindow)
2856  {
2857  NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
2858  break; // No more
2859  }
2860  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
2861  // in the buffer and the amount of data to send is less than one segment
2862  if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_segmentSize)
2863  {
2864  NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next <<
2865  ", SFS: " << m_txBuffer->SizeFromSequence (next) <<
2866  ". Wait to send.");
2867  break;
2868  }
2869 
2870  uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize);
2871 
2872  // (C.2) If any of the data octets sent in (C.1) are below HighData,
2873  // HighRxt MUST be set to the highest sequence number of the
2874  // retransmitted segment unless NextSeg () rule (4) was
2875  // invoked for this retransmission.
2876  // (C.3) If any of the data octets sent in (C.1) are above HighData,
2877  // HighData must be updated to reflect the transmission of
2878  // previously unsent data.
2879  //
2880  // These steps are done in m_txBuffer with the tags.
2881  if (m_tcb->m_nextTxSequence != next)
2882  {
2883  m_tcb->m_nextTxSequence = next;
2884  }
2885  if (m_bytesInFlight.Get () == 0)
2886  {
2888  }
2889  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck);
2890  m_tcb->m_nextTxSequence += sz;
2891 
2892  NS_LOG_LOGIC (" rxwin " << m_rWnd <<
2893  " segsize " << m_tcb->m_segmentSize <<
2894  " highestRxAck " << m_txBuffer->HeadSequence () <<
2895  " pd->Size " << m_txBuffer->Size () <<
2896  " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence));
2897 
2898  NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd <<
2899  " total unAck: " << UnAckDataCount () <<
2900  " sent seq " << m_tcb->m_nextTxSequence <<
2901  " size " << sz);
2902  ++nPacketsSent;
2903  if (m_tcb->m_pacing)
2904  {
2905  NS_LOG_INFO ("Pacing is enabled");
2906  if (m_pacingTimer.IsExpired ())
2907  {
2908  NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_currentPacingRate);
2909  NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_currentPacingRate.CalculateBytesTxTime (sz));
2911  break;
2912  }
2913  }
2914  }
2915 
2916  // (C.4) The estimate of the amount of data outstanding in the
2917  // network must be updated by incrementing pipe by the number
2918  // of octets transmitted in (C.1).
2919  //
2920  // Done in BytesInFlight, inside AvailableWindow.
2921  availableWindow = AvailableWindow ();
2922 
2923  // (C.5) If cwnd - pipe >= 1 SMSS, return to (C.1)
2924  // loop again!
2925  }
2926 
2927  if (nPacketsSent > 0)
2928  {
2929  if (!m_sackEnabled)
2930  {
2931  if (!m_limitedTx)
2932  {
2933  // We can't transmit in CA_DISORDER without limitedTx active
2935  }
2936  }
2937 
2938  NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments");
2939  }
2940  else
2941  {
2942  NS_LOG_DEBUG ("SendPendingData no segments sent");
2943  }
2944  return nPacketsSent;
2945 }
2946 
2947 uint32_t
2949 {
2950  return m_tcb->m_highTxMark - m_txBuffer->HeadSequence ();
2951 }
2952 
2953 uint32_t
2955 {
2956  uint32_t bytesInFlight = m_txBuffer->BytesInFlight ();
2957  // Ugly, but we are not modifying the state; m_bytesInFlight is used
2958  // only for tracing purpose.
2959  const_cast<TcpSocketBase*> (this)->m_bytesInFlight = bytesInFlight;
2960 
2961  NS_LOG_DEBUG ("Returning calculated bytesInFlight: " << bytesInFlight);
2962  return bytesInFlight;
2963 }
2964 
2965 uint32_t
2967 {
2968  return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
2969 }
2970 
2971 uint32_t
2973 {
2974  uint32_t win = Window (); // Number of bytes allowed to be outstanding
2975  uint32_t inflight = BytesInFlight (); // Number of outstanding bytes
2976  return (inflight > win) ? 0 : win - inflight;
2977 }
2978 
2979 uint16_t
2981 {
2982  NS_LOG_FUNCTION (this << scale);
2983  uint32_t w;
2984 
2985  // We don't want to advertise 0 after a FIN is received. So, we just use
2986  // the previous value of the advWnd.
2987  if (m_rxBuffer->GotFin ())
2988  {
2989  w = m_advWnd;
2990  }
2991  else
2992  {
2993  uint32_t max = m_rxBuffer->MaxRxSequence ().GetValue ();
2994  uint32_t next = m_rxBuffer->NextRxSequence ().GetValue ();
2995  w = ( max > next ) ? max - next : 0;
2996  }
2997 
2998  // Ugly, but we are not modifying the state, that variable
2999  // is used only for tracing purpose.
3000  if (w != m_advWnd)
3001  {
3002  const_cast<TcpSocketBase*> (this)->m_advWnd = w;
3003  }
3004  if (scale)
3005  {
3006  w >>= m_rcvWindShift;
3007  }
3008  if (w > m_maxWinSize)
3009  {
3010  w = m_maxWinSize;
3011  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
3012  }
3013  NS_LOG_LOGIC ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
3014  return static_cast<uint16_t> (w);
3015 }
3016 
3017 // Receipt of new packet, put into Rx buffer
3018 void
3020 {
3021  NS_LOG_FUNCTION (this << tcpHeader);
3022  NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () <<
3023  " pkt size=" << p->GetSize () );
3024 
3025  // Put into Rx buffer
3026  SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence ();
3027  if (!m_rxBuffer->Add (p, tcpHeader))
3028  { // Insert failed: No data or RX buffer full
3030  return;
3031  }
3032  // Notify app to receive if necessary
3033  if (expectedSeq < m_rxBuffer->NextRxSequence ())
3034  { // NextRxSeq advanced, we have something to send to the app
3035  if (!m_shutdownRecv)
3036  {
3037  NotifyDataRecv ();
3038  }
3039  // Handle exceptions
3040  if (m_closeNotified)
3041  {
3042  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
3043  }
3044  // If we received FIN before and now completed all "holes" in rx buffer,
3045  // invoke peer close procedure
3046  if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
3047  {
3048  DoPeerClose ();
3049  return;
3050  }
3051  }
3052  // Now send a new ACK packet acknowledging all received and delivered data
3053  if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
3054  { // A gap exists in the buffer, or we filled a gap: Always ACK
3057  }
3058  else
3059  { // In-sequence packet: ACK if delayed ack count allows
3061  {
3062  m_delAckEvent.Cancel ();
3063  m_delAckCount = 0;
3066  }
3067  else if (m_delAckEvent.IsExpired ())
3068  {
3071  NS_LOG_LOGIC (this << " scheduled delayed ACK at " <<
3072  (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
3073  }
3074  }
3075 }
3076 
3084 void
3086 {
3087  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber ();
3088  Time m = Time (0.0);
3089 
3090  // An ack has been received, calculate rtt and log this measurement
3091  // Note we use a linear search (O(n)) for this since for the common
3092  // case the ack'ed packet will be at the head of the list
3093  if (!m_history.empty ())
3094  {
3095  RttHistory& h = m_history.front ();
3096  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
3097  { // Ok to use this sample
3098  if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
3099  {
3101  ts = DynamicCast<const TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
3102  m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
3103  }
3104  else
3105  {
3106  m = Simulator::Now () - h.time; // Elapsed time
3107  }
3108  }
3109  }
3110 
3111  // Now delete all ack history with seq <= ack
3112  while (!m_history.empty ())
3113  {
3114  RttHistory& h = m_history.front ();
3115  if ((h.seq + SequenceNumber32 (h.count)) > ackSeq)
3116  {
3117  break; // Done removing
3118  }
3119  m_history.pop_front (); // Remove
3120  }
3121 
3122  if (!m.IsZero ())
3123  {
3124  m_rtt->Measurement (m); // Log the measurement
3125  // RFC 6298, clause 2.4
3126  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3127  m_lastRtt = m_rtt->GetEstimate ();
3129  NS_LOG_INFO (this << m_lastRtt << m_tcb->m_minRtt);
3130  }
3131 }
3132 
3133 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
3134 // when the three-way handshake completed. This cancels retransmission timer
3135 // and advances Tx window
3136 void
3137 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO)
3138 {
3139  NS_LOG_FUNCTION (this << ack);
3140 
3141  // Reset the data retransmission count. We got a new ACK!
3143 
3144  if (m_state != SYN_RCVD && resetRTO)
3145  { // Set RTO unless the ACK is received in SYN_RCVD state
3146  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3147  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3148  m_retxEvent.Cancel ();
3149  // On receiving a "New" ack we restart retransmission timer .. RFC 6298
3150  // RFC 6298, clause 2.4
3151  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3152 
3153  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
3154  Simulator::Now ().GetSeconds () << " to expire at time " <<
3155  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
3157  }
3158 
3159  // Note the highest ACK and tell app to send more
3160  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
3161  " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
3162 
3163  if (GetTxAvailable () > 0)
3164  {
3166  }
3167  if (ack > m_tcb->m_nextTxSequence)
3168  {
3169  m_tcb->m_nextTxSequence = ack; // If advanced
3170  }
3171  if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
3172  { // No retransmit timer if no data to retransmit
3173  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3174  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3175  m_retxEvent.Cancel ();
3176  }
3177 }
3178 
3179 // Retransmit timeout
3180 void
3182 {
3183  NS_LOG_FUNCTION (this);
3184  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
3185  // If erroneous timeout in closed/timed-wait state, just return
3186  if (m_state == CLOSED || m_state == TIME_WAIT)
3187  {
3188  return;
3189  }
3190 
3191  if (m_state == SYN_SENT)
3192  {
3193  if (m_synCount > 0)
3194  {
3196  }
3197  else
3198  {
3200  }
3201  return;
3202  }
3203 
3204  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3205  if (m_txBuffer->Size () == 0)
3206  {
3207  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3208  { // Must have lost FIN, re-send
3210  }
3211  return;
3212  }
3213 
3214  NS_LOG_DEBUG ("Checking if Connection is Established");
3215  // If all data are received (non-closing socket and nothing to send), just return
3216  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark && m_txBuffer->Size () == 0)
3217  {
3218  NS_LOG_DEBUG ("Already Sent full data" << m_txBuffer->HeadSequence () << " " << m_tcb->m_highTxMark);
3219  return;
3220  }
3221 
3222  if (m_dataRetrCount == 0)
3223  {
3224  NS_LOG_INFO ("No more data retries available. Dropping connection");
3225  NotifyErrorClose ();
3226  DeallocateEndPoint ();
3227  return;
3228  }
3229  else
3230  {
3231  --m_dataRetrCount;
3232  }
3233 
3234  uint32_t inFlightBeforeRto = BytesInFlight ();
3235  bool resetSack = !m_sackEnabled; // Reset SACK information if SACK is not enabled.
3236  // The information in the TcpTxBuffer is guessed, in this case.
3237 
3238  // Reset dupAckCount
3239  m_dupAckCount = 0;
3240  if (!m_sackEnabled)
3241  {
3242  m_txBuffer->ResetRenoSack ();
3243  }
3244 
3245  // From RFC 6675, Section 5.1
3246  // [RFC2018] suggests that a TCP sender SHOULD expunge the SACK
3247  // information gathered from a receiver upon a retransmission timeout
3248  // (RTO) "since the timeout might indicate that the data receiver has
3249  // reneged." Additionally, a TCP sender MUST "ignore prior SACK
3250  // information in determining which data to retransmit."
3251  // It has been suggested that, as long as robust tests for
3252  // reneging are present, an implementation can retain and use SACK
3253  // information across a timeout event [Errata1610].
3254  // The head of the sent list will not be marked as sacked, therefore
3255  // will be retransmitted, if the receiver renegotiate the SACK blocks
3256  // that we received.
3257  m_txBuffer->SetSentListLost (resetSack);
3258 
3259  // From RFC 6675, Section 5.1
3260  // If an RTO occurs during loss recovery as specified in this document,
3261  // RecoveryPoint MUST be set to HighData. Further, the new value of
3262  // RecoveryPoint MUST be preserved and the loss recovery algorithm
3263  // outlined in this document MUST be terminated.
3265 
3266  // RFC 6298, clause 2.5, double the timer
3267  Time doubledRto = m_rto + m_rto;
3268  m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
3269 
3270  // Empty RTT history
3271  m_history.clear ();
3272 
3273  // Please don't reset highTxMark, it is used for retransmission detection
3274 
3275  // When a TCP sender detects segment loss using the retransmission timer
3276  // and the given segment has not yet been resent by way of the
3277  // retransmission timer, decrease ssThresh
3278  if (m_tcb->m_congState != TcpSocketState::CA_LOSS || !m_txBuffer->IsHeadRetransmitted ())
3279  {
3280  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, inFlightBeforeRto);
3281  }
3282 
3283  // Cwnd set to 1 MSS
3285  m_cWndInfl = m_tcb->m_cWnd;
3287  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS);
3289 
3290  m_pacingTimer.Cancel ();
3291 
3292  NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
3293  m_tcb->m_ssThresh << ", restart from seqnum " <<
3294  m_txBuffer->HeadSequence () << " doubled rto to " <<
3295  m_rto.Get ().GetSeconds () << " s");
3296 
3297  NS_ASSERT_MSG (BytesInFlight () == 0, "There are some bytes in flight after an RTO: " <<
3298  BytesInFlight ());
3299 
3301 
3303  "In flight (" << BytesInFlight () <<
3304  ") there is more than one segment (" << m_tcb->m_segmentSize << ")");
3305 }
3306 
3307 void
3309 {
3310  m_delAckCount = 0;
3313 }
3314 
3315 void
3317 {
3318  NS_LOG_FUNCTION (this);
3319 
3321  if (m_state == LAST_ACK)
3322  {
3323  CloseAndNotify ();
3324  }
3325  if (!m_closeNotified)
3326  {
3327  m_closeNotified = true;
3328  }
3329 }
3330 
3331 // Send 1-byte data to probe for the window size at the receiver when
3332 // the local knowledge tells that the receiver has zero window size
3333 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
3334 void
3336 {
3337  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
3338  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
3339  Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence);
3340  m_txBuffer->ResetLastSegmentSent ();
3341  TcpHeader tcpHeader;
3343  tcpHeader.SetAckNumber (m_rxBuffer->NextRxSequence ());
3344  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
3345  if (m_endPoint != nullptr)
3346  {
3347  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
3348  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
3349  }
3350  else
3351  {
3352  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
3353  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
3354  }
3355  AddOptions (tcpHeader);
3356 
3357  m_txTrace (p, tcpHeader, this);
3358 
3359  if (m_endPoint != nullptr)
3360  {
3361  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
3363  }
3364  else
3365  {
3366  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
3368  }
3369 
3370  NS_LOG_LOGIC ("Schedule persist timeout at time "
3371  << Simulator::Now ().GetSeconds () << " to expire at time "
3372  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
3374 }
3375 
3376 void
3378 {
3379  NS_LOG_FUNCTION (this);
3380  bool res;
3381  SequenceNumber32 seq;
3382 
3383  // Find the first segment marked as lost and not retransmitted. With Reno,
3384  // that should be the head
3385  res = m_txBuffer->NextSeg (&seq, false);
3386  if (!res)
3387  {
3388  // We have already retransmitted the head. However, we still received
3389  // three dupacks, or the RTO expired, but no data to transmit.
3390  // Therefore, re-send again the head.
3391  seq = m_txBuffer->HeadSequence ();
3392  }
3393  NS_ASSERT (m_sackEnabled || seq == m_txBuffer->HeadSequence ());
3394 
3395  NS_LOG_INFO ("Retransmitting " << seq);
3396  // Update the trace and retransmit the segment
3397  m_tcb->m_nextTxSequence = seq;
3398  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, m_tcb->m_segmentSize, true);
3399 
3400  NS_ASSERT (sz > 0);
3401 }
3402 
3403 void
3405 {
3406  m_retxEvent.Cancel ();
3408  m_delAckEvent.Cancel ();
3412  m_pacingTimer.Cancel ();
3413 }
3414 
3415 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
3416 void
3418 {
3419  NS_LOG_DEBUG (TcpStateName[m_state] << " -> TIME_WAIT");
3420  m_state = TIME_WAIT;
3421  CancelAllTimers ();
3422  if (!m_closeNotified)
3423  {
3424  // Technically the connection is not fully closed, but we notify now
3425  // because an implementation (real socket) would behave as if closed.
3426  // Notify normal close when entering TIME_WAIT or leaving LAST_ACK.
3427  NotifyNormalClose ();
3428  m_closeNotified = true;
3429  }
3430  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
3431  // according to RFC793, p.28
3434 }
3435 
3436 /* Below are the attribute get/set functions */
3437 
3438 void
3440 {
3441  NS_LOG_FUNCTION (this << size);
3442  m_txBuffer->SetMaxBufferSize (size);
3443 }
3444 
3445 uint32_t
3447 {
3448  return m_txBuffer->MaxBufferSize ();
3449 }
3450 
3451 void
3453 {
3454  NS_LOG_FUNCTION (this << size);
3455  uint32_t oldSize = GetRcvBufSize ();
3456 
3457  m_rxBuffer->SetMaxBufferSize (size);
3458 
3459  /* The size has (manually) increased. Actively inform the other end to prevent
3460  * stale zero-window states.
3461  */
3462  if (oldSize < size && m_connected)
3463  {
3465  }
3466 }
3467 
3468 uint32_t
3470 {
3471  return m_rxBuffer->MaxBufferSize ();
3472 }
3473 
3474 void
3476 {
3477  NS_LOG_FUNCTION (this << size);
3478  m_tcb->m_segmentSize = size;
3479  m_txBuffer->SetSegmentSize (size);
3480 
3481  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
3482 }
3483 
3484 uint32_t
3486 {
3487  return m_tcb->m_segmentSize;
3488 }
3489 
3490 void
3492 {
3493  NS_LOG_FUNCTION (this << timeout);
3494  m_cnTimeout = timeout;
3495 }
3496 
3497 Time
3499 {
3500  return m_cnTimeout;
3501 }
3502 
3503 void
3505 {
3506  NS_LOG_FUNCTION (this << count);
3507  m_synRetries = count;
3508 }
3509 
3510 uint32_t
3512 {
3513  return m_synRetries;
3514 }
3515 
3516 void
3518 {
3519  NS_LOG_FUNCTION (this << retries);
3520  m_dataRetries = retries;
3521 }
3522 
3523 uint32_t
3525 {
3526  NS_LOG_FUNCTION (this);
3527  return m_dataRetries;
3528 }
3529 
3530 void
3532 {
3533  NS_LOG_FUNCTION (this << timeout);
3535 }
3536 
3537 Time
3539 {
3540  return m_delAckTimeout;
3541 }
3542 
3543 void
3545 {
3546  NS_LOG_FUNCTION (this << count);
3547  m_delAckMaxCount = count;
3548 }
3549 
3550 uint32_t
3552 {
3553  return m_delAckMaxCount;
3554 }
3555 
3556 void
3558 {
3559  NS_LOG_FUNCTION (this << noDelay);
3560  m_noDelay = noDelay;
3561 }
3562 
3563 bool
3565 {
3566  return m_noDelay;
3567 }
3568 
3569 void
3571 {
3572  NS_LOG_FUNCTION (this << timeout);
3574 }
3575 
3576 Time
3578 {
3579  return m_persistTimeout;
3580 }
3581 
3582 bool
3584 {
3585  // Broadcast is not implemented. Return true only if allowBroadcast==false
3586  return (!allowBroadcast);
3587 }
3588 
3589 bool
3591 {
3592  return false;
3593 }
3594 
3595 void
3597 {
3598  NS_LOG_FUNCTION (this << header);
3599 
3600  if (m_timestampEnabled)
3601  {
3602  AddOptionTimestamp (header);
3603  }
3604 }
3605 
3606 void
3608 {
3609  NS_LOG_FUNCTION (this << option);
3610 
3611  Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
3612 
3613  // In naming, we do the contrary of RFC 1323. The received scaling factor
3614  // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
3615  m_sndWindShift = ws->GetScale ();
3616 
3617  if (m_sndWindShift > 14)
3618  {
3619  NS_LOG_WARN ("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
3620  m_sndWindShift = 14;
3621  }
3622 
3623  NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
3624  static_cast<int> (m_sndWindShift));
3625 }
3626 
3627 uint8_t
3629 {
3630  NS_LOG_FUNCTION (this);
3631  uint32_t maxSpace = m_rxBuffer->MaxBufferSize ();
3632  uint8_t scale = 0;
3633 
3634  while (maxSpace > m_maxWinSize)
3635  {
3636  maxSpace = maxSpace >> 1;
3637  ++scale;
3638  }
3639 
3640  if (scale > 14)
3641  {
3642  NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
3643  scale = 14;
3644  }
3645 
3646  NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
3647  static_cast<int> (scale) << " for buffer size " << m_rxBuffer->MaxBufferSize ());
3648  return scale;
3649 }
3650 
3651 void
3653 {
3654  NS_LOG_FUNCTION (this << header);
3655  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
3656 
3657  Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
3658 
3659  // In naming, we do the contrary of RFC 1323. The sended scaling factor
3660  // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
3661 
3663  option->SetScale (m_rcvWindShift);
3664 
3665  header.AppendOption (option);
3666 
3667  NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
3668  static_cast<int> (m_rcvWindShift));
3669 }
3670 
3671 bool
3673 {
3674  NS_LOG_FUNCTION (this << option);
3675 
3676  Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option);
3677  TcpOptionSack::SackList list = s->GetSackList ();
3678  return m_txBuffer->Update (list);
3679 }
3680 
3681 void
3683 {
3684  NS_LOG_FUNCTION (this << option);
3685 
3686  Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted> (option);
3687 
3688  NS_ASSERT (m_sackEnabled == true);
3689  NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s);
3690 }
3691 
3692 void
3694 {
3695  NS_LOG_FUNCTION (this << header);
3696  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
3697 
3698  Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> ();
3699  header.AppendOption (option);
3700  NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED");
3701 }
3702 
3703 void
3705 {
3706  NS_LOG_FUNCTION (this << header);
3707 
3708  // Calculate the number of SACK blocks allowed in this packet
3709  uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength ();
3710  uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8;
3711 
3712  TcpOptionSack::SackList sackList = m_rxBuffer->GetSackList ();
3713  if (allowedSackBlocks == 0 || sackList.empty ())
3714  {
3715  NS_LOG_LOGIC ("No space available or sack list empty, not adding sack blocks");
3716  return;
3717  }
3718 
3719  // Append the allowed number of SACK blocks
3720  Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> ();
3721  TcpOptionSack::SackList::iterator i;
3722  for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i)
3723  {
3724  option->AddSackBlock (*i);
3725  allowedSackBlocks--;
3726  }
3727 
3728  header.AppendOption (option);
3729  NS_LOG_INFO (m_node->GetId () << " Add option SACK " << *option);
3730 }
3731 
3732 void
3734  const SequenceNumber32 &seq)
3735 {
3736  NS_LOG_FUNCTION (this << option);
3737 
3738  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
3739 
3740  // This is valid only when no overflow occours. It happens
3741  // when a connection last longer than 50 days.
3742  if (m_tcb->m_rcvTimestampValue > ts->GetTimestamp ())
3743  {
3744  // Do not save a smaller timestamp (probably there is reordering)
3745  return;
3746  }
3747 
3748  m_tcb->m_rcvTimestampValue = ts->GetTimestamp ();
3749  m_tcb->m_rcvTimestampEchoReply = ts->GetEcho ();
3750 
3751  if (seq == m_rxBuffer->NextRxSequence () && seq <= m_highTxAck)
3752  {
3753  m_timestampToEcho = ts->GetTimestamp ();
3754  }
3755 
3756  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
3757  m_timestampToEcho << " and Echo=" << ts->GetEcho ());
3758 }
3759 
3760 void
3762 {
3763  NS_LOG_FUNCTION (this << header);
3764 
3765  Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
3766 
3767  option->SetTimestamp (TcpOptionTS::NowToTsValue ());
3768  option->SetEcho (m_timestampToEcho);
3769 
3770  header.AppendOption (option);
3771  NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
3772  option->GetTimestamp () << " echo=" << m_timestampToEcho);
3773 }
3774 
3776 {
3777  NS_LOG_FUNCTION (this << header);
3778  // If the connection is not established, the window size is always
3779  // updated
3780  uint32_t receivedWindow = header.GetWindowSize ();
3781  receivedWindow <<= m_sndWindShift;
3782  NS_LOG_INFO ("Received (scaled) window is " << receivedWindow << " bytes");
3783  if (m_state < ESTABLISHED)
3784  {
3785  m_rWnd = receivedWindow;
3786  NS_LOG_LOGIC ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
3787  return;
3788  }
3789 
3790  // Test for conditions that allow updating of the window
3791  // 1) segment contains new data (advancing the right edge of the receive
3792  // buffer),
3793  // 2) segment does not contain new data but the segment acks new data
3794  // (highest sequence number acked advances), or
3795  // 3) the advertised window is larger than the current send window
3796  bool update = false;
3797  if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
3798  {
3799  // right edge of the send window is increased (window update)
3800  update = true;
3801  }
3802  if (header.GetAckNumber () > m_highRxAckMark)
3803  {
3804  m_highRxAckMark = header.GetAckNumber ();
3805  update = true;
3806  }
3807  if (header.GetSequenceNumber () > m_highRxMark)
3808  {
3809  m_highRxMark = header.GetSequenceNumber ();
3810  update = true;
3811  }
3812  if (update == true)
3813  {
3814  m_rWnd = receivedWindow;
3815  NS_LOG_LOGIC ("updating rWnd to " << m_rWnd);
3816  }
3817 }
3818 
3819 void
3821 {
3822  NS_LOG_FUNCTION (this << minRto);
3823  m_minRto = minRto;
3824 }
3825 
3826 Time
3828 {
3829  return m_minRto;
3830 }
3831 
3832 void
3834 {
3835  NS_LOG_FUNCTION (this << clockGranularity);
3836  m_clockGranularity = clockGranularity;
3837 }
3838 
3839 Time
3841 {
3842  return m_clockGranularity;
3843 }
3844 
3847 {
3848  return m_txBuffer;
3849 }
3850 
3853 {
3854  return m_rxBuffer;
3855 }
3856 
3857 void
3858 TcpSocketBase::SetRetxThresh (uint32_t retxThresh)
3859 {
3860  m_retxThresh = retxThresh;
3861  m_txBuffer->SetDupAckThresh (retxThresh);
3862 }
3863 
3864 void
3865 TcpSocketBase::UpdateCwnd (uint32_t oldValue, uint32_t newValue)
3866 {
3867  m_cWndTrace (oldValue, newValue);
3868 }
3869 
3870 void
3871 TcpSocketBase::UpdateSsThresh (uint32_t oldValue, uint32_t newValue)
3872 {
3873  m_ssThTrace (oldValue, newValue);
3874 }
3875 
3876 void
3879 {
3880  m_congStateTrace (oldValue, newValue);
3881 }
3882 
3883 void
3885  SequenceNumber32 newValue)
3886 
3887 {
3888  m_nextTxSequenceTrace (oldValue, newValue);
3889 }
3890 
3891 void
3893 {
3894  m_highTxMarkTrace (oldValue, newValue);
3895 }
3896 
3897 void
3899 {
3900  NS_LOG_FUNCTION (this << algo);
3901  m_congestionControl = algo;
3902 }
3903 
3906 {
3907  return CopyObject<TcpSocketBase> (this);
3908 }
3909 
3910 uint32_t
3911 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b)
3912 {
3913  if (a > b)
3914  {
3915  return a-b;
3916  }
3917 
3918  return 0;
3919 }
3920 
3921 void
3923 {
3925  NS_LOG_INFO ("Performing Pacing");
3927 }
3928 
3929 
3930 //RttHistory methods
3932  : seq (s),
3933  count (c),
3934  time (t),
3935  retx (false)
3936 {
3937 }
3938 
3940  : seq (h.seq),
3941  count (h.count),
3942  time (h.time),
3943  retx (h.retx)
3944 {
3945 }
3946 
3947 } // 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
TracedValue< uint32_t > m_bytesInFlight
Bytes in flight.
log2() macro definition; to deal with Bug 1467.
void SetTclass(uint8_t tclass)
Set the tag's Tclass.
Definition: socket.cc:906
static std::string FlagsToString(uint8_t flags, const std::string &delimiter="|")
Converts an integer into a human readable list of Tcp flags.
Definition: tcp-header.cc:55
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.
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
virtual int Listen(void)
Listen for incoming connections.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
bool IsManualIpTtl(void) const
Checks if the socket has a specific IPv4 TTL set.
Definition: socket.cc:377
Packet header for IPv6.
Definition: ipv6-header.h:34
an Inet address class
virtual int GetSockName(Address &address) const
Get socket address.
Ipv4Address GetIpv4(void) const
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
static Ipv4Address GetAny(void)
virtual uint32_t Window(void) const
Return the max possible number of unacked bytes.
#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.
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
DataRate m_currentPacingRate
Current Pacing rate.
const TcpOptionList & GetOptionList(void) const
Get the list of option in this header.
Definition: tcp-header.cc:489
Normal state, no dubious events.
uint32_t m_dataRetries
Number of data retransmission attempts.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
Connection established.
Definition: tcp-socket.h:71
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
virtual void SetInitialSSThresh(uint32_t threshold)
Set the initial Slow Start Threshold.
AttributeValue implementation for Boolean.
Definition: boolean.h:36
virtual uint8_t GetIpTtl(void) const
Query the value of IP Time to Live field of this socket.
Definition: socket.cc:526
Callback template class.
Definition: callback.h:1176
bool m_noDelay
Set to true to disable Nagle's algorithm.
virtual uint32_t GetSegSize(void) const
Get the segment size.
CWND was reduced, we are fast-retransmitting.
In all the respects it is "Open", but requires a bit more attention.
Time GetClockGranularity(void) const
Get the Clock Granularity (used in RTO calcs).
uint8_t GetIpTos(void) const
Query the value of IP Type of Service of this socket.
Definition: socket.cc:459
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:1159
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.
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
virtual uint32_t BytesInFlight(void) const
Return total bytes in flight.
virtual ~TcpSocketBase(void)
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:459
Time CalculateBytesTxTime(uint32_t bytes) const
Calculate transmission time.
Definition: data-rate.cc:235
uint32_t m_dataRetrCount
Count of remaining data retransmission attempts.
TracedValue< Time > m_lastRtt
Last RTT sample collected.
uint32_t m_synRetries
Number of connection attempts.
#define min(a, b)
Definition: 80211b.c:44
void NotifyDataRecv(void)
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:305
TracedValue< SequenceNumber32 > m_highRxAckMark
Highest ack received.
uint32_t m_initialSsThresh
Initial Slow Start Threshold value.
virtual int ShutdownRecv(void)
void SetRxCallback(Callback< void, Ptr< Packet >, Ipv4Header, uint16_t, Ptr< Ipv4Interface > > callback)
Set the reception callback.
TcpSocketBase(void)
Create an unbound TCP socket.
void SetClockGranularity(Time clockGranularity)
Sets the Clock Granularity (used in RTO calcs).
EventId m_retxEvent
Retransmission event.
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:175
IPv6 layer implementation.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:84
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
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.
bool IsZero(void) const
Definition: nstime.h:288
void ProcessOptionSackPermitted(const Ptr< const TcpOption > option)
Read the SACK PERMITTED option.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:852
virtual void SetPersistTimeout(Time timeout)
Set the timout for persistent connection.
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
virtual bool GetAllowBroadcast(void) const
Query whether broadcast datagram transmissions are allowed.
EventId m_timewaitEvent
TIME_WAIT expiration event: Move this socket to CLOSED state.
std::list< SackBlock > SackList
SACK list definition.
void NotifyConnectionFailed(void)
Notify through the callback (if set) that the connection has not been established due to an error...
Definition: socket.cc:227
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 GetDestination(void) const
Definition: ipv4-header.cc:304
void ProcessOptionTimestamp(const Ptr< const TcpOption > option, const SequenceNumber32 &seq)
Process the timestamp option from other side.
Both sides have shutdown but we still have data we have to finish sending.
Definition: tcp-socket.h:81
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
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.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Ptr< TcpSocketState > m_tcb
Congestion control informations.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1015
bool m_winScalingEnabled
Window Scale option enabled (RFC 7323)
bool m_timestampEnabled
Timestamp option enabled.
Timer m_pacingTimer
Pacing Event.
uint16_t m_maxWinSize
Maximum window size to advertise.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:821
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
second
Definition: nstime.h:114
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.
TcpSocketState()
TcpSocketState Constructor.
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:277
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:551
Time m_cnTimeout
Timeout for connection retry.
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
uint32_t m_initialCWnd
Initial cWnd value.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:733
Data structure that records the congestion state of a connection.
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
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's TOS.
Definition: socket.cc:791
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
T Get(void) const
Get the underlying value.
Definition: traced-value.h:218
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:1111
virtual uint32_t GetDataRetries(void) const
Get the number of data transmission retries before giving up.
virtual Time GetPersistTimeout(void) const
Get the timout for persistent connection.
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
virtual void PersistTimeout(void)
Send 1 byte probe to get an updated window size.
uint8_t GetMaxOptionLength() const
Get maximum option length.
Definition: tcp-header.cc:167
virtual void SetSynRetries(uint32_t count)
Set the number of connection retries before giving up.
Ptr< TcpTxBuffer > GetTxBuffer(void) const
Get a pointer to the Tx buffer.
TracedValue< TcpStates_t > m_state
TCP state.
uint32_t m_delAckMaxCount
Number of packet to fire an ACK before delay timeout.
uint8_t CalculateWScale() const
Calculate window scale value based on receive buffer space.
void DupAck()
Dupack management.
uint16_t port
Definition: dsdv-manet.cc:44
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 AttributeChecker > MakeDataRateChecker(void)
Definition: data-rate.cc:30
virtual uint32_t GetRcvBufSize(void) const
Get the receive buffer size.
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.
bool IsRunning(void) const
Definition: timer.cc:127
virtual bool GetTcpNoDelay(void) const
Check if Nagle's algorithm is enabled or not.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
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 int GetPeerName(Address &address) const
Get the peer address of a connected socket.
Class for representing data rates.
Definition: data-rate.h:88
Ptr< NetDevice > GetBoundNetDevice()
Returns socket's bound NetDevice, if any.
Definition: socket.cc:351
Packet header for IPv4.
Definition: ipv4-header.h:33
void SetLocalAddress(Ipv6Address addr)
Set the local address.
virtual void 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.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send data to a specified peer.
NS_ASSERT_MSG(false,"Ipv4AddressGenerator::MaskToIndex(): Impossible")
void UpdateCwnd(uint32_t oldValue, uint32_t newValue)
Callback function to hook to TcpSocketState congestion window.
virtual void EstimateRtt(const TcpHeader &tcpHeader)
Take into account the packet for RTT estimation.
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
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1375
Time time
Time this one was sent.
#define max(a, b)
Definition: 80211b.c:45
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.
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's TTL.
Definition: socket.cc:610
AttributeValue implementation for Time.
Definition: nstime.h:1069
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
void Schedule(void)
Schedule a new event using the currently-configured delay, function, and arguments.
Definition: timer.cc:158
virtual uint32_t GetSndBufSize(void) const
Get the send buffer size.
virtual enum SocketType GetSocketType(void) const
uint16_t GetLocalPort()
Get the local port.
virtual uint16_t AdvertisedWindowSize(bool scale=true) const
The amount of Rx window announced to the peer.
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.
void AddSocketTags(const Ptr< Packet > &p) const
Add Tags for the Socket.
bool OutOfRange(SequenceNumber32 head, SequenceNumber32 tail) const
Check if a sequence number range is within the rx window.
std::deque< RttHistory > m_history
List of sent packet.
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:1303
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's algorithm.
RttHistory(SequenceNumber32 s, uint32_t c, Time t)
Constructor - builds an RttHistory with the given parameters.
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.
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:371
SequenceNumber32 m_lastAckedSeq
Last sequence ACKed.
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:285
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:128
Ipv4Address GetSource(void) const
Definition: ipv4-route.cc:56
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.
uint8_t GetTos(void) const
void ProcessSynSent(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon SYN_SENT.
Ptr< const AttributeAccessor > MakeDataRateAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: data-rate.h:242
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.
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's Hop Limit.
Definition: socket.cc:671
void ReadOptions(const TcpHeader &tcpHeader, bool &scoreboardUpdated)
Read TCP options begore 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.
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.
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:383
TracedValue< uint32_t > m_cWndInfl
Inflated congestion window trace (not used in the real code, deprecated)
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
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.
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.
Used only in debug messages.
uint32_t GetRetxThresh(void) const
Get the retransmission threshold (dup ack threshold for a fast retransmit)
Ptr< Node > m_node
the associated node
Hold objects of type Ptr.
Definition: pointer.h:36
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.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
virtual void SetNode(Ptr< Node > node)
Set the associated node.
void AddOptionSackPermitted(TcpHeader &header)
Add the SACK PERMITTED option to the header.
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:161
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
virtual uint32_t UnAckDataCount(void) const
Return count of number of unacked bytes.
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1350
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:501
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
static TypeId GetTypeId(void)
Get the type ID.
virtual uint32_t GetInitialSSThresh(void) const
Get the initial Slow Start Threshold.
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
Time TimeStep(uint64_t ts)
Definition: nstime.h:1064
static EventId ScheduleNow(MEM mem_ptr, OBJ obj)
Schedule an event to expire Now.
Definition: simulator.h:1564
virtual int Close(void)
Close a socket.
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:1070
Our side has shutdown after remote has shutdown.
Definition: tcp-socket.h:75
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer informations (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.
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
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.
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.
bool IsTcpOptionEnabled(uint8_t kind) const
Return true if the specified option is enabled.
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.
virtual TypeId GetInstanceTypeId() const
Get the instance TypeId.
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< TcpRxBuffer > GetRxBuffer(void) const
Get a pointer to the Rx buffer.
Describes an IPv6 address.
Definition: ipv6-address.h:49
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
Time GetMinRto(void) const
Get the Minimum RTO.
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:1072
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
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
uint32_t GetId(void) const
Definition: node.cc:107
TracedValue< Time > m_rto
Retransmit timeout.
Helper class to store RTT measurements.
uint16_t GetLocalPort(void)
Get the local port.
uint8_t m_rcvWindShift
Window shift to apply to outgoing segments.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
AttributeValue implementation for DataRate.
Definition: data-rate.h:242
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
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.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:269
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1007
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.
virtual uint32_t GetInitialCwnd(void) const
Get the initial Congestion Window.
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.
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.
uint16_t GetPort(void) const
Get the port.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
virtual enum SocketErrno GetErrno(void) const
Get last error number.
bool IsExpired(void) const
Definition: timer.cc:121
TracedValue< SequenceNumber32 > m_highTxMark
Highest seqno ever sent, regardless of ReTx.
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
void ProcessLastAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
Received a packet upon LAST_ACK.
Ipv4Address GetIpv4MappedAddress() const
Return the Ipv4 address.
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.
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:253
uint16_t GetPort(void) const
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.
A base class which provides memory management and object aggregation.
Definition: object.h:87
tuple address
Definition: first.py:37
virtual Ptr< Node > GetNode(void) const
Return the node this socket is associated with.
virtual void SetRcvBufSize(uint32_t size)
Set the receive buffer size.
bool m_shutdownRecv
Receive no longer allowed.
virtual Time GetDelAckTimeout(void) const
Get the time to delay an ACK.
TracedCallback< uint32_t, uint32_t > m_ssThTrace
Callback pointer for ssTh trace chaining.
EventId m_sendPendingDataEvent
micro-delay event to send pending data
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.
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:511
virtual void LastAckTimeout(void)
Timeout at LAST_ACK, close the connection.
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
Time GetDelayLeft(void) const
Definition: timer.cc:87
void SetPriority(uint8_t priority)
Set the tag's priority.
Definition: socket.cc:848
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Definition: double.h:41
uint32_t m_bytesAckedNotProcessed
Bytes acked, but not processed.
uint8_t GetPriority(void) const
Query the priority value of this socket.
Definition: socket.cc:402
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:1257
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
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.
void SetIpTos(uint8_t ipTos)
Manually set IP Type of Service field.
Definition: socket.cc:443
bool IsIpv4MappedAddress() const
If the address is an IPv4-mapped address.
EventId m_delAckEvent
Delayed ACK timeout event.
a unique identifier for an interface.
Definition: type-id.h:58
uint8_t m_sndWindShift
Window shift to apply to incoming segments.
bool m_shutdownSend
Send no longer allowed.
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:105
virtual Ptr< TcpSocketBase > Fork(void)
Call CopyObject<> to clone me.
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:914
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.
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
void AddOptionWScale(TcpHeader &header)
Add the window scale option to the header.
virtual uint32_t GetDelAckMaxCount(void) const
Get the number of packet to fire an ACK before delay timeout.
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 informations (address and port).
int SetupEndpoint(void)
Configure the endpoint to a local address.
virtual Time GetConnTimeout(void) const
Get the connection timeout.
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.
virtual uint32_t AvailableWindow(void) const
Return unfilled portion of window.
Time m_persistTimeout
Time between sending 1-byte probes.
virtual uint32_t GetTxAvailable(void) const
Returns the number of bytes which can be sent in a single call to Send.
Ptr< const TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:495
virtual uint32_t GetRxAvailable(void) const
Return number of bytes which can be returned from one or multiple calls to Recv.