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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 */
18
19#define __STDC_LIMIT_MACROS
20#include "ns3/buffer.h"
21#include "ns3/core-module.h"
22#include "ns3/tcp-header.h"
23#include "ns3/tcp-option-rfc793.h"
24#include "ns3/test.h"
25
26#include <stdint.h>
27
28using namespace ns3;
29
30#define GET_RANDOM_UINT32(RandomVariable) \
31 static_cast<uint32_t>(RandomVariable->GetInteger(0, UINT32_MAX))
32
33#define GET_RANDOM_UINT16(RandomVariable) \
34 static_cast<uint16_t>(RandomVariable->GetInteger(0, UINT16_MAX))
35
36#define GET_RANDOM_UINT8(RandomVariable) \
37 static_cast<uint8_t>(RandomVariable->GetInteger(0, UINT8_MAX))
38
39#define GET_RANDOM_UINT6(RandomVariable) \
40 static_cast<uint8_t>(RandomVariable->GetInteger(0, UINT8_MAX >> 2))
41
42/**
43 * \ingroup internet-test
44 *
45 * \brief TCP header Get/Set test.
46 */
48{
49 public:
50 /**
51 * Constructor.
52 * \param name Test description.
53 */
54 TcpHeaderGetSetTestCase(std::string name);
55
56 protected:
57 private:
58 void DoRun() override;
59 void DoTeardown() override;
60};
61
63 : TestCase(name)
64{
65}
66
67void
69{
70 uint16_t sourcePort; // Source port
71 uint16_t destinationPort; // Destination port
72 SequenceNumber32 sequenceNumber; // Sequence number
73 SequenceNumber32 ackNumber; // ACK number
74 uint8_t flags; // Flags (really a uint6_t)
75 uint16_t windowSize; // Window size
76 uint16_t urgentPointer; // Urgent pointer
77 TcpHeader header;
78 Buffer buffer;
79
80 Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable>();
81 for (uint32_t i = 0; i < 1000; ++i)
82 {
83 sourcePort = GET_RANDOM_UINT16(x);
84 destinationPort = GET_RANDOM_UINT16(x);
85 sequenceNumber = SequenceNumber32(GET_RANDOM_UINT32(x));
86 ackNumber = SequenceNumber32(GET_RANDOM_UINT32(x));
87 flags = GET_RANDOM_UINT6(x);
88 windowSize = GET_RANDOM_UINT16(x);
89 urgentPointer = GET_RANDOM_UINT16(x);
90
91 header.SetSourcePort(sourcePort);
92 header.SetDestinationPort(destinationPort);
93 header.SetSequenceNumber(sequenceNumber);
94 header.SetAckNumber(ackNumber);
95 header.SetFlags(flags);
96 header.SetWindowSize(windowSize);
97 header.SetUrgentPointer(urgentPointer);
98
100 5,
101 "TcpHeader without option is"
102 " not 5 word");
103
104 buffer.AddAtStart(header.GetSerializedSize());
105 header.Serialize(buffer.Begin());
106
107 NS_TEST_ASSERT_MSG_EQ(sourcePort, header.GetSourcePort(), "Different source port found");
108 NS_TEST_ASSERT_MSG_EQ(destinationPort,
109 header.GetDestinationPort(),
110 "Different destination port found");
111 NS_TEST_ASSERT_MSG_EQ(sequenceNumber,
112 header.GetSequenceNumber(),
113 "Different sequence number found");
114 NS_TEST_ASSERT_MSG_EQ(ackNumber, header.GetAckNumber(), "Different ack number found");
115 NS_TEST_ASSERT_MSG_EQ(flags, header.GetFlags(), "Different flags found");
116 NS_TEST_ASSERT_MSG_EQ(windowSize, header.GetWindowSize(), "Different window size found");
117 NS_TEST_ASSERT_MSG_EQ(urgentPointer,
118 header.GetUrgentPointer(),
119 "Different urgent pointer found");
120
122 5,
123 "TcpHeader without option is"
124 " not 5 word");
125
126 TcpHeader copyHeader;
127
128 copyHeader.Deserialize(buffer.Begin());
129
130 NS_TEST_ASSERT_MSG_EQ(sourcePort,
131 copyHeader.GetSourcePort(),
132 "Different source port found in deserialized header");
133 NS_TEST_ASSERT_MSG_EQ(destinationPort,
134 copyHeader.GetDestinationPort(),
135 "Different destination port found in deserialized header");
136 NS_TEST_ASSERT_MSG_EQ(sequenceNumber,
137 copyHeader.GetSequenceNumber(),
138 "Different sequence number found in deserialized header");
139 NS_TEST_ASSERT_MSG_EQ(ackNumber,
140 copyHeader.GetAckNumber(),
141 "Different ack number found in deserialized header");
143 copyHeader.GetFlags(),
144 "Different flags found in deserialized header");
145 NS_TEST_ASSERT_MSG_EQ(windowSize,
146 copyHeader.GetWindowSize(),
147 "Different window size found in deserialized header");
148 NS_TEST_ASSERT_MSG_EQ(urgentPointer,
149 copyHeader.GetUrgentPointer(),
150 "Different urgent pointer found in deserialized header");
151 }
152}
153
154void
156{
157}
158
159/**
160 * \ingroup internet-test
161 *
162 * \brief TCP header with RFC793 Options test.
163 */
165{
166 public:
167 /**
168 * Constructor.
169 * \param name Test description.
170 */
171 TcpHeaderWithRFC793OptionTestCase(std::string name);
172
173 private:
174 void DoRun() override;
175 void DoTeardown() override;
176
177 /**
178 * \brief Check an header with only one kind of option.
179 */
180 void OneOptionAtTime();
181 /**
182 * \brief Check an header for the correct padding.
183 */
184 void CheckNoPadding();
185 /**
186 * \brief Check the correct header deserialization.
187 */
189};
190
192 : TestCase(name)
193{
194}
195
196void
198{
202}
203
204void
206{
207 TcpHeader source;
208 TcpHeader destination;
209 auto temp = CreateObject<TcpOptionNOP>();
210 Buffer buffer;
211 buffer.AddAtStart(40);
212
213 Buffer::Iterator i = buffer.Begin();
214 source.AppendOption(temp);
215
216 source.Serialize(i);
217
218 i.ReadU8();
219 i.WriteU8(59);
220
221 i = buffer.Begin();
222 destination.Deserialize(i);
223
224 NS_TEST_ASSERT_MSG_EQ(destination.HasOption(59), false, "Kind 59 registered");
225}
226
227void
229{
230 {
231 TcpOptionNOP oNop1;
232 TcpOptionNOP oNop2;
233 TcpOptionNOP oNop3;
234 TcpOptionNOP oNop4;
235 TcpHeader header;
236 Buffer buffer;
237
239 5,
240 "TcpHeader without option is"
241 " not 5 word");
242 header.AppendOption(&oNop1);
243 header.AppendOption(&oNop2);
244 header.AppendOption(&oNop3);
245 header.AppendOption(&oNop4);
246
248 6,
249 "Four byte added as option "
250 "are not a word");
252 24,
253 "Four byte added as option "
254 "are not a word");
255
256 buffer.AddAtStart(header.GetSerializedSize());
257 header.Serialize(buffer.Begin());
258
260 buffer.GetSize(),
261 "Header not correctly serialized");
262
263 // Inserted 4 byte NOP, no padding should be present
264 Buffer::Iterator i = buffer.Begin();
265 i.Next(20);
266
267 for (uint32_t j = 0; j < 4; ++j)
268 {
269 std::stringstream ss;
270 ss << j;
271 uint8_t value = i.ReadU8();
272 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::NOP, "NOP not present at position " + ss.str());
273 }
274 }
275}
276
277void
279{
280 {
281 TcpOptionEnd oEnd;
282 TcpHeader header;
283 Buffer buffer;
284
286 5,
287 "TcpHeader without option is"
288 " not 5 word");
289 header.AppendOption(&oEnd);
291 5,
292 "Length has changed also for"
293 " END option");
295 20,
296 "Length has changed also for"
297 " END option");
298
299 buffer.AddAtStart(header.GetSerializedSize());
300 header.Serialize(buffer.Begin());
301
303 buffer.GetSize(),
304 "Header not correctly serialized");
305 }
306
307 {
308 TcpOptionNOP oNop;
309 TcpHeader header;
310 Buffer buffer;
311
313 5,
314 "TcpHeader without option is"
315 " not 5 word");
316 header.AppendOption(&oNop);
317 NS_TEST_ASSERT_MSG_EQ(header.GetLength(), 6, "NOP option not handled correctly");
319 24,
320 "Different length found for"
321 "NOP option");
322
323 buffer.AddAtStart(header.GetSerializedSize());
324 header.Serialize(buffer.Begin());
325
327 buffer.GetSize(),
328 "Header not correctly serialized");
329
330 // Inserted only 1 byte NOP, and so implementation should pad; so
331 // the other 3 bytes should be END, PAD, PAD (n.b. PAD is same as END)
332 Buffer::Iterator i = buffer.Begin();
333 i.Next(20);
334
335 uint8_t value = i.ReadU8();
336 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::NOP, "NOP not present at byte 1");
337 value = i.ReadU8();
338 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "END not present at byte 2");
339 value = i.ReadU8();
340 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "pad not present at byte 3");
341 value = i.ReadU8();
342 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "pad not present at byte 4");
343 }
344
345 {
346 TcpOptionMSS oMSS;
347 oMSS.SetMSS(50);
348 TcpHeader header;
349 TcpHeader dest;
350 Buffer buffer;
351
353 5,
354 "TcpHeader without option is"
355 " not 5 word");
356 header.AppendOption(&oMSS);
357 NS_TEST_ASSERT_MSG_EQ(header.GetLength(), 6, "MSS option not handled correctly");
359 24,
360 "Different length found for"
361 "MSS option");
362
363 buffer.AddAtStart(header.GetSerializedSize());
364 header.Serialize(buffer.Begin());
365
367 buffer.GetSize(),
368 "Header not correctly serialized");
369
370 dest.Deserialize(buffer.Begin());
372 true,
373 "MSS option not correctly serialized");
375 oMSS.GetSerializedSize(),
376 "MSS Option not counted in the total");
377 }
378}
379
380void
382{
383}
384
385/**
386 * \ingroup internet-test
387 *
388 * \brief TCP header Flags to String test.
389 */
391{
392 public:
393 /**
394 * Constructor.
395 * \param name Test description.
396 */
397 TcpHeaderFlagsToString(std::string name);
398
399 private:
400 void DoRun() override;
401};
402
404 : TestCase(name)
405{
406}
407
408void
410{
411 std::string str;
412 std::string target;
413 str = TcpHeader::FlagsToString(0x0);
414 target = "";
415 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
416 str = TcpHeader::FlagsToString(0x1);
417 target = "FIN";
418 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
419 str = TcpHeader::FlagsToString(0x2);
420 target = "SYN";
421 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
422 str = TcpHeader::FlagsToString(0x4);
423 target = "RST";
424 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
425 str = TcpHeader::FlagsToString(0x8);
426 target = "PSH";
427 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
428 str = TcpHeader::FlagsToString(0x10);
429 target = "ACK";
430 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
431 str = TcpHeader::FlagsToString(0x20);
432 target = "URG";
433 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
434 str = TcpHeader::FlagsToString(0x40);
435 target = "ECE";
436 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
437 str = TcpHeader::FlagsToString(0x80);
438 target = "CWR";
439 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
440 str = TcpHeader::FlagsToString(0x3);
441 target = "FIN|SYN";
442 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
443 str = TcpHeader::FlagsToString(0x5);
444 target = "FIN|RST";
445 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
446 str = TcpHeader::FlagsToString(0xff);
447 target = "FIN|SYN|RST|PSH|ACK|URG|ECE|CWR";
448 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
449 str = TcpHeader::FlagsToString(0xff, ":");
450 target = "FIN:SYN:RST:PSH:ACK:URG:ECE:CWR";
451 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
452}
453
454/**
455 * \ingroup internet-test
456 *
457 * \brief TCP header TestSuite
458 */
460{
461 public:
463 : TestSuite("tcp-header", Type::UNIT)
464 {
465 AddTestCase(new TcpHeaderGetSetTestCase("GetSet test cases"), TestCase::Duration::QUICK);
466 AddTestCase(new TcpHeaderWithRFC793OptionTestCase("Test for options in RFC 793"),
467 TestCase::Duration::QUICK);
468 AddTestCase(new TcpHeaderFlagsToString("Test flags to string function"),
469 TestCase::Duration::QUICK);
470 }
471};
472
473static 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:100
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void Next()
go forward by one byte
Definition: buffer.h:853
automatically resized byte buffer
Definition: buffer.h:94
uint32_t GetSize() const
Definition: buffer.h:1068
void AddAtStart(uint32_t start)
Definition: buffer.cc:314
Buffer::Iterator Begin() const
Definition: buffer.h:1074
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Header for the Transmission Control Protocol.
Definition: tcp-header.h:47
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:100
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:70
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:76
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:118
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:130
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:112
uint32_t Deserialize(Buffer::Iterator start) override
Definition: tcp-header.cc:330
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:88
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:94
uint32_t GetSerializedSize() const override
Definition: tcp-header.cc:279
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:154
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:136
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:432
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:39
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:478
void Serialize(Buffer::Iterator start) const override
Definition: tcp-header.cc:285
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:106
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:64
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:82
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:160
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:148
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:124
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:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
static constexpr auto UNIT
Definition: test.h:1286
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:145
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)