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/private/tcp-option-rfc793.h"
27 
28 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 
43 {
44 public:
45  TcpHeaderGetSetTestCase (std::string name);
46 protected:
47 private:
48  virtual void DoRun (void);
49  virtual void DoTeardown (void);
50 
51 };
52 
54 {
55 }
57 {
58  uint16_t sourcePort;
59  uint16_t destinationPort;
60  SequenceNumber32 sequenceNumber;
61  SequenceNumber32 ackNumber;
62  uint8_t flags;
63  uint16_t windowSize;
64  uint16_t urgentPointer;
65  TcpHeader header;
66  Buffer buffer;
67 
68  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
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));
74  ackNumber = 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 
87  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
88  " not 5 word");
89 
90  buffer.AddAtStart (header.GetSerializedSize ());
91  header.Serialize (buffer.Begin ());
92 
93  NS_TEST_ASSERT_MSG_EQ (sourcePort, header.GetSourcePort (),
94  "Different source port found");
95  NS_TEST_ASSERT_MSG_EQ (destinationPort, header.GetDestinationPort (),
96  "Different destination port found");
97  NS_TEST_ASSERT_MSG_EQ (sequenceNumber, header.GetSequenceNumber (),
98  "Different sequence number found");
99  NS_TEST_ASSERT_MSG_EQ (ackNumber, header.GetAckNumber (),
100  "Different ack number found");
101  NS_TEST_ASSERT_MSG_EQ (flags, header.GetFlags (),
102  "Different flags found");
103  NS_TEST_ASSERT_MSG_EQ (windowSize, header.GetWindowSize (),
104  "Different window size found");
105  NS_TEST_ASSERT_MSG_EQ (urgentPointer, header.GetUrgentPointer (),
106  "Different urgent pointer found");
107 
108  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
109  " not 5 word");
110 
111  TcpHeader copyHeader;
112 
113  copyHeader.Deserialize (buffer.Begin ());
114 
115  NS_TEST_ASSERT_MSG_EQ (sourcePort, copyHeader.GetSourcePort (),
116  "Different source port found in deserialized header");
117  NS_TEST_ASSERT_MSG_EQ (destinationPort, copyHeader.GetDestinationPort (),
118  "Different destination port found in deserialized header");
119  NS_TEST_ASSERT_MSG_EQ (sequenceNumber, copyHeader.GetSequenceNumber (),
120  "Different sequence number found in deserialized header");
121  NS_TEST_ASSERT_MSG_EQ (ackNumber, copyHeader.GetAckNumber (),
122  "Different ack number found in deserialized header");
123  NS_TEST_ASSERT_MSG_EQ (flags, copyHeader.GetFlags (),
124  "Different flags found in deserialized header");
125  NS_TEST_ASSERT_MSG_EQ (windowSize, copyHeader.GetWindowSize (),
126  "Different window size found in deserialized header");
127  NS_TEST_ASSERT_MSG_EQ (urgentPointer, copyHeader.GetUrgentPointer (),
128  "Different urgent pointer found in deserialized header");
129  }
130 }
131 
133 {
134 
135 }
136 
138 {
139 public:
140  TcpHeaderWithRFC793OptionTestCase (std::string name);
141 
142 private:
143  virtual void DoRun (void);
144  virtual void DoTeardown (void);
145 
150  void OneOptionAtTime ();
151  void CheckNoPadding ();
152  void CheckCorrectDeserialize ();
153 };
154 
155 
157  : TestCase (name)
158 {
159 
160 }
161 
162 void
164 {
165  OneOptionAtTime ();
166  CheckNoPadding ();
168 }
169 
170 void
172 {
173  TcpHeader source, destination;
174  TcpOptionNOP temp;
175  Buffer buffer;
176  buffer.AddAtStart (40);
177 
178  Buffer::Iterator i = buffer.Begin ();
179  source.AppendOption (&temp);
180 
181  source.Serialize (i);
182 
183  i.ReadU8 ();
184  i.WriteU8 (59);
185 
186  i = buffer.Begin ();
187  destination.Deserialize (i);
188 
189  NS_TEST_ASSERT_MSG_EQ (destination.HasOption (59), false, "Kind 59 registered");
190 }
191 
192 void
194 {
195  {
196  TcpOptionNOP oNop1, oNop2, oNop3, oNop4;
197  TcpHeader header;
198  Buffer buffer;
199 
200  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
201  " not 5 word");
202  header.AppendOption (&oNop1);
203  header.AppendOption (&oNop2);
204  header.AppendOption (&oNop3);
205  header.AppendOption (&oNop4);
206 
207  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "Four byte added as option "
208  "are not a word");
209  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Four byte added as option "
210  "are not a word");
211 
212  buffer.AddAtStart (header.GetSerializedSize ());
213  header.Serialize (buffer.Begin ());
214 
216  buffer.GetSize (), "Header not correctly serialized");
217 
218  // Inserted 4 byte NOP, no padding should be present
219  Buffer::Iterator i = buffer.Begin ();
220  i.Next (20);
221 
222  for (uint32_t j = 0; j < 4; ++j)
223  {
224  std::stringstream ss;
225  ss << j;
226  uint8_t value = i.ReadU8 ();
228  "NOP not present at position " + ss.str ());
229  }
230  }
231 }
232 
233 void
235 {
236  {
237  TcpOptionEnd oEnd;
238  TcpHeader header;
239  Buffer buffer;
240 
241  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
242  " not 5 word");
243  header.AppendOption (&oEnd);
244  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "Length has changed also for"
245  " END option");
246  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 20, "Length has changed also for"
247  " END option");
248 
249 
250  buffer.AddAtStart (header.GetSerializedSize ());
251  header.Serialize (buffer.Begin ());
252 
254  buffer.GetSize (), "Header not correctly serialized");
255  }
256 
257  {
258  TcpOptionNOP oNop;
259  TcpHeader header;
260  Buffer buffer;
261 
262  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
263  " not 5 word");
264  header.AppendOption (&oNop);
265  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "NOP option not handled correctly");
266  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Different length found for"
267  "NOP option");
268 
269  buffer.AddAtStart (header.GetSerializedSize ());
270  header.Serialize (buffer.Begin ());
271 
273  buffer.GetSize (), "Header not correctly serialized");
274 
275  // Inserted only 1 byte NOP, and so implementation should pad; so
276  // the other 3 bytes should be END, PAD, PAD (n.b. PAD is same as END)
277  Buffer::Iterator i = buffer.Begin ();
278  i.Next (20);
279 
280  uint8_t value = i.ReadU8 ();
281  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::NOP, "NOP not present at byte 1");
282  value = i.ReadU8 ();
283  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "END not present at byte 2");
284  value = i.ReadU8 ();
285  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "pad not present at byte 3");
286  value = i.ReadU8 ();
287  NS_TEST_ASSERT_MSG_EQ (value, TcpOption::END, "pad not present at byte 4");
288  }
289 
290  {
291  TcpOptionMSS oMSS;
292  oMSS.SetMSS (50);
293  TcpHeader header, dest;
294  Buffer buffer;
295 
296  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 5, "TcpHeader without option is"
297  " not 5 word");
298  header.AppendOption (&oMSS);
299  NS_TEST_ASSERT_MSG_EQ (header.GetLength (), 6, "MSS option not handled correctly");
300  NS_TEST_ASSERT_MSG_EQ (header.GetSerializedSize (), 24, "Different length found for"
301  "MSS option");
302 
303  buffer.AddAtStart (header.GetSerializedSize ());
304  header.Serialize (buffer.Begin ());
305 
307  buffer.GetSize (), "Header not correctly serialized");
308 
309  dest.Deserialize (buffer.Begin ());
311  true, "MSS option not correctly serialized");
313  "MSS Option not counted in the total");
314  }
315 }
316 
317 
318 void
320 {
321  uint32_t foo;
322  foo = UINT32_MAX;
323  foo--;
324 
325 }
326 
328 {
329 public:
330  TcpHeaderFlagsToString (std::string name);
331 
332 private:
333  virtual void DoRun (void);
334 };
335 
337  : TestCase (name)
338 {
339 }
340 
341 void
343 {
344  std::string str, target;
345  str = TcpHeader::FlagsToString (0x0);
346  target = "";
347  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
348  str = TcpHeader::FlagsToString (0x1);
349  target = "FIN";
350  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
351  str = TcpHeader::FlagsToString (0x2);
352  target = "SYN";
353  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
354  str = TcpHeader::FlagsToString (0x4);
355  target = "RST";
356  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
357  str = TcpHeader::FlagsToString (0x8);
358  target = "PSH";
359  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
360  str = TcpHeader::FlagsToString (0x10);
361  target = "ACK";
362  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
363  str = TcpHeader::FlagsToString (0x20);
364  target = "URG";
365  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
366  str = TcpHeader::FlagsToString (0x40);
367  target = "ECE";
368  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
369  str = TcpHeader::FlagsToString (0x80);
370  target = "CWR";
371  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
372  str = TcpHeader::FlagsToString (0x3);
373  target = "FIN|SYN";
374  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
375  str = TcpHeader::FlagsToString (0x5);
376  target = "FIN|RST";
377  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
378  str = TcpHeader::FlagsToString (0xff);
379  target = "FIN|SYN|RST|PSH|ACK|URG|ECE|CWR";
380  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
381  str = TcpHeader::FlagsToString (0xff, ":");
382  target = "FIN:SYN:RST:PSH:ACK:URG:ECE:CWR";
383  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
384 }
385 
386 static class TcpHeaderTestSuite : public TestSuite
387 {
388 public:
390  : TestSuite ("tcp-header", UNIT)
391  {
392  AddTestCase (new TcpHeaderGetSetTestCase ("GetSet test cases"), TestCase::QUICK);
393  AddTestCase (new TcpHeaderWithRFC793OptionTestCase ("Test for options in RFC 793"), TestCase::QUICK);
394  AddTestCase (new TcpHeaderFlagsToString ("Test flags to string function"), TestCase::QUICK);
395  }
396 
398 
399 } // namespace ns3
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:55
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
virtual uint32_t GetSerializedSize(void) const
Returns number of bytes required for Option serialization.
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
void SetMSS(uint16_t mss)
Set the Maximum Segment Size stored in the Option.
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
Defines the TCP option of kind 1 (no operation) as in RFC 793
Fast test.
Definition: test.h:1152
A suite of tests to run.
Definition: test.h:1333
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
automatically resized byte buffer
Definition: buffer.h:92
#define GET_RANDOM_UINT6(RandomVariable)
encapsulates test code
Definition: test.h:1147
This test suite implements a Unit Test.
Definition: test.h:1343
iterator in a Buffer instance
Definition: buffer.h:98
TcpHeaderGetSetTestCase(std::string name)
bool AppendOption(Ptr< TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:463
ns3::TcpHeaderTestSuite g_TcpHeaderTestSuite
TcpHeaderFlagsToString(std::string name)
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:298
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
#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:161
virtual void DoRun(void)
Implementation to actually run this TestCase.
Defines the TCP option of kind 0 (end of option list) as in RFC 793
void Next(void)
go forward by one byte
Definition: buffer.h:844
Buffer::Iterator Begin(void) const
Definition: buffer.h:1068
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
void OneOptionAtTime()
Check an header with only one kind of option.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:161
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:125
uint32_t GetSize(void) const
Definition: buffer.h:1062
virtual uint32_t GetSerializedSize(void) const
Definition: tcp-header.cc:309
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:155
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: tcp-header.cc:360
#define GET_RANDOM_UINT16(RandomVariable)
void WriteU8(uint8_t data)
Definition: buffer.h:868
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
#define GET_RANDOM_UINT32(RandomVariable)
Defines the TCP option of kind 2 (maximum segment size) as in RFC 793
uint8_t ReadU8(void)
Definition: buffer.h:1020
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:505
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
virtual void DoRun(void)
Implementation to actually run this TestCase.
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:185
virtual void Serialize(Buffer::Iterator start) const
Definition: tcp-header.cc:315
virtual void DoRun(void)
Implementation to actually run this TestCase.