Ipv6Extension-Option link
This commit is contained in:
@@ -120,6 +120,83 @@ uint32_t Ipv6ExtensionHeader::Deserialize (Buffer::Iterator start)
|
||||
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 @@ TypeId Ipv6ExtensionHopByHopHeader::GetInstanceTypeId () const
|
||||
}
|
||||
|
||||
Ipv6ExtensionHopByHopHeader::Ipv6ExtensionHopByHopHeader ()
|
||||
: OptionField(2)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -151,7 +229,7 @@ void Ipv6ExtensionHopByHopHeader::Print (std::ostream &os) const
|
||||
|
||||
uint32_t Ipv6ExtensionHopByHopHeader::GetSerializedSize () const
|
||||
{
|
||||
return 2;
|
||||
return 2 + OptionField::GetSerializedSize();
|
||||
}
|
||||
|
||||
void Ipv6ExtensionHopByHopHeader::Serialize (Buffer::Iterator start) const
|
||||
@@ -160,6 +238,7 @@ void Ipv6ExtensionHopByHopHeader::Serialize (Buffer::Iterator start) const
|
||||
|
||||
i.WriteU8 (GetNextHeader ());
|
||||
i.WriteU8 ((GetLength () >> 3) - 1);
|
||||
OptionField::Serialize(i);
|
||||
}
|
||||
|
||||
uint32_t Ipv6ExtensionHopByHopHeader::Deserialize (Buffer::Iterator start)
|
||||
@@ -168,6 +247,7 @@ uint32_t Ipv6ExtensionHopByHopHeader::Deserialize (Buffer::Iterator start)
|
||||
|
||||
SetNextHeader (i.ReadU8 ());
|
||||
SetLength ((i.ReadU8 () + 1) << 3);
|
||||
OptionField::Deserialize(i, GetLength() - 2);
|
||||
|
||||
return GetSerializedSize ();
|
||||
}
|
||||
@@ -189,6 +269,7 @@ TypeId Ipv6ExtensionDestinationHeader::GetInstanceTypeId () const
|
||||
}
|
||||
|
||||
Ipv6ExtensionDestinationHeader::Ipv6ExtensionDestinationHeader ()
|
||||
: OptionField(2)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -203,7 +284,7 @@ void Ipv6ExtensionDestinationHeader::Print (std::ostream &os) const
|
||||
|
||||
uint32_t Ipv6ExtensionDestinationHeader::GetSerializedSize () const
|
||||
{
|
||||
return 2;
|
||||
return 2 + OptionField::GetSerializedSize();
|
||||
}
|
||||
|
||||
void Ipv6ExtensionDestinationHeader::Serialize (Buffer::Iterator start) const
|
||||
@@ -212,6 +293,8 @@ void Ipv6ExtensionDestinationHeader::Serialize (Buffer::Iterator start) const
|
||||
|
||||
i.WriteU8 (GetNextHeader ());
|
||||
i.WriteU8 ((GetLength () >> 3) - 1);
|
||||
|
||||
OptionField::Serialize(i);
|
||||
}
|
||||
|
||||
uint32_t Ipv6ExtensionDestinationHeader::Deserialize (Buffer::Iterator start)
|
||||
@@ -220,6 +303,7 @@ uint32_t Ipv6ExtensionDestinationHeader::Deserialize (Buffer::Iterator start)
|
||||
|
||||
SetNextHeader (i.ReadU8 ());
|
||||
SetLength ((i.ReadU8 () + 1) << 3);
|
||||
OptionField::Deserialize(i, GetLength() - 2);
|
||||
|
||||
return GetSerializedSize ();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -126,11 +128,69 @@ class Ipv6ExtensionHeader : public Header
|
||||
Buffer m_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* \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 Ipv6ExtensionHopByHopHeader : public Ipv6ExtensionHeader
|
||||
* \class Ipv6ExtensionDestinationHeader
|
||||
* \brief Header of IPv6 Extension Destination
|
||||
*/
|
||||
class Ipv6ExtensionDestinationHeader : public Ipv6ExtensionHeader
|
||||
class Ipv6ExtensionDestinationHeader : public Ipv6ExtensionHeader, public OptionField
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
||||
@@ -81,6 +81,87 @@ Ptr<Node> Ipv6Extension::GetNode () const
|
||||
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!");
|
||||
/* TODO */
|
||||
/* icmpv6->SendErrorParameterError (malformedPacket, dst, 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 ())
|
||||
{
|
||||
/* TODO */
|
||||
/* icmpv6->SendErrorParameterError (malformedPacket, dst, 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);
|
||||
}
|
||||
|
||||
return processedSize;
|
||||
}
|
||||
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionHopByHop);
|
||||
|
||||
@@ -116,10 +197,6 @@ uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -130,74 +207,11 @@ uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
|
||||
*nextHeader = hopbyhopHeader.GetNextHeader ();
|
||||
}
|
||||
|
||||
Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
|
||||
uint8_t processedSize = hopbyhopHeader.GetOptionsOffset();
|
||||
offset += processedSize;
|
||||
uint8_t length = hopbyhopHeader.GetLength() - hopbyhopHeader.GetOptionsOffset();
|
||||
|
||||
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);
|
||||
|
||||
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!");
|
||||
/* TODO */
|
||||
/* icmpv6->SendErrorParameterError (malformedPacket, dst, 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 ())
|
||||
{
|
||||
/* TODO */
|
||||
/* icmpv6->SendErrorParameterError (malformedPacket, dst, 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;
|
||||
}
|
||||
@@ -237,10 +251,6 @@ uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset,
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -251,74 +261,11 @@ uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset,
|
||||
*nextHeader = destinationHeader.GetNextHeader ();
|
||||
}
|
||||
|
||||
Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
|
||||
uint8_t processedSize = destinationHeader.GetOptionsOffset();
|
||||
offset += processedSize;
|
||||
uint8_t length = destinationHeader.GetLength() - destinationHeader.GetOptionsOffset();
|
||||
|
||||
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;
|
||||
|
||||
case 2:
|
||||
NS_LOG_LOGIC ("Unknown Option. Drop!");
|
||||
/* TODO */
|
||||
/* icmpv6->SendErrorParameterError (malformedPacket, dst, 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 ())
|
||||
{
|
||||
/* TODO */
|
||||
/* icmpv6->SendErrorParameterError (malformedPacket, dst, 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;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,21 @@ class Ipv6Extension : public Object
|
||||
*/
|
||||
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:
|
||||
TracedCallback<Ptr<const Packet> > m_dropTrace;
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ void Ipv6OptionHeader::Print (std::ostream &os) const
|
||||
|
||||
uint32_t Ipv6OptionHeader::GetSerializedSize () const
|
||||
{
|
||||
return 1;
|
||||
return m_length + 2;
|
||||
}
|
||||
|
||||
void Ipv6OptionHeader::Serialize (Buffer::Iterator start) const
|
||||
@@ -89,6 +89,9 @@ void Ipv6OptionHeader::Serialize (Buffer::Iterator start) const
|
||||
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 @@ uint32_t Ipv6OptionHeader::Deserialize (Buffer::Iterator start)
|
||||
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 @@ TypeId Ipv6OptionPad1Header::GetInstanceTypeId () const
|
||||
|
||||
Ipv6OptionPad1Header::Ipv6OptionPad1Header ()
|
||||
{
|
||||
SetType(0);
|
||||
}
|
||||
|
||||
Ipv6OptionPad1Header::~Ipv6OptionPad1Header ()
|
||||
@@ -166,8 +183,11 @@ TypeId Ipv6OptionPadnHeader::GetInstanceTypeId () const
|
||||
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 @@ TypeId Ipv6OptionJumbogramHeader::GetInstanceTypeId () const
|
||||
|
||||
Ipv6OptionJumbogramHeader::Ipv6OptionJumbogramHeader ()
|
||||
{
|
||||
SetType (0xC2);
|
||||
SetLength (4);
|
||||
}
|
||||
|
||||
@@ -258,7 +279,7 @@ void Ipv6OptionJumbogramHeader::Serialize (Buffer::Iterator start) const
|
||||
|
||||
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 @@ uint32_t Ipv6OptionJumbogramHeader::Deserialize (Buffer::Iterator start)
|
||||
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 @@ uint32_t Ipv6OptionRouterAlertHeader::Deserialize (Buffer::Iterator start)
|
||||
return GetSerializedSize ();
|
||||
}
|
||||
|
||||
Ipv6OptionHeader::Alignment Ipv6OptionRouterAlertHeader::GetAlignment() const
|
||||
{
|
||||
return (Alignment){2,0}; //2n+0
|
||||
}
|
||||
|
||||
} /* namespace ns3 */
|
||||
|
||||
|
||||
@@ -35,6 +35,20 @@ namespace ns3
|
||||
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 @@ class Ipv6OptionHeader : public Header
|
||||
*/
|
||||
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,12 @@ class Ipv6OptionHeader : public Header
|
||||
*/
|
||||
uint8_t m_length;
|
||||
|
||||
/**
|
||||
* \brief The anonymous data of this option
|
||||
*/
|
||||
|
||||
Buffer m_data;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -197,8 +226,9 @@ class Ipv6OptionPadnHeader : public Ipv6OptionHeader
|
||||
|
||||
/**
|
||||
* \brief Constructor.
|
||||
* \param pad Number of bytes to pad (>=2)
|
||||
*/
|
||||
Ipv6OptionPadnHeader ();
|
||||
Ipv6OptionPadnHeader (uint32_t pad = 2);
|
||||
|
||||
/**
|
||||
* \brief Destructor.
|
||||
@@ -299,6 +329,12 @@ class Ipv6OptionJumbogramHeader : public Ipv6OptionHeader
|
||||
*/
|
||||
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 +408,12 @@ class Ipv6OptionRouterAlertHeader : public Ipv6OptionHeader
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -130,6 +130,7 @@ def build(bld):
|
||||
'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',
|
||||
|
||||
Reference in New Issue
Block a user