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"),
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"),
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.
Definition ptr.h:66
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.
TcpGeneralTest(const std::string &desc)
TcpGeneralTest constructor.
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
@ EXTENSIVE
Medium length test.
Definition test.h:1056
Type
Type of test.
Definition test.h:1274
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:490
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:1369
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TcpLossTestSuite g_tcpLossTest
static var for test initialization