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