在NS3中,分组(packet)由四部分组成:byte buffer,一组byte tags,一组packet tags,metadata[1]。
byte buffer存储了经过序列化处理(serialize)的分组头部(headers)和尾部(trailers)。这样做的目的是让分组的呈现形式更加符合真实分组的情况。
下面介绍序列化处理的概念。序列化处理是serialize的中文翻译。在真实网络中,消息的呈现形式是一串二进制0/1序列。而在NS3仿真中,消息以C++数据结构(类)的形式出现。序列化处理是将数据结构形式的消息按照特定的协议转化为二进制序列[3]。
去序列化处理(deserialize)的过程与序列化处理的过程正好相反,是从二进制序列中恢复消息的数据结构。
下面以AODV协议的RREQ消息为例形象的说明序列化处理的过程。在仿真中,RREQ消息以头部的形式出现,通过Packet::AddHeader()方法以序列化的形式被添加进分组。
RREQ消息的格式如下[2]:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type |J|R|G|D|U| Reserved | Hop Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RREQ ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Originator IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Originator Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
在NS3中,RREQ消息通过类RreqHeader(在文件aodv-packet.h文件中定义)来实现,源码如下:
class RreqHeader : public Header
{
public:
/// c-tor
RreqHeader (uint8_t flags = 0, uint8_t reserved = 0, uint8_t hopCount = 0,
uint32_t requestID = 0, Ipv4Address dst = Ipv4Address (),
uint32_t dstSeqNo = 0, Ipv4Address origin = Ipv4Address (),
uint32_t originSeqNo = 0);
// Header serialization/deserialization
static TypeId GetTypeId ();
TypeId GetInstanceTypeId () const;
uint32_t GetSerializedSize () const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start);
void Print (std::ostream &os) const;
// Fields
......
// Flags
......
bool operator== (RreqHeader const & o) const;
private:
uint8_t m_flags; ///< |J|R|G|D|U| bit flags, see RFC
uint8_t m_reserved; ///< Not used
uint8_t m_hopCount; ///< Hop Count
uint32_t m_requestID; ///< RREQ ID
Ipv4Address m_dst; ///< Destination IP Address
uint32_t m_dstSeqNo; ///< Destination Sequence Number
Ipv4Address m_origin; ///< Originator IP Address
uint32_t m_originSeqNo; ///< Source Sequence Number
};
注:该类中不包含消息的第一个字节Type。该字节单独添加。
序列化处理函数的源码(在文件aodv-packet.cc中)如下:
void
RreqHeader::Serialize (Buffer::Iterator i) const
{
i.WriteU8 (m_flags);
i.WriteU8 (m_reserved);
i.WriteU8 (m_hopCount);
i.WriteHtonU32 (m_requestID);
WriteTo (i, m_dst);
i.WriteHtonU32 (m_dstSeqNo);
WriteTo (i, m_origin);
i.WriteHtonU32 (m_originSeqNo);
}
从源码中可以看出,序列化处理是将RREQ消息的各个字段按照协议规定的先后次序写入Buffer。
至此,序列化概念介绍完毕。
tags包含了特定的仿真信息。由于协议的头部和尾部不存在这些信息的字段,因此在byte buffer中不能包含这些信息,需要使用tags来存放这些信息。
metadata描述了头部和尾部的类型(type)。
参考文献:
网友评论