A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-loss-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Tom Henderson
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include "tcp-general-test.h"
8
9#include "ns3/error-model.h"
10#include "ns3/log.h"
11
12#include <list>
13
14using namespace ns3;
15
16NS_LOG_COMPONENT_DEFINE("TcpLossTestSuite");
17
18/**
19 * \ingroup internet-test
20 *
21 * \brief Check rollover of sequence number and how that affects loss recovery
22 *
23 * This test checks that fast recovery is entered correctly even if it has
24 * been a long time since the last recovery event. Merge request !156
25 * reported the error and fixed the issue with large transfers.
26 *
27 * The issue reported is that fast recovery detection relies on comparing
28 * the sequence number against the last recovery point, maintained by
29 * an 'm_recover' variable. The sequence number is a 32-bit value that
30 * wraps, so the comparison of 'is current sequence number > m_recover'
31 * will work for only about half of the 32-bit sequence space. This
32 * test confirms that the above inequality will correctly evaluate even if
33 * the current sequence number is greater than half of the sequence space
34 * above m_recover.
35 *
36 * The test configures a large bandwidth, long flow (to wrap the sequence
37 * space) and inserts two forced losses. In the first test case, the two
38 * sequence numbers are close in sequence; we expect to see the TCP
39 * implementation cycle between CA_OPEN->CA_DISORDER->CA_RECOVERY->CA_OPEN.
40 * We also check in the second case when the two sequence numbers are far
41 * apart (more than half) in the sequence space.
42 */
44{
45 public:
46 /**
47 * \brief Constructor
48 *
49 * \param firstLoss First packet number to force loss
50 * \param secondLoss Second packet number to force loss
51 * \param lastSegment Last packet number to transmit
52 * \param desc Description about the test
53 */
55 uint32_t secondLoss,
56 uint32_t lastSegment,
57 const std::string& desc);
58
59 protected:
60 void ConfigureProperties() override;
61 void ConfigureEnvironment() override;
62 void FinalChecks() override;
63 void Tx(const Ptr<const Packet> p, const TcpHeader& h, SocketWho who) override;
64 void Rx(const Ptr<const Packet> p, const TcpHeader& h, SocketWho who) override;
66 const TcpSocketState::TcpCongState_t newValue) override;
68
69 private:
70 uint32_t m_firstLoss; //!< First segment loss
71 uint32_t m_secondLoss; //!< Second segment loss
72 uint32_t m_sent{0}; //!< Number of segments sent
73 uint32_t m_received{0}; //!< Number of segments received
74 uint32_t m_lastSegment{0}; //!< Last received segment
75 std::list<int> m_expectedStates; //!< Expected TCP states
76};
77
79 uint32_t secondLoss,
80 uint32_t lastSegment,
81 const std::string& desc)
82 : TcpGeneralTest(desc),
83 m_firstLoss(firstLoss),
84 m_secondLoss(secondLoss),
85 m_lastSegment(lastSegment)
86{
87 NS_TEST_ASSERT_MSG_NE(m_lastSegment, 0, "Last segment should be > 0");
90 "Second segment number should be greater than first");
98}
99
100void
102 const TcpSocketState::TcpCongState_t newValue)
103{
104 int expectedOldState = m_expectedStates.front();
105 m_expectedStates.pop_front();
106 NS_TEST_ASSERT_MSG_EQ(oldValue, expectedOldState, "State transition wrong");
107 NS_TEST_ASSERT_MSG_EQ(newValue, m_expectedStates.front(), "State transition wrong");
108}
109
110void
112{
113 NS_LOG_FUNCTION(this);
115 SetPropagationDelay(MicroSeconds(1)); // Keep low to avoid window limit
117 SetAppPktSize(1000);
118 // Note: 4294967295 is the maximum TCP sequence number, so rollover will be
119 // on the 4294967th packet with a packet (segment) size of 1000 bytes
121 SetAppPktInterval(MicroSeconds(8)); // 1 Gb/s
122}
123
124void
132
135{
137 std::list<uint32_t> errorList;
138 errorList.push_back(m_firstLoss);
139 errorList.push_back(m_secondLoss);
140 rem->SetList(errorList);
141 return rem;
142}
143
144void
149
150void
155
156void
158{
159 // The addition of 2 accounts for the two forcibly lost packets
161 (m_received + 2),
162 "Did not observe expected number of sent packets");
163}
164
165/**
166 * \ingroup internet-test
167 *
168 * Test various packet losses
169 */
171{
172 public:
174 : TestSuite("tcp-loss-test", Type::UNIT)
175 {
176 // For large transfer tests, the three sequence numbers passed in
177 // are the segment (i.e. not byte) number that should be dropped first,
178 // then the second drop, and then the last segment number to send
179 //
180 // If we force a loss at packet 1000 and then shortly after at 2000,
181 // the TCP logic should correctly pass this case (no sequence wrapping).
183 new TcpLargeTransferLossTest(1000, 2000, 2500, "large-transfer-loss-without-wrap"),
184 TestCase::Duration::EXTENSIVE);
185 // If we force a loss at packet 1000 and then much later at 3294967, the
186 // second sequence number will evaluate to less than 1000 considering
187 // the sequence space wrap, so check this case also.
189 new TcpLargeTransferLossTest(1000, 3294967, 3295100, "large-transfer-loss-with-wrap"),
190 TestCase::Duration::EXTENSIVE);
191 }
192};
193
194static TcpLossTestSuite g_tcpLossTest; //!< static var for test initialization
Check rollover of sequence number and how that affects loss recovery.
void FinalChecks() override
Performs the (eventual) final checks through test asserts.
TcpLargeTransferLossTest(uint32_t firstLoss, uint32_t secondLoss, uint32_t lastSegment, const std::string &desc)
Constructor.
void Rx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who) override
Packet received from IP layer.
uint32_t m_sent
Number of segments sent.
std::list< int > m_expectedStates
Expected TCP states.
void ConfigureEnvironment() override
Change the configuration of the environment.
uint32_t m_firstLoss
First segment loss.
void Tx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who) override
Packet transmitted down to IP layer.
uint32_t m_secondLoss
Second segment loss.
void CongStateTrace(const TcpSocketState::TcpCongState_t oldValue, const TcpSocketState::TcpCongState_t newValue) override
State on Ack state machine changes.
uint32_t m_received
Number of segments received.
uint32_t m_lastSegment
Last received segment.
void ConfigureProperties() override
Change the configuration of the socket properties.
Ptr< ErrorModel > CreateReceiverErrorModel() override
Create and return the error model to install in the receiver node.
Test various packet losses.
Smart pointer class similar to boost::intrusive_ptr.
General infrastructure for TCP testing.
void SetPropagationDelay(Time propDelay)
Propagation delay of the bottleneck link.
void SetAppPktCount(uint32_t pktCount)
Set app packet count.
SocketWho
Used as parameter of methods, specifies on what node the caller is interested (e.g.
@ RECEIVER
Receiver node.
void SetAppPktSize(uint32_t pktSize)
Set app packet size.
virtual void ConfigureProperties()
Change the configuration of the socket properties.
void SetAppPktInterval(Time pktInterval)
Interval between app-generated packet.
virtual void ConfigureEnvironment()
Change the configuration of the environment.
void SetTransmitStart(Time startTime)
Set the initial time at which the application sends the first data packet.
void SetSegmentSize(SocketWho who, uint32_t segmentSize)
Forcefully set the segment size.
Header for the Transmission Control Protocol.
Definition tcp-header.h:36
TcpCongState_t
Definition of the Congestion state machine.
@ CA_RECOVERY
CWND was reduced, we are fast-retransmitting.
@ CA_DISORDER
In all the respects it is "Open", but requires a bit more attention.
@ CA_OPEN
Normal state, no dubious events.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
static constexpr auto UNIT
Definition test.h:1291
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:554
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
Definition test.h:864
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1332
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TcpLossTestSuite g_tcpLossTest
static var for test initialization