A Discrete-Event Network Simulator
API
tcp-socket-base.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2007 Georgia Tech Research Corporation
4 * Copyright (c) 2010 Adrian Sai-wah Tam
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
20 */
21
22#define NS_LOG_APPEND_CONTEXT \
23 if (m_node) { std::clog << " [node " << m_node->GetId () << "] "; }
24
25#include "ns3/abort.h"
26#include "ns3/node.h"
27#include "ns3/inet-socket-address.h"
28#include "ns3/inet6-socket-address.h"
29#include "ns3/log.h"
30#include "ns3/ipv4.h"
31#include "ns3/ipv6.h"
32#include "ns3/ipv4-interface-address.h"
33#include "ns3/ipv4-route.h"
34#include "ns3/ipv6-route.h"
35#include "ns3/ipv4-routing-protocol.h"
36#include "ns3/ipv6-routing-protocol.h"
37#include "ns3/simulation-singleton.h"
38#include "ns3/simulator.h"
39#include "ns3/packet.h"
40#include "ns3/uinteger.h"
41#include "ns3/double.h"
42#include "ns3/pointer.h"
43#include "ns3/trace-source-accessor.h"
44#include "ns3/data-rate.h"
45#include "ns3/object.h"
46#include "tcp-socket-base.h"
47#include "tcp-l4-protocol.h"
48#include "ipv4-end-point.h"
49#include "ipv6-end-point.h"
50#include "ipv6-l3-protocol.h"
51#include "tcp-tx-buffer.h"
52#include "tcp-rx-buffer.h"
53#include "rtt-estimator.h"
54#include "tcp-header.h"
55#include "tcp-option-winscale.h"
56#include "tcp-option-ts.h"
58#include "tcp-option-sack.h"
59#include "tcp-congestion-ops.h"
60#include "tcp-recovery-ops.h"
61#include "ns3/tcp-rate-ops.h"
62
63#include <math.h>
64#include <algorithm>
65
66namespace ns3 {
67
68NS_LOG_COMPONENT_DEFINE ("TcpSocketBase");
69
70NS_OBJECT_ENSURE_REGISTERED (TcpSocketBase);
71
72TypeId
74{
75 static TypeId tid = TypeId ("ns3::TcpSocketBase")
77 .SetGroupName ("Internet")
78 .AddConstructor<TcpSocketBase> ()
79// .AddAttribute ("TcpState", "State in TCP state machine",
80// TypeId::ATTR_GET,
81// EnumValue (CLOSED),
82// MakeEnumAccessor (&TcpSocketBase::m_state),
83// MakeEnumChecker (CLOSED, "Closed"))
84 .AddAttribute ("MaxSegLifetime",
85 "Maximum segment lifetime in seconds, use for TIME_WAIT state transition to CLOSED state",
86 DoubleValue (120), /* RFC793 says MSL=2 minutes*/
88 MakeDoubleChecker<double> (0))
89 .AddAttribute ("MaxWindowSize", "Max size of advertised window",
90 UintegerValue (65535),
92 MakeUintegerChecker<uint16_t> ())
93 .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
97 .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
101 .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option",
102 BooleanValue (true),
105 .AddAttribute ("Sack", "Enable or disable Sack option",
106 BooleanValue (true),
109 .AddAttribute ("Timestamp", "Enable or disable Timestamp option",
110 BooleanValue (true),
113 .AddAttribute ("MinRto",
114 "Minimum retransmit timeout value",
115 TimeValue (Seconds (1.0)), // RFC 6298 says min RTO=1 sec, but Linux uses 200ms.
116 // See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
120 .AddAttribute ("ClockGranularity",
121 "Clock Granularity used in RTO calculations",
122 TimeValue (MilliSeconds (1)), // RFC6298 suggest to use fine clock granularity
126 .AddAttribute ("TxBuffer",
127 "TCP Tx buffer",
128 PointerValue (),
130 MakePointerChecker<TcpTxBuffer> ())
131 .AddAttribute ("RxBuffer",
132 "TCP Rx buffer",
133 PointerValue (),
135 MakePointerChecker<TcpRxBuffer> ())
136 .AddAttribute ("CongestionOps",
137 "Pointer to TcpCongestionOps object",
138 PointerValue (),
140 MakePointerChecker<TcpCongestionOps> ())
141 .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit",
142 UintegerValue (3),
145 MakeUintegerChecker<uint32_t> ())
146 .AddAttribute ("LimitedTransmit", "Enable limited transmit",
147 BooleanValue (true),
150 .AddAttribute ("UseEcn", "Parameter to set ECN functionality",
154 TcpSocketState::On, "On",
155 TcpSocketState::AcceptOnly, "AcceptOnly"))
156 .AddTraceSource ("RTO",
157 "Retransmission timeout",
159 "ns3::TracedValueCallback::Time")
160 .AddTraceSource ("RTT",
161 "Last RTT sample",
163 "ns3::TracedValueCallback::Time")
164 .AddTraceSource ("NextTxSequence",
165 "Next sequence number to send (SND.NXT)",
167 "ns3::SequenceNumber32TracedValueCallback")
168 .AddTraceSource ("HighestSequence",
169 "Highest sequence number ever sent in socket's life time",
171 "ns3::TracedValueCallback::SequenceNumber32")
172 .AddTraceSource ("State",
173 "TCP state",
175 "ns3::TcpStatesTracedValueCallback")
176 .AddTraceSource ("CongState",
177 "TCP Congestion machine state",
179 "ns3::TcpSocketState::TcpCongStatesTracedValueCallback")
180 .AddTraceSource ("EcnState",
181 "Trace ECN state change of socket",
183 "ns3::TcpSocketState::EcnStatesTracedValueCallback")
184 .AddTraceSource ("AdvWND",
185 "Advertised Window Size",
187 "ns3::TracedValueCallback::Uint32")
188 .AddTraceSource ("RWND",
189 "Remote side's flow control window",
191 "ns3::TracedValueCallback::Uint32")
192 .AddTraceSource ("BytesInFlight",
193 "Socket estimation of bytes in flight",
195 "ns3::TracedValueCallback::Uint32")
196 .AddTraceSource ("HighestRxSequence",
197 "Highest sequence number received from peer",
199 "ns3::TracedValueCallback::SequenceNumber32")
200 .AddTraceSource ("HighestRxAck",
201 "Highest ack received from peer",
203 "ns3::TracedValueCallback::SequenceNumber32")
204 .AddTraceSource ("PacingRate",
205 "The current TCP pacing rate",
207 "ns3::TracedValueCallback::DataRate")
208 .AddTraceSource ("CongestionWindow",
209 "The TCP connection's congestion window",
211 "ns3::TracedValueCallback::Uint32")
212 .AddTraceSource ("CongestionWindowInflated",
213 "The TCP connection's congestion window inflates as in older RFC",
215 "ns3::TracedValueCallback::Uint32")
216 .AddTraceSource ("SlowStartThreshold",
217 "TCP slow start threshold (bytes)",
219 "ns3::TracedValueCallback::Uint32")
220 .AddTraceSource ("Tx",
221 "Send tcp packet to IP protocol",
223 "ns3::TcpSocketBase::TcpTxRxTracedCallback")
224 .AddTraceSource ("Rx",
225 "Receive tcp packet from IP protocol",
227 "ns3::TcpSocketBase::TcpTxRxTracedCallback")
228 .AddTraceSource ("EcnEchoSeq",
229 "Sequence of last received ECN Echo",
231 "ns3::SequenceNumber32TracedValueCallback")
232 .AddTraceSource ("EcnCeSeq",
233 "Sequence of last received CE",
235 "ns3::SequenceNumber32TracedValueCallback")
236 .AddTraceSource ("EcnCwrSeq",
237 "Sequence of last received CWR",
239 "ns3::SequenceNumber32TracedValueCallback")
240 ;
241 return tid;
242}
243
244TypeId
246{
247 return TcpSocketBase::GetTypeId ();
248}
249
251 : TcpSocket ()
252{
253 NS_LOG_FUNCTION (this);
254 m_txBuffer = CreateObject<TcpTxBuffer> ();
255 m_txBuffer->SetRWndCallback (MakeCallback (&TcpSocketBase::GetRWnd, this));
256 m_tcb = CreateObject<TcpSocketState> ();
257 m_rateOps = CreateObject <TcpRateLinux> ();
258
259 m_tcb->m_rxBuffer = CreateObject<TcpRxBuffer> ();
260
263
265
266 bool ok;
267
268 ok = m_tcb->TraceConnectWithoutContext ("PacingRate",
270 NS_ASSERT (ok == true);
271
272 ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
274 NS_ASSERT (ok == true);
275
276 ok = m_tcb->TraceConnectWithoutContext ("CongestionWindowInflated",
278 NS_ASSERT (ok == true);
279
280 ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
282 NS_ASSERT (ok == true);
283
284 ok = m_tcb->TraceConnectWithoutContext ("CongState",
286 NS_ASSERT (ok == true);
287
288 ok = m_tcb->TraceConnectWithoutContext ("EcnState",
290 NS_ASSERT (ok == true);
291
292 ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
294 NS_ASSERT (ok == true);
295
296 ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
298 NS_ASSERT (ok == true);
299
300 ok = m_tcb->TraceConnectWithoutContext ("BytesInFlight",
302 NS_ASSERT (ok == true);
303
306 NS_ASSERT (ok == true);
307}
308
310 : TcpSocket (sock),
311 //copy object::m_tid and socket::callbacks
312 m_dupAckCount (sock.m_dupAckCount),
313 m_delAckCount (0),
314 m_delAckMaxCount (sock.m_delAckMaxCount),
315 m_noDelay (sock.m_noDelay),
316 m_synCount (sock.m_synCount),
317 m_synRetries (sock.m_synRetries),
318 m_dataRetrCount (sock.m_dataRetrCount),
319 m_dataRetries (sock.m_dataRetries),
320 m_rto (sock.m_rto),
321 m_minRto (sock.m_minRto),
322 m_clockGranularity (sock.m_clockGranularity),
323 m_delAckTimeout (sock.m_delAckTimeout),
324 m_persistTimeout (sock.m_persistTimeout),
325 m_cnTimeout (sock.m_cnTimeout),
326 m_endPoint (nullptr),
327 m_endPoint6 (nullptr),
328 m_node (sock.m_node),
329 m_tcp (sock.m_tcp),
330 m_state (sock.m_state),
331 m_errno (sock.m_errno),
332 m_closeNotified (sock.m_closeNotified),
333 m_closeOnEmpty (sock.m_closeOnEmpty),
334 m_shutdownSend (sock.m_shutdownSend),
335 m_shutdownRecv (sock.m_shutdownRecv),
336 m_connected (sock.m_connected),
337 m_msl (sock.m_msl),
338 m_maxWinSize (sock.m_maxWinSize),
339 m_bytesAckedNotProcessed (sock.m_bytesAckedNotProcessed),
340 m_rWnd (sock.m_rWnd),
341 m_highRxMark (sock.m_highRxMark),
342 m_highRxAckMark (sock.m_highRxAckMark),
343 m_sackEnabled (sock.m_sackEnabled),
344 m_winScalingEnabled (sock.m_winScalingEnabled),
345 m_rcvWindShift (sock.m_rcvWindShift),
346 m_sndWindShift (sock.m_sndWindShift),
347 m_timestampEnabled (sock.m_timestampEnabled),
348 m_timestampToEcho (sock.m_timestampToEcho),
349 m_recover (sock.m_recover),
350 m_recoverActive (sock.m_recoverActive),
351 m_retxThresh (sock.m_retxThresh),
352 m_limitedTx (sock.m_limitedTx),
353 m_isFirstPartialAck (sock.m_isFirstPartialAck),
354 m_txTrace (sock.m_txTrace),
355 m_rxTrace (sock.m_rxTrace),
356 m_pacingTimer (Timer::CANCEL_ON_DESTROY),
357 m_ecnEchoSeq (sock.m_ecnEchoSeq),
358 m_ecnCESeq (sock.m_ecnCESeq),
359 m_ecnCWRSeq (sock.m_ecnCWRSeq)
360{
361 NS_LOG_FUNCTION (this);
362 NS_LOG_LOGIC ("Invoked the copy constructor");
363 // Copy the rtt estimator if it is set
364 if (sock.m_rtt)
365 {
366 m_rtt = sock.m_rtt->Copy ();
367 }
368 // Reset all callbacks to null
369 Callback<void, Ptr< Socket > > vPS = MakeNullCallback<void, Ptr<Socket> > ();
370 Callback<void, Ptr<Socket>, const Address &> vPSA = MakeNullCallback<void, Ptr<Socket>, const Address &> ();
371 Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t> ();
372 SetConnectCallback (vPS, vPS);
373 SetDataSentCallback (vPSUI);
374 SetSendCallback (vPSUI);
375 SetRecvCallback (vPS);
377 m_txBuffer->SetRWndCallback (MakeCallback (&TcpSocketBase::GetRWnd, this));
378 m_tcb = CopyObject (sock.m_tcb);
380
383
384 if (sock.m_congestionControl)
385 {
388 }
389
390 if (sock.m_recoveryOps)
391 {
392 m_recoveryOps = sock.m_recoveryOps->Fork ();
393 }
394
395 m_rateOps = CreateObject <TcpRateLinux> ();
397 {
399 }
400
401 bool ok;
402
403 ok = m_tcb->TraceConnectWithoutContext ("PacingRate",
405
406 ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
408 NS_ASSERT (ok == true);
409
410 ok = m_tcb->TraceConnectWithoutContext ("CongestionWindowInflated",
412 NS_ASSERT (ok == true);
413
414 ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
416 NS_ASSERT (ok == true);
417
418 ok = m_tcb->TraceConnectWithoutContext ("CongState",
420 NS_ASSERT (ok == true);
421
422 ok = m_tcb->TraceConnectWithoutContext ("EcnState",
424 NS_ASSERT (ok == true);
425
426 ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence",
428 NS_ASSERT (ok == true);
429
430 ok = m_tcb->TraceConnectWithoutContext ("HighestSequence",
432 NS_ASSERT (ok == true);
433
434 ok = m_tcb->TraceConnectWithoutContext ("BytesInFlight",
436 NS_ASSERT (ok == true);
437
440 NS_ASSERT (ok == true);
441}
442
444{
445 NS_LOG_FUNCTION (this);
446 m_node = nullptr;
447 if (m_endPoint != nullptr)
448 {
450 /*
451 * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
452 * DestroyCallback is set to TcpSocketBase::Destroy. If we called
453 * m_tcp->DeAllocate, it will destroy its Ipv4EndpointDemux::DeAllocate,
454 * which in turn destroys my m_endPoint, and in turn invokes
455 * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
456 */
457 NS_ASSERT (m_endPoint != nullptr);
458 m_tcp->DeAllocate (m_endPoint);
459 NS_ASSERT (m_endPoint == nullptr);
460 }
461 if (m_endPoint6 != nullptr)
462 {
464 NS_ASSERT (m_endPoint6 != nullptr);
465 m_tcp->DeAllocate (m_endPoint6);
466 NS_ASSERT (m_endPoint6 == nullptr);
467 }
468 m_tcp = 0;
470}
471
472/* Associate a node with this TCP socket */
473void
475{
476 m_node = node;
477}
478
479/* Associate the L4 protocol (e.g. mux/demux) with this socket */
480void
482{
483 m_tcp = tcp;
484}
485
486/* Set an RTT estimator with this socket */
487void
489{
490 m_rtt = rtt;
491}
492
493/* Inherit from Socket class: Returns error code */
496{
497 return m_errno;
498}
499
500/* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
503{
504 return NS3_SOCK_STREAM;
505}
506
507/* Inherit from Socket class: Returns associated node */
510{
511 return m_node;
512}
513
514/* Inherit from Socket class: Bind socket to an end-point in TcpL4Protocol */
515int
517{
518 NS_LOG_FUNCTION (this);
519 m_endPoint = m_tcp->Allocate ();
520 if (0 == m_endPoint)
521 {
522 m_errno = ERROR_ADDRNOTAVAIL;
523 return -1;
524 }
525
526 m_tcp->AddSocket (this);
527
528 return SetupCallback ();
529}
530
531int
533{
534 NS_LOG_FUNCTION (this);
535 m_endPoint6 = m_tcp->Allocate6 ();
536 if (0 == m_endPoint6)
537 {
538 m_errno = ERROR_ADDRNOTAVAIL;
539 return -1;
540 }
541
542 m_tcp->AddSocket (this);
543
544 return SetupCallback ();
545}
546
547/* Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
548int
550{
551 NS_LOG_FUNCTION (this << address);
553 {
555 Ipv4Address ipv4 = transport.GetIpv4 ();
556 uint16_t port = transport.GetPort ();
557 SetIpTos (transport.GetTos ());
558 if (ipv4 == Ipv4Address::GetAny () && port == 0)
559 {
560 m_endPoint = m_tcp->Allocate ();
561 }
562 else if (ipv4 == Ipv4Address::GetAny () && port != 0)
563 {
564 m_endPoint = m_tcp->Allocate (GetBoundNetDevice (), port);
565 }
566 else if (ipv4 != Ipv4Address::GetAny () && port == 0)
567 {
568 m_endPoint = m_tcp->Allocate (ipv4);
569 }
570 else if (ipv4 != Ipv4Address::GetAny () && port != 0)
571 {
572 m_endPoint = m_tcp->Allocate (GetBoundNetDevice (), ipv4, port);
573 }
574 if (0 == m_endPoint)
575 {
577 return -1;
578 }
579 }
581 {
583 Ipv6Address ipv6 = transport.GetIpv6 ();
584 uint16_t port = transport.GetPort ();
585 if (ipv6 == Ipv6Address::GetAny () && port == 0)
586 {
587 m_endPoint6 = m_tcp->Allocate6 ();
588 }
589 else if (ipv6 == Ipv6Address::GetAny () && port != 0)
590 {
591 m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (), port);
592 }
593 else if (ipv6 != Ipv6Address::GetAny () && port == 0)
594 {
595 m_endPoint6 = m_tcp->Allocate6 (ipv6);
596 }
597 else if (ipv6 != Ipv6Address::GetAny () && port != 0)
598 {
599 m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (), ipv6, port);
600 }
601 if (0 == m_endPoint6)
602 {
604 return -1;
605 }
606 }
607 else
608 {
609 m_errno = ERROR_INVAL;
610 return -1;
611 }
612
613 m_tcp->AddSocket (this);
614
615 NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
616
617 return SetupCallback ();
618}
619
620void
622{
624 "TcpSocketBase::SetSSThresh() cannot change initial ssThresh after connection started.");
625
626 m_tcb->m_initialSsThresh = threshold;
627}
628
631{
632 return m_tcb->m_initialSsThresh;
633}
634
635void
637{
639 "TcpSocketBase::SetInitialCwnd() cannot change initial cwnd after connection started.");
640
641 m_tcb->m_initialCWnd = cwnd;
642}
643
646{
647 return m_tcb->m_initialCWnd;
648}
649
650/* Inherit from Socket class: Initiate connection to a remote address:port */
651int
653{
654 NS_LOG_FUNCTION (this << address);
655
656 // If haven't do so, Bind() this socket first
658 {
659 if (m_endPoint == nullptr)
660 {
661 if (Bind () == -1)
662 {
663 NS_ASSERT (m_endPoint == nullptr);
664 return -1; // Bind() failed
665 }
666 NS_ASSERT (m_endPoint != nullptr);
667 }
669 m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
670 SetIpTos (transport.GetTos ());
671 m_endPoint6 = nullptr;
672
673 // Get the appropriate local address and port number from the routing protocol and set up endpoint
674 if (SetupEndpoint () != 0)
675 {
676 NS_LOG_ERROR ("Route to destination does not exist ?!");
677 return -1;
678 }
679 }
681 {
682 // If we are operating on a v4-mapped address, translate the address to
683 // a v4 address and re-call this function
685 Ipv6Address v6Addr = transport.GetIpv6 ();
686 if (v6Addr.IsIpv4MappedAddress () == true)
687 {
688 Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
689 return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
690 }
691
692 if (m_endPoint6 == nullptr)
693 {
694 if (Bind6 () == -1)
695 {
696 NS_ASSERT (m_endPoint6 == nullptr);
697 return -1; // Bind() failed
698 }
699 NS_ASSERT (m_endPoint6 != nullptr);
700 }
701 m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
702 m_endPoint = nullptr;
703
704 // Get the appropriate local address and port number from the routing protocol and set up endpoint
705 if (SetupEndpoint6 () != 0)
706 {
707 NS_LOG_ERROR ("Route to destination does not exist ?!");
708 return -1;
709 }
710 }
711 else
712 {
713 m_errno = ERROR_INVAL;
714 return -1;
715 }
716
717 // Re-initialize parameters in case this socket is being reused after CLOSE
718 m_rtt->Reset ();
721
722 // DoConnect() will do state-checking and send a SYN packet
723 return DoConnect ();
724}
725
726/* Inherit from Socket class: Listen on the endpoint for an incoming connection */
727int
729{
730 NS_LOG_FUNCTION (this);
731
732 // Linux quits EINVAL if we're not in CLOSED state, so match what they do
733 if (m_state != CLOSED)
734 {
735 m_errno = ERROR_INVAL;
736 return -1;
737 }
738 // In other cases, set the state to LISTEN and done
739 NS_LOG_DEBUG ("CLOSED -> LISTEN");
740 m_state = LISTEN;
741 return 0;
742}
743
744/* Inherit from Socket class: Kill this socket and signal the peer (if any) */
745int
747{
748 NS_LOG_FUNCTION (this);
752 if (m_tcb->m_rxBuffer->Size () != 0)
753 {
754 NS_LOG_WARN ("Socket " << this << " << unread rx data during close. Sending reset." <<
755 "This is probably due to a bad sink application; check its code");
756 SendRST ();
757 return 0;
758 }
759
760 if (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0)
761 { // App close with pending data must wait until all data transmitted
762 if (m_closeOnEmpty == false)
763 {
764 m_closeOnEmpty = true;
765 NS_LOG_INFO ("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
766 }
767 return 0;
768 }
769 return DoClose ();
770}
771
772/* Inherit from Socket class: Signal a termination of send */
773int
775{
776 NS_LOG_FUNCTION (this);
777
778 //this prevents data from being added to the buffer
779 m_shutdownSend = true;
780 m_closeOnEmpty = true;
781 //if buffer is already empty, send a fin now
782 //otherwise fin will go when buffer empties.
783 if (m_txBuffer->Size () == 0)
784 {
786 {
787 NS_LOG_INFO ("Empty tx buffer, send fin");
789
790 if (m_state == ESTABLISHED)
791 { // On active close: I am the first one to send FIN
792 NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
794 }
795 else
796 { // On passive close: Peer sent me FIN already
797 NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
799 }
800 }
801 }
802
803 return 0;
804}
805
806/* Inherit from Socket class: Signal a termination of receive */
807int
809{
810 NS_LOG_FUNCTION (this);
811 m_shutdownRecv = true;
812 return 0;
813}
814
815/* Inherit from Socket class: Send a packet. Parameter flags is not used.
816 Packet has no TCP header. Invoked by upper-layer application */
817int
819{
820 NS_LOG_FUNCTION (this << p);
821 NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Send()");
823 {
824 // Store the packet into Tx buffer
825 if (!m_txBuffer->Add (p))
826 { // TxBuffer overflow, send failed
827 m_errno = ERROR_MSGSIZE;
828 return -1;
829 }
830 if (m_shutdownSend)
831 {
832 m_errno = ERROR_SHUTDOWN;
833 return -1;
834 }
835
837 m_txBuffer->TailSequence (), m_tcb->m_nextTxSequence,
838 m_txBuffer->GetLost (), m_txBuffer->GetRetransmitsCount ());
839
840 // Submit the data to lower layers
841 NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpStateName[m_state]);
842 if ((m_state == ESTABLISHED || m_state == CLOSE_WAIT) && AvailableWindow () > 0)
843 { // Try to send the data out: Add a little step to allow the application
844 // to fill the buffer
846 {
849 this, m_connected);
850 }
851 }
852 return p->GetSize ();
853 }
854 else
855 { // Connection not established yet
856 m_errno = ERROR_NOTCONN;
857 return -1; // Send failure
858 }
859}
860
861/* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
862int
863TcpSocketBase::SendTo (Ptr<Packet> p, uint32_t flags, [[maybe_unused]] const Address &address)
864{
865 return Send (p, flags); // SendTo() and Send() are the same
866}
867
868/* Inherit from Socket class: Return data to upper-layer application. Parameter flags
869 is not used. Data is returned as a packet of size no larger than maxSize */
872{
873 NS_LOG_FUNCTION (this);
874 NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()");
875 if (m_tcb->m_rxBuffer->Size () == 0 && m_state == CLOSE_WAIT)
876 {
877 return Create<Packet> (); // Send EOF on connection close
878 }
879 Ptr<Packet> outPacket = m_tcb->m_rxBuffer->Extract (maxSize);
880 return outPacket;
881}
882
883/* Inherit from Socket class: Recv and return the remote's address */
885TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
886{
887 NS_LOG_FUNCTION (this << maxSize << flags);
888 Ptr<Packet> packet = Recv (maxSize, flags);
889 // Null packet means no data to read, and an empty packet indicates EOF
890 if (packet && packet->GetSize () != 0)
891 {
892 if (m_endPoint != nullptr)
893 {
895 }
896 else if (m_endPoint6 != nullptr)
897 {
899 }
900 else
901 {
902 fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
903 }
904 }
905 return packet;
906}
907
908/* Inherit from Socket class: Get the max number of bytes an app can send */
911{
912 NS_LOG_FUNCTION (this);
913 return m_txBuffer->Available ();
914}
915
916/* Inherit from Socket class: Get the max number of bytes an app can read */
919{
920 NS_LOG_FUNCTION (this);
921 return m_tcb->m_rxBuffer->Available ();
922}
923
924/* Inherit from Socket class: Return local address:port */
925int
927{
928 NS_LOG_FUNCTION (this);
929 if (m_endPoint != nullptr)
930 {
932 }
933 else if (m_endPoint6 != nullptr)
934 {
936 }
937 else
938 { // It is possible to call this method on a socket without a name
939 // in which case, behavior is unspecified
940 // Should this return an InetSocketAddress or an Inet6SocketAddress?
942 }
943 return 0;
944}
945
946int
948{
949 NS_LOG_FUNCTION (this << address);
950
951 if (!m_endPoint && !m_endPoint6)
952 {
953 m_errno = ERROR_NOTCONN;
954 return -1;
955 }
956
957 if (m_endPoint)
958 {
961 }
962 else if (m_endPoint6)
963 {
966 }
967 else
968 {
969 NS_ASSERT (false);
970 }
971
972 return 0;
973}
974
975/* Inherit from Socket class: Bind this socket to the specified NetDevice */
976void
978{
979 NS_LOG_FUNCTION (netdevice);
980 Socket::BindToNetDevice (netdevice); // Includes sanity check
981 if (m_endPoint != nullptr)
982 {
983 m_endPoint->BindToNetDevice (netdevice);
984 }
985
986 if (m_endPoint6 != nullptr)
987 {
988 m_endPoint6->BindToNetDevice (netdevice);
989 }
990}
991
992/* Clean up after Bind. Set up callback functions in the end-point. */
993int
995{
996 NS_LOG_FUNCTION (this);
997
998 if (m_endPoint == nullptr && m_endPoint6 == nullptr)
999 {
1000 return -1;
1001 }
1002 if (m_endPoint != nullptr)
1003 {
1007 }
1008 if (m_endPoint6 != nullptr)
1009 {
1013 }
1014
1015 return 0;
1016}
1017
1018/* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
1019int
1021{
1022 NS_LOG_FUNCTION (this);
1023
1024 // A new connection is allowed only if this socket does not have a connection
1026 { // send a SYN packet and change state into SYN_SENT
1027 // send a SYN packet with ECE and CWR flags set if sender is ECN capable
1029 {
1031 }
1032 else
1033 {
1035 }
1036 NS_LOG_DEBUG (TcpStateName[m_state] << " -> SYN_SENT");
1037 m_state = SYN_SENT;
1038 m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; // because sender is not yet aware about receiver's ECN capability
1039 }
1040 else if (m_state != TIME_WAIT)
1041 { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
1042 // exists. We send RST, tear down everything, and close this socket.
1043 SendRST ();
1044 CloseAndNotify ();
1045 }
1046 return 0;
1047}
1048
1049/* Do the action to close the socket. Usually send a packet with appropriate
1050 flags depended on the current m_state. */
1051int
1053{
1054 NS_LOG_FUNCTION (this);
1055 switch (m_state)
1056 {
1057 case SYN_RCVD:
1058 case ESTABLISHED:
1059 // send FIN to close the peer
1061 NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
1063 break;
1064 case CLOSE_WAIT:
1065 // send FIN+ACK to close the peer
1067 NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
1068 m_state = LAST_ACK;
1069 break;
1070 case SYN_SENT:
1071 case CLOSING:
1072 // Send RST if application closes in SYN_SENT and CLOSING
1073 SendRST ();
1074 CloseAndNotify ();
1075 break;
1076 case LISTEN:
1077 // In this state, move to CLOSED and tear down the end point
1078 CloseAndNotify ();
1079 break;
1080 case LAST_ACK:
1081 case CLOSED:
1082 case FIN_WAIT_1:
1083 case FIN_WAIT_2:
1084 case TIME_WAIT:
1085 default: /* mute compiler */
1086 // Do nothing in these five states
1087 break;
1088 }
1089 return 0;
1090}
1091
1092/* Peacefully close the socket by notifying the upper layer and deallocate end point */
1093void
1095{
1096 NS_LOG_FUNCTION (this);
1097
1098 if (!m_closeNotified)
1099 {
1101 m_closeNotified = true;
1102 }
1104 {
1106 }
1107 NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSED");
1108 m_state = CLOSED;
1110}
1111
1112
1113/* Tell if a sequence number range is out side the range that my rx buffer can
1114 accpet */
1115bool
1117{
1118 if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
1119 { // Rx buffer in these states are not initialized.
1120 return false;
1121 }
1122 if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
1123 { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
1124 // sequence number must equals to m_rxBuffer->NextRxSequence ()
1125 return (m_tcb->m_rxBuffer->NextRxSequence () != head);
1126 }
1127
1128 // In all other cases, check if the sequence number is in range
1129 return (tail < m_tcb->m_rxBuffer->NextRxSequence () || m_tcb->m_rxBuffer->MaxRxSequence () <= head);
1130}
1131
1132/* Function called by the L3 protocol when it received a packet to pass on to
1133 the TCP. This function is registered as the "RxCallback" function in
1134 SetupCallback(), which invoked by Bind(), and CompleteFork() */
1135void
1137 Ptr<Ipv4Interface> incomingInterface)
1138{
1139 NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1141 ":" << m_endPoint->GetPeerPort () <<
1142 " to " << m_endPoint->GetLocalAddress () <<
1143 ":" << m_endPoint->GetLocalPort ());
1144
1145 Address fromAddress = InetSocketAddress (header.GetSource (), port);
1146 Address toAddress = InetSocketAddress (header.GetDestination (),
1148
1149 TcpHeader tcpHeader;
1150 uint32_t bytesRemoved = packet->PeekHeader (tcpHeader);
1151
1152 if (!IsValidTcpSegment (tcpHeader.GetSequenceNumber (), bytesRemoved,
1153 packet->GetSize () - bytesRemoved))
1154 {
1155 return;
1156 }
1157
1158 if (header.GetEcn() == Ipv4Header::ECN_CE && m_ecnCESeq < tcpHeader.GetSequenceNumber ())
1159 {
1160 NS_LOG_INFO ("Received CE flag is valid");
1162 m_ecnCESeq = tcpHeader.GetSequenceNumber ();
1165 }
1167 {
1169 }
1170
1171 DoForwardUp (packet, fromAddress, toAddress);
1172}
1173
1174void
1176 Ptr<Ipv6Interface> incomingInterface)
1177{
1178 NS_LOG_LOGIC ("Socket " << this << " forward up " <<
1180 ":" << m_endPoint6->GetPeerPort () <<
1181 " to " << m_endPoint6->GetLocalAddress () <<
1182 ":" << m_endPoint6->GetLocalPort ());
1183
1184 Address fromAddress = Inet6SocketAddress (header.GetSource (), port);
1185 Address toAddress = Inet6SocketAddress (header.GetDestination (),
1187
1188 TcpHeader tcpHeader;
1189 uint32_t bytesRemoved = packet->PeekHeader (tcpHeader);
1190
1191 if (!IsValidTcpSegment (tcpHeader.GetSequenceNumber (), bytesRemoved,
1192 packet->GetSize () - bytesRemoved))
1193 {
1194 return;
1195 }
1196
1197 if (header.GetEcn() == Ipv6Header::ECN_CE && m_ecnCESeq < tcpHeader.GetSequenceNumber ())
1198 {
1199 NS_LOG_INFO ("Received CE flag is valid");
1201 m_ecnCESeq = tcpHeader.GetSequenceNumber ();
1204 }
1205 else if (header.GetEcn() != Ipv6Header::ECN_NotECT)
1206 {
1208 }
1209
1210 DoForwardUp (packet, fromAddress, toAddress);
1211}
1212
1213void
1214TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1215 uint8_t icmpType, uint8_t icmpCode,
1216 uint32_t icmpInfo)
1217{
1218 NS_LOG_FUNCTION (this << icmpSource << static_cast<uint32_t> (icmpTtl) <<
1219 static_cast<uint32_t> (icmpType) <<
1220 static_cast<uint32_t> (icmpCode) << icmpInfo);
1221 if (!m_icmpCallback.IsNull ())
1222 {
1223 m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1224 }
1225}
1226
1227void
1228TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1229 uint8_t icmpType, uint8_t icmpCode,
1230 uint32_t icmpInfo)
1231{
1232 NS_LOG_FUNCTION (this << icmpSource << static_cast<uint32_t> (icmpTtl) <<
1233 static_cast<uint32_t> (icmpType) <<
1234 static_cast<uint32_t> (icmpCode) << icmpInfo);
1235 if (!m_icmpCallback6.IsNull ())
1236 {
1237 m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1238 }
1239}
1240
1241bool
1243 const uint32_t tcpPayloadSize)
1244{
1245 if (tcpHeaderSize == 0 || tcpHeaderSize > 60)
1246 {
1247 NS_LOG_ERROR ("Bytes removed: " << tcpHeaderSize << " invalid");
1248 return false; // Discard invalid packet
1249 }
1250 else if (tcpPayloadSize > 0 && OutOfRange (seq, seq + tcpPayloadSize))
1251 {
1252 // Discard fully out of range data packets
1253 NS_LOG_WARN ("At state " << TcpStateName[m_state] <<
1254 " received packet of seq [" << seq <<
1255 ":" << seq + tcpPayloadSize <<
1256 ") out of range [" << m_tcb->m_rxBuffer->NextRxSequence () << ":" <<
1257 m_tcb->m_rxBuffer->MaxRxSequence () << ")");
1258 // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
1260 return false;
1261 }
1262 return true;
1263}
1264
1265void
1267 const Address &toAddress)
1268{
1269 // in case the packet still has a priority tag attached, remove it
1270 SocketPriorityTag priorityTag;
1271 packet->RemovePacketTag (priorityTag);
1272
1273 // Peel off TCP header
1274 TcpHeader tcpHeader;
1275 packet->RemoveHeader (tcpHeader);
1276 SequenceNumber32 seq = tcpHeader.GetSequenceNumber ();
1277
1278 if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
1279 {
1280 // Check if the sender has responded to ECN echo by reducing the Congestion Window
1281 if (tcpHeader.GetFlags () & TcpHeader::CWR )
1282 {
1283 // Check if a packet with CE bit set is received. If there is no CE bit set, then change the state to ECN_IDLE to
1284 // stop sending ECN Echo messages. If there is CE bit set, the packet should continue sending ECN Echo messages
1285 //
1287 {
1290 }
1291 }
1292 }
1293
1294 m_rxTrace (packet, tcpHeader, this);
1295
1296 if (tcpHeader.GetFlags () & TcpHeader::SYN)
1297 {
1298 /* The window field in a segment where the SYN bit is set (i.e., a <SYN>
1299 * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be
1300 * saved anyway..
1301 */
1302 m_rWnd = tcpHeader.GetWindowSize ();
1303
1305 {
1307 }
1308 else
1309 {
1310 m_winScalingEnabled = false;
1311 }
1312
1314 {
1316 }
1317 else
1318 {
1319 m_sackEnabled = false;
1320 m_txBuffer->SetSackEnabled (false);
1321 }
1322
1323 // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end
1324 if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled)
1325 {
1327 tcpHeader.GetSequenceNumber ());
1328 }
1329 else
1330 {
1331 m_timestampEnabled = false;
1332 }
1333
1334 // Initialize cWnd and ssThresh
1338
1339 if (tcpHeader.GetFlags () & TcpHeader::ACK)
1340 {
1341 EstimateRtt (tcpHeader);
1342 m_highRxAckMark = tcpHeader.GetAckNumber ();
1343 }
1344 }
1345 else if (tcpHeader.GetFlags () & TcpHeader::ACK)
1346 {
1347 NS_ASSERT (!(tcpHeader.GetFlags () & TcpHeader::SYN));
1349 {
1350 if (!tcpHeader.HasOption (TcpOption::TS))
1351 {
1352 // Ignoring segment without TS, RFC 7323
1353 NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
1354 " received packet of seq [" << seq <<
1355 ":" << seq + packet->GetSize () <<
1356 ") without TS option. Silently discard it");
1357 return;
1358 }
1359 else
1360 {
1362 tcpHeader.GetSequenceNumber ());
1363 }
1364 }
1365
1366 EstimateRtt (tcpHeader);
1367 UpdateWindowSize (tcpHeader);
1368 }
1369
1370
1371 if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ())
1372 { // Zero window: Enter persist state to send 1 byte to probe
1373 NS_LOG_LOGIC (this << " Enter zerowindow persist state");
1374 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
1375 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
1377 NS_LOG_LOGIC ("Schedule persist timeout at time " <<
1378 Simulator::Now ().GetSeconds () << " to expire at time " <<
1379 (Simulator::Now () + m_persistTimeout).GetSeconds ());
1382 }
1383
1384 // TCP state machine code in different process functions
1385 // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1386 switch (m_state)
1387 {
1388 case ESTABLISHED:
1389 ProcessEstablished (packet, tcpHeader);
1390 break;
1391 case LISTEN:
1392 ProcessListen (packet, tcpHeader, fromAddress, toAddress);
1393 break;
1394 case TIME_WAIT:
1395 // Do nothing
1396 break;
1397 case CLOSED:
1398 // Send RST if the incoming packet is not a RST
1399 if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1400 { // Since m_endPoint is not configured yet, we cannot use SendRST here
1401 TcpHeader h;
1402 Ptr<Packet> p = Create<Packet> ();
1405 h.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
1406 h.SetSourcePort (tcpHeader.GetDestinationPort ());
1407 h.SetDestinationPort (tcpHeader.GetSourcePort ());
1409 AddOptions (h);
1410 m_txTrace (p, h, this);
1411 m_tcp->SendPacket (p, h, toAddress, fromAddress, m_boundnetdevice);
1412 }
1413 break;
1414 case SYN_SENT:
1415 ProcessSynSent (packet, tcpHeader);
1416 break;
1417 case SYN_RCVD:
1418 ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
1419 break;
1420 case FIN_WAIT_1:
1421 case FIN_WAIT_2:
1422 case CLOSE_WAIT:
1423 ProcessWait (packet, tcpHeader);
1424 break;
1425 case CLOSING:
1426 ProcessClosing (packet, tcpHeader);
1427 break;
1428 case LAST_ACK:
1429 ProcessLastAck (packet, tcpHeader);
1430 break;
1431 default: // mute compiler
1432 break;
1433 }
1434
1435 if (m_rWnd.Get () != 0 && m_persistEvent.IsRunning ())
1436 { // persist probes end, the other end has increased the window
1438 NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
1440
1442 }
1443}
1444
1445/* Received a packet upon ESTABLISHED state. This function is mimicking the
1446 role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1447void
1449{
1450 NS_LOG_FUNCTION (this << tcpHeader);
1451
1452 // Extract the flags. PSH, URG, CWR and ECE are disregarded.
1453 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
1454
1455 // Different flags are different events
1456 if (tcpflags == TcpHeader::ACK)
1457 {
1458 if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ())
1459 {
1460 // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be ignored.
1461 // Pag. 72 RFC 793
1462 NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1463 " SND.UNA = " << m_txBuffer->HeadSequence ());
1464
1465 // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation]
1466 }
1467 else if (tcpHeader.GetAckNumber () > m_tcb->m_highTxMark)
1468 {
1469 // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then
1470 // send an ACK, drop the segment, and return.
1471 // Pag. 72 RFC 793
1472 NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () <<
1473 " HighTxMark = " << m_tcb->m_highTxMark);
1474
1475 // Receiver sets ECE flags when it receives a packet with CE bit on or sender hasn’t responded to ECN echo sent by receiver
1477 {
1479 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
1481 }
1482 else
1483 {
1485 }
1486 }
1487 else
1488 {
1489 // SND.UNA < SEG.ACK =< HighTxMark
1490 // Pag. 72 RFC 793
1491 ReceivedAck (packet, tcpHeader);
1492 }
1493 }
1494 else if (tcpflags == TcpHeader::SYN)
1495 { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1496 // respond with a SYN+ACK. But it is not a legal state transition as of
1497 // RFC793. Thus this is ignored.
1498 }
1499 else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1500 { // No action for received SYN+ACK, it is probably a duplicated packet
1501 }
1502 else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1503 { // Received FIN or FIN+ACK, bring down this socket nicely
1504 PeerClose (packet, tcpHeader);
1505 }
1506 else if (tcpflags == 0)
1507 { // No flags means there is only data
1508 ReceivedData (packet, tcpHeader);
1509 if (m_tcb->m_rxBuffer->Finished ())
1510 {
1511 PeerClose (packet, tcpHeader);
1512 }
1513 }
1514 else
1515 { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1516 if (tcpflags != TcpHeader::RST)
1517 { // this must be an invalid flag, send reset
1518 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
1519 SendRST ();
1520 }
1521 CloseAndNotify ();
1522 }
1523}
1524
1525bool
1527{
1528 NS_LOG_FUNCTION (this << static_cast<uint32_t> (kind));
1529
1530 switch (kind)
1531 {
1532 case TcpOption::TS:
1533 return m_timestampEnabled;
1535 return m_winScalingEnabled;
1537 case TcpOption::SACK:
1538 return m_sackEnabled;
1539 default:
1540 break;
1541 }
1542 return false;
1543}
1544
1545void
1546TcpSocketBase::ReadOptions (const TcpHeader &tcpHeader, uint32_t *bytesSacked)
1547{
1548 NS_LOG_FUNCTION (this << tcpHeader);
1549 TcpHeader::TcpOptionList::const_iterator it;
1550 const TcpHeader::TcpOptionList options = tcpHeader.GetOptionList ();
1551
1552 for (it = options.begin (); it != options.end (); ++it)
1553 {
1554 const Ptr<const TcpOption> option = (*it);
1555
1556 // Check only for ACK options here
1557 switch (option->GetKind ())
1558 {
1559 case TcpOption::SACK:
1560 *bytesSacked = ProcessOptionSack (option);
1561 break;
1562 default:
1563 continue;
1564 }
1565 }
1566}
1567
1568// Sender should reduce the Congestion Window as a response to receiver's
1569// ECN Echo notification only once per window
1570void
1572{
1573 NS_LOG_FUNCTION (this << currentDelivered);
1575 NS_LOG_DEBUG ("Reduce ssThresh to " << m_tcb->m_ssThresh);
1576 // Do not update m_cWnd, under assumption that recovery process will
1577 // gradually bring it down to m_ssThresh. Update the 'inflated' value of
1578 // cWnd used for tracing, however.
1583 // CWR state will be exited when the ack exceeds the m_recover variable.
1584 // Do not set m_recoverActive (which applies to a loss-based recovery)
1585 // m_recover corresponds to Linux tp->high_seq
1587 if (!m_congestionControl->HasCongControl ())
1588 {
1589 // If there is a recovery algorithm, invoke it.
1590 m_recoveryOps->EnterRecovery (m_tcb, m_dupAckCount, UnAckDataCount (), currentDelivered);
1591 NS_LOG_INFO ("Enter CWR recovery mode; set cwnd to " << m_tcb->m_cWnd
1592 << ", ssthresh to " << m_tcb->m_ssThresh
1593 << ", recover to " << m_recover);
1594 }
1595}
1596
1597void
1599{
1600 NS_LOG_FUNCTION (this);
1602
1604 " -> CA_RECOVERY");
1605
1606 if (!m_sackEnabled)
1607 {
1608 // One segment has left the network, PLUS the head is lost
1609 m_txBuffer->AddRenoSack ();
1610 m_txBuffer->MarkHeadAsLost ();
1611 }
1612 else
1613 {
1614 if (!m_txBuffer->IsLost (m_txBuffer->HeadSequence ()))
1615 {
1616 // We received 3 dupacks, but the head is not marked as lost
1617 // (received less than 3 SACK block ahead).
1618 // Manually set it as lost.
1619 m_txBuffer->MarkHeadAsLost ();
1620 }
1621 }
1622
1623 // RFC 6675, point (4):
1624 // (4) Invoke fast retransmit and enter loss recovery as follows:
1625 // (4.1) RecoveryPoint = HighData
1627 m_recoverActive = true;
1628
1631
1632 // (4.2) ssthresh = cwnd = (FlightSize / 2)
1633 // If SACK is not enabled, still consider the head as 'in flight' for
1634 // compatibility with old ns-3 versions
1636 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, bytesInFlight);
1637
1638 if (!m_congestionControl->HasCongControl ())
1639 {
1640 m_recoveryOps->EnterRecovery (m_tcb, m_dupAckCount, UnAckDataCount (), currentDelivered);
1641 NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." <<
1642 "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
1643 m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover <<
1644 " calculated in flight: " << bytesInFlight);
1645 }
1646
1647
1648 // (4.3) Retransmit the first data segment presumed dropped
1649 DoRetransmit ();
1650 // (4.4) Run SetPipe ()
1651 // (4.5) Proceed to step (C)
1652 // these steps are done after the ProcessAck function (SendPendingData)
1653}
1654
1655void
1657{
1658 NS_LOG_FUNCTION (this);
1659 // NOTE: We do not count the DupAcks received in CA_LOSS, because we
1660 // don't know if they are generated by a spurious retransmission or because
1661 // of a real packet loss. With SACK, it is easy to know, but we do not consider
1662 // dupacks. Without SACK, there are some euristics in the RFC 6582, but
1663 // for now, we do not implement it, leading to ignoring the dupacks.
1665 {
1666 return;
1667 }
1668
1669 // RFC 6675, Section 5, 3rd paragraph:
1670 // If the incoming ACK is a duplicate acknowledgment per the definition
1671 // in Section 2 (regardless of its status as a cumulative
1672 // acknowledgment), and the TCP is not currently in loss recovery
1673 // the TCP MUST increase DupAcks by one ...
1675 {
1676 ++m_dupAckCount;
1677 }
1678
1680 {
1681 // From Open we go Disorder
1682 NS_ASSERT_MSG (m_dupAckCount == 1, "From OPEN->DISORDER but with " <<
1683 m_dupAckCount << " dup ACKs");
1684
1687
1688 NS_LOG_DEBUG ("CA_OPEN -> CA_DISORDER");
1689 }
1690
1692 {
1693 if (!m_sackEnabled)
1694 {
1695 // If we are in recovery and we receive a dupack, one segment
1696 // has left the network. This is equivalent to a SACK of one block.
1697 m_txBuffer->AddRenoSack ();
1698 }
1699 if (!m_congestionControl->HasCongControl ())
1700 {
1701 m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
1702 NS_LOG_INFO (m_dupAckCount << " Dupack received in fast recovery mode."
1703 "Increase cwnd to " << m_tcb->m_cWnd);
1704 }
1705 }
1707 {
1708 // m_dupackCount should not exceed its threshold in CA_DISORDER state
1709 // when m_recoverActive has not been set. When recovery point
1710 // have been set after timeout, the sender could enter into CA_DISORDER
1711 // after receiving new ACK smaller than m_recover. After that, m_dupackCount
1712 // can be equal and larger than m_retxThresh and we should avoid entering
1713 // CA_RECOVERY and reducing sending rate again.
1715
1716 // RFC 6675, Section 5, continuing:
1717 // ... and take the following steps:
1718 // (1) If DupAcks >= DupThresh, go to step (4).
1719 // Sequence number comparison (m_highRxAckMark >= m_recover) will take
1720 // effect only when m_recover has been set. Hence, we can avoid to use
1721 // m_recover in the last congestion event and fail to enter
1722 // CA_RECOVERY when sequence number is advanced significantly since
1723 // the last congestion event, which could be common for
1724 // bandwidth-greedy application in high speed and reliable network
1725 // (such as datacenter network) whose sending rate is constrainted by
1726 // TCP socket buffer size at receiver side.
1728 {
1729 EnterRecovery (currentDelivered);
1731 }
1732 // (2) If DupAcks < DupThresh but IsLost (HighACK + 1) returns true
1733 // (indicating at least three segments have arrived above the current
1734 // cumulative acknowledgment point, which is taken to indicate loss)
1735 // go to step (4).
1736 else if (m_txBuffer->IsLost (m_highRxAckMark + m_tcb->m_segmentSize))
1737 {
1738 EnterRecovery (currentDelivered);
1740 }
1741 else
1742 {
1743 // (3) The TCP MAY transmit previously unsent data segments as per
1744 // Limited Transmit [RFC5681] ...except that the number of octets
1745 // which may be sent is governed by pipe and cwnd as follows:
1746 //
1747 // (3.1) Set HighRxt to HighACK.
1748 // Not clear in RFC. We don't do this here, since we still have
1749 // to retransmit the segment.
1750
1751 if (!m_sackEnabled && m_limitedTx)
1752 {
1753 m_txBuffer->AddRenoSack ();
1754
1755 // In limited transmit, cwnd Infl is not updated.
1756 }
1757 }
1758 }
1759}
1760
1761/* Process the newly received ACK */
1762void
1764{
1765 NS_LOG_FUNCTION (this << tcpHeader);
1766
1767 NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK));
1769
1770 uint32_t previousLost = m_txBuffer->GetLost ();
1771 uint32_t priorInFlight = m_tcb->m_bytesInFlight.Get ();
1772
1773 // RFC 6675, Section 5, 1st paragraph:
1774 // Upon the receipt of any ACK containing SACK information, the
1775 // scoreboard MUST be updated via the Update () routine (done in ReadOptions)
1776 uint32_t bytesSacked = 0;
1777 uint64_t previousDelivered = m_rateOps->GetConnectionRate ().m_delivered;
1778 ReadOptions (tcpHeader, &bytesSacked);
1779
1780 SequenceNumber32 ackNumber = tcpHeader.GetAckNumber ();
1781 SequenceNumber32 oldHeadSequence = m_txBuffer->HeadSequence ();
1782
1783 if (ackNumber < oldHeadSequence)
1784 {
1785 NS_LOG_DEBUG ("Possibly received a stale ACK (ack number < head sequence)");
1786 // If there is any data piggybacked, store it into m_rxBuffer
1787 if (packet->GetSize () > 0)
1788 {
1789 ReceivedData (packet, tcpHeader);
1790 }
1791 return;
1792 }
1793 if ((ackNumber > oldHeadSequence) && (ackNumber < m_recover)
1795 {
1796 uint32_t segAcked = (ackNumber - oldHeadSequence)/m_tcb->m_segmentSize;
1797 for (uint32_t i = 0; i < segAcked; i++)
1798 {
1799 if (m_txBuffer->IsRetransmittedDataAcked (ackNumber - (i * m_tcb->m_segmentSize)))
1800 {
1802 NS_LOG_DEBUG ("Ack Number " << ackNumber <<
1803 "is ACK of retransmitted packet.");
1804 }
1805 }
1806 }
1807
1808 m_txBuffer->DiscardUpTo (ackNumber, MakeCallback (&TcpRateOps::SkbDelivered, m_rateOps));
1809
1810 uint32_t currentDelivered = static_cast<uint32_t> (m_rateOps->GetConnectionRate ().m_delivered - previousDelivered);
1811 m_tcb->m_lastAckedSackedBytes = currentDelivered;
1812
1813 if (m_tcb->m_congState == TcpSocketState::CA_CWR && (ackNumber > m_recover))
1814 {
1815 // Recovery is over after the window exceeds m_recover
1816 // (although it may be re-entered below if ECE is still set)
1819 if (!m_congestionControl->HasCongControl ())
1820 {
1822 m_recoveryOps->ExitRecovery (m_tcb);
1824 }
1825 }
1826
1827 if (ackNumber > oldHeadSequence && (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED) && (tcpHeader.GetFlags () & TcpHeader::ECE))
1828 {
1829 if (m_ecnEchoSeq < ackNumber)
1830 {
1831 NS_LOG_INFO ("Received ECN Echo is valid");
1832 m_ecnEchoSeq = ackNumber;
1836 {
1837 EnterCwr (currentDelivered);
1838 }
1839 }
1840 }
1841 else if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && !(tcpHeader.GetFlags () & TcpHeader::ECE))
1842 {
1844 }
1845
1846 // Update bytes in flight before processing the ACK for proper calculation of congestion window
1847 NS_LOG_INFO ("Update bytes in flight before processing the ACK.");
1848 BytesInFlight ();
1849
1850 // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation
1851 // are inside the function ProcessAck
1852 ProcessAck (ackNumber, (bytesSacked > 0), currentDelivered, oldHeadSequence);
1853 m_tcb->m_isRetransDataAcked = false;
1854
1855 if (m_congestionControl->HasCongControl ())
1856 {
1857 uint32_t currentLost = m_txBuffer->GetLost ();
1858 uint32_t lost = (currentLost > previousLost) ?
1859 currentLost - previousLost :
1860 previousLost - currentLost;
1861 auto rateSample = m_rateOps->GenerateSample (currentDelivered, lost,
1862 false, priorInFlight, m_tcb->m_minRtt);
1863 auto rateConn = m_rateOps->GetConnectionRate ();
1864 m_congestionControl->CongControl(m_tcb, rateConn, rateSample);
1865 }
1866
1867 // If there is any data piggybacked, store it into m_rxBuffer
1868 if (packet->GetSize () > 0)
1869 {
1870 ReceivedData (packet, tcpHeader);
1871 }
1872
1873 // RFC 6675, Section 5, point (C), try to send more data. NB: (C) is implemented
1874 // inside SendPendingData
1876}
1877
1878void
1879TcpSocketBase::ProcessAck(const SequenceNumber32 &ackNumber, bool scoreboardUpdated,
1880 uint32_t currentDelivered, const SequenceNumber32 &oldHeadSequence)
1881{
1882 NS_LOG_FUNCTION (this << ackNumber << scoreboardUpdated);
1883 // RFC 6675, Section 5, 2nd paragraph:
1884 // If the incoming ACK is a cumulative acknowledgment, the TCP MUST
1885 // reset DupAcks to zero.
1886 bool exitedFastRecovery = false;
1887 uint32_t oldDupAckCount = m_dupAckCount; // remember the old value
1888 m_tcb->m_lastAckedSeq = ackNumber; // Update lastAckedSeq
1889 uint32_t bytesAcked = 0;
1890
1891 /* In RFC 5681 the definition of duplicate acknowledgment was strict:
1892 *
1893 * (a) the receiver of the ACK has outstanding data,
1894 * (b) the incoming acknowledgment carries no data,
1895 * (c) the SYN and FIN bits are both off,
1896 * (d) the acknowledgment number is equal to the greatest acknowledgment
1897 * received on the given connection (TCP.UNA from [RFC793]),
1898 * (e) the advertised window in the incoming acknowledgment equals the
1899 * advertised window in the last incoming acknowledgment.
1900 *
1901 * With RFC 6675, this definition has been reduced:
1902 *
1903 * (a) the ACK is carrying a SACK block that identifies previously
1904 * unacknowledged and un-SACKed octets between HighACK (TCP.UNA) and
1905 * HighData (m_highTxMark)
1906 */
1907
1908 bool isDupack = m_sackEnabled ?
1909 scoreboardUpdated
1910 : ackNumber == oldHeadSequence &&
1911 ackNumber < m_tcb->m_highTxMark;
1912
1913 NS_LOG_DEBUG ("ACK of " << ackNumber <<
1914 " SND.UNA=" << oldHeadSequence <<
1915 " SND.NXT=" << m_tcb->m_nextTxSequence <<
1917 " with m_recover: " << m_recover);
1918
1919 // RFC 6675, Section 5, 3rd paragraph:
1920 // If the incoming ACK is a duplicate acknowledgment per the definition
1921 // in Section 2 (regardless of its status as a cumulative
1922 // acknowledgment), and the TCP is not currently in loss recovery
1923 if (isDupack)
1924 {
1925 // loss recovery check is done inside this function thanks to
1926 // the congestion state machine
1927 DupAck (currentDelivered);
1928 }
1929
1930 if (ackNumber == oldHeadSequence
1931 && ackNumber == m_tcb->m_highTxMark)
1932 {
1933 // Dupack, but the ACK is precisely equal to the nextTxSequence
1934 return;
1935 }
1936 else if (ackNumber == oldHeadSequence
1937 && ackNumber > m_tcb->m_highTxMark)
1938 {
1939 // ACK of the FIN bit ... nextTxSequence is not updated since we
1940 // don't have anything to transmit
1941 NS_LOG_DEBUG ("Update nextTxSequence manually to " << ackNumber);
1942 m_tcb->m_nextTxSequence = ackNumber;
1943 }
1944 else if (ackNumber == oldHeadSequence)
1945 {
1946 // DupAck. Artificially call PktsAcked: after all, one segment has been ACKed.
1947 m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
1948 }
1949 else if (ackNumber > oldHeadSequence)
1950 {
1951 // Please remember that, with SACK, we can enter here even if we
1952 // received a dupack.
1953 bytesAcked = ackNumber - oldHeadSequence;
1954 uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
1956 bytesAcked -= bytesAcked % m_tcb->m_segmentSize;
1957
1959 {
1960 segsAcked += 1;
1961 bytesAcked += m_tcb->m_segmentSize;
1963 }
1964
1965 // Dupack count is reset to eventually fast-retransmit after 3 dupacks.
1966 // Any SACK-ed segment will be cleaned up by DiscardUpTo.
1967 // In the case that we advanced SND.UNA, but the ack contains SACK blocks,
1968 // we do not reset. At the third one we will retransmit.
1969 // If we are already in recovery, this check is useless since dupAcks
1970 // are not considered in this phase. When from Recovery we go back
1971 // to open, then dupAckCount is reset anyway.
1972 if (!isDupack)
1973 {
1974 m_dupAckCount = 0;
1975 }
1976
1977 // RFC 6675, Section 5, part (B)
1978 // (B) Upon receipt of an ACK that does not cover RecoveryPoint, the
1979 // following actions MUST be taken:
1980 //
1981 // (B.1) Use Update () to record the new SACK information conveyed
1982 // by the incoming ACK.
1983 // (B.2) Use SetPipe () to re-calculate the number of octets still
1984 // in the network.
1985 //
1986 // (B.1) is done at the beginning, while (B.2) is delayed to part (C) while
1987 // trying to transmit with SendPendingData. We are not allowed to exit
1988 // the CA_RECOVERY phase. Just process this partial ack (RFC 5681)
1989 if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
1990 {
1991 if (!m_sackEnabled)
1992 {
1993 // Manually set the head as lost, it will be retransmitted.
1994 NS_LOG_INFO ("Partial ACK. Manually setting head as lost");
1995 m_txBuffer->MarkHeadAsLost ();
1996 }
1997
1998 // Before retransmitting the packet perform DoRecovery and check if
1999 // there is available window
2000 if (!m_congestionControl->HasCongControl () && segsAcked >= 1)
2001 {
2002 m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
2003 }
2004
2005 // If the packet is already retransmitted do not retransmit it
2006 if (!m_txBuffer->IsRetransmittedDataAcked (ackNumber + m_tcb->m_segmentSize))
2007 {
2008 DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
2010 }
2011
2012 // This partial ACK acknowledge the fact that one segment has been
2013 // previously lost and now successfully received. All others have
2014 // been processed when they come under the form of dupACKs
2015 m_congestionControl->PktsAcked (m_tcb, 1, m_tcb->m_lastRtt);
2016 NewAck (ackNumber, m_isFirstPartialAck);
2017
2019 {
2020 NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
2021 " and this is the first (RTO will be reset);"
2022 " cwnd set to " << m_tcb->m_cWnd <<
2023 " recover seq: " << m_recover <<
2024 " dupAck count: " << m_dupAckCount);
2025 m_isFirstPartialAck = false;
2026 }
2027 else
2028 {
2029 NS_LOG_DEBUG ("Partial ACK of " << ackNumber <<
2030 " and this is NOT the first (RTO will not be reset)"
2031 " cwnd set to " << m_tcb->m_cWnd <<
2032 " recover seq: " << m_recover <<
2033 " dupAck count: " << m_dupAckCount);
2034 }
2035 }
2036 // From RFC 6675 section 5.1
2037 // In addition, a new recovery phase (as described in Section 5) MUST NOT
2038 // be initiated until HighACK is greater than or equal to the new value
2039 // of RecoveryPoint.
2040 else if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_LOSS)
2041 {
2042 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2043 m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
2044
2045 NS_LOG_DEBUG (" Cong Control Called, cWnd=" << m_tcb->m_cWnd <<
2046 " ssTh=" << m_tcb->m_ssThresh);
2047 if (!m_sackEnabled)
2048 {
2049 NS_ASSERT_MSG (m_txBuffer->GetSacked () == 0,
2050 "Some segment got dup-acked in CA_LOSS state: " <<
2051 m_txBuffer->GetSacked ());
2052 }
2053 NewAck (ackNumber, true);
2054 }
2056 {
2057 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2058 // TODO: need to check behavior if marking is compounded by loss
2059 // and/or packet reordering
2060 if (!m_congestionControl->HasCongControl () && segsAcked >= 1)
2061 {
2062 m_recoveryOps->DoRecovery (m_tcb, currentDelivered);
2063 }
2064 NewAck (ackNumber, true);
2065 }
2066 else
2067 {
2069 {
2070 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2071 }
2073 {
2074 if (segsAcked >= oldDupAckCount)
2075 {
2076 m_congestionControl->PktsAcked (m_tcb, segsAcked - oldDupAckCount, m_tcb->m_lastRtt);
2077 }
2078
2079 if (!isDupack)
2080 {
2081 // The network reorder packets. Linux changes the counting lost
2082 // packet algorithm from FACK to NewReno. We simply go back in Open.
2083 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2085 NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
2086 ackNumber << " exiting CA_DISORDER -> CA_OPEN");
2087 }
2088 else
2089 {
2090 NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of " <<
2091 ackNumber << " but still in CA_DISORDER");
2092 }
2093 }
2094 // RFC 6675, Section 5:
2095 // Once a TCP is in the loss recovery phase, the following procedure
2096 // MUST be used for each arriving ACK:
2097 // (A) An incoming cumulative ACK for a sequence number greater than
2098 // RecoveryPoint signals the end of loss recovery, and the loss
2099 // recovery phase MUST be terminated. Any information contained in
2100 // the scoreboard for sequence numbers greater than the new value of
2101 // HighACK SHOULD NOT be cleared when leaving the loss recovery
2102 // phase.
2104 {
2105 m_isFirstPartialAck = true;
2106
2107 // Recalculate the segs acked, that are from m_recover to ackNumber
2108 // (which are the ones we have not passed to PktsAcked and that
2109 // can increase cWnd)
2110 // TODO: check consistency for dynamic segment size
2111 segsAcked = static_cast<uint32_t>(ackNumber - oldHeadSequence) / m_tcb->m_segmentSize;
2112 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2114 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2116 exitedFastRecovery = true;
2117 m_dupAckCount = 0; // From recovery to open, reset dupack
2118
2119 NS_LOG_DEBUG (segsAcked << " segments acked in CA_RECOVER, ack of " <<
2120 ackNumber << ", exiting CA_RECOVERY -> CA_OPEN");
2121 }
2123 {
2124 m_isFirstPartialAck = true;
2125
2126 // Recalculate the segs acked, that are from m_recover to ackNumber
2127 // (which are the ones we have not passed to PktsAcked and that
2128 // can increase cWnd)
2129 segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
2130
2131 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_tcb->m_lastRtt);
2132
2133 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2135 NS_LOG_DEBUG (segsAcked << " segments acked in CA_LOSS, ack of" <<
2136 ackNumber << ", exiting CA_LOSS -> CA_OPEN");
2137 }
2138
2139 if (ackNumber >= m_recover)
2140 {
2141 // All lost segments in the congestion event have been
2142 // retransmitted successfully. The recovery point (m_recover)
2143 // should be deactivated.
2144 m_recoverActive = false;
2145 }
2146
2147 if (exitedFastRecovery)
2148 {
2149 NewAck (ackNumber, true);
2151 m_recoveryOps->ExitRecovery (m_tcb);
2152 NS_LOG_DEBUG ("Leaving Fast Recovery; BytesInFlight() = " <<
2153 BytesInFlight () << "; cWnd = " << m_tcb->m_cWnd);
2154 }
2156 {
2157 m_congestionControl->IncreaseWindow (m_tcb, segsAcked);
2158
2160
2161 NS_LOG_LOGIC ("Congestion control called: " <<
2162 " cWnd: " << m_tcb->m_cWnd <<
2163 " ssTh: " << m_tcb->m_ssThresh <<
2164 " segsAcked: " << segsAcked);
2165
2166 NewAck (ackNumber, true);
2167 }
2168 }
2169 }
2170 // Update the pacing rate, since m_congestionControl->IncreaseWindow() or
2171 // m_congestionControl->PktsAcked () may change m_tcb->m_cWnd
2172 // Make sure that control reaches the end of this function and there is no
2173 // return in between
2175}
2176
2177/* Received a packet upon LISTEN state. */
2178void
2180 const Address& fromAddress, const Address& toAddress)
2181{
2182 NS_LOG_FUNCTION (this << tcpHeader);
2183
2184 // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2185 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2186
2187 // Fork a socket if received a SYN. Do nothing otherwise.
2188 // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
2189 if (tcpflags != TcpHeader::SYN)
2190 {
2191 return;
2192 }
2193
2194 // Call socket's notify function to let the server app know we got a SYN
2195 // If the server app refuses the connection, do nothing
2196 if (!NotifyConnectionRequest (fromAddress))
2197 {
2198 return;
2199 }
2200 // Clone the socket, simulate fork
2201 Ptr<TcpSocketBase> newSock = Fork ();
2202 NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
2204 packet, tcpHeader, fromAddress, toAddress);
2205}
2206
2207/* Received a packet upon SYN_SENT */
2208void
2210{
2211 NS_LOG_FUNCTION (this << tcpHeader);
2212
2213 // Extract the flags. PSH and URG are disregarded.
2214 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2215
2216 if (tcpflags == 0)
2217 { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove this?
2218 NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2219 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2222 m_connected = true;
2225 ReceivedData (packet, tcpHeader);
2227 }
2228 else if (tcpflags & TcpHeader::ACK && !(tcpflags & TcpHeader::SYN))
2229 { // Ignore ACK in SYN_SENT
2230 }
2231 else if (tcpflags & TcpHeader::SYN && !(tcpflags & TcpHeader::ACK))
2232 { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
2233 NS_LOG_DEBUG ("SYN_SENT -> SYN_RCVD");
2234 m_state = SYN_RCVD;
2236 m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2237 /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if the traffic is ECN capable and
2238 * sender has sent ECN SYN packet
2239 */
2240
2242 {
2243 NS_LOG_INFO ("Received ECN SYN packet");
2247 }
2248 else
2249 {
2252 }
2253 }
2254 else if (tcpflags & (TcpHeader::SYN | TcpHeader::ACK)
2255 && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ())
2256 { // Handshake completed
2257 NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED");
2258 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2261 m_connected = true;
2263 m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2265 m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2266 // Before sending packets, update the pacing rate based on RTT measurement so far
2269
2270 /* Check if we received an ECN SYN-ACK packet. Change the ECN state of sender to ECN_IDLE if receiver has sent an ECN SYN-ACK
2271 * packet and the traffic is ECN Capable
2272 */
2274 {
2275 NS_LOG_INFO ("Received ECN SYN-ACK packet.");
2278 }
2279 else
2280 {
2282 }
2285 // Always respond to first data packet to speed up the connection.
2286 // Remove to get the behaviour of old NS-3 code.
2288 }
2289 else
2290 { // Other in-sequence input
2291 if (!(tcpflags & TcpHeader::RST))
2292 { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
2293 NS_LOG_LOGIC ("Illegal flag combination " << TcpHeader::FlagsToString (tcpHeader.GetFlags ()) <<
2294 " received in SYN_SENT. Reset packet is sent.");
2295 SendRST ();
2296 }
2297 CloseAndNotify ();
2298 }
2299}
2300
2301/* Received a packet upon SYN_RCVD */
2302void
2304 const Address& fromAddress,
2305 [[maybe_unused]] const Address& toAddress)
2306{
2307 NS_LOG_FUNCTION (this << tcpHeader);
2308
2309 // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2310 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2311
2312 if (tcpflags == 0
2313 || (tcpflags == TcpHeader::ACK
2314 && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
2315 { // If it is bare data, accept it and move to ESTABLISHED state. This is
2316 // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
2317 // handshake is completed nicely.
2318 NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED");
2319 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN);
2322 m_connected = true;
2325 m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2326 if (m_endPoint)
2327 {
2328 m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2329 InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2330 }
2331 else if (m_endPoint6)
2332 {
2333 m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2334 Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2335 }
2336 // Always respond to first data packet to speed up the connection.
2337 // Remove to get the behaviour of old NS-3 code.
2339 NotifyNewConnectionCreated (this, fromAddress);
2340 ReceivedAck (packet, tcpHeader);
2341 // Update the pacing rate based on RTT measurement so far
2343 // As this connection is established, the socket is available to send data now
2344 if (GetTxAvailable () > 0)
2345 {
2347 }
2348 }
2349 else if (tcpflags == TcpHeader::SYN)
2350 { // Probably the peer lost my SYN+ACK
2351 m_tcb->m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1));
2352 /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2353 * packet and the traffic is ECN Capable
2354 */
2356 {
2357 NS_LOG_INFO ("Received ECN SYN packet");
2361 }
2362 else
2363 {
2366 }
2367 }
2368 else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2369 {
2370 if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2371 { // In-sequence FIN before connection complete. Set up connection and close.
2372 m_connected = true;
2375 m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence);
2376 if (m_endPoint)
2377 {
2378 m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2379 InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2380 }
2381 else if (m_endPoint6)
2382 {
2383 m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2384 Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2385 }
2386 NotifyNewConnectionCreated (this, fromAddress);
2387 PeerClose (packet, tcpHeader);
2388 }
2389 }
2390 else
2391 { // Other in-sequence input
2392 if (tcpflags != TcpHeader::RST)
2393 { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
2394 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2395 " received. Reset packet is sent.");
2396 if (m_endPoint)
2397 {
2398 m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2399 InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2400 }
2401 else if (m_endPoint6)
2402 {
2403 m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2404 Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2405 }
2406 SendRST ();
2407 }
2408 CloseAndNotify ();
2409 }
2410}
2411
2412/* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
2413void
2415{
2416 NS_LOG_FUNCTION (this << tcpHeader);
2417
2418 // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2419 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG | TcpHeader::CWR | TcpHeader::ECE);
2420
2421 if (packet->GetSize () > 0 && !(tcpflags & TcpHeader::ACK))
2422 { // Bare data, accept it
2423 ReceivedData (packet, tcpHeader);
2424 }
2425 else if (tcpflags == TcpHeader::ACK)
2426 { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
2427 ReceivedAck (packet, tcpHeader);
2428 if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0
2429 && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2430 { // This ACK corresponds to the FIN sent
2431 NS_LOG_DEBUG ("FIN_WAIT_1 -> FIN_WAIT_2");
2433 }
2434 }
2435 else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2436 { // Got FIN, respond with ACK and move to next state
2437 if (tcpflags & TcpHeader::ACK)
2438 { // Process the ACK first
2439 ReceivedAck (packet, tcpHeader);
2440 }
2441 m_tcb->m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ());
2442 }
2443 else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
2444 { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
2445 return;
2446 }
2447 else
2448 { // This is a RST or bad flags
2449 if (tcpflags != TcpHeader::RST)
2450 {
2451 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <<
2452 " received. Reset packet is sent.");
2453 SendRST ();
2454 }
2455 CloseAndNotify ();
2456 return;
2457 }
2458
2459 // Check if the close responder sent an in-sequence FIN, if so, respond ACK
2460 if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_tcb->m_rxBuffer->Finished ())
2461 {
2462 if (m_state == FIN_WAIT_1)
2463 {
2464 NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2465 m_state = CLOSING;
2466 if (m_txBuffer->Size () == 0
2467 && tcpHeader.GetAckNumber () == m_tcb->m_highTxMark + SequenceNumber32 (1))
2468 { // This ACK corresponds to the FIN sent
2469 TimeWait ();
2470 }
2471 }
2472 else if (m_state == FIN_WAIT_2)
2473 {
2474 TimeWait ();
2475 }
2477 if (!m_shutdownRecv)
2478 {
2479 NotifyDataRecv ();
2480 }
2481 }
2482}
2483
2484/* Received a packet upon CLOSING */
2485void
2487{
2488 NS_LOG_FUNCTION (this << tcpHeader);
2489
2490 // Extract the flags. PSH and URG are disregarded.
2491 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2492
2493 if (tcpflags == TcpHeader::ACK)
2494 {
2495 if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2496 { // This ACK corresponds to the FIN sent
2497 TimeWait ();
2498 }
2499 }
2500 else
2501 { // CLOSING state means simultaneous close, i.e. no one is sending data to
2502 // anyone. If anything other than ACK is received, respond with a reset.
2503 if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2504 { // FIN from the peer as well. We can close immediately.
2506 }
2507 else if (tcpflags != TcpHeader::RST)
2508 { // Receive of SYN or SYN+ACK or bad flags or pure data
2509 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2510 SendRST ();
2511 }
2512 CloseAndNotify ();
2513 }
2514}
2515
2516/* Received a packet upon LAST_ACK */
2517void
2519{
2520 NS_LOG_FUNCTION (this << tcpHeader);
2521
2522 // Extract the flags. PSH and URG are disregarded.
2523 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
2524
2525 if (tcpflags == 0)
2526 {
2527 ReceivedData (packet, tcpHeader);
2528 }
2529 else if (tcpflags == TcpHeader::ACK)
2530 {
2531 if (tcpHeader.GetSequenceNumber () == m_tcb->m_rxBuffer->NextRxSequence ())
2532 { // This ACK corresponds to the FIN sent. This socket closed peacefully.
2533 CloseAndNotify ();
2534 }
2535 }
2536 else if (tcpflags == TcpHeader::FIN)
2537 { // Received FIN again, the peer probably lost the FIN+ACK
2539 }
2540 else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2541 {
2542 CloseAndNotify ();
2543 }
2544 else
2545 { // Received a SYN or SYN+ACK or bad flags
2546 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) << " received. Reset packet is sent.");
2547 SendRST ();
2548 CloseAndNotify ();
2549 }
2550}
2551
2552/* Peer sent me a FIN. Remember its sequence in rx buffer. */
2553void
2555{
2556 NS_LOG_FUNCTION (this << tcpHeader);
2557
2558 // Ignore all out of range packets
2559 if (tcpHeader.GetSequenceNumber () < m_tcb->m_rxBuffer->NextRxSequence ()
2560 || tcpHeader.GetSequenceNumber () > m_tcb->m_rxBuffer->MaxRxSequence ())
2561 {
2562 return;
2563 }
2564 // For any case, remember the FIN position in rx buffer first
2565 m_tcb->m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2566 NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
2567 // If there is any piggybacked data, process it
2568 if (p->GetSize ())
2569 {
2570 ReceivedData (p, tcpHeader);
2571 }
2572 // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2573 if (!m_tcb->m_rxBuffer->Finished ())
2574 {
2575 return;
2576 }
2577
2578 // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2579 if (m_state == FIN_WAIT_1)
2580 {
2581 NS_LOG_DEBUG ("FIN_WAIT_1 -> CLOSING");
2582 m_state = CLOSING;
2583 return;
2584 }
2585
2586 DoPeerClose (); // Change state, respond with ACK
2587}
2588
2589/* Received a in-sequence FIN. Close down this socket. */
2590void
2592{
2595
2596 // Move the state to CLOSE_WAIT
2597 NS_LOG_DEBUG (TcpStateName[m_state] << " -> CLOSE_WAIT");
2599
2600 if (!m_closeNotified)
2601 {
2602 // The normal behaviour for an application is that, when the peer sent a in-sequence
2603 // FIN, the app should prepare to close. The app has two choices at this point: either
2604 // respond with ShutdownSend() call to declare that it has nothing more to send and
2605 // the socket can be closed immediately; or remember the peer's close request, wait
2606 // until all its existing data are pushed into the TCP socket, then call Close()
2607 // explicitly.
2608 NS_LOG_LOGIC ("TCP " << this << " calling NotifyNormalClose");
2610 m_closeNotified = true;
2611 }
2612 if (m_shutdownSend)
2613 { // The application declares that it would not sent any more, close this socket
2614 Close ();
2615 }
2616 else
2617 { // Need to ack, the application will close later
2619 }
2620 if (m_state == LAST_ACK)
2621 {
2622 m_dataRetrCount = m_dataRetries; // prevent endless FINs
2623 NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
2624 Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
2626 }
2627}
2628
2629/* Kill this socket. This is a callback function configured to m_endpoint in
2630 SetupCallback(), invoked when the endpoint is destroyed. */
2631void
2633{
2634 NS_LOG_FUNCTION (this);
2635 m_endPoint = nullptr;
2636 if (m_tcp)
2637 {
2638 m_tcp->RemoveSocket (this);
2639 }
2640 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2641 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2642 CancelAllTimers ();
2643}
2644
2645/* Kill this socket. This is a callback function configured to m_endpoint in
2646 SetupCallback(), invoked when the endpoint is destroyed. */
2647void
2649{
2650 NS_LOG_FUNCTION (this);
2651 m_endPoint6 = nullptr;
2652 if (m_tcp)
2653 {
2654 m_tcp->RemoveSocket (this);
2655 }
2656 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
2657 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
2658 CancelAllTimers ();
2659}
2660
2661/* Send an empty packet with specified TCP flags */
2662void
2664{
2665 NS_LOG_FUNCTION (this << static_cast<uint32_t> (flags));
2666
2667 if (m_endPoint == nullptr && m_endPoint6 == nullptr)
2668 {
2669 NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
2670 return;
2671 }
2672
2673 Ptr<Packet> p = Create<Packet> ();
2674 TcpHeader header;
2676
2677 if (flags & TcpHeader::FIN)
2678 {
2679 flags |= TcpHeader::ACK;
2680 }
2681 else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2682 {
2683 ++s;
2684 }
2685
2686 AddSocketTags (p);
2687
2688 header.SetFlags (flags);
2689 header.SetSequenceNumber (s);
2690 header.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
2691 if (m_endPoint != nullptr)
2692 {
2695 }
2696 else
2697 {
2700 }
2701 AddOptions (header);
2702
2703 // RFC 6298, clause 2.4
2704 m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
2705
2706 uint16_t windowSize = AdvertisedWindowSize ();
2707 bool hasSyn = flags & TcpHeader::SYN;
2708 bool hasFin = flags & TcpHeader::FIN;
2709 bool isAck = flags == TcpHeader::ACK;
2710 if (hasSyn)
2711 {
2713 { // The window scaling option is set only on SYN packets
2714 AddOptionWScale (header);
2715 }
2716
2717 if (m_sackEnabled)
2718 {
2719 AddOptionSackPermitted (header);
2720 }
2721
2722 if (m_synCount == 0)
2723 { // No more connection retries, give up
2724 NS_LOG_LOGIC ("Connection failed.");
2725 m_rtt->Reset (); //According to recommendation -> RFC 6298
2727 m_state = CLOSED;
2729 return;
2730 }
2731 else
2732 { // Exponential backoff of connection time out
2733 int backoffCount = 0x1 << (m_synRetries - m_synCount);
2734 m_rto = m_cnTimeout * backoffCount;
2735 m_synCount--;
2736 }
2737
2738 if (m_synRetries - 1 == m_synCount)
2739 {
2740 UpdateRttHistory (s, 0, false);
2741 }
2742 else
2743 { // This is SYN retransmission
2744 UpdateRttHistory (s, 0, true);
2745 }
2746
2747 windowSize = AdvertisedWindowSize (false);
2748 }
2749 header.SetWindowSize (windowSize);
2750
2751 if (flags & TcpHeader::ACK)
2752 { // If sending an ACK, cancel the delay ACK as well
2754 m_delAckCount = 0;
2755 if (m_highTxAck < header.GetAckNumber ())
2756 {
2757 m_highTxAck = header.GetAckNumber ();
2758 }
2759 if (m_sackEnabled && m_tcb->m_rxBuffer->GetSackListSize () > 0)
2760 {
2761 AddOptionSack (header);
2762 }
2763 NS_LOG_INFO ("Sending a pure ACK, acking seq " << m_tcb->m_rxBuffer->NextRxSequence ());
2764 }
2765
2766 m_txTrace (p, header, this);
2767
2768 if (m_endPoint != nullptr)
2769 {
2770 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
2772 }
2773 else
2774 {
2775 m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
2777 }
2778
2779
2780 if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck )
2781 { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2782 NS_LOG_LOGIC ("Schedule retransmission timeout at time "
2783 << Simulator::Now ().GetSeconds () << " to expire at time "
2784 << (Simulator::Now () + m_rto.Get ()).GetSeconds ());
2786 }
2787}
2788
2789/* This function closes the endpoint completely. Called upon RST_TX action. */
2790void
2792{
2793 NS_LOG_FUNCTION (this);
2797}
2798
2799/* Deallocate the end point and cancel all the timers */
2800void
2802{
2803 if (m_endPoint != nullptr)
2804 {
2805 CancelAllTimers ();
2806 m_endPoint->SetDestroyCallback (MakeNullCallback<void> ());
2807 m_tcp->DeAllocate (m_endPoint);
2808 m_endPoint = nullptr;
2809 m_tcp->RemoveSocket (this);
2810 }
2811 else if (m_endPoint6 != nullptr)
2812 {
2813 CancelAllTimers ();
2814 m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
2815 m_tcp->DeAllocate (m_endPoint6);
2816 m_endPoint6 = nullptr;
2817 m_tcp->RemoveSocket (this);
2818 }
2819}
2820
2821/* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2822int
2824{
2825 NS_LOG_FUNCTION (this);
2826 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
2827 NS_ASSERT (ipv4);
2828 if (!ipv4->GetRoutingProtocol ())
2829 {
2830 NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
2831 }
2832 // Create a dummy packet, then ask the routing function for the best output
2833 // interface's address
2834 Ipv4Header header;
2836 Socket::SocketErrno errno_;
2837 Ptr<Ipv4Route> route;
2839 route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2840 if (!route)
2841 {
2842 NS_LOG_LOGIC ("Route to " << m_endPoint->GetPeerAddress () << " does not exist");
2843 NS_LOG_ERROR (errno_);
2844 m_errno = errno_;
2845 return -1;
2846 }
2847 NS_LOG_LOGIC ("Route exists");
2848 m_endPoint->SetLocalAddress (route->GetSource ());
2849 return 0;
2850}
2851
2852int
2854{
2855 NS_LOG_FUNCTION (this);
2857 NS_ASSERT (ipv6);
2858 if (!ipv6->GetRoutingProtocol ())
2859 {
2860 NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
2861 }
2862 // Create a dummy packet, then ask the routing function for the best output
2863 // interface's address
2864 Ipv6Header header;
2866 Socket::SocketErrno errno_;
2867 Ptr<Ipv6Route> route;
2869 route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
2870 if (!route)
2871 {
2872 NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
2873 NS_LOG_ERROR (errno_);
2874 m_errno = errno_;
2875 return -1;
2876 }
2877 NS_LOG_LOGIC ("Route exists");
2878 m_endPoint6->SetLocalAddress (route->GetSource ());
2879 return 0;
2880}
2881
2882/* This function is called only if a SYN received in LISTEN state. After
2883 TcpSocketBase cloned, allocate a new end point to handle the incoming
2884 connection and send a SYN+ACK to complete the handshake. */
2885void
2887 const Address& fromAddress, const Address& toAddress)
2888{
2889 NS_LOG_FUNCTION (this << p << h << fromAddress << toAddress);
2890 // Get port and address from peer (connecting host)
2891 if (InetSocketAddress::IsMatchingType (toAddress))
2892 {
2893 m_endPoint = m_tcp->Allocate (GetBoundNetDevice (),
2894 InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
2895 InetSocketAddress::ConvertFrom (toAddress).GetPort (),
2896 InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
2897 InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
2898 m_endPoint6 = nullptr;
2899 }
2900 else if (Inet6SocketAddress::IsMatchingType (toAddress))
2901 {
2902 m_endPoint6 = m_tcp->Allocate6 (GetBoundNetDevice (),
2903 Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
2904 Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
2905 Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
2906 Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
2907 m_endPoint = nullptr;
2908 }
2909 m_tcp->AddSocket (this);
2910
2911 // Change the cloned socket from LISTEN state to SYN_RCVD
2912 NS_LOG_DEBUG ("LISTEN -> SYN_RCVD");
2913 m_state = SYN_RCVD;
2916 SetupCallback ();
2917 // Set the sequence number and send SYN+ACK
2918 m_tcb->m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1));
2919
2920 /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if sender has sent an ECN SYN
2921 * packet and the traffic is ECN Capable
2922 */
2925 {
2929 }
2930 else
2931 {
2934 }
2935}
2936
2937void
2939{ // Wrapper to protected function NotifyConnectionSucceeded() so that it can
2940 // be called as a scheduled event
2942 // The if-block below was moved from ProcessSynSent() to here because we need
2943 // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
2944 // reflect the behaviour in the real world.
2945 if (GetTxAvailable () > 0)
2946 {
2948 }
2949}
2950
2951void
2953{
2954 /*
2955 * Add tags for each socket option.
2956 * Note that currently the socket adds both IPv4 tag and IPv6 tag
2957 * if both options are set. Once the packet got to layer three, only
2958 * the corresponding tags will be read.
2959 */
2960 if (GetIpTos ())
2961 {
2962 SocketIpTosTag ipTosTag;
2964 {
2966 }
2967 else
2968 {
2969 // Set the last received ipTos
2970 ipTosTag.SetTos (GetIpTos ());
2971 }
2972 p->AddPacketTag (ipTosTag);
2973 }
2974 else
2975 {
2977 {
2978 SocketIpTosTag ipTosTag;
2980 p->AddPacketTag (ipTosTag);
2981 }
2982 }
2983
2984 if (IsManualIpv6Tclass ())
2985 {
2986 SocketIpv6TclassTag ipTclassTag;
2988 {
2990 }
2991 else
2992 {
2993 // Set the last received ipTos
2994 ipTclassTag.SetTclass (GetIpv6Tclass ());
2995 }
2996 p->AddPacketTag (ipTclassTag);
2997 }
2998 else
2999 {
3001 {
3002 SocketIpv6TclassTag ipTclassTag;
3004 p->AddPacketTag (ipTclassTag);
3005 }
3006 }
3007
3008 if (IsManualIpTtl ())
3009 {
3010 SocketIpTtlTag ipTtlTag;
3011 ipTtlTag.SetTtl (GetIpTtl ());
3012 p->AddPacketTag (ipTtlTag);
3013 }
3014
3015 if (IsManualIpv6HopLimit ())
3016 {
3017 SocketIpv6HopLimitTag ipHopLimitTag;
3018 ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ());
3019 p->AddPacketTag (ipHopLimitTag);
3020 }
3021
3022 uint8_t priority = GetPriority ();
3023 if (priority)
3024 {
3025 SocketPriorityTag priorityTag;
3026 priorityTag.SetPriority (priority);
3027 p->ReplacePacketTag (priorityTag);
3028 }
3029}
3030
3031/* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
3032 TCP header, and send to TcpL4Protocol */
3035{
3036 NS_LOG_FUNCTION (this << seq << maxSize << withAck);
3037
3038 bool isStartOfTransmission = BytesInFlight () == 0U;
3039 TcpTxItem *outItem = m_txBuffer->CopyFromSequence (maxSize, seq);
3040
3041 m_rateOps->SkbSent(outItem, isStartOfTransmission);
3042
3043 bool isRetransmission = outItem->IsRetrans ();
3044 Ptr<Packet> p = outItem->GetPacketCopy ();
3045 uint32_t sz = p->GetSize (); // Size of packet
3046 uint8_t flags = withAck ? TcpHeader::ACK : 0;
3047 uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz));
3048
3049 // TCP sender should not send data out of the window advertised by the
3050 // peer when it is not retransmission.
3051 NS_ASSERT (isRetransmission || ((m_highRxAckMark + SequenceNumber32 (m_rWnd)) >= (seq + SequenceNumber32 (maxSize))));
3052
3053 if (IsPacingEnabled ())
3054 {
3055 NS_LOG_INFO ("Pacing is enabled");
3056 if (m_pacingTimer.IsExpired ())
3057 {
3058 NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_pacingRate);
3059 NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3060 m_pacingTimer.Schedule (m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3061 }
3062 else
3063 {
3064 NS_LOG_INFO ("Timer is already in running state");
3065 }
3066 }
3067 else
3068 {
3069 NS_LOG_INFO ("Pacing is disabled");
3070 }
3071
3072 if (withAck)
3073 {
3075 m_delAckCount = 0;
3076 }
3077
3078 if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && m_ecnEchoSeq.Get() > m_ecnCWRSeq.Get () && !isRetransmission)
3079 {
3082 m_ecnCWRSeq = seq;
3083 flags |= TcpHeader::CWR;
3084 NS_LOG_INFO ("CWR flags set");
3085 }
3086
3087 AddSocketTags (p);
3088
3089 if (m_closeOnEmpty && (remainingData == 0))
3090 {
3091 flags |= TcpHeader::FIN;
3092 if (m_state == ESTABLISHED)
3093 { // On active close: I am the first one to send FIN
3094 NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1");
3096 }
3097 else if (m_state == CLOSE_WAIT)
3098 { // On passive close: Peer sent me FIN already
3099 NS_LOG_DEBUG ("CLOSE_WAIT -> LAST_ACK");
3100 m_state = LAST_ACK;
3101 }
3102 }
3103 TcpHeader header;
3104 header.SetFlags (flags);
3105 header.SetSequenceNumber (seq);
3106 header.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
3107 if (m_endPoint)
3108 {
3111 }
3112 else
3113 {
3116 }
3118 AddOptions (header);
3119
3120 if (m_retxEvent.IsExpired ())
3121 {
3122 // Schedules retransmit timeout. m_rto should be already doubled.
3123
3124 NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
3125 Simulator::Now ().GetSeconds () << " to expire at time " <<
3126 (Simulator::Now () + m_rto.Get ()).GetSeconds () );
3128 }
3129
3130 m_txTrace (p, header, this);
3131
3132 if (m_endPoint)
3133 {
3134 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
3136 NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
3137 remainingData << " via TcpL4Protocol to " << m_endPoint->GetPeerAddress () <<
3138 ". Header " << header);
3139 }
3140 else
3141 {
3142 m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
3144 NS_LOG_DEBUG ("Send segment of size " << sz << " with remaining data " <<
3145 remainingData << " via TcpL4Protocol to " << m_endPoint6->GetPeerAddress () <<
3146 ". Header " << header);
3147 }
3148
3149 UpdateRttHistory (seq, sz, isRetransmission);
3150
3151 // Update bytes sent during recovery phase
3153 {
3154 m_recoveryOps->UpdateBytesSent (sz);
3155 }
3156
3157 // Notify the application of the data being sent unless this is a retransmit
3158 if (!isRetransmission)
3159 {
3161 (seq + sz - m_tcb->m_highTxMark.Get ()));
3162 }
3163 // Update highTxMark
3164 m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ());
3165 return sz;
3166}
3167
3168void
3170 bool isRetransmission)
3171{
3172 NS_LOG_FUNCTION (this);
3173
3174 // update the history of sequence numbers used to calculate the RTT
3175 if (isRetransmission == false)
3176 { // This is the next expected one, just log at end
3177 m_history.push_back (RttHistory (seq, sz, Simulator::Now ()));
3178 }
3179 else
3180 { // This is a retransmit, find in list and mark as re-tx
3181 for (std::deque<RttHistory>::iterator i = m_history.begin (); i != m_history.end (); ++i)
3182 {
3183 if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
3184 { // Found it
3185 i->retx = true;
3186 i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
3187 break;
3188 }
3189 }
3190 }
3191}
3192
3193// Note that this function did not implement the PSH flag
3196{
3197 NS_LOG_FUNCTION (this << withAck);
3198 if (m_txBuffer->Size () == 0)
3199 {
3200 return false; // Nothing to send
3201 }
3202 if (m_endPoint == nullptr && m_endPoint6 == nullptr)
3203 {
3204 NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
3205 return false; // Is this the right way to handle this condition?
3206 }
3207
3208 uint32_t nPacketsSent = 0;
3209 uint32_t availableWindow = AvailableWindow ();
3210
3211 // RFC 6675, Section (C)
3212 // If cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more
3213 // segments as follows:
3214 // (NOTE: We check > 0, and do the checks for segmentSize in the following
3215 // else branch to control silly window syndrome and Nagle)
3216 while (availableWindow > 0)
3217 {
3218 if (IsPacingEnabled ())
3219 {
3220 NS_LOG_INFO ("Pacing is enabled");
3221 if (m_pacingTimer.IsRunning ())
3222 {
3223 NS_LOG_INFO ("Skipping Packet due to pacing" << m_pacingTimer.GetDelayLeft ());
3224 break;
3225 }
3226 NS_LOG_INFO ("Timer is not running");
3227 }
3228
3231 {
3232 NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit");
3233 break;
3234 }
3235 // (C.1) The scoreboard MUST be queried via NextSeg () for the
3236 // sequence number range of the next segment to transmit (if
3237 // any), and the given segment sent. If NextSeg () returns
3238 // failure (no data to send), return without sending anything
3239 // (i.e., terminate steps C.1 -- C.5).
3240 SequenceNumber32 next;
3241 SequenceNumber32 nextHigh;
3243 if (!m_txBuffer->NextSeg (&next, &nextHigh, enableRule3))
3244 {
3245 NS_LOG_INFO ("no valid seq to transmit, or no data available");
3246 break;
3247 }
3248 else
3249 {
3250 // It's time to transmit, but before do silly window and Nagle's check
3251 uint32_t availableData = m_txBuffer->SizeFromSequence (next);
3252
3253 // If there's less app data than the full window, ask the app for more
3254 // data before trying to send
3255 if (availableData < availableWindow)
3256 {
3258 }
3259
3260 // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
3261 // but continue if we don't have data
3262 if (availableWindow < m_tcb->m_segmentSize && availableData > availableWindow)
3263 {
3264 NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
3265 break; // No more
3266 }
3267 // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
3268 // in the buffer and the amount of data to send is less than one segment
3269 if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_segmentSize)
3270 {
3271 NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next <<
3272 ", SFS: " << m_txBuffer->SizeFromSequence (next) <<
3273 ". Wait to send.");
3274 break;
3275 }
3276
3277 uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize);
3278 // NextSeg () may have further constrained the segment size
3279 uint32_t maxSizeToSend = static_cast<uint32_t> (nextHigh - next);
3280 s = std::min (s, maxSizeToSend);
3281
3282 // (C.2) If any of the data octets sent in (C.1) are below HighData,
3283 // HighRxt MUST be set to the highest sequence number of the
3284 // retransmitted segment unless NextSeg () rule (4) was
3285 // invoked for this retransmission.
3286 // (C.3) If any of the data octets sent in (C.1) are above HighData,
3287 // HighData must be updated to reflect the transmission of
3288 // previously unsent data.
3289 //
3290 // These steps are done in m_txBuffer with the tags.
3291 if (m_tcb->m_nextTxSequence != next)
3292 {
3293 m_tcb->m_nextTxSequence = next;
3294 }
3295 if (m_tcb->m_bytesInFlight.Get () == 0)
3296 {
3298 }
3299 uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck);
3300
3301 NS_LOG_LOGIC (" rxwin " << m_rWnd <<
3302 " segsize " << m_tcb->m_segmentSize <<
3303 " highestRxAck " << m_txBuffer->HeadSequence () <<
3304 " pd->Size " << m_txBuffer->Size () <<
3305 " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence));
3306
3307 NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd <<
3308 " total unAck: " << UnAckDataCount () <<
3309 " sent seq " << m_tcb->m_nextTxSequence <<
3310 " size " << sz);
3311 m_tcb->m_nextTxSequence += sz;
3312 ++nPacketsSent;
3313 if (IsPacingEnabled ())
3314 {
3315 NS_LOG_INFO ("Pacing is enabled");
3316 if (m_pacingTimer.IsExpired ())
3317 {
3318 NS_LOG_DEBUG ("Current Pacing Rate " << m_tcb->m_pacingRate);
3319 NS_LOG_DEBUG ("Timer is in expired state, activate it " << m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3320 m_pacingTimer.Schedule (m_tcb->m_pacingRate.Get ().CalculateBytesTxTime (sz));
3321 break;
3322 }
3323 }
3324 }
3325
3326 // (C.4) The estimate of the amount of data outstanding in the
3327 // network must be updated by incrementing pipe by the number
3328 // of octets transmitted in (C.1).
3329 //
3330 // Done in BytesInFlight, inside AvailableWindow.
3331 availableWindow = AvailableWindow ();
3332
3333 // (C.5) If cwnd - pipe >= 1 SMSS, return to (C.1)
3334 // loop again!
3335 }
3336
3337 if (nPacketsSent > 0)
3338 {
3339 if (!m_sackEnabled)
3340 {
3341 if (!m_limitedTx)
3342 {
3343 // We can't transmit in CA_DISORDER without limitedTx active
3345 }
3346 }
3347
3348 NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments");
3349 }
3350 else
3351 {
3352 NS_LOG_DEBUG ("SendPendingData no segments sent");
3353 }
3354 return nPacketsSent;
3355}
3356
3359{
3360 return m_tcb->m_highTxMark - m_txBuffer->HeadSequence ();
3361}
3362
3365{
3366 uint32_t bytesInFlight = m_txBuffer->BytesInFlight ();
3367 // Ugly, but we are not modifying the state; m_bytesInFlight is used
3368 // only for tracing purpose.
3369 m_tcb->m_bytesInFlight = bytesInFlight;
3370
3371 NS_LOG_DEBUG ("Returning calculated bytesInFlight: " << bytesInFlight);
3372 return bytesInFlight;
3373}
3374
3377{
3378 return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
3379}
3380
3383{
3384 uint32_t win = Window (); // Number of bytes allowed to be outstanding
3385 uint32_t inflight = BytesInFlight (); // Number of outstanding bytes
3386 return (inflight > win) ? 0 : win - inflight;
3387}
3388
3389uint16_t
3391{
3392 NS_LOG_FUNCTION (this << scale);
3393 uint32_t w;
3394
3395 // We don't want to advertise 0 after a FIN is received. So, we just use
3396 // the previous value of the advWnd.
3397 if (m_tcb->m_rxBuffer->GotFin ())
3398 {
3399 w = m_advWnd;
3400 }
3401 else
3402 {
3403 NS_ASSERT_MSG (m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence () >= 0,
3404 "Unexpected sequence number values");
3405 w = static_cast<uint32_t> (m_tcb->m_rxBuffer->MaxRxSequence () - m_tcb->m_rxBuffer->NextRxSequence ());
3406 }
3407
3408 // Ugly, but we are not modifying the state, that variable
3409 // is used only for tracing purpose.
3410 if (w != m_advWnd)
3411 {
3412 const_cast<TcpSocketBase*> (this)->m_advWnd = w;
3413 }
3414 if (scale)
3415 {
3416 w >>= m_rcvWindShift;
3417 }
3418 if (w > m_maxWinSize)
3419 {
3420 w = m_maxWinSize;
3421 NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
3422 }
3423 NS_LOG_LOGIC ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w));
3424 return static_cast<uint16_t> (w);
3425}
3426
3427// Receipt of new packet, put into Rx buffer
3428void
3430{
3431 NS_LOG_FUNCTION (this << tcpHeader);
3432 NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () <<
3433 " pkt size=" << p->GetSize () );
3434
3435 // Put into Rx buffer
3436 SequenceNumber32 expectedSeq = m_tcb->m_rxBuffer->NextRxSequence ();
3437 if (!m_tcb->m_rxBuffer->Add (p, tcpHeader))
3438 { // Insert failed: No data or RX buffer full
3440 {
3442 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3444 }
3445 else
3446 {
3448 }
3449 return;
3450 }
3451 // Notify app to receive if necessary
3452 if (expectedSeq < m_tcb->m_rxBuffer->NextRxSequence ())
3453 { // NextRxSeq advanced, we have something to send to the app
3454 if (!m_shutdownRecv)
3455 {
3456 NotifyDataRecv ();
3457 }
3458 // Handle exceptions
3459 if (m_closeNotified)
3460 {
3461 NS_LOG_WARN ("Why TCP " << this << " got data after close notification?");
3462 }
3463 // If we received FIN before and now completed all "holes" in rx buffer,
3464 // invoke peer close procedure
3465 if (m_tcb->m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0)
3466 {
3467 DoPeerClose ();
3468 return;
3469 }
3470 }
3471 // Now send a new ACK packet acknowledging all received and delivered data
3472 if (m_tcb->m_rxBuffer->Size () > m_tcb->m_rxBuffer->Available () || m_tcb->m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ())
3473 { // A gap exists in the buffer, or we filled a gap: Always ACK
3476 {
3478 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3480 }
3481 else
3482 {
3484 }
3485 }
3486 else
3487 { // In-sequence packet: ACK if delayed ack count allows
3489 {
3491 m_delAckCount = 0;
3494 {
3495 NS_LOG_DEBUG("Congestion algo " << m_congestionControl->GetName ());
3497 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3499 }
3500 else
3501 {
3503 }
3504 }
3505 else if (!m_delAckEvent.IsExpired ())
3506 {
3508 }
3509 else if (m_delAckEvent.IsExpired ())
3510 {
3514 NS_LOG_LOGIC (this << " scheduled delayed ACK at " <<
3516 }
3517 }
3518}
3519
3520void
3522{
3523 SequenceNumber32 ackSeq = tcpHeader.GetAckNumber ();
3524 Time m = Time (0.0);
3525
3526 // An ack has been received, calculate rtt and log this measurement
3527 // Note we use a linear search (O(n)) for this since for the common
3528 // case the ack'ed packet will be at the head of the list
3529 if (!m_history.empty ())
3530 {
3531 RttHistory& h = m_history.front ();
3532 if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
3533 { // Ok to use this sample
3534 if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
3535 {
3537 ts = DynamicCast<const TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
3538 m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
3539 if (m.IsZero ())
3540 {
3541 NS_LOG_LOGIC ("TcpSocketBase::EstimateRtt - RTT calculated from TcpOption::TS is zero, approximating to 1us.");
3542 m = MicroSeconds (1);
3543 }
3544 }
3545 else
3546 {
3547 m = Simulator::Now () - h.time; // Elapsed time
3548 }
3549 }
3550 }
3551
3552 // Now delete all ack history with seq <= ack
3553 while (!m_history.empty ())
3554 {
3555 RttHistory& h = m_history.front ();
3556 if ((h.seq + SequenceNumber32 (h.count)) > ackSeq)
3557 {
3558 break; // Done removing
3559 }
3560 m_history.pop_front (); // Remove
3561 }
3562
3563 if (!m.IsZero ())
3564 {
3565 m_rtt->Measurement (m); // Log the measurement
3566 // RFC 6298, clause 2.4
3567 m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3568 m_tcb->m_lastRtt = m_rtt->GetEstimate ();
3570 NS_LOG_INFO (this << m_tcb->m_lastRtt << m_tcb->m_minRtt);
3571 }
3572}
3573
3574// Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
3575// when the three-way handshake completed. This cancels retransmission timer
3576// and advances Tx window
3577void
3578TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO)
3579{
3580 NS_LOG_FUNCTION (this << ack);
3581
3582 // Reset the data retransmission count. We got a new ACK!
3584
3585 if (m_state != SYN_RCVD && resetRTO)
3586 { // Set RTO unless the ACK is received in SYN_RCVD state
3587 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3588 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3590 // On receiving a "New" ack we restart retransmission timer .. RFC 6298
3591 // RFC 6298, clause 2.4
3592 m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4), m_minRto);
3593
3594 NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
3595 Simulator::Now ().GetSeconds () << " to expire at time " <<
3596 (Simulator::Now () + m_rto.Get ()).GetSeconds ());
3598 }
3599
3600 // Note the highest ACK and tell app to send more
3601 NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack <<
3602 " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed
3603
3604 if (GetTxAvailable () > 0)
3605 {
3607 }
3608 if (ack > m_tcb->m_nextTxSequence)
3609 {
3610 m_tcb->m_nextTxSequence = ack; // If advanced
3611 }
3612 if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
3613 { // No retransmit timer if no data to retransmit
3614 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
3615 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
3617 }
3618}
3619
3620// Retransmit timeout
3621void
3623{
3624 NS_LOG_FUNCTION (this);
3625 NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
3626 // If erroneous timeout in closed/timed-wait state, just return
3627 if (m_state == CLOSED || m_state == TIME_WAIT)
3628 {
3629 return;
3630 }
3631
3632 if (m_state == SYN_SENT)
3633 {
3634 NS_ASSERT (m_synCount > 0);
3636 {
3638 }
3639 else
3640 {
3642 }
3643 return;
3644 }
3645
3646 // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3647 if (m_txBuffer->Size () == 0)
3648 {
3649 if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3650 { // Must have lost FIN, re-send
3652 }
3653 return;
3654 }
3655
3656 NS_LOG_DEBUG ("Checking if Connection is Established");
3657 // If all data are received (non-closing socket and nothing to send), just return
3658 if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMark && m_txBuffer->Size () == 0)
3659 {
3660 NS_LOG_DEBUG ("Already Sent full data" << m_txBuffer->HeadSequence () << " " << m_tcb->m_highTxMark);
3661 return;
3662 }
3663
3664 if (m_dataRetrCount == 0)
3665 {
3666 NS_LOG_INFO ("No more data retries available. Dropping connection");
3669 return;
3670 }
3671 else
3672 {
3674 }
3675
3676 uint32_t inFlightBeforeRto = BytesInFlight ();
3677 bool resetSack = !m_sackEnabled; // Reset SACK information if SACK is not enabled.
3678 // The information in the TcpTxBuffer is guessed, in this case.
3679
3680 // Reset dupAckCount
3681 m_dupAckCount = 0;
3682 if (!m_sackEnabled)
3683 {
3684 m_txBuffer->ResetRenoSack ();
3685 }
3686
3687 // From RFC 6675, Section 5.1
3688 // [RFC2018] suggests that a TCP sender SHOULD expunge the SACK
3689 // information gathered from a receiver upon a retransmission timeout
3690 // (RTO) "since the timeout might indicate that the data receiver has
3691 // reneged." Additionally, a TCP sender MUST "ignore prior SACK
3692 // information in determining which data to retransmit."
3693 // It has been suggested that, as long as robust tests for
3694 // reneging are present, an implementation can retain and use SACK
3695 // information across a timeout event [Errata1610].
3696 // The head of the sent list will not be marked as sacked, therefore
3697 // will be retransmitted, if the receiver renegotiate the SACK blocks
3698 // that we received.
3699 m_txBuffer->SetSentListLost (resetSack);
3700
3701 // From RFC 6675, Section 5.1
3702 // If an RTO occurs during loss recovery as specified in this document,
3703 // RecoveryPoint MUST be set to HighData. Further, the new value of
3704 // RecoveryPoint MUST be preserved and the loss recovery algorithm
3705 // outlined in this document MUST be terminated.
3707 m_recoverActive = true;
3708
3709 // RFC 6298, clause 2.5, double the timer
3710 Time doubledRto = m_rto + m_rto;
3711 m_rto = Min (doubledRto, Time::FromDouble (60, Time::S));
3712
3713 // Empty RTT history
3714 m_history.clear ();
3715
3716 // Please don't reset highTxMark, it is used for retransmission detection
3717
3718 // When a TCP sender detects segment loss using the retransmission timer
3719 // and the given segment has not yet been resent by way of the
3720 // retransmission timer, decrease ssThresh
3721 if (m_tcb->m_congState != TcpSocketState::CA_LOSS || !m_txBuffer->IsHeadRetransmitted ())
3722 {
3723 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, inFlightBeforeRto);
3724 }
3725
3726 // Cwnd set to 1 MSS
3728 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS);
3732
3734
3735 NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
3736 m_tcb->m_ssThresh << ", restart from seqnum " <<
3737 m_txBuffer->HeadSequence () << " doubled rto to " <<
3738 m_rto.Get ().GetSeconds () << " s");
3739
3740 NS_ASSERT_MSG (BytesInFlight () == 0, "There are some bytes in flight after an RTO: " <<
3741 BytesInFlight ());
3742
3744
3746 "In flight (" << BytesInFlight () <<
3747 ") there is more than one segment (" << m_tcb->m_segmentSize << ")");
3748}
3749
3750void
3752{
3753 m_delAckCount = 0;
3756 {
3759 }
3760 else
3761 {
3763 }
3764}
3765
3766void
3768{
3769 NS_LOG_FUNCTION (this);
3770
3772 if (m_state == LAST_ACK)
3773 {
3774 if (m_dataRetrCount == 0)
3775 {
3776 NS_LOG_INFO ("LAST-ACK: No more data retries available. Dropping connection");
3779 return;
3780 }
3783 NS_LOG_LOGIC ("TcpSocketBase " << this << " rescheduling LATO1");
3784 Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation () * 4);
3786 }
3787}
3788
3789// Send 1-byte data to probe for the window size at the receiver when
3790// the local knowledge tells that the receiver has zero window size
3791// C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
3792void
3794{
3795 NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ());
3796 m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s
3797 Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence)->GetPacketCopy ();
3798 m_txBuffer->ResetLastSegmentSent ();
3799 TcpHeader tcpHeader;
3801 tcpHeader.SetAckNumber (m_tcb->m_rxBuffer->NextRxSequence ());
3802 tcpHeader.SetWindowSize (AdvertisedWindowSize ());
3803 if (m_endPoint != nullptr)
3804 {
3805 tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
3807 }
3808 else
3809 {
3810 tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
3812 }
3813 AddOptions (tcpHeader);
3814 //Send a packet tag for setting ECT bits in IP header
3816 {
3817 SocketIpTosTag ipTosTag;
3819 p->AddPacketTag (ipTosTag);
3820
3821 SocketIpv6TclassTag ipTclassTag;
3822 ipTclassTag.SetTclass (MarkEcnCodePoint (0, m_tcb->m_ectCodePoint));
3823 p->AddPacketTag (ipTclassTag);
3824 }
3825 m_txTrace (p, tcpHeader, this);
3826
3827 if (m_endPoint != nullptr)
3828 {
3829 m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
3831 }
3832 else
3833 {
3834 m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
3836 }
3837
3838 NS_LOG_LOGIC ("Schedule persist timeout at time "
3839 << Simulator::Now ().GetSeconds () << " to expire at time "
3840 << (Simulator::Now () + m_persistTimeout).GetSeconds ());
3842}
3843
3844void
3846{
3847 NS_LOG_FUNCTION (this);
3848 bool res;
3849 SequenceNumber32 seq;
3850 SequenceNumber32 seqHigh;
3851 uint32_t maxSizeToSend;
3852
3853 // Find the first segment marked as lost and not retransmitted. With Reno,
3854 // that should be the head
3855 res = m_txBuffer->NextSeg (&seq, &seqHigh, false);
3856 if (!res)
3857 {
3858 // We have already retransmitted the head. However, we still received
3859 // three dupacks, or the RTO expired, but no data to transmit.
3860 // Therefore, re-send again the head.
3861 seq = m_txBuffer->HeadSequence ();
3862 maxSizeToSend = m_tcb->m_segmentSize;
3863 }
3864 else
3865 {
3866 // NextSeg() may constrain the segment size when res is true
3867 maxSizeToSend = static_cast<uint32_t> (seqHigh - seq);
3868 }
3869 NS_ASSERT (m_sackEnabled || seq == m_txBuffer->HeadSequence ());
3870
3871 NS_LOG_INFO ("Retransmitting " << seq);
3872 // Update the trace and retransmit the segment
3873 m_tcb->m_nextTxSequence = seq;
3874 uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, maxSizeToSend, true);
3875
3876 NS_ASSERT (sz > 0);
3877}
3878
3879void
3881{
3889}
3890
3891/* Move TCP to Time_Wait state and schedule a transition to Closed state */
3892void
3894{
3895 NS_LOG_DEBUG (TcpStateName[m_state] << " -> TIME_WAIT");
3897 CancelAllTimers ();
3898 if (!m_closeNotified)
3899 {
3900 // Technically the connection is not fully closed, but we notify now
3901 // because an implementation (real socket) would behave as if closed.
3902 // Notify normal close when entering TIME_WAIT or leaving LAST_ACK.
3904 m_closeNotified = true;
3905 }
3906 // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
3907 // according to RFC793, p.28
3910}
3911
3912/* Below are the attribute get/set functions */
3913
3914void
3916{
3917 NS_LOG_FUNCTION (this << size);
3918 m_txBuffer->SetMaxBufferSize (size);
3919}
3920
3923{
3924 return m_txBuffer->MaxBufferSize ();
3925}
3926
3927void
3929{
3930 NS_LOG_FUNCTION (this << size);
3931 uint32_t oldSize = GetRcvBufSize ();
3932
3933 m_tcb->m_rxBuffer->SetMaxBufferSize (size);
3934
3935 /* The size has (manually) increased. Actively inform the other end to prevent
3936 * stale zero-window states.
3937 */
3938 if (oldSize < size && m_connected)
3939 {
3941 {
3943 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3945 }
3946 else
3947 {
3949 }
3950 }
3951}
3952
3955{
3956 return m_tcb->m_rxBuffer->MaxBufferSize ();
3957}
3958
3959void
3961{
3962 NS_LOG_FUNCTION (this << size);
3963 m_tcb->m_segmentSize = size;
3964 m_txBuffer->SetSegmentSize (size);
3965
3966 NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
3967}
3968
3971{
3972 return m_tcb->m_segmentSize;
3973}
3974
3975void
3977{
3978 NS_LOG_FUNCTION (this << timeout);
3980}
3981
3982Time
3984{
3985 return m_cnTimeout;
3986}
3987
3988void
3990{
3991 NS_LOG_FUNCTION (this << count);
3992 m_synRetries = count;
3993}
3994
3997{
3998 return m_synRetries;
3999}
4000
4001void
4003{
4004 NS_LOG_FUNCTION (this << retries);
4005 m_dataRetries = retries;
4006}
4007
4010{
4011 NS_LOG_FUNCTION (this);
4012 return m_dataRetries;
4013}
4014
4015void
4017{
4018 NS_LOG_FUNCTION (this << timeout);
4020}
4021
4022Time
4024{
4025 return m_delAckTimeout;
4026}
4027
4028void
4030{
4031 NS_LOG_FUNCTION (this << count);
4032 m_delAckMaxCount = count;
4033}
4034
4037{
4038 return m_delAckMaxCount;
4039}
4040
4041void
4043{
4044 NS_LOG_FUNCTION (this << noDelay);
4045 m_noDelay = noDelay;
4046}
4047
4048bool
4050{
4051 return m_noDelay;
4052}
4053
4054void
4056{
4057 NS_LOG_FUNCTION (this << timeout);
4059}
4060
4061Time
4063{
4064 return m_persistTimeout;
4065}
4066
4067bool
4069{
4070 // Broadcast is not implemented. Return true only if allowBroadcast==false
4071 return (!allowBroadcast);
4072}
4073
4074bool
4076{
4077 return false;
4078}
4079
4080void
4082{
4083 NS_LOG_FUNCTION (this << header);
4084
4086 {
4087 AddOptionTimestamp (header);
4088 }
4089}
4090
4091void
4093{
4094 NS_LOG_FUNCTION (this << option);
4095
4096 Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale> (option);
4097
4098 // In naming, we do the contrary of RFC 1323. The received scaling factor
4099 // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
4100 m_sndWindShift = ws->GetScale ();
4101
4102 if (m_sndWindShift > 14)
4103 {
4104 NS_LOG_WARN ("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
4105 m_sndWindShift = 14;
4106 }
4107
4108 NS_LOG_INFO (m_node->GetId () << " Received a scale factor of " <<
4109 static_cast<int> (m_sndWindShift));
4110}
4111
4112uint8_t
4114{
4115 NS_LOG_FUNCTION (this);
4116 uint32_t maxSpace = m_tcb->m_rxBuffer->MaxBufferSize ();
4117 uint8_t scale = 0;
4118
4119 while (maxSpace > m_maxWinSize)
4120 {
4121 maxSpace = maxSpace >> 1;
4122 ++scale;
4123 }
4124
4125 if (scale > 14)
4126 {
4127 NS_LOG_WARN ("Possible error; scale exceeds 14: " << scale);
4128 scale = 14;
4129 }
4130
4131 NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " <<
4132 static_cast<int> (scale) << " for buffer size " << m_tcb->m_rxBuffer->MaxBufferSize ());
4133 return scale;
4134}
4135
4136void
4138{
4139 NS_LOG_FUNCTION (this << header);
4140 NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
4141
4142 Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale> ();
4143
4144 // In naming, we do the contrary of RFC 1323. The sended scaling factor
4145 // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
4146
4148 option->SetScale (m_rcvWindShift);
4149
4150 header.AppendOption (option);
4151
4152 NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " <<
4153 static_cast<int> (m_rcvWindShift));
4154}
4155
4158{
4159 NS_LOG_FUNCTION (this << option);
4160
4161 Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option);
4162 return m_txBuffer->Update (s->GetSackList (), MakeCallback (&TcpRateOps::SkbDelivered, m_rateOps));
4163}
4164
4165void
4167{
4168 NS_LOG_FUNCTION (this << option);
4169
4170 Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted> (option);
4171
4172 NS_ASSERT (m_sackEnabled == true);
4173 NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s);
4174}
4175
4176void
4178{
4179 NS_LOG_FUNCTION (this << header);
4180 NS_ASSERT (header.GetFlags () & TcpHeader::SYN);
4181
4182 Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> ();
4183 header.AppendOption (option);
4184 NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED");
4185}
4186
4187void
4189{
4190 NS_LOG_FUNCTION (this << header);
4191
4192 // Calculate the number of SACK blocks allowed in this packet
4193 uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength ();
4194 uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8;
4195
4196 TcpOptionSack::SackList sackList = m_tcb->m_rxBuffer->GetSackList ();
4197 if (allowedSackBlocks == 0 || sackList.empty ())
4198 {
4199 NS_LOG_LOGIC ("No space available or sack list empty, not adding sack blocks");
4200 return;
4201 }
4202
4203 // Append the allowed number of SACK blocks
4204 Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> ();
4205 TcpOptionSack::SackList::iterator i;
4206 for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i)
4207 {
4208 option->AddSackBlock (*i);
4209 allowedSackBlocks--;
4210 }
4211
4212 header.AppendOption (option);
4213 NS_LOG_INFO (m_node->GetId () << " Add option SACK " << *option);
4214}
4215
4216void
4218 const SequenceNumber32 &seq)
4219{
4220 NS_LOG_FUNCTION (this << option);
4221
4222 Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
4223
4224 // This is valid only when no overflow occurs. It happens
4225 // when a connection last longer than 50 days.
4226 if (m_tcb->m_rcvTimestampValue > ts->GetTimestamp ())
4227 {
4228 // Do not save a smaller timestamp (probably there is reordering)
4229 return;
4230 }
4231
4232 m_tcb->m_rcvTimestampValue = ts->GetTimestamp ();
4233 m_tcb->m_rcvTimestampEchoReply = ts->GetEcho ();
4234
4235 if (seq == m_tcb->m_rxBuffer->NextRxSequence () && seq <= m_highTxAck)
4236 {
4237 m_timestampToEcho = ts->GetTimestamp ();
4238 }
4239
4240 NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
4241 m_timestampToEcho << " and Echo=" << ts->GetEcho ());
4242}
4243
4244void
4246{
4247 NS_LOG_FUNCTION (this << header);
4248
4249 Ptr<TcpOptionTS> option = CreateObject<TcpOptionTS> ();
4250
4251 option->SetTimestamp (TcpOptionTS::NowToTsValue ());
4252 option->SetEcho (m_timestampToEcho);
4253
4254 header.AppendOption (option);
4255 NS_LOG_INFO (m_node->GetId () << " Add option TS, ts=" <<
4256 option->GetTimestamp () << " echo=" << m_timestampToEcho);
4257}
4258
4260{
4261 NS_LOG_FUNCTION (this << header);
4262 // If the connection is not established, the window size is always
4263 // updated
4264 uint32_t receivedWindow = header.GetWindowSize ();
4265 receivedWindow <<= m_sndWindShift;
4266 NS_LOG_INFO ("Received (scaled) window is " << receivedWindow << " bytes");
4267 if (m_state < ESTABLISHED)
4268 {
4269 m_rWnd = receivedWindow;
4270 NS_LOG_LOGIC ("State less than ESTABLISHED; updating rWnd to " << m_rWnd);
4271 return;
4272 }
4273
4274 // Test for conditions that allow updating of the window
4275 // 1) segment contains new data (advancing the right edge of the receive
4276 // buffer),
4277 // 2) segment does not contain new data but the segment acks new data
4278 // (highest sequence number acked advances), or
4279 // 3) the advertised window is larger than the current send window
4280 bool update = false;
4281 if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd)
4282 {
4283 // right edge of the send window is increased (window update)
4284 update = true;
4285 }
4286 if (header.GetAckNumber () > m_highRxAckMark)
4287 {
4288 m_highRxAckMark = header.GetAckNumber ();
4289 update = true;
4290 }
4291 if (header.GetSequenceNumber () > m_highRxMark)
4292 {
4293 m_highRxMark = header.GetSequenceNumber ();
4294 update = true;
4295 }
4296 if (update == true)
4297 {
4298 m_rWnd = receivedWindow;
4299 NS_LOG_LOGIC ("updating rWnd to " << m_rWnd);
4300 }
4301}
4302
4303void
4305{
4306 NS_LOG_FUNCTION (this << minRto);
4307 m_minRto = minRto;
4308}
4309
4310Time
4312{
4313 return m_minRto;
4314}
4315
4316void
4318{
4319 NS_LOG_FUNCTION (this << clockGranularity);
4320 m_clockGranularity = clockGranularity;
4321}
4322
4323Time
4325{
4326 return m_clockGranularity;
4327}
4328
4331{
4332 return m_txBuffer;
4333}
4334
4337{
4338 return m_tcb->m_rxBuffer;
4339}
4340
4341void
4343{
4344 m_retxThresh = retxThresh;
4345 m_txBuffer->SetDupAckThresh (retxThresh);
4346}
4347
4348void
4350{
4351 m_pacingRateTrace (oldValue, newValue);
4352}
4353
4354void
4356{
4357 m_cWndTrace (oldValue, newValue);
4358}
4359
4360void
4362{
4363 m_cWndInflTrace (oldValue, newValue);
4364}
4365
4366void
4368{
4369 m_ssThTrace (oldValue, newValue);
4370}
4371
4372void
4375{
4376 m_congStateTrace (oldValue, newValue);
4377}
4378
4379 void
4382{
4383 m_ecnStateTrace (oldValue, newValue);
4384}
4385
4386void
4388 SequenceNumber32 newValue)
4389
4390{
4391 m_nextTxSequenceTrace (oldValue, newValue);
4392}
4393
4394void
4396{
4397 m_highTxMarkTrace (oldValue, newValue);
4398}
4399
4400void
4402{
4403 m_bytesInFlightTrace (oldValue, newValue);
4404}
4405
4406void
4408{
4409 m_lastRttTrace (oldValue, newValue);
4410}
4411
4412void
4414{
4415 NS_LOG_FUNCTION (this << algo);
4416 m_congestionControl = algo;
4417 m_congestionControl->Init (m_tcb);
4418}
4419
4420void
4422{
4423 NS_LOG_FUNCTION (this << recovery);
4424 m_recoveryOps = recovery;
4425}
4426
4429{
4430 return CopyObject<TcpSocketBase> (this);
4431}
4432
4435{
4436 if (a > b)
4437 {
4438 return a-b;
4439 }
4440
4441 return 0;
4442}
4443
4444void
4446{
4447 NS_LOG_FUNCTION (this);
4448 NS_LOG_INFO ("Performing Pacing");
4450}
4451
4452bool
4454{
4455 if (!m_tcb->m_pacing)
4456 {
4457 return false;
4458 }
4459 else
4460 {
4462 {
4463 return true;
4464 }
4465 SequenceNumber32 highTxMark = m_tcb->m_highTxMark; // cast traced value
4466 if (highTxMark.GetValue () > (GetInitialCwnd () * m_tcb->m_segmentSize))
4467 {
4468 return true;
4469 }
4470 }
4471 return false;
4472}
4473
4474void
4476{
4477 NS_LOG_FUNCTION (this << m_tcb);
4478
4479 // According to Linux, set base pacing rate to (cwnd * mss) / srtt
4480 //
4481 // In (early) slow start, multiply base by the slow start factor.
4482 // In late slow start and congestion avoidance, multiply base by
4483 // the congestion avoidance factor.
4484 // Comment from Linux code regarding early/late slow start:
4485 // Normal Slow Start condition is (tp->snd_cwnd < tp->snd_ssthresh)
4486 // If snd_cwnd >= (tp->snd_ssthresh / 2), we are approaching
4487 // end of slow start and should slow down.
4488
4489 // Similar to Linux, do not update pacing rate here if the
4490 // congestion control implements TcpCongestionOps::CongControl ()
4491 if (m_congestionControl->HasCongControl () || !m_tcb->m_pacing) return;
4492
4493 double factor;
4494 if (m_tcb->m_cWnd < m_tcb->m_ssThresh/2)
4495 {
4496 NS_LOG_DEBUG ("Pacing according to slow start factor; " << m_tcb->