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
80 if (m_recvSocket)
81 {
83 m_recvSocket = nullptr;
84 }
85
86 for (auto it = m_sendSockets.begin(); it != m_sendSockets.end(); ++it)
87 {
88 if (it->second)
89 {
90 it->second->Close();
91 it->second = nullptr;
92 }
93 }
94
96}
97
98void
100{
101 NS_LOG_FUNCTION(this);
102
103 TypeId tid = TypeId::LookupByName("ns3::Ipv6RawSocketFactory");
104
105 if (!m_recvSocket)
106 {
108
110
116 }
117
118 for (auto it = m_configurations.begin(); it != m_configurations.end(); it++)
119 {
120 if ((*it)->IsSendAdvert())
121 {
122 m_unsolicitedEventIds[(*it)->GetInterface()] =
125 this,
126 (*it),
128 true);
129 }
130
131 if (m_sendSockets.find((*it)->GetInterface()) == m_sendSockets.end())
132 {
134 Ptr<Ipv6Interface> iFace = ipv6->GetInterface((*it)->GetInterface());
135
136 m_sendSockets[(*it)->GetInterface()] = Socket::CreateSocket(GetNode(), tid);
137 m_sendSockets[(*it)->GetInterface()]->Bind(
138 Inet6SocketAddress(iFace->GetLinkLocalAddress().GetAddress(), 0));
139 m_sendSockets[(*it)->GetInterface()]->SetAttribute(
140 "Protocol",
142 m_sendSockets[(*it)->GetInterface()]->ShutdownRecv();
143 }
144 }
145}
146
147void
149{
150 NS_LOG_FUNCTION(this);
151
152 if (m_recvSocket)
153 {
155 }
156
157 for (auto it = m_unsolicitedEventIds.begin(); it != m_unsolicitedEventIds.end(); ++it)
158 {
159 Simulator::Cancel((*it).second);
160 }
161 m_unsolicitedEventIds.clear();
162
163 for (auto it = m_solicitedEventIds.begin(); it != m_solicitedEventIds.end(); ++it)
164 {
165 Simulator::Cancel((*it).second);
166 }
167 m_solicitedEventIds.clear();
168}
169
170void
172{
173 NS_LOG_FUNCTION(this << routerInterface);
174 m_configurations.push_back(routerInterface);
175}
176
177int64_t
178Radvd::AssignStreams(int64_t stream)
179{
180 NS_LOG_FUNCTION(this << stream);
181 auto currentStream = stream;
182 m_jitter->SetStream(currentStream++);
183 currentStream += Application::AssignStreams(currentStream);
184 return (currentStream - stream);
185}
186
187void
188Radvd::Send(Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
189{
190 NS_LOG_FUNCTION(this << dst << reschedule);
191
192 if (reschedule)
193 {
194 config->SetLastRaTxTime(Simulator::Now());
195 }
196
197 Icmpv6RA raHdr;
199 Icmpv6OptionMtu mtuHdr;
201
202 std::list<Ptr<RadvdPrefix>> prefixes = config->GetPrefixes();
204 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
205
206 /* set RA header information */
207 raHdr.SetFlagM(config->IsManagedFlag());
208 raHdr.SetFlagO(config->IsOtherConfigFlag());
209 raHdr.SetFlagH(config->IsHomeAgentFlag());
210 raHdr.SetCurHopLimit(config->GetCurHopLimit());
211 raHdr.SetLifeTime(config->GetDefaultLifeTime());
212 raHdr.SetReachableTime(config->GetReachableTime());
213 raHdr.SetRetransmissionTime(config->GetRetransTimer());
214
215 if (config->IsSourceLLAddress())
216 {
217 /* Get L2 address from NetDevice */
218 Address addr = ipv6->GetNetDevice(config->GetInterface())->GetAddress();
219 llaHdr = Icmpv6OptionLinkLayerAddress(true, addr);
220 p->AddHeader(llaHdr);
221 }
222
223 if (config->GetLinkMtu())
224 {
225 NS_ASSERT(config->GetLinkMtu() >= 1280);
226 mtuHdr = Icmpv6OptionMtu(config->GetLinkMtu());
227 p->AddHeader(mtuHdr);
228 }
229
230 /* add list of prefixes */
231 for (auto jt = prefixes.begin(); jt != prefixes.end(); jt++)
232 {
233 uint8_t flags = 0;
234 prefixHdr = Icmpv6OptionPrefixInformation();
235 prefixHdr.SetPrefix((*jt)->GetNetwork());
236 prefixHdr.SetPrefixLength((*jt)->GetPrefixLength());
237 prefixHdr.SetValidTime((*jt)->GetValidLifeTime());
238 prefixHdr.SetPreferredTime((*jt)->GetPreferredLifeTime());
239
240 if ((*jt)->IsOnLinkFlag())
241 {
243 }
244
245 if ((*jt)->IsAutonomousFlag())
246 {
248 }
249
250 if ((*jt)->IsRouterAddrFlag())
251 {
253 }
254
255 prefixHdr.SetFlags(flags);
256
257 p->AddHeader(prefixHdr);
258 }
259
260 Address sockAddr;
261 m_sendSockets[config->GetInterface()]->GetSockName(sockAddr);
263
264 /* as we know interface index that will be used to send RA and
265 * we always send RA with router's link-local address, we can
266 * calculate checksum here.
267 */
269 dst,
270 p->GetSize() + raHdr.GetSerializedSize(),
271 58 /* ICMPv6 */);
272 p->AddHeader(raHdr);
273
274 /* Router advertisements MUST always have a ttl of 255
275 * The ttl value should be set as a socket option, but this is not yet implemented
276 */
277 SocketIpTtlTag ttl;
278 ttl.SetTtl(255);
279 p->AddPacketTag(ttl);
280
281 /* send RA */
282 NS_LOG_LOGIC("Send RA to " << dst);
283 m_sendSockets[config->GetInterface()]->SendTo(p, 0, Inet6SocketAddress(dst, 0));
284
285 if (reschedule)
286 {
287 auto delay = static_cast<uint64_t>(
288 m_jitter->GetValue(config->GetMinRtrAdvInterval(), config->GetMaxRtrAdvInterval()) +
289 0.5);
290 if (config->IsInitialRtrAdv())
291 {
293 {
295 }
296 }
297
298 NS_LOG_INFO("Reschedule in " << delay << " milliseconds");
299 Time t = MilliSeconds(delay);
300 m_unsolicitedEventIds[config->GetInterface()] =
303 this,
304 config,
306 true);
307 }
308}
309
310void
312{
313 NS_LOG_FUNCTION(this << socket);
314 Ptr<Packet> packet = nullptr;
315 Address from;
316
317 while ((packet = socket->RecvFrom(from)))
318 {
320 {
321 Ipv6PacketInfoTag interfaceInfo;
322 if (!packet->RemovePacketTag(interfaceInfo))
323 {
324 NS_ABORT_MSG("No incoming interface on RADVD message, aborting.");
325 }
326 uint32_t incomingIf = interfaceInfo.GetRecvIf();
327 Ptr<NetDevice> dev = GetNode()->GetDevice(incomingIf);
328 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
329 uint32_t ipInterfaceIndex = ipv6->GetInterfaceForDevice(dev);
330
331 Ipv6Header hdr;
332 Icmpv6RS rsHdr;
333 uint64_t delay = 0;
334 Time t;
335
336 packet->RemoveHeader(hdr);
337 uint8_t type;
338 packet->CopyData(&type, sizeof(type));
339
340 switch (type)
341 {
343 packet->RemoveHeader(rsHdr);
344 NS_LOG_INFO("Received ICMPv6 Router Solicitation from "
345 << hdr.GetSource() << " code = " << (uint32_t)rsHdr.GetCode());
346
347 for (auto it = m_configurations.begin(); it != m_configurations.end(); it++)
348 {
349 if (ipInterfaceIndex == (*it)->GetInterface())
350 {
351 /* calculate minimum delay between RA */
352 delay =
353 static_cast<uint64_t>(m_jitter->GetValue(0, MAX_RA_DELAY_TIME) + 0.5);
354 t = Simulator::Now() +
355 MilliSeconds(delay); /* absolute time of solicited RA */
356
357 if (Simulator::Now() <
358 (*it)->GetLastRaTxTime() + MilliSeconds(MIN_DELAY_BETWEEN_RAS))
359 {
361 }
362
363 /* if our solicited RA is before the next periodic RA, we schedule it */
364 bool scheduleSingle = true;
365
366 if (m_solicitedEventIds.find((*it)->GetInterface()) !=
368 {
369 if (m_solicitedEventIds[(*it)->GetInterface()].IsPending())
370 {
371 scheduleSingle = false;
372 }
373 }
374
375 if (m_unsolicitedEventIds.find((*it)->GetInterface()) !=
377 {
378 if (t.GetTimeStep() >
379 static_cast<int64_t>(
380 m_unsolicitedEventIds[(*it)->GetInterface()].GetTs()))
381 {
382 scheduleSingle = false;
383 }
384 }
385
386 if (scheduleSingle)
387 {
388 NS_LOG_INFO("schedule new RA");
389 m_solicitedEventIds[(*it)->GetInterface()] =
392 this,
393 (*it),
395 false);
396 }
397 }
398 }
399 break;
400 default:
401 break;
402 }
403 }
404 }
405}
406
407} /* 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:178
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:188
~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:311
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:148
void AddConfiguration(Ptr< RadvdInterface > routerInterface)
Add configuration for an interface;.
Definition radvd.cc:171
RadvdInterfaceList m_configurations
List of configuration for interface.
Definition radvd.h:136
void StartApplication() override
Application specific startup code.
Definition radvd.cc:99
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:561
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:49
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:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
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