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