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, Ipv6Header ipv6Header, uint32_t maxFragmentSize, std::list<Ipv6PayloadHeaderPair>& listFragments)
425 {
426  Ptr<Packet> p = packet->Copy ();
427 
428  uint8_t nextHeader = ipv6Header.GetNextHeader ();
429  uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize ();
430 
431  uint8_t type;
432  p->CopyData (&type, sizeof(type));
433 
434  bool moreHeader = true;
435  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
436  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
437  {
438  moreHeader = false;
440  }
441 
442  std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart;
443  uint32_t unfragmentablePartSize = 0;
444 
446  Ptr<Ipv6Extension> extension = extensionDemux->GetExtension (nextHeader);
447  uint8_t extensionHeaderLength;
448 
449  while (moreHeader)
450  {
451  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
452  {
454  p->RemoveHeader (*hopbyhopHeader);
455 
456  nextHeader = hopbyhopHeader->GetNextHeader ();
457  extensionHeaderLength = hopbyhopHeader->GetLength ();
458 
459  uint8_t type;
460  p->CopyData (&type, sizeof(type));
461 
462  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
463  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
464  {
465  moreHeader = false;
467  }
468 
469  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
470  unfragmentablePartSize += extensionHeaderLength;
471  }
472  else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
473  {
474  uint8_t buf[2];
475  p->CopyData (buf, sizeof(buf));
476  uint8_t numberAddress = buf[1] / 2;
478  routingHeader->SetNumberAddress (numberAddress);
479  p->RemoveHeader (*routingHeader);
480 
481  nextHeader = routingHeader->GetNextHeader ();
482  extensionHeaderLength = routingHeader->GetLength ();
483 
484  uint8_t type;
485  p->CopyData (&type, sizeof(type));
486  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
487  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
488  {
489  moreHeader = false;
491  }
492 
493  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
494  unfragmentablePartSize += extensionHeaderLength;
495  }
496  else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
497  {
499  p->RemoveHeader (*destinationHeader);
500 
501  nextHeader = destinationHeader->GetNextHeader ();
502  extensionHeaderLength = destinationHeader->GetLength ();
503 
504  uint8_t type;
505  p->CopyData (&type, sizeof(type));
506  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
507  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
508  {
509  moreHeader = false;
511  }
512 
513  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
514  unfragmentablePartSize += extensionHeaderLength;
515  }
516  }
517 
518  Ipv6ExtensionFragmentHeader fragmentHeader;
519  uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize ();
520 
521  uint32_t maxFragmentablePartSize = maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
522  uint32_t currentFragmentablePartSize = 0;
523 
524  bool moreFragment = true;
525  uint32_t identification = (uint32_t) m_uvar->GetValue (0, (uint32_t)-1);
526  uint16_t offset = 0;
527 
528  do
529  {
530  if (p->GetSize () > offset + maxFragmentablePartSize)
531  {
532  moreFragment = true;
533  currentFragmentablePartSize = maxFragmentablePartSize;
534  currentFragmentablePartSize -= currentFragmentablePartSize % 8;
535  }
536  else
537  {
538  moreFragment = false;
539  currentFragmentablePartSize = p->GetSize () - offset;
540  }
541 
542 
543  fragmentHeader.SetNextHeader (nextHeader);
544  fragmentHeader.SetOffset (offset);
545  fragmentHeader.SetMoreFragment (moreFragment);
546  fragmentHeader.SetIdentification (identification);
547 
548  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
549  offset += currentFragmentablePartSize;
550 
551  fragment->AddHeader (fragmentHeader);
552 
553  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
554  {
555  if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
556  {
558  dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first);
559  NS_ASSERT (p != 0);
560  fragment->AddHeader (*p);
561  }
562  else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
563  {
565  dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first);
566  NS_ASSERT (p != 0);
567  fragment->AddHeader (*p);
568  }
569  else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
570  {
572  dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first);
573  NS_ASSERT (p != 0);
574  fragment->AddHeader (*p);
575  }
576  }
577 
578  ipv6Header.SetPayloadLength (fragment->GetSize ());
579 
580  std::ostringstream oss;
581  oss << ipv6Header;
582  fragment->Print (oss);
583 
584  listFragments.push_back (Ipv6PayloadHeaderPair (fragment, ipv6Header));
585  }
586  while (moreFragment);
587 
588  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
589  {
590  delete it->first;
591  }
592 
593  unfragmentablePart.clear ();
594 }
595 
596 
597 void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId,
598  Ipv6Header ipHeader)
599 {
600  Ptr<Fragments> fragments;
601 
602  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
603  NS_ASSERT_MSG(it != m_fragments.end (), "IPv6 Fragment timeout reached for non-existent fragment");
604  fragments = it->second;
605 
606  Ptr<Packet> packet = fragments->GetPartialPacket ();
607 
608  // if we have at least 8 bytes, we can send an ICMP.
609  if ( packet->GetSize () > 8 )
610  {
611  Ptr<Packet> p = packet->Copy ();
612  p->AddHeader (ipHeader);
614  icmp->SendErrorTimeExceeded (p, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
615  }
616 
618  ipL3->ReportDrop (ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
619 
620  // clear the buffers
621  m_fragments.erase (fragmentsId);
622 }
623 
625  : m_moreFragment (0)
626 {
627 }
628 
630 {
631 }
632 
633 void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
634 {
635  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
636 
637  for (it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
638  {
639  if (it->second > fragmentOffset)
640  {
641  break;
642  }
643  }
644 
645  if (it == m_packetFragments.end ())
646  {
647  m_moreFragment = moreFragment;
648  }
649 
650  m_packetFragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
651 }
652 
654 {
655  m_unfragmentable = unfragmentablePart;
656 }
657 
659 {
660  bool ret = !m_moreFragment && m_packetFragments.size () > 0;
661 
662  if (ret)
663  {
664  uint16_t lastEndOffset = 0;
665 
666  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
667  {
668  if (lastEndOffset != it->second)
669  {
670  ret = false;
671  break;
672  }
673 
674  lastEndOffset += it->first->GetSize ();
675  }
676  }
677 
678  return ret;
679 }
680 
682 {
683  Ptr<Packet> p = m_unfragmentable->Copy ();
684 
685  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
686  {
687  p->AddAtEnd (it->first);
688  }
689 
690  return p;
691 }
692 
694 {
695  Ptr<Packet> p;
696 
697  if ( m_unfragmentable )
698  {
699  p = m_unfragmentable->Copy ();
700  }
701  else
702  {
703  return p;
704  }
705 
706  uint16_t lastEndOffset = 0;
707 
708  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
709  {
710  if (lastEndOffset != it->second)
711  {
712  break;
713  }
714  p->AddAtEnd (it->first);
715  lastEndOffset += it->first->GetSize ();
716  }
717 
718  return p;
719 }
720 
722 {
723  m_timeoutEventId = event;
724  return;
725 }
726 
728 {
729  m_timeoutEventId.Cancel ();
730  return;
731 }
732 
733 
735 
737 {
738  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRouting")
740  .SetGroupName ("Internet")
741  .AddConstructor<Ipv6ExtensionRouting> ()
742  ;
743  return tid;
744 }
745 
747 {
749 }
750 
752 {
754 }
755 
757 {
759 
760  return EXT_NUMBER;
761 }
762 
764 {
766  return 0;
767 }
768 
770  uint8_t offset,
771  Ipv6Header const& ipv6Header,
772  Ipv6Address dst,
773  uint8_t *nextHeader,
774  bool& stopProcessing,
775  bool& isDropped,
776  Ipv6L3Protocol::DropReason& dropReason)
777 {
778  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
779 
780  // For ICMPv6 Error Packets
781  Ptr<Packet> malformedPacket = packet->Copy ();
782  malformedPacket->AddHeader (ipv6Header);
783 
784  Ptr<Packet> p = packet->Copy ();
785  p->RemoveAtStart (offset);
786 
787  uint8_t buf[4];
788  packet->CopyData (buf, sizeof(buf));
789 
790  uint8_t routingNextHeader = buf[0];
791  uint8_t routingLength = buf[1];
792  uint8_t routingTypeRouting = buf[2];
793  uint8_t routingSegmentsLeft = buf[3];
794 
795  if (nextHeader)
796  {
797  *nextHeader = routingNextHeader;
798  }
799 
800  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
801 
803  Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting);
804 
805  if (ipv6ExtensionRouting == 0)
806  {
807  if (routingSegmentsLeft == 0)
808  {
809  isDropped = false;
810  }
811  else
812  {
813  NS_LOG_LOGIC ("Malformed header. Drop!");
814 
815  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
817  isDropped = true;
818  stopProcessing = true;
819  }
820 
821  return routingLength;
822  }
823 
824  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, stopProcessing, isDropped, dropReason);
825 }
826 
827 
829 
831 {
832  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux")
833  .SetParent<Object> ()
834  .SetGroupName ("Internet")
835  .AddAttribute ("RoutingExtensions", "The set of IPv6 Routing extensions registered with this demux.",
838  MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
839  ;
840  return tid;
841 }
842 
844 {
845 }
846 
848 {
849 }
850 
852 {
853  for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
854  {
855  (*it)->Dispose ();
856  *it = 0;
857  }
858  m_extensionsRouting.clear ();
859  m_node = 0;
861 }
862 
864 {
865  m_node = node;
866 }
867 
869 {
870  m_extensionsRouting.push_back (extensionRouting);
871 }
872 
874 {
875  for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
876  {
877  if ((*i)->GetTypeRouting () == typeRouting)
878  {
879  return *i;
880  }
881  }
882  return 0;
883 }
884 
886 {
887  m_extensionsRouting.remove (extensionRouting);
888 }
889 
890 
892 
894 {
895  static TypeId tid = TypeId ("ns3::Ipv6ExtensionLooseRouting")
897  .SetGroupName ("Internet")
898  .AddConstructor<Ipv6ExtensionLooseRouting> ()
899  ;
900  return tid;
901 }
902 
904 {
906 }
907 
909 {
911 }
912 
914 {
916 
917  return TYPE_ROUTING;
918 }
919 
921  uint8_t offset,
922  Ipv6Header const& ipv6Header,
923  Ipv6Address dst,
924  uint8_t *nextHeader,
925  bool& stopProcessing,
926  bool& isDropped,
927  Ipv6L3Protocol::DropReason& dropReason)
928 {
929  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
930 
931  // For ICMPv6 Error packets
932  Ptr<Packet> malformedPacket = packet->Copy ();
933  malformedPacket->AddHeader (ipv6Header);
934 
935  Ptr<Packet> p = packet->Copy ();
936  p->RemoveAtStart (offset);
937 
938  // Copy IPv6 Header : ipv6Header -> ipv6header
939  Buffer tmp;
940  tmp.AddAtStart (ipv6Header.GetSerializedSize ());
941  Buffer::Iterator it = tmp.Begin ();
942  Ipv6Header ipv6header;
943  ipv6Header.Serialize (it);
944  ipv6header.Deserialize (it);
945 
946  // Get the number of routers' address field
947  uint8_t buf[2];
948  p->CopyData (buf, sizeof(buf));
949  uint8_t numberAddress = buf[1] / 2;
950  Ipv6ExtensionLooseRoutingHeader routingHeader;
951  routingHeader.SetNumberAddress (numberAddress);
952  p->RemoveHeader (routingHeader);
953 
954  if (nextHeader)
955  {
956  *nextHeader = routingHeader.GetNextHeader ();
957  }
958 
959  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
960 
961  Ipv6Address srcAddress = ipv6header.GetSourceAddress ();
962  Ipv6Address destAddress = ipv6header.GetDestinationAddress ();
963  uint8_t hopLimit = ipv6header.GetHopLimit ();
964  uint8_t segmentsLeft = routingHeader.GetSegmentsLeft ();
965  uint8_t length = (routingHeader.GetLength () >> 3) - 1;
966  uint8_t nbAddress = length / 2;
967  uint8_t nextAddressIndex;
968  Ipv6Address nextAddress;
969 
970  if (segmentsLeft == 0)
971  {
972  isDropped = false;
973  return routingHeader.GetSerializedSize ();
974  }
975 
976  if (length % 2 != 0)
977  {
978  NS_LOG_LOGIC ("Malformed header. Drop!");
979  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
981  isDropped = true;
982  stopProcessing = true;
983  return routingHeader.GetSerializedSize ();
984  }
985 
986  if (segmentsLeft > nbAddress)
987  {
988  NS_LOG_LOGIC ("Malformed header. Drop!");
989  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
991  isDropped = true;
992  stopProcessing = true;
993  return routingHeader.GetSerializedSize ();
994  }
995 
996  routingHeader.SetSegmentsLeft (segmentsLeft - 1);
997  nextAddressIndex = nbAddress - segmentsLeft;
998  nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
999 
1000  if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
1001  {
1003  isDropped = true;
1004  stopProcessing = true;
1005  return routingHeader.GetSerializedSize ();
1006  }
1007 
1008  routingHeader.SetRouterAddress (nextAddressIndex, destAddress);
1009  ipv6header.SetDestinationAddress (nextAddress);
1010 
1011  if (hopLimit <= 1)
1012  {
1013  NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
1014  icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
1016  isDropped = true;
1017  stopProcessing = true;
1018  return routingHeader.GetSerializedSize ();
1019  }
1020 
1021  ipv6header.SetHopLimit (hopLimit - 1);
1022  p->AddHeader (routingHeader);
1023 
1024  /* short-circuiting routing stuff
1025  *
1026  * If we process this option,
1027  * the packet was for us so we resend it to
1028  * the new destination (modified in the header above).
1029  */
1030 
1032  Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
1033  Socket::SocketErrno err;
1034  NS_ASSERT (ipv6rp);
1035 
1036  Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
1037 
1038  if (rtentry)
1039  {
1040  /* we know a route exists so send packet now */
1041  ipv6->SendRealOut (rtentry, p, ipv6header);
1042  }
1043  else
1044  {
1045  NS_LOG_INFO ("No route for next router");
1046  }
1047 
1048  /* as we directly send packet, mark it as dropped */
1049  isDropped = true;
1050 
1051  return routingHeader.GetSerializedSize ();
1052 }
1053 
1054 
1056 
1058 {
1059  static TypeId tid = TypeId ("ns3::Ipv6ExtensionESP")
1061  .SetGroupName ("Internet")
1062  .AddConstructor<Ipv6ExtensionESP> ()
1063  ;
1064  return tid;
1065 }
1066 
1068 {
1070 }
1071 
1073 {
1075 }
1076 
1078 {
1080 
1081  return EXT_NUMBER;
1082 }
1083 
1085  uint8_t offset,
1086  Ipv6Header const& ipv6Header,
1087  Ipv6Address dst,
1088  uint8_t *nextHeader,
1089  bool& stopProcessing,
1090  bool& isDropped,
1091  Ipv6L3Protocol::DropReason& dropReason)
1092 {
1093  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1094 
1097  return 0;
1098 }
1099 
1100 
1102 
1104 {
1105  static TypeId tid = TypeId ("ns3::Ipv6ExtensionAH")
1107  .SetGroupName ("Internet")
1108  .AddConstructor<Ipv6ExtensionAH> ()
1109  ;
1110  return tid;
1111 }
1112 
1114 {
1116 }
1117 
1119 {
1121 }
1122 
1124 {
1126 
1127  return EXT_NUMBER;
1128 }
1129 
1131  uint8_t offset,
1132  Ipv6Header const& ipv6Header,
1133  Ipv6Address dst,
1134  uint8_t *nextHeader,
1135  bool& stopProcessing,
1136  bool& isDropped,
1137  Ipv6L3Protocol::DropReason& dropReason)
1138 {
1139  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1140 
1143  return true;
1144 }
1145 
1146 } /* namespace ns3 */
1147 
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
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:143
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:65
IPv6 Extension base If you want to implement a new IPv6 extension, all you have to do is implement a ...
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.
Packet header for IPv6.
Definition: ipv6-header.h:34
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:462
void Insert(Ptr< Ipv6ExtensionRouting > extensionRouting)
Insert a new IPv6 Routing Extension.
static const uint8_t EXT_NUMBER
Fragmentation extension number.
IPv6 layer implementation.
Demultiplexes IPv6 extensions.
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:792
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:75
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.
void GetFragments(Ptr< Packet > packet, Ipv6Header ipv6Header, uint32_t fragmentSize, std::list< Ipv6PayloadHeaderPair > &listFragments)
Fragment a packet.
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
#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:412
IPv6 Extension Destination.
Ipv6ExtensionFragment()
Constructor.
Header of IPv6 Extension "Hop by Hop".
iterator in a Buffer instance
Definition: buffer.h:98
virtual uint8_t GetExtensionNumber() const
Get the extension number.
IPv6 Extension Routing.
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.
DropReason
Reason why a packet has been dropped.
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:313
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:340
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1238
void SetTimeoutEventId(EventId event)
Set the Timeout EventId.
Header of IPv6 Extension Routing : Type 0 (Loose Routing)
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.
IPv6 Extension ESP (Encapsulating Security Payload)
~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:1068
Ipv6ExtensionDestination()
Constructor.
IPv6 Extension Routing Demux.
#define list
void SetUnfragmentablePart(Ptr< Packet > unfragmentablePart)
Set the unfragmentable part of the packet.
bool IsEntire() const
If all fragments have been added.
IPv6 Extension "Hop By Hop".
virtual uint32_t Deserialize(Buffer::Iterator start)
Deserialize the packet.
Definition: ipv6-header.cc:164
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:90
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:333
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.
std::pair< Ptr< Packet >, Ipv6Header > Ipv6PayloadHeaderPair
Pair of a packet and an Ipv6 header.
static TypeId GetTypeId()
Get the type identificator.
IPv6 Extension Loose Routing.
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.
IPv6 Extension Fragment.
uint8_t GetNextHeader() const
Get the next header.
Describes an IPv6 address.
Definition: ipv6-address.h:48
virtual void Serialize(Buffer::Iterator start) const
Serialize the packet.
Definition: ipv6-header.cc:148
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:85
An identifier for simulation events.
Definition: event-id.h:53
Ipv6ExtensionRouting()
Constructor.
uint32_t GetIdentification() const
Get the field "Identification".
Header of IPv6 Extension Destination.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
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.
Header of IPv6 Extension Fragment.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:356
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
IPv6 Option Demux.
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:105
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
static TypeId GetTypeId()
Get the type identificator.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:257
~Ipv6ExtensionAH()
Destructor.
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
virtual ~Ipv6Extension()
Destructor.
IPv6 Extension AH (Authentication Header)
void SetSegmentsLeft(uint8_t segmentsLeft)
Set the "Segments left" field.