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
36
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();
353 if (m_timeoutEvent.IsPending())
354 {
355 m_timeoutEvent.Cancel();
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 std::shared_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 = std::make_shared<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
634 auto it = m_fragments.find(fragmentKey);
635 NS_ASSERT_MSG(it != m_fragments.end(),
636 "IPv6 Fragment timeout reached for non-existent fragment");
637
638 std::shared_ptr<Fragments> fragments = it->second;
639 Ptr<Packet> packet = fragments->GetPartialPacket();
640
641 // if we have at least 8 bytes, we can send an ICMP.
642 if (packet && packet->GetSize() > 8)
643 {
644 Ptr<Packet> p = packet->Copy();
645 p->AddHeader(ipHeader);
647 icmp->SendErrorTimeExceeded(p, ipHeader.GetSource(), Icmpv6Header::ICMPV6_FRAGTIME);
648 }
649
651 ipL3->ReportDrop(ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
652
653 // clear the buffers
654 m_fragments.erase(fragmentKey);
655}
656
659{
660 NS_LOG_FUNCTION(this << key.first << key.second << ipHeader);
661 if (m_timeoutEventList.empty())
662 {
663 NS_LOG_DEBUG("Scheduling timeout for IP hdr id "
664 << key.second << " at time "
665 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds());
668 this);
669 }
670 NS_LOG_DEBUG("Adding timeout at "
671 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds() << " with key "
672 << key.second);
673 m_timeoutEventList.emplace_back(Simulator::Now() + m_fragmentExpirationTimeout, key, ipHeader);
674
675 auto iter = --m_timeoutEventList.end();
676
677 return iter;
678}
679
680void
682{
683 NS_LOG_FUNCTION(this);
684 Time now = Simulator::Now();
685
686 // std::list Time, Fragment_key_t, Ipv6Header
687 // Fragment key is a pair: Ipv6Address, uint32_t ipHeaderId
688 for (auto& element : m_timeoutEventList)
689 {
690 NS_LOG_DEBUG("Handle time " << std::get<0>(element).GetSeconds() << " IP hdr id "
691 << std::get<1>(element).second);
692 }
693 while (!m_timeoutEventList.empty() && std::get<0>(*m_timeoutEventList.begin()) == now)
694 {
695 HandleFragmentsTimeout(std::get<1>(*m_timeoutEventList.begin()),
696 std::get<2>(*m_timeoutEventList.begin()));
697 m_timeoutEventList.pop_front();
698 }
699
700 if (m_timeoutEventList.empty())
701 {
702 return;
703 }
704
705 Time difference = std::get<0>(*m_timeoutEventList.begin()) - now;
706 NS_LOG_DEBUG("Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
708}
709
714
718
719void
721 uint16_t fragmentOffset,
722 bool moreFragment)
723{
724 NS_LOG_FUNCTION(this << fragment << fragmentOffset << moreFragment);
725 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
726
727 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
728 {
729 if (it->second > fragmentOffset)
730 {
731 break;
732 }
733 }
734
735 if (it == m_packetFragments.end())
736 {
737 m_moreFragment = moreFragment;
738 }
739
740 m_packetFragments.insert(it, std::pair<Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
741}
742
743void
745{
746 NS_LOG_FUNCTION(this << unfragmentablePart);
747 m_unfragmentable = unfragmentablePart;
748}
749
750bool
752{
753 bool ret = !m_moreFragment && !m_packetFragments.empty();
754
755 if (ret)
756 {
757 uint16_t lastEndOffset = 0;
758
759 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
760 {
761 if (lastEndOffset != it->second)
762 {
763 ret = false;
764 break;
765 }
766
767 lastEndOffset += it->first->GetSize();
768 }
769 }
770
771 return ret;
772}
773
776{
777 Ptr<Packet> p = m_unfragmentable->Copy();
778
779 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
780 {
781 p->AddAtEnd(it->first);
782 }
783
784 return p;
785}
786
789{
790 Ptr<Packet> p;
791
793 {
794 p = m_unfragmentable->Copy();
795 }
796 else
797 {
798 return p;
799 }
800
801 uint16_t lastEndOffset = 0;
802
803 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
804 {
805 if (lastEndOffset != it->second)
806 {
807 break;
808 }
809 p->AddAtEnd(it->first);
810 lastEndOffset += it->first->GetSize();
811 }
812
813 return p;
814}
815
816void
822
828
830
831TypeId
833{
834 static TypeId tid = TypeId("ns3::Ipv6ExtensionRouting")
836 .SetGroupName("Internet")
837 .AddConstructor<Ipv6ExtensionRouting>();
838 return tid;
839}
840
844
848
849uint8_t
854
855uint8_t
857{
858 return 0;
859}
860
866
867uint8_t
869 uint8_t offset,
870 const Ipv6Header& ipv6Header,
871 Ipv6Address dst,
872 uint8_t* nextHeader,
873 bool& stopProcessing,
874 bool& isDropped,
875 Ipv6L3Protocol::DropReason& dropReason)
876{
877 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
878
879 // For ICMPv6 Error Packets
880 Ptr<Packet> malformedPacket = packet->Copy();
881 malformedPacket->AddHeader(ipv6Header);
882
883 Ptr<Packet> p = packet->Copy();
884 p->RemoveAtStart(offset);
885
886 uint8_t buf[4];
887 packet->CopyData(buf, sizeof(buf));
888
889 uint8_t routingNextHeader = buf[0];
890 uint8_t routingLength = buf[1];
891 uint8_t routingTypeRouting = buf[2];
892 uint8_t routingSegmentsLeft = buf[3];
893
894 if (nextHeader)
895 {
896 *nextHeader = routingNextHeader;
897 }
898
899 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
900
901 Ptr<Ipv6ExtensionRoutingDemux> ipv6ExtensionRoutingDemux =
903 Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting =
904 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
905
906 if (!ipv6ExtensionRouting)
907 {
908 if (routingSegmentsLeft == 0)
909 {
910 isDropped = false;
911 }
912 else
913 {
914 NS_LOG_LOGIC("Malformed header. Drop!");
915
916 icmpv6->SendErrorParameterError(malformedPacket,
917 ipv6Header.GetSource(),
919 offset + 1);
921 isDropped = true;
922 stopProcessing = true;
923 }
924
925 return routingLength;
926 }
927
928 return ipv6ExtensionRouting->Process(packet,
929 offset,
930 ipv6Header,
931 dst,
932 (uint8_t*)nullptr,
933 stopProcessing,
934 isDropped,
935 dropReason);
936}
937
939
940TypeId
942{
943 static TypeId tid =
944 TypeId("ns3::Ipv6ExtensionRoutingDemux")
945 .SetParent<Object>()
946 .SetGroupName("Internet")
947 .AddAttribute("RoutingExtensions",
948 "The set of IPv6 Routing extensions registered with this demux.",
952 return tid;
953}
954
958
962
963void
965{
966 NS_LOG_FUNCTION(this);
967 for (auto it = m_extensionsRouting.begin(); it != m_extensionsRouting.end(); it++)
968 {
969 (*it)->Dispose();
970 *it = nullptr;
971 }
972 m_extensionsRouting.clear();
973 m_node = nullptr;
975}
976
977void
979{
980 NS_LOG_FUNCTION(this << node);
981 m_node = node;
982}
983
984void
986{
987 NS_LOG_FUNCTION(this << extensionRouting);
988 m_extensionsRouting.push_back(extensionRouting);
989}
990
993{
994 for (const auto& extRouting : m_extensionsRouting)
995 {
996 if (extRouting->GetTypeRouting() == typeRouting)
997 {
998 return extRouting;
999 }
1000 }
1001
1002 return nullptr;
1003}
1004
1007{
1008 NS_LOG_FUNCTION(this << typeRouting);
1009
1010 for (const auto& extRouting : m_extensionsRouting)
1011 {
1012 if (extRouting->GetTypeRouting() == typeRouting)
1013 {
1014 return extRouting->GetExtensionRoutingHeaderPtr();
1015 }
1016 }
1017
1018 return nullptr;
1019}
1020
1021void
1023{
1024 NS_LOG_FUNCTION(this << extensionRouting);
1025 m_extensionsRouting.remove(extensionRouting);
1026}
1027
1028int64_t
1030{
1031 int64_t currentStream = stream;
1032 for (auto& extension : m_extensionsRouting)
1033 {
1034 currentStream += extension->AssignStreams(currentStream);
1035 }
1036 return currentStream - stream;
1037}
1038
1040
1041TypeId
1043{
1044 static TypeId tid = TypeId("ns3::Ipv6ExtensionLooseRouting")
1046 .SetGroupName("Internet")
1047 .AddConstructor<Ipv6ExtensionLooseRouting>();
1048 return tid;
1049}
1050
1054
1058
1059uint8_t
1064
1070
1071uint8_t
1073 uint8_t offset,
1074 const Ipv6Header& ipv6Header,
1075 Ipv6Address dst,
1076 uint8_t* nextHeader,
1077 bool& stopProcessing,
1078 bool& isDropped,
1079 Ipv6L3Protocol::DropReason& dropReason)
1080{
1081 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1082
1083 // For ICMPv6 Error packets
1084 Ptr<Packet> malformedPacket = packet->Copy();
1085 malformedPacket->AddHeader(ipv6Header);
1086
1087 Ptr<Packet> p = packet->Copy();
1088 p->RemoveAtStart(offset);
1089
1090 // Copy IPv6 Header : ipv6Header -> ipv6header
1091 Buffer tmp;
1092 tmp.AddAtStart(ipv6Header.GetSerializedSize());
1093 Buffer::Iterator it = tmp.Begin();
1094 Ipv6Header ipv6header;
1095 ipv6Header.Serialize(it);
1096 ipv6header.Deserialize(it);
1097
1098 // Get the number of routers' address field
1099 uint8_t buf[2];
1100 p->CopyData(buf, sizeof(buf));
1101 Ipv6ExtensionLooseRoutingHeader routingHeader;
1102 p->RemoveHeader(routingHeader);
1103
1104 if (nextHeader)
1105 {
1106 *nextHeader = routingHeader.GetNextHeader();
1107 }
1108
1109 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
1110
1111 Ipv6Address srcAddress = ipv6header.GetSource();
1112 Ipv6Address destAddress = ipv6header.GetDestination();
1113 uint8_t hopLimit = ipv6header.GetHopLimit();
1114 uint8_t segmentsLeft = routingHeader.GetSegmentsLeft();
1115 uint8_t length = (routingHeader.GetLength() >> 3) - 1;
1116 uint8_t nbAddress = length / 2;
1117 uint8_t nextAddressIndex;
1118 Ipv6Address nextAddress;
1119
1120 if (segmentsLeft == 0)
1121 {
1122 isDropped = false;
1123 return routingHeader.GetSerializedSize();
1124 }
1125
1126 if (length % 2 != 0)
1127 {
1128 NS_LOG_LOGIC("Malformed header. Drop!");
1129 icmpv6->SendErrorParameterError(malformedPacket,
1130 srcAddress,
1132 offset + 1);
1134 isDropped = true;
1135 stopProcessing = true;
1136 return routingHeader.GetSerializedSize();
1137 }
1138
1139 if (segmentsLeft > nbAddress)
1140 {
1141 NS_LOG_LOGIC("Malformed header. Drop!");
1142 icmpv6->SendErrorParameterError(malformedPacket,
1143 srcAddress,
1145 offset + 3);
1147 isDropped = true;
1148 stopProcessing = true;
1149 return routingHeader.GetSerializedSize();
1150 }
1151
1152 routingHeader.SetSegmentsLeft(segmentsLeft - 1);
1153 nextAddressIndex = nbAddress - segmentsLeft;
1154 nextAddress = routingHeader.GetRouterAddress(nextAddressIndex);
1155
1156 if (nextAddress.IsMulticast() || destAddress.IsMulticast())
1157 {
1159 isDropped = true;
1160 stopProcessing = true;
1161 return routingHeader.GetSerializedSize();
1162 }
1163
1164 routingHeader.SetRouterAddress(nextAddressIndex, destAddress);
1165 ipv6header.SetDestination(nextAddress);
1166
1167 if (hopLimit <= 1)
1168 {
1169 NS_LOG_LOGIC("Time Exceeded : Hop Limit <= 1. Drop!");
1170 icmpv6->SendErrorTimeExceeded(malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
1172 isDropped = true;
1173 stopProcessing = true;
1174 return routingHeader.GetSerializedSize();
1175 }
1176
1177 ipv6header.SetHopLimit(hopLimit - 1);
1178 p->AddHeader(routingHeader);
1179
1180 /* short-circuiting routing stuff
1181 *
1182 * If we process this option,
1183 * the packet was for us so we resend it to
1184 * the new destination (modified in the header above).
1185 */
1186
1188 Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol();
1190 NS_ASSERT(ipv6rp);
1191
1192 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header, nullptr, err);
1193
1194 if (rtentry)
1195 {
1196 /* we know a route exists so send packet now */
1197 ipv6->SendRealOut(rtentry, p, ipv6header);
1198 }
1199 else
1200 {
1201 NS_LOG_INFO("No route for next router");
1202 }
1203
1204 /* as we directly send packet, mark it as dropped */
1205 isDropped = true;
1206
1207 return routingHeader.GetSerializedSize();
1208}
1209
1211
1212TypeId
1214{
1215 static TypeId tid = TypeId("ns3::Ipv6ExtensionESP")
1217 .SetGroupName("Internet")
1218 .AddConstructor<Ipv6ExtensionESP>();
1219 return tid;
1220}
1221
1225
1229
1230uint8_t
1232{
1233 return EXT_NUMBER;
1234}
1235
1236uint8_t
1238 uint8_t offset,
1239 const Ipv6Header& ipv6Header,
1240 Ipv6Address dst,
1241 uint8_t* nextHeader,
1242 bool& stopProcessing,
1243 bool& isDropped,
1244 Ipv6L3Protocol::DropReason& dropReason)
1245{
1246 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1247
1248 /** @todo */
1249
1250 return 0;
1251}
1252
1254
1255TypeId
1257{
1258 static TypeId tid = TypeId("ns3::Ipv6ExtensionAH")
1260 .SetGroupName("Internet")
1261 .AddConstructor<Ipv6ExtensionAH>();
1262 return tid;
1263}
1264
1268
1272
1273uint8_t
1275{
1276 return EXT_NUMBER;
1277}
1278
1279uint8_t
1281 uint8_t offset,
1282 const Ipv6Header& ipv6Header,
1283 Ipv6Address dst,
1284 uint8_t* nextHeader,
1285 bool& stopProcessing,
1286 bool& isDropped,
1287 Ipv6L3Protocol::DropReason& dropReason)
1288{
1289 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1290
1291 /** @todo */
1292
1293 return 1;
1294}
1295
1296} /* 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:1075
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.
static const uint8_t EXT_NUMBER
AH extension number.
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 const uint8_t EXT_NUMBER
ESP 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.
std::list< std::pair< Ptr< Packet >, uint16_t > > m_packetFragments
The current fragments.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
bool m_moreFragment
If other fragments will be sent.
Ptr< Packet > m_unfragmentable
The unfragmentable part.
FragmentsTimeoutsListI_t m_timeoutIter
Timeout iterator to "event" handler.
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.
static const uint8_t TYPE_ROUTING
Routing type.
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.
int64_t AssignStreams(int64_t stream)
Assigns stream numbers to the registered extensions of this IPv6 routing demux object.
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.
static const uint8_t EXT_NUMBER
Routing 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.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:518
Object()
Caller graph was not generated because of its size.
Definition object.cc:93
virtual void DoDispose()
Destructor implementation.
Definition object.cc:430
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.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
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:95
AttributeValue implementation for Time.
Definition nstime.h:1375
a unique identifier for an interface.
Definition type-id.h:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
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:1376
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1396
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:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#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:267
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint8_t data[writeSize]