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  .AddTraceSource ("Drop", "Drop IPv6 packet",
59  ;
60  return tid;
61 }
62 
64 {
66 
67  m_uvar = CreateObject<UniformRandomVariable> ();
68 }
69 
71 {
73 }
74 
76 {
77  NS_LOG_FUNCTION (this << node);
78 
79  m_node = node;
80 }
81 
83 {
85 
86  return m_node;
87 }
88 
89 uint8_t Ipv6Extension::ProcessOptions (Ptr<Packet>& packet, uint8_t offset, uint8_t length, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
90 {
91  NS_LOG_FUNCTION (this << packet << offset << length << ipv6Header << dst << nextHeader << isDropped);
92 
93  // For ICMPv6 Error packets
94  Ptr<Packet> malformedPacket = packet->Copy ();
95  malformedPacket->AddHeader (ipv6Header);
96  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
97 
98  Ptr<Packet> p = packet->Copy ();
99  p->RemoveAtStart (offset);
100 
101  Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> ();
102  Ptr<Ipv6Option> ipv6Option;
103 
104  uint8_t processedSize = 0;
105  uint32_t size = p->GetSize ();
106  uint8_t *data = new uint8_t[size];
107  p->CopyData (data, size);
108 
109  uint8_t optionType = 0;
110  uint8_t optionLength = 0;
111 
112  while (length > processedSize && !isDropped)
113  {
114  optionType = *(data + processedSize);
115  ipv6Option = ipv6OptionDemux->GetOption (optionType);
116 
117  if (ipv6Option == 0)
118  {
119  optionType >>= 6;
120  switch (optionType)
121  {
122  case 0:
123  optionLength = *(data + processedSize + 1) + 2;
124  break;
125 
126  case 1:
127  NS_LOG_LOGIC ("Unknown Option. Drop!");
128  m_dropTrace (packet);
129  optionLength = 0;
130  isDropped = true;
131  break;
132 
133  case 2:
134  NS_LOG_LOGIC ("Unknown Option. Drop!");
135  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
136  m_dropTrace (packet);
137  optionLength = 0;
138  isDropped = true;
139  break;
140 
141  case 3:
142  NS_LOG_LOGIC ("Unknown Option. Drop!");
143 
144  if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
145  {
146  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
147  m_dropTrace (packet);
148  optionLength = 0;
149  isDropped = true;
150  break;
151  }
152 
153  m_dropTrace (packet);
154  optionLength = 0;
155  isDropped = true;
156  break;
157 
158  default:
159  break;
160  }
161 
162  }
163  else
164  {
165  optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
166  }
167 
168  processedSize += optionLength;
169  p->RemoveAtStart (optionLength);
170  }
171 
172  delete [] data;
173 
174  return processedSize;
175 }
176 
177 int64_t
179 {
180  NS_LOG_FUNCTION (this << stream);
181  m_uvar->SetStream (stream);
182  return 1;
183 }
184 
186 
188 {
189  static TypeId tid = TypeId ("ns3::Ipv6ExtensionHopByHop")
191  .AddConstructor<Ipv6ExtensionHopByHop> ()
192  ;
193  return tid;
194 }
195 
197 {
199 }
200 
202 {
204 }
205 
207 {
209 
210  return EXT_NUMBER;
211 }
212 
213 uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
214 {
215  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
216 
217  Ptr<Packet> p = packet->Copy ();
218  p->RemoveAtStart (offset);
219 
220  Ipv6ExtensionHopByHopHeader hopbyhopHeader;
221  p->RemoveHeader (hopbyhopHeader);
222  if (nextHeader)
223  {
224  *nextHeader = hopbyhopHeader.GetNextHeader ();
225  }
226 
227  uint8_t processedSize = hopbyhopHeader.GetOptionsOffset ();
228  offset += processedSize;
229  uint8_t length = hopbyhopHeader.GetLength () - hopbyhopHeader.GetOptionsOffset ();
230 
231  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
232 
233  return processedSize;
234 }
235 
236 
238 
240 {
241  static TypeId tid = TypeId ("ns3::Ipv6ExtensionDestination")
243  .AddConstructor<Ipv6ExtensionDestination> ()
244  ;
245  return tid;
246 }
247 
249 {
251 }
252 
254 {
256 }
257 
259 {
261 
262  return EXT_NUMBER;
263 }
264 
265 uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
266 {
267  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
268 
269  Ptr<Packet> p = packet->Copy ();
270  p->RemoveAtStart (offset);
271 
272  Ipv6ExtensionDestinationHeader destinationHeader;
273  p->RemoveHeader (destinationHeader);
274  if (nextHeader)
275  {
276  *nextHeader = destinationHeader.GetNextHeader ();
277  }
278 
279  uint8_t processedSize = destinationHeader.GetOptionsOffset ();
280  offset += processedSize;
281  uint8_t length = destinationHeader.GetLength () - destinationHeader.GetOptionsOffset ();
282 
283  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
284 
285  return processedSize;
286 }
287 
288 
290 
292 {
293  static TypeId tid = TypeId ("ns3::Ipv6ExtensionFragment")
295  .AddConstructor<Ipv6ExtensionFragment> ()
296  ;
297  return tid;
298 }
299 
301 {
303 }
304 
306 {
308 }
309 
311 {
313 
314  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
315  {
316  it->second = 0;
317  }
318 
319  m_fragments.clear ();
321 }
322 
324 {
326 
327  return EXT_NUMBER;
328 }
329 
330 uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
331 {
332  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
333 
334  Ptr<Packet> p = packet->Copy ();
335  p->RemoveAtStart (offset);
336 
337  Ipv6ExtensionFragmentHeader fragmentHeader;
338  p->RemoveHeader (fragmentHeader);
339 
340  if (nextHeader)
341  {
342  *nextHeader = fragmentHeader.GetNextHeader ();
343  }
344 
345  bool moreFragment = fragmentHeader.GetMoreFragment ();
346  uint16_t fragmentOffset = fragmentHeader.GetOffset ();
347  uint32_t identification = fragmentHeader.GetIdentification ();
348  Ipv6Address src = ipv6Header.GetSourceAddress ();
349 
350  std::pair<Ipv6Address, uint32_t> fragmentsId = std::pair<Ipv6Address, uint32_t> (src, identification);
351  Ptr<Fragments> fragments;
352 
353  Ipv6Header ipHeader = ipv6Header;
354  ipHeader.SetNextHeader (fragmentHeader.GetNextHeader ());
355 
356  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
357  if (it == m_fragments.end ())
358  {
359  fragments = Create<Fragments> ();
360  m_fragments.insert (std::make_pair (fragmentsId, fragments));
361  EventId timeout = Simulator::Schedule (Seconds (60),
363  fragmentsId, ipHeader);
364  fragments->SetTimeoutEventId (timeout);
365  }
366  else
367  {
368  fragments = it->second;
369  }
370 
371  if (fragmentOffset == 0)
372  {
373  Ptr<Packet> unfragmentablePart = packet->Copy ();
374  unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset);
375  fragments->SetUnfragmentablePart (unfragmentablePart);
376  }
377 
378  fragments->AddFragment (p, fragmentOffset, moreFragment);
379 
380  if (fragments->IsEntire ())
381  {
382  packet = fragments->GetPacket ();
383  fragments->CancelTimeout ();
384  m_fragments.erase (fragmentsId);
385  isDropped = false;
386  }
387  else
388  {
389  // the fragment is not "dropped", but Ipv6L3Protocol::LocalDeliver must stop processing it.
390  isDropped = true;
391  }
392 
393  return 0;
394 }
395 
396 void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragmentSize, std::list<Ptr<Packet> >& listFragments)
397 {
398  Ptr<Packet> p = packet->Copy ();
399 
400  Ipv6Header ipv6Header;
401  p->RemoveHeader (ipv6Header);
402 
403  uint8_t nextHeader = ipv6Header.GetNextHeader ();
404  uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize ();
405 
406  uint8_t type;
407  p->CopyData (&type, sizeof(type));
408 
409  bool moreHeader = true;
410  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
411  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
412  {
413  moreHeader = false;
415  }
416 
417  std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart;
418  uint32_t unfragmentablePartSize = 0;
419 
421  Ptr<Ipv6Extension> extension = extensionDemux->GetExtension (nextHeader);
422  uint8_t extensionHeaderLength;
423 
424  while (moreHeader)
425  {
426  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
427  {
429  p->RemoveHeader (*hopbyhopHeader);
430 
431  nextHeader = hopbyhopHeader->GetNextHeader ();
432  extensionHeaderLength = hopbyhopHeader->GetLength ();
433 
434  uint8_t type;
435  p->CopyData (&type, sizeof(type));
436 
437  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
438  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
439  {
440  moreHeader = false;
442  }
443 
444  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
445  unfragmentablePartSize += extensionHeaderLength;
446  }
447  else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
448  {
449  uint8_t buf[2];
450  p->CopyData (buf, sizeof(buf));
451  uint8_t numberAddress = buf[1] / 2;
453  routingHeader->SetNumberAddress (numberAddress);
454  p->RemoveHeader (*routingHeader);
455 
456  nextHeader = routingHeader->GetNextHeader ();
457  extensionHeaderLength = routingHeader->GetLength ();
458 
459  uint8_t type;
460  p->CopyData (&type, sizeof(type));
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> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
469  unfragmentablePartSize += extensionHeaderLength;
470  }
471  else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
472  {
474  p->RemoveHeader (*destinationHeader);
475 
476  nextHeader = destinationHeader->GetNextHeader ();
477  extensionHeaderLength = destinationHeader->GetLength ();
478 
479  uint8_t type;
480  p->CopyData (&type, sizeof(type));
481  if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
482  || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
483  {
484  moreHeader = false;
486  }
487 
488  unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
489  unfragmentablePartSize += extensionHeaderLength;
490  }
491  }
492 
493  Ipv6ExtensionFragmentHeader fragmentHeader;
494  uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize ();
495 
496  uint32_t maxFragmentablePartSize = maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
497  uint32_t currentFragmentablePartSize = 0;
498 
499  bool moreFragment = true;
500  uint32_t identification = (uint32_t) m_uvar->GetValue (0, (uint32_t)-1);
501  uint16_t offset = 0;
502 
503  do
504  {
505  if (p->GetSize () > offset + maxFragmentablePartSize)
506  {
507  moreFragment = true;
508  currentFragmentablePartSize = maxFragmentablePartSize;
509  }
510  else
511  {
512  moreFragment = false;
513  currentFragmentablePartSize = p->GetSize () - offset;
514  }
515 
516  currentFragmentablePartSize -= currentFragmentablePartSize % 8;
517 
518  fragmentHeader.SetNextHeader (nextHeader);
519  fragmentHeader.SetLength (currentFragmentablePartSize);
520  fragmentHeader.SetOffset (offset);
521  fragmentHeader.SetMoreFragment (moreFragment);
522  fragmentHeader.SetIdentification (identification);
523 
524  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
525  offset += currentFragmentablePartSize;
526 
527  fragment->AddHeader (fragmentHeader);
528 
529  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
530  {
531  if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
532  {
534  dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first);
535  NS_ASSERT (p != 0);
536  fragment->AddHeader (*p);
537  }
538  else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
539  {
541  dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first);
542  NS_ASSERT (p != 0);
543  fragment->AddHeader (*p);
544  }
545  else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
546  {
548  dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first);
549  NS_ASSERT (p != 0);
550  fragment->AddHeader (*p);
551  }
552  }
553 
554  ipv6Header.SetPayloadLength (fragment->GetSize ());
555  fragment->AddHeader (ipv6Header);
556 
557  std::ostringstream oss;
558  fragment->Print (oss);
559  listFragments.push_back (fragment);
560  }
561  while (moreFragment);
562 
563  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
564  {
565  delete it->first;
566  }
567 
568  unfragmentablePart.clear ();
569 }
570 
571 
572 void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId,
573  Ipv6Header & ipHeader)
574 {
575  Ptr<Fragments> fragments;
576 
577  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
578  NS_ASSERT_MSG(it != m_fragments.end (), "IPv6 Fragment timeout reached for non-existent fragment");
579  fragments = it->second;
580 
581  Ptr<Packet> packet = fragments->GetPartialPacket ();
582 
583  packet->AddHeader (ipHeader);
584 
585  // if we have at least 8 bytes, we can send an ICMP.
586  if ( packet->GetSize () > 8 )
587  {
589  icmp->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
590  }
591  m_dropTrace (packet);
592 
593  // clear the buffers
594  m_fragments.erase (fragmentsId);
595 }
596 
598  : m_moreFragment (0)
599 {
600 }
601 
603 {
604 }
605 
606 void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
607 {
608  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
609 
610  for (it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
611  {
612  if (it->second > fragmentOffset)
613  {
614  break;
615  }
616  }
617 
618  if (it == m_packetFragments.end ())
619  {
620  m_moreFragment = moreFragment;
621  }
622 
623  m_packetFragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
624 }
625 
627 {
628  m_unfragmentable = unfragmentablePart;
629 }
630 
632 {
633  bool ret = !m_moreFragment && m_packetFragments.size () > 0;
634 
635  if (ret)
636  {
637  uint16_t lastEndOffset = 0;
638 
639  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
640  {
641  if (lastEndOffset != it->second)
642  {
643  ret = false;
644  break;
645  }
646 
647  lastEndOffset += it->first->GetSize ();
648  }
649  }
650 
651  return ret;
652 }
653 
655 {
656  Ptr<Packet> p = m_unfragmentable->Copy ();
657 
658  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
659  {
660  p->AddAtEnd (it->first);
661  }
662 
663  return p;
664 }
665 
667 {
668  Ptr<Packet> p;
669 
670  if ( m_unfragmentable )
671  {
672  p = m_unfragmentable->Copy ();
673  }
674  else
675  {
676  return p;
677  }
678 
679  uint16_t lastEndOffset = 0;
680 
681  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
682  {
683  if (lastEndOffset != it->second)
684  {
685  break;
686  }
687  p->AddAtEnd (it->first);
688  lastEndOffset += it->first->GetSize ();
689  }
690 
691  return p;
692 }
693 
695 {
696  m_timeoutEventId = event;
697  return;
698 }
699 
701 {
702  m_timeoutEventId.Cancel ();
703  return;
704 }
705 
706 
708 
710 {
711  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRouting")
713  .AddConstructor<Ipv6ExtensionRouting> ()
714  ;
715  return tid;
716 }
717 
719 {
721 }
722 
724 {
726 }
727 
729 {
731 
732  return EXT_NUMBER;
733 }
734 
736 {
738  return 0;
739 }
740 
741 uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
742 {
743  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
744 
745  // For ICMPv6 Error Packets
746  Ptr<Packet> malformedPacket = packet->Copy ();
747  malformedPacket->AddHeader (ipv6Header);
748 
749  Ptr<Packet> p = packet->Copy ();
750  p->RemoveAtStart (offset);
751 
752  uint8_t buf[4];
753  packet->CopyData (buf, sizeof(buf));
754 
755  uint8_t routingNextHeader = buf[0];
756  uint8_t routingLength = buf[1];
757  uint8_t routingTypeRouting = buf[2];
758  uint8_t routingSegmentsLeft = buf[3];
759 
760  if (nextHeader)
761  {
762  *nextHeader = routingNextHeader;
763  }
764 
765  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
766 
768  Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting);
769 
770  if (ipv6ExtensionRouting == 0)
771  {
772  if (routingSegmentsLeft == 0)
773  {
774  isDropped = false;
775  }
776  else
777  {
778  NS_LOG_LOGIC ("Malformed header. Drop!");
779 
780  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
781  m_dropTrace (packet);
782  isDropped = true;
783  }
784 
785  return routingLength;
786  }
787 
788  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped);
789 }
790 
791 
793 
795 {
796  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux")
797  .SetParent<Object> ()
798  .AddAttribute ("Routing Extensions", "The set of IPv6 Routing extensions registered with this demux.",
801  MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
802  ;
803  return tid;
804 }
805 
807 {
808 }
809 
811 {
812 }
813 
815 {
816  for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
817  {
818  (*it)->Dispose ();
819  *it = 0;
820  }
821  m_extensionsRouting.clear ();
822  m_node = 0;
824 }
825 
827 {
828  m_node = node;
829 }
830 
832 {
833  m_extensionsRouting.push_back (extensionRouting);
834 }
835 
837 {
838  for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
839  {
840  if ((*i)->GetTypeRouting () == typeRouting)
841  {
842  return *i;
843  }
844  }
845  return 0;
846 }
847 
849 {
850  m_extensionsRouting.remove (extensionRouting);
851 }
852 
853 
855 
857 {
858  static TypeId tid = TypeId ("ns3::Ipv6ExtensionLooseRouting")
860  .AddConstructor<Ipv6ExtensionLooseRouting> ()
861  ;
862  return tid;
863 }
864 
866 {
868 }
869 
871 {
873 }
874 
876 {
878 
879  return TYPE_ROUTING;
880 }
881 
882 uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
883 {
884  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
885 
886  // For ICMPv6 Error packets
887  Ptr<Packet> malformedPacket = packet->Copy ();
888  malformedPacket->AddHeader (ipv6Header);
889 
890  Ptr<Packet> p = packet->Copy ();
891  p->RemoveAtStart (offset);
892 
893  // Copy IPv6 Header : ipv6Header -> ipv6header
894  Buffer tmp;
895  tmp.AddAtStart (ipv6Header.GetSerializedSize ());
896  Buffer::Iterator it = tmp.Begin ();
897  Ipv6Header ipv6header;
898  ipv6Header.Serialize (it);
899  ipv6header.Deserialize (it);
900 
901  // Get the number of routers' address field
902  uint8_t buf[2];
903  p->CopyData (buf, sizeof(buf));
904  uint8_t numberAddress = buf[1] / 2;
905  Ipv6ExtensionLooseRoutingHeader routingHeader;
906  routingHeader.SetNumberAddress (numberAddress);
907  p->RemoveHeader (routingHeader);
908 
909  if (nextHeader)
910  {
911  *nextHeader = routingHeader.GetNextHeader ();
912  }
913 
914  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
915 
916  Ipv6Address srcAddress = ipv6header.GetSourceAddress ();
917  Ipv6Address destAddress = ipv6header.GetDestinationAddress ();
918  uint8_t hopLimit = ipv6header.GetHopLimit ();
919  uint8_t segmentsLeft = routingHeader.GetSegmentsLeft ();
920  uint8_t length = (routingHeader.GetLength () >> 3) - 1;
921  uint8_t nbAddress = length / 2;
922  uint8_t nextAddressIndex;
923  Ipv6Address nextAddress;
924 
925  if (segmentsLeft == 0)
926  {
927  isDropped = false;
928  return routingHeader.GetSerializedSize ();
929  }
930 
931  if (length % 2 != 0)
932  {
933  NS_LOG_LOGIC ("Malformed header. Drop!");
934  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
935  m_dropTrace (packet);
936  isDropped = true;
937  return routingHeader.GetSerializedSize ();
938  }
939 
940  if (segmentsLeft > nbAddress)
941  {
942  NS_LOG_LOGIC ("Malformed header. Drop!");
943  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
944  m_dropTrace (packet);
945  isDropped = true;
946  return routingHeader.GetSerializedSize ();
947  }
948 
949  routingHeader.SetSegmentsLeft (segmentsLeft - 1);
950  nextAddressIndex = nbAddress - segmentsLeft;
951  nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
952 
953  if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
954  {
955  m_dropTrace (packet);
956  isDropped = true;
957  return routingHeader.GetSerializedSize ();
958  }
959 
960  routingHeader.SetRouterAddress (nextAddressIndex, destAddress);
961  ipv6header.SetDestinationAddress (nextAddress);
962 
963  if (hopLimit <= 1)
964  {
965  NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
966  icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
967  m_dropTrace (packet);
968  isDropped = true;
969  return routingHeader.GetSerializedSize ();
970  }
971 
972  routingHeader.SetLength (88);
973  ipv6header.SetHopLimit (hopLimit - 1);
974  p->AddHeader (routingHeader);
975 
976  /* short-circuiting routing stuff
977  *
978  * If we process this option,
979  * the packet was for us so we resend it to
980  * the new destination (modified in the header above).
981  */
982 
984  Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
986  NS_ASSERT (ipv6rp);
987 
988  Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
989 
990  if (rtentry)
991  {
992  /* we know a route exists so send packet now */
993  ipv6->SendRealOut (rtentry, p, ipv6header);
994  }
995  else
996  {
997  NS_LOG_INFO ("No route for next router");
998  }
999 
1000  /* as we directly send packet, mark it as dropped */
1001  isDropped = true;
1002 
1003  return routingHeader.GetSerializedSize ();
1004 }
1005 
1006 
1008 
1010 {
1011  static TypeId tid = TypeId ("ns3::Ipv6ExtensionESP")
1013  .AddConstructor<Ipv6ExtensionESP> ()
1014  ;
1015  return tid;
1016 }
1017 
1019 {
1021 }
1022 
1024 {
1026 }
1027 
1029 {
1031 
1032  return EXT_NUMBER;
1033 }
1034 
1035 uint8_t Ipv6ExtensionESP::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
1036 {
1037  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1038 
1041  return 0;
1042 }
1043 
1044 
1046 
1048 {
1049  static TypeId tid = TypeId ("ns3::Ipv6ExtensionAH")
1051  .AddConstructor<Ipv6ExtensionAH> ()
1052  ;
1053  return tid;
1054 }
1055 
1057 {
1059 }
1060 
1062 {
1064 }
1065 
1067 {
1069 
1070  return EXT_NUMBER;
1071 }
1072 
1073 uint8_t Ipv6ExtensionAH::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
1074 {
1075  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1076 
1079  return true;
1080 }
1081 
1082 } /* namespace ns3 */
1083 
void GetFragments(Ptr< Packet > packet, uint32_t fragmentSize, std::list< Ptr< Packet > > &listFragments)
Fragment a packet.
uint32_t RemoveHeader(Header &header)
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: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
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)
Ipv6ExtensionLooseRouting()
Constructor.
Packet header for IPv6.
Definition: ipv6-header.h:33
virtual void DoDispose()
Dispose this object.
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
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.
Demultiplexes IPv6 extensions.
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.
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:76
static TypeId GetTypeId()
Get the type identificator.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_INFO(msg)
Definition: log.h:264
static TypeId GetTypeId()
Get the type identificator.
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
virtual ~Ipv6ExtensionRoutingDemux()
Destructor.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
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
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 If you want to implement a new IPv6 routing extension, all you have to do is i...
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionHopByHop()
Destructor.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Definition: packet.cc:228
void AddAtEnd(Ptr< const Packet > packet)
Definition: packet.cc:317
void RemoveAtStart(uint32_t size)
Definition: packet.cc:353
void SetTimeoutEventId(EventId event)
Set the Timeout EventId.
Header of IPv6 Extension Routing : Type 0 (Loose Routing)
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.
NS_OBJECT_ENSURE_REGISTERED(AntennaModel)
IPv6 Extension ESP (Encapsulating Security Payload)
~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:334
Buffer::Iterator Begin(void) const
Definition: buffer.h:875
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
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.
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)
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.
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)
Definition: assert.h:86
Ipv6Extension()
Constructor.
IPv6 Extension Fragment.
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
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".
Header of IPv6 Extension Destination.
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 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.
void SetLength(uint16_t length)
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
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
IPv6 Option Demux.
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:360
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
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)
Definition: packet.cc:253
~Ipv6ExtensionAH()
Destructor.
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
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.
IPv6 Extension AH (Authentication Header)
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.