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 =
37 TypeId("ns3::Ipv6Interface")
39 .SetGroupName("Internet")
40 .AddTraceSource("InterfaceStatus",
41 "Interface has been set up or down.",
43 "ns3::Ipv6Address::TracedCallback");
44 return tid;
45}
46
48 : m_ifup(false),
49 m_forwarding(true),
50 m_metric(1),
51 m_node(nullptr),
52 m_device(nullptr),
53 m_tc(nullptr),
54 m_ndCache(nullptr),
55 m_curHopLimit(0),
56 m_baseReachableTime(0),
57 m_reachableTime(0),
58 m_retransTimer(0)
59{
60 NS_LOG_FUNCTION(this);
61}
62
66
67void
69{
70 NS_LOG_FUNCTION(this);
71 m_node = nullptr;
72 m_device = nullptr;
73 m_tc = nullptr;
74 m_ndCache = nullptr;
76}
77
78void
80{
81 NS_LOG_FUNCTION(this);
82
83 if (!m_node || !m_device)
84 {
85 return;
86 }
87
88 /* set up link-local address */
89 if (!DynamicCast<LoopbackNetDevice>(m_device)) /* no autoconf for ip6-localhost */
90 {
91 Address addr = GetDevice()->GetAddress();
94 Ipv6Prefix(64));
95 AddAddress(ifaddr);
96 m_linkLocalAddress = ifaddr;
97 }
98 else
99 {
100 return; /* no NDISC cache for ip6-localhost */
101 }
102 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
105 interfaceId));
106
107 if (icmpv6 && !m_ndCache)
108 {
109 m_ndCache = icmpv6->CreateCache(m_device, this);
110 }
111}
112
113void
115{
116 NS_LOG_FUNCTION(this << node);
117 m_node = node;
118}
119
120void
122{
123 NS_LOG_FUNCTION(this << device);
124 m_device = device;
125}
126
127void
133
136{
137 NS_LOG_FUNCTION(this);
138 return m_device;
139}
140
141void
143{
144 NS_LOG_FUNCTION(this << metric);
145 m_metric = metric;
146}
147
148uint16_t
150{
151 NS_LOG_FUNCTION(this);
152 return m_metric;
153}
154
155bool
157{
158 NS_LOG_FUNCTION(this);
159 return m_ifup;
160}
161
162bool
164{
165 NS_LOG_FUNCTION(this);
166 return !m_ifup;
167}
168
169void
171{
172 NS_LOG_FUNCTION(this);
173
174 if (m_ifup)
175 {
176 return;
177 }
178 DoSetup();
179 m_ifup = true;
180
182 NS_ASSERT_MSG(ip, "IPv6 not installed on node.");
183 auto ifIndex = ip->GetInterfaceForDevice(m_device);
184 m_interfaceStatus(m_ifup, ifIndex);
185}
186
187void
189{
190 NS_LOG_FUNCTION(this);
191 m_ifup = false;
192 m_addresses.clear();
193 m_ndCache->Flush();
194
196 NS_ASSERT_MSG(ip, "IPv6 not installed on node.");
197 auto ifIndex = ip->GetInterfaceForDevice(m_device);
198 m_interfaceStatus(m_ifup, ifIndex);
199}
200
201bool
203{
204 NS_LOG_FUNCTION(this);
205 return m_forwarding;
206}
207
208void
210{
211 NS_LOG_FUNCTION(this << forwarding);
212 m_forwarding = forwarding;
213}
214
215bool
217{
218 NS_LOG_FUNCTION(this << iface);
219 Ipv6Address addr = iface.GetAddress();
220
221 /* DAD handling */
222 if (!addr.IsAny())
223 {
224 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
225 {
226 if (it->first.GetAddress() == addr)
227 {
228 return false;
229 }
230 }
231
233 m_addresses.emplace_back(iface, solicited);
234 if (!m_addAddressCallback.IsNull())
235 {
236 m_addAddressCallback(this, addr);
237 }
238
239 if (!addr.IsAny() || !addr.IsLocalhost())
240 {
241 /* DAD handling */
242
243 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
246 interfaceId));
247
248 if (icmpv6)
249 {
250 if (icmpv6->IsAlwaysDad())
251 {
252 Simulator::Schedule(Seconds(0.), &Icmpv6L4Protocol::DoDAD, icmpv6, addr, this);
253 Simulator::Schedule(icmpv6->GetDadTimeout(),
255 icmpv6,
256 this,
257 addr);
258 }
259 else
260 {
263 icmpv6,
264 this,
265 addr);
266 }
267 }
268 }
269 return true;
270 }
271
272 /* bad address */
273 return false;
274}
275
278{
279 /* IPv6 interface has always at least one IPv6 link-local address */
280 NS_LOG_FUNCTION(this);
281
282 return m_linkLocalAddress;
283}
284
285bool
287{
288 /* IPv6 interface has always at least one IPv6 Solicited Multicast address */
289 NS_LOG_FUNCTION(this << address);
290
291 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
292 {
293 if (it->second == address)
294 {
295 return true;
296 }
297 }
298
299 return false;
300}
301
304{
305 NS_LOG_FUNCTION(this << index);
306 uint32_t i = 0;
307
308 if (m_addresses.size() > index)
309 {
310 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
311 {
312 if (i == index)
313 {
314 return it->first;
315 }
316 i++;
317 }
318 }
319 else
320 {
321 NS_FATAL_ERROR("index " << index << " out of bounds");
322 }
324 return addr; /* quiet compiler */
325}
326
329{
330 NS_LOG_FUNCTION(this);
331 return m_addresses.size();
332}
333
336{
337 NS_LOG_FUNCTION(this << index);
338 uint32_t i = 0;
339
340 if (m_addresses.size() < index)
341 {
342 NS_FATAL_ERROR("Removing index that does not exist in Ipv6Interface::RemoveAddress");
343 }
344
345 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
346 {
347 if (i == index)
348 {
349 Ipv6InterfaceAddress iface = it->first;
350 m_addresses.erase(it);
351 if (!m_removeAddressCallback.IsNull())
352 {
353 m_removeAddressCallback(this, iface);
354 }
355 return iface;
356 }
357
358 i++;
359 }
360 NS_FATAL_ERROR("Address " << index << " not found");
362 return addr; /* quiet compiler */
363}
364
367{
368 NS_LOG_FUNCTION(this << address);
369
370 if (address == Ipv6Address::GetLoopback())
371 {
372 NS_LOG_WARN("Cannot remove loopback address.");
373 return Ipv6InterfaceAddress();
374 }
375
376 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
377 {
378 if (it->first.GetAddress() == address)
379 {
380 Ipv6InterfaceAddress iface = it->first;
381 m_addresses.erase(it);
382 if (!m_removeAddressCallback.IsNull())
383 {
384 m_removeAddressCallback(this, iface);
385 }
386 return iface;
387 }
388 }
389 return Ipv6InterfaceAddress();
390}
391
394{
395 NS_LOG_FUNCTION(this << dst);
396
397 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
398 {
399 Ipv6InterfaceAddress ifaddr = it->first;
400
401 if (ifaddr.GetPrefix().IsMatch(ifaddr.GetAddress(), dst))
402 {
403 return ifaddr;
404 }
405 }
406
407 /* NS_ASSERT_MSG (false, "Not matching address."); */
409 return ret; /* quiet compiler */
410}
411
412void
414{
415 NS_LOG_FUNCTION(this << p << dest);
416
417 if (!IsUp())
418 {
419 return;
420 }
421
423
424 /* check if destination is localhost (::1), if yes we don't pass through
425 * traffic control layer */
427 {
428 /** @todo additional checks needed here (such as whether multicast
429 * goes to loopback)?
430 */
431 p->AddHeader(hdr);
432 m_device->Send(p, m_device->GetBroadcast(), Ipv6L3Protocol::PROT_NUMBER);
433 return;
434 }
435
437
438 /* check if destination is for one of our interface */
439 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
440 {
441 if (dest == it->first.GetAddress())
442 {
443 p->AddHeader(hdr);
445 m_tc,
446 m_device,
447 p,
449 m_device->GetBroadcast(),
450 m_device->GetBroadcast(),
452 return;
453 }
454 }
455
456 /* other address */
457 if (m_device->NeedsArp())
458 {
459 NS_LOG_LOGIC("Needs NDISC " << dest);
460
461 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
464 interfaceId));
465
466 Address hardwareDestination;
467 bool found = false;
468
469 NS_ASSERT(icmpv6);
470
471 if (dest.IsMulticast())
472 {
473 NS_LOG_LOGIC("IsMulticast");
475 m_device->IsMulticast(),
476 "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
477
478 hardwareDestination = m_device->GetMulticast(dest);
479 found = true;
480 }
481 else
482 {
483 NS_LOG_LOGIC("NDISC Lookup");
484 found = icmpv6->Lookup(p, hdr, dest, GetDevice(), m_ndCache, &hardwareDestination);
485 }
486
487 if (found)
488 {
489 NS_LOG_LOGIC("Address Resolved. Send.");
490 m_tc->Send(m_device,
492 hardwareDestination,
494 hdr));
495 }
496 }
497 else
498 {
499 NS_LOG_LOGIC("Doesn't need NDISC");
500 m_tc->Send(m_device,
502 m_device->GetBroadcast(),
504 hdr));
505 }
506}
507
508void
510{
511 NS_LOG_FUNCTION(this << curHopLimit);
512 m_curHopLimit = curHopLimit;
513}
514
515uint8_t
517{
518 NS_LOG_FUNCTION(this);
519 return m_curHopLimit;
520}
521
522void
523Ipv6Interface::SetBaseReachableTime(uint16_t baseReachableTime)
524{
525 NS_LOG_FUNCTION(this << baseReachableTime);
526 m_baseReachableTime = baseReachableTime;
527}
528
529uint16_t
535
536void
537Ipv6Interface::SetReachableTime(uint16_t reachableTime)
538{
539 NS_LOG_FUNCTION(this << reachableTime);
540 m_reachableTime = reachableTime;
541}
542
543uint16_t
545{
546 NS_LOG_FUNCTION(this);
547 return m_reachableTime;
548}
549
550void
551Ipv6Interface::SetRetransTimer(uint16_t retransTimer)
552{
553 NS_LOG_FUNCTION(this << retransTimer);
554 m_retransTimer = retransTimer;
555}
556
557uint16_t
559{
560 NS_LOG_FUNCTION(this);
561 return m_retransTimer;
562}
563
564void
566{
567 NS_LOG_FUNCTION(this << address << state);
568
569 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
570 {
571 if (it->first.GetAddress() == address)
572 {
573 it->first.SetState(state);
574 return;
575 }
576 }
577 /* not found, maybe address has expired */
578}
579
580void
582{
583 NS_LOG_FUNCTION(this << address << uid);
584
585 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
586 {
587 if (it->first.GetAddress() == address)
588 {
589 it->first.SetNsDadUid(uid);
590 return;
591 }
592 }
593 /* not found, maybe address has expired */
594}
595
598{
599 NS_LOG_FUNCTION(this);
600 return m_ndCache;
601}
602
603void
605 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> removeAddressCallback)
606{
607 NS_LOG_FUNCTION(this << &removeAddressCallback);
608 m_removeAddressCallback = removeAddressCallback;
609}
610
611void
613 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback)
614{
615 NS_LOG_FUNCTION(this << &addAddressCallback);
616 m_addAddressCallback = addAddressCallback;
617}
618
619} /* 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.
ns3::TracedCallback< bool, int32_t > m_interfaceStatus
The trace fired when the interface state changes.
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 constexpr 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:561
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:595
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:49
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:1345
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
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