A Discrete-Event Network Simulator
API
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
49{
50 public:
55 TcpHeaderGetSetTestCase(std::string name);
56
57 protected:
58 private:
59 void DoRun() override;
60 void DoTeardown() override;
61};
62
64 : TestCase(name)
65{
66}
67
68void
70{
71 uint16_t sourcePort; // Source port
72 uint16_t destinationPort; // Destination port
73 SequenceNumber32 sequenceNumber; // Sequence number
74 SequenceNumber32 ackNumber; // ACK number
75 uint8_t flags; // Flags (really a uint6_t)
76 uint16_t windowSize; // Window size
77 uint16_t urgentPointer; // Urgent pointer
78 TcpHeader header;
79 Buffer buffer;
80
81 Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable>();
82 for (uint32_t i = 0; i < 1000; ++i)
83 {
84 sourcePort = GET_RANDOM_UINT16(x);
85 destinationPort = GET_RANDOM_UINT16(x);
86 sequenceNumber = SequenceNumber32(GET_RANDOM_UINT32(x));
87 ackNumber = SequenceNumber32(GET_RANDOM_UINT32(x));
88 flags = GET_RANDOM_UINT6(x);
89 windowSize = GET_RANDOM_UINT16(x);
90 urgentPointer = GET_RANDOM_UINT16(x);
91
92 header.SetSourcePort(sourcePort);
93 header.SetDestinationPort(destinationPort);
94 header.SetSequenceNumber(sequenceNumber);
95 header.SetAckNumber(ackNumber);
96 header.SetFlags(flags);
97 header.SetWindowSize(windowSize);
98 header.SetUrgentPointer(urgentPointer);
99
101 5,
102 "TcpHeader without option is"
103 " not 5 word");
104
105 buffer.AddAtStart(header.GetSerializedSize());
106 header.Serialize(buffer.Begin());
107
108 NS_TEST_ASSERT_MSG_EQ(sourcePort, header.GetSourcePort(), "Different source port found");
109 NS_TEST_ASSERT_MSG_EQ(destinationPort,
110 header.GetDestinationPort(),
111 "Different destination port found");
112 NS_TEST_ASSERT_MSG_EQ(sequenceNumber,
113 header.GetSequenceNumber(),
114 "Different sequence number found");
115 NS_TEST_ASSERT_MSG_EQ(ackNumber, header.GetAckNumber(), "Different ack number found");
116 NS_TEST_ASSERT_MSG_EQ(flags, header.GetFlags(), "Different flags found");
117 NS_TEST_ASSERT_MSG_EQ(windowSize, header.GetWindowSize(), "Different window size found");
118 NS_TEST_ASSERT_MSG_EQ(urgentPointer,
119 header.GetUrgentPointer(),
120 "Different urgent pointer found");
121
123 5,
124 "TcpHeader without option is"
125 " not 5 word");
126
127 TcpHeader copyHeader;
128
129 copyHeader.Deserialize(buffer.Begin());
130
131 NS_TEST_ASSERT_MSG_EQ(sourcePort,
132 copyHeader.GetSourcePort(),
133 "Different source port found in deserialized header");
134 NS_TEST_ASSERT_MSG_EQ(destinationPort,
135 copyHeader.GetDestinationPort(),
136 "Different destination port found in deserialized header");
137 NS_TEST_ASSERT_MSG_EQ(sequenceNumber,
138 copyHeader.GetSequenceNumber(),
139 "Different sequence number found in deserialized header");
140 NS_TEST_ASSERT_MSG_EQ(ackNumber,
141 copyHeader.GetAckNumber(),
142 "Different ack number found in deserialized header");
144 copyHeader.GetFlags(),
145 "Different flags found in deserialized header");
146 NS_TEST_ASSERT_MSG_EQ(windowSize,
147 copyHeader.GetWindowSize(),
148 "Different window size found in deserialized header");
149 NS_TEST_ASSERT_MSG_EQ(urgentPointer,
150 copyHeader.GetUrgentPointer(),
151 "Different urgent pointer found in deserialized header");
152 }
153}
154
155void
157{
158}
159
167{
168 public:
173 TcpHeaderWithRFC793OptionTestCase(std::string name);
174
175 private:
176 void DoRun() override;
177 void DoTeardown() override;
178
182 void OneOptionAtTime();
186 void CheckNoPadding();
191};
192
194 : TestCase(name)
195{
196}
197
198void
200{
204}
205
206void
208{
209 TcpHeader source;
210 TcpHeader destination;
211 TcpOptionNOP temp;
212 Buffer buffer;
213 buffer.AddAtStart(40);
214
215 Buffer::Iterator i = buffer.Begin();
216 source.AppendOption(&temp);
217
218 source.Serialize(i);
219
220 i.ReadU8();
221 i.WriteU8(59);
222
223 i = buffer.Begin();
224 destination.Deserialize(i);
225
226 NS_TEST_ASSERT_MSG_EQ(destination.HasOption(59), false, "Kind 59 registered");
227}
228
229void
231{
232 {
233 TcpOptionNOP oNop1;
234 TcpOptionNOP oNop2;
235 TcpOptionNOP oNop3;
236 TcpOptionNOP oNop4;
237 TcpHeader header;
238 Buffer buffer;
239
241 5,
242 "TcpHeader without option is"
243 " not 5 word");
244 header.AppendOption(&oNop1);
245 header.AppendOption(&oNop2);
246 header.AppendOption(&oNop3);
247 header.AppendOption(&oNop4);
248
250 6,
251 "Four byte added as option "
252 "are not a word");
254 24,
255 "Four byte added as option "
256 "are not a word");
257
258 buffer.AddAtStart(header.GetSerializedSize());
259 header.Serialize(buffer.Begin());
260
262 buffer.GetSize(),
263 "Header not correctly serialized");
264
265 // Inserted 4 byte NOP, no padding should be present
266 Buffer::Iterator i = buffer.Begin();
267 i.Next(20);
268
269 for (uint32_t j = 0; j < 4; ++j)
270 {
271 std::stringstream ss;
272 ss << j;
273 uint8_t value = i.ReadU8();
274 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::NOP, "NOP not present at position " + ss.str());
275 }
276 }
277}
278
279void
281{
282 {
283 TcpOptionEnd oEnd;
284 TcpHeader header;
285 Buffer buffer;
286
288 5,
289 "TcpHeader without option is"
290 " not 5 word");
291 header.AppendOption(&oEnd);
293 5,
294 "Length has changed also for"
295 " END option");
297 20,
298 "Length has changed also for"
299 " END option");
300
301 buffer.AddAtStart(header.GetSerializedSize());
302 header.Serialize(buffer.Begin());
303
305 buffer.GetSize(),
306 "Header not correctly serialized");
307 }
308
309 {
310 TcpOptionNOP oNop;
311 TcpHeader header;
312 Buffer buffer;
313
315 5,
316 "TcpHeader without option is"
317 " not 5 word");
318 header.AppendOption(&oNop);
319 NS_TEST_ASSERT_MSG_EQ(header.GetLength(), 6, "NOP option not handled correctly");
321 24,
322 "Different length found for"
323 "NOP option");
324
325 buffer.AddAtStart(header.GetSerializedSize());
326 header.Serialize(buffer.Begin());
327
329 buffer.GetSize(),
330 "Header not correctly serialized");
331
332 // Inserted only 1 byte NOP, and so implementation should pad; so
333 // the other 3 bytes should be END, PAD, PAD (n.b. PAD is same as END)
334 Buffer::Iterator i = buffer.Begin();
335 i.Next(20);
336
337 uint8_t value = i.ReadU8();
338 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::NOP, "NOP not present at byte 1");
339 value = i.ReadU8();
340 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "END not present at byte 2");
341 value = i.ReadU8();
342 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "pad not present at byte 3");
343 value = i.ReadU8();
344 NS_TEST_ASSERT_MSG_EQ(value, TcpOption::END, "pad not present at byte 4");
345 }
346
347 {
348 TcpOptionMSS oMSS;
349 oMSS.SetMSS(50);
350 TcpHeader header;
351 TcpHeader dest;
352 Buffer buffer;
353
355 5,
356 "TcpHeader without option is"
357 " not 5 word");
358 header.AppendOption(&oMSS);
359 NS_TEST_ASSERT_MSG_EQ(header.GetLength(), 6, "MSS option not handled correctly");
361 24,
362 "Different length found for"
363 "MSS option");
364
365 buffer.AddAtStart(header.GetSerializedSize());
366 header.Serialize(buffer.Begin());
367
369 buffer.GetSize(),
370 "Header not correctly serialized");
371
372 dest.Deserialize(buffer.Begin());
373 NS_TEST_ASSERT_MSG_EQ(header.HasOption(TcpOption::MSS),
374 true,
375 "MSS option not correctly serialized");
377 oMSS.GetSerializedSize(),
378 "MSS Option not counted in the total");
379 }
380}
381
382void
384{
385}
386
394{
395 public:
400 TcpHeaderFlagsToString(std::string name);
401
402 private:
403 void DoRun() override;
404};
405
407 : TestCase(name)
408{
409}
410
411void
413{
414 std::string str;
415 std::string target;
416 str = TcpHeader::FlagsToString(0x0);
417 target = "";
418 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
419 str = TcpHeader::FlagsToString(0x1);
420 target = "FIN";
421 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
422 str = TcpHeader::FlagsToString(0x2);
423 target = "SYN";
424 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
425 str = TcpHeader::FlagsToString(0x4);
426 target = "RST";
427 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
428 str = TcpHeader::FlagsToString(0x8);
429 target = "PSH";
430 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
431 str = TcpHeader::FlagsToString(0x10);
432 target = "ACK";
433 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
434 str = TcpHeader::FlagsToString(0x20);
435 target = "URG";
436 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
437 str = TcpHeader::FlagsToString(0x40);
438 target = "ECE";
439 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
440 str = TcpHeader::FlagsToString(0x80);
441 target = "CWR";
442 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
443 str = TcpHeader::FlagsToString(0x3);
444 target = "FIN|SYN";
445 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
446 str = TcpHeader::FlagsToString(0x5);
447 target = "FIN|RST";
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 str = TcpHeader::FlagsToString(0xff, ":");
453 target = "FIN:SYN:RST:PSH:ACK:URG:ECE:CWR";
454 NS_TEST_ASSERT_MSG_EQ(str, target, "str " << str << " does not equal target " << target);
455}
456
464{
465 public:
467 : TestSuite("tcp-header", UNIT)
468 {
469 AddTestCase(new TcpHeaderGetSetTestCase("GetSet test cases"), TestCase::QUICK);
470 AddTestCase(new TcpHeaderWithRFC793OptionTestCase("Test for options in RFC 793"),
471 TestCase::QUICK);
472 AddTestCase(new TcpHeaderFlagsToString("Test flags to string function"), TestCase::QUICK);
473 }
474};
475
TCP header Flags to Striing 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:311
Buffer::Iterator Begin() const
Definition: buffer.h:1074
Header for the Transmission Control Protocol.
Definition: tcp-header.h:46
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:119
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:89
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:95
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:137
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:149
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:131
uint32_t Deserialize(Buffer::Iterator start) override
Definition: tcp-header.cc:351
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:107
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:113
uint32_t GetSerializedSize() const override
Definition: tcp-header.cc:300
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:173
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:155
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:454
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:502
void Serialize(Buffer::Iterator start) const override
Definition: tcp-header.cc:306
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:125
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:83
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:101
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:179
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:167
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:143
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:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
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:144
Every class exported by the ns3 library is enclosed in the ns3 namespace.
value
Definition: second.py:41
#define END
End of a line.
static TcpHeaderTestSuite g_TcpHeaderTestSuite
Static variable for test initialization.
#define GET_RANDOM_UINT32(RandomVariable)
#define GET_RANDOM_UINT6(RandomVariable)
#define GET_RANDOM_UINT16(RandomVariable)