diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 10a7ed2..5fdd743 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -21,6 +21,7 @@ include(GrPlatform) #define LIB_SUFFIX list(APPEND gr_ieee802_11_sources + ether_encap_impl.cc ofdm_decode_mac.cc ofdm_decode_signal.cc ofdm_equalize_symbols.cc @@ -32,12 +33,10 @@ list(APPEND gr_ieee802_11_sources list(APPEND gr_ieee802_11_libs ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} - ${GNURADIO_FILTER_LIBRARIES} - ${GNURADIO_FFT_LIBRARIES} ) add_library(gnuradio-ieee802_11 SHARED ${gr_ieee802_11_sources}) -target_link_libraries(gnuradio-ieee802_11 ${gr_ieee802_11_libs} itpp) +target_link_libraries(gnuradio-ieee802_11 ${gr_ieee802_11_libs} itpp gnuradio-fft gnuradio-filter) set_target_properties(gnuradio-ieee802_11 PROPERTIES DEFINE_SYMBOL "gnuradio_ieee802_11_EXPORTS") ######################################################################## diff --git a/lib/ether_encap_impl.cc b/lib/ether_encap_impl.cc new file mode 100644 index 0000000..3673c18 --- /dev/null +++ b/lib/ether_encap_impl.cc @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013 Bastian Bloessl + * + * 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 3 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, see . + */ +#include "ether_encap_impl.h" +#include "ofdm_parse_mac_impl.h" + +#include +#include +#include + +using namespace gr::ieee802_11; + +#define dout d_debug && std::cout + +ether_encap_impl::ether_encap_impl(bool debug) : + block("ether_encap", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_debug(debug), + d_last_seq(123) { + + message_port_register_out(pmt::mp("out")); + + message_port_register_in(pmt::mp("in")); + set_msg_handler(pmt::mp("in"), boost::bind(ðer_encap_impl::parse, this, _1)); +} + +void +ether_encap_impl::parse(pmt::pmt_t msg) { + + if(pmt::is_eof_object(msg)) { + message_port_pub(pmt::mp("out"), pmt::PMT_EOF); + detail().get()->set_done(true); + return; + } + + msg = pmt::cdr(msg); + + int data_len = pmt::blob_length(msg); + const mac_header *mhdr = reinterpret_cast(pmt::blob_data(msg)); + + if(d_last_seq == mhdr->seq_control) { + dout << "Ether Encap: frame already seen -- skipping" << std::endl; + return; + } + + d_last_seq = mhdr->seq_control; + + if(data_len < 33) { + dout << "Ether Encap: frame too short to parse (<33)" << std::endl; + return; + } + + ethernet_header *ehdr = reinterpret_cast(buf); + + if(((mhdr->frame_control >> 2) & 3) != 2) { + dout << "this is not a data frame -- ignoring" << std::endl; + return; + } + + memcpy(ehdr->dest, mhdr->addr1, 6); + memcpy(ehdr->src, mhdr->addr2, 6); + ehdr->type = 0x0008; + + char *frame = (char*)pmt::blob_data(msg); + + // DATA + if((((mhdr->frame_control) >> 2) & 63) == 2) { + memcpy(buf + sizeof(ethernet_header), frame + 32, data_len - 32); + pmt::pmt_t payload = pmt::make_blob(buf, data_len - 32 + 14); + message_port_pub(pmt::mp("out"), pmt::cons(pmt::PMT_NIL, payload)); + + // QoS Data + } else if((((mhdr->frame_control) >> 2) & 63) == 34) { + + memcpy(buf + sizeof(ethernet_header), frame + 34, data_len - 34); + pmt::pmt_t payload = pmt::make_blob(buf, data_len - 34 + 14); + message_port_pub(pmt::mp("out"), pmt::cons(pmt::PMT_NIL, payload)); + } +} + +ether_encap::sptr +ether_encap::make(bool debug) { + return gnuradio::get_initial_sptr(new ether_encap_impl(debug)); +} + diff --git a/lib/ether_encap_impl.h b/lib/ether_encap_impl.h new file mode 100644 index 0000000..df70d1b --- /dev/null +++ b/lib/ether_encap_impl.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 Bastian Bloessl + * + * 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 3 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, see . + */ +#ifndef INCLUDED_IEEE802_11_ETHER_ENCAP_IMPL_H +#define INCLUDED_IEEE802_11_ETHER_ENCAP_IMPL_H + +#include + +namespace gr { +namespace ieee802_11 { + + struct ethernet_header { + uint8_t dest[6]; + uint8_t src[6]; + uint16_t type; + }__attribute__((packed)); + + class ether_encap_impl : public ether_encap { + + public: + ether_encap_impl(bool debug); + + private: + void parse(pmt::pmt_t msg); + + bool d_debug; + char buf[3000]; + uint16_t d_last_seq; + }; + +} // namespace ieee802_11 +} // namespace gr + +#endif /* INCLUDED_IEEE802_11_ETHER_ENCAP_IMPL_H */ + diff --git a/lib/ofdm_decode_mac.cc b/lib/ofdm_decode_mac.cc index 3c8f2fe..bef097b 100644 --- a/lib/ofdm_decode_mac.cc +++ b/lib/ofdm_decode_mac.cc @@ -14,166 +14,25 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include + +#include "ofdm_utils.h" + +#include #include #include - #include #include using namespace gr::ieee802_11; using namespace itpp; -enum ENCODING { - BPSK_1_2, - BPSK_3_4, - QPSK_1_2, - QPSK_3_4, - QAM16_1_2, - QAM16_3_4, - QAM64_2_3, - QAM64_3_4, -}; - -/** - * OFDM parameters - */ -class GR_IEEE802_11_API ofdm_param { -public: -ofdm_param(ENCODING e) { - encoding = e; - - switch(e) { - case BPSK_1_2: - n_bpsc = 1; - n_cbps = 48; - n_dbps = 24; - rate_field = 0x0D; // 0b00001101 - break; - - case BPSK_3_4: - n_bpsc = 1; - n_cbps = 48; - n_dbps = 36; - rate_field = 0x0F; // 0b00001111 - break; - - case QPSK_1_2: - n_bpsc = 2; - n_cbps = 96; - n_dbps = 48; - rate_field = 0x05; // 0b00000101 - break; - - case QPSK_3_4: - n_bpsc = 2; - n_cbps = 96; - n_dbps = 72; - rate_field = 0x07; // 0b00000111 - break; - - case QAM16_1_2: - n_bpsc = 4; - n_cbps = 192; - n_dbps = 96; - rate_field = 0x09; // 0b00001001 - break; - - case QAM16_3_4: - n_bpsc = 4; - n_cbps = 192; - n_dbps = 144; - rate_field = 0x0B; // 0b00001011 - break; - - case QAM64_2_3: - n_bpsc = 6; - n_cbps = 288; - n_dbps = 192; - rate_field = 0x01; // 0b00000001 - break; - - case QAM64_3_4: - n_bpsc = 6; - n_cbps = 288; - n_dbps = 216; - rate_field = 0x03; // 0b00000011 - break; - defaut: - assert(false); - break; - } -} - -void print_out() { - std::cout << "OFDM Parameters:" << std::endl; - std::cout << "endcoding :" << encoding << std::endl; - std::cout << "rate_field :" << (int)rate_field << std::endl; - std::cout << "n_bpsc :" << n_bpsc << std::endl; - std::cout << "n_cbps :" << n_cbps << std::endl; - std::cout << "n_dbps :" << n_dbps << std::endl; -} - - // data rate - ENCODING encoding; - // rate field of the SIGNAL header - char rate_field; - // number of coded bits per sub carrier - int n_bpsc; - // number of coded bits per OFDM symbol - int n_cbps; - // number of data bits per OFDM symbol - int n_dbps; -}; - -/** - * packet specific parameters - */ -class tx_param { -public: -tx_param(ofdm_param &ofdm, int psdu_length) { - - psdu_size = psdu_length; - - // number of symbols (17-11) - n_sym = (int) ceil((16 + 8 * psdu_size + 6) / (double) ofdm.n_dbps); - - // number of bits of the data field (17-12) - n_data = n_sym * ofdm.n_dbps; - - // number of padding bits (17-13) - n_pad = n_data - (16 + 8 * psdu_size + 6); - - n_encoded_bits = n_sym * ofdm.n_cbps; -} - // PSDU size in bytes - int psdu_size; - // number of OFDM symbols (17-11) - int n_sym; - // number of data bits in the DATA field, including service and padding (17-12) - int n_data; - // number of padding bits in the DATA field (17-13) - int n_pad; - int n_encoded_bits; - -void print_out() { - std::cout << "TX Parameters:" << std::endl; - std::cout << "psdu_size: " << psdu_size << std::endl; - std::cout << "n_sym: " << n_sym << std::endl; - std::cout << "n_data: " << n_data << std::endl; - std::cout << "n_pad: " << n_pad << std::endl; -} - -}; - - - class ofdm_decode_mac_impl : public ofdm_decode_mac { #define dout d_debug && std::cout public: -ofdm_decode_mac_impl(bool debug) : gr::block("ofdm_decode_mac", +ofdm_decode_mac_impl(bool debug) : block("ofdm_decode_mac", gr::io_signature::make(1, 1, 48 * sizeof(gr_complex)), gr::io_signature::make(0, 0, 0)), d_debug(debug), @@ -253,8 +112,19 @@ void decode() { print_output(); // skip service field - pmt::pmt_t blob = pmt::make_blob(out_bytes + 2, tx.psdu_size); - message_port_pub(pmt::mp("out"), blob); + boost::crc_32_type result; + result.process_bytes(out_bytes + 2, tx.psdu_size); + if(result.checksum() != 558161692) { + dout << "checksum wrong -- dropping" << std::endl; + return; + } + + // create PDU + pmt::pmt_t blob = pmt::make_blob(out_bytes + 2, tx.psdu_size - 4); + pmt::pmt_t enc = pmt::from_uint64(ofdm.encoding); + pmt::pmt_t dict = pmt::make_dict(); + dict = pmt::dict_add(dict, pmt::mp("encoding"), enc); + message_port_pub(pmt::mp("out"), pmt::cons(dict, blob)); } void demodulate() { diff --git a/lib/ofdm_decode_signal.cc b/lib/ofdm_decode_signal.cc index 16fc6fe..2bc426b 100644 --- a/lib/ofdm_decode_signal.cc +++ b/lib/ofdm_decode_signal.cc @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include #include #include @@ -29,7 +29,7 @@ class ofdm_decode_signal_impl : public ofdm_decode_signal { #define dout d_debug && std::cout public: -ofdm_decode_signal_impl(bool debug) : gr::block("ofdm_decode_signal", +ofdm_decode_signal_impl(bool debug) : block("ofdm_decode_signal", gr::io_signature::make(1, 1, 48 * sizeof(gr_complex)), gr::io_signature::make(1, 1, 48 * sizeof(gr_complex))), d_debug(debug), @@ -37,7 +37,7 @@ ofdm_decode_signal_impl(bool debug) : gr::block("ofdm_decode_signal", decoded_bits.set_size(24); set_relative_rate(1); - set_tag_propagation_policy(gr::block::TPP_DONT); + set_tag_propagation_policy(block::TPP_DONT); } ~ofdm_decode_signal_impl(){ diff --git a/lib/ofdm_equalize_symbols.cc b/lib/ofdm_equalize_symbols.cc index dbe1f37..6d7c4c8 100644 --- a/lib/ofdm_equalize_symbols.cc +++ b/lib/ofdm_equalize_symbols.cc @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include #include #include @@ -27,7 +27,7 @@ class ofdm_equalize_symbols_impl : public ofdm_equalize_symbols { #define dout d_debug && std::cout public: -ofdm_equalize_symbols_impl(bool debug) : gr::block("ofdm_equalize_symbols", +ofdm_equalize_symbols_impl(bool debug) : block("ofdm_equalize_symbols", gr::io_signature::make(1, 1, 64 * sizeof(gr_complex)), gr::io_signature::make(1, 1, 48 * sizeof(gr_complex))), d_debug(debug) { diff --git a/lib/ofdm_parse_mac.cc b/lib/ofdm_parse_mac.cc index ea99b07..c788dc0 100644 --- a/lib/ofdm_parse_mac.cc +++ b/lib/ofdm_parse_mac.cc @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include #include "ofdm_parse_mac_impl.h" #include @@ -30,9 +30,9 @@ class ofdm_parse_mac_impl : public ofdm_parse_mac { public: ofdm_parse_mac_impl(bool debug) : - gr::block("ofdm_parse_mac", - gr::io_signature::make (0, 0, 0), - gr::io_signature::make (0, 0, 0)), + block("ofdm_parse_mac", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), d_debug(debug) { message_port_register_out(pmt::mp("out")); @@ -45,41 +45,6 @@ ofdm_parse_mac_impl(bool debug) : } -unsigned int update_crc32(unsigned int crc, const char *data, size_t len) { - int j; - unsigned int byte, mask; - static unsigned int table[256]; - /* Set up the table if necesary */ - if (table[1] == 0) { - for (byte = 0; byte <= 255; byte++) { - crc = byte; - for (j = 7; j >= 0; j--) { - mask = -(crc & 1); - crc = (crc >> 1) ^ (0xEDB88320 & mask); - } - table[byte] = crc; - } - } - - /* Calculate the CRC32*/ - size_t i = 0; - crc = 0xFFFFFFFF; - for (i = 0; i < len; i++) { - byte = data[i]; //Get next byte - crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF]; - } - unsigned int crc_reversed; - crc_reversed = 0x00000000; - for (j = 31; j >= 0; j--) { - crc_reversed |= ((crc >> j) & 1) << (31 - j); - } - return crc; -} - -unsigned int crc32(const char *buf, int len) { - return update_crc32(0xffffffff, buf, len) ^ 0xffffffff; -} - void parse(pmt::pmt_t msg) { if(pmt::is_eof_object(msg)) { @@ -88,7 +53,7 @@ void parse(pmt::pmt_t msg) { return; } - assert(pmt::is_blob(msg)); + msg = pmt::cdr(msg); int data_len = pmt::blob_length(msg); mac_header *h = (mac_header*)pmt::blob_data(msg); @@ -125,28 +90,22 @@ void parse(pmt::pmt_t msg) { break; } - bool crc = check_crc((char*)pmt::blob_data(msg), data_len); - dout << "crc "; - dout << (crc ? "correct" : "wrong") << std::endl; - - - if(!crc || data_len < 32) { + if(data_len < 32) { return; } char *frame = (char*)pmt::blob_data(msg); - frame[data_len - 4] = '\n'; // DATA if((((h->frame_control) >> 2) & 63) == 2) { - print_ascii(frame + 24, data_len - 24 - 4); - pmt::pmt_t payload = pmt::make_blob(frame + 24, data_len - 24 - 3); + print_ascii(frame + 24, data_len - 24); + pmt::pmt_t payload = pmt::make_blob(frame + 24, data_len - 24); message_port_pub(pmt::mp("out"), pmt::cons(pmt::PMT_NIL, payload)); // QoS Data } else if((((h->frame_control) >> 2) & 63) == 34) { - print_ascii(frame + 26, data_len - 26 - 4); - pmt::pmt_t payload = pmt::make_blob(frame + 26, data_len - 26 - 3); + print_ascii(frame + 26, data_len - 26); + pmt::pmt_t payload = pmt::make_blob(frame + 26, data_len - 26); message_port_pub(pmt::mp("out"), pmt::cons(pmt::PMT_NIL, payload)); } @@ -386,14 +345,6 @@ void print_ascii(char* buf, int length) { dout << std::endl; } -bool check_crc(char *data, int len) { - unsigned int crc = crc32(data, len); - if(crc == 558161692) { - return true; - } - return false; -} - private: bool d_debug; diff --git a/lib/ofdm_parse_mac_impl.h b/lib/ofdm_parse_mac_impl.h index bd6779b..3fea567 100644 --- a/lib/ofdm_parse_mac_impl.h +++ b/lib/ofdm_parse_mac_impl.h @@ -14,8 +14,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef INCLUDED_GR_IEEE802_11_OFDM_PARSE_MAC_IMPL_H -#define INCLUDED_GR_IEEE802_11_OFDM_PARSE_MAC_IMPL_H +#ifndef INCLUDED_IEEE802_11_OFDM_PARSE_MAC_IMPL_H +#define INCLUDED_IEEE802_11_OFDM_PARSE_MAC_IMPL_H struct mac_header { uint16_t frame_control; @@ -26,5 +26,5 @@ struct mac_header { uint16_t seq_control; }__attribute__((packed)); -#endif /* INCLUDED_GR_IEEE802_11_OFDM_PARSE_MAC_IMPL_H */ +#endif /* INCLUDED_IEEE802_11_OFDM_PARSE_MAC_IMPL_H */ diff --git a/lib/ofdm_sync_long.cc b/lib/ofdm_sync_long.cc index 698ab58..79cbec1 100644 --- a/lib/ofdm_sync_long.cc +++ b/lib/ofdm_sync_long.cc @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include #include #include #include @@ -31,7 +31,7 @@ class ofdm_sync_long_impl : public ofdm_sync_long { #define dout d_debug && std::cout public: -ofdm_sync_long_impl(unsigned int sync_lenght, unsigned int freq_est, bool debug) : gr::block("ofdm_sync_long", +ofdm_sync_long_impl(unsigned int sync_lenght, unsigned int freq_est, bool debug) : block("ofdm_sync_long", gr::io_signature::make2(2, 2, sizeof(gr_complex), sizeof(gr_complex)), gr::io_signature::make(1, 1, sizeof(gr_complex))), d_debug(debug), @@ -41,7 +41,7 @@ ofdm_sync_long_impl(unsigned int sync_lenght, unsigned int freq_est, bool debug) SYNC_LENGTH(sync_lenght), FREQ_EST(freq_est) { - set_tag_propagation_policy(gr::block::TPP_DONT); + set_tag_propagation_policy(block::TPP_DONT); d_fir = new gr::filter::kernel::fir_filter_ccc(1, LONG); d_correlation = gr::fft::malloc_complex(8192); } diff --git a/lib/ofdm_sync_short.cc b/lib/ofdm_sync_short.cc index 21157a3..7317046 100644 --- a/lib/ofdm_sync_short.cc +++ b/lib/ofdm_sync_short.cc @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include +#include #include #include @@ -27,7 +27,7 @@ class ofdm_sync_short_impl : public ofdm_sync_short { public: ofdm_sync_short_impl(double threshold, unsigned int max_samples, - unsigned int min_plateau, bool debug) : gr::block("ofdm_sync_short", + unsigned int min_plateau, bool debug) : block("ofdm_sync_short", gr::io_signature::make2(2, 2, sizeof(gr_complex), sizeof(float)), gr::io_signature::make(1, 1, sizeof(gr_complex))), d_debug(debug), @@ -37,7 +37,7 @@ ofdm_sync_short_impl(double threshold, unsigned int max_samples, MIN_PLATEAU(min_plateau), d_threshold(threshold) { - set_tag_propagation_policy(gr::block::TPP_DONT); + set_tag_propagation_policy(block::TPP_DONT); } ~ofdm_sync_short_impl(){