More on IPv6 extensions support.
authorSebastien Vincent <vincent@clarinet.u-strasbg.fr>
Fri, 16 Oct 2009 11:33:56 +0200
changeset 5784 512909f442f7
parent 5783 66c507d12317
child 5785 5d433b13a9c1
More on IPv6 extensions support.
src/helper/internet-stack-helper.cc
src/internet-stack/ipv6-extension.cc
src/internet-stack/ipv6-extension.h
src/internet-stack/ipv6-l3-protocol.cc
src/internet-stack/ipv6-l3-protocol.h
src/internet-stack/ipv6-option.cc
src/internet-stack/ipv6-option.h
src/node/ipv6.h
--- a/src/helper/internet-stack-helper.cc	Fri Oct 16 10:25:12 2009 +0200
+++ b/src/helper/internet-stack-helper.cc	Fri Oct 16 11:33:56 2009 +0200
@@ -360,6 +360,10 @@
       Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
       Ptr<Ipv6RoutingProtocol> ipv6Routing = m_routingv6->Create (node);
       ipv6->SetRoutingProtocol (ipv6Routing);
+
+      /* register IPv6 extensions and options */
+      ipv6->RegisterExtensions ();
+      ipv6->RegisterOptions ();
     }
 }
 
--- a/src/internet-stack/ipv6-extension.cc	Fri Oct 16 10:25:12 2009 +0200
+++ b/src/internet-stack/ipv6-extension.cc	Fri Oct 16 11:33:56 2009 +0200
@@ -109,9 +109,9 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << nextHeader << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
   // For ICMPv6 Error packets
   Ptr<Packet> malformedPacket = packet->Copy();
@@ -163,7 +163,7 @@
         case 2:
           NS_LOG_LOGIC ("Unknown Option. Drop!");
           /* TODO */
-          /* icmpv6->SendErrorParameterError (malformedPacket, ipv6Interface->GetAddress(), ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */
+          /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */
           m_dropTrace (packet);
           optionLength = 0;
           isDropped = true;
@@ -175,7 +175,7 @@
           if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
           {
             /* TODO */
-            /* icmpv6->SendErrorParameterError (malformedPacket, ipv6Interface->GetAddress(), ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */
+            /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */
           }
 
           m_dropTrace (packet);
@@ -190,7 +190,7 @@
 
     else 
     {
-      optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, ipv6Interface, isDropped);
+      optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
     }
 
     processedSize += optionLength;
@@ -231,9 +231,9 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << nextHeader << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
   // For ICMPv6 Error packets
   Ptr<Packet> malformedPacket = packet->Copy();
@@ -285,7 +285,7 @@
         case 2:
           NS_LOG_LOGIC ("Unknown Option. Drop!");
           /* TODO */
-          /* icmpv6->SendErrorParameterError (malformedPacket, ipv6Interface->GetAddress(), ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */
+          /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */
           m_dropTrace (packet);
           optionLength = 0;
           isDropped = true;
@@ -297,7 +297,7 @@
           if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
           {
             /* TODO */
-            /* icmpv6->SendErrorParameterError (malformedPacket, ipv6Interface->GetAddress(), ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */
+            /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */
           }
 
           m_dropTrace (packet);
@@ -312,7 +312,7 @@
 
     else 
     {
-      optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, ipv6Interface, isDropped);
+      optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
     }
 
     processedSize += optionLength;
@@ -366,9 +366,9 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << nextHeader << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
   Ptr<Packet> p = packet->Copy ();
   p->RemoveAtStart (offset);
@@ -709,9 +709,9 @@
   return 0;
 }
 
-uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << nextHeader << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
   // For ICMPv6 Error Packets
   Ptr<Packet> malformedPacket = packet->Copy();
@@ -749,7 +749,7 @@
       NS_LOG_LOGIC("Malformed header. Drop!");
 
       /* TODO */
-      /* icmpv6->SendErrorParameterError (malformedPacket, ipv6Interface->GetAddress(), ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1); */
+      /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1); */
       m_dropTrace (packet);
       isDropped = true;
     }
