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
180 m_ifup = true;
181
182 Ptr<Ipv6> ip = m_node->GetObject<Ipv6>();
183 NS_ASSERT_MSG(ip, "IPv6 not installed on node.");
184 auto ifIndex = ip->GetInterfaceForDevice(m_device);
185 m_interfaceStatus(m_ifup, ifIndex);
186}
187
188void
190{
191 NS_LOG_FUNCTION(this);
192 m_ifup = false;
193 m_addresses.clear();
194 m_ndCache->Flush();
195
196 Ptr<Ipv6> ip = m_node->GetObject<Ipv6>();
197 NS_ASSERT_MSG(ip, "IPv6 not installed on node.");
198 auto ifIndex = ip->GetInterfaceForDevice(m_device);
199 m_interfaceStatus(m_ifup, ifIndex);
200}
201
202bool
204{
205 NS_LOG_FUNCTION(this);
206 return m_forwarding;
207}
208
209void
211{
212 NS_LOG_FUNCTION(this << forwarding);
213 m_forwarding = forwarding;
214}
215
216bool
218{
219 NS_LOG_FUNCTION(this << iface);
220 Ipv6Address addr = iface.GetAddress();
221
222 /* DAD handling */
223 if (!addr.IsAny())
224 {
225 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
226 {
227 if (it->first.GetAddress() == addr)
228 {
229 return false;
230 }
231 }
232
234 m_addresses.emplace_back(iface, solicited);
235 if (!m_addAddressCallback.IsNull())
236 {
237 m_addAddressCallback(this, addr);
238 }
239
240 if (!addr.IsAny() || !addr.IsLocalhost())
241 {
242 /* DAD handling */
243
244 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
247 interfaceId));
248
249 if (icmpv6)
250 {
251 if (icmpv6->IsAlwaysDad())
252 {
253 Simulator::Schedule(Seconds(0.), &Icmpv6L4Protocol::DoDAD, icmpv6, addr, this);
254 Simulator::Schedule(icmpv6->GetDadTimeout(),
256 icmpv6,
257 this,
258 addr);
259 }
260 else
261 {
264 icmpv6,
265 this,
266 addr);
267 }
268 }
269 }
270 return true;
271 }
272
273 /* bad address */
274 return false;
275}
276
279{
280 /* IPv6 interface has always at least one IPv6 link-local address */
281 NS_LOG_FUNCTION(this);
282
283 return m_linkLocalAddress;
284}
285
286bool
288{
289 /* IPv6 interface has always at least one IPv6 Solicited Multicast address */
290 NS_LOG_FUNCTION(this << address);
291
292 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
293 {
294 if (it->second == address)
295 {
296 return true;
297 }
298 }
299
300 return false;
301}
302
305{
306 NS_LOG_FUNCTION(this << index);
307 uint32_t i = 0;
308
309 if (m_addresses.size() > index)
310 {
311 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
312 {
313 if (i == index)
314 {
315 return it->first;
316 }
317 i++;
318 }
319 }
320 else
321 {
322 NS_FATAL_ERROR("index " << index << " out of bounds");
323 }
325 return addr; /* quiet compiler */
326}
327
330{
331 NS_LOG_FUNCTION(this);
332 return m_addresses.size();
333}
334
337{
338 NS_LOG_FUNCTION(this << index);
339 uint32_t i = 0;
340
341 if (m_addresses.size() < index)
342 {
343 NS_FATAL_ERROR("Removing index that does not exist in Ipv6Interface::RemoveAddress");
344 }
345
346 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
347 {
348 if (i == index)
349 {
350 Ipv6InterfaceAddress iface = it->first;
351 m_addresses.erase(it);
352 if (!m_removeAddressCallback.IsNull())
353 {
354 m_removeAddressCallback(this, iface);
355 }
356 return iface;
357 }
358
359 i++;
360 }
361 NS_FATAL_ERROR("Address " << index << " not found");
363 return addr; /* quiet compiler */
364}
365
368{
369 NS_LOG_FUNCTION(this << address);
370
371 if (address == Ipv6Address::GetLoopback())
372 {
373 NS_LOG_WARN("Cannot remove loopback address.");
374 return Ipv6InterfaceAddress();
375 }
376
377 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
378 {
379 if (it->first.GetAddress() == address)
380 {
381 Ipv6InterfaceAddress iface = it->first;
382 m_addresses.erase(it);
383 if (!m_removeAddressCallback.IsNull())
384 {
385 m_removeAddressCallback(this, iface);
386 }
387 return iface;
388 }
389 }
390 return Ipv6InterfaceAddress();
391}
392
395{
396 NS_LOG_FUNCTION(this << dst);
397
398 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
399 {
400 Ipv6InterfaceAddress ifaddr = it->first;
401
402 if (ifaddr.GetPrefix().IsMatch(ifaddr.GetAddress(), dst))
403 {
404 return ifaddr;
405 }
406 }
407
408 /* NS_ASSERT_MSG (false, "Not matching address."); */
410 return ret; /* quiet compiler */
411}
412
413void
415{
416 NS_LOG_FUNCTION(this << p << dest);
417
418 if (!IsUp())
419 {
420 return;
421 }
422
423 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
424
425 /* check if destination is localhost (::1), if yes we don't pass through
426 * traffic control layer */
428 {
429 /** @todo additional checks needed here (such as whether multicast
430 * goes to loopback)?
431 */
432 p->AddHeader(hdr);
433 m_device->Send(p, m_device->GetBroadcast(), Ipv6L3Protocol::PROT_NUMBER);
434 return;
435 }
436
438
439 /* check if destination is for one of our interface */
440 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
441 {
442 if (dest == it->first.GetAddress())
443 {
444 p->AddHeader(hdr);
446 m_tc,
447 m_device,
448 p,
450 m_device->GetBroadcast(),
451 m_device->GetBroadcast(),
453 return;
454 }
455 }
456
457 /* other address */
458 if (m_device->NeedsArp())
459 {
460 NS_LOG_LOGIC("Needs NDISC " << dest);
461
462 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
465 interfaceId));
466
467 Address hardwareDestination;
468 bool found = false;
469
470 NS_ASSERT(icmpv6);
471
472 if (dest.IsMulticast())
473 {
474 NS_LOG_LOGIC("IsMulticast");
476 m_device->IsMulticast(),
477 "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
478
479 hardwareDestination = m_device->GetMulticast(dest);
480 found = true;
481 }
482 else
483 {
484 NS_LOG_LOGIC("NDISC Lookup");
485 found = icmpv6->Lookup(p, hdr, dest, GetDevice(), m_ndCache, &hardwareDestination);
486 }
487
488 if (found)
489 {
490 NS_LOG_LOGIC("Address Resolved. Send.");
491 m_tc->Send(m_device,
493 hardwareDestination,
495 hdr));
496 }
497 }
498 else
499 {
500 NS_LOG_LOGIC("Doesn't need NDISC");
501 m_tc->Send(m_device,
503 m_device->GetBroadcast(),
505 hdr));
506 }
507}
508
509void
511{
512 NS_LOG_FUNCTION(this << curHopLimit);
513 m_curHopLimit = curHopLimit;
514}
515
516uint8_t
518{
519 NS_LOG_FUNCTION(this);
520 return m_curHopLimit;
521}
522
523void
524Ipv6Interface::SetBaseReachableTime(uint16_t baseReachableTime)
525{
526 NS_LOG_FUNCTION(this << baseReachableTime);
527 m_baseReachableTime = baseReachableTime;
528}
529
530uint16_t
536
537void
538Ipv6Interface::SetReachableTime(uint16_t reachableTime)
539{
540 NS_LOG_FUNCTION(this << reachableTime);
541 m_reachableTime = reachableTime;
542}
543
544uint16_t
546{
547 NS_LOG_FUNCTION(this);
548 return m_reachableTime;
549}
550
551void
552Ipv6Interface::SetRetransTimer(uint16_t retransTimer)
553{
554 NS_LOG_FUNCTION(this << retransTimer);
555 m_retransTimer = retransTimer;
556}
557
558uint16_t
560{
561 NS_LOG_FUNCTION(this);
562 return m_retransTimer;
563}
564
565void
567{
568 NS_LOG_FUNCTION(this << address << state);
569
570 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
571 {
572 if (it->first.GetAddress() == address)
573 {
574 it->first.SetState(state);
575 return;
576 }
577 }
578 /* not found, maybe address has expired */
579}
580
581void
583{
584 NS_LOG_FUNCTION(this << address << uid);
585
586 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
587 {
588 if (it->first.GetAddress() == address)
589 {
590 it->first.SetNsDadUid(uid);
591 return;
592 }
593 }
594 /* not found, maybe address has expired */
595}
596
599{
600 NS_LOG_FUNCTION(this);
601 return m_ndCache;
602}
603
604void
606 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> removeAddressCallback)
607{
608 NS_LOG_FUNCTION(this << &removeAddressCallback);
609 m_removeAddressCallback = removeAddressCallback;
610}
611
612void
614 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback)
615{
616 NS_LOG_FUNCTION(this << &addAddressCallback);
617 m_addAddressCallback = addAddressCallback;
618}
619
620} /* namespace ns3 */
a polymophic address class
Definition address.h:114
Callback template class.
Definition callback.h:428
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()
Caller graph was not generated because of its size.
Definition object.cc:93
virtual void DoDispose()
Destructor implementation.
Definition object.cc:430
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:614
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:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
#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:194
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#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:253
#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:454
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
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:605