Merge with Fabian's repository.
authorSebastien Vincent <vincent@clarinet.u-strasbg.fr>
Wed, 11 Nov 2009 16:25:10 +0100
changeset 5802 e93f45bb4bdf
parent 5800 082bd197b99a (current diff)
parent 5801 86b47c42316c (diff)
child 5803 56b5e7ff673a
Merge with Fabian's repository.
src/internet-stack/ipv6-extension-header.cc
src/internet-stack/ipv6-extension-header.h
src/internet-stack/ipv6-extension.cc
src/internet-stack/ipv6-extension.h
src/internet-stack/ipv6-option-header.cc
src/internet-stack/ipv6-option-header.h
--- a/src/internet-stack/ipv6-extension-header.cc	Wed Nov 04 14:42:58 2009 +0100
+++ b/src/internet-stack/ipv6-extension-header.cc	Wed Nov 11 16:25:10 2009 +0100
@@ -120,6 +120,83 @@
   return GetSerializedSize ();
 }
 
+OptionField::OptionField (uint32_t optionsOffset)
+  : m_optionData (0),
+  m_optionsOffset (optionsOffset)
+{
+}
+
+OptionField::~OptionField ()
+{
+}
+
+uint32_t OptionField::GetSerializedSize () const
+{
+  return m_optionData.GetSize () + CalculatePad ((Ipv6OptionHeader::Alignment) {8,0});
+}
+
+void OptionField::Serialize (Buffer::Iterator start) const
+{
+  start.Write (m_optionData.Begin (), m_optionData.End ());
+  uint32_t fill = CalculatePad ((Ipv6OptionHeader::Alignment) {8,0});
+  NS_LOG_LOGIC ("fill with " << fill << " bytes padding");
+  switch (fill)
+  {
+    case 0: return;
+    case 1: Ipv6OptionPad1Header ().Serialize (start);
+            return;
+    default: Ipv6OptionPadnHeader (fill).Serialize (start);
+             return;
+  }
+}
+
+uint32_t OptionField::Deserialize (Buffer::Iterator start, uint32_t length)
+{
+  uint8_t buf[length];
+  start.Read (buf,length);
+  m_optionData = Buffer ();
+  m_optionData.AddAtEnd (length);
+  m_optionData.Begin ().Write (buf,length);
+  return length;
+}
+
+void OptionField::AddOption (Ipv6OptionHeader const& option)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  uint32_t pad = CalculatePad (option.GetAlignment ());
+  NS_LOG_LOGIC ("need " << pad << " bytes padding");
+  switch (pad)
+  {
+    case 0: break; //no padding needed
+    case 1: AddOption (Ipv6OptionPad1Header ());
+      break;
+    default: AddOption (Ipv6OptionPadnHeader (pad));
+      break;
+  }
+
+  m_optionData.AddAtEnd (option.GetSerializedSize ());
+  Buffer::Iterator it = m_optionData.End ();
+  it.Prev (option.GetSerializedSize ());
+  option.Serialize (it);
+}
+
+uint32_t OptionField::CalculatePad (Ipv6OptionHeader::Alignment alignment) const
+{
+  return (alignment.offset - (m_optionData.GetSize () + m_optionsOffset)) % alignment.factor;
+}
+
+uint32_t OptionField::GetOptionsOffset ()
+{
+  return m_optionsOffset;
+}
+
+Buffer OptionField::GetOptionBuffer ()
+{
+  return m_optionData;
+}
+
+
 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionHopByHopHeader);
 
 TypeId Ipv6ExtensionHopByHopHeader::GetTypeId ()
@@ -137,6 +214,7 @@
 }
 
 Ipv6ExtensionHopByHopHeader::Ipv6ExtensionHopByHopHeader ()
+  : OptionField (2)
 {
 }
 
