Packets/80211Bundle: add WLAN Packet Parser and Unittests
cni [Mon, 8 Dec 2008 17:20:10 +0000 (17:20 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1005 270642c3-0616-0410-b53a-bc976706d245

Packets/80211Bundle/WLANPacket.cc [new file with mode: 0644]
Packets/80211Bundle/WLANPacket.hh [new file with mode: 0644]
Packets/80211Bundle/WLANPacket.test.cc [new file with mode: 0644]

diff --git a/Packets/80211Bundle/WLANPacket.cc b/Packets/80211Bundle/WLANPacket.cc
new file mode 100644 (file)
index 0000000..ff4f271
--- /dev/null
@@ -0,0 +1,131 @@
+// $Id: $
+//
+// Copyright (C) 2006
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Christian Niephaus <christian.niephaus@fokus.fraunhofer.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.
+
+// Definition of non-inline non-template functions
+
+// Custom includes
+#include "WLANPacket.hh"
+#include "../../Packets/Packets.hh"
+#include "../DefaultBundle/LlcSnapPacket.hh"
+#include <boost/io/ios_state.hpp>
+
+#define prefix_
+
+namespace
+{
+
+}
+
+prefix_ senf::MACAddressParser senf::WLANPacketParser_DataFrameParser::da()
+    const
+{
+    switch (dsBits())
+    {
+    case 0 :
+    case 2 :
+        return addr1();
+        break;
+    case 1 :
+    case 3 :
+        return addr3();
+        break;
+    }
+}
+
+prefix_ senf::MACAddressParser senf::WLANPacketParser_DataFrameParser::sa()
+    const
+{
+    switch (dsBits())
+    {
+    case 0 :
+    case 1 :
+        return addr2();
+        break;
+    case 2 :
+        return addr3();
+        break;
+//TODO wds frames
+//    case 3:
+//        return addr4();
+    }
+}
+
+prefix_ senf::MACAddressParser senf::WLANPacketParser_DataFrameParser::bssid()
+    const
+{
+    switch (dsBits())
+    {
+    case 0 :
+        return addr3();
+        break;
+    case 1 :
+        return addr1();
+        break;
+    case 2:
+        return addr2();
+    }
+}
+
+//shift some bits to read the 12bit sequence number bit field in LSB byte order
+prefix_ boost::uint16_t senf::WLANPacketParser_MgtFrameParser::sequenceNumber()
+    const
+{
+    boost::uint16_t seqN = 0;
+    seqN |= seqNumber_2();
+    seqN <<= 4;
+    seqN |= seqNumber_1();
+    return seqN;
+}
+
+//shift some bits to read the 12bit sequence number bit field in LSB byte order
+prefix_ boost::uint16_t senf::WLANPacketParser_DataFrameParser::sequenceNumber()
+    const
+{
+    boost::uint16_t seqN = 0;
+    seqN |= seqNumber_2();
+    seqN <<= 4;
+    seqN |= seqNumber_1();
+    return seqN;
+}
+
+prefix_ void senf::WLANPacketType::dump(packet p, std::ostream &os)
+{
+    boost::io::ios_all_saver ias(os);
+    os  << "802.11 MAC Frame:\n"
+        << "  Type              : " << unsigned (p->type()) << "\n"
+        << "  Subtype           : " << unsigned (p->subtype()) << "\n"
+        << "  Retransmission    : " << unsigned (p->retry()) << "\n"
+        << "  Duration          : " << unsigned (p->duration()) << "\n";
+
+    if (p->has_mgtFrame())
+    {
+        os << "  BSSID              : " << p->mgtFrame().bssid() << "\n";
+        os << "  Destination Addr.  : " << p->mgtFrame().da() << "\n";
+        os << "  Source Addr.  : " << p->mgtFrame().sa() << "\n";
+    }
+
+};
+
+
+
+
+#undef prefix_
diff --git a/Packets/80211Bundle/WLANPacket.hh b/Packets/80211Bundle/WLANPacket.hh
new file mode 100644 (file)
index 0000000..47f4930
--- /dev/null
@@ -0,0 +1,230 @@
+// $Id:$
+//
+// Copyright (C) 2006
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Christian Niephaus <christian.niephaus@fokus.fraunhofer.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 802.11 WLan MAC frame \n
+
+
+    */
+
+#ifndef WLANPACKET_HH_
+#define WLANPACKET_HH_
+
+#include "../../Packets/Packets.hh"
+#include "../DefaultBundle/EthernetPacket.hh"
+#include <boost/cstdint.hpp>
+
+namespace senf
+{
+
+    /** \brief Management frame parser
+     * <b>Re-ordering of bits due to LSB byte order</b>
+
+     */
+    struct WLANPacketParser_MgtFrameParser : public senf::PacketParserBase
+    {
+    #   include SENF_FIXED_PARSER()
+        SENF_PARSER_PRIVATE_BITFIELD    ( subtype,  4,  unsigned);
+        SENF_PARSER_SKIP_BITS   ( 4                                    ); //skip type and version
+        //jump to fist address field
+        SENF_PARSER_SKIP                ( 3                                    );
+        SENF_PARSER_FIELD               ( da, MACAddressParser        );
+        SENF_PARSER_FIELD               ( sa, MACAddressParser        );
+        SENF_PARSER_FIELD               ( bssid, MACAddressParser        );
+
+        //workaround since bitfield LSB parsers are not available
+        SENF_PARSER_PRIVATE_BITFIELD    (seqNumber_1, 4, unsigned);
+        SENF_PARSER_BITFIELD    (fragmentNumber, 4, unsigned);
+        SENF_PARSER_PRIVATE_FIELD     (seqNumber_2, UInt8Parser);
+
+        SENF_PARSER_FINALIZE(WLANPacketParser_MgtFrameParser);
+
+        //this is needed due to the goto in the WLANPacketParser. Don't know exactly why yet.
+        SENF_PARSER_INIT() {}
+
+        boost::uint16_t sequenceNumber() const;
+
+    };
+
+    /** \brief Control frame parser
+     * <b>Re-ordering of bits due to LSB byte order</b>
+     *
+     * currently only CTS, RTS and ACK control frames are supported
+
+     */
+    struct WLANPacketParser_CtrlFrameParser : public senf::PacketParserBase
+    {
+    #   include SENF_PARSER()
+        SENF_PARSER_PRIVATE_BITFIELD    ( subtype,  4,  unsigned);
+        SENF_PARSER_SKIP_BITS   ( 4                                    ); //skip type and version
+        //jump to fist address field
+        SENF_PARSER_SKIP                ( 3,3                        );
+        SENF_PARSER_FIELD               ( ra, MACAddressParser         );
+
+        //only RTS frame contains a source address field
+        //variant is also needed so set to correct subtype value
+        SENF_PARSER_VARIANT ( subtype__,             subtype,
+                ( ids (na, na, set_cts, key(12, VoidPacketParser)) )
+                ( ids (na, na, set_ack, key(13, VoidPacketParser)) )
+                ( ids (sa, has_sa, set_rts, key(11, MACAddressParser)) ) );
+
+        SENF_PARSER_FINALIZE(WLANPacketParser_CtrlFrameParser);
+
+        //this is needed to due to the goto in the WLANPacketParser. Don't know exactly why yet.
+        SENF_PARSER_INIT() {}
+    };
+
+    /** \brief Data frame parser
+     * <b>Re-ordering of bits due to LSB byte order</b>
+
+     */
+    struct WLANPacketParser_DataFrameParser : public senf::PacketParserBase
+    {
+    #   include SENF_PARSER()
+        SENF_PARSER_PRIVATE_BITFIELD    ( subtype,  4,  unsigned);
+        //jump to 'toDS' and 'fromDS' bits
+        //skip type and version
+        SENF_PARSER_SKIP_BITS   ( 4                                    );
+        //skip other flags
+        SENF_PARSER_SKIP_BITS   ( 6                                    );
+        //needed in data frames due to the variable address fields
+        SENF_PARSER_PRIVATE_BITFIELD    ( dsBits,    2,  unsigned);
+        //skip duration field
+        SENF_PARSER_SKIP        ( 2,0                          );
+
+        SENF_PARSER_PRIVATE_FIELD               ( addr1, MACAddressParser        );
+        SENF_PARSER_PRIVATE_FIELD               ( addr2, MACAddressParser        );
+        SENF_PARSER_PRIVATE_FIELD               ( addr3, MACAddressParser        );
+
+        //sequence Number and fragment number
+        //shift bits manually due to LSB
+        SENF_PARSER_PRIVATE_BITFIELD    (seqNumber_1, 4, unsigned);
+        SENF_PARSER_BITFIELD    (fragmentNumber, 4, unsigned);
+        SENF_PARSER_PRIVATE_FIELD     (seqNumber_2, UInt8Parser)
+
+        //TODO fourth address field in case of WDS
+//        SENF_PARSER_PRIVATE_VARIANT (wds_, dsBits,
+//                ( novalue ( disable_addr4,               VoidPacketParser                    ))
+//                ( id      ( addr4,  key (3,                   MACAddressParser                     ))) );
+
+        //QoS Filed
+        SENF_PARSER_VARIANT (qosField_, subtype,
+                ( ids (na, na, set_data, key(0, VoidPacketParser)))
+                ( ids (na, na, set_nullData, key(4, VoidPacketParser)))
+                ( ids (qosField, has_qosField, set_qosData, key(8, UInt16LSBParser)))
+                //we cannot parse qos Null (data) frames at the moment
+                ( ids (na, na, set_qosNullData, key(12, UInt16LSBParser))) );
+
+
+
+        SENF_PARSER_FINALIZE(WLANPacketParser_DataFrameParser);
+
+        //this is needed to due to the goto in the WLANPacketParser. Don't know exactly why yet.
+        SENF_PARSER_INIT() {}
+
+        boost::uint16_t sequenceNumber() const;
+
+        MACAddressParser ra() const { return addr1(); }; //ra is always addr1
+        MACAddressParser ta() const { return addr2(); }; //ta is always addr2
+        MACAddressParser sa() const;
+        MACAddressParser da() const;
+        MACAddressParser bssid() const;
+    };
+
+
+    /** \brief 802.11 Frame parser
+     * (see IEEE 802.11-2007 standard - Chapter 7 Frame formats)
+     * <b>Re-ordering of bits due to LSB byte order</b>
+
+     */
+    struct WLANPacketParser : public senf::PacketParserBase
+    {
+    #   include SENF_PARSER()
+
+        /*
+         * Frame control field
+         * re-ordering of fields due to the byte order
+         */
+        SENF_PARSER_BITFIELD_RO    ( subtype,  4,  unsigned);
+        SENF_PARSER_BITFIELD_RO    ( type,     2,  unsigned);
+        SENF_PARSER_BITFIELD    ( version,  2,  unsigned);
+        SENF_PARSER_BITFIELD    ( order,     1,  bool);
+        SENF_PARSER_BITFIELD    ( protectedFrame,    1,  bool);
+        SENF_PARSER_BITFIELD    ( moreData,  1,  bool);
+        SENF_PARSER_BITFIELD    ( pwrMgt,   1,  bool);
+        SENF_PARSER_BITFIELD    ( retry,     1,  bool);
+        SENF_PARSER_BITFIELD    ( moreFrag,  1,  bool);
+        SENF_PARSER_BITFIELD    ( fromDS,    1,  bool);
+        SENF_PARSER_BITFIELD    ( toDS,      1,  bool);
+
+        SENF_PARSER_FIELD   (duration,          UInt16LSBParser);
+
+        SENF_PARSER_GOTO( subtype ); //subparsers need to know the subtype
+        SENF_PARSER_VARIANT ( type__,             type,
+                                ( id      ( mgtFrame,   WLANPacketParser_MgtFrameParser     ))
+                                ( id      ( ctrlFrame,  WLANPacketParser_CtrlFrameParser    ))
+                                ( id      ( dataFrame,  WLANPacketParser_DataFrameParser    ))
+                                ( novalue ( reserved,   WLANPacketParser_CtrlFrameParser    )) );
+
+        SENF_PARSER_CUSTOM_FIELD( fcs, senf:: UInt32Parser, fcs_t::fixed_bytes, fcs_t::fixed_bytes) {
+          return parse<UInt32Parser>( data().size()-4 ); }
+
+        SENF_PARSER_FINALIZE(WLANPacketParser);
+
+        SENF_PARSER_INIT() {
+            version() = 0;
+
+
+        }
+
+        //Problems can occur with old madwifi and ath5k. Some frames only
+        //contains two byte FCS instead of four.
+//        UInt32Parser fcs() const { return parse<UInt32Parser>( data().size()-4 ); }
+
+    };
+
+    struct WLANPacketType
+        : public senf::PacketTypeBase,
+        public senf::PacketTypeMixin<WLANPacketType>
+    {
+
+        typedef senf::PacketTypeMixin<WLANPacketType> mixin;
+        typedef senf::ConcretePacket<WLANPacketType> packet;
+        typedef WLANPacketParser parser;
+
+//        using mixin::nextPacketRange;
+        using mixin::init;
+        using mixin::initSize;
+        using senf::PacketTypeBase::nextPacketRange;;
+
+
+        static void dump(packet p, std::ostream &os);
+//        static PacketParserBase::size_type initSize();
+    };
+
+    typedef WLANPacketType::packet WLANPacket;
+
+}
+
+
+
+#endif /* WLANPACKET_HH_ */
diff --git a/Packets/80211Bundle/WLANPacket.test.cc b/Packets/80211Bundle/WLANPacket.test.cc
new file mode 100644 (file)
index 0000000..e66acd0
--- /dev/null
@@ -0,0 +1,228 @@
+// $Id: main.test.cc 206 2008-08-06 14:20:52Z pug $
+//
+// Copyright (C) 2006
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Christian Niephaus <christian.niephaus@fokus.fraunhofer.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.
+
+// Definition of non-inline non-template functions
+
+// Custom includes
+
+#include "../../Packets/Packets.hh"
+#include "../../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+#include "WLANPacket.hh"
+
+/* test parser with a data frame */
+BOOST_AUTO_UNIT_TEST(WLANPacket_dataFrame_packet)
+{
+
+
+    unsigned char data[] = {0x88, 0x01, 0x00, 0x00, 0x00, 0x1a,             //header
+                            0x4d, 0x3e, 0xc7, 0x5c, 0x00, 0x0b, 0x6b, 0x57,
+                            0x06, 0xb0, 0x00, 0x18, 0x4d, 0x6e, 0x78, 0x48,
+                            0x30, 0x00, 0x01, 0x00,
+                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //dummy data
+                            0x38, 0x39, 0x30, 0x31                          //trailer
+                            };
+
+
+
+
+    senf::WLANPacket p (senf::WLANPacket::create(data));
+
+    BOOST_CHECK_EQUAL( p->version(), 0u);
+    BOOST_CHECK_EQUAL( p->type(), 2u);
+    BOOST_CHECK_EQUAL( p->subtype(), 8u);
+    BOOST_CHECK_EQUAL( p->toDS(), true);
+    BOOST_CHECK_EQUAL( p->fromDS(), false);
+    BOOST_CHECK_EQUAL( p->moreFrag(), false);
+    BOOST_CHECK_EQUAL( p->retry(), false);
+    BOOST_CHECK_EQUAL( p->pwrMgt(), false);
+    BOOST_CHECK_EQUAL( p->moreData(), false);
+    BOOST_CHECK_EQUAL( p->protectedFrame(), false);
+    BOOST_CHECK_EQUAL( p->order(), false);
+
+    BOOST_CHECK_EQUAL( p->duration(), 0u);
+
+    BOOST_CHECK_EQUAL( p->dataFrame().da()[0], 0x00 );
+    BOOST_CHECK_EQUAL( p->dataFrame().da()[1], 0x18 );
+    BOOST_CHECK_EQUAL( p->dataFrame().da()[2], 0x4d );
+    BOOST_CHECK_EQUAL( p->dataFrame().da()[3], 0x6e );
+    BOOST_CHECK_EQUAL( p->dataFrame().da()[4], 0x78 );
+    BOOST_CHECK_EQUAL( p->dataFrame().da()[5], 0x48 );
+
+    BOOST_CHECK_EQUAL( p->dataFrame().sa()[0], 0x00 );
+    BOOST_CHECK_EQUAL( p->dataFrame().sa()[3], 0x57 );
+    BOOST_CHECK_EQUAL( p->dataFrame().sa()[5], 0xb0 );
+
+    BOOST_CHECK_EQUAL( p->dataFrame().bssid()[0], 0x00 );
+    BOOST_CHECK_EQUAL( p->dataFrame().bssid()[3], 0x3e );
+    BOOST_CHECK_EQUAL( p->dataFrame().bssid()[5], 0x5c );
+
+    BOOST_CHECK_EQUAL( p->dataFrame().bssid()[3],
+                       p->dataFrame().ra()[3]);
+
+    BOOST_CHECK_EQUAL( p->dataFrame().ta()[3],
+                       p->dataFrame().sa()[3]);
+
+    BOOST_CHECK_EQUAL( p->dataFrame().sequenceNumber(), 3u );
+    BOOST_CHECK_EQUAL( p->dataFrame().fragmentNumber(), 0u );
+
+
+
+}
+
+/* test parser with creating a data frame*/
+BOOST_AUTO_UNIT_TEST(WLANPacket_dataFrame_create)
+{
+    senf::WLANPacket p (senf::WLANPacket::create());
+
+    SENF_CHECK_NO_THROW(p->init_dataFrame());
+    p->dataFrame().bssid()=senf::MACAddress::from_string("00:1a:4d:3e:c7:5c");
+    BOOST_CHECK_EQUAL( p->type(), 2u);
+}
+
+
+
+/* test parser with a beacon frame */
+BOOST_AUTO_UNIT_TEST(WLANPacket_beaconFrame_packet)
+{
+
+
+    unsigned char data[] = {0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+                            0xff, 0xff, 0x00, 0x1a, 0x4d, 0x3e, 0xc7, 0x5c,
+                            0x00, 0x1a, 0x4d, 0x3e, 0xc7, 0x5c, 0xe0, 0x12,
+                            0x38, 0xa0, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00,
+                            0x64, 0x00, 0x01, 0x05, 0x00, 0x05, 0x62, 0x6f,
+                            0x78, 0x43, 0x31, 0x01, 0x08, 0x8c, 0x12, 0x98,
+                            0x24, 0xb0, 0x48, 0x60, 0x6c, 0x03, 0x01, 0x40,
+                            0x05, 0x04, 0x00, 0x01, 0x00, 0x00, 0x07, 0x2a,
+                            0x4e, 0x41, 0x49, 0x24, 0x01, 0x11, 0x28, 0x01,
+                            0x11, 0x2c, 0x01, 0x11, 0x30, 0x01, 0x11, 0x34,
+                            0x01, 0x17, 0x38, 0x01, 0x17, 0x3c, 0x01, 0x17,
+                            0x40, 0x01, 0x17, 0x95, 0x01, 0x1e, 0x99, 0x01,
+                            0x1e, 0x9d, 0x01, 0x1e, 0xa1, 0x01, 0x1e, 0xa5,
+                            0x01, 0x1e, 0x20, 0x01, 0x00, 0xdd, 0x18, 0x00,
+                            0x50, 0xf2, 0x02, 0x01, 0x01, 0x81, 0x00, 0x02,
+                            0xa3, 0x40, 0x00, 0x27, 0xa4, 0x00, 0x00, 0x42,
+                            0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, 0xa0,
+                            0x00, 0xdd, 0x09, 0x00, 0x03, 0x7f, 0x01, 0x01,
+                            0x00, 0x24, 0xff, 0x7f, 0x87, 0x07, 0x1f, 0xf5,
+                            };
+
+    senf::WLANPacket p (senf::WLANPacket::create(data));
+
+    BOOST_CHECK_EQUAL( p->version(), 0u);
+    BOOST_CHECK_EQUAL( p->type(), 0u);
+    BOOST_CHECK_EQUAL( p->subtype(), 8u);
+    BOOST_CHECK_EQUAL( p->toDS(), false);
+    BOOST_CHECK_EQUAL( p->fromDS(), false);
+    BOOST_CHECK_EQUAL( p->moreFrag(), false);
+    BOOST_CHECK_EQUAL( p->retry(), false);
+    BOOST_CHECK_EQUAL( p->pwrMgt(), false);
+    BOOST_CHECK_EQUAL( p->moreData(), false);
+    BOOST_CHECK_EQUAL( p->protectedFrame(), false);
+    BOOST_CHECK_EQUAL( p->order(), false);
+
+    BOOST_CHECK_EQUAL( p->duration(), 0u);
+
+    BOOST_CHECK_EQUAL (p->has_mgtFrame(), true);
+
+    BOOST_CHECK_EQUAL( p->mgtFrame().da()[0], 0xff );
+    BOOST_CHECK_EQUAL( p->mgtFrame().da()[3], 0xff );
+    BOOST_CHECK_EQUAL( p->mgtFrame().da()[5], 0xff );
+
+    BOOST_CHECK_EQUAL( p->mgtFrame().sa()[0], 0x00 );
+    BOOST_CHECK_EQUAL( p->mgtFrame().sa()[3], 0x3e );
+    BOOST_CHECK_EQUAL( p->mgtFrame().sa()[5], 0x5c );
+
+    BOOST_CHECK_EQUAL( p->mgtFrame().bssid()[0], 0x00 );
+    BOOST_CHECK_EQUAL( p->mgtFrame().bssid()[3], 0x3e );
+    BOOST_CHECK_EQUAL( p->mgtFrame().bssid()[5], 0x5c );
+
+    BOOST_CHECK_EQUAL( p->mgtFrame().sequenceNumber(), 302u );
+    BOOST_CHECK_EQUAL( p->mgtFrame().fragmentNumber(), 0u );
+
+
+    BOOST_CHECK_EQUAL ( p->fcs(), 0x87071ff5);
+
+}
+
+/* test parser with creating a beacon frame*/
+BOOST_AUTO_UNIT_TEST(WLANPacket_mgtFrame_create)
+{
+    senf::WLANPacket p (senf::WLANPacket::create());
+
+    SENF_CHECK_NO_THROW(p->init_mgtFrame());
+    SENF_CHECK_NO_THROW(
+            p->mgtFrame().da()=senf::MACAddress::from_string("ff:ff:ff:ff:ff:ff")
+    );
+    SENF_CHECK_NO_THROW(
+            p->mgtFrame().sa()=senf::MACAddress::from_string("00:1a:4d:3e:c7:5c")
+    );
+    SENF_CHECK_NO_THROW(
+            p->mgtFrame().bssid()=senf::MACAddress::from_string("00:1a:4d:3e:c7:5c")
+    );
+
+    BOOST_CHECK_EQUAL( p->type(), 0u);
+}
+
+/* test parser with an ACK frame*/
+BOOST_AUTO_UNIT_TEST(WLANPacket_ctrlFrame_packet)
+{
+
+
+    unsigned char data[] = {0xd4, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x6b, 0x57,
+                            0x06, 0xb0, 0x4f, 0xda};
+
+    senf::WLANPacket p (senf::WLANPacket::create(data));
+
+    BOOST_CHECK_EQUAL( p->version(), 0u);
+    BOOST_CHECK_EQUAL( p->type(), 1u);
+    BOOST_CHECK_EQUAL( p->subtype(), 13u);
+    BOOST_CHECK_EQUAL( p->toDS(), false);
+    BOOST_CHECK_EQUAL( p->fromDS(), false);
+    BOOST_CHECK_EQUAL( p->moreFrag(), false);
+    BOOST_CHECK_EQUAL( p->retry(), false);
+    BOOST_CHECK_EQUAL( p->pwrMgt(), false);
+    BOOST_CHECK_EQUAL( p->moreData(), false);
+    BOOST_CHECK_EQUAL( p->protectedFrame(), false);
+    BOOST_CHECK_EQUAL( p->order(), false);
+
+    BOOST_CHECK_EQUAL( p->duration(), 0u);
+
+    BOOST_CHECK_EQUAL (p->ctrlFrame().ra()[0], 0x00);
+    BOOST_CHECK_EQUAL (p->ctrlFrame().ra()[3], 0x57);
+    BOOST_CHECK_EQUAL (p->ctrlFrame().ra()[5], 0xb0);
+}
+
+/* test parser with creating an ACK frame*/
+BOOST_AUTO_UNIT_TEST(WLANPacket_ctrlFrame_create)
+{
+    senf::WLANPacket p (senf::WLANPacket::create()) ;
+//    std::cout << unsigned( senf::init_bytes<senf::WLANPacketParser_CtrlFrameParser>::value ) << "\n";
+    SENF_CHECK_NO_THROW(p->init_ctrlFrame());
+//    std::cout << unsigned( senf::init_bytes<senf::WLANPacketParser_CtrlFrameParser>::value ) << "\n";
+    p->ctrlFrame().ra()=senf::MACAddress::from_string("00:1a:4d:3e:c7:5c");
+    p->ctrlFrame().set_ack();
+    BOOST_CHECK_EQUAL( p->type(), 1u);
+    BOOST_CHECK_EQUAL( p->subtype(), 13u);
+}
+