Bug 1843 - IPv6 extensions dropped packets do not fire L3 drop trace
authorTommaso Pecorella <tommaso.pecorella@unifi.it>
Mon, 17 Mar 2014 19:43:11 +0100
changeset 10669 46c9391bc38b
parent 10668 50137e334cf2
child 10670 d04c750525d7
Bug 1843 - IPv6 extensions dropped packets do not fire L3 drop trace
RELEASE_NOTES
src/internet/model/ipv6-extension.cc
src/internet/model/ipv6-extension.h
src/internet/model/ipv6-l3-protocol.cc
src/internet/model/ipv6-l3-protocol.h
--- a/RELEASE_NOTES	Mon Mar 17 19:34:43 2014 +0100
+++ b/RELEASE_NOTES	Mon Mar 17 19:43:11 2014 +0100
@@ -31,6 +31,8 @@
   define the minimum compressed packet size has been added. 
 - FlowMonitor "SerializeToXml" functions are now directly available 
   from the Helper.
+- Ipv6Extension::m_dropTrace has been removed. Ipv6L3Protocol::m_dropTrace 
+  is now fired when appropriate.
 
 Bugs fixed
 ----------
@@ -46,6 +48,7 @@
 - Bug 1838 - FlowMonitorHelper must not be copied.
 - Bug 1841 - FlowMonitor fails to install if IPv4 is not installed in the node
 - Bug 1842 - FlowMonitor SerializeToXml<Something> should be called by the helper
+- Bug 1843 - IPv6 extensions dropped packets do not fire L3 drop trace
 - Bug 1846 - IPv6 should send Destination Unreachable if no route is available
 - Bug 1852 - cairo-wideint-private.h error cannot find definitions for fixed-width integral types
 - Bug 1853 - NS_LOG_FUNCTION broken on OSX 10.9
--- a/src/internet/model/ipv6-extension.cc	Mon Mar 17 19:34:43 2014 +0100
+++ b/src/internet/model/ipv6-extension.cc	Mon Mar 17 19:43:11 2014 +0100
@@ -54,8 +54,6 @@
                    UintegerValue (0),
                    MakeUintegerAccessor (&Ipv6Extension::GetExtensionNumber),
                    MakeUintegerChecker<uint8_t> ())
-    .AddTraceSource ("Drop", "Drop IPv6 packet",
-                     MakeTraceSourceAccessor (&Ipv6Extension::m_dropTrace))
   ;
   return tid;
 }
@@ -86,7 +84,15 @@
   return m_node;
 }
 
-uint8_t Ipv6Extension::ProcessOptions (Ptr<Packet>& packet, uint8_t offset, uint8_t length, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6Extension::ProcessOptions (Ptr<Packet>& packet,
+                                       uint8_t offset,
+                                       uint8_t length,
+                                       Ipv6Header const& ipv6Header,
+                                       Ipv6Address dst,
+                                       uint8_t *nextHeader,
+                                       bool& stopProcessing,
+                                       bool& isDropped,
+                                       Ipv6L3Protocol::DropReason& dropReason)
 {
   NS_LOG_FUNCTION (this << packet << offset << length << ipv6Header << dst << nextHeader << isDropped);
 
@@ -125,17 +131,19 @@
 
             case 1:
               NS_LOG_LOGIC ("Unknown Option. Drop!");
-              m_dropTrace (packet);
               optionLength = 0;
               isDropped = true;
+              stopProcessing = true;
+              dropReason = Ipv6L3Protocol::DROP_UNKNOWN_OPTION;
               break;
 
             case 2:
               NS_LOG_LOGIC ("Unknown Option. Drop!");
               icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
-              m_dropTrace (packet);
               optionLength = 0;
               isDropped = true;
+              stopProcessing = true;
+              dropReason = Ipv6L3Protocol::DROP_UNKNOWN_OPTION;
               break;
 
             case 3:
@@ -144,15 +152,11 @@
               if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
                 {
                   icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
-                  m_dropTrace (packet);
-                  optionLength = 0;
-                  isDropped = true;
-                  break;
                 }
-
-              m_dropTrace (packet);
               optionLength = 0;
               isDropped = true;
+              stopProcessing = true;
+              dropReason = Ipv6L3Protocol::DROP_UNKNOWN_OPTION;
               break;
 
             default:
@@ -210,7 +214,14 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet,
+                                        uint8_t offset,
+                                        Ipv6Header const& ipv6Header,
+                                        Ipv6Address dst,
+                                        uint8_t *nextHeader,
+                                        bool& stopProcessing,
+                                        bool& isDropped,
+                                        Ipv6L3Protocol::DropReason& dropReason)
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
@@ -228,7 +239,7 @@
   offset += processedSize;
   uint8_t length = hopbyhopHeader.GetLength () - hopbyhopHeader.GetOptionsOffset ();
 
-  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
+  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, stopProcessing, isDropped, dropReason);
 
   return processedSize;
 }
@@ -262,7 +273,14 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet,
+                                           uint8_t offset,
+                                           Ipv6Header const& ipv6Header,
+                                           Ipv6Address dst,
+                                           uint8_t *nextHeader,
+                                           bool& stopProcessing,
+                                           bool& isDropped,
+                                           Ipv6L3Protocol::DropReason& dropReason)
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
@@ -280,7 +298,7 @@
   offset += processedSize;
   uint8_t length = destinationHeader.GetLength () - destinationHeader.GetOptionsOffset ();
 
-  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
+  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, stopProcessing, isDropped, dropReason);
 
   return processedSize;
 }
@@ -327,7 +345,14 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet,
+                                        uint8_t offset,
+                                        Ipv6Header const& ipv6Header,
+                                        Ipv6Address dst,
+                                        uint8_t *nextHeader,
+                                        bool& stopProcessing,
+                                        bool& isDropped,
+                                        Ipv6L3Protocol::DropReason& dropReason)
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
@@ -382,12 +407,11 @@
       packet = fragments->GetPacket ();
       fragments->CancelTimeout ();
       m_fragments.erase (fragmentsId);
-      isDropped = false;
+      stopProcessing = false;
     }
   else
     {
-      // the fragment is not "dropped", but Ipv6L3Protocol::LocalDeliver must stop processing it.
-      isDropped = true;
+      stopProcessing = true;
     }
 
   return 0;
@@ -569,7 +593,7 @@
 
 
 void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId,
-                                                    Ipv6Header & ipHeader)
+                                                    Ipv6Header ipHeader)
 {
   Ptr<Fragments> fragments;
 
@@ -579,15 +603,17 @@
 
   Ptr<Packet> packet = fragments->GetPartialPacket ();
 
-  packet->AddHeader (ipHeader);
-
   // if we have at least 8 bytes, we can send an ICMP.
   if ( packet->GetSize () > 8 )
     {
+      Ptr<Packet> p = packet->Copy ();
+      p->AddHeader (ipHeader);
       Ptr<Icmpv6L4Protocol> icmp = GetNode ()->GetObject<Icmpv6L4Protocol> ();
-      icmp->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
+      icmp->SendErrorTimeExceeded (p, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
     }
-  m_dropTrace (packet);
+
+  Ptr<Ipv6L3Protocol> ipL3 = GetNode ()->GetObject<Ipv6L3Protocol> ();
+  ipL3->ReportDrop (ipHeader, packet, Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT);
 
   // clear the buffers
   m_fragments.erase (fragmentsId);
@@ -737,7 +763,14 @@
   return 0;
 }
 
-uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet,
+                                       uint8_t offset,
+                                       Ipv6Header const& ipv6Header,
+                                       Ipv6Address dst,
+                                       uint8_t *nextHeader,
+                                       bool& stopProcessing,
+                                       bool& isDropped,
+                                       Ipv6L3Protocol::DropReason& dropReason)
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
@@ -777,14 +810,15 @@
           NS_LOG_LOGIC ("Malformed header. Drop!");
 
           icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
-          m_dropTrace (packet);
+          dropReason = Ipv6L3Protocol::DROP_MALFORMED_HEADER;
           isDropped = true;
+          stopProcessing = true;
         }
 
       return routingLength;
     }
 
-  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped);
+  return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, stopProcessing, isDropped, dropReason);
 }
 
 
@@ -878,7 +912,14 @@
   return TYPE_ROUTING;
 }
 
-uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet,
+                                            uint8_t offset,
+                                            Ipv6Header const& ipv6Header,
+                                            Ipv6Address dst,
+                                            uint8_t *nextHeader,
+                                            bool& stopProcessing,
+                                            bool& isDropped,
+                                            Ipv6L3Protocol::DropReason& dropReason)
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
@@ -931,8 +972,9 @@
     {
       NS_LOG_LOGIC ("Malformed header. Drop!");
       icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
-      m_dropTrace (packet);
+      dropReason = Ipv6L3Protocol::DROP_MALFORMED_HEADER;
       isDropped = true;
+      stopProcessing = true;
       return routingHeader.GetSerializedSize ();
     }
 
