A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ns3tcp-interop-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 University of Washington
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 #include <string>
20 
21 #include "ns3/log.h"
22 #include "ns3/abort.h"
23 #include "ns3/test.h"
24 #include "ns3/pcap-file.h"
25 #include "ns3/config.h"
26 #include "ns3/string.h"
27 #include "ns3/uinteger.h"
28 #include "ns3/inet-socket-address.h"
29 #include "ns3/point-to-point-helper.h"
30 #include "ns3/internet-stack-helper.h"
31 #include "ns3/ipv4-address-helper.h"
32 #include "ns3/ipv4-header.h"
33 #include "ns3/packet-sink-helper.h"
34 #include "ns3/on-off-helper.h"
35 #include "ns3/simulator.h"
36 
37 using namespace ns3;
38 
39 NS_LOG_COMPONENT_DEFINE ("Ns3TcpInteropTest");
40 
41 const bool WRITE_VECTORS = false; // set to true to write response vectors
42 const uint32_t PCAP_LINK_TYPE = 1187373553; // Some large random number -- we use to verify data was written by this program
43 const uint32_t PCAP_SNAPLEN = 64; // Don't bother to save much data
44 
45 
46 // ===========================================================================
47 // This is a simple test to demonstrate how a known good model (a reference
48 // implementation) may be used to test another model in a relatively simple
49 // way.
50 //
51 // Node zero contains the model under test, in this case the ns-3 TCP
52 // implementation. Node one contains the reference implementation that we
53 // assume will generate good test vectors for us. In this case, a Linux
54 // TCP implementation is used to stimulate the ns-3 TCP model with what we
55 // assume are perfectly good packets. We watch the ns-3 implementation to
56 // see what it does in the presence of these assumed good stimuli.
57 //
58 // The test is arranged as a typical ns-3 script, but we use the trace system
59 // to peek into the running system and monitor the ns-3 TCP.
60 //
61 // The topology is just two nodes communicating over a point-to-point network.
62 // The point-to-point network is chosen because it is simple and allows us to
63 // easily generate pcap traces we can use to separately verify that the ns-3
64 // implementation is responding correctly. Once the opration is verified, we
65 // capture a set of response vectors that are then checked in the test to
66 // ensure that the ns-3 TCP continues to respond correctly over time.
67 //
68 // node 0 node 1
69 // +----------------+ +----------------+
70 // | ns-3 TCP | | Linux TCP |
71 // +----------------+ +----------------+
72 // | 10.1.1.1 | | 10.1.1.2 |
73 // +----------------+ +----------------+
74 // | point-to-point | | point-to-point |
75 // +----------------+ +----------------+
76 // | |
77 // +---------------------+
78 // 5 Mbps, 2 ms
79 //
80 // ===========================================================================
82 {
83 public:
86 
87 private:
88  virtual void DoSetup (void);
89  virtual void DoRun (void);
90  virtual void DoTeardown (void);
91 
92  void Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface);
93 
94  std::string m_pcapFilename;
97 };
98 
100  : TestCase ("Check to see that the ns-3 TCP can work with liblinux2.6.26.so"), m_writeVectors (WRITE_VECTORS)
101 {
102 }
103 
105 {
106 }
107 
108 void
110 {
111  //
112  // We expect there to be a file called tcp-interop-response-vectors.pcap in
113  // response-vectors/ of this directory
114  //
115  m_pcapFilename = static_cast<std::string> (NS_TEST_SOURCEDIR) +
116  static_cast<std::string> ("/response-vectors/ns3tcp-interop-response-vectors.pcap");
117 
118  if (m_writeVectors)
119  {
120  m_pcapFile.Open (m_pcapFilename, std::ios::out|std::ios::binary);
122  }
123  else
124  {
125  m_pcapFile.Open (m_pcapFilename, std::ios::in|std::ios::binary);
126  NS_ABORT_MSG_UNLESS (m_pcapFile.GetDataLinkType () == PCAP_LINK_TYPE, "Wrong response vectors in directory");
127  }
128 }
129 
130 void
132 {
133  m_pcapFile.Close ();
134 }
135 
136 void
137 Ns3TcpInteroperabilityTestCase::Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface)
138 {
139  //
140  // We're not testing IP so remove and toss the header. In order to do this,
141  // though, we need to copy the packet since we have a const version.
142  //
143  Ptr<Packet> p = packet->Copy ();
144  Ipv4Header ipHeader;
145  p->RemoveHeader (ipHeader);
146 
147  //
148  // What is left is the TCP header and any data that may be sent. We aren't
149  // sending any TCP data, so we expect what remains is only TCP header, which
150  // is a small thing to save.
151  //
152  if (m_writeVectors)
153  {
154  //
155  // Save the TCP under test response for later testing.
156  //
157  Time tNow = Simulator::Now ();
158  int64_t tMicroSeconds = tNow.GetMicroSeconds ();
159 
160  uint32_t size = p->GetSize ();
161  uint8_t *buf = new uint8_t[size];
162  p->CopyData (buf, size);
163 
164  m_pcapFile.Write (uint32_t (tMicroSeconds / 1000000),
165  uint32_t (tMicroSeconds % 1000000),
166  buf,
167  size);
168  delete [] buf;
169  }
170  else
171  {
172  //
173  // Read the TCP under test expected response from the expected vector
174  // file and see if it still does the right thing.
175  //
176  uint8_t expected[PCAP_SNAPLEN];
177  uint32_t tsSec, tsUsec, inclLen, origLen, readLen;
178  m_pcapFile.Read (expected, sizeof(expected), tsSec, tsUsec, inclLen, origLen, readLen);
179 
180  uint8_t *actual = new uint8_t[readLen];
181  p->CopyData (actual, readLen);
182 
183  uint32_t result = memcmp (actual, expected, readLen);
184 
185  delete [] actual;
186 
187  //
188  // Avoid streams of errors -- only report the first.
189  //
190  if (IsStatusSuccess ())
191  {
192  NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error");
193  }
194  }
195 }
196 
197 void
199 {
200  //
201  // Just create two nodes. One (node zero) will be the node with the TCP
202  // under test which is the ns-3 TCP implementation. The other node (node
203  // one) will be the node with the reference implementation we use to drive
204  // the tests.
205  //
207  nodes.Create (2);
208 
209  //
210  // For this test we'll use a point-to-point net device. It's not as simple
211  // as a simple-net-device, but it provides nice places to hook trace events
212  // so we can see what's moving between our nodes.
213  //
215  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
216  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
217 
218  //
219  // Install the point-to-point devices on both nodes and connec them up.
220  //
222  devices = pointToPoint.Install (nodes);
223 
224  //
225  // Install two variants of the internet stack. The first, on node zero
226  // uses the TCP under test, which is the default ns-3 TCP implementation.
227  //
229  stack.Install (nodes.Get (0));
230 
231  //
232  // The other node, node one, is going to be set up to use a Linux TCP
233  // implementation that we consider a known good TCP.
234  //
235  std::string nscStack = "liblinux2.6.26.so";
236  stack.SetTcp ("ns3::NscTcpL4Protocol", "Library", StringValue ("liblinux2.6.26.so"));
237  stack.Install (nodes.Get (1));
238 
239  //
240  // Assign the address 10.1.1.1 to the TCP implementation under test (index
241  // zero) and 10.1.1.2 to the reference implementation (index one).
242  //
244  address.SetBase ("10.1.1.0", "255.255.255.252");
245  Ipv4InterfaceContainer interfaces = address.Assign (devices);
246 
247  //
248  // We need a place for the TCP data to go on the node with the TCP under
249  // test, so just create a sink on node zero.
250  //
251  uint16_t sinkPort = 8080;
252  Address sinkAddress (InetSocketAddress (interfaces.GetAddress (0), sinkPort));
253  PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
254  ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (0));
255  sinkApps.Start (Seconds (0.));
256 
257  //
258  // We need something to shove data down the pipe, so we create an on-off
259  // application on the soure node with the reference TCP implementation.
260  // The default behavior is to send for one second, then go quiet for one
261  // second, and repeat.
262  //
263  OnOffHelper onOffHelper ("ns3::TcpSocketFactory", sinkAddress);
264  onOffHelper.SetAttribute ("MaxBytes", UintegerValue (100000));
265  ApplicationContainer sourceApps = onOffHelper.Install (nodes.Get (1));
266  sourceApps.Start (Seconds (1.));
267  sourceApps.Stop (Seconds (10.));
268 
269  //
270  // There are currently a limited number of trace hooks in the ns-3 TCP code.
271  // Rather than editing TCP to insert a bunch of trace hooks, we can just
272  // intercept the packets at the IPv4 layer. See internet-stack-helper.cc
273  // for complete description of the trace hooks. We're interested in the
274  // responses of the TCP under test, which implies we need to hook the node
275  // zero Ipv4 layer three transmit trace source. We'll then get all of the
276  // responses we need
277  //
278  Config::Connect ("/NodeList/0/$ns3::Ipv4L3Protocol/Tx",
280 
281  //
282  // The idea here is that someone will look very closely at the all of the
283  // communications between the reference TCP and the TCP under test in this
284  // simulation and determine that all of the responses are correct. We expect
285  // that this means generating a pcap trace file from the point-to-point link
286  // and examining the packets closely using tcpdump, wireshark or some such
287  // program. So we provide the ability to generate a pcap trace of the
288  // test execution for your perusal.
289  //
290  // Once the validation test is determined to be running exactly as exptected,
291  // we allow you to generate a file that contains the response vectors that
292  // will be checked during the actual execution of the test.
293  //
294 
295  if (m_writeVectors)
296  {
297  pointToPoint.EnablePcapAll ("tcp-interop");
298  }
299 
300  Simulator::Stop (Seconds (20));
301  Simulator::Run ();
302  Simulator::Destroy ();
303 }
304 
306 {
307 public:
309 };
310 
312  : TestSuite ("ns3-tcp-interoperability", SYSTEM)
313 {
314  AddTestCase (new Ns3TcpInteroperabilityTestCase, TestCase::QUICK);
315 }
316 
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
holds a vector of ns3::Application pointers.
tuple pointToPoint
Definition: first.py:28
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
an Inet address class
tuple devices
Definition: first.py:32
holds a vector of std::pair of Ptr and interface index.
hold variables of type string
Definition: string.h:18
NetDeviceContainer Install(NodeContainer c)
A suite of tests to run.
Definition: test.h:1105
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
aggregate IP/TCP/UDP functionality to existing Nodes.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:265
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:744
virtual void DoSetup(void)
Implementation to do any local setup required for this TestCase.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes...
Build a set of PointToPointNetDevice objects.
encapsulates test code
Definition: test.h:929
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:728
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
Definition: on-off-helper.h:42
a polymophic address class
Definition: address.h:86
tuple nodes
Definition: first.py:25
Packet header for IPv4.
Definition: ipv4-header.h:31
void EnablePcapAll(std::string prefix, bool promiscuous=false)
Enable pcap output on each device (which is of the appropriate type) in the set of all nodes created ...
int64_t GetMicroSeconds(void) const
Definition: nstime.h:289
A class representing a pcap file.
Definition: pcap-file.h:42
void Read(uint8_t *const data, uint32_t maxBytes, uint32_t &tsSec, uint32_t &tsUsec, uint32_t &inclLen, uint32_t &origLen, uint32_t &readLen)
Read next packet from file.
Definition: pcap-file.cc:437
Hold an unsigned integer type.
Definition: uinteger.h:46
tuple interfaces
Definition: first.py:40
holds a vector of ns3::NetDevice pointers
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1242
const bool WRITE_VECTORS
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter...
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
keep track of a set of node pointers.
void SetTcp(std::string tid)
set the Tcp stack which will not need any other parameter.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
void Init(uint32_t dataLinkType, uint32_t snapLen=SNAPLEN_DEFAULT, int32_t timeZoneCorrection=ZONE_DEFAULT, bool swapMode=false)
Initialize the pcap file associated with this object.
Definition: pcap-file.cc:329
const uint32_t PCAP_SNAPLEN
void Close(void)
Close the underlying file.
Definition: pcap-file.cc:86
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual child TestCase case to this TestCase.
Definition: test.cc:184
bool IsStatusSuccess(void) const
Definition: test.cc:347
tuple stack
Definition: first.py:34
void Open(std::string const &filename, std::ios::openmode mode)
Create a new pcap file or open an existing pcap file.
Definition: pcap-file.cc:310
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter...
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
Definition: abort.h:136
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
Ptr< Node > Get(uint32_t i) const
Get the Ptr stored in this container at a given index.
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
const uint32_t PCAP_LINK_TYPE
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:381
ApplicationContainer Install(NodeContainer c) const
Install an ns3::PacketSinkApplication on each node of the input container configured with all the att...
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
uint32_t GetDataLinkType(void)
Returns the data link type field of the pcap file as defined by the network field in the pcap global ...
Definition: pcap-file.cc:135
tuple address
Definition: first.py:37
void Write(uint32_t tsSec, uint32_t tsUsec, uint8_t const *const data, uint32_t totalLen)
Write next packet to file.
Definition: pcap-file.cc:404
ApplicationContainer Install(NodeContainer c) const
Install an ns3::OnOffApplication on each node of the input container configured with all the attribut...
void Ipv4L3Tx(std::string context, Ptr< const Packet > packet, Ptr< Ipv4 > ipv4, uint32_t interface)
void SetAttribute(std::string name, const AttributeValue &value)
Helper function used to set the underlying application attributes.
static Ns3TcpInteroperabilityTestSuite ns3TcpInteroperabilityTestSuite
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const