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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: David Gross <gdavid.devel@gmail.com>
18 */
19
20#include "ipv6-extension.h"
21
22#include "icmpv6-l4-protocol.h"
25#include "ipv6-header.h"
26#include "ipv6-l3-protocol.h"
27#include "ipv6-option-demux.h"
28#include "ipv6-option.h"
29#include "ipv6-route.h"
30
31#include "ns3/assert.h"
32#include "ns3/ipv6-address.h"
33#include "ns3/log.h"
34#include "ns3/object-vector.h"
35#include "ns3/trace-source-accessor.h"
36#include "ns3/uinteger.h"
37
38#include <ctime>
39#include <list>
40
41namespace ns3
42{
43
44NS_LOG_COMPONENT_DEFINE("Ipv6Extension");
45
46NS_OBJECT_ENSURE_REGISTERED(Ipv6Extension);
47
48TypeId
50{
51 static TypeId tid = TypeId("ns3::Ipv6Extension")
53 .SetGroupName("Internet")
54 .AddAttribute("ExtensionNumber",
55 "The IPv6 extension number.",
58 MakeUintegerChecker<uint8_t>());
59 return tid;
60}
61
63{
64 m_uvar = CreateObject<UniformRandomVariable>();
65}
66
68{
69}
70
71void
73{
74 NS_LOG_FUNCTION(this << node);
75
76 m_node = node;
77}
78
81{
82 return m_node;
83}
84
85uint8_t
87 uint8_t offset,
88 uint8_t length,
89 const Ipv6Header& ipv6Header,
90 Ipv6Address dst,
91 uint8_t* nextHeader,
92 bool& stopProcessing,
93 bool& isDropped,
95{
96 NS_LOG_FUNCTION(this << packet << offset << length << ipv6Header << dst << nextHeader
97 << isDropped);
98
99 // For ICMPv6 Error packets
100 Ptr<Packet> malformedPacket = packet->Copy();
101 malformedPacket->AddHeader(ipv6Header);
102 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
103
104 Ptr<Packet> p = packet->Copy();
105 p->RemoveAtStart(offset);
106
108 Ptr<Ipv6Option> ipv6Option;
109
110 uint8_t processedSize = 0;
111 uint32_t size = p->GetSize();
112 uint8_t* data = new uint8_t[size];
113 p->CopyData(data, size);
114
115 uint8_t optionType = 0;
116 uint8_t optionLength = 0;
117
118 while (length > processedSize && !isDropped)
119 {
120 optionType = *(data + processedSize);
121 ipv6Option = ipv6OptionDemux->GetOption(optionType);
122
123 if (!ipv6Option)
124 {
125 optionType >>= 6;
126 switch (optionType)
127 {
128 case 0:
129 optionLength = *(data + processedSize + 1) + 2;
130 break;
131
132 case 1:
133 NS_LOG_LOGIC("Unknown Option. Drop!");
134 optionLength = 0;
135 isDropped = true;
136 stopProcessing = true;
138 break;
139
140 case 2:
141 NS_LOG_LOGIC("Unknown Option. Drop!");
142 icmpv6->SendErrorParameterError(malformedPacket,
143 ipv6Header.GetSource(),
145 offset + processedSize);
146 optionLength = 0;
147 isDropped = true;
148 stopProcessing = true;
150 break;
151
152 case 3:
153 NS_LOG_LOGIC("Unknown Option. Drop!");
154
155 if (!ipv6Header.GetDestination().IsMulticast())
156 {
157 icmpv6->SendErrorParameterError(malformedPacket,
158 ipv6Header.GetSource(),
160 offset + processedSize);
161 }
162 optionLength = 0;
163 isDropped = true;
164 stopProcessing = true;
166 break;
167
168 default:
169 break;
170 }
171 }
172 else
173 {
174 optionLength =
175 ipv6Option->Process(packet, offset + processedSize, ipv6Header, isDropped);
176 }
177
178 processedSize += optionLength;
179 p->RemoveAtStart(optionLength);
180 }
181
182 delete[] data;
183
184 return processedSize;
185}
186
187int64_t
189{
190 NS_LOG_FUNCTION(this << stream);
191 m_uvar->SetStream(stream);
192 return 1;
193}
194
196
197TypeId
199{
200 static TypeId tid = TypeId("ns3::Ipv6ExtensionHopByHop")
202 .SetGroupName("Internet")
203 .AddConstructor<Ipv6ExtensionHopByHop>();
204 return tid;
205}
206
208{
209}
210
212{
213}
214
215uint8_t
217{
218 return EXT_NUMBER;
219}
220
221uint8_t
223 uint8_t offset,
224 const Ipv6Header& ipv6Header,
225 Ipv6Address dst,
226 uint8_t* nextHeader,
227 bool& stopProcessing,
228 bool& isDropped,
229 Ipv6L3Protocol::DropReason& dropReason)
230{
231 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
232
233 Ptr<Packet> p = packet->Copy();
234 p->RemoveAtStart(offset);
235
236 Ipv6ExtensionHopByHopHeader hopbyhopHeader;
237 p->RemoveHeader(hopbyhopHeader);
238 if (nextHeader)
239 {
240 *nextHeader = hopbyhopHeader.GetNextHeader();
241 }
242
243 uint8_t processedSize = hopbyhopHeader.GetOptionsOffset();
244 offset += processedSize;
245 uint8_t length = hopbyhopHeader.GetLength() - hopbyhopHeader.GetOptionsOffset();
246
247 processedSize += ProcessOptions(packet,
248 offset,
249 length,
250 ipv6Header,
251 dst,
252 nextHeader,
253 stopProcessing,
254 isDropped,
255 dropReason);
256
257 return processedSize;
258}
259
261
262TypeId
264{
265 static TypeId tid = TypeId("ns3::Ipv6ExtensionDestination")
267 .SetGroupName("Internet")
268 .AddConstructor<Ipv6ExtensionDestination>();
269 return tid;
270}
271
273{
274}
275
277{
278}
279
280uint8_t
282{
283 return EXT_NUMBER;
284}
285
286uint8_t
288 uint8_t offset,
289 const Ipv6Header& ipv6Header,
290 Ipv6Address dst,
291 uint8_t* nextHeader,
292 bool& stopProcessing,
293 bool& isDropped,
294 Ipv6L3Protocol::DropReason& dropReason)
295{
296 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
297
298 Ptr<Packet> p = packet->Copy();
299 p->RemoveAtStart(offset);
300
301 Ipv6ExtensionDestinationHeader destinationHeader;
302 p->RemoveHeader(destinationHeader);
303 if (nextHeader)
304 {
305 *nextHeader = destinationHeader.GetNextHeader();
306 }
307
308 uint8_t processedSize = destinationHeader.GetOptionsOffset();
309 offset += processedSize;
310 uint8_t length = destinationHeader.GetLength() - destinationHeader.GetOptionsOffset();
311
312 processedSize += ProcessOptions(packet,
313 offset,
314 length,
315 ipv6Header,
316 dst,
317 nextHeader,
318 stopProcessing,
319 isDropped,
320 dropReason);
321
322 return processedSize;
323}
324
326
327TypeId
329{
330 static TypeId tid =
331 TypeId("ns3::Ipv6ExtensionFragment")
333 .SetGroupName("Internet")
334 .AddConstructor<Ipv6ExtensionFragment>()
335 .AddAttribute("FragmentExpirationTimeout",
336 "When this timeout expires, the fragments "
337 "will be cleared from the buffer.",
338 TimeValue(Seconds(60)),
341 return tid;
342}
343
345{
346}
347
349{
350}
351
352void
354{
355 NS_LOG_FUNCTION(this);
356
357 for (MapFragments_t::iterator it = m_fragments.begin(); it != m_fragments.end(); it++)
358 {
359 it->second = nullptr;
360 }
361
362 m_fragments.clear();
363 m_timeoutEventList.clear();
365 {
367 }
369}
370
371uint8_t
373{
374 return EXT_NUMBER;
375}
376
377uint8_t
379 uint8_t offset,
380 const Ipv6Header& ipv6Header,
381 Ipv6Address dst,
382 uint8_t* nextHeader,
383 bool& stopProcessing,
384 bool& isDropped,
385 Ipv6L3Protocol::DropReason& dropReason)
386{
387 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
388
389 Ptr<Packet> p = packet->Copy();
390 p->RemoveAtStart(offset);
391
392 Ipv6ExtensionFragmentHeader fragmentHeader;
393 p->RemoveHeader(fragmentHeader);
394
395 if (nextHeader)
396 {
397 *nextHeader = fragmentHeader.GetNextHeader();
398 }
399
400 bool moreFragment = fragmentHeader.GetMoreFragment();
401 uint16_t fragmentOffset = fragmentHeader.GetOffset();
402 uint32_t identification = fragmentHeader.GetIdentification();
403 Ipv6Address src = ipv6Header.GetSource();
404
405 FragmentKey_t fragmentKey = FragmentKey_t(src, identification);
406 Ptr<Fragments> fragments;
407
408 Ipv6Header ipHeader = ipv6Header;
409 ipHeader.SetNextHeader(fragmentHeader.GetNextHeader());
410
411 MapFragments_t::iterator it = m_fragments.find(fragmentKey);
412 if (it == m_fragments.end())
413 {
414 fragments = Create<Fragments>();
415 m_fragments.insert(std::make_pair(fragmentKey, fragments));
416 NS_LOG_DEBUG("Insert new fragment key: src: "
417 << src << " IP hdr id " << identification << " m_fragments.size() "
418 << m_fragments.size() << " offset " << fragmentOffset);
419 FragmentsTimeoutsListI_t iter = SetTimeout(fragmentKey, ipHeader);
420 fragments->SetTimeoutIter(iter);
421 }
422 else
423 {
424 fragments = it->second;
425 }
426
427 if (fragmentOffset == 0)
428 {
429 Ptr<Packet> unfragmentablePart = packet->Copy();
430 unfragmentablePart->RemoveAtEnd(packet->GetSize() - offset);
431 fragments->SetUnfragmentablePart(unfragmentablePart);
432 }
433
434 NS_LOG_DEBUG("Add fragment with IP hdr id " << identification << " offset " << fragmentOffset);
435 fragments->AddFragment(p, fragmentOffset, moreFragment);
436
437 if (fragments->IsEntire())
438 {
439 packet = fragments->GetPacket();
440 m_timeoutEventList.erase(fragments->GetTimeoutIter());
441 m_fragments.erase(fragmentKey);
442 NS_LOG_DEBUG("Finished fragment with IP hdr id "
443 << fragmentKey.second
444 << " erase timeout, m_fragments.size(): " << m_fragments.size());
445 stopProcessing = false;
446 }
447 else
448 {
449 stopProcessing = true;
450 }
451
452 return 0;
453}
454
455void
457 Ipv6Header ipv6Header,
458 uint32_t maxFragmentSize,
459 std::list<Ipv6PayloadHeaderPair>& listFragments)
460{
461 NS_LOG_FUNCTION(this << packet << ipv6Header << maxFragmentSize);
462 Ptr<Packet> p = packet->Copy();
463
464 uint8_t nextHeader = ipv6Header.GetNextHeader();
465 uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize();
466
467 uint8_t type;
468 p->CopyData(&type, sizeof(type));
469
470 bool moreHeader = true;
471 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
472 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
474 {
475 moreHeader = false;
477 }
478
479 std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>> unfragmentablePart;
480 uint32_t unfragmentablePartSize = 0;
481
483 Ptr<Ipv6Extension> extension = extensionDemux->GetExtension(nextHeader);
484 uint8_t extensionHeaderLength;
485
486 while (moreHeader)
487 {
488 if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
489 {
491 p->RemoveHeader(*hopbyhopHeader);
492
493 nextHeader = hopbyhopHeader->GetNextHeader();
494 extensionHeaderLength = hopbyhopHeader->GetLength();
495
496 uint8_t type;
497 p->CopyData(&type, sizeof(type));
498
499 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
500 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
501 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
503 {
504 moreHeader = false;
506 }
507
508 unfragmentablePart.emplace_back(hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP);
509 unfragmentablePartSize += extensionHeaderLength;
510 }
511 else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
512 {
513 Ptr<Ipv6ExtensionRoutingDemux> ipv6ExtensionRoutingDemux =
515
516 uint8_t buf[4];
517 p->CopyData(buf, sizeof(buf));
518 uint8_t routingType = buf[2];
519
520 Ipv6ExtensionRoutingHeader* routingHeader =
521 ipv6ExtensionRoutingDemux->GetExtensionRoutingHeaderPtr(routingType);
522
523 p->RemoveHeader(*routingHeader);
524
525 nextHeader = routingHeader->GetNextHeader();
526 extensionHeaderLength = routingHeader->GetLength();
527
528 uint8_t type;
529 p->CopyData(&type, sizeof(type));
530 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
531 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
532 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
534 {
535 moreHeader = false;
537 }
538
539 unfragmentablePart.emplace_back(routingHeader, Ipv6Header::IPV6_EXT_ROUTING);
540 unfragmentablePartSize += extensionHeaderLength;
541 }
542 else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
543 {
544 Ipv6ExtensionDestinationHeader* destinationHeader =
546 p->RemoveHeader(*destinationHeader);
547
548 nextHeader = destinationHeader->GetNextHeader();
549 extensionHeaderLength = destinationHeader->GetLength();
550
551 uint8_t type;
552 p->CopyData(&type, sizeof(type));
553 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
554 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
555 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
557 {
558 moreHeader = false;
560 }
561
562 unfragmentablePart.emplace_back(destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION);
563 unfragmentablePartSize += extensionHeaderLength;
564 }
565 }
566
567 Ipv6ExtensionFragmentHeader fragmentHeader;
568 uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize();
569
570 uint32_t maxFragmentablePartSize =
571 maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
572 uint32_t currentFragmentablePartSize = 0;
573
574 bool moreFragment = true;
575 uint32_t identification = (uint32_t)m_uvar->GetValue(0, (uint32_t)-1);
576 uint16_t offset = 0;
577
578 do
579 {
580 if (p->GetSize() > offset + maxFragmentablePartSize)
581 {
582 moreFragment = true;
583 currentFragmentablePartSize = maxFragmentablePartSize;
584 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
585 }
586 else
587 {
588 moreFragment = false;
589 currentFragmentablePartSize = p->GetSize() - offset;
590 }
591
592 fragmentHeader.SetNextHeader(nextHeader);
593 fragmentHeader.SetOffset(offset);
594 fragmentHeader.SetMoreFragment(moreFragment);
595 fragmentHeader.SetIdentification(identification);
596
597 Ptr<Packet> fragment = p->CreateFragment(offset, currentFragmentablePartSize);
598 offset += currentFragmentablePartSize;
599
600 fragment->AddHeader(fragmentHeader);
601
602 for (std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>>::iterator it =
603 unfragmentablePart.begin();
604 it != unfragmentablePart.end();
605 it++)
606 {
607 if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
608 {
610 dynamic_cast<Ipv6ExtensionHopByHopHeader*>(it->first);
611 NS_ASSERT(p != nullptr);
612 fragment->AddHeader(*p);
613 }
614 else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
615 {
617 dynamic_cast<Ipv6ExtensionLooseRoutingHeader*>(it->first);
618 NS_ASSERT(p != nullptr);
619 fragment->AddHeader(*p);
620 }
621 else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
622 {
624 dynamic_cast<Ipv6ExtensionDestinationHeader*>(it->first);
625 NS_ASSERT(p != nullptr);
626 fragment->AddHeader(*p);
627 }
628 }
629
630 ipv6Header.SetPayloadLength(fragment->GetSize());
631
632 std::ostringstream oss;
633 oss << ipv6Header;
634 fragment->Print(oss);
635
636 listFragments.emplace_back(fragment, ipv6Header);
637 } while (moreFragment);
638
639 for (std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>>::iterator it =
640 unfragmentablePart.begin();
641 it != unfragmentablePart.end();
642 it++)
643 {
644 delete it->first;
645 }
646
647 unfragmentablePart.clear();
648}
649
650void
652{
653 NS_LOG_FUNCTION(this << fragmentKey.first << fragmentKey.second << ipHeader);
654 Ptr<Fragments> fragments;
655
656 MapFragments_t::iterator it = m_fragments.find(fragmentKey);
657 NS_ASSERT_MSG(it != m_fragments.end(),
658 "IPv6 Fragment timeout reached for non-existent fragment");
659 fragments = it->second;
660
661 Ptr<Packet> packet = fragments->GetPartialPacket();
662
663 // if we have at least 8 bytes, we can send an ICMP.
664 if (packet && packet->GetSize() > 8)
665 {
666 Ptr<Packet> p = packet->Copy();
667 p->AddHeader(ipHeader);
669 icmp->SendErrorTimeExceeded(p, ipHeader.GetSource(), Icmpv6Header::ICMPV6_FRAGTIME);
670 }
671
673 ipL3->ReportDrop(ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
674
675 // clear the buffers
676 m_fragments.erase(fragmentKey);
677}
678
681{
682 NS_LOG_FUNCTION(this << key.first << key.second << ipHeader);
683 if (m_timeoutEventList.empty())
684 {
685 NS_LOG_DEBUG("Scheduling timeout for IP hdr id "
686 << key.second << " at time "
687 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds());
690 this);
691 }
692 NS_LOG_DEBUG("Adding timeout at "
693 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds() << " with key "
694 << key.second);
695 m_timeoutEventList.emplace_back(Simulator::Now() + m_fragmentExpirationTimeout, key, ipHeader);
696
698
699 return (iter);
700}
701
702void
704{
705 NS_LOG_FUNCTION(this);
706 Time now = Simulator::Now();
707
708 // std::list Time, Fragment_key_t, Ipv6Header
709 // Fragment key is a pair: Ipv6Address, uint32_t ipHeaderId
710 for (auto& element : m_timeoutEventList)
711 {
712 NS_LOG_DEBUG("Handle time " << std::get<0>(element).GetSeconds() << " IP hdr id "
713 << std::get<1>(element).second);
714 }
715 while (!m_timeoutEventList.empty() && std::get<0>(*m_timeoutEventList.begin()) == now)
716 {
717 HandleFragmentsTimeout(std::get<1>(*m_timeoutEventList.begin()),
718 std::get<2>(*m_timeoutEventList.begin()));
719 m_timeoutEventList.pop_front();
720 }
721
722 if (m_timeoutEventList.empty())
723 {
724 return;
725 }
726
727 Time difference = std::get<0>(*m_timeoutEventList.begin()) - now;
728 NS_LOG_DEBUG("Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
730}
731
733 : m_moreFragment(0)
734{
735}
736
738{
739}
740
741void
743 uint16_t fragmentOffset,
744 bool moreFragment)
745{
746 NS_LOG_FUNCTION(this << fragment << fragmentOffset << moreFragment);
747 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
748
749 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
750 {
751 if (it->second > fragmentOffset)
752 {
753 break;
754 }
755 }
756
757 if (it == m_packetFragments.end())
758 {
759 m_moreFragment = moreFragment;
760 }
761
762 m_packetFragments.insert(it, std::pair<Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
763}
764
765void
767{
768 NS_LOG_FUNCTION(this << unfragmentablePart);
769 m_unfragmentable = unfragmentablePart;
770}
771
772bool
774{
775 bool ret = !m_moreFragment && !m_packetFragments.empty();
776
777 if (ret)
778 {
779 uint16_t lastEndOffset = 0;
780
781 for (std::list<std::pair<Ptr<Packet>, uint16_t>>::const_iterator it =
782 m_packetFragments.begin();
783 it != m_packetFragments.end();
784 it++)
785 {
786 if (lastEndOffset != it->second)
787 {
788 ret = false;
789 break;
790 }
791
792 lastEndOffset += it->first->GetSize();
793 }
794 }
795
796 return ret;
797}
798
801{
802 Ptr<Packet> p = m_unfragmentable->Copy();
803
804 for (std::list<std::pair<Ptr<Packet>, uint16_t>>::const_iterator it = m_packetFragments.begin();
805 it != m_packetFragments.end();
806 it++)
807 {
808 p->AddAtEnd(it->first);
809 }
810
811 return p;
812}
813
816{
817 Ptr<Packet> p;
818
819 if (m_unfragmentable)
820 {
821 p = m_unfragmentable->Copy();
822 }
823 else
824 {
825 return p;
826 }
827
828 uint16_t lastEndOffset = 0;
829
830 for (std::list<std::pair<Ptr<Packet>, uint16_t>>::const_iterator it = m_packetFragments.begin();
831 it != m_packetFragments.end();
832 it++)
833 {
834 if (lastEndOffset != it->second)
835 {
836 break;
837 }
838 p->AddAtEnd(it->first);
839 lastEndOffset += it->first->GetSize();
840 }
841
842 return p;
843}
844
845void
847{
848 NS_LOG_FUNCTION(this);
849 m_timeoutIter = iter;
850}
851
854{
855 return m_timeoutIter;
856}
857
859
860TypeId
862{
863 static TypeId tid = TypeId("ns3::Ipv6ExtensionRouting")
865 .SetGroupName("Internet")
866 .AddConstructor<Ipv6ExtensionRouting>();
867 return tid;
868}
869
871{
872}
873
875{
876}
877
878uint8_t
880{
881 return EXT_NUMBER;
882}
883
884uint8_t
886{
887 return 0;
888}
889
892{
893 return nullptr;
894}
895
896uint8_t
898 uint8_t offset,
899 const Ipv6Header& ipv6Header,
900 Ipv6Address dst,
901 uint8_t* nextHeader,
902 bool& stopProcessing,
903 bool& isDropped,
904 Ipv6L3Protocol::DropReason& dropReason)
905{
906 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
907
908 // For ICMPv6 Error Packets
909 Ptr<Packet> malformedPacket = packet->Copy();
910 malformedPacket->AddHeader(ipv6Header);
911
912 Ptr<Packet> p = packet->Copy();
913 p->RemoveAtStart(offset);
914
915 uint8_t buf[4];
916 packet->CopyData(buf, sizeof(buf));
917
918 uint8_t routingNextHeader = buf[0];
919 uint8_t routingLength = buf[1];
920 uint8_t routingTypeRouting = buf[2];
921 uint8_t routingSegmentsLeft = buf[3];
922
923 if (nextHeader)
924 {
925 *nextHeader = routingNextHeader;
926 }
927
928 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
929
930 Ptr<Ipv6ExtensionRoutingDemux> ipv6ExtensionRoutingDemux =
932 Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting =
933 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
934
935 if (!ipv6ExtensionRouting)
936 {
937 if (routingSegmentsLeft == 0)
938 {
939 isDropped = false;
940 }
941 else
942 {
943 NS_LOG_LOGIC("Malformed header. Drop!");
944
945 icmpv6->SendErrorParameterError(malformedPacket,
946 ipv6Header.GetSource(),
948 offset + 1);
950 isDropped = true;
951 stopProcessing = true;
952 }
953
954 return routingLength;
955 }
956
957 return ipv6ExtensionRouting->Process(packet,
958 offset,
959 ipv6Header,
960 dst,
961 (uint8_t*)nullptr,
962 stopProcessing,
963 isDropped,
964 dropReason);
965}
966
968
969TypeId
971{
972 static TypeId tid =
973 TypeId("ns3::Ipv6ExtensionRoutingDemux")
974 .SetParent<Object>()
975 .SetGroupName("Internet")
976 .AddAttribute("RoutingExtensions",
977 "The set of IPv6 Routing extensions registered with this demux.",
980 MakeObjectVectorChecker<Ipv6ExtensionRouting>());
981 return tid;
982}
983
985{
986}
987
989{
990}
991
992void
994{
995 NS_LOG_FUNCTION(this);
996 for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin();
997 it != m_extensionsRouting.end();
998 it++)
999 {
1000 (*it)->Dispose();
1001 *it = nullptr;
1002 }
1003 m_extensionsRouting.clear();
1004 m_node = nullptr;
1006}
1007
1008void
1010{
1011 NS_LOG_FUNCTION(this << node);
1012 m_node = node;
1013}
1014
1015void
1017{
1018 NS_LOG_FUNCTION(this << extensionRouting);
1019 m_extensionsRouting.push_back(extensionRouting);
1020}
1021
1024{
1025 for (const auto& extRouting : m_extensionsRouting)
1026 {
1027 if (extRouting->GetTypeRouting() == typeRouting)
1028 {
1029 return extRouting;
1030 }
1031 }
1032
1033 return nullptr;
1034}
1035
1038{
1039 NS_LOG_FUNCTION(this << typeRouting);
1040
1041 for (const auto& extRouting : m_extensionsRouting)
1042 {
1043 if (extRouting->GetTypeRouting() == typeRouting)
1044 {
1045 return extRouting->GetExtensionRoutingHeaderPtr();
1046 }
1047 }
1048
1049 return nullptr;
1050}
1051
1052void
1054{
1055 NS_LOG_FUNCTION(this << extensionRouting);
1056 m_extensionsRouting.remove(extensionRouting);
1057}
1058
1060
1061TypeId
1063{
1064 static TypeId tid = TypeId("ns3::Ipv6ExtensionLooseRouting")
1066 .SetGroupName("Internet")
1067 .AddConstructor<Ipv6ExtensionLooseRouting>();
1068 return tid;
1069}
1070
1072{
1073}
1074
1076{
1077}
1078
1079uint8_t
1081{
1082 return TYPE_ROUTING;
1083}
1084
1087{
1089}
1090
1091uint8_t
1093 uint8_t offset,
1094 const Ipv6Header& ipv6Header,
1095 Ipv6Address dst,
1096 uint8_t* nextHeader,
1097 bool& stopProcessing,
1098 bool& isDropped,
1099 Ipv6L3Protocol::DropReason& dropReason)
1100{
1101 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1102
1103 // For ICMPv6 Error packets
1104 Ptr<Packet> malformedPacket = packet->Copy();
1105 malformedPacket->AddHeader(ipv6Header);
1106
1107 Ptr<Packet> p = packet->Copy();
1108 p->RemoveAtStart(offset);
1109
1110 // Copy IPv6 Header : ipv6Header -> ipv6header
1111 Buffer tmp;
1112 tmp.AddAtStart(ipv6Header.GetSerializedSize());
1113 Buffer::Iterator it = tmp.Begin();
1114 Ipv6Header ipv6header;
1115 ipv6Header.Serialize(it);
1116 ipv6header.Deserialize(it);
1117
1118 // Get the number of routers' address field
1119 uint8_t buf[2];
1120 p->CopyData(buf, sizeof(buf));
1121 Ipv6ExtensionLooseRoutingHeader routingHeader;
1122 p->RemoveHeader(routingHeader);
1123
1124 if (nextHeader)
1125 {
1126 *nextHeader = routingHeader.GetNextHeader();
1127 }
1128
1129 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
1130
1131 Ipv6Address srcAddress = ipv6header.GetSource();
1132 Ipv6Address destAddress = ipv6header.GetDestination();
1133 uint8_t hopLimit = ipv6header.GetHopLimit();
1134 uint8_t segmentsLeft = routingHeader.GetSegmentsLeft();
1135 uint8_t length = (routingHeader.GetLength() >> 3) - 1;
1136 uint8_t nbAddress = length / 2;
1137 uint8_t nextAddressIndex;
1138 Ipv6Address nextAddress;
1139
1140 if (segmentsLeft == 0)
1141 {
1142 isDropped = false;
1143 return routingHeader.GetSerializedSize();
1144 }
1145
1146 if (length % 2 != 0)
1147 {
1148 NS_LOG_LOGIC("Malformed header. Drop!");
1149 icmpv6->SendErrorParameterError(malformedPacket,
1150 srcAddress,
1152 offset + 1);
1154 isDropped = true;
1155 stopProcessing = true;
1156 return routingHeader.GetSerializedSize();
1157 }
1158
1159 if (segmentsLeft > nbAddress)
1160 {
1161 NS_LOG_LOGIC("Malformed header. Drop!");
1162 icmpv6->SendErrorParameterError(malformedPacket,
1163 srcAddress,
1165 offset + 3);
1167 isDropped = true;
1168 stopProcessing = true;
1169 return routingHeader.GetSerializedSize();
1170 }
1171
1172 routingHeader.SetSegmentsLeft(segmentsLeft - 1);
1173 nextAddressIndex = nbAddress - segmentsLeft;
1174 nextAddress = routingHeader.GetRouterAddress(nextAddressIndex);
1175
1176 if (nextAddress.IsMulticast() || destAddress.IsMulticast())
1177 {
1179 isDropped = true;
1180 stopProcessing = true;
1181 return routingHeader.GetSerializedSize();
1182 }
1183
1184 routingHeader.SetRouterAddress(nextAddressIndex, destAddress);
1185 ipv6header.SetDestination(nextAddress);
1186
1187 if (hopLimit <= 1)
1188 {
1189 NS_LOG_LOGIC("Time Exceeded : Hop Limit <= 1. Drop!");
1190 icmpv6->SendErrorTimeExceeded(malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
1192 isDropped = true;
1193 stopProcessing = true;
1194 return routingHeader.GetSerializedSize();
1195 }
1196
1197 ipv6header.SetHopLimit(hopLimit - 1);
1198 p->AddHeader(routingHeader);
1199
1200 /* short-circuiting routing stuff
1201 *
1202 * If we process this option,
1203 * the packet was for us so we resend it to
1204 * the new destination (modified in the header above).
1205 */
1206
1208 Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol();
1210 NS_ASSERT(ipv6rp);
1211
1212 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header, nullptr, err);
1213
1214 if (rtentry)
1215 {
1216 /* we know a route exists so send packet now */
1217 ipv6->SendRealOut(rtentry, p, ipv6header);
1218 }
1219 else
1220 {
1221 NS_LOG_INFO("No route for next router");
1222 }
1223
1224 /* as we directly send packet, mark it as dropped */
1225 isDropped = true;
1226
1227 return routingHeader.GetSerializedSize();
1228}
1229
1231
1232TypeId
1234{
1235 static TypeId tid = TypeId("ns3::Ipv6ExtensionESP")
1237 .SetGroupName("Internet")
1238 .AddConstructor<Ipv6ExtensionESP>();
1239 return tid;
1240}
1241
1243{
1244}
1245
1247{
1248}
1249
1250uint8_t
1252{
1253 return EXT_NUMBER;
1254}
1255
1256uint8_t
1258 uint8_t offset,
1259 const Ipv6Header& ipv6Header,
1260 Ipv6Address dst,
1261 uint8_t* nextHeader,
1262 bool& stopProcessing,
1263 bool& isDropped,
1264 Ipv6L3Protocol::DropReason& dropReason)
1265{
1266 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1267
1270 return 0;
1271}
1272
1274
1275TypeId
1277{
1278 static TypeId tid = TypeId("ns3::Ipv6ExtensionAH")
1280 .SetGroupName("Internet")
1281 .AddConstructor<Ipv6ExtensionAH>();
1282 return tid;
1283}
1284
1286{
1287}
1288
1290{
1291}
1292
1293uint8_t
1295{
1296 return EXT_NUMBER;
1297}
1298
1299uint8_t
1301 uint8_t offset,
1302 const Ipv6Header& ipv6Header,
1303 Ipv6Address dst,
1304 uint8_t* nextHeader,
1305 bool& stopProcessing,
1306 bool& isDropped,
1307 Ipv6L3Protocol::DropReason& dropReason)
1308{
1309 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1310
1313 return true;
1314}
1315
1316} /* namespace ns3 */
iterator in a Buffer instance
Definition: buffer.h:100
automatically resized byte buffer
Definition: buffer.h:94
void AddAtStart(uint32_t start)
Definition: buffer.cc:314
Buffer::Iterator Begin() const
Definition: buffer.h:1074
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
An implementation of the ICMPv6 protocol.
Describes an IPv6 address.
Definition: ipv6-address.h:49
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.
Ipv6ExtensionFragment()
Constructor.
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.
Ipv6ExtensionHopByHop()
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.
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()
Constructor.
~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:35
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:118
uint8_t GetHopLimit() const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:100
uint8_t GetNextHeader() const
Get the next header.
Definition: ipv6-header.cc:88
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:94
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:70
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Definition: ipv6-header.cc:159
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
void Serialize(Buffer::Iterator start) const override
Serialize the packet.
Definition: ipv6-header.cc:165
uint32_t Deserialize(Buffer::Iterator start) override
Deserialize the packet.
Definition: ipv6-header.cc:182
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:82
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:89
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
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:78
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Definition: object-vector.h:40
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:76
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1444
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Definition: second.py:1
uint8_t data[writeSize]