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
47TypeId
49{
50 static TypeId tid =
51 TypeId("ns3::Ipv6L3Protocol")
52 .SetParent<Ipv6>()
53 .SetGroupName("Internet")
54 .AddConstructor<Ipv6L3Protocol>()
55 .AddAttribute("DefaultTtl",
56 "The TTL value set by default on all "
57 "outgoing packets generated on this node.",
58 UintegerValue(64),
61 .AddAttribute("DefaultTclass",
62 "The TCLASS value set by default on all "
63 "outgoing packets generated on this node.",
67 .AddAttribute("InterfaceList",
68 "The set of IPv6 interfaces associated to this IPv6 stack.",
72 .AddAttribute("SendIcmpv6Redirect",
73 "Send the ICMPv6 Redirect when appropriate.",
74 BooleanValue(true),
78 .AddTraceSource("Tx",
79 "Send IPv6 packet to outgoing interface.",
81 "ns3::Ipv6L3Protocol::TxRxTracedCallback")
82 .AddTraceSource("Rx",
83 "Receive IPv6 packet from incoming interface.",
85 "ns3::Ipv6L3Protocol::TxRxTracedCallback")
86 .AddTraceSource("Drop",
87 "Drop IPv6 packet",
89 "ns3::Ipv6L3Protocol::DropTracedCallback")
90
91 .AddTraceSource("SendOutgoing",
92 "A newly-generated packet by this node is "
93 "about to be queued for transmission",
95 "ns3::Ipv6L3Protocol::SentTracedCallback")
96 .AddTraceSource("UnicastForward",
97 "A unicast IPv6 packet was received by this node "
98 "and is being forwarded to another node",
100 "ns3::Ipv6L3Protocol::SentTracedCallback")
101 .AddTraceSource("LocalDeliver",
102 "An IPv6 packet was received by/for this node, "
103 "and it is being forward up the stack",
105 "ns3::Ipv6L3Protocol::SentTracedCallback");
106 return tid;
107}
108
122
127
128void
130{
131 NS_LOG_FUNCTION(this);
132
133 /* clear protocol and interface list */
134 for (auto it = m_protocols.begin(); it != m_protocols.end(); ++it)
135 {
136 it->second = nullptr;
137 }
138 m_protocols.clear();
139
140 /* remove interfaces */
141 for (auto it = m_interfaces.begin(); it != m_interfaces.end(); ++it)
142 {
143 *it = nullptr;
144 }
145 m_interfaces.clear();
147
148 /* remove raw sockets */
149 for (auto it = m_sockets.begin(); it != m_sockets.end(); ++it)
150 {
151 *it = nullptr;
152 }
153 m_sockets.clear();
154
155 /* remove list of prefix */
156 for (auto it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
157 {
158 (*it)->StopValidTimer();
159 (*it)->StopPreferredTimer();
160 (*it) = nullptr;
161 }
162 m_prefixes.clear();
163
164 m_node = nullptr;
165 m_routingProtocol = nullptr;
166 m_pmtuCache = nullptr;
168}
169
170void
172{
173 NS_LOG_FUNCTION(this << routingProtocol);
174 m_routingProtocol = routingProtocol;
175 m_routingProtocol->SetIpv6(this);
176}
177
183
186{
187 NS_LOG_FUNCTION(this << device);
189
191
192 NS_ASSERT(tc);
193
196 device);
197
198 tc->RegisterProtocolHandler(MakeCallback(&Ipv6L3Protocol::Receive, this),
200 device);
201
202 interface->SetNode(m_node);
203 interface->SetDevice(device);
204 interface->SetTrafficControl(tc);
205 interface->SetForwarding(m_ipForward);
206 return AddIpv6Interface(interface);
207}
208
211{
212 NS_LOG_FUNCTION(this << interface);
213 uint32_t index = m_nInterfaces;
214
215 m_interfaces.push_back(interface);
216 m_reverseInterfacesContainer[interface->GetDevice()] = index;
218 return index;
219}
220
223{
224 if (index < m_interfaces.size())
225 {
226 return m_interfaces[index];
227 }
228 return nullptr;
229}
230
233{
234 return m_nInterfaces;
235}
236
239{
240 int32_t index = 0;
241
242 for (auto it = m_interfaces.begin(); it != m_interfaces.end(); it++)
243 {
244 uint32_t j = 0;
245 uint32_t max = (*it)->GetNAddresses();
246
247 for (j = 0; j < max; j++)
248 {
249 if ((*it)->GetAddress(j).GetAddress() == address)
250 {
251 return index;
252 }
253 }
254 index++;
255 }
256 return -1;
257}
258
261{
262 int32_t index = 0;
263
264 for (auto it = m_interfaces.begin(); it != m_interfaces.end(); it++)
265 {
266 uint32_t j = 0;
267 for (j = 0; j < (*it)->GetNAddresses(); j++)
268 {
269 if ((*it)->GetAddress(j).GetAddress().CombinePrefix(mask) ==
270 address.CombinePrefix(mask))
271 {
272 return index;
273 }
274 }
275 index++;
276 }
277 return -1;
278}
279
285
288{
289 auto iter = m_reverseInterfacesContainer.find(device);
290 if (iter != m_reverseInterfacesContainer.end())
291 {
292 return (*iter).second;
293 }
294
295 return -1;
296}
297
298void
300 Ipv6Address network,
301 Ipv6Prefix mask,
302 uint8_t flags,
303 uint32_t validTime,
304 uint32_t preferredTime,
305 Ipv6Address defaultRouter)
306{
307 NS_LOG_FUNCTION(this << interface << network << mask << (uint32_t)flags << validTime
308 << preferredTime);
309 Ipv6InterfaceAddress address;
310
311 Address addr = GetInterface(interface)->GetDevice()->GetAddress();
312
313 if (!defaultRouter.IsAny())
314 {
315 GetRoutingProtocol()->NotifyAddRoute(Ipv6Address::GetAny(),
316 Ipv6Prefix((uint8_t)0),
317 defaultRouter,
318 interface,
319 network);
320 }
321
322 bool onLink = false;
324 {
325 onLink = true;
326 }
327
328 if (flags & Icmpv6OptionPrefixInformation::AUTADDRCONF) /* auto flag */
329 {
330 address = Ipv6Address::MakeAutoconfiguredAddress(addr, network);
331 address.SetOnLink(onLink);
332
333 /* see if we have already the prefix */
334 for (auto it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
335 {
336 if ((*it)->GetInterface() == interface && (*it)->GetPrefix() == network &&
337 (*it)->GetMask() == mask)
338 {
339 (*it)->StopPreferredTimer();
340 (*it)->StopValidTimer();
341 (*it)->StartPreferredTimer();
342 return;
343 }
344 }
345
346 /* no prefix found, add autoconfigured address and the prefix */
347 NS_LOG_INFO("Autoconfigured address is :" << address.GetAddress());
348 AddAddress(interface, address, onLink);
349
352 interface,
353 network,
354 mask,
355 preferredTime,
356 validTime,
357 defaultRouter);
358 aPrefix->StartPreferredTimer();
359
360 m_prefixes.push_back(aPrefix);
361 }
362
363 if (onLink) /* on-link flag */
364 {
365 /* add default router
366 * if a previous default route exists, the new ones is simply added
367 */
368 m_routingProtocol->NotifyAddRoute(network, mask, Ipv6Address::GetAny(), interface);
369 }
370}
371
372void
374 Ipv6Address network,
375 Ipv6Prefix mask,
376 Ipv6Address defaultRouter)
377{
378 NS_LOG_FUNCTION(this << interface << network << mask);
379 Ptr<Ipv6Interface> iface = GetInterface(interface);
380 Address addr = iface->GetDevice()->GetAddress();
381
382 Ipv6Address addressToFind = Ipv6Address::MakeAutoconfiguredAddress(addr, network);
383
384 for (uint32_t i = 0; i < iface->GetNAddresses(); i++)
385 {
386 if (iface->GetAddress(i).GetAddress() == addressToFind)
387 {
388 RemoveAddress(interface, i);
389 break;
390 }
391 }
392
393 /* remove from list of autoconfigured address */
394 for (auto it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
395 {
396 if ((*it)->GetInterface() == interface && (*it)->GetPrefix() == network &&
397 (*it)->GetMask() == mask)
398 {
399 *it = nullptr;
400 m_prefixes.erase(it);
401 break;
402 }
403 }
404
405 GetRoutingProtocol()->NotifyRemoveRoute(Ipv6Address::GetAny(),
406 Ipv6Prefix((uint8_t)0),
407 defaultRouter,
408 interface,
409 network);
410}
411
412bool
414{
415 NS_LOG_FUNCTION(this << i << address);
416 Ptr<Ipv6Interface> interface = GetInterface(i);
417 address.SetOnLink(addOnLinkRoute);
418 bool ret = interface->AddAddress(address);
419
420 if (m_routingProtocol)
421 {
422 m_routingProtocol->NotifyAddAddress(i, address);
423 }
424
425 if (addOnLinkRoute)
426 {
427 Ipv6Address networkAddress = address.GetAddress().CombinePrefix(address.GetPrefix());
428 Ipv6Prefix networkMask = address.GetPrefix();
429 GetRoutingProtocol()->NotifyAddRoute(networkAddress,
430 networkMask,
431 Ipv6Address::GetZero(),
432 i);
433 }
434 return ret;
435}
436
439{
440 Ptr<Ipv6Interface> interface = GetInterface(i);
441 return interface->GetNAddresses();
442}
443
446{
447 Ptr<Ipv6Interface> interface = GetInterface(i);
448 return interface->GetAddress(addressIndex);
449}
450
451bool
453{
454 NS_LOG_FUNCTION(this << i << addressIndex);
455 Ptr<Ipv6Interface> interface = GetInterface(i);
456 Ipv6InterfaceAddress address = interface->RemoveAddress(addressIndex);
457
458 if (address != Ipv6InterfaceAddress())
459 {
460 if (m_routingProtocol)
461 {
462 m_routingProtocol->NotifyRemoveAddress(i, address);
463 }
464 return true;
465 }
466 return false;
467}
468
469bool
471{
472 NS_LOG_FUNCTION(this << i << address);
473
474 if (address == Ipv6Address::GetLoopback())
475 {
476 NS_LOG_WARN("Cannot remove loopback address.");
477 return false;
478 }
479 Ptr<Ipv6Interface> interface = GetInterface(i);
480 Ipv6InterfaceAddress ifAddr = interface->RemoveAddress(address);
481 if (ifAddr != Ipv6InterfaceAddress())
482 {
483 if (m_routingProtocol)
484 {
485 m_routingProtocol->NotifyRemoveAddress(i, ifAddr);
486 }
487 return true;
488 }
489 return false;
490}
491
492void
494{
495 NS_LOG_FUNCTION(this << i << metric);
496 Ptr<Ipv6Interface> interface = GetInterface(i);
497 interface->SetMetric(metric);
498}
499
500uint16_t
502{
503 Ptr<Ipv6Interface> interface = GetInterface(i);
504 return interface->GetMetric();
505}
506
507uint16_t
509{
510 // RFC 1981, if PMTU is disabled, return the minimum MTU
511 if (!m_mtuDiscover)
512 {
513 return IPV6_MIN_MTU;
514 }
515
516 Ptr<Ipv6Interface> interface = GetInterface(i);
517 return interface->GetDevice()->GetMtu();
518}
519
520void
522{
523 NS_LOG_FUNCTION(this << dst << int(pmtu));
524 m_pmtuCache->SetPmtu(dst, pmtu);
525}
526
527bool
529{
530 Ptr<Ipv6Interface> interface = GetInterface(i);
531 return interface->IsUp();
532}
533
534void
536{
537 NS_LOG_FUNCTION(this << i);
538 Ptr<Ipv6Interface> interface = GetInterface(i);
539
540 // RFC 2460, Section 5, pg. 24:
541 // IPv6 requires that every link in the internet have an MTU of 1280
542 // octets or greater. On any link that cannot convey a 1280-octet
543 // packet in one piece, link-specific fragmentation and reassembly must
544 // be provided at a layer below IPv6.
545 if (interface->GetDevice()->GetMtu() >= 1280)
546 {
547 interface->SetUp();
548
549 if (m_routingProtocol)
550 {
551 m_routingProtocol->NotifyInterfaceUp(i);
552 }
553 }
554 else
555 {
556 NS_LOG_LOGIC("Interface " << int(i)
557 << " is set to be down for IPv6. Reason: not respecting minimum "
558 "IPv6 MTU (1280 octets)");
559 }
560}
561
562void
564{
565 NS_LOG_FUNCTION(this << i);
566 Ptr<Ipv6Interface> interface = GetInterface(i);
567
568 interface->SetDown();
569
570 if (m_routingProtocol)
571 {
572 m_routingProtocol->NotifyInterfaceDown(i);
573 }
574}
575
576void
578{
579 NS_LOG_FUNCTION(this);
581 Ptr<LoopbackNetDevice> device = nullptr;
582 uint32_t i = 0;
583
584 /* see if we have already an loopback NetDevice */
585 for (i = 0; i < m_node->GetNDevices(); i++)
586 {
588 {
589 break;
590 }
591 }
592
593 if (!device)
594 {
596 m_node->AddDevice(device);
597 }
598
599 interface->SetDevice(device);
600 interface->SetNode(m_node);
601 Ipv6InterfaceAddress ifaceAddr =
603 interface->AddAddress(ifaceAddr);
604 uint32_t index = AddIpv6Interface(interface);
605 Ptr<Node> node = GetObject<Node>();
606 node->RegisterProtocolHandler(MakeCallback(&Ipv6L3Protocol::Receive, this),
608 device);
609 interface->SetUp();
610
612 {
613 m_routingProtocol->NotifyInterfaceUp(index);
614 }
615}
616
617bool
619{
620 Ptr<Ipv6Interface> interface = GetInterface(i);
621
622 NS_LOG_LOGIC("Forwarding state: " << interface->IsForwarding());
623 return interface->IsForwarding();
624}
625
626void
628{
629 NS_LOG_FUNCTION(this << i << val);
630 Ptr<Ipv6Interface> interface = GetInterface(i);
631 interface->SetForwarding(val);
632}
633
636{
637 NS_LOG_FUNCTION(this << interface << dest);
638 Ipv6Address ret;
639
640 if (dest.IsLocalhost())
641 {
643 }
644
645 if (dest.IsLinkLocal() || dest.IsLinkLocalMulticast())
646 {
647 for (uint32_t i = 0; i < GetNAddresses(interface); i++)
648 {
649 Ipv6InterfaceAddress test = GetAddress(interface, i);
650 if (test.GetScope() == Ipv6InterfaceAddress::LINKLOCAL)
651 {
652 return test.GetAddress();
653 }
654 }
655 NS_ASSERT_MSG(false, "No link-local address found on interface " << interface);
656 }
657
658 for (uint32_t i = 0; i < GetNAddresses(interface); i++)
659 {
660 Ipv6InterfaceAddress test = GetAddress(interface, i);
661
662 if (test.GetScope() == Ipv6InterfaceAddress::GLOBAL)
663 {
664 if (test.IsInSameSubnet(dest))
665 {
666 return test.GetAddress();
667 }
668 else
669 {
670 ret = test.GetAddress();
671 }
672 }
673 }
674
675 // no specific match found. Use a global address (any useful is fine).
676 NS_ASSERT_MSG(!ret.IsAny(),
677 "Could not find any address for " << dest << " on interface " << interface);
678 return ret;
679}
680
681void
683{
684 NS_LOG_FUNCTION(this << forward);
685 m_ipForward = forward;
686
687 for (auto it = m_interfaces.begin(); it != m_interfaces.end(); it++)
688 {
689 (*it)->SetForwarding(forward);
690 }
691}
692
693bool
695{
696 return m_ipForward;
697}
698
699void
701{
702 NS_LOG_FUNCTION(this << int(mtuDiscover));
703 m_mtuDiscover = mtuDiscover;
704}
705
706bool
708{
709 return m_mtuDiscover;
710}
711
712void
714{
715 NS_LOG_FUNCTION(this << sendIcmpv6Redirect);
716 m_sendIcmpv6Redirect = sendIcmpv6Redirect;
717}
718
719bool
724
725void
727{
728 NS_LOG_FUNCTION(this);
729
730 if (!m_node)
731 {
732 Ptr<Node> node = this->GetObject<Node>();
733 // verify that it's a valid node and that
734 // the node has not been set before
735 if (node)
736 {
737 this->SetNode(node);
738 }
739 }
740
742}
743
744void
746{
747 NS_LOG_FUNCTION(this << node);
748 m_node = node;
749 /* add LoopbackNetDevice if needed, and an Ipv6Interface on top of it */
751}
752
753void
755{
756 NS_LOG_FUNCTION(this << protocol);
757 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), -1);
758 if (m_protocols.find(key) != m_protocols.end())
759 {
760 NS_LOG_WARN("Overwriting default protocol " << int(protocol->GetProtocolNumber()));
761 }
762 m_protocols[key] = protocol;
763}
764
765void
767{
768 NS_LOG_FUNCTION(this << protocol << interfaceIndex);
769
770 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), interfaceIndex);
771 if (m_protocols.find(key) != m_protocols.end())
772 {
773 NS_LOG_WARN("Overwriting protocol " << int(protocol->GetProtocolNumber())
774 << " on interface " << int(interfaceIndex));
775 }
776 m_protocols[key] = protocol;
777}
778
779void
781{
782 NS_LOG_FUNCTION(this << protocol);
783
784 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), -1);
785 auto iter = m_protocols.find(key);
786 if (iter == m_protocols.end())
787 {
788 NS_LOG_WARN("Trying to remove an non-existent default protocol "
789 << int(protocol->GetProtocolNumber()));
790 }
791 else
792 {
793 m_protocols.erase(key);
794 }
795}
796
797void
799{
800 NS_LOG_FUNCTION(this << protocol << interfaceIndex);
801
802 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), interfaceIndex);
803 auto iter = m_protocols.find(key);
804 if (iter == m_protocols.end())
805 {
806 NS_LOG_WARN("Trying to remove an non-existent protocol "
807 << int(protocol->GetProtocolNumber()) << " on interface "
808 << int(interfaceIndex));
809 }
810 else
811 {
812 m_protocols.erase(key);
813 }
814}
815
817Ipv6L3Protocol::GetProtocol(int protocolNumber) const
818{
819 return GetProtocol(protocolNumber, -1);
820}
821
823Ipv6L3Protocol::GetProtocol(int protocolNumber, int32_t interfaceIndex) const
824{
825 if (interfaceIndex >= 0)
826 {
827 // try the interface-specific protocol.
828 auto key = std::make_pair(protocolNumber, interfaceIndex);
829 auto i = m_protocols.find(key);
830 if (i != m_protocols.end())
831 {
832 return i->second;
833 }
834 }
835 // try the generic protocol.
836 auto key = std::make_pair(protocolNumber, -1);
837 auto i = m_protocols.find(key);
838 if (i != m_protocols.end())
839 {
840 return i->second;
841 }
842
843 return nullptr;
844}
845
848{
849 NS_LOG_FUNCTION(this);
851 sock->SetNode(m_node);
852 m_sockets.push_back(sock);
853 return sock;
854}
855
856void
858{
859 NS_LOG_FUNCTION(this << socket);
860
861 for (auto it = m_sockets.begin(); it != m_sockets.end(); ++it)
862 {
863 if ((*it) == socket)
864 {
865 m_sockets.erase(it);
866 return;
867 }
868 }
869}
870
873{
875
876 if (protocol)
877 {
878 return protocol->GetObject<Icmpv6L4Protocol>();
879 }
880 else
881 {
882 return nullptr;
883 }
884}
885
886void
888{
889 NS_LOG_FUNCTION(this << ttl);
890 m_defaultTtl = ttl;
891}
892
893void
895{
896 NS_LOG_FUNCTION(this << tclass);
897 m_defaultTclass = tclass;
898}
899
900void
902 Ipv6Address source,
903 Ipv6Address destination,
904 uint8_t protocol,
905 Ptr<Ipv6Route> route)
906{
907 NS_LOG_FUNCTION(this << packet << source << destination << (uint32_t)protocol << route);
908 Ipv6Header hdr;
909 uint8_t ttl = m_defaultTtl;
911 bool found = packet->RemovePacketTag(tag);
912
913 if (found)
914 {
915 ttl = tag.GetHopLimit();
916 }
917
918 SocketIpv6TclassTag tclassTag;
919 uint8_t tclass = m_defaultTclass;
920 found = packet->RemovePacketTag(tclassTag);
921
922 if (found)
923 {
924 tclass = tclassTag.GetTclass();
925 }
926
927 /* Handle 3 cases:
928 * 1) Packet is passed in with a route entry
929 * 2) Packet is passed in with a route entry but route->GetGateway is not set (e.g., same
930 * network) 3) route is NULL (e.g., a raw socket call or ICMPv6)
931 */
932
933 /* 1) */
934 if (route && route->GetGateway() != Ipv6Address::GetZero())
935 {
936 NS_LOG_LOGIC("Ipv6L3Protocol::Send case 1: passed in with a route");
937 hdr = BuildHeader(source, destination, protocol, packet->GetSize(), ttl, tclass);
938 int32_t interface = GetInterfaceForDevice(route->GetOutputDevice());
939 m_sendOutgoingTrace(hdr, packet, interface);
940 SendRealOut(route, packet, hdr);
941 return;
942 }
943
944 /* 2) */
945 if (route && route->GetGateway() == Ipv6Address::GetZero())
946 {
947 NS_LOG_LOGIC("Ipv6L3Protocol::Send case 2: probably sent to machine on same IPv6 network");
948 hdr = BuildHeader(source, destination, protocol, packet->GetSize(), ttl, tclass);
949 int32_t interface = GetInterfaceForDevice(route->GetOutputDevice());
950 m_sendOutgoingTrace(hdr, packet, interface);
951 SendRealOut(route, packet, hdr);
952 return;
953 }
954
955 /* 3) */
956 NS_LOG_LOGIC("Ipv6L3Protocol::Send case 3: passed in with no route " << destination);
958 Ptr<NetDevice> oif(nullptr);
959 Ptr<Ipv6Route> newRoute = nullptr;
960
961 hdr = BuildHeader(source, destination, protocol, packet->GetSize(), ttl, tclass);
962
963 // for link-local traffic, we need to determine the interface
964 if (source.IsLinkLocal() || destination.IsLinkLocal() || destination.IsLinkLocalMulticast())
965 {
966 int32_t index = GetInterfaceForAddress(source);
967 NS_ASSERT_MSG(index >= 0,
968 "Can not find an outgoing interface for a packet with src "
969 << source << " and dst " << destination);
970 oif = GetNetDevice(index);
971 }
972
973 newRoute = m_routingProtocol->RouteOutput(packet, hdr, oif, err);
974
975 if (newRoute)
976 {
977 int32_t interface = GetInterfaceForDevice(newRoute->GetOutputDevice());
978 m_sendOutgoingTrace(hdr, packet, interface);
979 SendRealOut(newRoute, packet, hdr);
980 }
981 else
982 {
983 NS_LOG_WARN("No route to host, drop!");
984 m_dropTrace(hdr, packet, DROP_NO_ROUTE, this, GetInterfaceForDevice(oif));
985 }
986}
987
988void
991 uint16_t protocol,
992 const Address& from,
993 const Address& to,
994 NetDevice::PacketType packetType)
995{
996 NS_LOG_FUNCTION(this << device << p << protocol << from << to << packetType);
997 NS_LOG_LOGIC("Packet from " << from << " received on node " << m_node->GetId());
998
1000 "Received a packet from an interface that is not known to IPv6");
1001 uint32_t interface = GetInterfaceForDevice(device);
1002
1003 Ptr<Ipv6Interface> ipv6Interface = m_interfaces[interface];
1004 Ptr<Packet> packet = p->Copy();
1005
1006 if (ipv6Interface->IsUp())
1007 {
1008 m_rxTrace(packet, this, interface);
1009 }
1010 else
1011 {
1012 NS_LOG_LOGIC("Dropping received packet-- interface is down");
1013 Ipv6Header hdr;
1014 packet->RemoveHeader(hdr);
1015 m_dropTrace(hdr, packet, DROP_INTERFACE_DOWN, this, interface);
1016 return;
1017 }
1018
1019 Ipv6Header hdr;
1020 packet->RemoveHeader(hdr);
1021
1022 // Trim any residual frame padding from underlying devices
1023 if (hdr.GetPayloadLength() < packet->GetSize())
1024 {
1025 packet->RemoveAtEnd(packet->GetSize() - hdr.GetPayloadLength());
1026 }
1027
1028 // the packet is valid, we update the NDISC cache entry (if present)
1029 Ptr<NdiscCache> ndiscCache = ipv6Interface->GetNdiscCache();
1030 if (ndiscCache)
1031 {
1032 // case one, it's a a direct routing.
1033 NdiscCache::Entry* entry = ndiscCache->Lookup(hdr.GetSource());
1034 if (entry)
1035 {
1036 entry->UpdateReachableTimer();
1037 }
1038 else
1039 {
1040 // It's not in the direct routing, so it's the router, and it could have multiple IP
1041 // addresses. In doubt, update all of them. Note: it's a confirmed behavior for Linux
1042 // routers.
1043 std::list<NdiscCache::Entry*> entryList = ndiscCache->LookupInverse(from);
1044 for (auto iter = entryList.begin(); iter != entryList.end(); iter++)
1045 {
1046 (*iter)->UpdateReachableTimer();
1047 }
1048 }
1049 }
1050
1051 Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
1052 Ptr<Ipv6Extension> ipv6Extension = nullptr;
1053 uint8_t nextHeader = hdr.GetNextHeader();
1054 bool stopProcessing = false;
1055 bool isDropped = false;
1056 DropReason dropReason;
1057
1058 if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1059 {
1060 ipv6Extension = ipv6ExtensionDemux->GetExtension(nextHeader);
1061
1062 if (ipv6Extension)
1063 {
1064 ipv6Extension->Process(packet,
1065 0,
1066 hdr,
1067 hdr.GetDestination(),
1068 (uint8_t*)nullptr,
1069 stopProcessing,
1070 isDropped,
1071 dropReason);
1072 }
1073
1074 if (isDropped)
1075 {
1076 m_dropTrace(hdr, packet, dropReason, this, interface);
1077 }
1078
1079 if (stopProcessing)
1080 {
1081 return;
1082 }
1083 }
1084
1085 if (hdr.GetDestination().IsAllNodesMulticast() ||
1086 (hdr.GetDestination().IsAllRoutersMulticast() && ipv6Interface->IsForwarding()))
1087 {
1088 LocalDeliver(packet, hdr, interface);
1089 return;
1090 }
1091 else if (hdr.GetDestination().IsMulticast())
1092 {
1093 bool isSolicited = ipv6Interface->IsSolicitedMulticastAddress(hdr.GetDestination());
1094 bool isRegisteredOnInterface =
1095 IsRegisteredMulticastAddress(hdr.GetDestination(), interface);
1096 bool isRegisteredGlobally = IsRegisteredMulticastAddress(hdr.GetDestination());
1097 if (isSolicited || isRegisteredGlobally || isRegisteredOnInterface)
1098 {
1099 LocalDeliver(packet, hdr, interface);
1100 // do not return, the packet could be handled by a routing protocol
1101 }
1102 }
1103
1104 for (uint32_t j = 0; j < GetNInterfaces(); j++)
1105 {
1106 for (uint32_t i = 0; i < GetNAddresses(j); i++)
1107 {
1108 Ipv6InterfaceAddress iaddr = GetAddress(j, i);
1109 Ipv6Address addr = iaddr.GetAddress();
1110 if (addr == hdr.GetDestination())
1111 {
1112 if (j == interface)
1113 {
1114 NS_LOG_LOGIC("For me (destination " << addr << " match)");
1115 LocalDeliver(packet, hdr, interface);
1116 return;
1117 }
1118 else if (!GetStrongEndSystemModel())
1119 {
1120 NS_LOG_LOGIC("For me (destination "
1121 << addr
1122 << " match) on another interface with Weak End System Model"
1123 << hdr.GetDestination());
1124 LocalDeliver(packet, hdr, interface);
1125 return;
1126 }
1127 else
1128 {
1130 "For me (destination "
1131 << addr
1132 << " match) on another interface with Strong End System Model - discarding"
1133 << hdr.GetDestination());
1134 m_dropTrace(hdr, packet, DROP_NO_ROUTE, this, interface);
1135 return;
1136 }
1137 }
1138 NS_LOG_LOGIC("Address " << addr << " not a match");
1139 }
1140 }
1141
1142 if (!m_routingProtocol->RouteInput(packet, hdr, device, m_ucb, m_mcb, m_lcb, m_ecb))
1143 {
1144 NS_LOG_WARN("No route found for forwarding packet. Drop.");
1145 // Drop trace and ICMPs are courtesy of RouteInputError
1146 }
1147}
1148
1149void
1151 Ptr<Packet> packet,
1152 Ptr<Ipv6> ipv6,
1153 uint32_t interface)
1154{
1155 if (!m_txTrace.IsEmpty())
1156 {
1157 Ptr<Packet> packetCopy = packet->Copy();
1158 packetCopy->AddHeader(ipHeader);
1159 m_txTrace(packetCopy, ipv6, interface);
1160 }
1161}
1162
1163void
1165{
1166 NS_LOG_FUNCTION(this << route << packet << ipHeader);
1167
1168 if (!route)
1169 {
1170 NS_LOG_LOGIC("No route to host, drop!.");
1171 return;
1172 }
1173
1174 Ptr<NetDevice> dev = route->GetOutputDevice();
1175 int32_t interface = GetInterfaceForDevice(dev);
1176 NS_ASSERT(interface >= 0);
1177
1178 Ptr<Ipv6Interface> outInterface = GetInterface(interface);
1179 NS_LOG_LOGIC("Send via NetDevice ifIndex " << dev->GetIfIndex() << " Ipv6InterfaceIndex "
1180 << interface);
1181
1182 // Check packet size
1183 std::list<Ipv6ExtensionFragment::Ipv6PayloadHeaderPair> fragments;
1184
1185 // Check if this is the source of the packet
1186 bool fromMe = false;
1187 for (uint32_t i = 0; i < GetNInterfaces(); i++)
1188 {
1189 for (uint32_t j = 0; j < GetNAddresses(i); j++)
1190 {
1191 if (GetAddress(i, j).GetAddress() == ipHeader.GetSource())
1192 {
1193 fromMe = true;
1194 break;
1195 }
1196 }
1197 }
1198
1199 size_t targetMtu = 0;
1200
1201 // Check if we have a Path MTU stored. If so, use it. Else, use the link MTU.
1202 // Note: PMTU must not be cached in intermediate nodes, and must be checked only by the source
1203 // node
1204 if (fromMe)
1205 {
1206 targetMtu = (size_t)(m_pmtuCache->GetPmtu(ipHeader.GetDestination()));
1207 }
1208 if (targetMtu == 0)
1209 {
1210 targetMtu = dev->GetMtu();
1211 }
1212
1213 if (packet->GetSize() + ipHeader.GetSerializedSize() > targetMtu)
1214 {
1215 // Router => drop
1216 if (!fromMe)
1217 {
1218 Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6();
1219 if (icmpv6)
1220 {
1221 packet->AddHeader(ipHeader);
1222 icmpv6->SendErrorTooBig(packet, ipHeader.GetSource(), dev->GetMtu());
1223 }
1224 return;
1225 }
1226
1227 Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
1228
1229 // To get specific method GetFragments from Ipv6ExtensionFragmentation
1230 Ipv6ExtensionFragment* ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment*>(
1231 PeekPointer(ipv6ExtensionDemux->GetExtension(Ipv6Header::IPV6_EXT_FRAGMENTATION)));
1232 NS_ASSERT(ipv6Fragment != nullptr);
1233 ipv6Fragment->GetFragments(packet, ipHeader, targetMtu, fragments);
1234 }
1235
1236 if (route->GetGateway() != Ipv6Address::GetAny())
1237 {
1238 if (outInterface->IsUp())
1239 {
1240 NS_LOG_LOGIC("Send to gateway " << route->GetGateway());
1241
1242 if (!fragments.empty())
1243 {
1244 std::ostringstream oss;
1245
1246 for (auto it = fragments.begin(); it != fragments.end(); it++)
1247 {
1248 CallTxTrace(it->second, it->first, this, interface);
1249 outInterface->Send(it->first, it->second, route->GetGateway());
1250 }
1251 }
1252 else
1253 {
1254 CallTxTrace(ipHeader, packet, this, interface);
1255 outInterface->Send(packet, ipHeader, route->GetGateway());
1256 }
1257 }
1258 else
1259 {
1260 NS_LOG_LOGIC("Dropping-- outgoing interface is down: " << route->GetGateway());
1261 m_dropTrace(ipHeader, packet, DROP_INTERFACE_DOWN, this, interface);
1262 }
1263 }
1264 else
1265 {
1266 if (outInterface->IsUp())
1267 {
1268 NS_LOG_LOGIC("Send to destination " << ipHeader.GetDestination());
1269
1270 if (!fragments.empty())
1271 {
1272 std::ostringstream oss;
1273
1274 for (auto it = fragments.begin(); it != fragments.end(); it++)
1275 {
1276 CallTxTrace(it->second, it->first, this, interface);
1277 outInterface->Send(it->first, it->second, ipHeader.GetDestination());
1278 }
1279 }
1280 else
1281 {
1282 CallTxTrace(ipHeader, packet, this, interface);
1283 outInterface->Send(packet, ipHeader, ipHeader.GetDestination());
1284 }
1285 }
1286 else
1287 {
1288 NS_LOG_LOGIC("Dropping-- outgoing interface is down: " << ipHeader.GetDestination());
1289 m_dropTrace(ipHeader, packet, DROP_INTERFACE_DOWN, this, interface);
1290 }
1291 }
1292}
1293
1294void
1296 Ptr<Ipv6Route> rtentry,
1298 const Ipv6Header& header)
1299{
1300 NS_LOG_FUNCTION(this << rtentry << p << header);
1301 NS_LOG_LOGIC("Forwarding logic for node: " << m_node->GetId());
1302
1303 // Drop RFC 3849 packets: 2001:db8::/32
1304 if (header.GetDestination().IsDocumentation())
1305 {
1306 NS_LOG_WARN("Received a packet for 2001:db8::/32 (documentation class). Drop.");
1307 m_dropTrace(header, p, DROP_ROUTE_ERROR, this, 0);
1308 return;
1309 }
1310
1311 // Forwarding
1312 Ipv6Header ipHeader = header;
1313 Ptr<Packet> packet = p->Copy();
1314
1315 if (ipHeader.GetSource().IsLinkLocal())
1316 {
1317 /* no forward for link-local address */
1318 return;
1319 }
1320
1321 // RFC 8200: When forwarding, the packet is discarded if Hop
1322 // Limit was zero when received or is decremented to zero.
1323 if (ipHeader.GetHopLimit() <= 1)
1324 {
1325 NS_LOG_WARN("TTL exceeded. Drop.");
1326 m_dropTrace(ipHeader, packet, DROP_TTL_EXPIRED, this, 0);
1327 // Do not reply to multicast IPv6 address
1328 if (!ipHeader.GetDestination().IsMulticast())
1329 {
1330 packet->AddHeader(ipHeader);
1331 GetIcmpv6()->SendErrorTimeExceeded(packet,
1332 ipHeader.GetSource(),
1334 }
1335 return;
1336 }
1337 ipHeader.SetHopLimit(ipHeader.GetHopLimit() - 1);
1338
1339 /* ICMPv6 Redirect */
1340
1341 /* if we forward to a machine on the same network as the source,
1342 * we send him an ICMPv6 redirect message to notify him that a short route
1343 * exists.
1344 */
1345
1346 /* Theoretically we should also check if the redirect target is on the same network
1347 * as the source node. On the other hand, we are sure that the router we're redirecting to
1348 * used a link-local address. As a consequence, they MUST be on the same network, the link-local
1349 * net.
1350 */
1351
1352 if (m_sendIcmpv6Redirect && (rtentry->GetOutputDevice() == idev))
1353 {
1354 NS_LOG_LOGIC("ICMPv6 redirect!");
1356 Address hardwareTarget;
1357 Ipv6Address dst = header.GetDestination();
1358 Ipv6Address src = header.GetSource();
1359 Ipv6Address target = rtentry->GetGateway();
1360 Ptr<Packet> copy = p->Copy();
1361
1362 if (target.IsAny())
1363 {
1364 target = dst;
1365 }
1366
1367 copy->AddHeader(header);
1368 Ipv6Address linkLocal = GetInterface(GetInterfaceForDevice(rtentry->GetOutputDevice()))
1370 .GetAddress();
1371
1372 if (icmpv6->Lookup(target, rtentry->GetOutputDevice(), nullptr, &hardwareTarget))
1373 {
1374 icmpv6->SendRedirection(copy, linkLocal, src, target, dst, hardwareTarget);
1375 }
1376 else
1377 {
1378 icmpv6->SendRedirection(copy, linkLocal, src, target, dst, Address());
1379 }
1380 }
1381 // in case the packet still has a priority tag attached, remove it
1382 SocketPriorityTag priorityTag;
1383 packet->RemovePacketTag(priorityTag);
1384 int32_t interface = GetInterfaceForDevice(rtentry->GetOutputDevice());
1385 m_unicastForwardTrace(ipHeader, packet, interface);
1386 SendRealOut(rtentry, packet, ipHeader);
1387}
1388
1389void
1391 Ptr<Ipv6MulticastRoute> mrtentry,
1393 const Ipv6Header& header)
1394{
1395 NS_LOG_FUNCTION(this << mrtentry << p << header);
1396 NS_LOG_LOGIC("Multicast forwarding logic for node: " << m_node->GetId());
1397
1398 std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap();
1399
1400 for (auto mapIter = ttlMap.begin(); mapIter != ttlMap.end(); mapIter++)
1401 {
1402 uint32_t interfaceId = mapIter->first;
1403 // uint32_t outputTtl = mapIter->second; // Unused for now
1404 Ptr<Packet> packet = p->Copy();
1405 Ipv6Header h = header;
1406 h.SetHopLimit(header.GetHopLimit() - 1);
1407 if (h.GetHopLimit() == 0)
1408 {
1409 NS_LOG_WARN("TTL exceeded. Drop.");
1410 m_dropTrace(header, packet, DROP_TTL_EXPIRED, this, interfaceId);
1411 return;
1412 }
1413 NS_LOG_LOGIC("Forward multicast via interface " << interfaceId);
1415 rtentry->SetSource(h.GetSource());
1416 rtentry->SetDestination(h.GetDestination());
1417 rtentry->SetGateway(Ipv6Address::GetAny());
1418 rtentry->SetOutputDevice(GetNetDevice(interfaceId));
1419 SendRealOut(rtentry, packet, h);
1420 }
1421}
1422
1423void
1425{
1426 NS_LOG_FUNCTION(this << packet << ip << iif);
1427 Ptr<Packet> p = packet->Copy();
1428 Ptr<IpL4Protocol> protocol = nullptr;
1430 Ptr<Ipv6Extension> ipv6Extension = nullptr;
1431 Ipv6Address src = ip.GetSource();
1432 Ipv6Address dst = ip.GetDestination();
1433 uint8_t nextHeader = ip.GetNextHeader();
1434 uint8_t nextHeaderPosition = 0;
1435 bool isDropped = false;
1436 bool stopProcessing = false;
1437 DropReason dropReason;
1438 Ptr<NetDevice> device = GetNetDevice(iif);
1439
1440 // check for a malformed hop-by-hop extension
1441 // this is a common case when forging IPv6 raw packets
1442 if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
1443 {
1444 uint8_t buf;
1445 p->CopyData(&buf, 1);
1447 {
1448 NS_LOG_WARN("Double Ipv6Header::IPV6_EXT_HOP_BY_HOP in packet, dropping packet");
1449 return;
1450 }
1451 }
1452
1453 /* process all the extensions found and the layer 4 protocol */
1454 do
1455 {
1456 /* it return 0 for non-extension (i.e. layer 4 protocol) */
1457 ipv6Extension = ipv6ExtensionDemux->GetExtension(nextHeader);
1458
1459 if (ipv6Extension)
1460 {
1461 uint8_t nextHeaderStep = 0;
1462 uint8_t curHeader = nextHeader;
1463 nextHeaderStep = ipv6Extension->Process(p,
1464 nextHeaderPosition,
1465 ip,
1466 dst,
1467 &nextHeader,
1468 stopProcessing,
1469 isDropped,
1470 dropReason);
1471 nextHeaderPosition += nextHeaderStep;
1472
1473 if (isDropped)
1474 {
1475 m_dropTrace(ip, packet, dropReason, this, iif);
1476 }
1477
1478 if (stopProcessing)
1479 {
1480 return;
1481 }
1482 NS_ASSERT_MSG(nextHeaderStep != 0 || curHeader == Ipv6Header::IPV6_EXT_FRAGMENTATION,
1483 "Zero-size IPv6 Option Header, aborting" << *packet);
1484 }
1485 else
1486 {
1487 protocol = GetProtocol(nextHeader, iif);
1488
1489 if (!protocol)
1490 {
1491 NS_LOG_LOGIC("Unknown Next Header. Drop!");
1492
1493 // For ICMPv6 Error packets
1494 Ptr<Packet> malformedPacket = packet->Copy();
1495 malformedPacket->AddHeader(ip);
1496
1497 if (nextHeaderPosition == 0)
1498 {
1499 GetIcmpv6()->SendErrorParameterError(malformedPacket,
1500 dst,
1502 40);
1503 }
1504 else
1505 {
1506 GetIcmpv6()->SendErrorParameterError(malformedPacket,
1507 dst,
1509 ip.GetSerializedSize() +
1510 nextHeaderPosition);
1511 }
1512 m_dropTrace(ip, p, DROP_UNKNOWN_PROTOCOL, this, iif);
1513 break;
1514 }
1515 else
1516 {
1517 p->RemoveAtStart(nextHeaderPosition);
1518 /* protocol->Receive (p, src, dst, incomingInterface); */
1519
1520 // Options have been processed, and the packet is good.
1521 // We need to adjust the IP header fields
1522 Ipv6Header newIpHeader = ip;
1523 newIpHeader.SetNextHeader(nextHeader);
1524 newIpHeader.SetPayloadLength(p->GetSize());
1525
1526 /* L4 protocol */
1527 Ptr<Packet> copy = p->Copy();
1528
1529 m_localDeliverTrace(newIpHeader, p, iif);
1530
1531 for (auto& socket : m_sockets)
1532 {
1533 NS_LOG_INFO("Delivering to raw socket " << socket);
1534 socket->ForwardUp(p, newIpHeader, device);
1535 }
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.
static constexpr uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
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.
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:49
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:439
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:448
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:585
-ns3 Test suite for the ns3 wrapper script