A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-socket-base.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007 Georgia Tech Research Corporation
3 * Copyright (c) 2010 Adrian Sai-wah Tam
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
19 */
20
21#define NS_LOG_APPEND_CONTEXT \
22 if (m_node) \
23 { \
24 std::clog << " [node " << m_node->GetId() << "] "; \
25 }
26
27#include "tcp-socket-base.h"
28
29#include "ipv4-end-point.h"
30#include "ipv4-route.h"
32#include "ipv4.h"
33#include "ipv6-end-point.h"
34#include "ipv6-l3-protocol.h"
35#include "ipv6-route.h"
37#include "rtt-estimator.h"
38#include "tcp-congestion-ops.h"
39#include "tcp-header.h"
40#include "tcp-l4-protocol.h"
42#include "tcp-option-sack.h"
43#include "tcp-option-ts.h"
44#include "tcp-option-winscale.h"
45#include "tcp-rate-ops.h"
46#include "tcp-recovery-ops.h"
47#include "tcp-rx-buffer.h"
48#include "tcp-tx-buffer.h"
49
50#include "ns3/abort.h"
51#include "ns3/data-rate.h"
52#include "ns3/double.h"
53#include "ns3/inet-socket-address.h"
54#include "ns3/inet6-socket-address.h"
55#include "ns3/log.h"
56#include "ns3/node.h"
57#include "ns3/object.h"
58#include "ns3/packet.h"
59#include "ns3/pointer.h"
60#include "ns3/simulation-singleton.h"
61#include "ns3/simulator.h"
62#include "ns3/trace-source-accessor.h"
63#include "ns3/uinteger.h"
64
65#include <algorithm>
66#include <math.h>
67
68namespace ns3
69{
70
71NS_LOG_COMPONENT_DEFINE("TcpSocketBase");
72
73NS_OBJECT_ENSURE_REGISTERED(TcpSocketBase);
74
75TypeId
77{
78 static TypeId tid =
79 TypeId("ns3::TcpSocketBase")
81 .SetGroupName("Internet")
82 .AddConstructor<TcpSocketBase>()
83 // .AddAttribute ("TcpState", "State in TCP state machine",
84 // TypeId::ATTR_GET,
85 // EnumValue (CLOSED),
86 // MakeEnumAccessor (&TcpSocketBase::m_state),
87 // MakeEnumChecker (CLOSED, "Closed"))
88 .AddAttribute("MaxSegLifetime",
89 "Maximum segment lifetime in seconds, use for TIME_WAIT state transition "
90 "to CLOSED state",
91 DoubleValue(120), /* RFC793 says MSL=2 minutes*/
93 MakeDoubleChecker<double>(0))
94 .AddAttribute("MaxWindowSize",
95 "Max size of advertised window",
96 UintegerValue(65535),
98 MakeUintegerChecker<uint16_t>())
99 .AddAttribute("IcmpCallback",
100 "Callback invoked whenever an icmp error is received on this socket.",
104 .AddAttribute("IcmpCallback6",
105 "Callback invoked whenever an icmpv6 error is received on this socket.",
109 .AddAttribute("WindowScaling",
110 "Enable or disable Window Scaling option",
111 BooleanValue(true),
114 .AddAttribute("Sack",
115 "Enable or disable Sack option",
116 BooleanValue(true),
119 .AddAttribute("Timestamp",
120 "Enable or disable Timestamp option",
121 BooleanValue(true),
124 .AddAttribute(
125 "MinRto",
126 "Minimum retransmit timeout value",
127 TimeValue(Seconds(1.0)), // RFC 6298 says min RTO=1 sec, but Linux uses 200ms.
128 // See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
131 .AddAttribute(
132 "ClockGranularity",
133 "Clock Granularity used in RTO calculations",
134 TimeValue(MilliSeconds(1)), // RFC6298 suggest to use fine clock granularity
138 .AddAttribute("TxBuffer",
139 "TCP Tx buffer",
140 PointerValue(),
142 MakePointerChecker<TcpTxBuffer>())
143 .AddAttribute("RxBuffer",
144 "TCP Rx buffer",
145 PointerValue(),
147 MakePointerChecker<TcpRxBuffer>())
148 .AddAttribute("CongestionOps",
149 "Pointer to TcpCongestionOps object",
150 PointerValue(),
152 MakePointerChecker<TcpCongestionOps>())
153 .AddAttribute(
154 "ReTxThreshold",
155 "Threshold for fast retransmit",
156 UintegerValue(3),
158 MakeUintegerChecker<uint32_t>())
159 .AddAttribute("LimitedTransmit",
160 "Enable limited transmit",
161 BooleanValue(true),
164 .AddAttribute("UseEcn",
165 "Parameter to set ECN functionality",
169 "Off",
171 "On",
173 "AcceptOnly"))
174 .AddTraceSource("RTO",
175 "Retransmission timeout",
177 "ns3::TracedValueCallback::Time")
178 .AddTraceSource("RTT",
179 "Last RTT sample",
181 "ns3::TracedValueCallback::Time")
182 .AddTraceSource("NextTxSequence",
183 "Next sequence number to send (SND.NXT)",
185 "ns3::SequenceNumber32TracedValueCallback")
186 .AddTraceSource("HighestSequence",
187 "Highest sequence number ever sent in socket's life time",
189 "ns3::TracedValueCallback::SequenceNumber32")
190 .AddTraceSource("State",
191 "TCP state",
193 "ns3::TcpStatesTracedValueCallback")
194 .AddTraceSource("CongState",
195 "TCP Congestion machine state",
197 "ns3::TcpSocketState::TcpCongStatesTracedValueCallback")
198 .AddTraceSource("EcnState",
199 "Trace ECN state change of socket",
201 "ns3::TcpSocketState::EcnStatesTracedValueCallback")
202 .AddTraceSource("AdvWND",
203 "Advertised Window Size",
205 "ns3::TracedValueCallback::Uint32")
206 .AddTraceSource("RWND",
207 "Remote side's flow control window",
209 "ns3::TracedValueCallback::Uint32")
210 .AddTraceSource("BytesInFlight",
211 "Socket estimation of bytes in flight",
213 "ns3::TracedValueCallback::Uint32")
214 .AddTraceSource("HighestRxSequence",
215 "Highest sequence number received from peer",
217 "ns3::TracedValueCallback::SequenceNumber32")
218 .AddTraceSource("HighestRxAck",
219 "Highest ack received from peer",
221 "ns3::TracedValueCallback::SequenceNumber32")
222 .AddTraceSource("PacingRate",
223 "The current TCP pacing rate",
225 "ns3::TracedValueCallback::DataRate")
226 .AddTraceSource("CongestionWindow",
227 "The TCP connection's congestion window",
229 "ns3::TracedValueCallback::Uint32")
230 .AddTraceSource("CongestionWindowInflated",
231 "The TCP connection's congestion window inflates as in older RFC",
233 "ns3::TracedValueCallback::Uint32")
234 .AddTraceSource("SlowStartThreshold",
235 "TCP slow start threshold (bytes)",
237 "ns3::TracedValueCallback::Uint32")
238 .AddTraceSource("Tx",
239 "Send tcp packet to IP protocol",
241 "ns3::TcpSocketBase::TcpTxRxTracedCallback")
242 .AddTraceSource("Rx",
243 "Receive tcp packet from IP protocol",
245 "ns3::TcpSocketBase::TcpTxRxTracedCallback")
246 .AddTraceSource("EcnEchoSeq",
247 "Sequence of last received ECN Echo",
249 "ns3::SequenceNumber32TracedValueCallback")
250 .AddTraceSource("EcnCeSeq",
251 "Sequence of last received CE",
253 "ns3::SequenceNumber32TracedValueCallback")
254 .AddTraceSource("EcnCwrSeq",
255 "Sequence of last received CWR",
257 "ns3::SequenceNumber32TracedValueCallback");
258 return tid;
259}
260
261TypeId
263{
265}
266
268 : TcpSocket()
269{
270 NS_LOG_FUNCTION(this);
271 m_txBuffer = CreateObject<TcpTxBuffer>();
272 m_txBuffer->SetRWndCallback(MakeCallback(&TcpSocketBase::GetRWnd, this));
273 m_tcb = CreateObject<TcpSocketState>();
274 m_rateOps = CreateObject<TcpRateLinux>();
275
276 m_tcb->m_rxBuffer = CreateObject<TcpRxBuffer>();
277
280
282
283 bool ok;
284
286 "PacingRate",
288 NS_ASSERT(ok == true);
289
290 ok = m_tcb->TraceConnectWithoutContext("CongestionWindow",
292 NS_ASSERT(ok == true);
293
294 ok = m_tcb->TraceConnectWithoutContext("CongestionWindowInflated",
296 NS_ASSERT(ok == true);
297
298 ok = m_tcb->TraceConnectWithoutContext("SlowStartThreshold",
300 NS_ASSERT(ok == true);
301
302 ok = m_tcb->TraceConnectWithoutContext("CongState",
304 NS_ASSERT(ok == true);
305
306 ok = m_tcb->TraceConnectWithoutContext("EcnState",
308 NS_ASSERT(ok == true);
309
310 ok =
311 m_tcb->TraceConnectWithoutContext("NextTxSequence",
313 NS_ASSERT(ok == true);
314
315 ok = m_tcb->TraceConnectWithoutContext("HighestSequence",
317 NS_ASSERT(ok == true);
318
319 ok = m_tcb->TraceConnectWithoutContext("BytesInFlight",
321 NS_ASSERT(ok == true);
322
324 NS_ASSERT(ok == true);
325}
326
328 : TcpSocket(sock),
329 // copy object::m_tid and socket::callbacks
330 m_dupAckCount(sock.m_dupAckCount),
331 m_delAckCount(0),
332 m_delAckMaxCount(sock.m_delAckMaxCount),
333 m_noDelay(sock.m_noDelay),
334 m_synCount(sock.m_synCount),
335 m_synRetries(sock.m_synRetries),
336 m_dataRetrCount(sock.m_dataRetrCount),
337 m_dataRetries(sock.m_dataRetries),
338 m_rto(sock.m_rto),
339 m_minRto(sock.m_minRto),
340 m_clockGranularity(sock.m_clockGranularity),
341 m_delAckTimeout(sock.m_delAckTimeout),
342 m_persistTimeout(sock.m_persistTimeout),
343 m_cnTimeout(sock.m_cnTimeout),
344 m_endPoint(nullptr),
345 m_endPoint6(nullptr),
346 m_node(sock.m_node),
347 m_tcp(sock.m_tcp),
348 m_state(sock.m_state),
349 m_errno(sock.m_errno),
350 m_closeNotified(sock.m_closeNotified),
351 m_closeOnEmpty(sock.m_closeOnEmpty),
352 m_shutdownSend(sock.m_shutdownSend),
353 m_shutdownRecv(sock.m_shutdownRecv),
354 m_connected(sock.m_connected),
355 m_msl(sock.m_msl),
356 m_maxWinSize(sock.m_maxWinSize),
357 m_bytesAckedNotProcessed(sock.m_bytesAckedNotProcessed),
358 m_rWnd(sock.m_rWnd),
359 m_highRxMark(sock.m_highRxMark),
360 m_highRxAckMark(sock.m_highRxAckMark),
361 m_sackEnabled(sock.m_sackEnabled),
362 m_winScalingEnabled(sock.m_winScalingEnabled),
363 m_rcvWindShift(sock.m_rcvWindShift),
364 m_sndWindShift(sock.m_sndWindShift),
365 m_timestampEnabled(sock.m_timestampEnabled),
366 m_timestampToEcho(sock.m_timestampToEcho),
367 m_recover(sock.m_recover),
368 m_recoverActive(sock.m_recoverActive),
369 m_retxThresh(sock.m_retxThresh),
370 m_limitedTx(sock.m_limitedTx),
371 m_isFirstPartialAck(sock.m_isFirstPartialAck),
372 m_txTrace(sock.m_txTrace),
373 m_rxTrace(sock.m_rxTrace),
374 m_pacingTimer(Timer::CANCEL_ON_DESTROY),
375 m_ecnEchoSeq(sock.m_ecnEchoSeq),
376 m_ecnCESeq(sock.m_ecnCESeq),
377 m_ecnCWRSeq(sock.m_ecnCWRSeq)
378{
379 NS_LOG_FUNCTION(this);
380 NS_LOG_LOGIC("Invoked the copy constructor");
381 // Copy the rtt estimator if it is set
382 if (sock.m_rtt)
383 {
384 m_rtt = sock.m_rtt->Copy();
385 }
386 // Reset all callbacks to null
387 Callback<void, Ptr<Socket>> vPS = MakeNullCallback<void, Ptr<Socket>>();
388 Callback<void, Ptr<Socket>, const Address&> vPSA =
389 MakeNullCallback<void, Ptr<Socket>, const Address&>();
390 Callback<void, Ptr<Socket>, uint32_t> vPSUI = MakeNullCallback<void, Ptr<Socket>, uint32_t>();
391 SetConnectCallback(vPS, vPS);
392 SetDataSentCallback(vPSUI);
393 SetSendCallback(vPSUI);
394 SetRecvCallback(vPS);
396 m_txBuffer->SetRWndCallback(MakeCallback(&TcpSocketBase::GetRWnd, this));
397 m_tcb = CopyObject(sock.m_tcb);
399
402
403 if (sock.m_congestionControl)
404 {
407 }
408
409 if (sock.m_recoveryOps)
410 {
411 m_recoveryOps = sock.m_recoveryOps->Fork();
412 }
413
414 m_rateOps = CreateObject<TcpRateLinux>();
416 {
418 }
419
420 bool ok;
421
423 "PacingRate",
425
426 ok = m_tcb->TraceConnectWithoutContext("CongestionWindow",
428 NS_ASSERT(ok == true);
429
430 ok = m_tcb->TraceConnectWithoutContext("CongestionWindowInflated",
432 NS_ASSERT(ok == true);
433
434 ok = m_tcb->TraceConnectWithoutContext("SlowStartThreshold",
436 NS_ASSERT(ok == true);
437
438 ok = m_tcb->TraceConnectWithoutContext("CongState",
440 NS_ASSERT(ok == true);
441
442 ok = m_tcb->TraceConnectWithoutContext("EcnState",
444 NS_ASSERT(ok == true);
445
446 ok =
447 m_tcb->TraceConnectWithoutContext("NextTxSequence",
449 NS_ASSERT(ok == true);
450
451 ok = m_tcb->TraceConnectWithoutContext("HighestSequence",
453 NS_ASSERT(ok == true);
454
455 ok = m_tcb->TraceConnectWithoutContext("BytesInFlight",
457 NS_ASSERT(ok == true);
458
460 NS_ASSERT(ok == true);
461}
462
464{
465 NS_LOG_FUNCTION(this);
466 m_node = nullptr;
467 if (m_endPoint != nullptr)
468 {
470 /*
471 * Upon Bind, an Ipv4Endpoint is allocated and set to m_endPoint, and
472 * DestroyCallback is set to TcpSocketBase::Destroy. If we called
473 * m_tcp->DeAllocate, it will destroy its Ipv4EndpointDemux::DeAllocate,
474 * which in turn destroys my m_endPoint, and in turn invokes
475 * TcpSocketBase::Destroy to nullify m_node, m_endPoint, and m_tcp.
476 */
477 NS_ASSERT(m_endPoint != nullptr);
478 m_tcp->DeAllocate(m_endPoint);
479 NS_ASSERT(m_endPoint == nullptr);
480 }
481 if (m_endPoint6 != nullptr)
482 {
484 NS_ASSERT(m_endPoint6 != nullptr);
485 m_tcp->DeAllocate(m_endPoint6);
486 NS_ASSERT(m_endPoint6 == nullptr);
487 }
488 m_tcp = nullptr;
490}
491
492/* Associate a node with this TCP socket */
493void
495{
496 m_node = node;
497}
498
499/* Associate the L4 protocol (e.g. mux/demux) with this socket */
500void
502{
503 m_tcp = tcp;
504}
505
506/* Set an RTT estimator with this socket */
507void
509{
510 m_rtt = rtt;
511}
512
513/* Inherit from Socket class: Returns error code */
516{
517 return m_errno;
518}
519
520/* Inherit from Socket class: Returns socket type, NS3_SOCK_STREAM */
523{
524 return NS3_SOCK_STREAM;
525}
526
527/* Inherit from Socket class: Returns associated node */
530{
531 return m_node;
532}
533
534/* Inherit from Socket class: Bind socket to an end-point in TcpL4Protocol */
535int
537{
538 NS_LOG_FUNCTION(this);
539 m_endPoint = m_tcp->Allocate();
540 if (nullptr == m_endPoint)
541 {
543 return -1;
544 }
545
546 m_tcp->AddSocket(this);
547
548 return SetupCallback();
549}
550
551int
553{
554 NS_LOG_FUNCTION(this);
555 m_endPoint6 = m_tcp->Allocate6();
556 if (nullptr == m_endPoint6)
557 {
559 return -1;
560 }
561
562 m_tcp->AddSocket(this);
563
564 return SetupCallback();
565}
566
567/* Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol
568 */
569int
571{
572 NS_LOG_FUNCTION(this << address);
574 {
576 Ipv4Address ipv4 = transport.GetIpv4();
577 uint16_t port = transport.GetPort();
578 SetIpTos(transport.GetTos());
579 if (ipv4 == Ipv4Address::GetAny() && port == 0)
580 {
581 m_endPoint = m_tcp->Allocate();
582 }
583 else if (ipv4 == Ipv4Address::GetAny() && port != 0)
584 {
585 m_endPoint = m_tcp->Allocate(GetBoundNetDevice(), port);
586 }
587 else if (ipv4 != Ipv4Address::GetAny() && port == 0)
588 {
589 m_endPoint = m_tcp->Allocate(ipv4);
590 }
591 else if (ipv4 != Ipv4Address::GetAny() && port != 0)
592 {
593 m_endPoint = m_tcp->Allocate(GetBoundNetDevice(), ipv4, port);
594 }
595 if (nullptr == m_endPoint)
596 {
598 return -1;
599 }
600 }
601 else if (Inet6SocketAddress::IsMatchingType(address))
602 {
604 Ipv6Address ipv6 = transport.GetIpv6();
605 uint16_t port = transport.GetPort();
606 if (ipv6 == Ipv6Address::GetAny() && port == 0)
607 {
608 m_endPoint6 = m_tcp->Allocate6();
609 }
610 else if (ipv6 == Ipv6Address::GetAny() && port != 0)
611 {
612 m_endPoint6 = m_tcp->Allocate6(GetBoundNetDevice(), port);
613 }
614 else if (ipv6 != Ipv6Address::GetAny() && port == 0)
615 {
616 m_endPoint6 = m_tcp->Allocate6(ipv6);
617 }
618 else if (ipv6 != Ipv6Address::GetAny() && port != 0)
619 {
620 m_endPoint6 = m_tcp->Allocate6(GetBoundNetDevice(), ipv6, port);
621 }
622 if (nullptr == m_endPoint6)
623 {
625 return -1;
626 }
627 }
628 else
629 {
631 return -1;
632 }
633
634 m_tcp->AddSocket(this);
635
636 NS_LOG_LOGIC("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
637
638 return SetupCallback();
639}
640
641void
643{
645 (m_state == CLOSED) || threshold == m_tcb->m_initialSsThresh,
646 "TcpSocketBase::SetSSThresh() cannot change initial ssThresh after connection started.");
647
648 m_tcb->m_initialSsThresh = threshold;
649}
650
653{
654 return m_tcb->m_initialSsThresh;
655}
656
657void
659{
661 (m_state == CLOSED) || cwnd == m_tcb->m_initialCWnd,
662 "TcpSocketBase::SetInitialCwnd() cannot change initial cwnd after connection started.");
663
664 m_tcb->m_initialCWnd = cwnd;
665}
666
669{
670 return m_tcb->m_initialCWnd;
671}
672
673/* Inherit from Socket class: Initiate connection to a remote address:port */
674int
676{
677 NS_LOG_FUNCTION(this << address);
678
679 // If haven't do so, Bind() this socket first
681 {
682 if (m_endPoint == nullptr)
683 {
684 if (Bind() == -1)
685 {
686 NS_ASSERT(m_endPoint == nullptr);
687 return -1; // Bind() failed
688 }
689 NS_ASSERT(m_endPoint != nullptr);
690 }
692 m_endPoint->SetPeer(transport.GetIpv4(), transport.GetPort());
693 SetIpTos(transport.GetTos());
694 m_endPoint6 = nullptr;
695
696 // Get the appropriate local address and port number from the routing protocol and set up
697 // endpoint
698 if (SetupEndpoint() != 0)
699 {
700 NS_LOG_ERROR("Route to destination does not exist ?!");
701 return -1;
702 }
703 }
704 else if (Inet6SocketAddress::IsMatchingType(address))
705 {
706 // If we are operating on a v4-mapped address, translate the address to
707 // a v4 address and re-call this function
709 Ipv6Address v6Addr = transport.GetIpv6();
710 if (v6Addr.IsIpv4MappedAddress())
711 {
712 Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress();
713 return Connect(InetSocketAddress(v4Addr, transport.GetPort()));
714 }
715
716 if (m_endPoint6 == nullptr)
717 {
718 if (Bind6() == -1)
719 {
720 NS_ASSERT(m_endPoint6 == nullptr);
721 return -1; // Bind() failed
722 }
723 NS_ASSERT(m_endPoint6 != nullptr);
724 }
725 m_endPoint6->SetPeer(v6Addr, transport.GetPort());
726 m_endPoint = nullptr;
727
728 // Get the appropriate local address and port number from the routing protocol and set up
729 // endpoint
730 if (SetupEndpoint6() != 0)
731 {
732 NS_LOG_ERROR("Route to destination does not exist ?!");
733 return -1;
734 }
735 }
736 else
737 {
739 return -1;
740 }
741
742 // Re-initialize parameters in case this socket is being reused after CLOSE
743 m_rtt->Reset();
746
747 // DoConnect() will do state-checking and send a SYN packet
748 return DoConnect();
749}
750
751/* Inherit from Socket class: Listen on the endpoint for an incoming connection */
752int
754{
755 NS_LOG_FUNCTION(this);
756
757 // Linux quits EINVAL if we're not in CLOSED state, so match what they do
758 if (m_state != CLOSED)
759 {
761 return -1;
762 }
763 // In other cases, set the state to LISTEN and done
764 NS_LOG_DEBUG("CLOSED -> LISTEN");
765 m_state = LISTEN;
766 return 0;
767}
768
769/* Inherit from Socket class: Kill this socket and signal the peer (if any) */
770int
772{
773 NS_LOG_FUNCTION(this);
777 if (m_tcb->m_rxBuffer->Size() != 0)
778 {
779 NS_LOG_WARN("Socket " << this << " << unread rx data during close. Sending reset."
780 << "This is probably due to a bad sink application; check its code");
781 SendRST();
782 return 0;
783 }
784
785 if (m_txBuffer->SizeFromSequence(m_tcb->m_nextTxSequence) > 0)
786 { // App close with pending data must wait until all data transmitted
787 if (!m_closeOnEmpty)
788 {
789 m_closeOnEmpty = true;
790 NS_LOG_INFO("Socket " << this << " deferring close, state " << TcpStateName[m_state]);
791 }
792 return 0;
793 }
794 return DoClose();
795}
796
797/* Inherit from Socket class: Signal a termination of send */
798int
800{
801 NS_LOG_FUNCTION(this);
802
803 // this prevents data from being added to the buffer
804 m_shutdownSend = true;
805 m_closeOnEmpty = true;
806 // if buffer is already empty, send a fin now
807 // otherwise fin will go when buffer empties.
808 if (m_txBuffer->Size() == 0)
809 {
811 {
812 NS_LOG_INFO("Empty tx buffer, send fin");
814
815 if (m_state == ESTABLISHED)
816 { // On active close: I am the first one to send FIN
817 NS_LOG_DEBUG("ESTABLISHED -> FIN_WAIT_1");
819 }
820 else
821 { // On passive close: Peer sent me FIN already
822 NS_LOG_DEBUG("CLOSE_WAIT -> LAST_ACK");
824 }
825 }
826 }
827
828 return 0;
829}
830
831/* Inherit from Socket class: Signal a termination of receive */
832int
834{
835 NS_LOG_FUNCTION(this);
836 m_shutdownRecv = true;
837 return 0;
838}
839
840/* Inherit from Socket class: Send a packet. Parameter flags is not used.
841 Packet has no TCP header. Invoked by upper-layer application */
842int
844{
845 NS_LOG_FUNCTION(this << p);
846 NS_ABORT_MSG_IF(flags, "use of flags is not supported in TcpSocketBase::Send()");
848 {
849 // Store the packet into Tx buffer
850 if (!m_txBuffer->Add(p))
851 { // TxBuffer overflow, send failed
853 return -1;
854 }
855 if (m_shutdownSend)
856 {
858 return -1;
859 }
860
864 m_txBuffer->TailSequence(),
866 m_txBuffer->GetLost(),
867 m_txBuffer->GetRetransmitsCount());
868
869 // Submit the data to lower layers
870 NS_LOG_LOGIC("txBufSize=" << m_txBuffer->Size() << " state " << TcpStateName[m_state]);
871 if ((m_state == ESTABLISHED || m_state == CLOSE_WAIT) && AvailableWindow() > 0)
872 { // Try to send the data out: Add a little step to allow the application
873 // to fill the buffer
875 {
878 this,
880 }
881 }
882 return p->GetSize();
883 }
884 else
885 { // Connection not established yet
887 return -1; // Send failure
888 }
889}
890
891/* Inherit from Socket class: In TcpSocketBase, it is same as Send() call */
892int
893TcpSocketBase::SendTo(Ptr<Packet> p, uint32_t flags, const Address& /* address */)
894{
895 return Send(p, flags); // SendTo() and Send() are the same
896}
897
898/* Inherit from Socket class: Return data to upper-layer application. Parameter flags
899 is not used. Data is returned as a packet of size no larger than maxSize */
902{
903 NS_LOG_FUNCTION(this);
904 NS_ABORT_MSG_IF(flags, "use of flags is not supported in TcpSocketBase::Recv()");
905 if (m_tcb->m_rxBuffer->Size() == 0 && m_state == CLOSE_WAIT)
906 {
907 return Create<Packet>(); // Send EOF on connection close
908 }
909 Ptr<Packet> outPacket = m_tcb->m_rxBuffer->Extract(maxSize);
910 return outPacket;
911}
912
913/* Inherit from Socket class: Recv and return the remote's address */
916{
917 NS_LOG_FUNCTION(this << maxSize << flags);
918 Ptr<Packet> packet = Recv(maxSize, flags);
919 // Null packet means no data to read, and an empty packet indicates EOF
920 if (packet && packet->GetSize() != 0)
921 {
922 if (m_endPoint != nullptr)
923 {
924 fromAddress =
926 }
927 else if (m_endPoint6 != nullptr)
928 {
929 fromAddress =
931 }
932 else
933 {
934 fromAddress = InetSocketAddress(Ipv4Address::GetZero(), 0);
935 }
936 }
937 return packet;
938}
939
940/* Inherit from Socket class: Get the max number of bytes an app can send */
943{
944 NS_LOG_FUNCTION(this);
945 return m_txBuffer->Available();
946}
947
948/* Inherit from Socket class: Get the max number of bytes an app can read */
951{
952 NS_LOG_FUNCTION(this);
953 return m_tcb->m_rxBuffer->Available();
954}
955
956/* Inherit from Socket class: Return local address:port */
957int
959{
960 NS_LOG_FUNCTION(this);
961 if (m_endPoint != nullptr)
962 {
964 }
965 else if (m_endPoint6 != nullptr)
966 {
968 }
969 else
970 { // It is possible to call this method on a socket without a name
971 // in which case, behavior is unspecified
972 // Should this return an InetSocketAddress or an Inet6SocketAddress?
974 }
975 return 0;
976}
977
978int
980{
981 NS_LOG_FUNCTION(this << address);
982
983 if (!m_endPoint && !m_endPoint6)
984 {
986 return -1;
987 }
988
989 if (m_endPoint)
990 {
992 }
993 else if (m_endPoint6)
994 {
996 }
997 else
998 {
999 NS_ASSERT(false);
1000 }
1001
1002 return 0;
1003}
1004
1005/* Inherit from Socket class: Bind this socket to the specified NetDevice */
1006void
1008{
1009 NS_LOG_FUNCTION(netdevice);
1010 Socket::BindToNetDevice(netdevice); // Includes sanity check
1011 if (m_endPoint != nullptr)
1012 {
1013 m_endPoint->BindToNetDevice(netdevice);
1014 }
1015
1016 if (m_endPoint6 != nullptr)
1017 {
1018 m_endPoint6->BindToNetDevice(netdevice);
1019 }
1020}
1021
1022/* Clean up after Bind. Set up callback functions in the end-point. */
1023int
1025{
1026 NS_LOG_FUNCTION(this);
1027
1028 if (m_endPoint == nullptr && m_endPoint6 == nullptr)
1029 {
1030 return -1;
1031 }
1032 if (m_endPoint != nullptr)
1033 {
1040 }
1041 if (m_endPoint6 != nullptr)
1042 {
1049 }
1050
1051 return 0;
1052}
1053
1054/* Perform the real connection tasks: Send SYN if allowed, RST if invalid */
1055int
1057{
1058 NS_LOG_FUNCTION(this);
1059
1060 // A new connection is allowed only if this socket does not have a connection
1061 if (m_state == CLOSED || m_state == LISTEN || m_state == SYN_SENT || m_state == LAST_ACK ||
1063 { // send a SYN packet and change state into SYN_SENT
1064 // send a SYN packet with ECE and CWR flags set if sender is ECN capable
1066 {
1068 }
1069 else
1070 {
1072 }
1073 NS_LOG_DEBUG(TcpStateName[m_state] << " -> SYN_SENT");
1074 m_state = SYN_SENT;
1075 m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; // because sender is not yet aware about
1076 // receiver's ECN capability
1077 }
1078 else if (m_state != TIME_WAIT)
1079 { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, an connection
1080 // exists. We send RST, tear down everything, and close this socket.
1081 SendRST();
1083 }
1084 return 0;
1085}
1086
1087/* Do the action to close the socket. Usually send a packet with appropriate
1088 flags depended on the current m_state. */
1089int
1091{
1092 NS_LOG_FUNCTION(this);
1093 switch (m_state)
1094 {
1095 case SYN_RCVD:
1096 case ESTABLISHED:
1097 // send FIN to close the peer
1099 NS_LOG_DEBUG("ESTABLISHED -> FIN_WAIT_1");
1101 break;
1102 case CLOSE_WAIT:
1103 // send FIN+ACK to close the peer
1105 NS_LOG_DEBUG("CLOSE_WAIT -> LAST_ACK");
1106 m_state = LAST_ACK;
1107 break;
1108 case SYN_SENT:
1109 case CLOSING:
1110 // Send RST if application closes in SYN_SENT and CLOSING
1111 SendRST();
1113 break;
1114 case LISTEN:
1115 // In this state, move to CLOSED and tear down the end point
1117 break;
1118 case LAST_ACK:
1119 case CLOSED:
1120 case FIN_WAIT_1:
1121 case FIN_WAIT_2:
1122 case TIME_WAIT:
1123 default: /* mute compiler */
1124 // Do nothing in these five states
1125 break;
1126 }
1127 return 0;
1128}
1129
1130/* Peacefully close the socket by notifying the upper layer and deallocate end point */
1131void
1133{
1134 NS_LOG_FUNCTION(this);
1135
1136 if (!m_closeNotified)
1137 {
1139 m_closeNotified = true;
1140 }
1142 {
1144 }
1145 NS_LOG_DEBUG(TcpStateName[m_state] << " -> CLOSED");
1146 m_state = CLOSED;
1148}
1149
1150/* Tell if a sequence number range is out side the range that my rx buffer can
1151 accept */
1152bool
1154{
1155 if (m_state == LISTEN || m_state == SYN_SENT || m_state == SYN_RCVD)
1156 { // Rx buffer in these states are not initialized.
1157 return false;
1158 }
1159 if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT)
1160 { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
1161 // sequence number must equals to m_rxBuffer->NextRxSequence ()
1162 return (m_tcb->m_rxBuffer->NextRxSequence() != head);
1163 }
1164
1165 // In all other cases, check if the sequence number is in range
1166 return (tail < m_tcb->m_rxBuffer->NextRxSequence() ||
1167 m_tcb->m_rxBuffer->MaxRxSequence() <= head);
1168}
1169
1170/* Function called by the L3 protocol when it received a packet to pass on to
1171 the TCP. This function is registered as the "RxCallback" function in
1172 SetupCallback(), which invoked by Bind(), and CompleteFork() */
1173void
1175 Ipv4Header header,
1176 uint16_t port,
1177 Ptr<Ipv4Interface> incomingInterface)
1178{
1179 NS_LOG_LOGIC("Socket " << this << " forward up " << m_endPoint->GetPeerAddress() << ":"
1180 << m_endPoint->GetPeerPort() << " to " << m_endPoint->GetLocalAddress()
1181 << ":" << m_endPoint->GetLocalPort());
1182
1183 Address fromAddress = InetSocketAddress(header.GetSource(), port);
1185
1186 TcpHeader tcpHeader;
1187 uint32_t bytesRemoved = packet->PeekHeader(tcpHeader);
1188
1189 if (!IsValidTcpSegment(tcpHeader.GetSequenceNumber(),
1190 bytesRemoved,
1191 packet->GetSize() - bytesRemoved))
1192 {
1193 return;
1194 }
1195
1196 if (header.GetEcn() == Ipv4Header::ECN_CE && m_ecnCESeq < tcpHeader.GetSequenceNumber())
1197 {
1198 NS_LOG_INFO("Received CE flag is valid");
1200 m_ecnCESeq = tcpHeader.GetSequenceNumber();
1203 }
1204 else if (header.GetEcn() != Ipv4Header::ECN_NotECT &&
1206 {
1208 }
1209
1210 DoForwardUp(packet, fromAddress, toAddress);
1211}
1212
1213void
1215 Ipv6Header header,
1216 uint16_t port,
1217 Ptr<Ipv6Interface> incomingInterface)
1218{
1219 NS_LOG_LOGIC("Socket " << this << " forward up " << m_endPoint6->GetPeerAddress() << ":"
1221 << ":" << m_endPoint6->GetLocalPort());
1222
1223 Address fromAddress = Inet6SocketAddress(header.GetSource(), port);
1225
1226 TcpHeader tcpHeader;
1227 uint32_t bytesRemoved = packet->PeekHeader(tcpHeader);
1228
1229 if (!IsValidTcpSegment(tcpHeader.GetSequenceNumber(),
1230 bytesRemoved,
1231 packet->GetSize() - bytesRemoved))
1232 {
1233 return;
1234 }
1235
1236 if (header.GetEcn() == Ipv6Header::ECN_CE && m_ecnCESeq < tcpHeader.GetSequenceNumber())
1237 {
1238 NS_LOG_INFO("Received CE flag is valid");
1240 m_ecnCESeq = tcpHeader.GetSequenceNumber();
1243 }
1244 else if (header.GetEcn() != Ipv6Header::ECN_NotECT)
1245 {
1247 }
1248
1249 DoForwardUp(packet, fromAddress, toAddress);
1250}
1251
1252void
1254 uint8_t icmpTtl,
1255 uint8_t icmpType,
1256 uint8_t icmpCode,
1257 uint32_t icmpInfo)
1258{
1259 NS_LOG_FUNCTION(this << icmpSource << static_cast<uint32_t>(icmpTtl)
1260 << static_cast<uint32_t>(icmpType) << static_cast<uint32_t>(icmpCode)
1261 << icmpInfo);
1262 if (!m_icmpCallback.IsNull())
1263 {
1264 m_icmpCallback(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1265 }
1266}
1267
1268void
1270 uint8_t icmpTtl,
1271 uint8_t icmpType,
1272 uint8_t icmpCode,
1273 uint32_t icmpInfo)
1274{
1275 NS_LOG_FUNCTION(this << icmpSource << static_cast<uint32_t>(icmpTtl)
1276 << static_cast<uint32_t>(icmpType) << static_cast<uint32_t>(icmpCode)
1277 << icmpInfo);
1278 if (!m_icmpCallback6.IsNull())
1279 {
1280 m_icmpCallback6(icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1281 }
1282}
1283
1284bool
1286 const uint32_t tcpHeaderSize,
1287 const uint32_t tcpPayloadSize)
1288{
1289 if (tcpHeaderSize == 0 || tcpHeaderSize > 60)
1290 {
1291 NS_LOG_ERROR("Bytes removed: " << tcpHeaderSize << " invalid");
1292 return false; // Discard invalid packet
1293 }
1294 else if (tcpPayloadSize > 0 && OutOfRange(seq, seq + tcpPayloadSize))
1295 {
1296 // Discard fully out of range data packets
1297 NS_LOG_WARN("At state " << TcpStateName[m_state] << " received packet of seq [" << seq
1298 << ":" << seq + tcpPayloadSize << ") out of range ["
1299 << m_tcb->m_rxBuffer->NextRxSequence() << ":"
1300 << m_tcb->m_rxBuffer->MaxRxSequence() << ")");
1301 // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
1303 return false;
1304 }
1305 return true;
1306}
1307
1308void
1309TcpSocketBase::DoForwardUp(Ptr<Packet> packet, const Address& fromAddress, const Address& toAddress)
1310{
1311 // in case the packet still has a priority tag attached, remove it
1312 SocketPriorityTag priorityTag;
1313 packet->RemovePacketTag(priorityTag);
1314
1315 // Peel off TCP header
1316 TcpHeader tcpHeader;
1317 packet->RemoveHeader(tcpHeader);
1318 SequenceNumber32 seq = tcpHeader.GetSequenceNumber();
1319
1320 if (m_state == ESTABLISHED && !(tcpHeader.GetFlags() & TcpHeader::RST))
1321 {
1322 // Check if the sender has responded to ECN echo by reducing the Congestion Window
1323 if (tcpHeader.GetFlags() & TcpHeader::CWR)
1324 {
1325 // Check if a packet with CE bit set is received. If there is no CE bit set, then change
1326 // the state to ECN_IDLE to stop sending ECN Echo messages. If there is CE bit set, the
1327 // packet should continue sending ECN Echo messages
1328 //
1330 {
1333 }
1334 }
1335 }
1336
1337 m_rxTrace(packet, tcpHeader, this);
1338
1339 if (tcpHeader.GetFlags() & TcpHeader::SYN)
1340 {
1341 /* The window field in a segment where the SYN bit is set (i.e., a <SYN>
1342 * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be
1343 * saved anyway..
1344 */
1345 m_rWnd = tcpHeader.GetWindowSize();
1346
1348 {
1350 }
1351 else
1352 {
1353 m_winScalingEnabled = false;
1354 }
1355
1357 {
1359 }
1360 else
1361 {
1362 m_sackEnabled = false;
1363 m_txBuffer->SetSackEnabled(false);
1364 }
1365
1366 // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end
1367 if (tcpHeader.HasOption(TcpOption::TS) && m_timestampEnabled)
1368 {
1370 tcpHeader.GetSequenceNumber());
1371 }
1372 else
1373 {
1374 m_timestampEnabled = false;
1375 }
1376
1377 // Initialize cWnd and ssThresh
1381
1382 if (tcpHeader.GetFlags() & TcpHeader::ACK)
1383 {
1384 EstimateRtt(tcpHeader);
1385 m_highRxAckMark = tcpHeader.GetAckNumber();
1386 }
1387 }
1388 else if (tcpHeader.GetFlags() & TcpHeader::ACK)
1389 {
1390 NS_ASSERT(!(tcpHeader.GetFlags() & TcpHeader::SYN));
1392 {
1393 if (!tcpHeader.HasOption(TcpOption::TS))
1394 {
1395 // Ignoring segment without TS, RFC 7323
1396 NS_LOG_LOGIC("At state " << TcpStateName[m_state] << " received packet of seq ["
1397 << seq << ":" << seq + packet->GetSize()
1398 << ") without TS option. Silently discard it");
1399 return;
1400 }
1401 else
1402 {
1404 tcpHeader.GetSequenceNumber());
1405 }
1406 }
1407
1408 EstimateRtt(tcpHeader);
1409 UpdateWindowSize(tcpHeader);
1410 }
1411
1412 if (m_rWnd.Get() == 0 && m_persistEvent.IsExpired())
1413 { // Zero window: Enter persist state to send 1 byte to probe
1414 NS_LOG_LOGIC(this << " Enter zerowindow persist state");
1416 this << " Cancelled ReTxTimeout event which was set to expire at "
1417 << (Simulator::Now() + Simulator::GetDelayLeft(m_retxEvent)).GetSeconds());
1419 NS_LOG_LOGIC("Schedule persist timeout at time "
1420 << Simulator::Now().GetSeconds() << " to expire at time "
1421 << (Simulator::Now() + m_persistTimeout).GetSeconds());
1425 }
1426
1427 // TCP state machine code in different process functions
1428 // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
1429 switch (m_state)
1430 {
1431 case ESTABLISHED:
1432 ProcessEstablished(packet, tcpHeader);
1433 break;
1434 case LISTEN:
1435 ProcessListen(packet, tcpHeader, fromAddress, toAddress);
1436 break;
1437 case TIME_WAIT:
1438 // Do nothing
1439 break;
1440 case CLOSED:
1441 // Send RST if the incoming packet is not a RST
1442 if ((tcpHeader.GetFlags() & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
1443 { // Since m_endPoint is not configured yet, we cannot use SendRST here
1444 TcpHeader h;
1445 Ptr<Packet> p = Create<Packet>();
1448 h.SetAckNumber(m_tcb->m_rxBuffer->NextRxSequence());
1449 h.SetSourcePort(tcpHeader.GetDestinationPort());
1450 h.SetDestinationPort(tcpHeader.GetSourcePort());
1452 AddOptions(h);
1453 m_txTrace(p, h, this);
1454 m_tcp->SendPacket(p, h, toAddress, fromAddress, m_boundnetdevice);
1455 }
1456 break;
1457 case SYN_SENT:
1458 ProcessSynSent(packet, tcpHeader);
1459 break;
1460 case SYN_RCVD:
1461 ProcessSynRcvd(packet, tcpHeader, fromAddress, toAddress);
1462 break;
1463 case FIN_WAIT_1:
1464 case FIN_WAIT_2:
1465 case CLOSE_WAIT:
1466 ProcessWait(packet, tcpHeader);
1467 break;
1468 case CLOSING:
1469 ProcessClosing(packet, tcpHeader);
1470 break;
1471 case LAST_ACK:
1472 ProcessLastAck(packet, tcpHeader);
1473 break;
1474 default: // mute compiler
1475 break;
1476 }
1477
1478 if (m_rWnd.Get() != 0 && m_persistEvent.IsRunning())
1479 { // persist probes end, the other end has increased the window
1481 NS_LOG_LOGIC(this << " Leaving zerowindow persist state");
1483
1485 }
1486}
1487
1488/* Received a packet upon ESTABLISHED state. This function is mimicking the
1489 role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
1490void
1492{
1493 NS_LOG_FUNCTION(this << tcpHeader);
1494
1495 // Extract the flags. PSH, URG, CWR and ECE are disregarded.
1496 uint8_t tcpflags =
1498
1499 // Different flags are different events
1500 if (tcpflags == TcpHeader::ACK)
1501 {
1502 if (tcpHeader.GetAckNumber() < m_txBuffer->HeadSequence())
1503 {
1504 // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be ignored.
1505 // Pag. 72 RFC 793
1506 NS_LOG_WARN("Ignored ack of " << tcpHeader.GetAckNumber()
1507 << " SND.UNA = " << m_txBuffer->HeadSequence());
1508
1509 // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation]
1510 }
1511 else if (tcpHeader.GetAckNumber() > m_tcb->m_highTxMark)
1512 {
1513 // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then
1514 // send an ACK, drop the segment, and return.
1515 // Pag. 72 RFC 793
1516 NS_LOG_WARN("Ignored ack of " << tcpHeader.GetAckNumber()
1517 << " HighTxMark = " << m_tcb->m_highTxMark);
1518
1519 // Receiver sets ECE flags when it receives a packet with CE bit on or sender hasn’t
1520 // responded to ECN echo sent by receiver
1523 {
1526 << " -> ECN_SENDING_ECE");
1528 }
1529 else
1530 {
1532 }
1533 }
1534 else
1535 {
1536 // SND.UNA < SEG.ACK =< HighTxMark
1537 // Pag. 72 RFC 793
1538 ReceivedAck(packet, tcpHeader);
1539 }
1540 }
1541 else if (tcpflags == TcpHeader::SYN)
1542 { // Received SYN, old NS-3 behaviour is to set state to SYN_RCVD and
1543 // respond with a SYN+ACK. But it is not a legal state transition as of
1544 // RFC793. Thus this is ignored.
1545 }
1546 else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
1547 { // No action for received SYN+ACK, it is probably a duplicated packet
1548 }
1549 else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
1550 { // Received FIN or FIN+ACK, bring down this socket nicely
1551 PeerClose(packet, tcpHeader);
1552 }
1553 else if (tcpflags == 0)
1554 { // No flags means there is only data
1555 ReceivedData(packet, tcpHeader);
1556 if (m_tcb->m_rxBuffer->Finished())
1557 {
1558 PeerClose(packet, tcpHeader);
1559 }
1560 }
1561 else
1562 { // Received RST or the TCP flags is invalid, in either case, terminate this socket
1563 if (tcpflags != TcpHeader::RST)
1564 { // this must be an invalid flag, send reset
1565 NS_LOG_LOGIC("Illegal flag " << TcpHeader::FlagsToString(tcpflags)
1566 << " received. Reset packet is sent.");
1567 SendRST();
1568 }
1570 }
1571}
1572
1573bool
1575{
1576 NS_LOG_FUNCTION(this << static_cast<uint32_t>(kind));
1577
1578 switch (kind)
1579 {
1580 case TcpOption::TS:
1581 return m_timestampEnabled;
1583 return m_winScalingEnabled;
1585 case TcpOption::SACK:
1586 return m_sackEnabled;
1587 default:
1588 break;
1589 }
1590 return false;
1591}
1592
1593void
1594TcpSocketBase::ReadOptions(const TcpHeader& tcpHeader, uint32_t* bytesSacked)
1595{
1596 NS_LOG_FUNCTION(this << tcpHeader);
1597
1598 for (const auto& option : tcpHeader.GetOptionList())
1599 {
1600 // Check only for ACK options here
1601 switch (option->GetKind())
1602 {
1603 case TcpOption::SACK:
1604 *bytesSacked = ProcessOptionSack(option);
1605 break;
1606 default:
1607 continue;
1608 }
1609 }
1610}
1611
1612// Sender should reduce the Congestion Window as a response to receiver's
1613// ECN Echo notification only once per window
1614void
1616{
1617 NS_LOG_FUNCTION(this << currentDelivered);
1619 NS_LOG_DEBUG("Reduce ssThresh to " << m_tcb->m_ssThresh);
1620 // Do not update m_cWnd, under assumption that recovery process will
1621 // gradually bring it down to m_ssThresh. Update the 'inflated' value of
1622 // cWnd used for tracing, however.
1627 // CWR state will be exited when the ack exceeds the m_recover variable.
1628 // Do not set m_recoverActive (which applies to a loss-based recovery)
1629 // m_recover corresponds to Linux tp->high_seq
1631 if (!m_congestionControl->HasCongControl())
1632 {
1633 // If there is a recovery algorithm, invoke it.
1634 m_recoveryOps->EnterRecovery(m_tcb, m_dupAckCount, UnAckDataCount(), currentDelivered);
1635 NS_LOG_INFO("Enter CWR recovery mode; set cwnd to " << m_tcb->m_cWnd << ", ssthresh to "
1636 << m_tcb->m_ssThresh << ", recover to "
1637 << m_recover);
1638 }
1639}
1640
1641void
1643{
1644 NS_LOG_FUNCTION(this);
1646
1648
1649 if (!m_sackEnabled)
1650 {
1651 // One segment has left the network, PLUS the head is lost
1652 m_txBuffer->AddRenoSack();
1653 m_txBuffer->MarkHeadAsLost();
1654 }
1655 else
1656 {
1657 if (!m_txBuffer->IsLost(m_txBuffer->HeadSequence()))
1658 {
1659 // We received 3 dupacks, but the head is not marked as lost
1660 // (received less than 3 SACK block ahead).
1661 // Manually set it as lost.
1662 m_txBuffer->MarkHeadAsLost();
1663 }
1664 }
1665
1666 // RFC 6675, point (4):
1667 // (4) Invoke fast retransmit and enter loss recovery as follows:
1668 // (4.1) RecoveryPoint = HighData
1670 m_recoverActive = true;
1671
1674
1675 // (4.2) ssthresh = cwnd = (FlightSize / 2)
1676 // If SACK is not enabled, still consider the head as 'in flight' for
1677 // compatibility with old ns-3 versions
1678 uint32_t bytesInFlight =
1680 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh(m_tcb, bytesInFlight);
1681
1682 if (!m_congestionControl->HasCongControl())
1683 {
1684 m_recoveryOps->EnterRecovery(m_tcb, m_dupAckCount, UnAckDataCount(), currentDelivered);
1685 NS_LOG_INFO(m_dupAckCount << " dupack. Enter fast recovery mode."
1686 << "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to "
1687 << m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover
1688 << " calculated in flight: " << bytesInFlight);
1689 }
1690
1691 // (4.3) Retransmit the first data segment presumed dropped
1692 DoRetransmit();
1693 // (4.4) Run SetPipe ()
1694 // (4.5) Proceed to step (C)
1695 // these steps are done after the ProcessAck function (SendPendingData)
1696}
1697
1698void
1700{
1701 NS_LOG_FUNCTION(this);
1702 // NOTE: We do not count the DupAcks received in CA_LOSS, because we
1703 // don't know if they are generated by a spurious retransmission or because
1704 // of a real packet loss. With SACK, it is easy to know, but we do not consider
1705 // dupacks. Without SACK, there are some heuristics in the RFC 6582, but
1706 // for now, we do not implement it, leading to ignoring the dupacks.
1708 {
1709 return;
1710 }
1711
1712 // RFC 6675, Section 5, 3rd paragraph:
1713 // If the incoming ACK is a duplicate acknowledgment per the definition
1714 // in Section 2 (regardless of its status as a cumulative
1715 // acknowledgment), and the TCP is not currently in loss recovery
1716 // the TCP MUST increase DupAcks by one ...
1718 {
1719 ++m_dupAckCount;
1720 }
1721
1723 {
1724 // From Open we go Disorder
1726 "From OPEN->DISORDER but with " << m_dupAckCount << " dup ACKs");
1727
1730
1731 NS_LOG_DEBUG("CA_OPEN -> CA_DISORDER");
1732 }
1733
1735 {
1736 if (!m_sackEnabled)
1737 {
1738 // If we are in recovery and we receive a dupack, one segment
1739 // has left the network. This is equivalent to a SACK of one block.
1740 m_txBuffer->AddRenoSack();
1741 }
1742 if (!m_congestionControl->HasCongControl())
1743 {
1744 m_recoveryOps->DoRecovery(m_tcb, currentDelivered);
1745 NS_LOG_INFO(m_dupAckCount << " Dupack received in fast recovery mode."
1746 "Increase cwnd to "
1747 << m_tcb->m_cWnd);
1748 }
1749 }
1751 {
1752 // m_dupackCount should not exceed its threshold in CA_DISORDER state
1753 // when m_recoverActive has not been set. When recovery point
1754 // have been set after timeout, the sender could enter into CA_DISORDER
1755 // after receiving new ACK smaller than m_recover. After that, m_dupackCount
1756 // can be equal and larger than m_retxThresh and we should avoid entering
1757 // CA_RECOVERY and reducing sending rate again.
1759
1760 // RFC 6675, Section 5, continuing:
1761 // ... and take the following steps:
1762 // (1) If DupAcks >= DupThresh, go to step (4).
1763 // Sequence number comparison (m_highRxAckMark >= m_recover) will take
1764 // effect only when m_recover has been set. Hence, we can avoid to use
1765 // m_recover in the last congestion event and fail to enter
1766 // CA_RECOVERY when sequence number is advanced significantly since
1767 // the last congestion event, which could be common for
1768 // bandwidth-greedy application in high speed and reliable network
1769 // (such as datacenter network) whose sending rate is constrained by
1770 // TCP socket buffer size at receiver side.
1771 if ((m_dupAckCount == m_retxThresh) &&
1773 {
1774 EnterRecovery(currentDelivered);
1776 }
1777 // (2) If DupAcks < DupThresh but IsLost (HighACK + 1) returns true
1778 // (indicating at least three segments have arrived above the current
1779 // cumulative acknowledgment point, which is taken to indicate loss)
1780 // go to step (4).
1781 else if (m_txBuffer->IsLost(m_highRxAckMark + m_tcb->m_segmentSize))
1782 {
1783 EnterRecovery(currentDelivered);
1785 }
1786 else
1787 {
1788 // (3) The TCP MAY transmit previously unsent data segments as per
1789 // Limited Transmit [RFC5681] ...except that the number of octets
1790 // which may be sent is governed by pipe and cwnd as follows:
1791 //
1792 // (3.1) Set HighRxt to HighACK.
1793 // Not clear in RFC. We don't do this here, since we still have
1794 // to retransmit the segment.
1795
1796 if (!m_sackEnabled && m_limitedTx)
1797 {
1798 m_txBuffer->AddRenoSack();
1799
1800 // In limited transmit, cwnd Infl is not updated.
1801 }
1802 }
1803 }
1804}
1805
1806/* Process the newly received ACK */
1807void
1809{
1810 NS_LOG_FUNCTION(this << tcpHeader);
1811
1812 NS_ASSERT(0 != (tcpHeader.GetFlags() & TcpHeader::ACK));
1814
1815 uint32_t previousLost = m_txBuffer->GetLost();
1816 uint32_t priorInFlight = m_tcb->m_bytesInFlight.Get();
1817
1818 // RFC 6675, Section 5, 1st paragraph:
1819 // Upon the receipt of any ACK containing SACK information, the
1820 // scoreboard MUST be updated via the Update () routine (done in ReadOptions)
1821 uint32_t bytesSacked = 0;
1822 uint64_t previousDelivered = m_rateOps->GetConnectionRate().m_delivered;
1823 ReadOptions(tcpHeader, &bytesSacked);
1824
1825 SequenceNumber32 ackNumber = tcpHeader.GetAckNumber();
1826 SequenceNumber32 oldHeadSequence = m_txBuffer->HeadSequence();
1827
1828 if (ackNumber < oldHeadSequence)
1829 {
1830 NS_LOG_DEBUG("Possibly received a stale ACK (ack number < head sequence)");
1831 // If there is any data piggybacked, store it into m_rxBuffer
1832 if (packet->GetSize() > 0)
1833 {
1834 ReceivedData(packet, tcpHeader);
1835 }
1836 return;
1837 }
1838 if ((ackNumber > oldHeadSequence) && (ackNumber < m_recover) &&
1840 {
1841 uint32_t segAcked = (ackNumber - oldHeadSequence) / m_tcb->m_segmentSize;
1842 for (uint32_t i = 0; i < segAcked; i++)
1843 {
1844 if (m_txBuffer->IsRetransmittedDataAcked(ackNumber - (i * m_tcb->m_segmentSize)))
1845 {
1847 NS_LOG_DEBUG("Ack Number " << ackNumber << "is ACK of retransmitted packet.");
1848 }
1849 }
1850 }
1851
1852 m_txBuffer->DiscardUpTo(ackNumber, MakeCallback(&TcpRateOps::SkbDelivered, m_rateOps));
1853
1854 uint32_t currentDelivered =
1855 static_cast<uint32_t>(m_rateOps->GetConnectionRate().m_delivered - previousDelivered);
1856 m_tcb->m_lastAckedSackedBytes = currentDelivered;
1857
1858 if (m_tcb->m_congState == TcpSocketState::CA_CWR && (ackNumber > m_recover))
1859 {
1860 // Recovery is over after the window exceeds m_recover
1861 // (although it may be re-entered below if ECE is still set)
1864 if (!m_congestionControl->HasCongControl())
1865 {
1867 m_recoveryOps->ExitRecovery(m_tcb);
1869 }
1870 }
1871
1872 if (ackNumber > oldHeadSequence && (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED) &&
1873 (tcpHeader.GetFlags() & TcpHeader::ECE))
1874 {
1875 if (m_ecnEchoSeq < ackNumber)
1876 {
1877 NS_LOG_INFO("Received ECN Echo is valid");
1878 m_ecnEchoSeq = ackNumber;
1882 {
1883 EnterCwr(currentDelivered);
1884 }
1885 }
1886 }
1888 !(tcpHeader.GetFlags() & TcpHeader::ECE))
1889 {
1891 }
1892
1893 // Update bytes in flight before processing the ACK for proper calculation of congestion window
1894 NS_LOG_INFO("Update bytes in flight before processing the ACK.");
1895 BytesInFlight();
1896
1897 // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation
1898 // are inside the function ProcessAck
1899 ProcessAck(ackNumber, (bytesSacked > 0), currentDelivered, oldHeadSequence);
1900 m_tcb->m_isRetransDataAcked = false;
1901
1902 if (m_congestionControl->HasCongControl())
1903 {
1904 uint32_t currentLost = m_txBuffer->GetLost();
1905 uint32_t lost =
1906 (currentLost > previousLost) ? currentLost - previousLost : previousLost - currentLost;
1907 auto rateSample = m_rateOps->GenerateSample(currentDelivered,
1908 lost,
1909 false,
1910 priorInFlight,
1911 m_tcb->m_minRtt);
1912 auto rateConn = m_rateOps->GetConnectionRate();
1913 m_congestionControl->CongControl(m_tcb, rateConn, rateSample);
1914 }
1915
1916 // If there is any data piggybacked, store it into m_rxBuffer
1917 if (packet->GetSize() > 0)
1918 {
1919 ReceivedData(packet, tcpHeader);
1920 }
1921
1922 // RFC 6675, Section 5, point (C), try to send more data. NB: (C) is implemented
1923 // inside SendPendingData
1925}
1926
1927void
1929 bool scoreboardUpdated,
1930 uint32_t currentDelivered,
1931 const SequenceNumber32& oldHeadSequence)
1932{
1933 NS_LOG_FUNCTION(this << ackNumber << scoreboardUpdated);
1934 // RFC 6675, Section 5, 2nd paragraph:
1935 // If the incoming ACK is a cumulative acknowledgment, the TCP MUST
1936 // reset DupAcks to zero.
1937 bool exitedFastRecovery = false;
1938 uint32_t oldDupAckCount = m_dupAckCount; // remember the old value
1939 m_tcb->m_lastAckedSeq = ackNumber; // Update lastAckedSeq
1940 uint32_t bytesAcked = 0;
1941
1942 /* In RFC 5681 the definition of duplicate acknowledgment was strict:
1943 *
1944 * (a) the receiver of the ACK has outstanding data,
1945 * (b) the incoming acknowledgment carries no data,
1946 * (c) the SYN and FIN bits are both off,
1947 * (d) the acknowledgment number is equal to the greatest acknowledgment
1948 * received on the given connection (TCP.UNA from [RFC793]),
1949 * (e) the advertised window in the incoming acknowledgment equals the
1950 * advertised window in the last incoming acknowledgment.
1951 *
1952 * With RFC 6675, this definition has been reduced:
1953 *
1954 * (a) the ACK is carrying a SACK block that identifies previously
1955 * unacknowledged and un-SACKed octets between HighACK (TCP.UNA) and
1956 * HighData (m_highTxMark)
1957 */
1958
1959 bool isDupack = m_sackEnabled ? scoreboardUpdated
1960 : ackNumber == oldHeadSequence && ackNumber < m_tcb->m_highTxMark;
1961
1962 NS_LOG_DEBUG("ACK of " << ackNumber << " SND.UNA=" << oldHeadSequence
1963 << " SND.NXT=" << m_tcb->m_nextTxSequence
1965 << " with m_recover: " << m_recover);
1966
1967 // RFC 6675, Section 5, 3rd paragraph:
1968 // If the incoming ACK is a duplicate acknowledgment per the definition
1969 // in Section 2 (regardless of its status as a cumulative
1970 // acknowledgment), and the TCP is not currently in loss recovery
1971 if (isDupack)
1972 {
1973 // loss recovery check is done inside this function thanks to
1974 // the congestion state machine
1975 DupAck(currentDelivered);
1976 }
1977
1978 if (ackNumber == oldHeadSequence && ackNumber == m_tcb->m_highTxMark)
1979 {
1980 // Dupack, but the ACK is precisely equal to the nextTxSequence
1981 return;
1982 }
1983 else if (ackNumber == oldHeadSequence && ackNumber > m_tcb->m_highTxMark)
1984 {
1985 // ACK of the FIN bit ... nextTxSequence is not updated since we
1986 // don't have anything to transmit
1987 NS_LOG_DEBUG("Update nextTxSequence manually to " << ackNumber);
1988 m_tcb->m_nextTxSequence = ackNumber;
1989 }
1990 else if (ackNumber == oldHeadSequence)
1991 {
1992 // DupAck. Artificially call PktsAcked: after all, one segment has been ACKed.
1993 m_congestionControl->PktsAcked(m_tcb, 1, m_tcb->m_lastRtt);
1994 }
1995 else if (ackNumber > oldHeadSequence)
1996 {
1997 // Please remember that, with SACK, we can enter here even if we
1998 // received a dupack.
1999 bytesAcked = ackNumber - oldHeadSequence;
2000 uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize;
2002 bytesAcked -= bytesAcked % m_tcb->m_segmentSize;
2003
2005 {
2006 segsAcked += 1;
2007 bytesAcked += m_tcb->m_segmentSize;
2009 }
2010
2011 // Dupack count is reset to eventually fast-retransmit after 3 dupacks.
2012 // Any SACK-ed segment will be cleaned up by DiscardUpTo.
2013 // In the case that we advanced SND.UNA, but the ack contains SACK blocks,
2014 // we do not reset. At the third one we will retransmit.
2015 // If we are already in recovery, this check is useless since dupAcks
2016 // are not considered in this phase. When from Recovery we go back
2017 // to open, then dupAckCount is reset anyway.
2018 if (!isDupack)
2019 {
2020 m_dupAckCount = 0;
2021 }
2022
2023 // RFC 6675, Section 5, part (B)
2024 // (B) Upon receipt of an ACK that does not cover RecoveryPoint, the
2025 // following actions MUST be taken:
2026 //
2027 // (B.1) Use Update () to record the new SACK information conveyed
2028 // by the incoming ACK.
2029 // (B.2) Use SetPipe () to re-calculate the number of octets still
2030 // in the network.
2031 //
2032 // (B.1) is done at the beginning, while (B.2) is delayed to part (C) while
2033 // trying to transmit with SendPendingData. We are not allowed to exit
2034 // the CA_RECOVERY phase. Just process this partial ack (RFC 5681)
2035 if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_RECOVERY)
2036 {
2037 if (!m_sackEnabled)
2038 {
2039 // Manually set the head as lost, it will be retransmitted.
2040 NS_LOG_INFO("Partial ACK. Manually setting head as lost");
2041 m_txBuffer->MarkHeadAsLost();
2042 }
2043
2044 // Before retransmitting the packet perform DoRecovery and check if
2045 // there is available window
2046 if (!m_congestionControl->HasCongControl() && segsAcked >= 1)
2047 {
2048 m_recoveryOps->DoRecovery(m_tcb, currentDelivered);
2049 }
2050
2051 // If the packet is already retransmitted do not retransmit it
2052 if (!m_txBuffer->IsRetransmittedDataAcked(ackNumber + m_tcb->m_segmentSize))
2053 {
2054 DoRetransmit(); // Assume the next seq is lost. Retransmit lost packet
2056 }
2057
2058 // This partial ACK acknowledge the fact that one segment has been
2059 // previously lost and now successfully received. All others have
2060 // been processed when they come under the form of dupACKs
2061 m_congestionControl->PktsAcked(m_tcb, 1, m_tcb->m_lastRtt);
2062 NewAck(ackNumber, m_isFirstPartialAck);
2063
2065 {
2066 NS_LOG_DEBUG("Partial ACK of " << ackNumber
2067 << " and this is the first (RTO will be reset);"
2068 " cwnd set to "
2069 << m_tcb->m_cWnd << " recover seq: " << m_recover
2070 << " dupAck count: " << m_dupAckCount);
2071 m_isFirstPartialAck = false;
2072 }
2073 else
2074 {
2075 NS_LOG_DEBUG("Partial ACK of "
2076 << ackNumber
2077 << " and this is NOT the first (RTO will not be reset)"
2078 " cwnd set to "
2079 << m_tcb->m_cWnd << " recover seq: " << m_recover
2080 << " dupAck count: " << m_dupAckCount);
2081 }
2082 }
2083 // From RFC 6675 section 5.1
2084 // In addition, a new recovery phase (as described in Section 5) MUST NOT
2085 // be initiated until HighACK is greater than or equal to the new value
2086 // of RecoveryPoint.
2087 else if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_LOSS)
2088 {
2089 m_congestionControl->PktsAcked(m_tcb, segsAcked, m_tcb->m_lastRtt);
2090 m_congestionControl->IncreaseWindow(m_tcb, segsAcked);
2091
2092 NS_LOG_DEBUG(" Cong Control Called, cWnd=" << m_tcb->m_cWnd
2093 << " ssTh=" << m_tcb->m_ssThresh);
2094 if (!m_sackEnabled)
2095 {
2097 m_txBuffer->GetSacked() == 0,
2098 "Some segment got dup-acked in CA_LOSS state: " << m_txBuffer->GetSacked());
2099 }
2100 NewAck(ackNumber, true);
2101 }
2103 {
2104 m_congestionControl->PktsAcked(m_tcb, segsAcked, m_tcb->m_lastRtt);
2105 // TODO: need to check behavior if marking is compounded by loss
2106 // and/or packet reordering
2107 if (!m_congestionControl->HasCongControl() && segsAcked >= 1)
2108 {
2109 m_recoveryOps->DoRecovery(m_tcb, currentDelivered);
2110 }
2111 NewAck(ackNumber, true);
2112 }
2113 else
2114 {
2116 {
2117 m_congestionControl->PktsAcked(m_tcb, segsAcked, m_tcb->m_lastRtt);
2118 }
2120 {
2121 if (segsAcked >= oldDupAckCount)
2122 {
2123 m_congestionControl->PktsAcked(m_tcb,
2124 segsAcked - oldDupAckCount,
2125 m_tcb->m_lastRtt);
2126 }
2127
2128 if (!isDupack)
2129 {
2130 // The network reorder packets. Linux changes the counting lost
2131 // packet algorithm from FACK to NewReno. We simply go back in Open.
2134 NS_LOG_DEBUG(segsAcked << " segments acked in CA_DISORDER, ack of " << ackNumber
2135 << " exiting CA_DISORDER -> CA_OPEN");
2136 }
2137 else
2138 {
2139 NS_LOG_DEBUG(segsAcked << " segments acked in CA_DISORDER, ack of " << ackNumber
2140 << " but still in CA_DISORDER");
2141 }
2142 }
2143 // RFC 6675, Section 5:
2144 // Once a TCP is in the loss recovery phase, the following procedure
2145 // MUST be used for each arriving ACK:
2146 // (A) An incoming cumulative ACK for a sequence number greater than
2147 // RecoveryPoint signals the end of loss recovery, and the loss
2148 // recovery phase MUST be terminated. Any information contained in
2149 // the scoreboard for sequence numbers greater than the new value of
2150 // HighACK SHOULD NOT be cleared when leaving the loss recovery
2151 // phase.
2153 {
2154 m_isFirstPartialAck = true;
2155
2156 // Recalculate the segs acked, that are from m_recover to ackNumber
2157 // (which are the ones we have not passed to PktsAcked and that
2158 // can increase cWnd)
2159 // TODO: check consistency for dynamic segment size
2160 segsAcked =
2161 static_cast<uint32_t>(ackNumber - oldHeadSequence) / m_tcb->m_segmentSize;
2162 m_congestionControl->PktsAcked(m_tcb, segsAcked, m_tcb->m_lastRtt);
2166 exitedFastRecovery = true;
2167 m_dupAckCount = 0; // From recovery to open, reset dupack
2168
2169 NS_LOG_DEBUG(segsAcked << " segments acked in CA_RECOVER, ack of " << ackNumber
2170 << ", exiting CA_RECOVERY -> CA_OPEN");
2171 }
2173 {
2174 m_isFirstPartialAck = true;
2175
2176 // Recalculate the segs acked, that are from m_recover to ackNumber
2177 // (which are the ones we have not passed to PktsAcked and that
2178 // can increase cWnd)
2179 segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize;
2180
2181 m_congestionControl->PktsAcked(m_tcb, segsAcked, m_tcb->m_lastRtt);
2182
2185 NS_LOG_DEBUG(segsAcked << " segments acked in CA_LOSS, ack of" << ackNumber
2186 << ", exiting CA_LOSS -> CA_OPEN");
2187 }
2188
2189 if (ackNumber >= m_recover)
2190 {
2191 // All lost segments in the congestion event have been
2192 // retransmitted successfully. The recovery point (m_recover)
2193 // should be deactivated.
2194 m_recoverActive = false;
2195 }
2196
2197 if (exitedFastRecovery)
2198 {
2199 NewAck(ackNumber, true);
2201 m_recoveryOps->ExitRecovery(m_tcb);
2202 NS_LOG_DEBUG("Leaving Fast Recovery; BytesInFlight() = "
2203 << BytesInFlight() << "; cWnd = " << m_tcb->m_cWnd);
2204 }
2206 {
2207 m_congestionControl->IncreaseWindow(m_tcb, segsAcked);
2208
2210
2211 NS_LOG_LOGIC("Congestion control called: "
2212 << " cWnd: " << m_tcb->m_cWnd << " ssTh: " << m_tcb->m_ssThresh
2213 << " segsAcked: " << segsAcked);
2214
2215 NewAck(ackNumber, true);
2216 }
2217 }
2218 }
2219 // Update the pacing rate, since m_congestionControl->IncreaseWindow() or
2220 // m_congestionControl->PktsAcked () may change m_tcb->m_cWnd
2221 // Make sure that control reaches the end of this function and there is no
2222 // return in between
2224}
2225
2226/* Received a packet upon LISTEN state. */
2227void
2229 const TcpHeader& tcpHeader,
2230 const Address& fromAddress,
2231 const Address& toAddress)
2232{
2233 NS_LOG_FUNCTION(this << tcpHeader);
2234
2235 // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2236 uint8_t tcpflags =
2238
2239 // Fork a socket if received a SYN. Do nothing otherwise.
2240 // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
2241 if (tcpflags != TcpHeader::SYN)
2242 {
2243 return;
2244 }
2245
2246 // Call socket's notify function to let the server app know we got a SYN
2247 // If the server app refuses the connection, do nothing
2248 if (!NotifyConnectionRequest(fromAddress))
2249 {
2250 return;
2251 }
2252 // Clone the socket, simulate fork
2253 Ptr<TcpSocketBase> newSock = Fork();
2254 NS_LOG_LOGIC("Cloned a TcpSocketBase " << newSock);
2256 newSock,
2257 packet,
2258 tcpHeader,
2259 fromAddress,
2260 toAddress);
2261}
2262
2263/* Received a packet upon SYN_SENT */
2264void
2266{
2267 NS_LOG_FUNCTION(this << tcpHeader);
2268
2269 // Extract the flags. PSH and URG are disregarded.
2270 uint8_t tcpflags = tcpHeader.GetFlags() & ~(TcpHeader::PSH | TcpHeader::URG);
2271
2272 if (tcpflags == 0)
2273 { // Bare data, accept it and move to ESTABLISHED state. This is not a normal behaviour. Remove
2274 // this?
2275 NS_LOG_DEBUG("SYN_SENT -> ESTABLISHED");
2279 m_connected = true;
2282 ReceivedData(packet, tcpHeader);
2284 }
2285 else if (tcpflags & TcpHeader::ACK && !(tcpflags & TcpHeader::SYN))
2286 { // Ignore ACK in SYN_SENT
2287 }
2288 else if (tcpflags & TcpHeader::SYN && !(tcpflags & TcpHeader::ACK))
2289 { // Received SYN, move to SYN_RCVD state and respond with SYN+ACK
2290 NS_LOG_DEBUG("SYN_SENT -> SYN_RCVD");
2291 m_state = SYN_RCVD;
2293 m_tcb->m_rxBuffer->SetNextRxSequence(tcpHeader.GetSequenceNumber() + SequenceNumber32(1));
2294 /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if
2295 * the traffic is ECN capable and sender has sent ECN SYN packet
2296 */
2297
2300 {
2301 NS_LOG_INFO("Received ECN SYN packet");
2305 }
2306 else
2307 {
2310 }
2311 }
2312 else if (tcpflags & (TcpHeader::SYN | TcpHeader::ACK) &&
2314 { // Handshake completed
2315 NS_LOG_DEBUG("SYN_SENT -> ESTABLISHED");
2319 m_connected = true;
2321 m_tcb->m_rxBuffer->SetNextRxSequence(tcpHeader.GetSequenceNumber() + SequenceNumber32(1));
2323 m_txBuffer->SetHeadSequence(m_tcb->m_nextTxSequence);
2324 // Before sending packets, update the pacing rate based on RTT measurement so far
2327
2328 /* Check if we received an ECN SYN-ACK packet. Change the ECN state of sender to ECN_IDLE if
2329 * receiver has sent an ECN SYN-ACK packet and the traffic is ECN Capable
2330 */
2332 (tcpflags & (TcpHeader::CWR | TcpHeader::ECE)) == (TcpHeader::ECE))
2333 {
2334 NS_LOG_INFO("Received ECN SYN-ACK packet.");
2337 }
2338 else
2339 {
2341 }
2344 // Always respond to first data packet to speed up the connection.
2345 // Remove to get the behaviour of old NS-3 code.
2347 }
2348 else
2349 { // Other in-sequence input
2350 if (!(tcpflags & TcpHeader::RST))
2351 { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
2352 NS_LOG_LOGIC("Illegal flag combination "
2353 << TcpHeader::FlagsToString(tcpHeader.GetFlags())
2354 << " received in SYN_SENT. Reset packet is sent.");
2355 SendRST();
2356 }
2358 }
2359}
2360
2361/* Received a packet upon SYN_RCVD */
2362void
2364 const TcpHeader& tcpHeader,
2365 const Address& fromAddress,
2366 const Address& /* toAddress */)
2367{
2368 NS_LOG_FUNCTION(this << tcpHeader);
2369
2370 // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2371 uint8_t tcpflags =
2373
2374 if (tcpflags == 0 ||
2375 (tcpflags == TcpHeader::ACK &&
2377 { // If it is bare data, accept it and move to ESTABLISHED state. This is
2378 // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
2379 // handshake is completed nicely.
2380 NS_LOG_DEBUG("SYN_RCVD -> ESTABLISHED");
2384 m_connected = true;
2387 m_txBuffer->SetHeadSequence(m_tcb->m_nextTxSequence);
2388 if (m_endPoint)
2389 {
2390 m_endPoint->SetPeer(InetSocketAddress::ConvertFrom(fromAddress).GetIpv4(),
2391 InetSocketAddress::ConvertFrom(fromAddress).GetPort());
2392 }
2393 else if (m_endPoint6)
2394 {
2395 m_endPoint6->SetPeer(Inet6SocketAddress::ConvertFrom(fromAddress).GetIpv6(),
2396 Inet6SocketAddress::ConvertFrom(fromAddress).GetPort());
2397 }
2398 // Always respond to first data packet to speed up the connection.
2399 // Remove to get the behaviour of old NS-3 code.
2401 NotifyNewConnectionCreated(this, fromAddress);
2402 ReceivedAck(packet, tcpHeader);
2403 // Update the pacing rate based on RTT measurement so far
2405 // As this connection is established, the socket is available to send data now
2406 if (GetTxAvailable() > 0)
2407 {
2409 }
2410 }
2411 else if (tcpflags == TcpHeader::SYN)
2412 { // Probably the peer lost my SYN+ACK
2413 m_tcb->m_rxBuffer->SetNextRxSequence(tcpHeader.GetSequenceNumber() + SequenceNumber32(1));
2414 /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if
2415 * sender has sent an ECN SYN packet and the traffic is ECN Capable
2416 */
2418 (tcpHeader.GetFlags() & (TcpHeader::CWR | TcpHeader::ECE)) ==
2420 {
2421 NS_LOG_INFO("Received ECN SYN packet");
2425 }
2426 else
2427 {
2430 }
2431 }
2432 else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2433 {
2434 if (tcpHeader.GetSequenceNumber() == m_tcb->m_rxBuffer->NextRxSequence())
2435 { // In-sequence FIN before connection complete. Set up connection and close.
2436 m_connected = true;
2439 m_txBuffer->SetHeadSequence(m_tcb->m_nextTxSequence);
2440 if (m_endPoint)
2441 {
2442 m_endPoint->SetPeer(InetSocketAddress::ConvertFrom(fromAddress).GetIpv4(),
2443 InetSocketAddress::ConvertFrom(fromAddress).GetPort());
2444 }
2445 else if (m_endPoint6)
2446 {
2447 m_endPoint6->SetPeer(Inet6SocketAddress::ConvertFrom(fromAddress).GetIpv6(),
2448 Inet6SocketAddress::ConvertFrom(fromAddress).GetPort());
2449 }
2450 NotifyNewConnectionCreated(this, fromAddress);
2451 PeerClose(packet, tcpHeader);
2452 }
2453 }
2454 else
2455 { // Other in-sequence input
2456 if (tcpflags != TcpHeader::RST)
2457 { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
2458 NS_LOG_LOGIC("Illegal flag " << TcpHeader::FlagsToString(tcpflags)
2459 << " received. Reset packet is sent.");
2460 if (m_endPoint)
2461 {
2462 m_endPoint->SetPeer(InetSocketAddress::ConvertFrom(fromAddress).GetIpv4(),
2463 InetSocketAddress::ConvertFrom(fromAddress).GetPort());
2464 }
2465 else if (m_endPoint6)
2466 {
2467 m_endPoint6->SetPeer(Inet6SocketAddress::ConvertFrom(fromAddress).GetIpv6(),
2468 Inet6SocketAddress::ConvertFrom(fromAddress).GetPort());
2469 }
2470 SendRST();
2471 }
2473 }
2474}
2475
2476/* Received a packet upon CLOSE_WAIT, FIN_WAIT_1, or FIN_WAIT_2 states */
2477void
2479{
2480 NS_LOG_FUNCTION(this << tcpHeader);
2481
2482 // Extract the flags. PSH, URG, CWR and ECE are disregarded.
2483 uint8_t tcpflags =
2485
2486 if (packet->GetSize() > 0 && !(tcpflags & TcpHeader::ACK))
2487 { // Bare data, accept it
2488 ReceivedData(packet, tcpHeader);
2489 }
2490 else if (tcpflags == TcpHeader::ACK)
2491 { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
2492 ReceivedAck(packet, tcpHeader);
2493 if (m_state == FIN_WAIT_1 && m_txBuffer->Size() == 0 &&
2494 tcpHeader.GetAckNumber() == m_tcb->m_highTxMark + SequenceNumber32(1))
2495 { // This ACK corresponds to the FIN sent
2496 NS_LOG_DEBUG("FIN_WAIT_1 -> FIN_WAIT_2");
2498 }
2499 }
2500 else if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2501 { // Got FIN, respond with ACK and move to next state
2502 if (tcpflags & TcpHeader::ACK)
2503 { // Process the ACK first
2504 ReceivedAck(packet, tcpHeader);
2505 }
2506 m_tcb->m_rxBuffer->SetFinSequence(tcpHeader.GetSequenceNumber());
2507 }
2508 else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK))
2509 { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission
2510 return;
2511 }
2512 else
2513 { // This is a RST or bad flags
2514 if (tcpflags != TcpHeader::RST)
2515 {
2516 NS_LOG_LOGIC("Illegal flag " << TcpHeader::FlagsToString(tcpflags)
2517 << " received. Reset packet is sent.");
2518 SendRST();
2519 }
2521 return;
2522 }
2523
2524 // Check if the close responder sent an in-sequence FIN, if so, respond ACK
2525 if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_tcb->m_rxBuffer->Finished())
2526 {
2527 if (m_state == FIN_WAIT_1)
2528 {
2529 NS_LOG_DEBUG("FIN_WAIT_1 -> CLOSING");
2530 m_state = CLOSING;
2531 if (m_txBuffer->Size() == 0 &&
2532 tcpHeader.GetAckNumber() == m_tcb->m_highTxMark + SequenceNumber32(1))
2533 { // This ACK corresponds to the FIN sent
2534 TimeWait();
2535 }
2536 }
2537 else if (m_state == FIN_WAIT_2)
2538 {
2539 TimeWait();
2540 }
2542 if (!m_shutdownRecv)
2543 {
2545 }
2546 }
2547}
2548
2549/* Received a packet upon CLOSING */
2550void
2552{
2553 NS_LOG_FUNCTION(this << tcpHeader);
2554
2555 // Extract the flags. PSH and URG are disregarded.
2556 uint8_t tcpflags = tcpHeader.GetFlags() & ~(TcpHeader::PSH | TcpHeader::URG);
2557
2558 if (tcpflags == TcpHeader::ACK)
2559 {
2560 if (tcpHeader.GetSequenceNumber() == m_tcb->m_rxBuffer->NextRxSequence())
2561 { // This ACK corresponds to the FIN sent
2562 TimeWait();
2563 }
2564 }
2565 else
2566 { // CLOSING state means simultaneous close, i.e. no one is sending data to
2567 // anyone. If anything other than ACK is received, respond with a reset.
2568 if (tcpflags == TcpHeader::FIN || tcpflags == (TcpHeader::FIN | TcpHeader::ACK))
2569 { // FIN from the peer as well. We can close immediately.
2571 }
2572 else if (tcpflags != TcpHeader::RST)
2573 { // Receive of SYN or SYN+ACK or bad flags or pure data
2574 NS_LOG_LOGIC("Illegal flag " << TcpHeader::FlagsToString(tcpflags)
2575 << " received. Reset packet is sent.");
2576 SendRST();
2577 }
2579 }
2580}
2581
2582/* Received a packet upon LAST_ACK */
2583void
2585{
2586 NS_LOG_FUNCTION(this << tcpHeader);
2587
2588 // Extract the flags. PSH and URG are disregarded.
2589 uint8_t tcpflags = tcpHeader.GetFlags() & ~(TcpHeader::PSH | TcpHeader::URG);
2590
2591 if (tcpflags == 0)
2592 {
2593 ReceivedData(packet, tcpHeader);
2594 }
2595 else if (tcpflags == TcpHeader::ACK)
2596 {
2597 if (tcpHeader.GetSequenceNumber() == m_tcb->m_rxBuffer->NextRxSequence())
2598 { // This ACK corresponds to the FIN sent. This socket closed peacefully.
2600 }
2601 }
2602 else if (tcpflags == TcpHeader::FIN)
2603 { // Received FIN again, the peer probably lost the FIN+ACK
2605 }
2606 else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK) || tcpflags == TcpHeader::RST)
2607 {
2609 }
2610 else
2611 { // Received a SYN or SYN+ACK or bad flags
2612 NS_LOG_LOGIC("Illegal flag " << TcpHeader::FlagsToString(tcpflags)
2613 << " received. Reset packet is sent.");
2614 SendRST();
2616 }
2617}
2618
2619/* Peer sent me a FIN. Remember its sequence in rx buffer. */
2620void
2622{
2623 NS_LOG_FUNCTION(this << tcpHeader);
2624
2625 // Ignore all out of range packets
2626 if (tcpHeader.GetSequenceNumber() < m_tcb->m_rxBuffer->NextRxSequence() ||
2627 tcpHeader.GetSequenceNumber() > m_tcb->m_rxBuffer->MaxRxSequence())
2628 {
2629 return;
2630 }
2631 // For any case, remember the FIN position in rx buffer first
2632 m_tcb->m_rxBuffer->SetFinSequence(tcpHeader.GetSequenceNumber() +
2633 SequenceNumber32(p->GetSize()));
2634 NS_LOG_LOGIC("Accepted FIN at seq "
2635 << tcpHeader.GetSequenceNumber() + SequenceNumber32(p->GetSize()));
2636 // If there is any piggybacked data, process it
2637 if (p->GetSize())
2638 {
2639 ReceivedData(p, tcpHeader);
2640 }
2641 // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
2642 if (!m_tcb->m_rxBuffer->Finished())
2643 {
2644 return;
2645 }
2646
2647 // Simultaneous close: Application invoked Close() when we are processing this FIN packet
2648 if (m_state == FIN_WAIT_1)
2649 {
2650 NS_LOG_DEBUG("FIN_WAIT_1 -> CLOSING");
2651 m_state = CLOSING;
2652 return;
2653 }
2654
2655 DoPeerClose(); // Change state, respond with ACK
2656}
2657
2658/* Received a in-sequence FIN. Close down this socket. */
2659void
2661{
2663 m_state == FIN_WAIT_2);
2664
2665 // Move the state to CLOSE_WAIT
2666 NS_LOG_DEBUG(TcpStateName[m_state] << " -> CLOSE_WAIT");
2668
2669 if (!m_closeNotified)
2670 {
2671 // The normal behaviour for an application is that, when the peer sent a in-sequence
2672 // FIN, the app should prepare to close. The app has two choices at this point: either
2673 // respond with ShutdownSend() call to declare that it has nothing more to send and
2674 // the socket can be closed immediately; or remember the peer's close request, wait
2675 // until all its existing data are pushed into the TCP socket, then call Close()
2676 // explicitly.
2677 NS_LOG_LOGIC("TCP " << this << " calling NotifyNormalClose");
2679 m_closeNotified = true;
2680 }
2681 if (m_shutdownSend)
2682 { // The application declares that it would not sent any more, close this socket
2683 Close();
2684 }
2685 else
2686 { // Need to ack, the application will close later
2688 }
2689 if (m_state == LAST_ACK)
2690 {
2691 m_dataRetrCount = m_dataRetries; // prevent endless FINs
2692 NS_LOG_LOGIC("TcpSocketBase " << this << " scheduling LATO1");
2693 Time lastRto = m_rtt->GetEstimate() + Max(m_clockGranularity, m_rtt->GetVariation() * 4);
2695 }
2696}
2697
2698/* Kill this socket. This is a callback function configured to m_endpoint in
2699 SetupCallback(), invoked when the endpoint is destroyed. */
2700void
2702{
2703 NS_LOG_FUNCTION(this);
2704 m_endPoint = nullptr;
2705 if (m_tcp)
2706 {
2707 m_tcp->RemoveSocket(this);
2708 }
2709 NS_LOG_LOGIC(this << " Cancelled ReTxTimeout event which was set to expire at "
2710 << (Simulator::Now() + Simulator::GetDelayLeft(m_retxEvent)).GetSeconds());
2712}
2713
2714/* Kill this socket. This is a callback function configured to m_endpoint in
2715 SetupCallback(), invoked when the endpoint is destroyed. */
2716void
2718{
2719 NS_LOG_FUNCTION(this);
2720 m_endPoint6 = nullptr;
2721 if (m_tcp)
2722 {
2723 m_tcp->RemoveSocket(this);
2724 }
2725 NS_LOG_LOGIC(this << " Cancelled ReTxTimeout event which was set to expire at "
2726 << (Simulator::Now() + Simulator::GetDelayLeft(m_retxEvent)).GetSeconds());
2728}
2729
2730/* Send an empty packet with specified TCP flags */
2731void
2733{
2734 NS_LOG_FUNCTION(this << static_cast<uint32_t>(flags));
2735
2736 if (m_endPoint == nullptr && m_endPoint6 == nullptr)
2737 {
2738 NS_LOG_WARN("Failed to send empty packet due to null endpoint");
2739 return;
2740 }
2741
2742 Ptr<Packet> p = Create<Packet>();
2743 TcpHeader header;
2745
2746 if (flags & TcpHeader::FIN)
2747 {
2748 flags |= TcpHeader::ACK;
2749 }
2750 else if (m_state == FIN_WAIT_1 || m_state == LAST_ACK || m_state == CLOSING)
2751 {
2752 ++s;
2753 }
2754
2755 AddSocketTags(p);
2756
2757 header.SetFlags(flags);
2758 header.SetSequenceNumber(s);
2759 header.SetAckNumber(m_tcb->m_rxBuffer->NextRxSequence());
2760 if (m_endPoint != nullptr)
2761 {
2764 }
2765 else
2766 {
2769 }
2770 AddOptions(header);
2771
2772 // RFC 6298, clause 2.4
2773 m_rto =
2774 Max(m_rtt->GetEstimate() + Max(m_clockGranularity, m_rtt->GetVariation() * 4), m_minRto);
2775
2776 uint16_t windowSize = AdvertisedWindowSize();
2777 bool hasSyn = flags & TcpHeader::SYN;
2778 bool hasFin = flags & TcpHeader::FIN;
2779 bool isAck = flags == TcpHeader::ACK;
2780 if (hasSyn)
2781 {
2783 { // The window scaling option is set only on SYN packets
2784 AddOptionWScale(header);
2785 }
2786
2787 if (m_sackEnabled)
2788 {
2789 AddOptionSackPermitted(header);
2790 }
2791
2792 if (m_synCount == 0)
2793 { // No more connection retries, give up
2794 NS_LOG_LOGIC("Connection failed.");
2795 m_rtt->Reset(); // According to recommendation -> RFC 6298
2797 m_state = CLOSED;
2799 return;
2800 }
2801 else
2802 { // Exponential backoff of connection time out
2803 int backoffCount = 0x1 << (m_synRetries - m_synCount);
2804 m_rto = m_cnTimeout * backoffCount;
2805 m_synCount--;
2806 }
2807
2808 if (m_synRetries - 1 == m_synCount)
2809 {
2810 UpdateRttHistory(s, 0, false);
2811 }
2812 else
2813 { // This is SYN retransmission
2814 UpdateRttHistory(s, 0, true);
2815 }
2816
2817 windowSize = AdvertisedWindowSize(false);
2818 }
2819 header.SetWindowSize(windowSize);
2820
2821 if (flags & TcpHeader::ACK)
2822 { // If sending an ACK, cancel the delay ACK as well
2824 m_delAckCount = 0;
2825 if (m_highTxAck < header.GetAckNumber())
2826 {
2827 m_highTxAck = header.GetAckNumber();
2828 }
2829 if (m_sackEnabled && m_tcb->m_rxBuffer->GetSackListSize() > 0)
2830 {
2831 AddOptionSack(header);
2832 }
2833 NS_LOG_INFO("Sending a pure ACK, acking seq " << m_tcb->m_rxBuffer->NextRxSequence());
2834 }
2835
2836 m_txTrace(p, header, this);
2837
2838 if (m_endPoint != nullptr)
2839 {
2840 m_tcp->SendPacket(p,
2841 header,
2845 }
2846 else
2847 {
2848 m_tcp->SendPacket(p,
2849 header,
2853 }
2854
2855 if (m_retxEvent.IsExpired() && (hasSyn || hasFin) && !isAck)
2856 { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost
2857 NS_LOG_LOGIC("Schedule retransmission timeout at time "
2858 << Simulator::Now().GetSeconds() << " to expire at time "
2859 << (Simulator::Now() + m_rto.Get()).GetSeconds());
2861 }
2862}
2863
2864/* This function closes the endpoint completely. Called upon RST_TX action. */
2865void
2867{
2868 NS_LOG_FUNCTION(this);
2872}
2873
2874/* Deallocate the end point and cancel all the timers */
2875void
2877{
2878 // note: it shouldn't be necessary to invalidate the callback and manually call
2879 // TcpL4Protocol::RemoveSocket. Alas, if one relies on the endpoint destruction
2880 // callback, there's a weird memory access to a free'd area. Harmless, but valgrind
2881 // considers it an error.
2882
2883 if (m_endPoint != nullptr)
2884 {
2886 m_endPoint->SetDestroyCallback(MakeNullCallback<void>());
2887 m_tcp->DeAllocate(m_endPoint);
2888 m_endPoint = nullptr;
2889 m_tcp->RemoveSocket(this);
2890 }
2891 else if (m_endPoint6 != nullptr)
2892 {
2894 m_endPoint6->SetDestroyCallback(MakeNullCallback<void>());
2895 m_tcp->DeAllocate(m_endPoint6);
2896 m_endPoint6 = nullptr;
2897 m_tcp->RemoveSocket(this);
2898 }
2899}
2900
2901/* Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
2902int
2904{
2905 NS_LOG_FUNCTION(this);
2906 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4>();
2907 NS_ASSERT(ipv4);
2908 if (!ipv4->GetRoutingProtocol())
2909 {
2910 NS_FATAL_ERROR("No Ipv4RoutingProtocol in the node");
2911 }
2912 // Create a dummy packet, then ask the routing function for the best output
2913 // interface's address
2914 Ipv4Header header;
2916 Socket::SocketErrno errno_;
2917 Ptr<Ipv4Route> route;
2919 route = ipv4->GetRoutingProtocol()->RouteOutput(Ptr<Packet>(), header, oif, errno_);
2920 if (!route)
2921 {
2922 NS_LOG_LOGIC("Route to " << m_endPoint->GetPeerAddress() << " does not exist");
2923 NS_LOG_ERROR(errno_);
2924 m_errno = errno_;
2925 return -1;
2926 }
2927 NS_LOG_LOGIC("Route exists");
2928 m_endPoint->SetLocalAddress(route->GetSource());
2929 return 0;
2930}
2931
2932int
2934{
2935 NS_LOG_FUNCTION(this);
2937 NS_ASSERT(ipv6);
2938 if (!ipv6->GetRoutingProtocol())
2939 {
2940 NS_FATAL_ERROR("No Ipv6RoutingProtocol in the node");
2941 }
2942 // Create a dummy packet, then ask the routing function for the best output
2943 // interface's address
2944 Ipv6Header header;
2946 Socket::SocketErrno errno_;
2947 Ptr<Ipv6Route> route;
2949 route = ipv6->GetRoutingProtocol()->RouteOutput(Ptr<Packet>(), header, oif, errno_);
2950 if (!route)
2951 {
2952 NS_LOG_LOGIC("Route to " << m_endPoint6->GetPeerAddress() << " does not exist");
2953 NS_LOG_ERROR(errno_);
2954 m_errno = errno_;
2955 return -1;
2956 }
2957 NS_LOG_LOGIC("Route exists");
2958 m_endPoint6->SetLocalAddress(route->GetSource());
2959 return 0;
2960}
2961
2962/* This function is called only if a SYN received in LISTEN state. After
2963 TcpSocketBase cloned, allocate a new end point to handle the incoming
2964 connection and send a SYN+ACK to complete the handshake. */
2965void
2967 const TcpHeader& h,
2968 const Address& fromAddress,
2969 const Address& toAddress)
2970{
2971 NS_LOG_FUNCTION(this << p << h << fromAddress << toAddress);
2972 // Get port and address from peer (connecting host)
2973 if (InetSocketAddress::IsMatchingType(toAddress))
2974 {
2975 m_endPoint = m_tcp->Allocate(GetBoundNetDevice(),
2976 InetSocketAddress::ConvertFrom(toAddress).GetIpv4(),
2977 InetSocketAddress::ConvertFrom(toAddress).GetPort(),
2978 InetSocketAddress::ConvertFrom(fromAddress).GetIpv4(),
2979 InetSocketAddress::ConvertFrom(fromAddress).GetPort());
2980 m_endPoint6 = nullptr;
2981 }
2982 else if (Inet6SocketAddress::IsMatchingType(toAddress))
2983 {
2984 m_endPoint6 = m_tcp->Allocate6(GetBoundNetDevice(),
2985 Inet6SocketAddress::ConvertFrom(toAddress).GetIpv6(),
2986 Inet6SocketAddress::ConvertFrom(toAddress).GetPort(),
2987 Inet6SocketAddress::ConvertFrom(fromAddress).GetIpv6(),
2988 Inet6SocketAddress::ConvertFrom(fromAddress).GetPort());
2989 m_endPoint = nullptr;
2990 }
2991 m_tcp->AddSocket(this);
2992
2993 // Change the cloned socket from LISTEN state to SYN_RCVD
2994 NS_LOG_DEBUG("LISTEN -> SYN_RCVD");
2995 m_state = SYN_RCVD;
2998 SetupCallback();
2999 // Set the sequence number and send SYN+ACK
3000 m_tcb->m_rxBuffer->SetNextRxSequence(h.GetSequenceNumber() + SequenceNumber32(1));
3001
3002 /* Check if we received an ECN SYN packet. Change the ECN state of receiver to ECN_IDLE if
3003 * sender has sent an ECN SYN packet and the traffic is ECN Capable
3004 */
3007 {
3011 }
3012 else
3013 {
3016 }
3017}
3018
3019void
3021{ // Wrapper to protected function NotifyConnectionSucceeded() so that it can
3022 // be called as a scheduled event
3024 // The if-block below was moved from ProcessSynSent() to here because we need
3025 // to invoke the NotifySend() only after NotifyConnectionSucceeded() to
3026 // reflect the behaviour in the real world.
3027 if (GetTxAvailable() > 0)
3028 {
3030 }
3031}
3032
3033void
3035{
3036 /*
3037 * Add tags for each socket option.
3038 * Note that currently the socket adds both IPv4 tag and IPv6 tag
3039 * if both options are set. Once the packet got to layer three, only
3040 * the corresponding tags will be read.
3041 */
3042 if (GetIpTos())
3043 {
3044 SocketIpTosTag ipTosTag;
3046 {
3048 }
3049 else
3050 {
3051 // Set the last received ipTos
3052 ipTosTag.SetTos(GetIpTos());
3053 }
3054 p->AddPacketTag(ipTosTag);
3055 }
3056 else
3057 {
3058 if ((m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && p->GetSize() > 0) ||
3060 {
3061 SocketIpTosTag ipTosTag;
3063 p->AddPacketTag(ipTosTag);
3064 }
3065 }
3066
3067 if (IsManualIpv6Tclass())
3068 {
3069 SocketIpv6TclassTag ipTclassTag;
3071 {
3073 }
3074 else
3075 {
3076 // Set the last received ipTos
3077 ipTclassTag.SetTclass(GetIpv6Tclass());
3078 }
3079 p->AddPacketTag(ipTclassTag);
3080 }
3081 else
3082 {
3083 if ((m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && p->GetSize() > 0) ||
3085 {
3086 SocketIpv6TclassTag ipTclassTag;
3088 p->AddPacketTag(ipTclassTag);
3089 }
3090 }
3091
3092 if (IsManualIpTtl())
3093 {
3094 SocketIpTtlTag ipTtlTag;
3095 ipTtlTag.SetTtl(GetIpTtl());
3096 p->AddPacketTag(ipTtlTag);
3097 }
3098
3100 {
3101 SocketIpv6HopLimitTag ipHopLimitTag;
3102 ipHopLimitTag.SetHopLimit(GetIpv6HopLimit());
3103 p->AddPacketTag(ipHopLimitTag);
3104 }
3105
3106 uint8_t priority = GetPriority();
3107 if (priority)
3108 {
3109 SocketPriorityTag priorityTag;
3110 priorityTag.SetPriority(priority);
3111 p->ReplacePacketTag(priorityTag);
3112 }
3113}
3114
3115/* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the
3116 TCP header, and send to TcpL4Protocol */
3119{
3120 NS_LOG_FUNCTION(this << seq << maxSize << withAck);
3121
3122 bool isStartOfTransmission = BytesInFlight() == 0U;
3123 TcpTxItem* outItem = m_txBuffer->CopyFromSequence(maxSize, seq);
3124
3125 m_rateOps->SkbSent(outItem, isStartOfTransmission);
3126
3127 bool isRetransmission = outItem->IsRetrans();
3128 Ptr<Packet> p = outItem->GetPacketCopy();
3129 uint32_t sz = p->GetSize(); // Size of packet
3130 uint8_t flags = withAck ? TcpHeader::ACK : 0;
3131 uint32_t remainingData = m_txBuffer->SizeFromSequence(seq + SequenceNumber32(sz));
3132
3133 // TCP sender should not send data out of the window advertised by the
3134 // peer when it is not retransmission.
3135 NS_ASSERT(isRetransmission ||
3136 ((m_highRxAckMark + SequenceNumber32(m_rWnd)) >= (seq + SequenceNumber32(maxSize))));
3137
3138 if (IsPacingEnabled())
3139 {
3140 NS_LOG_INFO("Pacing is enabled");
3142 {
3143 NS_LOG_DEBUG("Current Pacing Rate " << m_tcb->m_pacingRate);
3144 NS_LOG_DEBUG("Timer is in expired state, activate it "
3145 << m_tcb->m_pacingRate.Get().CalculateBytesTxTime(sz));
3146 m_pacingTimer.Schedule(m_tcb->m_pacingRate.Get().CalculateBytesTxTime(sz));
3147 }
3148 else
3149 {
3150 NS_LOG_INFO("Timer is already in running state");
3151 }
3152 }
3153 else
3154 {
3155 NS_LOG_INFO("Pacing is disabled");
3156 }
3157
3158 if (withAck)
3159 {
3161 m_delAckCount = 0;
3162 }
3163
3165 m_ecnEchoSeq.Get() > m_ecnCWRSeq.Get() && !isRetransmission)
3166 {
3169 m_ecnCWRSeq = seq;
3170 flags |= TcpHeader::CWR;
3171 NS_LOG_INFO("CWR flags set");
3172 }
3173
3174 AddSocketTags(p);
3175
3176 if (m_closeOnEmpty && (remainingData == 0))
3177 {
3178 flags |= TcpHeader::FIN;
3179 if (m_state == ESTABLISHED)
3180 { // On active close: I am the first one to send FIN
3181 NS_LOG_DEBUG("ESTABLISHED -> FIN_WAIT_1");
3183 }
3184 else if (m_state == CLOSE_WAIT)
3185 { // On passive close: Peer sent me FIN already
3186 NS_LOG_DEBUG("CLOSE_WAIT -> LAST_ACK");
3187 m_state = LAST_ACK;
3188 }
3189 }
3190 TcpHeader header;
3191 header.SetFlags(flags);
3192 header.SetSequenceNumber(seq);
3193 header.SetAckNumber(m_tcb->m_rxBuffer->NextRxSequence());
3194 if (m_endPoint)
3195 {
3198 }
3199 else
3200 {
3203 }
3205 AddOptions(header);
3206
3207 if (m_retxEvent.IsExpired())
3208 {
3209 // Schedules retransmit timeout. m_rto should be already doubled.
3210
3211 NS_LOG_LOGIC(this << " SendDataPacket Schedule ReTxTimeout at time "
3212 << Simulator::Now().GetSeconds() << " to expire at time "
3213 << (Simulator::Now() + m_rto.Get()).GetSeconds());
3215 }
3216
3217 m_txTrace(p, header, this);
3218
3219 if (m_endPoint)
3220 {
3221 m_tcp->SendPacket(p,
3222 header,
3226 NS_LOG_DEBUG("Send segment of size "
3227 << sz << " with remaining data " << remainingData << " via TcpL4Protocol to "
3228 << m_endPoint->GetPeerAddress() << ". Header " << header);
3229 }
3230 else
3231 {
3232 m_tcp->SendPacket(p,
3233 header,
3237 NS_LOG_DEBUG("Send segment of size "
3238 << sz << " with remaining data " << remainingData << " via TcpL4Protocol to "
3239 << m_endPoint6->GetPeerAddress() << ". Header " << header);
3240 }
3241
3242 UpdateRttHistory(seq, sz, isRetransmission);
3243
3244 // Update bytes sent during recovery phase
3247 {
3248 m_recoveryOps->UpdateBytesSent(sz);
3249 }
3250
3251 // Notify the application of the data being sent unless this is a retransmit
3252 if (!isRetransmission)
3253 {
3255 this,
3256 (seq + sz - m_tcb->m_highTxMark.Get()));
3257 }
3258 // Update highTxMark
3259 m_tcb->m_highTxMark = std::max(seq + sz, m_tcb->m_highTxMark.Get());
3260 return sz;
3261}
3262
3263void
3264TcpSocketBase::UpdateRttHistory(const SequenceNumber32& seq, uint32_t sz, bool isRetransmission)
3265{
3266 NS_LOG_FUNCTION(this);
3267
3268 // update the history of sequence numbers used to calculate the RTT
3269 if (!isRetransmission)
3270 { // This is the next expected one, just log at end
3271 m_history.emplace_back(seq, sz, Simulator::Now());
3272 }
3273 else
3274 { // This is a retransmit, find in list and mark as re-tx
3275 for (std::deque<RttHistory>::iterator i = m_history.begin(); i != m_history.end(); ++i)
3276 {
3277 if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32(i->count))))
3278 { // Found it
3279 i->retx = true;
3280 i->count = ((seq + SequenceNumber32(sz)) - i->seq); // And update count in hist
3281 break;
3282 }
3283 }
3284 }
3285}
3286
3287// Note that this function did not implement the PSH flag
3290{
3291 NS_LOG_FUNCTION(this << withAck);
3292 if (m_txBuffer->Size() == 0)
3293 {
3294 return false; // Nothing to send
3295 }
3296 if (m_endPoint == nullptr && m_endPoint6 == nullptr)
3297 {
3299 "TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
3300 return false; // Is this the right way to handle this condition?
3301 }
3302
3303 uint32_t nPacketsSent = 0;
3304 uint32_t availableWindow = AvailableWindow();
3305
3306 // RFC 6675, Section (C)
3307 // If cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more
3308 // segments as follows:
3309 // (NOTE: We check > 0, and do the checks for segmentSize in the following
3310 // else branch to control silly window syndrome and Nagle)
3311 while (availableWindow > 0)
3312 {
3313 if (IsPacingEnabled())
3314 {
3315 NS_LOG_INFO("Pacing is enabled");
3317 {
3318 NS_LOG_INFO("Skipping Packet due to pacing" << m_pacingTimer.GetDelayLeft());
3319 break;
3320 }
3321 NS_LOG_INFO("Timer is not running");
3322 }
3323
3325 {
3326 NS_LOG_INFO("FIN_WAIT and OPEN state; no data to transmit");
3327 break;
3328 }
3329 // (C.1) The scoreboard MUST be queried via NextSeg () for the
3330 // sequence number range of the next segment to transmit (if
3331 // any), and the given segment sent. If NextSeg () returns
3332 // failure (no data to send), return without sending anything
3333 // (i.e., terminate steps C.1 -- C.5).
3334 SequenceNumber32 next;
3335 SequenceNumber32 nextHigh;
3337 if (!m_txBuffer->NextSeg(&next, &nextHigh, enableRule3))
3338 {
3339 NS_LOG_INFO("no valid seq to transmit, or no data available");
3340 break;
3341 }
3342 else
3343 {
3344 // It's time to transmit, but before do silly window and Nagle's check
3345 uint32_t availableData = m_txBuffer->SizeFromSequence(next);
3346
3347 // If there's less app data than the full window, ask the app for more
3348 // data before trying to send
3349 if (availableData < availableWindow)
3350 {
3352 }
3353
3354 // Stop sending if we need to wait for a larger Tx window (prevent silly window
3355 // syndrome) but continue if we don't have data
3356 if (availableWindow < m_tcb->m_segmentSize && availableData > availableWindow)
3357 {
3358 NS_LOG_LOGIC("Preventing Silly Window Syndrome. Wait to send.");
3359 break; // No more
3360 }
3361 // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
3362 // in the buffer and the amount of data to send is less than one segment
3363 if (!m_noDelay && UnAckDataCount() > 0 && availableData < m_tcb->m_segmentSize)
3364 {
3365 NS_LOG_DEBUG("Invoking Nagle's algorithm for seq "
3366 << next << ", SFS: " << m_txBuffer->SizeFromSequence(next)
3367 << ". Wait to send.");
3368 break;
3369 }
3370
3371 uint32_t s = std::min(availableWindow, m_tcb->m_segmentSize);
3372 // NextSeg () may have further constrained the segment size
3373 uint32_t maxSizeToSend = static_cast<uint32_t>(nextHigh - next);
3374 s = std::min(s, maxSizeToSend);
3375
3376 // (C.2) If any of the data octets sent in (C.1) are below HighData,
3377 // HighRxt MUST be set to the highest sequence number of the
3378 // retransmitted segment unless NextSeg () rule (4) was
3379 // invoked for this retransmission.
3380 // (C.3) If any of the data octets sent in (C.1) are above HighData,
3381 // HighData must be updated to reflect the transmission of
3382 // previously unsent data.
3383 //
3384 // These steps are done in m_txBuffer with the tags.
3385 if (m_tcb->m_nextTxSequence != next)
3386 {
3387 m_tcb->m_nextTxSequence = next;
3388 }
3389 if (m_tcb->m_bytesInFlight.Get() == 0)
3390 {
3392 }
3393 uint32_t sz = SendDataPacket(m_tcb->m_nextTxSequence, s, withAck);
3394
3395 NS_LOG_LOGIC(" rxwin " << m_rWnd << " segsize " << m_tcb->m_segmentSize
3396 << " highestRxAck " << m_txBuffer->HeadSequence() << " pd->Size "
3397 << m_txBuffer->Size() << " pd->SFS "
3398 << m_txBuffer->SizeFromSequence(m_tcb->m_nextTxSequence));
3399
3400 NS_LOG_DEBUG("cWnd: " << m_tcb->m_cWnd << " total unAck: " << UnAckDataCount()
3401 << " sent seq " << m_tcb->m_nextTxSequence << " size " << sz);
3402 m_tcb->m_nextTxSequence += sz;
3403 ++nPacketsSent;
3404 if (IsPacingEnabled())
3405 {
3406 NS_LOG_INFO("Pacing is enabled");
3408 {
3409 NS_LOG_DEBUG("Current Pacing Rate " << m_tcb->m_pacingRate);
3410 NS_LOG_DEBUG("Timer is in expired state, activate it "
3411 << m_tcb->m_pacingRate.Get().CalculateBytesTxTime(sz));
3412 m_pacingTimer.Schedule(m_tcb->m_pacingRate.Get().CalculateBytesTxTime(sz));
3413 break;
3414 }
3415 }
3416 }
3417
3418 // (C.4) The estimate of the amount of data outstanding in the
3419 // network must be updated by incrementing pipe by the number
3420 // of octets transmitted in (C.1).
3421 //
3422 // Done in BytesInFlight, inside AvailableWindow.
3423 availableWindow = AvailableWindow();
3424
3425 // (C.5) If cwnd - pipe >= 1 SMSS, return to (C.1)
3426 // loop again!
3427 }
3428
3429 if (nPacketsSent > 0)
3430 {
3431 if (!m_sackEnabled)
3432 {
3433 if (!m_limitedTx)
3434 {
3435 // We can't transmit in CA_DISORDER without limitedTx active
3437 }
3438 }
3439
3440 NS_LOG_DEBUG("SendPendingData sent " << nPacketsSent << " segments");
3441 }
3442 else
3443 {
3444 NS_LOG_DEBUG("SendPendingData no segments sent");
3445 }
3446 return nPacketsSent;
3447}
3448
3451{
3452 return m_tcb->m_highTxMark - m_txBuffer->HeadSequence();
3453}
3454
3457{
3458 uint32_t bytesInFlight = m_txBuffer->BytesInFlight();
3459 // Ugly, but we are not modifying the state; m_bytesInFlight is used
3460 // only for tracing purpose.
3461 m_tcb->m_bytesInFlight = bytesInFlight;
3462
3463 NS_LOG_DEBUG("Returning calculated bytesInFlight: " << bytesInFlight);
3464 return bytesInFlight;
3465}
3466
3469{
3470 return std::min(m_rWnd.Get(), m_tcb->m_cWnd.Get());
3471}
3472
3475{
3476 uint32_t win = Window(); // Number of bytes allowed to be outstanding
3477 uint32_t inflight = BytesInFlight(); // Number of outstanding bytes
3478 return (inflight > win) ? 0 : win - inflight;
3479}
3480
3481uint16_t
3483{
3484 NS_LOG_FUNCTION(this << scale);
3485 uint32_t w;
3486
3487 // We don't want to advertise 0 after a FIN is received. So, we just use
3488 // the previous value of the advWnd.
3489 if (m_tcb->m_rxBuffer->GotFin())
3490 {
3491 w = m_advWnd;
3492 }
3493 else
3494 {
3495 NS_ASSERT_MSG(m_tcb->m_rxBuffer->MaxRxSequence() - m_tcb->m_rxBuffer->NextRxSequence() >= 0,
3496 "Unexpected sequence number values");
3497 w = static_cast<uint32_t>(m_tcb->m_rxBuffer->MaxRxSequence() -
3498 m_tcb->m_rxBuffer->NextRxSequence());
3499 }
3500
3501 // Ugly, but we are not modifying the state, that variable
3502 // is used only for tracing purpose.
3503 if (w != m_advWnd)
3504 {
3505 const_cast<TcpSocketBase*>(this)->m_advWnd = w;
3506 }
3507 if (scale)
3508 {
3509 w >>= m_rcvWindShift;
3510 }
3511 if (w > m_maxWinSize)
3512 {
3513 w = m_maxWinSize;
3514 NS_LOG_WARN("Adv window size truncated to "
3515 << m_maxWinSize << "; possibly to avoid overflow of the 16-bit integer");
3516 }
3517 NS_LOG_LOGIC("Returning AdvertisedWindowSize of " << static_cast<uint16_t>(w));
3518 return static_cast<uint16_t>(w);
3519}
3520
3521// Receipt of new packet, put into Rx buffer
3522void
3524{
3525 NS_LOG_FUNCTION(this << tcpHeader);
3526 NS_LOG_DEBUG("Data segment, seq=" << tcpHeader.GetSequenceNumber()
3527 << " pkt size=" << p->GetSize());
3528
3529 // Put into Rx buffer
3530 SequenceNumber32 expectedSeq = m_tcb->m_rxBuffer->NextRxSequence();
3531 if (!m_tcb->m_rxBuffer->Add(p, tcpHeader))
3532 { // Insert failed: No data or RX buffer full
3535 {
3537 NS_LOG_DEBUG(TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3539 }
3540 else
3541 {
3543 }
3544 return;
3545 }
3546 // Notify app to receive if necessary
3547 if (expectedSeq < m_tcb->m_rxBuffer->NextRxSequence())
3548 { // NextRxSeq advanced, we have something to send to the app
3549 if (!m_shutdownRecv)
3550 {
3552 }
3553 // Handle exceptions
3554 if (m_closeNotified)
3555 {
3556 NS_LOG_WARN("Why TCP " << this << " got data after close notification?");
3557 }
3558 // If we received FIN before and now completed all "holes" in rx buffer,
3559 // invoke peer close procedure
3560 if (m_tcb->m_rxBuffer->Finished() && (tcpHeader.GetFlags() & TcpHeader::FIN) == 0)
3561 {
3562 DoPeerClose();
3563 return;
3564 }
3565 }
3566 // Now send a new ACK packet acknowledging all received and delivered data
3567 if (m_tcb->m_rxBuffer->Size() > m_tcb->m_rxBuffer->Available() ||
3568 m_tcb->m_rxBuffer->NextRxSequence() > expectedSeq + p->GetSize())
3569 { // A gap exists in the buffer, or we filled a gap: Always ACK
3573 {
3575 NS_LOG_DEBUG(TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
3577 }
3578 else
3579 {
3581 }
3582 }
3583 else
3584 { // In-sequence packet: ACK if delayed ack count allows
3586 {
3588 m_delAckCount = 0;
3592 {
3593 NS_LOG_DEBUG("Congestion algo " << m_congestionControl->GetName());
3596 << " -> ECN_SENDING_ECE");
3598 }
3599 else
3600 {
3602 }
3603 }
3604 else if (!m_delAckEvent.IsExpired())
3605 {
3607 }
3608 else if (m_delAckEvent.IsExpired())
3609 {
3614 this << " scheduled delayed ACK at "
3616 }
3617 }
3618}
3619
3620void
3622{
3623 SequenceNumber32 ackSeq = tcpHeader.GetAckNumber();
3624 Time m = Time(0.0);
3625
3626 // An ack has been received, calculate rtt and log this measurement
3627 // Note we use a linear search (O(n)) for this since for the common
3628 // case the ack'ed packet will be at the head of the list
3629 if (!m_history.empty())
3630 {
3631 RttHistory& h = m_history.front();
3632 if (!h.retx && ackSeq >= (h.seq + SequenceNumber32(h.count)))
3633 { // Ok to use this sample
3634 if (m_timestampEnabled && tcpHeader.HasOption(TcpOption::TS))
3635 {
3637 ts = DynamicCast<const TcpOptionTS>(tcpHeader.GetOption(TcpOption::TS));
3638 m = TcpOptionTS::ElapsedTimeFromTsValue(ts->GetEcho());
3639 if (m.IsZero())
3640 {
3641 NS_LOG_LOGIC("TcpSocketBase::EstimateRtt - RTT calculated from TcpOption::TS "
3642 "is zero, approximating to 1us.");
3643 m = MicroSeconds(1);
3644 }
3645 }
3646 else
3647 {
3648 m = Simulator::Now() - h.time; // Elapsed time
3649 }
3650 }
3651 }
3652
3653 // Now delete all ack history with seq <= ack
3654 while (!m_history.empty())
3655 {
3656 RttHistory& h = m_history.front();
3657 if ((h.seq + SequenceNumber32(h.count)) > ackSeq)
3658 {
3659 break; // Done removing
3660 }
3661 m_history.pop_front(); // Remove
3662 }
3663
3664 if (!m.IsZero())
3665 {
3666 m_rtt->Measurement(m); // Log the measurement
3667 // RFC 6298, clause 2.4
3668 m_rto = Max(m_rtt->GetEstimate() + Max(m_clockGranularity, m_rtt->GetVariation() * 4),
3669 m_minRto);
3670 m_tcb->m_lastRtt = m_rtt->GetEstimate();
3671 m_tcb->m_minRtt = std::min(m_tcb->m_lastRtt.Get(), m_tcb->m_minRtt);
3673 }
3674}
3675
3676// Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
3677// when the three-way handshake completed. This cancels retransmission timer
3678// and advances Tx window
3679void
3680TcpSocketBase::NewAck(const SequenceNumber32& ack, bool resetRTO)
3681{
3682 NS_LOG_FUNCTION(this << ack);
3683
3684 // Reset the data retransmission count. We got a new ACK!
3686
3687 if (m_state != SYN_RCVD && resetRTO)
3688 { // Set RTO unless the ACK is received in SYN_RCVD state
3690 this << " Cancelled ReTxTimeout event which was set to expire at "
3691 << (Simulator::Now() + Simulator::GetDelayLeft(m_retxEvent)).GetSeconds());
3693 // On receiving a "New" ack we restart retransmission timer .. RFC 6298
3694 // RFC 6298, clause 2.4
3695 m_rto = Max(m_rtt->GetEstimate() + Max(m_clockGranularity, m_rtt->GetVariation() * 4),
3696 m_minRto);
3697
3698 NS_LOG_LOGIC(this << " Schedule ReTxTimeout at time " << Simulator::Now().GetSeconds()
3699 << " to expire at time "
3700 << (Simulator::Now() + m_rto.Get()).GetSeconds());
3702 }
3703
3704 // Note the highest ACK and tell app to send more
3705 NS_LOG_LOGIC("TCP " << this << " NewAck " << ack << " numberAck "
3706 << (ack - m_txBuffer->HeadSequence())); // Number bytes ack'ed
3707
3708 if (GetTxAvailable() > 0)
3709 {
3711 }
3712 if (ack > m_tcb->m_nextTxSequence)
3713 {
3714 m_tcb->m_nextTxSequence = ack; // If advanced
3715 }
3716 if (m_txBuffer->Size() == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING)
3717 { // No retransmit timer if no data to retransmit
3719 this << " Cancelled ReTxTimeout event which was set to expire at "
3720 << (Simulator::Now() + Simulator::GetDelayLeft(m_retxEvent)).GetSeconds());
3722 }
3723}
3724
3725// Retransmit timeout
3726void
3728{
3729 NS_LOG_FUNCTION(this);
3730 NS_LOG_LOGIC(this << " ReTxTimeout Expired at time " << Simulator::Now().GetSeconds());
3731 // If erroneous timeout in closed/timed-wait state, just return
3732 if (m_state == CLOSED || m_state == TIME_WAIT)
3733 {
3734 return;
3735 }
3736
3737 if (m_state == SYN_SENT)
3738 {
3739 NS_ASSERT(m_synCount > 0);
3741 {
3743 }
3744 else
3745 {
3747 }
3748 return;
3749 }
3750
3751 // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state
3752 if (m_txBuffer->Size() == 0)
3753 {
3754 if (m_state == FIN_WAIT_1 || m_state == CLOSING)
3755 { // Must have lost FIN, re-send
3757 }
3758 return;
3759 }
3760
3761 NS_LOG_DEBUG("Checking if Connection is Established");
3762 // If all data are received (non-closing socket and nothing to send), just return
3763 if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence() >= m_tcb->m_highTxMark &&
3764 m_txBuffer->Size() == 0)
3765 {
3766 NS_LOG_DEBUG("Already Sent full data" << m_txBuffer->HeadSequence() << " "
3767 << m_tcb->m_highTxMark);
3768 return;
3769 }
3770
3771 if (m_dataRetrCount == 0)
3772 {
3773 NS_LOG_INFO("No more data retries available. Dropping connection");
3776 return;
3777 }
3778 else
3779 {
3781 }
3782
3783 uint32_t inFlightBeforeRto = BytesInFlight();
3784 bool resetSack = !m_sackEnabled; // Reset SACK information if SACK is not enabled.
3785 // The information in the TcpTxBuffer is guessed, in this case.
3786
3787 // Reset dupAckCount
3788 m_dupAckCount = 0;
3789 if (!m_sackEnabled)
3790 {
3791 m_txBuffer->ResetRenoSack();
3792 }
3793
3794 // From RFC 6675, Section 5.1
3795 // [RFC2018] suggests that a TCP sender SHOULD expunge the SACK
3796 // information gathered from a receiver upon a retransmission timeout
3797 // (RTO) "since the timeout might indicate that the data receiver has
3798 // reneged." Additionally, a TCP sender MUST "ignore prior SACK
3799 // information in determining which data to retransmit."
3800 // It has been suggested that, as long as robust tests for
3801 // reneging are present, an implementation can retain and use SACK
3802 // information across a timeout event [Errata1610].
3803 // The head of the sent list will not be marked as sacked, therefore
3804 // will be retransmitted, if the receiver renegotiate the SACK blocks
3805 // that we received.
3806 m_txBuffer->SetSentListLost(resetSack);
3807
3808 // From RFC 6675, Section 5.1
3809 // If an RTO occurs during loss recovery as specified in this document,
3810 // RecoveryPoint MUST be set to HighData. Further, the new value of
3811 // RecoveryPoint MUST be preserved and the loss recovery algorithm
3812 // outlined in this document MUST be terminated.
3814 m_recoverActive = true;
3815
3816 // RFC 6298, clause 2.5, double the timer
3817 Time doubledRto = m_rto + m_rto;
3818 m_rto = Min(doubledRto, Time::FromDouble(60, Time::S));
3819
3820 // Empty RTT history
3821 m_history.clear();
3822
3823 // Please don't reset highTxMark, it is used for retransmission detection
3824
3825 // When a TCP sender detects segment loss using the retransmission timer
3826 // and the given segment has not yet been resent by way of the
3827 // retransmission timer, decrease ssThresh
3828 if (m_tcb->m_congState != TcpSocketState::CA_LOSS || !m_txBuffer->IsHeadRetransmitted())
3829 {
3830 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh(m_tcb, inFlightBeforeRto);
3831 }
3832
3833 // Cwnd set to 1 MSS
3839
3841
3842 NS_LOG_DEBUG("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " << m_tcb->m_ssThresh
3843 << ", restart from seqnum " << m_txBuffer->HeadSequence()
3844 << " doubled rto to " << m_rto.Get().GetSeconds() << " s");
3845
3847 "There are some bytes in flight after an RTO: " << BytesInFlight());
3848
3850
3852 "In flight (" << BytesInFlight() << ") there is more than one segment ("
3853 << m_tcb->m_segmentSize << ")");
3854}
3855
3856void
3858{
3859 m_delAckCount = 0;
3863 {
3866 }
3867 else
3868 {
3870 }
3871}
3872
3873void
3875{
3876 NS_LOG_FUNCTION(this);
3877
3879 if (m_state == LAST_ACK)
3880 {
3881 if (m_dataRetrCount == 0)
3882 {
3883 NS_LOG_INFO("LAST-ACK: No more data retries available. Dropping connection");
3886 return;
3887 }
3890 NS_LOG_LOGIC("TcpSocketBase " << this << " rescheduling LATO1");
3891 Time lastRto = m_rtt->GetEstimate() + Max(m_clockGranularity, m_rtt->GetVariation() * 4);
3893 }
3894}
3895
3896// Send 1-byte data to probe for the window size at the receiver when
3897// the local knowledge tells that the receiver has zero window size
3898// C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17
3899void
3901{
3902 NS_LOG_LOGIC("PersistTimeout expired at " << Simulator::Now().GetSeconds());
3904 std::min(Seconds(60), Time(2 * m_persistTimeout)); // max persist timeout = 60s
3905 Ptr<Packet> p = m_txBuffer->CopyFromSequence(1, m_tcb->m_nextTxSequence)->GetPacketCopy();
3906 m_txBuffer->ResetLastSegmentSent();
3907 TcpHeader tcpHeader;
3909 tcpHeader.SetAckNumber(m_tcb->m_rxBuffer->NextRxSequence());
3911 if (m_endPoint != nullptr)
3912 {
3915 }
3916 else
3917 {
3920 }
3921 AddOptions(tcpHeader);
3922 // Send a packet tag for setting ECT bits in IP header
3924 {
3925 SocketIpTosTag ipTosTag;
3927 p->AddPacketTag(ipTosTag);
3928
3929 SocketIpv6TclassTag ipTclassTag;
3931 p->AddPacketTag(ipTclassTag);
3932 }
3933 m_txTrace(p, tcpHeader, this);
3934
3935 if (m_endPoint != nullptr)
3936 {
3937 m_tcp->SendPacket(p,
3938 tcpHeader,
3942 }
3943 else
3944 {
3945 m_tcp->SendPacket(p,
3946 tcpHeader,
3950 }
3951
3952 NS_LOG_LOGIC("Schedule persist timeout at time "
3953 << Simulator::Now().GetSeconds() << " to expire at time "
3954 << (Simulator::Now() + m_persistTimeout).GetSeconds());
3956}
3957
3958void
3960{
3961 NS_LOG_FUNCTION(this);
3962 bool res;
3963 SequenceNumber32 seq;
3964 SequenceNumber32 seqHigh;
3965 uint32_t maxSizeToSend;
3966
3967 // Find the first segment marked as lost and not retransmitted. With Reno,
3968 // that should be the head
3969 res = m_txBuffer->NextSeg(&seq, &seqHigh, false);
3970 if (!res)
3971 {
3972 // We have already retransmitted the head. However, we still received
3973 // three dupacks, or the RTO expired, but no data to transmit.
3974 // Therefore, re-send again the head.
3975 seq = m_txBuffer->HeadSequence();
3976 maxSizeToSend = m_tcb->m_segmentSize;
3977 }
3978 else
3979 {
3980 // NextSeg() may constrain the segment size when res is true
3981 maxSizeToSend = static_cast<uint32_t>(seqHigh - seq);
3982 }
3983 NS_ASSERT(m_sackEnabled || seq == m_txBuffer->HeadSequence());
3984
3985 NS_LOG_INFO("Retransmitting " << seq);
3986 // Update the trace and retransmit the segment
3987 m_tcb->m_nextTxSequence = seq;
3988 uint32_t sz = SendDataPacket(m_tcb->m_nextTxSequence, maxSizeToSend, true);
3989
3990 NS_ASSERT(sz > 0);
3991}
3992
3993void
3995{
4003}
4004
4005/* Move TCP to Time_Wait state and schedule a transition to Closed state */
4006void
4008{
4009 NS_LOG_DEBUG(TcpStateName[m_state] << " -> TIME_WAIT");
4012 if (!m_closeNotified)
4013 {
4014 // Technically the connection is not fully closed, but we notify now
4015 // because an implementation (real socket) would behave as if closed.
4016 // Notify normal close when entering TIME_WAIT or leaving LAST_ACK.
4018 m_closeNotified = true;
4019 }
4020 // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
4021 // according to RFC793, p.28
4023}
4024
4025/* Below are the attribute get/set functions */
4026
4027void
4029{
4030 NS_LOG_FUNCTION(this << size);
4031 m_txBuffer->SetMaxBufferSize(size);
4032}
4033
4036{
4037 return m_txBuffer->MaxBufferSize();
4038}
4039
4040void
4042{
4043 NS_LOG_FUNCTION(this << size);
4044 uint32_t oldSize = GetRcvBufSize();
4045
4046 m_tcb->m_rxBuffer->SetMaxBufferSize(size);
4047
4048 /* The size has (manually) increased. Actively inform the other end to prevent
4049 * stale zero-window states.
4050 */
4051 if (oldSize < size && m_connected)
4052 {
4055 {
4057 NS_LOG_DEBUG(TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_SENDING_ECE");
4059 }
4060 else
4061 {
4063 }
4064 }
4065}
4066
4069{
4070 return m_tcb->m_rxBuffer->MaxBufferSize();
4071}
4072
4073void
4075{
4076 NS_LOG_FUNCTION(this << size);
4077 m_tcb->m_segmentSize = size;
4078 m_txBuffer->SetSegmentSize(size);
4079
4080 NS_ABORT_MSG_UNLESS(m_state == CLOSED, "Cannot change segment size dynamically.");
4081}
4082
4085{
4086 return m_tcb->m_segmentSize;
4087}
4088
4089void
4091{
4092 NS_LOG_FUNCTION(this << timeout);
4094}
4095
4096Time
4098{
4099 return m_cnTimeout;
4100}
4101
4102void
4104{
4105 NS_LOG_FUNCTION(this << count);
4106 m_synRetries = count;
4107}
4108
4111{
4112 return m_synRetries;
4113}
4114
4115void
4117{
4118 NS_LOG_FUNCTION(this << retries);
4119 m_dataRetries = retries;
4120}
4121
4124{
4125 NS_LOG_FUNCTION(this);
4126 return m_dataRetries;
4127}
4128
4129void
4131{
4132 NS_LOG_FUNCTION(this << timeout);
4134}
4135
4136Time
4138{
4139 return m_delAckTimeout;
4140}
4141
4142void
4144{
4145 NS_LOG_FUNCTION(this << count);
4146 m_delAckMaxCount = count;
4147}
4148
4151{
4152 return m_delAckMaxCount;
4153}
4154
4155void
4157{
4158 NS_LOG_FUNCTION(this << noDelay);
4159 m_noDelay = noDelay;
4160}
4161
4162bool
4164{
4165 return m_noDelay;
4166}
4167
4168void
4170{
4171 NS_LOG_FUNCTION(this << timeout);
4173}
4174
4175Time
4177{
4178 return m_persistTimeout;
4179}
4180
4181bool
4183{
4184 // Broadcast is not implemented. Return true only if allowBroadcast==false
4185 return (!allowBroadcast);
4186}
4187
4188bool
4190{
4191 return false;
4192}
4193
4194void
4196{
4197 NS_LOG_FUNCTION(this << header);
4198
4200 {
4201 AddOptionTimestamp(header);
4202 }
4203}
4204
4205void
4207{
4208 NS_LOG_FUNCTION(this << option);
4209
4210 Ptr<const TcpOptionWinScale> ws = DynamicCast<const TcpOptionWinScale>(option);
4211
4212 // In naming, we do the contrary of RFC 1323. The received scaling factor
4213 // is Rcv.Wind.Scale (and not Snd.Wind.Scale)
4214 m_sndWindShift = ws->GetScale();
4215
4216 if (m_sndWindShift > 14)
4217 {
4218 NS_LOG_WARN("Possible error; m_sndWindShift exceeds 14: " << m_sndWindShift);
4219 m_sndWindShift = 14;
4220 }
4221
4222 NS_LOG_INFO(m_node->GetId() << " Received a scale factor of "
4223 << static_cast<int>(m_sndWindShift));
4224}
4225
4226uint8_t
4228{
4229 NS_LOG_FUNCTION(this);
4230 uint32_t maxSpace = m_tcb->m_rxBuffer->MaxBufferSize();
4231 uint8_t scale = 0;
4232
4233 while (maxSpace > m_maxWinSize)
4234 {
4235 maxSpace = maxSpace >> 1;
4236 ++scale;
4237 }
4238
4239 if (scale > 14)
4240 {
4241 NS_LOG_WARN("Possible error; scale exceeds 14: " << scale);
4242 scale = 14;
4243 }
4244
4245 NS_LOG_INFO("Node " << m_node->GetId() << " calculated wscale factor of "
4246 << static_cast<int>(scale) << " for buffer size "
4247 << m_tcb->m_rxBuffer->MaxBufferSize());
4248 return scale;
4249}
4250
4251void
4253{
4254 NS_LOG_FUNCTION(this << header);
4255 NS_ASSERT(header.GetFlags() & TcpHeader::SYN);
4256
4257 Ptr<TcpOptionWinScale> option = CreateObject<TcpOptionWinScale>();
4258
4259 // In naming, we do the contrary of RFC 1323. The sended scaling factor
4260 // is Snd.Wind.Scale (and not Rcv.Wind.Scale)
4261
4263 option->SetScale(m_rcvWindShift);
4264
4265 header.AppendOption(option);
4266
4267 NS_LOG_INFO(m_node->GetId() << " Send a scaling factor of "
4268 << static_cast<int>(m_rcvWindShift));
4269}
4270
4273{
4274 NS_LOG_FUNCTION(this << option);
4275
4276 Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack>(option);
4277 return m_txBuffer->Update(s->GetSackList(), MakeCallback(&TcpRateOps::SkbDelivered, m_rateOps));
4278}
4279
4280void
4282{
4283 NS_LOG_FUNCTION(this << option);
4284
4285 Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted>(option);
4286
4287 NS_ASSERT(m_sackEnabled == true);
4288 NS_LOG_INFO(m_node->GetId() << " Received a SACK_PERMITTED option " << s);
4289}
4290
4291void
4293{
4294 NS_LOG_FUNCTION(this << header);
4295 NS_ASSERT(header.GetFlags() & TcpHeader::SYN);
4296
4297 Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted>();
4298 header.AppendOption(option);
4299 NS_LOG_INFO(m_node->GetId() << " Add option SACK-PERMITTED");
4300}
4301
4302void
4304{
4305 NS_LOG_FUNCTION(this << header);
4306
4307 // Calculate the number of SACK blocks allowed in this packet
4308