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 (auto 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 (auto 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 (auto 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 (auto 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 (auto 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 (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
392  {
393  Ipv6InterfaceAddress ifaddr = it->first;
394 
395  if (ifaddr.GetPrefix().IsMatch(ifaddr.GetAddress(), dst))
396  {
397  return ifaddr;
398  }
399  }
400 
401  /* NS_ASSERT_MSG (false, "Not matching address."); */
403  return ret; /* quiet compiler */
404 }
405 
406 void
408 {
409  NS_LOG_FUNCTION(this << p << dest);
410 
411  if (!IsUp())
412  {
413  return;
414  }
415 
417 
418  /* check if destination is localhost (::1), if yes we don't pass through
419  * traffic control layer */
420  if (DynamicCast<LoopbackNetDevice>(m_device))
421  {
425  p->AddHeader(hdr);
426  m_device->Send(p, m_device->GetBroadcast(), Ipv6L3Protocol::PROT_NUMBER);
427  return;
428  }
429 
430  NS_ASSERT(m_tc);
431 
432  /* check if destination is for one of our interface */
433  for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
434  {
435  if (dest == it->first.GetAddress())
436  {
437  p->AddHeader(hdr);
439  m_tc,
440  m_device,
441  p,
443  m_device->GetBroadcast(),
444  m_device->GetBroadcast(),
446  return;
447  }
448  }
449 
450  /* other address */
451  if (m_device->NeedsArp())
452  {
453  NS_LOG_LOGIC("Needs NDISC " << dest);
454 
455  int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
456  Ptr<Icmpv6L4Protocol> icmpv6 = DynamicCast<Icmpv6L4Protocol>(
458  interfaceId));
459 
460  Address hardwareDestination;
461  bool found = false;
462 
463  NS_ASSERT(icmpv6);
464 
465  if (dest.IsMulticast())
466  {
467  NS_LOG_LOGIC("IsMulticast");
469  m_device->IsMulticast(),
470  "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
471 
472  hardwareDestination = m_device->GetMulticast(dest);
473  found = true;
474  }
475  else
476  {
477  NS_LOG_LOGIC("NDISC Lookup");
478  found = icmpv6->Lookup(p, hdr, dest, GetDevice(), m_ndCache, &hardwareDestination);
479  }
480 
481  if (found)
482  {
483  NS_LOG_LOGIC("Address Resolved. Send.");
484  m_tc->Send(m_device,
485  Create<Ipv6QueueDiscItem>(p,
486  hardwareDestination,
488  hdr));
489  }
490  }
491  else
492  {
493  NS_LOG_LOGIC("Doesn't need NDISC");
494  m_tc->Send(m_device,
495  Create<Ipv6QueueDiscItem>(p,
496  m_device->GetBroadcast(),
498  hdr));
499  }
500 }
501 
502 void
503 Ipv6Interface::SetCurHopLimit(uint8_t curHopLimit)
504 {
505  NS_LOG_FUNCTION(this << curHopLimit);
506  m_curHopLimit = curHopLimit;
507 }
508 
509 uint8_t
511 {
512  NS_LOG_FUNCTION(this);
513  return m_curHopLimit;
514 }
515 
516 void
517 Ipv6Interface::SetBaseReachableTime(uint16_t baseReachableTime)
518 {
519  NS_LOG_FUNCTION(this << baseReachableTime);
520  m_baseReachableTime = baseReachableTime;
521 }
522 
523 uint16_t
525 {
526  NS_LOG_FUNCTION(this);
527  return m_baseReachableTime;
528 }
529 
530 void
531 Ipv6Interface::SetReachableTime(uint16_t reachableTime)
532 {
533  NS_LOG_FUNCTION(this << reachableTime);
534  m_reachableTime = reachableTime;
535 }
536 
537 uint16_t
539 {
540  NS_LOG_FUNCTION(this);
541  return m_reachableTime;
542 }
543 
544 void
545 Ipv6Interface::SetRetransTimer(uint16_t retransTimer)
546 {
547  NS_LOG_FUNCTION(this << retransTimer);
548  m_retransTimer = retransTimer;
549 }
550 
551 uint16_t
553 {
554  NS_LOG_FUNCTION(this);
555  return m_retransTimer;
556 }
557 
558 void
560 {
561  NS_LOG_FUNCTION(this << address << state);
562 
563  for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
564  {
565  if (it->first.GetAddress() == address)
566  {
567  it->first.SetState(state);
568  return;
569  }
570  }
571  /* not found, maybe address has expired */
572 }
573 
574 void
576 {
577  NS_LOG_FUNCTION(this << address << uid);
578 
579  for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
580  {
581  if (it->first.GetAddress() == address)
582  {
583  it->first.SetNsDadUid(uid);
584  return;
585  }
586  }
587  /* not found, maybe address has expired */
588 }
589 
592 {
593  NS_LOG_FUNCTION(this);
594  return m_ndCache;
595 }
596 
597 void
599  Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> removeAddressCallback)
600 {
601  NS_LOG_FUNCTION(this << &removeAddressCallback);
602  m_removeAddressCallback = removeAddressCallback;
603 }
604 
605 void
607  Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback)
608 {
609  NS_LOG_FUNCTION(this << &addAddressCallback);
610  m_addAddressCallback = addAddressCallback;
611 }
612 
613 } /* namespace ns3 */
a polymophic address class
Definition: address.h:101
Callback template class.
Definition: callback.h:438
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:49
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:35
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
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.
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:455
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:352
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:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
virtual void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Called by NetDevices, incoming packet.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
#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:1326
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.