A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv6-extension.cc
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 
185 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionHopByHop);
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 
237 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionDestination);
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 
289 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionFragment);
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::make_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;
414  ipv6Header.SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
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;
441  hopbyhopHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
442  }
443 
444  unfragmentablePart.push_back (std::make_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;
465  routingHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
466  }
467 
468  unfragmentablePart.push_back (std::make_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;
485  destinationHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
486  }
487 
488  unfragmentablePart.push_back (std::make_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  {
533  fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first));
534  }
535  else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
536  {
537  fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first));
538  }
539  else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
540  {
541  fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first));
542  }
543  }
544 
545  ipv6Header.SetPayloadLength (fragment->GetSize ());
546  fragment->AddHeader (ipv6Header);
547 
548  std::ostringstream oss;
549  fragment->Print (oss);
550  listFragments.push_back (fragment);
551  }
552  while (moreFragment);
553 
554  for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
555  {
556  delete it->first;
557  }
558 
559  unfragmentablePart.clear ();
560 }
561 
562 
563 void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId,
564  Ipv6Header & ipHeader)
565 {
566  Ptr<Fragments> fragments;
567 
568  MapFragments_t::iterator it = m_fragments.find (fragmentsId);
569  NS_ASSERT_MSG(it != m_fragments.end (), "IPv6 Fragment timeout reached for non-existent fragment");
570  fragments = it->second;
571 
572  Ptr<Packet> packet = fragments->GetPartialPacket ();
573 
574  packet->AddHeader (ipHeader);
575 
576  // if we have at least 8 bytes, we can send an ICMP.
577  if ( packet->GetSize () > 8 )
578  {
580  icmp->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
581  }
582  m_dropTrace (packet);
583 
584  // clear the buffers
585  m_fragments.erase (fragmentsId);
586 }
587 
589  : m_moreFragment (0)
590 {
591 }
592 
594 {
595 }
596 
597 void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
598 {
599  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
600 
601  for (it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
602  {
603  if (it->second > fragmentOffset)
604  {
605  break;
606  }
607  }
608 
609  if (it == m_packetFragments.end ())
610  {
611  m_moreFragment = moreFragment;
612  }
613 
614  m_packetFragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
615 }
616 
618 {
619  m_unfragmentable = unfragmentablePart;
620 }
621 
623 {
624  bool ret = !m_moreFragment && m_packetFragments.size () > 0;
625 
626  if (ret)
627  {
628  uint16_t lastEndOffset = 0;
629 
630  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
631  {
632  if (lastEndOffset != it->second)
633  {
634  ret = false;
635  break;
636  }
637 
638  lastEndOffset += it->first->GetSize ();
639  }
640  }
641 
642  return ret;
643 }
644 
646 {
647  Ptr<Packet> p = m_unfragmentable->Copy ();
648 
649  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
650  {
651  p->AddAtEnd (it->first);
652  }
653 
654  return p;
655 }
656 
658 {
659  Ptr<Packet> p;
660 
661  if ( m_unfragmentable )
662  {
663  p = m_unfragmentable->Copy ();
664  }
665  else
666  {
667  return p;
668  }
669 
670  uint16_t lastEndOffset = 0;
671 
672  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
673  {
674  if (lastEndOffset != it->second)
675  {
676  break;
677  }
678  p->AddAtEnd (it->first);
679  lastEndOffset += it->first->GetSize ();
680  }
681 
682  return p;
683 }
684 
686 {
687  m_timeoutEventId = event;
688  return;
689 }
690 
692 {
693  m_timeoutEventId.Cancel ();
694  return;
695 }
696 
697 
698 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionRouting);
699 
701 {
702  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRouting")
704  .AddConstructor<Ipv6ExtensionRouting> ()
705  ;
706  return tid;
707 }
708 
710 {
712 }
713 
715 {
717 }
718 
720 {
722 
723  return EXT_NUMBER;
724 }
725 
727 {
729  return 0;
730 }
731 
732 uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
733 {
734  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
735 
736  // For ICMPv6 Error Packets
737  Ptr<Packet> malformedPacket = packet->Copy ();
738  malformedPacket->AddHeader (ipv6Header);
739 
740  Ptr<Packet> p = packet->Copy ();
741  p->RemoveAtStart (offset);
742 
743  uint8_t buf[4];
744  packet->CopyData (buf, sizeof(buf));
745 
746  uint8_t routingNextHeader = buf[0];
747  uint8_t routingLength = buf[1];
748  uint8_t routingTypeRouting = buf[2];
749  uint8_t routingSegmentsLeft = buf[3];
750 
751  if (nextHeader)
752  {
753  *nextHeader = routingNextHeader;
754  }
755 
756  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
757 
759  Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting);
760 
761  if (ipv6ExtensionRouting == 0)
762  {
763  if (routingSegmentsLeft == 0)
764  {
765  isDropped = false;
766  }
767  else
768  {
769  NS_LOG_LOGIC ("Malformed header. Drop!");
770 
771  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
772  m_dropTrace (packet);
773  isDropped = true;
774  }
775 
776  return routingLength;
777  }
778 
779  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped);
780 }
781 
782 
783 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionRoutingDemux);
784 
786 {
787  static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux")
788  .SetParent<Object> ()
789  .AddAttribute ("Routing Extensions", "The set of IPv6 Routing extensions registered with this demux.",
791  MakeObjectVectorAccessor (&Ipv6ExtensionRoutingDemux::m_extensionsRouting),
792  MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
793  ;
794  return tid;
795 }
796 
798 {
799 }
800 
802 {
803 }
804 
806 {
807  for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
808  {
809  (*it)->Dispose ();
810  *it = 0;
811  }
812  m_extensionsRouting.clear ();
813  m_node = 0;
815 }
816 
818 {
819  m_node = node;
820 }
821 
823 {
824  m_extensionsRouting.push_back (extensionRouting);
825 }
826 
828 {
829  for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
830  {
831  if ((*i)->GetTypeRouting () == typeRouting)
832  {
833  return *i;
834  }
835  }
836  return 0;
837 }
838 
840 {
841  m_extensionsRouting.remove (extensionRouting);
842 }
843 
844 
845 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionLooseRouting);
846 
848 {
849  static TypeId tid = TypeId ("ns3::Ipv6ExtensionLooseRouting")
851  .AddConstructor<Ipv6ExtensionLooseRouting> ()
852  ;
853  return tid;
854 }
855 
857 {
859 }
860 
862 {
864 }
865 
867 {
869 
870  return TYPE_ROUTING;
871 }
872 
873 uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
874 {
875  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
876 
877  // For ICMPv6 Error packets
878  Ptr<Packet> malformedPacket = packet->Copy ();
879  malformedPacket->AddHeader (ipv6Header);
880 
881  Ptr<Packet> p = packet->Copy ();
882  p->RemoveAtStart (offset);
883 
884  // Copy IPv6 Header : ipv6Header -> ipv6header
885  Buffer tmp;
886  tmp.AddAtStart (ipv6Header.GetSerializedSize ());
887  Buffer::Iterator it = tmp.Begin ();
888  Ipv6Header ipv6header;
889  ipv6Header.Serialize (it);
890  ipv6header.Deserialize (it);
891 
892  // Get the number of routers' address field
893  uint8_t buf[2];
894  p->CopyData (buf, sizeof(buf));
895  uint8_t numberAddress = buf[1] / 2;
896  Ipv6ExtensionLooseRoutingHeader routingHeader;
897  routingHeader.SetNumberAddress (numberAddress);
898  p->RemoveHeader (routingHeader);
899 
900  if (nextHeader)
901  {
902  *nextHeader = routingHeader.GetNextHeader ();
903  }
904 
905  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
906 
907  Ipv6Address srcAddress = ipv6header.GetSourceAddress ();
908  Ipv6Address destAddress = ipv6header.GetDestinationAddress ();
909  uint8_t hopLimit = ipv6header.GetHopLimit ();
910  uint8_t segmentsLeft = routingHeader.GetSegmentsLeft ();
911  uint8_t length = (routingHeader.GetLength () >> 3) - 1;
912  uint8_t nbAddress = length / 2;
913  uint8_t nextAddressIndex;
914  Ipv6Address nextAddress;
915 
916  if (segmentsLeft == 0)
917  {
918  isDropped = false;
919  return routingHeader.GetSerializedSize ();
920  }
921 
922  if (length % 2 != 0)
923  {
924  NS_LOG_LOGIC ("Malformed header. Drop!");
925  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
926  m_dropTrace (packet);
927  isDropped = true;
928  return routingHeader.GetSerializedSize ();
929  }
930 
931  if (segmentsLeft > nbAddress)
932  {
933  NS_LOG_LOGIC ("Malformed header. Drop!");
934  icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
935  m_dropTrace (packet);
936  isDropped = true;
937  return routingHeader.GetSerializedSize ();
938  }
939 
940  routingHeader.SetSegmentsLeft (segmentsLeft - 1);
941  nextAddressIndex = nbAddress - segmentsLeft;
942  nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
943 
944  if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
945  {
946  m_dropTrace (packet);
947  isDropped = true;
948  return routingHeader.GetSerializedSize ();
949  }
950 
951  routingHeader.SetRouterAddress (nextAddressIndex, destAddress);
952  ipv6header.SetDestinationAddress (nextAddress);
953 
954  if (hopLimit <= 1)
955  {
956  NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
957  icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
958  m_dropTrace (packet);
959  isDropped = true;
960  return routingHeader.GetSerializedSize ();
961  }
962 
963  routingHeader.SetLength (88);
964  ipv6header.SetHopLimit (hopLimit - 1);
965  p->AddHeader (routingHeader);
966 
967  /* short-circuiting routing stuff
968  *
969  * If we process this option,
970  * the packet was for us so we resend it to
971  * the new destination (modified in the header above).
972  */
973 
975  Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
976  Socket::SocketErrno err;
977  NS_ASSERT (ipv6rp);
978 
979  Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
980 
981  if (rtentry)
982  {
983  /* we know a route exists so send packet now */
984  ipv6->SendRealOut (rtentry, p, ipv6header);
985  }
986  else
987  {
988  NS_LOG_INFO ("No route for next router");
989  }
990 
991  /* as we directly send packet, mark it as dropped */
992  isDropped = true;
993 
994  return routingHeader.GetSerializedSize ();
995 }
996 
997 
998 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionESP);
999 
1001 {
1002  static TypeId tid = TypeId ("ns3::Ipv6ExtensionESP")
1004  .AddConstructor<Ipv6ExtensionESP> ()
1005  ;
1006  return tid;
1007 }
1008 
1010 {
1012 }
1013 
1015 {
1017 }
1018 
1020 {
1022 
1023  return EXT_NUMBER;
1024 }
1025 
1026 uint8_t Ipv6ExtensionESP::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
1027 {
1028  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1029 
1030  /* TODO */
1031 
1032  return 0;
1033 }
1034 
1035 
1036 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionAH);
1037 
1039 {
1040  static TypeId tid = TypeId ("ns3::Ipv6ExtensionAH")
1042  .AddConstructor<Ipv6ExtensionAH> ()
1043  ;
1044  return tid;
1045 }
1046 
1048 {
1050 }
1051 
1053 {
1055 }
1056 
1058 {
1060 
1061  return EXT_NUMBER;
1062 }
1063 
1064 uint8_t Ipv6ExtensionAH::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
1065 {
1066  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1067 
1068  /* TODO */
1069 
1070  return true;
1071 }
1072 
1073 } /* namespace ns3 */
1074 
void GetFragments(Ptr< Packet > packet, uint32_t fragmentSize, std::list< Ptr< Packet > > &listFragments)
Fragment a packet.
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
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
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.
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.
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual uint8_t GetExtensionNumber() const
Get the extension number.
uint32_t GetSize(void) const
Definition: packet.h:620
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:820
Ipv6ExtensionRoutingDemux()
Constructor.
void SetOffset(uint16_t offset)
Set the "Offset" field.
void Print(std::ostream &os) const
Definition: packet.cc:450
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:243
void AddAtEnd(Ptr< const Packet > packet)
Definition: packet.cc:334
void RemoveAtStart(uint32_t size)
Definition: packet.cc:370
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
Ptr< Packet > GetPacket() const
Get the entire packet.
IPv6 Extension ESP (Encapsulating Security Payload)
~Ipv6ExtensionFragment()
Destructor.
void CancelTimeout()
Cancel the timeout event.
An implementation of the ICMPv6 protocol.
~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.
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:131
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:363
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:44
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.
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
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:398
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:332
a unique identifier for an interface.
Definition: type-id.h:44
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:106
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
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:270
~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.