@@ -151,7 +229,7 @@
 
 uint32_t Ipv6ExtensionHopByHopHeader::GetSerializedSize () const
 {
-  return 2;
+  return 2 + OptionField::GetSerializedSize ();
 }
 
 void Ipv6ExtensionHopByHopHeader::Serialize (Buffer::Iterator start) const
@@ -160,6 +238,7 @@
 
   i.WriteU8 (GetNextHeader ());
   i.WriteU8 ((GetLength () >> 3) - 1);
+  OptionField::Serialize (i);
 }
 
 uint32_t Ipv6ExtensionHopByHopHeader::Deserialize (Buffer::Iterator start) 
@@ -168,6 +247,7 @@
 
   SetNextHeader (i.ReadU8 ());
   SetLength ((i.ReadU8 () + 1) << 3);
+  OptionField::Deserialize (i, GetLength () - 2);
 
   return GetSerializedSize ();
 }
@@ -189,6 +269,7 @@
 }
 
 Ipv6ExtensionDestinationHeader::Ipv6ExtensionDestinationHeader ()
+  : OptionField (2)
 {
 }
 
@@ -203,7 +284,7 @@
 
 uint32_t Ipv6ExtensionDestinationHeader::GetSerializedSize () const
 {
-  return 2;
+  return 2 + OptionField::GetSerializedSize ();
 }
 
 void Ipv6ExtensionDestinationHeader::Serialize (Buffer::Iterator start) const
@@ -212,6 +293,8 @@
 
   i.WriteU8 (GetNextHeader ());
   i.WriteU8 ((GetLength () >> 3) - 1);
+
+  OptionField::Serialize (i);
 }
 
 uint32_t Ipv6ExtensionDestinationHeader::Deserialize (Buffer::Iterator start) 
@@ -220,6 +303,7 @@
 
   SetNextHeader (i.ReadU8 ());
   SetLength ((i.ReadU8 () + 1) << 3);
+  OptionField::Deserialize (i, GetLength () - 2);
 
   return GetSerializedSize ();
 }
--- a/src/internet-stack/ipv6-extension-header.h	Wed Nov 04 14:42:58 2009 +0100
+++ b/src/internet-stack/ipv6-extension-header.h	Wed Nov 11 16:25:10 2009 +0100
@@ -22,10 +22,12 @@
 #define IPV6_EXTENSION_HEADER_H
 
 #include <vector>
+#include <list>
 #include <ostream>
 
 #include "ns3/header.h"
 #include "ns3/ipv6-address.h"
+#include "ipv6-option-header.h"
 
 namespace ns3
 {
@@ -127,10 +129,68 @@
 };
 
 /**
+ * \brief Option field for an IPv6ExtensionHeader
+ * Enables adding options to an IPv6ExtensionHeader
+ *
+ * Implementor's note: Make sure to add the result of
+ * OptionField::GetSerializedSize () to your IPv6ExtensionHeader::GetSerializedSize ()
+ * return value. Call OptionField::Serialize and OptionField::Deserialize at the
+ * end of your corresponding IPv6ExtensionHeader methods.
+ */
+
+class OptionField
+{
+  public:
+    OptionField (uint32_t opitonsOffset);
+    ~OptionField ();
+
+    /**
+     * \brief Get the serialized size of the packet.
+     * \return size
+     */
+    uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize all added options.
+     * \param start Buffer iterator
+     */
+    void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start Buffer iterator
+     * \return size of the packet
+     */
+    uint32_t Deserialize (Buffer::Iterator start, uint32_t length);
+
+    /**
+     * \brief Serialize the option, prepending pad1 or padn option as necessary
+     * \param option the option header to serialize
+     */
+    void AddOption (Ipv6OptionHeader const& option);
+
+    /**
+     * \brief Get the offset where the options begin, measured from the start of
+     * the extension header.
+     * \return the offset from the start of the extension header
+     */
+    uint32_t GetOptionsOffset ();
+
+    Buffer GetOptionBuffer ();
+
+  private:
+
+    uint32_t CalculatePad (Ipv6OptionHeader::Alignment alignment) const;
+
+    Buffer m_optionData;
+    uint32_t m_optionsOffset;
+};
+
+/**
  * \class Ipv6ExtensionHopByHopHeader
  * \brief Header of IPv6 Extension "Hop by Hop"
  */
