139514793d502b6ed482a15d138dfd6bab1dd03c
[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 HowTo: 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::PacketParser
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::PacketParser 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 dynamically
92     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::PacketParser
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::PacketParser
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::PacketParser
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 need now 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.
409
410     Of the typedefs, only \a parser is mandatory. It defines the packet parser to use to interpret
411     this type of packet. \a mixin and \a packet are defined to simplify the following
412     definitions (More on \a packet and senf::ConcretePacket later).
413
414     The next block of statements imports all the default implementations provided by the mixin
415     class:
416     
417     \li \a nextPacketRange provides information about where the next packet lives within the GRE
418         packet.
419     \li \a nextPacketType provides the type of the next packet from information in the GRE packet.
420     \li \a init is called to initialize a new GRE packet. This call is forwarded to \c
421         GREPacketParser::init.
422     \li \a initSize is called to find the size of an empty (newly create) GRE packet. This is also
423         provided by GREPacketParser.
424     
425     With these default implementations provided by the mixin, only a few additional members are
426     needed to complete the \c GREPacketType: \a nextPacketKey, \a finalize, and \a dump
427
428
429     \subsection howto_newpacket_type_registry Utilizing the packet registry
430
431     We want the GRE packet to utilize the senf::EtherTypes registry to find the type of packet
432     contained in the GRE payload. A registry maps an arbitrary key value to a packet type
433     represented by a packet factory instance. The details have already been taken care of by the
434     senf::PacketTypeMixin (it provides the \a nextPacketType member). However, to lookup the packet
435     in the registry, the mixin needs to know the key value. To this end, we implement \a
436     nextPacketKey(), which is very simple:
437
438     \code
439     static key_t nextPacketKey(packet p) { return p->protocolType(); }
440     \endcode
441
442     All \c GREPacketType members are static. They are passed the packet in question as an
443     argument. \a nextPacketKey() just needs to return the value of the correct packet field. And
444     since the \c parser type (as defined as a typedef) allows direct access to the packet parser
445     using the <tt>-></tt> operator, we can simply access that value.
446
447     The \c key_t return type is a typedef provided by the mixin class it is taken from the type of
448     registry, in this case it is senf::EtherTypes::key_t (which is defined as a 16 bit unsigned
449     integer value).
450
451     With this information, the packet library can now find out the type of packet needed to parse
452     the GRE payload -- as long as the protocolType() is registered with the senf::EtherTypes
453     registry. If this is not the case, the packet library will not try to interpret the payload, it
454     will return a senf::DataPacket.
455
456     One special case of GRE encapsulation occurs when layer 2 frames and especially ethernet frames
457     are carried in the GRE payload. The ETHERTYPE registry normally only contains layer 3 protocols
458     (like IP or IPX) however for this special case, the value 0x6558 has been added to the ETHERTYPE
459     registry. So we need to add this value to inform the packet library to parse the payload as an
460     ethernet packet if the \a protocolType() is 0x6558. This happens in the implementation file (the
461     \c .cc file):
462
463     \code
464     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
465
466     SENF_PACKET_REGISTRY_REGISTER( senf::EtherTypes, 0x6558, senf::EthernetPacket );
467     \endcode
468
469     This macro registers the value 0x6558 in the senf::EtherTypes registry and associates it with
470     the packet type senf::EthernetPacket. This macro declares an anonymous static variable, it
471     therefore must always be placed in the implementation file and \e never in an include file.
472
473     Additionally, we want the GRE packet to be parsed when present as an IP payload. Therefore we
474     additionally need to register GRE in the senf::IpTypes registry. Looking at the <a
475     href="http://www.iana.org/assignments/protocol-numbers">IP protocol numbers</a>, we find that
476     GRE has been assigned the value 47:
477
478     \code
479     #include <senf/Packets/DefaultBundle/IPv4Packet.hh>
480
481     SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 47, GREPacket );
482     \endcode
483
484     But wait -- what is \c GREPacket ? This question is answered a few section further down.
485
486
487     \subsection howto_newpacket_type_invariants Providing packet invariants
488
489     Many packets have some invariants that must hold: The payload size must be equal to some field,
490     a checksum must match and so on. When packets are newly created or changed, these invariants
491     have to be updated to be correct. This is the responsibility of the \a finalize() member. This
492     is also the place, where the \a protocolType() field is assigned.
493
494     \code
495     static void finalize(packet p) 
496     {
497         if (p->checksumPresent())
498             p->checksum() << p->calculateChecksum();
499         p->protocolType() << key(p.next(senf::nothrow));
500     }
501     \endcode
502     
503     \a finalize() first updates the \a checksum() field if present. It then sets the \a
504     protocolType() field depending on the \e next packet. The \c key() function is provided by the
505     mixin class: It will lookup the \e type of a packet in the registry and return that packets key
506     in the registry.
507
508     Here we are using the more generic parser assignment expressed using the \c << operator. This
509     operator in the most cases works like an ordinary assignment, however it can also be used to
510     assign parsers to each other efficiently and it supports 'optional values' (as provided by <a
511     href="http://www.boost.org/libs/optional/doc/optional.html">Boost.Optional</a> and as returned
512     by \c key()).
513
514
515     \subsection howto_newpacket_type_dump Writing out a complete packet: The 'dump()' member
516
517     For diagnostic purposes, every packet should provide a meaningful \a dump() member which writes
518     out the complete packet. This member is simple to implement and is often very helpful when
519     tracking down problems.
520     
521     \code
522     #include <boost/io/ios_state.hpp>
523
524     static void dump(packet p, std::ostream & os)
525     {
526         boost::io::ios_all_saver ias(os);
527         os << "General Routing Encapsulation:\n"
528            << "  checksum present              : " << p->checksumPresent() ? "true" : "false" << "\n"
529            << "  version                       : " << p->version() << "\n"
530            << "  protocol type                 : 0x" << std::hex << std::setw(4) << std::setfill('0')
531                                                      << p->protocolType() << "\n";
532         if (p->checksumPresent())
533             os << "  checksum                     : 0x" << std::hex << std::setw(4)
534                                                         << std::setfill('0') << p->checksum() << "\n"; 
535     }
536     \endcode
537     
538     This member is quite straight forward. We should try to adhere to the formating standard shown
539     above: The first line should be the type of packet/header being dumped followed by one line for
540     each protocol field. The colon's should be aligned at column 33 with the field name indented by
541     2 spaces. 
542
543     The \c boost::ios_all_saver is just used to ensure, that the stream formatting state is restored
544     correctly at the end of the method. An instance of this type will save the stream state when
545     constructed and will restore that state when destructed.
546
547     \subsection howto_newpacket_type_final Final touches
548
549     The \c GREPacket implementation is now almost complete. The only thing missing is the \c
550     GREPacket itself. \c GREPacket is just a typedef for a specific senf::ConcretePacket template
551     instantiation. Here the complete GREPacket definition:
552
553     \code
554     #include <senf/Packets.hh>
555
556     struct GREPacketType
557         : public senf::PacketTypeBase,
558           public senf::PacketTypeMixin<GREPacketType, EtherTypes>
559     {
560         typedef senf::PacketTypeMixin<GREPacketType, EtherTypes> mixin;
561         typedef senf::ConcretePacket<GREPacketType> packet;
562         typedef senf::GREPacketParser parser;
563     
564         using mixin::nextPacketRange;
565         using mixin::nextPacketType;
566         using mixin::init;
567         using mixin::initSize;
568
569         static key_t nextPacketKey(packet p) { return p->protocolType(); }
570     
571         static void finalize(packet p) {
572             if (p->checksumPresent()) p->checksum() << p->calculateChecksum();
573             p->protocolType() << key(p.next(senf::nothrow));
574         }
575     
576         static void dump(packet p, std::ostream & os);
577     };
578
579     typedef GREPacketType::packet GREPacket;
580     
581     // In the implementation (.cc) file:
582
583     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
584     #include <senf/Packets/DefaultBundle/IPv4Packet.hh>
585
586     SENF_PACKET_REGISTRY_REGISTER( senf::EtherTypes, 0x6558, senf::EthernetPacket );
587     SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 47, GREPacket );
588
589     void GREPacketType::dump(packet p, std::ostream & os)
590     {
591         boost::io::ios_all_saver ias(os);
592         os << "General Routing Encapsulation:\n"
593            << "  checksum present              : " << p->checksumPresent() ? "true" : "false" << "\n"
594            << "  version                       : " << p->version() << "\n"
595            << "  protocol type                 : 0x" << std::hex << std::setw(4) << std::setfill('0')
596                                                      << p->protocolType() << "\n";
597         if (p->checksumPresent())
598             os << "  checksum                     : 0x" << std::hex << std::setw(4)
599                                                         << std::setfill('0') << p->checksum() << "\n"; 
600     }
601     \endcode
602
603
604     \section howto_newpacket_advanced Going further
605
606     \subsection howto_newpacket_advanced_valid Checking the GRE packet for validity
607
608     We have implemented the \c GREPacket completely by now. There is however still room for
609     improvement. Reading the RFC, there are some restrictions which a packet needs to obey to be
610     considered valid. If the packet is not valid it cannot be parsed and should be dropped. There
611     are two conditions which lead to this: If one of the \a reserved0 fields first 5 bits is set or
612     if the version is not 0. We will add a \a valid() check to the parser and utilize this check in
613     the packet type.
614
615     So first lets update the parser. We will need to change the fields a little bit so we have
616     access to the first 5 bits of \a reserved0. We therefore replace the first three field
617     statements with
618
619     \code
620     SENF_PARSER_BITFIELD_RO      ( checksumPresent,  1, bool                      );
621     SENF_PARSER_PRIVATE_BITFIELD ( reserved0_5bits_, 5, unsigned                  );
622     SENF_PARSER_SKIP_BITS        (                   7                            );
623     SENF_PARSER_PRIVATE_BITFIELD ( version_,         3, unsigned                  );
624     \endcode
625
626     We have added an additional private bitfield \a reserved0_5bits_() and we made the \a version_()
627     field private since we do not want the user to change the value. We could have used a read-only
628     field in this special case (since the valid value is 0) but generally in a case like this since
629     the field will be initialized by the parser (see next section on how). the field should be
630     private with an additional public read-only accessor.
631
632     We will now add two additional simple members to the parser
633
634     \code
635     typedef version__t version_t;
636     version_t::value_type version() const { return version_(); }
637
638     bool valid() const { return version() == 0 && reserved0_5bits_() == 0; }
639     \endcode
640
641     I think, both are quite straight forward: \a version() will allow the user to read out the value
642     of the version field. However, since it does \e not return a parser but a numeric value, the
643     access is read-only. The \a valid() member will just check the restrictions as defined in the RFC.
644
645     Now to the packet type. We want to refrain from parsing the payload if the packet is
646     invalid. This is important: If the packet is not valid, we have no idea, whether the payload is
647     what we surmise it to be (if any of the \a reserved0_5bits_() are set, the packet is from an
648     older GRE RFC and the header is quite a bit longer so the payload will be incorrect).
649
650     So we need to change the logic which is used by the packet library to find the type of the next
651     packet. We have two ways to do this: We keep using the default \c nextPacketType()
652     implementation as provided by the senf::PacketTypeMixin and have our \a nextPacketKey()
653     implementation return a key value which is guaranteed never to be registered in the registry.
654
655     The more flexible possibility is implementing \c nextPacketType() ourselves. In this case, the
656     first method would suffice, but we will choose to go the second route to show how to write the
657     \c nextPacketType() member. We therefore remove the \c using declaration of \c nextPacketType()
658     and also remove the \a nextPacketKey() implementation. Instead we add the following to the
659     packet type
660
661     \code
662     // disabled: using Min::nextPacketType;
663
664     factory_t nextPacketType(packet p) { return p->valid() ? lookup(p->protocolType()) : no_factory(); }
665     \endcode
666     
667     As we see, this is still quite simple. \c factory_t is provided by senf::PacketTypeBase. For our
668     purpose it is an opaque type which somehow enables the packet library to create a new packet of
669     a specified packet type. The \c factory_t has a special value, \c no_factory() which stands for
670     the absence of any concrete factory. In a boolean context this (and only this) \c factory_t
671     value tests \c false.
672
673     The \c lookup() member is provided by the senf::PacketTypeMixin. It looks up the key passed as
674     argument in the registry and returns the factory or \c no_factory(), if the key was not found in
675     the registry.
676
677     In this case this is all. We can however return the factory for some specific type easily as in
678     the following example:
679
680     \code
681     factory_t nextPacketType(packet p) { 
682         if (p->valid()) {
683             if (p->protocolType() == 0x6558)  return senf::EthernetPacket::factory();
684             else                              return lookup(p->protocolType());
685         }
686         else                                  return no_factory();
687     }
688     \endcode
689
690     Of course, this example is academic since senf::EthernetPacket is correctly registered in the
691     senf::EtherTypes registry but you get the picture.
692
693
694     \subsection howto_newpacket_advanced_init Non-trivial packet initialization
695
696     When we create a new GRE packet using the packet library, the library will initialize the packet
697     with all 0 bytes. It just happens, that this is correct for our GRE packet. Lets just for the
698     sake of experiment assume, the GRE packet would have to set \a version() to 1 not 0. In this
699     case, the default initialization would not suffice. It is however very simple to explicitly
700     initialize the packet. The initialization happens within the parser. We just add
701
702     \code
703     SENF_PARSER_INIT() { version_() << 1u; }
704     \endcode
705
706     to \c GREPacketParser. Here we see, why we have defined \a version_() as a private and not a
707     read-only field.
708
709
710     \section howto_newpacket_final The ultimate GRE packet implementation completed
711
712     So here we now have \c GREPacket finally complete in all it's glory. First the header file \c
713     GREPacket.hh:
714
715     \code
716     #ifndef GRE_PACKET_HH
717     #define GRE_PACKET_HH
718
719     #include <senf/Packets.hh>
720     
721     struct GREPacketParser_OptFields : public senf::PacketParser
722     {
723     #   include SENF_FIXED_PARSER()
724
725         SENF_PARSER_FIELD           ( checksum,        senf::UInt16Parser            );
726         SENF_PARSER_SKIP            (                   2                            );
727
728         SENF_PARSER_FINALIZE(GREPacketParser_OptFields);
729     };
730
731     struct GREPacketParser : public senf::PacketParser
732     {
733     #   include SENF_PARSER()
734
735         SENF_PARSER_BITFIELD_RO      ( checksumPresent,  1, bool                      );
736         SENF_PARSER_PRIVATE_BITFIELD ( reserved0_5bits_, 5, unsigned                  );
737         SENF_PARSER_SKIP_BITS        (                   7                            );
738         SENF_PARSER_PRIVATE_BITFIELD ( version_,         3, unsigned                  );
739
740         SENF_PARSER_FIELD            ( protocolType,    senf::UInt16Parser            );
741
742         SENF_PARSER_PRIVATE_VARIANT  ( optionalFields_, checksumPresent,
743                                                           (senf::VoidPacketParser)
744                                                           (GREPacketParser_OptFields) );
745
746         typedef version__t version_t;
747         version_t::value_type version() const { return version_(); }
748
749         bool valid() const { return version() == 0 && reserved0_5bits_() == 0; }
750
751         typedef GREPacketParser_OptFields::checksum_t checksum_t;
752         checksum_t checksum() const
753             { return optionalFields_().get<1>().checksum(); }
754
755         void enableChecksum()  const { optionalFields_().init<1>(); }
756         void disableChecksum() const { optionalFields_().init<0>(); }
757     
758         SENF_PARSER_FINALIZE(GREPacketParser);
759
760         checksum_t::value_type calculateChecksum() const;
761     };
762
763     struct GREPacketType
764         : public senf::PacketTypeBase,
765           public senf::PacketTypeMixin<GREPacketType, EtherTypes>
766     {
767         typedef senf::PacketTypeMixin<GREPacketType, EtherTypes> mixin;
768         typedef senf::ConcretePacket<GREPacketType> packet;
769         typedef senf::GREPacketParser parser;
770     
771         using mixin::nextPacketRange;
772         using mixin::init;
773         using mixin::initSize;
774
775         factory_t nextPacketType(packet p) 
776             { return p->valid() ? lookup(p->protocolType()) : no_factory(); }
777     
778         static void finalize(packet p) {
779             if (p->checksumPresent()) p->checksum() << p->calculateChecksum();
780             p->protocolType() << key(p.next(senf::nothrow));
781         }
782     
783         static void dump(packet p, std::ostream & os);
784     };
785
786     typedef GREPacketType::packet GREPacket;
787     
788     #endif
789     \endcode
790
791     And the implementation file \c GREPacket.cc:
792
793     \code
794     #include "GREPacket.hh"
795     #include <senf/Utils/IpChecksum.hh>
796     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
797     #include <senf/Packets/DefaultBundle/IPv4Packet.hh>
798
799     SENF_PACKET_REGISTRY_REGISTER( senf::EtherTypes, 0x6558, senf::EthernetPacket );
800     SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 47, GREPacket );
801
802     GREPacketParser::checksum_t::value_type GREPacketParser::calculateChecksum() const
803     {
804         if (!checksumEnabled()) 
805             return 0;
806
807         validate(6);
808         senf::IpChecksum cs;
809         cs.feed( i(), i()+4 );
810         // Skip even number of 0 bytes (the 2 bytes checksum field)
811         // cs.feed(0); cs.feed(0);
812         cs.feed( i()+6, data().end() );
813
814         return cs.sum()
815     }
816
817     void GREPacketType::dump(packet p, std::ostream & os)
818     {
819         boost::io::ios_all_saver ias(os);
820         os << "General Routing Encapsulation:\n"
821            << "  checksum present              : " << p->checksumPresent() ? "true" : "false" << "\n"
822            << "  version                       : " << p->version() << "\n"
823            << "  protocol type                 : 0x" << std::hex << std::setw(4) << std::setfill('0')
824                                                      << p->protocolType() << "\n";
825         if (p->checksumPresent())
826             os << "  checksum                     : 0x" << std::hex << std::setw(4)
827                                                         << std::setfill('0') << p->checksum() << "\n"; 
828     }
829     \endcode
830
831
832     \section howto_newpacket_using Using the newly created GRE packet type
833
834     The GRE packet is now fully integrated into the packet library framework. For example, we can
835     read GRE packets from a raw INet socket and forward decapsulated Ethernet frames to a packet
836     socket.
837
838     \code
839     #include <iostream>
840     #include <senf/Packets.hh>
841     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
842     #include <senf/Socket/Protocols/INet/RawINetProtocol.hh>
843     #include <senf/Socket/Protocols/Raw/PacketSocketHandle.hh>
844     #include "GREPacket.hh"
845
846     int main(int, char const **)
847     {
848         senf::RawV6ClientSocketHandle isock (47u); // 47 = Read GRE packets
849         senf::PacketSocketHandle osock;
850
851         while (1) {
852             try {
853                 GREPacket gre (GREPacket::create(senf::noinit));
854                 isock.read(gre.data(),0u);
855                 if (gre->checksumPresent() && gre->checksum() != gre->calculateChecksum())
856                     throw InvalidPacketChainException();
857                 osock.write(gre.next<EthernetPacket>().data())
858             }
859             catch (senf::TruncatedPacketException & ex) {
860                 std::cerr << "Malformed packet dropped\n";
861             }
862             catch (senf::InvalidPacketChainException & ex) {
863                 std::cerr << "Invalid GRE packet dropped\n";
864             }
865         }
866     }
867     \endcode
868
869     Or we can do the opposite: Read ethernet packets from a \c tap device and send them out GRE
870     encapsulated.
871
872     \code
873     #include <iostream>
874     #include <senf/Packets.hh>
875     #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
876     #include <senf/Socket/Protocols/INet/RawINetProtocol.hh>
877     #include <senf/Socket/Protocols/Raw/TunTapSocketHandle.hh>
878     #include "GREPacket.hh"
879
880     int main(int argc, char const ** argv)
881     {
882         if (argc != 2) {
883             std::cerr << "Usage: " << argv[0] << " <tunnel endpoint>\n";
884             return 1;
885         }
886
887         senf::TapSocketHandle tap ("tap0");
888         senf::ConnectedRawV6ClientSocketHandle osock (47u, senf::INet6SocketAddress(argv[1]));
889     
890         while (1) {
891             senf::EthernetPacket eth (senf::EthernetPacket::create(senf::noinit));
892             isock.read(eth.data(),0u);
893             GREPacket gre (senf::GREPacket::createBefore(eth));
894             gre.finalize();
895             osock.write(gre.data());
896         }
897     }
898     \endcode
899
900     
901     \section howto_newpacket_further Further reading
902
903     Lets start with references to the important API's (Use the 'Show all members' link to get the
904     complete API of one of the classes and templates):
905
906     \li senf::ConcretePacket : this is the API provided by the packet handles.
907     \li senf::PacketData : this API provides raw data access accessible via the handles 'data'
908         member.
909     \li senf::PacketParserBase : this is the generic parser API. This API is accessible via the
910         packets \c -> operator or via the sub-parsers returned by the field accessors.
911
912     When implementing new packet's, the following information will be helpful:
913
914     \li senf::PacketTypeBase : here you find a description of the members which need to be
915         implemented to provide a 'packet type'. Most of these members will normally be provided by
916         the mixin helper.
917     \li senf::PacketTypeMixin : here you find all about the packet type mixin and how to use it.
918     \li \ref packetparser : This section describes the packet parser facility.
919     \li \ref packetparsermacros : A complete list and documentation of all the packet parser macros.
920     \li There are several lists of available reusable packet parsers: \ref parseint, \ref
921         parsecollection. However, this list is not complete as there are other protocol specific
922         reusable parsers (without claiming to be exhaustive: senf::INet4AddressParser,
923         senf::INet6AddressParser, senf::MACAddressParser)
924
925  */
926
927 \f
928 // Local Variables:
929 // mode: c++
930 // fill-column: 100
931 // comment-column: 40
932 // c-file-style: "senf"
933 // indent-tabs-mode: nil
934 // ispell-local-dictionary: "american"
935 // compile-command: "scons -u doc"
936 // mode: flyspell
937 // mode: auto-fill
938 // End: