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"
52 #include "rtt-estimator.h"
53 #include "tcp-congestion-ops.h"
54 
55 #include <math.h>
56 #include <algorithm>
57 
58 namespace ns3 {
59 
60 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase");
61 
62 NS_OBJECT_ENSURE_REGISTERED (TcpSocketBase);
63 
64 TypeId
66 {
67  static TypeId tid = TypeId ("ns3::TcpSocketBase")
68  .SetParent<TcpSocket> ()
69  .SetGroupName ("Internet")
70  .AddConstructor<TcpSocketBase> ()
71 // .AddAttribute ("TcpState", "State in TCP state machine",
72 // TypeId::ATTR_GET,
73 // EnumValue (CLOSED),
74 // MakeEnumAccessor (&TcpSocketBase::m_state),
75 // MakeEnumChecker (CLOSED, "Closed"))
76  .AddAttribute ("MaxSegLifetime",
77  "Maximum segment lifetime in seconds, use for TIME_WAIT state transition to CLOSED state",
78  DoubleValue (120), /* RFC793 says MSL=2 minutes*/
80  MakeDoubleChecker<double> (0))
81  .AddAttribute ("MaxWindowSize", "Max size of advertised window",
82  UintegerValue (65535),
84  MakeUintegerChecker<uint16_t> ())
85  .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
86  CallbackValue (),
89  .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
90  CallbackValue (),
93  .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option",
94  BooleanValue (true),
97  .AddAttribute ("Timestamp", "Enable or disable Timestamp option",
98  BooleanValue (true),
101  .AddAttribute ("MinRto",
102  "Minimum retransmit timeout value",
103  TimeValue (Seconds (1.0)), // RFC 6298 says min RTO=1 sec, but Linux uses 200ms.
104  // See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
107  MakeTimeChecker ())
108  .AddAttribute ("ClockGranularity",
109  "Clock Granularity used in RTO calculations",
110  TimeValue (MilliSeconds (1)), // RFC6298 suggest to use fine clock granularity
113  MakeTimeChecker ())
114  .AddAttribute ("TxBuffer",
115  "TCP Tx buffer",
116  PointerValue (),
118  MakePointerChecker<TcpTxBuffer> ())
119  .AddAttribute ("RxBuffer",
120  "TCP Rx buffer",
121  PointerValue (),
123  MakePointerChecker<TcpRxBuffer> ())
124  .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit",
125  UintegerValue (3),
127  MakeUintegerChecker<uint32_t> ())
128  .AddAttribute ("LimitedTransmit", "Enable limited transmit",
129  BooleanValue (true),
132  .AddTraceSource ("RTO",
133  "Retransmission timeout",
135  "ns3::Time::TracedValueCallback")
136  .AddTraceSource ("RTT",
137  "Last RTT sample",
139  "ns3::Time::TracedValueCallback")
140  .AddTraceSource ("NextTxSequence",
141  "Next sequence number to send (SND.NXT)",
143  "ns3::SequenceNumber32TracedValueCallback")
144  .AddTraceSource ("HighestSequence",
145  "Highest sequence number ever sent in socket's life time",
147  "ns3::SequenceNumber32TracedValueCallback")
148  .AddTraceSource ("State",
149  "TCP state",
151  "ns3::TcpStatesTracedValueCallback")
152  .AddTraceSource ("CongState",
153  "TCP Congestion machine state",
155  "ns3::TcpSocketState::TcpCongStatesTracedValueCallback")
156  .AddTraceSource ("RWND",
157  "Remote side's flow control window",
159  "ns3::TracedValueCallback::Uint32")
160  .AddTraceSource ("BytesInFlight",
161  "Socket estimation of bytes in flight",
163  "ns3::TracedValueCallback::Uint32")
164  .AddTraceSource ("HighestRxSequence",
165  "Highest sequence number received from peer",
167  "ns3::SequenceNumber32TracedValueCallback")
168  .AddTraceSource ("HighestRxAck",
169  "Highest ack received from peer",
171  "ns3::SequenceNumber32TracedValueCallback")
172  .AddTraceSource ("CongestionWindow",
173  "The TCP connection's congestion window",
175  "ns3::TracedValueCallback::Uint32")
176  .AddTraceSource ("SlowStartThreshold",
177  "TCP slow start threshold (bytes)",
179  "ns3::TracedValueCallback::Uint32")
180  .AddTraceSource ("Tx",
181  "Send tcp packet to IP protocol",
183  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
184  .AddTraceSource ("Rx",
185  "Receive tcp packet from IP protocol",
187  "ns3::TcpSocketBase::TcpTxRxTracedCallback")
188  ;
189  return tid;
190 }
191 
192 TypeId
194 {
195  return TcpSocketBase::GetTypeId ();
196 }
197 
198 
199 TypeId
201 {
202  static TypeId tid = TypeId ("ns3::TcpSocketState")
203  .SetParent<Object> ()
204  .SetGroupName ("Internet")
205  .AddConstructor <TcpSocketState> ()
206  .AddTraceSource ("CongestionWindow",
207  "The TCP connection's congestion window",
209  "ns3::TracedValue::Uint32Callback")
210  .AddTraceSource ("SlowStartThreshold",
211  "TCP slow start threshold (bytes)",
213  "ns3::TracedValue::Uint32Callback")
214  .AddTraceSource ("CongState",
215  "TCP Congestion machine state",
217  "ns3::TracedValue::TcpCongStatesTracedValueCallback")
218  .AddTraceSource ("HighestSequence",
219  "Highest sequence number received from peer",
221  "ns3::SequenceNumber32TracedValueCallback")
222  .AddTraceSource ("NextTxSequence",
223  "Next sequence number to send (SND.NXT)",
225  "ns3::SequenceNumber32TracedValueCallback")
226  ;
227  return tid;
228 }
229 
231  : Object (),
232  m_cWnd (0),
233  m_ssThresh (0),
234  m_initialCWnd (0),
235  m_initialSsThresh (0),
236  m_segmentSize (0),
237  m_lastAckedSeq (0),
238  m_congState (CA_OPEN),
239  m_highTxMark (0),
240  // Change m_nextTxSequence for non-zero initial sequence number
241  m_nextTxSequence (0)
242 {
243 }
244 
246  : Object (other),
247  m_cWnd (other.m_cWnd),
248  m_ssThresh (other.m_ssThresh),
249  m_initialCWnd (other.m_initialCWnd),
250  m_initialSsThresh (other.m_initialSsThresh),
251  m_segmentSize (other.m_segmentSize),
252  m_lastAckedSeq (other.m_lastAckedSeq),
253  m_congState (other.m_congState),
254  m_highTxMark (other.m_highTxMark),
255  m_nextTxSequence (other.m_nextTxSequence)
256 {
257 }
258 
259 const char* const
261 {
262  "CA_OPEN", "CA_DISORDER", "CA_CWR", "CA_RECOVERY", "CA_LOSS"
263 };
264 
266  : TcpSocket (),
267  m_retxEvent (),
268  m_lastAckEvent (),
269  m_delAckEvent (),
270  m_persistEvent (),
271  m_timewaitEvent (),
272  m_dupAckCount (0),
273  m_delAckCount (0),
274  m_delAckMaxCount (0),
275  m_noDelay (false),
276  m_synCount (0),
277  m_synRetries (0),
278  m_dataRetrCount (0),
279  m_dataRetries (0),
280  m_rto (Seconds (0.0)),
281  m_minRto (Time::Max ()),
282  m_clockGranularity (Seconds (0.001)),
283  m_lastRtt (Seconds (0.0)),
284  m_delAckTimeout (Seconds (0.0)),
285  m_persistTimeout (Seconds (0.0)),
286  m_cnTimeout (Seconds (0.0)),
287  m_endPoint (0),
288  m_endPoint6 (0),
289  m_node (0),
290  m_tcp (0),
291  m_rtt (0),
292  m_rxBuffer (0),
293  m_txBuffer (0),
294  m_state (CLOSED),
295  m_errno (ERROR_NOTERROR),
296  m_closeNotified (false),
297  m_closeOnEmpty (false),
298  m_shutdownSend (false),
299  m_shutdownRecv (false),
300  m_connected (false),
301  m_msl (0),
302  m_maxWinSize (0),
303  m_rWnd (0),
304  m_highRxMark (0),
305  m_highTxAck (0),
306  m_highRxAckMark (0),
307  m_bytesAckedNotProcessed (0),
308  m_bytesInFlight (0),
309  m_winScalingEnabled (false),
310  m_rcvWindShift (0),
311  m_sndWindShift (0),
312  m_timestampEnabled (true),
313  m_timestampToEcho (0),
314  m_sendPendingDataEvent (),
315  // Set m_recover to the initial sequence number
316  m_recover (0),
317  m_retxThresh (3),
318  m_limitedTx (false),
319  m_retransOut (0),
320  m_congestionControl (0),
321  m_isFirstPartialAck (true)
322 {
323  NS_LOG_FUNCTION (this);
324  m_rxBuffer = CreateObject<TcpRxBuffer> ();
325  m_txBuffer = CreateObject<TcpTxBuffer> ();
326  m_tcb = CreateObject<TcpSocketState> ();
327 
328  bool ok;
329 
330  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
332  NS_ASSERT (ok == true);
333 
334  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
336  NS_ASSERT (ok == true);
337 
338  ok = m_tcb->TraceConnectWithoutContext ("CongState",
340  NS_ASSERT (ok == true);
341 
342  ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
344  NS_ASSERT (ok == true);
345 
346  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
348  NS_ASSERT (ok == true);
349 }
350 
352  : TcpSocket (sock),
353  //copy object::m_tid and socket::callbacks
354  m_dupAckCount (sock.m_dupAckCount),
355  m_delAckCount (0),
356  m_delAckMaxCount (sock.m_delAckMaxCount),
357  m_noDelay (sock.m_noDelay),
358  m_synCount (sock.m_synCount),
359  m_synRetries (sock.m_synRetries),
360  m_dataRetrCount (sock.m_dataRetrCount),
361  m_dataRetries (sock.m_dataRetries),
362  m_rto (sock.m_rto),
363  m_minRto (sock.m_minRto),
364  m_clockGranularity (sock.m_clockGranularity),
365  m_lastRtt (sock.m_lastRtt),
366  m_delAckTimeout (sock.m_delAckTimeout),
367  m_persistTimeout (sock.m_persistTimeout),
368  m_cnTimeout (sock.m_cnTimeout),
369  m_endPoint (0),
370  m_endPoint6 (0),
371  m_node (sock.m_node),
372  m_tcp (sock.m_tcp),
373  m_state (sock.m_state),
374  m_errno (sock.m_errno),
375  m_closeNotified (sock.m_closeNotified),
376  m_closeOnEmpty (sock.m_closeOnEmpty),
377  m_shutdownSend (sock.m_shutdownSend),
378  m_shutdownRecv (sock.m_shutdownRecv),
379  m_connected (sock.m_connected),
380  m_msl (sock.m_msl),
381  m_maxWinSize (sock.m_maxWinSize),
382  m_rWnd (sock.m_rWnd),
383  m_highRxMark (sock.m_highRxMark),
384  m_highRxAckMark (sock.m_highRxAckMark),
385  m_bytesAckedNotProcessed (sock.m_bytesAckedNotProcessed),
386  m_bytesInFlight (sock.m_bytesInFlight),
387  m_winScalingEnabled (sock.m_winScalingEnabled),
388  m_rcvWindShift (sock.m_rcvWindShift),
389  m_sndWindShift (sock.m_sndWindShift),
390  m_timestampEnabled (sock.m_timestampEnabled),
391  m_timestampToEcho (sock.m_timestampToEcho),
392  m_recover (sock.m_recover),
393  m_retxThresh (sock.m_retxThresh),
394  m_limitedTx (sock.m_limitedTx),
395  m_retransOut (sock.m_retransOut),
396  m_isFirstPartialAck (sock.m_isFirstPartialAck),
397  m_txTrace (sock.m_txTrace),
398  m_rxTrace (sock.m_rxTrace)
399 {
400  NS_LOG_FUNCTION (this);
401  NS_LOG_LOGIC ("Invoked the copy constructor");
402  // Copy the rtt estimator if it is set
403  if (sock.m_rtt)
404  {
405  m_rtt = sock.m_rtt->Copy ();
406  }
407  // Reset all callbacks to null
408  Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
409  Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr<Socket>, const Address &> ();
410  Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t> ();
411  SetConnectCallback (vPS, vPS);
412  SetDataSentCallback (vPSUI);
413  SetSendCallback (vPSUI);
414  SetRecvCallback (vPS);
417  m_tcb = CopyObject (sock.m_tcb);
418  if (sock.m_congestionControl)
419  {
421  }
422 
423  bool ok;
424 
425  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
427  NS_ASSERT (ok == true);
428 
429  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
431  NS_ASSERT (ok == true);
432 
433  ok = m_tcb->TraceConnectWithoutContext ("CongState",
435  NS_ASSERT (ok == true);
436 
437  ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
439  NS_ASSERT (ok == true);
440 
441  ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
443 }
444 
446 {
447  NS_LOG_FUNCTION (this);
448  m_node = 0;
449  if (m_endPoint != 0)
450  {
451  NS_ASSERT (m_tcp != 0);
452  /*
453  * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
454  * DestroyCallback is set to TcpSocketBase::Destroy. If we called
455  * m_tcp->DeAllocate, it wil destroy its Ipv4EndpointDemux::DeAllocate,
456  * which in turn destroys my m_endPoint, and in turn invokes
457  * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
458  */
459  NS_ASSERT (m_endPoint != 0);
460  m_tcp->DeAllocate (m_endPoint);
461  NS_ASSERT (m_endPoint == 0);
462  }
463  if (m_endPoint6 != 0)
464  {
465  NS_ASSERT (m_tcp != 0);
466  NS_ASSERT (m_endPoint6 != 0);
467  m_tcp->DeAllocate (m_endPoint6);
468  NS_ASSERT (m_endPoint6 == 0);
469  }
470  m_tcp = 0;
471  CancelAllTimers ();
472 }
473 
474 /* Associate a node with this TCP socket */
475 void
477 {
478  m_node = node;
479 }
480 
481 /* Associate the L4 protocol (e.g. mux/demux) with this socket */
482 void
484 {
485  m_tcp = tcp;
486 }
487 
488 /* Set an RTT estimator with this socket */
489 void
491 {
492  m_rtt = rtt;
493 }
494 
495 /* Inherit from Socket class: Returns error code */
498 {
499  return m_errno;
500 }
501 
502 /* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
505 {
506  return NS3_SOCK_STREAM;
507 }
508 
509 /* Inherit from Socket class: Returns associated node */
510 Ptr<Node>
512 {
514  return m_node;
515 }
516 
517 /* Inherit from Socket class: Bind socket to an end-point in TcpL4Protocol */
518 int
520 {
521  NS_LOG_FUNCTION (this);
522  m_endPoint = m_tcp->Allocate ();
523  if (0 == m_endPoint)
524  {
526  return -1;
527  }
528 
529  m_tcp->AddSocket (this);
530 
531  return SetupCallback ();
532 }
533 
534 int
536 {
537  NS_LOG_FUNCTION (this);
538  m_endPoint6 = m_tcp->Allocate6 ();
539  if (0 == m_endPoint6)
540  {
542  return -1;
543  }
544 
545  m_tcp->AddSocket (this);
546 
547  return SetupCallback ();
548 }
549 
550 /* Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
551 int
553 {
554  NS_LOG_FUNCTION (this << address);
555  if (InetSocketAddress::IsMatchingType (address))
556  {
558  Ipv4Address ipv4 = transport.GetIpv4 ();
559  uint16_t port = transport.GetPort ();
560  SetIpTos (transport.GetTos ());
561  if (ipv4 == Ipv4Address::GetAny () && port == 0)
562  {
563  m_endPoint = m_tcp->Allocate ();
564  }
565  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
566  {
567  m_endPoint = m_tcp->Allocate (port);
568  }
569  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
570  {
571  m_endPoint = m_tcp->Allocate (ipv4);
572  }
573  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
574  {
575  m_endPoint = m_tcp->Allocate (ipv4, port);
576  }
577  if (0 == m_endPoint)
578  {
580  return -1;
581  }
582  }
583  else if (Inet6SocketAddress::IsMatchingType (address))
584  {
586  Ipv6Address ipv6 = transport.GetIpv6 ();
587  uint16_t port = transport.GetPort ();
588  if (ipv6 == Ipv6Address::GetAny () && port == 0)
589  {
590  m_endPoint6 = m_tcp->Allocate6 ();
591  }
592  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
593  {
594  m_endPoint6 = m_tcp->Allocate6 (port);
595  }
596  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
597  {
598  m_endPoint6 = m_tcp->Allocate6 (ipv6);
599  }
600  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
601  {
602  m_endPoint6 = m_tcp->Allocate6 (ipv6, port);
603  }
604  if (0 == m_endPoint6)
605  {
607  return -1;
608  }
609  }
610  else
611  {
613  return -1;
614  }
615 
616  m_tcp->AddSocket (this);
617 
618  NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
619 
620  return SetupCallback ();
621 }
622 
623 void
625 {
626  NS_ABORT_MSG_UNLESS ( (m_state == CLOSED) || threshold == m_tcb->m_initialSsThresh,
627  "TcpSocketBase::SetSSThresh() cannot change initial ssThresh after connection started.");
628 
629  m_tcb->m_initialSsThresh = threshold;
630 }
631 
632 uint32_t
634 {
635  return m_tcb->m_initialSsThresh;
636 }
637 
638 void
640 {
641  NS_ABORT_MSG_UNLESS ( (m_state == CLOSED) || cwnd == m_tcb->m_initialCWnd,
642  "TcpSocketBase::SetInitialCwnd() cannot change initial cwnd after connection started.");
643 
644  m_tcb->m_initialCWnd = cwnd;
645 }
646 
647 uint32_t
649 {
650  return m_tcb->m_initialCWnd;
651 }
652 
653 /* Inherit from Socket class: Initiate connection to a remote address:port */
654 int
656 {
657  NS_LOG_FUNCTION (this << address);
658 
659  // If haven't do so, Bind() this socket first
660  if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0)
661  {
662  if (m_endPoint == 0)
663  {
664  if (Bind () == -1)
665  {
666  NS_ASSERT (m_endPoint == 0);
667  return -1; // Bind() failed
668  }
669  NS_ASSERT (m_endPoint != 0);
670  }
672  m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
673  SetIpTos (transport.GetTos ());
674  m_endPoint6 = 0;
675 
676  // Get the appropriate local address and port number from the routing protocol and set up endpoint
677  if (SetupEndpoint () != 0)
678  {
679  NS_LOG_ERROR ("Route to destination does not exist ?!");
680  return -1;
681  }
682  }
683  else if (Inet6SocketAddress::IsMatchingType (address) && m_endPoint == 0)
684  {
685  // If we are operating on a v4-mapped address, translate the address to
686  // a v4 address and re-call this function
688  Ipv6Address v6Addr = transport.GetIpv6 ();
689  if (v6Addr.IsIpv4MappedAddress () == true)
690  {
691  Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
692  return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
693  }
694 
695  if (m_endPoint6 == 0)
696  {
697  if (Bind6 () == -1)
698  {
699  NS_ASSERT (m_endPoint6 == 0);
700  return -1; // Bind() failed
701  }
702  NS_ASSERT (m_endPoint6 != 0);
703  }
704  m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
705  m_endPoint = 0;
706 
707  // Get the appropriate local address and port number from the routing protocol and set up endpoint
708  if (SetupEndpoint6 () != 0)
709  { // Route to destination does not exist
710  return -1;
711  }
712  }
713  else
714  {
716  return -1;
717  }
718 
719  // Re-initialize parameters in case this socket is being reused after CLOSE
720  m_rtt->Reset ();
723 
724  // DoConnect() will do state-checking and send a SYN packet
725  return DoConnect ();
726 }
727 
728 /* Inherit from Socket class: Listen on the endpoint for an incoming connection */
729 int
731 {
732  NS_LOG_FUNCTION (this);
733 
734  // Linux quits EINVAL if we're not in CLOSED state, so match what they do
735  if (m_state != CLOSED)
736  {
738  return -1;
739  }
740  // In other cases, set the state to LISTEN and done
741  NS_LOG_DEBUG ("CLOSED -> LISTEN");
742  m_state = LISTEN;
743  return 0;
744 }
745 
746 /* Inherit from Socket class: Kill this socket and signal the peer (if any) */
747 int
749 {
750  NS_LOG_FUNCTION (this);
754  if (m_rxBuffer->Size () != 0)
755  {
756  NS_LOG_WARN ("Socket " << this << " << unread rx data during close. Sending reset." <<
757  "This is probably due to a bad sink application; check its code");
758  SendRST ();
759  return 0;
760  }
761 
762  if (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
763  { // App close with pending data must wait until all data transmitted
764  if (m_closeOnEmpty == false)
765  {
766  m_closeOnEmpty = true;
767  NS_LOG_INFO ("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
768  }
769  return 0;
770  }
771  return DoClose ();
772 }
773 
774 /* Inherit from Socket class: Signal a termination of send */
775 int
777 {
778  NS_LOG_FUNCTION (this);
779 
780  //this prevents data from being added to the buffer
781  m_shutdownSend = true;
782  m_closeOnEmpty = true;
783  //if buffer is already empty, send a fin now
784  //otherwise fin will go when buffer empties.
785  if (m_txBuffer->Size () == 0)
786  {
787  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
788  {
789  NS_LOG_INFO ("Emtpy tx buffer, send fin");
791 
792  if (m_state == ESTABLISHED)
793  { // On active close: I am the first one to send FIN
794  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
796  }
797  else
798  { // On passive close: Peer sent me FIN already
799  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
800  m_state = LAST_ACK;
801  }
802  }
803  }
804 
805  return 0;
806 }
807 
808 /* Inherit from Socket class: Signal a termination of receive */
809 int
811 {
812  NS_LOG_FUNCTION (this);
813  m_shutdownRecv = true;
814  return 0;
815 }
816 
817 /* Inherit from Socket class: Send a packet. Parameter flags is not used.
818  Packet has no TCP header. Invoked by upper-layer application */
819 int
820 TcpSocketBase::Send (Ptr<Packet> p, uint32_t flags)
821 {
822  NS_LOG_FUNCTION (this << p);
823  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Send()");
825  {
826  // Store the packet into Tx buffer
827  if (!m_txBuffer->Add (p))
828  { // TxBuffer overflow, send failed
830  return -1;
831  }
832  if (m_shutdownSend)
833  {
835  return -1;
836  }
837  // Submit the data to lower layers
838  NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpStateName[m_state]);
839  if (m_state == ESTABLISHED || m_state == CLOSE_WAIT)
840  { // Try to send the data out
842  {
845  this, m_connected);
846  }
847  }
848  return p->GetSize ();
849  }
850  else
851  { // Connection not established yet
853  return -1; // Send failure
854  }
855 }
856 
857 /* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
858 int
860 {
861  return Send (p, flags); // SendTo() and Send() are the same
862 }
863 
864 /* Inherit from Socket class: Return data to upper-layer application. Parameter flags
865  is not used. Data is returned as a packet of size no larger than maxSize */
867 TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
868 {
869  NS_LOG_FUNCTION (this);
870  NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()");
871  if (m_rxBuffer->Size () == 0 && m_state == CLOSE_WAIT)
872  {
873  return Create<Packet> (); // Send EOF on connection close
874  }
875  Ptr<Packet> outPacket = m_rxBuffer->Extract (maxSize);
876  return outPacket;
877 }
878 
879 /* Inherit from Socket class: Recv and return the remote's address */
881 TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
882 {
883  NS_LOG_FUNCTION (this << maxSize << flags);
884  Ptr<Packet> packet = Recv (maxSize, flags);
885  // Null packet means no data to read, and an empty packet indicates EOF
886  if (packet != 0 && packet->GetSize () != 0)
887  {
888  if (m_endPoint != 0)
889  {
891  }
892  else if (m_endPoint6 != 0)
893  {
895  }
896  else
897  {
898  fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
899  }
900  }
901  return packet;
902 }
903 
904 /* Inherit from Socket class: Get the max number of bytes an app can send */
905 uint32_t
907 {
908  NS_LOG_FUNCTION (this);
909  return m_txBuffer->Available ();
910 }
911 
912 /* Inherit from Socket class: Get the max number of bytes an app can read */
913 uint32_t
915 {
916  NS_LOG_FUNCTION (this);
917  return m_rxBuffer->Available ();
918 }
919 
920 /* Inherit from Socket class: Return local address:port */
921 int
923 {
924  NS_LOG_FUNCTION (this);
925  if (m_endPoint != 0)
926  {
928  }
929  else if (m_endPoint6 != 0)
930  {
932  }
933  else
934  { // It is possible to call this method on a socket without a name
935  // in which case, behavior is unspecified
936  // Should this return an InetSocketAddress or an Inet6SocketAddress?
937  address = InetSocketAddress (Ipv4Address::GetZero (), 0);
938  }
939  return 0;
940 }
941 
942 int
944 {
945  NS_LOG_FUNCTION (this << address);
946 
947  if (!m_endPoint && !m_endPoint6)
948  {
950  return -1;
951  }
952 
953  if (m_endPoint)
954  {
956  m_endPoint->GetPeerPort ());
957  }
958  else if (m_endPoint6)
959  {
962  }
963  else
964  {
965  NS_ASSERT (false);
966  }
967 
968  return 0;
969 }
970 
971 /* Inherit from Socket class: Bind this socket to the specified NetDevice */
972 void
974 {
975  NS_LOG_FUNCTION (netdevice);
976  Socket::BindToNetDevice (netdevice); // Includes sanity check
977  if (m_endPoint == 0)
978  {
979  if (Bind () == -1)
980  {
981  NS_ASSERT (m_endPoint == 0);
982  return;
983  }
984  NS_ASSERT (m_endPoint != 0);
985  }
986  m_endPoint->BindToNetDevice (netdevice);
987 
988  if (m_endPoint6 == 0)
989  {
990  if (Bind6 () == -1)
991  {
992  NS_ASSERT (m_endPoint6 == 0);
993  return;
994  }
995  NS_ASSERT (m_endPoint6 != 0);
996  }
997  m_endPoint6->BindToNetDevice (netdevice);
998 
999  return;
1000 }
1001 
1002 /* Clean up after Bind. Set up callback functions in the end-point. */
1003 int
1005 {
1006  NS_LOG_FUNCTION (this);
1007 
1008  if (m_endPoint == 0 && m_endPoint6 == 0)
1009  {
1010  return -1;
1011  }
1012  if (m_endPoint != 0)
1013  {
1017  }
1018  if (m_endPoint6 != 0)
1019  {
1023  }
1024 
1025  return 0;
1026 }
1027 
1028 /* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
1029 int
1031 {
1032  NS_LOG_FUNCTION (this);
1033 
1034  // A new connection is allowed only if this socket does not have a connection
1035  if (m_state == CLOSED || m_state == LISTEN || m_state == SYN_SENT || m_state == LAST_ACK || m_state == CLOSE_WAIT)
1036  { // send a SYN packet and change state into SYN_SENT
1038  NS_LOG_DEBUG (TcpStateName[m_state] << " -> SYN_SENT");
1039  m_state = SYN_SENT;
1040  }
1041  else if (m_state != TIME_WAIT)
1042  { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
1043  // exists. We send RST, tear down everything, and close this socket.
1044  SendRST ();
1045  CloseAndNotify ();
1046  }
1047  return 0;
1048 }
1049 
1050 /* Do the action to close the socket. Usually send a packet with appropriate
1051  flags depended on the current m_state. */
1052 int
1054 {
1055  NS_LOG_FUNCTION (this);
1056  switch (m_state)
1057  {
1058  case SYN_RCVD:
1059  case ESTABLISHED:
1060  // send FIN to close the peer
1062  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
1063  m_state = FIN_WAIT_1;
1064  break;
1065  case CLOSE_WAIT:
1066  // send FIN+ACK to close the peer
1068  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
1069  m_state = LAST_ACK;
1070  break;
1071  case SYN_SENT:
1072  case CLOSING:
1073  // Send RST if application closes in SYN_SENT and CLOSING
1074  SendRST ();
1075  CloseAndNotify ();
1076  break;
1077  case LISTEN:
1078  case LAST_ACK:
1079  // In these three states, move to CLOSED and tear down the end point
1080  CloseAndNotify ();
1081  break;
1082  case CLOSED:
1083  case FIN_WAIT_1:
1084  case FIN_WAIT_2:
1085  case TIME_WAIT:
1086  default: /* mute compiler */
1087  // Do nothing in these four states
1088  break;
1089  }
1090  return 0;
1091 }
1092 
1093 /* Peacefully close the socket by notifying the upper layer and deallocate end point */
1094 void
1096 {
1097  NS_LOG_FUNCTION (this);
1098 
1099  if (!m_closeNotified)
1100  {
1101  NotifyNormalClose ();
1102  m_closeNotified = true;
1103  }
1104 
1105  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSED");
1106  m_state = CLOSED;
1107  DeallocateEndPoint ();
1108 }
1109 
1110 
1111 /* Tell if a sequence number range is out side the range that my rx buffer can
1112  accpet */
1113 bool
1115 {
1116  if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
1117  { // Rx buffer in these states are not initialized.
1118  return false;
1119  }
1120  if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
1121  { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
1122  // sequence number must equals to m_rxBuffer->NextRxSequence ()
1123  return (m_rxBuffer->NextRxSequence () != head);
1124  }
1125 
1126  // In all other cases, check if the sequence number is in range
1127  return (tail < m_rxBuffer->NextRxSequence () || m_rxBuffer->MaxRxSequence () <= head);
1128 }
1129 
1130 /* Function called by the L3 protocol when it received a packet to pass on to
1131  the TCP. This function is registered as the "RxCallback" function in
1132  SetupCallback(), which invoked by Bind(), and CompleteFork() */
1133 void
1135  Ptr<Ipv4Interface> incomingInterface)
1136 {
1137  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1138  m_endPoint->GetPeerAddress () <<
1139  ":" << m_endPoint->GetPeerPort () <<
1140  " to " << m_endPoint->GetLocalAddress () <<
1141  ":" << m_endPoint->GetLocalPort ());
1142 
1143  Address fromAddress = InetSocketAddress (header.GetSource (), port);
1144  Address toAddress = InetSocketAddress (header.GetDestination (),
1145  m_endPoint->GetLocalPort ());
1146 
1147  DoForwardUp (packet, fromAddress, toAddress);
1148 }
1149 
1150 void
1152  Ptr<Ipv6Interface> incomingInterface)
1153 {
1154  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1156  ":" << m_endPoint6->GetPeerPort () <<
1157  " to " << m_endPoint6->GetLocalAddress () <<
1158  ":" << m_endPoint6->GetLocalPort ());
1159 
1160  Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port);
1161  Address toAddress = Inet6SocketAddress (header.GetDestinationAddress (),
1163 
1164  DoForwardUp (packet, fromAddress, toAddress);
1165 }
1166 
1167 void
1168 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1169  uint8_t icmpType, uint8_t icmpCode,
1170  uint32_t icmpInfo)
1171 {
1172  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1173  (uint32_t)icmpCode << icmpInfo);
1174  if (!m_icmpCallback.IsNull ())
1175  {
1176  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1177  }
1178 }
1179 
1180 void
1181 TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1182  uint8_t icmpType, uint8_t icmpCode,
1183  uint32_t icmpInfo)
1184 {
1185  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1186  (uint32_t)icmpCode << icmpInfo);
1187  if (!m_icmpCallback6.IsNull ())
1188  {
1189  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1190  }
1191 }
1192 
1193 void
1194 TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress,
1195  const Address &toAddress)
1196 {
1197  // in case the packet still has a priority tag attached, remove it
1198  SocketPriorityTag priorityTag;
1199  packet->RemovePacketTag (priorityTag);
1200 
1201  // Peel off TCP header and do validity checking
1202  TcpHeader tcpHeader;
1203  uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader);
1204  SequenceNumber32 seq = tcpHeader.GetSequenceNumber ();
1205  if (bytesRemoved == 0 || bytesRemoved > 60)
1206  {
1207  NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid");
1208  return; // Discard invalid packet
1209  }
1210  else if (packet->GetSize () > 0 && OutOfRange (seq, seq + packet->GetSize ()))
1211  {
1212  // Discard fully out of range data packets
1213  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1214  " received packet of seq [" << seq <<
1215  ":" << seq + packet->GetSize () <<
1216  ") out of range [" << m_rxBuffer->NextRxSequence () << ":" <<
1217  m_rxBuffer->MaxRxSequence () << ")");
1218  // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
1219  if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
1220  {
1222  }
1223  return;
1224  }
1225 
1226  m_rxTrace (packet, tcpHeader, this);
1227 
1228  if (tcpHeader.GetFlags () & TcpHeader::SYN)
1229  {
1230  /* The window field in a segment where the SYN bit is set (i.e., a <SYN>
1231  * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be
1232  * saved anyway..
1233  */
1234  m_rWnd = tcpHeader.GetWindowSize ();
1235 
1237  {
1239  }
1240  else
1241  {
1242  m_winScalingEnabled = false;
1243  }
1244 
1245  // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end
1246  if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled)
1247  {
1249  tcpHeader.GetSequenceNumber ());
1250  }
1251  else
1252  {
1253  m_timestampEnabled = false;
1254  }
1255 
1256  // Initialize cWnd and ssThresh
1257  m_tcb->m_cWnd = GetInitialCwnd () * GetSegSize ();
1258  m_tcb->m_ssThresh = GetInitialSSThresh ();
1259 
1260  if (tcpHeader.GetFlags () & TcpHeader::ACK)
1261  {
1262  EstimateRtt (tcpHeader);
1263  m_highRxAckMark = tcpHeader.GetAckNumber ();
1264  }
1265  }
1266  else if (tcpHeader.GetFlags () & TcpHeader::ACK)
1267  {
1268  NS_ASSERT (!(tcpHeader.GetFlags () & TcpHeader::SYN));
1269  if (m_timestampEnabled)
1270  {
1271  if (!tcpHeader.HasOption (TcpOption::TS))
1272  {
1273  // Ignoring segment without TS, RFC 7323
1274  NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1275  " received packet of seq [" << seq <<
1276  ":" << seq + packet->GetSize () <<
1277  ") without TS option. Silently discard it");
1278  return;
1279  }
1280  else
1281  {
1283  tcpHeader.GetSequenceNumber ());
1284  }
1285  }
1286 
1287  EstimateRtt (tcpHeader);
1288  UpdateWindowSize (tcpHeader);
1289  }
1290 
1291 
1292  if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ())
1293  { // Zero window: Enter persist state to send 1 byte to probe
1294  NS_LOG_LOGIC (this << " Enter zerowindow persist state");
1295  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1296  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1297  m_retxEvent.Cancel ();
1298  NS_LOG_LOGIC ("Schedule persist timeout at time " <<
1299  Simulator::Now ().GetSeconds () << " to expire at time " <<
1300  (Simulator::Now () + m_persistTimeout).GetSeconds ());
1303  }
1304 
1305  // TCP state machine code in different process functions
1306  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1307  switch (m_state)
1308  {
1309  case ESTABLISHED:
1310  ProcessEstablished (packet, tcpHeader);
1311  break;
1312  case LISTEN:
1313  ProcessListen (packet, tcpHeader, fromAddress, toAddress);
1314  break;
1315  case TIME_WAIT:
1316  // Do nothing
1317  break;
1318  case CLOSED:
1319  // Send RST if the incoming packet is not a RST
1320  if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1321  { // Since m_endPoint is not configured yet, we cannot use SendRST here
1322  TcpHeader h;
1323  Ptr<Packet> p = Create<Packet> ();
1325  h.SetSequenceNumber (m_tcb->m_nextTxSequence);
1326  h.SetAckNumber (m_rxBuffer->NextRxSequence ());
1327  h.SetSourcePort (tcpHeader.GetDestinationPort ());
1328  h.SetDestinationPort (tcpHeader.GetSourcePort ());
1330  AddOptions (h);
1331  m_txTrace (p, h, this);
1332  m_tcp->SendPacket (p, h, toAddress, fromAddress, m_boundnetdevice);
1333  }
1334  break;
1335  case SYN_SENT:
1336  ProcessSynSent (packet, tcpHeader);
1337  break;
1338  case SYN_RCVD:
1339  ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1340  break;
1341  case FIN_WAIT_1:
1342  case FIN_WAIT_2:
1343  case CLOSE_WAIT:
1344  ProcessWait (packet, tcpHeader);
1345  break;
1346  case CLOSING:
1347  ProcessClosing (packet, tcpHeader);
1348  break;
1349  case LAST_ACK:
1350  ProcessLastAck (packet, tcpHeader);
1351  break;
1352  default: // mute compiler
1353  break;
1354  }
1355 
1356  if (m_rWnd.Get () != 0 && m_persistEvent.IsRunning ())
1357  { // persist probes end, the other end has increased the window
1359  NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
1361 
1362  // Try to send more data, since window has been updated
1364  {
1367  this, m_connected);
1368  }
1369  }
1370 }
1371 
1372 /* Received a packet upon ESTABLISHED state. This function is mimicking the
1373  role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1374 void
1376 {
1377  NS_LOG_FUNCTION (this << tcpHeader);
1378 
1379  // Extract the flags. PSH and URG are not honoured.
1380  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1381 
1382  // Different flags are different events
1383  if (tcpflags == TcpHeader::ACK)
1384  {
1385  if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ())
1386  {
1387  // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be ignored.
1388  // Pag. 72 RFC 793
1389  NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1390  " SND.UNA = " << m_txBuffer->HeadSequence ());
1391 
1392  // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation]
1393  }
1394  else if (tcpHeader.GetAckNumber () > m_tcb->m_highTxMark)
1395  {
1396  // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then
1397  // send an ACK, drop the segment, and return.
1398  // Pag. 72 RFC 793
1399  NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1400  " HighTxMark = " << m_tcb->m_highTxMark);
1401 
1403  }
1404  else
1405  {
1406  // SND.UNA < SEG.ACK =< HighTxMark
1407  // Pag. 72 RFC 793
1408  ReceivedAck (packet, tcpHeader);
1409  }
1410  }
1411  else if (tcpflags == TcpHeader::SYN)
1412  { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1413  // respond with a SYN+ACK. But it is not a legal state transition as of
1414  // RFC793. Thus this is ignored.
1415  }
1416  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1417  { // No action for received SYN+ACK, it is probably a duplicated packet
1418  }
1419  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1420  { // Received FIN or FIN+ACK, bring down this socket nicely
1421  PeerClose (packet, tcpHeader);
1422  }
1423  else if (tcpflags == 0)
1424  { // No flags means there is only data
1425  ReceivedData (packet, tcpHeader);
1426  if (m_rxBuffer->Finished ())
1427  {
1428  PeerClose (packet, tcpHeader);
1429  }
1430  }
1431  else
1432  { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1433  if (tcpflags != TcpHeader::RST)
1434  { // this must be an invalid flag, send reset
1435  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
1436  SendRST ();
1437  }
1438  CloseAndNotify ();
1439  }
1440 }
1441 
1442 void
1444 {
1445  NS_LOG_FUNCTION (this);
1447  NS_ASSERT (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0);
1448 
1449  NS_LOG_INFO ("Limited transmit");
1450  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, m_tcb->m_segmentSize, true);
1451  m_tcb->m_nextTxSequence += sz;
1452 }
1453 
1454 void
1456 {
1457  NS_LOG_FUNCTION (this);
1458  NS_ASSERT (m_tcb->m_congState != TcpSocketState::CA_RECOVERY);
1459 
1460  m_recover = m_tcb->m_highTxMark;
1461  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_RECOVERY);
1462  m_tcb->m_congState = TcpSocketState::CA_RECOVERY;
1463 
1464  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb,
1465  BytesInFlight ());
1466  m_tcb->m_cWnd = m_tcb->m_ssThresh + m_dupAckCount * m_tcb->m_segmentSize;
1467 
1468  NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." <<
1469  "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
1470  m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover);
1471  DoRetransmit ();
1472 }
1473 
1474 void
1476 {
1477  NS_LOG_FUNCTION (this);
1478  ++m_dupAckCount;
1479 
1480  if (m_tcb->m_congState == TcpSocketState::CA_OPEN)
1481  {
1482  // From Open we go Disorder
1483  NS_ASSERT_MSG (m_dupAckCount == 1, "From OPEN->DISORDER but with " <<
1484  m_dupAckCount << " dup ACKs");
1485 
1486  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_DISORDER);
1487  m_tcb->m_congState = TcpSocketState::CA_DISORDER;
1488 
1489  NS_LOG_DEBUG ("OPEN -> DISORDER");
1490  }
1491 
1492  if (m_tcb->m_congState == TcpSocketState::CA_DISORDER)
1493  {
1495  {
1496  // triple duplicate ack triggers fast retransmit (RFC2582 sec.3 bullet #1)
1497  NS_LOG_DEBUG (TcpSocketState::TcpCongStateName[m_tcb->m_congState] <<
1498  " -> RECOVERY");
1499  FastRetransmit ();
1500  }
1501  else if (m_limitedTx && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
1502  {
1503  // RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit
1504  LimitedTransmit ();
1505  }
1506  }
1507  else if (m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1508  { // Increase cwnd for every additional dupack (RFC2582, sec.3 bullet #3)
1509  m_tcb->m_cWnd += m_tcb->m_segmentSize;
1510  NS_LOG_INFO (m_dupAckCount << " Dupack received in fast recovery mode."
1511  "Increase cwnd to " << m_tcb->m_cWnd);
1513  }
1514 
1515  // Artificially call PktsAcked. After all, one segment has been ACKed.
1516  m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt);
1517 }
1518 
1519 /* Process the newly received ACK */
1520 void
1522 {
1523  NS_LOG_FUNCTION (this << tcpHeader);
1524 
1525  NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK));
1526  NS_ASSERT (m_tcb->m_segmentSize > 0);
1527 
1528  SequenceNumber32 ackNumber = tcpHeader.GetAckNumber ();
1529 
1530  NS_LOG_DEBUG ("ACK of " << ackNumber <<
1531  " SND.UNA=" << m_txBuffer->HeadSequence () <<
1532  " SND.NXT=" << m_tcb->m_nextTxSequence);
1533 
1534  m_tcb->m_lastAckedSeq = ackNumber;
1535 
1536  if (ackNumber == m_txBuffer->HeadSequence ()
1537  && ackNumber < m_tcb->m_nextTxSequence
1538  && packet->GetSize () == 0)
1539  {
1540  // There is a DupAck
1541  DupAck ();
1542  }
1543  else if (ackNumber == m_txBuffer->HeadSequence ()
1544  && ackNumber == m_tcb->m_nextTxSequence)
1545  {
1546  // Dupack, but the ACK is precisely equal to the nextTxSequence
1547  }
1548  else if (ackNumber > m_txBuffer->HeadSequence ())
1549  { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer
1550  bool callCongestionControl = true;
1551  bool resetRTO = true;
1552  uint32_t bytesAcked = ackNumber - m_txBuffer->HeadSequence ();
1553  uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
1554  m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize;
1555 
1556  if (m_bytesAckedNotProcessed >= m_tcb->m_segmentSize)
1557  {
1558  segsAcked += 1;
1559  m_bytesAckedNotProcessed -= m_tcb->m_segmentSize;
1560  }
1561 
1562  NS_LOG_LOGIC (" Bytes acked: " << bytesAcked <<
1563  " Segments acked: " << segsAcked <<
1564  " bytes left: " << m_bytesAckedNotProcessed);
1565 
1566  /* The following switch is made because m_dupAckCount can be
1567  * "inflated" through out-of-order segments (e.g. from retransmission,
1568  * while segments have not been lost but are network-reordered). At
1569  * least one segment has been acked; in the luckiest case, an amount
1570  * equals to segsAcked-m_dupAckCount has not been processed.
1571  *
1572  * To be clear: segsAcked will be passed to PktsAcked, and it should take
1573  * in considerations the times that it has been already called, while newSegsAcked
1574  * will be passed to IncreaseCwnd, and it represents the amount of
1575  * segments that are allowed to increase the cWnd value.
1576  */
1577  uint32_t newSegsAcked = segsAcked;
1578  if (segsAcked > m_dupAckCount)
1579  {
1580  segsAcked -= m_dupAckCount;
1581  }
1582  else
1583  {
1584  segsAcked = 1;
1585  }
1586 
1587  if (m_tcb->m_congState == TcpSocketState::CA_OPEN)
1588  {
1589  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1590  }
1591  else if (m_tcb->m_congState == TcpSocketState::CA_DISORDER)
1592  {
1593  // The network reorder packets. Linux changes the counting lost
1594  // packet algorithm from FACK to NewReno. We simply go back in Open.
1595  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1596  m_tcb->m_congState = TcpSocketState::CA_OPEN;
1597  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1598  m_dupAckCount = 0;
1599  m_retransOut = 0;
1600 
1601  NS_LOG_DEBUG ("DISORDER -> OPEN");
1602  }
1603  else if (m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1604  {
1605  if (ackNumber < m_recover)
1606  {
1607  /* Partial ACK.
1608  * In case of partial ACK, retransmit the first unacknowledged
1609  * segment. Deflate the congestion window by the amount of new
1610  * data acknowledged by the Cumulative Acknowledgment field.
1611  * If the partial ACK acknowledges at least one SMSS of new data,
1612  * then add back SMSS bytes to the congestion window.
1613  * This artificially inflates the congestion window in order to
1614  * reflect the additional segment that has left the network.
1615  * Send a new segment if permitted by the new value of cwnd.
1616  * This "partial window deflation" attempts to ensure that, when
1617  * fast recovery eventually ends, approximately ssthresh amount
1618  * of data will be outstanding in the network. Do not exit the
1619  * fast recovery procedure (i.e., if any duplicate ACKs subsequently
1620  * arrive, execute step 4 of Section 3.2 of [RFC5681]).
1621  */
1622  m_tcb->m_cWnd = SafeSubtraction (m_tcb->m_cWnd, bytesAcked);
1623 
1624  if (segsAcked >= 1)
1625  {
1626  m_tcb->m_cWnd += m_tcb->m_segmentSize;
1627  }
1628 
1629  callCongestionControl = false; // No congestion control on cWnd show be invoked
1630  m_dupAckCount = SafeSubtraction (m_dupAckCount, segsAcked); // Update the dupAckCount
1631  m_retransOut = SafeSubtraction (m_retransOut, 1); // at least one retransmission
1632  // has reached the other side
1633  m_txBuffer->DiscardUpTo (ackNumber); //Bug 1850: retransmit before newack
1634  DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
1635 
1636  if (m_isFirstPartialAck)
1637  {
1638  m_isFirstPartialAck = false;
1639  }
1640  else
1641  {
1642  resetRTO = false;
1643  }
1644 
1645  /* This partial ACK acknowledge the fact that one segment has been
1646  * previously lost and now successfully received. All others have
1647  * been processed when they come under the form of dupACKs
1648  */
1649  m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt);
1650 
1651  NS_LOG_INFO ("Partial ACK for seq " << ackNumber <<
1652  " in fast recovery: cwnd set to " << m_tcb->m_cWnd <<
1653  " recover seq: " << m_recover <<
1654  " dupAck count: " << m_dupAckCount);
1655  }
1656  else if (ackNumber >= m_recover)
1657  { // Full ACK (RFC2582 sec.3 bullet #5 paragraph 2, option 1)
1658  m_tcb->m_cWnd = std::min (m_tcb->m_ssThresh.Get (),
1659  BytesInFlight () + m_tcb->m_segmentSize);
1660  m_isFirstPartialAck = true;
1661  m_dupAckCount = 0;
1662  m_retransOut = 0;
1663 
1664  /* This FULL ACK acknowledge the fact that one segment has been
1665  * previously lost and now successfully received. All others have
1666  * been processed when they come under the form of dupACKs,
1667  * except the (maybe) new ACKs which come from a new window
1668  */
1669  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1670  newSegsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
1671  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1672  m_tcb->m_congState = TcpSocketState::CA_OPEN;
1673 
1674  NS_LOG_INFO ("Received full ACK for seq " << ackNumber <<
1675  ". Leaving fast recovery with cwnd set to " << m_tcb->m_cWnd);
1676  NS_LOG_DEBUG ("RECOVERY -> OPEN");
1677  }
1678  }
1679  else if (m_tcb->m_congState == TcpSocketState::CA_LOSS)
1680  {
1681  // Go back in OPEN state
1682  m_isFirstPartialAck = true;
1683  m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt);
1684  m_dupAckCount = 0;
1685  m_retransOut = 0;
1686  if(ackNumber >= m_recover + 1)
1687  {
1688  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1689  m_tcb->m_congState = TcpSocketState::CA_OPEN;
1690  NS_LOG_DEBUG ("LOSS -> OPEN");
1691  }
1692  }
1693 
1694  if (callCongestionControl)
1695  {
1696  m_congestionControl->IncreaseWindow (m_tcb, newSegsAcked);
1697 
1698  NS_LOG_LOGIC ("Congestion control called: " <<
1699  " cWnd: " << m_tcb->m_cWnd <<
1700  " ssTh: " << m_tcb->m_ssThresh);
1701  }
1702 
1703  // Reset the data retransmission count. We got a new ACK!
1705 
1706  if (m_isFirstPartialAck == false)
1707  {
1708  NS_ASSERT (m_tcb->m_congState == TcpSocketState::CA_RECOVERY);
1709  }
1710 
1711  NewAck (ackNumber, resetRTO);
1712 
1713  // Try to send more data
1715  {
1718  this, m_connected);
1719  }
1720  }
1721 
1722  // If there is any data piggybacked, store it into m_rxBuffer
1723  if (packet->GetSize () > 0)
1724  {
1725  ReceivedData (packet, tcpHeader);
1726  }
1727 }
1728 
1729 /* Received a packet upon LISTEN state. */
1730 void
1732  const Address& fromAddress, const Address& toAddress)
1733 {
1734  NS_LOG_FUNCTION (this << tcpHeader);
1735 
1736  // Extract the flags. PSH and URG are not honoured.
1737  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1738 
1739  // Fork a socket if received a SYN. Do nothing otherwise.
1740  // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
1741  if (tcpflags != TcpHeader::SYN)
1742  {
1743  return;
1744  }
1745 
1746  // Call socket's notify function to let the server app know we got a SYN
1747  // If the server app refuses the connection, do nothing
1748  if (!NotifyConnectionRequest (fromAddress))
1749  {
1750  return;
1751  }
1752  // Clone the socket, simulate fork
1753  Ptr<TcpSocketBase> newSock = Fork ();
1754  NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
1756  packet, tcpHeader, fromAddress, toAddress);
1757 }
1758 
1759 /* Received a packet upon SYN_SENT */
1760 void
1762 {
1763  NS_LOG_FUNCTION (this << tcpHeader);
1764 
1765  // Extract the flags. PSH and URG are not honoured.
1766  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1767 
1768  if (tcpflags == 0)
1769  { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
1770  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
1771  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1772  m_state = ESTABLISHED;
1773  m_connected = true;
1774  m_retxEvent.Cancel ();
1776  ReceivedData (packet, tcpHeader);
1778  }
1779  else if (tcpflags == TcpHeader::ACK)
1780  { // Ignore ACK in SYN_SENT
1781  }
1782  else if (tcpflags == TcpHeader::SYN)
1783  { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
1784  NS_LOG_DEBUG ("SYN_SENT -> SYN_RCVD");
1785  m_state = SYN_RCVD;
1787  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1789  }
1790  else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK)
1791  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
1792  { // Handshake completed
1793  NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
1794  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1795  m_state = ESTABLISHED;
1796  m_connected = true;
1797  m_retxEvent.Cancel ();
1798  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1799  m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence;
1800  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
1804  // Always respond to first data packet to speed up the connection.
1805  // Remove to get the behaviour of old NS-3 code.
1807  }
1808  else
1809  { // Other in-sequence input
1810  if (tcpflags != TcpHeader::RST)
1811  { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
1812  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
1813  " received. Reset packet is sent.");
1814  SendRST ();
1815  }
1816  CloseAndNotify ();
1817  }
1818 }
1819 
1820 /* Received a packet upon SYN_RCVD */
1821 void
1823  const Address& fromAddress, const Address& toAddress)
1824 {
1825  NS_LOG_FUNCTION (this << tcpHeader);
1826 
1827  // Extract the flags. PSH and URG are not honoured.
1828  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1829 
1830  if (tcpflags == 0
1831  || (tcpflags == TcpHeader::ACK
1832  && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
1833  { // If it is bare data, accept it and move to ESTABLISHED state. This is
1834  // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
1835  // handshake is completed nicely.
1836  NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED");
1837  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
1838  m_state = ESTABLISHED;
1839  m_connected = true;
1840  m_retxEvent.Cancel ();
1841  m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence;
1842  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
1843  if (m_endPoint)
1844  {
1845  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1846  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1847  }
1848  else if (m_endPoint6)
1849  {
1850  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1851  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1852  }
1853  // Always respond to first data packet to speed up the connection.
1854  // Remove to get the behaviour of old NS-3 code.
1856  ReceivedAck (packet, tcpHeader);
1857  NotifyNewConnectionCreated (this, fromAddress);
1858  // As this connection is established, the socket is available to send data now
1859  if (GetTxAvailable () > 0)
1860  {
1862  }
1863  }
1864  else if (tcpflags == TcpHeader::SYN)
1865  { // Probably the peer lost my SYN+ACK
1866  m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
1868  }
1869  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1870  {
1871  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
1872  { // In-sequence FIN before connection complete. Set up connection and close.
1873  m_connected = true;
1874  m_retxEvent.Cancel ();
1875  m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence;
1876  m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
1877  if (m_endPoint)
1878  {
1879  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1880  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1881  }
1882  else if (m_endPoint6)
1883  {
1884  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1885  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1886  }
1887  PeerClose (packet, tcpHeader);
1888  }
1889  }
1890  else
1891  { // Other in-sequence input
1892  if (tcpflags != TcpHeader::RST)
1893  { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
1894  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
1895  " received. Reset packet is sent.");
1896  if (m_endPoint)
1897  {
1898  m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
1899  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
1900  }
1901  else if (m_endPoint6)
1902  {
1903  m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
1904  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
1905  }
1906  SendRST ();
1907  }
1908  CloseAndNotify ();
1909  }
1910 }
1911 
1912 /* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
1913 void
1915 {
1916  NS_LOG_FUNCTION (this << tcpHeader);
1917 
1918  // Extract the flags. PSH and URG are not honoured.
1919  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1920 
1921  if (packet->GetSize () > 0 && tcpflags != TcpHeader::ACK)
1922  { // Bare data, accept it
1923  ReceivedData (packet, tcpHeader);
1924  }
1925  else if (tcpflags == TcpHeader::ACK)
1926  { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
1927  ReceivedAck (packet, tcpHeader);
1928  if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
1929  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
1930  { // This ACK corresponds to the FIN sent
1931  NS_LOG_DEBUG ("FIN_WAIT_1 -> FIN_WAIT_2");
1932  m_state = FIN_WAIT_2;
1933  }
1934  }
1935  else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1936  { // Got FIN, respond with ACK and move to next state
1937  if (tcpflags & TcpHeader::ACK)
1938  { // Process the ACK first
1939  ReceivedAck (packet, tcpHeader);
1940  }
1941  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
1942  }
1943  else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1944  { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
1945  return;
1946  }
1947  else
1948  { // This is a RST or bad flags
1949  if (tcpflags != TcpHeader::RST)
1950  {
1951  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
1952  " received. Reset packet is sent.");
1953  SendRST ();
1954  }
1955  CloseAndNotify ();
1956  return;
1957  }
1958 
1959  // Check if the close responder sent an in-sequence FIN, if so, respond ACK
1960  if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_rxBuffer->Finished ())
1961  {
1962  if (m_state == FIN_WAIT_1)
1963  {
1964  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
1965  m_state = CLOSING;
1966  if (m_txBuffer->Size () == 0
1967  && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
1968  { // This ACK corresponds to the FIN sent
1969  TimeWait ();
1970  }
1971  }
1972  else if (m_state == FIN_WAIT_2)
1973  {
1974  TimeWait ();
1975  }
1977  if (!m_shutdownRecv)
1978  {
1979  NotifyDataRecv ();
1980  }
1981  }
1982 }
1983 
1984 /* Received a packet upon CLOSING */
1985 void
1987 {
1988  NS_LOG_FUNCTION (this << tcpHeader);
1989 
1990  // Extract the flags. PSH and URG are not honoured.
1991  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
1992 
1993  if (tcpflags == TcpHeader::ACK)
1994  {
1995  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
1996  { // This ACK corresponds to the FIN sent
1997  TimeWait ();
1998  }
1999  }
2000  else
2001  { // CLOSING state means simultaneous close, i.e. no one is sending data to
2002  // anyone. If anything other than ACK is received, respond with a reset.
2003  if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2004  { // FIN from the peer as well. We can close immediately.
2006  }
2007  else if (tcpflags != TcpHeader::RST)
2008  { // Receive of SYN or SYN+ACK or bad flags or pure data
2009  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2010  SendRST ();
2011  }
2012  CloseAndNotify ();
2013  }
2014 }
2015 
2016 /* Received a packet upon LAST_ACK */
2017 void
2019 {
2020  NS_LOG_FUNCTION (this << tcpHeader);
2021 
2022  // Extract the flags. PSH and URG are not honoured.
2023  uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2024 
2025  if (tcpflags == 0)
2026  {
2027  ReceivedData (packet, tcpHeader);
2028  }
2029  else if (tcpflags == TcpHeader::ACK)
2030  {
2031  if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ())
2032  { // This ACK corresponds to the FIN sent. This socket closed peacefully.
2033  CloseAndNotify ();
2034  }
2035  }
2036  else if (tcpflags == TcpHeader::FIN)
2037  { // Received FIN again, the peer probably lost the FIN+ACK
2039  }
2040  else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2041  {
2042  CloseAndNotify ();
2043  }
2044  else
2045  { // Received a SYN or SYN+ACK or bad flags
2046  NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2047  SendRST ();
2048  CloseAndNotify ();
2049  }
2050 }
2051 
2052 /* Peer sent me a FIN. Remember its sequence in rx buffer. */
2053 void
2055 {
2056  NS_LOG_FUNCTION (this << tcpHeader);
2057 
2058  // Ignore all out of range packets
2059  if (tcpHeader.GetSequenceNumber () < m_rxBuffer->NextRxSequence ()
2060  || tcpHeader.GetSequenceNumber () > m_rxBuffer->MaxRxSequence ())
2061  {
2062  return;
2063  }
2064  // For any case, remember the FIN position in rx buffer first
2065  m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2066  NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2067  // If there is any piggybacked data, process it
2068  if (p->GetSize ())
2069  {
2070  ReceivedData (p, tcpHeader);
2071  }
2072  // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2073  if (!m_rxBuffer->Finished ())
2074  {
2075  return;
2076  }
2077 
2078  // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2079  if (m_state == FIN_WAIT_1)
2080  {
2081  NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2082  m_state = CLOSING;
2083  return;
2084  }
2085 
2086  DoPeerClose (); // Change state, respond with ACK
2087 }
2088 
2089 /* Received a in-sequence FIN. Close down this socket. */
2090 void
2092 {
2094 
2095  // Move the state to CLOSE_WAIT
2096  NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSE_WAIT");
2097  m_state = CLOSE_WAIT;
2098 
2099  if (!m_closeNotified)
2100  {
2101  // The normal behaviour for an application is that, when the peer sent a in-sequence
2102  // FIN, the app should prepare to close. The app has two choices at this point: either
2103  // respond with ShutdownSend() call to declare that it has nothing more to send and
2104  // the socket can be closed immediately; or remember the peer's close request, wait
2105  // until all its existing data are pushed into the TCP socket, then call Close()
2106  // explicitly.
2107  NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
2108  NotifyNormalClose ();
2109  m_closeNotified = true;
2110  }
2111  if (m_shutdownSend)
2112  { // The application declares that it would not sent any more, close this socket
2113  Close ();
2114  }
2115  else
2116  { // Need to ack, the application will close later
2118  }
2119  if (m_state == LAST_ACK)
2120  {
2121  NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
2122  Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
2124  }
2125 }
2126 
2127 /* Kill this socket. This is a callback function configured to m_endpoint in
2128  SetupCallback(), invoked when the endpoint is destroyed. */
2129 void
2131 {
2132  NS_LOG_FUNCTION (this);
2133  m_endPoint = 0;
2134  if (m_tcp != 0)
2135  {
2136  m_tcp->RemoveSocket (this);
2137  }
2138  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2139  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2140  CancelAllTimers ();
2141 }
2142 
2143 /* Kill this socket. This is a callback function configured to m_endpoint in
2144  SetupCallback(), invoked when the endpoint is destroyed. */
2145 void
2147 {
2148  NS_LOG_FUNCTION (this);
2149  m_endPoint6 = 0;
2150  if (m_tcp != 0)
2151  {
2152  m_tcp->RemoveSocket (this);
2153  }
2154  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2155  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2156  CancelAllTimers ();
2157 }
2158 
2159 /* Send an empty packet with specified TCP flags */
2160 void
2162 {
2163  NS_LOG_FUNCTION (this << (uint32_t)flags);
2164  Ptr<Packet> p = Create<Packet> ();
2165  TcpHeader header;
2166  SequenceNumber32 s = m_tcb->m_nextTxSequence;
2167 
2168  /*
2169  * Add tags for each socket option.
2170  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2171  * if both options are set. Once the packet got to layer three, only
2172  * the corresponding tags will be read.
2173  */
2174  if (GetIpTos ())
2175  {
2176  SocketIpTosTag ipTosTag;
2177  ipTosTag.SetTos (GetIpTos ());
2178  p->AddPacketTag (ipTosTag);
2179  }
2180 
2181  if (IsManualIpv6Tclass ())
2182  {
2183  SocketIpv6TclassTag ipTclassTag;
2184  ipTclassTag.SetTclass (GetIpv6Tclass ());
2185  p->AddPacketTag (ipTclassTag);
2186  }
2187 
2188  if (IsManualIpTtl ())
2189  {
2190  SocketIpTtlTag ipTtlTag;
2191  ipTtlTag.SetTtl (GetIpTtl ());
2192  p->AddPacketTag (ipTtlTag);
2193  }
2194 
2195  if (IsManualIpv6HopLimit ())
2196  {
2197  SocketIpv6HopLimitTag ipHopLimitTag;
2198  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
2199  p->AddPacketTag (ipHopLimitTag);
2200  }
2201 
2202  uint8_t priority = GetPriority ();
2203  if (priority)
2204  {
2205  SocketPriorityTag priorityTag;
2206  priorityTag.SetPriority (priority);
2207  p->ReplacePacketTag (priorityTag);
2208  }
2209 
2210  if (m_endPoint == 0 && m_endPoint6 == 0)
2211  {
2212  NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
2213  return;
2214  }
2215  if (flags & TcpHeader::FIN)
2216  {
2217  flags |= TcpHeader::ACK;
2218  }
2219  else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2220  {
2221  ++s;
2222  }
2223 
2224  header.SetFlags (flags);
2225  header.SetSequenceNumber (s);
2226  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2227  if (m_endPoint != 0)
2228  {
2229  header.SetSourcePort (m_endPoint->GetLocalPort ());
2230  header.SetDestinationPort (m_endPoint->GetPeerPort ());
2231  }
2232  else
2233  {
2234  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2235  header.SetDestinationPort (m_endPoint6->GetPeerPort ());
2236  }
2237  AddOptions (header);
2238 
2239  // RFC 6298, clause 2.4
2240  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2241 
2242  uint16_t windowSize = AdvertisedWindowSize ();
2243  bool hasSyn = flags & TcpHeader::SYN;
2244  bool hasFin = flags & TcpHeader::FIN;
2245  bool isAck = flags == TcpHeader::ACK;
2246  if (hasSyn)
2247  {
2248  if (m_winScalingEnabled)
2249  { // The window scaling option is set only on SYN packets
2250  AddOptionWScale (header);
2251  }
2252 
2253  if (m_synCount == 0)
2254  { // No more connection retries, give up
2255  NS_LOG_LOGIC ("Connection failed.");
2256  m_rtt->Reset (); //According to recommendation -> RFC 6298
2257  CloseAndNotify ();
2258  return;
2259  }
2260  else
2261  { // Exponential backoff of connection time out
2262  int backoffCount = 0x1 << (m_synRetries - m_synCount);
2263  m_rto = m_cnTimeout * backoffCount;
2264  m_synCount--;
2265  }
2266 
2267  if (m_synRetries - 1 == m_synCount)
2268  {
2269  UpdateRttHistory (s, 0, false);
2270  }
2271  else
2272  { // This is SYN retransmission
2273  UpdateRttHistory (s, 0, true);
2274  }
2275 
2276  windowSize = AdvertisedWindowSize (false);
2277  }
2278  header.SetWindowSize (windowSize);
2279 
2280  m_txTrace (p, header, this);
2281 
2282  if (m_endPoint != 0)
2283  {
2284  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2286  }
2287  else
2288  {
2289  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2291  }
2292 
2293  if (flags & TcpHeader::ACK)
2294  { // If sending an ACK, cancel the delay ACK as well
2295  m_delAckEvent.Cancel ();
2296  m_delAckCount = 0;
2297  if (m_highTxAck < header.GetAckNumber ())
2298  {
2299  m_highTxAck = header.GetAckNumber ();
2300  }
2301  }
2302  if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
2303  { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2304  NS_LOG_LOGIC ("Schedule retransmission timeout at time "
2305  << Simulator::Now ().GetSeconds () << " to expire at time "
2306  << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2308  }
2309 }
2310 
2311 /* This function closes the endpoint completely. Called upon RST_TX action. */
2312 void
2314 {
2315  NS_LOG_FUNCTION (this);
2317  NotifyErrorClose ();
2318  DeallocateEndPoint ();
2319 }
2320 
2321 /* Deallocate the end point and cancel all the timers */
2322 void
2324 {
2325  if (m_endPoint != 0)
2326  {
2327  CancelAllTimers ();
2328  m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
2329  m_tcp->DeAllocate (m_endPoint);
2330  m_endPoint = 0;
2331  m_tcp->RemoveSocket (this);
2332  }
2333  else if (m_endPoint6 != 0)
2334  {
2335  CancelAllTimers ();
2336  m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
2337  m_tcp->DeAllocate (m_endPoint6);
2338  m_endPoint6 = 0;
2339  m_tcp->RemoveSocket (this);
2340  }
2341 }
2342 
2343 /* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2344 int
2346 {
2347  NS_LOG_FUNCTION (this);
2348  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
2349  NS_ASSERT (ipv4 != 0);
2350  if (ipv4->GetRoutingProtocol () == 0)
2351  {
2352  NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
2353  }
2354  // Create a dummy packet, then ask the routing function for the best output
2355  // interface's address
2356  Ipv4Header header;
2358  Socket::SocketErrno errno_;
2359  Ptr<Ipv4Route> route;
2361  route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2362  if (route == 0)
2363  {
2364  NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
2365  NS_LOG_ERROR (errno_);
2366  m_errno = errno_;
2367  return -1;
2368  }
2369  NS_LOG_LOGIC ("Route exists");
2370  m_endPoint->SetLocalAddress (route->GetSource ());
2371  return 0;
2372 }
2373 
2374 int
2376 {
2377  NS_LOG_FUNCTION (this);
2379  NS_ASSERT (ipv6 != 0);
2380  if (ipv6->GetRoutingProtocol () == 0)
2381  {
2382  NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
2383  }
2384  // Create a dummy packet, then ask the routing function for the best output
2385  // interface's address
2386  Ipv6Header header;
2388  Socket::SocketErrno errno_;
2389  Ptr<Ipv6Route> route;
2391  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2392  if (route == 0)
2393  {
2394  NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
2395  NS_LOG_ERROR (errno_);
2396  m_errno = errno_;
2397  return -1;
2398  }
2399  NS_LOG_LOGIC ("Route exists");
2400  m_endPoint6->SetLocalAddress (route->GetSource ());
2401  return 0;
2402 }
2403 
2404 /* This function is called only if a SYN received in LISTEN state. After
2405  TcpSocketBase cloned, allocate a new end point to handle the incoming
2406  connection and send a SYN+ACK to complete the handshake. */
2407 void
2409  const Address& fromAddress, const Address& toAddress)
2410 {
2411  // Get port and address from peer (connecting host)
2412  if (InetSocketAddress::IsMatchingType (toAddress))
2413  {
2414  m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
2415  InetSocketAddress::ConvertFrom (toAddress).GetPort (),
2416  InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2417  InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2418  m_endPoint6 = 0;
2419  }
2420  else if (Inet6SocketAddress::IsMatchingType (toAddress))
2421  {
2422  m_endPoint6 = m_tcp->Allocate6 (Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
2423  Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
2424  Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2425  Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2426  m_endPoint = 0;
2427  }
2428  m_tcp->AddSocket (this);
2429 
2430  // Change the cloned socket from LISTEN state to SYN_RCVD
2431  NS_LOG_DEBUG ("LISTEN -> SYN_RCVD");
2432  m_state = SYN_RCVD;
2435  SetupCallback ();
2436  // Set the sequence number and send SYN+ACK
2437  m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
2438 
2440 }
2441 
2442 void
2444 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can
2445  // be called as a scheduled event
2447  // The if-block below was moved from ProcessSynSent() to here because we need
2448  // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
2449  // reflect the behaviour in the real world.
2450  if (GetTxAvailable () > 0)
2451  {
2453  }
2454 }
2455 
2456 /* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
2457  TCP header, and send to TcpL4Protocol */
2458 uint32_t
2459 TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck)
2460 {
2461  NS_LOG_FUNCTION (this << seq << maxSize << withAck);
2462 
2463  bool isRetransmission = false;
2464  if (seq != m_tcb->m_highTxMark)
2465  {
2466  isRetransmission = true;
2467  }
2468 
2469  Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq);
2470  uint32_t sz = p->GetSize (); // Size of packet
2471  uint8_t flags = withAck ? TcpHeader::ACK : 0;
2472  uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
2473 
2474  if (withAck)
2475  {
2476  m_delAckEvent.Cancel ();
2477  m_delAckCount = 0;
2478  }
2479 
2480  /*
2481  * Add tags for each socket option.
2482  * Note that currently the socket adds both IPv4 tag and IPv6 tag
2483  * if both options are set. Once the packet got to layer three, only
2484  * the corresponding tags will be read.
2485  */
2486  if (GetIpTos ())
2487  {
2488  SocketIpTosTag ipTosTag;
2489  ipTosTag.SetTos (GetIpTos ());
2490  p->AddPacketTag (ipTosTag);
2491  }
2492 
2493  if (IsManualIpv6Tclass ())
2494  {
2495  SocketIpv6TclassTag ipTclassTag;
2496  ipTclassTag.SetTclass (GetIpv6Tclass ());
2497  p->AddPacketTag (ipTclassTag);
2498  }
2499 
2500  if (IsManualIpTtl ())
2501  {
2502  SocketIpTtlTag ipTtlTag;
2503  ipTtlTag.SetTtl (GetIpTtl ());
2504  p->AddPacketTag (ipTtlTag);
2505  }
2506 
2507  if (IsManualIpv6HopLimit ())
2508  {
2509  SocketIpv6HopLimitTag ipHopLimitTag;
2510  ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
2511  p->AddPacketTag (ipHopLimitTag);
2512  }
2513 
2514  uint8_t priority = GetPriority ();
2515  if (priority)
2516  {
2517  SocketPriorityTag priorityTag;
2518  priorityTag.SetPriority (priority);
2519  p->ReplacePacketTag (priorityTag);
2520  }
2521 
2522  if (m_closeOnEmpty && (remainingData == 0))
2523  {
2524  flags |= TcpHeader::FIN;
2525  if (m_state == ESTABLISHED)
2526  { // On active close: I am the first one to send FIN
2527  NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
2528  m_state = FIN_WAIT_1;
2529  }
2530  else if (m_state == CLOSE_WAIT)
2531  { // On passive close: Peer sent me FIN already
2532  NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
2533  m_state = LAST_ACK;
2534  }
2535  }
2536  TcpHeader header;
2537  header.SetFlags (flags);
2538  header.SetSequenceNumber (seq);
2539  header.SetAckNumber (m_rxBuffer->NextRxSequence ());
2540  if (m_endPoint)
2541  {
2542  header.SetSourcePort (m_endPoint->GetLocalPort ());
2544  }
2545  else
2546  {
2547  header.SetSourcePort (m_endPoint6->GetLocalPort ());
2549  }
2550  header.SetWindowSize (AdvertisedWindowSize ());
2551  AddOptions (header);
2552 
2553  if (m_retxEvent.IsExpired ())
2554  {
2555  // Schedules retransmit timeout. If this is a retransmission, double the timer
2556 
2557  if (isRetransmission)
2558  { // This is a retransmit
2559  // RFC 6298, clause 2.5
2560  Time doubledRto = m_rto + m_rto;
2561  m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
2562  }
2563 
2564  NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
2565  Simulator::Now ().GetSeconds () << " to expire at time " <<
2566  (Simulator::Now () + m_rto.Get ()).GetSeconds () );
2568  }
2569 
2570  m_txTrace (p, header, this);
2571 
2572  if (m_endPoint)
2573  {
2574  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2576  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
2577  remainingData << " via TcpL4Protocol to " << m_endPoint->GetPeerAddress () <<
2578  ". Header " << header);
2579  }
2580  else
2581  {
2582  m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2584  NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
2585  remainingData << " via TcpL4Protocol to " << m_endPoint6->GetPeerAddress () <<
2586  ". Header " << header);
2587  }
2588 
2589  UpdateRttHistory (seq, sz, isRetransmission);
2590 
2591  // Notify the application of the data being sent unless this is a retransmit
2592  if (seq + sz > m_tcb->m_highTxMark)
2593  {
2595  (seq + sz - m_tcb->m_highTxMark.Get ()));
2596  }
2597  // Update highTxMark
2598  m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ());
2599  return sz;
2600 }
2601 
2602 void
2604  bool isRetransmission)
2605 {
2606  NS_LOG_FUNCTION (this);
2607 
2608  // update the history of sequence numbers used to calculate the RTT
2609  if (isRetransmission == false)
2610  { // This is the next expected one, just log at end
2611  m_history.push_back (RttHistory (seq, sz, Simulator::Now ()));
2612  }
2613  else
2614  { // This is a retransmit, find in list and mark as re-tx
2615  for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i)
2616  {
2617  if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
2618  { // Found it
2619  i->retx = true;
2620  i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
2621  break;
2622  }
2623  }
2624  }
2625 }
2626 
2627 /* Send as much pending data as possible according to the Tx window. Note that
2628  * this function did not implement the PSH flag
2629  */
2630 bool
2632 {
2633  NS_LOG_FUNCTION (this << withAck);
2634  if (m_txBuffer->Size () == 0)
2635  {
2636  return false; // Nothing to send
2637  }
2638  if (m_endPoint == 0 && m_endPoint6 == 0)
2639  {
2640  NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
2641  return false; // Is this the right way to handle this condition?
2642  }
2643  uint32_t nPacketsSent = 0;
2644  while (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence))
2645  {
2646  uint32_t w = AvailableWindow (); // Get available window size
2647  // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
2648  if (w < m_tcb->m_segmentSize && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > w)
2649  {
2650  NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
2651  break; // No more
2652  }
2653  // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
2654  // in the buffer and the amount of data to send is less than one segment
2655  if (!m_noDelay && UnAckDataCount () > 0
2656  && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) < m_tcb->m_segmentSize)
2657  {
2658  NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send.");
2659  break;
2660  }
2661  NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" <<
2662  " w " << w <<
2663  " rxwin " << m_rWnd <<
2664  " segsize " << m_tcb->m_segmentSize <<
2665  " nextTxSeq " << m_tcb->m_nextTxSequence <<
2666  " highestRxAck " << m_txBuffer->HeadSequence () <<
2667  " pd->Size " << m_txBuffer->Size () <<
2668  " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence));
2669 
2670  NS_LOG_DEBUG ("Window: " << w <<
2671  " cWnd: " << m_tcb->m_cWnd <<
2672  " unAck: " << UnAckDataCount ());
2673 
2674  uint32_t s = std::min (w, m_tcb->m_segmentSize); // Send no more than window
2675  uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck);
2676  nPacketsSent++; // Count sent this loop
2677  m_tcb->m_nextTxSequence += sz; // Advance next tx sequence
2678  }
2679  if (nPacketsSent > 0)
2680  {
2681  NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments");
2682  }
2683  return (nPacketsSent > 0);
2684 }
2685 
2686 uint32_t
2688 {
2689  NS_LOG_FUNCTION (this);
2690  return m_tcb->m_nextTxSequence.Get () - m_txBuffer->HeadSequence ();
2691 }
2692 
2693 uint32_t
2695 {
2696  NS_LOG_FUNCTION (this);
2697  // Previous (see bug 1783):
2698  // uint32_t bytesInFlight = m_highTxMark.Get () - m_txBuffer->HeadSequence ();
2699  // RFC 4898 page 23
2700  // PipeSize=SND.NXT-SND.UNA+(retransmits-dupacks)*CurMSS
2701 
2702  // flightSize == UnAckDataCount (), but we avoid the call to save log lines
2703  uint32_t flightSize = m_tcb->m_nextTxSequence.Get () - m_txBuffer->HeadSequence ();
2704  uint32_t duplicatedSize;
2705  uint32_t bytesInFlight;
2706 
2708  {
2709  duplicatedSize = (m_retransOut - m_dupAckCount)*m_tcb->m_segmentSize;
2710  bytesInFlight = flightSize + duplicatedSize;
2711  }
2712  else
2713  {
2714  duplicatedSize = (m_dupAckCount - m_retransOut)*m_tcb->m_segmentSize;
2715  bytesInFlight = duplicatedSize > flightSize ? 0 : flightSize - duplicatedSize;
2716  }
2717 
2718  // m_bytesInFlight is traced; avoid useless assignments which would fire
2719  // fruitlessly the callback
2720  if (m_bytesInFlight != bytesInFlight)
2721  {
2722  m_bytesInFlight = bytesInFlight;
2723  }
2724 
2725  return bytesInFlight;
2726 }
2727 
2728 uint32_t
2730 {
2731  NS_LOG_FUNCTION (this);
2732  return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
2733 }
2734 
2735 uint32_t
2737 {
2739  uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
2740  uint32_t win = Window (); // Number of bytes allowed to be outstanding
2741 
2742  NS_LOG_DEBUG ("UnAckCount=" << unack << ", Win=" << win);
2743  return (win < unack) ? 0 : (win - unack);
2744 }
2745 
2746 uint16_t
2748 {
2749  NS_LOG_FUNCTION (this << scale);
2750  uint32_t w = m_rxBuffer->MaxBufferSize ();
2751 
2752  if (scale)
2753  {
2754  w >>= m_rcvWindShift;
2755  }
2756  if (w > m_maxWinSize)
2757  {
2758  w = m_maxWinSize;
2759  NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
2760  }
2761  NS_LOG_DEBUG ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
2762  return static_cast<uint16_t> (w);
2763 }
2764 
2765 // Receipt of new packet, put into Rx buffer
2766 void
2768 {
2769  NS_LOG_FUNCTION (this << tcpHeader);
2770  NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () <<
2771  " pkt size=" << p->GetSize () );
2772 
2773  // Put into Rx buffer
2774  SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence ();
2775  if (!m_rxBuffer->Add (p, tcpHeader))
2776  { // Insert failed: No data or RX buffer full
2778  return;
2779  }
2780  // Now send a new ACK packet acknowledging all received and delivered data
2781  if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
2782  { // A gap exists in the buffer, or we filled a gap: Always ACK
2784  }
2785  else
2786  { // In-sequence packet: ACK if delayed ack count allows
2788  {
2789  m_delAckEvent.Cancel ();
2790  m_delAckCount = 0;
2792  }
2793  else if (m_delAckEvent.IsExpired ())
2794  {
2797  NS_LOG_LOGIC (this << " scheduled delayed ACK at " <<
2798  (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ());
2799  }
2800  }
2801  // Notify app to receive if necessary
2802  if (expectedSeq < m_rxBuffer->NextRxSequence ())
2803  { // NextRxSeq advanced, we have something to send to the app
2804  if (!m_shutdownRecv)
2805  {
2806  NotifyDataRecv ();
2807  }
2808  // Handle exceptions
2809  if (m_closeNotified)
2810  {
2811  NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
2812  }
2813  // If we received FIN before and now completed all "holes" in rx buffer,
2814  // invoke peer close procedure
2815  if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
2816  {
2817  DoPeerClose ();
2818  }
2819  }
2820 }
2821 
2829 void
2831 {
2832  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber ();
2833  Time m = Time (0.0);
2834 
2835  // An ack has been received, calculate rtt and log this measurement
2836  // Note we use a linear search (O(n)) for this since for the common
2837  // case the ack'ed packet will be at the head of the list
2838  if (!m_history.empty ())
2839  {
2840  RttHistory& h = m_history.front ();
2841  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
2842  { // Ok to use this sample
2843  if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
2844  {
2845  Ptr<TcpOptionTS> ts;
2846  ts = DynamicCast<TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
2847  m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
2848  }
2849  else
2850  {
2851  m = Simulator::Now () - h.time; // Elapsed time
2852  }
2853  }
2854  }
2855 
2856  // Now delete all ack history with seq <= ack
2857  while (!m_history.empty ())
2858  {
2859  RttHistory& h = m_history.front ();
2860  if ((h.seq + SequenceNumber32 (h.count)) > ackSeq)
2861  {
2862  break; // Done removing
2863  }
2864  m_history.pop_front (); // Remove
2865  }
2866 
2867  if (!m.IsZero ())
2868  {
2869  m_rtt->Measurement (m); // Log the measurement
2870  // RFC 6298, clause 2.4
2871  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2872  m_lastRtt = m_rtt->GetEstimate ();
2873  NS_LOG_FUNCTION (this << m_lastRtt);
2874  }
2875 }
2876 
2877 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
2878 // when the three-way handshake completed. This cancels retransmission timer
2879 // and advances Tx window
2880 void
2881 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO)
2882 {
2883  NS_LOG_FUNCTION (this << ack);
2884 
2885  if (m_state != SYN_RCVD && resetRTO)
2886  { // Set RTO unless the ACK is received in SYN_RCVD state
2887  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2888  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2889  m_retxEvent.Cancel ();
2890  // On receiving a "New" ack we restart retransmission timer .. RFC 6298
2891  // RFC 6298, clause 2.4
2892  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2893 
2894  NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
2895  Simulator::Now ().GetSeconds () << " to expire at time " <<
2896  (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2898  }
2899 
2900  // Note the highest ACK and tell app to send more
2901  NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
2902  " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
2903  m_txBuffer->DiscardUpTo (ack);
2904  if (GetTxAvailable () > 0)
2905  {
2907  }
2908  if (ack > m_tcb->m_nextTxSequence)
2909  {
2910  m_tcb->m_nextTxSequence = ack; // If advanced
2911  }
2912  if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
2913  { // No retransmit timer if no data to retransmit
2914  NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2915  (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2916  m_retxEvent.Cancel ();
2917  }
2918 }
2919 
2920 // Retransmit timeout
2921 void
2923 {
2924  NS_LOG_FUNCTION (this);
2925  NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
2926  // If erroneous timeout in closed/timed-wait state, just return
2927  if (m_state == CLOSED || m_state == TIME_WAIT)
2928  {
2929  return;
2930  }
2931  // If all data are received (non-closing socket and nothing to send), just return
2932  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark)
2933  {
2934  return;
2935  }
2936 
2937  m_recover = m_tcb->m_highTxMark;
2938  Retransmit ();
2939 }
2940 
2941 void
2943 {
2944  m_delAckCount = 0;
2946 }
2947 
2948 void
2950 {
2951  NS_LOG_FUNCTION (this);
2952 
2954  if (m_state == LAST_ACK)
2955  {
2956  CloseAndNotify ();
2957  }
2958  if (!m_closeNotified)
2959  {
2960  m_closeNotified = true;
2961  }
2962 }
2963 
2964 // Send 1-byte data to probe for the window size at the receiver when
2965 // the local knowledge tells that the receiver has zero window size
2966 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
2967 void
2969 {
2970  NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
2971  m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
2972  Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence);
2973  TcpHeader tcpHeader;
2974  tcpHeader.SetSequenceNumber (m_tcb->m_nextTxSequence);
2975  tcpHeader.SetAckNumber (m_rxBuffer->NextRxSequence ());
2976  tcpHeader.SetWindowSize (AdvertisedWindowSize ());
2977  if (m_endPoint != 0)
2978  {
2979  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
2980  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
2981  }
2982  else
2983  {
2984  tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
2985  tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
2986  }
2987  AddOptions (tcpHeader);
2988 
2989  m_txTrace (p, tcpHeader, this);
2990 
2991  if (m_endPoint != 0)
2992  {
2993  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
2995  }
2996  else
2997  {
2998  m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
3000  }
3001 
3002  NS_LOG_LOGIC ("Schedule persist timeout at time "
3003  << Simulator::Now ().GetSeconds () << " to expire at time "
3004  << (Simulator::Now () + m_persistTimeout).GetSeconds ());
3006 }
3007 
3008 void
3010 {
3011  // If erroneous timeout in closed/timed-wait state, just return
3012  if (m_state == CLOSED || m_state == TIME_WAIT)
3013  {
3014  return;
3015  }
3016  // If all data are received (non-closing socket and nothing to send), just return
3017  if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark)
3018  {
3019  return;
3020  }
3021 
3022  /*
3023  * When a TCP sender detects segment loss using the retransmission timer
3024  * and the given segment has not yet been resent by way of the
3025  * retransmission timer, the value of ssthresh MUST be set to no more
3026  * than the value given in equation (4):
3027  *
3028  * ssthresh = max (FlightSize / 2, 2*SMSS) (4)
3029  *
3030  * where, as discussed above, FlightSize is the amount of outstanding
3031  * data in the network.
3032  *
3033  * On the other hand, when a TCP sender detects segment loss using the
3034  * retransmission timer and the given segment has already been
3035  * retransmitted by way of the retransmission timer at least once, the
3036  * value of ssthresh is held constant.
3037  *
3038  * Conditions to decrement slow - start threshold are as follows:
3039  *
3040  * *) The TCP state should be less than disorder, which is nothing but open.
3041  * If we are entering into the loss state from the open state, we have not yet
3042  * reduced the slow - start threshold for the window of data. (Nat: Recovery?)
3043  * *) If we have entered the loss state with all the data pointed to by high_seq
3044  * acknowledged. Once again it means that in whatever state we are (other than
3045  * open state), all the data from the window that got us into the state, prior to
3046  * retransmission timer expiry, has been acknowledged. (Nat: How this can happen?)
3047  * *) If the above two conditions fail, we still have one more condition that can
3048  * demand reducing the slow - start threshold: If we are already in the loss state
3049  * and have not yet retransmitted anything. The condition may arise in case we
3050  * are not able to retransmit anything because of local congestion.
3051  */
3052 
3053  if (m_tcb->m_congState != TcpSocketState::CA_LOSS)
3054  {
3055  m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS);
3056  m_tcb->m_congState = TcpSocketState::CA_LOSS;
3057  m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, BytesInFlight ());
3058  m_tcb->m_cWnd = m_tcb->m_segmentSize;
3059  }
3060 
3061  m_tcb->m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack
3062  m_dupAckCount = 0;
3063 
3064  NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
3065  m_tcb->m_ssThresh << ", restart from seqnum " << m_tcb->m_nextTxSequence);
3066  DoRetransmit (); // Retransmit the packet
3067 }
3068 
3069 void
3071 {
3072  NS_LOG_FUNCTION (this);
3073  // Retransmit SYN packet
3074  if (m_state == SYN_SENT)
3075  {
3076  if (m_synCount > 0)
3077  {
3079  }
3080  else
3081  {
3083  }
3084  return;
3085  }
3086 
3087  if (m_dataRetrCount == 0)
3088  {
3089  NS_LOG_INFO ("No more data retries available. Dropping connection");
3090  NotifyErrorClose ();
3091  DeallocateEndPoint ();
3092  return;
3093  }
3094  else
3095  {
3096  --m_dataRetrCount;
3097  }
3098 
3099  // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3100  if (m_txBuffer->Size () == 0)
3101  {
3102  if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3103  { // Must have lost FIN, re-send
3105  }
3106  return;
3107  }
3108 
3109  // Retransmit a data packet: Call SendDataPacket
3110  uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_tcb->m_segmentSize, true);
3111  ++m_retransOut;
3112 
3113  // In case of RTO, advance m_tcb->m_nextTxSequence
3114  m_tcb->m_nextTxSequence = std::max (m_tcb->m_nextTxSequence.Get (), m_txBuffer->HeadSequence () + sz);
3115 
3116  NS_LOG_DEBUG ("retxing seq " << m_txBuffer->HeadSequence ());
3117 }
3118 
3119 void
3121 {
3122  m_retxEvent.Cancel ();
3124  m_delAckEvent.Cancel ();
3128 }
3129 
3130 /* Move TCP to Time_Wait state and schedule a transition to Closed state */
3131 void
3133 {
3134  NS_LOG_DEBUG (TcpStateName[m_state] << " -> TIME_WAIT");
3135  m_state = TIME_WAIT;
3136  CancelAllTimers ();
3137  // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
3138  // according to RFC793, p.28
3141 }
3142 
3143 /* Below are the attribute get/set functions */
3144 
3145 void
3147 {
3148  NS_LOG_FUNCTION (this << size);
3149  m_txBuffer->SetMaxBufferSize (size);
3150 }
3151 
3152 uint32_t
3154 {
3155  return m_txBuffer->MaxBufferSize ();
3156 }
3157 
3158 void
3160 {
3161  NS_LOG_FUNCTION (this << size);
3162  uint32_t oldSize = GetRcvBufSize ();
3163 
3164  m_rxBuffer->SetMaxBufferSize (size);
3165 
3166  /* The size has (manually) increased. Actively inform the other end to prevent
3167  * stale zero-window states.
3168  */
3169  if (oldSize < size && m_connected)
3170  {
3172  }
3173 }
3174 
3175 uint32_t
3177 {
3178  return m_rxBuffer->MaxBufferSize ();
3179 }
3180 
3181 void
3183 {
3184  NS_LOG_FUNCTION (this << size);
3185  m_tcb->m_segmentSize = size;
3186 
3187  NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
3188 }
3189 
3190 uint32_t
3192 {
3193  return m_tcb->m_segmentSize;
3194 }
3195 
3196 void
3198 {
3199  NS_LOG_FUNCTION (this << timeout);
3200  m_cnTimeout = timeout;
3201 }
3202 
3203 Time
3205 {
3206  return m_cnTimeout;
3207 }
3208 
3209 void
3211 {
3212  NS_LOG_FUNCTION (this << count);
3213  m_synRetries = count;
3214 }
3215 
3216 uint32_t
3218 {
3219  return m_synRetries;
3220 }
3221 
3222 void
3224 {
3225  NS_LOG_FUNCTION (this << retries);
3226  m_dataRetries = retries;
3227 }
3228 
3229 uint32_t
3231 {
3232  NS_LOG_FUNCTION (this);
3233  return m_dataRetries;
3234 }
3235 
3236 void
3238 {
3239  NS_LOG_FUNCTION (this << timeout);
3241 }
3242 
3243 Time
3245 {
3246  return m_delAckTimeout;
3247 }
3248 
3249 void
3251 {
3252  NS_LOG_FUNCTION (this << count);
3253  m_delAckMaxCount = count;
3254 }
3255 
3256 uint32_t
3258 {
3259  return m_delAckMaxCount;
3260 }
3261 
3262 void
3264 {
3265  NS_LOG_FUNCTION (this << noDelay);
3266  m_noDelay = noDelay;
3267 }
3268 
3269 bool
3271 {
3272  return m_noDelay;
3273 }
3274 
3275 void
3277 {
3278  NS_LOG_FUNCTION (this << timeout);
3280 }
3281 
3282 Time
3284 {
3285  return m_persistTimeout;
3286 }
3287 
3288 bool
3290 {
3291  // Broadcast is not implemented. Return true only if allowBroadcast==false
3292  return (!allowBroadcast);
3293 }
3294 
3295 bool
3297 {
3298  return false;
3299 }
3300 
3301 void
3303 {
3304  NS_LOG_FUNCTION (this << header);
3305 
3306  if (m_timestampEnabled)
3307  {
3308  AddOptionTimestamp (header);
3309  }
3310 }
3311 
3312 void
3314 {
3315  NS_LOG_FUNCTION (this << option);
3316 
3317  Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
3318 
3319  // In naming, we do the contrary of RFC 1323. The received scaling factor
3320  // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
3321  m_sndWindShift = ws->GetScale ();
3322 
3323  if (m_sndWindShift > 14)
3324  {
3325  NS_LOG_WARN ("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
3326  m_sndWindShift = 14;
3327  }
3328 
3329  NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
3330  static_cast<int> (m_sndWindShift));
3331 }
3332 
3333 uint8_t
3335 {
3336  NS_LOG_FUNCTION (this);
3337  uint32_t maxSpace = m_rxBuffer->MaxBufferSize ();
3338  uint8_t scale = 0;
3339 
3340  while (maxSpace > m_maxWinSize)
3341  {
3342  maxSpace = maxSpace >> 1;
3343  ++scale;
3344  }
3345 
3346  if (scale > 14)
3347  {
3348  NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
3349  scale = 14;
3350  }
3351 
3352  NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
3353  static_cast<int> (scale) << " for buffer size " << m_rxBuffer->MaxBufferSize ());
3354  return scale;
3355 }
3356 
3357 void
3359 {
3360  NS_LOG_FUNCTION (this << header);
3361  NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
3362 
3363  Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
3364 
3365  // In naming, we do the contrary of RFC 1323. The sended scaling factor
3366  // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
3367 
3369  option->SetScale (m_rcvWindShift);
3370 
3371  header.AppendOption (option);
3372 
3373  NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
3374  static_cast<int> (m_rcvWindShift));
3375 }
3376 
3377 void
3379  const SequenceNumber32 &seq)
3380 {
3381  NS_LOG_FUNCTION (this << option);
3382 
3383  Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
3384 
3385  if (seq == m_rxBuffer->NextRxSequence () && seq <= m_highTxAck)
3386  {
3387  m_timestampToEcho = ts->GetTimestamp ();
3388  }
3389 
3390  NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
3391  m_timestampToEcho << " and Echo=" << ts->GetEcho ());
3392 }
3393 
3394 void
3396 {
3397  NS_LOG_FUNCTION (this << header);
3398 
3399  Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
3400 
3401  option->SetTimestamp (TcpOptionTS::NowToTsValue ());
3402  option->SetEcho (m_timestampToEcho);
3403 
3404  header.AppendOption (option);
3405  NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
3406  option->GetTimestamp () << " echo=" << m_timestampToEcho);
3407 }
3408 
3410 {
3411  NS_LOG_FUNCTION (this << header);
3412  // If the connection is not established, the window size is always
3413  // updated
3414  uint32_t receivedWindow = header.GetWindowSize ();
3415  receivedWindow <<= m_sndWindShift;
3416  NS_LOG_INFO ("Received (scaled) window is " << receivedWindow << " bytes");
3417  if (m_state < ESTABLISHED)
3418  {
3419  m_rWnd = receivedWindow;
3420  NS_LOG_LOGIC ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
3421  return;
3422  }
3423 
3424  // Test for conditions that allow updating of the window
3425  // 1) segment contains new data (advancing the right edge of the receive
3426  // buffer),
3427  // 2) segment does not contain new data but the segment acks new data
3428  // (highest sequence number acked advances), or
3429  // 3) the advertised window is larger than the current send window
3430  bool update = false;
3431  if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
3432  {
3433  // right edge of the send window is increased (window update)
3434  update = true;
3435  }
3436  if (header.GetAckNumber () > m_highRxAckMark)
3437  {
3438  m_highRxAckMark = header.GetAckNumber ();
3439  update = true;
3440  }
3441  if (header.GetSequenceNumber () > m_highRxMark)
3442  {
3443  m_highRxMark = header.GetSequenceNumber ();
3444  update = true;
3445  }
3446  if (update == true)
3447  {
3448  m_rWnd = receivedWindow;
3449  NS_LOG_LOGIC ("updating rWnd to " << m_rWnd);
3450  }
3451 }
3452 
3453 void
3455 {
3456  NS_LOG_FUNCTION (this << minRto);
3457  m_minRto = minRto;
3458 }
3459 
3460 Time
3462 {
3463  return m_minRto;
3464 }
3465 
3466 void
3468 {
3469  NS_LOG_FUNCTION (this << clockGranularity);
3470  m_clockGranularity = clockGranularity;
3471 }
3472 
3473 Time
3475 {
3476  return m_clockGranularity;
3477 }
3478 
3481 {
3482  return m_txBuffer;
3483 }
3484 
3487 {
3488  return m_rxBuffer;
3489 }
3490 
3491 void
3492 TcpSocketBase::UpdateCwnd (uint32_t oldValue, uint32_t newValue)
3493 {
3494  m_cWndTrace (oldValue, newValue);
3495 }
3496 
3497 void
3498 TcpSocketBase::UpdateSsThresh (uint32_t oldValue, uint32_t newValue)
3499 {
3500  m_ssThTrace (oldValue, newValue);
3501 }
3502 
3503 void
3506 {
3507  m_congStateTrace (oldValue, newValue);
3508 }
3509 
3510 void
3512  SequenceNumber32 newValue)
3513 
3514 {
3515  m_nextTxSequenceTrace (oldValue, newValue);
3516 }
3517 
3518 void
3520 {
3521  m_highTxMarkTrace (oldValue, newValue);
3522 }
3523 
3524 void
3526 {
3527  NS_LOG_FUNCTION (this << algo);
3528  m_congestionControl = algo;
3529 }
3530 
3533 {
3534  return CopyObject<TcpSocketBase> (this);
3535 }
3536 
3537 uint32_t
3538 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b)
3539 {
3540  if (a > b)
3541  {
3542  return a-b;
3543  }
3544 
3545  return 0;
3546 }
3547 
3548 //RttHistory methods
3550  : seq (s),
3551  count (c),
3552  time (t),
3553  retx (false)
3554 {
3555 }
3556 
3558  : seq (h.seq),
3559  count (h.count),
3560  time (h.time),
3561  retx (h.retx)
3562 {
3563 }
3564 
3565 } // 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:233
Ipv6Address GetLocalAddress()
Get the local address.
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:268
TracedValue< uint32_t > m_bytesInFlight
Bytes in flight.
Custom version of log2() 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.
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
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:34
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:1160
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:44
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 ~TcpSocketBase(void)
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:462
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.
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:81
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.
bool IsZero(void) const
Definition: nstime.h:274
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:824
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.
void FastRetransmit()
Enter the FastRetransmit, and retransmit the head.
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:903
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:792
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.
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:244
#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
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
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:1112
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.
virtual void SetSynRetries(uint32_t count)
Set the number of connection retries before giving up.
Ptr< TcpTxBuffer > GetTxBuffer(void) const
Get a pointer to the Tx buffer.
TracedValue< TcpStates_t > m_state
TCP state.
uint32_t m_delAckMaxCount
Number of packet to fire an ACK before delay timeout.
uint8_t CalculateWScale() const
Calculate window scale value based on receive buffer space.
void DupAck()
Dupack management.
uint16_t port
Definition: dsdv-manet.cc:44
a polymophic address class
Definition: address.h:90
void SetMinRto(Time minRto)
Sets the Minimum RTO.
void SetDestroyCallback(Callback< void > callback)
Set the default destroy callback.
uint16_t GetPeerPort()
Get the peer port.
AttributeValue implementation for Callback.
Definition: callback.h:1880
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.
virtual void Retransmit(void)
Halving cwnd and call DoRetransmit()
Packet header for IPv4.
Definition: ipv4-header.h:33
void SetLocalAddress(Ipv6Address addr)
Set the local address.
bool AppendOption(Ptr< TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:463
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:1238
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:957
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:838
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:1304
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
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:497
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.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
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
TracedValue< uint32_t > m_ssThresh
Slow start threshold.
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.
virtual 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 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.
virtual uint32_t BytesInFlight(void)
Return total bytes in flight.
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1351
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:952
static EventId ScheduleNow(MEM mem_ptr, OBJ obj)
Schedule an event to expire Now.
Definition: simulator.h:1401
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:958
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:224
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)
Call Retransmit() upon RTO event.
Ptr< const AttributeChecker > MakeCallbackChecker(void)
Definition: callback.cc:75
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.
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.
#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.
Ptr< TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:489
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:1073
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:228
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:831
CWND was reduced due to RTO timeout or SACK reneging.
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:236
RttHistory_t m_history
List of sent packet.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:895
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
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 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.
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:220
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.
uint32_t m_retransOut
Number of retransmission in this window.
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
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:505
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:1258
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:904
Time m_clockGranularity
Clock Granularity used in RTO calcs.
bool SendPendingData(bool withAck=false)
Send as much pending data as possible according to the Tx window.
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.
virtual uint32_t GetRxAvailable(void) const
Return number of bytes which can be returned from one or multiple calls to Recv.