@@ -940,8 +982,9 @@
     {
       NS_LOG_LOGIC ("Malformed header. Drop!");
       icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
-      m_dropTrace (packet);
+      dropReason = Ipv6L3Protocol::DROP_MALFORMED_HEADER;
       isDropped = true;
+      stopProcessing = true;
       return routingHeader.GetSerializedSize ();
     }
 
@@ -951,8 +994,9 @@
 
   if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
     {
-      m_dropTrace (packet);
+      dropReason = Ipv6L3Protocol::DROP_MALFORMED_HEADER;
       isDropped = true;
+      stopProcessing = true;
       return routingHeader.GetSerializedSize ();
     }
 
@@ -963,8 +1007,9 @@
     {
       NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
       icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
-      m_dropTrace (packet);
+      dropReason = Ipv6L3Protocol::DROP_MALFORMED_HEADER;
       isDropped = true;
+      stopProcessing = true;
       return routingHeader.GetSerializedSize ();
     }
 
@@ -1031,7 +1076,14 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionESP::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionESP::Process (Ptr<Packet>& packet,
+                                   uint8_t offset,
+                                   Ipv6Header const& ipv6Header,
+                                   Ipv6Address dst,
+                                   uint8_t *nextHeader,
+                                   bool& stopProcessing,
+                                   bool& isDropped,
+                                   Ipv6L3Protocol::DropReason& dropReason)
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
@@ -1069,7 +1121,14 @@
   return EXT_NUMBER;
 }
 
-uint8_t Ipv6ExtensionAH::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
+uint8_t Ipv6ExtensionAH::Process (Ptr<Packet>& packet,
+                                  uint8_t offset,
+                                  Ipv6Header const& ipv6Header,
+                                  Ipv6Address dst,
+                                  uint8_t *nextHeader,
+                                  bool& stopProcessing,
+                                  bool& isDropped,
+                                  Ipv6L3Protocol::DropReason& dropReason)
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
--- a/src/internet/model/ipv6-extension.h	Mon Mar 17 19:34:43 2014 +0100
+++ b/src/internet/model/ipv6-extension.h	Mon Mar 17 19:43:11 2014 +0100
@@ -33,6 +33,7 @@
 #include "ns3/packet.h"
 #include "ns3/random-variable-stream.h"
 #include "ns3/ipv6-address.h"
+#include "ns3/ipv6-l3-protocol.h"
 #include "ns3/traced-callback.h"
 
 
@@ -90,10 +91,19 @@
    * \param ipv6Header the IPv6 header of packet received
    * \param dst destination address of the packet received (i.e. us)
    * \param nextHeader the next header
-   * \param isDropped if the packet must be dropped
+   * \param stopProcessing true if the packet must not be further processed
+   * \param isDropped true if the packet must be dropped
+   * \param dropReason dropping reason
    * \return the size processed
    */
-  virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, 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& stopProcessing,
+                           bool& isDropped,
+                           Ipv6L3Protocol::DropReason& dropReason) = 0;
 
   /**
    * \brief Process options
@@ -105,10 +115,21 @@
    * \param ipv6Header the IPv6 header of packet received
    * \param dst destination address of the packet received (i.e. us)
    * \param nextHeader the next header
-   * \param isDropped if the packet must be dropped
+   * \param stopProcessing true if the packet must not be further processed
+   * \param isDropped true if the packet must be dropped
+   * \param dropReason dropping reason
    * \return the size processed
    */
