Skip to content
Snippets Groups Projects
Commit c97c06ad authored by g0dil's avatar g0dil
Browse files

Packets: annotation facility

parent ea4a4e50
No related branches found
No related tags found
No related merge requests found
......@@ -28,7 +28,8 @@
\autotoc
\section packet_intro_arch Overall Architecture
\section packet_intro_arch Introduction
\seechapter \ref packet_arch
The Packet library consists of several components:
......@@ -42,27 +43,22 @@
All these components work together to provide a hopefully simple and intuitive interface to
packet parsing and creation.
\see \ref packet_arch
\section packet_intro_usage Using the packet library
\section packet_intro_usage Tutorial
\seechapter \ref packet_usage
This chapter discusses the usage of the packet library from a high level view.
\see \ref packet_usage
\section packet_intro_parser Parsing packet data
\section packet_intro_api The packet API
This chapter goes into more detail discussing the usage of packet parsers.
\li categorizing packet parsers
\li reading and writing values
\li using complex parsers
The packet library API is divided into three areas
\see \ref packetparser
\li the \ref senf::PacketData API for accessing the raw data container
\li the packet interpreter chain providing \ref packet_module
\li and \ref packetparser which provides access to protocol specific packet fields.
\section protocolbundles Supported packet types (protocols)
Each protocol bundle provides a collection of related concrete packet classes for a group of
......@@ -83,11 +79,11 @@
\section packet_intro_new Defining new packet types
\seechapter \ref packet_new
The packet library provides the framework which allows to define arbitrary packet types. There
is quite some information needed to completely specify a specific type of paceket.
is quite some information needed to completely specify a specific type of packet.
\see \ref packet_new
*/
/** \page packet_arch Overall Packet library Architecture
......@@ -167,7 +163,7 @@
udp.first<IPv4Packet>() // throws InvalidPacketChainException
udp.prev() == ip // true
udp.prev<EthernetPacket>() // throws Inv
udp.prev<EthernetPacket>() // throws InvalidPacketChainException
\endcode
\see \ref packet_module
......@@ -181,7 +177,7 @@
To access this information, we need to use a protocol specific handle, the senf::ConcretePacket
which takes as a template argument the specific type of packet to be interpreted. This allows us
to easily interpret or create packets. Here an example on how to create a new Etheret / IP / UDP
to easily interpret or create packets. Here an example on how to create a new Ethernet / IP / UDP
/ Payload packet interpreter chain:
\code
......@@ -518,7 +514,7 @@
Each Record is a composite with the following relevant fields:
<table class="fields">
<tr><td>nrSources</td><td>Integer</td><td>Number of sources in this record</td></tr>
<tr><td>nrOfSources</td><td>Integer</td><td>Number of sources in this record</td></tr>
<tr><td>sources</td><td>Vector of IPv6 Addresses</td><td>Multicast sources</td></tr>
</table>
......@@ -567,7 +563,7 @@
for (MLDv2ReportPacket::Parser::records_t::container::iterator i (records.begin());
i != records.end(); ++i) {
// Allocate a collection wrapper for the multicast address record
typedef MLDv2ReportPackte::Parser::records_t::value_type::sources_t Sources;
typedef MLDv2ReportPacket::Parser::records_t::value_type::sources_t Sources;
Sources::container sources (i->sources());
// Iterate over the sources in this record
......
......@@ -316,9 +316,49 @@ namespace senf {
///\name Annotations
///@{
template <class Annotation>
Annotation & annotation();
Annotation & annotation(); ///< Get packet annotation
/**< This member will retrieve an arbitrary packet
annotation. Every annotation is identified by a unique
\a Annotation type. This type should \e always be a \c
struct.
\code
struct MyAnnotation {
int value;
};
senf::Packet p (...);
p.annotation<MyAnnotation>().value = 1;
\endcode
Annotations are shared by all headers / interpreters
within a single packet chain.
If an annotation is \e not a POD type (more
specifically, if it's constructor or destructor is not
trivial), the \a Annotation type \e must inherit from
senf::ComplexAnnotation. Failing to follow this rule
will result in undefined behavior and will probably
lead to a program crash.
\code
struct MyStringAnnotation : senf::ComplexAnnotation {
std::string value;
};
\endcode
\implementation The annotation system is implemented
quite efficiently since annotations are stored
within a packet embedded vector of fixed size (the
size is determined automatically at runtime by the
number of different annotations
used). Additionally, non-complex small annotations
require no additional memory management (\c new /
\c delete).
*/
///@}
......
......@@ -110,14 +110,22 @@ namespace {
}
struct IntAnnotation {
int value;
unsigned value;
};
struct LargeAnnotation {
char value[32];
};
struct ComplexAnnotation {
struct ComplexAnnotation : senf::ComplexAnnotation
{
std::string s;
int i;
};
struct ComplexEmptyAnnotation : senf::ComplexAnnotation
{};
}
BOOST_AUTO_UNIT_TEST(packet)
......@@ -125,10 +133,6 @@ BOOST_AUTO_UNIT_TEST(packet)
senf::Packet packet (FooPacket::create());
BarPacket::createAfter(packet);
SENF_CHECK_NO_THROW( packet.annotation<IntAnnotation>().value = 0xDEADBEEF );
ComplexAnnotation & ca (packet.annotation<ComplexAnnotation>());
ca.s = "dead beef";
ca.i = 0x12345678;
BOOST_REQUIRE( packet );
BOOST_CHECK( packet.next() );
BOOST_CHECK( ! packet.next().next(senf::nothrow) );
......@@ -247,6 +251,28 @@ BOOST_AUTO_UNIT_TEST(concretePacket)
BOOST_CHECK_EQUAL( BarPacket::create()->reserved(), 0xA0A0u );
}
BOOST_AUTO_UNIT_TEST(packetAnnotation)
{
senf::Packet packet (FooPacket::create());
BarPacket::createAfter(packet);
ComplexAnnotation & ca (packet.annotation<ComplexAnnotation>());
ca.s = "dead beef";
ca.i = 0x12345678;
SENF_CHECK_NO_THROW( packet.annotation<IntAnnotation>().value = 0xDEADBEEF );
senf::Packet p2 (packet.next());
BOOST_CHECK_EQUAL( p2.annotation<IntAnnotation>().value, 0xDEADBEEFu );
BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "dead beef" );
BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, 0x12345678 );
BOOST_CHECK( senf::detail::AnnotationIndexer<IntAnnotation>::Small );
BOOST_CHECK( ! senf::detail::AnnotationIndexer<LargeAnnotation>::Small );
BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexAnnotation>::Small );
BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexEmptyAnnotation>::Small );
}
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
......
......@@ -47,8 +47,8 @@ prefix_ senf::detail::PacketImpl::~PacketImpl()
Annotations::const_iterator const i_end (annotations_.end());
std::vector<bool>::iterator small (AnnotationIndexerBase::small().begin());
for (; i != i_end; ++i, ++small)
if (! *small && *i)
delete *i;
if (! *small && i->p)
delete i->p;
}
// This function has a problem being inlined. Somehow, often when calling this, the size of the
......
......@@ -72,11 +72,11 @@ prefix_ senf::detail::AnnotationP::~AnnotationP()
// senf::detail::PacketImpl
prefix_ senf::detail::PacketImpl::PacketImpl()
: refcount_(0), annotations_(AnnotationIndexerBase::maxAnnotations, 0)
: refcount_(0), annotations_(AnnotationIndexerBase::maxAnnotations)
{}
prefix_ senf::detail::PacketImpl::PacketImpl(size_type size, byte initValue)
: refcount_(0), data_(size,initValue), annotations_(AnnotationIndexerBase::maxAnnotations, 0)
: refcount_(0), data_(size,initValue), annotations_(AnnotationIndexerBase::maxAnnotations)
{}
// rerference/memory management
......
......@@ -50,20 +50,18 @@ prefix_ unsigned senf::detail::AnnotationIndexer<Annotation>::index()
// senf::detail::GetAnnotation<Annotation,Small>
template <class Annotation, bool Small>
prefix_ Annotation & senf::detail::GetAnnotation<Annotation,Small>::get(AnnotationP * & p)
prefix_ Annotation & senf::detail::GetAnnotation<Annotation,Small>::get(AnnotationEntry & e)
{
if (!p)
p = new TAnnotationP<Annotation>();
return static_cast< TAnnotationP<Annotation>* >(p)->annotation;
if (!e.p)
e.p = new TAnnotationP<Annotation>();
return static_cast< TAnnotationP<Annotation>* >(e.p)->annotation;
}
/*
template <class Annotation>
prefix_ Annotation & senf::detail::GetAnnotation<Annotation, true>::get(AnnotationP * & p)
prefix_ Annotation & senf::detail::GetAnnotation<Annotation, true>::get(AnnotationEntry & e)
{
return * reinterpret_cast<Annotation*>(p);
return * static_cast<Annotation*>(static_cast<void*>(& e.i));
}
*/
///////////////////////////////////////////////////////////////////////////
// senf::detail::PacketImpl
......@@ -81,7 +79,7 @@ prefix_ void senf::detail::PacketImpl::insert(PacketData * self, iterator pos, F
template <class InputIterator>
prefix_ senf::detail::PacketImpl::PacketImpl(InputIterator first, InputIterator last)
: refcount_(0), data_(first,last), annotations_(AnnotationIndexerBase::maxAnnotations, 0)
: refcount_(0), data_(first,last), annotations_(AnnotationIndexerBase::maxAnnotations)
{}
// Annotations
......
......@@ -30,6 +30,7 @@
#include <memory>
#include <vector>
#include <boost/utility.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include "../Utils/pool_alloc_mixin.hh"
#include "PacketTypes.hh"
#include "../Utils/singleton.hh"
......@@ -38,8 +39,28 @@
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
struct ComplexAnnotation {};
namespace detail {
struct AnnotationP
{
virtual ~AnnotationP();
};
template <class Annotation>
struct TAnnotationP
: public AnnotationP
{
Annotation annotation;
};
union AnnotationEntry {
AnnotationP * p;
unsigned long long i;
};
struct AnnotationIndexerBase
{
static unsigned maxAnnotations;
......@@ -54,34 +75,21 @@ namespace detail {
AnnotationIndexer();
unsigned index_;
static unsigned index();
static bool const Small = (sizeof(Annotation) <= sizeof(void*));
};
struct AnnotationP
{
virtual ~AnnotationP();
};
template <class Annotation>
struct TAnnotationP
: public AnnotationP
{
Annotation annotation;
static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry)
&& ! boost::is_base_of<ComplexAnnotation, Annotation>::value);
};
template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
struct GetAnnotation
{
static Annotation & get(AnnotationP * & p);
static Annotation & get(AnnotationEntry & e);
};
/*
template <class Annotation>
struct GetAnnotation<Annotation, true>
{
static Annotation & get(AnnotationP * & p);
static Annotation & get(AnnotationEntry & e);
};
*/
/** \brief Internal: Packet data storage
......@@ -171,7 +179,7 @@ namespace detail {
raw_container data_;
interpreter_list interpreters_;
typedef std::vector<AnnotationP*> Annotations;
typedef std::vector<AnnotationEntry> Annotations;
Annotations annotations_;
void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
......
......@@ -13,6 +13,7 @@ addr
AddressingPolicy
AddressingPolicyBase
AddressParser
addrs
addtogroup
aListCollection
alloc
......@@ -25,6 +26,7 @@ args
argTokens
ArgumentToken
argv
ArrayParser
async
attr
Augustin
......@@ -78,6 +80,7 @@ ConnectedRawV
ConnectedUDPv
const
copyable
cout
CPPDEFINES
CPPPATH
createAfter
......@@ -113,6 +116,9 @@ doxygen
DSENF
DSMCCSection
dt
DTCP
DTCPHelloPacket
DVB
ElementParser
enableChecksum
endcode
......@@ -134,6 +140,7 @@ errorNumber
eth
ethernet
EthernetPacket
EthernetPacketParser
EthernetPacketType
EthernetParser
ethertype
......@@ -155,11 +162,15 @@ ExampleVectorPolicy
EXC
ExceptionMixin
ExtendedParser
fbipList
FBIPList
fbips
FFFF
FileBody
filebody
FileHandle
FileTarget
finalizeAll
findNext
findPrev
fixedcolumn
......@@ -200,6 +211,7 @@ hostname
hostnames
howto
HowTo
HowTos
hpp
href
htm
......@@ -243,6 +255,7 @@ IpTypes
IpV
ipv
IPv
ipVersion
IPX
isock
iter
......@@ -269,6 +282,7 @@ LinkScope
linux
ListB
ListN
ListParser
ListPolicy
localAddr
localhost
......@@ -286,6 +300,10 @@ mem
memberfn
mixin
mkdir
mld
MLDv
MPEG
mpegdvb
MPEGDVBBundle
mpp
multicast
......@@ -310,6 +328,7 @@ nc
netcat
NETwork
newpacket
NewPacket
NextPacket
nextPacketKey
nextPacketRange
......@@ -321,6 +340,8 @@ NodeCreateTraits
noinit
noroute
nothrow
nrOfRecords
nrOfSources
nUsing
ob
ObjectDirectory
......@@ -403,6 +424,7 @@ protocolType
ptr
PUSHD
py
QueryPacket
QueueingDiscipline
queueSize
RateFilter
......@@ -420,6 +442,7 @@ registerPacket
registerPacketType
registerSomePacket
RegistrationProxy
ReportPacket
repos
rerference
rfc
......@@ -437,6 +460,7 @@ ScopedDirectory
ScopeId
screenshot
sec
seechapter
seekable
senf
senfscons
......@@ -518,6 +542,7 @@ STL
strerror
struct
structors
subsubsection
svn
svnbook
svnroot
......@@ -542,6 +567,7 @@ TunTapSocketHandle
TypeA
TypeB
typeField
UDLR
udp
UDPPacket
udpReader
......@@ -558,14 +584,18 @@ unthrottled
unthrottles
unthrottling
Utils
valueParser
ValueParser
var
varadd
varattr
varchange
varChanged
VariableAttributor
VariantParser
varro
VectorN
VectorParser
Ver
vlanId
VLanId
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment