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  ;
49 
51 {
52  static TypeId tid = TypeId ("ns3::Ipv6Extension")
53  .SetParent<Object> ()
54  .AddAttribute ("ExtensionNumber", "The IPv6 extension number.",
55  UintegerValue (0),
56  MakeUintegerAccessor (&Ipv6Extension::GetExtensionNumber),
57  MakeUintegerChecker<uint8_t> ())
58  .AddTraceSource ("Drop", "Drop IPv6 packet",
60  ;
61  return tid;
62 }
63 
65 {
67 
68  m_uvar = CreateObject<UniformRandomVariable> ();
69 }
70 
72 {
74 }
75 
77 {
78  NS_LOG_FUNCTION (this << node);
79 
80  m_node = node;
81 }
82 
84 {
86 
87  return m_node;
88 }
89 
90 uint8_t Ipv6Extension::ProcessOptions (Ptr<Packet>& packet, uint8_t offset, uint8_t length, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
91 {
92  NS_LOG_FUNCTION (this << packet << offset << length << ipv6Header << dst << nextHeader << isDropped);
93 
94  // For ICMPv6 Error packets
95  Ptr<Packet> malformedPacket = packet->Copy ();
96  malformedPacket->AddHeader (ipv6Header);
97  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
98 
99  Ptr<Packet> p = packet->Copy ();
100  p->RemoveAtStart (offset);
101 
102  Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> ();
103  Ptr<Ipv6Option> ipv6Option;
104 
105  uint8_t processedSize = 0;
106  uint32_t size = p->GetSize ();
107  uint8_t *data = new uint8_t[size];
108  p->CopyData (data, size);
109 
110  uint8_t optionType = 0;
111  uint8_t optionLength = 0;
112 
113  while (length > processedSize && !isDropped)
114  {
115  optionType = *(data + processedSize);
116  ipv6Option = ipv6OptionDemux->GetOption (optionType);
117 
118  if (ipv6Option == 0)
119  {
120  optionType >>= 6;
121  switch (optionType)
122  {
123  case 0:
124  optionLength = *(data + processedSize + 1) + 2;
125  break;
126 
127  case 1:
128  NS_LOG_LOGIC ("Unknown Option. Drop!");
129  m_dropTrace (packet);
130  optionLength = 0;
131  isDropped = true;
132  break;
133 
134  case 2:
135  NS_LOG_LOGIC ("Unknown Option. Drop!");
136  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
137  m_dropTrace (packet);
138  optionLength = 0;
139  isDropped = true;
140  break;
141 
142  case 3:
143  NS_LOG_LOGIC ("Unknown Option. Drop!");
144 
145  if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
146  {
147  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
148  m_dropTrace (packet);
149  optionLength = 0;
150  isDropped = true;
151  break;
152  }
153 
154  m_dropTrace (packet);
155  optionLength = 0;
156  isDropped = true;
157  break;
158 
159  default:
160  break;
161  }
162 
163  }
164  else
165  {
166  optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
167  }
168 
169  processedSize += optionLength;
170  p->RemoveAtStart (optionLength);
171  }
172 
173  delete [] data;
174 
175  return processedSize;
176 }
177 
178 int64_t
180 {
181  NS_LOG_FUNCTION (this << stream);
182  m_uvar->SetStream (stream);
183  return 1;
184 }
185 
187  ;
188 
190 {
191  static TypeId tid = TypeId ("ns3::Ipv6ExtensionHopByHop")
193  .AddConstructor<Ipv6ExtensionHopByHop> ()
194  ;
195  return tid;
196 }
197 
199 {
201 }
202 
204 {
206 }
207 
209 {
211 
212  return EXT_NUMBER;
213 }
214 
215 uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
216 {
217  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
218 
219  Ptr<Packet> p = packet->Copy ();
220  p->RemoveAtStart (offset);
221 
222  Ipv6ExtensionHopByHopHeader hopbyhopHeader;
223  p->RemoveHeader (hopbyhopHeader);
224  if (nextHeader)
225  {
226  *nextHeader = hopbyhopHeader.GetNextHeader ();
227  }
228 
229  uint8_t processedSize = hopbyhopHeader.GetOptionsOffset ();
230  offset += processedSize;
231  uint8_t length = hopbyhopHeader.GetLength () - hopbyhopHeader.GetOptionsOffset ();
232 
233  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
234 
235  return processedSize;
236 }
237 
238 
240  ;
241 
243 {
244  static TypeId tid = TypeId ("ns3::Ipv6ExtensionDestination")
246  .AddConstructor<Ipv6ExtensionDestination> ()
247  ;
248  return tid;
249 }
250 
252 {
254 }
255 
257 {
259 }
260 
262 {
264 
265  return EXT_NUMBER;
266 }
267 
268 uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
269 {
270  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
271 
272  Ptr<Packet> p = packet->Copy ();
273  p->RemoveAtStart (offset);
274 
275  Ipv6ExtensionDestinationHeader destinationHeader;
276  p->RemoveHeader (destinationHeader);
277  if (nextHeader)
278  {
279  *nextHeader = destinationHeader.GetNextHeader ();
280  }
281 
282  uint8_t processedSize = destinationHeader.GetOptionsOffset ();
283  offset += processedSize;
284  uint8_t length = destinationHeader.GetLength () - destinationHeader.GetOptionsOffset ();
285 
286  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
287 
288  return processedSize;
289 }
290 
291 
293  ;
294 
296 {
297  static TypeId tid = TypeId ("ns3::Ipv6ExtensionFragment")
299  .AddConstructor<Ipv6ExtensionFragment> ()
300  ;
301  return tid;
302 }
303 
305 {
307 }
308 
310 {
312 }
313 
315 {
317 
318  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
319  {
320  it->second = 0;
321  }
322 
323  m_fragments.clear ();
325 }
326 
328 {
330 
331  return EXT_NUMBER;
332 }
333 
334 uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
335 {
336  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
337 
338  Ptr<Packet> p = packet->Copy ();
339  p->RemoveAtStart (offset);
340 
341  Ipv6ExtensionFragmentHeader fragmentHeader;
342  p->RemoveHeader (fragmentHeader);
343 
344  if (nextHeader)
345  {
346  *nextHeader = fragmentHeader.GetNextHeader ();
347  }
348 
349  bool moreFragment = fragmentHeader.GetMoreFragment ();
350  uint16_t fragmentOffset = fragmentHeader.GetOffset ();
351  uint32_t identification = fragmentHeader.GetIdentification ();
352  Ipv6Address src = ipv6Header.GetSourceAddress ();
353 
354  std::pair<Ipv6Address, uint32_t> fragmentsId = std::pair<Ipv6Address, uint32_t> (src, identification);
355  Ptr<Fragments> fragments;
356 
357  Ipv6Header ipHeader = ipv6Header;
358  ipHeader.SetNextHeader (fragmentHeader.GetNextHeader ());
359 
360  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
361  if (it == m_fragments.end ())
362  {
363  fragments = Create<Fragments> ();
364  m_fragments.insert (std::make_pair (fragmentsId, fragments));
365  EventId timeout = Simulator::Schedule (Seconds (60),
367  fragmentsId, ipHeader);
368  fragments->SetTimeoutEventId (timeout);
369  }
370  else
371  {
372  fragments = it->second;
373  }
374 
375  if (fragmentOffset == 0)
376  {
377  Ptr<Packet> unfragmentablePart = packet->Copy ();
378  unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset);
379  fragments->SetUnfragmentablePart (unfragmentablePart);
380  }
381 
382  fragments->AddFragment (p, fragmentOffset, moreFragment);
383 
384  if (fragments->IsEntire ())
385  {
386  packet = fragments->GetPacket ();
387  fragments->CancelTimeout ();
388  m_fragments.erase (fragmentsId);
389  isDropped = false;
390  }
391  else
392  {
393  // the fragment is not "dropped", but Ipv6L3Protocol::LocalDeliver must stop processing it.
394  isDropped = true;
395  }
396 
397  return 0;
398 }
399 
400 void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragmentSize, std::list<Ptr<Packet> >& listFragments)
401 {
402  Ptr<Packet> p = packet->Copy ();
403 
404  Ipv6Header ipv6Header;
405  p->RemoveHeader (ipv6Header);
406 
407  uint8_t nextHeader = ipv6Header.GetNextHeader ();
408  uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize ();
409 
410  uint8_t type;
411  p->CopyData (&type, sizeof(type));
412 
413  bool moreHeader = true;
414  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
415  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
416  {
417  moreHeader = false;
419  }
420 
421  std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart;
422  uint32_t unfragmentablePartSize = 0;
423 
425  Ptr<Ipv6Extension> extension = extensionDemux->GetExtension (nextHeader);
426  uint8_t extensionHeaderLength;
427 
428  while (moreHeader)
429  {
430  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
431  {
433  p->RemoveHeader (*hopbyhopHeader);
434 
435  nextHeader = hopbyhopHeader->GetNextHeader ();
436  extensionHeaderLength = hopbyhopHeader->GetLength ();
437 
438  uint8_t type;
439  p->CopyData (&type, sizeof(type));
440 
441  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
442  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
443  {
444  moreHeader = false;
446  }
447 
448  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
449  unfragmentablePartSize += extensionHeaderLength;
450  }
451  else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
452  {
453  uint8_t buf[2];
454  p->CopyData (buf, sizeof(buf));
455  uint8_t numberAddress = buf[1] / 2;
457  routingHeader->SetNumberAddress (numberAddress);
458  p->RemoveHeader (*routingHeader);
459 
460  nextHeader = routingHeader->GetNextHeader ();
461  extensionHeaderLength = routingHeader->GetLength ();
462 
463  uint8_t type;
464  p->CopyData (&type, sizeof(type));
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> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
473  unfragmentablePartSize += extensionHeaderLength;
474  }
475  else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
476  {
478  p->RemoveHeader (*destinationHeader);
479 
480  nextHeader = destinationHeader->GetNextHeader ();
481  extensionHeaderLength = destinationHeader->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> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
493  unfragmentablePartSize += extensionHeaderLength;
494  }
495  }
496 
497  Ipv6ExtensionFragmentHeader fragmentHeader;
498  uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize ();
499 
500  uint32_t maxFragmentablePartSize = maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
501  uint32_t currentFragmentablePartSize = 0;
502 
503  bool moreFragment = true;
504  uint32_t identification = (uint32_t) m_uvar->GetValue (0, (uint32_t)-1);
505  uint16_t offset = 0;
506 
507  do
508  {
509  if (p->GetSize () > offset + maxFragmentablePartSize)
510  {
511  moreFragment = true;
512  currentFragmentablePartSize = maxFragmentablePartSize;
513  currentFragmentablePartSize -= currentFragmentablePartSize % 8;
514  }
515  else
516  {
517  moreFragment = false;
518  currentFragmentablePartSize = p->GetSize () - offset;
519  }
520 
521 
522  fragmentHeader.SetNextHeader (nextHeader);
523  fragmentHeader.SetOffset (offset);
524  fragmentHeader.SetMoreFragment (moreFragment);
525  fragmentHeader.SetIdentification (identification);
526 
527  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
528  offset += currentFragmentablePartSize;
529 
530  fragment->AddHeader (fragmentHeader);
531 
532  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
533  {
534  if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
535  {
537  dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first);
538  NS_ASSERT (p != 0);
539  fragment->AddHeader (*p);
540  }
541  else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
542  {
544  dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first);
545  NS_ASSERT (p != 0);
546  fragment->AddHeader (*p);
547  }
548  else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
549  {
551  dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first);
552  NS_ASSERT (p != 0);
553  fragment->AddHeader (*p);
554  }
555  }
556 
557  ipv6Header.SetPayloadLength (fragment->GetSize ());
558  fragment->AddHeader (ipv6Header);
559 
560  std::ostringstream oss;
561  fragment->Print (oss);
562  listFragments.push_back (fragment);
563  }
564  while (moreFragment);
565 
566  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
567  {
568  delete it->first;
569  }
570 
571  unfragmentablePart.clear ();
572 }
573 
574 
575 void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId,
576  Ipv6Header & ipHeader)
577 {
578  Ptr<Fragments> fragments;
579 
580  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
581  NS_ASSERT_MSG(it != m_fragments.end (), "IPv6 Fragment timeout reached for non-existent fragment");
582  fragments = it->second;
583 
584  Ptr<Packet> packet = fragments->GetPartialPacket ();
585 
586  packet->AddHeader (ipHeader);
587 
588  // if we have at least 8 bytes, we can send an ICMP.
589  if ( packet->GetSize () > 8 )
590  {
592  icmp->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
593  }
594  m_dropTrace (packet);
595 
596  // clear the buffers
597  m_fragments.erase (fragmentsId);
598 }
599 
601  : m_moreFragment (0)
602 {
603 }
604 
606 {
607 }
608 
609 void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
610 {
611  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
612 
613  for (it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
614  {
615  if (it->second > fragmentOffset)
616  {
617  break;
618  }
619  }
620 
621  if (it == m_packetFragments.end ())
622  {
623  m_moreFragment = moreFragment;
624  }
625 
626  m_packetFragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
627 }
628 
630 {
631  m_unfragmentable = unfragmentablePart;
632 }
633 
635 {
636  bool ret = !m_moreFragment && m_packetFragments.size () > 0;
637 
638  if (ret)
639  {
640  uint16_t lastEndOffset = 0;
641 
642  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
643  {
644  if (lastEndOffset != it->second)
645  {
646  ret = false;
647  break;
648  }
649 
650  lastEndOffset += it->first->GetSize ();
651  }
652  }
653 
654  return ret;
655 }
656 
658 {
659  Ptr<Packet> p = m_unfragmentable->Copy ();
660 
661  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
662  {
663  p->AddAtEnd (it->first);
664  }
665 
666  return p;
667 }
668 
670 {
671  Ptr<Packet> p;
672 
673  if ( m_unfragmentable )
674  {
675  p = m_unfragmentable->Copy ();
676  }
677  else
678  {
679  return p;
680  }
681 
682  uint16_t lastEndOffset = 0;
683 
684  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
685  {
686  if (lastEndOffset != it->second)
687  {
688  break;
689  }
690  p->AddAtEnd (it->first);
691  lastEndOffset += it->first->GetSize ();
692  }
693 
694  return p;
695 }
696 
698 {
699  m_timeoutEventId = event;
700  return;
701 }
702 
704 {
705  m_timeoutEventId.Cancel ();
706  return;
707 }
708 
709 
711  ;
712 
714 {
715  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRouting")
717  .AddConstructor<Ipv6ExtensionRouting> ()
718  ;
719  return tid;
720 }
721 
723 {
725 }
726 
728 {
730 }
731 
733 {
735 
736  return EXT_NUMBER;
737 }
738 
740 {
742  return 0;
743 }
744 
745 uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
746 {
747  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
748 
749  // For ICMPv6 Error Packets
750  Ptr<Packet> malformedPacket = packet->Copy ();
751  malformedPacket->AddHeader (ipv6Header);
752 
753  Ptr<Packet> p = packet->Copy ();
754  p->RemoveAtStart (offset);
755 
756  uint8_t buf[4];
757  packet->CopyData (buf, sizeof(buf));
758 
759  uint8_t routingNextHeader = buf[0];
760  uint8_t routingLength = buf[1];
761  uint8_t routingTypeRouting = buf[2];
762  uint8_t routingSegmentsLeft = buf[3];
763 
764  if (nextHeader)
765  {
766  *nextHeader = routingNextHeader;
767  }
768 
769  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
770 
772  Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting);
773 
774  if (ipv6ExtensionRouting == 0)
775  {
776  if (routingSegmentsLeft == 0)
777  {
778  isDropped = false;
779  }
780  else
781  {
782  NS_LOG_LOGIC ("Malformed header. Drop!");
783 
784  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
785  m_dropTrace (packet);
786  isDropped = true;
787  }
788 
789  return routingLength;
790  }
791 
792  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped);
793 }
794 
795 
797  ;
798 
800 {
801  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux")
802  .SetParent<Object> ()
803  .AddAttribute ("Routing Extensions", "The set of IPv6 Routing extensions registered with this demux.",
806  MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
807  ;
808  return tid;
809 }
810 
812 {
813 }
814 
816 {
817 }
818 
820 {
821  for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
822  {
823  (*it)->Dispose ();
824  *it = 0;
825  }
826  m_extensionsRouting.clear ();
827  m_node = 0;
829 }
830 
832 {
833  m_node = node;
834 }
835 
837 {
838  m_extensionsRouting.push_back (extensionRouting);
839 }
840 
842 {
843  for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
844  {
845  if ((*i)->GetTypeRouting () == typeRouting)
846  {
847  return *i;
848  }
849  }
850  return 0;
851 }
852 
854 {
855  m_extensionsRouting.remove (extensionRouting);
856 }
857 
858 
860  ;
861 
863 {
864  static TypeId tid = TypeId ("ns3::Ipv6ExtensionLooseRouting")
866  .AddConstructor<Ipv6ExtensionLooseRouting> ()
867  ;
868  return tid;
869 }
870 
872 {
874 }
875 
877 {
879 }
880 
882 {
884 
885  return TYPE_ROUTING;
886 }
887 
888 uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
889 {
890  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
891 
892  // For ICMPv6 Error packets
893  Ptr<Packet> malformedPacket = packet->Copy ();
894  malformedPacket->AddHeader (ipv6Header);
895 
896  Ptr<Packet> p = packet->Copy ();
897  p->RemoveAtStart (offset);
898 
899  // Copy IPv6 Header : ipv6Header -> ipv6header
900  Buffer tmp;
901  tmp.AddAtStart (ipv6Header.GetSerializedSize ());
902  Buffer::Iterator it = tmp.Begin ();
903  Ipv6Header ipv6header;
904  ipv6Header.Serialize (it);
905  ipv6header.Deserialize (it);
906 
907  // Get the number of routers' address field
908  uint8_t buf[2];
909  p->CopyData (buf, sizeof(buf));
910  uint8_t numberAddress = buf[1] / 2;
911  Ipv6ExtensionLooseRoutingHeader routingHeader;
912  routingHeader.SetNumberAddress (numberAddress);
913  p->RemoveHeader (routingHeader);
914 
915  if (nextHeader)
916  {
917  *nextHeader = routingHeader.GetNextHeader ();
918  }
919 
920  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
921 
922  Ipv6Address srcAddress = ipv6header.GetSourceAddress ();
923  Ipv6Address destAddress = ipv6header.GetDestinationAddress ();
924  uint8_t hopLimit = ipv6header.GetHopLimit ();
925  uint8_t segmentsLeft = routingHeader.GetSegmentsLeft ();
926  uint8_t length = (routingHeader.GetLength () >> 3) - 1;
927  uint8_t nbAddress = length / 2;
928  uint8_t nextAddressIndex;
929  Ipv6Address nextAddress;
930 
931  if (segmentsLeft == 0)
932  {
933  isDropped = false;
934  return routingHeader.GetSerializedSize ();
935  }
936 
937  if (length % 2 != 0)
938  {
939  NS_LOG_LOGIC ("Malformed header. Drop!");
940  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
941  m_dropTrace (packet);
942  isDropped = true;
943  return routingHeader.GetSerializedSize ();
944  }
945 
946  if (segmentsLeft > nbAddress)
947  {
948  NS_LOG_LOGIC ("Malformed header. Drop!");
949  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
950  m_dropTrace (packet);
951  isDropped = true;
952  return routingHeader.GetSerializedSize ();
953  }
954 
955  routingHeader.SetSegmentsLeft (segmentsLeft - 1);
956  nextAddressIndex = nbAddress - segmentsLeft;
957  nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
958 
959  if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
960  {
961  m_dropTrace (packet);
962  isDropped = true;
963  return routingHeader.GetSerializedSize ();
964  }
965 
966  routingHeader.SetRouterAddress (nextAddressIndex, destAddress);
967  ipv6header.SetDestinationAddress (nextAddress);
968 
969  if (hopLimit <= 1)
970  {
971  NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
972  icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
973  m_dropTrace (packet);
974  isDropped = true;
975  return routingHeader.GetSerializedSize ();
976  }
977 
978  routingHeader.SetLength (88);
979  ipv6header.SetHopLimit (hopLimit - 1);
980  p->AddHeader (routingHeader);
981 
982  /* short-circuiting routing stuff
983  *
984  * If we process this option,
985  * the packet was for us so we resend it to
986  * the new destination (modified in the header above).
987  */
988 
990  Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
992  NS_ASSERT (ipv6rp);
993 
994  Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
995 
996  if (rtentry)
997  {
998  /* we know a route exists so send packet now */
999  ipv6->SendRealOut (rtentry, p, ipv6header);
1000  }
1001  else
1002  {
1003  NS_LOG_INFO ("No route for next router");
1004  }
1005 
1006  /* as we directly send packet, mark it as dropped */
1007  isDropped = true;
1008 
1009  return routingHeader.GetSerializedSize ();
1010 }
1011 
1012 
1014  ;
1015 
1017 {
1018  static TypeId tid = TypeId ("ns3::Ipv6ExtensionESP")
1020  .AddConstructor<Ipv6ExtensionESP> ()
1021  ;
1022  return tid;
1023 }
1024 
1026 {
1028 }
1029 
1031 {
1033 }
1034 
1036 {
1038 
1039  return EXT_NUMBER;
1040 }
1041 
1042 uint8_t Ipv6ExtensionESP::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
1043 {
1044  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1045 
1048  return 0;
1049 }
1050 
1051 
1053  ;
1054 
1056 {
1057  static TypeId tid = TypeId ("ns3::Ipv6ExtensionAH")
1059  .AddConstructor<Ipv6ExtensionAH> ()
1060  ;
1061  return tid;
1062 }
1063 
1065 {
1067 }
1068 
1070 {
1072 }
1073 
1075 {
1077 
1078  return EXT_NUMBER;
1079 }
1080 
1081 uint8_t Ipv6ExtensionAH::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
1082 {
1083  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1084 
1087  return true;
1088 }
1089 
1090 } /* namespace ns3 */
1091 
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
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
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:82
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:67
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...
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)
Definition: log.h:345
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
TracedCallback< Ptr< const Packet > > m_dropTrace
Drop trace callback.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
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.
NS_LOG_COMPONENT_DEFINE("Ipv6Extension")
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)
Definition: assert.h:64
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
virtual void DoDispose()
Dispose this object.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
uint32_t GetSize(void) const
Definition: packet.h:650
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:77
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:336
#define NS_LOG_INFO(msg)
Definition: log.h:298
static TypeId GetTypeId()
Get the type identificator.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
Definition: log.h:309
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:824
ns3::Time timeout
Ipv6ExtensionRoutingDemux()
Constructor.
void SetOffset(uint16_t offset)
Set the "Offset" field.
void Print(std::ostream &os) const
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.
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.
void HandleFragmentsTimeout(std::pair< Ipv6Address, uint32_t > key, Ipv6Header &ipHeader)
Process the timeout for packet fragments.
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.
~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.
#define NS_LOG_LOGIC(msg)
Definition: log.h:368
Buffer::Iterator Begin(void) const
Definition: buffer.h:875
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: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
Definition: packet.cc:122
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:92
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.
virtual uint8_t ProcessOptions(Ptr< Packet > &packet, uint8_t offset, uint8_t length, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process options Called by implementing classes to process the options.
static TypeId GetTypeId()
Get the type identificator.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
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 It is safe to remove more bytes than are present...
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)
Definition: assert.h:86
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: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:87
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method.
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:102
virtual uint8_t GetExtensionNumber() const
Get the extension number.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
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.
bool AddAtStart(uint32_t start)
Definition: buffer.cc:305
uint16_t GetOffset() const
Get the field "Offset".
a base class which provides memory management and object aggregation
Definition: object.h:63
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:361
a unique identifier for an interface.
Definition: type-id.h:49
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:107
TypeId SetParent(TypeId tid)
Definition: type-id.cc:611
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
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:112
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
virtual ~Ipv6Extension()
Destructor.
Doxygen introspection did not find any typical Config paths.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method.
void SetSegmentsLeft(uint8_t segmentsLeft)
Set the "Segments left" field.