-  virtual uint8_t ProcessOptions (Ptr<Packet>& packet, uint8_t offset, uint8_t length, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+  virtual uint8_t ProcessOptions (Ptr<Packet>& packet,
+                                  uint8_t offset,
+                                  uint8_t length,
+                                  Ipv6Header const& ipv6Header,
+                                  Ipv6Address dst,
+                                  uint8_t *nextHeader,
+                                  bool& stopProcessing,
+                                  bool& isDropped,
+                                  Ipv6L3Protocol::DropReason& dropReason
+                                  );
 
  /**
   * Assign a fixed random variable stream number to the random variables
@@ -122,11 +143,6 @@
 
 protected:
   /**
-   * \brief Drop trace callback.
-   */
-  TracedCallback<Ptr<const Packet> > m_dropTrace;
-
-  /**
    * \brief Provides uniform random variables.
    */
   Ptr<UniformRandomVariable> m_uvar;
@@ -172,18 +188,14 @@
    */
   virtual uint8_t GetExtensionNumber () const;
 
-  /**
-   * \brief Process method
-   * Called from Ipv6L3Protocol::Receive.
-   * \param packet the packet
-   * \param offset the offset of the extension to process
-   * \param ipv6Header the IPv6 header of packet received
-   * \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, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+  virtual uint8_t Process (Ptr<Packet>& packet,
+                           uint8_t offset,
+                           Ipv6Header const& ipv6Header,
+                           Ipv6Address dst,
+                           uint8_t *nextHeader,
+                           bool& stopProcessing,
+                           bool& isDropped,
+                           Ipv6L3Protocol::DropReason& dropReason);
 };
 
 /**
@@ -220,18 +232,14 @@
    */
   virtual uint8_t GetExtensionNumber () const;
 
-  /**
-   * \brief Process method
-   * Called from Ipv6L3Protocol::Receive.
-   * \param packet the packet
-   * \param offset the offset of the extension to process
-   * \param ipv6Header the IPv6 header of packet received
-   * \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, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+  virtual uint8_t Process (Ptr<Packet>& packet,
+                           uint8_t offset,
+                           Ipv6Header const& ipv6Header,
+                           Ipv6Address dst,
+                           uint8_t *nextHeader,
+                           bool& stopProcessing,
+                           bool& isDropped,
+                           Ipv6L3Protocol::DropReason& dropReason);
 };
 
 /**
@@ -268,18 +276,14 @@
    */
   virtual uint8_t GetExtensionNumber () const;
 
-  /**
-   * \brief Process method
-   * Called from Ipv6L3Protocol::Receive.
-   * \param packet the packet
-   * \param offset the offset of the extension to process
-   * \param ipv6Header the IPv6 header of packet received
-   * \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, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+  virtual uint8_t Process (Ptr<Packet>& packet,
+                           uint8_t offset,
+                           Ipv6Header const& ipv6Header,
+                           Ipv6Address dst,
+                           uint8_t *nextHeader,
+                           bool& stopProcessing,
+                           bool& isDropped,
+                           Ipv6L3Protocol::DropReason& dropReason);
 
   /**
    * \brief Fragment a packet
@@ -382,7 +386,7 @@
    * \param key representing the packet fragments
    * \param ipHeader the IP header of the original packet
    */
-  void HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> key, Ipv6Header & ipHeader);
+  void HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> key, Ipv6Header ipHeader);
 
   /**
    * \brief Get the packet parts so far received.
@@ -453,19 +457,14 @@
    */
   virtual uint8_t GetTypeRouting () const;
 
-  /**
-   * \brief Process method
-   *
-   * Called from Ipv6L3Protocol::Receive.
-   * \param packet the packet
-   * \param offset the offset of the extension to process
-   * \param ipv6Header the IPv6 header of packet received
-   * \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, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+  virtual uint8_t Process (Ptr<Packet>& packet,
+                           uint8_t offset,
+                           Ipv6Header const& ipv6Header,
+                           Ipv6Address dst,
+                           uint8_t *nextHeader,
+                           bool& stopProcessing,
+                           bool& isDropped,
+                           Ipv6L3Protocol::DropReason& dropReason);
 };
 
 /**
@@ -573,20 +572,14 @@
    */
   virtual uint8_t GetTypeRouting () const;
 
-  /**
-   * \brief Process method
-   *
-   * Called from Ipv6L3Protocol::Receive.
-   *
-   * \param packet the packet
-   * \param offset the offset of the extension to process
-   * \param ipv6Header the IPv6 header of packet received
-   * \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, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+  virtual uint8_t Process (Ptr<Packet>& packet,
+                           uint8_t offset,
+                           Ipv6Header const& ipv6Header,
+                           Ipv6Address dst,
+                           uint8_t *nextHeader,
+                           bool& stopProcessing,
+                           bool& isDropped,
+                           Ipv6L3Protocol::DropReason& dropReason);
 };
 
 /**
@@ -623,19 +616,14 @@
    */
   virtual uint8_t GetExtensionNumber () const;
 
-  /**
-   * \brief Process method
-   * Called from Ipv6L3Protocol::Receive.
-   *
-   * \param packet the packet
-   * \param offset the offset of the extension to process
-   * \param ipv6Header the IPv6 header of packet received
-   * \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, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+  virtual uint8_t Process (Ptr<Packet>& packet,
+                           uint8_t offset,
+                           Ipv6Header const& ipv6Header,
+                           Ipv6Address dst,
+                           uint8_t *nextHeader,
+                           bool& stopProcessing,
+                           bool& isDropped,
+                           Ipv6L3Protocol::DropReason& dropReason);
 };
 
 /**
@@ -672,19 +660,14 @@
    */
   virtual uint8_t GetExtensionNumber () const;
 
