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 (auto 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 (auto 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 (auto 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 (auto 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 (auto 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 (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
392 {
393 Ipv6InterfaceAddress ifaddr = it->first;
394
395 if (ifaddr.GetPrefix().IsMatch(ifaddr.GetAddress(), dst))
396 {
397 return ifaddr;
398 }
399 }
400
401 /* NS_ASSERT_MSG (false, "Not matching address."); */
403 return ret; /* quiet compiler */
404}
405
406void
408{
409 NS_LOG_FUNCTION(this << p << dest);
410
411 if (!IsUp())
412 {
413 return;
414 }
415
417
418 /* check if destination is localhost (::1), if yes we don't pass through
419 * traffic control layer */
420 if (DynamicCast<LoopbackNetDevice>(m_device))
421 {
425 p->AddHeader(hdr);
426 m_device->Send(p, m_device->GetBroadcast(), Ipv6L3Protocol::PROT_NUMBER);
427 return;
428 }
429
431
432 /* check if destination is for one of our interface */
433 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
434 {
435 if (dest == it->first.GetAddress())
436 {
437 p->AddHeader(hdr);
439 m_tc,
440 m_device,
441 p,
443 m_device->GetBroadcast(),
444 m_device->GetBroadcast(),
446 return;
447 }
448 }
449
450 /* other address */
451 if (m_device->NeedsArp())
452 {
453 NS_LOG_LOGIC("Needs NDISC " << dest);
454
455 int32_t interfaceId = m_node->GetObject<Ipv6>()->GetInterfaceForDevice(m_device);
456 Ptr<Icmpv6L4Protocol> icmpv6 = DynamicCast<Icmpv6L4Protocol>(
458 interfaceId));
459
460 Address hardwareDestination;
461 bool found = false;
462
463 NS_ASSERT(icmpv6);
464
465 if (dest.IsMulticast())
466 {
467 NS_LOG_LOGIC("IsMulticast");
469 m_device->IsMulticast(),
470 "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
471
472 hardwareDestination = m_device->GetMulticast(dest);
473 found = true;
474 }
475 else
476 {
477 NS_LOG_LOGIC("NDISC Lookup");
478 found = icmpv6->Lookup(p, hdr, dest, GetDevice(), m_ndCache, &hardwareDestination);
479 }
480
481 if (found)
482 {
483 NS_LOG_LOGIC("Address Resolved. Send.");
484 m_tc->Send(m_device,
485 Create<Ipv6QueueDiscItem>(p,
486 hardwareDestination,
488 hdr));
489 }
490 }
491 else
492 {
493 NS_LOG_LOGIC("Doesn't need NDISC");
494 m_tc->Send(m_device,
495 Create<Ipv6QueueDiscItem>(p,
496 m_device->GetBroadcast(),
498 hdr));
499 }
500}
501
502void
504{
505 NS_LOG_FUNCTION(this << curHopLimit);
506 m_curHopLimit = curHopLimit;
507}
508
509uint8_t
511{
512 NS_LOG_FUNCTION(this);
513 return m_curHopLimit;
514}
515
516void
517Ipv6Interface::SetBaseReachableTime(uint16_t baseReachableTime)
518{
519 NS_LOG_FUNCTION(this << baseReachableTime);
520 m_baseReachableTime = baseReachableTime;
521}
522
523uint16_t
525{
526 NS_LOG_FUNCTION(this);
527 return m_baseReachableTime;
528}
529
530void
531Ipv6Interface::SetReachableTime(uint16_t reachableTime)
532{
533 NS_LOG_FUNCTION(this << reachableTime);
534 m_reachableTime = reachableTime;
535}
536
537uint16_t
539{
540 NS_LOG_FUNCTION(this);
541 return m_reachableTime;
542}
543
544void
545Ipv6Interface::SetRetransTimer(uint16_t retransTimer)
546{
547 NS_LOG_FUNCTION(this << retransTimer);
548 m_retransTimer = retransTimer;
549}
550
551uint16_t
553{
554 NS_LOG_FUNCTION(this);
555 return m_retransTimer;
556}
557
558void
560{
561 NS_LOG_FUNCTION(this << address << state);
562
563 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
564 {
565 if (it->first.GetAddress() == address)
566 {
567 it->first.SetState(state);
568 return;
569 }
570 }
571 /* not found, maybe address has expired */
572}
573
574void
576{
577 NS_LOG_FUNCTION(this << address << uid);
578
579 for (auto it = m_addresses.begin(); it != m_addresses.end(); ++it)
580 {
581 if (it->first.GetAddress() == address)
582 {
583 it->first.SetNsDadUid(uid);
584 return;
585 }
586 }
587 /* not found, maybe address has expired */
588}
589
592{
593 NS_LOG_FUNCTION(this);
594 return m_ndCache;
595}
596
597void
599 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> removeAddressCallback)
600{
601 NS_LOG_FUNCTION(this << &removeAddressCallback);
602 m_removeAddressCallback = removeAddressCallback;
603}
604
605void
607 Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback)
608{
609 NS_LOG_FUNCTION(this << &addAddressCallback);
610 m_addAddressCallback = addAddressCallback;
611}
612
613} /* namespace ns3 */
a polymophic address class
Definition: address.h:101
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.
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.
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:522
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:444
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
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:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
#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:1326
Every class exported by the ns3 library is enclosed in the ns3 namespace.