A Discrete-Event Network Simulator
API
nix-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 NITK Surathkal
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Ameya Deshpande <ameyanrd@outlook.com>
18  */
19 
20 #include "ns3/icmpv4-l4-protocol.h"
21 #include "ns3/icmpv6-l4-protocol.h"
22 #include "ns3/internet-stack-helper.h"
23 #include "ns3/ipv4-address-helper.h"
24 #include "ns3/ipv4-l3-protocol.h"
25 #include "ns3/ipv6-address-helper.h"
26 #include "ns3/ipv6-l3-protocol.h"
27 #include "ns3/nix-vector-helper.h"
28 #include "ns3/simple-net-device-helper.h"
29 #include "ns3/simulator.h"
30 #include "ns3/socket-factory.h"
31 #include "ns3/socket.h"
32 #include "ns3/test.h"
33 #include "ns3/udp-l4-protocol.h"
34 #include "ns3/udp-socket-factory.h"
35 
36 using namespace ns3;
37 
66 {
68 
74  void DoSendDatav4(Ptr<Socket> socket, Ipv4Address to);
75 
81  void DoSendDatav6(Ptr<Socket> socket, Ipv6Address to);
82 
89  void SendData(Time delay, Ptr<Socket> socket, Ipv4Address to);
90 
97  void SendData(Time delay, Ptr<Socket> socket, Ipv6Address to);
98 
99  public:
100  void DoRun() override;
102 
107  void ReceivePkt(Ptr<Socket> socket);
108 
109  std::vector<uint32_t> m_receivedPacketSizes;
110 };
111 
113  : TestCase("three router, two path test")
114 {
115 }
116 
117 void
119 {
120  uint32_t availableData [[maybe_unused]] = socket->GetRxAvailable();
122  NS_TEST_ASSERT_MSG_EQ(availableData,
124  "availableData should be equal to the size of packet received.");
126 }
127 
128 void
130 {
131  Address realTo = InetSocketAddress(to, 1234);
132  socket->SendTo(Create<Packet>(123), 0, realTo);
133 }
134 
135 void
137 {
138  Address realTo = Inet6SocketAddress(to, 1234);
139  socket->SendTo(Create<Packet>(123), 0, realTo);
140 }
141 
142 void
144 {
145  m_receivedPacket = Create<Packet>();
146  Simulator::ScheduleWithContext(socket->GetNode()->GetId(),
147  delay,
149  this,
150  socket,
151  to);
152 }
153 
154 void
156 {
157  m_receivedPacket = Create<Packet>();
158  Simulator::ScheduleWithContext(socket->GetNode()->GetId(),
159  delay,
161  this,
162  socket,
163  to);
164 }
165 
166 void
168 {
169  // Create topology
170  NodeContainer nSrcnA;
171  NodeContainer nAnB;
172  NodeContainer nBnC;
173  NodeContainer nCnDst;
174  NodeContainer nAnC;
175 
176  nSrcnA.Create(2);
177 
178  nAnB.Add(nSrcnA.Get(1));
179  nAnB.Create(1);
180 
181  nBnC.Add(nAnB.Get(1));
182  nBnC.Create(1);
183 
184  nCnDst.Add(nBnC.Get(1));
185  nCnDst.Create(1);
186 
187  nAnC.Add(nAnB.Get(0));
188  nAnC.Add(nCnDst.Get(0));
189 
190  SimpleNetDeviceHelper devHelper;
191  devHelper.SetNetDevicePointToPointMode(true);
192 
193  NodeContainer allNodes = NodeContainer(nSrcnA, nBnC, nCnDst.Get(1));
194 
195  std::ostringstream stringStream1v4;
196  Ptr<OutputStreamWrapper> routingStream1v4 = Create<OutputStreamWrapper>(&stringStream1v4);
197  std::ostringstream stringStream1v6;
198  Ptr<OutputStreamWrapper> routingStream1v6 = Create<OutputStreamWrapper>(&stringStream1v6);
199  std::ostringstream stringStream2v4;
200  Ptr<OutputStreamWrapper> cacheStreamv4 = Create<OutputStreamWrapper>(&stringStream2v4);
201  std::ostringstream stringStream2v6;
202  Ptr<OutputStreamWrapper> cacheStreamv6 = Create<OutputStreamWrapper>(&stringStream2v6);
203  std::ostringstream stringStream3v4;
204  Ptr<OutputStreamWrapper> routingStream3v4 = Create<OutputStreamWrapper>(&stringStream3v4);
205  std::ostringstream stringStream3v6;
206  Ptr<OutputStreamWrapper> routingStream3v6 = Create<OutputStreamWrapper>(&stringStream3v6);
207 
208  // NixHelper to install nix-vector routing on all nodes
209  Ipv4NixVectorHelper ipv4NixRouting;
210  Ipv6NixVectorHelper ipv6NixRouting;
212  stack.SetRoutingHelper(ipv4NixRouting); // has effect on the next Install ()
213  stack.SetRoutingHelper(ipv6NixRouting); // has effect on the next Install ()
214  stack.Install(allNodes);
215 
216  NetDeviceContainer dSrcdA;
217  NetDeviceContainer dAdB;
218  NetDeviceContainer dBdC;
219  NetDeviceContainer dCdDst;
220  NetDeviceContainer dAdC;
221  dSrcdA = devHelper.Install(nSrcnA);
222  dAdB = devHelper.Install(nAnB);
223  dBdC = devHelper.Install(nBnC);
224  dCdDst = devHelper.Install(nCnDst);
225  dAdC = devHelper.Install(nAnC);
226 
227  Ipv4AddressHelper aSrcaAv4;
228  aSrcaAv4.SetBase("10.1.0.0", "255.255.255.0");
229  Ipv4AddressHelper aAaBv4;
230  aAaBv4.SetBase("10.1.1.0", "255.255.255.0");
231  Ipv4AddressHelper aBaCv4;
232  aBaCv4.SetBase("10.1.2.0", "255.255.255.0");
233  Ipv4AddressHelper aCaDstv4;
234  aCaDstv4.SetBase("10.1.3.0", "255.255.255.0");
235  Ipv4AddressHelper aAaCv4;
236  aAaCv4.SetBase("10.1.4.0", "255.255.255.0");
237 
238  Ipv6AddressHelper aSrcaAv6;
239  aSrcaAv6.SetBase(Ipv6Address("2001:0::"), Ipv6Prefix(64));
240  Ipv6AddressHelper aAaBv6;
241  aAaBv6.SetBase(Ipv6Address("2001:1::"), Ipv6Prefix(64));
242  Ipv6AddressHelper aBaCv6;
243  aBaCv6.SetBase(Ipv6Address("2001:2::"), Ipv6Prefix(64));
244  Ipv6AddressHelper aCaDstv6;
245  aCaDstv6.SetBase(Ipv6Address("2001:3::"), Ipv6Prefix(64));
246  Ipv6AddressHelper aAaCv6;
247  aAaCv6.SetBase(Ipv6Address("2001:4::"), Ipv6Prefix(64));
248 
249  aSrcaAv4.Assign(dSrcdA);
250  aAaBv4.Assign(dAdB);
251  aBaCv4.Assign(dBdC);
252  Ipv4InterfaceContainer iCiDstv4 = aCaDstv4.Assign(dCdDst);
253  Ipv4InterfaceContainer iAiCv4 = aAaCv4.Assign(dAdC);
254 
255  aSrcaAv6.Assign(dSrcdA);
256  aAaBv6.Assign(dAdB);
257  aBaCv6.Assign(dBdC);
258  Ipv6InterfaceContainer iCiDstv6 = aCaDstv6.Assign(dCdDst);
259  Ipv6InterfaceContainer iAiCv6 = aAaCv6.Assign(dAdC);
260 
261  // Create the UDP sockets
262  Ptr<SocketFactory> rxSocketFactory = nCnDst.Get(1)->GetObject<UdpSocketFactory>();
263  Ptr<Socket> rxSocketv4 = rxSocketFactory->CreateSocket();
264  Ptr<Socket> rxSocketv6 = rxSocketFactory->CreateSocket();
265  NS_TEST_EXPECT_MSG_EQ(rxSocketv4->Bind(InetSocketAddress(iCiDstv4.GetAddress(1), 1234)),
266  0,
267  "trivial");
268  NS_TEST_EXPECT_MSG_EQ(rxSocketv6->Bind(Inet6SocketAddress(iCiDstv6.GetAddress(1, 1), 1234)),
269  0,
270  "trivial");
271  rxSocketv4->SetRecvCallback(MakeCallback(&NixVectorRoutingTest::ReceivePkt, this));
273 
274  Ptr<SocketFactory> txSocketFactory = nSrcnA.Get(0)->GetObject<UdpSocketFactory>();
275  Ptr<Socket> txSocket = txSocketFactory->CreateSocket();
276  txSocket->SetAllowBroadcast(true);
277 
278  SendData(Seconds(2), txSocket, Ipv4Address("10.1.3.2"));
279  SendData(Seconds(2), txSocket, Ipv6Address("2001:3::200:ff:fe00:8"));
280 
281  ipv4NixRouting.PrintRoutingPathAt(Seconds(3),
282  nSrcnA.Get(0),
283  iCiDstv4.GetAddress(1),
284  routingStream1v4);
285  ipv6NixRouting.PrintRoutingPathAt(Seconds(3),
286  nSrcnA.Get(0),
287  iCiDstv6.GetAddress(1, 1),
288  routingStream1v6);
289 
290  // Set the IPv4 nA interface on nA - nC channel down.
291  Ptr<Ipv4> ipv4 = nAnC.Get(0)->GetObject<Ipv4>();
292  int32_t ifIndex = ipv4->GetInterfaceForDevice(dAdC.Get(0));
293  Simulator::Schedule(Seconds(5), &Ipv4::SetDown, ipv4, ifIndex);
294 
295  // Set the IPv6 nA interface on nA - nC channel down.
296  Ptr<Ipv6> ipv6 = nAnC.Get(0)->GetObject<Ipv6>();
297  ifIndex = ipv6->GetInterfaceForDevice(dAdC.Get(0));
298  Simulator::Schedule(Seconds(5), &Ipv6::SetDown, ipv6, ifIndex);
299 
300  Ipv4NixVectorHelper::PrintRoutingTableAllAt(Seconds(7), cacheStreamv4);
301  Ipv6NixVectorHelper::PrintRoutingTableAllAt(Seconds(7), cacheStreamv6);
302 
303  SendData(Seconds(8), txSocket, Ipv4Address("10.1.3.2"));
304  SendData(Seconds(8), txSocket, Ipv6Address("2001:3::200:ff:fe00:8"));
305 
306  ipv4NixRouting.PrintRoutingPathAt(Seconds(9),
307  nSrcnA.Get(0),
308  iCiDstv4.GetAddress(1),
309  routingStream3v4);
310  ipv6NixRouting.PrintRoutingPathAt(Seconds(9),
311  nSrcnA.Get(0),
312  iCiDstv6.GetAddress(1, 1),
313  routingStream3v6);
314 
315  // Set the IPv4 nC interface on nB - nC channel down.
316  ipv4 = nBnC.Get(1)->GetObject<Ipv4>();
317  ifIndex = ipv4->GetInterfaceForDevice(dBdC.Get(1));
318  Simulator::Schedule(Seconds(10), &Ipv4::SetDown, ipv4, ifIndex);
319 
320  // Set the IPv6 nC interface on nB - nC channel down.
321  ipv6 = nBnC.Get(1)->GetObject<Ipv6>();
322  ifIndex = ipv6->GetInterfaceForDevice(dBdC.Get(1));
323  Simulator::Schedule(Seconds(10), &Ipv6::SetDown, ipv6, ifIndex);
324 
325  SendData(Seconds(11), txSocket, Ipv4Address("10.1.3.2"));
326  SendData(Seconds(11), txSocket, Ipv6Address("2001:3::200:ff:fe00:8"));
327 
328  Simulator::Stop(Seconds(66));
329  Simulator::Run();
330 
331  // ------ Now the tests ------------
332 
333  // Test the Routing
334  NS_TEST_EXPECT_MSG_EQ(m_receivedPacketSizes[0], 123, "IPv4 Nix-Vector Routing should work.");
335  NS_TEST_EXPECT_MSG_EQ(m_receivedPacketSizes[1], 123, "IPv6 Nix-Vector Routing should work.");
337  4,
338  "IPv4 and IPv6 Nix-Vector Routing should have received only 1 packet.");
339 
340  // Test the Path
341  const std::string p_nSrcnAnCnDstv4 =
342  "Time: +3s, Nix Routing\n"
343  "Route path from Node 0 to Node 4, Nix Vector: 01001 (5 bits left)\n"
344  "10.1.0.1 (Node 0) ----> 10.1.0.2 (Node 1)\n"
345  "10.1.4.1 (Node 1) ----> 10.1.4.2 (Node 3)\n"
346  "10.1.3.1 (Node 3) ----> 10.1.3.2 (Node 4)\n\n";
347  NS_TEST_EXPECT_MSG_EQ(stringStream1v4.str(), p_nSrcnAnCnDstv4, "Routing Path is incorrect.");
348 
349  const std::string p_nSrcnAnCnDstv6 =
350  "Time: +3s, Nix Routing\n"
351  "Route path from Node 0 to Node 4, Nix Vector: 01001 (5 bits left)\n"
352  "2001::200:ff:fe00:1 (Node 0) ----> fe80::200:ff:fe00:2 (Node 1)\n"
353  "fe80::200:ff:fe00:9 (Node 1) ----> fe80::200:ff:fe00:a (Node 3)\n"
354  "fe80::200:ff:fe00:7 (Node 3) ----> 2001:3::200:ff:fe00:8 (Node 4)\n\n";
355  NS_TEST_EXPECT_MSG_EQ(stringStream1v6.str(), p_nSrcnAnCnDstv6, "Routing Path is incorrect.");
356 
357  const std::string p_nSrcnAnBnCnDstv4 =
358  "Time: +9s, Nix Routing\n"
359  "Route path from Node 0 to Node 4, Nix Vector: 0111 (4 bits left)\n"
360  "10.1.0.1 (Node 0) ----> 10.1.0.2 (Node 1)\n"
361  "10.1.1.1 (Node 1) ----> 10.1.1.2 (Node 2)\n"
362  "10.1.2.1 (Node 2) ----> 10.1.2.2 (Node 3)\n"
363  "10.1.3.1 (Node 3) ----> 10.1.3.2 (Node 4)\n\n";
364  NS_TEST_EXPECT_MSG_EQ(stringStream3v4.str(), p_nSrcnAnBnCnDstv4, "Routing Path is incorrect.");
365 
366  const std::string p_nSrcnAnBnCnDstv6 =
367  "Time: +9s, Nix Routing\n"
368  "Route path from Node 0 to Node 4, Nix Vector: 0111 (4 bits left)\n"
369  "2001::200:ff:fe00:1 (Node 0) ----> fe80::200:ff:fe00:2 (Node 1)\n"
370  "fe80::200:ff:fe00:3 (Node 1) ----> fe80::200:ff:fe00:4 (Node 2)\n"
371  "fe80::200:ff:fe00:5 (Node 2) ----> fe80::200:ff:fe00:6 (Node 3)\n"
372  "fe80::200:ff:fe00:7 (Node 3) ----> 2001:3::200:ff:fe00:8 (Node 4)\n\n";
373  NS_TEST_EXPECT_MSG_EQ(stringStream3v6.str(), p_nSrcnAnBnCnDstv6, "Routing Path is incorrect.");
374 
375  const std::string emptyCaches = "Node: 0, Time: +7s, Local time: +7s, Nix Routing\n"
376  "NixCache:\n"
377  "IpRouteCache:\n\n"
378  "Node: 1, Time: +7s, Local time: +7s, Nix Routing\n"
379  "NixCache:\n"
380  "IpRouteCache:\n\n"
381  "Node: 2, Time: +7s, Local time: +7s, Nix Routing\n"
382  "NixCache:\n"
383  "IpRouteCache:\n\n"
384  "Node: 3, Time: +7s, Local time: +7s, Nix Routing\n"
385  "NixCache:\n"
386  "IpRouteCache:\n\n"
387  "Node: 4, Time: +7s, Local time: +7s, Nix Routing\n"
388  "NixCache:\n"
389  "IpRouteCache:\n\n";
390  NS_TEST_EXPECT_MSG_EQ(stringStream2v4.str(), emptyCaches, "The caches should have been empty.");
391  NS_TEST_EXPECT_MSG_EQ(stringStream2v6.str(), emptyCaches, "The caches should have been empty.");
392 
393  Simulator::Destroy();
394 }
395 
403 {
404  public:
406  : TestSuite("nix-vector-routing", UNIT)
407  {
408  AddTestCase(new NixVectorRoutingTest(), TestCase::QUICK);
409  }
410 };
411 
#define max(a, b)
Definition: 80211b.c:42
The topology is of the form:
Definition: nix-test.cc:66
void DoSendDatav4(Ptr< Socket > socket, Ipv4Address to)
Send data immediately after being called.
Definition: nix-test.cc:129
void DoRun() override
Implementation to actually run this TestCase.
Definition: nix-test.cc:167
std::vector< uint32_t > m_receivedPacketSizes
Received packet sizes.
Definition: nix-test.cc:109
Ptr< Packet > m_receivedPacket
Received packet.
Definition: nix-test.cc:67
void ReceivePkt(Ptr< Socket > socket)
Receive data.
Definition: nix-test.cc:118
void DoSendDatav6(Ptr< Socket > socket, Ipv6Address to)
Send data immediately after being called.
Definition: nix-test.cc:136
void SendData(Time delay, Ptr< Socket > socket, Ipv4Address to)
Schedules the DoSendData () function to send the data.
Definition: nix-test.cc:143
IPv4 Nix-Vector Routing TestSuite.
Definition: nix-test.cc:403
a polymophic address class
Definition: address.h:101
An Inet6 address class.
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:80
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
Helper class to auto-assign global IPv6 unicast addresses.
void SetBase(Ipv6Address network, Ipv6Prefix prefix, Ipv6Address base=Ipv6Address("::1"))
Set the base network number, network prefix, and base interface ID.
Ipv6InterfaceContainer Assign(const NetDeviceContainer &c)
Allocate an Ipv6InterfaceContainer with auto-assigned addresses.
Describes an IPv6 address.
Definition: ipv6-address.h:49
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
Keep track of a set of IPv6 interfaces.
Ipv6Address GetAddress(uint32_t i, uint32_t j) const
Get the address for the specified index.
Describes an IPv6 prefix.
Definition: ipv6-address.h:455
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
Helper class that adds Nix-vector routing to nodes.
void PrintRoutingPathAt(Time printTime, Ptr< Node > source, IpAddress dest, Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S)
prints the routing path for a source and destination at a particular time.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
void Add(const NodeContainer &nc)
Append the contents of another NodeContainer to the end of this container.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t GetId() const
Definition: node.cc:117
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
build a set of SimpleNetDevice objects
void SetNetDevicePointToPointMode(bool pointToPointMode)
SimpleNetDevice is Broadcast capable and ARP needing.
NetDeviceContainer Install(Ptr< Node > node) const
This method creates an ns3::SimpleChannel with the attributes configured by SimpleNetDeviceHelper::Se...
virtual uint32_t GetRxAvailable() const =0
Return number of bytes which can be returned from one or multiple calls to Recv.
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
virtual Ptr< Node > GetNode() const =0
Return the node this socket is associated with.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
API to create UDP socket instances.
#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:144
#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:251
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
stack
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
static NixVectorRoutingTestSuite g_nixVectorRoutingTestSuite
Static variable for test initialization.
Definition: nix-test.cc:413