-  /**
-   * \brief Process method
-   * Called from Ipv6L3Protocol::Receive.
-   *
-   * \param packet the packet
-   * \param offset the offset of the extension to process
-   * \param ipv6Header the IPv6 header of packet received
-   * \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, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+  virtual uint8_t Process (Ptr<Packet>& packet,
+                           uint8_t offset,
+                           Ipv6Header const& ipv6Header,
+                           Ipv6Address dst,
+                           uint8_t *nextHeader,
+                           bool& stopProcessing,
+                           bool& isDropped,
+                           Ipv6L3Protocol::DropReason& dropReason);
 };
 
 } /* namespace ns3 */
--- a/src/internet/model/ipv6-l3-protocol.cc	Mon Mar 17 19:34:43 2014 +0100
+++ b/src/internet/model/ipv6-l3-protocol.cc	Mon Mar 17 19:43:11 2014 +0100
@@ -882,7 +882,9 @@
   Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
   Ptr<Ipv6Extension> ipv6Extension = 0;
   uint8_t nextHeader = hdr.GetNextHeader ();
+  bool stopProcessing = false;
   bool isDropped = false;
+  DropReason dropReason;
 
   if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
     {
@@ -890,11 +892,16 @@
 
       if (ipv6Extension)
         {
-          ipv6Extension->Process (packet, 0, hdr, hdr.GetDestinationAddress (), (uint8_t *)0, isDropped);
+          ipv6Extension->Process (packet, 0, hdr, hdr.GetDestinationAddress (), (uint8_t *)0, stopProcessing, isDropped, dropReason);
         }
 
       if (isDropped)
         {
+          m_dropTrace (hdr, packet, dropReason, m_node->GetObject<Ipv6> (), interface);
+        }
+
+      if (stopProcessing)
+        {
           return;
         }
     }
@@ -1161,6 +1168,8 @@
   uint8_t nextHeader = ip.GetNextHeader ();
   uint8_t nextHeaderPosition = 0;
   bool isDropped = false;
+  bool stopProcessing = false;
+  DropReason dropReason;
 
   // check for a malformed hop-by-hop extension
   // this is a common case when forging IPv6 raw packets
@@ -1185,11 +1194,16 @@
         {
           uint8_t nextHeaderStep = 0;
           uint8_t curHeader = nextHeader;
-          nextHeaderStep = ipv6Extension->Process (p, nextHeaderPosition, ip, dst, &nextHeader, isDropped);
+          nextHeaderStep = ipv6Extension->Process (p, nextHeaderPosition, ip, dst, &nextHeader, stopProcessing, isDropped, dropReason);
           nextHeaderPosition += nextHeaderStep;
 
           if (isDropped)
             {
+              m_dropTrace (ip, packet, dropReason, m_node->GetObject<Ipv6> (), iif);
+            }
+
+          if (stopProcessing)
+            {
               return;
             }
           NS_ASSERT_MSG (nextHeaderStep != 0 || curHeader == Ipv6Header::IPV6_EXT_FRAGMENTATION,
@@ -1326,5 +1340,10 @@
   m_node->AggregateObject (ipv6OptionDemux);
 }
 
+void Ipv6L3Protocol::ReportDrop (Ipv6Header ipHeader, Ptr<Packet> p, DropReason dropReason)
+{
+  m_dropTrace (ipHeader, p, dropReason, m_node->GetObject<Ipv6> (), 0);
+}
+
 } /* namespace ns3 */
 
--- a/src/internet/model/ipv6-l3-protocol.h	Mon Mar 17 19:34:43 2014 +0100
+++ b/src/internet/model/ipv6-l3-protocol.h	Mon Mar 17 19:43:11 2014 +0100
@@ -83,6 +83,9 @@
     DROP_INTERFACE_DOWN, /**< Interface is down so can not send packet */
     DROP_ROUTE_ERROR, /**< Route error */
     DROP_UNKNOWN_PROTOCOL, /**< Unknown L4 protocol */
+    DROP_UNKNOWN_OPTION, /**< Unknown option */
+    DROP_MALFORMED_HEADER, /**< Malformed header */
+    DROP_FRAGMENT_TIMEOUT, /**< Fragment timeout */
   };
 
   /**
@@ -371,6 +374,18 @@
    */
   virtual void RegisterOptions ();
 
+  /**
+   * \brief Report a packet drop
+   *
+   * This function is used by Fragment Timeout handling to signal a fragment drop.
+   *
+   * \param ipv6Header the IPv6 header of dropped packet
+   * \param p the packet (if available)
+   * \param dropReason the drop reason
+   *
+   */
+  virtual void ReportDrop (Ipv6Header ipHeader, Ptr<Packet> p, DropReason dropReason);
+
 protected:
   /**
    * \brief Dispose object.