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"
23 #include "ipv6-extension-demux.h"
24 #include "ipv6-extension-header.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 
41 namespace ns3
42 {
43 
44 NS_LOG_COMPONENT_DEFINE("Ipv6Extension");
45 
46 NS_OBJECT_ENSURE_REGISTERED(Ipv6Extension);
47 
48 TypeId
50 {
51  static TypeId tid = TypeId("ns3::Ipv6Extension")
52  .SetParent<Object>()
53  .SetGroupName("Internet")
54  .AddAttribute("ExtensionNumber",
55  "The IPv6 extension number.",
56  UintegerValue(0),
58  MakeUintegerChecker<uint8_t>());
59  return tid;
60 }
61 
63 {
64  m_uvar = CreateObject<UniformRandomVariable>();
65 }
66 
68 {
69 }
70 
71 void
73 {
74  NS_LOG_FUNCTION(this << node);
75 
76  m_node = node;
77 }
78 
81 {
82  return m_node;
83 }
84 
85 uint8_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,
94  Ipv6L3Protocol::DropReason& dropReason)
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 
107  Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode()->GetObject<Ipv6OptionDemux>();
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 
187 int64_t
189 {
190  NS_LOG_FUNCTION(this << stream);
191  m_uvar->SetStream(stream);
192  return 1;
193 }
194 
196 
197 TypeId
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 
215 uint8_t
217 {
218  return EXT_NUMBER;
219 }
220 
221 uint8_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 
262 TypeId
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 
280 uint8_t
282 {
283  return EXT_NUMBER;
284 }
285 
286 uint8_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 
327 TypeId
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)),
340  MakeTimeChecker());
341  return tid;
342 }
343 
345 {
346 }
347 
349 {
350 }
351 
352 void
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 
371 uint8_t
373 {
374  return EXT_NUMBER;
375 }
376 
377 uint8_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 
455 void
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 
640 void
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 
692 void
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 
731 void
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 
755 void
757 {
758  NS_LOG_FUNCTION(this << unfragmentablePart);
759  m_unfragmentable = unfragmentablePart;
760 }
761 
762 bool
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 
828 void
830 {
831  NS_LOG_FUNCTION(this);
832  m_timeoutIter = iter;
833 }
834 
837 {
838  return m_timeoutIter;
839 }
840 
842 
843 TypeId
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 
861 uint8_t
863 {
864  return EXT_NUMBER;
865 }
866 
867 uint8_t
869 {
870  return 0;
871 }
872 
875 {
876  return nullptr;
877 }
878 
879 uint8_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 
952 TypeId
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 
975 void
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 
989 void
991 {
992  NS_LOG_FUNCTION(this << node);
993  m_node = node;
994 }
995 
996 void
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 
1033 void
1035 {
1036  NS_LOG_FUNCTION(this << extensionRouting);
1037  m_extensionsRouting.remove(extensionRouting);
1038 }
1039 
1041 
1042 TypeId
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 
1060 uint8_t
1062 {
1063  return TYPE_ROUTING;
1064 }
1065 
1068 {
1069  return new Ipv6ExtensionLooseRoutingHeader();
1070 }
1071 
1072 uint8_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();
1190  Socket::SocketErrno err;
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 
1213 TypeId
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 
1231 uint8_t
1233 {
1234  return EXT_NUMBER;
1235 }
1236 
1237 uint8_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 
1251  return 0;
1252 }
1253 
1255 
1256 TypeId
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 
1274 uint8_t
1276 {
1277  return EXT_NUMBER;
1278 }
1279 
1280 uint8_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 
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.
std::list< std::tuple< Time, FragmentKey_t, Ipv6Header > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
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.
~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:352
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:861
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: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
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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
#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.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
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(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
Definition: second.py:1
uint8_t data[writeSize]