A Discrete-Event Network Simulator
API
tcp-header-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Natale Patriciello <natale.patriciello@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  */
19 
20 #define __STDC_LIMIT_MACROS
21 #include <stdint.h>
22 #include "ns3/test.h"
23 #include "ns3/core-module.h"
24 #include "ns3/tcp-header.h"
25 #include "ns3/buffer.h"
26 #include "ns3/tcp-option-rfc793.h"
27 
28 using 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 
51 {
52 public:
57  TcpHeaderGetSetTestCase (std::string name);
58 protected:
59 private:
60  virtual void DoRun (void);
61  virtual void DoTeardown (void);
62 
63 };
64 
66 {
67 }
68 
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 
100  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
101  " not 5 word");
102 
103  buffer.AddAtStart (header.GetSerializedSize ());
104  header.Serialize (buffer.Begin ());
105 
106  NS_TEST_ASSERT_MSG_EQ (sourcePort, header.GetSourcePort (),
107  "Different source port found");
108  NS_TEST_ASSERT_MSG_EQ (destinationPort, header.GetDestinationPort (),
109  "Different destination port found");
110  NS_TEST_ASSERT_MSG_EQ (sequenceNumber, header.GetSequenceNumber (),
111  "Different sequence number found");
112  NS_TEST_ASSERT_MSG_EQ (ackNumber, header.GetAckNumber (),
113  "Different ack number found");
114  NS_TEST_ASSERT_MSG_EQ (flags, header.GetFlags (),
115  "Different flags found");
116  NS_TEST_ASSERT_MSG_EQ (windowSize, header.GetWindowSize (),
117  "Different window size found");
118  NS_TEST_ASSERT_MSG_EQ (urgentPointer, header.GetUrgentPointer (),
119  "Different urgent pointer found");
120 
121  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
122  " not 5 word");
123 
124  TcpHeader copyHeader;
125 
126  copyHeader.Deserialize (buffer.Begin ());
127 
128  NS_TEST_ASSERT_MSG_EQ (sourcePort, copyHeader.GetSourcePort (),
129  "Different source port found in deserialized header");
130  NS_TEST_ASSERT_MSG_EQ (destinationPort, copyHeader.GetDestinationPort (),
131  "Different destination port found in deserialized header");
132  NS_TEST_ASSERT_MSG_EQ (sequenceNumber, copyHeader.GetSequenceNumber (),
133  "Different sequence number found in deserialized header");
134  NS_TEST_ASSERT_MSG_EQ (ackNumber, copyHeader.GetAckNumber (),
135  "Different ack number found in deserialized header");
136  NS_TEST_ASSERT_MSG_EQ (flags, copyHeader.GetFlags (),
137  "Different flags found in deserialized header");
138  NS_TEST_ASSERT_MSG_EQ (windowSize, copyHeader.GetWindowSize (),
139  "Different window size found in deserialized header");
140  NS_TEST_ASSERT_MSG_EQ (urgentPointer, copyHeader.GetUrgentPointer (),
141  "Different urgent pointer found in deserialized header");
142  }
143 }
144 
146 {
147 }
148 
156 {
157 public:
162  TcpHeaderWithRFC793OptionTestCase (std::string name);
163 
164 private:
165  virtual void DoRun (void);
166  virtual void DoTeardown (void);
167 
171  void OneOptionAtTime ();
175  void CheckNoPadding ();
179  void CheckCorrectDeserialize ();
180 };
181 
182 
184  : TestCase (name)
185 {
186 
187 }
188 
189 void
191 {
192  OneOptionAtTime ();
193  CheckNoPadding ();
195 }
196 
197 void
199 {
200  TcpHeader source, destination;
201  TcpOptionNOP temp;
202  Buffer buffer;
203  buffer.AddAtStart (40);
204 
205  Buffer::Iterator i = buffer.Begin ();
206  source.AppendOption (&temp);
207 
208  source.Serialize (i);
209 
210  i.ReadU8 ();
211  i.WriteU8 (59);
212 
213  i = buffer.Begin ();
214  destination.Deserialize (i);
215 
216  NS_TEST_ASSERT_MSG_EQ (destination.HasOption (59), false, "Kind 59 registered");
217 }
218 
219 void
221 {
222  {
223  TcpOptionNOP oNop1, oNop2, oNop3, oNop4;
224  TcpHeader header;
225  Buffer buffer;
226 
227  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
228  " not 5 word");
229  header.AppendOption (&oNop1);
230  header.AppendOption (&oNop2);
231  header.AppendOption (&oNop3);
232  header.AppendOption (&oNop4);
233 
234  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "Four byte added as option "
235  "are not a word");
236  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Four byte added as option "
237  "are not a word");
238 
239  buffer.AddAtStart (header.GetSerializedSize ());
240  header.Serialize (buffer.Begin ());
241 
243  buffer.GetSize (), "Header not correctly serialized");
244 
245  // Inserted 4 byte NOP, no padding should be present
246  Buffer::Iterator i = buffer.Begin ();
247  i.Next (20);
248 
249  for (uint32_t j = 0; j < 4; ++j)
250  {
251  std::stringstream ss;
252  ss << j;
253  uint8_t value = i.ReadU8 ();
254  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::NOP,
255  "NOP not present at position " + ss.str ());
256  }
257  }
258 }
259 
260 void
262 {
263  {
264  TcpOptionEnd oEnd;
265  TcpHeader header;
266  Buffer buffer;
267 
268  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
269  " not 5 word");
270  header.AppendOption (&oEnd);
271  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "Length has changed also for"
272  " END option");
273  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 20, "Length has changed also for"
274  " END option");
275 
276 
277  buffer.AddAtStart (header.GetSerializedSize ());
278  header.Serialize (buffer.Begin ());
279 
281  buffer.GetSize (), "Header not correctly serialized");
282  }
283 
284  {
285  TcpOptionNOP oNop;
286  TcpHeader header;
287  Buffer buffer;
288 
289  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
290  " not 5 word");
291  header.AppendOption (&oNop);
292  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "NOP option not handled correctly");
293  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Different length found for"
294  "NOP option");
295 
296  buffer.AddAtStart (header.GetSerializedSize ());
297  header.Serialize (buffer.Begin ());
298 
300  buffer.GetSize (), "Header not correctly serialized");
301 
302  // Inserted only 1 byte NOP, and so implementation should pad; so
303  // the other 3 bytes should be END, PAD, PAD (n.b. PAD is same as END)
304  Buffer::Iterator i = buffer.Begin ();
305  i.Next (20);
306 
307  uint8_t value = i.ReadU8 ();
308  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::NOP, "NOP not present at byte 1");
309  value = i.ReadU8 ();
310  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "END not present at byte 2");
311  value = i.ReadU8 ();
312  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "pad not present at byte 3");
313  value = i.ReadU8 ();
314  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "pad not present at byte 4");
315  }
316 
317  {
318  TcpOptionMSS oMSS;
319  oMSS.SetMSS (50);
320  TcpHeader header, dest;
321  Buffer buffer;
322 
323  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
324  " not 5 word");
325  header.AppendOption (&oMSS);
326  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "MSS option not handled correctly");
327  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Different length found for"
328  "MSS option");
329 
330  buffer.AddAtStart (header.GetSerializedSize ());
331  header.Serialize (buffer.Begin ());
332 
334  buffer.GetSize (), "Header not correctly serialized");
335 
336  dest.Deserialize (buffer.Begin ());
337  NS_TEST_ASSERT_MSG_EQ (header.HasOption (TcpOption::MSS),
338  true, "MSS option not correctly serialized");
340  "MSS Option not counted in the total");
341  }
342 }
343 
344 
345 void
347 {
348  uint32_t foo;
349  foo = UINT32_MAX;
350  foo--;
351 
352 }
353 
361 {
362 public:
367  TcpHeaderFlagsToString (std::string name);
368 
369 private:
370  virtual void DoRun (void);
371 };
372 
374  : TestCase (name)
375 {
376 }
377 
378 void
380 {
381  std::string str, target;
382  str = TcpHeader::FlagsToString (0x0);
383  target = "";
384  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
385  str = TcpHeader::FlagsToString (0x1);
386  target = "FIN";
387  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
388  str = TcpHeader::FlagsToString (0x2);
389  target = "SYN";
390  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
391  str = TcpHeader::FlagsToString (0x4);
392  target = "RST";
393  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
394  str = TcpHeader::FlagsToString (0x8);
395  target = "PSH";
396  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
397  str = TcpHeader::FlagsToString (0x10);
398  target = "ACK";
399  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
400  str = TcpHeader::FlagsToString (0x20);
401  target = "URG";
402  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
403  str = TcpHeader::FlagsToString (0x40);
404  target = "ECE";
405  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
406  str = TcpHeader::FlagsToString (0x80);
407  target = "CWR";
408  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
409  str = TcpHeader::FlagsToString (0x3);
410  target = "FIN|SYN";
411  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
412  str = TcpHeader::FlagsToString (0x5);
413  target = "FIN|RST";
414  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
415  str = TcpHeader::FlagsToString (0xff);
416  target = "FIN|SYN|RST|PSH|ACK|URG|ECE|CWR";
417  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
418  str = TcpHeader::FlagsToString (0xff, ":");
419  target = "FIN:SYN:RST:PSH:ACK:URG:ECE:CWR";
420  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
421 }
422 
423 
431 {
432 public:
434  : TestSuite ("tcp-header", UNIT)
435  {
436  AddTestCase (new TcpHeaderGetSetTestCase ("GetSet test cases"), TestCase::QUICK);
437  AddTestCase (new TcpHeaderWithRFC793OptionTestCase ("Test for options in RFC 793"), TestCase::QUICK);
438  AddTestCase (new TcpHeaderFlagsToString ("Test flags to string function"), TestCase::QUICK);
439  }
440 
441 };
442 
444 
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
void SetMSS(uint16_t mss)
Set the Maximum Segment Size stored in the Option.
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
TCP header with RFC793 Options test.
virtual void DoRun(void)
Implementation to actually run this TestCase.
TcpHeaderFlagsToString(std::string name)
Constructor.
Defines the TCP option of kind 1 (no operation) as in RFC 793
A suite of tests to run.
Definition: test.h:1342
automatically resized byte buffer
Definition: buffer.h:92
TCP header Flags to Striing test.
virtual uint32_t GetSerializedSize(void) const
Definition: tcp-header.cc:309
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
#define GET_RANDOM_UINT6(RandomVariable)
encapsulates test code
Definition: test.h:1155
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
iterator in a Buffer instance
Definition: buffer.h:98
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:168
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:155
static TcpHeaderTestSuite g_TcpHeaderTestSuite
Static variable for test initialization.
TcpHeaderWithRFC793OptionTestCase(std::string name)
Constructor.
Defines the TCP option of kind 0 (end of option list) as in RFC 793
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
void Next(void)
go forward by one byte
Definition: buffer.h:845
virtual void DoRun(void)
Implementation to actually run this TestCase.
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:511
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:95
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:113
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:161
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:125
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: tcp-header.cc:360
#define GET_RANDOM_UINT16(RandomVariable)
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
void WriteU8(uint8_t data)
Definition: buffer.h:869
void CheckNoPadding()
Check an header for the correct padding.
void CheckCorrectDeserialize()
Check the correct header deserialization.
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
#define GET_RANDOM_UINT32(RandomVariable)
TCP header TestSuite.
void OneOptionAtTime()
Check an header with only one kind of option.
Defines the TCP option of kind 2 (maximum segment size) as in RFC 793
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:185
TcpHeaderGetSetTestCase(std::string name)
Constructor.
virtual uint32_t GetSerializedSize(void) const
Returns number of bytes required for Option serialization.
uint32_t GetSize(void) const
Definition: buffer.h:1063
uint8_t ReadU8(void)
Definition: buffer.h:1021
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:463
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
This test suite implements a Unit Test.
Definition: test.h:1352
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
TCP header Get/Set test.
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
virtual void Serialize(Buffer::Iterator start) const
Definition: tcp-header.cc:315