@@ -757,7 +757,7 @@
     return routingLength;
   }
 
-  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, ipv6Interface, (uint8_t *)0, isDropped);
+  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped);
 }
 
 
@@ -853,9 +853,9 @@
   return TYPE_ROUTING;
 }
 
-uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << nextHeader << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
   // For ICMPv6 Error packets
   Ptr<Packet> malformedPacket = packet->Copy ();
@@ -905,7 +905,7 @@
   {
     NS_LOG_LOGIC("Malformed header. Drop!");
     /* TODO */
-    /* icmpv6->SendErrorParameterError (malformedPacket, ipv6Interface->GetAddress(), srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1); */
+    /* icmpv6->SendErrorParameterError (malformedPacket, dst, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1); */
     m_dropTrace (packet);
     isDropped = true;
     return routingHeader.GetSerializedSize ();
@@ -915,7 +915,7 @@
   {
     NS_LOG_LOGIC("Malformed header. Drop!");
     /* TODO */
-    /* icmpv6->SendErrorParameterError (malformedPacket, ipv6Interface->GetAddress(), srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3); */
+    /* icmpv6->SendErrorParameterError (malformedPacket, dst, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3); */
     m_dropTrace (packet);
     isDropped = true;
     return routingHeader.GetSerializedSize ();
@@ -939,7 +939,7 @@
   {
     NS_LOG_LOGIC("Time Exceeded : Hop Limit <= 1. Drop!");
     /* TODO */
-    /* icmpv6->SendErrorTimeExceeded (malformedPacket, ipv6Interface->GetAddress(), srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT); */
+    /* icmpv6->SendErrorTimeExceeded (malformedPacket, dst, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT); */
     m_dropTrace (packet);
     isDropped = true;
     return routingHeader.GetSerializedSize ();
@@ -994,9 +994,9 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionESP::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionESP::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << nextHeader << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
   /* TODO */
 
@@ -1034,9 +1034,9 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionAH::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionAH::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << nextHeader << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
   /* TODO */
 
--- a/src/internet-stack/ipv6-extension.h	Fri Oct 16 10:25:12 2009 +0200
+++ b/src/internet-stack/ipv6-extension.h	Fri Oct 16 11:33:56 2009 +0200
@@ -83,12 +83,12 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
+     * \param dst destination address of the packet received (i.e. us)
      * \param nextHeader the next header
      * \param isDropped if the packet must be dropped
      * \return the size processed
      */
-    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped) = 0;
+    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) = 0;
 
   protected:
     TracedCallback<Ptr<const Packet> > m_dropTrace;
@@ -137,12 +137,12 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
+     * \param dst destination address of the packet received (i.e. us)
      * \param nextHeader the next header
      * \param isDropped if the packet must be dropped
      * \return the size processed
      */
-    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
 };
 
 /**
@@ -182,12 +182,12 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
+     * \param dst destination address of the packet received (i.e. us)
      * \param nextHeader the next header
      * \param isDropped if the packet must be dropped
      * \return the size processed
      */
-    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
 };
 
 /**
@@ -227,12 +227,12 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
+     * \param dst destination address of the packet received (i.e. us)
      * \param nextHeader the next header
      * \param isDropped if the packet must be dropped
      * \return the size processed
      */
-    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
 
     /**
      * \brief Fragment a packet
@@ -371,12 +371,12 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
+     * \param dst destination address of the packet received (i.e. us)
      * \param nextHeader the next header
      * \param isDropped if the packet must be dropped
      * \return the size processed
      */
-    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
 };
 
 /**
@@ -485,12 +485,12 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
+     * \param dst destination address of the packet received (i.e. us)
      * \param nextHeader the next header
      * \param isDropped if the packet must be dropped
      * \return the size processed
      */
-    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
 };
 
 /**
@@ -531,12 +531,12 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
+     * \param dst destination address of the packet received (i.e. us)
      * \param nextHeader the next header
      * \param isDropped if the packet must be dropped
      * \return the size processed
      */
-    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
 };
 
 /**
@@ -577,12 +577,12 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
+     * \param dst destination address of the packet received (i.e. us)
      * \param nextHeader the next header
      * \param isDropped if the packet must be dropped
      * \return the size processed
      */
-    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, uint8_t *nextHeader, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
 };
 
 } /* namespace ns3 */
--- a/src/internet-stack/ipv6-l3-protocol.cc	Fri Oct 16 10:25:12 2009 +0200
+++ b/src/internet-stack/ipv6-l3-protocol.cc	Fri Oct 16 11:33:56 2009 +0200
@@ -34,6 +34,11 @@
 #include "ipv6-interface.h"
 #include "ipv6-raw-socket-impl.h"
 #include "ipv6-autoconfigured-prefix.h"
+#include "ipv6-extension-demux.h"
+#include "ipv6-extension.h"
+#include "ipv6-extension-header.h"
+#include "ipv6-option-demux.h"
+#include "ipv6-option.h"
 #include "icmpv6-l4-protocol.h"
 #include "ndisc-cache.h"
 
@@ -692,6 +697,26 @@
     socket->ForwardUp (packet, hdr, device);
   }
 
+  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
+  Ptr<Ipv6Extension> ipv6Extension = 0;
+  uint8_t nextHeader = hdr.GetNextHeader ();
+  bool isDropped = false;
+
+  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
+  {
+    ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
+
+    if (ipv6Extension)
+    {
+      ipv6Extension->Process (packet, 0, hdr, hdr.GetDestinationAddress (), (uint8_t *)0, isDropped);
+    }
+
+    if (isDropped)
+    {
+      return;
+    }
+  }
+
   m_routingProtocol->RouteInput (packet, hdr, device,
     MakeCallback (&Ipv6L3Protocol::IpForward, this),
     MakeCallback (&Ipv6L3Protocol::IpMulticastForward, this),
@@ -717,15 +742,47 @@
   Ptr<Ipv6Interface> outInterface = GetInterface (interface);
   NS_LOG_LOGIC ("Send via NetDevice ifIndex " << dev->GetIfIndex () << " Ipv6InterfaceIndex " << interface);
 
+  // Check packet size
+  std::list<Ptr<Packet> > fragments;
+
+  if (packet->GetSize () > (size_t)(dev->GetMtu () + 40)) /* 40 => size of IPv6 header */
+  {
+    // Router => drop
+    if (m_ipForward)
+    {
+      return;
+    }
+
+    Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
+
+    // To get specific method GetFragments from Ipv6ExtensionFragmentation
+    Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *>(PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
+    ipv6Fragment->GetFragments (packet, outInterface->GetDevice ()->GetMtu (), fragments);
+  }
+
   if (!route->GetGateway ().IsEqual (Ipv6Address::GetAny ()))
   {
     if (outInterface->IsUp ())
     {
       NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
       packet->AddHeader (ipHeader);
-      NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ());
-      m_txTrace (packet, interface);
-      outInterface->Send (packet, route->GetGateway ());
+
+      if (fragments.size () != 0)
+      {
+        std::ostringstream oss;
+
+        for (std::list<Ptr<Packet> >::const_iterator it = fragments.begin (); it != fragments.end (); it++)
+        {
+          m_txTrace (*it, interface);
+          outInterface->Send (*it, route->GetGateway ());
+        }
+      }
+      else
+      {
+        /* NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ()); */
+        m_txTrace (packet, interface);
+        outInterface->Send (packet, route->GetGateway ());
+      }
     }
     else
     {
@@ -739,9 +796,23 @@
     {
        NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestinationAddress ());
        packet->AddHeader (ipHeader);
-       NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ());
-       m_txTrace (packet, interface);
-       outInterface->Send (packet, ipHeader.GetDestinationAddress ());
+
+      if (fragments.size () != 0)
+      {
+        std::ostringstream oss;
+
+        for (std::list<Ptr<Packet> >::const_iterator it = fragments.begin (); it != fragments.end (); it++)
+        {
+          m_txTrace (*it, interface);
+          outInterface->Send (*it, ipHeader.GetDestinationAddress ());
+        }
+      }
+      else
+      {
+        /* NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ()); */
+        m_txTrace (packet, interface);
+        outInterface->Send (packet, ipHeader.GetDestinationAddress ());
+      }
     }
     else
     {
@@ -855,8 +926,89 @@
 {
   NS_LOG_FUNCTION (this << packet << ip << iif);
   Ptr<Packet> p = packet->Copy ();
-  Ptr<Ipv6L4Protocol> protocol = GetProtocol (ip.GetNextHeader ());
+  Ptr<Ipv6L4Protocol> protocol = 0; 
+/*GetProtocol (ip.GetNextHeader ());*/
+
+  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
+  Ptr<Ipv6Extension> ipv6Extension = 0;
+
+  Ipv6Address src = ip.GetSourceAddress ();
+  Ipv6Address dst = ip.GetDestinationAddress ();
+  uint8_t nextHeader = ip.GetNextHeader ();
+  uint8_t nextHeaderPosition = 0;
+  bool isDropped = false;
+
+  if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
+  {
+    const uint8_t *buff = p->PeekData ();
+
+    nextHeader = *buff;
+    nextHeaderPosition = *(buff + 1);
+  }
+
+  do {
+    ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
+
+    if (ipv6Extension)
+    {
+      nextHeaderPosition += ipv6Extension->Process (p, nextHeaderPosition, ip, dst, &nextHeader, isDropped);
+
+      if (isDropped)
+      {
+        return;
+      }
+    }
+    else
+    {
+      protocol = GetProtocol (nextHeader);
+
+      if (!protocol)
+      {
+        NS_LOG_LOGIC ("Unknown Next Header. Drop!");
 
+        if (nextHeaderPosition == 0)
+        {
+          /* TODO */
+          /* GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, src, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, 40); */
+        }
+        else
+        {
+          /* TODO */
+          /* GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, src, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, ip.GetSerializedSize () + nextHeaderPosition); */
+        }
+        m_dropTrace (ip, p, DROP_UNKNOWN_PROTOCOL, iif);
+        break;
+      }
+      else
+      {
+        p->RemoveAtStart (nextHeaderPosition);
+        /* protocol->Receive (p, src, dst, incomingInterface); */
+        
+        /* L4 protocol */
+        Ptr<Packet> copy = p->Copy ();
+        enum Ipv6L4Protocol::RxStatus_e status = protocol->Receive (p, ip.GetSourceAddress (), ip.GetDestinationAddress (), GetInterface (iif));
+
+        switch (status)
+        {
+        case Ipv6L4Protocol::RX_OK:
+          break;
+        case Ipv6L4Protocol::RX_CSUM_FAILED:
+          break;
+        case Ipv6L4Protocol::RX_ENDPOINT_UNREACH:
+          if (ip.GetDestinationAddress ().IsMulticast ())
+          {
+            /* do not rely on multicast address */
+            break;
+          }
+
+          copy->AddHeader (ip);
+          GetIcmpv6 ()->SendErrorDestinationUnreachable (copy, ip.GetSourceAddress (), Icmpv6Header::ICMPV6_PORT_UNREACHABLE);
+        }
+      }
+    }
+  } while (ipv6Extension);
+
+#if 0
   if (protocol)
   {
     Ptr<Packet> copy = p->Copy ();
@@ -879,6 +1031,7 @@
       GetIcmpv6 ()->SendErrorDestinationUnreachable (copy, ip.GetSourceAddress (), Icmpv6Header::ICMPV6_PORT_UNREACHABLE);
     }
   }
+#endif
 }
 
 void Ipv6L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv6Header& ipHeader, Socket::SocketErrno sockErrno)
@@ -901,5 +1054,60 @@
   return hdr;
 }
 
+void Ipv6L3Protocol::RegisterExtensions ()
+{
+  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = CreateObject<Ipv6ExtensionDemux> ();
+  ipv6ExtensionDemux->SetNode (m_node);
+
+  Ptr<Ipv6ExtensionHopByHop> hopbyhopExtension = CreateObject<Ipv6ExtensionHopByHop> ();
+  hopbyhopExtension->SetNode (m_node);
+  Ptr<Ipv6ExtensionDestination> destinationExtension = CreateObject<Ipv6ExtensionDestination> ();
+  destinationExtension->SetNode (m_node);
+  Ptr<Ipv6ExtensionFragment> fragmentExtension = CreateObject<Ipv6ExtensionFragment> ();
+  fragmentExtension->SetNode (m_node);
+  Ptr<Ipv6ExtensionRouting> routingExtension = CreateObject<Ipv6ExtensionRouting> ();
+  routingExtension->SetNode (m_node);
+  // Ptr<Ipv6ExtensionESP> espExtension = CreateObject<Ipv6ExtensionESP> ();
+  // Ptr<Ipv6ExtensionAH> ahExtension = CreateObject<Ipv6ExtensionAH> ();
+
+  ipv6ExtensionDemux->Insert (hopbyhopExtension);
+  ipv6ExtensionDemux->Insert (destinationExtension);
+  ipv6ExtensionDemux->Insert (fragmentExtension);
+  ipv6ExtensionDemux->Insert (routingExtension);
+  // ipv6ExtensionDemux->Insert (espExtension);
+  // ipv6ExtensionDemux->Insert (ahExtension);
+
+  Ptr<Ipv6ExtensionRoutingDemux> routingExtensionDemux = CreateObject<Ipv6ExtensionRoutingDemux> ();
+  routingExtensionDemux->SetNode (m_node);
+  Ptr<Ipv6ExtensionLooseRouting> looseRoutingExtension = CreateObject<Ipv6ExtensionLooseRouting> ();
+  looseRoutingExtension->SetNode (m_node);
+  routingExtensionDemux->Insert (looseRoutingExtension);
+
+  m_node->AggregateObject (routingExtensionDemux);
+  m_node->AggregateObject (ipv6ExtensionDemux);
+}
+
+void Ipv6L3Protocol::RegisterOptions ()
+{
+  Ptr<Ipv6OptionDemux> ipv6OptionDemux = CreateObject<Ipv6OptionDemux> ();
+  ipv6OptionDemux->SetNode (m_node);
+
+  Ptr<Ipv6OptionPad1> pad1Option = CreateObject<Ipv6OptionPad1> ();
+  pad1Option->SetNode (m_node);
+  Ptr<Ipv6OptionPadn> padnOption = CreateObject<Ipv6OptionPadn> ();
+  padnOption->SetNode (m_node);
+  Ptr<Ipv6OptionJumbogram> jumbogramOption = CreateObject<Ipv6OptionJumbogram> ();
+  jumbogramOption->SetNode (m_node);
+  Ptr<Ipv6OptionRouterAlert> routerAlertOption = CreateObject<Ipv6OptionRouterAlert> ();
+  routerAlertOption->SetNode (m_node);
+
+  ipv6OptionDemux->Insert (pad1Option);
+  ipv6OptionDemux->Insert (padnOption);
+  ipv6OptionDemux->Insert (jumbogramOption);
+  ipv6OptionDemux->Insert (routerAlertOption);
+
+  m_node->AggregateObject (ipv6OptionDemux);
+}
+
 } /* namespace ns3 */
 
--- a/src/internet-stack/ipv6-l3-protocol.h	Fri Oct 16 10:25:12 2009 +0200
+++ b/src/internet-stack/ipv6-l3-protocol.h	Fri Oct 16 11:33:56 2009 +0200
@@ -79,6 +79,7 @@
         DROP_NO_ROUTE, /**< No route to host */
         DROP_INTERFACE_DOWN, /**< Interface is down so can not send packet */
         DROP_ROUTE_ERROR, /**< Route error */
+        DROP_UNKNOWN_PROTOCOL, /**< Unkown L4 protocol */
       };
     
     /**
@@ -329,6 +330,16 @@
      */
     void RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, Ipv6Address defaultRouter);
 
+    /**
+     * \brief Register the IPv6 Extensions.
+     */
+    virtual void RegisterExtensions ();
+
+    /**
+     * \brief Register the IPv6 Options.
+     */
+    virtual void RegisterOptions ();
+
   protected:
     /**
      * \brief Dispose object.
--- a/src/internet-stack/ipv6-option.cc	Fri Oct 16 10:25:12 2009 +0200
+++ b/src/internet-stack/ipv6-option.cc	Fri Oct 16 11:33:56 2009 +0200
@@ -85,9 +85,9 @@
   return OPT_NUMBER;
 }
 
-uint8_t Ipv6OptionPad1::Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped)
+uint8_t Ipv6OptionPad1::Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << isDropped);
 
   Ptr<Packet> p = packet->Copy ();
   p->RemoveAtStart (offset);
@@ -131,9 +131,9 @@
   return OPT_NUMBER;
 }
 
-uint8_t Ipv6OptionPadn::Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped)
+uint8_t Ipv6OptionPadn::Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << isDropped);
 
   Ptr<Packet> p = packet->Copy ();
   p->RemoveAtStart (offset);
@@ -177,9 +177,9 @@
   return OPT_NUMBER;
 }
 
-uint8_t Ipv6OptionJumbogram::Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped)
+uint8_t Ipv6OptionJumbogram::Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << isDropped);
 
   Ptr<Packet> p = packet->Copy ();
   p->RemoveAtStart (offset);
@@ -223,9 +223,9 @@
   return OPT_NUMBER;
 }
 
-uint8_t Ipv6OptionRouterAlert::Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped)
+uint8_t Ipv6OptionRouterAlert::Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped)
 {
-  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << ipv6Interface << isDropped);
+  NS_LOG_FUNCTION (this << packet << offset << ipv6Header << isDropped);
 
   Ptr<Packet> p = packet->Copy ();
   p->RemoveAtStart (offset);
--- a/src/internet-stack/ipv6-option.h	Fri Oct 16 10:25:12 2009 +0200
+++ b/src/internet-stack/ipv6-option.h	Fri Oct 16 11:33:56 2009 +0200
@@ -73,11 +73,10 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
      * \param isDropped if the packet must be dropped
      * \return the processed size
      */
