A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv6-interface.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007-2009 Strasbourg University
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
7 */
8
9#include "ipv6-interface.h"
10
11#include "icmpv6-l4-protocol.h"
12#include "ipv6-header.h"
13#include "ipv6-l3-protocol.h"
15#include "loopback-net-device.h"
16#include "ndisc-cache.h"
17
18#include "ns3/log.h"
19#include "ns3/mac16-address.h"
20#include "ns3/mac64-address.h"
21#include "ns3/net-device.h"
22#include "ns3/node.h"
23#include "ns3/packet.h"
24#include "ns3/traffic-control-layer.h"
25
26namespace ns3
27{
28
29NS_LOG_COMPONENT_DEFINE("Ipv6Interface");
30
31NS_OBJECT_ENSURE_REGISTERED(Ipv6Interface);
32
33TypeId
35{
36 static TypeId tid = TypeId("ns3::Ipv6Interface").SetParent<Object>().SetGroupName("Internet");
37 return tid;
38}
39
41 : m_ifup(false),
42 m_forwarding(true),
43 m_metric(1),
44 m_node(nullptr),
45 m_device(nullptr),
46 m_tc(nullptr),
47 m_ndCache(nullptr),
48 m_curHopLimit(0),
49 m_baseReachableTime(0),
50 m_reachableTime(0),
51 m_retransTimer(0)
52{
53 NS_LOG_FUNCTION(this);
54}
55
59
60void
62{
63 NS_LOG_FUNCTION(this);
64 m_node = nullptr;
65 m_device = nullptr;
66 m_tc = nullptr;
67 m_ndCache = nullptr;
69}
70
71void
73{
74 NS_LOG_FUNCTION(this);
75
76 if (!m_node || !m_device)
77 {
78 return;
79 }
80
81 /* set up link-local address */
82 if (!DynamicCast<LoopbackNetDevice>(m_device)) /* no autoconf for ip6-localhost */
83 {
84 Address addr = GetDevice()->GetAddress();
87 Ipv6Prefix(64));
88 AddAddress(ifaddr);
89 m_linkLocalAddress = ifaddr;
90 }
91 else
92 {
93 return; /* no NDISC cache for ip6-localhost */
94 }
95 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
98 interfaceId));
99
100 if (icmpv6 && !m_ndCache)
101 {
102 m_ndCache = icmpv6->CreateCache(m_device, this);
103 }
104}
105
106void
108{
109 NS_LOG_FUNCTION(this << node);
110 m_node = node;
111}
112
113void
115{
116 NS_LOG_FUNCTION(this << device);
117 m_device = device;
118}
119
120void
126
129{
130 NS_LOG_FUNCTION(this);
131 return m_device;
132}
133
134void
136{
137 NS_LOG_FUNCTION(this << metric);
138 m_metric = metric;
139}
140
141uint16_t
143{
144 NS_LOG_FUNCTION(this);
145 return m_metric;
146}
147
148bool
150{
151 NS_LOG_FUNCTION(this);
152 return m_ifup;
153}
154
155bool
157{
158 NS_LOG_FUNCTION(this);
159 return !m_ifup;
160}
161
162void
164{
165 NS_LOG_FUNCTION(this);
166
167 if (m_ifup)
168 {
169 return;
170 }
171 DoSetup();
172 m_ifup = true;
173}
174
175void
177{
178 NS_LOG_FUNCTION(this);
179 m_ifup = false;
180 m_addresses.clear();
181 m_ndCache->Flush();
182}
183
184bool
186{
187 NS_LOG_FUNCTION(this);
188 return m_forwarding;
189}
190
191void
193{
194 NS_LOG_FUNCTION(this << forwarding);
195 m_forwarding = forwarding;
196}
197
198bool
200{
201 NS_LOG_FUNCTION(this << iface);
202 Ipv6Address addr = iface.GetAddress();
203
204 /* DAD handling */
205 if (!addr.IsAny())
206 {
207 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
208 {
209 if (it->first.GetAddress() == addr)
210 {
211 return false;
212 }
213 }
214
216 m_addresses.emplace_back(iface, solicited);
217 if (!m_addAddressCallback.IsNull())
218 {
219 m_addAddressCallback(this, addr);
220 }
221
222 if (!addr.IsAny() || !addr.IsLocalhost())
223 {
224 /* DAD handling */
225
226 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
229 interfaceId));
230
231 if (icmpv6)
232 {
233 if (icmpv6->IsAlwaysDad())
234 {
235 Simulator::Schedule(Seconds(0.), &Icmpv6L4Protocol::DoDAD, icmpv6, addr, this);
236 Simulator::Schedule(icmpv6->GetDadTimeout(),
238 icmpv6,
239 this,
240 addr);
241 }
242 else
243 {
246 icmpv6,
247 this,
248 addr);
249 }
250 }
251 }
252 return true;
253 }
254
255 /* bad address */
256 return false;
257}
258
261{
262 /* IPv6 interface has always at least one IPv6 link-local address */
263 NS_LOG_FUNCTION(this);
264
265 return m_linkLocalAddress;
266}
267
268bool
270{
271 /* IPv6 interface has always at least one IPv6 Solicited Multicast address */
272 NS_LOG_FUNCTION(this << address);
273
274 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
275 {
276 if (it->second == address)
277 {
278 return true;
279 }
280 }
281
282 return false;
283}
284
287{
288 NS_LOG_FUNCTION(this << index);
289 uint32_t i = 0;
290
291 if (m_addresses.size() > index)
292 {
293 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
294 {
295 if (i == index)
296 {
297 return it->first;
298 }
299 i++;
300 }
301 }
302 else
303 {
304 NS_FATAL_ERROR("index " << index << " out of bounds");
305 }
307 return addr; /* quiet compiler */
308}
309
312{
313 NS_LOG_FUNCTION(this);
314 return m_addresses.size();
315}
316
319{
320 NS_LOG_FUNCTION(this << index);
321 uint32_t i = 0;
322
323 if (m_addresses.size() < index)
324 {
325 NS_FATAL_ERROR("Removing index that does not exist in Ipv6Interface::RemoveAddress");
326 }
327
328 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
329 {
330 if (i == index)
331 {
332 Ipv6InterfaceAddress iface = it->first;
333 m_addresses.erase(it);
334 if (!m_removeAddressCallback.IsNull())
335 {
336 m_removeAddressCallback(this, iface);
337 }
338 return iface;
339 }
340
341 i++;
342 }
343 NS_FATAL_ERROR("Address " << index << " not found");
345 return addr; /* quiet compiler */
346}
347
350{
351 NS_LOG_FUNCTION(this << address);
352
353 if (address == Ipv6Address::GetLoopback())
354 {
355 NS_LOG_WARN("Cannot remove loopback address.");
356 return Ipv6InterfaceAddress();
357 }
358
359 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
360 {
361 if (it->first.GetAddress() == address)
362 {
363 Ipv6InterfaceAddress iface = it->first;
364 m_addresses.erase(it);
365 if (!m_removeAddressCallback.IsNull())
366 {
367 m_removeAddressCallback(this, iface);
368 }
369 return iface;
370 }
371 }
372 return Ipv6InterfaceAddress();
373}
374
377{
378 NS_LOG_FUNCTION(this << dst);
379
380 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
381 {
382 Ipv6InterfaceAddress ifaddr = it->first;
383
384 if (ifaddr.GetPrefix().IsMatch(ifaddr.GetAddress(), dst))
385 {
386 return ifaddr;
387 }
388 }
389
390 /* NS_ASSERT_MSG (false, "Not matching address."); */
392 return ret; /* quiet compiler */
393}
394
395void
397{
398 NS_LOG_FUNCTION(this << p << dest);
399
400 if (!IsUp())
401 {
402 return;
403 }
404
406
407 /* check if destination is localhost (::1), if yes we don't pass through
408 * traffic control layer */
410 {
411 /** \todo additional checks needed here (such as whether multicast
412 * goes to loopback)?
413 */
414 p->AddHeader(hdr);
415 m_device->Send(p, m_device->GetBroadcast(), Ipv6L3Protocol::PROT_NUMBER);
416 return;
417 }
418
420
421 /* check if destination is for one of our interface */
422 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
423 {
424 if (dest == it->first.GetAddress())
425 {
426 p->AddHeader(hdr);
428 m_tc,
429 m_device,
430 p,
432 m_device->GetBroadcast(),
433 m_device->GetBroadcast(),
435 return;
436 }
437 }
438
439 /* other address */
440 if (m_device->NeedsArp())
441 {
442 NS_LOG_LOGIC("Needs NDISC " << dest);
443
444 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
447 interfaceId));
448
449 Address hardwareDestination;
450 bool found = false;
451
452 NS_ASSERT(icmpv6);
453
454 if (dest.IsMulticast())
455 {
456 NS_LOG_LOGIC("IsMulticast");
458 m_device->IsMulticast(),
459 "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
460
461 hardwareDestination = m_device->GetMulticast(dest);
462 found = true;
463 }
464 else
465 {
466 NS_LOG_LOGIC("NDISC Lookup");
467 found = icmpv6->Lookup(p, hdr, dest, GetDevice(), m_ndCache, &hardwareDestination);
468 }
469
470 if (found)
471 {
472 NS_LOG_LOGIC("Address Resolved. Send.");
473 m_tc->Send(m_device,
475 hardwareDestination,
477 hdr));
478 }
479 }
480 else
481 {
482 NS_LOG_LOGIC("Doesn't need NDISC");
483 m_tc->Send(m_device,
485 m_device->GetBroadcast(),
487 hdr));
488 }
489}
490
491void
493{
494 NS_LOG_FUNCTION(this << curHopLimit);
495 m_curHopLimit = curHopLimit;
496}
497
498uint8_t
500{
501 NS_LOG_FUNCTION(this);
502 return m_curHopLimit;
503}
504
505void
506Ipv6Interface::SetBaseReachableTime(uint16_t baseReachableTime)
507{
508 NS_LOG_FUNCTION(this << baseReachableTime);
509 m_baseReachableTime = baseReachableTime;
510}
511
512uint16_t
518
519void
520Ipv6Interface::SetReachableTime(uint16_t reachableTime)
521{
522 NS_LOG_FUNCTION(this << reachableTime);
523 m_reachableTime = reachableTime;
524}
525
526uint16_t
528{
529 NS_LOG_FUNCTION(this);
530 return m_reachableTime;
531}
532
533void
534Ipv6Interface::SetRetransTimer(uint16_t retransTimer)
535{
536 NS_LOG_FUNCTION(this << retransTimer);
537 m_retransTimer = retransTimer;
538}
539
540uint16_t
542{
543 NS_LOG_FUNCTION(this);
544 return m_retransTimer;
545}
546
547void
549{
550 NS_LOG_FUNCTION(this << address << state);
551
552 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
553 {
554 if (it->first.GetAddress() == address)
555 {
556 it->first.SetState(state);
557 return;
558 }
559 }
560 /* not found, maybe address has expired */
561}
562
563void
565{
566 NS_LOG_FUNCTION(this << address << uid);
567
568 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
569 {
570 if (it->first.GetAddress() == address)
571 {
572 it->first.SetNsDadUid(uid);
573 return;
574 }
575 }
576 /* not found, maybe address has expired */
577}
578
581{
582 NS_LOG_FUNCTION(this);
583 return m_ndCache;
584}
585
586void
588 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> removeAddressCallback)
589{
590 NS_LOG_FUNCTION(this << &removeAddressCallback);
591 m_removeAddressCallback = removeAddressCallback;
592}
593
594void
596 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback)
597{
598 NS_LOG_FUNCTION(this << &addAddressCallback);
599 m_addAddressCallback = addAddressCallback;
600}
601
602} /* namespace ns3 */
a polymophic address class
Definition address.h:90
Callback template class.
Definition callback.h:422
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.
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:24
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition ipv6.h:71
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.
bool IsMatch(Ipv6Address a, Ipv6Address b) const
If the Address match the type.
void Flush()
Flush the cache.
@ PACKET_HOST
Packet addressed to us.
Definition net-device.h:290
A base class which provides memory management and object aggregation.
Definition object.h:78
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:594
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:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#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:75
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:250
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580