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 auto 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 (auto 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 auto 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 auto 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 {
490 auto hopbyhopHeader = new Ipv6ExtensionHopByHopHeader();
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;
505 hopbyhopHeader->SetNextHeader(Ipv6Header::IPV6_EXT_FRAGMENTATION);
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 auto destinationHeader = new Ipv6ExtensionDestinationHeader();
545 p->RemoveHeader(*destinationHeader);
546
547 nextHeader = destinationHeader->GetNextHeader();
548 extensionHeaderLength = destinationHeader->GetLength();
549
550 uint8_t type;
551 p->CopyData(&type, sizeof(type));
552 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
553 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
554 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
556 {
557 moreHeader = false;
558 destinationHeader->SetNextHeader(Ipv6Header::IPV6_EXT_FRAGMENTATION);
559 }
560
561 unfragmentablePart.emplace_back(destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION);
562 unfragmentablePartSize += extensionHeaderLength;
563 }
564 }
565
566 Ipv6ExtensionFragmentHeader fragmentHeader;
567 uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize();
568
569 uint32_t maxFragmentablePartSize =
570 maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
571 uint32_t currentFragmentablePartSize = 0;
572
573 bool moreFragment = true;
574 auto identification = (uint32_t)m_uvar->GetValue(0, (uint32_t)-1);
575 uint16_t offset = 0;
576
577 do
578 {
579 if (p->GetSize() > offset + maxFragmentablePartSize)
580 {
581 moreFragment = true;
582 currentFragmentablePartSize = maxFragmentablePartSize;
583 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
584 }
585 else
586 {
587 moreFragment = false;
588 currentFragmentablePartSize = p->GetSize() - offset;
589 }
590
591 fragmentHeader.SetNextHeader(nextHeader);
592 fragmentHeader.SetOffset(offset);
593 fragmentHeader.SetMoreFragment(moreFragment);
594 fragmentHeader.SetIdentification(identification);
595
596 Ptr<Packet> fragment = p->CreateFragment(offset, currentFragmentablePartSize);
597 offset += currentFragmentablePartSize;
598
599 fragment->AddHeader(fragmentHeader);
600
601 for (auto it = unfragmentablePart.begin(); it != unfragmentablePart.end(); it++)
602 {
603 if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
604 {
605 auto p = dynamic_cast<Ipv6ExtensionHopByHopHeader*>(it->first);
606 NS_ASSERT(p != nullptr);
607 fragment->AddHeader(*p);
608 }
609 else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
610 {
611 auto p = dynamic_cast<Ipv6ExtensionLooseRoutingHeader*>(it->first);
612 NS_ASSERT(p != nullptr);
613 fragment->AddHeader(*p);
614 }
615 else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
616 {
617 auto p = dynamic_cast<Ipv6ExtensionDestinationHeader*>(it->first);
618 NS_ASSERT(p != nullptr);
619 fragment->AddHeader(*p);
620 }
621 }
622
623 ipv6Header.SetPayloadLength(fragment->GetSize());
624
625 std::ostringstream oss;
626 oss << ipv6Header;
627 fragment->Print(oss);
628
629 listFragments.emplace_back(fragment, ipv6Header);
630 } while (moreFragment);
631
632 for (auto it = unfragmentablePart.begin(); it != unfragmentablePart.end(); it++)
633 {
634 delete it->first;
635 }
636
637 unfragmentablePart.clear();
638}
639
640void
642{
643 NS_LOG_FUNCTION(this << fragmentKey.first << fragmentKey.second << ipHeader);
644 Ptr<Fragments> fragments;
645
646 auto it = m_fragments.find(fragmentKey);
647 NS_ASSERT_MSG(it != m_fragments.end(),
648 "IPv6 Fragment timeout reached for non-existent fragment");
649 fragments = it->second;
650
651 Ptr<Packet> packet = fragments->GetPartialPacket();
652
653 // if we have at least 8 bytes, we can send an ICMP.
654 if (packet && packet->GetSize() > 8)
655 {
656 Ptr<Packet> p = packet->Copy();
657 p->AddHeader(ipHeader);
659 icmp->SendErrorTimeExceeded(p, ipHeader.GetSource(), Icmpv6Header::ICMPV6_FRAGTIME);
660 }
661
663 ipL3->ReportDrop(ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
664
665 // clear the buffers
666 m_fragments.erase(fragmentKey);
667}
668
671{
672 NS_LOG_FUNCTION(this << key.first << key.second << ipHeader);
673 if (m_timeoutEventList.empty())
674 {
675 NS_LOG_DEBUG("Scheduling timeout for IP hdr id "
676 << key.second << " at time "
677 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds());
680 this);
681 }
682 NS_LOG_DEBUG("Adding timeout at "
683 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds() << " with key "
684 << key.second);
685 m_timeoutEventList.emplace_back(Simulator::Now() + m_fragmentExpirationTimeout, key, ipHeader);
686
687 auto iter = --m_timeoutEventList.end();
688
689 return iter;
690}
691
692void
694{
695 NS_LOG_FUNCTION(this);
696 Time now = Simulator::Now();
697
698 // std::list Time, Fragment_key_t, Ipv6Header
699 // Fragment key is a pair: Ipv6Address, uint32_t ipHeaderId
700 for (auto& element : m_timeoutEventList)
701 {
702 NS_LOG_DEBUG("Handle time " << std::get<0>(element).GetSeconds() << " IP hdr id "
703 << std::get<1>(element).second);
704 }
705 while (!m_timeoutEventList.empty() && std::get<0>(*m_timeoutEventList.begin()) == now)
706 {
707 HandleFragmentsTimeout(std::get<1>(*m_timeoutEventList.begin()),
708 std::get<2>(*m_timeoutEventList.begin()));
709 m_timeoutEventList.pop_front();
710 }
711
712 if (m_timeoutEventList.empty())
713 {
714 return;
715 }
716
717 Time difference = std::get<0>(*m_timeoutEventList.begin()) - now;
718 NS_LOG_DEBUG("Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
720}
721
723 : m_moreFragment(false)
724{
725}
726
728{
729}
730
731void
733 uint16_t fragmentOffset,
734 bool moreFragment)
735{
736 NS_LOG_FUNCTION(this << fragment << fragmentOffset << moreFragment);
737 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
738
739 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
740 {
741 if (it->second > fragmentOffset)
742 {
743 break;
744 }
745 }
746
747 if (it == m_packetFragments.end())
748 {
749 m_moreFragment = moreFragment;
750 }
751
752 m_packetFragments.insert(it, std::pair<Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
753}
754
755void
757{
758 NS_LOG_FUNCTION(this << unfragmentablePart);
759 m_unfragmentable = unfragmentablePart;
760}
761
762bool
764{
765 bool ret = !m_moreFragment && !m_packetFragments.empty();
766
767 if (ret)
768 {
769 uint16_t lastEndOffset = 0;
770
771 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
772 {
773 if (lastEndOffset != it->second)
774 {
775 ret = false;
776 break;
777 }
778
779 lastEndOffset += it->first->GetSize();
780 }
781 }
782
783 return ret;
784}
785
788{
789 Ptr<Packet> p = m_unfragmentable->Copy();
790
791 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
792 {
793 p->AddAtEnd(it->first);
794 }
795
796 return p;
797}
798
801{
802 Ptr<Packet> p;
803
804 if (m_unfragmentable)
805 {
806 p = m_unfragmentable->Copy();
807 }
808 else
809 {
810 return p;
811 }
812
813 uint16_t lastEndOffset = 0;
814
815 for (auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
816 {
817 if (lastEndOffset != it->second)
818 {
819 break;
820 }
821 p->AddAtEnd(it->first);
822 lastEndOffset += it->first->GetSize();
823 }
824
825 return p;
826}
827
828void
830{
831 NS_LOG_FUNCTION(this);
832 m_timeoutIter = iter;
833}
834
837{
838 return m_timeoutIter;
839}
840
842
843TypeId
845{
846 static TypeId tid = TypeId("ns3::Ipv6ExtensionRouting")
848 .SetGroupName("Internet")
849 .AddConstructor<Ipv6ExtensionRouting>();
850 return tid;
851}
852
854{
855}
856
858{
859}
860
861uint8_t
863{
864 return EXT_NUMBER;
865}
866
867uint8_t
869{
870 return 0;
871}
872
875{
876 return nullptr;
877}
878
879uint8_t
881 uint8_t offset,
882 const Ipv6Header& ipv6Header,
883 Ipv6Address dst,
884 uint8_t* nextHeader,
885 bool& stopProcessing,
886 bool& isDropped,
887 Ipv6L3Protocol::DropReason& dropReason)
888{
889 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
890
891 // For ICMPv6 Error Packets
892 Ptr<Packet> malformedPacket = packet->Copy();
893 malformedPacket->AddHeader(ipv6Header);
894
895 Ptr<Packet> p = packet->Copy();
896 p->RemoveAtStart(offset);
897
898 uint8_t buf[4];
899 packet->CopyData(buf, sizeof(buf));
900
901 uint8_t routingNextHeader = buf[0];
902 uint8_t routingLength = buf[1];
903 uint8_t routingTypeRouting = buf[2];
904 uint8_t routingSegmentsLeft = buf[3];
905
906 if (nextHeader)
907 {
908 *nextHeader = routingNextHeader;
909 }
910
911 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
912
913 Ptr<Ipv6ExtensionRoutingDemux> ipv6ExtensionRoutingDemux =
915 Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting =
916 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
917
918 if (!ipv6ExtensionRouting)
919 {
920 if (routingSegmentsLeft == 0)
921 {
922 isDropped = false;
923 }
924 else
925 {
926 NS_LOG_LOGIC("Malformed header. Drop!");
927
928 icmpv6->SendErrorParameterError(malformedPacket,
929 ipv6Header.GetSource(),
931 offset + 1);
933 isDropped = true;
934 stopProcessing = true;
935 }
936
937 return routingLength;
938 }
939
940 return ipv6ExtensionRouting->Process(packet,
941 offset,
942 ipv6Header,
943 dst,
944 (uint8_t*)nullptr,
945 stopProcessing,
946 isDropped,
947 dropReason);
948}
949
951
952TypeId
954{
955 static TypeId tid =
956 TypeId("ns3::Ipv6ExtensionRoutingDemux")
957 .SetParent<Object>()
958 .SetGroupName("Internet")
959 .AddAttribute("RoutingExtensions",
960 "The set of IPv6 Routing extensions registered with this demux.",
963 MakeObjectVectorChecker<Ipv6ExtensionRouting>());
964 return tid;
965}
966
968{
969}
970
972{
973}
974
975void
977{
978 NS_LOG_FUNCTION(this);
979 for (auto it = m_extensionsRouting.begin(); it != m_extensionsRouting.end(); it++)
980 {
981 (*it)->Dispose();
982 *it = nullptr;
983 }
984 m_extensionsRouting.clear();
985 m_node = nullptr;
987}
988
989void
991{
992 NS_LOG_FUNCTION(this << node);
993 m_node = node;
994}
995
996void
998{
999 NS_LOG_FUNCTION(this << extensionRouting);
1000 m_extensionsRouting.push_back(extensionRouting);
1001}
1002
1005{
1006 for (const auto& extRouting : m_extensionsRouting)
1007 {
1008 if (extRouting->GetTypeRouting() == typeRouting)
1009 {
1010 return extRouting;
1011 }
1012 }
1013
1014 return nullptr;
1015}
1016
1019{
1020 NS_LOG_FUNCTION(this << typeRouting);
1021
1022 for (const auto& extRouting : m_extensionsRouting)
1023 {
1024 if (extRouting->GetTypeRouting() == typeRouting)
1025 {
1026 return extRouting->GetExtensionRoutingHeaderPtr();
1027 }
1028 }
1029
1030 return nullptr;
1031}
1032
1033void
1035{
1036 NS_LOG_FUNCTION(this << extensionRouting);
1037 m_extensionsRouting.remove(extensionRouting);
1038}
1039
1041
1042TypeId
1044{
1045 static TypeId tid = TypeId("ns3::Ipv6ExtensionLooseRouting")
1047 .SetGroupName("Internet")
1048 .AddConstructor<Ipv6ExtensionLooseRouting>();
1049 return tid;
1050}
1051
1053{
1054}
1055
1057{
1058}
1059
1060uint8_t
1062{
1063 return TYPE_ROUTING;
1064}
1065
1068{
1070}
1071
1072uint8_t
1074 uint8_t offset,
1075 const Ipv6Header& ipv6Header,
1076 Ipv6Address dst,
1077 uint8_t* nextHeader,
1078 bool& stopProcessing,
1079 bool& isDropped,
1080 Ipv6L3Protocol::DropReason& dropReason)
1081{
1082 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1083
1084 // For ICMPv6 Error packets
1085 Ptr<Packet> malformedPacket = packet->Copy();
1086 malformedPacket->AddHeader(ipv6Header);
1087
1088 Ptr<Packet> p = packet->Copy();
1089 p->RemoveAtStart(offset);
1090
1091 // Copy IPv6 Header : ipv6Header -> ipv6header
1092 Buffer tmp;
1093 tmp.AddAtStart(ipv6Header.GetSerializedSize());
1094 Buffer::Iterator it = tmp.Begin();
1095 Ipv6Header ipv6header;
1096 ipv6Header.Serialize(it);
1097 ipv6header.Deserialize(it);
1098
1099 // Get the number of routers' address field
1100 uint8_t buf[2];
1101 p->CopyData(buf, sizeof(buf));
1102 Ipv6ExtensionLooseRoutingHeader routingHeader;
1103 p->RemoveHeader(routingHeader);
1104
1105 if (nextHeader)
1106 {
1107 *nextHeader = routingHeader.GetNextHeader();
1108 }
1109
1110 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
1111
1112 Ipv6Address srcAddress = ipv6header.GetSource();
1113 Ipv6Address destAddress = ipv6header.GetDestination();
1114 uint8_t hopLimit = ipv6header.GetHopLimit();
1115 uint8_t segmentsLeft = routingHeader.GetSegmentsLeft();
1116 uint8_t length = (routingHeader.GetLength() >> 3) - 1;
1117 uint8_t nbAddress = length / 2;
1118 uint8_t nextAddressIndex;
1119 Ipv6Address nextAddress;
1120
1121 if (segmentsLeft == 0)
1122 {
1123 isDropped = false;
1124 return routingHeader.GetSerializedSize();
1125 }
1126
1127 if (length % 2 != 0)
1128 {
1129 NS_LOG_LOGIC("Malformed header. Drop!");
1130 icmpv6->SendErrorParameterError(malformedPacket,
1131 srcAddress,
1133 offset + 1);
1135 isDropped = true;
1136 stopProcessing = true;
1137 return routingHeader.GetSerializedSize();
1138 }
1139
1140 if (segmentsLeft > nbAddress)
1141 {
1142 NS_LOG_LOGIC("Malformed header. Drop!");
1143 icmpv6->SendErrorParameterError(malformedPacket,
1144 srcAddress,
1146 offset + 3);
1148 isDropped = true;
1149 stopProcessing = true;
1150 return routingHeader.GetSerializedSize();
1151 }
1152
1153 routingHeader.SetSegmentsLeft(segmentsLeft - 1);
1154 nextAddressIndex = nbAddress - segmentsLeft;
1155 nextAddress = routingHeader.GetRouterAddress(nextAddressIndex);
1156
1157 if (nextAddress.IsMulticast() || destAddress.IsMulticast())
1158 {
1160 isDropped = true;
1161 stopProcessing = true;
1162 return routingHeader.GetSerializedSize();
1163 }
1164
1165 routingHeader.SetRouterAddress(nextAddressIndex, destAddress);
1166 ipv6header.SetDestination(nextAddress);
1167
1168 if (hopLimit <= 1)
1169 {
1170 NS_LOG_LOGIC("Time Exceeded : Hop Limit <= 1. Drop!");
1171 icmpv6->SendErrorTimeExceeded(malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
1173 isDropped = true;
1174 stopProcessing = true;
1175 return routingHeader.GetSerializedSize();
1176 }
1177
1178 ipv6header.SetHopLimit(hopLimit - 1);
1179 p->AddHeader(routingHeader);
1180
1181 /* short-circuiting routing stuff
1182 *
1183 * If we process this option,
1184 * the packet was for us so we resend it to
1185 * the new destination (modified in the header above).
1186 */
1187
1189 Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol();
1191 NS_ASSERT(ipv6rp);
1192
1193 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header, nullptr, err);
1194
1195 if (rtentry)
1196 {
1197 /* we know a route exists so send packet now */
1198 ipv6->SendRealOut(rtentry, p, ipv6header);
1199 }
1200 else
1201 {
1202 NS_LOG_INFO("No route for next router");
1203 }
1204
1205 /* as we directly send packet, mark it as dropped */
1206 isDropped = true;
1207
1208 return routingHeader.GetSerializedSize();
1209}
1210
1212
1213TypeId
1215{
1216 static TypeId tid = TypeId("ns3::Ipv6ExtensionESP")
1218 .SetGroupName("Internet")
1219 .AddConstructor<Ipv6ExtensionESP>();
1220 return tid;
1221}
1222
1224{
1225}
1226
1228{
1229}
1230
1231uint8_t
1233{
1234 return EXT_NUMBER;
1235}
1236
1237uint8_t
1239 uint8_t offset,
1240 const Ipv6Header& ipv6Header,
1241 Ipv6Address dst,
1242 uint8_t* nextHeader,
1243 bool& stopProcessing,
1244 bool& isDropped,
1245 Ipv6L3Protocol::DropReason& dropReason)
1246{
1247 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1248
1249 /** \todo */
1250
1251 return 0;
1252}
1253
1255
1256TypeId
1258{
1259 static TypeId tid = TypeId("ns3::Ipv6ExtensionAH")
1261 .SetGroupName("Internet")
1262 .AddConstructor<Ipv6ExtensionAH>();
1263 return tid;
1264}
1265
1267{
1268}
1269
1271{
1272}
1273
1274uint8_t
1276{
1277 return EXT_NUMBER;
1278}
1279
1280uint8_t
1282 uint8_t offset,
1283 const Ipv6Header& ipv6Header,
1284 Ipv6Address dst,
1285 uint8_t* nextHeader,
1286 bool& stopProcessing,
1287 bool& isDropped,
1288 Ipv6L3Protocol::DropReason& dropReason)
1289{
1290 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1291
1292 /** \todo */
1293
1294 return 1;
1295}
1296
1297} /* 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:522
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:444
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:77
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:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
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:1413
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
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:1434
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
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:1326
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Definition: second.py:1
uint8_t data[writeSize]