77c649bda6bf04a3ba84067fa2b1d21e1e12bc07
[senf.git] / HowTos / NewPacket / Mainpage.dox
1 // $Id$
2 //
3 // Copyright (C) 2008 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \mainpage libPackets: How to define and use a new Packet Type
24
25     This howto will introduce the facilities needed to define a new packet type. As example, the
26     \c GREPacket type is defined. 
27
28     \section howto_newpacket_start Getting started
29
30     Before starting with the implementation, we look at the specification of the GRE packet. This is
31     found in <a href="http://tools.ietf.org/html/rfc2784">RFC 2784</a> in Section 2.1:
32
33     <pre>
34      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
35     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36     |C|       Reserved0       | Ver |         Protocol Type         |
37     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38     |      Checksum (optional)      |       Reserved1 (Optional)    |
39     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40     </pre>
41
42     Using this protocol definition, we can decide the first important question: Whether the packet
43     header is fixed size or dynamically sized. As we see above, the header incorporates optional
44     fields. Therefore it must be dynamically sized. The RFC further details, that if the \a Checksum
45     \a Present bit \a C is set, both \a Checksum and \a Reserved1 are present, otherwise they must
46     both be omitted.
47
48     Another information we take from the RFC is, that the \a Protocol \a Type is used to define the
49     type of payload which directly follows the GRE header. This value is an <a
50     href="http://www.iana.org/assignments/ethernet-numbers">ETHERTYPE</a> value. To allow the packet
51     library to automatically parse the GRE payload data, we need to tell the packet library which
52     ETHERTYPE represents which packet type. This association already exists in form of the
53     senf::EtherTypes registry. Our GRE packet will therefore utilize this registry.
54
55     To summarize, we have gathered the following information:
56
57     \li The GRE packet header is a dynamically sized header.
58     \li The GRE packet header utilizes the senf::EtherTypes registry for next-header selection
59
60     \section howto_newpacket_parser Implementing the GRE Parser
61
62     The next step in creating a new packet type is to implement the parser. The parser is
63     responsible for turning a bunch of bytes into an interpreted header with specific fields. The
64     parser will later be constructed with an iterator (pointer) to the first byte to be interpreted
65     as a GRE header and will provide member functions to access the header fields. You can implement
66     these members manually but the SENF library provides a large set of helper macros which simplify
67     this task considerably.
68
69     \code
70     struct GREParser : public senf::PacketParser
71     {
72     #   include SENF_PARSER()
73
74         // Define fields
75
76         SENF_PARSER_FINALIZE(GREParser);
77     };
78     \endcode
79
80     This is the standard skeleton of any parser class: We need to inherit senf::PacketParser and
81     start out by including either \ref SENF_PARSER() or \ref SENF_FIXED_PARSER(). Which, depends on
82     whether we define a fixed size or a dynamically sized parser. As \c GREParser is dynamically
83     sized, we include \ref SENF_PARSER().
84
85     After the fields are defined, we need to call the \ref SENF_PARSER_FINALIZE() macro to close of
86     the parser definition. This call takes the name of the parser being defined as it's sole
87     argument.
88
89     This is already a valid parser, albeit not a very usable one since it defines no fields. We now
90     go back to define the parser fields and begin with the simple part: Those fields which are
91     always present.
92
93     \code
94     SENF_PARSER_BITFIELD  ( checksumPresent, 1, bool     );
95     SENF_PARSER_SKIP_BITS (                 12           );
96     SENF_PARSER_BITFIELD  ( version,         3, unsigned );
97     SENF_PARSER_BITFIELD  ( protocolType,   16, unsigned );
98     \endcode
99     
100     This is a direct transcript of the field definition above. There are quite a number of macros
101     which may be used to define fields. All these macros are documented in '\ref
102     packetparsermacros'.
103
104     This is a correct \c GREPacket header definition but we can optimize a little bit: Since the \a
105     protocolType field is aligned on a byte boundary, instead of defining it as a bitfield, we can
106     define it as a UInt16 field:
107     
108     \code
109     SENF_PARSER_BITFIELD  ( checksumPresent,  1, bool     );
110     SENF_PARSER_SKIP_BITS (                  12           );
111     SENF_PARSER_BITFIELD  ( version,          3, unsigned );
112
113     SENF_PARSER_FIELD     ( protocolType,    senf::UInt16Parser );
114     \endcode
115
116     Whereas \ref SENF_PARSER_BITFIELD can define only bit-fields, \ref SENF_PARSER_FIELD can define
117     almost arbitrary field types. The type is specified by passing the name of another parser to
118     \ref SENF_PARSER_FIELD.
119
120     It is important to understand, that the accessors do \e not return the parsed field value. They
121     return another \e parser which is used to further interpret the value. This is the inherent
122     recursive nature of the SENF packet parsers. This allows to define wildly complex header formats
123     if needed. Of course, at some point we need the real value. This is, what the so called
124     <em>value parsers</em> do: They interpret some bytes or bits and return the value of that field
125     (not a parser). Examples are the bitfield parsers returned by the accessors generated by
126     SENF_PARSER_BITFIELD (like senf::UIntFieldParser) or the senf::UInt16Parser.
127
128     What happens in the above macros? Most of the macros define an accessor for a specific field: \a
129     checksumPresent() or \a protocolType(). They also manage a <em>current Offset</em>. This value
130     is advanced according to the field size whenever a new field is defined (and since this parser
131     is defined as a dynamically sized parser, this offset is not a constant, it is an expression
132     which calculates the offset of a field depending on the preceding data).
133
134     We now come to the optional fields. Since there are two fields which need to be disabled/enabled
135     together, we first need to define an additional sub-parser which combines those two
136     fields. After this parser is defined, we can use \ref SENF_PARSER_VARIANT() to add this parser
137     as an optional parser to the GRE header.
138     
139     \code
140     struct GREParser_OptFields : public senf::PacketParser
141     {
142     #   include SENF_FIXED_PARSER()
143
144         SENF_PARSER_FIELD ( checksum, senf::UInt16Parser );
145         SENF_PARSER_SKIP  (           2                  );
146
147         SENF_PARSER_FINALIZE(GREParser_OptFields);
148     };
149     \endcode
150
151     This parser only parses the two optional fields of which the reserved field is just skipped. The
152     parser this time is a fixed size parser. We can now use this parser to continue the \c GREParser
153     implementation:
154
155     \code
156     SENF_PARSER_BITFIELD  ( checksumPresent,  1, bool     );
157     SENF_PARSER_SKIP_BITS (                  12           );
158     SENF_PARSER_BITFIELD  ( version,          3, unsigned );
159
160     SENF_PARSER_FIELD     ( protocolType,    senf::UInt16Parser );
161
162     SENF_PARSER_VARIANT   ( optionalFields,  checksumPresent,
163                                              (senf::VoidPacketParser)
164                                              (GREParser_OptFields) );
165     \endcode
166
167     For a variant parser, two things need to be specified: A selector and a list of variant
168     parsers. The selector is another parser field which is used to decide, which variant to
169     choose. In this simple case, the field must be an unsigned integer (more precisely a value
170     parser which returns a value which is implicitly convertible to \c unsigned). This value is used
171     as index into the list of variant types. So in our case, 0 is associated with
172     senf::VoidPacketParser whereas 1 is associated with \c
173     GREParser_OptFields. (senf::VoidPacketParser is a special empty parser which is used in a
174     Variant to denote cases in which the variant parser should not parse anything)
175
176     This parser will work, it is however not very safe and not very usable. If \a p is a GREParser
177     instance, than we access the fields via:
178     \code
179     p.checksumPresent()                    = true;
180     p.version()                            = 4u;
181     p.protocolType()                       = 0x86dd;
182     p.optionalFields().get<1>().checksum() = 12345u;
183     \endcode
184     
185     There are two problems here:
186     \li accessing the checksum field is quite unwieldy
187     \li changing the checksumPresent() value will break the parser
188
189     The reason for the second problem lies in the fact, that the variant parser needs to be informed
190     whenever the selector (here \a checksumPresent) is changed since the variant parser must ensure,
191     that the header data stays consistent. In this example, whenever the checksumPresent field is
192     enabled, the variant parser needs to insert additional 4 bytes of data and remove those bytes,
193     when the checksumPresent field is disabled. 
194
195     To fix this, we make the checksumPresent field read-only:
196
197     \code
198     SENF_PARSER_BITFIELD_RO ( checksumPresent,  1, bool     );
199     \endcode
200
201     To change the checksumPresent value, we now need to use the variant parsers \a init member:
202
203     \code
204     p.optionalFields().init<0>();
205     p.optionalFields().init<1>();
206     \endcode
207     
208     The first statements switches to the first variant and therefore in this case disables the
209     checksum field. The second statement will switch to the second variant and enable the checksum
210     field. 
211
212     This again is not very usable. So we complete the parser by providing simple additional members
213     which wrap these complicated calls. While doing this, we also mark the variant as a private
214     field so it is not directly accessible any more (since we now have the additional helpers which
215     are used to access the variant, we don't want anyone to mess around with it directly). Here the
216     final \c GREParser
217
218     \code
219     struct GREParser_OptFields : public senf::PacketParser
220     {
221     #   include SENF_FIXED_PARSER()
222
223         SENF_PARSER_FIELD           ( checksum,        senf::UInt16Parser         );
224         SENF_PARSER_SKIP            (                   2                         );
225
226         SENF_PARSER_FINALIZE(GREParser_OptFields);
227     };
228
229     struct GREParser : public senf::PacketParser
230     {
231     #   include SENF_PARSER()
232
233         SENF_PARSER_BITFIELD_RO     ( checksumPresent,  1, bool                   );
234         SENF_PARSER_SKIP_BITS       (                  12                         );
235         SENF_PARSER_BITFIELD        ( version,          3, unsigned               );
236
237         SENF_PARSER_FIELD           ( protocolType,    senf::UInt16Parser         );
238
239         SENF_PARSER_PRIVATE_VARIANT ( optionalFields_, checksumPresent,
240                                                          (senf::VoidPacketParser)
241                                                          (GREParser_OptFields)    );
242
243         typedef GREParser_OptFields::checksum_t checksum_t;
244         checksum_t checksum() const
245             { return optionalFields_().get<1>().checksum(); }
246
247         void enableChecksum()  const { optionalFields_().init<1>(); }
248         void disableChecksum() const { optionalFields_().init<0>(); }
249     
250         SENF_PARSER_FINALIZE(GREParser);
251     };
252     \endcode
253
254     Above code has one other twist we need to discuss: the \a checksum_t typedef. This is added as a
255     convenience to the user of this parser. The \c SENF_PARSER_* macros which define a field all
256     define some additional symbols providing further information about the field. Of these
257     additional symbols, the most important is <em>field</em><code>_t</code>, which is the (parser)
258     type returned by the field. This helps to work with a parser in more complex situations
259     (e.g. when using collection parsers) since it allows to access the parser type without exact
260     knowledge of this type (which may become quite complex if templates are involved) as long as the
261     field name is known. Since we provide an accessor for the \a checksum field, we also provide the
262     \a checksum_t typedef for this accessor.
263
264     The \c GREParser is now simple and safe to use. The only responsibility of the user now is to
265     only access \a checksum() if the \a checksumPresent() field is set. Otherwise, the behavior is
266     undefined (in debug builds, the parser will terminate the application with an assert).
267  */
268
269 \f
270 // Local Variables:
271 // mode: c++
272 // fill-column: 100
273 // comment-column: 40
274 // c-file-style: "senf"
275 // indent-tabs-mode: nil
276 // ispell-local-dictionary: "american"
277 // compile-command: "scons -u doc"
278 // mode: flyspell
279 // mode: auto-fill
280 // End: