A Discrete-Event Network Simulator
API
ipv6-extension.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007-2009 Strasbourg University
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: David Gross <gdavid.devel@gmail.com>
19  */
20 
21 #include <list>
22 #include <ctime>
23 
24 #include "ns3/log.h"
25 #include "ns3/assert.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/object-vector.h"
28 #include "ns3/ipv6-address.h"
29 #include "ns3/ipv6-header.h"
30 #include "ns3/ipv6-l3-protocol.h"
31 #include "ns3/ipv6-static-routing.h"
32 #include "ns3/ipv6-list-routing.h"
33 #include "ns3/ipv6-route.h"
34 #include "ns3/trace-source-accessor.h"
35 #include "icmpv6-l4-protocol.h"
36 #include "ipv6-extension-demux.h"
37 #include "ipv6-extension.h"
38 #include "ipv6-extension-header.h"
39 #include "ipv6-option-demux.h"
40 #include "ipv6-option.h"
41 #include "udp-header.h"
42 
43 namespace ns3 {
44 
45 NS_LOG_COMPONENT_DEFINE ("Ipv6Extension");
46 
47 NS_OBJECT_ENSURE_REGISTERED (Ipv6Extension);
48 
50 {
51  static TypeId tid = TypeId ("ns3::Ipv6Extension")
52  .SetParent<Object> ()
53  .SetGroupName ("Internet")
54  .AddAttribute ("ExtensionNumber", "The IPv6 extension number.",
55  UintegerValue (0),
57  MakeUintegerChecker<uint8_t> ())
58  ;
59  return tid;
60 }
61 
63 {
65 
66  m_uvar = CreateObject<UniformRandomVariable> ();
67 }
68 
70 {
72 }
73 
75 {
76  NS_LOG_FUNCTION (this << node);
77 
78  m_node = node;
79 }
80 
82 {
84 
85  return m_node;
86 }
87 
89  uint8_t offset,
90  uint8_t length,
91  Ipv6Header const& ipv6Header,
92  Ipv6Address dst,
93  uint8_t *nextHeader,
94  bool& stopProcessing,
95  bool& isDropped,
96  Ipv6L3Protocol::DropReason& dropReason)
97 {
98  NS_LOG_FUNCTION (this << packet << offset << length << ipv6Header << dst << nextHeader << isDropped);
99 
100  // For ICMPv6 Error packets
101  Ptr<Packet> malformedPacket = packet->Copy ();
102  malformedPacket->AddHeader (ipv6Header);
103  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
104 
105  Ptr<Packet> p = packet->Copy ();
106  p->RemoveAtStart (offset);
107 
108  Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> ();
109  Ptr<Ipv6Option> ipv6Option;
110 
111  uint8_t processedSize = 0;
112  uint32_t size = p->GetSize ();
113  uint8_t *data = new uint8_t[size];
114  p->CopyData (data, size);
115 
116  uint8_t optionType = 0;
117  uint8_t optionLength = 0;
118 
119  while (length > processedSize && !isDropped)
120  {
121  optionType = *(data + processedSize);
122  ipv6Option = ipv6OptionDemux->GetOption (optionType);
123 
124  if (ipv6Option == 0)
125  {
126  optionType >>= 6;
127  switch (optionType)
128  {
129  case 0:
130  optionLength = *(data + processedSize + 1) + 2;
131  break;
132 
133  case 1:
134  NS_LOG_LOGIC ("Unknown Option. Drop!");
135  optionLength = 0;
136  isDropped = true;
137  stopProcessing = true;
139  break;
140 
141  case 2:
142  NS_LOG_LOGIC ("Unknown Option. Drop!");
143  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
144  optionLength = 0;
145  isDropped = true;
146  stopProcessing = true;
148  break;
149 
150  case 3:
151  NS_LOG_LOGIC ("Unknown Option. Drop!");
152 
153  if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
154  {
155  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
156  }
157  optionLength = 0;
158  isDropped = true;
159  stopProcessing = true;
161  break;
162 
163  default:
164  break;
165  }
166 
167  }
168  else
169  {
170  optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
171  }
172 
173  processedSize += optionLength;
174  p->RemoveAtStart (optionLength);
175  }
176 
177  delete [] data;
178 
179  return processedSize;
180 }
181 
182 int64_t
184 {
185  NS_LOG_FUNCTION (this << stream);
186  m_uvar->SetStream (stream);
187  return 1;
188 }
189 
191 
193 {
194  static TypeId tid = TypeId ("ns3::Ipv6ExtensionHopByHop")
196  .SetGroupName ("Internet")
197  .AddConstructor<Ipv6ExtensionHopByHop> ()
198  ;
199  return tid;
200 }
201 
203 {
205 }
206 
208 {
210 }
211 
213 {
215 
216  return EXT_NUMBER;
217 }
218 
220  uint8_t offset,
221  Ipv6Header const& ipv6Header,
222  Ipv6Address dst,
223  uint8_t *nextHeader,
224  bool& stopProcessing,
225  bool& isDropped,
226  Ipv6L3Protocol::DropReason& dropReason)
227 {
228  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
229 
230  Ptr<Packet> p = packet->Copy ();
231  p->RemoveAtStart (offset);
232 
233  Ipv6ExtensionHopByHopHeader hopbyhopHeader;
234  p->RemoveHeader (hopbyhopHeader);
235  if (nextHeader)
236  {
237  *nextHeader = hopbyhopHeader.GetNextHeader ();
238  }
239 
240  uint8_t processedSize = hopbyhopHeader.GetOptionsOffset ();
241  offset += processedSize;
242  uint8_t length = hopbyhopHeader.GetLength () - hopbyhopHeader.GetOptionsOffset ();
243 
244  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, stopProcessing, isDropped, dropReason);
245 
246  return processedSize;
247 }
248 
249 
251 
253 {
254  static TypeId tid = TypeId ("ns3::Ipv6ExtensionDestination")
256  .SetGroupName ("Internet")
257  .AddConstructor<Ipv6ExtensionDestination> ()
258  ;
259  return tid;
260 }
261 
263 {
265 }
266 
268 {
270 }
271 
273 {
275 
276  return EXT_NUMBER;
277 }
278 
280  uint8_t offset,
281  Ipv6Header const& ipv6Header,
282  Ipv6Address dst,
283  uint8_t *nextHeader,
284  bool& stopProcessing,
285  bool& isDropped,
286  Ipv6L3Protocol::DropReason& dropReason)
287 {
288  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
289 
290  Ptr<Packet> p = packet->Copy ();
291  p->RemoveAtStart (offset);
292 
293  Ipv6ExtensionDestinationHeader destinationHeader;
294  p->RemoveHeader (destinationHeader);
295  if (nextHeader)
296  {
297  *nextHeader = destinationHeader.GetNextHeader ();
298  }
299 
300  uint8_t processedSize = destinationHeader.GetOptionsOffset ();
301  offset += processedSize;
302  uint8_t length = destinationHeader.GetLength () - destinationHeader.GetOptionsOffset ();
303 
304  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, stopProcessing, isDropped, dropReason);
305 
306  return processedSize;
307 }
308 
309 
311 
313 {
314  static TypeId tid = TypeId ("ns3::Ipv6ExtensionFragment")
316  .SetGroupName ("Internet")
317  .AddConstructor<Ipv6ExtensionFragment> ()
318  ;
319  return tid;
320 }
321 
323 {
325 }
326 
328 {
330 }
331 
333 {
335 
336  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
337  {
338  it->second = 0;
339  }
340 
341  m_fragments.clear ();
343 }
344 
346 {
348 
349  return EXT_NUMBER;
350 }
351 
353  uint8_t offset,
354  Ipv6Header const& ipv6Header,
355  Ipv6Address dst,
356  uint8_t *nextHeader,
357  bool& stopProcessing,
358  bool& isDropped,
359  Ipv6L3Protocol::DropReason& dropReason)
360 {
361  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
362 
363  Ptr<Packet> p = packet->Copy ();
364  p->RemoveAtStart (offset);
365 
366  Ipv6ExtensionFragmentHeader fragmentHeader;
367  p->RemoveHeader (fragmentHeader);
368 
369  if (nextHeader)
370  {
371  *nextHeader = fragmentHeader.GetNextHeader ();
372  }
373 
374  bool moreFragment = fragmentHeader.GetMoreFragment ();
375  uint16_t fragmentOffset = fragmentHeader.GetOffset ();
376  uint32_t identification = fragmentHeader.GetIdentification ();
377  Ipv6Address src = ipv6Header.GetSourceAddress ();
378 
379  std::pair<Ipv6Address, uint32_t> fragmentsId = std::pair<Ipv6Address, uint32_t> (src, identification);
380  Ptr<Fragments> fragments;
381 
382  Ipv6Header ipHeader = ipv6Header;
383  ipHeader.SetNextHeader (fragmentHeader.GetNextHeader ());
384 
385  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
386  if (it == m_fragments.end ())
387  {
388  fragments = Create<Fragments> ();
389  m_fragments.insert (std::make_pair (fragmentsId, fragments));
392  fragmentsId, ipHeader);
393  fragments->SetTimeoutEventId (timeout);
394  }
395  else
396  {
397  fragments = it->second;
398  }
399 
400  if (fragmentOffset == 0)
401  {
402  Ptr<Packet> unfragmentablePart = packet->Copy ();
403  unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset);
404  fragments->SetUnfragmentablePart (unfragmentablePart);
405  }
406 
407  fragments->AddFragment (p, fragmentOffset, moreFragment);
408 
409  if (fragments->IsEntire ())
410  {
411  packet = fragments->GetPacket ();
412  fragments->CancelTimeout ();
413  m_fragments.erase (fragmentsId);
414  stopProcessing = false;
415  }
416  else
417  {
418  stopProcessing = true;
419  }
420 
421  return 0;
422 }
423 
424 void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragmentSize, std::list<Ptr<Packet> >& listFragments)
425 {
426  Ptr<Packet> p = packet->Copy ();
427 
428  Ipv6Header ipv6Header;
429  p->RemoveHeader (ipv6Header);
430 
431  uint8_t nextHeader = ipv6Header.GetNextHeader ();
432  uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize ();
433 
434  uint8_t type;
435  p->CopyData (&type, sizeof(type));
436 
437  bool moreHeader = true;
438  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
439  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
440  {
441  moreHeader = false;
443  }
444 
445  std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart;
446  uint32_t unfragmentablePartSize = 0;
447 
449  Ptr<Ipv6Extension> extension = extensionDemux->GetExtension (nextHeader);
450  uint8_t extensionHeaderLength;
451 
452  while (moreHeader)
453  {
454  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
455  {
457  p->RemoveHeader (*hopbyhopHeader);
458 
459  nextHeader = hopbyhopHeader->GetNextHeader ();
460  extensionHeaderLength = hopbyhopHeader->GetLength ();
461 
462  uint8_t type;
463  p->CopyData (&type, sizeof(type));
464 
465  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
466  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
467  {
468  moreHeader = false;
470  }
471 
472  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
473  unfragmentablePartSize += extensionHeaderLength;
474  }
475  else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
476  {
477  uint8_t buf[2];
478  p->CopyData (buf, sizeof(buf));
479  uint8_t numberAddress = buf[1] / 2;
481  routingHeader->SetNumberAddress (numberAddress);
482  p->RemoveHeader (*routingHeader);
483 
484  nextHeader = routingHeader->GetNextHeader ();
485  extensionHeaderLength = routingHeader->GetLength ();
486 
487  uint8_t type;
488  p->CopyData (&type, sizeof(type));
489  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
490  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
491  {
492  moreHeader = false;
494  }
495 
496  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
497  unfragmentablePartSize += extensionHeaderLength;
498  }
499  else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
500  {
502  p->RemoveHeader (*destinationHeader);
503 
504  nextHeader = destinationHeader->GetNextHeader ();
505  extensionHeaderLength = destinationHeader->GetLength ();
506 
507  uint8_t type;
508  p->CopyData (&type, sizeof(type));
509  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
510  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
511  {
512  moreHeader = false;
514  }
515 
516  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
517  unfragmentablePartSize += extensionHeaderLength;
518  }
519  }
520 
521  Ipv6ExtensionFragmentHeader fragmentHeader;
522  uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize ();
523 
524  uint32_t maxFragmentablePartSize = maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
525  uint32_t currentFragmentablePartSize = 0;
526 
527  bool moreFragment = true;
528  uint32_t identification = (uint32_t) m_uvar->GetValue (0, (uint32_t)-1);
529  uint16_t offset = 0;
530 
531  do
532  {
533  if (p->GetSize () > offset + maxFragmentablePartSize)
534  {
535  moreFragment = true;
536  currentFragmentablePartSize = maxFragmentablePartSize;
537  currentFragmentablePartSize -= currentFragmentablePartSize % 8;
538  }
539  else
540  {
541  moreFragment = false;
542  currentFragmentablePartSize = p->GetSize () - offset;
543  }
544 
545 
546  fragmentHeader.SetNextHeader (nextHeader);
547  fragmentHeader.SetOffset (offset);
548  fragmentHeader.SetMoreFragment (moreFragment);
549  fragmentHeader.SetIdentification (identification);
550 
551  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
552  offset += currentFragmentablePartSize;
553 
554  fragment->AddHeader (fragmentHeader);
555 
556  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
557  {
558  if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
559  {
561  dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first);
562  NS_ASSERT (p != 0);
563  fragment->AddHeader (*p);
564  }
565  else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
566  {
568  dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first);
569  NS_ASSERT (p != 0);
570  fragment->AddHeader (*p);
571  }
572  else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
573  {
575  dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first);
576  NS_ASSERT (p != 0);
577  fragment->AddHeader (*p);
578  }
579  }
580 
581  ipv6Header.SetPayloadLength (fragment->GetSize ());
582  fragment->AddHeader (ipv6Header);
583 
584  std::ostringstream oss;
585  fragment->Print (oss);
586  listFragments.push_back (fragment);
587  }
588  while (moreFragment);
589 
590  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
591  {
592  delete it->first;
593  }
594 
595  unfragmentablePart.clear ();
596 }
597 
598 
599 void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId,
600  Ipv6Header ipHeader)
601 {
602  Ptr<Fragments> fragments;
603 
604  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
605  NS_ASSERT_MSG(it != m_fragments.end (), "IPv6 Fragment timeout reached for non-existent fragment");
606  fragments = it->second;
607 
608  Ptr<Packet> packet = fragments->GetPartialPacket ();
609 
610  // if we have at least 8 bytes, we can send an ICMP.
611  if ( packet->GetSize () > 8 )
612  {
613  Ptr<Packet> p = packet->Copy ();
614  p->AddHeader (ipHeader);
616  icmp->SendErrorTimeExceeded (p, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
617  }
618 
620  ipL3->ReportDrop (ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
621 
622  // clear the buffers
623  m_fragments.erase (fragmentsId);
624 }
625 
627  : m_moreFragment (0)
628 {
629 }
630 
632 {
633 }
634 
635 void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
636 {
637  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
638 
639  for (it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
640  {
641  if (it->second > fragmentOffset)
642  {
643  break;
644  }
645  }
646 
647  if (it == m_packetFragments.end ())
648  {
649  m_moreFragment = moreFragment;
650  }
651 
652  m_packetFragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
653 }
654 
656 {
657  m_unfragmentable = unfragmentablePart;
658 }
659 
661 {
662  bool ret = !m_moreFragment && m_packetFragments.size () > 0;
663 
664  if (ret)
665  {
666  uint16_t lastEndOffset = 0;
667 
668  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
669  {
670  if (lastEndOffset != it->second)
671  {
672  ret = false;
673  break;
674  }
675 
676  lastEndOffset += it->first->GetSize ();
677  }
678  }
679 
680  return ret;
681 }
682 
684 {
685  Ptr<Packet> p = m_unfragmentable->Copy ();
686 
687  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
688  {
689  p->AddAtEnd (it->first);
690  }
691 
692  return p;
693 }
694 
696 {
697  Ptr<Packet> p;
698 
699  if ( m_unfragmentable )
700  {
701  p = m_unfragmentable->Copy ();
702  }
703  else
704  {
705  return p;
706  }
707 
708  uint16_t lastEndOffset = 0;
709 
710  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
711  {
712  if (lastEndOffset != it->second)
713  {
714  break;
715  }
716  p->AddAtEnd (it->first);
717  lastEndOffset += it->first->GetSize ();
718  }
719 
720  return p;
721 }
722 
724 {
725  m_timeoutEventId = event;
726  return;
727 }
728 
730 {
731  m_timeoutEventId.Cancel ();
732  return;
733 }
734 
735 
737 
739 {
740  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRouting")
742  .SetGroupName ("Internet")
743  .AddConstructor<Ipv6ExtensionRouting> ()
744  ;
745  return tid;
746 }
747 
749 {
751 }
752 
754 {
756 }
757 
759 {
761 
762  return EXT_NUMBER;
763 }
764 
766 {
768  return 0;
769 }
770 
772  uint8_t offset,
773  Ipv6Header const& ipv6Header,
774  Ipv6Address dst,
775  uint8_t *nextHeader,
776  bool& stopProcessing,
777  bool& isDropped,
778  Ipv6L3Protocol::DropReason& dropReason)
779 {
780  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
781 
782  // For ICMPv6 Error Packets
783  Ptr<Packet> malformedPacket = packet->Copy ();
784  malformedPacket->AddHeader (ipv6Header);
785 
786  Ptr<Packet> p = packet->Copy ();
787  p->RemoveAtStart (offset);
788 
789  uint8_t buf[4];
790  packet->CopyData (buf, sizeof(buf));
791 
792  uint8_t routingNextHeader = buf[0];
793  uint8_t routingLength = buf[1];
794  uint8_t routingTypeRouting = buf[2];
795  uint8_t routingSegmentsLeft = buf[3];
796 
797  if (nextHeader)
798  {
799  *nextHeader = routingNextHeader;
800  }
801 
802  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
803 
805  Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting);
806 
807  if (ipv6ExtensionRouting == 0)
808  {
809  if (routingSegmentsLeft == 0)
810  {
811  isDropped = false;
812  }
813  else
814  {
815  NS_LOG_LOGIC ("Malformed header. Drop!");
816 
817  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
819  isDropped = true;
820  stopProcessing = true;
821  }
822 
823  return routingLength;
824  }
825 
826  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, stopProcessing, isDropped, dropReason);
827 }
828 
829 
831 
833 {
834  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux")
835  .SetParent<Object> ()
836  .SetGroupName ("Internet")
837  .AddAttribute ("Routing Extensions", "The set of IPv6 Routing extensions registered with this demux.",
840  MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
841  ;
842  return tid;
843 }
844 
846 {
847 }
848 
850 {
851 }
852 
854 {
855  for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
856  {
857  (*it)->Dispose ();
858  *it = 0;
859  }
860  m_extensionsRouting.clear ();
861  m_node = 0;
863 }
864 
866 {
867  m_node = node;
868 }
869 
871 {
872  m_extensionsRouting.push_back (extensionRouting);
873 }
874 
876 {
877  for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
878  {
879  if ((*i)->GetTypeRouting () == typeRouting)
880  {
881  return *i;
882  }
883  }
884  return 0;
885 }
886 
888 {
889  m_extensionsRouting.remove (extensionRouting);
890 }
891 
892 
894 
896 {
897  static TypeId tid = TypeId ("ns3::Ipv6ExtensionLooseRouting")
899  .SetGroupName ("Internet")
900  .AddConstructor<Ipv6ExtensionLooseRouting> ()
901  ;
902  return tid;
903 }
904 
906 {
908 }
909 
911 {
913 }
914 
916 {
918 
919  return TYPE_ROUTING;
920 }
921 
923  uint8_t offset,
924  Ipv6Header const& ipv6Header,
925  Ipv6Address dst,
926  uint8_t *nextHeader,
927  bool& stopProcessing,
928  bool& isDropped,
929  Ipv6L3Protocol::DropReason& dropReason)
930 {
931  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
932 
933  // For ICMPv6 Error packets
934  Ptr<Packet> malformedPacket = packet->Copy ();
935  malformedPacket->AddHeader (ipv6Header);
936 
937  Ptr<Packet> p = packet->Copy ();
938  p->RemoveAtStart (offset);
939 
940  // Copy IPv6 Header : ipv6Header -> ipv6header
941  Buffer tmp;
942  tmp.AddAtStart (ipv6Header.GetSerializedSize ());
943  Buffer::Iterator it = tmp.Begin ();
944  Ipv6Header ipv6header;
945  ipv6Header.Serialize (it);
946  ipv6header.Deserialize (it);
947 
948  // Get the number of routers' address field
949  uint8_t buf[2];
950  p->CopyData (buf, sizeof(buf));
951  uint8_t numberAddress = buf[1] / 2;
952  Ipv6ExtensionLooseRoutingHeader routingHeader;
953  routingHeader.SetNumberAddress (numberAddress);
954  p->RemoveHeader (routingHeader);
955 
956  if (nextHeader)
957  {
958  *nextHeader = routingHeader.GetNextHeader ();
959  }
960 
961  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
962 
963  Ipv6Address srcAddress = ipv6header.GetSourceAddress ();
964  Ipv6Address destAddress = ipv6header.GetDestinationAddress ();
965  uint8_t hopLimit = ipv6header.GetHopLimit ();
966  uint8_t segmentsLeft = routingHeader.GetSegmentsLeft ();
967  uint8_t length = (routingHeader.GetLength () >> 3) - 1;
968  uint8_t nbAddress = length / 2;
969  uint8_t nextAddressIndex;
970  Ipv6Address nextAddress;
971 
972  if (segmentsLeft == 0)
973  {
974  isDropped = false;
975  return routingHeader.GetSerializedSize ();
976  }
977 
978  if (length % 2 != 0)
979  {
980  NS_LOG_LOGIC ("Malformed header. Drop!");
981  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
983  isDropped = true;
984  stopProcessing = true;
985  return routingHeader.GetSerializedSize ();
986  }
987 
988  if (segmentsLeft > nbAddress)
989  {
990  NS_LOG_LOGIC ("Malformed header. Drop!");
991  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
993  isDropped = true;
994  stopProcessing = true;
995  return routingHeader.GetSerializedSize ();
996  }
997 
998  routingHeader.SetSegmentsLeft (segmentsLeft - 1);
999  nextAddressIndex = nbAddress - segmentsLeft;
1000  nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
1001 
1002  if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
1003  {
1005  isDropped = true;
1006  stopProcessing = true;
1007  return routingHeader.GetSerializedSize ();
1008  }
1009 
1010  routingHeader.SetRouterAddress (nextAddressIndex, destAddress);
1011  ipv6header.SetDestinationAddress (nextAddress);
1012 
1013  if (hopLimit <= 1)
1014  {
1015  NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
1016  icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
1018  isDropped = true;
1019  stopProcessing = true;
1020  return routingHeader.GetSerializedSize ();
1021  }
1022 
1023  routingHeader.SetLength (88);
1024  ipv6header.SetHopLimit (hopLimit - 1);
1025  p->AddHeader (routingHeader);
1026 
1027  /* short-circuiting routing stuff
1028  *
1029  * If we process this option,
1030  * the packet was for us so we resend it to
1031  * the new destination (modified in the header above).
1032  */
1033 
1035  Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
1036  Socket::SocketErrno err;
1037  NS_ASSERT (ipv6rp);
1038 
1039  Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
1040 
1041  if (rtentry)
1042  {
1043  /* we know a route exists so send packet now */
1044  ipv6->SendRealOut (rtentry, p, ipv6header);
1045  }
1046  else
1047  {
1048  NS_LOG_INFO ("No route for next router");
1049  }
1050 
1051  /* as we directly send packet, mark it as dropped */
1052  isDropped = true;
1053 
1054  return routingHeader.GetSerializedSize ();
1055 }
1056 
1057 
1059 
1061 {
1062  static TypeId tid = TypeId ("ns3::Ipv6ExtensionESP")
1064  .SetGroupName ("Internet")
1065  .AddConstructor<Ipv6ExtensionESP> ()
1066  ;
1067  return tid;
1068 }
1069 
1071 {
1073 }
1074 
1076 {
1078 }
1079 
1081 {
1083 
1084  return EXT_NUMBER;
1085 }
1086 
1088  uint8_t offset,
1089  Ipv6Header const& ipv6Header,
1090  Ipv6Address dst,
1091  uint8_t *nextHeader,
1092  bool& stopProcessing,
1093  bool& isDropped,
1094  Ipv6L3Protocol::DropReason& dropReason)
1095 {
1096  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1097 
1100  return 0;
1101 }
1102 
1103 
1105 
1107 {
1108  static TypeId tid = TypeId ("ns3::Ipv6ExtensionAH")
1110  .SetGroupName ("Internet")
1111  .AddConstructor<Ipv6ExtensionAH> ()
1112  ;
1113  return tid;
1114 }
1115 
1117 {
1119 }
1120 
1122 {
1124 }
1125 
1127 {
1129 
1130  return EXT_NUMBER;
1131 }
1132 
1134  uint8_t offset,
1135  Ipv6Header const& ipv6Header,
1136  Ipv6Address dst,
1137  uint8_t *nextHeader,
1138  bool& stopProcessing,
1139  bool& isDropped,
1140  Ipv6L3Protocol::DropReason& dropReason)
1141 {
1142  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1143 
1146  return true;
1147 }
1148 
1149 } /* namespace ns3 */
1150 
void GetFragments(Ptr< Packet > packet, uint32_t fragmentSize, std::list< Ptr< Packet > > &listFragments)
Fragment a packet.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:266
Ptr< UniformRandomVariable > m_uvar
Provides uniform random variables.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:144
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:81
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:66
Introspection did not find any typical Config paths.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process method Called from Ipv6L3Protocol::Receive.
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
Ipv6ExtensionLooseRouting()
Constructor.
Introspection did not find any typical Config paths.
Definition: ipv6-header.h:33
virtual void DoDispose()
Dispose this object.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
Ptr< Packet > GetPartialPacket() const
Get the packet parts so far received.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:455
void Insert(Ptr< Ipv6ExtensionRouting > extensionRouting)
Insert a new IPv6 Routing Extension.
static const uint8_t EXT_NUMBER
Fragmentation extension number.
IPv6 layer implementation.
Introspection did not find any typical Config paths.
automatically resized byte buffer
Definition: buffer.h:92
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
void SetNode(Ptr< Node > node)
Set the node.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
virtual void DoDispose()
Dispose this object.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
virtual uint8_t GetExtensionNumber() const
Get the extension number.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:786
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:76
static TypeId GetTypeId()
Get the type identificator.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process method Called from Ipv6L3Protocol::Receive.
static TypeId GetTypeId()
Get the type identificator.
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:339
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
virtual ~Ipv6ExtensionRoutingDemux()
Destructor.
ns3::Time timeout
Ipv6ExtensionRoutingDemux()
Constructor.
void SetOffset(uint16_t offset)
Set the "Offset" field.
void Print(std::ostream &os) const
Print the packet contents.
Definition: packet.cc:410
Introspection did not find any typical Config paths.
Ipv6ExtensionFragment()
Constructor.
Introspection did not find any typical Config paths.
iterator in a Buffer instance
Definition: buffer.h:98
virtual uint8_t GetExtensionNumber() const
Get the extension number.
Introspection did not find any typical Config paths.
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionHopByHop()
Destructor.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process method Called from Ipv6L3Protocol::Receive.
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:228
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:311
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:338
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1216
void SetTimeoutEventId(EventId event)
Set the Timeout EventId.
Introspection did not find any typical Config paths.
Ipv6ExtensionHopByHop()
Constructor.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process method Called from Ipv6L3Protocol::Receive.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process method Called from Ipv6L3Protocol::Receive.
Hold an unsigned integer type.
Definition: uinteger.h:44
uint8_t data[writeSize]
Ptr< Packet > GetPacket() const
Get the entire packet.
Introspection did not find any typical Config paths.
~Ipv6ExtensionFragment()
Destructor.
void CancelTimeout()
Cancel the timeout event.
An implementation of the ICMPv6 protocol.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process method Called from Ipv6L3Protocol::Receive.
~Ipv6ExtensionRouting()
Destructor.
void SetMoreFragment(bool moreFragment)
Set the status of "More Fragment" bit.
void SetIdentification(uint32_t identification)
Set the "Identification" field.
static TypeId GetTypeId()
Get the type identificator.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process method Called from Ipv6L3Protocol::Receive.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
Buffer::Iterator Begin(void) const
Definition: buffer.h:1063
Ipv6ExtensionDestination()
Constructor.
Introspection did not find any typical Config paths.
#define list
void SetUnfragmentablePart(Ptr< Packet > unfragmentablePart)
Set the unfragmentable part of the packet.
bool IsEntire() const
If all fragments have been added.
Introspection did not find any typical Config paths.
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
Definition: ipv6-header.cc:165
Ptr< Node > GetNode() const
Get the node.
void Remove(Ptr< Ipv6ExtensionRouting > extensionRouting)
Remove a routing extension from this demux.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:91
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
void SetNode(Ptr< Node > node)
Set the node.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
void SetNextHeader(uint8_t nextHeader)
Set the "Next header" field.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TypeId GetTypeId()
Get the type identificator.
uint32_t GetOptionsOffset()
Get the offset where the options begin, measured from the start of the extension header.
MapFragments_t m_fragments
The hash of fragmented packets.
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:331
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
static TypeId GetTypeId()
The interface ID.
static TypeId GetTypeId()
Get the type identificator.
Ipv6Address GetRouterAddress(uint8_t index) const
Get a Router IPv6 Address.
Ptr< Ipv6ExtensionRouting > GetExtensionRouting(uint8_t typeRouting)
Get the routing extension corresponding to typeRouting.
~Ipv6ExtensionESP()
Destructor.
Ipv6ExtensionAH()
Constructor.
static TypeId GetTypeId()
Get the type identificator.
Introspection did not find any typical Config paths.
virtual uint8_t GetExtensionNumber() const =0
Get the extension number.
bool GetMoreFragment() const
Get the status of "More Fragment" bit.
static const uint8_t EXT_NUMBER
Hop-by-hop extension number.
uint8_t GetSegmentsLeft() const
Get the field "Segments left".
#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:90
Ipv6Extension()
Constructor.
Introspection did not find any typical Config paths.
uint8_t GetNextHeader() const
Get the next header.
Describes an IPv6 address.
Definition: ipv6-address.h:47
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
Definition: ipv6-header.cc:149
virtual uint8_t GetTypeRouting() const
Get the type of routing.
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:86
An identifier for simulation events.
Definition: event-id.h:53
Ipv6ExtensionRouting()
Constructor.
uint32_t GetIdentification() const
Get the field "Identification".
Introspection did not find any typical Config paths.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:895
virtual uint8_t GetExtensionNumber() const
Get the extension number.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
virtual uint8_t ProcessOptions(Ptr< Packet > &packet, uint8_t offset, uint8_t length, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process options Called by implementing classes to process the options.
virtual uint32_t GetSerializedSize() const
Get the serialized size of the packet.
virtual uint8_t GetTypeRouting() const
Get the type of routing.
Introspection did not find any typical Config paths.
void SetLength(uint16_t length)
brief Set the length of the extension.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:354
Ipv6ExtensionRoutingList_t m_extensionsRouting
List of IPv6 Routing Extensions supported.
Ipv6ExtensionESP()
Constructor.
void HandleFragmentsTimeout(std::pair< Ipv6Address, uint32_t > key, Ipv6Header ipHeader)
Process the timeout for packet fragments.
uint16_t GetOffset() const
Get the field "Offset".
A base class which provides memory management and object aggregation.
Definition: object.h:87
Introspection did not find any typical Config paths.
static const uint8_t EXT_NUMBER
Destination extension number.
Container for a set of ns3::Object pointers.
uint16_t GetLength() const
Get the length of the extension.
Ptr< Node > m_node
The node.
void SetRouterAddress(uint8_t index, Ipv6Address addr)
Set a Router IPv6 Address.
void SetNumberAddress(uint8_t n)
Set the number of routers' address.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
a unique identifier for an interface.
Definition: type-id.h:58
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:106
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:826
static TypeId GetTypeId()
Get the type identificator.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:255
~Ipv6ExtensionAH()
Destructor.
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
DropReason
Reason why a packet has been dropped.
virtual ~Ipv6Extension()
Destructor.
Introspection did not find any typical Config paths.
void SetSegmentsLeft(uint8_t segmentsLeft)
Set the "Segments left" field.