4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
25 // Stefan Bund <g0dil@berlios.de>
28 /** \mainpage The SENF Packet Library
30 The SENF Packet library provides facilities to analyze, manipulate and create structured packet
31 oriented data (e.g. network packets).
36 \section packet_intro_arch Introduction
37 \seechapter \ref packet_arch
39 The Packet library consists of several components:
41 \li The \ref packet_module manages the packet data and provides the framework for handling the
42 chain of packet headers. The visible interface is provided by the Packet class.
43 \li \ref packetparser provides the framework for interpreting packet data. It handles
44 parsing the packet information into meaningful values.
45 \li The \ref protocolbundles provide concrete implementations for interpreting packets of
46 some protocol. The Protocol Bundles are built on top of the basic packet library.
48 All these components work together to provide a hopefully simple and intuitive interface to
49 packet parsing and creation.
52 \section packet_intro_usage Tutorial
53 \seechapter \ref packet_usage
55 This chapter discusses the usage of the packet library from a high level view.
58 \section packet_intro_api The packet API
60 The packet library API is divided into three areas
62 \li the \ref senf::PacketData API for accessing the raw data container
63 \li the packet interpreter chain providing \ref packet_module
64 \li and \ref packetparser which provides access to protocol specific packet fields.
67 \section protocolbundles Supported packet types (protocols)
69 Each protocol bundle provides a collection of related concrete packet classes for a group of
72 \li \ref protocolbundle_default : Some basic default protocols: Ethernet, Ip, TCP, UDP
73 \li \ref protocolbundle_mpegdvb : MPEG and DVB protocols
74 \li \ref protocolbundle_80211 : 802.11 protocols
75 \li \ref protocolbundle_80221 : 802.21 protocols
77 There are two ways to link with a bundle
79 \li If you only work with known packets which you explicitly reference you may just link with
80 the corresponding library.
81 \li If you need to parse unknown packets and want those to be parsed as complete as possible
82 without explicitly referencing the packet type, you will need to link against the combined
83 object file built for every bundle. This way, all packets defined in the bundle will be
84 included whether they are explicitly referenced or not (and they will all automatically be
88 \section packet_intro_new Defining new packet types
89 \seechapter \ref packet_new
91 The packet library provides the framework which allows to define arbitrary packet types. There
92 is quite some information needed to completely specify a specific type of packet.
96 /** \page packet_arch Overall Packet library Architecture
98 The packet library handles network packets of a large number of protocols. We work with a packet
104 \section packet_arch_handle The Packet handle
106 Whenever we are using a Packet, we are talking about a senf::Packet (or a
107 senf::ConcretePacket). This class is a \e handle referencing an internally managed packet data
108 structure. So even though we pass senf::Packet instances around by value, they work like
109 references. The packet library automatically manages all required memory resources using
112 Different Packet handles may really internally share one Packet data structure if they both
113 point to the same packet.
116 \section packet_arch_data The Packet as a 'bunch of bytes'
118 From the outside, a packet is just a bunch of bytes just as it is read from (or will be
119 written to) the wire. At this low-level view, we can access the data in it's raw form but
120 have no further information about what kind of packet we have.
122 The packet library provides a consistent container interface for this representation.
127 // Change first byte of packet to 1
130 // Copy packet data into a vector
131 std::vector<char> data (p.data().size());
132 std::copy(p.data().begin(), p.data().end(), data.begin());
135 This type of access is primarily needed when reading or writing packets (e.g. to/from the
138 \see senf::Packet::data() \n
142 \section packet_arch_chain The Interpreter Chain
144 On the next level, the packet is divided into a nested list of sub-packets (or headers) called
145 interpreters. Each senf::Packet handle internally points to an interpreter or header. This
146 allows us to access one and the same packet in different ways.
148 Consider an Ethernet Packet with an IP payload holding a UDP packet. We may reference either the
149 Ethernet packet as a whole or we may reference the IP or UDP interpreters (sub-packets or
150 headers). All handles really refer to the \e same data structure but provide access to a
151 different (sub-)range of the data in the packet.
153 We can navigate around this chained structure using appropriate members:
156 // eth, ip and udp all reference the same internal packet data albeit at different data ranges
158 Packet ip = eth.next();
159 Packet udp = ip.next();
161 eth.next() == ip // true
162 eth.next().is<IPv4Packet>() // true
163 eth.next().next() == udp // true
164 eth.next().is<UDPPacket>() // false
165 eth.find<UDPPacket>() == udp // true
167 udp.find<EthernetPacket>() // throws InvalidPacketChainException
168 udp.find<EthernetPacket>(senf::nothrow) // An in-valid() senf::Packet which tests as 'false'
169 udp.find<UDPPacket> == udp // true
170 udp.first<IPv4Packet>() // throws InvalidPacketChainException
172 udp.prev() == ip // true
173 udp.prev<EthernetPacket>() // throws InvalidPacketChainException
176 \see \ref packet_module
179 \section packet_arch_parser Parsing specific Protocols
181 On the next level, the packet library allows us to parse the individual protocols. This gives us
182 access to the protocol specific data members of a packet and allows us to access or manipulate a
183 packet in a protocol specific way.
185 To access this information, we need to use a protocol specific handle, the senf::ConcretePacket
186 which takes as a template argument the specific type of packet to be interpreted. This allows us
187 to easily interpret or create packets. Here an example on how to create a new Ethernet / IP / UDP
188 / Payload packet interpreter chain:
191 // EthernetPacket, IPv4Packet, UDPPacket and DataPacket are typedefs for corresponding
192 // ConcretePacket instantiations
193 senf::EthernetPacket eth (senf::EthernetPacket::create());
194 senf::IPv4Packet ip (senf::IPv4Packet ::createAfter(eth));
195 senf::UDPPacket udp (senf::UDPPacket ::createAfter(ip));
196 senf::DataPacket payload (senf::DataPacket ::createAfter(udp,
197 std::string("Hello, world!")));
199 udp->source() = 2000u;
200 udp->destination() = 2001u;
202 ip->source() = senf::INet4Address::from_string("192.168.0.1");
203 ip->destination() = senf::INet4Address::from_string("192.168.0.2");
204 eth->source() = senf::MACAddress::from_string("00:11:22:33:44:55");
205 eth->destination() = senf::MACAddress::from_string("00:11:22:33:44:66");
210 Again, realize, that \a eth, \a ip, \a udp and \a payload share the same internal packet
211 data structure (the respective \c data() members all provide access to the same underlying
212 container however at different byte ranges): The complete packet can be accessed at
213 <tt>eth.data()</tt> whereas <tt>payload.data()</tt> only holds UDP payload (in this case the
214 string "Hello, world!").
216 \see \ref packetparser \n
220 /** \page packet_usage Using the packet library
224 \section packet_usage_intro Includes
226 To use the library, you need to include the appropriate header files. This will probably happen
227 automatically when including the specific protocol headers. If needed, you may explicitly use
230 #include "Packets.hh"
235 \warning Never include any other Packets library header directly, only include \c
236 Packets.hh or one (or several) protocol headers from the protocol bundles.
238 Most every use of the packet library starts with some concrete packet typedef. Some fundamental
239 packet types are provided by \ref protocolbundle_default.
242 \section packet_usage_create Creating a new packet
244 Building on those packet types, this example will build a complex packet: This will be an
245 Ethernet packet containing an IPv4 UDP packet. We begin by building the raw packet skeleton:
248 #include "Packets/DefaultBundle/EthernetPacket.hh"
249 #include "Packets/DefaultBundle/IPv4Packet.hh"
250 #include "Packets/DefaultBundle/UDPPacket.hh"
252 senf::EthernetPacket eth (senf::EthernetPacket::create());
253 senf::IPv4Packet ip (senf::IPv4Packet ::createAfter(eth));
254 senf::UDPPacket udp (senf::UDPPacket ::createAfter(ip));
255 senf::DataPacket payload (senf::DataPacket ::createAfter(udp,
256 std::string("Hello, world!")));
259 These commands create what is called an interpreter chain. This chain consists of four
260 interpreters. All interpreters reference the same data storage. This data storage is a random
261 access sequence which contains the data bytes of the packet.
263 \note The data structures allocated are automatically managed using reference counting. In this
264 example we have four packet references each referencing the same underlying data
265 structure. This data structure will be freed when the last reference to it goes out of
268 The packet created above already has the correct UDP payload (The string "Hello, world!")
269 however all protocol fields are empty. We need to set those protocol fields:
272 udp->source() = 2000u;
273 udp->destination() = 2001u;
275 ip->source() = senf::INet4Address::from_string("192.168.0.1");
276 ip->destination() = senf::INet4Address::from_string("192.168.0.2");
277 eth->source() = senf::MACAddress::from_string("00:11:22:33:44:55");
278 eth->destination() = senf::MACAddress::from_string("00:11:22:33:44:66");
283 As seen above, packet fields are accessed using the <tt>-></tt> operator whereas other packet
284 facilities (like \c finalizeAll()) are directly accessed using the member operator. The field
285 values are simply set using appropriately named accessors. As a last step, the \c finalizeAll()
286 call will update all calculated fields (fields like next-protocol, header or payload length,
287 checksums etc). Now the packet is ready. We may now send it out using a packet socket
290 senf::PacketSocketHandle sock();
291 sock.bind( senf::LLSocketAddress("eth0"));
292 sock.write(eth.data());
296 \section packet_usage_read Reading and parsing packets
298 The chain navigation functions are also used to parse a packet. Let's read an Ethernet packet
299 from a packet socket handle:
302 senf::PacketSocketHandle sock();
303 sock.bind( senf::LLSocketAddress("eth0"));
304 senf::EthernetPacket packet (senf::EthernetPacket::create(senf::noinit));
305 sock.read(packet.data(),0u);
308 This first creates an uninitialized Ethernet packet and then reads into this packet. We can now
309 parse this packet. Let's find out, whether this is a UDP packet destined to port 2001:
313 senf::UDPPacket udp (packet.find<UDPPacket>());
314 if (udp->destination() == 2001u) {
317 } catch (senf::TruncatedPacketException &) {
318 std::cerr << "Ooops !! Broken packet received\n";
319 } catch (senf::InvalidPacketChainException &) {
320 std::cerr << "Not a udp packet\n";
324 TruncatedPacketException is thrown by <tt>udp->destination()</tt> if that field cannot be
325 accessed (that is it would be beyond the data read which means we have read a truncated
326 packet). More generally, whenever a field cannot be accessed because it would be out of bounds
327 of the data read, this exception is generated.
330 \section packet_usage_container The raw data container
332 Every packet is based internally on a raw data container holding the packet data. This container
333 is accessed via senf::Packet::data() member.
335 This container is a random access container. It can be used like an ordinary STL container and
336 supports all the standard container members.
341 // Insert 5 0x01 bytes
342 p.data().insert(p.data().begin()+5, 5, 0x01);
344 // Insert data from another container
345 p.data().insert(p.data().end(), other.begin(), other.end());
347 // Erase a single byte
348 p.data().erase(p.data().begin()+5);
350 // XOR byte 5 with 0xAA
354 A packet consists of a list of interpreters (packet headers or protocols) which all reference
355 the same data container at different byte ranges. Each packet consists of the protocol header \e
356 plus the packets payload. This means, that the data container ranges of successive packets from
357 a single interpreter chain are nested.
359 Example: The packet created above (the Ethernet-IP-UDP packet with payload "Hello, world!") has
360 4 Interpreters: Ethernet, IPv4, UDP and the UDP payload data. The nested data containers lead to
361 the following structure
364 // The ethernet header has a size of 14 bytes
365 eth.data().begin() + 14 == ip.data().begin()
366 eth.data().end() == ip.data().end()
368 // The IP header has a size of 20 bytes and therefore
369 ip.data().begin() + 20 == udp.data().begin()
370 ip.data().end() == udp.data().end()
372 // The UDP header has a size of 8 bytes and thus
373 udp.data().begin() + 8 == payload.data().begin()
374 udp.data().end() == payload.data().end()
377 This nesting will (and must) always hold: The data range of a subsequent packet will always be
378 within the range of it's preceding packet.
380 \warning It is forbidden to change the data of a subsequent packet interpreter from the
381 preceding packet even if the data container includes this data. If you do so, you may
382 corrupt the data structure (especially when changing it's size).
384 Every operation on a packet is considered to be \e within this packet and \e without and
385 following packet. When inserting or erasing data, the data ranges are all adjusted
386 accordingly. So the following are \e not the same even though \c eth.end(), \c ip.end() and \c
387 udp.end() are identical.
390 eth.data().insert(eth.data().end(), 5, 0x01);
391 assert( eth.data().end() == ip.data().end() + 5
392 && ip.data().end() == udp.data().end() );
394 // Or alternatively: (You could even use eth.data().end() here ... it's the same)
395 ip.data().insert(ip.data().end(), 5, 0x01);
396 assert( eth.data().end() == ip.data().end()
397 && ip.data().end() == udp.data().end() + 5 );
400 \warning When accessing the packet data via the container interface, you may easily build
401 invalid packets since the packet will not be validated against it's protocol.
404 \section packet_usage_fields Field access
406 When working with concrete protocols, the packet library provides direct access to all the
407 protocol information.
410 udp->source() = 2000u;
411 udp->destination() = 2001u;
413 ip->source() = senf::INet4Address::from_string("192.168.0.1");
414 ip->destination() = senf::INet4Address::from_string("192.168.0.2");
415 eth->source() = senf::MACAddress::from_string("00:11:22:33:44:55");
416 eth->destination() = senf::MACAddress::from_string("00:11:22:33:44:66");
419 The protocol field members above do \e not return references, they return parser instances.
420 Protocol fields are accessed via parsers. A parser is a very lightweight class which points into
421 the raw packet data and converts between raw data bytes and it's interpreted value: For example
422 a senf::UInt16Parser accesses 2 bytes (in network byte order) and converts them to or from a 16
423 bit integer. There are a few properties about parsers which need to be understood:
425 \li Parsers are created only temporarily when needed. They are created when accessing a protocol
426 field and are returned by value.
428 \li A parser never contains a value itself, it just references a packets data container.
430 \li Parsers can be built using other parsers and may have members which return further parsers.
432 The top-level interface to a packets protocol fields is provided by a protocol parser. This
433 protocol parser is a composite parser which has members to access the protocol fields (compare
434 with the example code above). Some protocol fields may be more complex than a simple value. In
435 this case, those accessors may return other composite parsers or collection parsers. Ultimately,
436 a value parser will be returned.
438 The simple value parsers which return plain values (integer numbers, network addresses etc) can
439 be used like those values and can also be assigned corresponding values. More complex parsers
440 don't allow simple assignment. However, they can always be copied from another parser <em>of the
441 same type</em> using the generalized parser assignment. This type of assignment also works for
442 simple parsers and is then identical to a normal assignment.
445 // Copy the complete udp parser from udp packet 2 to packet 1
446 udp1.parser() << udp2.parser();
449 Additionally, the parsers have a parser specific API which allows to manipulate or query the
452 This is a very abstract description of the parser structure. For a more concrete description, we
453 need to differentiate between the different parser types
455 \subsection packet_usage_fields_value Simple fields (Value parsers)
457 We have already seen value parsers: These are the lowest level building blocks witch parse
458 numbers, addresses etc. They return some type of value and can be assigned such a value. More
459 formally, they have a \c value_type typedef member which gives the type of value they accept and
460 they have an overloaded \c value() member which is used to read or set the value. Some parsers
461 have additional functionality: The numeric parser for Example provide conversion and arithmetic
462 operators so they can be used like a numeric value.
464 If you have a value parser \c valueParser with type \c ValueParser, the following will always be
467 // You can read the value and assign it to a variable of the corresponding value_type
468 ValueParser::value_type v (valueParser.value());
470 // You can assign that value to the parser
471 valueParser.value(v);
473 // The assignment can also be done using the generic parser assignment
478 \subsection packet_usage_fields_composite Composite and protocol parsers
480 A composite parser is a parser which just combines several other parsers into a structure: For
481 example, the senf::EthernetPacketParser has members \c destination(), \c source() and \c
482 type_length(). Those members return parsers again (in this case value parsers) to access the
485 Composite parsers can be nested; A composite parser may be returned by another composite
486 parser. The protocol parser is a composite parser which defines the field for a specific
487 protocol header like Ethernet.
489 \subsection packet_usage_fields_collection Collection parsers
491 Besides simple composites, the packet library has support for more complex collections.
493 \li The senf::ArrayParser allows to repeat an arbitrary parser a fixed number of times.
494 \li senf::VectorParser and senf::ListParser are two different types of lists with variable
496 \li The senf::VariantParser is a discriminated union: It will select one of several parsers
497 depending on the value of a discriminant.
500 \subsubsection packet_usage_collection_vector Vector and List Parsers
502 Remember, that a parser does \e not contain any data: It only points into the raw data
503 container. This is also true for the collection parsers. VectorParser and ListParser provide an
504 interface which looks like an STL container to access a sequence of elements.
506 We will use an \c MLDv2QueryPacket as an example (see <a
507 href="http://tools.ietf.org/html/rfc3810#section-5">RFC 3810</a>). Here an excerpt of the
510 <table class="fields">
511 <tr><td>nrOfSources</td><td>Integer</td><td>Number of multicast sources in this packet</td></tr>
512 <tr><td>sources</td><td>Vector of IPv6 Addresses</td><td>Multicast sources</td></tr>
515 To demonstrate nested collections, we use the \c MLDv2ReportPacket as an example. The relevant
516 fields of this packet are;
518 <table class="fields">
519 <tr><td>nrOfRecords</td><td>Integer</td><td>Number of multicast address records</td></tr>
520 <tr><td>records</td><td>List of Records</td><td>List of multicast groups and sources</td></tr>
523 Each Record is a composite with the following relevant fields:
525 <table class="fields">
526 <tr><td>nrOfSources</td><td>Integer</td><td>Number of sources in this record</td></tr>
527 <tr><td>sources</td><td>Vector of IPv6 Addresses</td><td>Multicast sources</td></tr>
530 The first example will iterate over the sources in a \c MLDv2QueryPacket:
533 MLDv2QueryPacket mld = ...;
535 // Instantiate a collection wrapper for the source list
536 MLDv2QueryPacket::Parser::sources_t::container sources (mld->sources());
538 // Iterate over all the addresses in that list
539 for (MLDv2QueryPacket::Parser::sources_t::container::iterator i (sources.begin());
540 i != sources.end(); ++i)
541 std::cout << *i << std::endl;
544 Beside other fields, the MLDv2Query consists of a list of source addresses. The \c sources()
545 member returns a VectorParser for these addresses. The collection parsers can only be accessed
546 completely using a container wrapper. The container wrapper type is available as the \c
547 container member of the collection parser, here it is \c
548 MLDv2QueryPacket::Parser::sources_t::container.
550 Using this wrapper, we can not only read the data, we can also manipulate the source list. Here
551 we copy a list of addresses from an \c std::vector into the packet:
554 std::vector<senf::INet6Address> addrs (...);
556 sources.resize(addrs.size());
557 std::copy(addrs.begin(), addrs.end(), sources.begin())
560 Collection parsers may be nested. To access a nested collection parser, a container wrapper must
561 be allocated for each level. An MLD Report (which is a composite parser) includes a list of
562 multicast address records called \c records(). Each record is again a composite which contains a
563 list of sources called \c sources():
566 MLDv2ReportPacket report = ...;
568 // Instantiate a collection wrapper for the list of records:
569 MLDv2ReportPacket::Parser::records_t::container records (report->records());
571 // Iterate over the multicast address records
572 for (MLDv2ReportPacket::Parser::records_t::container::iterator i (records.begin());
573 i != records.end(); ++i) {
574 // Allocate a collection wrapper for the multicast address record
575 typedef MLDv2ReportPacket::Parser::records_t::value_type::sources_t Sources;
576 Sources::container sources (i->sources());
578 // Iterate over the sources in this record
579 for (Sources::container::iterator i (sources.begin());
580 i != sources.end(); ++i)
581 std::cout << *i << std::endl;
585 In this example we also see how to find the type of a parser or container wrapper.
586 \li Composite parsers have typedefs for each their fields with a \c _t postfix
587 \li The vector or list parsers have a \c value_type typedef which gives the type of the
590 By traversing this hierarchical structure, the types of all the fields can be found.
592 The container wrapper is only temporary (even though it has a longer lifetime than a
593 parser). Any change made to the packet not via the collection wrapper has the potential to
594 invalidate the wrapper if it changes the packets size.
597 senf::VectorParser / senf::VectorParser_Container Interface of the vector parser \n
598 senf::ListParser / senf::ListParser_Container Interface of the list parser
601 \subsubsection packet_usage_collection_variant The Variant Parser
603 The senf::VariantParser is a discriminated union of parsers. It is also used for optional fields
604 (using senf::VoidPacketParser as one possible variant which is a parser parsing nothing). A
605 senf::VariantParser is not really a collection in the strict sense: It only ever contains one
606 element, the \e type of which is determined by the discriminant.
608 For Example, we look at the DTCP HELLO Packet as defined in the UDLR Protocol (see <a
609 href="http://tools.ietf.org/html/rfc3077">RFC 3077</a>)
612 DTCPHelloPacket hello (...);
614 if (hello->ipVersion() == 4) {
615 typedef DTCPHelloPacket::Parser::v4fbipList_t FBIPList;
616 FBIPList::container fbips (hello->v4fbipList());
617 for (FBIPList::container::iterator i (fbips.begin()); i != fbips.end(); ++i)
618 std::cout << *i << std::endl;
620 else { // if (hello->ipVersion() == 6)
621 typedef DTCPHelloPacket::Parser::v6fbipList_t FBIPList;
622 FBIPList::container fbips (hello->v6fbipList());
623 for (FBIPList::container::iterator i (fbips.begin()); i != fbips.end(); ++i)
624 std::cout << *i << std::endl;
628 This packet has a field \c ipVersion() which has a value of 4 or 6. Depending on the version,
629 the packet contains a list of IPv4 or IPv6 addresses. Only one of the fields \c v4fbipList() and
630 \c v6fbipList() is available at a time. Which one is decided by the value of \c
631 ipVersion(). Trying to access the wrong one will provoke undefined behavior.
633 Here we have used the variants discriminant (the \c ipVersion() field) to select, which field to
634 parse. More generically, every variant field should have a corresponding member to test for it's
637 if (hello->has_v4fbipList()) {
640 else { // if (hello->has_v6fbipList())
645 A variant can have more than 2 possible types and you can be sure, that exactly one type will be
646 accessible at any time.
648 It is not possible to change a variant by simply changing the discriminant:
651 hello->ipVersion() = 6;
653 Instead, for each variant field there is a special member which switches the variant to that
654 type. After switching the type, the field will be in it's initialized (that is mostly zero)
657 std::vector<senf::INet6Address> addrs (...);
659 // Initialize the IPv6 list
660 hello->init_v6fbipList();
662 // Copy values into that list
663 DTCPHelloPacket::Parser::v6fbipList_t::container fbips (hello->v6fbipList());
664 fbips.resize(addrs.size());
665 std::copy(addrs.begin(), addrs.end(), fbips.begin());
668 \note Here we have documented the default variant interface as it is preferred. It is possible
669 to define variants in a different way giving other names to the special members (\c has_\e
670 name or \c init_\e name etc.). This must be documented with the composite or protocol parser
671 which defines the variant.
673 \section packet_usage_annotation Annotations
675 Sometimes we need to store additional data with a packet. Data, which is not part of the packet
676 itself but gives us some information about the packet: A timestamp, the interface the packet was
677 received on or other processing related information.
679 This type of information can be stored using the annotation interface. The following example
680 will read packet data and will store the read timestamp as a packet annotation.
684 senf::ClockService::clock_t value;
687 std::ostream & operator<<(std::ostream & os, Timestamp const & tstamp) {
688 os << tstamp.value; return os;
691 senf::EthernetPacket packet (senf::EthernetPacket::create(senf::noinit));
692 sock.read(packet.data(), 0u);
693 packet.annotation<Timestamp>().value = senf::ClockService::now();
696 In the same way, the annotation can be used later
699 if (senf::ClockService::now() - packet.annotation<Timestamp>().value
700 > senf::ClockService::seconds(1)) {
701 // this packet is to old
706 It is very important to define a specific structure (or class or enum) type for each type of
707 annotation. \e Never directly store a fundamental type as an annotation: The name of the type is
708 used to look up the annotation, so you can store only one annotation for each built-in type. \c
709 typedef does not help since \c typedef does not introduce new type names, it only defines an
712 The annotation type must support the output \c operator<< for description purposes
713 (e.g. for the \ref senf::Packet::dump() "Packet::dump()" member).
715 Of course, the annotation structure can be arbitrary. However, one very important caveat: If the
716 annotation is not a POD type, it needs to inherit from senf::ComplexAnnotation. A type is POD,
717 if it is really just a bunch of bytes: No (non-static) members, no constructor or destructor and
718 no base classes and all it's members must be POD too. So the following annotation is complex
719 since \c std::string is not POD
722 struct ReadInfo : senf::ComplexAnnotation
724 std::string interface;
725 senf::ClockService::clock_t timestamp;
730 packet.annotation<ReadInfo>().interface = "eth0";
731 packet.annotation<ReadInfo>().timestamp = senf::ClockService::now();
733 // Or store a reference to the annotation for easier access
735 ReadInfo & info (packet.annotation<ReadInfo>());
737 if (info.interface == "eth0") {
742 Conceptually, all annotations always exist in every packet, there is no way to query, whether a
743 packet holds a specific annotation.
745 You should use annotations economically: Every annotation type used in your program will
746 allocate an annotation slot in \e all packet data structures. So don't use hundreds of different
747 annotation types if this is not really necessary: Reuse annotation types where possible or
748 aggregate data into larger annotation structures. The best solution is to use annotations only
749 for a small number of packet specific informations. If you really need to manage a train-load of
750 data together with the packet consider some other way (e.g. place the packet into another class
751 which holds that data).
753 \see senf::Packet::annotation() \n
754 senf::dumpPacketAnnotationRegistry() for annotation debugging and optimization
757 /** \page packet_new Defining new Packet types
759 Each packet is specified by the following two components:
761 \li A protocol parser which defines the protocol specific fields
762 \li A packet type class which is a policy class defining the packet
766 \see <a href="../../../../HowTos/NewPacket/doc/html/index.html">NewPacket HowTo</a>
768 \section packet_new_parser The protocol parser
770 The protocol parser is simply a composite parser. It defines all the protocol
771 fields. Additionally, the protocol parser may have additional members which will then be
772 accessible via the \c -> operator of the packet. Possibilities here are e.g. checksum
773 calculation and validation, packet validation as a whole and so on.
775 Defining a protocol parser is quite simple:
777 struct EthernetPacketParser : public PacketParserBase
779 # include SENF_FIXED_PARSER()
781 SENF_PARSER_FIELD( destination, MACAddressParser );
782 SENF_PARSER_FIELD( source, MACAddressParser );
783 SENF_PARSER_FIELD( type_length, UInt16Parser );
785 SENF_PARSER_FINALIZE(EthernetPacketParser);
789 There are a lot of other possibilities to define fields. See \ref packetparsermacros for a
790 detailed description of the macro language which is used to define composite parsers.
793 \ref packetparsermacros
795 \section packet_new_type The packet type policy class
797 This is a class which provides all the information needed to integrate the new packet type into
800 \li It provides the type of the protocol parser to use
801 \li It provides information on how the next protocol can be found and where the payload resides
803 \li It provides methods to initialize a new packet and get information about the packet size
805 All this information is provided via static or typedef members.
808 struct EthernetPacketType
809 : public PacketTypeBase,
810 public PacketTypeMixin<EthernetPacketType, EtherTypes>
812 typedef PacketTypeMixin<EthernetPacketType, EtherTypes> mixin;
813 typedef ConcretePacket<EthernetPacketType> packet;
814 typedef EthernetPacketParser parser;
816 using mixin::nextPacketRange;
817 using mixin::initSize;
820 static factory_t nextPacketType(packet p);
821 static void dump(packet p, std::ostream & os);
822 static void finalize(packet p);
825 typedef EthernetPacketType::packet EthernetPacket;
828 The definition of senf::EthernetPacket is quite straight forward. This template works for most
831 \see \ref senf::PacketTypeMixin \n
832 \ref senf::PacketTypeBase \n
833 \ref senf::PacketRegistry
840 // c-file-style: "senf"
841 // indent-tabs-mode: nil
842 // ispell-local-dictionary: "american"
844 // compile-command: "scons -u doc"