A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
radvd.cc
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 "ns3/log.h"
24 #include "ns3/ipv6-address.h"
25 #include "ns3/nstime.h"
26 #include "ns3/simulator.h"
27 #include "ns3/packet.h"
28 #include "ns3/net-device.h"
29 #include "ns3/uinteger.h"
30 #include "ns3/inet6-socket-address.h"
31 #include "ns3/ipv6.h"
32 #include "ns3/ipv6-raw-socket-factory.h"
33 #include "ns3/ipv6-header.h"
34 #include "ns3/icmpv6-header.h"
35 #include "ns3/string.h"
36 #include "ns3/pointer.h"
37 
38 #include "radvd.h"
39 
40 namespace ns3
41 {
42 
43 NS_LOG_COMPONENT_DEFINE ("RadvdApplication");
44 
45 NS_OBJECT_ENSURE_REGISTERED (Radvd);
46 
48 {
49  static TypeId tid = TypeId ("ns3::Radvd")
51  .AddConstructor<Radvd> ()
52  .AddAttribute ("AdvertisementJitter",
53  "Uniform variable to provide jitter between min and max values of AdvInterval",
54  StringValue("ns3::UniformRandomVariable"),
55  MakePointerAccessor (&Radvd::m_jitter),
56  MakePointerChecker<UniformRandomVariable> ());
57  ;
58  return tid;
59 }
60 
62 {
63  NS_LOG_FUNCTION (this);
64 }
65 
67 {
68  NS_LOG_FUNCTION (this);
69  for (RadvdInterfaceListI it = m_configurations.begin (); it != m_configurations.end (); ++it)
70  {
71  *it = 0;
72  }
73  m_configurations.clear ();
74  m_socket = 0;
75 }
76 
78 {
79  NS_LOG_FUNCTION (this);
81 }
82 
84 {
85  NS_LOG_FUNCTION (this);
86 
87  if (!m_socket)
88  {
89  TypeId tid = TypeId::LookupByName ("ns3::Ipv6RawSocketFactory");
91 
93 
94  /* m_socket->Bind (Inet6SocketAddress (m_localAddress, 0)); */
95  /* m_socket->Connect (Inet6SocketAddress (Ipv6Address::GetAllNodesMulticast (), 0)); */
96  m_socket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6));
98  }
99 
100  for (RadvdInterfaceListCI it = m_configurations.begin (); it != m_configurations.end (); it++)
101  {
102  m_eventIds[(*it)->GetInterface ()] = EventId ();
103  ScheduleTransmit (Seconds (0.), (*it), m_eventIds[(*it)->GetInterface ()], Ipv6Address::GetAllNodesMulticast (), true);
104  }
105 }
106 
108 {
109  NS_LOG_FUNCTION (this);
110 
111  if (m_socket)
112  {
114  }
115 
116  for (EventIdMapI it = m_eventIds.begin (); it != m_eventIds.end (); ++it)
117  {
118  Simulator::Cancel ((*it).second);
119  }
120  m_eventIds.clear ();
121 }
122 
124 {
125  NS_LOG_FUNCTION (this << routerInterface);
126  m_configurations.push_back (routerInterface);
127 }
128 
129 int64_t
130 Radvd:: AssignStreams (int64_t stream)
131 {
132  NS_LOG_FUNCTION (this << stream);
133  m_jitter->SetStream (stream);
134  return 1;
135 }
136 
137 void Radvd::ScheduleTransmit (Time dt, Ptr<RadvdInterface> config, EventId& eventId, Ipv6Address dst, bool reschedule)
138 {
139  NS_LOG_FUNCTION (this << dt << config << &eventId << dst << reschedule);
140  eventId = Simulator::Schedule (dt, &Radvd::Send, this, config, dst, reschedule);
141 }
142 
143 void Radvd::Send (Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
144 {
145  NS_LOG_FUNCTION (this << dst << reschedule);
146  NS_ASSERT (m_eventIds[config->GetInterface ()].IsExpired ());
147  Icmpv6RA raHdr;
149  Icmpv6OptionMtu mtuHdr;
151 
152  if (m_eventIds.size () == 0)
153  {
154  return;
155  }
156 
157  std::list<Ptr<RadvdPrefix> > prefixes = config->GetPrefixes ();
158  Ptr<Packet> p = Create<Packet> ();
159  Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
160 
161  /* set RA header information */
162  raHdr.SetFlagM (config->IsManagedFlag ());
163  raHdr.SetFlagO (config->IsOtherConfigFlag ());
164  raHdr.SetFlagH (config->IsHomeAgentFlag ());
165  raHdr.SetCurHopLimit (config->GetCurHopLimit ());
166  raHdr.SetLifeTime (config->GetDefaultLifeTime ());
167  raHdr.SetReachableTime (config->GetReachableTime ());
168  raHdr.SetRetransmissionTime (config->GetRetransTimer ());
169 
170  if (config->IsSourceLLAddress ())
171  {
172  /* Get L2 address from NetDevice */
173  Address addr = ipv6->GetNetDevice (config->GetInterface ())->GetAddress ();
174  llaHdr = Icmpv6OptionLinkLayerAddress (true, addr);
175  p->AddHeader (llaHdr);
176  }
177 
178  if (config->GetLinkMtu ())
179  {
180  NS_ASSERT (config->GetLinkMtu () >= 1280);
181  mtuHdr = Icmpv6OptionMtu (config->GetLinkMtu ());
182  p->AddHeader (mtuHdr);
183  }
184 
185  /* add list of prefixes */
186  for (std::list<Ptr<RadvdPrefix> >::const_iterator jt = prefixes.begin (); jt != prefixes.end (); jt++)
187  {
188  uint8_t flags = 0;
189  prefixHdr = Icmpv6OptionPrefixInformation ();
190  prefixHdr.SetPrefix ((*jt)->GetNetwork ());
191  prefixHdr.SetPrefixLength ((*jt)->GetPrefixLength ());
192  prefixHdr.SetValidTime ((*jt)->GetValidLifeTime ());
193  prefixHdr.SetPreferredTime ((*jt)->GetPreferredLifeTime ());
194 
195  if ((*jt)->IsOnLinkFlag ())
196  {
197  flags += 1 << 7;
198  }
199 
200  if ((*jt)->IsAutonomousFlag ())
201  {
202  flags += 1 << 6;
203  }
204 
205  if ((*jt)->IsRouterAddrFlag ())
206  {
207  flags += 1 << 5;
208  }
209 
210  prefixHdr.SetFlags (flags);
211 
212  p->AddHeader (prefixHdr);
213  }
214 
215  Ipv6Address src = ipv6->GetAddress (config->GetInterface (), 0).GetAddress ();
216  m_socket->Bind (Inet6SocketAddress (src, 0));
217  m_socket->Connect (Inet6SocketAddress (dst, 0));
218 
219  /* as we know interface index that will be used to send RA and
220  * we always send RA with router's link-local address, we can
221  * calculate checksum here.
222  */
223  raHdr.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + raHdr.GetSerializedSize (), 58 /* ICMPv6 */);
224  p->AddHeader (raHdr);
225 
226  /* Router advertisements MUST always have a ttl of 255
227  * The ttl value should be set as a socket option, but this is not yet implemented
228  */
229  SocketIpTtlTag ttl;
230  ttl.SetTtl (255);
231  p->AddPacketTag (ttl);
232 
233  /* send RA */
234  NS_LOG_LOGIC ("Send RA");
235  m_socket->Send (p, 0);
236 
237  if (reschedule)
238  {
239  uint64_t delay = static_cast<uint64_t> (m_jitter->GetValue (config->GetMinRtrAdvInterval (), config->GetMaxRtrAdvInterval ()) + 0.5);
240  NS_LOG_INFO ("Reschedule in " << delay);
241  Time t = MilliSeconds (delay);
242  ScheduleTransmit (t, config, m_eventIds[config->GetInterface ()], Ipv6Address::GetAllNodesMulticast (), reschedule);
243  }
244 }
245 
247 {
248  NS_LOG_FUNCTION (this << socket);
249  Ptr<Packet> packet = 0;
250  Address from;
251 
252  while ((packet = socket->RecvFrom (from)))
253  {
255  {
256  Ipv6Header hdr;
257  Icmpv6RS rsHdr;
259  uint64_t delay = 0;
260  Time t;
261 
262  packet->RemoveHeader (hdr);
263  uint8_t type;
264  packet->CopyData (&type, sizeof(type));
265 
266  switch (type)
267  {
268  case Icmpv6Header::ICMPV6_ND_ROUTER_SOLICITATION:
269  packet->RemoveHeader (rsHdr);
270  NS_LOG_INFO ("Received ICMPv6 Router Solicitation from " << hdr.GetSourceAddress () << " code = " << (uint32_t)rsHdr.GetCode ());
271 
272  /* XXX advertise just prefix(es) for the interface not all */
273  for (RadvdInterfaceListCI it = m_configurations.begin (); it != m_configurations.end (); it++)
274  {
275  /* calculate minimum delay between RA */
276  delay = static_cast<uint64_t> (m_jitter->GetValue (0, MAX_RA_DELAY_TIME) + 0.5);
277  t = Simulator::Now () + MilliSeconds (delay); /* absolute time of solicited RA */
278 
279  /* if our solicited RA is before the next periodic RA, we schedule it */
280  if (t.GetTimeStep () < static_cast<int64_t> (m_eventIds[(*it)->GetInterface ()].GetTs ()))
281  {
282  NS_LOG_INFO ("schedule new RA");
283  EventId ei;
284 
285  ScheduleTransmit (MilliSeconds (delay), (*it), ei, address.GetIpv6 (), false);
286  }
287  }
288  break;
289  default:
290  break;
291  }
292  }
293  }
294 }
295 
296 } /* namespace ns3 */
297 
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
std::list< Ptr< RadvdPrefix > > GetPrefixes() const
Get list of prefixes advertised for this interface.
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
keep track of time unit.
Definition: nstime.h:149
uint32_t GetMinRtrAdvInterval() const
Get minimum RA interval.
Packet header for IPv6.
Definition: ipv6-header.h:33
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
uint32_t GetLinkMtu() const
Get link MTU.
ICMPv6 Router Advertisement header.
virtual void StartApplication()
Start the application.
Definition: radvd.cc:83
RadvdInterfaceList m_configurations
List of configuration for interface.
Definition: radvd.h:144
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:79
hold variables of type string
Definition: string.h:19
uint32_t GetInterface() const
Get interface index for this configuration.
void ScheduleTransmit(Time dt, Ptr< RadvdInterface > config, EventId &eventId, Ipv6Address dst=Ipv6Address::GetAllNodesMulticast(), bool reschedule=false)
Schedule sending a packet.
Definition: radvd.cc:137
void AddPacketTag(const Tag &tag) const
Definition: packet.cc:868
ICMPv6 Router Solicitation header.
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetRetransTimer() const
Get retransmission timer.
uint32_t GetSize(void) const
Definition: packet.h:620
#define NS_LOG_INFO(msg)
Definition: log.h:264
static void Cancel(const EventId &id)
Definition: simulator.cc:267
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
uint8_t GetCurHopLimit() const
Get current hop limit.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:869
a polymophic address class
Definition: address.h:86
bool IsManagedFlag() const
Is managed flag enabled ?
void SetValidTime(uint32_t validTime)
Set the valid time of the information.
int64_t AssignStreams(int64_t stream)
Definition: radvd.cc:130
virtual ~Radvd()
Destructor.
Definition: radvd.cc:66
void SetPreferredTime(uint32_t preferredTime)
Set the preferred time of the information.
EventIdMap m_eventIds
Event ID map.
Definition: radvd.h:149
The base class for all ns3 applications.
Definition: application.h:61
bool IsOtherConfigFlag() const
Is "other config" flag enabled ?
Hold an unsigned integer type.
Definition: uinteger.h:46
void SetPrefixLength(uint8_t prefixLength)
Set the prefix length.
ICMPv6 Option Prefix Information.
Ptr< Node > GetNode() const
Definition: application.cc:103
An Inet6 address class.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:127
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
Definition: socket.cc:70
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual void DoDispose()
Dispose the instance.
Definition: radvd.cc:77
Ptr< Socket > m_socket
Raw socket to send RA.
Definition: radvd.h:139
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
void HandleRead(Ptr< Socket > socket)
Handle received packet, especially router solicitation.
Definition: radvd.cc:246
virtual void DoDispose(void)
Definition: application.cc:82
static const uint32_t MAX_RA_DELAY_TIME
Default value for maximum delay of RA (ms)
Definition: radvd.h:69
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
ICMPv6 MTU option.
uint8_t GetCode() const
Get the code field.
Callback< R > MakeNullCallback(void)
Definition: callback.h:781
double GetValue(double min, double max)
Returns a random double from the uniform distribution with the specified range.
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
int64_t GetTimeStep(void) const
Definition: nstime.h:311
static Time Now(void)
Definition: simulator.cc:179
void Send(Ptr< RadvdInterface > config, Ipv6Address dst=Ipv6Address::GetAllNodesMulticast(), bool reschedule=false)
Send a packet.
Definition: radvd.cc:143
virtual void StopApplication()
Stop the application.
Definition: radvd.cc:107
void SetFlags(uint8_t flags)
Set the flags.
Describes an IPv6 address.
Definition: ipv6-address.h:44
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
Radvd()
Constructor.
Definition: radvd.cc:61
void AddConfiguration(Ptr< RadvdInterface > routerInterface)
Add configuration for an interface;.
Definition: radvd.cc:123
an identifier for simulation events.
Definition: event-id.h:46
Ptr< UniformRandomVariable > m_jitter
Variable to provide jitter in advertisement interval.
Definition: radvd.h:154
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
static bool IsMatchingType(const Address &addr)
If the address match.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Definition: packet.cc:398
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.
Definition: nstime.h:601
uint32_t GetMaxRtrAdvInterval() const
Get maximum RA interval.
uint32_t GetDefaultLifeTime() const
Get default lifetime.
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.
bool IsSourceLLAddress() const
Is source LLA option should be included in RA ?
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
static TypeId GetTypeId(void)
Get the type ID.
Definition: radvd.cc:47
void SetAttribute(std::string name, const AttributeValue &value)
Definition: object-base.cc:160
Ptr< T > GetObject(void) const
Definition: object.h:332
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
void SetPrefix(Ipv6Address prefix)
Set the IPv6 prefix.
void AddHeader(const Header &header)
Definition: packet.cc:270
uint32_t GetReachableTime() const
Get reachable time.
bool IsHomeAgentFlag() const
Is "home agent" flag enabled ?
static TypeId LookupByName(std::string name)
Definition: type-id.cc:415