Difference between revisions of "HOWTO create a new type of protocol header or trailer"
(HOWTO create a new type of protocol header or trailer) |
|||
(One intermediate revision by one other user not shown) | |||
Line 3: | Line 3: | ||
At some point you may wish to create a new or existing protocol which is currently not implemented in ns-3. This protocol will likely require a new type of header. Creating a new header or trailer for this protocol is relatively straightforward and requires subclassing the ns3::Header class described below. | At some point you may wish to create a new or existing protocol which is currently not implemented in ns-3. This protocol will likely require a new type of header. Creating a new header or trailer for this protocol is relatively straightforward and requires subclassing the ns3::Header class described below. | ||
− | == HOWTO | + | == HOWTO create a new type of protocol header or trailer == |
The key is to implement a new subclass of the ns3::Header base class to represent your protocol header: | The key is to implement a new subclass of the ns3::Header base class to represent your protocol header: | ||
Line 17: | Line 17: | ||
virtual uint32_t Deserialize (Buffer::Iterator start); | virtual uint32_t Deserialize (Buffer::Iterator start); | ||
virtual void Print (std::ostream &os) const; | virtual void Print (std::ostream &os) const; | ||
− | |||
// allow protocol-specific access to the header data. | // allow protocol-specific access to the header data. | ||
void SetData (uint32_t data); | void SetData (uint32_t data); | ||
Line 24: | Line 23: | ||
uint32_t m_data; | uint32_t m_data; | ||
}; | }; | ||
+ | |||
+ | Once this class is implemented, you can easily store your protocol header into a packet: | ||
+ | |||
+ | Ptr<Packet> p = ...; | ||
+ | YHeader yHeader; | ||
+ | yHeader.SetData (0xdeadbeaf); | ||
+ | // copy the header into the packet | ||
+ | p->AddHeader (yHeader); | ||
+ | |||
+ | and get it out of a packet: | ||
+ | |||
+ | Ptr<Packet> p = ...; | ||
+ | YHeader yHeader; | ||
+ | // copy the header from the packet | ||
+ | p->RemoveHeader (yHeader); | ||
+ | uint32_t data = yHeader.GetData (); | ||
+ | |||
+ | The implementation of the new header is very simple. First, you need to give a TypeId to your YHeader class: | ||
+ | |||
+ | TypeId | ||
+ | YHeader::GetTypeId (void) | ||
+ | { | ||
+ | static TypeId tid = TypeId ("YHeader") | ||
+ | .SetParent<Header> () | ||
+ | .AddConstructor<YHeader> () | ||
+ | ; | ||
+ | return tid; | ||
+ | } | ||
+ | TypeId | ||
+ | YHeader::GetInstanceTypeId (void) | ||
+ | { | ||
+ | return GetTypeId (); | ||
+ | } | ||
+ | |||
+ | Then, you need to allow your header to serialize and deserialize itself to a byte buffer in its network representation. Here, our new protocol header contains first a 2-byte constant, and, then, the data field so, the total size of the header is 2+4=6 bytes. | ||
+ | |||
+ | uint32_t | ||
+ | YHeader::GetSerializedSize (void) const | ||
+ | { | ||
+ | return 6; | ||
+ | } | ||
+ | void | ||
+ | YHeader::Serialize (Buffer::Iterator start) const | ||
+ | { | ||
+ | // The 2 byte-constant | ||
+ | start.WriteU8 (0xfe); | ||
+ | start.WriteU8 (0xef); | ||
+ | // The data. | ||
+ | start.WriteHtonU32 (m_data); | ||
+ | } | ||
+ | uint32_t | ||
+ | YHeader::Deserialize (Buffer::Iterator start) | ||
+ | { | ||
+ | uint8_t tmp; | ||
+ | tmp = start.ReadU8 (); | ||
+ | NS_ASSERT (tmp == 0xfe); | ||
+ | tmp = start.ReadU8 (); | ||
+ | NS_ASSERT (tmp == 0xef); | ||
+ | m_data = start.ReadNtohU32 (); | ||
+ | return 6; // the number of bytes consumed. | ||
+ | } | ||
+ | |||
+ | Finally, to make sure that Packet::Print also prints the content of your header, just as it prints the content of the other headers of the system, you need to provide a Print method: | ||
+ | |||
+ | void | ||
+ | YHeader::Print (std::ostream &os) const | ||
+ | { | ||
+ | os << "data=" << m_data; | ||
+ | } | ||
+ | |||
+ | The code will look the same if you want to implement a trailer, that is, a protocol data structure which will be appended to the end of the packet, not its start: you need to make sure that you derive from the ns3::Trailer base class and that you call Packet::AddTrailer and Packet::RemoveTrailer. Another important detail is that you must make sure to rewind the iterator in your Serialize and Deserialize methods writing to or reading from the underlying buffer. |
Latest revision as of 22:49, 15 June 2009
Main Page - Current Development - Developer FAQ - Tools - Related Projects - Project Ideas - Summer Projects
Installation - Troubleshooting - User FAQ - HOWTOs - Samples - Models - Education - Contributed Code - Papers
At some point you may wish to create a new or existing protocol which is currently not implemented in ns-3. This protocol will likely require a new type of header. Creating a new header or trailer for this protocol is relatively straightforward and requires subclassing the ns3::Header class described below.
HOWTO create a new type of protocol header or trailer
The key is to implement a new subclass of the ns3::Header base class to represent your protocol header:
class YHeader : public Header { public: // must be implemented to become a valid new header. static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; virtual uint32_t GetSerializedSize (void) const; virtual void Serialize (Buffer::Iterator start) const; virtual uint32_t Deserialize (Buffer::Iterator start); virtual void Print (std::ostream &os) const; // allow protocol-specific access to the header data. void SetData (uint32_t data); uint32_t GetData (void) const; private: uint32_t m_data; };
Once this class is implemented, you can easily store your protocol header into a packet:
Ptr<Packet> p = ...; YHeader yHeader; yHeader.SetData (0xdeadbeaf); // copy the header into the packet p->AddHeader (yHeader);
and get it out of a packet:
Ptr<Packet> p = ...; YHeader yHeader; // copy the header from the packet p->RemoveHeader (yHeader); uint32_t data = yHeader.GetData ();
The implementation of the new header is very simple. First, you need to give a TypeId to your YHeader class:
TypeId YHeader::GetTypeId (void) { static TypeId tid = TypeId ("YHeader") .SetParent<Header> () .AddConstructor<YHeader> () ; return tid; } TypeId YHeader::GetInstanceTypeId (void) { return GetTypeId (); }
Then, you need to allow your header to serialize and deserialize itself to a byte buffer in its network representation. Here, our new protocol header contains first a 2-byte constant, and, then, the data field so, the total size of the header is 2+4=6 bytes.
uint32_t YHeader::GetSerializedSize (void) const { return 6; } void YHeader::Serialize (Buffer::Iterator start) const { // The 2 byte-constant start.WriteU8 (0xfe); start.WriteU8 (0xef); // The data. start.WriteHtonU32 (m_data); } uint32_t YHeader::Deserialize (Buffer::Iterator start) { uint8_t tmp; tmp = start.ReadU8 (); NS_ASSERT (tmp == 0xfe); tmp = start.ReadU8 (); NS_ASSERT (tmp == 0xef); m_data = start.ReadNtohU32 (); return 6; // the number of bytes consumed. }
Finally, to make sure that Packet::Print also prints the content of your header, just as it prints the content of the other headers of the system, you need to provide a Print method:
void YHeader::Print (std::ostream &os) const { os << "data=" << m_data; }
The code will look the same if you want to implement a trailer, that is, a protocol data structure which will be appended to the end of the packet, not its start: you need to make sure that you derive from the ns3::Trailer base class and that you call Packet::AddTrailer and Packet::RemoveTrailer. Another important detail is that you must make sure to rewind the iterator in your Serialize and Deserialize methods writing to or reading from the underlying buffer.