os << ": \n"
<< " destination : " << p->destination() << "\n"
<< " source : " << p->source() << "\n"
- << " ethertype : "
+ << " ethertype : 0x"
<< std::hex << std::setw(4) << std::setfill('0') << p->type() << "\n";
}
+prefix_ void senf::EthernetPacketType::finalize(packet p)
+{
+ p->type() << key(p.next());
+}
+
prefix_ void senf::EthVLanPacketType::dump(packet p, std::ostream & os)
{
boost::io::ios_all_saver ias(os);
<< " priority : " << p->priority() << "\n"
<< " cfi : " << p->cfi() << "\n"
<< " vlan-ID : " << p->vlanId() << "\n"
- << " ethertype : "
+ << " ethertype : 0x"
<< std::hex << std::setw(4) << std::setfill('0') << p->type() << "\n";
}
+prefix_ void senf::EthVLanPacketType::finalize(packet p)
+{
+ p->type() << key(p.next());
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
{ return p->type(); }
static void dump(packet p, std::ostream & os);
+ static void finalize(packet p);
};
/** \brief Ethernet packet typedef */
{ return p->type(); }
static void dump(packet p, std::ostream & os);
+ static void finalize(packet p);
};
/** \brief Ethernet VLAN tag typedef */
// Custom includes
#include "EthernetPacket.hh"
+#include "IpV4Packet.hh"
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_tools.hpp>
BOOST_CHECK_EQUAL( *v.next().data().begin(), 0xf0 );
}
+BOOST_AUTO_UNIT_TEST(ethernetPacket_create)
+{
+ senf::EthernetPacket eth (senf::EthernetPacket::create());
+ eth->source() = senf::MACAddress::from_string("01:02:03:04:05:06");
+ eth->destination() = senf::MACAddress::from_string("07:08:09:0a:0b:0c");
+
+ senf::EthVLanPacket vlan (senf::EthVLanPacket::createAfter(eth));
+ vlan->priority() = 9u;
+ vlan->cfi() = true;
+ vlan->vlanId() = 0x234u;
+
+ eth.finalize();
+ BOOST_CHECK_EQUAL(eth->type(), 0x8100u);
+ BOOST_CHECK_EQUAL(vlan->type(), 0u);
+
+ senf::IpV4Packet ip (senf::IpV4Packet::createAfter(vlan));
+ eth.finalize();
+ BOOST_CHECK_EQUAL(vlan->type(), 0x0800u);
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "IpV4Packet.ih"
// Custom includes
+#include <iomanip>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <boost/io/ios_state.hpp>
+#include "../../Utils/IpChecksum.hh"
#include "EthernetPacket.hh"
#define prefix_
regsiterIpV4Packet2 (4); // IP-in-IP encapsulation
}
+///////////////////////////////////////////////////////////////////////////
+// senf::Parse_IpV4
+
+prefix_ boost::uint16_t senf::Parse_IpV4::calcChecksum()
+ const
+{
+ IpChecksum summer;
+ summer.feed( i(), i()+checksum_offset );
+ // Not needed since the number of 0-bytes is even
+ // summer.feed( 0u );
+ // summer.feed( 0u );
+ summer.feed( i()+checksum_offset+2, i()+bytes(*this) );
+ return summer.sum();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::IpV4PacketType
+
prefix_ void senf::IpV4PacketType::dump(packet p, std::ostream & os)
{
+ boost::io::ios_all_saver ias(os);
os << "Internet protocol Version 4:\n"
<< " version : " << p->version() << "\n"
<< " IHL : " << p->ihl() << "\n"
<< " fragment : " << p->frag() << "\n"
<< " TTL : " << unsigned(p->ttl()) << "\n"
<< " protocol : " << unsigned(p->protocol()) << "\n"
- << " CRC : " << std::hex << p->crc() << std::dec << "\n"
+ << " checksum : 0x"
+ << std::hex << std::setw(4) << std::setfill('0') << p->checksum() << std::dec << "\n"
<< " source : " << p->source() << "\n"
<< " destination : " << p->destination() << "\n";
}
+prefix_ void senf::IpV4PacketType::finalize(packet p)
+{
+ p->length() << p.size();
+ p->protocol() << key(p.next());
+ p->checksum() << p->calcChecksum();
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
((Field )( frag, Parse_Frag ))
((Field )( ttl, Parse_8bit ))
((Field )( protocol, Parse_8bit ))
- ((Field )( crc, Parse_16bit ))
+ ((Field )( checksum, Parse_16bit ))
((Field )( source, Parse_Addr ))
((Field )( destination, Parse_Addr )) );
Parse_Frag frag() const;
Parse_8bit ttl() const;
Parse_8bit protocol() const;
- Parse_16bit crc() const;
+ Parse_16bit checksum() const;
Parse_Addr source() const;
Parse_Addr destination() const;
void init() {
version() = 4;
+ // We don't support option headers at the moment ...
+ ihl() = 5;
+ }
+
+ boost::uint16_t calcChecksum() const;
+ bool validateChecksum() const {
+ return checksum() == calcChecksum();
}
};
{ return p->protocol(); }
static void dump(packet p, std::ostream & os);
+ static void finalize(packet p);
};
/** \brief IpV4 packet typedef */
// Custom includes
#include "IpV4Packet.hh"
+#include "UDPPacket.hh"
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_tools.hpp>
BOOST_CHECK_EQUAL( p->frag(), 0x0708u );
BOOST_CHECK_EQUAL( p->ttl(), 0x09u );
BOOST_CHECK_EQUAL( p->protocol(), 0x0Au );
- BOOST_CHECK_EQUAL( p->crc(), 0x0B0Cu );
+ BOOST_CHECK_EQUAL( p->checksum(), 0x0B0Cu );
BOOST_CHECK_EQUAL( p->source().value(), senf::INet4Address(0x11121314u) );
BOOST_CHECK_EQUAL( p->destination().value(), senf::INet4Address(0x15161718u) );
}
+BOOST_AUTO_UNIT_TEST(ipV4Packet_create)
+{
+ senf::IpV4Packet ip (senf::IpV4Packet::create());
+
+ BOOST_CHECK_EQUAL( ip->version(), 4u );
+ BOOST_CHECK_EQUAL( ip->ihl(), 5u );
+ BOOST_CHECK_EQUAL( ip.size(), 20u );
+
+ senf::UDPPacket udp (senf::UDPPacket::createAfter(ip));
+
+ BOOST_CHECK( ! ip->validateChecksum() );
+
+ ip.finalize();
+ BOOST_CHECK_EQUAL( ip->length(), 28u );
+ BOOST_CHECK_EQUAL( ip->protocol(), 17u );
+ BOOST_CHECK_EQUAL( ip->checksum(), 0xbad2 );
+
+ // Check, that the checksum field is correctly skipped
+ ip.finalize();
+ BOOST_CHECK_EQUAL( ip->checksum(), 0xbad2 );
+
+ BOOST_CHECK( ip->validateChecksum() );
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
Packet next() const;
///< Get next packet in chain
+ /**< \returns in - valid() packet, if no next packet
+ exists */
template <class OtherPacket> OtherPacket next() const;
///< Get next packet of given type in chain
/**< \throws InvalidPacketChainException if no such packet
///< Get next packet of given type in chain
/**< \param[in] nothrow This argument always has the value
\c senf::nothrow
- \returns in-valid() packet, if no such packet is found */
+ \returns in - valid() packet, if no such packet is
+ found */
template <class OtherPacket> OtherPacket findNext() const;
///< Find next packet of given type in chain
/**< findNext() is like next(), it will however return \c
*this if it is of the given type.
\param[in] nothrow This argument always has the value
\c senf::nothrow
- \returns in-valid() packet, if no such packet is found */
+ \returns in - valid() packet, if no such packet is
+ found */
Packet prev() const;
///< Get previous packet in chain
+ /**< \returns in - valid() packet, if no previous packet
+ exists */
template <class OtherPacket> OtherPacket prev() const;
///< Get previous packet of given type in chain
/**< \throws InvalidPacketChainException if no such packet
///< Get previous packet of given type in chain
/**< \param[in] nothrow This argument always has the value
\c senf::nothrow
- \returns in-valid() packet, if no such packet is found */
+ \returns in - valid() packet, if no such packet is
+ found */
template <class OtherPacket> OtherPacket findPrev() const;
///< Find previous packet of given type in chain
/**< findPrev() is like prev(), it will however return \c
*this if it is of the type
\param[in] nothrow This argument always has the value
\c senf::nothrow
- \returns in-valid() packet, if no such packet is found */
+ \returns in - valid() packet, if no such packet is
+ found */
Packet first() const;
///< Return first packet of given type in chain
/**< \param[in] nothrow This argument always has the value
\c senf::nothrow
- \returns in-valid() packet, if no such packet is found */
+ \returns in - valid() packet, if no such packet is
+ found */
Packet last() const;
///< Return last packet in chain
///< Return last packet of given type in chain
/**< \param[in] nothrow This argument always has the value
\c senf::nothrow
- \returns in-valid() packet, if no such packet is found */
+ \returns in - valid() packet, if no such packet is
+ found */
template <class OtherPacket> OtherPacket parseNextAs() const;
bool boolean_test() const; ///< Check, whether the packet is valid()
/**< \see valid() */
bool valid() const; ///< Check, whether the packet is valid()
- /**< An in-valid() packet does not allow any operation
- except checking for validity and assignment. in-valid()
- packets serve the same role as 0-pointers. */
-
+ /**< An in - valid() packet does not allow any operation
+ except checking for validity and assignment. in -
+ valid() packets serve the same role as 0-pointers.
+
+ This is an alias for boolean_test() which is called
+ when using a packet in a boolean context. */
void finalize() const; ///< Update calculated fields
/**< This call will update all calculated fields of the
{}
#endif
+#ifndef DOXYGEN
+template <class Parser, class Value>
+prefix_ typename boost::enable_if_c <
+ boost::is_base_of<senf::PacketParserBase, Parser>::value
+ && ! boost::is_base_of<senf::PacketParserBase, Value>::value,
+ Parser >::type senf::operator<<(Parser target, boost::optional<Value> const & value)
+{
+ if (value)
+ target.value(*value);
+ return target;
+}
+#else
+template <class Parser, class Value>
+prefix_ Parser senf::operator<<(Parser target, Value const & value)
+{}
+#endif
+
+
template <class Parser>
prefix_ senf::PacketParserBase::size_type
senf::detail::packetParserSize(Parser p, int, senf::mpl::take_uint<Parser::fixed_bytes> *)
# else
/** \brief Generic parser copying
+
This operator allows to copy the values of identical parsers. This operation does \e not
depend on the parsers detailed implementation, it will just replace the data bytes of the
target parser with those from the source parser. This allows to easily copy around complex
Parser operator<<(Parser target, Value const & value);
# endif
+# ifndef DOXYGEN
+ template <class Parser, class Value>
+ typename boost::enable_if_c <
+ boost::is_base_of<PacketParserBase, Parser>::value
+ && ! boost::is_base_of<PacketParserBase, Value>::value,
+ Parser >::type
+ operator<<(Parser target, boost::optional<Value> const & value);
+# else
+ /** \brief Generic parser value assignment
+
+ This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
+ value<tt>)</tt> member. This special version allows to assign optional values: IF the
+ optional value is not set, the assignment will be skipped.
+
+ This operator allows to use a common syntax for assigning values or parsers to a parser.
+
+ \ingroup packetparser
+ */
+ template <class Parser, class Value>
+ Parser operator<<(Parser target, boost::optional<Value> const & value);
+# endif
+
/** \defgroup packetparsermacros Helper macros for defining new packet parsers
To simplify the definition of simple packet parsers, several macros are provided. Before
return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () + senf::bytes( name () ); \
} \
size_type BOOST_PP_CAT(name, _offset) () const { \
- return BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) () ; \
+ return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () ; \
}
#
# define SENF_PACKET_PARSER_I_FIXED_Field(n,name,type) \
static const size_type BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) = \
BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) + type::fixed_bytes; \
static const size_type BOOST_PP_CAT(name,_offset) = \
- BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_));
+ BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_));
#
# define SENF_PACKET_PARSER_I_OverlayField(n,name,type) \
typedef type BOOST_PP_CAT(name,_t) ; \
return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) (); \
} \
size_type BOOST_PP_CAT(name, _offset) () const { \
- return BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) () ; \
+ return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () ; \
}
#
# define SENF_PACKET_PARSER_I_FIXED_OverlayField(n,name,type) \
static const size_type BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) = \
BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)); \
static const size_type BOOST_PP_CAT(name,_offset) = \
- BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_));
+ BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_));
#
# ///////////////////////////////mpp.e///////////////////////////////////////
# endif
p.as< ConcretePacket<Self> >()->init();
}
+template <class Self, class Registry>
+prefix_ typename senf::PacketTypeMixin<Self,Registry>::optional_registry_key_t
+senf::PacketTypeMixin<Self,Registry>::key(Packet p)
+{
+ return p ? PacketRegistry<Registry>::key(p, nothrow) : optional_registry_key_t();
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::PacketTypeMixin<Self,void>
static void finalize(packet p)
{
+ // Set the type field by querying the type of the next packet. This is an
+ // optional assignment: If the key is not found, the value returned by 'key'
+ // is an empty optional and the assignment will be skipped.
+ p->typeField << key(p.next());
+
// optionally complete the packet by generating auto-generated information
// (like checksums)
}
using mixin::init;
static registry_key_t nextPacketKey(packet p)
- { return i.fields().typeField(); }
+ { return p->typeField(); }
};
\endcode
{
public:
typedef typename Registry::key_t registry_key_t;
+ typedef boost::optional<registry_key_t> optional_registry_key_t;
+
+ static optional_registry_key_t key (Packet p); ///< Find key of packet from registry
+ /**< key() will query the registry to find the key of the
+ given packet. Whereas \c nextPacketKey() as implemented
+ by the mixin user will provide the registry key of the
+ next packet from information stored in the current
+ packets header, the key() member will look up the type
+ of packet \a p in the registry and return it's
+ key.
+
+ If either \a p is an in - valid() packet or the packet
+ type is not found in the registry, the returned
+ optional value will be empty. */
+
+ ///@{
+ ///\name PacketType interface implementation
static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
static PacketInterpreterBase::factory_t nextPacketType (Packet p);
static PacketInterpreterBase::size_type initSize ();
static void init (Packet p);
+
+ ///@}
};
# ifndef DOXYGEN
def checkLocalConf(target, source, env):
if [ True for f in env['CONFIG_FILES'] if nonemptyFile(f) ]:
print
- print "You have made local modifications to 'SConfig' and/or 'Doxyfile.local'."
+ print "You have made local modifications to one of the following local configuration"
+ print "files:"
+ for f in env['CONFIG_FILES']:
+ print " ",f
+ print
print "Building a debian package would remove those files."
print
print "To continue, remove the offending file(s) and try again. Alternatively,"
print "build a source package using 'scons debsrc' and may then build debian"
- print "binary packages from this source-package without disrupting your print local"
+ print "binary packages from this source-package without disrupting your local"
print "configuration."
print
return 1
PhonyTarget(env, 'linklint', [
'rm -rf linklint',
- 'linklint -doc linklint -net -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
+ 'linklint -doc linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
'[ ! -r linklint/errorX.html ] || python linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
'[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
'[ ! -r linklint/errorAX.html ] || python linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief IpChecksum inline non-template implementation */
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ senf::IpChecksum::IpChecksum()
+ : sum_(0), odd_(false)
+{}
+
+prefix_ void senf::IpChecksum::feed(boost::uint8_t byte)
+{
+ sum_ += odd_ ? byte : (byte<<8);
+ odd_ = ! odd_;
+}
+
+prefix_ boost::uint16_t senf::IpChecksum::sum()
+ const
+{
+ boost::uint32_t v (sum_);
+ while (v >> 16)
+ v = (v & 0xffff) + (v >> 16);
+ return ~ v;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief IpChecksum inline template implementation */
+
+//#include "IpChecksum.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class InputIterator>
+prefix_ void senf::IpChecksum::feed(InputIterator b, InputIterator e)
+{
+ for (; b != e; ++b)
+ feed(*b);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief IpChecksum public header */
+
+#ifndef HH_IpChecksum_
+#define HH_IpChecksum_ 1
+
+// Custom includes
+#include <boost/cstdint.hpp>
+
+//#include "IpChecksum.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+
+ /** \brief
+ */
+ class IpChecksum
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ IpChecksum();
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ void feed(boost::uint8_t byte);
+
+ template <class InputIterator>
+ void feed(InputIterator b, InputIterator e);
+
+ boost::uint16_t sum() const;
+
+ protected:
+
+ private:
+ boost::uint32_t sum_;
+ bool odd_;
+ };
+
+
+}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "IpChecksum.cci"
+//#include "IpChecksum.ct"
+#include "IpChecksum.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief IpChecksum.test unit tests */
+
+//#include "IpChecksum.test.hh"
+//#include "IpChecksum.test.ih"
+
+// Custom includes
+#include "IpChecksum.hh"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+BOOST_AUTO_UNIT_TEST(ipChecksum)
+{
+ char data[] = { 0x45, 0x00, 0x00, 0x28, 0x49, 0x44, 0x40, 0x00,
+ 0x40, 0x06, 0x00, 0x00, 0x0a, 0xc1, 0x01, 0x06,
+ 0xc2, 0x9f, 0xa4, 0xc3 };
+
+ senf::IpChecksum summer;
+ summer.feed(data, data+sizeof(data));
+ BOOST_CHECK_EQUAL( summer.sum(), 0x7e62u );
+}
+
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End: