A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv6-interface.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007-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  */
20 
21 #include "ns3/log.h"
22 #include "ns3/node.h"
23 #include "ns3/packet.h"
24 
25 #include "ipv6-interface.h"
26 #include "ns3/net-device.h"
27 #include "loopback-net-device.h"
28 #include "ipv6-l3-protocol.h"
29 #include "icmpv6-l4-protocol.h"
30 #include "ndisc-cache.h"
31 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE ("Ipv6Interface");
36 
37 NS_OBJECT_ENSURE_REGISTERED (Ipv6Interface);
38 
40 {
41  static TypeId tid = TypeId ("ns3::Ipv6Interface")
42  .SetParent<Object> ()
43  ;
44  return tid;
45 }
46 
48  : m_ifup (false),
49  m_forwarding (true),
50  m_metric (1),
51  m_node (0),
52  m_device (0),
53  m_ndCache (0),
54  m_curHopLimit (0),
55  m_baseReachableTime (0),
56  m_reachableTime (0),
57  m_retransTimer (0)
58 {
59  NS_LOG_FUNCTION (this);
60 }
61 
63 {
65 }
66 
68 {
70  m_node = 0;
71  m_device = 0;
72  m_ndCache = 0;
74 }
75 
77 {
79 
80  if (m_node == 0 || m_device == 0)
81  {
82  return;
83  }
84 
85  /* set up link-local address */
86  if (!DynamicCast<LoopbackNetDevice> (m_device)) /* no autoconf for ip6-localhost */
87  {
88  Address addr = GetDevice ()->GetAddress ();
89 
91  {
93  AddAddress (ifaddr);
94  }
95  else
96  {
97  NS_ASSERT_MSG (false, "IPv6 autoconf for this kind of address not implemented.");
98  }
99  }
100  else
101  {
102  return; /* no NDISC cache for ip6-localhost */
103  }
104 
105  Ptr<Icmpv6L4Protocol> icmpv6 = m_node->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
106  m_ndCache = icmpv6->CreateCache (m_device, this);
107 }
108 
110 {
111  NS_LOG_FUNCTION (this << node);
112  m_node = node;
113  DoSetup ();
114 }
115 
117 {
118  NS_LOG_FUNCTION (this << device);
119  m_device = device;
120  DoSetup ();
121 }
122 
124 {
126  return m_device;
127 }
128 
129 void Ipv6Interface::SetMetric (uint16_t metric)
130 {
131  NS_LOG_FUNCTION (this << metric);
132  m_metric = metric;
133 }
134 
135 uint16_t Ipv6Interface::GetMetric () const
136 {
138  return m_metric;
139 }
140 
141 bool Ipv6Interface::IsUp () const
142 {
144  return m_ifup;
145 }
146 
148 {
150  return !m_ifup;
151 }
152 
154 {
156 
157  if (m_ifup)
158  {
159  return;
160  }
161  m_ifup = true;
162 }
163 
165 {
167  m_ifup = false;
168  m_addresses.clear ();
169 }
170 
172 {
174  return m_forwarding;
175 }
176 
177 void Ipv6Interface::SetForwarding (bool forwarding)
178 {
179  NS_LOG_FUNCTION (this << forwarding);
180  m_forwarding = forwarding;
181 }
182 
184 {
186  Ipv6Address addr = iface.GetAddress ();
187 
188  /* DAD handling */
189  if (!addr.IsAny ())
190  {
191  for (Ipv6InterfaceAddressListCI it = m_addresses.begin (); it != m_addresses.end (); ++it)
192  {
193  if ((*it).GetAddress () == addr)
194  {
195  return false;
196  }
197  }
198 
199  m_addresses.push_back (iface);
200 
201  if (!addr.IsAny () || !addr.IsLocalhost ())
202  {
203  /* DAD handling */
204  Ptr<Icmpv6L4Protocol> icmpv6 = m_node->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
205 
206  if (icmpv6 && icmpv6->IsAlwaysDad ())
207  {
208  Simulator::Schedule (Seconds (0.), &Icmpv6L4Protocol::DoDAD, icmpv6, addr, this);
210  }
211  }
212  return true;
213  }
214 
215  /* bad address */
216  return false;
217 }
218 
220 {
221  /* IPv6 interface has always at least one IPv6 link-local address */
223 
224  for (Ipv6InterfaceAddressListCI it = m_addresses.begin (); it != m_addresses.end (); ++it)
225  {
226  if ((*it).GetAddress ().IsLinkLocal ())
227  {
228  return (*it);
229  }
230  }
231  NS_ASSERT_MSG (false, "No link-local address on interface " << this);
233  return addr; /* quiet compiler */
234 }
235 
237 {
238  NS_LOG_FUNCTION (this << index);
239  uint32_t i = 0;
240 
241  if (m_addresses.size () > index)
242  {
243  for (Ipv6InterfaceAddressListCI it = m_addresses.begin (); it != m_addresses.end (); ++it)
244  {
245  if (i == index)
246  {
247  return (*it);
248  }
249  i++;
250  }
251  }
252 
253  NS_ASSERT_MSG (false, "Address " << index << " not found");
255  return addr; /* quiet compiler */
256 }
257 
259 {
261  return m_addresses.size ();
262 }
263 
265 {
266  NS_LOG_FUNCTION (this << index);
267  uint32_t i = 0;
268 
269  if (m_addresses.size () < index)
270  {
271  NS_ASSERT_MSG (false, "Try to remove index that don't exist in Ipv6Interface::RemoveAddress");
272  }
273 
274  for (Ipv6InterfaceAddressListI it = m_addresses.begin (); it != m_addresses.end (); ++it)
275  {
276  if (i == index)
277  {
278  Ipv6InterfaceAddress iface = (*it);
279  m_addresses.erase (it);
280  return iface;
281  }
282 
283  i++;
284  }
285 
286  NS_ASSERT_MSG (false, "Address " << index << " not found");
288  return addr; /* quiet compiler */
289 }
290 
292 {
293  NS_LOG_FUNCTION (this << dst);
294 
295  for (Ipv6InterfaceAddressList::const_iterator it = m_addresses.begin (); it != m_addresses.end (); ++it)
296  {
297  Ipv6InterfaceAddress ifaddr = (*it);
298 
299  if (ifaddr.GetPrefix ().IsMatch (ifaddr.GetAddress (), dst))
300  {
301  return ifaddr;
302  }
303  }
304 
305  /* NS_ASSERT_MSG (false, "Not matching address."); */
307  return ret; /* quiet compiler */
308 }
309 
311 {
312  NS_LOG_FUNCTION (this << p << dest);
314 
315  if (!IsUp ())
316  {
317  return;
318  }
319 
320  /* check if destination is localhost (::1) */
321  if (DynamicCast<LoopbackNetDevice> (m_device))
322  {
323  /* XXX additional checks needed here (such as whether multicast
324  * goes to loopback)?
325  */
326  m_device->Send (p, m_device->GetBroadcast (), Ipv6L3Protocol::PROT_NUMBER);
327  return;
328  }
329 
330  /* check if destination is for one of our interface */
331  for (Ipv6InterfaceAddressListCI it = m_addresses.begin (); it != m_addresses.end (); ++it)
332  {
333  if (dest == (*it).GetAddress ())
334  {
335  ipv6->Receive (m_device, p, Ipv6L3Protocol::PROT_NUMBER,
336  m_device->GetBroadcast (),
337  m_device->GetBroadcast (),
338  NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here
339  );
340  return;
341  }
342  }
343 
344  /* other address */
345  if (m_device->NeedsArp ())
346  {
347  NS_LOG_LOGIC ("Needs ARP" << " " << dest);
348  Ptr<Icmpv6L4Protocol> icmpv6 = ipv6->GetIcmpv6 ();
349  Address hardwareDestination;
350  bool found = false;
351 
352  NS_ASSERT (icmpv6);
353 
354  if (dest.IsMulticast ())
355  {
356  NS_LOG_LOGIC ("IsMulticast");
357  NS_ASSERT_MSG (m_device->IsMulticast (), "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
358 
359  hardwareDestination = m_device->GetMulticast (dest);
360  found = true;
361  }
362  else
363  {
364  NS_LOG_LOGIC ("NDISC Lookup");
365  found = icmpv6->Lookup (p, dest, GetDevice (), m_ndCache, &hardwareDestination);
366  }
367 
368  if (found)
369  {
370  NS_LOG_LOGIC ("Address Resolved. Send.");
371  m_device->Send (p, hardwareDestination, Ipv6L3Protocol::PROT_NUMBER);
372  }
373  }
374  else
375  {
376  NS_LOG_LOGIC ("Doesn't need ARP");
377  m_device->Send (p, m_device->GetBroadcast (), Ipv6L3Protocol::PROT_NUMBER);
378  }
379 }
380 
381 void Ipv6Interface::SetCurHopLimit (uint8_t curHopLimit)
382 {
383  NS_LOG_FUNCTION (this << curHopLimit);
384  m_curHopLimit = curHopLimit;
385 }
386 
388 {
390  return m_curHopLimit;
391 }
392 
393 void Ipv6Interface::SetBaseReachableTime (uint16_t baseReachableTime)
394 {
395  NS_LOG_FUNCTION (this << baseReachableTime);
396  m_baseReachableTime = baseReachableTime;
397 }
398 
400 {
402  return m_baseReachableTime;
403 }
404 
405 void Ipv6Interface::SetReachableTime (uint16_t reachableTime)
406 {
407  NS_LOG_FUNCTION (this << reachableTime);
408  m_reachableTime = reachableTime;
409 }
410 
412 {
414  return m_reachableTime;
415 }
416 
417 void Ipv6Interface::SetRetransTimer (uint16_t retransTimer)
418 {
419  NS_LOG_FUNCTION (this << retransTimer);
420  m_retransTimer = retransTimer;
421 }
422 
424 {
426  return m_retransTimer;
427 }
428 
430 {
431  NS_LOG_FUNCTION (this << address << state);
432 
433  for (Ipv6InterfaceAddressListI it = m_addresses.begin (); it != m_addresses.end (); ++it)
434  {
435  if ((*it).GetAddress () == address)
436  {
437  (*it).SetState (state);
438  return;
439  }
440  }
441  /* not found, maybe address has expired */
442 }
443 
444 void Ipv6Interface::SetNsDadUid (Ipv6Address address, uint32_t uid)
445 {
446  NS_LOG_FUNCTION (this << address << uid);
447 
448  for (Ipv6InterfaceAddressListI it = m_addresses.begin (); it != m_addresses.end (); ++it)
449  {
450  if ((*it).GetAddress () == address)
451  {
452  (*it).SetNsDadUid (uid);
453  return;
454  }
455  }
456  /* not found, maybe address has expired */
457 }
458 
459 } /* namespace ns3 */
460 
bool IsMatch(Ipv6Address a, Ipv6Address b) const
If the Address match the type.
Ipv6InterfaceAddressList m_addresses
The addresses assigned to this interface.
bool IsAny() const
If the IPv6 address is the "Any" address.
static bool IsMatchingType(const Address &address)
bool m_ifup
The state of this interface.
bool AddAddress(Ipv6InterfaceAddress iface)
Add an IPv6 address.
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void SetState(Ipv6Address address, Ipv6InterfaceAddress::State_e state)
Update state of an interface address.
void SetUp()
Enable this interface.
uint16_t GetRetransTimer() const
Get the retransmission timer.
bool m_forwarding
Forwarding state.
IPv6 layer implementation.
#define NS_ASSERT(condition)
Definition: assert.h:64
Ipv6InterfaceAddress GetAddress(uint32_t index) const
Get an address from IPv6 interface.
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
IPv6 address associated with an interface.
Ptr< NetDevice > m_device
NetDevice associated with this interface.
void SetDevice(Ptr< NetDevice > device)
Set the NetDevice.
void SetReachableTime(uint16_t reachableTime)
Set the reachable time.
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
bool IsUp() const
Is the interface UP ?
bool IsDown() const
Is the interface DOWN ?
a polymophic address class
Definition: address.h:86
void SetBaseReachableTime(uint16_t baseReachableTime)
Set the base reachable time.
static void FunctionDadTimeout(Ptr< Icmpv6L4Protocol > icmpv6, Ipv6Interface *interface, Ipv6Address addr)
Function called when DAD timeout.
uint16_t m_baseReachableTime
Base value used for computing the random reachable time value (in millisecond).
uint16_t GetBaseReachableTime() const
Get the base reachable time.
Ipv6Address GetAddress() const
Get the IPv6 address.
uint32_t GetNAddresses(void) const
Get number of addresses on this IPv6 interface.
void SetMetric(uint16_t metric)
Set the metric.
Ptr< Node > m_node
Node associated with this interface.
virtual ~Ipv6Interface()
Destructor.
void SetRetransTimer(uint16_t retransTimer)
Set the retransmission timer.
uint16_t m_retransTimer
Retransmission timer (in millisecond). Time between retransmission of NS.
static TypeId GetTypeId()
Get the type ID.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
Ipv6Prefix GetPrefix() const
Get the IPv6 prefix.
void Send(Ptr< Packet > p, Ipv6Address dest)
Send a packet through this interface.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void SetNsDadUid(Ipv6Address address, uint32_t uid)
Update NS DAD packet UID of an interface address.
static Mac48Address ConvertFrom(const Address &address)
void SetNode(Ptr< Node > node)
Set node associated with interface.
void SetForwarding(bool forward)
Set forwarding enabled or not.
uint8_t m_curHopLimit
Current hop limit.
void SetCurHopLimit(uint8_t curHopLimit)
Set the current hop limit.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
void DoDAD(Ipv6Address target, Ptr< Ipv6Interface > interface)
Do the Duplication Address Detection (DAD). It consists in sending a NS with our IPv6 as target...
Ipv6InterfaceAddress GetLinkLocalAddress() const
Get link-local address from IPv6 interface.
uint8_t GetCurHopLimit() const
Get the current hop limit value.
Describes an IPv6 address.
Definition: ipv6-address.h:44
uint16_t GetMetric() const
Get the metric.
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
State_e
State of an address associated with an interface.
void DoSetup()
Initialize interface.
uint16_t m_reachableTime
Reachable time (in millisecond). The time a neighbor is considered reachable after receiving a reacha...
bool IsForwarding() const
If the interface allows forwarding packets.
Describes an IPv6 prefix. It is just a bitmask like Ipv4Mask.
Definition: ipv6-address.h:326
uint16_t GetReachableTime() const
Get the reachable time.
Ipv6InterfaceAddress RemoveAddress(uint32_t index)
Remove an address from interface.
a base class which provides memory management and object aggregation
Definition: object.h:63
virtual void DoDispose()
Dispose this object.
uint16_t m_metric
The metric.
bool IsLocalhost() const
If the IPv6 address is localhost (::1).
Ptr< T > GetObject(void) const
Definition: object.h:332
void SetDown()
Disable this interface.
a unique identifier for an interface.
Definition: type-id.h:44
Ipv6InterfaceAddress GetAddressMatchingDestination(Ipv6Address dst)
Get an address which is in the same network prefix as destination.
static Ipv6Address MakeAutoconfiguredLinkLocalAddress(Mac48Address mac)
Make the autoconfigured link-local IPv6 address with Mac48Address.
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
Ptr< NdiscCache > m_ndCache
Neighbor cache.
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Ipv6Interface()
Constructs an Ipv6Interface.