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