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 m_jitter->SetStream(stream);
176 return 1;
177}
178
179void
180Radvd::Send(Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
181{
182 NS_LOG_FUNCTION(this << dst << reschedule);
183
184 if (reschedule)
185 {
186 config->SetLastRaTxTime(Simulator::Now());
187 }
188
189 Icmpv6RA raHdr;
191 Icmpv6OptionMtu mtuHdr;
193
194 std::list<Ptr<RadvdPrefix>> prefixes = config->GetPrefixes();
196 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
197
198 /* set RA header information */
199 raHdr.SetFlagM(config->IsManagedFlag());
200 raHdr.SetFlagO(config->IsOtherConfigFlag());
201 raHdr.SetFlagH(config->IsHomeAgentFlag());
202 raHdr.SetCurHopLimit(config->GetCurHopLimit());
203 raHdr.SetLifeTime(config->GetDefaultLifeTime());
204 raHdr.SetReachableTime(config->GetReachableTime());
205 raHdr.SetRetransmissionTime(config->GetRetransTimer());
206
207 if (config->IsSourceLLAddress())
208 {
209 /* Get L2 address from NetDevice */
210 Address addr = ipv6->GetNetDevice(config->GetInterface())->GetAddress();
211 llaHdr = Icmpv6OptionLinkLayerAddress(true, addr);
212 p->AddHeader(llaHdr);
213 }
214
215 if (config->GetLinkMtu())
216 {
217 NS_ASSERT(config->GetLinkMtu() >= 1280);
218 mtuHdr = Icmpv6OptionMtu(config->GetLinkMtu());
219 p->AddHeader(mtuHdr);
220 }
221
222 /* add list of prefixes */
223 for (auto jt = prefixes.begin(); jt != prefixes.end(); jt++)
224 {
225 uint8_t flags = 0;
226 prefixHdr = Icmpv6OptionPrefixInformation();
227 prefixHdr.SetPrefix((*jt)->GetNetwork());
228 prefixHdr.SetPrefixLength((*jt)->GetPrefixLength());
229 prefixHdr.SetValidTime((*jt)->GetValidLifeTime());
230 prefixHdr.SetPreferredTime((*jt)->GetPreferredLifeTime());
231
232 if ((*jt)->IsOnLinkFlag())
233 {
235 }
236
237 if ((*jt)->IsAutonomousFlag())
238 {
240 }
241
242 if ((*jt)->IsRouterAddrFlag())
243 {
245 }
246
247 prefixHdr.SetFlags(flags);
248
249 p->AddHeader(prefixHdr);
250 }
251
252 Address sockAddr;
253 m_sendSockets[config->GetInterface()]->GetSockName(sockAddr);
255
256 /* as we know interface index that will be used to send RA and
257 * we always send RA with router's link-local address, we can
258 * calculate checksum here.
259 */
261 dst,
262 p->GetSize() + raHdr.GetSerializedSize(),
263 58 /* ICMPv6 */);
264 p->AddHeader(raHdr);
265
266 /* Router advertisements MUST always have a ttl of 255
267 * The ttl value should be set as a socket option, but this is not yet implemented
268 */
269 SocketIpTtlTag ttl;
270 ttl.SetTtl(255);
271 p->AddPacketTag(ttl);
272
273 /* send RA */
274 NS_LOG_LOGIC("Send RA to " << dst);
275 m_sendSockets[config->GetInterface()]->SendTo(p, 0, Inet6SocketAddress(dst, 0));
276
277 if (reschedule)
278 {
279 auto delay = static_cast<uint64_t>(
280 m_jitter->GetValue(config->GetMinRtrAdvInterval(), config->GetMaxRtrAdvInterval()) +
281 0.5);
282 if (config->IsInitialRtrAdv())
283 {
285 {
287 }
288 }
289
290 NS_LOG_INFO("Reschedule in " << delay << " milliseconds");
291 Time t = MilliSeconds(delay);
292 m_unsolicitedEventIds[config->GetInterface()] =
295 this,
296 config,
298 true);
299 }
300}
301
302void
304{
305 NS_LOG_FUNCTION(this << socket);
306 Ptr<Packet> packet = nullptr;
307 Address from;
308
309 while ((packet = socket->RecvFrom(from)))
310 {
312 {
313 Ipv6PacketInfoTag interfaceInfo;
314 if (!packet->RemovePacketTag(interfaceInfo))
315 {
316 NS_ABORT_MSG("No incoming interface on RADVD message, aborting.");
317 }
318 uint32_t incomingIf = interfaceInfo.GetRecvIf();
319 Ptr<NetDevice> dev = GetNode()->GetDevice(incomingIf);
320 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
321 uint32_t ipInterfaceIndex = ipv6->GetInterfaceForDevice(dev);
322
323 Ipv6Header hdr;
324 Icmpv6RS rsHdr;
325 uint64_t delay = 0;
326 Time t;
327
328 packet->RemoveHeader(hdr);
329 uint8_t type;
330 packet->CopyData(&type, sizeof(type));
331
332 switch (type)
333 {
335 packet->RemoveHeader(rsHdr);
336 NS_LOG_INFO("Received ICMPv6 Router Solicitation from "
337 << hdr.GetSource() << " code = " << (uint32_t)rsHdr.GetCode());
338
339 for (auto it = m_configurations.begin(); it != m_configurations.end(); it++)
340 {
341 if (ipInterfaceIndex == (*it)->GetInterface())
342 {
343 /* calculate minimum delay between RA */
344 delay =
345 static_cast<uint64_t>(m_jitter->GetValue(0, MAX_RA_DELAY_TIME) + 0.5);
346 t = Simulator::Now() +
347 MilliSeconds(delay); /* absolute time of solicited RA */
348
349 if (Simulator::Now() <
350 (*it)->GetLastRaTxTime() + MilliSeconds(MIN_DELAY_BETWEEN_RAS))
351 {
353 }
354
355 /* if our solicited RA is before the next periodic RA, we schedule it */
356 bool scheduleSingle = true;
357
358 if (m_solicitedEventIds.find((*it)->GetInterface()) !=
360 {
361 if (m_solicitedEventIds[(*it)->GetInterface()].IsPending())
362 {
363 scheduleSingle = false;
364 }
365 }
366
367 if (m_unsolicitedEventIds.find((*it)->GetInterface()) !=
369 {
370 if (t.GetTimeStep() >
371 static_cast<int64_t>(
372 m_unsolicitedEventIds[(*it)->GetInterface()].GetTs()))
373 {
374 scheduleSingle = false;
375 }
376 }
377
378 if (scheduleSingle)
379 {
380 NS_LOG_INFO("schedule new RA");
381 m_solicitedEventIds[(*it)->GetInterface()] =
384 this,
385 (*it),
387 false);
388 }
389 }
390 }
391 break;
392 default:
393 break;
394 }
395 }
396 }
397}
398
399} /* 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.
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:180
~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:303
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:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
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