Skip to content

Commit

Permalink
refactor rf metrics aggregation into its own class
Browse files Browse the repository at this point in the history
  • Loading branch information
Consti10 committed Oct 6, 2023
1 parent e7c5a81 commit 4e83f70
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 98 deletions.
3 changes: 2 additions & 1 deletion WBLib.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ target_sources(wifibroadcast PRIVATE
${CMAKE_CURRENT_LIST_DIR}/src/Ieee80211Header.hpp
src/radiotap/RadiotapHeaderTx.hpp
src/radiotap/RadiotapHeaderTxHolder.hpp
${CMAKE_CURRENT_LIST_DIR}/src/RSSIAccumulator.hpp
src/radiotap/RSSIAccumulator.hpp
${CMAKE_CURRENT_LIST_DIR}/src/wifibroadcast_spdlog.cpp
${CMAKE_CURRENT_LIST_DIR}/src/Encryption.cpp
${CMAKE_CURRENT_LIST_DIR}/src/radiotap/RadiotapRxRfAggregator.cpp
)

target_include_directories(wifibroadcast PUBLIC
Expand Down
83 changes: 13 additions & 70 deletions src/WBTxRx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ WBTxRx::WBTxRx(std::vector<wifibroadcast::WifiCard> wifi_cards1,Options options1
for(int i=0;i<m_wifi_cards.size();i++){
auto tmp=std::make_shared<PerCardCalculators>();
tmp->seq_nr.set_store_and_debug_gaps(i,m_options.debug_packet_gaps);
tmp->card_rssi.set_debug_invalid_rssi(m_options.debug_rssi>=1,0);
tmp->antenna1_rssi.set_debug_invalid_rssi(m_options.debug_rssi>=1,1);
tmp->antenna2_rssi.set_debug_invalid_rssi(m_options.debug_rssi>=1,2);
tmp->signal_quality.set_debug_invalid_signal_quality(m_options.debug_rssi>=1);
tmp->rf_aggregator.set_debug_invalid_values(m_options.debug_rssi>=1);
m_per_card_calc.push_back(tmp);
m_card_is_disconnected[i]=false;
}
Expand Down Expand Up @@ -439,15 +436,6 @@ void WBTxRx::on_new_packet(const uint8_t wlan_idx,const uint8_t *pkt,const int p
}
return;
}
// Issue when using multiple wifi card(s) on ground - by example:
// When we inject data on card 1, it is intended for the "air unit" - however,
// card 2 on the ground likely picks up such a packet and if we were not to ignore it, we'd get the session key
// TODO make it better -
// for now, ignore session key packets not from card 0
// Not needed anymore, due to unique air / ground id's
/*if(wlan_idx!=0){
return ;
}*/
SessionKeyPacket &sessionKeyPacket = *((SessionKeyPacket*) parsedPacket->payload);
const auto decrypt_res=m_decryptor->onNewPacketSessionKeyData(sessionKeyPacket.sessionKeyNonce, sessionKeyPacket.sessionKeyData);
if(decrypt_res==wb::Decryptor::SESSION_VALID_NEW || decrypt_res==wb::Decryptor::SESSION_VALID_NOT_NEW){
Expand Down Expand Up @@ -506,55 +494,8 @@ void WBTxRx::on_new_packet(const uint8_t wlan_idx,const uint8_t *pkt,const int p
if(m_options.debug_rssi>=2){
m_console->debug("{}",radiotap::rx::all_rf_path_to_string(parsedPacket->allAntennaValues));
}
// assumes driver gives 1st and 2nd antenna as 2nd and 3rd value
if(parsedPacket->allAntennaValues.size()>=1){
const auto rssi=parsedPacket->allAntennaValues[0].radiotap_dbm_antsignal;
auto opt_minmaxavg= this_wifi_card_calc.card_rssi.add_and_recalculate_if_needed(rssi);
if(opt_minmaxavg.has_value()){
// See below for how this value is calculated on rtl8812au
if(m_wifi_cards[wlan_idx].type!=wifibroadcast::WIFI_CARD_TYPE_RTL8812AU){
this_wifi_card_stats.card_dbm=opt_minmaxavg.value().avg;
}
if(m_options.debug_rssi>=1){
m_console->debug("Card{}:{}",wlan_idx, RSSIAccumulator::min_max_avg_to_string(opt_minmaxavg.value(), false));
}
}
}
if(parsedPacket->allAntennaValues.size()>=2){
const auto rssi=parsedPacket->allAntennaValues[1].radiotap_dbm_antsignal;
auto opt_minmaxavg= this_wifi_card_calc.antenna1_rssi.add_and_recalculate_if_needed(rssi);
if(opt_minmaxavg.has_value()){
this_wifi_card_stats.antenna1_dbm=opt_minmaxavg.value().avg;
if(m_options.debug_rssi>=1){
m_console->debug("Card{} Antenna{}:{}",wlan_idx,0, RSSIAccumulator::min_max_avg_to_string(opt_minmaxavg.value(), false));
}
}
}
if(parsedPacket->allAntennaValues.size()>=3){
const auto rssi=parsedPacket->allAntennaValues[2].radiotap_dbm_antsignal;
auto opt_minmaxavg= this_wifi_card_calc.antenna2_rssi.add_and_recalculate_if_needed(rssi);
if(opt_minmaxavg.has_value()){
this_wifi_card_stats.antenna2_dbm=opt_minmaxavg.value().avg;
if(m_options.debug_rssi>=1){
m_console->debug("Card{} Antenna{}:{}",wlan_idx,1, RSSIAccumulator::min_max_avg_to_string(opt_minmaxavg.value(), false));
}
}
}
if(m_wifi_cards[wlan_idx].type==wifibroadcast::WIFI_CARD_TYPE_RTL8812AU){
// RTL8812AU BUG - general value cannot be used, use max of antennas instead
this_wifi_card_stats.card_dbm=std::max(this_wifi_card_stats.antenna1_dbm,this_wifi_card_stats.antenna2_dbm);
}
this_wifi_card_calc.rf_aggregator.on_valid_openhd_packet(parsedPacket.value());
this_wifi_card_stats.count_p_valid++;
if(parsedPacket->adapter.mcs_index.has_value()){
m_rx_stats.last_received_packet_mcs_index=parsedPacket->adapter.mcs_index.value();
}
if(parsedPacket->adapter.channel_width.has_value()){
m_rx_stats.last_received_packet_channel_width=parsedPacket->adapter.channel_width.value();
}
if(parsedPacket->adapter.radiotap_lock_quality.has_value()){
this_wifi_card_calc.signal_quality.add_signal_quality(parsedPacket->adapter.radiotap_lock_quality.value());
this_wifi_card_stats.signal_quality=this_wifi_card_calc.signal_quality.get_current_signal_quality();
}
if(wlan_idx==0){
m_pollution_openhd_rx_packets++;
}
Expand All @@ -581,14 +522,15 @@ void WBTxRx::switch_tx_card_if_needed() {
// Check if this card is behaving "okay", aka receiving packets at the time
const auto delta_valid_packets=this_card_stats.count_p_valid-m_active_tx_card_data[i].last_received_n_valid_packets;
m_active_tx_card_data[i].last_received_n_valid_packets=this_card_stats.count_p_valid;
if(delta_valid_packets!=0){
// TODO
/*if(delta_valid_packets!=0){
// Some valid packets on this card, or reset
const auto dbm_average=this_card_stats.card_dbm;
if(dbm_average>highest_dbm){
idx_card_highest_rssi=i;
highest_dbm=static_cast<int>(dbm_average); // NOLINT(cert-str34-c)
}
}
}*/
//m_console->debug("Card {} dbm_average:{}",i,dbm_average);
}
if(m_curr_tx_card!=idx_card_highest_rssi){
Expand Down Expand Up @@ -799,19 +741,20 @@ std::string WBTxRx::rx_stats_to_string(const WBTxRx::RxStats& data) {
}
std::string WBTxRx::rx_stats_per_card_to_string(
const WBTxRx::RxStatsPerCard& data) {
return fmt::format("Card{}[packets total:{} valid:{}, loss:{}% RSSI:{}/{},{}]",data.card_index,
data.count_p_any,data.count_p_valid,data.curr_packet_loss,
(int)data.card_dbm,data.antenna1_dbm,data.antenna2_dbm);
return fmt::format("Card{}[packets total:{} valid:{}, loss:{}%]",data.card_index,
data.count_p_any,data.count_p_valid,data.curr_packet_loss);
}
std::string WBTxRx::options_to_string(const std::vector<std::string>& wifi_cards,const WBTxRx::Options& options) {
return fmt::format("Id:{} Cards:{} Key:{} ",options.use_gnd_identifier ? "Ground":"Air",StringHelper::string_vec_as_string(wifi_cards),
options.secure_keypair.has_value() ? "Custom" : "Default(openhd)");
}

RadiotapRxRfAggregator::CardKeyRfIndicators WBTxRx::get_rx_rf_stats_for_card(
int card_index) {
return m_per_card_calc.at(card_index)->rf_aggregator.get_current();
}

void WBTxRx::PerCardCalculators::reset_all() {
seq_nr.reset();
card_rssi.reset();
antenna1_rssi.reset();
antenna2_rssi.reset();
signal_quality.reset();
rf_aggregator.reset();
}
22 changes: 5 additions & 17 deletions src/WBTxRx.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
#include "HelperSources/UINT16SeqNrHelper.hpp"
#include "HelperSources/UINT64SeqNrHelper.hpp"
#include "Ieee80211Header.hpp"
#include "RSSIAccumulator.hpp"
#include "SignalQualityAccumulator.hpp"
#include "WiFiCard.h"
#include "radiotap/RSSIAccumulator.hpp"
#include "radiotap/RadiotapHeaderTx.hpp"
#include "radiotap/RadiotapHeaderTxHolder.hpp"
#include "radiotap/RadiotapRxRfAggregator.h"
#include "radiotap/SignalQualityAccumulator.hpp"

/**
* This class exists to provide a clean, working interface to create a
Expand Down Expand Up @@ -186,10 +187,6 @@ class WBTxRx {
int32_t curr_bits_per_second=-1;
// n received valid session key packets
int n_received_valid_session_key_packets=0;
// mcs index on the most recent valid data packet, if the card supports reporting it
int last_received_packet_mcs_index=-1;
// channel width (20Mhz or 40Mhz) on the most recent received valid data packet, if the card supports reporting it
int last_received_packet_channel_width=-1;
// complicated but important metric in our case - how many "big gaps" we had in the last 1 second
int16_t curr_big_gaps_counter=-1;
// Percentage of non openhd packets over total n of packets
Expand All @@ -207,17 +204,11 @@ class WBTxRx {
int64_t count_p_any=0;
int64_t count_p_valid=0;
int32_t curr_packet_loss=-1;
// [0,100] if valid, -1 otherwise
int8_t signal_quality=-1;
// These values are updated in regular intervals as long as packets are coming in
// -128 = invalid, [-127..-1] otherwise
int8_t card_dbm=-128; // Depends on driver
int8_t antenna1_dbm=-128;
int8_t antenna2_dbm=-128;
};
TxStats get_tx_stats();
RxStats get_rx_stats();
RxStatsPerCard get_rx_stats_for_card(int card_index);
RadiotapRxRfAggregator::CardKeyRfIndicators get_rx_rf_stats_for_card(int card_index);
// used by openhd during frequency scan
void rx_reset_stats();
// used by the rate adjustment test executable
Expand Down Expand Up @@ -304,10 +295,7 @@ class WBTxRx {
// for calculating the loss and more per rx card (when multiple rx cards are used)
struct PerCardCalculators{
UINT64SeqNrHelper seq_nr{};
RSSIAccumulator card_rssi{};
RSSIAccumulator antenna1_rssi{};
RSSIAccumulator antenna2_rssi{};
SignalQualityAccumulator signal_quality{};
RadiotapRxRfAggregator rf_aggregator;
void reset_all();
};
std::vector<std::shared_ptr<PerCardCalculators>> m_per_card_calc;
Expand Down
5 changes: 3 additions & 2 deletions src/RSSIAccumulator.hpp → src/radiotap/RSSIAccumulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

#include <optional>

#include "HelperSources/TimeHelper.hpp"
#include "wifibroadcast_spdlog.h"
#include "../wifibroadcast_spdlog.h"
#include "TimeHelper.hpp"
#include "spdlog/spdlog.h"

/**
* UINT16SeqNrHelper to accumulate RSSI values
Expand Down
13 changes: 7 additions & 6 deletions src/radiotap/RadiotapHeaderRx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace radiotap::rx{
struct ParsedRfPath{
// which antenna the value refers to,
// or -1 this dgm value came before a IEEE80211_RADIOTAP_ANTENNA field and the antenna idx is therefore unknown
const int8_t antennaIdx;
int8_t antennaIdx;
// https://www.radiotap.org/fields/Antenna%20signal.html
// IEEE80211_RADIOTAP_DBM_ANTSIGNAL
int8_t radiotap_dbm_antsignal;
Expand All @@ -32,8 +32,6 @@ struct ParsedAdapter{
// Atheros forwards frames even though the fcs check failed ( this packet is corrupted)
// This is pretty much the only adapter that does that though
bool radiotap_f_bad_fcs= false;
std::optional<uint8_t> mcs_index=std::nullopt;
std::optional<uint8_t> channel_width=std::nullopt;
std::optional<int8_t> radiotap_dbm_antsignal=std::nullopt;
std::optional<uint16_t> radiotap_lock_quality=std::nullopt;
std::optional<int8_t> radiotap_dbm_antnoise=std::nullopt;
Expand Down Expand Up @@ -101,18 +99,21 @@ static std::optional<ParsedRxRadiotapPacket> process_received_radiotap_packet(co
uint8_t flags = iterator.this_arg[1];
uint8_t mcs = iterator.this_arg[2];
if(known & IEEE80211_RADIOTAP_MCS_HAVE_MCS){
parsed_adapter.mcs_index=static_cast<uint16_t>(mcs);
// Not needed for now
//parsed_adapter.mcs_index=static_cast<uint16_t>(mcs);
}
if (known & IEEE80211_RADIOTAP_MCS_HAVE_BW) {
const uint8_t bandwidth = flags & IEEE80211_RADIOTAP_MCS_BW_MASK;
switch (bandwidth) {
case IEEE80211_RADIOTAP_MCS_BW_20:
case IEEE80211_RADIOTAP_MCS_BW_20U:
case IEEE80211_RADIOTAP_MCS_BW_20L:
parsed_adapter.channel_width=static_cast<uint16_t>(20);
// Not needed for now
//parsed_adapter.channel_width=static_cast<uint16_t>(20);
break;
case IEEE80211_RADIOTAP_MCS_BW_40:
parsed_adapter.channel_width=static_cast<uint16_t>(40);
// Not needed for now
//parsed_adapter.channel_width=static_cast<uint16_t>(40);
break;
default:
break ;
Expand Down
5 changes: 5 additions & 0 deletions src/radiotap/RadiotapRxRfAggregator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//
// Created by consti10 on 05.10.23.
//

#include "RadiotapRxRfAggregator.h"
111 changes: 111 additions & 0 deletions src/radiotap/RadiotapRxRfAggregator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//
// Created by consti10 on 05.10.23.
//

#ifndef WIFIBROADCAST_RADIOTAPRXRFAGGREGATOR_H
#define WIFIBROADCAST_RADIOTAPRXRFAGGREGATOR_H

#include "RSSIAccumulator.hpp"
#include "RadiotapHeaderRx.hpp"
#include "SignalQualityAccumulator.hpp"

class RadiotapRxRfAggregator {
public:
void on_valid_openhd_packet(const radiotap::rx::ParsedRxRadiotapPacket& packet){
if(packet.adapter.radiotap_dbm_antsignal.has_value()){
const auto radiotap_dbm_antsignal=packet.adapter.radiotap_dbm_antsignal.value();
auto opt_minmaxavg= adapter_rssi.add_and_recalculate_if_needed(radiotap_dbm_antsignal);
if(opt_minmaxavg.has_value()){
m_current_rx_stats.adapter.rssi_dbm=opt_minmaxavg->avg;
}
}
if(packet.adapter.radiotap_dbm_antnoise.has_value()){
const auto radiotap_dbm_antnoise=packet.adapter.radiotap_dbm_antnoise.value();
auto opt_minmaxavg= adapter_noise.add_and_recalculate_if_needed(radiotap_dbm_antnoise);
if(opt_minmaxavg.has_value()){
m_current_rx_stats.adapter.noise_dbm=opt_minmaxavg->avg;
}
}
if(packet.adapter.radiotap_lock_quality.has_value()){
const auto radiotap_lock_quality=packet.adapter.radiotap_lock_quality.value();
adapter_signal_quality.add_signal_quality(radiotap_lock_quality);
m_current_rx_stats.adapter.card_signal_quality_perc=adapter_signal_quality.get_current_signal_quality();
}
for(int i=0;i<packet.allAntennaValues.size();i++){
const auto& path=packet.allAntennaValues[i];
on_per_rf_path(i,path);
}
//if(m_wifi_cards[wlan_idx].type==wifibroadcast::WIFI_CARD_TYPE_RTL8812AU){
// RTL8812AU BUG - general value cannot be used, use max of antennas instead
// this_wifi_card_stats.card_dbm=std::max(this_wifi_card_stats.antenna1_dbm,this_wifi_card_stats.antenna2_dbm);
//}
}
struct KeyRfIndicators {
// -128 = invalid, [-127..-1] otherwise
int8_t rssi_dbm=-128;
int8_t noise_dbm=-128;
// [0,100] if valid, -1 otherwise
int8_t card_signal_quality_perc=-1;
};
struct CardKeyRfIndicators {
// ------------- PER ADAPTER ------------
KeyRfIndicators adapter;
// -------------- PER ANTENNA ----------
KeyRfIndicators antenna1;
KeyRfIndicators antenna2;
};
void set_debug_invalid_values(bool enable){
adapter_rssi.set_debug_invalid_rssi(enable,0);
adapter_noise.set_debug_invalid_rssi(enable,0);
m_antenna1.rssi_dbm.set_debug_invalid_rssi(enable,1);
m_antenna2.rssi_dbm.set_debug_invalid_rssi(enable,2);
}
void reset(){
m_current_rx_stats={};
adapter_rssi.reset();
adapter_noise.reset();
m_antenna1.rssi_dbm.reset();
m_antenna2.rssi_dbm.reset();
}
CardKeyRfIndicators get_current(){
return m_current_rx_stats;
}
private:
void on_per_rf_path(int index,const radiotap::rx::ParsedRfPath& data){
// For simplicity, we only track up to 2 antennas
if(index>1) return ;
auto& per_path=index==0 ? m_antenna1 : m_antenna2;
auto& current=index==0 ? m_current_rx_stats.antenna1 : m_current_rx_stats.antenna2;
{
auto opt_minmaxavg= per_path.rssi_dbm.add_and_recalculate_if_needed(data.radiotap_dbm_antsignal);
if(opt_minmaxavg.has_value()){
current.rssi_dbm=opt_minmaxavg->avg;
}
}
{
auto opt_minmaxavg= per_path.noise_dbm.add_and_recalculate_if_needed(data.radiotap_dbm_antnoise);
if(opt_minmaxavg.has_value()){
current.rssi_dbm=opt_minmaxavg->avg;
}
}
{
per_path.signal_quality.add_signal_quality(data.radiotap_dbm_antsignal);
current.card_signal_quality_perc=per_path.signal_quality.get_current_signal_quality();
}
}
// Stats per-adapter
RSSIAccumulator adapter_rssi{};
RSSIAccumulator adapter_noise{};
SignalQualityAccumulator adapter_signal_quality{};
// Stats per antenna (we only track up to 2 antenna(s)
struct PerAntenna{
RSSIAccumulator rssi_dbm;
RSSIAccumulator noise_dbm;
SignalQualityAccumulator signal_quality;
};
PerAntenna m_antenna1;
PerAntenna m_antenna2;
CardKeyRfIndicators m_current_rx_stats{};
};

#endif // WIFIBROADCAST_RADIOTAPRXRFAGGREGATOR_H
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

#include <optional>

#include "HelperSources/TimeHelper.hpp"
#include "wifibroadcast_spdlog.h"
#include "../wifibroadcast_spdlog.h"
#include "TimeHelper.hpp"

/**
* UINT16SeqNrHelper to accumulate (rtl8812au) signal quality values
Expand Down

0 comments on commit 4e83f70

Please sign in to comment.