A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv6-l3-protocol.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-l3-protocol.h"
10
11#include "icmpv6-l4-protocol.h"
14#include "ipv6-extension.h"
15#include "ipv6-interface.h"
16#include "ipv6-option-demux.h"
17#include "ipv6-option.h"
20#include "ipv6-route.h"
22#include "loopback-net-device.h"
23#include "ndisc-cache.h"
24
25#include "ns3/boolean.h"
26#include "ns3/callback.h"
27#include "ns3/log.h"
28#include "ns3/mac16-address.h"
29#include "ns3/mac64-address.h"
30#include "ns3/node.h"
31#include "ns3/object-vector.h"
32#include "ns3/trace-source-accessor.h"
33#include "ns3/traffic-control-layer.h"
34#include "ns3/uinteger.h"
35#include "ns3/vector.h"
36
37/// Minimum IPv6 MTU, as defined by \RFC{2460}
38#define IPV6_MIN_MTU 1280
39
40namespace ns3
41{
42
43NS_LOG_COMPONENT_DEFINE("Ipv6L3Protocol");
44
45NS_OBJECT_ENSURE_REGISTERED(Ipv6L3Protocol);
46
47const uint16_t Ipv6L3Protocol::PROT_NUMBER = 0x86DD;
48
49TypeId
51{
52 static TypeId tid =
53 TypeId("ns3::Ipv6L3Protocol")
54 .SetParent<Ipv6>()
55 .SetGroupName("Internet")
56 .AddConstructor<Ipv6L3Protocol>()
57 .AddAttribute("DefaultTtl",
58 "The TTL value set by default on all "
59 "outgoing packets generated on this node.",
60 UintegerValue(64),
63 .AddAttribute("DefaultTclass",
64 "The TCLASS value set by default on all "
65 "outgoing packets generated on this node.",
69 .AddAttribute("InterfaceList",
70 "The set of IPv6 interfaces associated to this IPv6 stack.",
74 .AddAttribute("SendIcmpv6Redirect",
75 "Send the ICMPv6 Redirect when appropriate.",
76 BooleanValue(true),
80 .AddTraceSource("Tx",
81 "Send IPv6 packet to outgoing interface.",
83 "ns3::Ipv6L3Protocol::TxRxTracedCallback")
84 .AddTraceSource("Rx",
85 "Receive IPv6 packet from incoming interface.",
87 "ns3::Ipv6L3Protocol::TxRxTracedCallback")
88 .AddTraceSource("Drop",
89 "Drop IPv6 packet",
91 "ns3::Ipv6L3Protocol::DropTracedCallback")
92
93 .AddTraceSource("SendOutgoing",
94 "A newly-generated packet by this node is "
95 "about to be queued for transmission",
97 "ns3::Ipv6L3Protocol::SentTracedCallback")
98 .AddTraceSource("UnicastForward",
99 "A unicast IPv6 packet was received by this node "
100 "and is being forwarded to another node",
102 "ns3::Ipv6L3Protocol::SentTracedCallback")
103 .AddTraceSource("LocalDeliver",
104 "An IPv6 packet was received by/for this node, "
105 "and it is being forward up the stack",
107 "ns3::Ipv6L3Protocol::SentTracedCallback");
108 return tid;
109}
110
124
129
130void
132{
133 NS_LOG_FUNCTION(this);
134
135 /* clear protocol and interface list */
136 for (auto it = m_protocols.begin(); it != m_protocols.end(); ++it)
137 {
138 it->second = nullptr;
139 }
140 m_protocols.clear();
141
142 /* remove interfaces */
143 for (auto it = m_interfaces.begin(); it != m_interfaces.end(); ++it)
144 {
145 *it = nullptr;
146 }
147 m_interfaces.clear();
149
150 /* remove raw sockets */
151 for (auto it = m_sockets.begin(); it != m_sockets.end(); ++it)
152 {
153 *it = nullptr;
154 }
155 m_sockets.clear();
156
157 /* remove list of prefix */
158 for (auto it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
159 {
160 (*it)->StopValidTimer();
161 (*it)->StopPreferredTimer();
162 (*it) = nullptr;
163 }
164 m_prefixes.clear();
165
166 m_node = nullptr;
167 m_routingProtocol = nullptr;
168 m_pmtuCache = nullptr;
170}
171
172void
174{
175 NS_LOG_FUNCTION(this << routingProtocol);
176 m_routingProtocol = routingProtocol;
177 m_routingProtocol->SetIpv6(this);
178}
179
185
188{
189 NS_LOG_FUNCTION(this << device);
191
193
194 NS_ASSERT(tc);
195
198 device);
199
200 tc->RegisterProtocolHandler(MakeCallback(&Ipv6L3Protocol::Receive, this),
202 device);
203
204 interface->SetNode(m_node);
205 interface->SetDevice(device);
206 interface->SetTrafficControl(tc);
207 interface->SetForwarding(m_ipForward);
208 return AddIpv6Interface(interface);
209}
210
213{
214 NS_LOG_FUNCTION(this << interface);
215 uint32_t index = m_nInterfaces;
216
217 m_interfaces.push_back(interface);
218 m_reverseInterfacesContainer[interface->GetDevice()] = index;
220 return index;
221}
222
225{
226 if (index < m_interfaces.size())
227 {
228 return m_interfaces[index];
229 }
230 return nullptr;
231}
232
235{
236 return m_nInterfaces;
237}
238
241{
242 int32_t index = 0;
243
244 for (auto it = m_interfaces.begin(); it != m_interfaces.end(); it++)
245 {
246 uint32_t j = 0;
247 uint32_t max = (*it)->GetNAddresses();
248
249 for (j = 0; j < max; j++)
250 {
251 if ((*it)->GetAddress(j).GetAddress() == address)
252 {
253 return index;
254 }
255 }
256 index++;
257 }
258 return -1;
259}
260
263{
264 int32_t index = 0;
265
266 for (auto it = m_interfaces.begin(); it != m_interfaces.end(); it++)
267 {
268 uint32_t j = 0;
269 for (j = 0; j < (*it)->GetNAddresses(); j++)
270 {
271 if ((*it)->GetAddress(j).GetAddress().CombinePrefix(mask) ==
272 address.CombinePrefix(mask))
273 {
274 return index;
275 }
276 }
277 index++;
278 }
279 return -1;
280}
281
287
290{
291 auto iter = m_reverseInterfacesContainer.find(device);
292 if (iter != m_reverseInterfacesContainer.end())
293 {
294 return (*iter).second;
295 }
296
297 return -1;
298}
299
300void
302 Ipv6Address network,
303 Ipv6Prefix mask,
304 uint8_t flags,
305 uint32_t validTime,
306 uint32_t preferredTime,
307 Ipv6Address defaultRouter)
308{
309 NS_LOG_FUNCTION(this << interface << network << mask << (uint32_t)flags << validTime
310 << preferredTime);
311 Ipv6InterfaceAddress address;
312
313 Address addr = GetInterface(interface)->GetDevice()->GetAddress();
314
315 if (!defaultRouter.IsAny())
316 {
317 GetRoutingProtocol()->NotifyAddRoute(Ipv6Address::GetAny(),
318 Ipv6Prefix((uint8_t)0),
319 defaultRouter,
320 interface,
321 network);
322 }
323
324 bool onLink = false;
326 {
327 onLink = true;
328 }
329
330 if (flags & Icmpv6OptionPrefixInformation::AUTADDRCONF) /* auto flag */
331 {
332 address = Ipv6Address::MakeAutoconfiguredAddress(addr, network);
333 address.SetOnLink(onLink);
334
335 /* see if we have already the prefix */
336 for (auto it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
337 {
338 if ((*it)->GetInterface() == interface && (*it)->GetPrefix() == network &&
339 (*it)->GetMask() == mask)
340 {
341 (*it)->StopPreferredTimer();
342 (*it)->StopValidTimer();
343 (*it)->StartPreferredTimer();
344 return;
345 }
346 }
347
348 /* no prefix found, add autoconfigured address and the prefix */
349 NS_LOG_INFO("Autoconfigured address is :" << address.GetAddress());
350 AddAddress(interface, address, onLink);
351
354 interface,
355 network,
356 mask,
357 preferredTime,
358 validTime,
359 defaultRouter);
360 aPrefix->StartPreferredTimer();
361
362 m_prefixes.push_back(aPrefix);
363 }
364
365 if (onLink) /* on-link flag */
366 {
367 /* add default router
368 * if a previous default route exists, the new ones is simply added
369 */
370 m_routingProtocol->NotifyAddRoute(network, mask, Ipv6Address::GetAny(), interface);
371 }
372}
373
374void
376 Ipv6Address network,
377 Ipv6Prefix mask,
378 Ipv6Address defaultRouter)
379{
380 NS_LOG_FUNCTION(this << interface << network << mask);
381 Ptr<Ipv6Interface> iface = GetInterface(interface);
382 Address addr = iface->GetDevice()->GetAddress();
383
384 Ipv6Address addressToFind = Ipv6Address::MakeAutoconfiguredAddress(addr, network);
385
386 for (uint32_t i = 0; i < iface->GetNAddresses(); i++)
387 {
388 if (iface->GetAddress(i).GetAddress() == addressToFind)
389 {
390 RemoveAddress(interface, i);
391 break;
392 }
393 }
394
395 /* remove from list of autoconfigured address */
396 for (auto it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
397 {
398 if ((*it)->GetInterface() == interface && (*it)->GetPrefix() == network &&
399 (*it)->GetMask() == mask)
400 {
401 *it = nullptr;
402 m_prefixes.erase(it);
403 break;
404 }
405 }
406
407 GetRoutingProtocol()->NotifyRemoveRoute(Ipv6Address::GetAny(),
408 Ipv6Prefix((uint8_t)0),
409 defaultRouter,
410 interface,
411 network);
412}
413
414bool
416{
417 NS_LOG_FUNCTION(this << i << address);
418 Ptr<Ipv6Interface> interface = GetInterface(i);
419 address.SetOnLink(addOnLinkRoute);
420 bool ret = interface->AddAddress(address);
421
422 if (m_routingProtocol)
423 {
424 m_routingProtocol->NotifyAddAddress(i, address);
425 }
426
427 if (addOnLinkRoute)
428 {
429 Ipv6Address networkAddress = address.GetAddress().CombinePrefix(address.GetPrefix());
430 Ipv6Prefix networkMask = address.GetPrefix();
431 GetRoutingProtocol()->NotifyAddRoute(networkAddress,
432 networkMask,
433 Ipv6Address::GetZero(),
434 i);
435 }
436 return ret;
437}
438
441{
442 Ptr<Ipv6Interface> interface = GetInterface(i);
443 return interface->GetNAddresses();
444}
445
448{
449 Ptr<Ipv6Interface> interface = GetInterface(i);
450 return interface->GetAddress(addressIndex);
451}
452
453bool
455{
456 NS_LOG_FUNCTION(this << i << addressIndex);
457 Ptr<Ipv6Interface> interface = GetInterface(i);
458 Ipv6InterfaceAddress address = interface->RemoveAddress(addressIndex);
459
460 if (address != Ipv6InterfaceAddress())
461 {
462 if (m_routingProtocol)
463 {
464 m_routingProtocol->NotifyRemoveAddress(i, address);
465 }
466 return true;
467 }
468 return false;
469}
470
471bool
473{
474 NS_LOG_FUNCTION(this << i << address);
475
476 if (address == Ipv6Address::GetLoopback())
477 {
478 NS_LOG_WARN("Cannot remove loopback address.");
479 return false;
480 }
481 Ptr<Ipv6Interface> interface = GetInterface(i);
482 Ipv6InterfaceAddress ifAddr = interface->RemoveAddress(address);
483 if (ifAddr != Ipv6InterfaceAddress())
484 {
485 if (m_routingProtocol)
486 {
487 m_routingProtocol->NotifyRemoveAddress(i, ifAddr);
488 }
489 return true;
490 }
491 return false;
492}
493
494void
496{
497 NS_LOG_FUNCTION(this << i << metric);
498 Ptr<Ipv6Interface> interface = GetInterface(i);
499 interface->SetMetric(metric);
500}
501
502uint16_t
504{
505 Ptr<Ipv6Interface> interface = GetInterface(i);
506 return interface->GetMetric();
507}
508
509uint16_t
511{
512 // RFC 1981, if PMTU is disabled, return the minimum MTU
513 if (!m_mtuDiscover)
514 {
515 return IPV6_MIN_MTU;
516 }
517
518 Ptr<Ipv6Interface> interface = GetInterface(i);
519 return interface->GetDevice()->GetMtu();
520}
521
522void
524{
525 NS_LOG_FUNCTION(this << dst << int(pmtu));
526 m_pmtuCache->SetPmtu(dst, pmtu);
527}
528
529bool
531{
532 Ptr<Ipv6Interface> interface = GetInterface(i);
533 return interface->IsUp();
534}
535
536void
538{
539 NS_LOG_FUNCTION(this << i);
540 Ptr<Ipv6Interface> interface = GetInterface(i);
541
542 // RFC 2460, Section 5, pg. 24:
543 // IPv6 requires that every link in the internet have an MTU of 1280
544 // octets or greater. On any link that cannot convey a 1280-octet
545 // packet in one piece, link-specific fragmentation and reassembly must
546 // be provided at a layer below IPv6.
547 if (interface->GetDevice()->GetMtu() >= 1280)
548 {
549 interface->SetUp();
550
551 if (m_routingProtocol)
552 {
553 m_routingProtocol->NotifyInterfaceUp(i);
554 }
555 }
556 else
557 {
558 NS_LOG_LOGIC("Interface " << int(i)
559 << " is set to be down for IPv6. Reason: not respecting minimum "
560 "IPv6 MTU (1280 octets)");
561 }
562}
563
564void
566{
567 NS_LOG_FUNCTION(this << i);
568 Ptr<Ipv6Interface> interface = GetInterface(i);
569
570 interface->SetDown();
571
572 if (m_routingProtocol)
573 {
574 m_routingProtocol->NotifyInterfaceDown(i);
575 }
576}
577
578void
580{
581 NS_LOG_FUNCTION(this);
583 Ptr<LoopbackNetDevice> device = nullptr;
584 uint32_t i = 0;
585
586 /* see if we have already an loopback NetDevice */
587 for (i = 0; i < m_node->GetNDevices(); i++)
588 {
590 {
591 break;
592 }
593 }
594
595 if (!device)
596 {
598 m_node->AddDevice(device);
599 }
600
601 interface->SetDevice(device);
602 interface->SetNode(m_node);
603 Ipv6InterfaceAddress ifaceAddr =
605 interface->AddAddress(ifaceAddr);
606 uint32_t index = AddIpv6Interface(interface);
607 Ptr<Node> node = GetObject<Node>();
608 node->RegisterProtocolHandler(MakeCallback(&Ipv6L3Protocol::Receive, this),
610 device);
611 interface->SetUp();
612
614 {
615 m_routingProtocol->NotifyInterfaceUp(index);
616 }
617}
618
619bool
621{
622 Ptr<Ipv6Interface> interface = GetInterface(i);
623
624 NS_LOG_LOGIC("Forwarding state: " << interface->IsForwarding());
625 return interface->IsForwarding();
626}
627
628void
630{
631 NS_LOG_FUNCTION(this << i << val);
632 Ptr<Ipv6Interface> interface = GetInterface(i);
633 interface->SetForwarding(val);
634}
635
638{
639 NS_LOG_FUNCTION(this << interface << dest);
640 Ipv6Address ret;
641
642 if (dest.IsLocalhost())
643 {
645 }
646
647 if (dest.IsLinkLocal() || dest.IsLinkLocalMulticast())
648 {
649 for (uint32_t i = 0; i < GetNAddresses(interface); i++)
650 {
651 Ipv6InterfaceAddress test = GetAddress(interface, i);
652 if (test.GetScope() == Ipv6InterfaceAddress::LINKLOCAL)
653 {
654 return test.GetAddress();
655 }
656 }
657 NS_ASSERT_MSG(false, "No link-local address found on interface " << interface);
658 }
659
660 for (uint32_t i = 0; i < GetNAddresses(interface); i++)
661 {
662 Ipv6InterfaceAddress test = GetAddress(interface, i);
663
664 if (test.GetScope() == Ipv6InterfaceAddress::GLOBAL)
665 {
666 if (test.IsInSameSubnet(dest))
667 {
668 return test.GetAddress();
669 }
670 else
671 {
672 ret = test.GetAddress();
673 }
674 }
675 }
676
677 // no specific match found. Use a global address (any useful is fine).
678 NS_ASSERT_MSG(!ret.IsAny(),
679 "Could not find any address for " << dest << " on interface " << interface);
680 return ret;
681}
682
683void
685{
686 NS_LOG_FUNCTION(this << forward);
687 m_ipForward = forward;
688
689 for (auto it = m_interfaces.begin(); it != m_interfaces.end(); it++)
690 {
691 (*it)->SetForwarding(forward);
692 }
693}
694
695bool
697{
698 return m_ipForward;
699}
700
701void
703{
704 NS_LOG_FUNCTION(this << int(mtuDiscover));
705 m_mtuDiscover = mtuDiscover;
706}
707
708bool
710{
711 return m_mtuDiscover;
712}
713
714void
716{
717 NS_LOG_FUNCTION(this << sendIcmpv6Redirect);
718 m_sendIcmpv6Redirect = sendIcmpv6Redirect;
719}
720
721bool
726
727void
729{
730 NS_LOG_FUNCTION(this);
731
732 if (!m_node)
733 {
734 Ptr<Node> node = this->GetObject<Node>();
735 // verify that it's a valid node and that
736 // the node has not been set before
737 if (node)
738 {
739 this->SetNode(node);
740 }
741 }
742
744}
745
746void
748{
749 NS_LOG_FUNCTION(this << node);
750 m_node = node;
751 /* add LoopbackNetDevice if needed, and an Ipv6Interface on top of it */
753}
754
755void
757{
758 NS_LOG_FUNCTION(this << protocol);
759 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), -1);
760 if (m_protocols.find(key) != m_protocols.end())
761 {
762 NS_LOG_WARN("Overwriting default protocol " << int(protocol->GetProtocolNumber()));
763 }
764 m_protocols[key] = protocol;
765}
766
767void
769{
770 NS_LOG_FUNCTION(this << protocol << interfaceIndex);
771
772 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), interfaceIndex);
773 if (m_protocols.find(key) != m_protocols.end())
774 {
775 NS_LOG_WARN("Overwriting protocol " << int(protocol->GetProtocolNumber())
776 << " on interface " << int(interfaceIndex));
777 }
778 m_protocols[key] = protocol;
779}
780
781void
783{
784 NS_LOG_FUNCTION(this << protocol);
785
786 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), -1);
787 auto iter = m_protocols.find(key);
788 if (iter == m_protocols.end())
789 {
790 NS_LOG_WARN("Trying to remove an non-existent default protocol "
791 << int(protocol->GetProtocolNumber()));
792 }
793 else
794 {
795 m_protocols.erase(key);
796 }
797}
798
799void
801{
802 NS_LOG_FUNCTION(this << protocol << interfaceIndex);
803
804 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), interfaceIndex);
805 auto iter = m_protocols.find(key);
806 if (iter == m_protocols.end())
807 {
808 NS_LOG_WARN("Trying to remove an non-existent protocol "
809 << int(protocol->GetProtocolNumber()) << " on interface "
810 << int(interfaceIndex));
811 }
812 else
813 {
814 m_protocols.erase(key);
815 }
816}
817
819Ipv6L3Protocol::GetProtocol(int protocolNumber) const
820{
821 return GetProtocol(protocolNumber, -1);
822}
823
825Ipv6L3Protocol::GetProtocol(int protocolNumber, int32_t interfaceIndex) const
826{
827 if (interfaceIndex >= 0)
828 {
829 // try the interface-specific protocol.
830 auto key = std::make_pair(protocolNumber, interfaceIndex);
831 auto i = m_protocols.find(key);
832 if (i != m_protocols.end())
833 {
834 return i->second;
835 }
836 }
837 // try the generic protocol.
838 auto key = std::make_pair(protocolNumber, -1);
839 auto i = m_protocols.find(key);
840 if (i != m_protocols.end())
841 {
842 return i->second;
843 }
844
845 return nullptr;
846}
847
850{
851 NS_LOG_FUNCTION(this);
853 sock->SetNode(m_node);
854 m_sockets.push_back(sock);
855 return sock;
856}
857
858void
860{
861 NS_LOG_FUNCTION(this << socket);
862
863 for (auto it = m_sockets.begin(); it != m_sockets.end(); ++it)
864 {
865 if ((*it) == socket)
866 {
867 m_sockets.erase(it);
868 return;
869 }
870 }
871}
872
875{
877
878 if (protocol)
879 {
880 return protocol->GetObject<Icmpv6L4Protocol>();
881 }
882 else
883 {
884 return nullptr;
885 }
886}
887
888void
890{
891 NS_LOG_FUNCTION(this << ttl);
892 m_defaultTtl = ttl;
893}
894
895void
897{
898 NS_LOG_FUNCTION(this << tclass);
899 m_defaultTclass = tclass;
900}
901
902void
904 Ipv6Address source,
905 Ipv6Address destination,
906 uint8_t protocol,
907 Ptr<Ipv6Route> route)
908{
909 NS_LOG_FUNCTION(this << packet << source << destination << (uint32_t)protocol << route);
910 Ipv6Header hdr;
911 uint8_t ttl = m_defaultTtl;
913 bool found = packet->RemovePacketTag(tag);
914
915 if (found)
916 {
917 ttl = tag.GetHopLimit();
918 }
919
920 SocketIpv6TclassTag tclassTag;
921 uint8_t tclass = m_defaultTclass;
922 found = packet->RemovePacketTag(tclassTag);
923
924 if (found)
925 {
926 tclass = tclassTag.GetTclass();
927 }
928
929 /* Handle 3 cases:
930 * 1) Packet is passed in with a route entry
931 * 2) Packet is passed in with a route entry but route->GetGateway is not set (e.g., same
932 * network) 3) route is NULL (e.g., a raw socket call or ICMPv6)
933 */
934
935 /* 1) */
936 if (route && route->GetGateway() != Ipv6Address::GetZero())
937 {
938 NS_LOG_LOGIC("Ipv6L3Protocol::Send case 1: passed in with a route");
939 hdr = BuildHeader(source, destination, protocol, packet->GetSize(), ttl, tclass);
940 int32_t interface = GetInterfaceForDevice(route->GetOutputDevice());
941 m_sendOutgoingTrace(hdr, packet, interface);
942 SendRealOut(route, packet, hdr);
943 return;
944 }
945
946 /* 2) */
947 if (route && route->GetGateway() == Ipv6Address::GetZero())
948 {
949 NS_LOG_LOGIC("Ipv6L3Protocol::Send case 2: probably sent to machine on same IPv6 network");
950 hdr = BuildHeader(source, destination, protocol, packet->GetSize(), ttl, tclass);
951 int32_t interface = GetInterfaceForDevice(route->GetOutputDevice());
952 m_sendOutgoingTrace(hdr, packet, interface);
953 SendRealOut(route, packet, hdr);
954 return;
955 }
956
957 /* 3) */
958 NS_LOG_LOGIC("Ipv6L3Protocol::Send case 3: passed in with no route " << destination);
960 Ptr<NetDevice> oif(nullptr);
961 Ptr<Ipv6Route> newRoute = nullptr;
962
963 hdr = BuildHeader(source, destination, protocol, packet->GetSize(), ttl, tclass);
964
965 // for link-local traffic, we need to determine the interface
966 if (source.IsLinkLocal() || destination.IsLinkLocal() || destination.IsLinkLocalMulticast())
967 {
968 int32_t index = GetInterfaceForAddress(source);
969 NS_ASSERT_MSG(index >= 0,
970 "Can not find an outgoing interface for a packet with src "
971 << source << " and dst " << destination);
972 oif = GetNetDevice(index);
973 }
974
975 newRoute = m_routingProtocol->RouteOutput(packet, hdr, oif, err);
976
977 if (newRoute)
978 {
979 int32_t interface = GetInterfaceForDevice(newRoute->GetOutputDevice());
980 m_sendOutgoingTrace(hdr, packet, interface);
981 SendRealOut(newRoute, packet, hdr);
982 }
983 else
984 {
985 NS_LOG_WARN("No route to host, drop!");
986 m_dropTrace(hdr, packet, DROP_NO_ROUTE, this, GetInterfaceForDevice(oif));
987 }
988}
989
990void
993 uint16_t protocol,
994 const Address& from,
995 const Address& to,
996 NetDevice::PacketType packetType)
997{
998 NS_LOG_FUNCTION(this << device << p << protocol << from << to << packetType);
999 NS_LOG_LOGIC("Packet from " << from << " received on node " << m_node->GetId());
1000
1002 "Received a packet from an interface that is not known to IPv6");
1003 uint32_t interface = GetInterfaceForDevice(device);
1004
1005 Ptr<Ipv6Interface> ipv6Interface = m_interfaces[interface];
1006 Ptr<Packet> packet = p->Copy();
1007
1008 if (ipv6Interface->IsUp())
1009 {
1010 m_rxTrace(packet, this, interface);
1011 }
1012 else
1013 {
1014 NS_LOG_LOGIC("Dropping received packet-- interface is down");
1015 Ipv6Header hdr;
1016 packet->RemoveHeader(hdr);
1017 m_dropTrace(hdr, packet, DROP_INTERFACE_DOWN, this, interface);
1018 return;
1019 }
1020
1021 Ipv6Header hdr;
1022 packet->RemoveHeader(hdr);
1023
1024 // Trim any residual frame padding from underlying devices
1025 if (hdr.GetPayloadLength() < packet->GetSize())
1026 {
1027 packet->RemoveAtEnd(packet->GetSize() - hdr.GetPayloadLength());
1028 }
1029
1030 // the packet is valid, we update the NDISC cache entry (if present)
1031 Ptr<NdiscCache> ndiscCache = ipv6Interface->GetNdiscCache();
1032 if (ndiscCache)
1033 {
1034 // case one, it's a a direct routing.
1035 NdiscCache::Entry* entry = ndiscCache->Lookup(hdr.GetSource());
1036 if (entry)
1037 {
1038 entry->UpdateReachableTimer();
1039 }
1040 else
1041 {
1042 // It's not in the direct routing, so it's the router, and it could have multiple IP
1043 // addresses. In doubt, update all of them. Note: it's a confirmed behavior for Linux
1044 // routers.
1045 std::list<NdiscCache::Entry*> entryList = ndiscCache->LookupInverse(from);
1046 for (auto iter = entryList.begin(); iter != entryList.end(); iter++)
1047 {
1048 (*iter)->UpdateReachableTimer();
1049 }
1050 }
1051 }
1052
1053 /* forward up to IPv6 raw sockets */
1054 for (auto it = m_sockets.begin(); it != m_sockets.end(); ++it)
1055 {
1056 Ptr<Ipv6RawSocketImpl> socket = *it;
1057 socket->ForwardUp(packet, hdr, device);
1058 }
1059
1060 Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
1061 Ptr<Ipv6Extension> ipv6Extension = nullptr;
1062 uint8_t nextHeader = hdr.GetNextHeader();
1063 bool stopProcessing = false;
1064 bool isDropped = false;
1065 DropReason dropReason;
1066
1067 if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1068 {
1069 ipv6Extension = ipv6ExtensionDemux->GetExtension(nextHeader);
1070
1071 if (ipv6Extension)
1072 {
1073 ipv6Extension->Process(packet,
1074 0,
1075 hdr,
1076 hdr.GetDestination(),
1077 (uint8_t*)nullptr,
1078 stopProcessing,
1079 isDropped,
1080 dropReason);
1081 }
1082
1083 if (isDropped)
1084 {
1085 m_dropTrace(hdr, packet, dropReason, this, interface);
1086 }
1087
1088 if (stopProcessing)
1089 {
1090 return;
1091 }
1092 }
1093
1094 if (hdr.GetDestination().IsAllNodesMulticast() ||
1095 (hdr.GetDestination().IsAllRoutersMulticast() && ipv6Interface->IsForwarding()))
1096 {
1097 LocalDeliver(packet, hdr, interface);
1098 return;
1099 }
1100 else if (hdr.GetDestination().IsMulticast())
1101 {
1102 bool isSolicited = ipv6Interface->IsSolicitedMulticastAddress(hdr.GetDestination());
1103 bool isRegisteredOnInterface =
1104 IsRegisteredMulticastAddress(hdr.GetDestination(), interface);
1105 bool isRegisteredGlobally = IsRegisteredMulticastAddress(hdr.GetDestination());
1106 if (isSolicited || isRegisteredGlobally || isRegisteredOnInterface)
1107 {
1108 LocalDeliver(packet, hdr, interface);
1109 // do not return, the packet could be handled by a routing protocol
1110 }
1111 }
1112
1113 for (uint32_t j = 0; j < GetNInterfaces(); j++)
1114 {
1115 for (uint32_t i = 0; i < GetNAddresses(j); i++)
1116 {
1117 Ipv6InterfaceAddress iaddr = GetAddress(j, i);
1118 Ipv6Address addr = iaddr.GetAddress();
1119 if (addr == hdr.GetDestination())
1120 {
1121 if (j == interface)
1122 {
1123 NS_LOG_LOGIC("For me (destination " << addr << " match)");
1124 LocalDeliver(packet, hdr, interface);
1125 return;
1126 }
1127 else if (!GetStrongEndSystemModel())
1128 {
1129 NS_LOG_LOGIC("For me (destination "
1130 << addr
1131 << " match) on another interface with Weak End System Model"
1132 << hdr.GetDestination());
1133 LocalDeliver(packet, hdr, interface);
1134 return;
1135 }
1136 else
1137 {
1139 "For me (destination "
1140 << addr
1141 << " match) on another interface with Strong End System Model - discarding"
1142 << hdr.GetDestination());
1143 m_dropTrace(hdr, packet, DROP_NO_ROUTE, this, interface);
1144 return;
1145 }
1146 }
1147 NS_LOG_LOGIC("Address " << addr << " not a match");
1148 }
1149 }
1150
1151 if (!m_routingProtocol->RouteInput(packet, hdr, device, m_ucb, m_mcb, m_lcb, m_ecb))
1152 {
1153 NS_LOG_WARN("No route found for forwarding packet. Drop.");
1154 // Drop trace and ICMPs are courtesy of RouteInputError
1155 }
1156}
1157
1158void
1160 Ptr<Packet> packet,
1161 Ptr<Ipv6> ipv6,
1162 uint32_t interface)
1163{
1164 if (!m_txTrace.IsEmpty())
1165 {
1166 Ptr<Packet> packetCopy = packet->Copy();
1167 packetCopy->AddHeader(ipHeader);
1168 m_txTrace(packetCopy, ipv6, interface);
1169 }
1170}
1171
1172void
1174{
1175 NS_LOG_FUNCTION(this << route << packet << ipHeader);
1176
1177 if (!route)
1178 {
1179 NS_LOG_LOGIC("No route to host, drop!.");
1180 return;
1181 }
1182
1183 Ptr<NetDevice> dev = route->GetOutputDevice();
1184 int32_t interface = GetInterfaceForDevice(dev);
1185 NS_ASSERT(interface >= 0);
1186
1187 Ptr<Ipv6Interface> outInterface = GetInterface(interface);
1188 NS_LOG_LOGIC("Send via NetDevice ifIndex " << dev->GetIfIndex() << " Ipv6InterfaceIndex "
1189 << interface);
1190
1191 // Check packet size
1192 std::list<Ipv6ExtensionFragment::Ipv6PayloadHeaderPair> fragments;
1193
1194 // Check if this is the source of the packet
1195 bool fromMe = false;
1196 for (uint32_t i = 0; i < GetNInterfaces(); i++)
1197 {
1198 for (uint32_t j = 0; j < GetNAddresses(i); j++)
1199 {
1200 if (GetAddress(i, j).GetAddress() == ipHeader.GetSource())
1201 {
1202 fromMe = true;
1203 break;
1204 }
1205 }
1206 }
1207
1208 size_t targetMtu = 0;
1209
1210 // Check if we have a Path MTU stored. If so, use it. Else, use the link MTU.
1211 // Note: PMTU must not be cached in intermediate nodes, and must be checked only by the source
1212 // node
1213 if (fromMe)
1214 {
1215 targetMtu = (size_t)(m_pmtuCache->GetPmtu(ipHeader.GetDestination()));
1216 }
1217 if (targetMtu == 0)
1218 {
1219 targetMtu = dev->GetMtu();
1220 }
1221
1222 if (packet->GetSize() + ipHeader.GetSerializedSize() > targetMtu)
1223 {
1224 // Router => drop
1225 if (!fromMe)
1226 {
1227 Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6();
1228 if (icmpv6)
1229 {
1230 packet->AddHeader(ipHeader);
1231 icmpv6->SendErrorTooBig(packet, ipHeader.GetSource(), dev->GetMtu());
1232 }
1233 return;
1234 }
1235
1236 Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
1237
1238 // To get specific method GetFragments from Ipv6ExtensionFragmentation
1239 Ipv6ExtensionFragment* ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment*>(
1240 PeekPointer(ipv6ExtensionDemux->GetExtension(Ipv6Header::IPV6_EXT_FRAGMENTATION)));
1241 NS_ASSERT(ipv6Fragment != nullptr);
1242 ipv6Fragment->GetFragments(packet, ipHeader, targetMtu, fragments);
1243 }
1244
1245 if (route->GetGateway() != Ipv6Address::GetAny())
1246 {
1247 if (outInterface->IsUp())
1248 {
1249 NS_LOG_LOGIC("Send to gateway " << route->GetGateway());
1250
1251 if (!fragments.empty())
1252 {
1253 std::ostringstream oss;
1254
1255 for (auto it = fragments.begin(); it != fragments.end(); it++)
1256 {
1257 CallTxTrace(it->second, it->first, this, interface);
1258 outInterface->Send(it->first, it->second, route->GetGateway());
1259 }
1260 }
1261 else
1262 {
1263 CallTxTrace(ipHeader, packet, this, interface);
1264 outInterface->Send(packet, ipHeader, route->GetGateway());
1265 }
1266 }
1267 else
1268 {
1269 NS_LOG_LOGIC("Dropping-- outgoing interface is down: " << route->GetGateway());
1270 m_dropTrace(ipHeader, packet, DROP_INTERFACE_DOWN, this, interface);
1271 }
1272 }
1273 else
1274 {
1275 if (outInterface->IsUp())
1276 {
1277 NS_LOG_LOGIC("Send to destination " << ipHeader.GetDestination());
1278
1279 if (!fragments.empty())
1280 {
1281 std::ostringstream oss;
1282
1283 for (auto it = fragments.begin(); it != fragments.end(); it++)
1284 {
1285 CallTxTrace(it->second, it->first, this, interface);
1286 outInterface->Send(it->first, it->second, ipHeader.GetDestination());
1287 }
1288 }
1289 else
1290 {
1291 CallTxTrace(ipHeader, packet, this, interface);
1292 outInterface->Send(packet, ipHeader, ipHeader.GetDestination());
1293 }
1294 }
1295 else
1296 {
1297 NS_LOG_LOGIC("Dropping-- outgoing interface is down: " << ipHeader.GetDestination());
1298 m_dropTrace(ipHeader, packet, DROP_INTERFACE_DOWN, this, interface);
1299 }
1300 }
1301}
1302
1303void
1305 Ptr<Ipv6Route> rtentry,
1307 const Ipv6Header& header)
1308{
1309 NS_LOG_FUNCTION(this << rtentry << p << header);
1310 NS_LOG_LOGIC("Forwarding logic for node: " << m_node->GetId());
1311
1312 // Drop RFC 3849 packets: 2001:db8::/32
1313 if (header.GetDestination().IsDocumentation())
1314 {
1315 NS_LOG_WARN("Received a packet for 2001:db8::/32 (documentation class). Drop.");
1316 m_dropTrace(header, p, DROP_ROUTE_ERROR, this, 0);
1317 return;
1318 }
1319
1320 // Forwarding
1321 Ipv6Header ipHeader = header;
1322 Ptr<Packet> packet = p->Copy();
1323 ipHeader.SetHopLimit(ipHeader.GetHopLimit() - 1);
1324
1325 if (ipHeader.GetSource().IsLinkLocal())
1326 {
1327 /* no forward for link-local address */
1328 return;
1329 }
1330
1331 if (ipHeader.GetHopLimit() == 0)
1332 {
1333 NS_LOG_WARN("TTL exceeded. Drop.");
1334 m_dropTrace(ipHeader, packet, DROP_TTL_EXPIRED, this, 0);
1335 // Do not reply to multicast IPv6 address
1336 if (!ipHeader.GetDestination().IsMulticast())
1337 {
1338 packet->AddHeader(ipHeader);
1339 GetIcmpv6()->SendErrorTimeExceeded(packet,
1340 ipHeader.GetSource(),
1342 }
1343 return;
1344 }
1345
1346 /* ICMPv6 Redirect */
1347
1348 /* if we forward to a machine on the same network as the source,
1349 * we send him an ICMPv6 redirect message to notify him that a short route
1350 * exists.
1351 */
1352
1353 /* Theoretically we should also check if the redirect target is on the same network
1354 * as the source node. On the other hand, we are sure that the router we're redirecting to
1355 * used a link-local address. As a consequence, they MUST be on the same network, the link-local
1356 * net.
1357 */
1358
1359 if (m_sendIcmpv6Redirect && (rtentry->GetOutputDevice() == idev))
1360 {
1361 NS_LOG_LOGIC("ICMPv6 redirect!");
1363 Address hardwareTarget;
1364 Ipv6Address dst = header.GetDestination();
1365 Ipv6Address src = header.GetSource();
1366 Ipv6Address target = rtentry->GetGateway();
1367 Ptr<Packet> copy = p->Copy();
1368
1369 if (target.IsAny())
1370 {
1371 target = dst;
1372 }
1373
1374 copy->AddHeader(header);
1375 Ipv6Address linkLocal = GetInterface(GetInterfaceForDevice(rtentry->GetOutputDevice()))
1377 .GetAddress();
1378
1379 if (icmpv6->Lookup(target, rtentry->GetOutputDevice(), nullptr, &hardwareTarget))
1380 {
1381 icmpv6->SendRedirection(copy, linkLocal, src, target, dst, hardwareTarget);
1382 }
1383 else
1384 {
1385 icmpv6->SendRedirection(copy, linkLocal, src, target, dst, Address());
1386 }
1387 }
1388 // in case the packet still has a priority tag attached, remove it
1389 SocketPriorityTag priorityTag;
1390 packet->RemovePacketTag(priorityTag);
1391 int32_t interface = GetInterfaceForDevice(rtentry->GetOutputDevice());
1392 m_unicastForwardTrace(ipHeader, packet, interface);
1393 SendRealOut(rtentry, packet, ipHeader);
1394}
1395
1396void
1398 Ptr<Ipv6MulticastRoute> mrtentry,
1400 const Ipv6Header& header)
1401{
1402 NS_LOG_FUNCTION(this << mrtentry << p << header);
1403 NS_LOG_LOGIC("Multicast forwarding logic for node: " << m_node->GetId());
1404
1405 std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap();
1406
1407 for (auto mapIter = ttlMap.begin(); mapIter != ttlMap.end(); mapIter++)
1408 {
1409 uint32_t interfaceId = mapIter->first;
1410 // uint32_t outputTtl = mapIter->second; // Unused for now
1411 Ptr<Packet> packet = p->Copy();
1412 Ipv6Header h = header;
1413 h.SetHopLimit(header.GetHopLimit() - 1);
1414 if (h.GetHopLimit() == 0)
1415 {
1416 NS_LOG_WARN("TTL exceeded. Drop.");
1417 m_dropTrace(header, packet, DROP_TTL_EXPIRED, this, interfaceId);
1418 return;
1419 }
1420 NS_LOG_LOGIC("Forward multicast via interface " << interfaceId);
1422 rtentry->SetSource(h.GetSource());
1423 rtentry->SetDestination(h.GetDestination());
1424 rtentry->SetGateway(Ipv6Address::GetAny());
1425 rtentry->SetOutputDevice(GetNetDevice(interfaceId));
1426 SendRealOut(rtentry, packet, h);
1427 }
1428}
1429
1430void
1432{
1433 NS_LOG_FUNCTION(this << packet << ip << iif);
1434 Ptr<Packet> p = packet->Copy();
1435 Ptr<IpL4Protocol> protocol = nullptr;
1437 Ptr<Ipv6Extension> ipv6Extension = nullptr;
1438 Ipv6Address src = ip.GetSource();
1439 Ipv6Address dst = ip.GetDestination();
1440 uint8_t nextHeader = ip.GetNextHeader();
1441 uint8_t nextHeaderPosition = 0;
1442 bool isDropped = false;
1443 bool stopProcessing = false;
1444 DropReason dropReason;
1445
1446 // check for a malformed hop-by-hop extension
1447 // this is a common case when forging IPv6 raw packets
1448 if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1449 {
1450 uint8_t buf;
1451 p->CopyData(&buf, 1);
1453 {
1454 NS_LOG_WARN("Double Ipv6Header::IPV6_EXT_HOP_BY_HOP in packet, dropping packet");
1455 return;
1456 }
1457 }
1458
1459 /* process all the extensions found and the layer 4 protocol */
1460 do
1461 {
1462 /* it return 0 for non-extension (i.e. layer 4 protocol) */
1463 ipv6Extension = ipv6ExtensionDemux->GetExtension(nextHeader);
1464
1465 if (ipv6Extension)
1466 {
1467 uint8_t nextHeaderStep = 0;
1468 uint8_t curHeader = nextHeader;
1469 nextHeaderStep = ipv6Extension->Process(p,
1470 nextHeaderPosition,
1471 ip,
1472 dst,
1473 &nextHeader,
1474 stopProcessing,
1475 isDropped,
1476 dropReason);
1477 nextHeaderPosition += nextHeaderStep;
1478
1479 if (isDropped)
1480 {
1481 m_dropTrace(ip, packet, dropReason, this, iif);
1482 }
1483
1484 if (stopProcessing)
1485 {
1486 return;
1487 }
1488 NS_ASSERT_MSG(nextHeaderStep != 0 || curHeader == Ipv6Header::IPV6_EXT_FRAGMENTATION,
1489 "Zero-size IPv6 Option Header, aborting" << *packet);
1490 }
1491 else
1492 {
1493 protocol = GetProtocol(nextHeader, iif);
1494
1495 if (!protocol)
1496 {
1497 NS_LOG_LOGIC("Unknown Next Header. Drop!");
1498
1499 // For ICMPv6 Error packets
1500 Ptr<Packet> malformedPacket = packet->Copy();
1501 malformedPacket->AddHeader(ip);
1502
1503 if (nextHeaderPosition == 0)
1504 {
1505 GetIcmpv6()->SendErrorParameterError(malformedPacket,
1506 dst,
1508 40);
1509 }
1510 else
1511 {
1512 GetIcmpv6()->SendErrorParameterError(malformedPacket,
1513 dst,
1515 ip.GetSerializedSize() +
1516 nextHeaderPosition);
1517 }
1518 m_dropTrace(ip, p, DROP_UNKNOWN_PROTOCOL, this, iif);
1519 break;
1520 }
1521 else
1522 {
1523 p->RemoveAtStart(nextHeaderPosition);
1524 /* protocol->Receive (p, src, dst, incomingInterface); */
1525
1526 // Options have been processed, and the packet is good.
1527 // We need to adjust the IP header fields
1528 Ipv6Header newIpHeader = ip;
1529 newIpHeader.SetNextHeader(nextHeader);
1530 newIpHeader.SetPayloadLength(p->GetSize());
1531
1532 /* L4 protocol */
1533 Ptr<Packet> copy = p->Copy();
1534
1535 m_localDeliverTrace(newIpHeader, p, iif);
1536
1537 IpL4Protocol::RxStatus status =
1538 protocol->Receive(p, newIpHeader, GetInterface(iif));
1539
1540 switch (status)
1541 {
1545 break;
1547 if (newIpHeader.GetDestination().IsMulticast())
1548 {
1549 /* do not rely on multicast address */
1550 break;
1551 }
1552
1553 copy->AddHeader(newIpHeader);
1554 GetIcmpv6()->SendErrorDestinationUnreachable(
1555 copy,
1556 newIpHeader.GetSource(),
1558 }
1559 }
1560 }
1561 } while (ipv6Extension);
1562}
1563
1564void
1566 const Ipv6Header& ipHeader,
1567 Socket::SocketErrno sockErrno)
1568{
1569 NS_LOG_FUNCTION(this << p << ipHeader << sockErrno);
1570 NS_LOG_LOGIC("Route input failure-- dropping packet to " << ipHeader << " with errno "
1571 << sockErrno);
1572
1573 m_dropTrace(ipHeader, p, DROP_ROUTE_ERROR, this, 0);
1574
1575 if (!ipHeader.GetDestination().IsMulticast())
1576 {
1577 Ptr<Packet> packet = p->Copy();
1578 packet->AddHeader(ipHeader);
1579 GetIcmpv6()->SendErrorDestinationUnreachable(packet,
1580 ipHeader.GetSource(),
1582 }
1583}
1584
1587 Ipv6Address dst,
1588 uint8_t protocol,
1589 uint16_t payloadSize,
1590 uint8_t ttl,
1591 uint8_t tclass)
1592{
1593 NS_LOG_FUNCTION(this << src << dst << (uint32_t)protocol << (uint32_t)payloadSize
1594 << (uint32_t)ttl << (uint32_t)tclass);
1595 Ipv6Header hdr;
1596
1597 hdr.SetSource(src);
1598 hdr.SetDestination(dst);
1599 hdr.SetNextHeader(protocol);
1600 hdr.SetPayloadLength(payloadSize);
1601 hdr.SetHopLimit(ttl);
1602 hdr.SetTrafficClass(tclass);
1603 return hdr;
1604}
1605
1606void
1608{
1610 {
1611 return;
1612 }
1614 ipv6ExtensionDemux->SetNode(m_node);
1615
1617 hopbyhopExtension->SetNode(m_node);
1619 destinationExtension->SetNode(m_node);
1621 fragmentExtension->SetNode(m_node);
1623 routingExtension->SetNode(m_node);
1624 // Ptr<Ipv6ExtensionESP> espExtension = CreateObject<Ipv6ExtensionESP> ();
1625 // Ptr<Ipv6ExtensionAH> ahExtension = CreateObject<Ipv6ExtensionAH> ();
1626
1627 ipv6ExtensionDemux->Insert(hopbyhopExtension);
1628 ipv6ExtensionDemux->Insert(destinationExtension);
1629 ipv6ExtensionDemux->Insert(fragmentExtension);
1630 ipv6ExtensionDemux->Insert(routingExtension);
1631 // ipv6ExtensionDemux->Insert (espExtension);
1632 // ipv6ExtensionDemux->Insert (ahExtension);
1633
1634 Ptr<Ipv6ExtensionRoutingDemux> routingExtensionDemux =
1636 routingExtensionDemux->SetNode(m_node);
1637 Ptr<Ipv6ExtensionLooseRouting> looseRoutingExtension =
1639 looseRoutingExtension->SetNode(m_node);
1640 routingExtensionDemux->Insert(looseRoutingExtension);
1641
1642 m_node->AggregateObject(routingExtensionDemux);
1643 m_node->AggregateObject(ipv6ExtensionDemux);
1644}
1645
1646void
1648{
1650 {
1651 return;
1652 }
1654 ipv6OptionDemux->SetNode(m_node);
1655
1657 pad1Option->SetNode(m_node);
1659 padnOption->SetNode(m_node);
1661 jumbogramOption->SetNode(m_node);
1663 routerAlertOption->SetNode(m_node);
1664
1665 ipv6OptionDemux->Insert(pad1Option);
1666 ipv6OptionDemux->Insert(padnOption);
1667 ipv6OptionDemux->Insert(jumbogramOption);
1668 ipv6OptionDemux->Insert(routerAlertOption);
1669
1670 m_node->AggregateObject(ipv6OptionDemux);
1671}
1672
1673void
1675{
1676 m_dropTrace(ipHeader, p, dropReason, this, 0);
1677}
1678
1679void
1681{
1682 NS_LOG_FUNCTION(address << interface);
1683
1684 if (!address.IsMulticast())
1685 {
1686 NS_LOG_WARN("Not adding a non-multicast address " << address);
1687 return;
1688 }
1689
1690 Ipv6RegisteredMulticastAddressKey_t key = std::make_pair(address, interface);
1691 m_multicastAddresses[key]++;
1692}
1693
1694void
1696{
1697 NS_LOG_FUNCTION(address);
1698
1699 if (!address.IsMulticast())
1700 {
1701 NS_LOG_WARN("Not adding a non-multicast address " << address);
1702 return;
1703 }
1704
1706}
1707
1708void
1710{
1711 NS_LOG_FUNCTION(address << interface);
1712
1713 Ipv6RegisteredMulticastAddressKey_t key = std::make_pair(address, interface);
1714
1715 m_multicastAddresses[key]--;
1716 if (m_multicastAddresses[key] == 0)
1717 {
1718 m_multicastAddresses.erase(key);
1719 }
1720}
1721
1722void
1724{
1725 NS_LOG_FUNCTION(address);
1726
1728 if (m_multicastAddressesNoInterface[address] == 0)
1729 {
1730 m_multicastAddressesNoInterface.erase(address);
1731 }
1732}
1733
1734bool
1736{
1737 Ipv6RegisteredMulticastAddressKey_t key = std::make_pair(address, interface);
1738 auto iter = m_multicastAddresses.find(key);
1739
1740 return iter != m_multicastAddresses.end();
1741}
1742
1743bool
1745{
1746 auto iter = m_multicastAddressesNoInterface.find(address);
1747
1748 return iter != m_multicastAddressesNoInterface.end();
1749}
1750
1751bool
1753{
1754 if (ipInterfaceIndex >= m_interfaces.size())
1755 {
1756 return false;
1757 }
1758
1759 Ptr<NdiscCache> ndiscCache = m_interfaces[ipInterfaceIndex]->GetNdiscCache();
1760 if (!ndiscCache)
1761 {
1762 return false;
1763 }
1764
1765 NdiscCache::Entry* entry = ndiscCache->Lookup(address);
1766 if (!entry || entry->IsIncomplete())
1767 {
1768 return false;
1769 }
1770
1771 if (entry->IsReachable())
1772 {
1773 entry->UpdateReachableTimer();
1774 }
1775 else if (entry->IsPermanent() || entry->IsAutoGenerated())
1776 {
1777 return true;
1778 }
1779 else if (entry->IsProbe())
1780 {
1781 // we just confirm the entry's MAC address to get the waiting packets (if any)
1782 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting =
1783 entry->MarkReachable(entry->GetMacAddress());
1784 for (auto it = waiting.begin(); it != waiting.end(); it++)
1785 {
1786 ndiscCache->GetInterface()->Send(it->first, it->second, it->second.GetSource());
1787 }
1788 entry->ClearWaitingPacket();
1789 entry->StartReachableTimer();
1790 }
1791 else // STALE OR DELAY
1792 {
1793 entry->MarkReachable();
1794 entry->StartReachableTimer();
1795 }
1796
1797 return true;
1798}
1799
1800void
1802{
1803 NS_LOG_FUNCTION(this << model);
1804 m_strongEndSystemModel = model;
1805}
1806
1807bool
1812
1813} /* namespace ns3 */
a polymophic address class
Definition address.h:90
AttributeValue implementation for Boolean.
Definition boolean.h:26
An implementation of the ICMPv6 protocol.
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
@ AUTADDRCONF
Autonomous Address Configuration.
RxStatus
Rx status codes.
Describes an IPv6 address.
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
bool IsDocumentation() const
If the IPv6 address is a documentation address (2001:DB8::/32).
bool IsAllNodesMulticast() const
If the IPv6 address is "all nodes multicast" (ff02::1/8).
bool IsLinkLocalMulticast() const
If the IPv6 address is link-local multicast (ff02::/16).
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
static Ipv6Address MakeAutoconfiguredAddress(Address addr, Ipv6Address prefix)
Make the autoconfigured IPv6 address from a Mac 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 GetLoopback()
Get the loopback address.
bool IsAllRoutersMulticast() const
If the IPv6 address is "all routers multicast" (ff02::2/8).
Demultiplexes IPv6 extensions.
IPv6 Extension Fragment.
Packet header for IPv6.
Definition ipv6-header.h:24
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
void SetSource(Ipv6Address src)
Set the "Source address" field.
uint8_t GetHopLimit() const
Get the "Hop limit" field (TTL).
uint8_t GetNextHeader() const
Get the next header.
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Ipv6Address GetDestination() const
Get the "Destination address" field.
uint16_t GetPayloadLength() const
Get the "Payload length" field.
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Ipv6Address GetSource() const
Get the "Source address" field.
void SetTrafficClass(uint8_t traffic)
Set the "Traffic class" field.
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition ipv6.h:71
IPv6 address associated with an interface.
Ipv6Address GetAddress() const
Get the IPv6 address.
@ LINKLOCAL
Link-local address (fe80::/64)
@ GLOBAL
Global address (2000::/3)
The IPv6 representation of a network interface.
Ipv6InterfaceAddress GetLinkLocalAddress() const
Get link-local address from IPv6 interface.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
IPv6 layer implementation.
bool GetIpForward() const override
Get IPv6 forwarding state.
Ptr< Ipv6PmtuCache > m_pmtuCache
Path MTU Cache.
Ipv6RoutingProtocol::MulticastForwardCallback m_mcb
Multicast forward callback.
void SetForwarding(uint32_t i, bool val) override
Enable or disable forwarding on interface.
void SetPmtu(Ipv6Address dst, uint32_t pmtu) override
Set the Path MTU for the specified IPv6 destination address.
void RegisterOptions() override
Register the IPv6 Options.
void RouteInputError(Ptr< const Packet > p, const Ipv6Header &ipHeader, Socket::SocketErrno sockErrno)
Fallback when no route is found.
uint8_t m_defaultTclass
Default TCLASS for outgoing packets.
bool IsRegisteredMulticastAddress(Ipv6Address address) const
Checks if the address has been registered.
Ptr< Ipv6RoutingProtocol > GetRoutingProtocol() const override
Get current routing protocol used.
bool GetMtuDiscover() const override
Get IPv6 MTU discover state.
bool AddAddress(uint32_t i, Ipv6InterfaceAddress address, bool addOnLinkRoute=true) override
Add an address on interface.
uint16_t GetMetric(uint32_t i) const override
Get metric for an interface.
Ipv6RoutingProtocol::UnicastForwardCallback m_ucb
Unicast forward callback.
void AddAutoconfiguredAddress(uint32_t interface, Ipv6Address network, Ipv6Prefix mask, uint8_t flags, uint32_t validTime, uint32_t preferredTime, Ipv6Address defaultRouter=Ipv6Address::GetZero())
Add an autoconfigured address with RA information.
void SetUp(uint32_t i) override
Set an interface up.
TracedCallback< Ptr< const Packet >, Ptr< Ipv6 >, uint32_t > m_txTrace
Callback to trace TX (transmission) packets.
bool IsForwarding(uint32_t i) const override
Is interface allows forwarding ?
void SetStrongEndSystemModel(bool model) override
Set or unset the Strong End System Model.
bool m_sendIcmpv6Redirect
Allow ICMPv6 Redirect sending state.
Ptr< Icmpv6L4Protocol > GetIcmpv6() const
Get ICMPv6 protocol.
bool ReachabilityHint(uint32_t ipInterfaceIndex, Ipv6Address address)
Provides reachability hint for Neighbor Cache Entries from L4-L7 protocols.
uint8_t m_defaultTtl
Default TTL for outgoing packets.
void SetMetric(uint32_t i, uint16_t metric) override
Set metric for an interface.
TracedCallback< Ptr< const Packet >, Ptr< Ipv6 >, uint32_t > m_rxTrace
Callback to trace RX (reception) packets.
TracedCallback< const Ipv6Header &, Ptr< const Packet >, DropReason, Ptr< Ipv6 >, uint32_t > m_dropTrace
Callback to trace drop packets.
DropReason
Reason why a packet has been dropped.
@ DROP_ROUTE_ERROR
Route error.
@ DROP_TTL_EXPIRED
Packet TTL has expired.
@ DROP_NO_ROUTE
No route to host.
@ DROP_UNKNOWN_PROTOCOL
Unknown L4 protocol.
uint32_t GetNAddresses(uint32_t interface) const override
Get number of address for an interface.
int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const override
Get interface index which is on a specified net device.
void RegisterExtensions() override
Register the IPv6 Extensions.
TracedCallback< const Ipv6Header &, Ptr< const Packet >, uint32_t > m_sendOutgoingTrace
Trace of sent packets.
bool m_ipForward
Forwarding packets (i.e.
Ipv6AutoconfiguredPrefixList m_prefixes
List of IPv6 prefix received from RA.
void CallTxTrace(const Ipv6Header &ipHeader, Ptr< Packet > packet, Ptr< Ipv6 > ipv6, uint32_t interface)
Make a copy of the packet, add the header and invoke the TX trace callback.
Ipv6InterfaceList m_interfaces
List of IPv6 interfaces.
void Remove(Ptr< IpL4Protocol > protocol) override
Remove a L4 protocol.
Ipv6RegisteredMulticastAddressNoInterface_t m_multicastAddressesNoInterface
List of multicast IP addresses of interest for all the interfaces.
Ipv6InterfaceAddress GetAddress(uint32_t interfaceIndex, uint32_t addressIndex) const override
Get an address.
SocketList m_sockets
List of IPv6 raw sockets.
Ipv6Header BuildHeader(Ipv6Address src, Ipv6Address dst, uint8_t protocol, uint16_t payloadSize, uint8_t hopLimit, uint8_t tclass)
Construct an IPv6 header.
void SetNode(Ptr< Node > node)
Set node associated with this stack.
Ipv6Address SourceAddressSelection(uint32_t interface, Ipv6Address dest) override
Choose the source address to use with destination address.
Ptr< Node > m_node
Node attached to stack.
virtual bool GetSendIcmpv6Redirect() const
Get the ICMPv6 Redirect sending state.
L4List_t m_protocols
List of transport protocol.
Ptr< Ipv6Interface > GetInterface(uint32_t i) const
Get an interface.
TracedCallback< const Ipv6Header &, Ptr< const Packet >, uint32_t > m_unicastForwardTrace
Trace of unicast forwarded packets.
uint32_t m_nInterfaces
Number of IPv6 interfaces managed by the stack.
void AddMulticastAddress(Ipv6Address address)
Adds a multicast address to the list of addresses to pass to local deliver.
virtual void ReportDrop(Ipv6Header ipHeader, Ptr< Packet > p, DropReason dropReason)
Report a packet drop.
void Send(Ptr< Packet > packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr< Ipv6Route > route) override
Higher-level layers call this method to send a packet down the stack to the MAC and PHY layers.
void SetupLoopback()
Setup loopback interface.
Ptr< IpL4Protocol > GetProtocol(int protocolNumber) const override
Get L4 protocol by protocol number.
Ptr< Socket > CreateRawSocket()
Create raw IPv6 socket.
Ipv6RegisteredMulticastAddress_t m_multicastAddresses
List of multicast IP addresses of interest, divided per interface.
void RemoveAutoconfiguredAddress(uint32_t interface, Ipv6Address network, Ipv6Prefix mask, Ipv6Address defaultRouter)
Remove an autoconfigured address.
uint16_t GetMtu(uint32_t i) const override
Get MTU for an interface.
void Insert(Ptr< IpL4Protocol > protocol) override
Add a L4 protocol.
bool m_mtuDiscover
MTU Discover (i.e.
void SetDefaultTtl(uint8_t ttl)
Set the default TTL.
uint32_t AddInterface(Ptr< NetDevice > device) override
Add IPv6 interface for a device.
Ipv6RoutingProtocol::ErrorCallback m_ecb
Error callback.
bool RemoveAddress(uint32_t interfaceIndex, uint32_t addressIndex) override
Remove an address from an interface.
void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Receive method when a packet arrive in the stack.
Ptr< NetDevice > GetNetDevice(uint32_t i) override
Get device by index.
void RemoveMulticastAddress(Ipv6Address address)
Removes a multicast address from the list of addresses to pass to local deliver.
void SetDown(uint32_t i) override
set an interface down.
void DoDispose() override
Dispose object.
uint32_t AddIpv6Interface(Ptr< Ipv6Interface > interface)
Add an IPv6 interface to the stack.
Ptr< Ipv6RoutingProtocol > m_routingProtocol
Routing protocol.
virtual void SetSendIcmpv6Redirect(bool sendIcmpv6Redirect)
Set the ICMPv6 Redirect sending state.
void NotifyNewAggregate() override
Notify other components connected to the node that a new stack member is now connected.
void IpMulticastForward(Ptr< const NetDevice > idev, Ptr< Ipv6MulticastRoute > mrtentry, Ptr< const Packet > p, const Ipv6Header &header)
Forward a multicast packet.
~Ipv6L3Protocol() override
Destructor.
void DeleteRawSocket(Ptr< Socket > socket)
Remove raw IPv6 socket.
Ipv6InterfaceReverseContainer m_reverseInterfacesContainer
Container of NetDevice / Interface index associations.
void SendRealOut(Ptr< Ipv6Route > route, Ptr< Packet > packet, const Ipv6Header &ipHeader)
Send packet with route.
bool m_strongEndSystemModel
Rejects packets directed to an interface with wrong address (RFC 1222 ).
TracedCallback< const Ipv6Header &, Ptr< const Packet >, uint32_t > m_localDeliverTrace
Trace of locally delivered packets.
int32_t GetInterfaceForPrefix(Ipv6Address addr, Ipv6Prefix mask) const override
Get interface index which match specified address/prefix.
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
void SetDefaultTclass(uint8_t tclass)
Set the default TCLASS.
void IpForward(Ptr< const NetDevice > idev, Ptr< Ipv6Route > rtentry, Ptr< const Packet > p, const Ipv6Header &header)
Forward a packet.
uint32_t GetNInterfaces() const override
Get current number of interface on this stack.
bool IsUp(uint32_t i) const override
Is specified interface up ?
void SetRoutingProtocol(Ptr< Ipv6RoutingProtocol > routingProtocol) override
Set routing protocol for this stack.
std::pair< Ipv6Address, uint64_t > Ipv6RegisteredMulticastAddressKey_t
IPv6 multicast addresses / interface key.
Ipv6RoutingProtocol::LocalDeliverCallback m_lcb
Local delivery callback.
std::pair< int, int32_t > L4ListKey_t
Container of the IPv6 L4 keys: protocol number, interface index.
bool GetStrongEndSystemModel() const override
Get the Strong End System Model status.
int32_t GetInterfaceForAddress(Ipv6Address addr) const override
Get interface index which has specified IPv6 address.
Ipv6L3Protocol()
Constructor.
void SetIpForward(bool forward) override
Set IPv6 forwarding state.
void LocalDeliver(Ptr< const Packet > p, const Ipv6Header &ip, uint32_t iif)
Deliver a packet.
static TypeId GetTypeId()
Get the type ID of this class.
void SetMtuDiscover(bool mtuDiscover) override
Set IPv6 MTU discover state.
IPv6 Option Demux.
Describes an IPv6 prefix.
A record that holds information about a NdiscCache entry.
bool IsPermanent() const
Is the entry PERMANENT.
void ClearWaitingPacket()
Clear the waiting packet list.
void StartReachableTimer()
Start the reachable timer.
void UpdateReachableTimer()
Update the reachable timer.
Address GetMacAddress() const
Get the MAC address of this entry.
std::list< Ipv6PayloadHeaderPair > MarkReachable(Address mac)
Changes the state to this entry to REACHABLE.
bool IsIncomplete() const
Is the entry INCOMPLETE.
bool IsProbe() const
Is the entry PROBE.
bool IsAutoGenerated() const
Is the entry STATIC_AUTOGENERATED.
bool IsReachable() const
Is the entry REACHABLE.
PacketType
Packet types are used as they are in Linux.
Definition net-device.h:289
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition node.cc:124
uint32_t GetNDevices() const
Definition node.cc:147
uint32_t GetId() const
Definition node.cc:106
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition node.cc:138
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition node.cc:220
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition object.cc:412
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition object.cc:298
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition socket.h:73
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition socket.h:1161
uint8_t GetHopLimit() const
Get the tag's Hop Limit.
Definition socket.cc:663
indicates whether the socket has IPV6_TCLASS set.
Definition socket.h:1355
uint8_t GetTclass() const
Get the tag's Tclass.
Definition socket.cc:905
indicates whether the socket has a priority set.
Definition socket.h:1307
The Traffic Control layer aims at introducing an equivalent of the Linux Traffic Control infrastructu...
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:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
#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
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeObjectVectorChecker()
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
#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_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#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
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
#define IPV6_MIN_MTU
Minimum IPv6 MTU, as defined by RFC 2460
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:443
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
-ns3 Test suite for the ns3 wrapper script