A Discrete-Event Network Simulator
API
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 
45 namespace ns3
46 {
47 
48 NS_LOG_COMPONENT_DEFINE("RadvdApplication");
49 
51 
52 TypeId
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 (RadvdInterfaceListI it = m_configurations.begin(); it != m_configurations.end(); ++it)
79  {
80  *it = nullptr;
81  }
82  m_configurations.clear();
83  m_recvSocket = nullptr;
84 }
85 
86 void
88 {
89  NS_LOG_FUNCTION(this);
90 
92  m_recvSocket = nullptr;
93 
94  for (SocketMapI it = m_sendSockets.begin(); it != m_sendSockets.end(); ++it)
95  {
96  it->second->Close();
97  it->second = nullptr;
98  }
99 
101 }
102 
103 void
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 (RadvdInterfaceListCI it = m_configurations.begin(); it != m_configurations.end(); it++)
124  {
125  if ((*it)->IsSendAdvert())
126  {
127  m_unsolicitedEventIds[(*it)->GetInterface()] =
129  &Radvd::Send,
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 
152 void
154 {
155  NS_LOG_FUNCTION(this);
156 
157  if (m_recvSocket)
158  {
160  }
161 
162  for (EventIdMapI it = m_unsolicitedEventIds.begin(); it != m_unsolicitedEventIds.end(); ++it)
163  {
164  Simulator::Cancel((*it).second);
165  }
166  m_unsolicitedEventIds.clear();
167 
168  for (EventIdMapI it = m_solicitedEventIds.begin(); it != m_solicitedEventIds.end(); ++it)
169  {
170  Simulator::Cancel((*it).second);
171  }
172  m_solicitedEventIds.clear();
173 }
174 
175 void
177 {
178  NS_LOG_FUNCTION(this << routerInterface);
179  m_configurations.push_back(routerInterface);
180 }
181 
182 int64_t
183 Radvd::AssignStreams(int64_t stream)
184 {
185  NS_LOG_FUNCTION(this << stream);
186  m_jitter->SetStream(stream);
187  return 1;
188 }
189 
190 void
191 Radvd::Send(Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
192 {
193  NS_LOG_FUNCTION(this << dst << reschedule);
194 
195  if (reschedule == true)
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 (std::list<Ptr<RadvdPrefix>>::const_iterator jt = prefixes.begin(); jt != prefixes.end();
235  jt++)
236  {
237  uint8_t flags = 0;
238  prefixHdr = Icmpv6OptionPrefixInformation();
239  prefixHdr.SetPrefix((*jt)->GetNetwork());
240  prefixHdr.SetPrefixLength((*jt)->GetPrefixLength());
241  prefixHdr.SetValidTime((*jt)->GetValidLifeTime());
242  prefixHdr.SetPreferredTime((*jt)->GetPreferredLifeTime());
243 
244  if ((*jt)->IsOnLinkFlag())
245  {
247  }
248 
249  if ((*jt)->IsAutonomousFlag())
250  {
252  }
253 
254  if ((*jt)->IsRouterAddrFlag())
255  {
257  }
258 
259  prefixHdr.SetFlags(flags);
260 
261  p->AddHeader(prefixHdr);
262  }
263 
264  Address sockAddr;
265  m_sendSockets[config->GetInterface()]->GetSockName(sockAddr);
267 
268  /* as we know interface index that will be used to send RA and
269  * we always send RA with router's link-local address, we can
270  * calculate checksum here.
271  */
273  dst,
274  p->GetSize() + raHdr.GetSerializedSize(),
275  58 /* ICMPv6 */);
276  p->AddHeader(raHdr);
277 
278  /* Router advertisements MUST always have a ttl of 255
279  * The ttl value should be set as a socket option, but this is not yet implemented
280  */
281  SocketIpTtlTag ttl;
282  ttl.SetTtl(255);
283  p->AddPacketTag(ttl);
284 
285  /* send RA */
286  NS_LOG_LOGIC("Send RA to " << dst);
287  m_sendSockets[config->GetInterface()]->SendTo(p, 0, Inet6SocketAddress(dst, 0));
288 
289  if (reschedule)
290  {
291  uint64_t delay = static_cast<uint64_t>(
293  0.5);
294  if (config->IsInitialRtrAdv())
295  {
297  {
299  }
300  }
301 
302  NS_LOG_INFO("Reschedule in " << delay << " milliseconds");
303  Time t = MilliSeconds(delay);
306  &Radvd::Send,
307  this,
308  config,
310  true);
311  }
312 }
313 
314 void
316 {
317  NS_LOG_FUNCTION(this << socket);
318  Ptr<Packet> packet = nullptr;
319  Address from;
320 
321  while ((packet = socket->RecvFrom(from)))
322  {
324  {
325  Ipv6PacketInfoTag interfaceInfo;
326  if (!packet->RemovePacketTag(interfaceInfo))
327  {
328  NS_ABORT_MSG("No incoming interface on RADVD message, aborting.");
329  }
330  uint32_t incomingIf = interfaceInfo.GetRecvIf();
331  Ptr<NetDevice> dev = GetNode()->GetDevice(incomingIf);
332  Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
333  uint32_t ipInterfaceIndex = ipv6->GetInterfaceForDevice(dev);
334 
335  Ipv6Header hdr;
336  Icmpv6RS rsHdr;
337  uint64_t delay = 0;
338  Time t;
339 
340  packet->RemoveHeader(hdr);
341  uint8_t type;
342  packet->CopyData(&type, sizeof(type));
343 
344  switch (type)
345  {
347  packet->RemoveHeader(rsHdr);
348  NS_LOG_INFO("Received ICMPv6 Router Solicitation from "
349  << hdr.GetSource() << " code = " << (uint32_t)rsHdr.GetCode());
350 
351  for (RadvdInterfaceListCI it = m_configurations.begin();
352  it != m_configurations.end();
353  it++)
354  {
355  if (ipInterfaceIndex == (*it)->GetInterface())
356  {
357  /* calculate minimum delay between RA */
358  delay =
359  static_cast<uint64_t>(m_jitter->GetValue(0, MAX_RA_DELAY_TIME) + 0.5);
360  t = Simulator::Now() +
361  MilliSeconds(delay); /* absolute time of solicited RA */
362 
363  if (Simulator::Now() <
364  (*it)->GetLastRaTxTime() + MilliSeconds(MIN_DELAY_BETWEEN_RAS))
365  {
367  }
368 
369  /* if our solicited RA is before the next periodic RA, we schedule it */
370  bool scheduleSingle = true;
371 
372  if (m_solicitedEventIds.find((*it)->GetInterface()) !=
373  m_solicitedEventIds.end())
374  {
375  if (m_solicitedEventIds[(*it)->GetInterface()].IsRunning())
376  {
377  scheduleSingle = false;
378  }
379  }
380 
381  if (m_unsolicitedEventIds.find((*it)->GetInterface()) !=
382  m_unsolicitedEventIds.end())
383  {
384  if (t.GetTimeStep() >
385  static_cast<int64_t>(
386  m_unsolicitedEventIds[(*it)->GetInterface()].GetTs()))
387  {
388  scheduleSingle = false;
389  }
390  }
391 
392  if (scheduleSingle)
393  {
394  NS_LOG_INFO("schedule new RA");
395  m_solicitedEventIds[(*it)->GetInterface()] =
397  &Radvd::Send,
398  this,
399  (*it),
401  false);
402  }
403  }
404  }
405  break;
406  default:
407  break;
408  }
409  }
410  }
411 }
412 
413 } /* namespace ns3 */
a polymophic address class
Definition: address.h:100
The base class for all ns3 applications.
Definition: application.h:61
void DoDispose() override
Destructor implementation.
Definition: application.cc:85
Ptr< Node > GetNode() const
Definition: application.cc:107
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:50
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:36
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:152
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Router advertisement daemon.
Definition: radvd.h:47
EventIdMap m_solicitedEventIds
Event ID map for solicited RAs.
Definition: radvd.h:175
Ptr< UniformRandomVariable > m_jitter
Variable to provide jitter in advertisement interval.
Definition: radvd.h:180
void DoDispose() override
Dispose the instance.
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:155
void HandleRead(Ptr< Socket > socket)
Handle received packet, especially router solicitation.
Definition: radvd.cc:315
std::map< uint32_t, Ptr< Socket > >::iterator SocketMapI
Container Iterator: interface number, Socket.
Definition: radvd.h:122
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
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: radvd.cc:183
EventIdMap m_unsolicitedEventIds
Event ID map for unsolicited RAs.
Definition: radvd.h:170
std::list< Ptr< RadvdInterface > >::iterator RadvdInterfaceListI
Container Iterator: Ptr to RadvdInterface.
Definition: radvd.h:108
static TypeId GetTypeId()
Get the type ID.
Definition: radvd.cc:53
SocketMap m_sendSockets
Raw socket to send RA.
Definition: radvd.h:160
void StopApplication() override
Stop the application.
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:165
void StartApplication() override
Start the application.
Definition: radvd.cc:104
std::map< uint32_t, EventId >::iterator EventIdMapI
Container Iterator: interface number, EventId.
Definition: radvd.h:115
std::list< Ptr< RadvdInterface > >::const_iterator RadvdInterfaceListCI
Container Const Iterator: Ptr to RadvdInterface.
Definition: radvd.h:110
Radvd()
Constructor.
Definition: radvd.cc:70
uint32_t GetDefaultLifeTime() const
Get default lifetime.
void SetLastRaTxTime(Time now)
Set the last RA send time.
uint32_t GetMaxRtrAdvInterval() const
Get maximum RA interval.
uint32_t GetInterface() const
Get interface index for this configuration.
uint32_t GetMinRtrAdvInterval() const
Get minimum RA interval.
RadvdPrefixList GetPrefixes() const
Get list of prefixes advertised for this interface.
uint32_t GetRetransTimer() const
Get retransmission timer.
bool IsHomeAgentFlag() const
Is "home agent" flag enabled ?
uint32_t GetReachableTime() const
Get reachable time.
bool IsInitialRtrAdv() const
Checks if the interface is subject to the initial Rtr Advertisements rule.
bool IsOtherConfigFlag() const
Is "other config" flag enabled ?
uint8_t GetCurHopLimit() const
Get current hop limit.
uint32_t GetLinkMtu() const
Get link MTU.
bool IsSourceLLAddress() const
Is source LLA option should be included in RA ?
bool IsManagedFlag() const
Is managed flag enabled ?
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:568
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:276
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:352
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:126
virtual int ShutdownSend()=0
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.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer.
Definition: socket.h:1122
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition: socket.cc:602
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:444
a unique identifier for an interface.
Definition: type-id.h:60
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:839
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: pointer.h:231
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:750
#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:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
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:707
#define list