00001 /*! 00002 \page packet-header-trailer How to create a new type of protocol header or trailer 00003 \anchor howtos-packet-header-trailer 00004 00005 <b>Question:</b> I want to implement a new protocol X which uses a new 00006 type of header Y. How do I implement and use this new header Y in ns-3 ? 00007 00008 <b>Answer:</b> The key is to implement a new subclass of the ns3::Header 00009 base class to represent your protocol header: 00010 \code 00011 class YHeader : public Header 00012 { 00013 public: 00014 // must be implemented to become a valid new header. 00015 static TypeId GetTypeId (void); 00016 virtual TypeId GetInstanceTypeId (void) const; 00017 virtual uint32_t GetSerializedSize (void) const; 00018 virtual void Serialize (Buffer::Iterator start) const; 00019 virtual uint32_t Deserialize (Buffer::Iterator start); 00020 virtual void Print (std::ostream &os) const; 00021 00022 // allow protocol-specific access to the header data. 00023 void SetData (uint32_t data); 00024 uint32_t GetData (void) const; 00025 private: 00026 uint32_t m_data; 00027 }; 00028 \endcode 00029 00030 Once this class is implemented, you can easily store your protocol 00031 header into a packet: 00032 \code 00033 Ptr<Packet> p = ...; 00034 YHeader yHeader; 00035 yHeader.SetData (0xdeadbeaf); 00036 // copy the header into the packet 00037 p->AddHeader (yHeader); 00038 \endcode 00039 and get it out of a packet: 00040 \code 00041 Ptr<Packet> p = ...; 00042 YHeader yHeader; 00043 // copy the header from the packet 00044 p->RemoveHeader (yHeader); 00045 uint32_t data = yHeader.GetData (); 00046 \endcode 00047 00048 The implementation of the new header is very simple. First, you need 00049 to give a TypeId to your YHeader class: 00050 \code 00051 TypeId 00052 YHeader::GetTypeId (void) 00053 { 00054 static TypeId tid = TypeId ("YHeader") 00055 .SetParent<Header> () 00056 .AddConstructor<YHeader> () 00057 ; 00058 return tid; 00059 } 00060 TypeId 00061 YHeader::GetInstanceTypeId (void) 00062 { 00063 return GetTypeId (); 00064 } 00065 \endcode 00066 00067 Then, you need to allow your header to serialize and deserialize itself 00068 to a byte buffer in its network representation. Here, our new protocol 00069 header contains first a 2-byte constant, and, then, the data field so, 00070 the total size of the header is 2+4=6 bytes. 00071 \code 00072 uint32_t 00073 YHeader::GetSerializedSize (void) const 00074 { 00075 return 6; 00076 } 00077 void 00078 YHeader::Serialize (Buffer::Iterator start) const 00079 { 00080 // The 2 byte-constant 00081 start.WriteU8 (0xfe); 00082 start.WriteU8 (0xef); 00083 // The data. 00084 start.WriteHtonU32 (m_data); 00085 } 00086 uint32_t 00087 YHeader::Deserialize (Buffer::Iterator start) 00088 { 00089 uint8_t tmp; 00090 tmp = start.ReadU8 (); 00091 NS_ASSERT (tmp == 0xfe); 00092 tmp = start.ReadU8 (); 00093 NS_ASSERT (tmp == 0xef); 00094 m_data = start.ReadNtohU32 (); 00095 return 6; // the number of bytes consumed. 00096 } 00097 \endcode 00098 00099 Finally, to make sure that Packet::Print also prints the content 00100 of your header, just as it prints the content of the other 00101 headers of the system, you need to provide a Print method: 00102 \code 00103 void 00104 YHeader::Print (std::ostream &os) const 00105 { 00106 os << "data=" << m_data; 00107 } 00108 \endcode 00109 00110 The code will look the same if you want to implement a trailer, 00111 that is, a protocol data structure which will be appended to the 00112 end of the packet, not its start: you need to make sure that 00113 you derive from the ns3::Trailer base class and that you call 00114 Packet::AddTrailer and Packet::RemoveTrailer. Another important 00115 detail is that you must make sure to rewind the iterator in your 00116 Serialize and Deserialize methods writing to or reading from 00117 the underlying buffer. 00118 00119 */