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