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 
TCP header Flags to Striing test.
TcpHeaderFlagsToString(std::string name)
Constructor.
virtual void DoRun(void)
Implementation to actually run this TestCase.
TCP header Get/Set test.
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
TcpHeaderGetSetTestCase(std::string name)
Constructor.
virtual void DoRun(void)
Implementation to actually run 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.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void CheckNoPadding()
Check an header for the correct padding.
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
void CheckCorrectDeserialize()
Check the correct header deserialization.
iterator in a Buffer instance
Definition: buffer.h:99
void WriteU8(uint8_t data)
Definition: buffer.h:869
void Next(void)
go forward by one byte
Definition: buffer.h:845
uint8_t ReadU8(void)
Definition: buffer.h:1021
automatically resized byte buffer
Definition: buffer.h:93
uint32_t GetSize(void) const
Definition: buffer.h:1063
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
Header for the Transmission Control Protocol.
Definition: tcp-header.h:45
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:125
virtual void Serialize(Buffer::Iterator start) const
Definition: tcp-header.cc:315
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:95
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
virtual uint32_t GetSerializedSize(void) const
Definition: tcp-header.cc:309
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:155
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:113
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:161
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:463
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:511
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: tcp-header.cc:360
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:185
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
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.
virtual uint32_t GetSerializedSize(void) const
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:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1197
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:141
Every class exported by the ns3 library is enclosed in the ns3 namespace.
list x
Random number samples.
#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)