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