A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 NS_LOG_COMPONENT_DEFINE ("Ipv6Extension");
44 
45 namespace ns3 {
46 
47 NS_OBJECT_ENSURE_REGISTERED (Ipv6Extension);
48 
50 {
51  static TypeId tid = TypeId ("ns3::Ipv6Extension")
52  .SetParent<Object> ()
53  .AddAttribute ("ExtensionNumber", "The IPv6 extension number.",
54  UintegerValue (0),
55  MakeUintegerAccessor (&Ipv6Extension::GetExtensionNumber),
56  MakeUintegerChecker<uint8_t> ())
57  ;
58  return tid;
59 }
60 
62 {
64 
65  m_uvar = CreateObject<UniformRandomVariable> ();
66 }
67 
69 {
71 }
72 
74 {
75  NS_LOG_FUNCTION (this << node);
76 
77  m_node = node;
78 }
79 
81 {
83 
84  return m_node;
85 }
86 
88  uint8_t offset,
89  uint8_t length,
90  Ipv6Header const& ipv6Header,
91  Ipv6Address dst,
92  uint8_t *nextHeader,
93  bool& stopProcessing,
94  bool& isDropped,
95  Ipv6L3Protocol::DropReason& dropReason)
96 {
97  NS_LOG_FUNCTION (this << packet << offset << length << ipv6Header << dst << nextHeader << 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  uint8_t *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 == 0)
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, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
143  optionLength = 0;
144  isDropped = true;
145  stopProcessing = true;
147  break;
148 
149  case 3:
150  NS_LOG_LOGIC ("Unknown Option. Drop!");
151 
152  if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
153  {
154  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
155  }
156  optionLength = 0;
157  isDropped = true;
158  stopProcessing = true;
160  break;
161 
162  default:
163  break;
164  }
165 
166  }
167  else
168  {
169  optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
170  }
171 
172  processedSize += optionLength;
173  p->RemoveAtStart (optionLength);
174  }
175 
176  delete [] data;
177 
178  return processedSize;
179 }
180 
181 int64_t
183 {
184  NS_LOG_FUNCTION (this << stream);
185  m_uvar->SetStream (stream);
186  return 1;
187 }
188 
190 
192 {
193  static TypeId tid = TypeId ("ns3::Ipv6ExtensionHopByHop")
195  .AddConstructor<Ipv6ExtensionHopByHop> ()
196  ;
197  return tid;
198 }
199 
201 {
203 }
204 
206 {
208 }
209 
211 {
213 
214  return EXT_NUMBER;
215 }
216 
218  uint8_t offset,
219  Ipv6Header const& ipv6Header,
220  Ipv6Address dst,
221  uint8_t *nextHeader,
222  bool& stopProcessing,
223  bool& isDropped,
224  Ipv6L3Protocol::DropReason& dropReason)
225 {
226  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
227 
228  Ptr<Packet> p = packet->Copy ();
229  p->RemoveAtStart (offset);
230 
231  Ipv6ExtensionHopByHopHeader hopbyhopHeader;
232  p->RemoveHeader (hopbyhopHeader);
233  if (nextHeader)
234  {
235  *nextHeader = hopbyhopHeader.GetNextHeader ();
236  }
237 
238  uint8_t processedSize = hopbyhopHeader.GetOptionsOffset ();
239  offset += processedSize;
240  uint8_t length = hopbyhopHeader.GetLength () - hopbyhopHeader.GetOptionsOffset ();
241 
242  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, stopProcessing, isDropped, dropReason);
243 
244  return processedSize;
245 }
246 
247 
249 
251 {
252  static TypeId tid = TypeId ("ns3::Ipv6ExtensionDestination")
254  .AddConstructor<Ipv6ExtensionDestination> ()
255  ;
256  return tid;
257 }
258 
260 {
262 }
263 
265 {
267 }
268 
270 {
272 
273  return EXT_NUMBER;
274 }
275 
277  uint8_t offset,
278  Ipv6Header const& ipv6Header,
279  Ipv6Address dst,
280  uint8_t *nextHeader,
281  bool& stopProcessing,
282  bool& isDropped,
283  Ipv6L3Protocol::DropReason& dropReason)
284 {
285  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
286 
287  Ptr<Packet> p = packet->Copy ();
288  p->RemoveAtStart (offset);
289 
290  Ipv6ExtensionDestinationHeader destinationHeader;
291  p->RemoveHeader (destinationHeader);
292  if (nextHeader)
293  {
294  *nextHeader = destinationHeader.GetNextHeader ();
295  }
296 
297  uint8_t processedSize = destinationHeader.GetOptionsOffset ();
298  offset += processedSize;
299  uint8_t length = destinationHeader.GetLength () - destinationHeader.GetOptionsOffset ();
300 
301  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, stopProcessing, isDropped, dropReason);
302 
303  return processedSize;
304 }
305 
306 
308 
310 {
311  static TypeId tid = TypeId ("ns3::Ipv6ExtensionFragment")
313  .AddConstructor<Ipv6ExtensionFragment> ()
314  ;
315  return tid;
316 }
317 
319 {
321 }
322 
324 {
326 }
327 
329 {
331 
332  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
333  {
334  it->second = 0;
335  }
336 
337  m_fragments.clear ();
339 }
340 
342 {
344 
345  return EXT_NUMBER;
346 }
347 
349  uint8_t offset,
350  Ipv6Header const& ipv6Header,
351  Ipv6Address dst,
352  uint8_t *nextHeader,
353  bool& stopProcessing,
354  bool& isDropped,
355  Ipv6L3Protocol::DropReason& dropReason)
356 {
357  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
358 
359  Ptr<Packet> p = packet->Copy ();
360  p->RemoveAtStart (offset);
361 
362  Ipv6ExtensionFragmentHeader fragmentHeader;
363  p->RemoveHeader (fragmentHeader);
364 
365  if (nextHeader)
366  {
367  *nextHeader = fragmentHeader.GetNextHeader ();
368  }
369 
370  bool moreFragment = fragmentHeader.GetMoreFragment ();
371  uint16_t fragmentOffset = fragmentHeader.GetOffset ();
372  uint32_t identification = fragmentHeader.GetIdentification ();
373  Ipv6Address src = ipv6Header.GetSourceAddress ();
374 
375  std::pair<Ipv6Address, uint32_t> fragmentsId = std::pair<Ipv6Address, uint32_t> (src, identification);
376  Ptr<Fragments> fragments;
377 
378  Ipv6Header ipHeader = ipv6Header;
379  ipHeader.SetNextHeader (fragmentHeader.GetNextHeader ());
380 
381  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
382  if (it == m_fragments.end ())
383  {
384  fragments = Create<Fragments> ();
385  m_fragments.insert (std::make_pair (fragmentsId, fragments));
386  EventId timeout = Simulator::Schedule (Seconds (60),
388  fragmentsId, ipHeader);
389  fragments->SetTimeoutEventId (timeout);
390  }
391  else
392  {
393  fragments = it->second;
394  }
395 
396  if (fragmentOffset == 0)
397  {
398  Ptr<Packet> unfragmentablePart = packet->Copy ();
399  unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset);
400  fragments->SetUnfragmentablePart (unfragmentablePart);
401  }
402 
403  fragments->AddFragment (p, fragmentOffset, moreFragment);
404 
405  if (fragments->IsEntire ())
406  {
407  packet = fragments->GetPacket ();
408  fragments->CancelTimeout ();
409  m_fragments.erase (fragmentsId);
410  stopProcessing = false;
411  }
412  else
413  {
414  stopProcessing = true;
415  }
416 
417  return 0;
418 }
419 
420 void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragmentSize, std::list<Ptr<Packet> >& listFragments)
421 {
422  Ptr<Packet> p = packet->Copy ();
423 
424  Ipv6Header ipv6Header;
425  p->RemoveHeader (ipv6Header);
426 
427  uint8_t nextHeader = ipv6Header.GetNextHeader ();
428  uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize ();
429 
430  uint8_t type;
431  p->CopyData (&type, sizeof(type));
432 
433  bool moreHeader = true;
434  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
435  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
436  {
437  moreHeader = false;
439  }
440 
441  std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart;
442  uint32_t unfragmentablePartSize = 0;
443 
445  Ptr<Ipv6Extension> extension = extensionDemux->GetExtension (nextHeader);
446  uint8_t extensionHeaderLength;
447 
448  while (moreHeader)
449  {
450  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
451  {
453  p->RemoveHeader (*hopbyhopHeader);
454 
455  nextHeader = hopbyhopHeader->GetNextHeader ();
456  extensionHeaderLength = hopbyhopHeader->GetLength ();
457 
458  uint8_t type;
459  p->CopyData (&type, sizeof(type));
460 
461  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
462  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
463  {
464  moreHeader = false;
466  }
467 
468  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
469  unfragmentablePartSize += extensionHeaderLength;
470  }
471  else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
472  {
473  uint8_t buf[2];
474  p->CopyData (buf, sizeof(buf));
475  uint8_t numberAddress = buf[1] / 2;
477  routingHeader->SetNumberAddress (numberAddress);
478  p->RemoveHeader (*routingHeader);
479 
480  nextHeader = routingHeader->GetNextHeader ();
481  extensionHeaderLength = routingHeader->GetLength ();
482 
483  uint8_t type;
484  p->CopyData (&type, sizeof(type));
485  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
486  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
487  {
488  moreHeader = false;
490  }
491 
492  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
493  unfragmentablePartSize += extensionHeaderLength;
494  }
495  else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
496  {
498  p->RemoveHeader (*destinationHeader);
499 
500  nextHeader = destinationHeader->GetNextHeader ();
501  extensionHeaderLength = destinationHeader->GetLength ();
502 
503  uint8_t type;
504  p->CopyData (&type, sizeof(type));
505  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
506  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
507  {
508  moreHeader = false;
510  }
511 
512  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
513  unfragmentablePartSize += extensionHeaderLength;
514  }
515  }
516 
517  Ipv6ExtensionFragmentHeader fragmentHeader;
518  uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize ();
519 
520  uint32_t maxFragmentablePartSize = maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
521  uint32_t currentFragmentablePartSize = 0;
522 
523  bool moreFragment = true;
524  uint32_t identification = (uint32_t) m_uvar->GetValue (0, (uint32_t)-1);
525  uint16_t offset = 0;
526 
527  do
528  {
529  if (p->GetSize () > offset + maxFragmentablePartSize)
530  {
531  moreFragment = true;
532  currentFragmentablePartSize = maxFragmentablePartSize;
533  currentFragmentablePartSize -= currentFragmentablePartSize % 8;
534  }
535  else
536  {
537  moreFragment = false;
538  currentFragmentablePartSize = p->GetSize () - offset;
539  }
540 
541 
542  fragmentHeader.SetNextHeader (nextHeader);
543  fragmentHeader.SetOffset (offset);
544  fragmentHeader.SetMoreFragment (moreFragment);
545  fragmentHeader.SetIdentification (identification);
546 
547  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
548  offset += currentFragmentablePartSize;
549 
550  fragment->AddHeader (fragmentHeader);
551 
552  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
553  {
554  if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
555  {
557  dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first);
558  NS_ASSERT (p != 0);
559  fragment->AddHeader (*p);
560  }
561  else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
562  {
564  dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first);
565  NS_ASSERT (p != 0);
566  fragment->AddHeader (*p);
567  }
568  else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
569  {
571  dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first);
572  NS_ASSERT (p != 0);
573  fragment->AddHeader (*p);
574  }
575  }
576 
577  ipv6Header.SetPayloadLength (fragment->GetSize ());
578  fragment->AddHeader (ipv6Header);
579 
580  std::ostringstream oss;
581  fragment->Print (oss);
582  listFragments.push_back (fragment);
583  }
584  while (moreFragment);
585 
586  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
587  {
588  delete it->first;
589  }
590 
591  unfragmentablePart.clear ();
592 }
593 
594 
595 void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId,
596  Ipv6Header ipHeader)
597 {
598  Ptr<Fragments> fragments;
599 
600  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
601  NS_ASSERT_MSG(it != m_fragments.end (), "IPv6 Fragment timeout reached for non-existent fragment");
602  fragments = it->second;
603 
604  Ptr<Packet> packet = fragments->GetPartialPacket ();
605 
606  // if we have at least 8 bytes, we can send an ICMP.
607  if ( packet->GetSize () > 8 )
608  {
609  Ptr<Packet> p = packet->Copy ();
610  p->AddHeader (ipHeader);
612  icmp->SendErrorTimeExceeded (p, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
613  }
614 
616  ipL3->ReportDrop (ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
617 
618  // clear the buffers
619  m_fragments.erase (fragmentsId);
620 }
621 
623  : m_moreFragment (0)
624 {
625 }
626 
628 {
629 }
630 
631 void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
632 {
633  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
634 
635  for (it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
636  {
637  if (it->second > fragmentOffset)
638  {
639  break;
640  }
641  }
642 
643  if (it == m_packetFragments.end ())
644  {
645  m_moreFragment = moreFragment;
646  }
647 
648  m_packetFragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
649 }
650 
652 {
653  m_unfragmentable = unfragmentablePart;
654 }
655 
657 {
658  bool ret = !m_moreFragment && m_packetFragments.size () > 0;
659 
660  if (ret)
661  {
662  uint16_t lastEndOffset = 0;
663 
664  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
665  {
666  if (lastEndOffset != it->second)
667  {
668  ret = false;
669  break;
670  }
671 
672  lastEndOffset += it->first->GetSize ();
673  }
674  }
675 
676  return ret;
677 }
678 
680 {
681  Ptr<Packet> p = m_unfragmentable->Copy ();
682 
683  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
684  {
685  p->AddAtEnd (it->first);
686  }
687 
688  return p;
689 }
690 
692 {
693  Ptr<Packet> p;
694 
695  if ( m_unfragmentable )
696  {
697  p = m_unfragmentable->Copy ();
698  }
699  else
700  {
701  return p;
702  }
703 
704  uint16_t lastEndOffset = 0;
705 
706  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
707  {
708  if (lastEndOffset != it->second)
709  {
710  break;
711  }
712  p->AddAtEnd (it->first);
713  lastEndOffset += it->first->GetSize ();
714  }
715 
716  return p;
717 }
718 
720 {
721  m_timeoutEventId = event;
722  return;
723 }
724 
726 {
727  m_timeoutEventId.Cancel ();
728  return;
729 }
730 
731 
733 
735 {
736  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRouting")
738  .AddConstructor<Ipv6ExtensionRouting> ()
739  ;
740  return tid;
741 }
742 
744 {
746 }
747 
749 {
751 }
752 
754 {
756 
757  return EXT_NUMBER;
758 }
759 
761 {
763  return 0;
764 }
765 
767  uint8_t offset,
768  Ipv6Header const& ipv6Header,
769  Ipv6Address dst,
770  uint8_t *nextHeader,
771  bool& stopProcessing,
772  bool& isDropped,
773  Ipv6L3Protocol::DropReason& dropReason)
774 {
775  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
776 
777  // For ICMPv6 Error Packets
778  Ptr<Packet> malformedPacket = packet->Copy ();
779  malformedPacket->AddHeader (ipv6Header);
780 
781  Ptr<Packet> p = packet->Copy ();
782  p->RemoveAtStart (offset);
783 
784  uint8_t buf[4];
785  packet->CopyData (buf, sizeof(buf));
786 
787  uint8_t routingNextHeader = buf[0];
788  uint8_t routingLength = buf[1];
789  uint8_t routingTypeRouting = buf[2];
790  uint8_t routingSegmentsLeft = buf[3];
791 
792  if (nextHeader)
793  {
794  *nextHeader = routingNextHeader;
795  }
796 
797  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
798 
800  Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting);
801 
802  if (ipv6ExtensionRouting == 0)
803  {
804  if (routingSegmentsLeft == 0)
805  {
806  isDropped = false;
807  }
808  else
809  {
810  NS_LOG_LOGIC ("Malformed header. Drop!");
811 
812  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
814  isDropped = true;
815  stopProcessing = true;
816  }
817 
818  return routingLength;
819  }
820 
821  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, stopProcessing, isDropped, dropReason);
822 }
823 
824 
826 
828 {
829  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux")
830  .SetParent<Object> ()
831  .AddAttribute ("Routing Extensions", "The set of IPv6 Routing extensions registered with this demux.",
834  MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
835  ;
836  return tid;
837 }
838 
840 {
841 }
842 
844 {
845 }
846 
848 {
849  for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
850  {
851  (*it)->Dispose ();
852  *it = 0;
853  }
854  m_extensionsRouting.clear ();
855  m_node = 0;
857 }
858 
860 {
861  m_node = node;
862 }
863 
865 {
866  m_extensionsRouting.push_back (extensionRouting);
867 }
868 
870 {
871  for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
872  {
873  if ((*i)->GetTypeRouting () == typeRouting)
874  {
875  return *i;
876  }
877  }
878  return 0;
879 }
880 
882 {
883  m_extensionsRouting.remove (extensionRouting);
884 }
885 
886 
888 
890 {
891  static TypeId tid = TypeId ("ns3::Ipv6ExtensionLooseRouting")
893  .AddConstructor<Ipv6ExtensionLooseRouting> ()
894  ;
895  return tid;
896 }
897 
899 {
901 }
902 
904 {
906 }
907 
909 {
911 
912  return TYPE_ROUTING;
913 }
914 
916  uint8_t offset,
917  Ipv6Header const& ipv6Header,
918  Ipv6Address dst,
919  uint8_t *nextHeader,
920  bool& stopProcessing,
921  bool& isDropped,
922  Ipv6L3Protocol::DropReason& dropReason)
923 {
924  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
925 
926  // For ICMPv6 Error packets
927  Ptr<Packet> malformedPacket = packet->Copy ();
928  malformedPacket->AddHeader (ipv6Header);
929 
930  Ptr<Packet> p = packet->Copy ();
931  p->RemoveAtStart (offset);
932 
933  // Copy IPv6 Header : ipv6Header -> ipv6header
934  Buffer tmp;
935  tmp.AddAtStart (ipv6Header.GetSerializedSize ());
936  Buffer::Iterator it = tmp.Begin ();
937  Ipv6Header ipv6header;
938  ipv6Header.Serialize (it);
939  ipv6header.Deserialize (it);
940 
941  // Get the number of routers' address field
942  uint8_t buf[2];
943  p->CopyData (buf, sizeof(buf));
944  uint8_t numberAddress = buf[1] / 2;
945  Ipv6ExtensionLooseRoutingHeader routingHeader;
946  routingHeader.SetNumberAddress (numberAddress);
947  p->RemoveHeader (routingHeader);
948 
949  if (nextHeader)
950  {
951  *nextHeader = routingHeader.GetNextHeader ();
952  }
953 
954  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
955 
956  Ipv6Address srcAddress = ipv6header.GetSourceAddress ();
957  Ipv6Address destAddress = ipv6header.GetDestinationAddress ();
958  uint8_t hopLimit = ipv6header.GetHopLimit ();
959  uint8_t segmentsLeft = routingHeader.GetSegmentsLeft ();
960  uint8_t length = (routingHeader.GetLength () >> 3) - 1;
961  uint8_t nbAddress = length / 2;
962  uint8_t nextAddressIndex;
963  Ipv6Address nextAddress;
964 
965  if (segmentsLeft == 0)
966  {
967  isDropped = false;
968  return routingHeader.GetSerializedSize ();
969  }
970 
971  if (length % 2 != 0)
972  {
973  NS_LOG_LOGIC ("Malformed header. Drop!");
974  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
976  isDropped = true;
977  stopProcessing = true;
978  return routingHeader.GetSerializedSize ();
979  }
980 
981  if (segmentsLeft > nbAddress)
982  {
983  NS_LOG_LOGIC ("Malformed header. Drop!");
984  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
986  isDropped = true;
987  stopProcessing = true;
988  return routingHeader.GetSerializedSize ();
989  }
990 
991  routingHeader.SetSegmentsLeft (segmentsLeft - 1);
992  nextAddressIndex = nbAddress - segmentsLeft;
993  nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
994 
995  if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
996  {
998  isDropped = true;
999  stopProcessing = true;
1000  return routingHeader.GetSerializedSize ();
1001  }
1002 
1003  routingHeader.SetRouterAddress (nextAddressIndex, destAddress);
1004  ipv6header.SetDestinationAddress (nextAddress);
1005 
1006  if (hopLimit <= 1)
1007  {
1008  NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
1009  icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
1011  isDropped = true;
1012  stopProcessing = true;
1013  return routingHeader.GetSerializedSize ();
1014  }
1015 
1016  routingHeader.SetLength (88);
1017  ipv6header.SetHopLimit (hopLimit - 1);
1018  p->AddHeader (routingHeader);
1019 
1020  /* short-circuiting routing stuff
1021  *
1022  * If we process this option,
1023  * the packet was for us so we resend it to
1024  * the new destination (modified in the header above).
1025  */
1026 
1028  Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
1029  Socket::SocketErrno err;
1030  NS_ASSERT (ipv6rp);
1031 
1032  Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
1033 
1034  if (rtentry)
1035  {
1036  /* we know a route exists so send packet now */
1037  ipv6->SendRealOut (rtentry, p, ipv6header);
1038  }
1039  else
1040  {
1041  NS_LOG_INFO ("No route for next router");
1042  }
1043 
1044  /* as we directly send packet, mark it as dropped */
1045  isDropped = true;
1046 
1047  return routingHeader.GetSerializedSize ();
1048 }
1049 
1050 
1052 
1054 {
1055  static TypeId tid = TypeId ("ns3::Ipv6ExtensionESP")
1057  .AddConstructor<Ipv6ExtensionESP> ()
1058  ;
1059  return tid;
1060 }
1061 
1063 {
1065 }
1066 
1068 {
1070 }
1071 
1073 {
1075 
1076  return EXT_NUMBER;
1077 }
1078 
1080  uint8_t offset,
1081  Ipv6Header const& ipv6Header,
1082  Ipv6Address dst,
1083  uint8_t *nextHeader,
1084  bool& stopProcessing,
1085  bool& isDropped,
1086  Ipv6L3Protocol::DropReason& dropReason)
1087 {
1088  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1089 
1092  return 0;
1093 }
1094 
1095 
1097 
1099 {
1100  static TypeId tid = TypeId ("ns3::Ipv6ExtensionAH")
1102  .AddConstructor<Ipv6ExtensionAH> ()
1103  ;
1104  return tid;
1105 }
1106 
1108 {
1110 }
1111 
1113 {
1115 }
1116 
1118 {
1120 
1121  return EXT_NUMBER;
1122 }
1123 
1125  uint8_t offset,
1126  Ipv6Header const& ipv6Header,
1127  Ipv6Address dst,
1128  uint8_t *nextHeader,
1129  bool& stopProcessing,
1130  bool& isDropped,
1131  Ipv6L3Protocol::DropReason& dropReason)
1132 {
1133  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1134 
1137  return true;
1138 }
1139 
1140 } /* namespace ns3 */
1141 
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: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:81
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberContainer)
Definition: object-vector.h:51
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:66
Doxygen 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.
Ipv6ExtensionLooseRouting()
Constructor.
Doxygen 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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
Ptr< Packet > GetPartialPacket() const
Get the packet parts so far received.
void Insert(Ptr< Ipv6ExtensionRouting > extensionRouting)
Insert a new IPv6 Routing Extension.
static const uint8_t EXT_NUMBER
Fragmentation extension number.
IPv6 layer implementation.
Doxygen introspection did not find any typical Config paths.
automatically resized byte buffer
Definition: buffer.h:92
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:61
virtual void DoDispose()
Dispose this object.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
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:744
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.
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:335
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:223
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.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
virtual ~Ipv6ExtensionRoutingDemux()
Destructor.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
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:429
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
Doxygen introspection did not find any typical Config paths.
Ipv6ExtensionFragment()
Constructor.
Doxygen 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.
Doxygen 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:317
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:353
void SetTimeoutEventId(EventId event)
Set the Timeout EventId.
Doxygen 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:46
uint8_t data[writeSize]
Ptr< Packet > GetPacket() const
Get the entire packet.
Doxygen 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:233
Buffer::Iterator Begin(void) const
Definition: buffer.h:1076
Ipv6ExtensionDestination()
Constructor.
Doxygen 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.
Doxygen introspection did not find any typical Config paths.
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: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.
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:346
double GetValue(double min, double max)
Returns a random double from the uniform distribution with 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.
Doxygen 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:84
Ipv6Extension()
Constructor.
Doxygen introspection did not find any typical Config paths.
uint8_t GetNextHeader() const
Get the next header.
Describes an IPv6 address.
Definition: ipv6-address.h:46
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:86
an identifier for simulation events.
Definition: event-id.h:46
Ipv6ExtensionRouting()
Constructor.
uint32_t GetIdentification() const
Get the field "Identification".
Doxygen introspection did not find any typical Config paths.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
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.
Doxygen 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:381
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.
bool AddAtStart(uint32_t start)
Definition: buffer.cc:309
uint16_t GetOffset() const
Get the field "Offset".
a base class which provides memory management and object aggregation
Definition: object.h:64
Doxygen introspection did not find any typical Config paths.
static const uint8_t EXT_NUMBER
Destination extension number.
contain 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< T > GetObject(void) const
Definition: object.h:362
a unique identifier for an interface.
Definition: type-id.h:49
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:106
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
static TypeId GetTypeId()
Get the type identificator.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
~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.
Doxygen introspection did not find any typical Config paths.
void SetSegmentsLeft(uint8_t segmentsLeft)
Set the "Segments left" field.