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 "../model/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");
312  }
313 }
314 
315 
316 void
318 {
319  uint32_t foo;
320  foo = UINT32_MAX;
321  foo--;
322 
323 }
324 
326 {
327 public:
328  TcpHeaderFlagsToString (std::string name);
329 
330 private:
331  virtual void DoRun (void);
332 };
333 
335  : TestCase (name)
336 {
337 }
338 
339 void
341 {
342  std::string str, target;
343  str = TcpHeader::FlagsToString (0x0);
344  target = "";
345  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
346  str = TcpHeader::FlagsToString (0x1);
347  target = "FIN";
348  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
349  str = TcpHeader::FlagsToString (0x2);
350  target = "SYN";
351  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
352  str = TcpHeader::FlagsToString (0x4);
353  target = "RST";
354  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
355  str = TcpHeader::FlagsToString (0x8);
356  target = "PSH";
357  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
358  str = TcpHeader::FlagsToString (0x10);
359  target = "ACK";
360  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
361  str = TcpHeader::FlagsToString (0x20);
362  target = "URG";
363  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
364  str = TcpHeader::FlagsToString (0x40);
365  target = "ECE";
366  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
367  str = TcpHeader::FlagsToString (0x80);
368  target = "CWR";
369  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
370  str = TcpHeader::FlagsToString (0x3);
371  target = "FIN|SYN";
372  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
373  str = TcpHeader::FlagsToString (0x5);
374  target = "FIN|RST";
375  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
376  str = TcpHeader::FlagsToString (0xff);
377  target = "FIN|SYN|RST|PSH|ACK|URG|ECE|CWR";
378  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
379  str = TcpHeader::FlagsToString (0xff, ":");
380  target = "FIN:SYN:RST:PSH:ACK:URG:ECE:CWR";
381  NS_TEST_ASSERT_MSG_EQ (str, target, "str " << str << " does not equal target " << target);
382 }
383 
384 static class TcpHeaderTestSuite : public TestSuite
385 {
386 public:
388  : TestSuite ("tcp-header", UNIT)
389  {
390  AddTestCase (new TcpHeaderGetSetTestCase ("GetSet test cases"), TestCase::QUICK);
391  AddTestCase (new TcpHeaderWithRFC793OptionTestCase ("Test for options in RFC 793"), TestCase::QUICK);
392  AddTestCase (new TcpHeaderFlagsToString ("Test flags to string function"), TestCase::QUICK);
393  }
394 
396 
397 } // 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
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:460
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:297
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:839
Buffer::Iterator Begin(void) const
Definition: buffer.h:1063
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
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:1057
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:863
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:1015
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:502
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.