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
32
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),
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
181 Ptr<Ipv6> ip = m_node->GetObject<Ipv6>();
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
195 Ptr<Ipv6> ip = m_node->GetObject<Ipv6>();
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
422 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
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:111
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.
The IPv6 representation of a network 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
Check whether two addresses have the same bits in the prefix portion of their addresses.
@ PACKET_HOST
Packet addressed to us.
Definition net-device.h:290
Object()
Constructor.
Definition object.cc:96
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
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:439
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
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:585