A Discrete-Event Network Simulator
API
ipv6-interface.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2009 Strasbourg University
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
18  */
19 
20 #include "ipv6-interface.h"
21 
22 #include "icmpv6-l4-protocol.h"
23 #include "ipv6-header.h"
24 #include "ipv6-l3-protocol.h"
25 #include "ipv6-queue-disc-item.h"
26 #include "loopback-net-device.h"
27 #include "ndisc-cache.h"
28 
29 #include "ns3/log.h"
30 #include "ns3/mac16-address.h"
31 #include "ns3/mac64-address.h"
32 #include "ns3/net-device.h"
33 #include "ns3/node.h"
34 #include "ns3/packet.h"
35 #include "ns3/traffic-control-layer.h"
36 
37 namespace ns3
38 {
39 
40 NS_LOG_COMPONENT_DEFINE("Ipv6Interface");
41 
42 NS_OBJECT_ENSURE_REGISTERED(Ipv6Interface);
43 
44 TypeId
46 {
47  static TypeId tid = TypeId("ns3::Ipv6Interface").SetParent<Object>().SetGroupName("Internet");
48  return tid;
49 }
50 
52  : m_ifup(false),
53  m_forwarding(true),
54  m_metric(1),
55  m_node(nullptr),
56  m_device(nullptr),
57  m_tc(nullptr),
58  m_ndCache(nullptr),
59  m_curHopLimit(0),
60  m_baseReachableTime(0),
61  m_reachableTime(0),
62  m_retransTimer(0)
63 {
64  NS_LOG_FUNCTION(this);
65 }
66 
68 {
69 }
70 
71 void
73 {
74  NS_LOG_FUNCTION(this);
75  m_node = nullptr;
76  m_device = nullptr;
77  m_tc = nullptr;
78  m_ndCache = nullptr;
80 }
81 
82 void
84 {
85  NS_LOG_FUNCTION(this);
86 
87  if (!m_node || !m_device)
88  {
89  return;
90  }
91 
92  /* set up link-local address */
93  if (!DynamicCast<LoopbackNetDevice>(m_device)) /* no autoconf for ip6-localhost */
94  {
95  Address addr = GetDevice()->GetAddress();
96  Ipv6InterfaceAddress ifaddr =
98  Ipv6Prefix(64));
99  AddAddress(ifaddr);
100  m_linkLocalAddress = ifaddr;
101  }
102  else
103  {
104  return; /* no NDISC cache for ip6-localhost */
105  }
106  int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
107  Ptr<Icmpv6L4Protocol> icmpv6 = DynamicCast<Icmpv6L4Protocol>(
109  interfaceId));
110 
111  if (icmpv6 && !m_ndCache)
112  {
113  m_ndCache = icmpv6->CreateCache(m_device, this);
114  }
115 }
116 
117 void
119 {
120  NS_LOG_FUNCTION(this << node);
121  m_node = node;
122 }
123 
124 void
126 {
127  NS_LOG_FUNCTION(this << device);
128  m_device = device;
129 }
130 
131 void
133 {
134  NS_LOG_FUNCTION(this << tc);
135  m_tc = tc;
136 }
137 
140 {
141  NS_LOG_FUNCTION(this);
142  return m_device;
143 }
144 
145 void
146 Ipv6Interface::SetMetric(uint16_t metric)
147 {
148  NS_LOG_FUNCTION(this << metric);
149  m_metric = metric;
150 }
151 
152 uint16_t
154 {
155  NS_LOG_FUNCTION(this);
156  return m_metric;
157 }
158 
159 bool
161 {
162  NS_LOG_FUNCTION(this);
163  return m_ifup;
164 }
165 
166 bool
168 {
169  NS_LOG_FUNCTION(this);
170  return !m_ifup;
171 }
172 
173 void
175 {
176  NS_LOG_FUNCTION(this);
177 
178  if (m_ifup)
179  {
180  return;
181  }
182  DoSetup();
183  m_ifup = true;
184 }
185 
186 void
188 {
189  NS_LOG_FUNCTION(this);
190  m_ifup = false;
191  m_addresses.clear();
192  m_ndCache->Flush();
193 }
194 
195 bool
197 {
198  NS_LOG_FUNCTION(this);
199  return m_forwarding;
200 }
201 
202 void
204 {
205  NS_LOG_FUNCTION(this << forwarding);
206  m_forwarding = forwarding;
207 }
208 
209 bool
211 {
212  NS_LOG_FUNCTION(this << iface);
213  Ipv6Address addr = iface.GetAddress();
214 
215  /* DAD handling */
216  if (!addr.IsAny())
217  {
218  for (Ipv6InterfaceAddressListCI it = m_addresses.begin(); it != m_addresses.end(); ++it)
219  {
220  if (it->first.GetAddress() == addr)
221  {
222  return false;
223  }
224  }
225 
227  m_addresses.emplace_back(iface, solicited);
228  if (!m_addAddressCallback.IsNull())
229  {
230  m_addAddressCallback(this, addr);
231  }
232 
233  if (!addr.IsAny() || !addr.IsLocalhost())
234  {
235  /* DAD handling */
236 
237  int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
238  Ptr<Icmpv6L4Protocol> icmpv6 = DynamicCast<Icmpv6L4Protocol>(
240  interfaceId));
241 
242  if (icmpv6)
243  {
244  if (icmpv6->IsAlwaysDad())
245  {
246  Simulator::Schedule(Seconds(0.), &Icmpv6L4Protocol::DoDAD, icmpv6, addr, this);
247  Simulator::Schedule(icmpv6->GetDadTimeout(),
249  icmpv6,
250  this,
251  addr);
252  }
253  else
254  {
257  icmpv6,
258  this,
259  addr);
260  }
261  }
262  }
263  return true;
264  }
265 
266  /* bad address */
267  return false;
268 }
269 
272 {
273  /* IPv6 interface has always at least one IPv6 link-local address */
274  NS_LOG_FUNCTION(this);
275 
276  return m_linkLocalAddress;
277 }
278 
279 bool
281 {
282  /* IPv6 interface has always at least one IPv6 Solicited Multicast address */
283  NS_LOG_FUNCTION(this << address);
284 
285  for (Ipv6InterfaceAddressListCI it = m_addresses.begin(); it != m_addresses.end(); ++it)
286  {
287  if (it->second == address)
288  {
289  return true;
290  }
291  }
292 
293  return false;
294 }
295 
297 Ipv6Interface::GetAddress(uint32_t index) const
298 {
299  NS_LOG_FUNCTION(this << index);
300  uint32_t i = 0;
301 
302  if (m_addresses.size() > index)
303  {
304  for (Ipv6InterfaceAddressListCI it = m_addresses.begin(); it != m_addresses.end(); ++it)
305  {
306  if (i == index)
307  {
308  return it->first;
309  }
310  i++;
311  }
312  }
313  else
314  {
315  NS_FATAL_ERROR("index " << index << " out of bounds");
316  }
318  return addr; /* quiet compiler */
319 }
320 
321 uint32_t
323 {
324  NS_LOG_FUNCTION(this);
325  return m_addresses.size();
326 }
327 
330 {
331  NS_LOG_FUNCTION(this << index);
332  uint32_t i = 0;
333 
334  if (m_addresses.size() < index)
335  {
336  NS_FATAL_ERROR("Removing index that does not exist in Ipv6Interface::RemoveAddress");
337  }
338 
339  for (Ipv6InterfaceAddressListI it = m_addresses.begin(); it != m_addresses.end(); ++it)
340  {
341  if (i == index)
342  {
343  Ipv6InterfaceAddress iface = it->first;
344  m_addresses.erase(it);
345  if (!m_removeAddressCallback.IsNull())
346  {
347  m_removeAddressCallback(this, iface);
348  }
349  return iface;
350  }
351 
352  i++;
353  }
354  NS_FATAL_ERROR("Address " << index << " not found");
356  return addr; /* quiet compiler */
357 }
358 
361 {
362  NS_LOG_FUNCTION(this << address);
363 
365  {
366  NS_LOG_WARN("Cannot remove loopback address.");
367  return Ipv6InterfaceAddress();
368  }
369 
370  for (Ipv6InterfaceAddressListI it = m_addresses.begin(); it != m_addresses.end(); ++it)
371  {
372  if (it->first.GetAddress() == address)
373  {
374  Ipv6InterfaceAddress iface = it->first;
375  m_addresses.erase(it);
376  if (!m_removeAddressCallback.IsNull())
377  {
378  m_removeAddressCallback(this, iface);
379  }
380  return iface;
381  }
382  }
383  return Ipv6InterfaceAddress();
384 }
385 
388 {
389  NS_LOG_FUNCTION(this << dst);
390 
391  for (Ipv6InterfaceAddressList::const_iterator it = m_addresses.begin(); it != m_addresses.end();
392  ++it)
393  {
394  Ipv6InterfaceAddress ifaddr = it->first;
395 
396  if (ifaddr.GetPrefix().IsMatch(ifaddr.GetAddress(), dst))
397  {
398  return ifaddr;
399  }
400  }
401 
402  /* NS_ASSERT_MSG (false, "Not matching address."); */
404  return ret; /* quiet compiler */
405 }
406 
407 void
409 {
410  NS_LOG_FUNCTION(this << p << dest);
411 
412  if (!IsUp())
413  {
414  return;
415  }
416 
418 
419  /* check if destination is localhost (::1), if yes we don't pass through
420  * traffic control layer */
421  if (DynamicCast<LoopbackNetDevice>(m_device))
422  {
426  p->AddHeader(hdr);
427  m_device->Send(p, m_device->GetBroadcast(), Ipv6L3Protocol::PROT_NUMBER);
428  return;
429  }
430 
431  NS_ASSERT(m_tc);
432 
433  /* check if destination is for one of our interface */
434  for (Ipv6InterfaceAddressListCI it = m_addresses.begin(); it != m_addresses.end(); ++it)
435  {
436  if (dest == it->first.GetAddress())
437  {
438  p->AddHeader(hdr);
439  m_tc->Receive(m_device,
440  p,
442  m_device->GetBroadcast(),
443  m_device->GetBroadcast(),
445  return;
446  }
447  }
448 
449  /* other address */
450  if (m_device->NeedsArp())
451  {
452  NS_LOG_LOGIC("Needs NDISC " << dest);
453 
454  int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
455  Ptr<Icmpv6L4Protocol> icmpv6 = DynamicCast<Icmpv6L4Protocol>(
457  interfaceId));
458 
459  Address hardwareDestination;
460  bool found = false;
461 
462  NS_ASSERT(icmpv6);
463 
464  if (dest.IsMulticast())
465  {
466  NS_LOG_LOGIC("IsMulticast");
468  m_device->IsMulticast(),
469  "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
470 
471  hardwareDestination = m_device->GetMulticast(dest);
472  found = true;
473  }
474  else
475  {
476  NS_LOG_LOGIC("NDISC Lookup");
477  found = icmpv6->Lookup(p, hdr, dest, GetDevice(), m_ndCache, &hardwareDestination);
478  }
479 
480  if (found)
481  {
482  NS_LOG_LOGIC("Address Resolved. Send.");
483  m_tc->Send(m_device,
484  Create<Ipv6QueueDiscItem>(p,
485  hardwareDestination,
487  hdr));
488  }
489  }
490  else
491  {
492  NS_LOG_LOGIC("Doesn't need NDISC");
493  m_tc->Send(m_device,
494  Create<Ipv6QueueDiscItem>(p,
495  m_device->GetBroadcast(),
497  hdr));
498  }
499 }
500 
501 void
502 Ipv6Interface::SetCurHopLimit(uint8_t curHopLimit)
503 {
504  NS_LOG_FUNCTION(this << curHopLimit);
505  m_curHopLimit = curHopLimit;
506 }
507 
508 uint8_t
510 {
511  NS_LOG_FUNCTION(this);
512  return m_curHopLimit;
513 }
514 
515 void
516 Ipv6Interface::SetBaseReachableTime(uint16_t baseReachableTime)
517 {
518  NS_LOG_FUNCTION(this << baseReachableTime);
519  m_baseReachableTime = baseReachableTime;
520 }
521 
522 uint16_t
524 {
525  NS_LOG_FUNCTION(this);
526  return m_baseReachableTime;
527 }
528 
529 void
530 Ipv6Interface::SetReachableTime(uint16_t reachableTime)
531 {
532  NS_LOG_FUNCTION(this << reachableTime);
533  m_reachableTime = reachableTime;
534 }
535 
536 uint16_t
538 {
539  NS_LOG_FUNCTION(this);
540  return m_reachableTime;
541 }
542 
543 void
544 Ipv6Interface::SetRetransTimer(uint16_t retransTimer)
545 {
546  NS_LOG_FUNCTION(this << retransTimer);
547  m_retransTimer = retransTimer;
548 }
549 
550 uint16_t
552 {
553  NS_LOG_FUNCTION(this);
554  return m_retransTimer;
555 }
556 
557 void
559 {
560  NS_LOG_FUNCTION(this << address << state);
561 
562  for (Ipv6InterfaceAddressListI it = m_addresses.begin(); it != m_addresses.end(); ++it)
563  {
564  if (it->first.GetAddress() == address)
565  {
566  it->first.SetState(state);
567  return;
568  }
569  }
570  /* not found, maybe address has expired */
571 }
572 
573 void
575 {
576  NS_LOG_FUNCTION(this << address << uid);
577 
578  for (Ipv6InterfaceAddressListI it = m_addresses.begin(); it != m_addresses.end(); ++it)
579  {
580  if (it->first.GetAddress() == address)
581  {
582  it->first.SetNsDadUid(uid);
583  return;
584  }
585  }
586  /* not found, maybe address has expired */
587 }
588 
591 {
592  NS_LOG_FUNCTION(this);
593  return m_ndCache;
594 }
595 
596 void
598  Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> removeAddressCallback)
599 {
600  NS_LOG_FUNCTION(this << &removeAddressCallback);
601  m_removeAddressCallback = removeAddressCallback;
602 }
603 
604 void
606  Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback)
607 {
608  NS_LOG_FUNCTION(this << &addAddressCallback);
609  m_addAddressCallback = addAddressCallback;
610 }
611 
612 } /* namespace ns3 */
a polymophic address class
Definition: address.h:100
Callback template class.
Definition: callback.h:443
virtual void FunctionDadTimeout(Ipv6Interface *interface, Ipv6Address addr)
Function called when DAD timeout.
void DoDAD(Ipv6Address target, Ptr< Ipv6Interface > interface)
Do the Duplication Address Detection (DAD).
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
Describes an IPv6 address.
Definition: ipv6-address.h:50
static Ipv6Address MakeSolicitedAddress(Ipv6Address addr)
Make the solicited IPv6 address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
bool IsAny() const
If the IPv6 address is the "Any" address.
bool IsLocalhost() const
If the IPv6 address is localhost (::1).
static Ipv6Address MakeAutoconfiguredLinkLocalAddress(Address mac)
Make the autoconfigured link-local IPv6 address from a Mac address.
static Ipv6Address GetLoopback()
Get the loopback address.
Packet header for IPv6.
Definition: ipv6-header.h:36
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
virtual Ptr< IpL4Protocol > GetProtocol(int protocolNumber) const =0
Get L4 protocol by protocol number.
IPv6 address associated with an interface.
Ipv6Address GetAddress() const
Get the IPv6 address.
Ipv6Prefix GetPrefix() const
Get the IPv6 prefix.
State_e
State of an address associated with an interface.
Ipv6InterfaceAddress RemoveAddress(uint32_t index)
Remove an address from interface.
uint16_t GetBaseReachableTime() const
Get the base reachable time.
uint8_t m_curHopLimit
Current hop limit.
Ptr< NetDevice > m_device
NetDevice associated with this interface.
bool IsDown() const
Is the interface DOWN ?
Ptr< NdiscCache > m_ndCache
Neighbor cache.
Ipv6InterfaceAddress GetLinkLocalAddress() const
Get link-local address from IPv6 interface.
bool m_ifup
The state of this interface.
uint8_t GetCurHopLimit() const
Get the current hop limit value.
static TypeId GetTypeId()
Get the type ID.
Ipv6Interface()
Constructs an Ipv6Interface.
void SetRetransTimer(uint16_t retransTimer)
Set the retransmission timer.
void DoSetup()
Initialize interface.
void SetForwarding(bool forward)
Set forwarding enabled or not.
void SetReachableTime(uint16_t reachableTime)
Set the reachable time.
Ipv6InterfaceAddress GetAddressMatchingDestination(Ipv6Address dst)
Get an address which is in the same network prefix as destination.
void SetNode(Ptr< Node > node)
Set node associated with interface.
void SetDown()
Disable this interface.
bool IsForwarding() const
If the interface allows forwarding packets.
void RemoveAddressCallback(Callback< void, Ptr< Ipv6Interface >, Ipv6InterfaceAddress > removeAddressCallback)
This callback is set when an address is removed from an interface with auto-generated Ndisc cache and...
uint16_t GetReachableTime() const
Get the reachable time.
bool IsUp() const
Is the interface UP ?
bool m_forwarding
Forwarding state.
uint16_t m_metric
The metric.
uint16_t m_reachableTime
Reachable time (in millisecond).
uint32_t GetNAddresses() const
Get number of addresses on this IPv6 interface.
void DoDispose() override
Dispose this object.
Callback< void, Ptr< Ipv6Interface >, Ipv6InterfaceAddress > m_removeAddressCallback
remove address callback
std::list< std::pair< Ipv6InterfaceAddress, Ipv6Address > >::const_iterator Ipv6InterfaceAddressListCI
Const Container Iterator for the Ipv6InterfaceAddresses.
bool IsSolicitedMulticastAddress(Ipv6Address address) const
Checks if the address is a Solicited Multicast address for this interface.
void SetCurHopLimit(uint8_t curHopLimit)
Set the current hop limit.
Ipv6InterfaceAddress GetAddress(uint32_t index) const
Get an address from IPv6 interface.
~Ipv6Interface() override
Destructor.
bool AddAddress(Ipv6InterfaceAddress iface)
Add an IPv6 address.
void SetUp()
Enable this interface.
void SetNsDadUid(Ipv6Address address, uint32_t uid)
Update NS DAD packet UID of an interface address.
uint16_t m_retransTimer
Retransmission timer (in millisecond).
void Send(Ptr< Packet > p, const Ipv6Header &hdr, Ipv6Address dest)
Send a packet through this interface.
Ipv6InterfaceAddressList m_addresses
The addresses assigned to this interface.
uint16_t GetRetransTimer() const
Get the retransmission timer.
uint16_t GetMetric() const
Get the metric.
void SetBaseReachableTime(uint16_t baseReachableTime)
Set the base reachable time.
Ptr< NdiscCache > GetNdiscCache() const
Ipv6InterfaceAddress m_linkLocalAddress
The link-local addresses assigned to this interface.
Ptr< Node > m_node
Node associated with this interface.
std::list< std::pair< Ipv6InterfaceAddress, Ipv6Address > >::iterator Ipv6InterfaceAddressListI
Container Iterator for the Ipv6InterfaceAddresses.
Callback< void, Ptr< Ipv6Interface >, Ipv6InterfaceAddress > m_addAddressCallback
add address callback
void SetTrafficControl(Ptr< TrafficControlLayer > tc)
Set the TrafficControlLayer.
void SetMetric(uint16_t metric)
Set the metric.
uint16_t m_baseReachableTime
Base value used for computing the random reachable time value (in millisecond).
Ptr< TrafficControlLayer > m_tc
TrafficControlLayer associated with this interface.
void AddAddressCallback(Callback< void, Ptr< Ipv6Interface >, Ipv6InterfaceAddress > addAddressCallback)
This callback is set when an address is added from an interface with auto-generated Ndisc cache and i...
void SetDevice(Ptr< NetDevice > device)
Set the NetDevice.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
void SetState(Ipv6Address address, Ipv6InterfaceAddress::State_e state)
Update state of an interface address.
IPv6 layer implementation.
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Describes an IPv6 prefix.
Definition: ipv6-address.h:456
bool IsMatch(Ipv6Address a, Ipv6Address b) const
If the Address match the type.
void Flush()
Flush the cache.
Definition: ndisc-cache.cc:163
@ PACKET_HOST
Packet addressed to us.
Definition: net-device.h:301
A base class which provides memory management and object aggregation.
Definition: object.h:89
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
#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
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#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_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#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
address
Definition: first.py:40
Every class exported by the ns3 library is enclosed in the ns3 namespace.