From 7e04718672d441affc85c1dcb195542ce12d5f45 Mon Sep 17 00:00:00 2001 From: Vitaly Bukhovsky Date: Tue, 16 Jun 2020 08:04:13 +0000 Subject: [PATCH 01/28] btlvf: format yaml files Signed-off-by: Vitaly Bukhovsky --- .../tlvf/beerocks_message_1905_vs.yaml | 16 +- .../tlvf/beerocks_message_action.yaml | 75 ++++---- .../tlvf/beerocks_message_apmanager.yaml | 22 +-- .../tlvf/beerocks_message_backhaul.yaml | 36 ++-- .../beerocks/tlvf/beerocks_message_bml.yaml | 90 ++++----- .../beerocks/tlvf/beerocks_message_cli.yaml | 39 ++-- .../tlvf/beerocks_message_cli_net_map.yaml | 38 ++-- .../tlvf/beerocks_message_control.yaml | 176 +++++++++--------- .../tlvf/beerocks_message_header.yaml | 13 +- .../tlvf/beerocks_message_monitor.yaml | 79 ++++---- .../tlvf/beerocks_message_platform.yaml | 68 +++---- 11 files changed, 322 insertions(+), 330 deletions(-) diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_1905_vs.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_1905_vs.yaml index 845bc2ba34..01b3ccf0ab 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_1905_vs.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_1905_vs.yaml @@ -1,9 +1,7 @@ # --- -_include: { - bcl/beerocks_message_structs.h, - beerocks/tlvf/beerocks_message_action.h, -} +_include: + { bcl/beerocks_message_structs.h, beerocks/tlvf/beerocks_message_action.h } _namespace: beerocks_message @@ -11,7 +9,7 @@ _multi_class: True _multi_class_auto_insert: action_op: _type: eActionOp_1905_VS - _value_const: ACTION_TLV_VENDOR_SPECIFIC + _value_const: ACTION_TLV_VENDOR_SPECIFIC _class_const: True ################################################# @@ -23,15 +21,15 @@ tlvVsClientAssociationEvent: mac: sMacAddr bssid: sMacAddr vap_id: int8_t - capabilities: + capabilities: _type: beerocks::message::sRadioCapabilities _comment: relevant only on connect event - disconnect_reason: + disconnect_reason: _type: uint8_t _comment: relevant only on disconnect event - disconnect_source: + disconnect_source: _type: uint8_t _comment: relevant only on disconnect event - disconnect_type: + disconnect_type: _type: uint8_t _comment: relevant only on disconnect event diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_action.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_action.yaml index e793c314b5..3cd129fdf0 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_action.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_action.yaml @@ -48,7 +48,7 @@ eActionOp_CONTROL: ACTION_CONTROL_BACKHAUL_ROAM_REQUEST: 30 ACTION_CONTROL_BACKHAUL_DL_RSSI_REPORT_NOTIFICATION: 31 ACTION_CONTROL_BACKHAUL_RESET: 32 - + ACTION_CONTROL_HOSTAP_CHANNEL_SWITCH_REQUEST: 53 ACTION_CONTROL_HOSTAP_CSA_ERROR_NOTIFICATION: 54 ACTION_CONTROL_HOSTAP_CSA_NOTIFICATION: 55 @@ -79,7 +79,7 @@ eActionOp_CONTROL: ACTION_CONTROL_CLIENT_RX_RSSI_MEASUREMENT_NOTIFICATION: 106 ACTION_CONTROL_CLIENT_NO_RESPONSE_NOTIFICATION: 107 ACTION_CONTROL_CLIENT_NEW_IP_ADDRESS_NOTIFICATION: 108 - + ACTION_CONTROL_CLIENT_DISCONNECT_REQUEST: 111 ACTION_CONTROL_CLIENT_DISCONNECT_RESPONSE: 112 ACTION_CONTROL_CLIENT_DHCP_COMPLETE_NOTIFICATION: 115 @@ -98,19 +98,19 @@ eActionOp_CONTROL: ACTION_CONTROL_STEERING_CLIENT_SET_GROUP_RESPONSE: 128 ACTION_CONTROL_STEERING_CLIENT_SET_REQUEST: 129 ACTION_CONTROL_STEERING_CLIENT_SET_RESPONSE: 130 - ACTION_CONTROL_STEERING_EVENT_CLIENT_ACTIVITY_NOTIFICATION : 131 - ACTION_CONTROL_STEERING_EVENT_SNR_XING_NOTIFICATION : 132 - ACTION_CONTROL_STEERING_EVENT_PROBE_REQ_NOTIFICATION : 133 - ACTION_CONTROL_STEERING_EVENT_AUTH_FAIL_NOTIFICATION : 134 + ACTION_CONTROL_STEERING_EVENT_CLIENT_ACTIVITY_NOTIFICATION: 131 + ACTION_CONTROL_STEERING_EVENT_SNR_XING_NOTIFICATION: 132 + ACTION_CONTROL_STEERING_EVENT_PROBE_REQ_NOTIFICATION: 133 + ACTION_CONTROL_STEERING_EVENT_AUTH_FAIL_NOTIFICATION: 134 - ACTION_CONTROL_CHANNEL_SCAN_TRIGGER_SCAN_REQUEST : 140 - ACTION_CONTROL_CHANNEL_SCAN_TRIGGER_SCAN_RESPONSE : 141 + ACTION_CONTROL_CHANNEL_SCAN_TRIGGER_SCAN_REQUEST: 140 + ACTION_CONTROL_CHANNEL_SCAN_TRIGGER_SCAN_RESPONSE: 141 ACTION_CONTROL_CHANNEL_SCAN_DUMP_RESULTS_REQUEST: 142 ACTION_CONTROL_CHANNEL_SCAN_DUMP_RESULTS_RESPONSE: 143 - ACTION_CONTROL_CHANNEL_SCAN_TRIGGERED_NOTIFICATION : 144 - ACTION_CONTROL_CHANNEL_SCAN_RESULTS_NOTIFICATION : 145 - ACTION_CONTROL_CHANNEL_SCAN_ABORT_NOTIFICATION : 146 - ACTION_CONTROL_CHANNEL_SCAN_FINISHED_NOTIFICATION : 147 + ACTION_CONTROL_CHANNEL_SCAN_TRIGGERED_NOTIFICATION: 144 + ACTION_CONTROL_CHANNEL_SCAN_RESULTS_NOTIFICATION: 145 + ACTION_CONTROL_CHANNEL_SCAN_ABORT_NOTIFICATION: 146 + ACTION_CONTROL_CHANNEL_SCAN_FINISHED_NOTIFICATION: 147 ACTION_CONTROL_ENUM_END: 148 @@ -291,9 +291,9 @@ eActionOp_MONITOR: ACTION_MONITOR_HOSTAP_LOAD_MEASUREMENT_NOTIFICATION: 52 ACTION_MONITOR_HOSTAP_ACTIVITY_NOTIFICATION: 53 ACTION_MONITOR_HOSTAP_STATUS_CHANGED_NOTIFICATION: 54 - - ACTION_MONITOR_CHANNEL_SCAN_TRIGGER_SCAN_REQUEST : 60 - ACTION_MONITOR_CHANNEL_SCAN_TRIGGER_SCAN_RESPONSE : 61 + + ACTION_MONITOR_CHANNEL_SCAN_TRIGGER_SCAN_REQUEST: 60 + ACTION_MONITOR_CHANNEL_SCAN_TRIGGER_SCAN_RESPONSE: 61 ACTION_MONITOR_CHANNEL_SCAN_TRIGGERED_NOTIFICATION: 62 ACTION_MONITOR_CHANNEL_SCAN_DUMP_RESULTS_REQUEST: 63 ACTION_MONITOR_CHANNEL_SCAN_DUMP_RESULTS_RESPONSE: 64 @@ -310,7 +310,6 @@ eActionOp_MONITOR: ACTION_MONITOR_ENUM_END: 86 - #################################################### #################################################### eActionOp_CLI: @@ -343,12 +342,12 @@ eActionOp_CLI: ACTION_CLI_CLIENT_CHANNEL_LOAD_11K_REQUEST: 85 ACTION_CLI_CLIENT_BEACON_11K_REQUEST: 86 ACTION_CLI_CLIENT_STATISTICS_11K_REQUEST: 87 - + ACTION_CLI_HOSTAP_CHANNEL_SWITCH_REQUEST: 122 ACTION_CLI_HOSTAP_SET_NEIGHBOR_11K_REQUEST: 123 ACTION_CLI_HOSTAP_REMOVE_NEIGHBOR_11K_REQUEST: 124 ACTION_CLI_HOSTAP_STATS_MEASUREMENT: 125 - + ACTION_CLI_ENUM_END: 126 #################################################### @@ -404,12 +403,12 @@ eActionOp_BML: ACTION_BML_SET_SERVICE_FAIRNESS_RESPONSE: 77 ACTION_BML_GET_SERVICE_FAIRNESS_REQUEST: 78 ACTION_BML_GET_SERVICE_FAIRNESS_RESPONSE: 79 - + ACTION_BML_SET_CLIENT_ROAMING_PREFER_SIGNAL_STRENGTH_REQUEST: 80 ACTION_BML_SET_CLIENT_ROAMING_PREFER_SIGNAL_STRENGTH_RESPONSE: 81 ACTION_BML_GET_CLIENT_ROAMING_PREFER_SIGNAL_STRENGTH_REQUEST: 82 ACTION_BML_GET_CLIENT_ROAMING_PREFER_SIGNAL_STRENGTH_RESPONSE: 83 - + ACTION_BML_SET_DFS_REENTRY_REQUEST: 84 ACTION_BML_SET_DFS_REENTRY_RESPONSE: 85 ACTION_BML_GET_DFS_REENTRY_REQUEST: 86 @@ -434,7 +433,7 @@ eActionOp_BML: ACTION_BML_CHANGE_MODULE_LOGGING_LEVEL_REQUEST: 140 ACTION_BML_CHANGE_MODULE_LOGGING_LEVEL_RESPONSE: 141 - + ACTION_BML_SET_VAP_LIST_CREDENTIALS_REQUEST: 150 ACTION_BML_SET_VAP_LIST_CREDENTIALS_RESPONSE: 151 ACTION_BML_GET_VAP_LIST_CREDENTIALS_REQUEST: 152 @@ -448,8 +447,8 @@ eActionOp_BML: ACTION_BML_STEERING_EVENT_REGISTER_UNREGISTER_RESPONSE: 168 ACTION_BML_STEERING_CLIENT_DISCONNECT_REQUEST: 169 ACTION_BML_STEERING_CLIENT_DISCONNECT_RESPONSE: 170 - ACTION_BML_STEERING_CLIENT_MEASURE_REQUEST : 171 - ACTION_BML_STEERING_CLIENT_MEASURE_RESPONSE : 172 + ACTION_BML_STEERING_CLIENT_MEASURE_REQUEST: 171 + ACTION_BML_STEERING_CLIENT_MEASURE_RESPONSE: 172 ACTION_BML_STEERING_EVENT_PROBE_REQ_NOTIFICATION: 178 ACTION_BML_STEERING_EVENT_CLIENT_CONNECT_NOTIFICATION: 179 @@ -458,7 +457,7 @@ eActionOp_BML: ACTION_BML_STEERING_EVENT_SNR_XING_NOTIFICATION: 182 ACTION_BML_STEERING_EVENT_SNR_NOTIFICATION: 183 ACTION_BML_STEERING_EVENT_AUTH_FAIL_NOTIFICATION: 184 - ACTION_BML_STEERING_EVENTS_UPDATE : 185 + ACTION_BML_STEERING_EVENTS_UPDATE: 185 ACTION_BML_TRIGGER_CHANNEL_SELECTION_REQUEST: 190 ACTION_BML_TRIGGER_TOPOLOGY_QUERY: 191 @@ -466,19 +465,19 @@ eActionOp_BML: ACTION_BML_REGISTER_TOPOLOGY_QUERY: 193 ACTION_BML_UNREGISTER_TOPOLOGY_QUERY: 194 - ACTION_BML_CHANNEL_SCAN_SET_CONTINUOUS_PARAMS_REQUEST : 200 - ACTION_BML_CHANNEL_SCAN_SET_CONTINUOUS_PARAMS_RESPONSE : 201 - ACTION_BML_CHANNEL_SCAN_GET_CONTINUOUS_PARAMS_REQUEST : 202 - ACTION_BML_CHANNEL_SCAN_GET_CONTINUOUS_PARAMS_RESPONSE : 203 - ACTION_BML_CHANNEL_SCAN_SET_CONTINUOUS_ENABLE_REQUEST : 204 - ACTION_BML_CHANNEL_SCAN_SET_CONTINUOUS_ENABLE_RESPONSE : 205 - ACTION_BML_CHANNEL_SCAN_GET_CONTINUOUS_ENABLE_REQUEST : 206 - ACTION_BML_CHANNEL_SCAN_GET_CONTINUOUS_ENABLE_RESPONSE : 207 - ACTION_BML_CHANNEL_SCAN_START_SCAN_REQUEST : 208 - ACTION_BML_CHANNEL_SCAN_START_SCAN_RESPONSE : 209 - ACTION_BML_CHANNEL_SCAN_GET_RESULTS_REQUEST : 210 - ACTION_BML_CHANNEL_SCAN_GET_RESULTS_RESPONSE : 211 - ACTION_BML_CHANNEL_SCAN_DUMP_RESULTS_REQUEST : 212 - ACTION_BML_CHANNEL_SCAN_DUMP_RESULTS_RESPONSE : 213 + ACTION_BML_CHANNEL_SCAN_SET_CONTINUOUS_PARAMS_REQUEST: 200 + ACTION_BML_CHANNEL_SCAN_SET_CONTINUOUS_PARAMS_RESPONSE: 201 + ACTION_BML_CHANNEL_SCAN_GET_CONTINUOUS_PARAMS_REQUEST: 202 + ACTION_BML_CHANNEL_SCAN_GET_CONTINUOUS_PARAMS_RESPONSE: 203 + ACTION_BML_CHANNEL_SCAN_SET_CONTINUOUS_ENABLE_REQUEST: 204 + ACTION_BML_CHANNEL_SCAN_SET_CONTINUOUS_ENABLE_RESPONSE: 205 + ACTION_BML_CHANNEL_SCAN_GET_CONTINUOUS_ENABLE_REQUEST: 206 + ACTION_BML_CHANNEL_SCAN_GET_CONTINUOUS_ENABLE_RESPONSE: 207 + ACTION_BML_CHANNEL_SCAN_START_SCAN_REQUEST: 208 + ACTION_BML_CHANNEL_SCAN_START_SCAN_RESPONSE: 209 + ACTION_BML_CHANNEL_SCAN_GET_RESULTS_REQUEST: 210 + ACTION_BML_CHANNEL_SCAN_GET_RESULTS_RESPONSE: 211 + ACTION_BML_CHANNEL_SCAN_DUMP_RESULTS_REQUEST: 212 + ACTION_BML_CHANNEL_SCAN_DUMP_RESULTS_RESPONSE: 213 ACTION_BML_ENUM_END: 214 diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_apmanager.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_apmanager.yaml index a92dbdeabd..7b0940678a 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_apmanager.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_apmanager.yaml @@ -1,21 +1,18 @@ # --- -_include: { - beerocks/tlvf/beerocks_message_common.h, - tlvf/WSC/WSC_Attributes.h, -} +_include: { beerocks/tlvf/beerocks_message_common.h, tlvf/WSC/WSC_Attributes.h } _namespace: beerocks_message _multi_class: True _multi_class_auto_insert: action_op: _type: eActionOp_APMANAGER - _value_const: [_auto_value_by_name, 1] + _value_const: [_auto_value_by_name, 1] _class_const: True ################################################# ################################################# - + cACTION_APMANAGER_UP_NOTIFICATION: _type: class iface_name_length: @@ -38,13 +35,13 @@ cACTION_APMANAGER_JOINED_NOTIFICATION: _length_var: True preferred_channels: _type: beerocks::message::sWifiChannel - _length: [ preferred_channels_size ] + _length: [preferred_channels_size] supported_channels_size: _type: uint8_t _length_var: True supported_channels: _type: beerocks::message::sWifiChannel - _length: [ supported_channels_size ] + _length: [supported_channels_size] cACTION_APMANAGER_ENABLE_APS_REQUEST: _type: class @@ -109,7 +106,7 @@ cACTION_APMANAGER_HOSTAP_ACS_NOTIFICATION: _length_var: True preferred_channels: _type: beerocks::message::sWifiChannel - _length: [ preferred_channels_size ] + _length: [preferred_channels_size] cACTION_APMANAGER_HOSTAP_DFS_CAC_COMPLETED_NOTIFICATION: _type: class @@ -143,7 +140,7 @@ cACTION_APMANAGER_CLIENT_ASSOCIATED_NOTIFICATION: vap_id: int8_t association_frame: _type: uint8_t - _length: [] + _length: [] cACTION_APMANAGER_CLIENT_DISCONNECTED_NOTIFICATION: _type: class @@ -219,7 +216,7 @@ cACTION_APMANAGER_WIFI_CREDENTIALS_UPDATE_REQUEST: _length_var: True wifi_credentials: _type: WSC::cConfigData - _length: [ wifi_credentials_size ] + _length: [wifi_credentials_size] cACTION_APMANAGER_START_WPS_PBC_REQUEST: _type: class @@ -237,5 +234,4 @@ cACTION_APMANAGER_READ_ACS_REPORT_RESPONSE: _length_var: True preferred_channels: _type: beerocks::message::sWifiChannel - _length: [ preferred_channels_size ] - + _length: [preferred_channels_size] diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_backhaul.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_backhaul.yaml index 42257e6ced..0d1cf6b5da 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_backhaul.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_backhaul.yaml @@ -6,7 +6,7 @@ _multi_class: True _multi_class_auto_insert: action_op: _type: eActionOp_BACKHAUL - _value_const: [_auto_value_by_name, 1] + _value_const: [_auto_value_by_name, 1] _class_const: True ################################################# @@ -16,10 +16,10 @@ cACTION_BACKHAUL_REGISTER_REQUEST: _type: class sta_iface: _type: char - _length: [ "beerocks::message::IFACE_NAME_LENGTH" ] + _length: ["beerocks::message::IFACE_NAME_LENGTH"] hostap_iface: _type: char - _length: [ "beerocks::message::IFACE_NAME_LENGTH" ] + _length: ["beerocks::message::IFACE_NAME_LENGTH"] local_master: uint8_t local_gw: uint8_t sta_iface_filter_low: uint8_t @@ -38,40 +38,40 @@ cACTION_BACKHAUL_ENABLE: iface_mac: sMacAddr wire_iface: _type: char - _length: [ "beerocks::message::IFACE_NAME_LENGTH" ] + _length: ["beerocks::message::IFACE_NAME_LENGTH"] sta_iface: _type: char - _length: [ "beerocks::message::IFACE_NAME_LENGTH" ] + _length: ["beerocks::message::IFACE_NAME_LENGTH"] ssid: _type: char - _length: [ "beerocks::message::WIFI_SSID_MAX_LENGTH" ] + _length: ["beerocks::message::WIFI_SSID_MAX_LENGTH"] pass: _type: char - _length: [ "beerocks::message::WIFI_PASS_MAX_LENGTH" ] + _length: ["beerocks::message::WIFI_PASS_MAX_LENGTH"] security_type: uint32_t # bwl::sta_wlan_hal::Security preferred_bssid: sMacAddr - wire_iface_type: uint8_t - wireless_iface_type: uint8_t + wire_iface_type: uint8_t + wireless_iface_type: uint8_t mem_only_psk: uint8_t backhaul_preferred_radio_band: uint8_t frequency_band: beerocks::eFreqType - max_bandwidth: beerocks::eWiFiBandwidth + max_bandwidth: beerocks::eWiFiBandwidth ht_supported: uint8_t #bool ht_capability: uint16_t ht_mcs_set: _type: uint8_t - _length: [ "beerocks::message::HT_MCS_SET_SIZE" ] + _length: ["beerocks::message::HT_MCS_SET_SIZE"] vht_supported: uint8_t #bool vht_capability: uint32_t vht_mcs_set: _type: uint8_t - _length: [ "beerocks::message::VHT_MCS_SET_SIZE" ] + _length: ["beerocks::message::VHT_MCS_SET_SIZE"] preferred_channels_size: _type: uint8_t _length_var: True preferred_channels: _type: beerocks::message::sWifiChannel - _length: [ preferred_channels_size ] + _length: [preferred_channels_size] cACTION_BACKHAUL_CONNECTED_NOTIFICATION: _type: class @@ -93,7 +93,7 @@ cACTION_BACKHAUL_ROAM_REQUEST: cACTION_BACKHAUL_ROAM_RESPONSE: _type: class - connected: uint8_t + connected: uint8_t cACTION_BACKHAUL_RESET: _type: class @@ -134,8 +134,8 @@ cACTION_BACKHAUL_CLIENT_ASSOCIATED_NOTIFICATION: client_mac: sMacAddr bssid: sMacAddr association_frame: - _type: uint8_t - _length: [] + _type: uint8_t + _length: [] cACTION_BACKHAUL_CLIENT_DISCONNECTED_NOTIFICATION: _type: class @@ -149,7 +149,7 @@ cACTION_BACKHAUL_ASSOCIATED_STA_LINK_METRICS_REQUEST: cACTION_BACKHAUL_ASSOCIATED_STA_LINK_METRICS_RESPONSE: _type: class - _is_tlv_class : True + _is_tlv_class: True length: uint16_t sta_mac: sMacAddr bssid_info_list_length: @@ -157,7 +157,7 @@ cACTION_BACKHAUL_ASSOCIATED_STA_LINK_METRICS_RESPONSE: _length_var: True bssid_info_list: _type: sBssidInfo - _length: [ bssid_info_list_length ] + _length: [bssid_info_list_length] cACTION_BACKHAUL_START_WPS_PBC_REQUEST: _type: class diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_bml.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_bml.yaml index 864163a033..065e0d05f6 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_bml.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_bml.yaml @@ -6,14 +6,14 @@ _multi_class: True _multi_class_auto_insert: action_op: _type: eActionOp_BML - _value_const: [_auto_value_by_name, 1] + _value_const: [_auto_value_by_name, 1] _class_const: True ################################################# ################################################# cACTION_BML_PING_REQUEST: - _type: class + _type: class cACTION_BML_PING_RESPONSE: _type: class @@ -27,9 +27,9 @@ cACTION_BML_NW_MAP_RESPONSE: buffer_size: _type: uint32_t _length_var: True - buffer: + buffer: _type: char - _length: [ buffer_size ] + _length: [buffer_size] cACTION_BML_NW_MAP_UPDATE: _type: class @@ -37,9 +37,9 @@ cACTION_BML_NW_MAP_UPDATE: buffer_size: _type: uint32_t _length_var: True - buffer: + buffer: _type: char - _length: [ buffer_size ] + _length: [buffer_size] cACTION_BML_STATS_UPDATE: _type: class @@ -47,18 +47,18 @@ cACTION_BML_STATS_UPDATE: buffer_size: _type: uint32_t _length_var: True - buffer: + buffer: _type: char - _length: [ buffer_size ] + _length: [buffer_size] cACTION_BML_EVENTS_UPDATE: _type: class buffer_size: _type: uint32_t _length_var: True - buffer: + buffer: _type: char - _length: [ buffer_size ] + _length: [buffer_size] cACTION_BML_REGISTER_TO_NW_MAP_UPDATES_REQUEST: _type: class @@ -79,28 +79,28 @@ cACTION_BML_GET_LEGACY_CLIENT_ROAMING_REQUEST: _type: class cACTION_BML_REGISTER_TO_EVENTS_UPDATES_REQUEST: - _type: class + _type: class cACTION_BML_REGISTER_TO_EVENTS_UPDATES_RESPONSE: - _type: class + _type: class cACTION_BML_UNREGISTER_FROM_EVENTS_UPDATES_REQUEST: - _type: class + _type: class cACTION_BML_UNREGISTER_FROM_EVENTS_UPDATES_RESPONSE: - _type: class + _type: class cACTION_BML_REGISTER_TO_STATS_UPDATES_REQUEST: - _type: class + _type: class cACTION_BML_REGISTER_TO_STATS_UPDATES_RESPONSE: - _type: class + _type: class cACTION_BML_UNREGISTER_FROM_STATS_UPDATES_REQUEST: - _type: class + _type: class cACTION_BML_UNREGISTER_FROM_STATS_UPDATES_RESPONSE: - _type: class + _type: class cACTION_BML_SET_LEGACY_CLIENT_ROAMING_REQUEST: _type: class @@ -109,16 +109,16 @@ cACTION_BML_SET_LEGACY_CLIENT_ROAMING_REQUEST: cACTION_BML_GET_LEGACY_CLIENT_ROAMING_RESPONSE: _type: class isEnable: uint8_t - + cACTION_BML_SET_CLIENT_ROAMING_REQUEST: _type: class isEnable: uint8_t cACTION_BML_SET_CLIENT_ROAMING_RESPONSE: _type: class - + cACTION_BML_GET_CLIENT_ROAMING_REQUEST: - _type: class + _type: class cACTION_BML_GET_CLIENT_ROAMING_RESPONSE: _type: class @@ -130,9 +130,9 @@ cACTION_BML_SET_DFS_REENTRY_REQUEST: cACTION_BML_SET_DFS_REENTRY_RESPONSE: _type: class - + cACTION_BML_GET_DFS_REENTRY_REQUEST: - _type: class + _type: class cACTION_BML_GET_DFS_REENTRY_RESPONSE: _type: class @@ -227,19 +227,19 @@ cACTION_BML_WIFI_CREDENTIALS_SET_REQUEST: _length_var: True ssid: _type: char - _length: [ ssid_size ] + _length: [ssid_size] network_key_size: _type: uint8_t _length_var: True network_key: _type: char - _length: [ network_key_size ] + _length: [network_key_size] operating_classes_size: _type: uint8_t _length_var: True operating_classes: _type: uint8_t - _length: [ operating_classes_size ] + _length: [operating_classes_size] cACTION_BML_WIFI_CREDENTIALS_SET_RESPONSE: _type: class @@ -276,37 +276,37 @@ cACTION_BML_GET_CERTIFICATION_MODE_RESPONSE: isEnable: uint8_t cACTION_BML_SET_VAP_LIST_CREDENTIALS_REQUEST: - _type: class + _type: class result: _type: uint32_t - _comment: # 0 - Failure, 1 - Success + _comment: # 0 - Failure, 1 - Success vap_list_size: _type: uint8_t _length_var: True vap_list: _type: sConfigVapInfo - _length: [ vap_list_size ] + _length: [vap_list_size] cACTION_BML_SET_VAP_LIST_CREDENTIALS_RESPONSE: - _type: class + _type: class result: _type: uint32_t - _comment: # 0 - Failure, 1 - Success - + _comment: # 0 - Failure, 1 - Success + cACTION_BML_GET_VAP_LIST_CREDENTIALS_RESPONSE: - _type: class + _type: class result: _type: uint32_t - _comment: # 0 - Failure, 1 - Success + _comment: # 0 - Failure, 1 - Success vap_list_size: _type: uint8_t _length_var: True vap_list: _type: sConfigVapInfo - _length: [ vap_list_size ] - + _length: [vap_list_size] + cACTION_BML_GET_VAP_LIST_CREDENTIALS_REQUEST: - _type: class + _type: class result: _type: uint32_t _comment: # 0 - Failure, 1 - Success @@ -320,7 +320,7 @@ cACTION_BML_STEERING_SET_GROUP_REQUEST: cACTION_BML_STEERING_SET_GROUP_RESPONSE: _type: class - error_code: int32_t + error_code: int32_t cACTION_BML_STEERING_CLIENT_SET_REQUEST: _type: class @@ -339,7 +339,7 @@ cACTION_BML_STEERING_EVENT_REGISTER_UNREGISTER_REQUEST: unregister: uint8_t cACTION_BML_STEERING_EVENT_REGISTER_UNREGISTER_RESPONSE: - _type: class + _type: class error_code: int32_t cACTION_BML_STEERING_CLIENT_DISCONNECT_REQUEST: @@ -351,7 +351,7 @@ cACTION_BML_STEERING_CLIENT_DISCONNECT_REQUEST: reason: uint32_t cACTION_BML_STEERING_CLIENT_DISCONNECT_RESPONSE: - _type: class + _type: class error_code: int32_t cACTION_BML_STEERING_CLIENT_MEASURE_REQUEST: @@ -361,7 +361,7 @@ cACTION_BML_STEERING_CLIENT_MEASURE_REQUEST: client_mac: sMacAddr cACTION_BML_STEERING_CLIENT_MEASURE_RESPONSE: - _type: class + _type: class error_code: int32_t ################################################ @@ -372,9 +372,9 @@ cACTION_BML_STEERING_EVENTS_UPDATE: buffer_size: _type: uint32_t _length_var: True - buffer: + buffer: _type: char - _length: [ buffer_size ] + _length: [buffer_size] cACTION_BML_TRIGGER_TOPOLOGY_QUERY: _type: class @@ -385,7 +385,7 @@ cACTION_BML_TOPOLOGY_RESPONSE: device_data: sDeviceData result: _type: uint32_t - _comment: # 0 - Failure, 1 - Success + _comment: # 0 - Failure, 1 - Success cACTION_BML_REGISTER_TOPOLOGY_QUERY: _type: class @@ -469,7 +469,7 @@ cACTION_BML_CHANNEL_SCAN_GET_RESULTS_RESPONSE: _length_var: True results: _type: sChannelScanResults - _length: [ results_size ] + _length: [results_size] cACTION_BML_CHANNEL_SCAN_DUMP_RESULTS_REQUEST: _type: class diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_cli.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_cli.yaml index a4d9261105..b27cc65e4f 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_cli.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_cli.yaml @@ -1,15 +1,16 @@ # --- -_include: { - beerocks/tlvf/beerocks_message_common.h, - beerocks/tlvf/beerocks_message_cli_net_map.h, -} +_include: + { + beerocks/tlvf/beerocks_message_common.h, + beerocks/tlvf/beerocks_message_cli_net_map.h, + } _namespace: beerocks_message _multi_class: True _multi_class_auto_insert: action_op: _type: eActionOp_CLI - _value_const: [_auto_value_by_name, 1] + _value_const: [_auto_value_by_name, 1] _class_const: True ################################################# @@ -41,9 +42,9 @@ cACTION_CLI_RESPONSE_STR: buffer_size: _type: uint32_t _length_var: True - buffer: + buffer: _type: char - _length: [ buffer_size ] + _length: [buffer_size] cACTION_CLI_CROSS_RX_RSSI_MEASUREMENT: _type: class @@ -127,22 +128,22 @@ cACTION_CLI_CLIENT_CHANNEL_LOAD_11K_REQUEST: cACTION_CLI_CLIENT_BEACON_11K_REQUEST: _type: class - client_mac: sMacAddr - bssid: sMacAddr + client_mac: sMacAddr + bssid: sMacAddr ssid: - _type: uint8_t - _length: [ "beerocks::message::WIFI_SSID_MAX_LENGTH" ] - use_optional_ssid: uint8_t - channel: uint8_t - measurement_mode: uint8_t - duration: uint16_t - rand_ival: uint16_t - repeats: uint16_t - op_class: int16_t + _type: uint8_t + _length: ["beerocks::message::WIFI_SSID_MAX_LENGTH"] + use_optional_ssid: uint8_t + channel: uint8_t + measurement_mode: uint8_t + duration: uint16_t + rand_ival: uint16_t + repeats: uint16_t + op_class: int16_t cACTION_CLI_CLIENT_STATISTICS_11K_REQUEST: _type: class - hostap_mac: sMacAddr + hostap_mac: sMacAddr client_mac: sMacAddr peer_mac: sMacAddr group_identity: uint8_t diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_cli_net_map.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_cli_net_map.yaml index 37db87c93f..c04cff6c27 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_cli_net_map.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_cli_net_map.yaml @@ -17,23 +17,23 @@ sCliNetworkMapNodeSta: sCliNetworkMapsNodeInfo: _type: struct - mac: sMacAddr - ipv4: beerocks::net::sIpv4Addr + mac: sMacAddr + ipv4: beerocks::net::sIpv4Addr name: - _type: char - _length: [ "beerocks::message::NODE_NAME_LENGTH" ] - type: uint8_t - state: uint8_t - channel: uint8_t - bandwidth: uint8_t #beerocks::eWiFiBandwidth - channel_ext_above_secondary: uint8_t - is_dfs: uint8_t - cac_completed: uint8_t - tx_bytes: uint32_t - rx_bytes: uint32_t - stats_delta_ms: uint16_t - tx_load_percent: uint8_t # for HOSTAP it is the total sta tx_load - rx_load_percent: uint8_t # for HOSTAP it is the total sta rx_load - channel_load_percent: uint8_t # only for HOSTAP - iface_type: uint8_t #eIfaceType - vap_id: int8_t + _type: char + _length: ["beerocks::message::NODE_NAME_LENGTH"] + type: uint8_t + state: uint8_t + channel: uint8_t + bandwidth: uint8_t #beerocks::eWiFiBandwidth + channel_ext_above_secondary: uint8_t + is_dfs: uint8_t + cac_completed: uint8_t + tx_bytes: uint32_t + rx_bytes: uint32_t + stats_delta_ms: uint16_t + tx_load_percent: uint8_t # for HOSTAP it is the total sta tx_load + rx_load_percent: uint8_t # for HOSTAP it is the total sta rx_load + channel_load_percent: uint8_t # only for HOSTAP + iface_type: uint8_t #eIfaceType + vap_id: int8_t diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_control.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_control.yaml index f2525acc42..ada2ccef08 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_control.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_control.yaml @@ -6,7 +6,7 @@ _multi_class: True _multi_class_auto_insert: action_op: _type: eActionOp_CONTROL - _value_const: [_auto_value_by_name, 1] + _value_const: [_auto_value_by_name, 1] _class_const: True ################################################# @@ -17,59 +17,59 @@ _multi_class_auto_insert: ################################################# cACTION_CONTROL_SLAVE_HANDSHAKE_REQUEST: - _type: class + _type: class cACTION_CONTROL_SLAVE_HANDSHAKE_RESPONSE: - _type: class + _type: class cACTION_CONTROL_SLAVE_JOINED_NOTIFICATION: _type: class slave_version: _type: char - _length: [ "beerocks::message::VERSION_LENGTH" ] + _length: ["beerocks::message::VERSION_LENGTH"] platform_settings: sPlatformSettings - wlan_settings: sWlanSettings - backhaul_params: sBackhaulParams - hostap: sNodeHostap - cs_params: sApChannelSwitch - low_pass_filter_on: uint8_t # configuration - enable_repeater_mode: uint8_t + wlan_settings: sWlanSettings + backhaul_params: sBackhaulParams + hostap: sNodeHostap + cs_params: sApChannelSwitch + low_pass_filter_on: uint8_t # configuration + enable_repeater_mode: uint8_t radio_identifier: sMacAddr is_slave_reconf: uint8_t cACTION_CONTROL_SLAVE_JOINED_RESPONSE: _type: class master_version: - _type: char - _length: [ "beerocks::message::VERSION_LENGTH" ] - err_code: uint8_t #beerocks::eSlaveJoinResponseErrCode - config: sSonConfig + _type: char + _length: ["beerocks::message::VERSION_LENGTH"] + err_code: uint8_t #beerocks::eSlaveJoinResponseErrCode + config: sSonConfig cACTION_CONTROL_SLAVE_JOINED_4ADDR_MODE_NOTIFICATION: _type: class - backhaul_iface_mac: sMacAddr - backhaul_ipv4: beerocks::net::sIpv4Addr - bridge_iface_mac: sMacAddr - bridge_ipv4: beerocks::net::sIpv4Addr - hostap: sNodeHostap + backhaul_iface_mac: sMacAddr + backhaul_ipv4: beerocks::net::sIpv4Addr + bridge_iface_mac: sMacAddr + bridge_ipv4: beerocks::net::sIpv4Addr + hostap: sNodeHostap cACTION_CONTROL_SON_CONFIG_UPDATE: _type: class - config: sSonConfig + config: sSonConfig cACTION_CONTROL_CONTROLLER_PING_REQUEST: _type: class - total: uint16_t - seq: uint16_t - size: uint16_t + total: uint16_t + seq: uint16_t + size: uint16_t data: _type: uint8_t _length: [] cACTION_CONTROL_CONTROLLER_PING_RESPONSE: _type: class - total: uint16_t - seq: uint16_t + total: uint16_t + seq: uint16_t size: uint16_t data: _type: uint8_t @@ -77,17 +77,17 @@ cACTION_CONTROL_CONTROLLER_PING_RESPONSE: cACTION_CONTROL_AGENT_PING_REQUEST: _type: class - total: uint16_t - seq: uint16_t - size: uint16_t + total: uint16_t + seq: uint16_t + size: uint16_t data: _type: uint8_t _length: [] cACTION_CONTROL_AGENT_PING_RESPONSE: _type: class - total: uint16_t - seq: uint16_t + total: uint16_t + seq: uint16_t size: uint16_t data: _type: uint8_t @@ -95,31 +95,31 @@ cACTION_CONTROL_AGENT_PING_RESPONSE: cACTION_CONTROL_ARP_QUERY_REQUEST: _type: class - params: sArpQuery + params: sArpQuery cACTION_CONTROL_ARP_QUERY_RESPONSE: _type: class - params: sArpMonitorData + params: sArpMonitorData cACTION_CONTROL_PLATFORM_OPERATIONAL_NOTIFICATION: _type: class - bridge_mac: sMacAddr - operational: uint8_t + bridge_mac: sMacAddr + operational: uint8_t cACTION_CONTROL_BACKHAUL_DL_RSSI_REPORT_NOTIFICATION: _type: class - params: sBackhaulRssi + params: sBackhaulRssi cACTION_CONTROL_BACKHAUL_RESET: _type: class cACTION_CONTROL_BACKHAUL_ROAM_REQUEST: _type: class - params: sBackhaulRoam + params: sBackhaulRoam cACTION_CONTROL_CHANGE_MODULE_LOGGING_LEVEL: _type: class - params: sLoggingLevelChange + params: sLoggingLevelChange ################################################# # HOSTAP @@ -127,95 +127,95 @@ cACTION_CONTROL_CHANGE_MODULE_LOGGING_LEVEL: cACTION_CONTROL_HOSTAP_CSA_ERROR_NOTIFICATION: _type: class - cs_params: sApChannelSwitch + cs_params: sApChannelSwitch cACTION_CONTROL_HOSTAP_CSA_NOTIFICATION: _type: class - cs_params: sApChannelSwitch + cs_params: sApChannelSwitch cACTION_CONTROL_HOSTAP_ACS_ERROR_NOTIFICATION: _type: class - cs_params: sApChannelSwitch + cs_params: sApChannelSwitch cACTION_CONTROL_HOSTAP_ACS_NOTIFICATION: _type: class - cs_params: sApChannelSwitch + cs_params: sApChannelSwitch preferred_channels_size: _type: uint8_t _length_var: True preferred_channels: _type: beerocks::message::sWifiChannel - _length: [ preferred_channels_size ] + _length: [preferred_channels_size] cACTION_CONTROL_HOSTAP_DFS_CAC_COMPLETED_NOTIFICATION: _type: class - params: sDfsCacCompleted + params: sDfsCacCompleted cACTION_CONTROL_HOSTAP_DFS_CHANNEL_AVAILABLE_NOTIFICATION: _type: class - params: sDfsChannelAvailable + params: sDfsChannelAvailable cACTION_CONTROL_HOSTAP_SET_RESTRICTED_FAILSAFE_CHANNEL_REQUEST: _type: class - params: sApSetRestrictedFailsafe + params: sApSetRestrictedFailsafe cACTION_CONTROL_HOSTAP_SET_RESTRICTED_FAILSAFE_CHANNEL_RESPONSE: _type: class - success: uint8_t + success: uint8_t cACTION_CONTROL_HOSTAP_CHANNEL_SWITCH_ACS_START: _type: class - cs_params: sApChannelSwitch + cs_params: sApChannelSwitch cACTION_CONTROL_HOSTAP_UPDATE_STOP_ON_FAILURE_ATTEMPTS_REQUEST: _type: class - attempts: uint32_t + attempts: uint32_t cACTION_CONTROL_HOSTAP_DISABLED_BY_MASTER: _type: class cACTION_CONTROL_HOSTAP_CHANNEL_SWITCH_REQUEST: _type: class - cs_params: sApChannelSwitch + cs_params: sApChannelSwitch cACTION_CONTROL_HOSTAP_STATS_MEASUREMENT_REQUEST: _type: class - sync: uint8_t + sync: uint8_t cACTION_CONTROL_HOSTAP_STATS_MEASUREMENT_RESPONSE: _type: class ap_stats_size: _type: uint8_t _length_var: True - ap_stats: + ap_stats: _type: sApStatsParams - _length: [ ap_stats_size ] + _length: [ap_stats_size] sta_stats_size: _type: uint8_t _length_var: True sta_stats: _type: sStaStatsParams - _length: [ sta_stats_size ] + _length: [sta_stats_size] cACTION_CONTROL_HOSTAP_LOAD_MEASUREMENT_NOTIFICATION: _type: class - params: sApLoadNotificationParams + params: sApLoadNotificationParams cACTION_CONTROL_HOSTAP_SET_NEIGHBOR_11K_REQUEST: _type: class - params: sNeighborSetParams11k + params: sNeighborSetParams11k cACTION_CONTROL_HOSTAP_REMOVE_NEIGHBOR_11K_REQUEST: _type: class - params: sNeighborRemoveParams11k + params: sNeighborRemoveParams11k cACTION_CONTROL_HOSTAP_ACTIVITY_NOTIFICATION: _type: class - params: sApActivityNotificationParams + params: sApActivityNotificationParams cACTION_CONTROL_HOSTAP_VAPS_LIST_UPDATE_NOTIFICATION: _type: class - params: sVapsList + params: sVapsList cACTION_CONTROL_HOSTAP_AP_DISABLED_NOTIFICATION: _type: class @@ -226,26 +226,24 @@ cACTION_CONTROL_HOSTAP_AP_ENABLED_NOTIFICATION: vap_id: int8_t vap_info: sVapInfo - ################################################# # CLIENT ################################################# cACTION_CONTROL_CLIENT_START_MONITORING_REQUEST: _type: class - params: sClientMonitoringParams + params: sClientMonitoringParams - cACTION_CONTROL_CLIENT_START_MONITORING_RESPONSE: _type: class success: uint8_t cACTION_CONTROL_CLIENT_RX_RSSI_MEASUREMENT_REQUEST: _type: class - params: sNodeRssiMeasurementRequest + params: sNodeRssiMeasurementRequest cACTION_CONTROL_CLIENT_RX_RSSI_MEASUREMENT_RESPONSE: _type: class - params: sNodeRssiMeasurement + params: sNodeRssiMeasurement cACTION_CONTROL_CLIENT_RX_RSSI_MEASUREMENT_START_NOTIFICATION: _type: class @@ -253,28 +251,28 @@ cACTION_CONTROL_CLIENT_RX_RSSI_MEASUREMENT_START_NOTIFICATION: cACTION_CONTROL_CLIENT_RX_RSSI_MEASUREMENT_CMD_RESPONSE: _type: class - mac: sMacAddr + mac: sMacAddr cACTION_CONTROL_CLIENT_RX_RSSI_MEASUREMENT_NOTIFICATION: _type: class - params: sNodeRssiMeasurement + params: sNodeRssiMeasurement cACTION_CONTROL_CLIENT_NO_ACTIVITY_NOTIFICATION: _type: class - mac: sMacAddr + mac: sMacAddr cACTION_CONTROL_CLIENT_NO_RESPONSE_NOTIFICATION: _type: class - mac: sMacAddr + mac: sMacAddr cACTION_CONTROL_CLIENT_NEW_IP_ADDRESS_NOTIFICATION: _type: class mac: sMacAddr - ipv4: beerocks::net::sIpv4Addr + ipv4: beerocks::net::sIpv4Addr cACTION_CONTROL_CLIENT_DISCONNECT_REQUEST: _type: class - mac: sMacAddr + mac: sMacAddr vap_id: int8_t type: eDisconnectType reason: uint32_t @@ -285,43 +283,43 @@ cACTION_CONTROL_CLIENT_DISCONNECT_RESPONSE: cACTION_CONTROL_CLIENT_DHCP_COMPLETE_NOTIFICATION: _type: class - mac: sMacAddr - ipv4: beerocks::net::sIpv4Addr - name: - _type: char - _length: [ "beerocks::message::NODE_NAME_LENGTH" ] + mac: sMacAddr + ipv4: beerocks::net::sIpv4Addr + name: + _type: char + _length: ["beerocks::message::NODE_NAME_LENGTH"] cACTION_CONTROL_CLIENT_ARP_MONITOR_NOTIFICATION: _type: class - params: sArpMonitorData + params: sArpMonitorData cACTION_CONTROL_CLIENT_BEACON_11K_REQUEST: _type: class - params: sBeaconRequest11k + params: sBeaconRequest11k cACTION_CONTROL_CLIENT_BEACON_11K_RESPONSE: _type: class - params: sBeaconResponse11k + params: sBeaconResponse11k cACTION_CONTROL_CLIENT_CHANNEL_LOAD_11K_REQUEST: _type: class - params: sStaChannelLoadRequest11k + params: sStaChannelLoadRequest11k cACTION_CONTROL_CLIENT_CHANNEL_LOAD_11K_RESPONSE: _type: class - params: sStaChannelLoadResponse11k + params: sStaChannelLoadResponse11k cACTION_CONTROL_CLIENT_STATISTICS_11K_REQUEST: _type: class - params: sStatisticsRequest11k + params: sStatisticsRequest11k cACTION_CONTROL_CLIENT_STATISTICS_11K_RESPONSE: _type: class - params: sStatisticsResponse11k + params: sStatisticsResponse11k cACTION_CONTROL_CLIENT_LINK_MEASUREMENT_11K_REQUEST: _type: class - mac: sMacAddr + mac: sMacAddr cACTION_CONTROL_CLIENT_LINK_MEASUREMENTS_11K_RESPONSE: _type: class @@ -330,19 +328,19 @@ cACTION_CONTROL_CLIENT_LINK_MEASUREMENTS_11K_RESPONSE: ################################################# # MONITOR RDKB CONFIGURATIONS ################################################# -cACTION_CONTROL_STEERING_CLIENT_SET_GROUP_REQUEST: +cACTION_CONTROL_STEERING_CLIENT_SET_GROUP_REQUEST: _type: class params: sSteeringSetGroupRequest -cACTION_CONTROL_STEERING_CLIENT_SET_GROUP_RESPONSE: +cACTION_CONTROL_STEERING_CLIENT_SET_GROUP_RESPONSE: _type: class params: sSteeringSetGroupResponse -cACTION_CONTROL_STEERING_CLIENT_SET_REQUEST: +cACTION_CONTROL_STEERING_CLIENT_SET_REQUEST: _type: class params: sSteeringClientSetRequest -cACTION_CONTROL_STEERING_CLIENT_SET_RESPONSE: +cACTION_CONTROL_STEERING_CLIENT_SET_RESPONSE: _type: class params: sSteeringClientSetResponse ################################################ @@ -353,18 +351,18 @@ cACTION_CONTROL_STEERING_EVENT_CLIENT_ACTIVITY_NOTIFICATION: params: sSteeringEvActivity cACTION_CONTROL_STEERING_EVENT_SNR_XING_NOTIFICATION: - _type: class + _type: class params: sSteeringEvSnrXing ################################################ # AP_MANAGER RDKB NOTIFICATIONS(softblock) ################################################# cACTION_CONTROL_STEERING_EVENT_PROBE_REQ_NOTIFICATION: - _type: class + _type: class params: sSteeringEvProbeReq cACTION_CONTROL_STEERING_EVENT_AUTH_FAIL_NOTIFICATION: - _type: class + _type: class params: sSteeringEvAuthFail ################################################ diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_header.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_header.yaml index 1fb66d6ca7..9c163da338 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_header.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_header.yaml @@ -1,10 +1,11 @@ # --- _namespace: beerocks_message -_include: { - beerocks/tlvf/beerocks_message_common.h, - beerocks/tlvf/beerocks_message_action.h, -} +_include: + { + beerocks/tlvf/beerocks_message_common.h, + beerocks/tlvf/beerocks_message_action.h, + } cACTION_HEADER: _type: class @@ -14,11 +15,11 @@ cACTION_HEADER: version: _type: uint8_t _value_const: "beerocks::message::MESSAGE_VERSION" - action: eAction + action: eAction action_op: _type: uint8_t _comment: need to cast eActionOp_XXXX to uint8_t - direction: + direction: _type: uint8_t _value: 1 #BEEROCKS_DIRECTION_AGENT radio_mac: sMacAddr diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_monitor.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_monitor.yaml index 4ff77ec5ef..55c1ce0db5 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_monitor.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_monitor.yaml @@ -6,7 +6,7 @@ _multi_class: True _multi_class_auto_insert: action_op: _type: eActionOp_MONITOR - _value_const: [_auto_value_by_name, 1] + _value_const: [_auto_value_by_name, 1] _class_const: True ################################################# @@ -20,15 +20,15 @@ cACTION_MONITOR_JOINED_NOTIFICATION: cACTION_MONITOR_SON_CONFIG_UPDATE: _type: class - config: sSonConfig + config: sSonConfig cACTION_MONITOR_CHANGE_MODULE_LOGGING_LEVEL: _type: class - params: sLoggingLevelChange + params: sLoggingLevelChange cACTION_MONITOR_ERROR_NOTIFICATION: _type: class - error_code: uint32_t + error_code: uint32_t cACTION_MONITOR_ERROR_NOTIFICATION_ACK: _type: class @@ -42,7 +42,7 @@ cACTION_MONITOR_HEARTBEAT_NOTIFICATION: cACTION_MONITOR_CLIENT_START_MONITORING_REQUEST: _type: class - params: sClientMonitoringParams + params: sClientMonitoringParams cACTION_MONITOR_CLIENT_START_MONITORING_RESPONSE: _type: class @@ -50,41 +50,41 @@ cACTION_MONITOR_CLIENT_START_MONITORING_RESPONSE: cACTION_MONITOR_CLIENT_RX_RSSI_MEASUREMENT_REQUEST: _type: class - params: sNodeRssiMeasurementRequest + params: sNodeRssiMeasurementRequest cACTION_MONITOR_CLIENT_DISCONNECT_REQUEST: _type: class - mac: sMacAddr - ipv4: beerocks::net::sIpv4Addr - channel: uint8_t + mac: sMacAddr + ipv4: beerocks::net::sIpv4Addr + channel: uint8_t cACTION_MONITOR_CLIENT_RX_RSSI_MEASUREMENT_NOTIFICATION: _type: class - params: sNodeRssiMeasurement - + params: sNodeRssiMeasurement + cACTION_MONITOR_CLIENT_RX_RSSI_MEASUREMENT_RESPONSE: _type: class - params: sNodeRssiMeasurement + params: sNodeRssiMeasurement cACTION_MONITOR_CLIENT_NO_RESPONSE_NOTIFICATION: _type: class - mac: sMacAddr + mac: sMacAddr cACTION_MONITOR_CLIENT_RX_RSSI_MEASUREMENT_START_NOTIFICATION: _type: class - mac: sMacAddr - + mac: sMacAddr + cACTION_MONITOR_CLIENT_RX_RSSI_MEASUREMENT_CMD_RESPONSE: _type: class - mac: sMacAddr + mac: sMacAddr cACTION_MONITOR_CLIENT_NO_ACTIVITY_NOTIFICATION: _type: class - mac: sMacAddr + mac: sMacAddr cACTION_MONITOR_HOSTAP_ACTIVITY_NOTIFICATION: _type: class - params: sApActivityNotificationParams + params: sApActivityNotificationParams cACTION_MONITOR_CLIENT_ASSOCIATED_STA_LINK_METRIC_REQUEST: _type: class @@ -93,7 +93,7 @@ cACTION_MONITOR_CLIENT_ASSOCIATED_STA_LINK_METRIC_REQUEST: cACTION_MONITOR_CLIENT_ASSOCIATED_STA_LINK_METRIC_RESPONSE: _type: class - _is_tlv_class : True + _is_tlv_class: True length: uint16_t sta_mac: sMacAddr bssid_info_list_length: @@ -101,7 +101,7 @@ cACTION_MONITOR_CLIENT_ASSOCIATED_STA_LINK_METRIC_RESPONSE: _length_var: True bssid_info_list: _type: sBssidInfo - _length: [ bssid_info_list_length ] + _length: [bssid_info_list_length] ################################################# # HOSTAP @@ -109,7 +109,7 @@ cACTION_MONITOR_CLIENT_ASSOCIATED_STA_LINK_METRIC_RESPONSE: cACTION_MONITOR_HOSTAP_STATS_MEASUREMENT_REQUEST: _type: class - sync: uint8_t + sync: uint8_t cACTION_MONITOR_HOSTAP_STATUS_CHANGED_NOTIFICATION: _type: class @@ -121,76 +121,76 @@ cACTION_MONITOR_HOSTAP_STATS_MEASUREMENT_RESPONSE: ap_stats_size: _type: uint8_t _length_var: True - ap_stats: + ap_stats: _type: sApStatsParams - _length: [ ap_stats_size ] + _length: [ap_stats_size] sta_stats_size: _type: uint8_t _length_var: True sta_stats: _type: sStaStatsParams - _length: [ sta_stats_size ] + _length: [sta_stats_size] cACTION_MONITOR_HOSTAP_LOAD_MEASUREMENT_NOTIFICATION: _type: class - params: sApLoadNotificationParams + params: sApLoadNotificationParams cACTION_MONITOR_CLIENT_BEACON_11K_REQUEST: _type: class - params: sBeaconRequest11k + params: sBeaconRequest11k cACTION_MONITOR_CLIENT_BEACON_11K_RESPONSE: _type: class - params: sBeaconResponse11k + params: sBeaconResponse11k cACTION_MONITOR_CLIENT_CHANNEL_LOAD_11K_REQUEST: _type: class - params: sStaChannelLoadRequest11k + params: sStaChannelLoadRequest11k cACTION_MONITOR_CLIENT_CHANNEL_LOAD_11K_RESPONSE: _type: class - params: sStaChannelLoadResponse11k + params: sStaChannelLoadResponse11k cACTION_MONITOR_CLIENT_STATISTICS_11K_REQUEST: _type: class - params: sStatisticsRequest11k + params: sStatisticsRequest11k cACTION_MONITOR_CLIENT_STATISTICS_11K_RESPONSE: _type: class - params: sStatisticsResponse11k + params: sStatisticsResponse11k cACTION_MONITOR_CLIENT_LINK_MEASUREMENT_11K_REQUEST: _type: class - mac: sMacAddr + mac: sMacAddr cACTION_MONITOR_CLIENT_LINK_MEASUREMENTS_11K_RESPONSE: _type: class - params: sLinkMeasurementsResponse11k + params: sLinkMeasurementsResponse11k cACTION_MONITOR_CLIENT_NEW_IP_ADDRESS_NOTIFICATION: _type: class mac: sMacAddr - ipv4: beerocks::net::sIpv4Addr + ipv4: beerocks::net::sIpv4Addr ################################################# # CLIENT MONITOR RDKB HAL ################################################# -cACTION_MONITOR_STEERING_CLIENT_SET_GROUP_REQUEST: +cACTION_MONITOR_STEERING_CLIENT_SET_GROUP_REQUEST: _type: class params: sSteeringSetGroupRequest -cACTION_MONITOR_STEERING_CLIENT_SET_GROUP_RESPONSE: +cACTION_MONITOR_STEERING_CLIENT_SET_GROUP_RESPONSE: _type: class params: sSteeringSetGroupResponse -cACTION_MONITOR_STEERING_CLIENT_SET_REQUEST: +cACTION_MONITOR_STEERING_CLIENT_SET_REQUEST: _type: class params: sSteeringClientSetRequest -cACTION_MONITOR_STEERING_CLIENT_SET_RESPONSE: +cACTION_MONITOR_STEERING_CLIENT_SET_RESPONSE: _type: class params: sSteeringClientSetResponse - + cACTION_MONITOR_STEERING_EVENT_CLIENT_ACTIVITY_NOTIFICATION: _type: class params: sSteeringEvActivity @@ -231,4 +231,3 @@ cACTION_MONITOR_CHANNEL_SCAN_ABORT_NOTIFICATION: cACTION_MONITOR_CHANNEL_SCAN_FINISHED_NOTIFICATION: _type: class - diff --git a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_platform.yaml b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_platform.yaml index 1714cd2df6..b45ffa1bc3 100755 --- a/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_platform.yaml +++ b/common/beerocks/tlvf/yaml/beerocks/tlvf/beerocks_message_platform.yaml @@ -6,7 +6,7 @@ _multi_class: True _multi_class_auto_insert: action_op: _type: eActionOp_PLATFORM - _value_const: [_auto_value_by_name, 1] + _value_const: [_auto_value_by_name, 1] _class_const: True ################################################# @@ -19,72 +19,72 @@ cACTION_PLATFORM_SON_SLAVE_BACKHAUL_CONNECTION_COMPLETE_NOTIFICATION: cACTION_PLATFORM_SON_SLAVE_REGISTER_REQUEST: _type: class iface_name: - _type: char - _length: [ "beerocks::message::IFACE_NAME_LENGTH" ] + _type: char + _length: ["beerocks::message::IFACE_NAME_LENGTH"] cACTION_PLATFORM_SON_SLAVE_REGISTER_RESPONSE: _type: class - platform_settings: sPlatformSettings - wlan_settings: sWlanSettings + platform_settings: sPlatformSettings + wlan_settings: sWlanSettings valid: _type: uint32_t _comment: #Marks whether the settings are valid cACTION_PLATFORM_ARP_MONITOR_NOTIFICATION: _type: class - params: sArpMonitorData + params: sArpMonitorData cACTION_PLATFORM_WLAN_PARAMS_CHANGED_NOTIFICATION: _type: class - wlan_settings: sWlanSettings + wlan_settings: sWlanSettings cACTION_PLATFORM_DHCP_MONITOR_NOTIFICATION: _type: class dhcp_op: eDHCPOp - op: uint32_t - mac: sMacAddr - ipv4: beerocks::net::sIpv4Addr - hostname: - _type: char - _length: [ "beerocks::message::NODE_NAME_LENGTH" ] + op: uint32_t + mac: sMacAddr + ipv4: beerocks::net::sIpv4Addr + hostname: + _type: char + _length: ["beerocks::message::NODE_NAME_LENGTH"] cACTION_PLATFORM_CHANGE_MODULE_LOGGING_LEVEL: _type: class - params: sLoggingLevelChange + params: sLoggingLevelChange cACTION_PLATFORM_ARP_QUERY_REQUEST: _type: class - params: sArpQuery + params: sArpQuery cACTION_PLATFORM_ARP_QUERY_RESPONSE: _type: class - params: sArpMonitorData + params: sArpMonitorData cACTION_PLATFORM_ONBOARD_QUERY_REQUEST: _type: class cACTION_PLATFORM_ONBOARD_QUERY_RESPONSE: _type: class - params: sOnboarding + params: sOnboarding cACTION_PLATFORM_ONBOARD_SET_REQUEST: _type: class - params: sOnboarding + params: sOnboarding cACTION_PLATFORM_WPS_ONBOARDING_REQUEST: _type: class - iface_name: - _type: char - _length: [ "beerocks::message::IFACE_NAME_LENGTH" ] + iface_name: + _type: char + _length: ["beerocks::message::IFACE_NAME_LENGTH"] cACTION_PLATFORM_WIFI_CREDENTIALS_GET_REQUEST: _type: class - vap_id: uint8_t + vap_id: uint8_t cACTION_PLATFORM_WIFI_CREDENTIALS_GET_RESPONSE: _type: class - front_params: sWifiCredentials - back_params: sWifiCredentials + front_params: sWifiCredentials + back_params: sWifiCredentials result: _type: uint32_t _comment: # 0 - Failure, 1 - Success @@ -94,7 +94,7 @@ cACTION_PLATFORM_ADMIN_CREDENTIALS_GET_REQUEST: cACTION_PLATFORM_ADMIN_CREDENTIALS_GET_RESPONSE: _type: class - params: sAdminCredentials + params: sAdminCredentials result: _type: uint32_t _comment: # 0 - Failure, 1 - Success @@ -104,7 +104,7 @@ cACTION_PLATFORM_DEVICE_INFO_GET_REQUEST: cACTION_PLATFORM_DEVICE_INFO_GET_RESPONSE: _type: class - params: sDeviceInfo + params: sDeviceInfo result: _type: uint32_t _comment: # 0 - Failure, 1 - Success @@ -114,31 +114,31 @@ cACTION_PLATFORM_LOCAL_MASTER_GET_REQUEST: cACTION_PLATFORM_LOCAL_MASTER_GET_RESPONSE: _type: class - local_master: uint8_t + local_master: uint8_t cACTION_PLATFORM_VERSION_MISMATCH_NOTIFICATION: _type: class - versions: sVersions + versions: sVersions cACTION_PLATFORM_MASTER_SLAVE_VERSIONS_NOTIFICATION: _type: class - versions: sVersions + versions: sVersions cACTION_PLATFORM_GET_MASTER_SLAVE_VERSIONS_REQUEST: _type: class cACTION_PLATFORM_GET_MASTER_SLAVE_VERSIONS_RESPONSE: _type: class - versions: sVersions + versions: sVersions result: _type: uint32_t _comment: # 0 - Failure, 1 - Success cACTION_PLATFORM_ERROR_NOTIFICATION: _type: class - code: uint32_t - data: - _type: char - _length: [ 256 ] + code: uint32_t + data: + _type: char + _length: [256] _comment: # Must match BPL_ERROR_STRING_LEN From 7af6b78f570fa596e1ea15db3927eaa1a69940e3 Mon Sep 17 00:00:00 2001 From: Vladyslav Tupikin Date: Thu, 11 Jun 2020 13:50:14 +0300 Subject: [PATCH 02/28] documentation: agent: Add UML diaram for Backhaul STA steering According to the test plan and source code create the UML diagram which describes data flow and methods for Backhaul STA steering. Signed-off-by: Vladyslav Tupikin --- .../plantuml/agent/flows/bh_sta_steering.png | Bin 0 -> 44889 bytes .../plantuml/agent/flows/bh_sta_steering.puml | 19 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 documentation/images/plantuml/agent/flows/bh_sta_steering.png create mode 100644 documentation/images/plantuml/agent/flows/bh_sta_steering.puml diff --git a/documentation/images/plantuml/agent/flows/bh_sta_steering.png b/documentation/images/plantuml/agent/flows/bh_sta_steering.png new file mode 100644 index 0000000000000000000000000000000000000000..a4b9f7e837851f718aa571fa42c4d4179207f722 GIT binary patch literal 44889 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: dev_reset_default +->controller: Prepare setup( execute 4.1.2 test) +controller->backhaul_manager: send_cmdu(Backhaul Steering Request with correct data) +backhaul_manager->backhaul_manager: handle_1905_msg(\n Backhaul Steering Request message,\n Backhaul Steering Request TLV(0x9E)) +backhaul_manager->controller: send_cmdu(ACK) +backhaul_manager->backhaul_manager: sta_wlan_hal->connect(bssid,channel) +backhaul_manager->wpa_supplicant: NETWORK_ENABLE +wpa_supplicant->ctt_agent_2: Association Request +ctt_agent_2->wpa_supplicant: Association Response +wpa_supplicant->backhaul_manager: ENABLED +backhaul_manager->controller: send_cmdu(Backhaul Steering Response message) +controller->controller: handle_1905_msg(Backhaul Steering Response message) +controller->backhaul_manager: send_cmdu(Backhaul Steering Request with bogus channel number) +backhaul_manager->backhaul_manager: handle_1905_msg(\n Backhaul Steering Request message,\n Backhaul Steering Request TLV(0x9E)) +backhaul_manager->controller: send_cmdu(ACK) +backhaul_manager->controller: send_cmdu(Backhaul Steering Response message) +controller->controller: handle_1905_msg(Backhaul Steering Response message) +@enduml From 59de4622a048a5b93c3477d42da79eb62527fb2c Mon Sep 17 00:00:00 2001 From: Anton Bilohai Date: Tue, 2 Jun 2020 11:20:52 +0300 Subject: [PATCH 03/28] tests: add device to boardfarm config Add "prplWRT" device "rax40-1" to boardfarm config. In order to this config to work, you have to: 1. Create docker bridge network with name "prplMesh-net-rax40-1". `docker network create --driver=bridge prplMesh-net-rax40-1` 2. Include interface connected to the board in docker network. `ip link set $RAX40_IFACE master $DOCKER_BRIDGE` 3. Config relies on RAX40 consoles to be at "/dev/ttyUSB0". You may have to adjust this path to fit your system. Those steps are required, as regular user is not permitted to attach interfaces to the bridge. Signed-off-by: Anton Bilohai --- .../boardfarm_prplmesh/prplmesh_config.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/prplmesh_config.json b/tests/boardfarm_plugins/boardfarm_prplmesh/prplmesh_config.json index b8114775c1..e16a4b5bf3 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/prplmesh_config.json +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/prplmesh_config.json @@ -16,5 +16,22 @@ "conn_cmd": "" } ] + }, + "netgear-rax40-1": { + "name": "agent-rax40", + "board_type": "prplWRT", + "role": "agent", + "docker_network": "prplMesh-net-rax40-1", + "connection_type": "local_serial", + "conn_cmd": "cu -s 115200 -l /dev/ttyUSB0", + "devices": [ + { + "name": "controller", + "type": "prplmesh_docker", + "role": "controller", + "docker_network": "prplMesh-net-rax40-1", + "conn_cmd": "" + } + ] } } From 41d2a8055b01dc218766c3c04f7fd01aa066decf Mon Sep 17 00:00:00 2001 From: Anton Bilohai Date: Tue, 2 Jun 2020 11:48:54 +0300 Subject: [PATCH 04/28] tests: boardfarm: add prplWRT device Add prplWRT class which represents device running prplWRT with prplMesh installed. This class has required methods to init the board and execute InitialApConfig test on board. Signed-off-by: Anton Bilohai --- .../devices/prplmesh_prplwrt.py | 90 ++++++++++++++++--- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py index 877373aadf..e159ea089d 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py @@ -6,19 +6,28 @@ ############################################################### import boardfarm -from boardfarm.devices import OpenWrtRouter -from environment import ALEntityPrplWrt, _get_bridge_interface +import json +import os +import pexpect +import subprocess +import sys + from .prplmesh_base import PrplMeshBase +from boardfarm.devices import connection_decider +from boardfarm.devices.openwrt_router import OpenWrtRouter +from environment import ALEntityPrplWrt, _get_bridge_interface +from ipaddress import IPv4Network, IPv4Address from sniffer import Sniffer class PrplMeshPrplWRT(OpenWrtRouter, PrplMeshBase): """prplWRT burned device with prplMesh installed.""" - model = "prplWRT" + model = ("prplWRT") prompt = ['root\\@OpenWrt:/#', '/#', '@OpenWrt:/#'] wan_iface = "eth1" uboot_eth = "eth0_1" + linesep = "\r" agent_entity = None controller_entity = None @@ -27,17 +36,41 @@ def __init__(self, *args, **kwargs): self.args = args self.kwargs = kwargs config = kwargs.get("config", kwargs) + + self.unique_id = os.getenv("SUDO_USER", os.getenv("USER", "")) self.docker_network = config.get("docker_network", "prplMesh-net-{}".format(self.unique_id)) self.role = config.get("role", "agent") - if self.role == "controller": - self.controller_entity = ALEntityPrplWrt(self.name, is_controller=True) - else: - self.agent_entity = ALEntityPrplWrt(self.name, is_controller=False) + self.connection_type = config.get("connection_type", None) + self.conn_cmd = config.get("conn_cmd", None) + + self.connection = connection_decider.connection(device=self, + conn_type=kwargs['connection_type'], + **kwargs) + self.connection.connect() + self.name = "-".join((config.get("name", "rax40"), self.unique_id)) + self.consoles = [self] + self.logfile_read = sys.stdout + + self.wan_network = self.get_docker_subnet(self.docker_network) + self.set_iface_to_bridge(self.wan_iface) + self.set_iface_ip("br-lan", self.wan_network[+245], self.wan_network.prefixlen) self.wired_sniffer = Sniffer(_get_bridge_interface(self.docker_network), boardfarm.config.output_dir) - self.check_status() + if self.role == "controller": + self.controller_entity = ALEntityPrplWrt(self, is_controller=True) + else: + self.agent_entity = ALEntityPrplWrt(self, is_controller=False) + self.prplMesh_start_agent() + + def _prplMesh_exec(self, mode: str): + """Send line to prplmesh initd script.""" + self.sendline("/etc/init.d/prplmesh {}".format(mode)) + + def kill_console_at_exit(self): + """Kill connections on device termination.""" + self.connection.close() def check_status(self) -> bool: """Check status of device, return bool to indicate state. @@ -45,11 +78,15 @@ def check_status(self) -> bool: It is used by boardfarm to indicate that spawned device instance is ready for test and also after test - to insure that device still operational. """ + return True + + def prplMesh_check_state(self) -> bool: + """ Check prplMesh status. Return True if operational.""" self.sendline("/etc/init.d/prplmesh status") match = self.expect( - ["OPERATIONAL", self.device.pexpect.EOF, self.device.pexpect.TIMEOUT], + ["operational", "FAIL", pexpect.EOF, pexpect.TIMEOUT], timeout=10) - if match == 1: + if match == 0: return True else: return False @@ -67,3 +104,36 @@ def touch(self): Purpose is to keep consoles active, so they don't disconnect for long running activities. """ pass + + def get_docker_subnet(self, docker_network: str) -> IPv4Network: + """Get subnet used by docker network.""" + docker_network_inspect_cmd = ('docker', 'network', 'inspect', docker_network) + inspect_raw = subprocess.run(docker_network_inspect_cmd, stdout=subprocess.PIPE) + if inspect_raw.returncode != 0: + # Assume network doesn't exist yet. Create it. + # Raise an exception if it fails (check=True). + subprocess.run(('docker', 'network', 'create', docker_network), check=True, + stdout=subprocess.DEVNULL) + # Inspect again, now raise if it fails (check=True). + inspect_raw = subprocess.run(docker_network_inspect_cmd, check=True, + stdout=subprocess.PIPE) + inspect_json = json.loads(inspect_raw.stdout) + + return IPv4Network(inspect_json[0]["IPAM"]["Config"][0]["Subnet"]) + + def set_iface_to_bridge(self, iface: str) -> bool: + """Add specified interface to the specified bridge.""" + ip_command = ("ip link set {} master br-lan".format(iface)) + self.sendline(ip_command) + self.expect(self.prompt, timeout=10) + + def set_iface_ip(self, iface: str, ip: IPv4Address, prefixlen :int) -> bool: + """Set interface IPv4 address.""" + self.sendline("ip a add {}/{} dev {}".format(ip, prefixlen, iface)) + self.expect(self.prompt, timeout=10) + + def prplMesh_start_agent(self) -> bool: + """Start prplMesh in certification_mode agent. Return true if done.""" + self._prplMesh_exec("certification_mode agent") + self.expect_exact("CAC timer expired", timeout=120) + self.expect_exact("device br-lan entered promiscuous mode", timeout=40) From 827a7457c0b766381bae73e03542bac40b4d374c Mon Sep 17 00:00:00 2001 From: Anton Bilohai Date: Tue, 2 Jun 2020 12:05:03 +0300 Subject: [PATCH 05/28] tests: environment.py: complete prplWRT entities prplWRT entities are not debugged, as there was no way to test them at the moment of commit. `_device_wait_for_log` method: count in start_line given to it, format return as it's expected by callers. `ALEntityPrplWrt` constructor: get main bridge name from config. Parse output of console in Python to be less dependent on board. `RadioHostapd` constructor: remove usage of `ip -o` as `-o` option is bugged on RAX40 and mutes output of `ip` command. Signed-off-by: Anton Bilohai --- tests/environment.py | 97 ++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/tests/environment.py b/tests/environment.py index 155436df41..08c31f9db8 100644 --- a/tests/environment.py +++ b/tests/environment.py @@ -225,16 +225,23 @@ def logfilename(program): def _device_wait_for_log(device: None, log_path: str, regex: str, - start_line: int, timeout: int) -> bool: - """Waits for log mathing regex expression to show up.""" - device.sendline("tail -n10 -f {}".format(log_path)) - match = device.expect( - pattern=[regex, device.pexpect.EOF, device.pexpect.TIMEOUT], - timeout=timeout) - if match == 1: - return True + timeout: int, start_line: int = 0): + """Waits for log matching regex expression to show up.""" + device.sendline("tail -f -n +{:d} {}".format(start_line + 1, log_path)) + device.expect(regex, timeout=timeout) + match = device.match.group(0) + # Send Ctrl-C to interrupt tail -f + device.send('\003') + device.expect(device.prompt) + if match: + device.sendline("tail -n +{:d} {} | grep -n \"{}\"".format(start_line, log_path, match)) + # Typical output of grep -n from log: "line_num:severity" + # this regex has to capture just number of line in log + device.expect(r"(?P[0-9]+):[A-Z]+\s[0-9]", timeout=timeout) + matched_line = int(device.match.group('line_number')) + start_line + return (True, matched_line, match) else: - return False + return (False, start_line, None) class ALEntityDocker(ALEntity): @@ -254,7 +261,8 @@ def __init__(self, name: str, is_controller: bool = False): config_file_name = 'beerocks_agent.conf' with open(os.path.join(installdir, 'config', config_file_name)) as config_file: ucc_port = \ - re.search(r'ucc_listener_port=(?P[0-9]+)', config_file.read()).group('port') + re.search(r'ucc_listener_port=(?P[0-9]+)', + config_file.read()).group('port') # On WSL, connect to the locally exposed container port if on_wsl: @@ -265,8 +273,8 @@ def __init__(self, name: str, is_controller: bool = False): else: device_ip_output = self.command( 'ip', '-f', 'inet', 'addr', 'show', self.bridge_name) - device_ip = re.search( - r'inet (?P[0-9.]+)', device_ip_output.decode('utf-8')).group('ip') + device_ip = re.search(r'inet (?P[0-9.]+)', + device_ip_output.decode('utf-8')).group('ip') ucc_socket = UCCSocket(device_ip, ucc_port) mac = ucc_socket.dev_get_parameter('ALid') @@ -293,7 +301,8 @@ class RadioDocker(Radio): def __init__(self, agent: ALEntityDocker, iface_name: str): self.iface_name = iface_name ip_output = agent.command("ip", "-o", "link", "list", "dev", self.iface_name).decode() - mac = re.search(r"link/ether (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})", ip_output).group(1) + mac = re.search(r"link/ether (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})", + ip_output).group(1) super().__init__(agent, mac) # Since dummy bwl always uses the first VAP, in practice we always have a single VAP with @@ -404,16 +413,16 @@ def launch_environment_docker(unique_id: str, skip_init: bool = False, tag: str class ALEntityPrplWrt(ALEntity): """Abstraction of ALEntity in real device.""" - def __init__(self, name: str, device: None, is_controller: bool = False): + def __init__(self, device: None, is_controller: bool = False): self.device = device - self.name = name - self.bridge_name = 'br-lan' + self.name = device.name if is_controller: self.config_file_name = '/opt/prplmesh/config/beerocks_controller.conf' else: self.config_file_name = '/opt/prplmesh/config/beerocks_agent.conf' +<<<<<<< HEAD ucc_port = self.command(("grep \"ucc_listener_port\" {} " "| cut -d'=' -f2 | cut -d\" \" -f 1").format(self.config_file_name)) @@ -425,45 +434,71 @@ def __init__(self, name: str, device: None, is_controller: bool = False): "grep log_files_path {} | cut -d=\'=\' -f2".format(self.config_file_name)) ucc_socket = UCCSocket(device_ip, ucc_port) +======= + ucc_port_raw = self.command("grep \"ucc_listener_port\" {}".format(self.config_file_name)) + ucc_port = int(re.search(r'ucc_listener_port=(?P[0-9]+)', + ucc_port_raw).group('port')) + bridge_name_raw = self.command("grep \"bridge_iface\" {}".format(self.config_file_name)) + self.bridge_name = re.search(r'bridge_iface=(?P.+)\r\n', + bridge_name_raw).group('bridge') + + # Multiple IPs may be set to same interface. We are interested in the last one, which is set + # by test during board init procedure. + device_ip_raw = self.command( + "ip -family inet addr show {} | tail -n 2".format(self.bridge_name)) + self.device_ip = re.search(r'inet (?P[0-9.]+)', + device_ip_raw).group('ip') + + log_folder_raw = self.command( + "grep log_files_path {}".format(self.config_file_name)) + self.log_folder = re.search(r'log_files_path=(?P[a-zA-Z0-9_\/]+)', + log_folder_raw).group('log_path') + + ucc_socket = UCCSocket(self.device_ip, int(ucc_port)) +>>>>>>> tests: environment.py: complete prplWRT entities mac = ucc_socket.dev_get_parameter('ALid') super().__init__(mac, ucc_socket, installdir, is_controller) # We always have two radios, wlan0 and wlan2 - RadioHostapd(self, "wlan0", device=self) - RadioHostapd(self, "wlan2", device=self) + RadioHostapd(self, "wlan0") + RadioHostapd(self, "wlan2") def command(self, *command: str) -> bytes: """Execute `command` in device and return its output.""" - self.device.sendline(command) - return self.device.read() + self.device.sendline(" ".join(command)) + self.device.expect(self.device.prompt, timeout=10) + return self.device.before def wait_for_log(self, regex: str, start_line: int, timeout: float) -> bool: """Poll the entity's logfile until it contains "regex" or times out.""" program = "controller" if self.is_controller else "agent" + # Multiply timeout by 100, as test sets it in float. return _device_wait_for_log(self.device, "{}/beerocks_{}.log".format(self.log_folder, program), - regex, start_line, timeout) + regex, start_line, timeout*100) class RadioHostapd(Radio): """Abstraction of real Radio in prplWRT device.""" - def __init__(self, agent: ALEntityPrplWrt, bssid: str, device: None): - self.iface_name = bssid - ip_output = agent.command("ip -o link list dev {}".format(self.iface_name)) - mac = re.search(r"link/ether (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})", ip_output).group(1) - self.log_folder = self.command( - "grep log_files_path {} | cut -d=\'=\' -f2".format(self.config_file_name)) + def __init__(self, agent: ALEntityPrplWrt, iface_name: str): + self.iface_name = iface_name + self.agent = agent + ip_raw = self.agent.command("ip link list dev {}".format(self.iface_name)) + mac = re.search(r"link/ether (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})", + ip_raw).group(1) + self.log_folder = agent.log_folder super().__init__(agent, mac) VirtualAPHostapd(self, mac) VirtualAPHostapd(self, mac) - def wait_for_log(self, regex: str, start_line: int, timeout: float) -> bool: + def wait_for_log(self, regex: str, start_line: int, timeout: float): ''' Poll the Radio's logfile until it match regular expression ''' - return _device_wait_for_log(self.device, "{}/beerocks_agent_{}.log".format( - self.log_folder, self.iface_name), regex, start_line, timeout) + # Multiply timeout by 100, as test sets it in float. + return _device_wait_for_log(self.agent.device, "{}/beerocks_agent_{}.log".format( + self.log_folder, self.iface_name), regex, timeout*100, start_line) class VirtualAPHostapd(VirtualAP): @@ -475,7 +510,9 @@ def __init__(self, radio: RadioHostapd, bssid: str): def associate(self, sta: Station) -> bool: ''' Associate "sta" with this VAP ''' # TODO: complete this stub + return True def disassociate(self, sta: Station) -> bool: ''' Disassociate "sta" from this VAP.''' # TODO: complete this stub + return True From f985a5239e96b09f22f22eaff405a995f220861e Mon Sep 17 00:00:00 2001 From: Anton Bilohai Date: Tue, 2 Jun 2020 14:09:05 +0300 Subject: [PATCH 06/28] tests: boardfarm: InitialApConfig - too greedy regex search Currently, test is trying to match r".* Controller configuration \(WSC M2 Encrypted Settings\)") which is greedy and captures all chars before key message. Chars captured by `.*` are not important for us. Get rid of `.*` in the beginning of regex. Reorder expected logs to match them in right order. Signed-off-by: Anton Bilohai --- .../tests/initial_ap_config.py | 16 ++++++++++------ .../tests/prplmesh_base_test.py | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py index d8432cf1ba..0567c10f20 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py @@ -14,6 +14,10 @@ def runTest(self): if dev.agent_entity: dev.wired_sniffer.start(self.__class__.__name__ + "-" + dev.name) + self.check_log(dev.agent_entity.radios[0], + r"Controller configuration \(WSC M2 Encrypted Settings\)") + self.check_log(dev.agent_entity.radios[1], + r"Controller configuration \(WSC M2 Encrypted Settings\)") self.check_log(dev.agent_entity.radios[0], r"WSC Global authentication success") self.check_log(dev.agent_entity.radios[1], @@ -22,13 +26,13 @@ def runTest(self): r"KWA \(Key Wrap Auth\) success") self.check_log(dev.agent_entity.radios[1], r"KWA \(Key Wrap Auth\) success") - self.check_log(dev.agent_entity.radios[0], - r".* Controller configuration \(WSC M2 Encrypted Settings\)") - self.check_log(dev.agent_entity.radios[1], - r".* Controller configuration \(WSC M2 Encrypted Settings\)") - - dev.wired_sniffer.stop() @classmethod def teardown_class(cls): """Teardown method, optional for boardfarm tests.""" + test = cls.test_obj + for dev in test.dev: + if dev.agent_entity: + print("Sniffer - stop") + dev.agent_entity.device.send('\003') + dev.wired_sniffer.stop() diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/prplmesh_base_test.py b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/prplmesh_base_test.py index 9a9f32ef9f..e981fb65db 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/prplmesh_base_test.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/prplmesh_base_test.py @@ -16,7 +16,7 @@ class PrplMeshBaseTest(bft_base_test.BftBaseTest): """ def check_log(self, entity_or_radio: Union[env.ALEntity, env.Radio], regex: str, - start_line: int = 0, timeout: float = 0.3) -> bool: + start_line: int = 0, timeout: float = 0.6) -> bool: result, line, match = entity_or_radio.wait_for_log(regex, start_line, timeout) if not result: raise Exception From a714d81607fb78b141fb58e014370f7ccb2db612 Mon Sep 17 00:00:00 2001 From: Anton Bilohai Date: Fri, 5 Jun 2020 23:16:44 +0300 Subject: [PATCH 07/28] tests: boardfarm: move to ssh as primary connection Currently, boardfarm tests are using UART (serial) connection as main channel to interact with the board. Sadly, but UART on RAX40 board frequently suffers from tty overruns. Hence, tests are frequently failed due to corrupted input line. Moving to ssh as primary channel resolves issue above. It's faster, so chance of meeting input overruns is significantly low. But, via ssh we are unable to see logs from the Intel WiFi driver. Logs from the driver are used to detect when device has prplMesh in operational state. As those logs are not longer shown, we have to come up with other way to check when prplMesh is operational. Add fallback mechanism: if IP address of DUTs wan is not set - retrieve IP subnet from docker network of set up and choose .245 address. This configuration happens over UART. Move from UART to SSH as primary communication channel. Add prplmesh_status_check method to tests, to check if prplMesh on device is operational. Signed-off-by: Anton Bilohai --- .../devices/prplmesh_docker.py | 7 ++ .../devices/prplmesh_prplwrt.py | 99 +++++++++++++------ .../boardfarm_prplmesh/prplmesh_config.json | 1 - .../tests/initial_ap_config.py | 5 +- .../tests/prplmesh_base_test.py | 9 ++ tests/environment.py | 25 +---- 6 files changed, 91 insertions(+), 55 deletions(-) diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_docker.py b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_docker.py index aa41f53691..faad645446 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_docker.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_docker.py @@ -83,3 +83,10 @@ def isalive(self): States that device is operational and its consoles are accessible. """ return True + + def prprlmesh_status_check(self) -> bool: + """Check prplMesh status by executing status command to initd service. + Return True if operational. + """ + self.check_status() + return True diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py index e159ea089d..e095e9c8fe 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py @@ -9,8 +9,10 @@ import json import os import pexpect +import signal import subprocess import sys +import time from .prplmesh_base import PrplMeshBase from boardfarm.devices import connection_decider @@ -23,8 +25,8 @@ class PrplMeshPrplWRT(OpenWrtRouter, PrplMeshBase): """prplWRT burned device with prplMesh installed.""" - model = ("prplWRT") - prompt = ['root\\@OpenWrt:/#', '/#', '@OpenWrt:/#'] + model = "prplWRT" + prompt = ['root\\@OpenWrt:/#', '/#', '@OpenWrt:/#', "@OpenWrt:~#"] wan_iface = "eth1" uboot_eth = "eth0_1" linesep = "\r" @@ -43,34 +45,67 @@ def __init__(self, *args, **kwargs): self.role = config.get("role", "agent") self.connection_type = config.get("connection_type", None) self.conn_cmd = config.get("conn_cmd", None) + self.wan_ip = config.get("wan_ip", None) + self.username = config.get("username", "root") + + self.name = "-".join((config.get("name", "netgear-rax40"), self.unique_id)) + + # If no WAN IP is set in config file retrieve IP from docker network set in config + # X.X.X.245 IP will be selected from docker network + if not self.wan_ip: + self.connection = connection_decider.connection(device=self, + conn_type="local_serial", + **kwargs) + self.connection.connect() + self.consoles = [self] + self.logfile_read = sys.stdout + self.wan_network = self.get_docker_subnet() + self.wan_ip = self.wan_network[+245] + self.set_iface_ip("br-lan", self.wan_ip, self.wan_network.prefixlen) + self.connection.close() + self.kill(signal.SIGTERM) + # Removal of PID is required by pexpect in order to spawn a new process + # serial connection should be terminated by 2 commands above + self.pid = None + self.wired_sniffer = Sniffer(_get_bridge_interface(self.docker_network), + boardfarm.config.output_dir) self.connection = connection_decider.connection(device=self, - conn_type=kwargs['connection_type'], - **kwargs) + conn_type="ssh", + conn_cmd="ssh {}@{}".format( + self.username, self.wan_ip)) self.connection.connect() - - self.name = "-".join((config.get("name", "rax40"), self.unique_id)) + # Append active connection to the general array for logging self.consoles = [self] + # Point what to log as data read from child process of pexpect + # Result: boardfarm will log communication in separate file self.logfile_read = sys.stdout + self.add_iface_to_bridge(self.wan_iface, "br-lan") - self.wan_network = self.get_docker_subnet(self.docker_network) - self.set_iface_to_bridge(self.wan_iface) - self.set_iface_ip("br-lan", self.wan_network[+245], self.wan_network.prefixlen) - self.wired_sniffer = Sniffer(_get_bridge_interface(self.docker_network), - boardfarm.config.output_dir) if self.role == "controller": self.controller_entity = ALEntityPrplWrt(self, is_controller=True) else: self.agent_entity = ALEntityPrplWrt(self, is_controller=False) - self.prplMesh_start_agent() + self.prplmesh_start_agent() def _prplMesh_exec(self, mode: str): """Send line to prplmesh initd script.""" self.sendline("/etc/init.d/prplmesh {}".format(mode)) - def kill_console_at_exit(self): - """Kill connections on device termination.""" - self.connection.close() + def _prplmesh_status_poll(self, timeout: int = 120) -> bool: + """Poll prplMesh status for timeout time. + + Main agent and wlan0, wlan2 radios should be operational. + Return True if status is operational and timeout not reached. + """ + deadline = time.monotonic() + timeout + while time.monotonic() < deadline: + if self.prplMesh_check_state(): + break + time.sleep(5) + else: + return False + return True def check_status(self) -> bool: """Check status of device, return bool to indicate state. @@ -83,10 +118,12 @@ def check_status(self) -> bool: def prplMesh_check_state(self) -> bool: """ Check prplMesh status. Return True if operational.""" self.sendline("/etc/init.d/prplmesh status") - match = self.expect( - ["operational", "FAIL", pexpect.EOF, pexpect.TIMEOUT], - timeout=10) - if match == 0: + self.expect( + ["(?POK) Main agent.+" + "(?POK) wlan0.+" + "(?POK) wlan2", pexpect.TIMEOUT], + timeout=5) + if self.match is not pexpect.TIMEOUT: return True else: return False @@ -105,14 +142,14 @@ def touch(self): """ pass - def get_docker_subnet(self, docker_network: str) -> IPv4Network: + def get_docker_subnet(self) -> IPv4Network: """Get subnet used by docker network.""" - docker_network_inspect_cmd = ('docker', 'network', 'inspect', docker_network) + docker_network_inspect_cmd = ('docker', 'network', 'inspect', self.docker_network) inspect_raw = subprocess.run(docker_network_inspect_cmd, stdout=subprocess.PIPE) if inspect_raw.returncode != 0: # Assume network doesn't exist yet. Create it. # Raise an exception if it fails (check=True). - subprocess.run(('docker', 'network', 'create', docker_network), check=True, + subprocess.run(('docker', 'network', 'create', self.docker_network), check=True, stdout=subprocess.DEVNULL) # Inspect again, now raise if it fails (check=True). inspect_raw = subprocess.run(docker_network_inspect_cmd, check=True, @@ -121,19 +158,25 @@ def get_docker_subnet(self, docker_network: str) -> IPv4Network: return IPv4Network(inspect_json[0]["IPAM"]["Config"][0]["Subnet"]) - def set_iface_to_bridge(self, iface: str) -> bool: + def add_iface_to_bridge(self, iface: str, bridge: str) -> bool: """Add specified interface to the specified bridge.""" - ip_command = ("ip link set {} master br-lan".format(iface)) + ip_command = ("ip link set {} master {}".format(iface, bridge)) self.sendline(ip_command) self.expect(self.prompt, timeout=10) - def set_iface_ip(self, iface: str, ip: IPv4Address, prefixlen :int) -> bool: + def set_iface_ip(self, iface: str, ip: IPv4Address, prefixlen: int) -> bool: """Set interface IPv4 address.""" self.sendline("ip a add {}/{} dev {}".format(ip, prefixlen, iface)) self.expect(self.prompt, timeout=10) - def prplMesh_start_agent(self) -> bool: + def prplmesh_start_agent(self) -> bool: """Start prplMesh in certification_mode agent. Return true if done.""" self._prplMesh_exec("certification_mode agent") - self.expect_exact("CAC timer expired", timeout=120) - self.expect_exact("device br-lan entered promiscuous mode", timeout=40) + self.expect(self.prompt) + return True + + def prprlmesh_status_check(self) -> bool: + """Check prplMesh status by executing status command to initd service. + Return True if operational. + """ + return self._prplmesh_status_poll() diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/prplmesh_config.json b/tests/boardfarm_plugins/boardfarm_prplmesh/prplmesh_config.json index e16a4b5bf3..7a55f651c2 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/prplmesh_config.json +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/prplmesh_config.json @@ -22,7 +22,6 @@ "board_type": "prplWRT", "role": "agent", "docker_network": "prplMesh-net-rax40-1", - "connection_type": "local_serial", "conn_cmd": "cu -s 115200 -l /dev/ttyUSB0", "devices": [ { diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py index 0567c10f20..d80d0ce8c2 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py @@ -14,10 +14,11 @@ def runTest(self): if dev.agent_entity: dev.wired_sniffer.start(self.__class__.__name__ + "-" + dev.name) + self.prplmesh_status_check(dev.agent_entity.device) self.check_log(dev.agent_entity.radios[0], - r"Controller configuration \(WSC M2 Encrypted Settings\)") + r"\(WSC M2 Encrypted Settings\)") self.check_log(dev.agent_entity.radios[1], - r"Controller configuration \(WSC M2 Encrypted Settings\)") + r"\(WSC M2 Encrypted Settings\)") self.check_log(dev.agent_entity.radios[0], r"WSC Global authentication success") self.check_log(dev.agent_entity.radios[1], diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/prplmesh_base_test.py b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/prplmesh_base_test.py index e981fb65db..5e03247c77 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/prplmesh_base_test.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/prplmesh_base_test.py @@ -21,3 +21,12 @@ def check_log(self, entity_or_radio: Union[env.ALEntity, env.Radio], regex: str, if not result: raise Exception return result, line, match + + def prplmesh_status_check(self, entity_or_radio: Union[env.ALEntity, env.Radio]) -> bool: + """Check prplMesh status by executing status command to initd service. + Return True if operational. + """ + result = entity_or_radio.prprlmesh_status_check() + if not result: + raise Exception + return result diff --git a/tests/environment.py b/tests/environment.py index 08c31f9db8..42e75cc07c 100644 --- a/tests/environment.py +++ b/tests/environment.py @@ -422,40 +422,17 @@ def __init__(self, device: None, is_controller: bool = False): else: self.config_file_name = '/opt/prplmesh/config/beerocks_agent.conf' -<<<<<<< HEAD - ucc_port = self.command(("grep \"ucc_listener_port\" {} " - "| cut -d'=' -f2 | cut -d\" \" -f 1").format(self.config_file_name)) - - device_ip_output = self.command( - "ip -f inet addr show {} | head -n 2".format(self.bridge_name)) - device_ip = re.search( - r'inet (?P[0-9.]+)', device_ip_output.decode('utf-8')).group('ip') - self.log_folder = self.command( - "grep log_files_path {} | cut -d=\'=\' -f2".format(self.config_file_name)) - - ucc_socket = UCCSocket(device_ip, ucc_port) -======= ucc_port_raw = self.command("grep \"ucc_listener_port\" {}".format(self.config_file_name)) ucc_port = int(re.search(r'ucc_listener_port=(?P[0-9]+)', ucc_port_raw).group('port')) bridge_name_raw = self.command("grep \"bridge_iface\" {}".format(self.config_file_name)) self.bridge_name = re.search(r'bridge_iface=(?P.+)\r\n', bridge_name_raw).group('bridge') - - # Multiple IPs may be set to same interface. We are interested in the last one, which is set - # by test during board init procedure. - device_ip_raw = self.command( - "ip -family inet addr show {} | tail -n 2".format(self.bridge_name)) - self.device_ip = re.search(r'inet (?P[0-9.]+)', - device_ip_raw).group('ip') - log_folder_raw = self.command( "grep log_files_path {}".format(self.config_file_name)) self.log_folder = re.search(r'log_files_path=(?P[a-zA-Z0-9_\/]+)', log_folder_raw).group('log_path') - - ucc_socket = UCCSocket(self.device_ip, int(ucc_port)) ->>>>>>> tests: environment.py: complete prplWRT entities + ucc_socket = UCCSocket(str(self.device.wan_ip), int(ucc_port)) mac = ucc_socket.dev_get_parameter('ALid') super().__init__(mac, ucc_socket, installdir, is_controller) From 9a855a82d7272ffd574eb74481921fc8cbc3cb66 Mon Sep 17 00:00:00 2001 From: Anton Bilohai Date: Wed, 10 Jun 2020 12:01:44 +0300 Subject: [PATCH 08/28] tests: boardfarm: docker devices support of InitialAPConfig teardown Teardown section of InitialAPConfig test introduced by port of this test to prplWRT devices is incompatible with dockerized devices. It uses `device.send` method which is not available for docker devices. Also, prplmesh_status_check method isn't working for docker devices due to missing link between AlEntityDocker and PrplMeshDocker device. Following EAFP strategy, surround sent of Ctrl+C in try-catch block. Add link between AlEntityDocker and PrplMeshDocker as it done for prplWRT device and restore prplmesh_status_check method functionality. Signed-off-by: Anton Bilohai --- .../devices/prplmesh_docker.py | 4 ++-- .../devices/prplmesh_prplwrt.py | 4 ++-- .../tests/initial_ap_config.py | 9 +++++++-- tests/environment.py | 18 +++++++++++++----- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_docker.py b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_docker.py index faad645446..d4f9870d3c 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_docker.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_docker.py @@ -51,14 +51,14 @@ def __init__(self, *args, **kwargs): self._run_shell_cmd(docker_cmd, docker_args) time.sleep(self.delay) - self.controller_entity = ALEntityDocker(self.name, is_controller=True) + self.controller_entity = ALEntityDocker(self.name, device=self, is_controller=True) else: # Spawn dockerized agent docker_args.append("start-agent") self._run_shell_cmd(docker_cmd, docker_args) time.sleep(self.delay) - self.agent_entity = ALEntityDocker(self.name, is_controller=False) + self.agent_entity = ALEntityDocker(self.name, device=self, is_controller=False) self.wired_sniffer = Sniffer(_get_bridge_interface(self.docker_network), boardfarm.config.output_dir) diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py index e095e9c8fe..b8e9120c6c 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/devices/prplmesh_prplwrt.py @@ -100,7 +100,7 @@ def _prplmesh_status_poll(self, timeout: int = 120) -> bool: """ deadline = time.monotonic() + timeout while time.monotonic() < deadline: - if self.prplMesh_check_state(): + if self.get_prplMesh_status(): break time.sleep(5) else: @@ -115,7 +115,7 @@ def check_status(self) -> bool: """ return True - def prplMesh_check_state(self) -> bool: + def get_prplMesh_status(self) -> bool: """ Check prplMesh status. Return True if operational.""" self.sendline("/etc/init.d/prplmesh status") self.expect( diff --git a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py index d80d0ce8c2..c959dadb21 100644 --- a/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py +++ b/tests/boardfarm_plugins/boardfarm_prplmesh/tests/initial_ap_config.py @@ -14,7 +14,7 @@ def runTest(self): if dev.agent_entity: dev.wired_sniffer.start(self.__class__.__name__ + "-" + dev.name) - self.prplmesh_status_check(dev.agent_entity.device) + self.prplmesh_status_check(dev.agent_entity) self.check_log(dev.agent_entity.radios[0], r"\(WSC M2 Encrypted Settings\)") self.check_log(dev.agent_entity.radios[1], @@ -35,5 +35,10 @@ def teardown_class(cls): for dev in test.dev: if dev.agent_entity: print("Sniffer - stop") - dev.agent_entity.device.send('\003') + # Send Ctrl+C to the device to terminate "tail -f" + # Which is used to read log from device. Required only for tests on HW + try: + dev.agent_entity.device.send('\003') + except AttributeError: + pass dev.wired_sniffer.stop() diff --git a/tests/environment.py b/tests/environment.py index 42e75cc07c..675397d33f 100644 --- a/tests/environment.py +++ b/tests/environment.py @@ -249,10 +249,13 @@ class ALEntityDocker(ALEntity): The entity is defined from the name of the container, the rest is derived from that. ''' - - def __init__(self, name: str, is_controller: bool = False): + # NOTE: name arg can be also extracted from the device class itself, but test_flows.py + # don't have it. We can remove this arg as soon, as we drop test_flows.py + def __init__(self, name: str, device: None = None, is_controller: bool = False): self.name = name self.bridge_name = 'br-lan' + if device: + self.device = device # First, get the UCC port from the config file if is_controller: @@ -294,10 +297,12 @@ def wait_for_log(self, regex: str, start_line: int, timeout: float) -> bool: program = "controller" if self.is_controller else "agent" return _docker_wait_for_log(self.name, [program], regex, start_line, timeout) + def prprlmesh_status_check(self): + return self.device.prprlmesh_status_check() + class RadioDocker(Radio): '''Docker implementation of a radio.''' - def __init__(self, agent: ALEntityDocker, iface_name: str): self.iface_name = iface_name ip_output = agent.command("ip", "-o", "link", "list", "dev", self.iface_name).decode() @@ -398,8 +403,8 @@ def launch_environment_docker(unique_id: str, skip_init: bool = False, tag: str wired_sniffer.stop() global controller, agents - controller = ALEntityDocker(gateway, True) - agents = (ALEntityDocker(repeater1), ALEntityDocker(repeater2)) + controller = ALEntityDocker(name=gateway, is_controller=True) + agents = (ALEntityDocker(name=repeater1), ALEntityDocker(name=repeater2)) debug('controller: {}'.format(controller.mac)) debug('agent1: {}'.format(agents[0].mac)) @@ -455,6 +460,9 @@ def wait_for_log(self, regex: str, start_line: int, timeout: float) -> bool: "{}/beerocks_{}.log".format(self.log_folder, program), regex, start_line, timeout*100) + def prprlmesh_status_check(self): + return self.device.prprlmesh_status_check() + class RadioHostapd(Radio): """Abstraction of real Radio in prplWRT device.""" From 89e1bce0120fb33d0f9a7946f256036e17315eaa Mon Sep 17 00:00:00 2001 From: Mario Maz Date: Mon, 15 Jun 2020 19:35:12 +0200 Subject: [PATCH 09/28] btl: add if_index to UDS header of received message Modify transport to include which interface the message was received on. Interface index will later be stored in topology database whenever a Topology Discovery message is received. Signed-off-by: Mario Maz --- common/beerocks/bcl/include/bcl/beerocks_message_structs.h | 1 + common/beerocks/btl/btl_local_bus.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/common/beerocks/bcl/include/bcl/beerocks_message_structs.h b/common/beerocks/bcl/include/bcl/beerocks_message_structs.h index 7533dfc8cf..119f5fe218 100644 --- a/common/beerocks/bcl/include/bcl/beerocks_message_structs.h +++ b/common/beerocks/bcl/include/bcl/beerocks_message_structs.h @@ -17,6 +17,7 @@ namespace beerocks { namespace message { typedef struct { + uint32_t if_index = 0; // index of the network interface the message was received on uint8_t dst_bridge_mac[net::MAC_ADDR_LEN] = {}; uint8_t src_bridge_mac[net::MAC_ADDR_LEN] = {}; uint16_t length = 0; diff --git a/common/beerocks/btl/btl_local_bus.cpp b/common/beerocks/btl/btl_local_bus.cpp index 0bd71b308c..3dea49233d 100644 --- a/common/beerocks/btl/btl_local_bus.cpp +++ b/common/beerocks/btl/btl_local_bus.cpp @@ -200,6 +200,7 @@ bool transport_socket_thread::handle_cmdu_message_bus() // fill UDS Header message::sUdsHeader *uds_header = (message::sUdsHeader *)rx_buffer; + uds_header->if_index = cmdu_rx_msg->metadata()->if_index; std::copy_n((uint8_t *)cmdu_rx_msg->metadata()->src, sizeof(mapf::CmduRxMessage::Metadata::src), uds_header->src_bridge_mac); std::copy_n((uint8_t *)cmdu_rx_msg->metadata()->dst, sizeof(mapf::CmduRxMessage::Metadata::dst), From 4edaf3dee7846e09cb20afbaef6182e9093de0e7 Mon Sep 17 00:00:00 2001 From: Mario Maz Date: Mon, 15 Jun 2020 19:39:41 +0200 Subject: [PATCH 10/28] agent: backhaul: extend topology database with if_index and MAC When processing Topology Discovery message we must store the IEEE 1905.1 AL MAC address of the transmitting device together with the MAC address of the interface on which the message is transmitted and the interface on which such message is received. Currently we are storing AL MAC address only. This additional information is required to build Topology Response and Link Metric Response messages properly. Signed-off-by: Mario Maz --- .../backhaul_manager_thread.cpp | 16 +++++++++++++-- .../backhaul_manager_thread.h | 20 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) 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 7a57169f5e..1632e174e2 100644 --- a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp +++ b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp @@ -523,7 +523,7 @@ void backhaul_manager::after_select(bool timeout) // and send a Topology Notification message. bool neighbors_list_changed = false; for (auto it = m_1905_neighbor_devices.begin(); it != m_1905_neighbor_devices.end();) { - const auto &last_topology_discovery = it->second; + const auto &last_topology_discovery = it->second.timestamp; if (last_topology_discovery + std::chrono::seconds(DISCOVERY_NEIGHBOUR_REMOVAL_TIMEOUT) < std::chrono::steady_clock::now()) { const auto &device_al_mac = it->first; @@ -3290,11 +3290,23 @@ bool backhaul_manager::handle_1905_topology_discovery(const std::string &src_mac LOG(INFO) << "Received TOPOLOGY_DISCOVERY_MESSAGE from AL MAC=" << tlvAlMac->mac() << ", mid=" << std::hex << int(mid); + auto tlvMac = cmdu_rx.getClass(); + if (!tlvMac) { + LOG(ERROR) << "getClass tlvMacAddress failed"; + return false; + } + auto new_device = m_1905_neighbor_devices.find(tlvAlMac->mac()) == m_1905_neighbor_devices.end(); // Add/Update the device on our list. - m_1905_neighbor_devices[tlvAlMac->mac()] = std::chrono::steady_clock::now(); + sNeighborDevice neighbor_device; + neighbor_device.al_mac = tlvAlMac->mac(); + neighbor_device.mac = tlvMac->mac(); + neighbor_device.if_index = message_com::get_uds_header(cmdu_rx)->if_index; + neighbor_device.timestamp = std::chrono::steady_clock::now(); + + m_1905_neighbor_devices[tlvAlMac->mac()] = neighbor_device; // If it is a new device, then our 1905.1 neighbors list has changed and we are required to send // Topology Notification Message. 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 e44fbc8c86..1980241986 100644 --- a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.h +++ b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.h @@ -454,16 +454,32 @@ class backhaul_manager : public btl::transport_socket_thread { get_neighbor_links(const sMacAddr &neighbor_mac_filter, std::map> &neighbor_links_map); + /** + * @brief 1905.1 Neighbor device information + * + * Information gathered from a neighbor device upon reception of a Topology Discovery message. + */ + struct sNeighborDevice { + sMacAddr al_mac = beerocks::net::network_utils:: + ZERO_MAC; /**< 1905.1 AL MAC address of the Topology Discovery message transmitting device. */ + sMacAddr mac = beerocks::net::network_utils:: + ZERO_MAC; /**< MAC address of the interface on which the Topology Discovery message is transmitted. */ + uint32_t if_index = + 0; /**< Index of the network interface the Topology Discovery message was received on */ + std::chrono::steady_clock::time_point + timestamp; /**< Timestamp of the last Topology Discovery message received from this neighbor device. */ + }; + /* * @brief List of known 1905 neighbor devices * * key: 1905.1 device AL-MAC - * value: Last timestamp receiving discovery message from AL-MAC + * value: 1905.1 device information * Devices are being added to the list when receiving a 1905.1 Topology Discovery message from * an unknown 1905.1 device. Every 1905.1 device shall send this message every 60 seconds, and * we update the time stamp in which the message is received. */ - std::unordered_map m_1905_neighbor_devices; + std::unordered_map m_1905_neighbor_devices; /** * @brief Adds an AP HT Capabilities TLV to AP Capability Report message. From 72c58f8f7a9633b2d1fd43c0b8f788f5bec2cd2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20M=C3=A9lotte?= Date: Wed, 17 Jun 2020 18:57:07 +0200 Subject: [PATCH 11/28] bwl: initialize SStaStats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SStaStats values were not initialized, which could have lead to unexpected results if they are read before being assigned to. Signed-off-by: Raphaël Mélotte --- .../bwl/include/bwl/mon_wlan_hal_types.h | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/common/beerocks/bwl/include/bwl/mon_wlan_hal_types.h b/common/beerocks/bwl/include/bwl/mon_wlan_hal_types.h index 906e9d33c6..ea078a0b85 100644 --- a/common/beerocks/bwl/include/bwl/mon_wlan_hal_types.h +++ b/common/beerocks/bwl/include/bwl/mon_wlan_hal_types.h @@ -64,29 +64,29 @@ struct SVapStats { }; struct SStaStats { - float rx_rssi_watt; - uint8_t rx_rssi_watt_samples_cnt; - float rx_snr_watt; - uint8_t rx_snr_watt_samples_cnt; + float rx_rssi_watt = 0; + uint8_t rx_rssi_watt_samples_cnt = 0; + float rx_snr_watt = 0; + uint8_t rx_snr_watt_samples_cnt = 0; // int8_t rx_rssi_prev=beerocks::RSSI_INVALID; // int8_t rx_rssi_curr=beerocks::RSSI_INVALID; - uint16_t tx_phy_rate_100kb; + uint16_t tx_phy_rate_100kb = 0; // uint16_t tx_phy_rate_100kb_avg; // uint16_t tx_phy_rate_100kb_min; // uint16_t tx_phy_rate_100kb_acc; - uint16_t rx_phy_rate_100kb; + uint16_t rx_phy_rate_100kb = 0; // uint16_t rx_phy_rate_100kb_avg; // uint16_t rx_phy_rate_100kb_min; // uint16_t rx_phy_rate_100kb_acc; - uint64_t tx_bytes_cnt; - uint64_t rx_bytes_cnt; - uint64_t tx_packets_cnt; - uint64_t rx_packets_cnt; - uint32_t tx_packets; - uint32_t tx_bytes; - uint32_t rx_packets; - uint32_t rx_bytes; - uint32_t retrans_count; + uint64_t tx_bytes_cnt = 0; + uint64_t rx_bytes_cnt = 0; + uint64_t tx_packets_cnt = 0; + uint64_t rx_packets_cnt = 0; + uint32_t tx_packets = 0; + uint32_t tx_bytes = 0; + uint32_t rx_packets = 0; + uint32_t rx_bytes = 0; + uint32_t retrans_count = 0; // uint8_t tx_load_percent_curr=0; // uint8_t tx_load_percent_prev=0; // uint8_t rx_load_percent_curr=0; From 6dd386675bf5e2c7c79556ec7990256c0d9cc4bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20M=C3=A9lotte?= Date: Wed, 17 Jun 2020 22:41:59 +0200 Subject: [PATCH 12/28] mon_wlan_hal_dwpal: parse SNR and ShortTermRSSIAverage as strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous parsing of SNR and ShortTermRSSIAverage was failing, leading to a segmentation fault of beerocks_fronthaul. Parse them as strings instead. Since they contain space-separated values, split them later. Fixes https://github.com/prplfoundation/prplMesh/issues/1438 MAP-4.3.2_ETH_FH24G:netgear-rax40 Signed-off-by: Raphaël Mélotte --- .../beerocks/bwl/dwpal/mon_wlan_hal_dwpal.cpp | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/common/beerocks/bwl/dwpal/mon_wlan_hal_dwpal.cpp b/common/beerocks/bwl/dwpal/mon_wlan_hal_dwpal.cpp index 940f9fb61e..d38f60eace 100644 --- a/common/beerocks/bwl/dwpal/mon_wlan_hal_dwpal.cpp +++ b/common/beerocks/bwl/dwpal/mon_wlan_hal_dwpal.cpp @@ -689,9 +689,9 @@ bool mon_wlan_hal_dwpal::update_stations_stats(const std::string &vap_iface_name size_t numOfValidArgs[10] = {0}, replyLen = strnlen(reply, HOSTAPD_TO_DWPAL_MSG_LENGTH); uint64_t BytesSent = 0, BytesReceived = 0, PacketsSent = 0, PacketsReceived = 0, LastDataDownlinkRate = 0, LastDataUplinkRate = 0, Active = 0; - char ShortTermRSSIAverage[32][HOSTAPD_TO_DWPAL_VALUE_STRING_LENGTH] = {'\0'}; - char SNR[32][HOSTAPD_TO_DWPAL_VALUE_STRING_LENGTH] = {'\0'}; - FieldsToParse fieldsToParse[] = { + char ShortTermRSSIAverage[32] = {'\0'}; + char SNR[32] = {'\0'}; + FieldsToParse fieldsToParse[] = { {(void *)&BytesSent, &numOfValidArgs[0], DWPAL_LONG_LONG_INT_PARAM, "BytesSent=", 0}, {(void *)&BytesReceived, &numOfValidArgs[1], DWPAL_LONG_LONG_INT_PARAM, "BytesReceived=", 0}, @@ -699,9 +699,9 @@ bool mon_wlan_hal_dwpal::update_stations_stats(const std::string &vap_iface_name {(void *)&PacketsReceived, &numOfValidArgs[3], DWPAL_LONG_LONG_INT_PARAM, "PacketsReceived=", 0}, {(void *)&sta_stats.retrans_count, &numOfValidArgs[4], DWPAL_INT_PARAM, "RetransCount=", 0}, - {(void *)ShortTermRSSIAverage, &numOfValidArgs[5], DWPAL_STR_ARRAY_PARAM, + {(void *)ShortTermRSSIAverage, &numOfValidArgs[5], DWPAL_STR_PARAM, "ShortTermRSSIAverage=", sizeof(ShortTermRSSIAverage)}, - {(void *)SNR, &numOfValidArgs[6], DWPAL_STR_ARRAY_PARAM, "SNR=", sizeof(SNR)}, + {(void *)SNR, &numOfValidArgs[6], DWPAL_STR_PARAM, "SNR=", sizeof(SNR)}, {(void *)&Active, &numOfValidArgs[7], DWPAL_LONG_LONG_INT_PARAM, "Active=", 0}, {(void *)&LastDataDownlinkRate, &numOfValidArgs[8], DWPAL_LONG_LONG_INT_PARAM, "LastDataDownlinkRate=", 0}, @@ -738,18 +738,20 @@ bool mon_wlan_hal_dwpal::update_stations_stats(const std::string &vap_iface_name } } - //save avarage RSSI in watt - for (uint8_t i = 0; i < numOfValidArgs[5]; i++) { - float s_float = float(beerocks::string_utils::stoi(std::string(ShortTermRSSIAverage[i]))); + //save average RSSI in watt + // ShortTermRSSIAverage values are space-separated: + for (const auto &rssi : beerocks::string_utils::str_split(ShortTermRSSIAverage, ' ')) { + float s_float = float(beerocks::string_utils::stoi(std::string(rssi))); if (s_float > beerocks::RSSI_MIN) { sta_stats.rx_rssi_watt += std::pow(10, s_float / float(10)); sta_stats.rx_rssi_watt_samples_cnt++; } } - //save avarage SNR in watt - for (uint8_t i = 0; i < numOfValidArgs[6]; i++) { - float s_float = float(beerocks::string_utils::stoi(std::string(SNR[i]))); + //save average SNR in watt + // SNR values are space-separated: + for (const auto &snr : beerocks::string_utils::str_split(SNR, ' ')) { + float s_float = float(beerocks::string_utils::stoi(std::string(snr))); if (s_float > beerocks::SNR_MIN) { sta_stats.rx_snr_watt += std::pow(10, s_float / float(10)); sta_stats.rx_snr_watt_samples_cnt++; From d17285b11e9c93309a1c3db3f74b3c0962ef0454 Mon Sep 17 00:00:00 2001 From: Vitaly Bukhovsky Date: Wed, 10 Jun 2020 16:38:58 +0000 Subject: [PATCH 13/28] devcontainer: add missing packages Latest changes introduced dependecies to new tools that are not currently installed in the devcontainer. Install the missing tools as part of the creation of the devcontainer. Signed-off-by: Vitaly Bukhovsky --- .devcontainer/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 7005476a41..0493bcd02f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -13,13 +13,13 @@ RUN apt-get update \ # Install C++ tools && apt-get -y install build-essential cmake cppcheck valgrind \ # Libraries - libjson-c-dev python-yaml libzmq3-dev libssl-dev \ + libjson-c-dev python-yaml python3-yaml libzmq3-dev libssl-dev \ libncurses-dev libreadline-dev libnl-3-dev libnl-route-3-dev libnl-genl-3-dev \ # Install Helper tools bash-completion locales ninja-build pkg-config shellcheck \ flake8 clang-format vim \ # Network capturing - tcpdump openssh-server + tcpdump tshark wireshark-common openssh-server # Install podman RUN echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$(lsb_release -sr)/ /" \ From 975f72805cf354e12d51244d26c41e8c2155f16e Mon Sep 17 00:00:00 2001 From: Vitaly Bukhovsky Date: Wed, 10 Jun 2020 16:41:10 +0000 Subject: [PATCH 14/28] vscode_launch: beerocks_fronthaul support Change beerocks_monitor attach tasks to beerocks_fronthaul Signed-off-by: Vitaly Bukhovsky --- .vscode/launch.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 2781aaaa6d..beff1b83f6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -53,10 +53,10 @@ } }, { - "name": "(gdb) GATEWAY - Attach to beerocks_monitor", + "name": "(gdb) GATEWAY - Attach to beerocks_fronthaul", "type": "cppdbg", "request": "attach", - "program": "${workspaceFolder}/build/install/bin/beerocks_monitor", + "program": "${workspaceFolder}/build/install/bin/beerocks_fronthaul", "processId": "${command:pickRemoteProcess}", "pipeTransport": { "pipeCwd": "${workspaceRoot}", @@ -125,10 +125,10 @@ } }, { - "name": "(gdb) REPEATER #1 - Attach to beerocks_monitor", + "name": "(gdb) REPEATER #1 - Attach to beerocks_fronthaul", "type": "cppdbg", "request": "attach", - "program": "${workspaceFolder}/build/install/bin/beerocks_monitor", + "program": "${workspaceFolder}/build/install/bin/beerocks_fronthaul", "processId": "${command:pickRemoteProcess}", "pipeTransport": { "pipeCwd": "${workspaceRoot}", @@ -173,10 +173,10 @@ } }, { - "name": "(gdb) REPEATER #2 - Attach to beerocks_monitor", + "name": "(gdb) REPEATER #2 - Attach to beerocks_fronthaul", "type": "cppdbg", "request": "attach", - "program": "${workspaceFolder}/build/install/bin/beerocks_monitor", + "program": "${workspaceFolder}/build/install/bin/beerocks_fronthaul", "processId": "${command:pickRemoteProcess}", "pipeTransport": { "pipeCwd": "${workspaceRoot}", From d2d7e02847a8e9a2a790d22d951ccbcdbf375722 Mon Sep 17 00:00:00 2001 From: Ran Regev Date: Thu, 18 Jun 2020 13:41:05 +0300 Subject: [PATCH 15/28] slave: backhaul manager: fixed weird curly brackets fixed a strange code in handle_1905_1_message's switch case Signed-off-by: Ran Regev --- .../beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1632e174e2..e8f8b1bab3 100644 --- a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp +++ b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp @@ -2212,6 +2212,7 @@ bool backhaul_manager::handle_1905_1_message(ieee1905_1::CmduMessageRx &cmdu_rx, } case ieee1905_1::eMessageType::MULTI_AP_POLICY_CONFIG_REQUEST_MESSAGE: { return handle_multi_ap_policy_config_request(cmdu_rx, src_mac); + } case ieee1905_1::eMessageType::AP_METRICS_QUERY_MESSAGE: { return handle_ap_metrics_query(cmdu_rx, src_mac); } @@ -2227,7 +2228,6 @@ bool backhaul_manager::handle_1905_1_message(ieee1905_1::CmduMessageRx &cmdu_rx, return false; } } - } } bool backhaul_manager::handle_slave_1905_1_message(ieee1905_1::CmduMessageRx &cmdu_rx, const std::string &src_mac) From 2489113485d794e1ab6f3ce0f2b1253fca461d85 Mon Sep 17 00:00:00 2001 From: Itay Elenzweig Date: Wed, 10 Jun 2020 15:46:00 +0000 Subject: [PATCH 16/28] common: prplmesh_utils.sh: add bml execute func This is a preparative commit for "common: prplmesh_utils.sh: use BML for operational check" Add execute BML function Signed-off-by: itay elenzweig --- common/beerocks/scripts/prplmesh_utils.sh.in | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/common/beerocks/scripts/prplmesh_utils.sh.in b/common/beerocks/scripts/prplmesh_utils.sh.in index a1d73839fb..36e855d830 100755 --- a/common/beerocks/scripts/prplmesh_utils.sh.in +++ b/common/beerocks/scripts/prplmesh_utils.sh.in @@ -246,6 +246,17 @@ stop_function() { [ "$DELETE_LOGS" = "true" ] && prplmesh_delete_logs } +execute_beerocks_command() { + dbg "Executing beerocks cli command: $*" + if [ -e $PRPLMESH_BIN_DIR/beerocks_cli ]; then + output=$(${PRPLMESH_BIN_DIR}/beerocks_cli -c "$@") + return $? + else + err "BML CLI not found" + return 1 + fi +} + # Note: Apparently on some Linux version space is added to the process name. # Therefore added "($|[[:blank:]])" to the end of the regex expression which means the end of the # line ($) or blank character ([[:blank:]]) From d9d1b58d6c770fc814973ea256a96b169e562ccd Mon Sep 17 00:00:00 2001 From: Itay Elenzweig Date: Wed, 10 Jun 2020 15:46:18 +0000 Subject: [PATCH 17/28] common: prplmesh_utils.sh: use BML operational check prplmesh_utils.sh status returns an operational status determined by parsing the logs. In some platforms logs wrap around could return "fail" status although system is operational state. To resolve this issue, the status check should use the BML command bml_get_device_operational_radios which returns the status of the current device using the bridge's MAC address. Use BML to check operational status Signed-off-by: itay elenzweig --- common/beerocks/scripts/prplmesh_utils.sh.in | 49 +++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/common/beerocks/scripts/prplmesh_utils.sh.in b/common/beerocks/scripts/prplmesh_utils.sh.in index 36e855d830..30528c47c7 100755 --- a/common/beerocks/scripts/prplmesh_utils.sh.in +++ b/common/beerocks/scripts/prplmesh_utils.sh.in @@ -253,6 +253,7 @@ execute_beerocks_command() { return $? else err "BML CLI not found" + output="" return 1 fi } @@ -287,21 +288,45 @@ status_function() { pgrep -l ieee1905_transport pgrep -l local_bus - # check for operational status - LOGS_PATH=@BEEROCKS_LOG_FILES_PATH@ + bridge_mac="$(ip link show dev @BEEROCKS_BRIDGE_IFACE@ | awk '/^ *link\/ether / {print $2}')" + bml_cmd="bml_get_device_operational_radios $bridge_mac" + + if pgrep -l beerocks_cont ; then + if execute_beerocks_command "$bml_cmd" ; then + # Expecting + # > OK Main radio agent operational + # > OK wlan0 radio agent operational + # > OK wlan2 radio agent operational + OK_Count=$(echo "$output" | grep -c -e "OK.*operational") + if [ "$OK_Count" -eq 3 ]; then + success "operational test success!" + exit 0 + else + err "operational test failed!" + err "$output" + exit 1 + fi + else + err "Beerocks command failed to execute!" + exit 1 + fi + else + # check for operational status + LOGS_PATH=@BEEROCKS_LOG_FILES_PATH@ - error=0 - report "Main agent operational" main_agent_operational $LOGS_PATH - report "@BEEROCKS_WLAN1_IFACE@ radio agent operational" radio_agent_operational $LOGS_PATH @BEEROCKS_WLAN1_IFACE@ - report "@BEEROCKS_WLAN2_IFACE@ radio agent operational" radio_agent_operational $LOGS_PATH @BEEROCKS_WLAN2_IFACE@ + error=0 + report "Main agent operational" main_agent_operational $LOGS_PATH + report "@BEEROCKS_WLAN1_IFACE@ radio agent operational" radio_agent_operational $LOGS_PATH @BEEROCKS_WLAN1_IFACE@ + report "@BEEROCKS_WLAN2_IFACE@ radio agent operational" radio_agent_operational $LOGS_PATH @BEEROCKS_WLAN2_IFACE@ - [ "$VERBOSE" = "true" ] && [ $error = 1 ] && { - cat $LOGS_PATH/beerocks_agent@BEEROCKS_LOG_FILES_SUFFIX@ - cat $LOGS_PATH/beerocks_agent_@BEEROCKS_WLAN1_IFACE@@BEEROCKS_LOG_FILES_SUFFIX@ - cat $LOGS_PATH/beerocks_agent_@BEEROCKS_WLAN2_IFACE@@BEEROCKS_LOG_FILES_SUFFIX@ - } + [ "$VERBOSE" = "true" ] && [ $error = 1 ] && { + cat $LOGS_PATH/beerocks_agent@BEEROCKS_LOG_FILES_SUFFIX@ + cat $LOGS_PATH/beerocks_agent_@BEEROCKS_WLAN1_IFACE@@BEEROCKS_LOG_FILES_SUFFIX@ + cat $LOGS_PATH/beerocks_agent_@BEEROCKS_WLAN2_IFACE@@BEEROCKS_LOG_FILES_SUFFIX@ + } - exit $error + exit $error + fi } usage() { From 9e60f1e1c223d45718403bb2a869c061dfdd73d0 Mon Sep 17 00:00:00 2001 From: Alex Kanter Date: Thu, 18 Jun 2020 13:40:40 +0000 Subject: [PATCH 18/28] prplmesh_uttils.sh: use SIGTERM in killall_program() Currently prplmesh_utills.sh stop sends SIGKILL to all processes. Since SIGKILL cannot be handled monitor/agent/controller processes are not shutdown properly. As a result old wpa ctrl socket are not detached and files are not deleted. Change killall_program() to send SIGTERM instead on default. Signed-off-by: Alex Kanter --- common/beerocks/scripts/prplmesh_utils.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/beerocks/scripts/prplmesh_utils.sh.in b/common/beerocks/scripts/prplmesh_utils.sh.in index 30528c47c7..432111949c 100755 --- a/common/beerocks/scripts/prplmesh_utils.sh.in +++ b/common/beerocks/scripts/prplmesh_utils.sh.in @@ -27,7 +27,7 @@ run() { killall_program() { PROGRAM_NAME=$1 - KILL_SIG=${2:-KILL} + KILL_SIG=${2:-TERM} echo "killing $PROGRAM_NAME ($KILL_SIG)" start-stop-daemon -K -s "$KILL_SIG" -x "$PRPLMESH_BIN_DIR"/"$PROGRAM_NAME" > /dev/null 2>&1 } From fd9ffe58c3d2ccee72ea59c53c711d62a8f81141 Mon Sep 17 00:00:00 2001 From: "Arnout Vandecappelle (Essensium/Mind)" Date: Mon, 22 Jun 2020 11:22:03 +0200 Subject: [PATCH 19/28] mergify: allow status check failures We have a requirement for mergify that no status checks should fail. This is kind of redundant, because mergify will only do the merge if no *required* status checks fail anyway. Since we now have a non-required status check (UTAF) that often fails, we really need to remove that redundant requirement. Signed-off-by: Arnout Vandecappelle (Essensium/Mind) --- .mergify.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index 06b02b686b..e71849589b 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -5,7 +5,6 @@ pull_request_rules: - "#changes-requested-reviews-by=0" # Changes requested blocks the merge - "label=ready for merge" # Must have ready for merge label - "label!=don't merge" # Don't merge label blocks the merge - - "#status-failure=0" # Just to be sure that we don't consider it as passed when the status checks haven't even # started yet. - "#status-success>=3" From c81a31cd11136ae85751649ddc49d04b2bb8c9a0 Mon Sep 17 00:00:00 2001 From: Mario Maz Date: Wed, 10 Jun 2020 16:10:46 +0200 Subject: [PATCH 20/28] tlvf: fix tlv_mac_tlv in msgTopologyDiscovery Change the type of field tlv_mac_tlv from tlvAlMacAddressType to tlvMacAddress. Note that this change does not affect to autogenerated files nor to source code. Signed-off-by: Mario Maz --- .../tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml index 4445a61c20..df28ce6d45 100644 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml @@ -8,6 +8,6 @@ msgTopologyDiscovery: _type: cmduHeader _setValue: { "messageType" : TOPOLOGY_DISCOVERY_MESSAGE } tlv_al_mac_tlv: tlvAlMacAddressType - tlv_mac_tlv: tlvAlMacAddressType + tlv_mac_tlv: tlvMacAddress tlv_eof: tlvEndOfMessage \ No newline at end of file From 08b2c5f81ed88409ef8336bffdffead8b412475f Mon Sep 17 00:00:00 2001 From: Mario Maz Date: Wed, 10 Jun 2020 16:15:36 +0200 Subject: [PATCH 21/28] tlvf: rename tlvAlMacAddressType to tlvAlMacAddress No TLV type ends with prefix 'Type' except this one. Rename it to look like the rest of TLVs Signed-off-by: Mario Maz --- .../backhaul_manager_thread.cpp | 18 +-- agent/src/beerocks/slave/son_slave_thread.cpp | 4 +- .../src/beerocks/master/son_actions.cpp | 4 +- controller/src/beerocks/master/son_actions.h | 2 +- .../src/beerocks/master/son_master_thread.cpp | 10 +- .../include/tlvf/ieee_1905_1/eTlvType.h | 2 +- .../tlvf/ieee_1905_1/tlvAlMacAddress.h | 52 ++++++++ .../src/tlvf/ieee_1905_1/tlvAlMacAddress.cpp | 118 ++++++++++++++++++ framework/tlvf/src/src/CmduMessageRx.cpp | 4 +- .../tlvf/yaml/tlvf/ieee_1905_1/eTlvType.yaml | 2 +- ...cAddressType.yaml => tlvAlMacAddress.yaml} | 4 +- .../msgApAutoConfigurationRenew.yaml | 2 +- .../msgApAutoConfigurationSearch.yaml | 2 +- .../msgPushButtonEventNotification.yaml | 2 +- .../msgPushButtonJoinNotification.yaml | 2 +- .../ieee_1905_1_msg/msgTopologyDiscovery.yaml | 2 +- .../msgTopologyNotification.yaml | 2 +- 17 files changed, 201 insertions(+), 31 deletions(-) create mode 100644 framework/tlvf/AutoGenerated/include/tlvf/ieee_1905_1/tlvAlMacAddress.h create mode 100644 framework/tlvf/AutoGenerated/src/tlvf/ieee_1905_1/tlvAlMacAddress.cpp rename framework/tlvf/yaml/tlvf/ieee_1905_1/{tlvAlMacAddressType.yaml => tlvAlMacAddress.yaml} (67%) 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 e8f8b1bab3..0ae2123b0f 100644 --- a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp +++ b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp @@ -50,7 +50,7 @@ */ #include #include -#include +#include #include #include #include @@ -1125,9 +1125,9 @@ bool backhaul_manager::send_1905_topology_discovery_message() LOG(ERROR) << "Failed to create TOPOLOGY_DISCOVERY_MESSAGE cmdu"; return false; } - auto tlvAlMac = cmdu_tx.addClass(); + auto tlvAlMac = cmdu_tx.addClass(); if (!tlvAlMac) { - LOG(ERROR) << "Failed to create tlvAlMacAddressType tlv"; + LOG(ERROR) << "Failed to create tlvAlMacAddress tlv"; return false; } tlvAlMac->mac() = tlvf::mac_from_string(bridge_info.mac); @@ -1162,12 +1162,12 @@ bool backhaul_manager::send_autoconfig_search_message(std::shared_ptr(); - if (!tlvAlMacAddressType) { - LOG(ERROR) << "addClass ieee1905_1::tlvAlMacAddressType failed"; + auto tlvAlMacAddress = cmdu_tx.addClass(); + if (!tlvAlMacAddress) { + LOG(ERROR) << "addClass ieee1905_1::tlvAlMacAddress failed"; return false; } - tlvf::mac_from_string(tlvAlMacAddressType->mac().oct, bridge_info.mac); + tlvf::mac_from_string(tlvAlMacAddress->mac().oct, bridge_info.mac); auto tlvSearchedRole = cmdu_tx.addClass(); if (!tlvSearchedRole) { @@ -3275,9 +3275,9 @@ bool backhaul_manager::handle_1905_combined_infrastructure_metrics( bool backhaul_manager::handle_1905_topology_discovery(const std::string &src_mac, ieee1905_1::CmduMessageRx &cmdu_rx) { - auto tlvAlMac = cmdu_rx.getClass(); + auto tlvAlMac = cmdu_rx.getClass(); if (!tlvAlMac) { - LOG(ERROR) << "getClass tlvAlMacAddressType failed"; + LOG(ERROR) << "getClass tlvAlMacAddress failed"; return false; } diff --git a/agent/src/beerocks/slave/son_slave_thread.cpp b/agent/src/beerocks/slave/son_slave_thread.cpp index 79298fe5ea..d3a6297977 100644 --- a/agent/src/beerocks/slave/son_slave_thread.cpp +++ b/agent/src/beerocks/slave/son_slave_thread.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -3990,7 +3990,7 @@ bool slave_thread::handle_autoconfiguration_renew(Socket *sd, ieee1905_1::CmduMe { LOG(INFO) << "received autoconfig renew message"; - auto tlvAlMac = cmdu_rx.getClass(); + auto tlvAlMac = cmdu_rx.getClass(); if (tlvAlMac) { LOG(DEBUG) << "tlvAlMac=" << tlvAlMac->mac(); // TODO register/update mapping of AL-MAC to interface, cfr. #81 diff --git a/controller/src/beerocks/master/son_actions.cpp b/controller/src/beerocks/master/son_actions.cpp index babe5e49ec..4896823aaa 100644 --- a/controller/src/beerocks/master/son_actions.cpp +++ b/controller/src/beerocks/master/son_actions.cpp @@ -467,9 +467,9 @@ bool son_actions::send_ap_config_renew_msg(ieee1905_1::CmduMessageTx &cmdu_tx, d LOG(ERROR) << "Failed building IEEE1905 AP_AUTOCONFIGURATION_RENEW_MESSAGE"; } - auto tlvAlMac = cmdu_tx.addClass(); + auto tlvAlMac = cmdu_tx.addClass(); if (!tlvAlMac) { - LOG(ERROR) << "Failed addClass ieee1905_1::tlvAlMacAddressType"; + LOG(ERROR) << "Failed addClass ieee1905_1::tlvAlMacAddress"; result = false; } diff --git a/controller/src/beerocks/master/son_actions.h b/controller/src/beerocks/master/son_actions.h index 024dc42f80..fba85f867b 100644 --- a/controller/src/beerocks/master/son_actions.h +++ b/controller/src/beerocks/master/son_actions.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include diff --git a/controller/src/beerocks/master/son_master_thread.cpp b/controller/src/beerocks/master/son_master_thread.cpp index 1a5e6970b0..9e0e1e7805 100644 --- a/controller/src/beerocks/master/son_master_thread.cpp +++ b/controller/src/beerocks/master/son_master_thread.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include @@ -326,9 +326,9 @@ bool master_thread::handle_cmdu_1905_autoconfiguration_search(const std::string { LOG(DEBUG) << "Received AP_AUTOCONFIGURATION_SEARCH_MESSAGE"; - auto tlvAlMacAddressType = cmdu_rx.getClass(); - if (!tlvAlMacAddressType) { - LOG(ERROR) << "getClass failed"; + auto tlvAlMacAddress = cmdu_rx.getClass(); + if (!tlvAlMacAddress) { + LOG(ERROR) << "getClass failed"; return false; } auto tlvSearchedRole = cmdu_rx.getClass(); @@ -352,7 +352,7 @@ bool master_thread::handle_cmdu_1905_autoconfiguration_search(const std::string return false; } - auto al_mac = tlvf::mac_to_string((const unsigned char *)tlvAlMacAddressType->mac().oct); + auto al_mac = tlvf::mac_to_string((const unsigned char *)tlvAlMacAddress->mac().oct); LOG(DEBUG) << "mac=" << al_mac; LOG(DEBUG) << "searched_role=" << int(tlvSearchedRole->value()); diff --git a/framework/tlvf/AutoGenerated/include/tlvf/ieee_1905_1/eTlvType.h b/framework/tlvf/AutoGenerated/include/tlvf/ieee_1905_1/eTlvType.h index fd14a9497a..c5b6f6d168 100644 --- a/framework/tlvf/AutoGenerated/include/tlvf/ieee_1905_1/eTlvType.h +++ b/framework/tlvf/AutoGenerated/include/tlvf/ieee_1905_1/eTlvType.h @@ -21,7 +21,7 @@ namespace ieee1905_1 { enum class eTlvType : uint8_t { TLV_END_OF_MESSAGE = 0x0, - TLV_AL_MAC_ADDRESS_TYPE = 0x1, + TLV_AL_MAC_ADDRESS = 0x1, TLV_MAC_ADDRESS = 0x2, TLV_DEVICE_INFORMATION = 0x3, TLV_DEVICE_BRIDGING_CAPABILITY = 0x4, diff --git a/framework/tlvf/AutoGenerated/include/tlvf/ieee_1905_1/tlvAlMacAddress.h b/framework/tlvf/AutoGenerated/include/tlvf/ieee_1905_1/tlvAlMacAddress.h new file mode 100644 index 0000000000..0544c3bc15 --- /dev/null +++ b/framework/tlvf/AutoGenerated/include/tlvf/ieee_1905_1/tlvAlMacAddress.h @@ -0,0 +1,52 @@ +/////////////////////////////////////// +// AUTO GENERATED FILE - DO NOT EDIT // +/////////////////////////////////////// + +/* 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 _TLVF_IEEE_1905_1_TLVALMACADDRESS_H_ +#define _TLVF_IEEE_1905_1_TLVALMACADDRESS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "tlvf/ieee_1905_1/eTlvType.h" +#include "tlvf/common/sMacAddr.h" + +namespace ieee1905_1 { + + +class tlvAlMacAddress : public BaseClass +{ + public: + tlvAlMacAddress(uint8_t* buff, size_t buff_len, bool parse = false); + explicit tlvAlMacAddress(std::shared_ptr base, bool parse = false); + ~tlvAlMacAddress(); + + const eTlvType& type(); + const uint16_t& length(); + sMacAddr& mac(); + void class_swap() override; + bool finalize() override; + static size_t get_initial_size(); + + private: + bool init(); + eTlvType* m_type = nullptr; + uint16_t* m_length = nullptr; + sMacAddr* m_mac = nullptr; +}; + +}; // close namespace: ieee1905_1 + +#endif //_TLVF/IEEE_1905_1_TLVALMACADDRESS_H_ diff --git a/framework/tlvf/AutoGenerated/src/tlvf/ieee_1905_1/tlvAlMacAddress.cpp b/framework/tlvf/AutoGenerated/src/tlvf/ieee_1905_1/tlvAlMacAddress.cpp new file mode 100644 index 0000000000..165c28e51c --- /dev/null +++ b/framework/tlvf/AutoGenerated/src/tlvf/ieee_1905_1/tlvAlMacAddress.cpp @@ -0,0 +1,118 @@ +/////////////////////////////////////// +// AUTO GENERATED FILE - DO NOT EDIT // +/////////////////////////////////////// + +/* 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. + */ + +#include +#include + +using namespace ieee1905_1; + +tlvAlMacAddress::tlvAlMacAddress(uint8_t* buff, size_t buff_len, bool parse) : + BaseClass(buff, buff_len, parse) { + m_init_succeeded = init(); +} +tlvAlMacAddress::tlvAlMacAddress(std::shared_ptr base, bool parse) : +BaseClass(base->getBuffPtr(), base->getBuffRemainingBytes(), parse){ + m_init_succeeded = init(); +} +tlvAlMacAddress::~tlvAlMacAddress() { +} +const eTlvType& tlvAlMacAddress::type() { + return (const eTlvType&)(*m_type); +} + +const uint16_t& tlvAlMacAddress::length() { + return (const uint16_t&)(*m_length); +} + +sMacAddr& tlvAlMacAddress::mac() { + return (sMacAddr&)(*m_mac); +} + +void tlvAlMacAddress::class_swap() +{ + tlvf_swap(16, reinterpret_cast(m_length)); + m_mac->struct_swap(); +} + +bool tlvAlMacAddress::finalize() +{ + if (m_parse__) { + TLVF_LOG(DEBUG) << "finalize() called but m_parse__ is set"; + return true; + } + if (m_finalized__) { + TLVF_LOG(DEBUG) << "finalize() called for already finalized class"; + return true; + } + if (!isPostInitSucceeded()) { + TLVF_LOG(ERROR) << "post init check failed"; + return false; + } + if (m_inner__) { + if (!m_inner__->finalize()) { + TLVF_LOG(ERROR) << "m_inner__->finalize() failed"; + return false; + } + auto tailroom = m_inner__->getMessageBuffLength() - m_inner__->getMessageLength(); + m_buff_ptr__ -= tailroom; + *m_length -= tailroom; + } + class_swap(); + m_finalized__ = true; + return true; +} + +size_t tlvAlMacAddress::get_initial_size() +{ + size_t class_size = 0; + class_size += sizeof(eTlvType); // type + class_size += sizeof(uint16_t); // length + class_size += sizeof(sMacAddr); // mac + return class_size; +} + +bool tlvAlMacAddress::init() +{ + if (getBuffRemainingBytes() < get_initial_size()) { + TLVF_LOG(ERROR) << "Not enough available space on buffer. Class init failed"; + return false; + } + m_type = reinterpret_cast(m_buff_ptr__); + if (!m_parse__) *m_type = eTlvType::TLV_AL_MAC_ADDRESS; + if (!buffPtrIncrementSafe(sizeof(eTlvType))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(eTlvType) << ") Failed!"; + return false; + } + m_length = reinterpret_cast(m_buff_ptr__); + if (!m_parse__) *m_length = 0; + if (!buffPtrIncrementSafe(sizeof(uint16_t))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(uint16_t) << ") Failed!"; + return false; + } + m_mac = reinterpret_cast(m_buff_ptr__); + if (!buffPtrIncrementSafe(sizeof(sMacAddr))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(sMacAddr) << ") Failed!"; + return false; + } + if(m_length && !m_parse__){ (*m_length) += sizeof(sMacAddr); } + if (!m_parse__) { m_mac->struct_init(); } + if (m_parse__) { class_swap(); } + if (m_parse__) { + if (*m_type != eTlvType::TLV_AL_MAC_ADDRESS) { + TLVF_LOG(ERROR) << "TLV type mismatch. Expected value: " << int(eTlvType::TLV_AL_MAC_ADDRESS) << ", received value: " << int(*m_type); + return false; + } + } + return true; +} + + diff --git a/framework/tlvf/src/src/CmduMessageRx.cpp b/framework/tlvf/src/src/CmduMessageRx.cpp index ea730cc5e9..6080528575 100644 --- a/framework/tlvf/src/src/CmduMessageRx.cpp +++ b/framework/tlvf/src/src/CmduMessageRx.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -88,7 +88,7 @@ std::shared_ptr CmduMessageRx::parseNextTlv() return msg.addClass(); } case (1): { - return msg.addClass(); + return msg.addClass(); } case (2): { return msg.addClass(); diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1/eTlvType.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1/eTlvType.yaml index cf445c9edf..32a76b42af 100644 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1/eTlvType.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1/eTlvType.yaml @@ -6,7 +6,7 @@ eTlvType: _type: enum_class _enum_storage: uint8_t TLV_END_OF_MESSAGE: 0x00 - TLV_AL_MAC_ADDRESS_TYPE: 0x01 + TLV_AL_MAC_ADDRESS: 0x01 TLV_MAC_ADDRESS: 0x02 TLV_DEVICE_INFORMATION: 0x03 TLV_DEVICE_BRIDGING_CAPABILITY: 0x04 diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1/tlvAlMacAddressType.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1/tlvAlMacAddress.yaml similarity index 67% rename from framework/tlvf/yaml/tlvf/ieee_1905_1/tlvAlMacAddressType.yaml rename to framework/tlvf/yaml/tlvf/ieee_1905_1/tlvAlMacAddress.yaml index 1ed526a3b5..df7450587c 100755 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1/tlvAlMacAddressType.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1/tlvAlMacAddress.yaml @@ -2,11 +2,11 @@ --- _namespace: ieee1905_1 -tlvAlMacAddressType: +tlvAlMacAddress: _type: class _is_tlv_class: True type: _type: eTlvType - _value_const: TLV_AL_MAC_ADDRESS_TYPE + _value_const: TLV_AL_MAC_ADDRESS length: uint16_t mac: sMacAddr diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgApAutoConfigurationRenew.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgApAutoConfigurationRenew.yaml index 4d39c26107..2400f483ac 100644 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgApAutoConfigurationRenew.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgApAutoConfigurationRenew.yaml @@ -7,7 +7,7 @@ msgApAutoConfigurationRenew: header: _type: cmduHeader _setValue: { "messageType" : AP_AUTOCONFIGURATION_RENEW_MESSAGE } - tlv_al_mac_tlv: tlvAlMacAddressType + tlv_al_mac_tlv: tlvAlMacAddress tlv_supported_role: tlvSupportedRole tlv_supported_freq_band: tlvSupportedFreqBand tlv_eof: tlvEndOfMessage \ No newline at end of file diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgApAutoConfigurationSearch.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgApAutoConfigurationSearch.yaml index c52087c503..c93b28e73c 100644 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgApAutoConfigurationSearch.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgApAutoConfigurationSearch.yaml @@ -7,7 +7,7 @@ msgApAutoConfigurationSearch: header: _type: cmduHeader _setValue: { "messageType" : AP_AUTOCONFIGURATION_SEARCH_MESSAGE } - tlv_al_mac_tlv: tlvAlMacAddressType + tlv_al_mac_tlv: tlvAlMacAddress tlv_searched_role: tlvSearchedRole tlv_auto_conf_freq_band: tlvAutoconfigFreqBand tlv_eof: tlvEndOfMessage \ No newline at end of file diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgPushButtonEventNotification.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgPushButtonEventNotification.yaml index 5e4264e544..09ed65658a 100644 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgPushButtonEventNotification.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgPushButtonEventNotification.yaml @@ -7,6 +7,6 @@ msgPushButtonEventNotification: header: _type: cmduHeader _setValue: { "messageType" : PUSH_BUTTON_EVENT_NOTIFICATION_MESSAGE } - tlv_al_mac_tlv: tlvAlMacAddressType + tlv_al_mac_tlv: tlvAlMacAddress tlv_push_butt_event_notif: tlvPushButtonEventNotification tlv_eof: tlvEndOfMessage \ No newline at end of file diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgPushButtonJoinNotification.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgPushButtonJoinNotification.yaml index 5f8ccd82be..f2ccf9d12b 100644 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgPushButtonJoinNotification.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgPushButtonJoinNotification.yaml @@ -7,6 +7,6 @@ msgPushButtonJoinNotification: header: _type: cmduHeader _setValue: { "messageType" : PUSH_BUTTON_JOIN_NOTIFICATION_MESSAGE } - tlv_al_mac_tlv: tlvAlMacAddressType + tlv_al_mac_tlv: tlvAlMacAddress tlv_push_butt_join_notif: tlvPushButtonJoinNotification tlv_eof: tlvEndOfMessage \ No newline at end of file diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml index df28ce6d45..90c011dbac 100644 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyDiscovery.yaml @@ -7,7 +7,7 @@ msgTopologyDiscovery: header: _type: cmduHeader _setValue: { "messageType" : TOPOLOGY_DISCOVERY_MESSAGE } - tlv_al_mac_tlv: tlvAlMacAddressType + tlv_al_mac_tlv: tlvAlMacAddress tlv_mac_tlv: tlvMacAddress tlv_eof: tlvEndOfMessage \ No newline at end of file diff --git a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyNotification.yaml b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyNotification.yaml index e870ec7d22..aae39736c6 100644 --- a/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyNotification.yaml +++ b/framework/tlvf/yaml/tlvf/ieee_1905_1_msg/msgTopologyNotification.yaml @@ -7,5 +7,5 @@ msgTopologyNotification: header: _type: cmduHeader _setValue: { "messageType" : TOPOLOGY_NOTIFICATION_MESSAGE } - tlv_al_mac_tlv: tlvAlMacAddressType + tlv_al_mac_tlv: tlvAlMacAddress tlv_eof: tlvEndOfMessage \ No newline at end of file From f3a266933e18fe210d83fe95bf835dbb3a05b753 Mon Sep 17 00:00:00 2001 From: Mario Maz Date: Wed, 10 Jun 2020 19:46:11 +0200 Subject: [PATCH 22/28] bcl: change return type of linux_get_iface_index Method linux_get_iface_index() is a wrapper for if_nametoindex but return types differ. Change return type of linux_get_iface_index from int to uint32_t and also write a message to log in case of error. This is a preparatory commit. This method is currently not used but it will be in next commits. Signed-off-by: Mario Maz --- common/beerocks/bcl/include/bcl/network/network_utils.h | 9 ++++++++- common/beerocks/bcl/source/network/network_utils.cpp | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/common/beerocks/bcl/include/bcl/network/network_utils.h b/common/beerocks/bcl/include/bcl/network/network_utils.h index ce81205ddd..939a516a89 100644 --- a/common/beerocks/bcl/include/bcl/network/network_utils.h +++ b/common/beerocks/bcl/include/bcl/network/network_utils.h @@ -111,7 +111,14 @@ class network_utils { static std::string get_mac_from_arp_table(const std::string &ipv4); static std::vector linux_get_iface_list_from_bridge(const std::string &bridge); - static int linux_get_iface_index(const std::string &iface); + + /** + * @brief Gets the interface index corresponding to a particular name. + * + * @param iface_name The name of the network interface. + * @return interface index or 0 if no interface exists with the name given. + */ + static uint32_t linux_get_iface_index(const std::string &iface_name); static bool linux_add_iface_to_bridge(const std::string &bridge, const std::string &iface); static bool linux_remove_iface_from_bridge(const std::string &bridge, const std::string &iface); static bool linux_iface_ctrl(const std::string &iface, bool up, std::string ip = "", diff --git a/common/beerocks/bcl/source/network/network_utils.cpp b/common/beerocks/bcl/source/network/network_utils.cpp index abcacc250d..3e4277633a 100644 --- a/common/beerocks/bcl/source/network/network_utils.cpp +++ b/common/beerocks/bcl/source/network/network_utils.cpp @@ -525,9 +525,12 @@ std::vector network_utils::linux_get_iface_list_from_bridge(const s return ifs; } -int network_utils::linux_get_iface_index(const std::string &iface) +uint32_t network_utils::linux_get_iface_index(const std::string &iface_name) { - return if_nametoindex(iface.c_str()); + uint32_t iface_index = if_nametoindex(iface_name.c_str()); + LOG_IF(!iface_index, ERROR) << "Failed to read the index of interface " << iface_name << ": " + << strerror(errno); + return iface_index; } bool network_utils::linux_add_iface_to_bridge(const std::string &bridge, const std::string &iface) From 27adc96ea42031ec4fecdac12b2dc21388b4be5f Mon Sep 17 00:00:00 2001 From: Mario Maz Date: Thu, 11 Jun 2020 12:25:10 +0200 Subject: [PATCH 23/28] btl: add iface_name param to send_cmdu functions Add new iface_name parameter to send_cmdu() functions to specify on which interface the transport should send given CMDU. This is a preparatory commit to later implement neighbor multicast of Topology Discovery message. Signed-off-by: Mario Maz --- common/beerocks/btl/btl.cpp | 10 +++++---- common/beerocks/btl/btl_local_bus.cpp | 6 ++++-- common/beerocks/btl/btl_uds.cpp | 6 ++++-- common/beerocks/btl/include/btl/btl.h | 30 +++++++++++++++++++++++---- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/common/beerocks/btl/btl.cpp b/common/beerocks/btl/btl.cpp index 87dfc5e331..4275cb0787 100644 --- a/common/beerocks/btl/btl.cpp +++ b/common/beerocks/btl/btl.cpp @@ -40,19 +40,21 @@ void transport_socket_thread::set_select_timeout(unsigned msec) { poll_timeout_m bool transport_socket_thread::send_cmdu_to_bus(ieee1905_1::CmduMessageTx &cmdu_tx, const std::string &dst_mac, - const std::string &src_mac) + const std::string &src_mac, + const std::string &iface_name) { if (!cmdu_tx.finalize()) { THREAD_LOG(ERROR) << "finalize failed"; return false; } - return send_cmdu_to_bus(cmdu_tx, dst_mac, src_mac, cmdu_tx.getMessageLength()); + return send_cmdu_to_bus(cmdu_tx, dst_mac, src_mac, cmdu_tx.getMessageLength(), iface_name); } bool transport_socket_thread::send_cmdu_to_bus(ieee1905_1::CmduMessage &cmdu, const std::string &dst_mac, - const std::string &src_mac, uint16_t length) + const std::string &src_mac, uint16_t length, + const std::string &iface_name) { // This method should be used by Message Routers only. It is used to forward CMDU messages from UDS socket to the BUS. LOG_IF(!bus, FATAL) << "Bus is not allocated!"; @@ -68,5 +70,5 @@ bool transport_socket_thread::send_cmdu_to_bus(ieee1905_1::CmduMessage &cmdu, return false; } - return bus_send(cmdu, dst_mac, src_mac, length); + return bus_send(cmdu, iface_name, dst_mac, src_mac, length); } diff --git a/common/beerocks/btl/btl_local_bus.cpp b/common/beerocks/btl/btl_local_bus.cpp index 3dea49233d..6ef31c595b 100644 --- a/common/beerocks/btl/btl_local_bus.cpp +++ b/common/beerocks/btl/btl_local_bus.cpp @@ -225,8 +225,9 @@ bool transport_socket_thread::handle_cmdu_message_bus() return true; } -bool transport_socket_thread::bus_send(ieee1905_1::CmduMessage &cmdu, const std::string &dst_mac, - const std::string &src_mac, uint16_t length) +bool transport_socket_thread::bus_send(ieee1905_1::CmduMessage &cmdu, const std::string &iface_name, + const std::string &dst_mac, const std::string &src_mac, + uint16_t length) { mapf::CmduTxMessage msg; @@ -237,6 +238,7 @@ bool transport_socket_thread::bus_send(ieee1905_1::CmduMessage &cmdu, const std: msg.metadata()->length = length; msg.metadata()->msg_type = static_cast(cmdu.getMessageType()); msg.metadata()->preset_message_id = cmdu.getMessageId() ? 1 : 0; + msg.metadata()->if_index = if_nametoindex(iface_name.c_str()); std::copy_n((uint8_t *)cmdu.getMessageBuff(), msg.metadata()->length, (uint8_t *)msg.data()); return bus->publisher().Send(msg); diff --git a/common/beerocks/btl/btl_uds.cpp b/common/beerocks/btl/btl_uds.cpp index ab2931e14f..54e327d048 100644 --- a/common/beerocks/btl/btl_uds.cpp +++ b/common/beerocks/btl/btl_uds.cpp @@ -108,8 +108,10 @@ void transport_socket_thread::bus_connected(Socket *sd) add_socket(bus); } -bool transport_socket_thread::bus_send(ieee1905_1::CmduMessage &cmdu, const std::string &dst_mac, - const std::string &src_mac, uint16_t length) +bool transport_socket_thread::bus_send(ieee1905_1::CmduMessage &cmdu, + [[gnu::unused]] const std::string &iface_name, + const std::string &dst_mac, const std::string &src_mac, + uint16_t length) { auto uds_header = message_com::get_uds_header(cmdu); if (!uds_header) { diff --git a/common/beerocks/btl/include/btl/btl.h b/common/beerocks/btl/include/btl/btl.h index 544d402ccd..6fcb9ed484 100644 --- a/common/beerocks/btl/include/btl/btl.h +++ b/common/beerocks/btl/include/btl/btl.h @@ -35,8 +35,18 @@ class transport_socket_thread : public socket_thread { virtual void set_select_timeout(unsigned msec) override; virtual bool work() override; + /** + * @brief Sends CDMU to transport for dispatching. + * + * @param cmdu Control Message Data Unit to send. + * @param dst_mac Destination MAC address. + * @param src_mac Source MAC address. + * @param iface_name Name of the network interface to use (set to empty string to send on all + * available interfaces). + * @return True on success and false otherwise. + */ bool send_cmdu_to_bus(ieee1905_1::CmduMessageTx &cmdu, const std::string &dst_mac, - const std::string &src_mac); + const std::string &src_mac, const std::string &iface_name = ""); protected: void add_socket(Socket *s, bool add_to_vector = true) override; @@ -50,13 +60,25 @@ class transport_socket_thread : public socket_thread { bool bus_connect(const std::string &beerocks_temp_path, const bool local_master); void bus_connected(Socket *sd); + /** + * @brief Sends CDMU to transport for dispatching. + * + * @param cmdu Control Message Data Unit to send. + * @param dst_mac Destination MAC address. + * @param src_mac Source MAC address. + * @param length Message length. + * @param iface_name Name of the network interface to use (set to empty string to send on all + * available interfaces). + * @return True on success and false otherwise. + */ bool send_cmdu_to_bus(ieee1905_1::CmduMessage &cmdu, const std::string &dst_mac, - const std::string &src_mac, uint16_t length); + const std::string &src_mac, uint16_t length, + const std::string &iface_name = ""); private: bool bus_init(); - bool bus_send(ieee1905_1::CmduMessage &cmdu, const std::string &dst_mac, - const std::string &src_mac, uint16_t length); + bool bus_send(ieee1905_1::CmduMessage &cmdu, const std::string &iface_name, + const std::string &dst_mac, const std::string &src_mac, uint16_t length); bool handle_cmdu_message_bus(); int poll_timeout_ms = 500; From 2408bfeb189e268751077a33caf2f1a48832815f Mon Sep 17 00:00:00 2001 From: Mario Maz Date: Thu, 11 Jun 2020 12:44:15 +0200 Subject: [PATCH 24/28] agent: backhaul: send Topology Discovery on all interfaces Currently, we sent a single Topology Discovery message through the bridge. However, according to IEEE1905.1, the message should include a MAC Address TLV which contains the address of the interface on which you send the message. Thus, a different message should be sent on each interface. Therefore, the agent should send a separate Discovery message on each interface. Signed-off-by: Mario Maz --- .../backhaul_manager_thread.cpp | 49 ++++++++++++++++--- .../backhaul_manager_thread.h | 9 ++++ 2 files changed, 50 insertions(+), 8 deletions(-) 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 0ae2123b0f..4ab978b7f9 100644 --- a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp +++ b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.cpp @@ -1120,26 +1120,59 @@ bool backhaul_manager::backhaul_fsm_main(bool &skip_select) bool backhaul_manager::send_1905_topology_discovery_message() { + // TODO: get the list of interfaces that are up_and_running using the event-driven mechanism + // to be implemented in #866 + + /** + * Transmission type of Topology Discovery message is 'neighbor multicast'. + * That is, the CMDU must be transmitted once on each and every of its 1905.1 interfaces. + * Also, according to IEEE1905.1, the message should include a MAC Address TLV which contains + * the address of the interface on which the message is sent. Thus, a different message should + * be sent on each interface. + */ + auto ifaces = network_utils::linux_get_iface_list_from_bridge(m_sConfig.bridge_iface); + for (const auto &iface_name : ifaces) { + if (!network_utils::linux_iface_is_up_and_running(iface_name)) { + continue; + } + + send_1905_topology_discovery_message(iface_name); + } + + return true; +} + +bool backhaul_manager::send_1905_topology_discovery_message(const std::string &iface_name) +{ + sMacAddr iface_mac; + if (!get_iface_mac(iface_name, iface_mac)) { + return false; + } + auto cmdu_hdr = cmdu_tx.create(0, ieee1905_1::eMessageType::TOPOLOGY_DISCOVERY_MESSAGE); if (!cmdu_hdr) { LOG(ERROR) << "Failed to create TOPOLOGY_DISCOVERY_MESSAGE cmdu"; return false; } - auto tlvAlMac = cmdu_tx.addClass(); - if (!tlvAlMac) { + + auto tlvAlMacAddress = cmdu_tx.addClass(); + if (!tlvAlMacAddress) { LOG(ERROR) << "Failed to create tlvAlMacAddress tlv"; return false; } - tlvAlMac->mac() = tlvf::mac_from_string(bridge_info.mac); - auto tlvMac = cmdu_tx.addClass(); - if (!tlvMac) { + tlvAlMacAddress->mac() = tlvf::mac_from_string(bridge_info.mac); + + auto tlvMacAddress = cmdu_tx.addClass(); + if (!tlvMacAddress) { LOG(ERROR) << "Failed to create tlvMacAddress tlv"; return false; } - tlvMac->mac() = tlvf::mac_from_string(bridge_info.mac); + tlvMacAddress->mac() = iface_mac; - LOG(DEBUG) << "send_1905_topology_discovery_message, bridge_mac=" << bridge_info.mac; - return send_cmdu_to_bus(cmdu_tx, network_utils::MULTICAST_1905_MAC_ADDR, bridge_info.mac); + LOG(DEBUG) << "send_1905_topology_discovery_message, bridge_mac=" << bridge_info.mac + << ", iface=" << iface_name; + return send_cmdu_to_bus(cmdu_tx, network_utils::MULTICAST_1905_MAC_ADDR, bridge_info.mac, + iface_name); } bool backhaul_manager::send_autoconfig_search_message(std::shared_ptr soc) 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 1980241986..64a244c41c 100644 --- a/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.h +++ b/agent/src/beerocks/slave/backhaul_manager/backhaul_manager_thread.h @@ -91,6 +91,15 @@ class backhaul_manager : public btl::transport_socket_thread { bool send_autoconfig_search_message(std::shared_ptr soc); bool send_1905_topology_discovery_message(); + + /** + * @brief Sends Topology Discovery message on given interface. + * + * @param iface_name Name of the network interface on which the message is transmitted. + * @return True on success and false otherwise + */ + bool send_1905_topology_discovery_message(const std::string &iface_name); + bool send_slave_ap_metric_query_message(uint16_t mid, std::vector const &bssid_list); // cmdu handlers From 1605bb710f9fdb9cdbb1c5a532b838d78ee3d62d Mon Sep 17 00:00:00 2001 From: Vladyslav Tupikin Date: Thu, 11 Jun 2020 16:37:55 +0300 Subject: [PATCH 25/28] framework: tlvf: Turn on Backhaul STA Steering TLV's For auto-generating TLV for Backhaul STA Steering Request/Response needs to add yaml files to the tlv_conf.yaml. It is turning on auto-generation code from those TLV. Signed-off-by: Vladyslav Tupikin --- .../tlvf/wfa_map/tlvBackhaulSteeringRequest.h | 58 +++++++ .../wfa_map/tlvBackhaulSteeringResponse.h | 61 +++++++ .../wfa_map/tlvBackhaulSteeringRequest.cpp | 153 ++++++++++++++++++ .../wfa_map/tlvBackhaulSteeringResponse.cpp | 143 ++++++++++++++++ framework/tlvf/tlvf_conf.yaml | 2 + 5 files changed, 417 insertions(+) create mode 100644 framework/tlvf/AutoGenerated/include/tlvf/wfa_map/tlvBackhaulSteeringRequest.h create mode 100644 framework/tlvf/AutoGenerated/include/tlvf/wfa_map/tlvBackhaulSteeringResponse.h create mode 100644 framework/tlvf/AutoGenerated/src/tlvf/wfa_map/tlvBackhaulSteeringRequest.cpp create mode 100644 framework/tlvf/AutoGenerated/src/tlvf/wfa_map/tlvBackhaulSteeringResponse.cpp diff --git a/framework/tlvf/AutoGenerated/include/tlvf/wfa_map/tlvBackhaulSteeringRequest.h b/framework/tlvf/AutoGenerated/include/tlvf/wfa_map/tlvBackhaulSteeringRequest.h new file mode 100644 index 0000000000..4298516803 --- /dev/null +++ b/framework/tlvf/AutoGenerated/include/tlvf/wfa_map/tlvBackhaulSteeringRequest.h @@ -0,0 +1,58 @@ +/////////////////////////////////////// +// AUTO GENERATED FILE - DO NOT EDIT // +/////////////////////////////////////// + +/* 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 _TLVF_WFA_MAP_TLVBACKHAULSTEERINGREQUEST_H_ +#define _TLVF_WFA_MAP_TLVBACKHAULSTEERINGREQUEST_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "tlvf/wfa_map/eTlvTypeMap.h" +#include "tlvf/common/sMacAddr.h" + +namespace wfa_map { + + +class tlvBackhaulSteeringRequest : public BaseClass +{ + public: + tlvBackhaulSteeringRequest(uint8_t* buff, size_t buff_len, bool parse = false); + explicit tlvBackhaulSteeringRequest(std::shared_ptr base, bool parse = false); + ~tlvBackhaulSteeringRequest(); + + const eTlvTypeMap& type(); + const uint16_t& length(); + sMacAddr& backhaul_station_mac(); + sMacAddr& target_bssid(); + uint8_t& operating_class(); + uint8_t& target_channel_number(); + void class_swap() override; + bool finalize() override; + static size_t get_initial_size(); + + private: + bool init(); + eTlvTypeMap* m_type = nullptr; + uint16_t* m_length = nullptr; + sMacAddr* m_backhaul_station_mac = nullptr; + sMacAddr* m_target_bssid = nullptr; + uint8_t* m_operating_class = nullptr; + uint8_t* m_target_channel_number = nullptr; +}; + +}; // close namespace: wfa_map + +#endif //_TLVF/WFA_MAP_TLVBACKHAULSTEERINGREQUEST_H_ diff --git a/framework/tlvf/AutoGenerated/include/tlvf/wfa_map/tlvBackhaulSteeringResponse.h b/framework/tlvf/AutoGenerated/include/tlvf/wfa_map/tlvBackhaulSteeringResponse.h new file mode 100644 index 0000000000..c3536d1dc0 --- /dev/null +++ b/framework/tlvf/AutoGenerated/include/tlvf/wfa_map/tlvBackhaulSteeringResponse.h @@ -0,0 +1,61 @@ +/////////////////////////////////////// +// AUTO GENERATED FILE - DO NOT EDIT // +/////////////////////////////////////// + +/* 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 _TLVF_WFA_MAP_TLVBACKHAULSTEERINGRESPONSE_H_ +#define _TLVF_WFA_MAP_TLVBACKHAULSTEERINGRESPONSE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "tlvf/wfa_map/eTlvTypeMap.h" +#include "tlvf/common/sMacAddr.h" + +namespace wfa_map { + + +class tlvBackhaulSteeringResponse : public BaseClass +{ + public: + tlvBackhaulSteeringResponse(uint8_t* buff, size_t buff_len, bool parse = false); + explicit tlvBackhaulSteeringResponse(std::shared_ptr base, bool parse = false); + ~tlvBackhaulSteeringResponse(); + + enum eResultCode: uint8_t { + SUCCESS = 0x0, + FAILURE = 0x1, + }; + + const eTlvTypeMap& type(); + const uint16_t& length(); + sMacAddr& backhaul_station_mac(); + sMacAddr& target_bssid(); + eResultCode& result_code(); + void class_swap() override; + bool finalize() override; + static size_t get_initial_size(); + + private: + bool init(); + eTlvTypeMap* m_type = nullptr; + uint16_t* m_length = nullptr; + sMacAddr* m_backhaul_station_mac = nullptr; + sMacAddr* m_target_bssid = nullptr; + eResultCode* m_result_code = nullptr; +}; + +}; // close namespace: wfa_map + +#endif //_TLVF/WFA_MAP_TLVBACKHAULSTEERINGRESPONSE_H_ diff --git a/framework/tlvf/AutoGenerated/src/tlvf/wfa_map/tlvBackhaulSteeringRequest.cpp b/framework/tlvf/AutoGenerated/src/tlvf/wfa_map/tlvBackhaulSteeringRequest.cpp new file mode 100644 index 0000000000..f8d211cd5f --- /dev/null +++ b/framework/tlvf/AutoGenerated/src/tlvf/wfa_map/tlvBackhaulSteeringRequest.cpp @@ -0,0 +1,153 @@ +/////////////////////////////////////// +// AUTO GENERATED FILE - DO NOT EDIT // +/////////////////////////////////////// + +/* 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. + */ + +#include +#include + +using namespace wfa_map; + +tlvBackhaulSteeringRequest::tlvBackhaulSteeringRequest(uint8_t* buff, size_t buff_len, bool parse) : + BaseClass(buff, buff_len, parse) { + m_init_succeeded = init(); +} +tlvBackhaulSteeringRequest::tlvBackhaulSteeringRequest(std::shared_ptr base, bool parse) : +BaseClass(base->getBuffPtr(), base->getBuffRemainingBytes(), parse){ + m_init_succeeded = init(); +} +tlvBackhaulSteeringRequest::~tlvBackhaulSteeringRequest() { +} +const eTlvTypeMap& tlvBackhaulSteeringRequest::type() { + return (const eTlvTypeMap&)(*m_type); +} + +const uint16_t& tlvBackhaulSteeringRequest::length() { + return (const uint16_t&)(*m_length); +} + +sMacAddr& tlvBackhaulSteeringRequest::backhaul_station_mac() { + return (sMacAddr&)(*m_backhaul_station_mac); +} + +sMacAddr& tlvBackhaulSteeringRequest::target_bssid() { + return (sMacAddr&)(*m_target_bssid); +} + +uint8_t& tlvBackhaulSteeringRequest::operating_class() { + return (uint8_t&)(*m_operating_class); +} + +uint8_t& tlvBackhaulSteeringRequest::target_channel_number() { + return (uint8_t&)(*m_target_channel_number); +} + +void tlvBackhaulSteeringRequest::class_swap() +{ + tlvf_swap(16, reinterpret_cast(m_length)); + m_backhaul_station_mac->struct_swap(); + m_target_bssid->struct_swap(); +} + +bool tlvBackhaulSteeringRequest::finalize() +{ + if (m_parse__) { + TLVF_LOG(DEBUG) << "finalize() called but m_parse__ is set"; + return true; + } + if (m_finalized__) { + TLVF_LOG(DEBUG) << "finalize() called for already finalized class"; + return true; + } + if (!isPostInitSucceeded()) { + TLVF_LOG(ERROR) << "post init check failed"; + return false; + } + if (m_inner__) { + if (!m_inner__->finalize()) { + TLVF_LOG(ERROR) << "m_inner__->finalize() failed"; + return false; + } + auto tailroom = m_inner__->getMessageBuffLength() - m_inner__->getMessageLength(); + m_buff_ptr__ -= tailroom; + *m_length -= tailroom; + } + class_swap(); + m_finalized__ = true; + return true; +} + +size_t tlvBackhaulSteeringRequest::get_initial_size() +{ + size_t class_size = 0; + class_size += sizeof(eTlvTypeMap); // type + class_size += sizeof(uint16_t); // length + class_size += sizeof(sMacAddr); // backhaul_station_mac + class_size += sizeof(sMacAddr); // target_bssid + class_size += sizeof(uint8_t); // operating_class + class_size += sizeof(uint8_t); // target_channel_number + return class_size; +} + +bool tlvBackhaulSteeringRequest::init() +{ + if (getBuffRemainingBytes() < get_initial_size()) { + TLVF_LOG(ERROR) << "Not enough available space on buffer. Class init failed"; + return false; + } + m_type = reinterpret_cast(m_buff_ptr__); + if (!m_parse__) *m_type = eTlvTypeMap::TLV_BACKHAUL_STEERING_REQUEST; + if (!buffPtrIncrementSafe(sizeof(eTlvTypeMap))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(eTlvTypeMap) << ") Failed!"; + return false; + } + m_length = reinterpret_cast(m_buff_ptr__); + if (!m_parse__) *m_length = 0; + if (!buffPtrIncrementSafe(sizeof(uint16_t))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(uint16_t) << ") Failed!"; + return false; + } + m_backhaul_station_mac = reinterpret_cast(m_buff_ptr__); + if (!buffPtrIncrementSafe(sizeof(sMacAddr))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(sMacAddr) << ") Failed!"; + return false; + } + if(m_length && !m_parse__){ (*m_length) += sizeof(sMacAddr); } + if (!m_parse__) { m_backhaul_station_mac->struct_init(); } + m_target_bssid = reinterpret_cast(m_buff_ptr__); + if (!buffPtrIncrementSafe(sizeof(sMacAddr))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(sMacAddr) << ") Failed!"; + return false; + } + if(m_length && !m_parse__){ (*m_length) += sizeof(sMacAddr); } + if (!m_parse__) { m_target_bssid->struct_init(); } + m_operating_class = reinterpret_cast(m_buff_ptr__); + if (!buffPtrIncrementSafe(sizeof(uint8_t))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(uint8_t) << ") Failed!"; + return false; + } + if(m_length && !m_parse__){ (*m_length) += sizeof(uint8_t); } + m_target_channel_number = reinterpret_cast(m_buff_ptr__); + if (!buffPtrIncrementSafe(sizeof(uint8_t))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(uint8_t) << ") Failed!"; + return false; + } + if(m_length && !m_parse__){ (*m_length) += sizeof(uint8_t); } + if (m_parse__) { class_swap(); } + if (m_parse__) { + if (*m_type != eTlvTypeMap::TLV_BACKHAUL_STEERING_REQUEST) { + TLVF_LOG(ERROR) << "TLV type mismatch. Expected value: " << int(eTlvTypeMap::TLV_BACKHAUL_STEERING_REQUEST) << ", received value: " << int(*m_type); + return false; + } + } + return true; +} + + diff --git a/framework/tlvf/AutoGenerated/src/tlvf/wfa_map/tlvBackhaulSteeringResponse.cpp b/framework/tlvf/AutoGenerated/src/tlvf/wfa_map/tlvBackhaulSteeringResponse.cpp new file mode 100644 index 0000000000..9d3b307777 --- /dev/null +++ b/framework/tlvf/AutoGenerated/src/tlvf/wfa_map/tlvBackhaulSteeringResponse.cpp @@ -0,0 +1,143 @@ +/////////////////////////////////////// +// AUTO GENERATED FILE - DO NOT EDIT // +/////////////////////////////////////// + +/* 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. + */ + +#include +#include + +using namespace wfa_map; + +tlvBackhaulSteeringResponse::tlvBackhaulSteeringResponse(uint8_t* buff, size_t buff_len, bool parse) : + BaseClass(buff, buff_len, parse) { + m_init_succeeded = init(); +} +tlvBackhaulSteeringResponse::tlvBackhaulSteeringResponse(std::shared_ptr base, bool parse) : +BaseClass(base->getBuffPtr(), base->getBuffRemainingBytes(), parse){ + m_init_succeeded = init(); +} +tlvBackhaulSteeringResponse::~tlvBackhaulSteeringResponse() { +} +const eTlvTypeMap& tlvBackhaulSteeringResponse::type() { + return (const eTlvTypeMap&)(*m_type); +} + +const uint16_t& tlvBackhaulSteeringResponse::length() { + return (const uint16_t&)(*m_length); +} + +sMacAddr& tlvBackhaulSteeringResponse::backhaul_station_mac() { + return (sMacAddr&)(*m_backhaul_station_mac); +} + +sMacAddr& tlvBackhaulSteeringResponse::target_bssid() { + return (sMacAddr&)(*m_target_bssid); +} + +tlvBackhaulSteeringResponse::eResultCode& tlvBackhaulSteeringResponse::result_code() { + return (eResultCode&)(*m_result_code); +} + +void tlvBackhaulSteeringResponse::class_swap() +{ + tlvf_swap(16, reinterpret_cast(m_length)); + m_backhaul_station_mac->struct_swap(); + m_target_bssid->struct_swap(); + tlvf_swap(8*sizeof(eResultCode), reinterpret_cast(m_result_code)); +} + +bool tlvBackhaulSteeringResponse::finalize() +{ + if (m_parse__) { + TLVF_LOG(DEBUG) << "finalize() called but m_parse__ is set"; + return true; + } + if (m_finalized__) { + TLVF_LOG(DEBUG) << "finalize() called for already finalized class"; + return true; + } + if (!isPostInitSucceeded()) { + TLVF_LOG(ERROR) << "post init check failed"; + return false; + } + if (m_inner__) { + if (!m_inner__->finalize()) { + TLVF_LOG(ERROR) << "m_inner__->finalize() failed"; + return false; + } + auto tailroom = m_inner__->getMessageBuffLength() - m_inner__->getMessageLength(); + m_buff_ptr__ -= tailroom; + *m_length -= tailroom; + } + class_swap(); + m_finalized__ = true; + return true; +} + +size_t tlvBackhaulSteeringResponse::get_initial_size() +{ + size_t class_size = 0; + class_size += sizeof(eTlvTypeMap); // type + class_size += sizeof(uint16_t); // length + class_size += sizeof(sMacAddr); // backhaul_station_mac + class_size += sizeof(sMacAddr); // target_bssid + class_size += sizeof(eResultCode); // result_code + return class_size; +} + +bool tlvBackhaulSteeringResponse::init() +{ + if (getBuffRemainingBytes() < get_initial_size()) { + TLVF_LOG(ERROR) << "Not enough available space on buffer. Class init failed"; + return false; + } + m_type = reinterpret_cast(m_buff_ptr__); + if (!m_parse__) *m_type = eTlvTypeMap::TLV_BACKHAUL_STEERING_RESPONSE; + if (!buffPtrIncrementSafe(sizeof(eTlvTypeMap))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(eTlvTypeMap) << ") Failed!"; + return false; + } + m_length = reinterpret_cast(m_buff_ptr__); + if (!m_parse__) *m_length = 0; + if (!buffPtrIncrementSafe(sizeof(uint16_t))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(uint16_t) << ") Failed!"; + return false; + } + m_backhaul_station_mac = reinterpret_cast(m_buff_ptr__); + if (!buffPtrIncrementSafe(sizeof(sMacAddr))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(sMacAddr) << ") Failed!"; + return false; + } + if(m_length && !m_parse__){ (*m_length) += sizeof(sMacAddr); } + if (!m_parse__) { m_backhaul_station_mac->struct_init(); } + m_target_bssid = reinterpret_cast(m_buff_ptr__); + if (!buffPtrIncrementSafe(sizeof(sMacAddr))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(sMacAddr) << ") Failed!"; + return false; + } + if(m_length && !m_parse__){ (*m_length) += sizeof(sMacAddr); } + if (!m_parse__) { m_target_bssid->struct_init(); } + m_result_code = reinterpret_cast(m_buff_ptr__); + if (!buffPtrIncrementSafe(sizeof(eResultCode))) { + LOG(ERROR) << "buffPtrIncrementSafe(" << std::dec << sizeof(eResultCode) << ") Failed!"; + return false; + } + if(m_length && !m_parse__){ (*m_length) += sizeof(eResultCode); } + if (m_parse__) { class_swap(); } + if (m_parse__) { + if (*m_type != eTlvTypeMap::TLV_BACKHAUL_STEERING_RESPONSE) { + TLVF_LOG(ERROR) << "TLV type mismatch. Expected value: " << int(eTlvTypeMap::TLV_BACKHAUL_STEERING_RESPONSE) << ", received value: " << int(*m_type); + return false; + } + } + return true; +} + + diff --git a/framework/tlvf/tlvf_conf.yaml b/framework/tlvf/tlvf_conf.yaml index 702c5ca15a..4c936eaf83 100644 --- a/framework/tlvf/tlvf_conf.yaml +++ b/framework/tlvf/tlvf_conf.yaml @@ -46,6 +46,8 @@ include_yaml_path: { "tlvf/wfa_map/tlvSupportedService.yaml", "tlvf/wfa_map/tlvTimestamp.yaml", "tlvf/wfa_map/tlvTransmitPowerLimit.yaml", + "tlvf/wfa_map/tlvBackhaulSteeringRequest.yaml", + "tlvf/wfa_map/tlvBackhaulSteeringResponse.yaml", } # Relative to tlvf.py src_path variable From 7af3b1901d4627128110bccced88ab4b6e80ee90 Mon Sep 17 00:00:00 2001 From: Vladyslav Tupikin Date: Mon, 15 Jun 2020 15:40:58 +0300 Subject: [PATCH 26/28] tlvf: CmduMessageRx: Add case for Backhaul STA Steering In the method parseNextTlv() missing cases for Backhaul STA Steering Request/Response TLV's. Add missing cases with correct values for message types. Signed-off-by: Vladyslav Tupikin --- framework/tlvf/src/src/CmduMessageRx.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/framework/tlvf/src/src/CmduMessageRx.cpp b/framework/tlvf/src/src/CmduMessageRx.cpp index 6080528575..db43454d90 100644 --- a/framework/tlvf/src/src/CmduMessageRx.cpp +++ b/framework/tlvf/src/src/CmduMessageRx.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -230,6 +232,12 @@ std::shared_ptr CmduMessageRx::parseNextTlv() case (157): { return msg.addClass(); } + case (158): { + return msg.addClass(); + } + case (159): { + return msg.addClass(); + } case (160): { return msg.addClass(); } From d2e2989d9cbdd71d5d70e17a3aaf8abd83f5dc91 Mon Sep 17 00:00:00 2001 From: Vladyslav Tupikin Date: Tue, 9 Jun 2020 15:18:58 +0300 Subject: [PATCH 27/28] 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 | 364 +++++++++--------- .../backhaul_manager_thread.h | 40 +- .../internal/expected_ap_metrics_response.cpp | 42 ++ .../internal/expected_ap_metrics_response.h | 54 +++ 5 files changed, 283 insertions(+), 218 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 4ab978b7f9..20d7f24dbf 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: @@ -1025,21 +1023,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"; } @@ -1268,51 +1261,101 @@ 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 thier hash values + auto mac_comp = [](const sMacAddr &addr1, const sMacAddr &addr2) -> bool { + return std::hash()(addr1) < std::hash()(addr2); + }; + + // sort the given bssid list + std::vector given_bssid_list = bssid_list; + std::sort(given_bssid_list.begin(), given_bssid_list.end(), mac_comp); + + // debug + LOG(DEBUG) << "given bssid list for current socket, " << given_bssid_list.size() + << " bssids:" << '\n'; + for (auto &bssid : given_bssid_list) { + LOG(DEBUG) << bssid << '\n'; + } + // end debug + + // for each socket - send only relevant bssids + auto ret = false; 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); + + // debug + LOG(DEBUG) << "bssid list for current socket, " << required_bssids.size() + << " bssids:" << '\n'; + for (auto &bssid : required_bssids) { + LOG(DEBUG) << bssid << '\n'; + } + // end debug + + 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; + } else { + ret = true; + } } + return ret; -} +} // namespace beerocks bool backhaul_manager::backhaul_fsm_wireless(bool &skip_select) { @@ -2572,8 +2615,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"; @@ -2585,14 +2632,22 @@ 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)); + + // #1421 implementation + 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"; - return false; + LOG(DEBUG) << "Forwarding AP_METRICS_QUERY_MESSAGE to all slaves, mid=" << std::hex << int(mid); + uint16_t length = message_com::get_uds_header(cmdu_rx)->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; @@ -2602,33 +2657,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); + 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; } - /** - * 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 (mid == 0) { + 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()); } + 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 @@ -2636,44 +2681,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"; @@ -2684,98 +2749,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}); + auto sta_link_metric_response_tlv = + ap_metrics_tx_message.addClass(); - // 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; - } - - 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 64a244c41c..16d07988ae 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..940361d952 --- /dev/null +++ b/agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.cpp @@ -0,0 +1,42 @@ + +#include "expected_ap_metrics_response.h" + +// mid +void ExpectedApMetricsResponse::reset_to_new_mid(uint16_t mid) +{ + _mid = mid; + _expected_bssid_list.clear(); + _response.reset(); + memset(_response_buffer, 0, sizeof(_response_buffer)); +} + +uint16_t ExpectedApMetricsResponse::get_mid() const { return _mid; } + +// bssid +void ExpectedApMetricsResponse::add_expected_bssid(const sMacAddr &bssid) +{ + _expected_bssid_list.insert(bssid); +} + +void ExpectedApMetricsResponse::remove_expected_bssid(const sMacAddr &bssid) +{ + _expected_bssid_list.erase(bssid); +} + +bool ExpectedApMetricsResponse::is_expected_bssid_empty() const +{ + return _expected_bssid_list.empty(); +} + +bool ExpectedApMetricsResponse::find_expected_bssid(const sMacAddr &bssid) const +{ + return _expected_bssid_list.find(bssid) != _expected_bssid_list.end(); +} + +// cmdu message +ieee1905_1::CmduMessageTx &ExpectedApMetricsResponse::create_tx_message() +{ + _response.create(_mid, ieee1905_1::eMessageType::AP_METRICS_RESPONSE_MESSAGE); + + return _response; +} 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..5541e4359c --- /dev/null +++ b/agent/src/beerocks/slave/backhaul_manager/internal/expected_ap_metrics_response.h @@ -0,0 +1,54 @@ +/* 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 + +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); + uint16_t get_mid() const; + ieee1905_1::CmduMessageTx &create_tx_message(); + + // bssid related operations +public: + template void add_expected_bssid(FirstIt first, LastIt last); + void add_expected_bssid(const sMacAddr &bssid); + void remove_expected_bssid(const sMacAddr &); + bool find_expected_bssid(const sMacAddr &) const; + bool is_expected_bssid_empty() const; + +private: + uint16_t _mid = 0; + std::unordered_set _expected_bssid_list; + +private: + uint8_t _response_buffer[beerocks::message::MESSAGE_BUFFER_LENGTH] = {0}; + ieee1905_1::CmduMessageTx _response = {_response_buffer, sizeof(_response_buffer)}; +}; + +template +void ExpectedApMetricsResponse::add_expected_bssid(FirstIt first, LastIt last) +{ + _expected_bssid_list.insert(first, last); +} + +#endif From 4207979f6399d4393caa9b915a015f2427bfcd9e Mon Sep 17 00:00:00 2001 From: Ran Regev Date: Tue, 16 Jun 2020 17:47:26 +0300 Subject: [PATCH 28/28] 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 --- tests/test_flows.py | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/test_flows.py b/tests/test_flows.py index 065e806d22..9f8e897bfe 100755 --- a/tests/test_flows.py +++ b/tests/test_flows.py @@ -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[0].radios[0].vaps[0].disassociate(sta2) + if __name__ == '__main__': t = TestFlows()