A Discrete-Event Network Simulator
API
ipv6-radvd-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 Universita' di Firenze, Italy
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  * Authors: Tommaso Pecorella <tommaso.pecorella@unifi.it>
18  *
19  */
20 
21 #include "ns3/data-rate.h"
22 #include "ns3/internet-stack-helper.h"
23 #include "ns3/ipv6-address-helper.h"
24 #include "ns3/ipv6-route.h"
25 #include "ns3/ipv6-routing-helper.h"
26 #include "ns3/ipv6-routing-protocol.h"
27 #include "ns3/radvd-helper.h"
28 #include "ns3/simple-net-device-helper.h"
29 #include "ns3/simple-net-device.h"
30 #include "ns3/test.h"
31 
32 using namespace ns3;
33 
45 class RadvdTestCase : public TestCase
46 {
47  public:
48  RadvdTestCase();
49  ~RadvdTestCase() override;
50 
51  private:
52  void DoRun() override;
53 
61  void CheckAddresses(Ptr<NetDevice> n0Dev,
62  Ptr<NetDevice> r0Dev,
63  Ptr<NetDevice> r1Dev,
64  Ptr<NetDevice> n1Dev);
72  void CheckRouting(Ptr<NetDevice> n0Dev,
73  Ptr<NetDevice> r0Dev,
74  Ptr<NetDevice> r1Dev,
75  Ptr<NetDevice> n1Dev);
76 
77  std::vector<Ipv6Address> m_addresses;
78  std::vector<Socket::SocketErrno> m_routingResults;
79  std::vector<Ptr<Ipv6Route>> m_routes;
80 };
81 
83  : TestCase("Radvd test case ")
84 {
85 }
86 
88 {
89 }
90 
91 void
93  Ptr<NetDevice> r0Dev,
94  Ptr<NetDevice> r1Dev,
95  Ptr<NetDevice> n1Dev)
96 {
98 
99  ipv6 = n0Dev->GetNode()->GetObject<Ipv6L3Protocol>();
100  m_addresses.push_back(ipv6->GetAddress(ipv6->GetInterfaceForDevice(n0Dev), 1).GetAddress());
101 
102  ipv6 = r0Dev->GetNode()->GetObject<Ipv6L3Protocol>();
103  m_addresses.push_back(ipv6->GetAddress(ipv6->GetInterfaceForDevice(r0Dev), 1).GetAddress());
104 
105  ipv6 = r1Dev->GetNode()->GetObject<Ipv6L3Protocol>();
106  m_addresses.push_back(ipv6->GetAddress(ipv6->GetInterfaceForDevice(r1Dev), 1).GetAddress());
107 
108  ipv6 = n1Dev->GetNode()->GetObject<Ipv6L3Protocol>();
109  m_addresses.push_back(ipv6->GetAddress(ipv6->GetInterfaceForDevice(n1Dev), 1).GetAddress());
110 }
111 
112 void
114  Ptr<NetDevice> r0Dev,
115  Ptr<NetDevice> r1Dev,
116  Ptr<NetDevice> n1Dev)
117 {
118  Ptr<Ipv6L3Protocol> ipv6;
119  Ptr<Packet> p = Create<Packet>();
120  Ipv6Header ipHdr;
121  Socket::SocketErrno sockerr;
122  Ptr<Ipv6Route> route;
123 
124  ipv6 = n0Dev->GetNode()->GetObject<Ipv6L3Protocol>();
125  ipHdr.SetSource(m_addresses[0]);
126  ipHdr.SetDestination(m_addresses[1]);
127  route = ipv6->GetRoutingProtocol()->RouteOutput(p, ipHdr, n0Dev, sockerr);
128  m_routingResults.push_back(sockerr);
129  m_routes.push_back(route);
130 
131  ipv6 = r0Dev->GetNode()->GetObject<Ipv6L3Protocol>();
132  ipHdr.SetSource(m_addresses[1]);
133  ipHdr.SetDestination(m_addresses[0]);
134  route = ipv6->GetRoutingProtocol()->RouteOutput(p, ipHdr, r0Dev, sockerr);
135  m_routingResults.push_back(sockerr);
136  m_routes.push_back(route);
137 
138  ipv6 = r1Dev->GetNode()->GetObject<Ipv6L3Protocol>();
139  ipHdr.SetSource(m_addresses[2]);
140  ipHdr.SetDestination(m_addresses[3]);
141  route = ipv6->GetRoutingProtocol()->RouteOutput(p, ipHdr, r1Dev, sockerr);
142  m_routingResults.push_back(sockerr);
143  m_routes.push_back(route);
144 
145  ipv6 = n1Dev->GetNode()->GetObject<Ipv6L3Protocol>();
146  ipHdr.SetSource(m_addresses[3]);
147  ipHdr.SetDestination(m_addresses[2]);
148  route = ipv6->GetRoutingProtocol()->RouteOutput(p, ipHdr, n1Dev, sockerr);
149  m_routingResults.push_back(sockerr);
150  m_routes.push_back(route);
151 }
152 
153 void
155 {
156  // Create nodes
157  Ptr<Node> n0 = CreateObject<Node>();
158  Ptr<Node> r = CreateObject<Node>();
159  Ptr<Node> n1 = CreateObject<Node>();
160 
161  NodeContainer net1(n0, r);
162  NodeContainer net2(r, n1);
163  NodeContainer all(n0, r, n1);
164 
165  // Create IPv6 Internet Stack
166  InternetStackHelper internetv6;
167  internetv6.Install(all);
168 
169  // Create channels
170  SimpleNetDeviceHelper simpleNetDevice;
171  simpleNetDevice.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2)));
172  simpleNetDevice.SetDeviceAttribute("DataRate", DataRateValue(DataRate("5Mbps")));
173 
174  NetDeviceContainer d1 = simpleNetDevice.Install(net1); /* n0 - R */
175  NetDeviceContainer d2 = simpleNetDevice.Install(net2); /* R - n1 */
176 
177  // Create networks and assign IPv6 Addresses
178  Ipv6AddressHelper ipv6;
179 
180  /* first subnet */
181  ipv6.SetBase(Ipv6Address("2001:1::"), Ipv6Prefix(64));
182  NetDeviceContainer tmp;
183  tmp.Add(d1.Get(0)); /* n0 */
184  Ipv6InterfaceContainer iic1 = ipv6.AssignWithoutAddress(tmp); /* n0 interface */
185 
186  NetDeviceContainer tmp2;
187  tmp2.Add(d1.Get(1)); /* R */
189  tmp2); /* R interface to the first subnet is just statically assigned */
190  iicr1.SetForwarding(0, true);
191  iic1.Add(iicr1);
192 
193  /* second subnet R - n1 */
194  ipv6.SetBase(Ipv6Address("2001:2::"), Ipv6Prefix(64));
195  NetDeviceContainer tmp3;
196  tmp3.Add(d2.Get(0)); /* R */
197  Ipv6InterfaceContainer iicr2 = ipv6.Assign(tmp3); /* R interface */
198  iicr2.SetForwarding(0, true);
199 
200  NetDeviceContainer tmp4;
201  tmp4.Add(d2.Get(1)); /* n1 */
203  iic2.Add(iicr2);
204 
205  /* radvd configuration */
206  RadvdHelper radvdHelper;
207 
208  /* R interface (n0 - R) */
209  /* n0 will receive unsolicited (periodic) RA */
210  radvdHelper.AddAnnouncedPrefix(iic1.GetInterfaceIndex(1), Ipv6Address("2001:1::0"), 64);
211  Ptr<RadvdPrefix> prefix =
212  *(radvdHelper.GetRadvdInterface(iic1.GetInterfaceIndex(1))->GetPrefixes().begin());
213  prefix->SetOnLinkFlag(false);
214 
215  /* R interface (R - n1) */
216  /* n1 will have to use RS, as RA are not sent automatically */
217  radvdHelper.AddAnnouncedPrefix(iic2.GetInterfaceIndex(1), Ipv6Address("2001:2::0"), 64);
218  radvdHelper.GetRadvdInterface(iic2.GetInterfaceIndex(1))->SetSendAdvert(false);
219 
220  ApplicationContainer radvdApps = radvdHelper.Install(r);
221  radvdApps.Start(Seconds(1.0));
222  radvdApps.Stop(Seconds(10.0));
223 
224  Simulator::Schedule(Seconds(2),
226  this,
227  d1.Get(0),
228  d1.Get(1),
229  d2.Get(0),
230  d2.Get(1));
231  Simulator::Schedule(Seconds(3),
233  this,
234  d1.Get(0),
235  d1.Get(1),
236  d2.Get(0),
237  d2.Get(1));
238 
239  Simulator::Stop(Seconds(10.0));
240 
241  Simulator::Run();
242 
243  // Address assignment checks
245  Ipv6Address("2001:1::200:ff:fe00:1"),
246  m_addresses[0] << " instead of "
247  << "2001:1::200:ff:fe00:1");
248 
250  Ipv6Address("2001:1::200:ff:fe00:2"),
251  m_addresses[1] << " instead of "
252  << "2001:1::200:ff:fe00:2");
253 
255  Ipv6Address("2001:2::200:ff:fe00:3"),
256  m_addresses[2] << " instead of "
257  << "2001:2::200:ff:fe00:3");
258 
260  Ipv6Address("2001:2::200:ff:fe00:4"),
261  m_addresses[3] << " instead of "
262  << "2001:2::200:ff:fe00:4");
263 
264  // Routes checks
266  Socket::ERROR_NOTERROR,
267  (int)m_routingResults[0] << " instead of Socket::ERROR_NOTERROR");
268 
269  NS_TEST_ASSERT_MSG_EQ(m_routes[0]->GetGateway(),
270  Ipv6Address("fe80::200:ff:fe00:2"),
271  m_routes[0]->GetGateway() << " instead of "
272  << "fe80::200:ff:fe00:2");
273 
275  Socket::ERROR_NOROUTETOHOST,
276  (int)m_routingResults[1] << " instead of Socket::ERROR_NOROUTETOHOST");
277 
279  Socket::ERROR_NOTERROR,
280  (int)m_routingResults[2] << " instead of Socket::ERROR_NOTERROR");
281 
282  NS_TEST_ASSERT_MSG_EQ(m_routes[2]->GetGateway(),
283  Ipv6Address("::"),
284  m_routes[2]->GetGateway() << " instead of "
285  << "::");
286 
288  Socket::ERROR_NOTERROR,
289  (int)m_routingResults[3] << " instead of Socket::ERROR_NOTERROR");
290 
291  NS_TEST_ASSERT_MSG_EQ(m_routes[3]->GetGateway(),
292  Ipv6Address("::"),
293  m_routes[3]->GetGateway() << " instead of "
294  << "::");
295 
296  Simulator::Destroy();
297 }
298 
305 class RadvdTestSuite : public TestSuite
306 {
307  public:
308  RadvdTestSuite();
309 };
310 
312  : TestSuite("radvd", UNIT)
313 {
314  AddTestCase(new RadvdTestCase, TestCase::QUICK);
315 }
316 
radvd basic tests
void CheckRouting(Ptr< NetDevice > n0Dev, Ptr< NetDevice > r0Dev, Ptr< NetDevice > r1Dev, Ptr< NetDevice > n1Dev)
Checks the routing between the selected NetDevices.
std::vector< Ipv6Address > m_addresses
Addresses on the nodes.
std::vector< Socket::SocketErrno > m_routingResults
Routing call return values.
void DoRun() override
Implementation to actually run this TestCase.
void CheckAddresses(Ptr< NetDevice > n0Dev, Ptr< NetDevice > r0Dev, Ptr< NetDevice > r1Dev, Ptr< NetDevice > n1Dev)
Checks the addresses on the selected NetDevices.
~RadvdTestCase() override
std::vector< Ptr< Ipv6Route > > m_routes
Routing call results.
radvd TestSuite
holds a vector of ns3::Application pointers.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
void Stop(Time stop) const
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
aggregate IP/TCP/UDP functionality to existing Nodes.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
Helper class to auto-assign global IPv6 unicast addresses.
Ipv6InterfaceContainer AssignWithoutAddress(const NetDeviceContainer &c)
Allocate an Ipv6InterfaceContainer but do not assign any IPv6 addresses.
void SetBase(Ipv6Address network, Ipv6Prefix prefix, Ipv6Address base=Ipv6Address("::1"))
Set the base network number, network prefix, and base interface ID.
Ipv6InterfaceContainer AssignWithoutOnLink(const NetDeviceContainer &c)
Allocate an Ipv6InterfaceContainer with auto-assigned addresses, but do not set the on-link property ...
Ipv6InterfaceContainer Assign(const NetDeviceContainer &c)
Allocate an Ipv6InterfaceContainer with auto-assigned addresses.
Describes an IPv6 address.
Definition: ipv6-address.h:49
Packet header for IPv6.
Definition: ipv6-header.h:35
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:118
void SetSource(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:106
Keep track of a set of IPv6 interfaces.
void SetForwarding(uint32_t i, bool state)
Set the state of the stack (act as a router or as an host) for the specified index.
uint32_t GetInterfaceIndex(uint32_t i) const
Get the interface index for the specified node index.
void Add(Ptr< Ipv6 > ipv6, uint32_t interface)
Add a couple IPv6/interface.
IPv6 layer implementation.
Describes an IPv6 prefix.
Definition: ipv6-address.h:455
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Radvd application helper.
Definition: radvd-helper.h:41
void AddAnnouncedPrefix(uint32_t interface, Ipv6Address prefix, uint32_t prefixLength)
Add a new prefix to be announced through an interface.
Definition: radvd-helper.cc:39
ApplicationContainer Install(Ptr< Node > node)
Install the application in a Node.
Ptr< RadvdInterface > GetRadvdInterface(uint32_t interface)
Get the low-level RadvdInterface specification for an interface.
Definition: radvd-helper.cc:97
RadvdPrefixList GetPrefixes() const
Get list of prefixes advertised for this interface.
void SetOnLinkFlag(bool onLinkFlag)
Set on-link flag.
build a set of SimpleNetDevice objects
void SetChannelAttribute(std::string n1, const AttributeValue &v1)
void SetDeviceAttribute(std::string n1, const AttributeValue &v1)
NetDeviceContainer Install(Ptr< Node > node) const
This method creates an ns3::SimpleChannel with the attributes configured by SimpleNetDeviceHelper::Se...
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
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
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:327
#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
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
static RadvdTestSuite radvdTestSuite
Static variable for test initialization.
Every class exported by the ns3 library is enclosed in the ns3 namespace.