doc/howtos/howtos-packet-header.h
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue, 02 Sep 2008 10:12:14 -0700
changeset 3576 f6abfdf47163
parent 3307 c1a29f8ab2af
permissions -rw-r--r--
bug 303: return value should not be const
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3307
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     1
/*!
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     2
\page packet-header-trailer How to create a new type of protocol header or trailer
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     3
\anchor howtos-packet-header-trailer
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     4
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     5
<b>Question:</b> I want to implement a new protocol X which uses a new
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     6
type of header Y. How do I implement and use this new header Y in ns-3 ?
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     7
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     8
<b>Answer:</b> The key is to implement a new subclass of the ns3::Header
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
     9
base class to represent your protocol header:
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    10
\code
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    11
class YHeader : public Header
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    12
{
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    13
public:
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    14
  // must be implemented to become a valid new header.
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    15
  static TypeId GetTypeId (void);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    16
  virtual TypeId GetInstanceTypeId (void) const;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    17
  virtual uint32_t GetSerializedSize (void) const;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    18
  virtual void Serialize (Buffer::Iterator start) const;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    19
  virtual uint32_t Deserialize (Buffer::Iterator start);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    20
  virtual void Print (std::ostream &os) const;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    21
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    22
  // allow protocol-specific access to the header data.
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    23
  void SetData (uint32_t data);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    24
  uint32_t GetData (void) const;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    25
private:
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    26
  uint32_t m_data;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    27
};
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    28
\endcode
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    29
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    30
Once this class is implemented, you can easily store your protocol
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    31
header into a packet:
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    32
\code
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    33
Ptr<Packet> p = ...;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    34
YHeader yHeader;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    35
yHeader.SetData (0xdeadbeaf);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    36
// copy the header into the packet
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    37
p->AddHeader (yHeader);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    38
\endcode
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    39
and get it out of a packet:
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    40
\code
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    41
Ptr<Packet> p = ...;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    42
YHeader yHeader;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    43
// copy the header from the packet
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    44
p->RemoveHeader (yHeader);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    45
uint32_t data = yHeader.GetData ();
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    46
\endcode
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    47
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    48
The implementation of the new header is very simple. First, you need
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    49
to give a TypeId to your YHeader class:
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    50
\code
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    51
TypeId
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    52
YHeader::GetTypeId (void)
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    53
{
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    54
  static TypeId tid = TypeId ("YHeader")
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    55
    .SetParent<Header> ()
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    56
    .AddConstructor<YHeader> ()
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    57
  ;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    58
  return tid;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    59
}
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    60
TypeId
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    61
YHeader::GetInstanceTypeId (void)
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    62
{
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    63
  return GetTypeId ();
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    64
}
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    65
\endcode
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    66
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    67
Then, you need to allow your header to serialize and deserialize itself
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    68
to a byte buffer in its network representation. Here, our new protocol
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    69
header contains first a 2-byte constant, and, then, the data field so,
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    70
the total size of the header is 2+4=6 bytes.
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    71
\code
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    72
uint32_t 
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    73
YHeader::GetSerializedSize (void) const
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    74
{
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    75
  return 6;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    76
}
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    77
void 
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    78
YHeader::Serialize (Buffer::Iterator start) const
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    79
{
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    80
  // The 2 byte-constant
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    81
  start.WriteU8 (0xfe);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    82
  start.WriteU8 (0xef);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    83
  // The data.
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    84
  start.WriteHtonU32 (m_data);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    85
}
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    86
uint32_t 
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    87
YHeader::Deserialize (Buffer::Iterator start)
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    88
{
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    89
  uint8_t tmp;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    90
  tmp = start.ReadU8 ();
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    91
  NS_ASSERT (tmp == 0xfe);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    92
  tmp = start.ReadU8 ();
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    93
  NS_ASSERT (tmp == 0xef);
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    94
  m_data = start.ReadNtohU32 ();
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    95
  return 6; // the number of bytes consumed.
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    96
}
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    97
\endcode
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    98
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
    99
Finally, to make sure that Packet::Print also prints the content
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   100
of your header, just as it prints the content of the other
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   101
headers of the system, you need to provide a Print method:
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   102
\code
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   103
void 
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   104
YHeader::Print (std::ostream &os) const
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   105
{
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   106
  os << "data=" << m_data;
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   107
}
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   108
\endcode
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   109
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   110
The code will look the same if you want to implement a trailer,
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   111
that is, a protocol data structure which will be appended to the
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   112
end of the packet, not its start: you need to make sure that
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   113
you derive from the ns3::Trailer base class and that you call
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   114
Packet::AddTrailer and Packet::RemoveTrailer. Another important
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   115
detail is that you must make sure to rewind the iterator in your
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   116
Serialize and Deserialize methods writing to or reading from 
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   117
the underlying buffer.
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   118
c1a29f8ab2af add packet header howto
Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
parents:
diff changeset
   119
*/