在NS3中贺奠,分組(packet)由四部分組成:byte buffer荚恶,一組byte tags,一組packet tags功舀,metadata[1]。
byte buffer存儲了經(jīng)過序列化處理(serialize)的分組頭部(headers)和尾部(trailers)身弊。這樣做的目的是讓分組的呈現(xiàn)形式更加符合真實(shí)分組的情況辟汰。
下面介紹序列化處理的概念。序列化處理是serialize的中文翻譯阱佛。在真實(shí)網(wǎng)絡(luò)中帖汞,消息的呈現(xiàn)形式是一串二進(jìn)制0/1序列。而在NS3仿真中凑术,消息以C++數(shù)據(jù)結(jié)構(gòu)(類)的形式出現(xiàn)翩蘸。序列化處理是將數(shù)據(jù)結(jié)構(gòu)形式的消息按照特定的協(xié)議轉(zhuǎn)化為二進(jìn)制序列[3]。
去序列化處理(deserialize)的過程與序列化處理的過程正好相反淮逊,是從二進(jìn)制序列中恢復(fù)消息的數(shù)據(jù)結(jié)構(gòu)催首。
下面以AODV協(xié)議的RREQ消息為例形象的說明序列化處理的過程。在仿真中壮莹,RREQ消息以頭部的形式出現(xiàn)翅帜,通過Packet::AddHeader()方法以序列化的形式被添加進(jìn)分組。
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文件中定義)來實(shí)現(xiàn)涝滴,源碼如下:
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
};
注:該類中不包含消息的第一個字節(jié)Type。該字節(jié)單獨(dú)添加。
序列化處理函數(shù)的源碼(在文件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消息的各個字段按照協(xié)議規(guī)定的先后次序?qū)懭隑uffer杂抽。
至此,序列化概念介紹完畢韩脏。
tags包含了特定的仿真信息缩麸。由于協(xié)議的頭部和尾部不存在這些信息的字段,因此在byte buffer中不能包含這些信息赡矢,需要使用tags來存放這些信息杭朱。
metadata描述了頭部和尾部的類型(type)。
參考文獻(xiàn):