-    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped) = 0;
+    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped) = 0;
 
   private:
     /**
@@ -123,11 +122,10 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
      * \param isDropped if the packet must be dropped
      * \return the processed size
      */
-    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped);
 };
 
 /**
@@ -167,11 +165,10 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
      * \param isDropped if the packet must be dropped
      * \return the processed size
      */
-    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped);
 };
 
 /**
@@ -211,11 +208,10 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
      * \param isDropped if the packet must be dropped
      * \return the processed size
      */
-    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped);
 
   private:
     /**
@@ -261,11 +257,10 @@
      * \param packet the packet
      * \param offset the offset of the extension to process
      * \param ipv6Header the IPv6 header of packet received
-     * \param ipv6Interface the Ipv6Interface on which the packet arrived
      * \param isDropped if the packet must be dropped
      * \return the processed size
      */
-    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, Ptr<Ipv6Interface> ipv6Interface, bool& isDropped);
+    virtual uint8_t Process (Ptr<Packet> packet, uint8_t offset, Ipv6Header const& ipv6Header, bool& isDropped);
 };
 
 } /* namespace ns3 */
--- a/src/node/ipv6.h	Fri Oct 16 10:25:12 2009 +0200
+++ b/src/node/ipv6.h	Fri Oct 16 11:33:56 2009 +0200
@@ -284,6 +284,16 @@
   virtual void SetForwarding (uint32_t interface, bool val) = 0;
 
   /**
+   * \brief Register the IPv6 Extensions.
+   */
+  virtual void RegisterExtensions () = 0;
+
+  /**
+   * \brief Register the IPv6 Options.
+   */
+  virtual void RegisterOptions () = 0;
+
+  /**
    * \brief Any interface magic number.
    */
   static const uint32_t IF_ANY = 0xffffffff;