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