A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv6-extension.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: David Gross <gdavid.devel@gmail.com>
7 */
8
9#include "ipv6-extension.h"
10
11#include "icmpv6-l4-protocol.h"
14#include "ipv6-header.h"
15#include "ipv6-l3-protocol.h"
16#include "ipv6-option-demux.h"
17#include "ipv6-option.h"
18#include "ipv6-route.h"
19
20#include "ns3/assert.h"
21#include "ns3/ipv6-address.h"
22#include "ns3/log.h"
23#include "ns3/object-vector.h"
24#include "ns3/trace-source-accessor.h"
25#include "ns3/uinteger.h"
26
27#include <ctime>
28#include <list>
29
30namespace ns3
31{
32
33NS_LOG_COMPONENT_DEFINE("Ipv6Extension");
34
35NS_OBJECT_ENSURE_REGISTERED(Ipv6Extension);
36
37TypeId
39{
40 static TypeId tid = TypeId("ns3::Ipv6Extension")
42 .SetGroupName("Internet")
43 .AddAttribute("ExtensionNumber",
44 "The IPv6 extension number.",
48 return tid;
49}
50
55
59
60void
62{
63 NS_LOG_FUNCTION(this << node);
64
65 m_node = node;
66}
67
70{
71 return m_node;
72}
73
74uint8_t
76 uint8_t offset,
77 uint8_t length,
78 const Ipv6Header& ipv6Header,
79 Ipv6Address dst,
80 uint8_t* nextHeader,
81 bool& stopProcessing,
82 bool& isDropped,
84{
85 NS_LOG_FUNCTION(this << packet << offset << length << ipv6Header << dst << nextHeader
86 << isDropped);
87
88 // For ICMPv6 Error packets
89 Ptr<Packet> malformedPacket = packet->Copy();
90 malformedPacket->AddHeader(ipv6Header);
91 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
92
93 Ptr<Packet> p = packet->Copy();
94 p->RemoveAtStart(offset);
95
97 Ptr<Ipv6Option> ipv6Option;
98
99 uint8_t processedSize = 0;
100 uint32_t size = p->GetSize();
101 auto data = new uint8_t[size];
102 p->CopyData(data, size);
103
104 uint8_t optionType = 0;
105 uint8_t optionLength = 0;
106
107 while (length > processedSize && !isDropped)
108 {
109 optionType = *(data + processedSize);
110 ipv6Option = ipv6OptionDemux->GetOption(optionType);
111
112 if (!ipv6Option)
113 {
114 optionType >>= 6;
115 switch (optionType)
116 {
117 case 0:
118 optionLength = *(data + processedSize + 1) + 2;
119 break;
120
121 case 1:
122 NS_LOG_LOGIC("Unknown Option. Drop!");
123 optionLength = 0;
124 isDropped = true;
125 stopProcessing = true;
127 break;
128
129 case 2:
130 NS_LOG_LOGIC("Unknown Option. Drop!");
131 icmpv6->SendErrorParameterError(malformedPacket,
132 ipv6Header.GetSource(),
134 offset + processedSize);
135 optionLength = 0;
136 isDropped = true;
137 stopProcessing = true;
139 break;
140
141 case 3:
142 NS_LOG_LOGIC("Unknown Option. Drop!");
143
144 if (!ipv6Header.GetDestination().IsMulticast())
145 {
146 icmpv6->SendErrorParameterError(malformedPacket,
147 ipv6Header.GetSource(),
149 offset + processedSize);
150 }
151 optionLength = 0;
152 isDropped = true;
153 stopProcessing = true;
155 break;
156
157 default:
158 break;
159 }
160 }
161 else
162 {
163 optionLength =
164 ipv6Option->Process(packet, offset + processedSize, ipv6Header, isDropped);
165 }
166
167 processedSize += optionLength;
168 p->RemoveAtStart(optionLength);
169 }
170
171 delete[] data;
172
173 return processedSize;
174}
175
176int64_t
178{
179 NS_LOG_FUNCTION(this << stream);
180 m_uvar->SetStream(stream);
181 return 1;
182}
183
185
186TypeId
188{
189 static TypeId tid = TypeId("ns3::Ipv6ExtensionHopByHop")
191 .SetGroupName("Internet")
192 .AddConstructor<Ipv6ExtensionHopByHop>();
193 return tid;
194}
195
199
203
204uint8_t
209
210uint8_t
212 uint8_t offset,
213 const Ipv6Header& ipv6Header,
214 Ipv6Address dst,
215 uint8_t* nextHeader,
216 bool& stopProcessing,
217 bool& isDropped,
218 Ipv6L3Protocol::DropReason& dropReason)
219{
220 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
221
222 Ptr<Packet> p = packet->Copy();
223 p->RemoveAtStart(offset);
224
225 Ipv6ExtensionHopByHopHeader hopbyhopHeader;
226 p->RemoveHeader(hopbyhopHeader);
227 if (nextHeader)
228 {
229 *nextHeader = hopbyhopHeader.GetNextHeader();
230 }
231
232 uint8_t processedSize = hopbyhopHeader.GetOptionsOffset();
233 offset += processedSize;
234 uint8_t length = hopbyhopHeader.GetLength() - hopbyhopHeader.GetOptionsOffset();
235
236 processedSize += ProcessOptions(packet,
237 offset,
238 length,
239 ipv6Header,
240 dst,
241 nextHeader,
242 stopProcessing,
243 isDropped,
244 dropReason);
245
246 return processedSize;
247}
248
250
251TypeId
253{
254 static TypeId tid = TypeId("ns3::Ipv6ExtensionDestination")
256 .SetGroupName("Internet")
257 .AddConstructor<Ipv6ExtensionDestination>();
258 return tid;
259}
260
264
268
269uint8_t
274
275uint8_t
277 uint8_t offset,
278 const Ipv6Header& ipv6Header,
279 Ipv6Address dst,
280 uint8_t* nextHeader,
281 bool& stopProcessing,
282 bool& isDropped,
283 Ipv6L3Protocol::DropReason& dropReason)
284{
285 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
286
287 Ptr<Packet> p = packet->Copy();
288 p->RemoveAtStart(offset);
289
290 Ipv6ExtensionDestinationHeader destinationHeader;
291 p->RemoveHeader(destinationHeader);
292 if (nextHeader)
293 {
294 *nextHeader = destinationHeader.GetNextHeader();
295 }
296
297 uint8_t processedSize = destinationHeader.GetOptionsOffset();
298 offset += processedSize;
299 uint8_t length = destinationHeader.GetLength() - destinationHeader.GetOptionsOffset();
300
301 processedSize += ProcessOptions(packet,
302 offset,
303 length,
304 ipv6Header,
305 dst,
306 nextHeader,
307 stopProcessing,
308 isDropped,
309 dropReason);
310
311 return processedSize;
312}
313
315
316TypeId
318{
319 static TypeId tid =
320 TypeId("ns3::Ipv6ExtensionFragment")
322 .SetGroupName("Internet")
323 .AddConstructor<Ipv6ExtensionFragment>()
324 .AddAttribute("FragmentExpirationTimeout",
325 "When this timeout expires, the fragments "
326 "will be cleared from the buffer.",
327 TimeValue(Seconds(60)),
330 return tid;
331}
332
336
340
341void
343{
344 NS_LOG_FUNCTION(this);
345
346 for (auto it = m_fragments.begin(); it != m_fragments.end(); it++)
347 {
348 it->second = nullptr;
349 }
350
351 m_fragments.clear();
352 m_timeoutEventList.clear();
354 {
356 }
358}
359
360uint8_t
365
366uint8_t
368 uint8_t offset,
369 const Ipv6Header& ipv6Header,
370 Ipv6Address dst,
371 uint8_t* nextHeader,
372 bool& stopProcessing,
373 bool& isDropped,
374 Ipv6L3Protocol::DropReason& dropReason)
375{
376 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
377
378 Ptr<Packet> p = packet->Copy();
379 p->RemoveAtStart(offset);
380
381 Ipv6ExtensionFragmentHeader fragmentHeader;
382 p->RemoveHeader(fragmentHeader);
383
384 if (nextHeader)
385 {
386 *nextHeader = fragmentHeader.GetNextHeader();
387 }
388
389 bool moreFragment = fragmentHeader.GetMoreFragment();
390 uint16_t fragmentOffset = fragmentHeader.GetOffset();
391 uint32_t identification = fragmentHeader.GetIdentification();
392 Ipv6Address src = ipv6Header.GetSource();
393
394 FragmentKey_t fragmentKey = FragmentKey_t(src, identification);
395 Ptr<Fragments> fragments;
396
397 Ipv6Header ipHeader = ipv6Header;
398 ipHeader.SetNextHeader(fragmentHeader.GetNextHeader());
399
400 auto it = m_fragments.find(fragmentKey);
401 if (it == m_fragments.end())
402 {
403 fragments = Create<Fragments>();
404 m_fragments.insert(std::make_pair(fragmentKey, fragments));
405 NS_LOG_DEBUG("Insert new fragment key: src: "
406 << src << " IP hdr id " << identification << " m_fragments.size() "
407 << m_fragments.size() << " offset " << fragmentOffset);
408 auto iter = SetTimeout(fragmentKey, ipHeader);
409 fragments->SetTimeoutIter(iter);
410 }
411 else
412 {
413 fragments = it->second;
414 }
415
416 if (fragmentOffset == 0)
417 {
418 Ptr<Packet> unfragmentablePart = packet->Copy();
419 unfragmentablePart->RemoveAtEnd(packet->GetSize() - offset);
420 fragments->SetUnfragmentablePart(unfragmentablePart);
421 }
422
423 NS_LOG_DEBUG("Add fragment with IP hdr id " << identification << " offset " << fragmentOffset);
424 fragments->AddFragment(p, fragmentOffset, moreFragment);
425
426 if (fragments->IsEntire())
427 {
428 packet = fragments->GetPacket();
429 m_timeoutEventList.erase(fragments->GetTimeoutIter());
430 m_fragments.erase(fragmentKey);
431 NS_LOG_DEBUG("Finished fragment with IP hdr id "
432 << fragmentKey.second
433 << " erase timeout, m_fragments.size(): " << m_fragments.size());
434 stopProcessing = false;
435 }
436 else
437 {
438 stopProcessing = true;
439 }
440
441 return 0;
442}
443
444void
446 Ipv6Header ipv6Header,
447 uint32_t maxFragmentSize,
448 std::list<Ipv6PayloadHeaderPair>& listFragments)
449{
450 NS_LOG_FUNCTION(this << packet << ipv6Header << maxFragmentSize);
451 Ptr<Packet> p = packet->Copy();
452
453 uint8_t nextHeader = ipv6Header.GetNextHeader();
454 uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize();
455
456 uint8_t type;
457 p->CopyData(&type, sizeof(type));
458
459 bool moreHeader = true;
460 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
461 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
463 {
464 moreHeader = false;
466 }
467
468 std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>> unfragmentablePart;
469 uint32_t unfragmentablePartSize = 0;
470
472 Ptr<Ipv6Extension> extension = extensionDemux->GetExtension(nextHeader);
473 uint8_t extensionHeaderLength;
474
475 while (moreHeader)
476 {
477 if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
478 {
479 auto hopbyhopHeader = new Ipv6ExtensionHopByHopHeader();
480 p->RemoveHeader(*hopbyhopHeader);
481
482 nextHeader = hopbyhopHeader->GetNextHeader();
483 extensionHeaderLength = hopbyhopHeader->GetLength();
484
485 uint8_t type;
486 p->CopyData(&type, sizeof(type));
487
488 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
489 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
490 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
492 {
493 moreHeader = false;
494 hopbyhopHeader->SetNextHeader(Ipv6Header::IPV6_EXT_FRAGMENTATION);
495 }
496
497 unfragmentablePart.emplace_back(hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP);
498 unfragmentablePartSize += extensionHeaderLength;
499 }
500 else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
501 {
502 Ptr<Ipv6ExtensionRoutingDemux> ipv6ExtensionRoutingDemux =
504
505 uint8_t buf[4];
506 p->CopyData(buf, sizeof(buf));
507 uint8_t routingType = buf[2];
508
509 Ipv6ExtensionRoutingHeader* routingHeader =
510 ipv6ExtensionRoutingDemux->GetExtensionRoutingHeaderPtr(routingType);
511
512 p->RemoveHeader(*routingHeader);
513
514 nextHeader = routingHeader->GetNextHeader();
515 extensionHeaderLength = routingHeader->GetLength();
516
517 uint8_t type;
518 p->CopyData(&type, sizeof(type));
519 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
520 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
521 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
523 {
524 moreHeader = false;
526 }
527
528 unfragmentablePart.emplace_back(routingHeader, Ipv6Header::IPV6_EXT_ROUTING);
529 unfragmentablePartSize += extensionHeaderLength;
530 }
531 else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
532 {
533 auto destinationHeader = new Ipv6ExtensionDestinationHeader();
534 p->RemoveHeader(*destinationHeader);
535
536 nextHeader = destinationHeader->GetNextHeader();
537 extensionHeaderLength = destinationHeader->GetLength();
538
539 uint8_t type;
540 p->CopyData(&type, sizeof(type));
541 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
542 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
543 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
545 {
546 moreHeader = false;
547 destinationHeader->SetNextHeader(Ipv6Header::IPV6_EXT_FRAGMENTATION);
548 }
549
550 unfragmentablePart.emplace_back(destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION);
551 unfragmentablePartSize += extensionHeaderLength;
552 }
553 }
554
555 Ipv6ExtensionFragmentHeader fragmentHeader;
556 uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize();
557
558 uint32_t maxFragmentablePartSize =
559 maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
560 uint32_t currentFragmentablePartSize = 0;
561
562 bool moreFragment = true;
563 auto identification = (uint32_t)m_uvar->GetValue(0, (uint32_t)-1);
564 uint16_t offset = 0;
565
566 do
567 {
568 if (p->GetSize() > offset + maxFragmentablePartSize)
569 {
570 moreFragment = true;
571 currentFragmentablePartSize = maxFragmentablePartSize;
572 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
573 }
574 else
575 {
576 moreFragment = false;
577 currentFragmentablePartSize = p->GetSize() - offset;
578 }
579
580 fragmentHeader.SetNextHeader(nextHeader);
581 fragmentHeader.SetOffset(offset);
582 fragmentHeader.SetMoreFragment(moreFragment);
583 fragmentHeader.SetIdentification(identification);
584
585 Ptr<Packet> fragment = p->CreateFragment(offset, currentFragmentablePartSize);
586 offset += currentFragmentablePartSize;
587
588 fragment->AddHeader(fragmentHeader);
589
590 for (auto it = unfragmentablePart.begin(); it != unfragmentablePart.end(); it++)
591 {
592 if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
593 {
594 auto p = dynamic_cast<Ipv6ExtensionHopByHopHeader*>(it->first);
595 NS_ASSERT(p != nullptr);
596 fragment->AddHeader(*p);
597 }
598 else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
599 {
600 auto p = dynamic_cast<Ipv6ExtensionLooseRoutingHeader*>(it->first);
601 NS_ASSERT(p != nullptr);
602 fragment->AddHeader(*p);
603 }
604 else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
605 {
606 auto p = dynamic_cast<Ipv6ExtensionDestinationHeader*>(it->first);
607 NS_ASSERT(p != nullptr);
608 fragment->AddHeader(*p);
609 }
610 }
611
612 ipv6Header.SetPayloadLength(fragment->GetSize());
613
614 std::ostringstream oss;
615 oss << ipv6Header;
616 fragment->Print(oss);
617
618 listFragments.emplace_back(fragment, ipv6Header);
619 } while (moreFragment);
620
621 for (auto it = unfragmentablePart.begin(); it != unfragmentablePart.end(); it++)
622 {
623 delete it->first;
624 }
625
626 unfragmentablePart.clear();
627}
628
629void
631{
632 NS_LOG_FUNCTION(this << fragmentKey.first << fragmentKey.second << ipHeader);
633 Ptr<Fragments> fragments;
634
635 auto it = m_fragments.find(fragmentKey);
636 NS_ASSERT_MSG(it != m_fragments.end(),
637 "IPv6 Fragment timeout reached for non-existent fragment");
638 fragments = it->second;
639
640 Ptr<Packet> packet = fragments->GetPartialPacket();
641
642 // if we have at least 8 bytes, we can send an ICMP.
643 if (packet && packet->GetSize() > 8)
644 {
645 Ptr<Packet> p = packet->Copy();
646 p->AddHeader(ipHeader);
648 icmp->SendErrorTimeExceeded(p, ipHeader.GetSource(), Icmpv6Header::ICMPV6_FRAGTIME);
649 }
650
652 ipL3->ReportDrop(ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
653
654 // clear the buffers
655 m_fragments.erase(fragmentKey);
656}
657
660{
661 NS_LOG_FUNCTION(this << key.first << key.second << ipHeader);
662 if (m_timeoutEventList.empty())
663 {
664 NS_LOG_DEBUG("Scheduling timeout for IP hdr id "
665 << key.second << " at time "
666 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds());
669 this);
670 }
671 NS_LOG_DEBUG("Adding timeout at "
672 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds() << " with key "
673 << key.second);
674 m_timeoutEventList.emplace_back(Simulator::Now() + m_fragmentExpirationTimeout, key, ipHeader);
675
676 auto iter = --m_timeoutEventList.end();
677
678 return iter;
679}
680
681void
683{
684 NS_LOG_FUNCTION(this);
685 Time now = Simulator::Now();
686
687 // std::list Time, Fragment_key_t, Ipv6Header
688 // Fragment key is a pair: Ipv6Address, uint32_t ipHeaderId
689 for (auto& element : m_timeoutEventList)
690 {
691 NS_LOG_DEBUG("Handle time " << std::get<0>(element).GetSeconds() << " IP hdr id "
692 << std::get<1>(element).second);
693 }
694 while (!m_timeoutEventList.empty() && std::get<0>(*m_timeoutEventList.begin()) == now)
695 {
696 HandleFragmentsTimeout(std::get<1>(*m_timeoutEventList.begin()),
697 std::get<2>(*m_timeoutEventList.begin()));
698 m_timeoutEventList.pop_front();
699 }
700
701 if (m_timeoutEventList.empty())
702 {
703 return;
704 }
705
706 Time difference = std::get<0>(*m_timeoutEventList.begin()) - now;
707 NS_LOG_DEBUG("Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
709}
710
712 : m_moreFragment(false)
713{
714}
715
719
720void
722 uint16_t fragmentOffset,
723 bool moreFragment)
724{
725 NS_LOG_FUNCTION(this << fragment << fragmentOffset << moreFragment);
726 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
727
728 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
729 {
730 if (it->second > fragmentOffset)
731 {
732 break;
733 }
734 }
735
736 if (it == m_packetFragments.end())
737 {
738 m_moreFragment = moreFragment;
739 }
740
741 m_packetFragments.insert(it, std::pair<Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
742}
743
744void
746{
747 NS_LOG_FUNCTION(this << unfragmentablePart);
748 m_unfragmentable = unfragmentablePart;
749}
750
751bool
753{
754 bool ret = !m_moreFragment && !m_packetFragments.empty();
755
756 if (ret)
757 {
758 uint16_t lastEndOffset = 0;
759
760 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
761 {
762 if (lastEndOffset != it->second)
763 {
764 ret = false;
765 break;
766 }
767
768 lastEndOffset += it->first->GetSize();
769 }
770 }
771
772 return ret;
773}
774
777{
778 Ptr<Packet> p = m_unfragmentable->Copy();
779
780 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
781 {
782 p->AddAtEnd(it->first);
783 }
784
785 return p;
786}
787
790{
791 Ptr<Packet> p;
792
793 if (m_unfragmentable)
794 {
795 p = m_unfragmentable->Copy();
796 }
797 else
798 {
799 return p;
800 }
801
802 uint16_t lastEndOffset = 0;
803
804 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
805 {
806 if (lastEndOffset != it->second)
807 {
808 break;
809 }
810 p->AddAtEnd(it->first);
811 lastEndOffset += it->first->GetSize();
812 }
813
814 return p;
815}
816
817void
823
826{
827 return m_timeoutIter;
828}
829
831
832TypeId
834{
835 static TypeId tid = TypeId("ns3::Ipv6ExtensionRouting")
837 .SetGroupName("Internet")
838 .AddConstructor<Ipv6ExtensionRouting>();
839 return tid;
840}
841
845
849
850uint8_t
855
856uint8_t
858{
859 return 0;
860}
861
867
868uint8_t
870 uint8_t offset,
871 const Ipv6Header& ipv6Header,
872 Ipv6Address dst,
873 uint8_t* nextHeader,
874 bool& stopProcessing,
875 bool& isDropped,
876 Ipv6L3Protocol::DropReason& dropReason)
877{
878 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
879
880 // For ICMPv6 Error Packets
881 Ptr<Packet> malformedPacket = packet->Copy();
882 malformedPacket->AddHeader(ipv6Header);
883
884 Ptr<Packet> p = packet->Copy();
885 p->RemoveAtStart(offset);
886
887 uint8_t buf[4];
888 packet->CopyData(buf, sizeof(buf));
889
890 uint8_t routingNextHeader = buf[0];
891 uint8_t routingLength = buf[1];
892 uint8_t routingTypeRouting = buf[2];
893 uint8_t routingSegmentsLeft = buf[3];
894
895 if (nextHeader)
896 {
897 *nextHeader = routingNextHeader;
898 }
899
900 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
901
902 Ptr<Ipv6ExtensionRoutingDemux> ipv6ExtensionRoutingDemux =
904 Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting =
905 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
906
907 if (!ipv6ExtensionRouting)
908 {
909 if (routingSegmentsLeft == 0)
910 {
911 isDropped = false;
912 }
913 else
914 {
915 NS_LOG_LOGIC("Malformed header. Drop!");
916
917 icmpv6->SendErrorParameterError(malformedPacket,
918 ipv6Header.GetSource(),
920 offset + 1);
922 isDropped = true;
923 stopProcessing = true;
924 }
925
926 return routingLength;
927 }
928
929 return ipv6ExtensionRouting->Process(packet,
930 offset,
931 ipv6Header,
932 dst,
933 (uint8_t*)nullptr,
934 stopProcessing,
935 isDropped,
936 dropReason);
937}
938
940
941TypeId
943{
944 static TypeId tid =
945 TypeId("ns3::Ipv6ExtensionRoutingDemux")
946 .SetParent<Object>()
947 .SetGroupName("Internet")
948 .AddAttribute("RoutingExtensions",
949 "The set of IPv6 Routing extensions registered with this demux.",
953 return tid;
954}
955
959
963
964void
966{
967 NS_LOG_FUNCTION(this);
968 for (auto it = m_extensionsRouting.begin(); it != m_extensionsRouting.end(); it++)
969 {
970 (*it)->Dispose();
971 *it = nullptr;
972 }
973 m_extensionsRouting.clear();
974 m_node = nullptr;
976}
977
978void
980{
981 NS_LOG_FUNCTION(this << node);
982 m_node = node;
983}
984
985void
987{
988 NS_LOG_FUNCTION(this << extensionRouting);
989 m_extensionsRouting.push_back(extensionRouting);
990}
991
994{
995 for (const auto& extRouting : m_extensionsRouting)
996 {
997 if (extRouting->GetTypeRouting() == typeRouting)
998 {
999 return extRouting;
1000 }
1001 }
1002
1003 return nullptr;
1004}
1005
1008{
1009 NS_LOG_FUNCTION(this << typeRouting);
1010
1011 for (const auto& extRouting : m_extensionsRouting)
1012 {
1013 if (extRouting->GetTypeRouting() == typeRouting)
1014 {
1015 return extRouting->GetExtensionRoutingHeaderPtr();
1016 }
1017 }
1018
1019 return nullptr;
1020}
1021
1022void
1024{
1025 NS_LOG_FUNCTION(this << extensionRouting);
1026 m_extensionsRouting.remove(extensionRouting);
1027}
1028
1030
1031TypeId
1033{
1034 static TypeId tid = TypeId("ns3::Ipv6ExtensionLooseRouting")
1036 .SetGroupName("Internet")
1037 .AddConstructor<Ipv6ExtensionLooseRouting>();
1038 return tid;
1039}
1040
1044
1048
1049uint8_t
1051{
1052 return TYPE_ROUTING;
1053}
1054
1060
1061uint8_t
1063 uint8_t offset,
1064 const Ipv6Header& ipv6Header,
1065 Ipv6Address dst,
1066 uint8_t* nextHeader,
1067 bool& stopProcessing,
1068 bool& isDropped,
1069 Ipv6L3Protocol::DropReason& dropReason)
1070{
1071 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1072
1073 // For ICMPv6 Error packets
1074 Ptr<Packet> malformedPacket = packet->Copy();
1075 malformedPacket->AddHeader(ipv6Header);
1076
1077 Ptr<Packet> p = packet->Copy();
1078 p->RemoveAtStart(offset);
1079
1080 // Copy IPv6 Header : ipv6Header -> ipv6header
1081 Buffer tmp;
1082 tmp.AddAtStart(ipv6Header.GetSerializedSize());
1083 Buffer::Iterator it = tmp.Begin();
1084 Ipv6Header ipv6header;
1085 ipv6Header.Serialize(it);
1086 ipv6header.Deserialize(it);
1087
1088 // Get the number of routers' address field
1089 uint8_t buf[2];
1090 p->CopyData(buf, sizeof(buf));
1091 Ipv6ExtensionLooseRoutingHeader routingHeader;
1092 p->RemoveHeader(routingHeader);
1093
1094 if (nextHeader)
1095 {
1096 *nextHeader = routingHeader.GetNextHeader();
1097 }
1098
1099 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
1100
1101 Ipv6Address srcAddress = ipv6header.GetSource();
1102 Ipv6Address destAddress = ipv6header.GetDestination();
1103 uint8_t hopLimit = ipv6header.GetHopLimit();
1104 uint8_t segmentsLeft = routingHeader.GetSegmentsLeft();
1105 uint8_t length = (routingHeader.GetLength() >> 3) - 1;
1106 uint8_t nbAddress = length / 2;
1107 uint8_t nextAddressIndex;
1108 Ipv6Address nextAddress;
1109
1110 if (segmentsLeft == 0)
1111 {
1112 isDropped = false;
1113 return routingHeader.GetSerializedSize();
1114 }
1115
1116 if (length % 2 != 0)
1117 {
1118 NS_LOG_LOGIC("Malformed header. Drop!");
1119 icmpv6->SendErrorParameterError(malformedPacket,
1120 srcAddress,
1122 offset + 1);
1124 isDropped = true;
1125 stopProcessing = true;
1126 return routingHeader.GetSerializedSize();
1127 }
1128
1129 if (segmentsLeft > nbAddress)
1130 {
1131 NS_LOG_LOGIC("Malformed header. Drop!");
1132 icmpv6->SendErrorParameterError(malformedPacket,
1133 srcAddress,
1135 offset + 3);
1137 isDropped = true;
1138 stopProcessing = true;
1139 return routingHeader.GetSerializedSize();
1140 }
1141
1142 routingHeader.SetSegmentsLeft(segmentsLeft - 1);
1143 nextAddressIndex = nbAddress - segmentsLeft;
1144 nextAddress = routingHeader.GetRouterAddress(nextAddressIndex);
1145
1146 if (nextAddress.IsMulticast() || destAddress.IsMulticast())
1147 {
1149 isDropped = true;
1150 stopProcessing = true;
1151 return routingHeader.GetSerializedSize();
1152 }
1153
1154 routingHeader.SetRouterAddress(nextAddressIndex, destAddress);
1155 ipv6header.SetDestination(nextAddress);
1156
1157 if (hopLimit <= 1)
1158 {
1159 NS_LOG_LOGIC("Time Exceeded : Hop Limit <= 1. Drop!");
1160 icmpv6->SendErrorTimeExceeded(malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
1162 isDropped = true;
1163 stopProcessing = true;
1164 return routingHeader.GetSerializedSize();
1165 }
1166
1167 ipv6header.SetHopLimit(hopLimit - 1);
1168 p->AddHeader(routingHeader);
1169
1170 /* short-circuiting routing stuff
1171 *
1172 * If we process this option,
1173 * the packet was for us so we resend it to
1174 * the new destination (modified in the header above).
1175 */
1176
1178 Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol();
1180 NS_ASSERT(ipv6rp);
1181
1182 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header, nullptr, err);
1183
1184 if (rtentry)
1185 {
1186 /* we know a route exists so send packet now */
1187 ipv6->SendRealOut(rtentry, p, ipv6header);
1188 }
1189 else
1190 {
1191 NS_LOG_INFO("No route for next router");
1192 }
1193
1194 /* as we directly send packet, mark it as dropped */
1195 isDropped = true;
1196
1197 return routingHeader.GetSerializedSize();
1198}
1199
1201
1202TypeId
1204{
1205 static TypeId tid = TypeId("ns3::Ipv6ExtensionESP")
1207 .SetGroupName("Internet")
1208 .AddConstructor<Ipv6ExtensionESP>();
1209 return tid;
1210}
1211
1215
1219
1220uint8_t
1222{
1223 return EXT_NUMBER;
1224}
1225
1226uint8_t
1228 uint8_t offset,
1229 const Ipv6Header& ipv6Header,
1230 Ipv6Address dst,
1231 uint8_t* nextHeader,
1232 bool& stopProcessing,
1233 bool& isDropped,
1234 Ipv6L3Protocol::DropReason& dropReason)
1235{
1236 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1237
1238 /** @todo */
1239
1240 return 0;
1241}
1242
1244
1245TypeId
1247{
1248 static TypeId tid = TypeId("ns3::Ipv6ExtensionAH")
1250 .SetGroupName("Internet")
1251 .AddConstructor<Ipv6ExtensionAH>();
1252 return tid;
1253}
1254
1258
1262
1263uint8_t
1265{
1266 return EXT_NUMBER;
1267}
1268
1269uint8_t
1271 uint8_t offset,
1272 const Ipv6Header& ipv6Header,
1273 Ipv6Address dst,
1274 uint8_t* nextHeader,
1275 bool& stopProcessing,
1276 bool& isDropped,
1277 Ipv6L3Protocol::DropReason& dropReason)
1278{
1279 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1280
1281 /** @todo */
1282
1283 return 1;
1284}
1285
1286} /* namespace ns3 */
iterator in a Buffer instance
Definition buffer.h:89
automatically resized byte buffer
Definition buffer.h:83
void AddAtStart(uint32_t start)
Definition buffer.cc:303
Buffer::Iterator Begin() const
Definition buffer.h:1063
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
An implementation of the ICMPv6 protocol.
Describes an IPv6 address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
IPv6 Extension AH (Authentication Header)
~Ipv6ExtensionAH() override
Destructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
static TypeId GetTypeId()
Get the type identificator.
uint8_t GetExtensionNumber() const override
Get the extension number.
Ipv6ExtensionAH()
Constructor.
Demultiplexes IPv6 extensions.
Header of IPv6 Extension Destination.
IPv6 Extension Destination.
uint8_t GetExtensionNumber() const override
Get the extension number.
static const uint8_t EXT_NUMBER
Destination extension number.
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionDestination() override
Destructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
IPv6 Extension ESP (Encapsulating Security Payload)
~Ipv6ExtensionESP() override
Destructor.
Ipv6ExtensionESP()
Constructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
uint8_t GetExtensionNumber() const override
Get the extension number.
static TypeId GetTypeId()
Get the type identificator.
Ptr< Packet > GetPartialPacket() const
Get the packet parts so far received.
Ptr< Packet > GetPacket() const
Get the entire packet.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
void SetUnfragmentablePart(Ptr< Packet > unfragmentablePart)
Set the unfragmentable part of the packet.
bool IsEntire() const
If all fragments have been added.
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
Header of IPv6 Extension Fragment.
void SetIdentification(uint32_t identification)
Set the "Identification" field.
void SetOffset(uint16_t offset)
Set the "Offset" field.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
uint16_t GetOffset() const
Get the field "Offset".
bool GetMoreFragment() const
Get the status of "More Fragment" bit.
uint32_t GetIdentification() const
Get the field "Identification".
void SetMoreFragment(bool moreFragment)
Set the status of "More Fragment" bit.
IPv6 Extension Fragment.
Time m_fragmentExpirationTimeout
Expiration timeout.
void HandleTimeout()
Handles a fragmented packet timeout.
static TypeId GetTypeId()
Get the type identificator.
void GetFragments(Ptr< Packet > packet, Ipv6Header ipv6Header, uint32_t fragmentSize, std::list< Ipv6PayloadHeaderPair > &listFragments)
Fragment a packet.
std::pair< Ipv6Address, uint32_t > FragmentKey_t
Key identifying a fragmented packet.
EventId m_timeoutEvent
Event for the next scheduled timeout.
MapFragments_t m_fragments
The hash of fragmented packets.
void DoDispose() override
Dispose this object.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
std::list< std::tuple< Time, FragmentKey_t, Ipv6Header > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
~Ipv6ExtensionFragment() override
Destructor.
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
void HandleFragmentsTimeout(FragmentKey_t key, Ipv6Header ipHeader)
Process the timeout for packet fragments.
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, Ipv6Header ipHeader)
Set a new timeout "event" for a fragmented packet.
uint8_t GetExtensionNumber() const override
Get the extension number.
static const uint8_t EXT_NUMBER
Fragmentation extension number.
uint16_t GetLength() const
Get the length of the extension.
void SetNextHeader(uint8_t nextHeader)
Set the "Next header" field.
uint8_t GetNextHeader() const
Get the next header.
Header of IPv6 Extension "Hop by Hop".
IPv6 Extension "Hop By Hop".
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionHopByHop() override
Destructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
static const uint8_t EXT_NUMBER
Hop-by-hop extension number.
uint8_t GetExtensionNumber() const override
Get the extension number.
IPv6 Extension base If you want to implement a new IPv6 extension, all you have to do is implement a ...
Ptr< Node > GetNode() const
Get the node.
virtual uint8_t ProcessOptions(Ptr< Packet > &packet, uint8_t offset, uint8_t length, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process options Called by implementing classes to process the options.
virtual uint8_t GetExtensionNumber() const =0
Get the extension number.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Ptr< Node > m_node
The node.
void SetNode(Ptr< Node > node)
Set the node.
Ptr< UniformRandomVariable > m_uvar
Provides uniform random variables.
~Ipv6Extension() override
Destructor.
Ipv6Extension()
Constructor.
static TypeId GetTypeId()
Get the type identificator.
Header of IPv6 Extension Routing : Type 0 (Loose Routing)
Ipv6Address GetRouterAddress(uint8_t index) const
Get a Router IPv6 Address.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
void SetRouterAddress(uint8_t index, Ipv6Address addr)
Set a Router IPv6 Address.
IPv6 Extension Loose Routing.
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionLooseRouting() override
Destructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
uint8_t GetTypeRouting() const override
Get the type of routing.
Ipv6ExtensionRoutingHeader * GetExtensionRoutingHeaderPtr() override
Get a pointer to a new routing extension header.
IPv6 Extension Routing Demux.
void DoDispose() override
Dispose this object.
void Insert(Ptr< Ipv6ExtensionRouting > extensionRouting)
Insert a new IPv6 Routing Extension.
static TypeId GetTypeId()
The interface ID.
void SetNode(Ptr< Node > node)
Set the node.
Ptr< Ipv6ExtensionRouting > GetExtensionRouting(uint8_t typeRouting)
Get the routing extension corresponding to typeRouting.
void Remove(Ptr< Ipv6ExtensionRouting > extensionRouting)
Remove a routing extension from this demux.
Ipv6ExtensionRoutingList_t m_extensionsRouting
List of IPv6 Routing Extensions supported.
Ipv6ExtensionRoutingHeader * GetExtensionRoutingHeaderPtr(uint8_t typeRouting)
Get a pointer to a new routing extension header corresponding to typeRouting.
~Ipv6ExtensionRoutingDemux() override
Destructor.
Header of IPv6 Extension Routing.
uint8_t GetSegmentsLeft() const
Get the field "Segments left".
void SetSegmentsLeft(uint8_t segmentsLeft)
Set the "Segments left" field.
IPv6 Extension Routing.
uint8_t GetExtensionNumber() const override
Get the extension number.
~Ipv6ExtensionRouting() override
Destructor.
virtual Ipv6ExtensionRoutingHeader * GetExtensionRoutingHeaderPtr()
Get a pointer to a new routing extension header.
static TypeId GetTypeId()
Get the type identificator.
virtual uint8_t GetTypeRouting() const
Get the type of routing.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
Packet header for IPv6.
Definition ipv6-header.h:24
void SetDestination(Ipv6Address dst)
Set the "Destination 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.
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 Serialize(Buffer::Iterator start) const override
Serialize the packet.
uint32_t Deserialize(Buffer::Iterator start) override
Deserialize the packet.
void SetNextHeader(uint8_t next)
Set the "Next header" field.
IPv6 layer implementation.
DropReason
Reason why a packet has been dropped.
@ DROP_FRAGMENT_TIMEOUT
Fragment timeout.
@ DROP_UNKNOWN_OPTION
Unknown option.
@ DROP_MALFORMED_HEADER
Malformed header.
IPv6 Option Demux.
A base class which provides memory management and object aggregation.
Definition object.h:78
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
uint32_t GetOptionsOffset() const
Get the offset where the options begin, measured from the start of the extension header.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition socket.h:73
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
AttributeValue implementation for Time.
Definition nstime.h:1431
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 > MakeObjectVectorChecker()
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1432
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1452
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_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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_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
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint8_t data[writeSize]