A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
36using namespace ns3;
37
38/**
39 * \defgroup nix-vector-routing-test Nix-Vector Routing Tests
40 */
41
42/**
43 * \ingroup nix-vector-routing-test
44 * \ingroup tests
45 *
46 * The topology is of the form:
47 * \verbatim
48 __________
49 / \
50 nSrc -- nA -- nB -- nC -- nDst
51 \endverbatim
52 *
53 * Following are the tests in this test case:
54 * - Test the routing from nSrc to nDst.
55 * - Test if the path taken is the shortest path.
56 * (Set down the interface of nA on nA-nC channel.)
57 * - Test if the NixCache and Ipv4RouteCache are empty.
58 * - Test the routing from nSrc to nDst again.
59 * - Test if the new shortest path is taken.
60 * (Set down the interface of nC on nB-nC channel.)
61 * - Test that routing is not possible from nSrc to nDst.
62 *
63 * \brief IPv4 Nix-Vector Routing Test
64 */
66{
67 Ptr<Packet> m_receivedPacket; //!< Received packet
68
69 /**
70 * \brief Send data immediately after being called.
71 * \param socket The sending socket.
72 * \param to IPv4 Destination address.
73 */
74 void DoSendDatav4(Ptr<Socket> socket, Ipv4Address to);
75
76 /**
77 * \brief Send data immediately after being called.
78 * \param socket The sending socket.
79 * \param to IPv6 Destination address.
80 */
81 void DoSendDatav6(Ptr<Socket> socket, Ipv6Address to);
82
83 /**
84 * \brief Schedules the DoSendData () function to send the data.
85 * \param delay The scheduled time to send data.
86 * \param socket The sending socket.
87 * \param to IPv4 Destination address.
88 */
89 void SendData(Time delay, Ptr<Socket> socket, Ipv4Address to);
90
91 /**
92 * \brief Schedules the DoSendData () function to send the data.
93 * \param delay The scheduled time to send data.
94 * \param socket The sending socket.
95 * \param to IPv6 Destination address.
96 */
97 void SendData(Time delay, Ptr<Socket> socket, Ipv6Address to);
98
99 public:
100 void DoRun() override;
102
103 /**
104 * \brief Receive data.
105 * \param socket The receiving socket.
106 */
107 void ReceivePkt(Ptr<Socket> socket);
108
109 std::vector<uint32_t> m_receivedPacketSizes; //!< Received packet sizes
110};
111
113 : TestCase("three router, two path test")
114{
115}
116
117void
119{
120 uint32_t availableData [[maybe_unused]] = socket->GetRxAvailable();
121 m_receivedPacket = socket->Recv(std::numeric_limits<uint32_t>::max(), 0);
122 NS_TEST_ASSERT_MSG_EQ(availableData,
124 "availableData should be equal to the size of packet received.");
126}
127
128void
130{
131 Address realTo = InetSocketAddress(to, 1234);
132 socket->SendTo(Create<Packet>(123), 0, realTo);
133}
134
135void
137{
138 Address realTo = Inet6SocketAddress(to, 1234);
139 socket->SendTo(Create<Packet>(123), 0, realTo);
140}
141
142void
144{
145 m_receivedPacket = Create<Packet>();
146 Simulator::ScheduleWithContext(socket->GetNode()->GetId(),
147 delay,
149 this,
150 socket,
151 to);
152}
153
154void
156{
157 m_receivedPacket = Create<Packet>();
158 Simulator::ScheduleWithContext(socket->GetNode()->GetId(),
159 delay,
161 this,
162 socket,
163 to);
164}
165
166void
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;
219 NetDeviceContainer dCdDst;
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));
272 rxSocketv6->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
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
394}
395
396/**
397 * \ingroup nix-vector-routing-test
398 * \ingroup tests
399 *
400 * \brief IPv4 Nix-Vector Routing TestSuite
401 */
403{
404 public:
406 : TestSuite("nix-vector-routing", Type::UNIT)
407 {
408 AddTestCase(new NixVectorRoutingTest(), TestCase::Duration::QUICK);
409 }
410};
411
412/// Static variable for test initialization
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
virtual void SetDown(uint32_t interface)=0
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
virtual void SetDown(uint32_t interface)=0
Set the interface into the "down" state.
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.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:522
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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...
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void ScheduleWithContext(uint32_t context, const Time &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition: simulator.h:588
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
static constexpr auto UNIT
Definition: test.h:1286
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:145
#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:252
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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