A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
radvd.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 Telecom Bretagne
3 * Copyright (c) 2009 Strasbourg University
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 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19 * Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
20 */
21
22#include "radvd.h"
23
24#include "ns3/abort.h"
25#include "ns3/icmpv6-header.h"
26#include "ns3/inet6-socket-address.h"
27#include "ns3/ipv6-address.h"
28#include "ns3/ipv6-header.h"
29#include "ns3/ipv6-interface.h"
30#include "ns3/ipv6-l3-protocol.h"
31#include "ns3/ipv6-packet-info-tag.h"
32#include "ns3/ipv6-raw-socket-factory.h"
33#include "ns3/ipv6.h"
34#include "ns3/log.h"
35#include "ns3/net-device.h"
36#include "ns3/nstime.h"
37#include "ns3/packet.h"
38#include "ns3/pointer.h"
39#include "ns3/random-variable-stream.h"
40#include "ns3/simulator.h"
41#include "ns3/socket.h"
42#include "ns3/string.h"
43#include "ns3/uinteger.h"
44
45namespace ns3
46{
47
48NS_LOG_COMPONENT_DEFINE("RadvdApplication");
49
51
52TypeId
54{
55 static TypeId tid =
56 TypeId("ns3::Radvd")
58 .SetGroupName("Internet-Apps")
59 .AddConstructor<Radvd>()
60 .AddAttribute(
61 "AdvertisementJitter",
62 "Uniform variable to provide jitter between min and max values of AdvInterval",
63 StringValue("ns3::UniformRandomVariable"),
65 MakePointerChecker<UniformRandomVariable>());
66 ;
67 return tid;
68}
69
71{
72 NS_LOG_FUNCTION(this);
73}
74
76{
77 NS_LOG_FUNCTION(this);
78 for (auto it = m_configurations.begin(); it != m_configurations.end(); ++it)
79 {
80 *it = nullptr;
81 }
82 m_configurations.clear();
83 m_recvSocket = nullptr;
84}
85
86void
88{
89 NS_LOG_FUNCTION(this);
90
92 m_recvSocket = nullptr;
93
94 for (auto it = m_sendSockets.begin(); it != m_sendSockets.end(); ++it)
95 {
96 it->second->Close();
97 it->second = nullptr;
98 }
99
101}
102
103void
105{
106 NS_LOG_FUNCTION(this);
107
108 TypeId tid = TypeId::LookupByName("ns3::Ipv6RawSocketFactory");
109
110 if (!m_recvSocket)
111 {
113
115
121 }
122
123 for (auto it = m_configurations.begin(); it != m_configurations.end(); it++)
124 {
125 if ((*it)->IsSendAdvert())
126 {
127 m_unsolicitedEventIds[(*it)->GetInterface()] =
130 this,
131 (*it),
133 true);
134 }
135
136 if (m_sendSockets.find((*it)->GetInterface()) == m_sendSockets.end())
137 {
139 Ptr<Ipv6Interface> iFace = ipv6->GetInterface((*it)->GetInterface());
140
141 m_sendSockets[(*it)->GetInterface()] = Socket::CreateSocket(GetNode(), tid);
142 m_sendSockets[(*it)->GetInterface()]->Bind(
143 Inet6SocketAddress(iFace->GetLinkLocalAddress().GetAddress(), 0));
144 m_sendSockets[(*it)->GetInterface()]->SetAttribute(
145 "Protocol",
147 m_sendSockets[(*it)->GetInterface()]->ShutdownRecv();
148 }
149 }
150}
151
152void
154{
155 NS_LOG_FUNCTION(this);
156
157 if (m_recvSocket)
158 {
160 }
161
162 for (auto it = m_unsolicitedEventIds.begin(); it != m_unsolicitedEventIds.end(); ++it)
163 {
164 Simulator::Cancel((*it).second);
165 }
166 m_unsolicitedEventIds.clear();
167
168 for (auto it = m_solicitedEventIds.begin(); it != m_solicitedEventIds.end(); ++it)
169 {
170 Simulator::Cancel((*it).second);
171 }
172 m_solicitedEventIds.clear();
173}
174
175void
177{
178 NS_LOG_FUNCTION(this << routerInterface);
179 m_configurations.push_back(routerInterface);
180}
181
182int64_t
183Radvd::AssignStreams(int64_t stream)
184{
185 NS_LOG_FUNCTION(this << stream);
186 m_jitter->SetStream(stream);
187 return 1;
188}
189
190void
191Radvd::Send(Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
192{
193 NS_LOG_FUNCTION(this << dst << reschedule);
194
195 if (reschedule)
196 {
197 config->SetLastRaTxTime(Simulator::Now());
198 }
199
200 Icmpv6RA raHdr;
202 Icmpv6OptionMtu mtuHdr;
204
205 std::list<Ptr<RadvdPrefix>> prefixes = config->GetPrefixes();
206 Ptr<Packet> p = Create<Packet>();
207 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
208
209 /* set RA header information */
210 raHdr.SetFlagM(config->IsManagedFlag());
211 raHdr.SetFlagO(config->IsOtherConfigFlag());
212 raHdr.SetFlagH(config->IsHomeAgentFlag());
213 raHdr.SetCurHopLimit(config->GetCurHopLimit());
214 raHdr.SetLifeTime(config->GetDefaultLifeTime());
215 raHdr.SetReachableTime(config->GetReachableTime());
216 raHdr.SetRetransmissionTime(config->GetRetransTimer());
217
218 if (config->IsSourceLLAddress())
219 {
220 /* Get L2 address from NetDevice */
221 Address addr = ipv6->GetNetDevice(config->GetInterface())->GetAddress();
222 llaHdr = Icmpv6OptionLinkLayerAddress(true, addr);
223 p->AddHeader(llaHdr);
224 }
225
226 if (config->GetLinkMtu())
227 {
228 NS_ASSERT(config->GetLinkMtu() >= 1280);
229 mtuHdr = Icmpv6OptionMtu(config->GetLinkMtu());
230 p->AddHeader(mtuHdr);
231 }
232
233 /* add list of prefixes */
234 for (auto jt = prefixes.begin(); jt != prefixes.end(); jt++)
235 {
236 uint8_t flags = 0;
237 prefixHdr = Icmpv6OptionPrefixInformation();
238 prefixHdr.SetPrefix((*jt)->GetNetwork());
239 prefixHdr.SetPrefixLength((*jt)->GetPrefixLength());
240 prefixHdr.SetValidTime((*jt)->GetValidLifeTime());
241 prefixHdr.SetPreferredTime((*jt)->GetPreferredLifeTime());
242
243 if ((*jt)->IsOnLinkFlag())
244 {
246 }
247
248 if ((*jt)->IsAutonomousFlag())
249 {
251 }
252
253 if ((*jt)->IsRouterAddrFlag())
254 {
256 }
257
258 prefixHdr.SetFlags(flags);
259
260 p->AddHeader(prefixHdr);
261 }
262
263 Address sockAddr;
264 m_sendSockets[config->GetInterface()]->GetSockName(sockAddr);
266
267 /* as we know interface index that will be used to send RA and
268 * we always send RA with router's link-local address, we can
269 * calculate checksum here.
270 */
272 dst,
273 p->GetSize() + raHdr.GetSerializedSize(),
274 58 /* ICMPv6 */);
275 p->AddHeader(raHdr);
276
277 /* Router advertisements MUST always have a ttl of 255
278 * The ttl value should be set as a socket option, but this is not yet implemented
279 */
280 SocketIpTtlTag ttl;
281 ttl.SetTtl(255);
282 p->AddPacketTag(ttl);
283
284 /* send RA */
285 NS_LOG_LOGIC("Send RA to " << dst);
286 m_sendSockets[config->GetInterface()]->SendTo(p, 0, Inet6SocketAddress(dst, 0));
287
288 if (reschedule)
289 {
290 auto delay = static_cast<uint64_t>(
291 m_jitter->GetValue(config->GetMinRtrAdvInterval(), config->GetMaxRtrAdvInterval()) +
292 0.5);
293 if (config->IsInitialRtrAdv())
294 {
296 {
298 }
299 }
300
301 NS_LOG_INFO("Reschedule in " << delay << " milliseconds");
302 Time t = MilliSeconds(delay);
303 m_unsolicitedEventIds[config->GetInterface()] =
306 this,
307 config,
309 true);
310 }
311}
312
313void
315{
316 NS_LOG_FUNCTION(this << socket);
317 Ptr<Packet> packet = nullptr;
318 Address from;
319
320 while ((packet = socket->RecvFrom(from)))
321 {
323 {
324 Ipv6PacketInfoTag interfaceInfo;
325 if (!packet->RemovePacketTag(interfaceInfo))
326 {
327 NS_ABORT_MSG("No incoming interface on RADVD message, aborting.");
328 }
329 uint32_t incomingIf = interfaceInfo.GetRecvIf();
330 Ptr<NetDevice> dev = GetNode()->GetDevice(incomingIf);
331 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
332 uint32_t ipInterfaceIndex = ipv6->GetInterfaceForDevice(dev);
333
334 Ipv6Header hdr;
335 Icmpv6RS rsHdr;
336 uint64_t delay = 0;
337 Time t;
338
339 packet->RemoveHeader(hdr);
340 uint8_t type;
341 packet->CopyData(&type, sizeof(type));
342
343 switch (type)
344 {
346 packet->RemoveHeader(rsHdr);
347 NS_LOG_INFO("Received ICMPv6 Router Solicitation from "
348 << hdr.GetSource() << " code = " << (uint32_t)rsHdr.GetCode());
349
350 for (auto it = m_configurations.begin(); it != m_configurations.end(); it++)
351 {
352 if (ipInterfaceIndex == (*it)->GetInterface())
353 {
354 /* calculate minimum delay between RA */
355 delay =
356 static_cast<uint64_t>(m_jitter->GetValue(0, MAX_RA_DELAY_TIME) + 0.5);
357 t = Simulator::Now() +
358 MilliSeconds(delay); /* absolute time of solicited RA */
359
360 if (Simulator::Now() <
361 (*it)->GetLastRaTxTime() + MilliSeconds(MIN_DELAY_BETWEEN_RAS))
362 {
364 }
365
366 /* if our solicited RA is before the next periodic RA, we schedule it */
367 bool scheduleSingle = true;
368
369 if (m_solicitedEventIds.find((*it)->GetInterface()) !=
371 {
372 if (m_solicitedEventIds[(*it)->GetInterface()].IsRunning())
373 {
374 scheduleSingle = false;
375 }
376 }
377
378 if (m_unsolicitedEventIds.find((*it)->GetInterface()) !=
380 {
381 if (t.GetTimeStep() >
382 static_cast<int64_t>(
383 m_unsolicitedEventIds[(*it)->GetInterface()].GetTs()))
384 {
385 scheduleSingle = false;
386 }
387 }
388
389 if (scheduleSingle)
390 {
391 NS_LOG_INFO("schedule new RA");
392 m_solicitedEventIds[(*it)->GetInterface()] =
395 this,
396 (*it),
398 false);
399 }
400 }
401 }
402 break;
403 default:
404 break;
405 }
406 }
407 }
408}
409
410} /* namespace ns3 */
a polymophic address class
Definition: address.h:101
The base class for all ns3 applications.
Definition: application.h:62
void DoDispose() override
Destructor implementation.
Definition: application.cc:86
Ptr< Node > GetNode() const
Definition: application.cc:108
uint8_t GetCode() const
Get the code field.
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
ICMPv6 MTU option.
ICMPv6 Option Prefix Information.
void SetValidTime(uint32_t validTime)
Set the valid time of the information.
void SetPrefix(Ipv6Address prefix)
Set the IPv6 prefix.
void SetFlags(uint8_t flags)
Set the flags.
void SetPrefixLength(uint8_t prefixLength)
Set the prefix length.
@ AUTADDRCONF
Autonomous Address Configuration.
void SetPreferredTime(uint32_t preferredTime)
Set the preferred time of the information.
ICMPv6 Router Advertisement header.
void SetLifeTime(uint16_t l)
Set the node Life time (Neighbor Discovery).
void SetFlagH(bool h)
Set the H flag.
void SetRetransmissionTime(uint32_t r)
Set the node Retransmission time (Neighbor Discovery).
void SetCurHopLimit(uint8_t m)
Set the IPv6 maximum number of jumps.
void SetFlagO(bool o)
Set the O flag.
void SetFlagM(bool m)
Set the M flag.
void SetReachableTime(uint32_t r)
Set the node Reachable time (Neighbor Discovery).
uint32_t GetSerializedSize() const override
Get the serialized size.
ICMPv6 Router Solicitation header.
An Inet6 address class.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
static bool IsMatchingType(const Address &addr)
If the address match.
Ipv6Address GetIpv6() const
Get the IPv6 address.
Describes an IPv6 address.
Definition: ipv6-address.h:49
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
static Ipv6Address GetAllRoutersMulticast()
Get the "all routers multicast" address.
Packet header for IPv6.
Definition: ipv6-header.h:35
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
IPv6 layer implementation.
This class implements a tag that carries socket ancillary data to the socket interface.
uint32_t GetRecvIf() const
Get the tag's receiving interface.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:149
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:211
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:522
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Router advertisement daemon.
Definition: radvd.h:47
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this Application object.
Definition: radvd.cc:183
EventIdMap m_solicitedEventIds
Event ID map for solicited RAs.
Definition: radvd.h:157
Ptr< UniformRandomVariable > m_jitter
Variable to provide jitter in advertisement interval.
Definition: radvd.h:162
void DoDispose() override
Destructor implementation.
Definition: radvd.cc:87
void Send(Ptr< RadvdInterface > config, Ipv6Address dst=Ipv6Address::GetAllNodesMulticast(), bool reschedule=false)
Send a packet.
Definition: radvd.cc:191
~Radvd() override
Destructor.
Definition: radvd.cc:75
Ptr< Socket > m_recvSocket
Raw socket to receive RS.
Definition: radvd.h:137
void HandleRead(Ptr< Socket > socket)
Handle received packet, especially router solicitation.
Definition: radvd.cc:314
static const uint32_t MAX_RA_DELAY_TIME
Default value for maximum delay of RA (ms)
Definition: radvd.h:68
static const uint32_t MAX_INITIAL_RTR_ADVERT_INTERVAL
Default value for maximum initial RA advertisements interval (ms)
Definition: radvd.h:76
static const uint32_t MIN_DELAY_BETWEEN_RAS
Default value for minimum delay between RA advertisements (ms)
Definition: radvd.h:80
EventIdMap m_unsolicitedEventIds
Event ID map for unsolicited RAs.
Definition: radvd.h:152
static TypeId GetTypeId()
Get the type ID.
Definition: radvd.cc:53
SocketMap m_sendSockets
Raw socket to send RA.
Definition: radvd.h:142
void StopApplication() override
Application specific shutdown code.
Definition: radvd.cc:153
void AddConfiguration(Ptr< RadvdInterface > routerInterface)
Add configuration for an interface;.
Definition: radvd.cc:176
RadvdInterfaceList m_configurations
List of configuration for interface.
Definition: radvd.h:147
void StartApplication() override
Application specific startup code.
Definition: radvd.cc:104
Radvd()
Constructor.
Definition: radvd.cc:70
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:285
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:354
virtual int ShutdownSend()=0
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:72
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer.
Definition: socket.h:1124
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition: socket.cc:604
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetTimeStep() const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:445
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:836
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:259
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:747
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
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
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