A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 "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 
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 {
64 }
65 
67 {
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 {
81 }
82 
84 {
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)); */
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 {
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  m_configurations.push_back (routerInterface);
126 }
127 
128 int64_t
129 Radvd:: AssignStreams (int64_t stream)
130 {
131  NS_LOG_FUNCTION (this << stream);
132  m_jitter->SetStream (stream);
133  return 1;
134 }
135 
136 void Radvd::ScheduleTransmit (Time dt, Ptr<RadvdInterface> config, EventId& eventId, Ipv6Address dst, bool reschedule)
137 {
138  NS_LOG_FUNCTION (this << dt);
139  eventId = Simulator::Schedule (dt, &Radvd::Send, this, config, dst, reschedule);
140 }
141 
142 void Radvd::Send (Ptr<RadvdInterface> config, Ipv6Address dst, bool reschedule)
143 {
144  NS_LOG_FUNCTION (this << dst);
145  NS_ASSERT (m_eventIds[config->GetInterface ()].IsExpired ());
146  Icmpv6RA raHdr;
148  Icmpv6OptionMtu mtuHdr;
150 
151  if (m_eventIds.size () == 0)
152  {
153  return;
154  }
155 
156  std::list<Ptr<RadvdPrefix> > prefixes = config->GetPrefixes ();
157  Ptr<Packet> p = Create<Packet> ();
158  Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
159 
160  /* set RA header information */
161  raHdr.SetFlagM (config->IsManagedFlag ());
162  raHdr.SetFlagO (config->IsOtherConfigFlag ());
163  raHdr.SetFlagH (config->IsHomeAgentFlag ());
164  raHdr.SetCurHopLimit (config->GetCurHopLimit ());
165  raHdr.SetLifeTime (config->GetDefaultLifeTime ());
166  raHdr.SetReachableTime (config->GetReachableTime ());
167  raHdr.SetRetransmissionTime (config->GetRetransTimer ());
168 
169  if (config->IsSourceLLAddress ())
170  {
171  /* Get L2 address from NetDevice */
172  Address addr = ipv6->GetNetDevice (config->GetInterface ())->GetAddress ();
173  llaHdr = Icmpv6OptionLinkLayerAddress (true, addr);
174  p->AddHeader (llaHdr);
175  }
176 
177  if (config->GetLinkMtu ())
178  {
179  NS_ASSERT (config->GetLinkMtu () >= 1280);
180  mtuHdr = Icmpv6OptionMtu (config->GetLinkMtu ());
181  p->AddHeader (mtuHdr);
182  }
183 
184  /* add list of prefixes */
185  for (std::list<Ptr<RadvdPrefix> >::const_iterator jt = prefixes.begin (); jt != prefixes.end (); jt++)
186  {
187  uint8_t flags = 0;
188  prefixHdr = Icmpv6OptionPrefixInformation ();
189  prefixHdr.SetPrefix ((*jt)->GetNetwork ());
190  prefixHdr.SetPrefixLength ((*jt)->GetPrefixLength ());
191  prefixHdr.SetValidTime ((*jt)->GetValidLifeTime ());
192  prefixHdr.SetPreferredTime ((*jt)->GetPreferredLifeTime ());
193 
194  if ((*jt)->IsOnLinkFlag ())
195  {
196  flags += 1 << 7;
197  }
198 
199  if ((*jt)->IsAutonomousFlag ())
200  {
201  flags += 1 << 6;
202  }
203 
204  if ((*jt)->IsRouterAddrFlag ())
205  {
206  flags += 1 << 5;
207  }
208 
209  prefixHdr.SetFlags (flags);
210 
211  p->AddHeader (prefixHdr);
212  }
213 
214  Ipv6Address src = ipv6->GetAddress (config->GetInterface (), 0).GetAddress ();
215  m_socket->Bind (Inet6SocketAddress (src, 0));
216  m_socket->Connect (Inet6SocketAddress (dst, 0));
217 
218  /* as we know interface index that will be used to send RA and
219  * we always send RA with router's link-local address, we can
220  * calculate checksum here.
221  */
222  raHdr.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + raHdr.GetSerializedSize (), 58 /* ICMPv6 */);
223  p->AddHeader (raHdr);
224 
225  /* Router advertisements MUST always have a ttl of 255
226  * The ttl value should be set as a socket option, but this is not yet implemented
227  */
228  SocketIpTtlTag ttl;
229  ttl.SetTtl (255);
230  p->AddPacketTag (ttl);
231 
232  /* send RA */
233  NS_LOG_LOGIC ("Send RA");
234  m_socket->Send (p, 0);
235 
236  if (reschedule)
237  {
238  uint64_t delay = static_cast<uint64_t> (m_jitter->GetValue (config->GetMinRtrAdvInterval (), config->GetMaxRtrAdvInterval ()) + 0.5);
239  NS_LOG_INFO ("Reschedule in " << delay);
240  Time t = MilliSeconds (delay);
241  ScheduleTransmit (t, config, m_eventIds[config->GetInterface ()], Ipv6Address::GetAllNodesMulticast (), reschedule);
242  }
243 }
244 
246 {
247  NS_LOG_FUNCTION (this << socket);
248  Ptr<Packet> packet = 0;
249  Address from;
250 
251  while ((packet = socket->RecvFrom (from)))
252  {
254  {
255  Ipv6Header hdr;
256  Icmpv6RS rsHdr;
258  uint64_t delay = 0;
259  Time t;
260 
261  packet->RemoveHeader (hdr);
262  uint8_t type;
263  packet->CopyData (&type, sizeof(type));
264 
265  switch (type)
266  {
268  packet->RemoveHeader (rsHdr);
269  NS_LOG_INFO ("Received ICMPv6 Router Solicitation from " << hdr.GetSourceAddress () << " code = " << (uint32_t)rsHdr.GetCode ());
270 
271  /* XXX advertise just prefix(es) for the interface not all */
272  for (RadvdInterfaceListCI it = m_configurations.begin (); it != m_configurations.end (); it++)
273  {
274  /* calculate minimum delay between RA */
275  delay = static_cast<uint64_t> (m_jitter->GetValue (0, MAX_RA_DELAY_TIME) + 0.5);
276  t = Simulator::Now () + MilliSeconds (delay); /* absolute time of solicited RA */
277 
278  /* if our solicited RA is before the next periodic RA, we schedule it */
279  if (t.GetTimeStep () < static_cast<int64_t> (m_eventIds[(*it)->GetInterface ()].GetTs ()))
280  {
281  NS_LOG_INFO ("schedule new RA");
282  EventId ei;
283 
284  ScheduleTransmit (MilliSeconds (delay), (*it), ei, address.GetIpv6 (), false);
285  }
286  }
287  break;
288  default:
289  break;
290  }
291  }
292  }
293 }
294 
295 } /* namespace ns3 */
296