HowTos/NewPacket: Remove old code from example
[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 Defining and using a new 'libPacket' 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     \autotoc
29
30
31     \section howto_newpacket_overview Overview
32
33     The packet library supports two basic packet representations, the more generic one being
34     senf::Packet. This representation does not know anything about the type of packet, its fields or
35     properties. It really only is a bunch of bytes. Possibly there is a preceding packet (header) or
36     a following one, but that is all, a senf::Packet knows.
37
38     The second representation is implemented by senf::ConcretePacket. This representation derives
39     from senf::Packet and adds information about the packet type, its fields, eventually some
40     invariants or packet specific operations etc. In what follows, we will concentrate on this
41     latter representation.
42
43     A concrete packet type in senf provides a lot of detailed information about a specific type of
44     packet:
45
46     \li It provides access to the packets fields
47     \li It may provide additional packet specific functions (e.g. calculating or validating a
48         checksum)
49     \li It provides information on the nesting of packets
50     \li It implements packet invariants
51
52     To define a new packet type, we need to implement two classes which together provide all this
53     information: 
54
55     \li a \e parser (a class derived from senf::PacketParserBase). This class defines the data
56         fields of the packet header and may also provide additional packet specific functionality.
57     \li a \e packet \e type (a class derived from senf::PacketTypeBase). This class defines, how
58         packets are nested and how to initialize and maintain invariants.
59
60     The following sections describe how to define these classes. Where appropriate, we will use GRE
61     (Generic Routing Encapsulation) as an example.
62
63     \section howto_newpacket_gre Introducing the GRE example packet type
64
65     When defining a new packet type, we start out by answering two important questions:
66
67     \li What kind of parser is needed for this packet type (fixed size or variable sized).
68     \li Whether the packet has another packet as payload (a nested packet) and how the type of this
69         payload is found (whether a registry is used and if yes, which).
70
71     In the case of GRE, these questions can be answered by just looking at the GRE specification in
72     <a href="http://tools.ietf.org/html/rfc2784">RFC 2784</a>. In Section 2.1 we find the header
73     layout:
74
75     <pre>
76      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
77     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78     |C|       Reserved0       | Ver |         Protocol Type         |
79     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80     |      Checksum (optional)      |       Reserved1 (Optional)    |
81     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82     </pre>
83
84     This header is followed by the payload data.
85
86     Using this protocol definition, we see that the header incorporates optional fields. Therefore
87     it must be dynamically sized: if the \a Checksum \a Present bit \a C is set, both \a Checksum
88     and \a Reserved1 are present, otherwise both must be omitted.
89
90     Further inspection of the RFC reveals that the \a Protocol \a Type is used to define the type of
91     payload which directly follows the GRE header. This value is an <a
92     href="http://www.iana.org/assignments/ethernet-numbers">ETHERTYPE</a> value. To allow the packet
93     library to automatically parse the GRE payload data, we need to tell the packet library which
94     ETHERTYPE is implemented by which packet type. This kind of association already exists in the
95     form of the senf::EtherTypes registry. Our GRE packet will therefore use this registry.
96
97     To summarize:
98
99     \li The GRE packet header is a dynamically sized header.
100     \li The GRE packet header uses the senf::EtherTypes registry for next-header selection.
101
102
103     \section howto_newpacket_parser Implementing the packet parser
104
105     Each parser is responsible for turning a bunch of bytes into an interpreted header with specific
106     fields. A parser instance is initialized with an iterator (pointer) to the first byte to be
107     interpreted (the first byte of the packet data) and provides member functions to access the
108     header fields. You could implement these members manually, but the SENF library provides a large
109     set of helper macros which simplify this task considerably.
110
111     \subsection howto_newpacket_parser_skeleton The PacketParser skeleton
112
113     \code
114     #include <senf/Packets.hh>
115
116     struct GREPacketParser : public senf::PacketParserBase
117     {
118     #   include SENF_PARSER()
119
120         // Define fields
121         // (see below)
122
123         SENF_PARSER_FINALIZE(GREPacketParser);
124     };
125     \endcode
126
127     This is the standard skeleton of any parser class: We need to inherit senf::PacketParserBase and
128     start out by including either \ref SENF_PARSER() or \ref SENF_FIXED_PARSER(), depending on
129     whether we define a fixed size or a dynamically sized parser. As \c GREPacketParser is
130     dynamically sized, we include \ref SENF_PARSER().
131
132     The definition of fields will be described in the next subsection.
133
134     After the fields have been defined, we need to call the \ref SENF_PARSER_FINALIZE() macro to
135     close of the parser definition. This call takes the name of the parser being defined as it's
136     sole argument.
137
138     This is already a valid parser, albeit not a very usable one, since it does not define any
139     fields. We now go back to define the parser fields and begin with the simple part: fields which
140     are always present.
141
142     \subsection howto_newpacket_parser_simple Simple field definitions
143
144     Packet parser fields are defined using special \ref packetpasermacros. We take the fields
145     directly from the packet definition (the GRE RFC in this case). This will give us to the
146     following code fragment:
147
148     \code
149     SENF_PARSER_BITFIELD  ( checksumPresent, 1, bool     );
150     SENF_PARSER_SKIP_BITS (                 12           );
151     SENF_PARSER_BITFIELD  ( version,         3, unsigned );
152     SENF_PARSER_BITFIELD  ( protocolType,   16, unsigned );
153     \endcode
154     
155     This is a correct \c GREPacket header definition, but there is room for a small optimization:
156     Since the \a protocolType field is exactly 2 bytes wide and is aligned on a byte boundary, we
157     can define it as a UInt16 field (instead of a bitfield):
158     
159     \code
160     SENF_PARSER_BITFIELD  ( checksumPresent,  1, bool     );
161     SENF_PARSER_SKIP_BITS (                  12           );
162     SENF_PARSER_BITFIELD  ( version,          3, unsigned );
163     SENF_PARSER_FIELD     ( protocolType,    senf::UInt16Parser );
164     \endcode
165
166     Whereas \ref SENF_PARSER_BITFIELD can only define bit-fields, \ref SENF_PARSER_FIELD can define
167     almost arbitrary field types. The type is specified by passing the name of another parser to
168     \ref SENF_PARSER_FIELD.
169
170     It is important to understand, that the accessors do \e not return the parsed field value.
171     Instead, they return another \e parser which is used to further interpret the value. This is due
172     to the inherently recursive nature of the SENF packet parsers, that allows us to define rather
173     complex header formats if needed. Of course, at some point we will hit bottom and need real
174     values. This is, what <em>value parsers</em> do: they interpret some bytes or bits and return
175     the value of that field (not a parser). Examples are the bitfield parsers returned by the
176     accessors generated by SENF_PARSER_BITFIELD (like senf::UIntFieldParser) or the
177     senf::UInt16Parser.
178
179     What is going on inside the macros above? Basically, they define accessor functions for a
180     specific field, like \a checksumPresent() or \a protocolType(). They also manage a <em>current
181     Offset</em>. This value is advanced according to the field size whenever a new field is defined
182     (and since this parser is defined as a dynamically sized parser, this offset is not constant but
183     an expression which calculates the offset of a field depending on the preceding data).
184
185     \subsection howto_newpacket_parser_variant Defining optional fields: The 'variant' parser
186
187     The parser is currently very simple, and it could have been defined as a fixed size parser. Now
188     for the tricky part: defining parsers the optional fields. The mechanism described here is
189     suitable for a single optional field as well as for an optional contiguous sequence of fields.
190
191     In our GRE example, there are two fields which need to be enabled/disabled en bloc. We first
192     define an auxiliary sub-parser which combines the two fields.    
193
194     \code
195     struct GREPacketParser_OptFields : public senf::PacketParserBase
196     {
197     #   include SENF_FIXED_PARSER()
198         
199         // typedef checksum_t uint16_t; XXX defined automatically???
200
201         SENF_PARSER_FIELD ( checksum, senf::UInt16Parser );
202         SENF_PARSER_SKIP  (           2                  );
203
204         SENF_PARSER_FINALIZE(GREPacketParser_OptFields);
205     };
206     \endcode
207
208     This parser only parses the two optional fields, the second ("Reserved1") field just being
209     skipped. It is a fixed size parser, as indicated by the SENF_FIXED_PARSER() macro. We can
210     now use \ref SENF_PARSER_VARIANT() to add it as an optional parser to the GRE header in our \c
211     GREPacketParser implementation (the typedef'ed checksum_t will be used later on):
212
213     \code
214     SENF_PARSER_BITFIELD  ( checksumPresent,  1, bool     );
215     SENF_PARSER_SKIP_BITS (                  12           );
216     SENF_PARSER_BITFIELD  ( version,          3, unsigned );
217
218     SENF_PARSER_FIELD     ( protocolType,    senf::UInt16Parser );
219
220     SENF_PARSER_VARIANT   ( optionalFields,  checksumPresent,
221                                              (senf::VoidPacketParser)
222                                              (GREPacketParser_OptFields) );
223     \endcode
224
225     For a variant parser, two things need to be specified: a selector and a list of variant parsers.
226     The selector is a distinct parser field that is used to decide which variant to choose. In this
227     simple case, the field must be an unsigned integer (more precisely: a value parser returning a
228     value which is implicitly convertible to \c unsigned). This value is used as an index into the
229     list of variant types. So in our case, the value 0 (zero) is associated with
230     senf::VoidPacketParser, whereas the value 1 (one) is associated with \c
231     GREPacketParser_OptFields. senf::VoidPacketParser is a special (empty or no-op) parser which is
232     used in a variant to denote a case in which the variant parser should not parse anything.
233
234     This parser will work, it is however not very safe and not very usable. If \a p is a
235     GREPacketParser instance, than we would access the fields via:
236     \code
237     p.checksumPresent()                    = true;
238     p.version()                            = 4u;
239     p.protocolType()                       = 0x86dd;
240     p.optionalFields().get<1>().checksum() = 12345u;
241     \endcode
242     
243     This code has two problems:
244     \li accessing the checksum field is quite unwieldy
245     \li changing the checksumPresent() value will break the parser
246
247     The second problem is caused by the fact that the variant parser needs to be informed whenever
248     the selector (here \a checksumPresent) is changed, since the variant parser must ensure that the
249     header data stays consistent. Whenever the checksumPresent field is enabled, the variant parser
250     needs to insert additional 4 bytes of data. And it must remove those bytes whenever the
251     checksumPresent field is disabled. 
252
253     \subsection howto_newpacket_parser_fixvariant Fixing access by providing custom accessor members
254
255     The problems outlined above will happen whenever we use variant parsers, and they will often
256     occur with other complex parsers too (most XXX \ref parsercollection reference some field
257     external to themselves, and they will break if that value is changed without them knowing about
258     it). There might be other reasons to restrict access to a field: the field may be set
259     automatically or it may be calculated from other values (we'll see later how to do this).
260
261     In all these cases we will want to disallow the user to directly change the value, while still
262     allowing to read the value. To do this, we mark \e value \e fields as read-only:
263
264     \code
265     SENF_PARSER_BITFIELD_RO ( checksumPresent,  1, bool     );
266     \endcode
267
268     \e Value \e fields are fields implemented by parsers returning a simple value (i.e. bit-field,
269     integer and some additional parsers like those parsing network addresses) as apposed to complex
270     sub-parsers.
271
272     In this case however, we still want to allow the user to change the field value, albeit not
273     directly. We will need to go through the collection parser, in this case the variant. Since the
274     variant syntax to change the currently active variant is not very comfortable, we provide some
275     helper functions:
276
277     \code
278     void enableChecksum()  const { optionalFields_().init<1>(); }
279     void disableChecksum() const { optionalFields_().init<0>(); }
280     \endcode
281
282     By changing the collection we automatically change the field, that this collection references.
283     Now we only need to provide an additional \a checksum member to hide the complex variant access
284     syntax from the user. And, since all variant access is now done via specialized members, we can
285     hide the variant field completely from the user:
286     
287     \code
288     SENF_PARSER_PRIVATE_VARIANT ( optionalFields_, checksumPresent,
289                                       (senf::VoidPacketParser)
290                                       (GREPacketParser_OptFields) );
291
292     GREPacketParser_OptFields::checksum_t checksum() const
293         { return optionalFields_().get<1>().checksum(); }
294     \endcode
295
296     As we can see here, we have used the <em>name</em><code>_t</code> typedef which is available for
297     all fields to provide the return value for our accessor member.
298
299     The \c GREPacketParser is now simple and safe to use. The only responsibility of the user now is to
300     only access \a checksum() if the \a checksumPresent() field is set. Otherwise, the behavior is
301     undefined (in debug builds, the parser will terminate the application with an assert).
302
303     
304     \subsection howto_newpacket_parser_add Providing additional functionality
305
306     We have now implemented parsing all the header fields. However, often packets would benefit from
307     additional functionality. In the case of GRE, this could be a function to calculate the checksum
308     value if it is enabled. Defining this member will also show, how to safely access the raw packet
309     data from a parser member.
310
311     \code
312     #include <senf/Utils/IpChecksum.hh>
313
314     checksum_t::value_type calculateChecksum() const 
315     {
316         if (!checksumEnabled()) 
317             return 0;
318
319         senf::IpChecksum cs;
320         cs.feed( i(), i(4) );
321         // Skip even number of 0 bytes (the 2 bytes checksum field)
322         // cs.feed(0); cs.feed(0);
323         cs.feed( i(6), data().end() );
324
325         return cs.sum()
326     }
327     \endcode
328
329     This code just implements what is defined in the RFC: The checksum covers the complete GRE
330     packet including it's header with the checksum field temporarily set to 0. Instead of really
331     changing the checksum field we manually pass the correct data to \a cs. 
332
333     We use the special <tt>i(</tt><i>offset</i><tt>)</tt> helper to get iterators \a offset number
334     of bytes into the data. This helper has the additional benefit of range-checking the returned
335     iterator and is thereby safe from errors due to truncated packets: If the offset is out of
336     range, a TruncatedPacketException will be thrown.
337
338     The \a data() function on the other hand returns a reference to the complete data container of
339     the packet under inspection (the GRE packet in this case). Access to \a data() should be
340     restricted as much as possible. It is safe when defining new packet parsers (parsers, which
341     parser a complete packet like GREPacketParser). It's usage from sub parsers (like
342     GREPacketParser_OptFields or even senf::UInt16Parser) would be much more arcane and should be
343     avoided.
344
345
346     \subsection howto_newpacket_parser_final The complete GREPacketParser implementation
347
348     So this is now the complete implementation of the \c GREPacketParser:
349
350     \code
351     #include <senf/Packets.hh>
352     
353     struct GREPacketParser_OptFields : public senf::PacketParserBase
354     {
355     #   include SENF_FIXED_PARSER()
356
357         SENF_PARSER_FIELD           ( checksum,        senf::UInt16Parser            );
358         SENF_PARSER_SKIP            (                   2                            );
359
360         SENF_PARSER_FINALIZE(GREPacketParser_OptFields);
361     };
362
363     struct GREPacketParser : public senf::PacketParserBase
364     {
365     #   include SENF_PARSER()
366
367         SENF_PARSER_BITFIELD_RO     ( checksumPresent,  1, bool                      );
368         SENF_PARSER_SKIP_BITS       (                  12                            );
369         SENF_PARSER_BITFIELD        ( version,          3, unsigned                  );
370
371         SENF_PARSER_FIELD           ( protocolType,    senf::UInt16Parser            );
372
373         SENF_PARSER_PRIVATE_VARIANT ( optionalFields_, checksumPresent,
374                                                          (senf::VoidPacketParser)
375                                                          (GREPacketParser_OptFields) );
376
377         GREPacketParser_OptFields::checksum_t checksum() const
378             { return optionalFields_().get<1>().checksum(); }
379
380         void enableChecksum()  const { optionalFields_().init<1>(); }
381         void disableChecksum() const { optionalFields_().init<0>(); }
382     
383         SENF_PARSER_FINALIZE(GREPacketParser);
384
385         checksum_t::value_type calculateChecksum() const;
386     };
387
388     // In the implementation (.cc) file:
389
390     #include <senf/Utils/IpChecksum.hh>
391     
392     GREPacketParser::checksum_t::value_type GREPacketParser::calculateChecksum() const
393     {
394         if (!checksumEnabled()) 
395             return 0;
396
397         validate(6);
398         senf::IpChecksum cs;
399         cs.feed( i(), i()+4 );
400         // Skip even number of 0 bytes (the 2 bytes checksum field)
401         // cs.feed(0); cs.feed(0);
402         cs.feed( i()+6, data().end() );
403
404         return cs.sum()
405     }
406     \endcode
407
408
409     \section howto_newpacket_type Defining the packet type
410
411     After defining the packet parser, the <em>packet type</em> must be defined. This class is used
412     as a policy and collects all the information necessary to be known about the packet type.
413
414     The <em>packet type</em> class is \e never instantiated. It has only typedef, constants or
415     static members.
416
417     \subsection howto_newpacket_type_skeleton The packet type skeleton
418
419     For every type of packet, the <em>packet type</em> class will look roughly the same. If the
420     packet uses a registry and is not hopelessly complex, the packet type will almost always
421     look like this:
422
423     \code
424     #include <senf/Packets.hh>
425
426     struct GREPacketType
427         : public senf::PacketTypeBase,
428           public senf::PacketTypeMixin<GREPacketType, EtherTypes>
429     {
430         typedef senf::PacketTypeMixin<GREPacketType, EtherTypes> mixin;
431         typedef senf::ConcretePacket<GREPacketType> packet;
432         typedef senf::GREPacketParser parser;
433     
434         using mixin::nextPacketRange;
435         using mixin::nextPacketType;
436         using mixin::init;
437         using mixin::initSize;
438
439         // Define members here
440     };
441     \endcode
442
443     We note, that it derives from two classes: senf::PacketTypeBase and
444     senf::PacketTypeMixin. senf::PacketTypeBase must be inherited by every packet type class. the
445     senf::PacketTypeMixin provides default implementations for some members which are useful for
446     most kinds of packets. If a packet type is very complex and these defaults don't work, the mixin
447     class can and should be left out. More on this (what the default members do exactly and when the
448     mixin can be used) can be found in the senf::PacketTypeMixin documentation.
449
450     Of the typedefs, only \a parser is mandatory. It defines the packet parser to use to interpret
451     this type of packet. \a mixin and \a packet are defined to simplify the following
452     definitions (More on \a packet and senf::ConcretePacket later).
453
454     The next block of statements imports all the default implementations provided by the mixin
455     class:
456     
457     \li \a nextPacketRange provides information about where the next packet lives within the GRE
458         packet.
459     \li \a nextPacketType provides the type of the next packet from information in the GRE packet.
460     \li \a init is called to initialize a new GRE packet. This call is forwarded to \c
461         GREPacketParser::init.
462     \li \a initSize is called to find the size of an empty (newly create) GRE packet. This is also
463         provided by GREPacketParser.
464     
465     With these default implementations provided by the mixin, only a few additional members are
466     needed to complete the \c GREPacketType: \a nextPacketKey, \a finalize, and \a dump.
467
468
469     \subsection howto_newpacket_type_registry Utilizing the packet registry
470
471     A packet registry maps an arbitrary key value to a type of packet represented by a packet
472     factory instance. There may be any number of packet registries. When working with packet
473     registries, there are three separate steps:
474     \li Using the registry to tell the packet library, what type of packet to instantiate for the
475         payload.
476     \li Given a payload packet of some type, set the appropriate payload type field in the packet
477         header to the correct value (inverse of above).
478     \li Adding packets to the registry.
479
480     We want the GRE packet to utilize the senf::EtherTypes registry to find the type of packet
481     contained in the GRE payload.  The details have already been taken care of by the
482     senf::PacketTypeMixin (it provides the \a nextPacketType member). However, to lookup the packet
483     in the registry, the mixin needs to know the key value. To this end, we implement \a
484     nextPacketKey(), which is very simple:
485
486     \code
487     static key_t nextPacketKey(packet p) { return p->protocolType(); }
488     \endcode
489
490     Since all \c GREPacketType members are static, they are passed the packet in question as an
491     argument. \a nextPacketKey() just needs to return the value of the correct packet field. And
492     since the \c packet type (as defined as a typedef) allows direct access to the packet parser
493     using the <tt>-></tt> operator, we can simply access that value.
494
495     The \c key_t return type is a typedef provided by the mixin class. It is taken from the type of
496     registry, in this case it is senf::EtherTypes::key_t (which is defined as a 16 bit unsigned
497     integer value).
498
499     With this information, the packet library can now find out the type of packet needed to parse
500     the GRE payload -- as long as the \a protocolType() is registered with the senf::EtherTypes
501     registry. If this is not the case, the packet library will not try to interpret the payload, it
502     will return a senf::DataPacket.
503
504     One special case of GRE encapsulation occurs when layer 2 frames and especially ethernet frames
505     are carried in the GRE payload. The ETHERTYPE registry normally only contains layer 3 protocols
506     (like IP or IPX) however for this special case, the value 0x6558 has been added to the ETHERTYPE
507     registry. So we need to add this value to inform the packet library to parse the payload as an
508     ethernet packet if the \a protocolType() is 0x6558. This happens in the implementation file (the
509     \c .cc file):
510
511     \code
512     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
513
514     SENF_PACKET_REGISTRY_REGISTER( senf::EtherTypes, 0x6558, senf::EthernetPacket );
515     \endcode
516
517     This macro registers the value 0x6558 in the senf::EtherTypes registry and associates it with
518     the packet type senf::EthernetPacket. This macro declares an anonymous static variable, it
519     therefore must always be placed in the implementation file and \e never in an include file.
520
521     Additionally, we want the GRE packet to be parsed when present as an IP payload. Therefore we
522     additionally need to register GRE in the senf::IpTypes registry. Looking at the <a
523     href="http://www.iana.org/assignments/protocol-numbers">IP protocol numbers</a>, we find that
524     GRE has been assigned the value 47:
525
526     \code
527     #include <senf/Packets/DefaultBundle/IPv4Packet.hh>
528
529     SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 47, GREPacket );
530     \endcode
531
532     But wait -- what is \c GREPacket ? This question is answered a few section further down.
533     
534     The last thing we need to do is, we need to set the \a protocolType() field to the correct value
535     when packets are newly created or changed. This is done within \a finalize:
536
537     \code
538     static void finalize(packet p) { p->protocolType() << key(p.next(senf::nothrow)); }
539     \endcode
540
541     The \c key() function is provided by the mixin class: It will lookup the \e type of a packet in
542     the registry and return that packets key in the registry. If the key cannot be found, the return
543     value is such that the assignment is effectively skipped.
544
545
546     \subsection howto_newpacket_type_invariants Providing packet invariants
547
548     Many packets have some invariants that must hold: The payload size must be equal to some field,
549     a checksum must match and so on. When packets are newly created or changed, these invariants
550     have to be updated to be correct. This is the responsibility of the \a finalize() member.
551
552     \code
553     static void finalize(packet p) 
554     {
555         p->protocolType() << key(p.next(senf::nothrow));
556         if (p->checksumPresent())
557             p->checksum() << p->calculateChecksum();
558     }
559     \endcode
560
561     We already used finalize above to set the \a protocolType() field. Now we add code to update the
562     \a checksum() field if present (this always needs to be done last since the checksum depends on
563     the other field values).
564
565     Here we are using the more generic parser assignment expressed using the \c << operator. This
566     operator in the most cases works like an ordinary assignment, however it can also be used to
567     assign parsers to each other efficiently and it supports 'optional values' (as provided by <a
568     href="http://www.boost.org/libs/optional/doc/optional.html">Boost.Optional</a> and as returned
569     by \c key()).
570
571
572     \subsection howto_newpacket_type_dump Writing out a complete packet: The 'dump()' member
573
574     For diagnostic purposes, every packet should provide a meaningful \a dump() member which writes
575     out the complete packet. This member is simple to implement and is often very helpful when
576     tracking down problems.
577     
578     \code
579     #include <boost/io/ios_state.hpp>
580
581     static void dump(packet p, std::ostream & os)
582     {
583         boost::io::ios_all_saver ias(os);
584         os << "General Routing Encapsulation:\n"
585            << "  checksum present              : " << p->checksumPresent() ? "true" : "false" << "\n"
586            << "  version                       : " << p->version() << "\n"
587            << "  protocol type                 : 0x" << std::hex << std::setw(4) << std::setfill('0')
588                                                      << p->protocolType() << "\n";
589         if (p->checksumPresent())
590             os << "  checksum                     : 0x" << std::hex << std::setw(4)
591                                                         << std::setfill('0') << p->checksum() << "\n"; 
592     }
593     \endcode
594     
595     This member is quite straight forward. We should try to adhere to the formating standard shown
596     above: The first line should be the type of packet/header being dumped followed by one line for
597     each protocol field. The colon's should be aligned at column 33 with the field name indented by
598     2 spaces. 
599
600     The \c boost::ios_all_saver is just used to ensure, that the stream formatting state is restored
601     correctly at the end of the method. An instance of this type will save the stream state when
602     constructed and will restore that state when destructed.
603
604     \subsection howto_newpacket_type_final Final touches
605
606     The \c GREPacket implementation is now almost complete. The only thing missing is the \c
607     GREPacket itself. \c GREPacket is just a typedef for a specific senf::ConcretePacket template
608     instantiation. Here the complete GREPacket definition:
609
610     \code
611     #include <senf/Packets.hh>
612
613     struct GREPacketType
614         : public senf::PacketTypeBase,
615           public senf::PacketTypeMixin<GREPacketType, EtherTypes>
616     {
617         typedef senf::PacketTypeMixin<GREPacketType, EtherTypes> mixin;
618         typedef senf::ConcretePacket<GREPacketType> packet;
619         typedef senf::GREPacketParser parser;
620     
621         using mixin::nextPacketRange;
622         using mixin::nextPacketType;
623         using mixin::init;
624         using mixin::initSize;
625
626         static key_t nextPacketKey(packet p) { return p->protocolType(); }
627     
628         static void finalize(packet p) {
629             p->protocolType() << key(p.next(senf::nothrow)); 
630             if (p->checksumPresent()) p->checksum() << p->calculateChecksum();
631        }
632     
633         static void dump(packet p, std::ostream & os);
634     };
635
636     typedef GREPacketType::packet GREPacket;
637     
638     // In the implementation (.cc) file:
639
640     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
641     #include <senf/Packets/DefaultBundle/IPv4Packet.hh>
642
643     SENF_PACKET_REGISTRY_REGISTER( senf::EtherTypes, 0x6558, senf::EthernetPacket );
644     SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 47, GREPacket );
645
646     void GREPacketType::dump(packet p, std::ostream & os)
647     {
648         boost::io::ios_all_saver ias(os);
649         os << "General Routing Encapsulation:\n"
650            << "  checksum present              : " << p->checksumPresent() ? "true" : "false" << "\n"
651            << "  version                       : " << p->version() << "\n"
652            << "  protocol type                 : 0x" << std::hex << std::setw(4) << std::setfill('0')
653                                                      << p->protocolType() << "\n";
654         if (p->checksumPresent())
655             os << "  checksum                     : 0x" << std::hex << std::setw(4)
656                                                         << std::setfill('0') << p->checksum() << "\n"; 
657     }
658     \endcode
659
660
661     \section howto_newpacket_advanced Going further
662
663     \subsection howto_newpacket_advanced_valid Checking the GRE packet for validity
664
665     We now know how to define packets, but there is more. In this section we will explore the
666     features available to make the packet chaining more flexible. We will show, how to implement
667     more complex logic than simple registry lookup to find the nested packet (the payload) type.
668
669     In our concrete example, reading the RFC we find there are some restrictions which a GRE packet
670     needs to obey to be considered valid. If the packet is not valid it cannot be parsed and should
671     be dropped. We can't drop it here but if the packet is invalid, we certainly must refrain from
672     trying to parser any payload since we cannot assume the packet to have the format we assume our
673     GRE packet to have. 
674
675     There are two conditions defined in the RFC which render a GRE packet invalid: If one of the \a
676     reserved0() fields first 5 bits is set or if the version is not 0. We will add a \a valid()
677     check to the parser and utilize this check in the packet type.
678
679     So first lets update the parser. We will need to change the fields a little bit so we have
680     access to the first 5 bits of \a reserved0. We therefore replace the first three field
681     statements with
682
683     \code
684     SENF_PARSER_BITFIELD_RO      ( checksumPresent,  1, bool                      );
685     SENF_PARSER_PRIVATE_BITFIELD ( reserved0_5bits_, 5, unsigned                  );
686     SENF_PARSER_SKIP_BITS        (                   7                            );
687     SENF_PARSER_BITFIELD_RO      ( version,          3, unsigned                  );
688     \endcode
689
690     We have added an additional private bitfield \a reserved0_5bits_() and we made the \a version()
691     field read-only.
692
693     We will now add a simple additional member to the parser:
694
695     \code
696     bool valid() const { return version() == 0 && reserved0_5bits_() == 0; }
697     \endcode
698
699     I think, this is quite straight forward: \a valid() will just check the restrictions as defined
700     in the RFC.
701
702     Now to the packet type. We want to refrain from parsing the payload if the packet is
703     invalid. This is important: If the packet is not valid, we have no idea, whether the payload is
704     what we surmise it to be (if any of the \a reserved0_5bits_() are set, the packet is from an
705     older GRE RFC and the header is quite a bit longer so the payload will be incorrect).
706
707     So we need to change the logic which is used by the packet library to find the type of the next
708     packet. We have two ways to do this: We keep using the default \c nextPacketType()
709     implementation as provided by the senf::PacketTypeMixin and have our \a nextPacketKey()
710     implementation return a key value which is guaranteed never to be registered in the registry.
711
712     The more flexible possibility is implementing \c nextPacketType() ourselves. In this case, the
713     first method would suffice, but we will choose to go the second route to show how to write the
714     \c nextPacketType() member. We therefore remove the \c using declaration of \c nextPacketType()
715     and also remove the \a nextPacketKey() implementation. Instead we add the following to the
716     packet type
717
718     \code
719     // disabled: using mixin::nextPacketType;
720
721     factory_t nextPacketType(packet p) { return p->valid() ? lookup(p->protocolType()) : no_factory(); }
722     \endcode
723     
724     As we see, this is still quite simple. \c factory_t is provided by senf::PacketTypeBase. For our
725     purpose it is an opaque type which somehow enables the packet library to create a new packet of
726     a specified packet type. The \c factory_t has a special value, \c no_factory() which stands for
727     the absence of any concrete factory. In a boolean context this (and only this) \c factory_t
728     value tests \c false.
729
730     The \c lookup() member is provided by the senf::PacketTypeMixin. It looks up the key passed as
731     argument in the registry and returns the factory or \c no_factory(), if the key was not found in
732     the registry.
733
734     In this case this is all. But let's elaborate on this example. What if we need to return some
735     specific factory from \a nextPacketType(), e.g. what, if we want to handle the case of
736     transparent ethernet bridging explicitly instead of registering the value in the
737     senf::EtherTypes registry ? Here one way to do this:
738
739     \code
740     factory_t nextPacketType(packet p) { 
741         if (p->valid()) {
742             if (p->protocolType() == 0x6558)  return senf::EthernetPacket::factory();
743             else                              return lookup(p->protocolType());
744         }
745         else                                  return no_factory();
746     }
747     \endcode
748
749     As can be seen above, every packet type has a (static) \a factory() member which returns the
750     factory for this type of packet.
751
752
753     \subsection howto_newpacket_advanced_init Non-trivial packet initialization
754
755     Every packet when created is automatically initialized with 0 bytes (all data bytes will be
756     0). In the case of GRE this is enough. But other packets will need other more complex
757     initialization to be performed.
758
759     Lets just for the sake of experiment assume, the GRE packet would have to set \a version() to 1
760     not 0. In this case, the default initialization would not suffice. It is however very simple to
761     explicitly initialize the packet. The initialization happens within the parser. We just add
762
763     \code
764     SENF_PARSER_INIT() { version_() << 1u; }
765     \endcode
766
767     to \c GREPacketParser. For every read-only defined field, the macros automatically define a \e
768     private read-write accessor which may be used internally. This read-write accessor is used here
769     to initialize the value.
770
771
772     \section howto_newpacket_final The ultimate GRE packet implementation completed
773
774     So here we now have \c GREPacket finally complete in all it's glory. First the header file \c
775     GREPacket.hh:
776
777     \code
778     #ifndef HH_GREPacket_
779     #define HH_GREPacket_
780
781     #include <senf/Packets.hh>
782     
783     struct GREPacketParser_OptFields : public senf::PacketParserBase
784     {
785     #   include SENF_FIXED_PARSER()
786
787         SENF_PARSER_FIELD           ( checksum,        senf::UInt16Parser            );
788         SENF_PARSER_SKIP            (                   2                            );
789
790         SENF_PARSER_FINALIZE(GREPacketParser_OptFields);
791     };
792
793     struct GREPacketParser : public senf::PacketParserBase
794     {
795     #   include SENF_PARSER()
796
797         SENF_PARSER_BITFIELD_RO      ( checksumPresent,  1, bool                      );
798         SENF_PARSER_PRIVATE_BITFIELD ( reserved0_5bits_, 5, unsigned                  );
799         SENF_PARSER_SKIP_BITS        (                   7                            );
800         SENF_PARSER_BITFIELD_RO      ( version,          3, unsigned                  );
801
802         SENF_PARSER_FIELD            ( protocolType,    senf::UInt16Parser            );
803
804         SENF_PARSER_PRIVATE_VARIANT  ( optionalFields_, checksumPresent,
805                                                           (senf::VoidPacketParser)
806                                                           (GREPacketParser_OptFields) );
807
808         bool valid() const { return version() == 0 && reserved0_5bits_() == 0; }
809
810         typedef GREPacketParser_OptFields::checksum_t checksum_t;
811         checksum_t checksum() const
812             { return optionalFields_().get<1>().checksum(); }
813
814         void enableChecksum()  const { optionalFields_().init<1>(); }
815         void disableChecksum() const { optionalFields_().init<0>(); }
816     
817         SENF_PARSER_FINALIZE(GREPacketParser);
818
819         checksum_t::value_type calculateChecksum() const;
820     };
821
822     struct GREPacketType
823         : public senf::PacketTypeBase,
824           public senf::PacketTypeMixin<GREPacketType, EtherTypes>
825     {
826         typedef senf::PacketTypeMixin<GREPacketType, EtherTypes> mixin;
827         typedef senf::ConcretePacket<GREPacketType> packet;
828         typedef senf::GREPacketParser parser;
829     
830         using mixin::nextPacketRange;
831         using mixin::init;
832         using mixin::initSize;
833
834         factory_t nextPacketType(packet p) 
835             { return p->valid() ? lookup(p->protocolType()) : no_factory(); }
836     
837         static void finalize(packet p) {
838             p->protocolType() << key(p.next(senf::nothrow));
839             if (p->checksumPresent()) p->checksum() << p->calculateChecksum();
840         }
841     
842         static void dump(packet p, std::ostream & os);
843     };
844
845     typedef GREPacketType::packet GREPacket;
846     
847     #endif
848     \endcode
849
850     And the implementation file \c GREPacket.cc:
851
852     \code
853     #include "GREPacket.hh"
854     #include <senf/Utils/IpChecksum.hh>
855     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
856     #include <senf/Packets/DefaultBundle/IPv4Packet.hh>
857
858     SENF_PACKET_REGISTRY_REGISTER( senf::EtherTypes, 0x6558, senf::EthernetPacket );
859     SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 47, GREPacket );
860
861     GREPacketParser::checksum_t::value_type GREPacketParser::calculateChecksum() const
862     {
863         if (!checksumEnabled()) 
864             return 0;
865
866         validate(6);
867         senf::IpChecksum cs;
868         cs.feed( i(), i()+4 );
869         // Skip even number of 0 bytes (the 2 bytes checksum field)
870         // cs.feed(0); cs.feed(0);
871         cs.feed( i()+6, data().end() );
872
873         return cs.sum()
874     }
875
876     void GREPacketType::dump(packet p, std::ostream & os)
877     {
878         boost::io::ios_all_saver ias(os);
879         os << "General Routing Encapsulation:\n"
880            << "  checksum present              : " << p->checksumPresent() ? "true" : "false" << "\n"
881            << "  version                       : " << p->version() << "\n"
882            << "  protocol type                 : 0x" << std::hex << std::setw(4) << std::setfill('0')
883                                                      << p->protocolType() << "\n";
884         if (p->checksumPresent())
885             os << "  checksum                     : 0x" << std::hex << std::setw(4)
886                                                         << std::setfill('0') << p->checksum() << "\n"; 
887     }
888     \endcode
889
890
891     \section howto_newpacket_using Using the newly created GRE packet type
892
893     The GRE packet is now fully integrated into the packet library framework. For example, we can
894     read GRE packets from a raw INet socket and forward decapsulated Ethernet frames to a packet
895     socket.
896
897     \code
898     #include <iostream>
899     #include <senf/Packets.hh>
900     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
901     #include <senf/Socket/Protocols/INet/RawINetProtocol.hh>
902     #include <senf/Socket/Protocols/Raw/PacketSocketHandle.hh>
903     #include "GREPacket.hh"
904
905     int main(int, char const **)
906     {
907         senf::RawV6ClientSocketHandle isock (47u); // 47 = Read GRE packets
908         senf::PacketSocketHandle osock;
909
910         while (true) {
911             try {
912                 GREPacket gre (GREPacket::create(senf::noinit));
913                 isock.read(gre.data(),0u);
914                 if (gre->checksumPresent() && gre->checksum() != gre->calculateChecksum())
915                     throw InvalidPacketChainException();
916                 osock.write(gre.next<EthernetPacket>().data())
917             }
918             catch (senf::TruncatedPacketException & ex) {
919                 std::cerr << "Malformed packet dropped\n";
920             }
921             catch (senf::InvalidPacketChainException & ex) {
922                 std::cerr << "Invalid GRE packet dropped\n";
923             }
924         }
925     }
926     \endcode
927
928     Or we can do the opposite: Read ethernet packets from a \c tap device and send them out GRE
929     encapsulated.
930
931     \code
932     #include <iostream>
933     #include <senf/Packets.hh>
934     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
935     #include <senf/Socket/Protocols/INet/RawINetProtocol.hh>
936     #include <senf/Socket/Protocols/Raw/TunTapSocketHandle.hh>
937     #include "GREPacket.hh"
938
939     int main(int argc, char const ** argv)
940     {
941         if (argc != 2) {
942             std::cerr << "Usage: " << argv[0] << " <tunnel endpoint>\n";
943             return 1;
944         }
945
946         senf::TapSocketHandle tap ("tap0");
947         senf::ConnectedRawV6ClientSocketHandle osock (47u, senf::INet6SocketAddress(argv[1]));
948     
949         while (true) {
950             senf::EthernetPacket eth (senf::EthernetPacket::create(senf::noinit));
951             isock.read(eth.data(),0u);
952             GREPacket gre (senf::GREPacket::createBefore(eth));
953             gre.finalize();
954             osock.write(gre.data());
955         }
956     }
957     \endcode
958
959     
960     \section howto_newpacket_further Further reading
961
962     Lets start with references to the important API's (Use the <i>List of all members</i> link to
963     get the complete API of one of the classes and templates):
964
965     <table class="senf fixedcolumn">
966
967     <tr><td>senf::ConcretePacket</td> <td>this is the API provided by the packet handles.</td></tr>
968
969     <tr><td>senf::PacketData</td> <td>this API provides raw data access accessible via the handles
970     'data' member.</td></tr>
971
972     <tr><td>senf::PacketParserBase</td> <td>this is the generic parser API. This API is accessible
973     via the packets \c -> operator or via the sub-parsers returned by the field accessors.</td></tr>
974
975     </table>
976
977     When implementing new packet's, the following information will be helpful:
978
979     <table class="senf fixedcolumn">
980     
981     <tr><td>senf::PacketTypeBase</td> <td>here you find a description of the members which need to
982     be implemented to provide a 'packet type'. Most of these members will normally be provided by
983     the mixin helper.</td></tr>
984
985     <tr><td>senf::PacketTypeMixin</td> <td>here you find all about the packet type mixin and how to
986     use it.</td></tr>
987
988     <tr><td>\ref packetparser</td> <td>This section describes the packet parser facility.</td></tr>
989     
990     <tr><td>\link packetparsermacros Packet parser macros\endlink</td> <td>A complete list and
991     documentation of all the packet parser macros.</td></tr>
992     
993     <tr><td>\ref parseint, \n \ref parsecollection</td> <td>There are several lists of available
994     reusable packet parsers. However, these lists are not complete as there are other protocol
995     specific reusable parsers (without claiming to be exhaustive: senf::INet4AddressParser,
996     senf::INet6AddressParser, senf::MACAddressParser)</td></tr>
997
998     </table>
999
1000  */
1001
1002 \f
1003 // Local Variables:
1004 // mode: c++
1005 // fill-column: 100
1006 // comment-column: 40
1007 // c-file-style: "senf"
1008 // indent-tabs-mode: nil
1009 // ispell-local-dictionary: "american"
1010 // compile-command: "scons -u doc"
1011 // mode: auto-fill
1012 // End:
1013 // vim:filetype=doxygen:textwidth=100: