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 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
8 * Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
9 */
10
11#include "radvd.h"
12
13#include "ns3/abort.h"
14#include "ns3/icmpv6-header.h"
15#include "ns3/inet6-socket-address.h"
16#include "ns3/ipv6-address.h"
17#include "ns3/ipv6-header.h"
18#include "ns3/ipv6-interface.h"
19#include "ns3/ipv6-l3-protocol.h"
20#include "ns3/ipv6-packet-info-tag.h"
21#include "ns3/ipv6-raw-socket-factory.h"
22#include "ns3/ipv6.h"
23#include "ns3/log.h"
24#include "ns3/net-device.h"
25#include "ns3/nstime.h"
26#include "ns3/packet.h"
27#include "ns3/pointer.h"
28#include "ns3/random-variable-stream.h"
29#include "ns3/simulator.h"
30#include "ns3/socket.h"
31#include "ns3/string.h"
32#include "ns3/uinteger.h"
33
34namespace ns3
35{
36
37NS_LOG_COMPONENT_DEFINE("RadvdApplication");
38
40
41TypeId
43{
44 static TypeId tid =
45 TypeId("ns3::Radvd")
47 .SetGroupName("Internet-Apps")
48 .AddConstructor<Radvd>()
49 .AddAttribute(
50 "AdvertisementJitter",
51 "Uniform variable to provide jitter between min and max values of AdvInterval",
52 StringValue("ns3::UniformRandomVariable"),
55 ;
56 return tid;
57}
58
60{
61 NS_LOG_FUNCTION(this);
62}
63
65{
66 NS_LOG_FUNCTION(this);
67 for (auto it = m_configurations.begin(); it != m_configurations.end(); ++it)
68 {
69 *it = nullptr;
70 }
71 m_configurations.clear();
72 m_recvSocket = nullptr;
73}
74
75void
77{
78 NS_LOG_FUNCTION(this);
79
81 m_recvSocket = nullptr;
82
83 for (auto it = m_sendSockets.begin(); it != m_sendSockets.end(); ++it)
84 {
85 it->second->Close();
86 it->second = nullptr;
87 }
88
90}
91
92void
94{
95 NS_LOG_FUNCTION(this);
96
97 TypeId tid = TypeId::LookupByName("ns3::Ipv6RawSocketFactory");
98
99 if (!m_recvSocket)
100 {
102
104
110 }
111
112 for (auto it = m_configurations.begin(); it != m_configurations.end(); it++)
113 {
114 if ((*it)->IsSendAdvert())
115 {
116 m_unsolicitedEventIds[(*it)->GetInterface()] =
119 this,
120 (*it),
122 true);
123 }
124
125 if (m_sendSockets.find((*it)->GetInterface()) == m_sendSockets.end())
126 {
128 Ptr<Ipv6Interface> iFace = ipv6->GetInterface((*it)->GetInterface());
129
130 m_sendSockets[(*it)->GetInterface()] = Socket::CreateSocket(GetNode(), tid);
131 m_sendSockets[(*it)->GetInterface()]->Bind(
132 Inet6SocketAddress(iFace->GetLinkLocalAddress().GetAddress(), 0));
133 m_sendSockets[(*it)->GetInterface()]->SetAttribute(
134 "Protocol",
136 m_sendSockets[(*it)->GetInterface()]->ShutdownRecv();
137 }
138 }
139}
140
141void
143{
144 NS_LOG_FUNCTION(this);
145
146 if (m_recvSocket)
147 {
149 }
150
151 for (auto it = m_unsolicitedEventIds.begin(); it != m_unsolicitedEventIds.end(); ++it)
152 {
153 Simulator::Cancel((*it).second);
154 }
155 m_unsolicitedEventIds.clear();
156
157 for (auto it = m_solicitedEventIds.begin(); it != m_solicitedEventIds.end(); ++it)
158 {
159 Simulator::Cancel((*it).second);
160 }
161 m_solicitedEventIds.clear();
162}
163
164void
166{
167 NS_LOG_FUNCTION(this << routerInterface);
168 m_configurations.push_back(routerInterface);
169}
170
171int64_t
172Radvd::AssignStreams(int64_t stream)
173{
174 NS_LOG_FUNCTION(this << stream);
175 auto currentStream = stream;
176 m_jitter->SetStream(currentStream++);
177 currentStream += Application::AssignStreams(currentStream);
178 return (currentStream - stream);
179}
180
181void
182Radvd::Send(Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
183{
184 NS_LOG_FUNCTION(this << dst << reschedule);
185
186 if (reschedule)
187 {
188 config->SetLastRaTxTime(Simulator::Now());
189 }
190
191 Icmpv6RA raHdr;
193 Icmpv6OptionMtu mtuHdr;
195
196 std::list<Ptr<RadvdPrefix>> prefixes = config->GetPrefixes();
198 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
199
200 /* set RA header information */
201 raHdr.SetFlagM(config->IsManagedFlag());
202 raHdr.SetFlagO(config->IsOtherConfigFlag());
203 raHdr.SetFlagH(config->IsHomeAgentFlag());
204 raHdr.SetCurHopLimit(config->GetCurHopLimit());
205 raHdr.SetLifeTime(config->GetDefaultLifeTime());
206 raHdr.SetReachableTime(config->GetReachableTime());
207 raHdr.SetRetransmissionTime(config->GetRetransTimer());
208
209 if (config->IsSourceLLAddress())
210 {
211 /* Get L2 address from NetDevice */
212 Address addr = ipv6->GetNetDevice(config->GetInterface())->GetAddress();
213 llaHdr = Icmpv6OptionLinkLayerAddress(true, addr);
214 p->AddHeader(llaHdr);
215 }
216
217 if (config->GetLinkMtu())
218 {
219 NS_ASSERT(config->GetLinkMtu() >= 1280);
220 mtuHdr = Icmpv6OptionMtu(config->GetLinkMtu());
221 p->AddHeader(mtuHdr);
222 }
223
224 /* add list of prefixes */
225 for (auto jt = prefixes.begin(); jt != prefixes.end(); jt++)
226 {
227 uint8_t flags = 0;
228 prefixHdr = Icmpv6OptionPrefixInformation();
229 prefixHdr.SetPrefix((*jt)->GetNetwork());
230 prefixHdr.SetPrefixLength((*jt)->GetPrefixLength());
231 prefixHdr.SetValidTime((*jt)->GetValidLifeTime());
232 prefixHdr.SetPreferredTime((*jt)->GetPreferredLifeTime());
233
234 if ((*jt)->IsOnLinkFlag())
235 {
237 }
238
239 if ((*jt)->IsAutonomousFlag())
240 {
242 }
243
244 if ((*jt)->IsRouterAddrFlag())
245 {
247 }
248
249 prefixHdr.SetFlags(flags);
250
251 p->AddHeader(prefixHdr);
252 }
253
254 Address sockAddr;
255 m_sendSockets[config->GetInterface()]->GetSockName(sockAddr);
257
258 /* as we know interface index that will be used to send RA and
259 * we always send RA with router's link-local address, we can
260 * calculate checksum here.
261 */
263 dst,
264 p->GetSize() + raHdr.GetSerializedSize(),
265 58 /* ICMPv6 */);
266 p->AddHeader(raHdr);
267
268 /* Router advertisements MUST always have a ttl of 255
269 * The ttl value should be set as a socket option, but this is not yet implemented
270 */
271 SocketIpTtlTag ttl;
272 ttl.SetTtl(255);
273 p->AddPacketTag(ttl);
274
275 /* send RA */
276 NS_LOG_LOGIC("Send RA to " << dst);
277 m_sendSockets[config->GetInterface()]->SendTo(p, 0, Inet6SocketAddress(dst, 0));
278
279 if (reschedule)
280 {
281 auto delay = static_cast<uint64_t>(
282 m_jitter->GetValue(config->GetMinRtrAdvInterval(), config->GetMaxRtrAdvInterval()) +
283 0.5);
284 if (config->IsInitialRtrAdv())
285 {
287 {
289 }
290 }
291
292 NS_LOG_INFO("Reschedule in " << delay << " milliseconds");
293 Time t = MilliSeconds(delay);
294 m_unsolicitedEventIds[config->GetInterface()] =
297 this,
298 config,
300 true);
301 }
302}
303
304void
306{
307 NS_LOG_FUNCTION(this << socket);
308 Ptr<Packet> packet = nullptr;
309 Address from;
310
311 while ((packet = socket->RecvFrom(from)))
312 {
314 {
315 Ipv6PacketInfoTag interfaceInfo;
316 if (!packet->RemovePacketTag(interfaceInfo))
317 {
318 NS_ABORT_MSG("No incoming interface on RADVD message, aborting.");
319 }
320 uint32_t incomingIf = interfaceInfo.GetRecvIf();
321 Ptr<NetDevice> dev = GetNode()->GetDevice(incomingIf);
322 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
323 uint32_t ipInterfaceIndex = ipv6->GetInterfaceForDevice(dev);
324
325 Ipv6Header hdr;
326 Icmpv6RS rsHdr;
327 uint64_t delay = 0;
328 Time t;
329
330 packet->RemoveHeader(hdr);
331 uint8_t type;
332 packet->CopyData(&type, sizeof(type));
333
334 switch (type)
335 {
337 packet->RemoveHeader(rsHdr);
338 NS_LOG_INFO("Received ICMPv6 Router Solicitation from "
339 << hdr.GetSource() << " code = " << (uint32_t)rsHdr.GetCode());
340
341 for (auto it = m_configurations.begin(); it != m_configurations.end(); it++)
342 {
343 if (ipInterfaceIndex == (*it)->GetInterface())
344 {
345 /* calculate minimum delay between RA */
346 delay =
347 static_cast<uint64_t>(m_jitter->GetValue(0, MAX_RA_DELAY_TIME) + 0.5);
348 t = Simulator::Now() +
349 MilliSeconds(delay); /* absolute time of solicited RA */
350
351 if (Simulator::Now() <
352 (*it)->GetLastRaTxTime() + MilliSeconds(MIN_DELAY_BETWEEN_RAS))
353 {
355 }
356
357 /* if our solicited RA is before the next periodic RA, we schedule it */
358 bool scheduleSingle = true;
359
360 if (m_solicitedEventIds.find((*it)->GetInterface()) !=
362 {
363 if (m_solicitedEventIds[(*it)->GetInterface()].IsPending())
364 {
365 scheduleSingle = false;
366 }
367 }
368
369 if (m_unsolicitedEventIds.find((*it)->GetInterface()) !=
371 {
372 if (t.GetTimeStep() >
373 static_cast<int64_t>(
374 m_unsolicitedEventIds[(*it)->GetInterface()].GetTs()))
375 {
376 scheduleSingle = false;
377 }
378 }
379
380 if (scheduleSingle)
381 {
382 NS_LOG_INFO("schedule new RA");
383 m_solicitedEventIds[(*it)->GetInterface()] =
386 this,
387 (*it),
389 false);
390 }
391 }
392 }
393 break;
394 default:
395 break;
396 }
397 }
398 }
399}
400
401} /* namespace ns3 */
a polymophic address class
Definition address.h:90
The base class for all ns3 applications.
Definition application.h:51
void DoDispose() override
Destructor implementation.
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this Application object.
Ptr< Node > GetNode() const
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.
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:24
Ipv6Address GetSource() const
Get the "Source address" field.
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition ipv6.h:71
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:138
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
Smart pointer class similar to boost::intrusive_ptr.
Router advertisement daemon.
Definition radvd.h:36
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:172
EventIdMap m_solicitedEventIds
Event ID map for solicited RAs.
Definition radvd.h:146
Ptr< UniformRandomVariable > m_jitter
Variable to provide jitter in advertisement interval.
Definition radvd.h:151
void DoDispose() override
Destructor implementation.
Definition radvd.cc:76
void Send(Ptr< RadvdInterface > config, Ipv6Address dst=Ipv6Address::GetAllNodesMulticast(), bool reschedule=false)
Send a packet.
Definition radvd.cc:182
~Radvd() override
Destructor.
Definition radvd.cc:64
Ptr< Socket > m_recvSocket
Raw socket to receive RS.
Definition radvd.h:126
void HandleRead(Ptr< Socket > socket)
Handle received packet, especially router solicitation.
Definition radvd.cc:305
static const uint32_t MAX_RA_DELAY_TIME
Default value for maximum delay of RA (ms)
Definition radvd.h:57
static const uint32_t MAX_INITIAL_RTR_ADVERT_INTERVAL
Default value for maximum initial RA advertisements interval (ms)
Definition radvd.h:65
static const uint32_t MIN_DELAY_BETWEEN_RAS
Default value for minimum delay between RA advertisements (ms)
Definition radvd.h:69
EventIdMap m_unsolicitedEventIds
Event ID map for unsolicited RAs.
Definition radvd.h:141
static TypeId GetTypeId()
Get the type ID.
Definition radvd.cc:42
SocketMap m_sendSockets
Raw socket to send RA.
Definition radvd.h:131
void StopApplication() override
Application specific shutdown code.
Definition radvd.cc:142
void AddConfiguration(Ptr< RadvdInterface > routerInterface)
Add configuration for an interface;.
Definition radvd.cc:165
RadvdInterfaceList m_configurations
List of configuration for interface.
Definition radvd.h:136
void StartApplication() override
Application specific startup code.
Definition radvd.cc:93
Radvd()
Constructor.
Definition radvd.cc:59
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
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:274
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition socket.cc:343
virtual int ShutdownSend()=0
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition socket.cc:117
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:61
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:1113
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition socket.cc:593
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
int64_t GetTimeStep() const
Get the raw time value, in the current resolution unit.
Definition nstime.h:434
a unique identifier for an interface.
Definition type-id.h:48
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition type-id.cc:872
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:264
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1356
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:684