From 983b114da9e3e3e35a98218b9c002549b5419a1e Mon Sep 17 00:00:00 2001 From: Vladyslav Tupikin Date: Tue, 9 Jun 2020 15:18:58 +0300 Subject: [PATCH 1/2] agent: backhaul_manager: Refactor handler for AP_METRICS_RESPONSE_MESSAGE Create new class ExpectedApMetricsResponse for easy handling of the logic of AP Metrics query and response. The class saves the expected bssids responses and collect them together before sending the combined response to the controller Signed-off-by: Vladyslav Tupikin Signed-off-by: Ran Regev --- agent/src/beerocks/slave/CMakeLists.txt | 1 + .../backhaul_manager_thread.cpp | 345 +++++++++--------- .../backhaul_manager_thread.h | 40 +- .../internal/expected_ap_metrics_response.cpp | 46 +++ .../internal/expected_ap_metrics_response.h | 97 +++++ 5 files changed, 314 insertions(+), 215 deletions(-) create mode 100644 agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.cpp create mode 100644 agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.h diff --git a/agent/src/beerocks/slave/CMakeLists.txt b/agent/src/beerocks/slave/CMakeLists.txt index 72d6752d78..eda458d175 100644 --- a/agent/src/beerocks/slave/CMakeLists.txt +++ b/agent/src/beerocks/slave/CMakeLists.txt @@ -11,6 +11,7 @@ file(GLOB beerocks_agent_sources ${MODULE_PATH}/link_metrics/*.c* ${MODULE_PATH}/platform_manager/*.c* ${MODULE_PATH}/gate/*.c* + ${MODULE_PATH}/backhaul_manager/internal/*.c* ${MODULE_PATH}/*.c* ) diff --git a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp index 45f6ab875a..feef1c6ad4 100644 --- a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp +++ b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp @@ -29,19 +29,17 @@ */ #include "backhaul_manager_thread.h" - #include "../link_metrics/ieee802_11_link_metrics_collector.h" #include "../link_metrics/ieee802_3_link_metrics_collector.h" #include "../tlvf_utils.h" - +#include "internal/expected_ap_metrics_response.h" #include #include -#include - #include #include #include #include +#include /* * TODO: @@ -1023,21 +1021,16 @@ bool backhaul_manager::backhaul_fsm_main(bool &skip_select) for (const auto &socket : slaves_sockets) { if (socket) { for (int i = 0; i < beerocks::IFACE_TOTAL_VAPS; ++i) { - if (socket->vaps_list.vaps[i].mac != network_utils::ZERO_MAC) { + if ((socket->vaps_list.vaps[i].mac != network_utils::ZERO_MAC) && + (socket->vaps_list.vaps[i].ssid[0] != '\0')) { bssid_list.push_back(socket->vaps_list.vaps[i].mac); } } } } - // We must generate a new MID for the periodic AP Metrics Response messages that - // do not correspond to an AP Metrics Query message. - // We cannot set MID to 0 here because we must also differentiate periodic - // AP Metrics Response messages and messages received from monitor thread - // due to channel utilization crossed configured threshold value. - // As a temporary solution, set MID to UINT16_MAX here. - // TODO: to be fixed as part of #1328 + if (!bssid_list.empty()) { - send_slave_ap_metric_query_message(UINT16_MAX, bssid_list); + send_slave_ap_metric_query_message(0, bssid_list); } else { LOG(DEBUG) << "Skipping AP_METRICS_QUERY for slave, empty BSSID list"; } @@ -1258,49 +1251,81 @@ bool backhaul_manager::send_autoconfig_search_message(std::shared_ptr &bssid_list) { - bool ret = false; + // save mid and clear previous query + m_expected_ap_metrics_response.reset_to_new_mid(mid); + + // compare two mac addresses using string compare on their octets + auto mac_comp = [](const sMacAddr &addr1, const sMacAddr &addr2) -> bool { + return memcmp((char *)addr1.oct, (char *)addr2.oct, sizeof(sMacAddr)) < 0; + }; + + // sort the given bssid list + std::vector given_bssid_list = bssid_list; + std::sort(given_bssid_list.begin(), given_bssid_list.end(), mac_comp); + + // for each socket - send only relevant bssids + auto ret = true; for (auto socket : slaves_sockets) { - for (const auto &mac : bssid_list) { - int i = 0; - if (mac == socket->vaps_list.vaps[i].mac) { - LOG(DEBUG) << "Forwarding AP_METRICS_QUERY_MESSAGE message to son_slave, bssid: " - << std::hex << tlvf::mac_to_string(mac); - - auto forward = - cmdu_tx.create(mid, ieee1905_1::eMessageType::AP_METRICS_QUERY_MESSAGE); - if (!forward) { - LOG(ERROR) << "Failed to create AP_METRICS_QUERY_MESSAGE"; - return false; - } - auto query = cmdu_tx.addClass(); - if (!query) { - LOG(ERROR) << "Failed addClass"; - return false; - } + // create the message to forward to current slaves + auto forward = cmdu_tx.create(mid, ieee1905_1::eMessageType::AP_METRICS_QUERY_MESSAGE); + if (!forward) { + LOG(ERROR) << "Failed to create AP_METRICS_QUERY_MESSAGE"; + return false; + } - if (!query->alloc_bssid_list(1)) { - LOG(ERROR) << "Failed allocate memory for bssid_list"; - return false; - } + // copy current vaps bssid + std::vector current_socket_bssids; + std::transform(socket->vaps_list.vaps, socket->vaps_list.vaps + beerocks::IFACE_TOTAL_VAPS, + std::back_inserter(current_socket_bssids), + [](const beerocks_message::sVapInfo &vap_info) { return vap_info.mac; }); - auto list = query->bssid_list(0); - std::get<0>(list) = true; - std::get<1>(list) = mac; + // sort current vaps bssid + std::sort(current_socket_bssids.begin(), current_socket_bssids.end(), mac_comp); - if (!message_com::send_cmdu(socket->slave, cmdu_tx)) { - LOG(ERROR) << "Failed forwarding AP_METRICS_QUERY_MESSAGE message to son_slave"; - ret = false; - continue; - } else { - ret = true; - // Fill a query vector - m_ap_metric_query.push_back({socket->slave, mac}); - } - } + // fill a list of the common bssids: given list with current vaps + std::vector required_bssids; + std::set_intersection(given_bssid_list.begin(), given_bssid_list.end(), + current_socket_bssids.begin(), current_socket_bssids.end(), + std::back_inserter(required_bssids), mac_comp); + + if (required_bssids.empty()) { + // skip if there is nothing to do + LOG(DEBUG) << "empty required bssid list, skipping"; + continue; + } + + // add metric query tlv + auto query = cmdu_tx.addClass(); + if (!query) { + LOG(ERROR) << "Failed addClass"; + return false; + } + + // alocate memory + if (!query->alloc_bssid_list(required_bssids.size())) { + LOG(ERROR) << "Failed allocate memory for bssid_list, size: " << bssid_list.size(); + return false; + } + + int i = 0; + for (const auto &mac : required_bssids) { + auto list = query->bssid_list(i); + std::get<0>(list) = true; + std::get<1>(list) = mac; i++; } + + // save the required list + m_expected_ap_metrics_response.add_expected_bssid(required_bssids.begin(), + required_bssids.end()); + + if (!message_com::send_cmdu(socket->slave, cmdu_tx)) { + LOG(ERROR) << "Failed forwarding AP_METRICS_QUERY_MESSAGE message to son_slave"; + ret = false; + } } + return ret; } @@ -2554,8 +2579,12 @@ bool backhaul_manager::handle_ap_capability_query(ieee1905_1::CmduMessageRx &cmd bool backhaul_manager::handle_ap_metrics_query(ieee1905_1::CmduMessageRx &cmdu_rx, const std::string &src_mac) { - std::vector bssid; - const auto mid = cmdu_rx.getMessageId(); + + const auto mid = cmdu_rx.getMessageId(); + + // save mid and erase data for previous query and response + m_expected_ap_metrics_response.reset_to_new_mid(mid); + auto ap_metric_query_tlv = cmdu_rx.getClass(); if (!ap_metric_query_tlv) { LOG(ERROR) << "AP Metrics Query CMDU mid=" << mid << " does not have AP Metric Query TLV"; @@ -2567,16 +2596,29 @@ bool backhaul_manager::handle_ap_metrics_query(ieee1905_1::CmduMessageRx &cmdu_r LOG(ERROR) << "Failed to get bssid " << bssid_idx << " from AP_METRICS_QUERY"; return false; } - bssid.push_back(std::get<1>(bssid_tuple)); + + m_expected_ap_metrics_response.add_expected_bssid(std::get<1>(bssid_tuple)); + LOG(DEBUG) << "Received AP_METRICS_QUERY_MESSAGE, mid=" << std::hex << int(mid) << " bssid " << std::get<1>(bssid_tuple); } - if (!send_slave_ap_metric_query_message(mid, bssid)) { - LOG(ERROR) << "Failed to forward AP_METRICS_RESPONSE to the son_slave_thread"; + LOG(DEBUG) << "Forwarding AP_METRICS_QUERY_MESSAGE to all slaves, mid=" << std::hex << int(mid); + auto header = message_com::get_uds_header(cmdu_rx); + if (!header) { + LOG(ERROR) << "Failed to extract header from rx message"; return false; } + uint16_t length = header->length; + cmdu_rx.swap(); // swap back before forwarding + for (const auto &soc : slaves_sockets) { + if (!message_com::forward_cmdu_to_uds(soc->slave, cmdu_rx, length)) { + LOG(ERROR) << "Failed forwarding AP_METRICS_QUERY_MESSAGE message to slave: " + << tlvf::mac_to_string(soc->radio_mac); + } + } + return true; } @@ -2584,33 +2626,23 @@ bool backhaul_manager::handle_slave_ap_metrics_response(ieee1905_1::CmduMessageR const std::string &src_mac) { auto mid = cmdu_rx.getMessageId(); - LOG(DEBUG) << "Received AP_METRICS_RESPONSE_MESSAGE, mid=" << std::hex << int(mid); - /** - * If AP Metrics Response message does not correspond to a previously received and forwarded - * AP Metrics Query message (which we know because message id is not set), then forward message - * to controller. - * This might happen when channel utilization value has crossed configured threshold or when - * periodic metrics reporting interval has elapsed. - */ if (0 == mid) { - uint16_t length = message_com::get_uds_header(cmdu_rx)->length; - cmdu_rx.swap(); //swap back before forwarding - return send_cmdu_to_bus(cmdu_rx, controller_bridge_mac, bridge_info.mac, length); + LOG(DEBUG) << "AP_METRICS_RESPONSE_MESSAGE. mid is zero (0), forwarding to controller " + "unconditionaly."; + cmdu_rx.swap(); + return send_cmdu_to_bus(cmdu_rx, controller_bridge_mac, bridge_info.mac, + cmdu_rx.getMessageLength()); } - /** - * When periodic metrics reporting interval has elapsed, we emulate that we have received an - * AP Metrics Query message from controller. To differentiate real queries from emulated ones, - * we use a "special" mid value. - * Note that this design is flaw as a real query might also have this special mid value. This - * is just a quick and dirty fix to pass 4.7.5 and 4.7.6 for M1 - * TODO: to be fixed as part of #1328 - */ - if (UINT16_MAX == mid) { - mid = 0; + if (m_expected_ap_metrics_response.get_mid() != mid) { + LOG(ERROR) << "Received AP_METRICS_RESPONSE_MESSAGE with bad mid: existing:" << std::hex + << m_expected_ap_metrics_response.get_mid() << " received: " << int(mid); + return false; } + LOG(DEBUG) << "Received AP_METRICS_RESPONSE_MESSAGE, mid=" << std::hex << int(mid); + auto ap_metrics_tlv = cmdu_rx.getClass(); if (!ap_metrics_tlv) { LOG(ERROR) << "Failed cmdu_rx.getClass(), mid=" << std::hex @@ -2618,44 +2650,64 @@ bool backhaul_manager::handle_slave_ap_metrics_response(ieee1905_1::CmduMessageR return false; } - auto bssid_tlv = ap_metrics_tlv->bssid(); - auto mac = std::find_if( - m_ap_metric_query.begin(), m_ap_metric_query.end(), - [&bssid_tlv](sApMetricsQuery const &query) { return query.bssid == bssid_tlv; }); - - if (mac == m_ap_metric_query.end()) { - LOG(ERROR) << "Failed search in ap_metric_query for bssid: " << bssid_tlv + if (!m_expected_ap_metrics_response.find_expected_bssid(ap_metrics_tlv->bssid())) { + LOG(ERROR) << "Failed search in ap_metric_query for bssid: " << ap_metrics_tlv->bssid() << " from mid=" << std::hex << int(mid); return false; } - sApMetrics metric; - // Copy data to the response vector - metric.bssid = ap_metrics_tlv->bssid(); - metric.channel_utilization = ap_metrics_tlv->channel_utilization(); - metric.number_of_stas_currently_associated = + // prepare ap metrics tlv + auto &ap_metrics_tx_message = m_expected_ap_metrics_response.create_tx_message(); + auto ap_metrics_response_tlv = ap_metrics_tx_message.addClass(); + if (!ap_metrics_response_tlv) { + LOG(ERROR) << "Failed addClass"; + return false; + } + ap_metrics_response_tlv->bssid() = ap_metrics_tlv->bssid(); + ap_metrics_response_tlv->channel_utilization() = ap_metrics_tlv->channel_utilization(); + ap_metrics_response_tlv->number_of_stas_currently_associated() = ap_metrics_tlv->number_of_stas_currently_associated(); - metric.estimated_service_parameters = ap_metrics_tlv->estimated_service_parameters(); - auto info = ap_metrics_tlv->estimated_service_info_field(); + ap_metrics_response_tlv->estimated_service_parameters() = + ap_metrics_tlv->estimated_service_parameters(); + + if (!ap_metrics_response_tlv->alloc_estimated_service_info_field( + ap_metrics_tlv->estimated_service_info_field_length())) { + LOG(ERROR) << "Couldn't allocate " + "ap_metrics_response_tlv->alloc_estimated_service_info_field"; + return false; + } + auto rx_info = ap_metrics_tlv->estimated_service_info_field(); + auto tx_info = ap_metrics_response_tlv->estimated_service_info_field(); for (size_t i = 0; i < ap_metrics_tlv->estimated_service_info_field_length(); i++) { - metric.estimated_service_info_field.push_back(info[i]); + tx_info[i] = rx_info[i]; } - std::vector traffic_stats_response; + // Prepare STA Traffic Stats TLV's for (auto &sta_traffic : cmdu_rx.getClassList()) { if (!sta_traffic) { LOG(ERROR) << "Failed to get class list for tlvAssociatedStaTrafficStats"; continue; } - traffic_stats_response.push_back( - {sta_traffic->sta_mac(), sta_traffic->byte_sent(), sta_traffic->byte_recived(), - sta_traffic->packets_sent(), sta_traffic->packets_recived(), - sta_traffic->tx_packets_error(), sta_traffic->rx_packets_error(), - sta_traffic->retransmission_count()}); + auto sta_traffic_response_tlv = + ap_metrics_tx_message.addClass(); + + if (!sta_traffic_response_tlv) { + LOG(ERROR) << "Failed addClass"; + continue; + } + + sta_traffic_response_tlv->sta_mac() = sta_traffic->sta_mac(); + sta_traffic_response_tlv->byte_sent() = sta_traffic->byte_sent(); + sta_traffic_response_tlv->byte_recived() = sta_traffic->byte_recived(); + sta_traffic_response_tlv->packets_sent() = sta_traffic->packets_sent(); + sta_traffic_response_tlv->packets_recived() = sta_traffic->packets_recived(); + sta_traffic_response_tlv->tx_packets_error() = sta_traffic->tx_packets_error(); + sta_traffic_response_tlv->rx_packets_error() = sta_traffic->rx_packets_error(); + sta_traffic_response_tlv->retransmission_count() = sta_traffic->retransmission_count(); } - std::vector link_metrics_response; + // Prepare STA Link Metrics TLV's for (auto &sta_link_metric : cmdu_rx.getClassList()) { if (!sta_link_metric) { LOG(ERROR) << "Failed getClassList"; @@ -2666,98 +2718,35 @@ bool backhaul_manager::handle_slave_ap_metrics_response(ieee1905_1::CmduMessageR continue; } auto response_list = sta_link_metric->bssid_info_list(0); - link_metrics_response.push_back({sta_link_metric->sta_mac(), std::get<1>(response_list)}); - } - - // Fill a response vector - m_ap_metric_response.push_back({metric, traffic_stats_response, link_metrics_response}); - - // Remove an entry from the processed query - m_ap_metric_query.erase( - std::remove_if(m_ap_metric_query.begin(), m_ap_metric_query.end(), - [&](sApMetricsQuery const &query) { return mac->bssid == query.bssid; }), - m_ap_metric_query.end()); - - if (!m_ap_metric_query.empty()) { - return true; - } - - // We received all responses - prepare and send response message to the controller - auto cmdu_header = cmdu_tx.create(mid, ieee1905_1::eMessageType::AP_METRICS_RESPONSE_MESSAGE); - - if (!cmdu_header) { - LOG(ERROR) << "Failed building IEEE1905 AP_METRICS_RESPONSE_MESSAGE"; - return false; - } - // Prepare tlvApMetrics for each processed query - for (const auto &response : m_ap_metric_response) { - auto ap_metrics_response_tlv = cmdu_tx.addClass(); - if (!ap_metrics_response_tlv) { - LOG(ERROR) << "Failed addClass"; - return false; - } + auto sta_link_metric_response_tlv = + ap_metrics_tx_message.addClass(); - ap_metrics_response_tlv->bssid() = response.metric.bssid; - ap_metrics_response_tlv->channel_utilization() = response.metric.channel_utilization; - ap_metrics_response_tlv->number_of_stas_currently_associated() = - response.metric.number_of_stas_currently_associated; - ap_metrics_response_tlv->estimated_service_parameters() = - response.metric.estimated_service_parameters; - if (!ap_metrics_response_tlv->alloc_estimated_service_info_field( - response.metric.estimated_service_info_field.size())) { - LOG(ERROR) << "Couldn't allocate " - "ap_metrics_response_tlv->alloc_estimated_service_info_field"; - return false; + if (!sta_link_metric_response_tlv) { + LOG(ERROR) << "Failed addClass"; + continue; } - std::copy_n(response.metric.estimated_service_info_field.begin(), - response.metric.estimated_service_info_field.size(), - ap_metrics_response_tlv->estimated_service_info_field()); - - for (auto &stat : response.sta_traffic_stats) { - auto sta_traffic_response_tlv = - cmdu_tx.addClass(); - - if (!sta_traffic_response_tlv) { - LOG(ERROR) << "Failed addClass"; - continue; - } - sta_traffic_response_tlv->sta_mac() = stat.sta_mac; - sta_traffic_response_tlv->byte_sent() = stat.byte_sent; - sta_traffic_response_tlv->byte_recived() = stat.byte_recived; - sta_traffic_response_tlv->packets_sent() = stat.packets_sent; - sta_traffic_response_tlv->packets_recived() = stat.packets_recived; - sta_traffic_response_tlv->tx_packets_error() = stat.tx_packets_error; - sta_traffic_response_tlv->rx_packets_error() = stat.rx_packets_error; - sta_traffic_response_tlv->retransmission_count() = stat.retransmission_count; + sta_link_metric_response_tlv->sta_mac() = sta_link_metric->sta_mac(); + if (!sta_link_metric_response_tlv->alloc_bssid_info_list(1)) { + LOG(ERROR) << "Failed alloc_bssid_info_list"; + continue; } + auto &sta_link_metric_response = + std::get<1>(sta_link_metric_response_tlv->bssid_info_list(0)); + sta_link_metric_response = std::get<1>(response_list); + } - for (auto &link_metric : response.sta_link_metrics) { - auto sta_link_metric_response_tlv = - cmdu_tx.addClass(); - - if (!sta_link_metric_response_tlv) { - LOG(ERROR) << "Failed addClass"; - continue; - } + // remove an entry from the processed query + m_expected_ap_metrics_response.remove_expected_bssid(ap_metrics_tlv->bssid()); - sta_link_metric_response_tlv->sta_mac() = link_metric.sta_mac; - if (!sta_link_metric_response_tlv->alloc_bssid_info_list(1)) { - LOG(ERROR) << "Failed alloc_bssid_info_list"; - continue; - } - auto &sta_link_metric_response = - std::get<1>(sta_link_metric_response_tlv->bssid_info_list(0)); - sta_link_metric_response = link_metric.bssid_info; - } + // waiting for all responses before sending the response + if (!m_expected_ap_metrics_response.is_expected_bssid_empty()) { + return true; } - // Clear the m_ap_metric_response vector after preparing response to the controller - m_ap_metric_response.clear(); - LOG(DEBUG) << "Sending AP_METRICS_RESPONSE_MESSAGE, mid=" << std::hex << int(mid); - return send_cmdu_to_bus(cmdu_tx, controller_bridge_mac, bridge_info.mac); + return send_cmdu_to_bus(ap_metrics_tx_message, controller_bridge_mac, bridge_info.mac); } /** diff --git a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.h b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.h index 165e10c5fd..8ec11a2f08 100644 --- a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.h +++ b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.h @@ -9,6 +9,7 @@ #ifndef _BACKHAUL_MANAGER_THREAD_H #define _BACKHAUL_MANAGER_THREAD_H +#include "internal/expected_ap_metrics_response.h" #include "wan_monitor.h" #include @@ -24,6 +25,7 @@ #include #include +#include #include #include #include @@ -544,43 +546,7 @@ class backhaul_manager : public btl::transport_socket_thread { const sLinkNeighbor &link_neighbor, const sLinkMetrics &link_metrics, ieee1905_1::eLinkMetricsType link_metrics_type); - struct sStaTrafficStats { - sMacAddr sta_mac; - uint32_t byte_sent; - uint32_t byte_recived; - uint32_t packets_sent; - uint32_t packets_recived; - uint32_t tx_packets_error; - uint32_t rx_packets_error; - uint32_t retransmission_count; - }; - - struct sStaLinkMetrics { - sMacAddr sta_mac; - wfa_map::tlvAssociatedStaLinkMetrics::sBssidInfo bssid_info; - }; - - struct sApMetricsQuery { - Socket *soc; - sMacAddr bssid; - }; - - struct sApMetrics { - sMacAddr bssid; - uint8_t channel_utilization; - uint16_t number_of_stas_currently_associated; - wfa_map::tlvApMetrics::sEstimatedService estimated_service_parameters; - std::vector estimated_service_info_field; - }; - - struct sApMetricsResponse { - sApMetrics metric; - std::vector sta_traffic_stats; - std::vector sta_link_metrics; - }; - - std::vector m_ap_metric_query; - std::vector m_ap_metric_response; + ExpectedApMetricsResponse m_expected_ap_metrics_response; struct sChannelSelectionResponse { sMacAddr radio_mac; diff --git a/agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.cpp b/agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.cpp new file mode 100644 index 0000000000..e90aae749a --- /dev/null +++ b/agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.cpp @@ -0,0 +1,46 @@ + +#include "expected_ap_metrics_response.h" + +namespace beerocks { + +// mid +void ExpectedApMetricsResponse::reset_to_new_mid(uint16_t mid) +{ + m_mid = mid; + m_expected_bssid_list.clear(); + m_response.reset(); + memset(m_response_buffer, 0, sizeof(m_response_buffer)); +} + +uint16_t ExpectedApMetricsResponse::get_mid() const { return m_mid; } + +// bssid +void ExpectedApMetricsResponse::add_expected_bssid(const sMacAddr &bssid) +{ + m_expected_bssid_list.insert(bssid); +} + +void ExpectedApMetricsResponse::remove_expected_bssid(const sMacAddr &bssid) +{ + m_expected_bssid_list.erase(bssid); +} + +bool ExpectedApMetricsResponse::is_expected_bssid_empty() const +{ + return m_expected_bssid_list.empty(); +} + +bool ExpectedApMetricsResponse::find_expected_bssid(const sMacAddr &bssid) const +{ + return m_expected_bssid_list.find(bssid) != m_expected_bssid_list.end(); +} + +// cmdu message +ieee1905_1::CmduMessageTx &ExpectedApMetricsResponse::create_tx_message() +{ + m_response.create(m_mid, ieee1905_1::eMessageType::AP_METRICS_RESPONSE_MESSAGE); + + return m_response; +} + +} // namespace beerocks diff --git a/agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.h b/agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.h new file mode 100644 index 0000000000..994a984cda --- /dev/null +++ b/agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-2-Clause-Patent + * + * SPDX-FileCopyrightText: 2016-2020 the prplMesh contributors (see AUTHORS.md) + * + * This code is subject to the terms of the BSD+Patent license. + * See LICENSE file for more details. + */ + +#ifndef _EXPECTED_AP_METRICS_RESPONSE_H +#define _EXPECTED_AP_METRICS_RESPONSE_H + +#include +#include +#include +#include +#include + +namespace beerocks { + +class ExpectedApMetricsResponse { +public: + /** + * @brief resets this object with a new mid + * @details resets all members of this object to its empty initial state except for the mid + * that is set as was given bt the parameter (mid default value is zero (0)) + * @param mid the new mid value + * @return radio mac of the found slave if found, otherwise empty string + */ + void reset_to_new_mid(uint16_t mid = 0); + + /** + * @brief returns the mid of this object + * @return mid + */ + uint16_t get_mid() const; + + /** + * @brief creates and returns a AP-RESPONSE-METRICS Tx message + * @return a fresh new CmduMessage with the correct type and mid + */ + ieee1905_1::CmduMessageTx &create_tx_message(); + + // bssid related operations + + /** + * @brief stores expected bssids + * @details adds the bssids in the range [first,last) to the already existing internal list + * @param first iterator to the source begin + * @param last iterator to the source last + * @return - nothing + */ + template void add_expected_bssid(FirstIt first, LastIt last); + + /** + * @brief stores expected bssid + * @details adds the input bssid to the already existing internal list + * @param bssid the bssid to store + * @return nothing + */ + void add_expected_bssid(const sMacAddr &bssid); + + /** + * @brief removes the given bssid from the internal list + * @param bssid the bssid to remove + * @return - nothing + */ + void remove_expected_bssid(const sMacAddr &); + + /** + * @brief search for the given bssid in the internal list + * @param bssid the bssid to search + * @return bool exists / does not exists + */ + bool find_expected_bssid(const sMacAddr &) const; + + /** + * @brief checks if the internal list is empty + * @return bool empty / not empty + */ + bool is_expected_bssid_empty() const; + +private: + uint16_t m_mid = 0; + std::unordered_set m_expected_bssid_list; + uint8_t m_response_buffer[beerocks::message::MESSAGE_BUFFER_LENGTH] = {0}; + ieee1905_1::CmduMessageTx m_response = {m_response_buffer, sizeof(m_response_buffer)}; +}; + +template +void ExpectedApMetricsResponse::add_expected_bssid(FirstIt first, LastIt last) +{ + m_expected_bssid_list.insert(first, last); +} + +} // namespace beerocks + +#endif From a0892f1f69827e6a8e64f3eb3cbf4ef5d60a37ba Mon Sep 17 00:00:00 2001 From: Ran Regev Date: Tue, 16 Jun 2020 17:47:26 +0300 Subject: [PATCH 2/2] test: test_flowys.py added test_ap_metrics_interval_response added test for ap metrics query/response tests that there is exactly one response from each agent within the time of the interval MAP-4.7.4_ETH_FH24G:netgear-rax40 MAP-4.7.4_ETH_FH5GL:netgear-rax40 MAP-4.7.4_ETH_FH5GH:netgear-rax40 MAP-4.7.5_ETH_FH24G:netgear-rax40 MAP-4.7.5_ETH_FH5GL:netgear-rax40 MAP-4.7.5_ETH_FH5GH:netgear-rax40 MAP-4.7.6_ETH_FH24G:netgear-rax40 MAP-4.7.6_ETH_FH5GL:netgear-rax40 MAP-4.7.6_ETH_FH5GH:netgear-rax40 Signed-off-by: Ran Regev --- tests/test_flows.py | 64 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/tests/test_flows.py b/tests/test_flows.py index 065e806d22..4c54acbc38 100755 --- a/tests/test_flows.py +++ b/tests/test_flows.py @@ -908,7 +908,7 @@ def test_client_association_dummy(self): if sta.mac in map_vap0.clients: self.fail("client {} still in conn_map, clients: {}".format(sta.mac, map_vap0.clients)) - # Associate with other radio implies disassociate from first + env.agents[0].radios[1].vaps[0].disassociate(sta) env.agents[0].radios[0].vaps[0].associate(sta) time.sleep(1) # Wait for conn_map to be updated conn_map = connmap.get_conn_map() @@ -1189,6 +1189,68 @@ def test_beacon_report_query(self): # r"inserting 1 RRM_EVENT_BEACON_REP_RXED event(s) to the pending list") env.agents[0].radios[0].vaps[0].disassociate(sta) + def test_ap_metrics_interval_response(self): + # Trigger( + # DEV_SEND_1905,DestAL id, + # WTS_REPLACE_DEST_A LID, + # MessageTypeValue,0x8003, + # tlv_type,0x8A, + # tlv_length,0x000C, + # tlv_value,{0x05 0x01 {WTS_REPLACE_MAUT_RUID 0x00 0x00 0x00 0xC0}) + + # set vaps for both agents + for agent in range(0, 2): + env.beerocks_cli_command('bml_clear_wifi_credentials {}'.format(env.agents[agent].mac)) + env.beerocks_cli_command('bml_set_wifi_credentials {} {} {} {} {}' + .format(env.agents[agent].mac, + "Multi-AP-24G-3-cli", "maprocks1", "24g", "fronthaul")) + env.beerocks_cli_command('bml_update_wifi_credentials {}'.format(env.agents[agent].mac)) + + # create and associate stations + + sta1 = env.Station.create() + debug("Connect dummy STA (" + sta1.mac + ") to wlan0") + env.agents[0].radios[0].vaps[0].associate(sta1) + + sta2 = env.Station.create() + debug("Connect dummy STA (" + sta2.mac + ") to wlan2") + env.agents[1].radios[1].vaps[0].associate(sta2) + + debug("sending multi-ap policy config request") + + # in seconds + interval_time = 5 + tlv_value = '0x{:02} 0x01 0x{ruid} 0x00 0x00 0x00 0xC0'.format( + interval_time, ruid=env.agents[0].radios[0].mac.replace(':', '')) + + debug(tlv_value) + + # sending two commands to the controller, for each agent + env.controller.dev_send_1905(env.agents[0].mac, 0x8003, + tlv(0x8A, 0x000C, "{" + tlv_value + "}")) + + env.controller.dev_send_1905(env.agents[1].mac, 0x8003, + tlv(0x8A, 0x000C, "{" + tlv_value + "}")) + + # wait for ACK + time.sleep(1) + self.check_cmdu_type_single("ACK", 0x8000, env.agents[0].mac, env.controller.mac) + self.check_cmdu_type_single("ACK", 0x8000, env.agents[1].mac, env.controller.mac) + + # wait for report + # since it is a periodic report and we want to verify that + # we have only _one_ response, we wait for a time correlated with the request itself + time.sleep(interval_time + interval_time/2) + + # expect two single reports + self.check_cmdu_type_single("ap metrics response agent1", 0x800C, + env.agents[0].mac, env.controller.mac) + self.check_cmdu_type_single("ap metrics response agent2", 0x800C, + env.agents[1].mac, env.controller.mac) + + env.agents[0].radios[0].vaps[0].disassociate(sta1) + env.agents[1].radios[1].vaps[0].disassociate(sta2) + if __name__ == '__main__': t = TestFlows()