A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-header-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 Natale Patriciello <natale.patriciello@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8#define __STDC_LIMIT_MACROS
9#include "ns3/buffer.h"
10#include "ns3/core-module.h"
11#include "ns3/tcp-header.h"
12#include "ns3/tcp-option-rfc793.h"
13#include "ns3/test.h"
14
15#include <stdint.h>
16
17using namespace ns3;
18
19#define GET_RANDOM_UINT32(RandomVariable) \
20 static_cast<uint32_t>(RandomVariable->GetInteger(0, UINT32_MAX))
21
22#define GET_RANDOM_UINT16(RandomVariable) \
23 static_cast<uint16_t>(RandomVariable->GetInteger(0, UINT16_MAX))
24
25#define GET_RANDOM_UINT8(RandomVariable) \
26 static_cast<uint8_t>(RandomVariable->GetInteger(0, UINT8_MAX))
27
28#define GET_RANDOM_UINT6(RandomVariable) \
29 static_cast<uint8_t>(RandomVariable->GetInteger(0, UINT8_MAX >> 2))
30
31/**
32 * @ingroup internet-test
33 *
34 * @brief TCP header Get/Set test.
35 */
37{
38 public:
39 /**
40 * Constructor.
41 * @param name Test description.
42 */
43 TcpHeaderGetSetTestCase(std::string name);
44
45 protected:
46 private:
47 void DoRun() override;
48 void DoTeardown() override;
49};
50
55
56void
58{
59 uint16_t sourcePort; // Source port
60 uint16_t destinationPort; // Destination port
61 SequenceNumber32 sequenceNumber; // Sequence number
62 SequenceNumber32 ackNumber; // ACK number
63 uint8_t flags; // Flags (really a uint6_t)
64 uint16_t windowSize; // Window size
65 uint16_t urgentPointer; // Urgent pointer
66 TcpHeader header;
67 Buffer buffer;
68
70 for (uint32_t i = 0; i < 1000; ++i)
71 {
72 sourcePort = GET_RANDOM_UINT16(x);
73 destinationPort = GET_RANDOM_UINT16(x);
74 sequenceNumber = SequenceNumber32(GET_RANDOM_UINT32(x));
75 ackNumber = SequenceNumber32(GET_RANDOM_UINT32(x));
76 flags = GET_RANDOM_UINT6(x);
77 windowSize = GET_RANDOM_UINT16(x);
78 urgentPointer = GET_RANDOM_UINT16(x);
79
80 header.SetSourcePort(sourcePort);
81 header.SetDestinationPort(destinationPort);
82 header.SetSequenceNumber(sequenceNumber);
83 header.SetAckNumber(ackNumber);
84 header.SetFlags(flags);
85 header.SetWindowSize(windowSize);
86 header.SetUrgentPointer(urgentPointer);
87
89 5,
90 "TcpHeader without option is"
91 " not 5 word");
92
93 buffer.AddAtStart(header.GetSerializedSize());
94 header.Serialize(buffer.Begin());
95
96 NS_TEST_ASSERT_MSG_EQ(sourcePort, header.GetSourcePort(), "Different source port found");
97 NS_TEST_ASSERT_MSG_EQ(destinationPort,
98 header.GetDestinationPort(),
99 "Different destination port found");
100 NS_TEST_ASSERT_MSG_EQ(sequenceNumber,
101 header.GetSequenceNumber(),
102 "Different sequence number found");
103 NS_TEST_ASSERT_MSG_EQ(ackNumber, header.GetAckNumber(), "Different ack number found");
104 NS_TEST_ASSERT_MSG_EQ(flags, header.GetFlags(), "Different flags found");
105 NS_TEST_ASSERT_MSG_EQ(windowSize, header.GetWindowSize(), "Different window size found");
106 NS_TEST_ASSERT_MSG_EQ(urgentPointer,
107 header.GetUrgentPointer(),
108 "Different urgent pointer found");
109
111 5,
112 "TcpHeader without option is"
113 " not 5 word");
114
115 TcpHeader copyHeader;
116
117 copyHeader.Deserialize(buffer.Begin());
118
119 NS_TEST_ASSERT_MSG_EQ(sourcePort,
120 copyHeader.GetSourcePort(),
121 "Different source port found in deserialized header");
122 NS_TEST_ASSERT_MSG_EQ(destinationPort,
123 copyHeader.GetDestinationPort(),
124 "Different destination port found in deserialized header");
125 NS_TEST_ASSERT_MSG_EQ(sequenceNumber,
126 copyHeader.GetSequenceNumber(),
127 "Different sequence number found in deserialized header");
128 NS_TEST_ASSERT_MSG_EQ(ackNumber,
129 copyHeader.GetAckNumber(),
130 "Different ack number found in deserialized header");
132 copyHeader.GetFlags(),
133 "Different flags found in deserialized header");
134 NS_TEST_ASSERT_MSG_EQ(windowSize,
135 copyHeader.GetWindowSize(),
136 "Different window size found in deserialized header");
137 NS_TEST_ASSERT_MSG_EQ(urgentPointer,
138 copyHeader.GetUrgentPointer(),
139 "Different urgent pointer found in deserialized header");
140 }
141}
142
143void
147
148/**
149 * @ingroup internet-test
150 *
151 * @brief TCP header with RFC793 Options test.
152 */
154{
155 public:
156 /**
157 * Constructor.
158 * @param name Test description.
159 */
160 TcpHeaderWithRFC793OptionTestCase(std::string name);
161
162 private:
163 void DoRun() override;
164 void DoTeardown() override;
165
166 /**
167 * @brief Check an header with only one kind of option.
168 */
169 void OneOptionAtTime();
170 /**
171 * @brief Check an header for the correct padding.
172 */
173 void CheckNoPadding();
174 /**
175 * @brief Check the correct header deserialization.
176 */
178};
179
184
185void
192
193void
195{
196 TcpHeader source;
197 TcpHeader destination;
198 auto temp = CreateObject<TcpOptionNOP>();
199 Buffer buffer;
200 buffer.AddAtStart(40);
201
202 Buffer::Iterator i = buffer.Begin();
203 source.AppendOption(temp);
204
205 source.Serialize(i);
206
207 i.ReadU8();
208 i.WriteU8(59);
209
210 i = buffer.Begin();
211 destination.Deserialize(i);
212
213 NS_TEST_ASSERT_MSG_EQ(destination.HasOption(59), false, "Kind 59 registered");
214}
215
216void
218{
219 {
220 TcpOptionNOP oNop1;
221 TcpOptionNOP oNop2;
222 TcpOptionNOP oNop3;
223 TcpOptionNOP oNop4;
224 TcpHeader header;
225 Buffer buffer;
226
228 5,
229 "TcpHeader without option is"
230 " not 5 word");
231 header.AppendOption(&oNop1);
232 header.AppendOption(&oNop2);
233 header.AppendOption(&oNop3);
234 header.AppendOption(&oNop4);
235
237 6,
238 "Four byte added as option "
239 "are not a word");
241 24,
242 "Four byte added as option "
243 "are not a word");
244
245 buffer.AddAtStart(header.GetSerializedSize());
246 header.Serialize(buffer.Begin());
247
249 buffer.GetSize(),
250 "Header not correctly serialized");
251
252 // Inserted 4 byte NOP, no padding should be present
253 Buffer::Iterator i = buffer.Begin();
254 i.Next(20);
255
256 for (uint32_t j = 0; j < 4; ++j)
257 {
258 std::stringstream ss;
259 ss << j;
260 uint8_t value = i.ReadU8();
261 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::NOP, "NOP not present at position " + ss.str());
262 }
263 }
264}
265
266void
268{
269 {
270 TcpOptionEnd oEnd;
271 TcpHeader header;
272 Buffer buffer;
273
275 5,
276 "TcpHeader without option is"
277 " not 5 word");
278 header.AppendOption(&oEnd);
280 5,
281 "Length has changed also for"
282 " END option");
284 20,
285 "Length has changed also for"
286 " END option");
287
288 buffer.AddAtStart(header.GetSerializedSize());
289 header.Serialize(buffer.Begin());
290
292 buffer.GetSize(),
293 "Header not correctly serialized");
294 }
295
296 {
297 TcpOptionNOP oNop;
298 TcpHeader header;
299 Buffer buffer;
300
302 5,
303 "TcpHeader without option is"
304 " not 5 word");
305 header.AppendOption(&oNop);
306 NS_TEST_ASSERT_MSG_EQ(header.GetLength(), 6, "NOP option not handled correctly");
308 24,
309 "Different length found for"
310 "NOP option");
311
312 buffer.AddAtStart(header.GetSerializedSize());
313 header.Serialize(buffer.Begin());
314
316 buffer.GetSize(),
317 "Header not correctly serialized");
318
319 // Inserted only 1 byte NOP, and so implementation should pad; so
320 // the other 3 bytes should be END, PAD, PAD (n.b. PAD is same as END)
321 Buffer::Iterator i = buffer.Begin();
322 i.Next(20);
323
324 uint8_t value = i.ReadU8();
325 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::NOP, "NOP not present at byte 1");
326 value = i.ReadU8();
327 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "END not present at byte 2");
328 value = i.ReadU8();
329 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "pad not present at byte 3");
330 value = i.ReadU8();
331 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "pad not present at byte 4");
332 }
333
334 {
335 TcpOptionMSS oMSS;
336 oMSS.SetMSS(50);
337 TcpHeader header;
338 TcpHeader dest;
339 Buffer buffer;
340
342 5,
343 "TcpHeader without option is"
344 " not 5 word");
345 header.AppendOption(&oMSS);
346 NS_TEST_ASSERT_MSG_EQ(header.GetLength(), 6, "MSS option not handled correctly");
348 24,
349 "Different length found for"
350 "MSS option");
351
352 buffer.AddAtStart(header.GetSerializedSize());
353 header.Serialize(buffer.Begin());
354
356 buffer.GetSize(),
357 "Header not correctly serialized");
358
359 dest.Deserialize(buffer.Begin());
361 true,
362 "MSS option not correctly serialized");
364 oMSS.GetSerializedSize(),
365 "MSS Option not counted in the total");
366 }
367}
368
369void
373
374/**
375 * @ingroup internet-test
376 *
377 * @brief TCP header Flags to String test.
378 */
380{
381 public:
382 /**
383 * Constructor.
384 * @param name Test description.
385 */
386 TcpHeaderFlagsToString(std::string name);
387
388 private:
389 void DoRun() override;
390};
391
393 : TestCase(name)
394{
395}
396
397void
399{
400 std::string str;
401 std::string target;
402 str = TcpHeader::FlagsToString(0x0);
403 target = "";
404 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
405 str = TcpHeader::FlagsToString(0x1);
406 target = "FIN";
407 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
408 str = TcpHeader::FlagsToString(0x2);
409 target = "SYN";
410 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
411 str = TcpHeader::FlagsToString(0x4);
412 target = "RST";
413 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
414 str = TcpHeader::FlagsToString(0x8);
415 target = "PSH";
416 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
417 str = TcpHeader::FlagsToString(0x10);
418 target = "ACK";
419 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
420 str = TcpHeader::FlagsToString(0x20);
421 target = "URG";
422 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
423 str = TcpHeader::FlagsToString(0x40);
424 target = "ECE";
425 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
426 str = TcpHeader::FlagsToString(0x80);
427 target = "CWR";
428 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
429 str = TcpHeader::FlagsToString(0x3);
430 target = "FIN|SYN";
431 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
432 str = TcpHeader::FlagsToString(0x5);
433 target = "FIN|RST";
434 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
435 str = TcpHeader::FlagsToString(0xff);
436 target = "FIN|SYN|RST|PSH|ACK|URG|ECE|CWR";
437 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
438 str = TcpHeader::FlagsToString(0xff, ":");
439 target = "FIN:SYN:RST:PSH:ACK:URG:ECE:CWR";
440 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
441}
442
443/**
444 * @ingroup internet-test
445 *
446 * @brief TCP header TestSuite
447 */
449{
450 public:
452 : TestSuite("tcp-header", Type::UNIT)
453 {
454 AddTestCase(new TcpHeaderGetSetTestCase("GetSet test cases"), TestCase::Duration::QUICK);
455 AddTestCase(new TcpHeaderWithRFC793OptionTestCase("Test for options in RFC 793"),
456 TestCase::Duration::QUICK);
457 AddTestCase(new TcpHeaderFlagsToString("Test flags to string function"),
458 TestCase::Duration::QUICK);
459 }
460};
461
462static TcpHeaderTestSuite g_TcpHeaderTestSuite; //!< Static variable for test initialization
TCP header Flags to String test.
void DoRun() override
Implementation to actually run this TestCase.
TcpHeaderFlagsToString(std::string name)
Constructor.
TCP header Get/Set test.
void DoRun() override
Implementation to actually run this TestCase.
TcpHeaderGetSetTestCase(std::string name)
Constructor.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
TCP header TestSuite.
TCP header with RFC793 Options test.
void OneOptionAtTime()
Check an header with only one kind of option.
TcpHeaderWithRFC793OptionTestCase(std::string name)
Constructor.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void CheckNoPadding()
Check an header for the correct padding.
void CheckCorrectDeserialize()
Check the correct header deserialization.
iterator in a Buffer instance
Definition buffer.h:89
void WriteU8(uint8_t data)
Definition buffer.h:870
void Next()
go forward by one byte
Definition buffer.h:842
automatically resized byte buffer
Definition buffer.h:83
uint32_t GetSize() const
Definition buffer.h:1057
void AddAtStart(uint32_t start)
Definition buffer.cc:303
Buffer::Iterator Begin() const
Definition buffer.h:1063
Smart pointer class similar to boost::intrusive_ptr.
Header for the Transmission Control Protocol.
Definition tcp-header.h:36
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition tcp-header.cc:89
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition tcp-header.cc:59
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition tcp-header.cc:65
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
uint8_t GetLength() const
Get the length in words.
uint16_t GetDestinationPort() const
Get the destination port.
uint32_t Deserialize(Buffer::Iterator start) override
void SetFlags(uint8_t flags)
Set flags of the header.
Definition tcp-header.cc:77
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition tcp-header.cc:83
uint32_t GetSerializedSize() const override
uint16_t GetWindowSize() const
Get the window size.
uint8_t GetOptionLength() const
Get the total length of appended options.
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
static std::string FlagsToString(uint8_t flags, const std::string &delimiter="|")
Converts an integer into a human readable list of Tcp flags.
Definition tcp-header.cc:28
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
void Serialize(Buffer::Iterator start) const override
uint16_t GetSourcePort() const
Get the source port.
Definition tcp-header.cc:95
void SetSourcePort(uint16_t port)
Set the source port.
Definition tcp-header.cc:53
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition tcp-header.cc:71
uint16_t GetUrgentPointer() const
Get the urgent pointer.
uint8_t GetFlags() const
Get the flags.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Defines the TCP option of kind 0 (end of option list) as in RFC 793
Defines the TCP option of kind 2 (maximum segment size) as in RFC 793
void SetMSS(uint16_t mss)
Set the Maximum Segment Size stored in the Option.
uint32_t GetSerializedSize() const override
Returns number of bytes required for Option serialization.
Defines the TCP option of kind 1 (no operation) as in RFC 793
encapsulates test code
Definition test.h:1050
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
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
#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
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TcpHeaderTestSuite g_TcpHeaderTestSuite
Static variable for test initialization.
#define GET_RANDOM_UINT32(RandomVariable)
#define GET_RANDOM_UINT6(RandomVariable)
#define GET_RANDOM_UINT16(RandomVariable)