-class Ipv6ExtensionHopByHopHeader : public Ipv6ExtensionHeader
+class Ipv6ExtensionHopByHopHeader : public Ipv6ExtensionHeader, public OptionField
 {
   public:
     /**
@@ -186,7 +246,7 @@
  * \class Ipv6ExtensionDestinationHeader
  * \brief Header of IPv6 Extension Destination
  */
-class Ipv6ExtensionDestinationHeader : public Ipv6ExtensionHeader
+class Ipv6ExtensionDestinationHeader : public Ipv6ExtensionHeader, public OptionField
 {
   public:
     /**
--- a/src/internet-stack/ipv6-extension.cc	Wed Nov 04 14:42:58 2009 +0100
+++ b/src/internet-stack/ipv6-extension.cc	Wed Nov 11 16:25:10 2009 +0100
@@ -81,6 +81,89 @@
   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)
+{
+  NS_LOG_FUNCTION (this << packet << offset << length << ipv6Header << dst << nextHeader << isDropped);
+
+  // For ICMPv6 Error packets
+  Ptr<Packet> malformedPacket = packet->Copy ();
+  malformedPacket->AddHeader (ipv6Header);
+  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
+
+  Ptr<Packet> p = packet->Copy ();
+  p->RemoveAtStart (offset);
+
+  Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> ();
+  Ptr<Ipv6Option> ipv6Option;
+
+  uint8_t processedSize = 0;
+  const uint8_t *data = p->PeekData ();
+  uint8_t optionType = 0;
+  uint8_t optionLength = 0;
+
+  while (length > processedSize && !isDropped)
+  {
+    optionType = *(data + processedSize);
+    ipv6Option = ipv6OptionDemux->GetOption (optionType);
+
+    if (ipv6Option == 0)
+    {
+      optionType >>= 6;
+      switch (optionType)
+      {
+        case 0:
+          optionLength = *(data + processedSize + 1);
+          break;
+
+        case 1:
+          NS_LOG_LOGIC ("Unknown Option. Drop!");
+          m_dropTrace (packet);
+          optionLength = 0;
+          isDropped = true;
+          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;
+          break;
+
+        case 3:
+          NS_LOG_LOGIC ("Unknown Option. Drop!");
+
+          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;
+          break;
+
+        default:
+          break;
+      }
+
+    }
+    else
+    {
+      optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
+    }
+
+    processedSize += optionLength;
+    p->RemoveAtStart (optionLength);
+  }
+
+  return processedSize;
+}
+
 
 NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionHopByHop);
 
@@ -114,10 +197,6 @@
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
-  // For ICMPv6 Error packets
-  Ptr<Packet> malformedPacket = packet->Copy ();
-  malformedPacket->AddHeader (ipv6Header);
-
   Ptr<Packet> p = packet->Copy ();
   p->RemoveAtStart (offset);
 
@@ -128,74 +207,11 @@
     *nextHeader = hopbyhopHeader.GetNextHeader ();
   }
 
-  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
-
-  Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> ();
-  Ptr<Ipv6Option> ipv6Option;
-
-  uint8_t totalSize = hopbyhopHeader.GetLength ();
-  uint8_t processedSize = hopbyhopHeader.GetSerializedSize ();
-  const uint8_t *data = p->PeekData ();
-  uint8_t optionType = 0;
-  uint8_t optionLength = 0;
-  isDropped = false;
-
-  while (totalSize > processedSize && !isDropped)
-  {
-    optionType = *(data + processedSize);
-    ipv6Option = ipv6OptionDemux->GetOption (optionType);
-
-    /* unknow option */
-    if (ipv6Option == 0)
-    {
-      optionType >>= 6;
-      switch (optionType)
-      {
-        case 0:
-          optionLength = *(data + processedSize + 1);
-          break;
-
-        case 1:
-          NS_LOG_LOGIC ("Unknown Option. Drop!");
-          m_dropTrace (packet);
-          optionLength = 0;
-          isDropped = true;
-          break;
+  uint8_t processedSize = hopbyhopHeader.GetOptionsOffset ();
+  offset += processedSize;
+  uint8_t length = hopbyhopHeader.GetLength () - hopbyhopHeader.GetOptionsOffset ();
 
-        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;
-          break;
-
-        case 3:
-          NS_LOG_LOGIC ("Unknown Option. Drop!");
-
-          if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
-          {
-            icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
-          }
-
-          m_dropTrace (packet);
-          optionLength = 0;
-          isDropped = true;
-          break;
-
-        default:
-          isDropped = true;
-          break;
-      }
-    }
-    else 
-    {
-      optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
-    }
-
-    processedSize += optionLength;
-    p->RemoveAtStart (optionLength);
-  }
+  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
 
   return processedSize;
 }
@@ -233,10 +249,6 @@
 {
   NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
 
-  // For ICMPv6 Error packets
-  Ptr<Packet> malformedPacket = packet->Copy ();
-  malformedPacket->AddHeader (ipv6Header);
-
   Ptr<Packet> p = packet->Copy ();
   p->RemoveAtStart (offset);
 
@@ -247,72 +259,11 @@
     *nextHeader = destinationHeader.GetNextHeader ();
   }
 
-  Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
-
-  Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> ();
-  Ptr<Ipv6Option> ipv6Option;
-
-  uint8_t totalSize = destinationHeader.GetLength ();
-  uint8_t processedSize = destinationHeader.GetSerializedSize ();
-  const uint8_t *data = p->PeekData ();
-  uint8_t optionType = 0;
-  uint8_t optionLength = 0;
-  isDropped = false;
-
-  while (totalSize > processedSize && !isDropped)
-  {
-    optionType = *(data + processedSize);
-    ipv6Option = ipv6OptionDemux->GetOption (optionType);
-
-    if (ipv6Option == 0)
-    {
-      optionType >>= 6;
-      switch (optionType)
-      {
-        case 0:
-          optionLength = *(data + processedSize + 1);
-          break;
-
-        case 1:
-          NS_LOG_LOGIC ("Unknown Option. Drop!");
-          m_dropTrace (packet);
-          optionLength = 0;
-          isDropped = true;
-          break;
+  uint8_t processedSize = destinationHeader.GetOptionsOffset ();
+  offset += processedSize;
+  uint8_t length = destinationHeader.GetLength () - destinationHeader.GetOptionsOffset ();
 
-        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;
-          break;
-
-        case 3:
-          NS_LOG_LOGIC ("Unknown Option. Drop!");
-
-          if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
-          {
-            icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
-          }
-
-          m_dropTrace (packet);
-          optionLength = 0;
-          isDropped = true;
-          break;
-
-        default:
-          break;
-      }
-    }
-    else 
-    {
-      optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
-    }
-
-    processedSize += optionLength;
-    p->RemoveAtStart (optionLength);
-  }
+  processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
 
   return processedSize;
 }
@@ -862,7 +813,7 @@
   {
     *nextHeader = routingHeader.GetNextHeader ();
   }
-  
+
   Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
 
   Ipv6Address srcAddress = ipv6header.GetSourceAddress ();
@@ -931,7 +882,7 @@
    * the packet was for us so we resend it to 
    * the new destination (modified in the header above).
    */
-  
+
   Ptr<Ipv6L3Protocol> ipv6 = GetNode ()->GetObject<Ipv6L3Protocol> ();
   Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
   Socket::SocketErrno err;
@@ -946,7 +897,7 @@
   }
   else
   {
-    NS_LOG_INFO("No route for next router");
+    NS_LOG_INFO ("No route for next router");
   }
 
   /* as we directly send packet, mark it as dropped */
--- a/src/internet-stack/ipv6-extension.h	Wed Nov 04 14:42:58 2009 +0100
+++ b/src/internet-stack/ipv6-extension.h	Wed Nov 11 16:25:10 2009 +0100
@@ -90,7 +90,25 @@
    */
   virtual uint8_t Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) = 0;
 
+  /**
+   * \brief Process options
+   * Called by implementing classes to process the options
+   *
+   * \param packet the packet
+   * \param offset the offset of the first option to process
+   * \param length the total length of all options (as specified in the extension header)
+   * \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 ProcessOptions (Ptr<Packet>& packet, uint8_t offset, uint8_t length, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped);
+
 protected:
+  /**
+   * \brief Drop trace callback.
+   */
   TracedCallback<Ptr<const Packet> > m_dropTrace;
 
 private:
@@ -431,7 +449,7 @@
   /**
    * \brief Dispose this object.
    */
-  virtual void DoDispose();
+  virtual void DoDispose ();
 
 private:
   typedef std::list<Ptr<Ipv6ExtensionRouting> > Ipv6ExtensionRoutingList_t;
--- a/src/internet-stack/ipv6-option-header.cc	Wed Nov 04 14:42:58 2009 +0100
+++ b/src/internet-stack/ipv6-option-header.cc	Wed Nov 11 16:25:10 2009 +0100
@@ -81,7 +81,7 @@
 
 uint32_t Ipv6OptionHeader::GetSerializedSize () const
 {
-  return 1;
+  return m_length + 2;
 }
 
 void Ipv6OptionHeader::Serialize (Buffer::Iterator start) const
@@ -89,6 +89,9 @@
   Buffer::Iterator i = start;
 
   i.WriteU8 (m_type);
+  i.WriteU8 (m_length);
+
+  i.Write (m_data.Begin (), m_data.End ());
 }
 
 uint32_t Ipv6OptionHeader::Deserialize (Buffer::Iterator start) 
@@ -96,10 +99,23 @@
   Buffer::Iterator i = start;
 
   m_type = i.ReadU8 ();
+  m_length = i.ReadU8 ();
+
+  m_data = Buffer ();
+  m_data.AddAtEnd (m_length);
+  Buffer::Iterator dataStart = i;
+  i.Next (m_length);
+  Buffer::Iterator dataEnd = i;
+  m_data.Begin ().Write (dataStart, dataEnd);
 
   return GetSerializedSize ();
 }
 
+Ipv6OptionHeader::Alignment Ipv6OptionHeader::GetAlignment () const
+{
+  return (Alignment){1,0};
+}
+
 NS_OBJECT_ENSURE_REGISTERED (Ipv6OptionPad1Header);
 
 TypeId Ipv6OptionPad1Header::GetTypeId ()
@@ -118,6 +134,7 @@
 
 Ipv6OptionPad1Header::Ipv6OptionPad1Header ()
 {
+  SetType (0);
 }
 
 Ipv6OptionPad1Header::~Ipv6OptionPad1Header ()
@@ -166,8 +183,11 @@
   return GetTypeId ();
 }
 
-Ipv6OptionPadnHeader::Ipv6OptionPadnHeader ()
+Ipv6OptionPadnHeader::Ipv6OptionPadnHeader (uint32_t pad)
 {
+  SetType (1);
+  NS_ASSERT_MSG (pad >= 2, "PadN must be at least 2 bytes long");
+  SetLength (pad - 2);
 }
 
 Ipv6OptionPadnHeader::~Ipv6OptionPadnHeader ()
@@ -225,6 +245,7 @@
 
 Ipv6OptionJumbogramHeader::Ipv6OptionJumbogramHeader ()
 {
+  SetType (0xC2);
   SetLength (4);
 }
 
