A Discrete-Event Network Simulator
API
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-option-demux.h"
26#include "ipv6-option.h"
27#include "udp-header.h"
28
29#include "ns3/assert.h"
30#include "ns3/ipv6-address.h"
31#include "ns3/ipv6-header.h"
32#include "ns3/ipv6-l3-protocol.h"
33#include "ns3/ipv6-list-routing.h"
34#include "ns3/ipv6-route.h"
35#include "ns3/ipv6-static-routing.h"
36#include "ns3/log.h"
37#include "ns3/object-vector.h"
38#include "ns3/trace-source-accessor.h"
39#include "ns3/uinteger.h"
40
41#include <ctime>
42#include <list>
43
44namespace ns3
45{
46
47NS_LOG_COMPONENT_DEFINE("Ipv6Extension");
48
49NS_OBJECT_ENSURE_REGISTERED(Ipv6Extension);
50
51TypeId
53{
54 static TypeId tid = TypeId("ns3::Ipv6Extension")
56 .SetGroupName("Internet")
57 .AddAttribute("ExtensionNumber",
58 "The IPv6 extension number.",
61 MakeUintegerChecker<uint8_t>());
62 return tid;
63}
64
66{
67 m_uvar = CreateObject<UniformRandomVariable>();
68}
69
71{
72}
73
74void
76{
77 NS_LOG_FUNCTION(this << node);
78
79 m_node = node;
80}
81
84{
85 return m_node;
86}
87
88uint8_t
90 uint8_t offset,
91 uint8_t length,
92 const Ipv6Header& ipv6Header,
93 Ipv6Address dst,
94 uint8_t* nextHeader,
95 bool& stopProcessing,
96 bool& isDropped,
98{
99 NS_LOG_FUNCTION(this << packet << offset << length << ipv6Header << dst << nextHeader
100 << isDropped);
101
102 // For ICMPv6 Error packets
103 Ptr<Packet> malformedPacket = packet->Copy();
104 malformedPacket->AddHeader(ipv6Header);
105 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
106
107 Ptr<Packet> p = packet->Copy();
108 p->RemoveAtStart(offset);
109
111 Ptr<Ipv6Option> ipv6Option;
112
113 uint8_t processedSize = 0;
114 uint32_t size = p->GetSize();
115 uint8_t* data = new uint8_t[size];
116 p->CopyData(data, size);
117
118 uint8_t optionType = 0;
119 uint8_t optionLength = 0;
120
121 while (length > processedSize && !isDropped)
122 {
123 optionType = *(data + processedSize);
124 ipv6Option = ipv6OptionDemux->GetOption(optionType);
125
126 if (!ipv6Option)
127 {
128 optionType >>= 6;
129 switch (optionType)
130 {
131 case 0:
132 optionLength = *(data + processedSize + 1) + 2;
133 break;
134
135 case 1:
136 NS_LOG_LOGIC("Unknown Option. Drop!");
137 optionLength = 0;
138 isDropped = true;
139 stopProcessing = true;
141 break;
142
143 case 2:
144 NS_LOG_LOGIC("Unknown Option. Drop!");
145 icmpv6->SendErrorParameterError(malformedPacket,
146 ipv6Header.GetSource(),
148 offset + processedSize);
149 optionLength = 0;
150 isDropped = true;
151 stopProcessing = true;
153 break;
154
155 case 3:
156 NS_LOG_LOGIC("Unknown Option. Drop!");
157
158 if (!ipv6Header.GetDestination().IsMulticast())
159 {
160 icmpv6->SendErrorParameterError(malformedPacket,
161 ipv6Header.GetSource(),
163 offset + processedSize);
164 }
165 optionLength = 0;
166 isDropped = true;
167 stopProcessing = true;
169 break;
170
171 default:
172 break;
173 }
174 }
175 else
176 {
177 optionLength =
178 ipv6Option->Process(packet, offset + processedSize, ipv6Header, isDropped);
179 }
180
181 processedSize += optionLength;
182 p->RemoveAtStart(optionLength);
183 }
184
185 delete[] data;
186
187 return processedSize;
188}
189
190int64_t
192{
193 NS_LOG_FUNCTION(this << stream);
194 m_uvar->SetStream(stream);
195 return 1;
196}
197
199
200TypeId
202{
203 static TypeId tid = TypeId("ns3::Ipv6ExtensionHopByHop")
205 .SetGroupName("Internet")
206 .AddConstructor<Ipv6ExtensionHopByHop>();
207 return tid;
208}
209
211{
212}
213
215{
216}
217
218uint8_t
220{
221 return EXT_NUMBER;
222}
223
224uint8_t
226 uint8_t offset,
227 const Ipv6Header& ipv6Header,
228 Ipv6Address dst,
229 uint8_t* nextHeader,
230 bool& stopProcessing,
231 bool& isDropped,
232 Ipv6L3Protocol::DropReason& dropReason)
233{
234 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
235
236 Ptr<Packet> p = packet->Copy();
237 p->RemoveAtStart(offset);
238
239 Ipv6ExtensionHopByHopHeader hopbyhopHeader;
240 p->RemoveHeader(hopbyhopHeader);
241 if (nextHeader)
242 {
243 *nextHeader = hopbyhopHeader.GetNextHeader();
244 }
245
246 uint8_t processedSize = hopbyhopHeader.GetOptionsOffset();
247 offset += processedSize;
248 uint8_t length = hopbyhopHeader.GetLength() - hopbyhopHeader.GetOptionsOffset();
249
250 processedSize += ProcessOptions(packet,
251 offset,
252 length,
253 ipv6Header,
254 dst,
255 nextHeader,
256 stopProcessing,
257 isDropped,
258 dropReason);
259
260 return processedSize;
261}
262
264
265TypeId
267{
268 static TypeId tid = TypeId("ns3::Ipv6ExtensionDestination")
270 .SetGroupName("Internet")
271 .AddConstructor<Ipv6ExtensionDestination>();
272 return tid;
273}
274
276{
277}
278
280{
281}
282
283uint8_t
285{
286 return EXT_NUMBER;
287}
288
289uint8_t
291 uint8_t offset,
292 const Ipv6Header& ipv6Header,
293 Ipv6Address dst,
294 uint8_t* nextHeader,
295 bool& stopProcessing,
296 bool& isDropped,
297 Ipv6L3Protocol::DropReason& dropReason)
298{
299 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
300
301 Ptr<Packet> p = packet->Copy();
302 p->RemoveAtStart(offset);
303
304 Ipv6ExtensionDestinationHeader destinationHeader;
305 p->RemoveHeader(destinationHeader);
306 if (nextHeader)
307 {
308 *nextHeader = destinationHeader.GetNextHeader();
309 }
310
311 uint8_t processedSize = destinationHeader.GetOptionsOffset();
312 offset += processedSize;
313 uint8_t length = destinationHeader.GetLength() - destinationHeader.GetOptionsOffset();
314
315 processedSize += ProcessOptions(packet,
316 offset,
317 length,
318 ipv6Header,
319 dst,
320 nextHeader,
321 stopProcessing,
322 isDropped,
323 dropReason);
324
325 return processedSize;
326}
327
329
330TypeId
332{
333 static TypeId tid =
334 TypeId("ns3::Ipv6ExtensionFragment")
336 .SetGroupName("Internet")
337 .AddConstructor<Ipv6ExtensionFragment>()
338 .AddAttribute("FragmentExpirationTimeout",
339 "When this timeout expires, the fragments "
340 "will be cleared from the buffer.",
341 TimeValue(Seconds(60)),
344 return tid;
345}
346
348{
349}
350
352{
353}
354
355void
357{
358 NS_LOG_FUNCTION(this);
359
360 for (MapFragments_t::iterator it = m_fragments.begin(); it != m_fragments.end(); it++)
361 {
362 it->second = nullptr;
363 }
364
365 m_fragments.clear();
366 m_timeoutEventList.clear();
368 {
370 }
372}
373
374uint8_t
376{
377 return EXT_NUMBER;
378}
379
380uint8_t
382 uint8_t offset,
383 const Ipv6Header& ipv6Header,
384 Ipv6Address dst,
385 uint8_t* nextHeader,
386 bool& stopProcessing,
387 bool& isDropped,
388 Ipv6L3Protocol::DropReason& dropReason)
389{
390 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
391
392 Ptr<Packet> p = packet->Copy();
393 p->RemoveAtStart(offset);
394
395 Ipv6ExtensionFragmentHeader fragmentHeader;
396 p->RemoveHeader(fragmentHeader);
397
398 if (nextHeader)
399 {
400 *nextHeader = fragmentHeader.GetNextHeader();
401 }
402
403 bool moreFragment = fragmentHeader.GetMoreFragment();
404 uint16_t fragmentOffset = fragmentHeader.GetOffset();
405 uint32_t identification = fragmentHeader.GetIdentification();
406 Ipv6Address src = ipv6Header.GetSource();
407
408 FragmentKey_t fragmentKey = FragmentKey_t(src, identification);
409 Ptr<Fragments> fragments;
410
411 Ipv6Header ipHeader = ipv6Header;
412 ipHeader.SetNextHeader(fragmentHeader.GetNextHeader());
413
414 MapFragments_t::iterator it = m_fragments.find(fragmentKey);
415 if (it == m_fragments.end())
416 {
417 fragments = Create<Fragments>();
418 m_fragments.insert(std::make_pair(fragmentKey, fragments));
419 NS_LOG_DEBUG("Insert new fragment key: src: "
420 << src << " IP hdr id " << identification << " m_fragments.size() "
421 << m_fragments.size() << " offset " << fragmentOffset);
422 FragmentsTimeoutsListI_t iter = SetTimeout(fragmentKey, ipHeader);
423 fragments->SetTimeoutIter(iter);
424 }
425 else
426 {
427 fragments = it->second;
428 }
429
430 if (fragmentOffset == 0)
431 {
432 Ptr<Packet> unfragmentablePart = packet->Copy();
433 unfragmentablePart->RemoveAtEnd(packet->GetSize() - offset);
434 fragments->SetUnfragmentablePart(unfragmentablePart);
435 }
436
437 NS_LOG_DEBUG("Add fragment with IP hdr id " << identification << " offset " << fragmentOffset);
438 fragments->AddFragment(p, fragmentOffset, moreFragment);
439
440 if (fragments->IsEntire())
441 {
442 packet = fragments->GetPacket();
443 m_timeoutEventList.erase(fragments->GetTimeoutIter());
444 m_fragments.erase(fragmentKey);
445 NS_LOG_DEBUG("Finished fragment with IP hdr id "
446 << fragmentKey.second
447 << " erase timeout, m_fragments.size(): " << m_fragments.size());
448 stopProcessing = false;
449 }
450 else
451 {
452 stopProcessing = true;
453 }
454
455 return 0;
456}
457
458void
460 Ipv6Header ipv6Header,
461 uint32_t maxFragmentSize,
462 std::list<Ipv6PayloadHeaderPair>& listFragments)
463{
464 NS_LOG_FUNCTION(this << packet << ipv6Header << maxFragmentSize);
465 Ptr<Packet> p = packet->Copy();
466
467 uint8_t nextHeader = ipv6Header.GetNextHeader();
468 uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize();
469
470 uint8_t type;
471 p->CopyData(&type, sizeof(type));
472
473 bool moreHeader = true;
474 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
475 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
477 {
478 moreHeader = false;
480 }
481
482 std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>> unfragmentablePart;
483 uint32_t unfragmentablePartSize = 0;
484
486 Ptr<Ipv6Extension> extension = extensionDemux->GetExtension(nextHeader);
487 uint8_t extensionHeaderLength;
488
489 while (moreHeader)
490 {
491 if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
492 {
494 p->RemoveHeader(*hopbyhopHeader);
495
496 nextHeader = hopbyhopHeader->GetNextHeader();
497 extensionHeaderLength = hopbyhopHeader->GetLength();
498
499 uint8_t type;
500 p->CopyData(&type, sizeof(type));
501
502 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
503 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
504 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
506 {
507 moreHeader = false;
509 }
510
511 unfragmentablePart.emplace_back(hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP);
512 unfragmentablePartSize += extensionHeaderLength;
513 }
514 else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
515 {
516 uint8_t buf[2];
517 p->CopyData(buf, sizeof(buf));
518 uint8_t numberAddress = buf[1] / 2;
520 routingHeader->SetNumberAddress(numberAddress);
521 p->RemoveHeader(*routingHeader);
522
523 nextHeader = routingHeader->GetNextHeader();
524 extensionHeaderLength = routingHeader->GetLength();
525
526 uint8_t type;
527 p->CopyData(&type, sizeof(type));
528 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
529 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
530 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
532 {
533 moreHeader = false;
535 }
536
537 unfragmentablePart.emplace_back(routingHeader, Ipv6Header::IPV6_EXT_ROUTING);
538 unfragmentablePartSize += extensionHeaderLength;
539 }
540 else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
541 {
542 Ipv6ExtensionDestinationHeader* destinationHeader =
544 p->RemoveHeader(*destinationHeader);
545
546 nextHeader = destinationHeader->GetNextHeader();
547 extensionHeaderLength = destinationHeader->GetLength();
548
549 uint8_t type;
550 p->CopyData(&type, sizeof(type));
551 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP ||
552 nextHeader == Ipv6Header::IPV6_EXT_ROUTING ||
553 (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION &&
555 {
556 moreHeader = false;
558 }
559
560 unfragmentablePart.emplace_back(destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION);
561 unfragmentablePartSize += extensionHeaderLength;
562 }
563 }
564
565 Ipv6ExtensionFragmentHeader fragmentHeader;
566 uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize();
567
568 uint32_t maxFragmentablePartSize =
569 maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
570 uint32_t currentFragmentablePartSize = 0;
571
572 bool moreFragment = true;
573 uint32_t identification = (uint32_t)m_uvar->GetValue(0, (uint32_t)-1);
574 uint16_t offset = 0;
575
576 do
577 {
578 if (p->GetSize() > offset + maxFragmentablePartSize)
579 {
580 moreFragment = true;
581 currentFragmentablePartSize = maxFragmentablePartSize;
582 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
583 }
584 else
585 {
586 moreFragment = false;
587 currentFragmentablePartSize = p->GetSize() - offset;
588 }
589
590 fragmentHeader.SetNextHeader(nextHeader);
591 fragmentHeader.SetOffset(offset);
592 fragmentHeader.SetMoreFragment(moreFragment);
593 fragmentHeader.SetIdentification(identification);
594
595 Ptr<Packet> fragment = p->CreateFragment(offset, currentFragmentablePartSize);
596 offset += currentFragmentablePartSize;
597
598 fragment->AddHeader(fragmentHeader);
599
600 for (std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>>::iterator it =
601 unfragmentablePart.begin();
602 it != unfragmentablePart.end();
603 it++)
604 {
605 if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
606 {
608 dynamic_cast<Ipv6ExtensionHopByHopHeader*>(it->first);
609 NS_ASSERT(p != nullptr);
610 fragment->AddHeader(*p);
611 }
612 else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
613 {
615 dynamic_cast<Ipv6ExtensionLooseRoutingHeader*>(it->first);
616 NS_ASSERT(p != nullptr);
617 fragment->AddHeader(*p);
618 }
619 else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
620 {
622 dynamic_cast<Ipv6ExtensionDestinationHeader*>(it->first);
623 NS_ASSERT(p != nullptr);
624 fragment->AddHeader(*p);
625 }
626 }
627
628 ipv6Header.SetPayloadLength(fragment->GetSize());
629
630 std::ostringstream oss;
631 oss << ipv6Header;
632 fragment->Print(oss);
633
634 listFragments.emplace_back(fragment, ipv6Header);
635 } while (moreFragment);
636
637 for (std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>>::iterator it =
638 unfragmentablePart.begin();
639 it != unfragmentablePart.end();
640 it++)
641 {
642 delete it->first;
643 }
644
645 unfragmentablePart.clear();
646}
647
648void
650{
651 NS_LOG_FUNCTION(this << fragmentKey.first << fragmentKey.second << ipHeader);
652 Ptr<Fragments> fragments;
653
654 MapFragments_t::iterator it = m_fragments.find(fragmentKey);
655 NS_ASSERT_MSG(it != m_fragments.end(),
656 "IPv6 Fragment timeout reached for non-existent fragment");
657 fragments = it->second;
658
659 Ptr<Packet> packet = fragments->GetPartialPacket();
660
661 // if we have at least 8 bytes, we can send an ICMP.
662 if (packet && packet->GetSize() > 8)
663 {
664 Ptr<Packet> p = packet->Copy();
665 p->AddHeader(ipHeader);
667 icmp->SendErrorTimeExceeded(p, ipHeader.GetSource(), Icmpv6Header::ICMPV6_FRAGTIME);
668 }
669
671 ipL3->ReportDrop(ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
672
673 // clear the buffers
674 m_fragments.erase(fragmentKey);
675}
676
679{
680 NS_LOG_FUNCTION(this << key.first << key.second << ipHeader);
681 if (m_timeoutEventList.empty())
682 {
683 NS_LOG_DEBUG("Scheduling timeout for IP hdr id "
684 << key.second << " at time "
685 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds());
688 this);
689 }
690 NS_LOG_DEBUG("Adding timeout at "
691 << (Simulator::Now() + m_fragmentExpirationTimeout).GetSeconds() << " with key "
692 << key.second);
693 m_timeoutEventList.emplace_back(Simulator::Now() + m_fragmentExpirationTimeout, key, ipHeader);
694
696
697 return (iter);
698}
699
700void
702{
703 NS_LOG_FUNCTION(this);
704 Time now = Simulator::Now();
705
706 // std::list Time, Fragment_key_t, Ipv6Header
707 // Fragment key is a pair: Ipv6Address, uint32_t ipHeaderId
708 for (auto& element : m_timeoutEventList)
709 {
710 NS_LOG_DEBUG("Handle time " << std::get<0>(element).GetSeconds() << " IP hdr id "
711 << std::get<1>(element).second);
712 }
713 while (!m_timeoutEventList.empty() && std::get<0>(*m_timeoutEventList.begin()) == now)
714 {
715 HandleFragmentsTimeout(std::get<1>(*m_timeoutEventList.begin()),
716 std::get<2>(*m_timeoutEventList.begin()));
717 m_timeoutEventList.pop_front();
718 }
719
720 if (m_timeoutEventList.empty())
721 {
722 return;
723 }
724
725 Time difference = std::get<0>(*m_timeoutEventList.begin()) - now;
726 NS_LOG_DEBUG("Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
728}
729
731 : m_moreFragment(0)
732{
733}
734
736{
737}
738
739void
741 uint16_t fragmentOffset,
742 bool moreFragment)
743{
744 NS_LOG_FUNCTION(this << fragment << fragmentOffset << moreFragment);
745 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
746
747 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
748 {
749 if (it->second > fragmentOffset)
750 {
751 break;
752 }
753 }
754
755 if (it == m_packetFragments.end())
756 {
757 m_moreFragment = moreFragment;
758 }
759
760 m_packetFragments.insert(it, std::pair<Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
761}
762
763void
765{
766 NS_LOG_FUNCTION(this << unfragmentablePart);
767 m_unfragmentable = unfragmentablePart;
768}
769
770bool
772{
773 bool ret = !m_moreFragment && !m_packetFragments.empty();
774
775 if (ret)
776 {
777 uint16_t lastEndOffset = 0;
778
779 for (std::list<std::pair<Ptr<Packet>, uint16_t>>::const_iterator it =
780 m_packetFragments.begin();
781 it != m_packetFragments.end();
782 it++)
783 {
784 if (lastEndOffset != it->second)
785 {
786 ret = false;
787 break;
788 }
789
790 lastEndOffset += it->first->GetSize();
791 }
792 }
793
794 return ret;
795}
796
799{
800 Ptr<Packet> p = m_unfragmentable->Copy();
801
802 for (std::list<std::pair<Ptr<Packet>, uint16_t>>::const_iterator it = m_packetFragments.begin();
803 it != m_packetFragments.end();
804 it++)
805 {
806 p->AddAtEnd(it->first);
807 }
808
809 return p;
810}
811
814{
815 Ptr<Packet> p;
816
817 if (m_unfragmentable)
818 {
819 p = m_unfragmentable->Copy();
820 }
821 else
822 {
823 return p;
824 }
825
826 uint16_t lastEndOffset = 0;
827
828 for (std::list<std::pair<Ptr<Packet>, uint16_t>>::const_iterator it = m_packetFragments.begin();
829 it != m_packetFragments.end();
830 it++)
831 {
832 if (lastEndOffset != it->second)
833 {
834 break;
835 }
836 p->AddAtEnd(it->first);
837 lastEndOffset += it->first->GetSize();
838 }
839
840 return p;
841}
842
843void
845{
846 NS_LOG_FUNCTION(this);
847 m_timeoutIter = iter;
848}
849
852{
853 return m_timeoutIter;
854}
855
857
858TypeId
860{
861 static TypeId tid = TypeId("ns3::Ipv6ExtensionRouting")
863 .SetGroupName("Internet")
864 .AddConstructor<Ipv6ExtensionRouting>();
865 return tid;
866}
867
869{
870}
871
873{
874}
875
876uint8_t
878{
879 return EXT_NUMBER;
880}
881
882uint8_t
884{
885 return 0;
886}
887
888uint8_t
890 uint8_t offset,
891 const Ipv6Header& ipv6Header,
892 Ipv6Address dst,
893 uint8_t* nextHeader,
894 bool& stopProcessing,
895 bool& isDropped,
896 Ipv6L3Protocol::DropReason& dropReason)
897{
898 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
899
900 // For ICMPv6 Error Packets
901 Ptr<Packet> malformedPacket = packet->Copy();
902 malformedPacket->AddHeader(ipv6Header);
903
904 Ptr<Packet> p = packet->Copy();
905 p->RemoveAtStart(offset);
906
907 uint8_t buf[4];
908 packet->CopyData(buf, sizeof(buf));
909
910 uint8_t routingNextHeader = buf[0];
911 uint8_t routingLength = buf[1];
912 uint8_t routingTypeRouting = buf[2];
913 uint8_t routingSegmentsLeft = buf[3];
914
915 if (nextHeader)
916 {
917 *nextHeader = routingNextHeader;
918 }
919
920 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
921
922 Ptr<Ipv6ExtensionRoutingDemux> ipv6ExtensionRoutingDemux =
924 Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting =
925 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
926
927 if (!ipv6ExtensionRouting)
928 {
929 if (routingSegmentsLeft == 0)
930 {
931 isDropped = false;
932 }
933 else
934 {
935 NS_LOG_LOGIC("Malformed header. Drop!");
936
937 icmpv6->SendErrorParameterError(malformedPacket,
938 ipv6Header.GetSource(),
940 offset + 1);
942 isDropped = true;
943 stopProcessing = true;
944 }
945
946 return routingLength;
947 }
948
949 return ipv6ExtensionRouting->Process(packet,
950 offset,
951 ipv6Header,
952 dst,
953 (uint8_t*)nullptr,
954 stopProcessing,
955 isDropped,
956 dropReason);
957}
958
960
961TypeId
963{
964 static TypeId tid =
965 TypeId("ns3::Ipv6ExtensionRoutingDemux")
966 .SetParent<Object>()
967 .SetGroupName("Internet")
968 .AddAttribute("RoutingExtensions",
969 "The set of IPv6 Routing extensions registered with this demux.",
972 MakeObjectVectorChecker<Ipv6ExtensionRouting>());
973 return tid;
974}
975
977{
978}
979
981{
982}
983
984void
986{
987 NS_LOG_FUNCTION(this);
988 for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin();
989 it != m_extensionsRouting.end();
990 it++)
991 {
992 (*it)->Dispose();
993 *it = nullptr;
994 }
995 m_extensionsRouting.clear();
996 m_node = nullptr;
998}
999
1000void
1002{
1003 NS_LOG_FUNCTION(this << node);
1004 m_node = node;
1005}
1006
1007void
1009{
1010 NS_LOG_FUNCTION(this << extensionRouting);
1011 m_extensionsRouting.push_back(extensionRouting);
1012}
1013
1016{
1017 for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin();
1018 i != m_extensionsRouting.end();
1019 i++)
1020 {
1021 if ((*i)->GetTypeRouting() == typeRouting)
1022 {
1023 return *i;
1024 }
1025 }
1026 return nullptr;
1027}
1028
1029void
1031{
1032 NS_LOG_FUNCTION(this << extensionRouting);
1033 m_extensionsRouting.remove(extensionRouting);
1034}
1035
1037
1038TypeId
1040{
1041 static TypeId tid = TypeId("ns3::Ipv6ExtensionLooseRouting")
1043 .SetGroupName("Internet")
1044 .AddConstructor<Ipv6ExtensionLooseRouting>();
1045 return tid;
1046}
1047
1049{
1050}
1051
1053{
1054}
1055
1056uint8_t
1058{
1059 return TYPE_ROUTING;
1060}
1061
1062uint8_t
1064 uint8_t offset,
1065 const Ipv6Header& ipv6Header,
1066 Ipv6Address dst,
1067 uint8_t* nextHeader,
1068 bool& stopProcessing,
1069 bool& isDropped,
1070 Ipv6L3Protocol::DropReason& dropReason)
1071{
1072 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1073
1074 // For ICMPv6 Error packets
1075 Ptr<Packet> malformedPacket = packet->Copy();
1076 malformedPacket->AddHeader(ipv6Header);
1077
1078 Ptr<Packet> p = packet->Copy();
1079 p->RemoveAtStart(offset);
1080
1081 // Copy IPv6 Header : ipv6Header -> ipv6header
1082 Buffer tmp;
1083 tmp.AddAtStart(ipv6Header.GetSerializedSize());
1084 Buffer::Iterator it = tmp.Begin();
1085 Ipv6Header ipv6header;
1086 ipv6Header.Serialize(it);
1087 ipv6header.Deserialize(it);
1088
1089 // Get the number of routers' address field
1090 uint8_t buf[2];
1091 p->CopyData(buf, sizeof(buf));
1092 uint8_t numberAddress = buf[1] / 2;
1093 Ipv6ExtensionLooseRoutingHeader routingHeader;
1094 routingHeader.SetNumberAddress(numberAddress);
1095 p->RemoveHeader(routingHeader);
1096
1097 if (nextHeader)
1098 {
1099 *nextHeader = routingHeader.GetNextHeader();
1100 }
1101
1102 Ptr<Icmpv6L4Protocol> icmpv6 = GetNode()->GetObject<Ipv6L3Protocol>()->GetIcmpv6();
1103
1104 Ipv6Address srcAddress = ipv6header.GetSource();
1105 Ipv6Address destAddress = ipv6header.GetDestination();
1106 uint8_t hopLimit = ipv6header.GetHopLimit();
1107 uint8_t segmentsLeft = routingHeader.GetSegmentsLeft();
1108 uint8_t length = (routingHeader.GetLength() >> 3) - 1;
1109 uint8_t nbAddress = length / 2;
1110 uint8_t nextAddressIndex;
1111 Ipv6Address nextAddress;
1112
1113 if (segmentsLeft == 0)
1114 {
1115 isDropped = false;
1116 return routingHeader.GetSerializedSize();
1117 }
1118
1119 if (length % 2 != 0)
1120 {
1121 NS_LOG_LOGIC("Malformed header. Drop!");
1122 icmpv6->SendErrorParameterError(malformedPacket,
1123 srcAddress,
1125 offset + 1);
1127 isDropped = true;
1128 stopProcessing = true;
1129 return routingHeader.GetSerializedSize();
1130 }
1131
1132 if (segmentsLeft > nbAddress)
1133 {
1134 NS_LOG_LOGIC("Malformed header. Drop!");
1135 icmpv6->SendErrorParameterError(malformedPacket,
1136 srcAddress,
1138 offset + 3);
1140 isDropped = true;
1141 stopProcessing = true;
1142 return routingHeader.GetSerializedSize();
1143 }
1144
1145 routingHeader.SetSegmentsLeft(segmentsLeft - 1);
1146 nextAddressIndex = nbAddress - segmentsLeft;
1147 nextAddress = routingHeader.GetRouterAddress(nextAddressIndex);
1148
1149 if (nextAddress.IsMulticast() || destAddress.IsMulticast())
1150 {
1152 isDropped = true;
1153 stopProcessing = true;
1154 return routingHeader.GetSerializedSize();
1155 }
1156
1157 routingHeader.SetRouterAddress(nextAddressIndex, destAddress);
1158 ipv6header.SetDestination(nextAddress);
1159
1160 if (hopLimit <= 1)
1161 {
1162 NS_LOG_LOGIC("Time Exceeded : Hop Limit <= 1. Drop!");
1163 icmpv6->SendErrorTimeExceeded(malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
1165 isDropped = true;
1166 stopProcessing = true;
1167 return routingHeader.GetSerializedSize();
1168 }
1169
1170 ipv6header.SetHopLimit(hopLimit - 1);
1171 p->AddHeader(routingHeader);
1172
1173 /* short-circuiting routing stuff
1174 *
1175 * If we process this option,
1176 * the packet was for us so we resend it to
1177 * the new destination (modified in the header above).
1178 */
1179
1181 Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol();
1183 NS_ASSERT(ipv6rp);
1184
1185 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header, nullptr, err);
1186
1187 if (rtentry)
1188 {
1189 /* we know a route exists so send packet now */
1190 ipv6->SendRealOut(rtentry, p, ipv6header);
1191 }
1192 else
1193 {
1194 NS_LOG_INFO("No route for next router");
1195 }
1196
1197 /* as we directly send packet, mark it as dropped */
1198 isDropped = true;
1199
1200 return routingHeader.GetSerializedSize();
1201}
1202
1204
1205TypeId
1207{
1208 static TypeId tid = TypeId("ns3::Ipv6ExtensionESP")
1210 .SetGroupName("Internet")
1211 .AddConstructor<Ipv6ExtensionESP>();
1212 return tid;
1213}
1214
1216{
1217}
1218
1220{
1221}
1222
1223uint8_t
1225{
1226 return EXT_NUMBER;
1227}
1228
1229uint8_t
1231 uint8_t offset,
1232 const Ipv6Header& ipv6Header,
1233 Ipv6Address dst,
1234 uint8_t* nextHeader,
1235 bool& stopProcessing,
1236 bool& isDropped,
1237 Ipv6L3Protocol::DropReason& dropReason)
1238{
1239 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1240
1243 return 0;
1244}
1245
1247
1248TypeId
1250{
1251 static TypeId tid = TypeId("ns3::Ipv6ExtensionAH")
1253 .SetGroupName("Internet")
1254 .AddConstructor<Ipv6ExtensionAH>();
1255 return tid;
1256}
1257
1259{
1260}
1261
1263{
1264}
1265
1266uint8_t
1268{
1269 return EXT_NUMBER;
1270}
1271
1272uint8_t
1274 uint8_t offset,
1275 const Ipv6Header& ipv6Header,
1276 Ipv6Address dst,
1277 uint8_t* nextHeader,
1278 bool& stopProcessing,
1279 bool& isDropped,
1280 Ipv6L3Protocol::DropReason& dropReason)
1281{
1282 NS_LOG_FUNCTION(this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1283
1286 return true;
1287}
1288
1289} /* 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:311
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.
void SetNumberAddress(uint8_t n)
Set the number of routers' 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.
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.
~Ipv6ExtensionRoutingDemux() override
Destructor.
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.
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.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:862
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:376
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:384
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:238
void Print(std::ostream &os) const
Print the packet contents.
Definition: packet.cc:456
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:935
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 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.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
Definition: second.py:1
#define list
uint8_t data[writeSize]