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 * 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"
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
37namespace ns3
38{
39
40NS_LOG_COMPONENT_DEFINE("Ipv6Interface");
41
42NS_OBJECT_ENSURE_REGISTERED(Ipv6Interface);
43
44TypeId
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
71void
73{
74 NS_LOG_FUNCTION(this);
75 m_node = nullptr;
76 m_device = nullptr;
77 m_tc = nullptr;
78 m_ndCache = nullptr;
80}
81
82void
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();
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
117void
119{
120 NS_LOG_FUNCTION(this << node);
121 m_node = node;
122}
123
124void
126{
127 NS_LOG_FUNCTION(this << device);
128 m_device = device;
129}
130
131void
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
145void
147{
148 NS_LOG_FUNCTION(this << metric);
149 m_metric = metric;
150}
151
152uint16_t
154{
155 NS_LOG_FUNCTION(this);
156 return m_metric;
157}
158
159bool
161{
162 NS_LOG_FUNCTION(this);
163 return m_ifup;
164}
165
166bool
168{
169 NS_LOG_FUNCTION(this);
170 return !m_ifup;
171}
172
173void
175{
176 NS_LOG_FUNCTION(this);
177
178 if (m_ifup)
179 {
180 return;
181 }
182 DoSetup();
183 m_ifup = true;
184}
185
186void
188{
189 NS_LOG_FUNCTION(this);
190 m_ifup = false;
191 m_addresses.clear();
192 m_ndCache->Flush();
193}
194
195bool
197{
198 NS_LOG_FUNCTION(this);
199 return m_forwarding;
200}
201
202void
204{
205 NS_LOG_FUNCTION(this << forwarding);
206 m_forwarding = forwarding;
207}
208
209bool
211{
212 NS_LOG_FUNCTION(this << iface);
213 Ipv6Address addr = iface.GetAddress();
214
215 /* DAD handling */
216 if (!addr.IsAny())
217 {
218 for (Ipv6InterfaceAddressListCI 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
279bool
281{
282 /* IPv6 interface has always at least one IPv6 Solicited Multicast address */
283 NS_LOG_FUNCTION(this << address);
284
285 for (Ipv6InterfaceAddressListCI 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
298{
299 NS_LOG_FUNCTION(this << index);
300 uint32_t i = 0;
301
302 if (m_addresses.size() > index)
303 {
304 for (Ipv6InterfaceAddressListCI 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
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 (Ipv6InterfaceAddressListI 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
364 if (address == Ipv6Address::GetLoopback())
365 {
366 NS_LOG_WARN("Cannot remove loopback address.");
367 return Ipv6InterfaceAddress();
368 }
369
370 for (Ipv6InterfaceAddressListI 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 (Ipv6InterfaceAddressList::const_iterator it = m_addresses.begin(); it != m_addresses.end();
392 ++it)
393 {
394 Ipv6InterfaceAddress ifaddr = it->first;
395
396 if (ifaddr.GetPrefix().IsMatch(ifaddr.GetAddress(), dst))
397 {
398 return ifaddr;
399 }
400 }
401
402 /* NS_ASSERT_MSG (false, "Not matching address."); */
404 return ret; /* quiet compiler */
405}
406
407void
409{
410 NS_LOG_FUNCTION(this << p << dest);
411
412 if (!IsUp())
413 {
414 return;
415 }
416
418
419 /* check if destination is localhost (::1), if yes we don't pass through
420 * traffic control layer */
421 if (DynamicCast<LoopbackNetDevice>(m_device))
422 {
426 p->AddHeader(hdr);
427 m_device->Send(p, m_device->GetBroadcast(), Ipv6L3Protocol::PROT_NUMBER);
428 return;
429 }
430
432
433 /* check if destination is for one of our interface */
434 for (Ipv6InterfaceAddressListCI it = m_addresses.begin(); it != m_addresses.end(); ++it)
435 {
436 if (dest == it->first.GetAddress())
437 {
438 p->AddHeader(hdr);
439 m_tc->Receive(m_device,
440 p,
442 m_device->GetBroadcast(),
443 m_device->GetBroadcast(),
445 return;
446 }
447 }
448
449 /* other address */
450 if (m_device->NeedsArp())
451 {
452 NS_LOG_LOGIC("Needs NDISC " << dest);
453
454 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
455 Ptr<Icmpv6L4Protocol> icmpv6 = DynamicCast<Icmpv6L4Protocol>(
457 interfaceId));
458
459 Address hardwareDestination;
460 bool found = false;
461
462 NS_ASSERT(icmpv6);
463
464 if (dest.IsMulticast())
465 {
466 NS_LOG_LOGIC("IsMulticast");
468 m_device->IsMulticast(),
469 "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
470
471 hardwareDestination = m_device->GetMulticast(dest);
472 found = true;
473 }
474 else
475 {
476 NS_LOG_LOGIC("NDISC Lookup");
477 found = icmpv6->Lookup(p, hdr, dest, GetDevice(), m_ndCache, &hardwareDestination);
478 }
479
480 if (found)
481 {
482 NS_LOG_LOGIC("Address Resolved. Send.");
483 m_tc->Send(m_device,
484 Create<Ipv6QueueDiscItem>(p,
485 hardwareDestination,
487 hdr));
488 }
489 }
490 else
491 {
492 NS_LOG_LOGIC("Doesn't need NDISC");
493 m_tc->Send(m_device,
494 Create<Ipv6QueueDiscItem>(p,
495 m_device->GetBroadcast(),
497 hdr));
498 }
499}
500
501void
503{
504 NS_LOG_FUNCTION(this << curHopLimit);
505 m_curHopLimit = curHopLimit;
506}
507
508uint8_t
510{
511 NS_LOG_FUNCTION(this);
512 return m_curHopLimit;
513}
514
515void
516Ipv6Interface::SetBaseReachableTime(uint16_t baseReachableTime)
517{
518 NS_LOG_FUNCTION(this << baseReachableTime);
519 m_baseReachableTime = baseReachableTime;
520}
521
522uint16_t
524{
525 NS_LOG_FUNCTION(this);
526 return m_baseReachableTime;
527}
528
529void
530Ipv6Interface::SetReachableTime(uint16_t reachableTime)
531{
532 NS_LOG_FUNCTION(this << reachableTime);
533 m_reachableTime = reachableTime;
534}
535
536uint16_t
538{
539 NS_LOG_FUNCTION(this);
540 return m_reachableTime;
541}
542
543void
544Ipv6Interface::SetRetransTimer(uint16_t retransTimer)
545{
546 NS_LOG_FUNCTION(this << retransTimer);
547 m_retransTimer = retransTimer;
548}
549
550uint16_t
552{
553 NS_LOG_FUNCTION(this);
554 return m_retransTimer;
555}
556
557void
559{
560 NS_LOG_FUNCTION(this << address << state);
561
562 for (Ipv6InterfaceAddressListI it = m_addresses.begin(); it != m_addresses.end(); ++it)
563 {
564 if (it->first.GetAddress() == address)
565 {
566 it->first.SetState(state);
567 return;
568 }
569 }
570 /* not found, maybe address has expired */
571}
572
573void
575{
576 NS_LOG_FUNCTION(this << address << uid);
577
578 for (Ipv6InterfaceAddressListI it = m_addresses.begin(); it != m_addresses.end(); ++it)
579 {
580 if (it->first.GetAddress() == address)
581 {
582 it->first.SetNsDadUid(uid);
583 return;
584 }
585 }
586 /* not found, maybe address has expired */
587}
588
591{
592 NS_LOG_FUNCTION(this);
593 return m_ndCache;
594}
595
596void
598 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> removeAddressCallback)
599{
600 NS_LOG_FUNCTION(this << &removeAddressCallback);
601 m_removeAddressCallback = removeAddressCallback;
602}
603
604void
606 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback)
607{
608 NS_LOG_FUNCTION(this << &addAddressCallback);
609 m_addAddressCallback = addAddressCallback;
610}
611
612} /* namespace ns3 */
a polymophic address class
Definition: address.h:100
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.
std::list< std::pair< Ipv6InterfaceAddress, Ipv6Address > >::iterator Ipv6InterfaceAddressListI
Container Iterator for the Ipv6InterfaceAddresses.
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.
std::list< std::pair< Ipv6InterfaceAddress, Ipv6Address > >::const_iterator Ipv6InterfaceAddressListCI
Const Container Iterator for the Ipv6InterfaceAddresses.
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:353
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
#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:1336
Every class exported by the ns3 library is enclosed in the ns3 namespace.