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 private:
46 void DoRun() override;
47 void DoTeardown() override;
48};
49
54
55void
57{
58 uint16_t sourcePort; // Source port
59 uint16_t destinationPort; // Destination port
60 SequenceNumber32 sequenceNumber; // Sequence number
61 SequenceNumber32 ackNumber; // ACK number
62 uint8_t flags; // Flags (really a uint6_t)
63 uint16_t windowSize; // Window size
64 uint16_t urgentPointer; // Urgent pointer
65 TcpHeader header;
66 Buffer buffer;
67
69 for (uint32_t i = 0; i < 1000; ++i)
70 {
71 sourcePort = GET_RANDOM_UINT16(x);
72 destinationPort = GET_RANDOM_UINT16(x);
73 sequenceNumber = SequenceNumber32(GET_RANDOM_UINT32(x));
75 flags = GET_RANDOM_UINT6(x);
76 windowSize = GET_RANDOM_UINT16(x);
77 urgentPointer = GET_RANDOM_UINT16(x);
78
79 header.SetSourcePort(sourcePort);
80 header.SetDestinationPort(destinationPort);
81 header.SetSequenceNumber(sequenceNumber);
82 header.SetAckNumber(ackNumber);
83 header.SetFlags(flags);
84 header.SetWindowSize(windowSize);
85 header.SetUrgentPointer(urgentPointer);
86
88 5,
89 "TcpHeader without option is"
90 " not 5 word");
91
92 buffer.AddAtStart(header.GetSerializedSize());
93 header.Serialize(buffer.Begin());
94
95 NS_TEST_ASSERT_MSG_EQ(sourcePort, header.GetSourcePort(), "Different source port found");
96 NS_TEST_ASSERT_MSG_EQ(destinationPort,
97 header.GetDestinationPort(),
98 "Different destination port found");
99 NS_TEST_ASSERT_MSG_EQ(sequenceNumber,
100 header.GetSequenceNumber(),
101 "Different sequence number found");
102 NS_TEST_ASSERT_MSG_EQ(ackNumber, header.GetAckNumber(), "Different ack number found");
103 NS_TEST_ASSERT_MSG_EQ(flags, header.GetFlags(), "Different flags found");
104 NS_TEST_ASSERT_MSG_EQ(windowSize, header.GetWindowSize(), "Different window size found");
105 NS_TEST_ASSERT_MSG_EQ(urgentPointer,
106 header.GetUrgentPointer(),
107 "Different urgent pointer found");
108
110 5,
111 "TcpHeader without option is"
112 " not 5 word");
113
114 TcpHeader copyHeader;
115
116 copyHeader.Deserialize(buffer.Begin());
117
118 NS_TEST_ASSERT_MSG_EQ(sourcePort,
119 copyHeader.GetSourcePort(),
120 "Different source port found in deserialized header");
121 NS_TEST_ASSERT_MSG_EQ(destinationPort,
122 copyHeader.GetDestinationPort(),
123 "Different destination port found in deserialized header");
124 NS_TEST_ASSERT_MSG_EQ(sequenceNumber,
125 copyHeader.GetSequenceNumber(),
126 "Different sequence number found in deserialized header");
127 NS_TEST_ASSERT_MSG_EQ(ackNumber,
128 copyHeader.GetAckNumber(),
129 "Different ack number found in deserialized header");
131 copyHeader.GetFlags(),
132 "Different flags found in deserialized header");
133 NS_TEST_ASSERT_MSG_EQ(windowSize,
134 copyHeader.GetWindowSize(),
135 "Different window size found in deserialized header");
136 NS_TEST_ASSERT_MSG_EQ(urgentPointer,
137 copyHeader.GetUrgentPointer(),
138 "Different urgent pointer found in deserialized header");
139 }
140}
141
142void
146
147/**
148 * @ingroup internet-test
149 *
150 * @brief TCP header with RFC793 Options test.
151 */
153{
154 public:
155 /**
156 * Constructor.
157 * @param name Test description.
158 */
159 TcpHeaderWithRFC793OptionTestCase(std::string name);
160
161 private:
162 void DoRun() override;
163 void DoTeardown() override;
164
165 /**
166 * @brief Check an header with only one kind of option.
167 */
168 void OneOptionAtTime();
169 /**
170 * @brief Check an header for the correct padding.
171 */
172 void CheckNoPadding();
173 /**
174 * @brief Check the correct header deserialization.
175 */
177};
178
183
184void
191
192void
194{
195 TcpHeader source;
196 TcpHeader destination;
197 auto temp = CreateObject<TcpOptionNOP>();
198 Buffer buffer;
199 buffer.AddAtStart(40);
200
201 Buffer::Iterator i = buffer.Begin();
202 source.AppendOption(temp);
203
204 source.Serialize(i);
205
206 i.ReadU8();
207 i.WriteU8(59);
208
209 i = buffer.Begin();
210 destination.Deserialize(i);
211
212 NS_TEST_ASSERT_MSG_EQ(destination.HasOption(59), false, "Kind 59 registered");
213}
214
215void
217{
218 {
219 TcpOptionNOP oNop1;
220 TcpOptionNOP oNop2;
221 TcpOptionNOP oNop3;
222 TcpOptionNOP oNop4;
223 TcpHeader header;
224 Buffer buffer;
225
227 5,
228 "TcpHeader without option is"
229 " not 5 word");
230 header.AppendOption(&oNop1);
231 header.AppendOption(&oNop2);
232 header.AppendOption(&oNop3);
233 header.AppendOption(&oNop4);
234
236 6,
237 "Four byte added as option "
238 "are not a word");
240 24,
241 "Four byte added as option "
242 "are not a word");
243
244 buffer.AddAtStart(header.GetSerializedSize());
245 header.Serialize(buffer.Begin());
246
248 buffer.GetSize(),
249 "Header not correctly serialized");
250
251 // Inserted 4 byte NOP, no padding should be present
252 Buffer::Iterator i = buffer.Begin();
253 i.Next(20);
254
255 for (uint32_t j = 0; j < 4; ++j)
256 {
257 std::stringstream ss;
258 ss << j;
259 uint8_t value = i.ReadU8();
260 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::NOP, "NOP not present at position " + ss.str());
261 }
262 }
263}
264
265void
267{
268 {
269 TcpOptionEnd oEnd;
270 TcpHeader header;
271 Buffer buffer;
272
274 5,
275 "TcpHeader without option is"
276 " not 5 word");
277 header.AppendOption(&oEnd);
279 5,
280 "Length has changed also for"
281 " END option");
283 20,
284 "Length has changed also for"
285 " END option");
286
287 buffer.AddAtStart(header.GetSerializedSize());
288 header.Serialize(buffer.Begin());
289
291 buffer.GetSize(),
292 "Header not correctly serialized");
293 }
294
295 {
296 TcpOptionNOP oNop;
297 TcpHeader header;
298 Buffer buffer;
299
301 5,
302 "TcpHeader without option is"
303 " not 5 word");
304 header.AppendOption(&oNop);
305 NS_TEST_ASSERT_MSG_EQ(header.GetLength(), 6, "NOP option not handled correctly");
307 24,
308 "Different length found for"
309 "NOP option");
310
311 buffer.AddAtStart(header.GetSerializedSize());
312 header.Serialize(buffer.Begin());
313
315 buffer.GetSize(),
316 "Header not correctly serialized");
317
318 // Inserted only 1 byte NOP, and so implementation should pad; so
319 // the other 3 bytes should be END, PAD, PAD (n.b. PAD is same as END)
320 Buffer::Iterator i = buffer.Begin();
321 i.Next(20);
322
323 uint8_t value = i.ReadU8();
324 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::NOP, "NOP not present at byte 1");
325 value = i.ReadU8();
326 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "END not present at byte 2");
327 value = i.ReadU8();
328 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "pad not present at byte 3");
329 value = i.ReadU8();
330 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "pad not present at byte 4");
331 }
332
333 {
334 TcpOptionMSS oMSS;
335 oMSS.SetMSS(50);
336 TcpHeader header;
337 TcpHeader dest;
338 Buffer buffer;
339
341 5,
342 "TcpHeader without option is"
343 " not 5 word");
344 header.AppendOption(&oMSS);
345 NS_TEST_ASSERT_MSG_EQ(header.GetLength(), 6, "MSS option not handled correctly");
347 24,
348 "Different length found for"
349 "MSS option");
350
351 buffer.AddAtStart(header.GetSerializedSize());
352 header.Serialize(buffer.Begin());
353
355 buffer.GetSize(),
356 "Header not correctly serialized");
357
358 dest.Deserialize(buffer.Begin());
360 true,
361 "MSS option not correctly serialized");
363 oMSS.GetSerializedSize(),
364 "MSS Option not counted in the total");
365 }
366}
367
368void
372
373/**
374 * @ingroup internet-test
375 *
376 * @brief TCP header Flags to String test.
377 */
379{
380 public:
381 /**
382 * Constructor.
383 * @param name Test description.
384 */
385 TcpHeaderFlagsToString(std::string name);
386
387 private:
388 void DoRun() override;
389};
390
392 : TestCase(name)
393{
394}
395
396void
398{
399 std::string str;
400 std::string target;
401 str = TcpHeader::FlagsToString(0x0);
402 target = "";
403 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
404 str = TcpHeader::FlagsToString(0x1);
405 target = "FIN";
406 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
407 str = TcpHeader::FlagsToString(0x2);
408 target = "SYN";
409 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
410 str = TcpHeader::FlagsToString(0x4);
411 target = "RST";
412 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
413 str = TcpHeader::FlagsToString(0x8);
414 target = "PSH";
415 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
416 str = TcpHeader::FlagsToString(0x10);
417 target = "ACK";
418 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
419 str = TcpHeader::FlagsToString(0x20);
420 target = "URG";
421 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
422 str = TcpHeader::FlagsToString(0x40);
423 target = "ECE";
424 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
425 str = TcpHeader::FlagsToString(0x80);
426 target = "CWR";
427 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
428 str = TcpHeader::FlagsToString(0x3);
429 target = "FIN|SYN";
430 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
431 str = TcpHeader::FlagsToString(0x5);
432 target = "FIN|RST";
433 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
434 str = TcpHeader::FlagsToString(0xff);
435 target = "FIN|SYN|RST|PSH|ACK|URG|ECE|CWR";
436 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
437 str = TcpHeader::FlagsToString(0xff, ":");
438 target = "FIN:SYN:RST:PSH:ACK:URG:ECE:CWR";
439 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
440}
441
442/**
443 * @ingroup internet-test
444 *
445 * @brief TCP header TestSuite
446 */
448{
449 public:
451 : TestSuite("tcp-header", Type::UNIT)
452 {
454 AddTestCase(new TcpHeaderWithRFC793OptionTestCase("Test for options in RFC 793"),
456 AddTestCase(new TcpHeaderFlagsToString("Test flags to string function"),
458 }
459};
460
461static TcpHeaderTestSuite g_TcpHeaderTestSuite; //!< Static variable for test initialization
cairo_uint64_t x
_cairo_uint_96by64_32x64_divrem:
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:882
void Next()
go forward by one byte
Definition buffer.h:854
automatically resized byte buffer
Definition buffer.h:83
uint32_t GetSize() const
Definition buffer.h:1069
void AddAtStart(uint32_t start)
Definition buffer.cc:303
Buffer::Iterator Begin() const
Definition buffer.h:1075
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
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.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
@ UNIT
This test suite implements a Unit Test.
Definition test.h:1273
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
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:133
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)