A Discrete-Event Network Simulator
API
radvd.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 Telecom Bretagne
4  * Copyright (c) 2009 Strasbourg University
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
20  * Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
21  */
22 
23 #include "radvd.h"
24 #include "ns3/log.h"
25 #include "ns3/abort.h"
26 #include "ns3/ipv6-address.h"
27 #include "ns3/nstime.h"
28 #include "ns3/simulator.h"
29 #include "ns3/packet.h"
30 #include "ns3/net-device.h"
31 #include "ns3/uinteger.h"
32 #include "ns3/inet6-socket-address.h"
33 #include "ns3/ipv6.h"
34 #include "ns3/ipv6-l3-protocol.h"
35 #include "ns3/ipv6-interface.h"
36 #include "ns3/ipv6-raw-socket-factory.h"
37 #include "ns3/ipv6-packet-info-tag.h"
38 #include "ns3/ipv6-header.h"
39 #include "ns3/icmpv6-header.h"
40 #include "ns3/string.h"
41 #include "ns3/pointer.h"
42 #include "ns3/random-variable-stream.h"
43 #include "ns3/socket.h"
44 
45 
46 namespace ns3
47 {
48 
49 NS_LOG_COMPONENT_DEFINE ("RadvdApplication");
50 
52 
54 {
55  static TypeId tid = TypeId ("ns3::Radvd")
57  .SetGroupName("Internet-Apps")
58  .AddConstructor<Radvd> ()
59  .AddAttribute ("AdvertisementJitter",
60  "Uniform variable to provide jitter between min and max values of AdvInterval",
61  StringValue("ns3::UniformRandomVariable"),
63  MakePointerChecker<UniformRandomVariable> ());
64  ;
65  return tid;
66 }
67 
69 {
70  NS_LOG_FUNCTION (this);
71 }
72 
74 {
75  NS_LOG_FUNCTION (this);
76  for (RadvdInterfaceListI it = m_configurations.begin (); it != m_configurations.end (); ++it)
77  {
78  *it = 0;
79  }
80  m_configurations.clear ();
81  m_recvSocket = 0;
82 }
83 
85 {
86  NS_LOG_FUNCTION (this);
87 
88  m_recvSocket->Close ();
89  m_recvSocket = 0;
90 
91  for (SocketMapI it = m_sendSockets.begin (); it != m_sendSockets.end (); ++it)
92  {
93  it->second->Close ();
94  it->second = 0;
95  }
96 
98 }
99 
101 {
102  NS_LOG_FUNCTION (this);
103 
104  TypeId tid = TypeId::LookupByName ("ns3::Ipv6RawSocketFactory");
105 
106  if (!m_recvSocket)
107  {
109 
111 
117  }
118 
119  for (RadvdInterfaceListCI it = m_configurations.begin (); it != m_configurations.end (); it++)
120  {
121  if ((*it)->IsSendAdvert ())
122  {
123  m_unsolicitedEventIds[(*it)->GetInterface ()] = Simulator::Schedule (Seconds (0.), &Radvd::Send,
124  this, (*it), Ipv6Address::GetAllNodesMulticast (), true);
125  }
126 
127  if (m_sendSockets.find ((*it)->GetInterface ()) == m_sendSockets.end ())
128  {
130  Ptr<Ipv6Interface> iFace = ipv6->GetInterface ((*it)->GetInterface ());
131 
132  m_sendSockets[(*it)->GetInterface ()] = Socket::CreateSocket (GetNode (), tid);
133  m_sendSockets[(*it)->GetInterface ()]->Bind (Inet6SocketAddress (iFace->GetLinkLocalAddress ().GetAddress (), 0));
134  m_sendSockets[(*it)->GetInterface ()]->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6));
135  m_sendSockets[(*it)->GetInterface ()]->ShutdownRecv ();
136  }
137  }
138 }
139 
141 {
142  NS_LOG_FUNCTION (this);
143 
144  if (m_recvSocket)
145  {
147  }
148 
149  for (EventIdMapI it = m_unsolicitedEventIds.begin (); it != m_unsolicitedEventIds.end (); ++it)
150  {
151  Simulator::Cancel ((*it).second);
152  }
153  m_unsolicitedEventIds.clear ();
154 
155  for (EventIdMapI it = m_solicitedEventIds.begin (); it != m_solicitedEventIds.end (); ++it)
156  {
157  Simulator::Cancel ((*it).second);
158  }
159  m_solicitedEventIds.clear ();
160 }
161 
163 {
164  NS_LOG_FUNCTION (this << routerInterface);
165  m_configurations.push_back (routerInterface);
166 }
167 
168 int64_t
169 Radvd:: AssignStreams (int64_t stream)
170 {
171  NS_LOG_FUNCTION (this << stream);
172  m_jitter->SetStream (stream);
173  return 1;
174 }
175 
176 void Radvd::Send (Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
177 {
178  NS_LOG_FUNCTION (this << dst << reschedule);
179 
180  if (reschedule == true)
181  {
182  config->SetLastRaTxTime (Simulator::Now ());
183  }
184 
185  Icmpv6RA raHdr;
187  Icmpv6OptionMtu mtuHdr;
189 
190  std::list<Ptr<RadvdPrefix> > prefixes = config->GetPrefixes ();
191  Ptr<Packet> p = Create<Packet> ();
192  Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
193 
194  /* set RA header information */
195  raHdr.SetFlagM (config->IsManagedFlag ());
196  raHdr.SetFlagO (config->IsOtherConfigFlag ());
197  raHdr.SetFlagH (config->IsHomeAgentFlag ());
198  raHdr.SetCurHopLimit (config->GetCurHopLimit ());
199  raHdr.SetLifeTime (config->GetDefaultLifeTime ());
200  raHdr.SetReachableTime (config->GetReachableTime ());
201  raHdr.SetRetransmissionTime (config->GetRetransTimer ());
202 
203  if (config->IsSourceLLAddress ())
204  {
205  /* Get L2 address from NetDevice */
206  Address addr = ipv6->GetNetDevice (config->GetInterface ())->GetAddress ();
207  llaHdr = Icmpv6OptionLinkLayerAddress (true, addr);
208  p->AddHeader (llaHdr);
209  }
210 
211  if (config->GetLinkMtu ())
212  {
213  NS_ASSERT (config->GetLinkMtu () >= 1280);
214  mtuHdr = Icmpv6OptionMtu (config->GetLinkMtu ());
215  p->AddHeader (mtuHdr);
216  }
217 
218  /* add list of prefixes */
219  for (std::list<Ptr<RadvdPrefix> >::const_iterator jt = prefixes.begin (); jt != prefixes.end (); jt++)
220  {
221  uint8_t flags = 0;
222  prefixHdr = Icmpv6OptionPrefixInformation ();
223  prefixHdr.SetPrefix ((*jt)->GetNetwork ());
224  prefixHdr.SetPrefixLength ((*jt)->GetPrefixLength ());
225  prefixHdr.SetValidTime ((*jt)->GetValidLifeTime ());
226  prefixHdr.SetPreferredTime ((*jt)->GetPreferredLifeTime ());
227 
228  if ((*jt)->IsOnLinkFlag ())
229  {
231  }
232 
233  if ((*jt)->IsAutonomousFlag ())
234  {
236  }
237 
238  if ((*jt)->IsRouterAddrFlag ())
239  {
241  }
242 
243  prefixHdr.SetFlags (flags);
244 
245  p->AddHeader (prefixHdr);
246  }
247 
248  Address sockAddr;
249  m_sendSockets[config->GetInterface ()]->GetSockName (sockAddr);
251 
252  /* as we know interface index that will be used to send RA and
253  * we always send RA with router's link-local address, we can
254  * calculate checksum here.
255  */
256  raHdr.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + raHdr.GetSerializedSize (), 58 /* ICMPv6 */);
257  p->AddHeader (raHdr);
258 
259  /* Router advertisements MUST always have a ttl of 255
260  * The ttl value should be set as a socket option, but this is not yet implemented
261  */
262  SocketIpTtlTag ttl;
263  ttl.SetTtl (255);
264  p->AddPacketTag (ttl);
265 
266  /* send RA */
267  NS_LOG_LOGIC ("Send RA to " << dst);
268  m_sendSockets[config->GetInterface ()]->SendTo (p, 0, Inet6SocketAddress (dst, 0));
269 
270  if (reschedule)
271  {
272  uint64_t delay = static_cast<uint64_t> (m_jitter->GetValue (config->GetMinRtrAdvInterval (), config->GetMaxRtrAdvInterval ()) + 0.5);
273  if (config->IsInitialRtrAdv ())
274  {
277  }
278 
279  NS_LOG_INFO ("Reschedule in " << delay << " milliseconds");
280  Time t = MilliSeconds (delay);
282  }
283 }
284 
286 {
287  NS_LOG_FUNCTION (this << socket);
288  Ptr<Packet> packet = 0;
289  Address from;
290 
291  while ((packet = socket->RecvFrom (from)))
292  {
294  {
295  Ipv6PacketInfoTag interfaceInfo;
296  if (!packet->RemovePacketTag (interfaceInfo))
297  {
298  NS_ABORT_MSG ("No incoming interface on RADVD message, aborting.");
299  }
300  uint32_t incomingIf = interfaceInfo.GetRecvIf ();
301  Ptr<NetDevice> dev = GetNode ()->GetDevice (incomingIf);
302  Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
303  uint32_t ipInterfaceIndex = ipv6->GetInterfaceForDevice (dev);
304 
305  Ipv6Header hdr;
306  Icmpv6RS rsHdr;
307  uint64_t delay = 0;
308  Time t;
309 
310  packet->RemoveHeader (hdr);
311  uint8_t type;
312  packet->CopyData (&type, sizeof(type));
313 
314  switch (type)
315  {
317  packet->RemoveHeader (rsHdr);
318  NS_LOG_INFO ("Received ICMPv6 Router Solicitation from " << hdr.GetSourceAddress () << " code = " << (uint32_t)rsHdr.GetCode ());
319 
320  for (RadvdInterfaceListCI it = m_configurations.begin (); it != m_configurations.end (); it++)
321  {
322  if (ipInterfaceIndex == (*it)->GetInterface ())
323  {
324  /* calculate minimum delay between RA */
325  delay = static_cast<uint64_t> (m_jitter->GetValue (0, MAX_RA_DELAY_TIME) + 0.5);
326  t = Simulator::Now () + MilliSeconds (delay); /* absolute time of solicited RA */
327 
328  if (Simulator::Now () < (*it)->GetLastRaTxTime () + MilliSeconds (MIN_DELAY_BETWEEN_RAS) )
329  {
331  }
332 
333  /* if our solicited RA is before the next periodic RA, we schedule it */
334  bool scheduleSingle = true;
335 
336  if (m_solicitedEventIds.find ((*it)->GetInterface ()) != m_solicitedEventIds.end ())
337  {
338  if (m_solicitedEventIds[(*it)->GetInterface ()].IsRunning ())
339  {
340  scheduleSingle = false;
341  }
342  }
343 
344  if (m_unsolicitedEventIds.find ((*it)->GetInterface ()) != m_unsolicitedEventIds.end ())
345  {
346  if (t.GetTimeStep () > static_cast<int64_t> (m_unsolicitedEventIds[(*it)->GetInterface ()].GetTs ()))
347  {
348  scheduleSingle = false;
349  }
350  }
351 
352  if (scheduleSingle)
353  {
354  NS_LOG_INFO ("schedule new RA");
355  m_solicitedEventIds[(*it)->GetInterface ()] = Simulator::Schedule (MilliSeconds (delay), &Radvd::Send,
356  this, (*it), Ipv6Address::GetAllNodesMulticast (), false);
357  }
358  }
359  }
360  break;
361  default:
362  break;
363  }
364  }
365  }
366 }
367 
368 } /* namespace ns3 */
369 
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
uint32_t GetInterface() const
Get interface index for this configuration.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Packet header for IPv6.
Definition: ipv6-header.h:34
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
ICMPv6 Router Advertisement header.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
virtual void StartApplication()
Start the application.
Definition: radvd.cc:100
RadvdInterfaceList m_configurations
List of configuration for interface.
Definition: radvd.h:164
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:81
Hold variables of type string.
Definition: string.h:41
Router advertisement daemon.
Definition: radvd.h:47
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:144
std::list< Ptr< RadvdInterface > >::const_iterator RadvdInterfaceListCI
Container Const Iterator: Ptr to RadvdInterface.
Definition: radvd.h:111
virtual int ShutdownSend(void)=0
IPv6 layer implementation.
ICMPv6 Router Solicitation header.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
uint32_t GetMinRtrAdvInterval() const
Get minimum RA interval.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
std::list< Ptr< RadvdInterface > >::iterator RadvdInterfaceListI
Container Iterator: Ptr to RadvdInterface.
Definition: radvd.h:109
void SetRetransmissionTime(uint32_t r)
Set the node Retransmission time (Neighbor Discovery).
std::map< uint32_t, Ptr< Socket > >::iterator SocketMapI
Container Iterator: interface number, Socket.
Definition: radvd.h:123
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event&#39;s associated function will not be invoked when it expires...
Definition: simulator.cc:268
SocketMap m_sendSockets
Raw socket to send RA.
Definition: radvd.h:159
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:1116
Callback< R, Ts... > MakeNullCallback(void)
Definition: callback.h:1682
uint32_t GetRetransTimer() const
Get retransmission timer.
uint32_t GetRecvIf(void) const
Get the tag&#39;s receiving interface.
bool IsManagedFlag() const
Is managed flag enabled ?
a polymophic address class
Definition: address.h:90
void SetLifeTime(uint16_t l)
Set the node Life time (Neighbor Discovery).
uint32_t GetDefaultLifeTime() const
Get default lifetime.
void SetValidTime(uint32_t validTime)
Set the valid time of the information.
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:358
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
Definition: radvd.cc:169
virtual ~Radvd()
Destructor.
Definition: radvd.cc:73
void SetCurHopLimit(uint8_t m)
Set the IPv6 maximum number of jumps.
void SetPreferredTime(uint32_t preferredTime)
Set the preferred time of the information.
bool IsInitialRtrAdv()
Checks if the interface is subject to the initial Rtr Advertisements rule.
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:227
The base class for all ns3 applications.
Definition: application.h:60
void SetTtl(uint8_t ttl)
Set the tag&#39;s TTL.
Definition: socket.cc:604
uint32_t GetLinkMtu() const
Get link MTU.
bool IsSourceLLAddress() const
Is source LLA option should be included in RA ?
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetPrefixLength(uint8_t prefixLength)
Set the prefix length.
ICMPv6 Option Prefix Information.
EventIdMap m_unsolicitedEventIds
Event ID map for unsolicited RAs.
Definition: radvd.h:169
An Inet6 address class.
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:71
static const uint32_t MIN_DELAY_BETWEEN_RAS
Default value for minimum delay between RA advertisements (ms)
Definition: radvd.h:81
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define list
Ptr< Node > GetNode() const
Definition: application.cc:104
RadvdPrefixList GetPrefixes() const
Get list of prefixes advertised for this interface.
virtual void DoDispose()
Dispose the instance.
Definition: radvd.cc:84
uint8_t GetCode() const
Get the code field.
void HandleRead(Ptr< Socket > socket)
Handle received packet, especially router solicitation.
Definition: radvd.cc:285
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:83
static const uint32_t MAX_RA_DELAY_TIME
Default value for maximum delay of RA (ms)
Definition: radvd.h:69
void SetLastRaTxTime(Time now)
Set the last RA send time.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool IsHomeAgentFlag() const
Is "home agent" flag enabled ?
ICMPv6 MTU option.
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
std::map< uint32_t, EventId >::iterator EventIdMapI
Container Iterator: interface number, EventId.
Definition: radvd.h:116
EventIdMap m_solicitedEventIds
Event ID map for solicited RAs.
Definition: radvd.h:174
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
void SetFlagO(bool o)
Set the O flag.
bool IsOtherConfigFlag() const
Is "other config" flag enabled ?
void SetFlagH(bool h)
Set the H flag.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
void Send(Ptr< RadvdInterface > config, Ipv6Address dst=Ipv6Address::GetAllNodesMulticast(), bool reschedule=false)
Send a packet.
Definition: radvd.cc:176
virtual void StopApplication()
Stop the application.
Definition: radvd.cc:140
void SetFlagM(bool m)
Set the M flag.
void SetFlags(uint8_t flags)
Set the flags.
void SetReachableTime(uint32_t r)
Set the node Reachable time (Neighbor Discovery).
Describes an IPv6 address.
Definition: ipv6-address.h:49
Radvd()
Constructor.
Definition: radvd.cc:68
void AddConfiguration(Ptr< RadvdInterface > routerInterface)
Add configuration for an interface;.
Definition: radvd.cc:162
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
Ptr< UniformRandomVariable > m_jitter
Variable to provide jitter in advertisement interval.
Definition: radvd.h:179
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
uint32_t GetReachableTime() const
Get reachable time.
uint8_t GetCurHopLimit() const
Get current hop limit.
static bool IsMatchingType(const Address &addr)
If the address match.
This class implements a tag that carries socket ancillary data to the socket interface.
Autonomous Address Configuration.
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.
uint32_t GetMaxRtrAdvInterval() const
Get maximum RA interval.
Ptr< Socket > m_recvSocket
Raw socket to receive RS.
Definition: radvd.h:154
static TypeId GetTypeId(void)
Get the type ID.
Definition: radvd.cc:53
virtual int Close(void)=0
Close a socket.
static const uint32_t MAX_INITIAL_RTR_ADVERT_INTERVAL
Default value for maximum initial RA advertisements interval (ms)
Definition: radvd.h:77
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
void SetPrefix(Ipv6Address prefix)
Set the IPv6 prefix.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:830
static Ipv6Address GetAllRoutersMulticast()
Get the "all routers multicast" address.
int64_t GetTimeStep(void) const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:416