@@ -258,7 +279,7 @@
 
   i.WriteU8 (GetType ());
   i.WriteU8 (GetLength ());
-  i.WriteHtonU16 (m_dataLength);
+  i.WriteHtonU32 (m_dataLength);
 }
 
 uint32_t Ipv6OptionJumbogramHeader::Deserialize (Buffer::Iterator start) 
@@ -272,6 +293,11 @@
   return GetSerializedSize ();
 }
 
+Ipv6OptionHeader::Alignment Ipv6OptionJumbogramHeader::GetAlignment () const
+{
+  return (Alignment){4,2}; //4n+2
+}
+
 NS_OBJECT_ENSURE_REGISTERED (Ipv6OptionRouterAlertHeader);
 
 TypeId Ipv6OptionRouterAlertHeader::GetTypeId ()
@@ -338,5 +364,10 @@
   return GetSerializedSize ();
 }
 
+Ipv6OptionHeader::Alignment Ipv6OptionRouterAlertHeader::GetAlignment () const
+{
+  return (Alignment){2,0}; //2n+0
+}
+
 } /* namespace ns3 */
 
--- a/src/internet-stack/ipv6-option-header.h	Wed Nov 04 14:42:58 2009 +0100
+++ b/src/internet-stack/ipv6-option-header.h	Wed Nov 11 16:25:10 2009 +0100
@@ -35,6 +35,20 @@
 class Ipv6OptionHeader : public Header 
 {
   public:
+
+    /**
+     * \brief represents the alignment requirements of an option header
+     *
+     * Represented as factor*n+offset (eg. 8n+2) See RFC 2460.
+     * No alignemt is represented as 1n+0.
+     *
+     */
+    struct Alignment
+    {
+      uint8_t factor;
+      uint8_t offset;
+    };
+
     /**
      * \brief Get the type identificator.
      * \return type identificator
@@ -107,6 +121,15 @@
      */
     virtual uint32_t Deserialize (Buffer::Iterator start);
 
+    /**
+     * \brief Get the Alignment requirement of this option header
+     * \return The required alignment
+     *
+     * Subclasses should only implement this method, if special alignemt is
+     * required. Default is no alignment (1n+0).
+     */
+    virtual Alignment GetAlignment () const;
+
   private:
     /**
      * \brief The type of the option.
@@ -118,6 +141,10 @@
      */
     uint8_t m_length;
 
+    /**
+     * \brief The anonymous data of this option
+     */
+    Buffer m_data;
 };
 
 /**
@@ -197,8 +224,9 @@
 
     /**
      * \brief Constructor.
+     * \param pad Number of bytes to pad (>=2)
      */
-    Ipv6OptionPadnHeader ();
+    Ipv6OptionPadnHeader (uint32_t pad = 2);
 
     /**
      * \brief Destructor.
@@ -299,6 +327,12 @@
      */
     virtual uint32_t Deserialize (Buffer::Iterator start);
 
+    /**
+     * \brief Get the Alignment requirement of this option header
+     * \return The required alignment
+     */
+    virtual Alignment GetAlignment () const;
+
   private:
     /**
      * \brief The data length.
@@ -372,6 +406,12 @@
      */
     virtual uint32_t Deserialize (Buffer::Iterator start);
 
+    /**
+     * \brief Get the Alignment requirement of this option header
+     * \return The required alignment
+     */
+    virtual Alignment GetAlignment () const;
+
   private:
     /**
      * \brief The value.
--- a/src/internet-stack/wscript	Wed Nov 04 14:42:58 2009 +0100
+++ b/src/internet-stack/wscript	Wed Nov 11 16:25:10 2009 +0100
@@ -130,6 +130,7 @@
         'ipv4-l3-protocol.h',
         'ipv6-l3-protocol.h',
         'ipv6-extension-header.h',
+        'ipv6-option-header.h',
         'arp-l3-protocol.h',
         'udp-l4-protocol.h',
         'tcp-l4-protocol.h',