From 9c0a65f62132409b55923ee78c1bad19003332ee Mon Sep 17 00:00:00 2001 From: Durmus Koyuncu Date: Wed, 22 Apr 2026 14:05:44 +0300 Subject: [PATCH] RDKBWIFI-402: Implement IEEE 1905.1 Backhaul Steering Add rbus handler and event processing for backhaul steering requests received from the EasyMesh agent. On receipt, the target mesh backhaul STA VAP is looked up by MAC address and the connection state machine is triggered with the target BSSID. --- include/wifi_events.h | 1 + source/apps/em/wifi_em.c | 147 ++++++++++++++++++++++++- source/apps/em/wifi_em.h | 1 + source/core/wifi_ctrl_queue_handlers.c | 3 +- source/core/wifi_events.c | 1 + 5 files changed, 151 insertions(+), 2 deletions(-) diff --git a/include/wifi_events.h b/include/wifi_events.h index 54c507b94..b48a118e7 100644 --- a/include/wifi_events.h +++ b/include/wifi_events.h @@ -186,6 +186,7 @@ typedef enum { wifi_event_type_sm_app_enable, wifi_event_type_link_quality_rfc, wifi_event_type_send_btm_req, + wifi_event_type_backhaul_steer, wifi_event_command_max, wifi_event_monitor_diagnostics = wifi_event_type_base diff --git a/source/apps/em/wifi_em.c b/source/apps/em/wifi_em.c index b0f1b0f9f..466919f58 100644 --- a/source/apps/em/wifi_em.c +++ b/source/apps/em/wifi_em.c @@ -89,6 +89,13 @@ typedef struct { em_ap_radio_report_t radio_report[MAX_NUM_RADIOS]; } em_ap_metrics_report_cache_t; +typedef struct { + mac_addr_t bh_sta_mac_addr; + bssid_t target_bssid; + unsigned char op_class; + unsigned char channel_num; +} __attribute__((packed)) bh_steering_req_t; + //em_ap_metrics_report_cache_t em_ap_metrics_report_cache[MAX_NUM_RADIOS] = { 0 }; em_ap_metrics_report_cache_t em_ap_metrics_report_cache = { 0 }; client_assoc_stats_t client_assoc_stats[MAX_NUM_RADIOS] = { 0 }; @@ -2863,6 +2870,136 @@ static void em_toggle_disconn_steady_state(void *data, unsigned int len) return bus_error_success; } +static wifi_vap_info_t *get_mesh_sta_vap_by_mac(wifi_mgr_t *mgr, unsigned char *mac) +{ + unsigned int r, i, num_vaps; + + if (mgr == NULL || mac == NULL) { + wifi_util_error_print(WIFI_EM, "%s:%d NULL input (mgr=%p mac=%p)\n", + __func__, __LINE__, mgr, mac); + return NULL; + } + + for (r = 0; r < MAX_NUM_RADIOS; r++) { + num_vaps = mgr->radio_config[r].vaps.vap_map.num_vaps; + for (i = 0; i < num_vaps; i++) { + wifi_vap_info_t *v = &mgr->radio_config[r].vaps.vap_map.vap_array[i]; + if (vap_svc_is_mesh_ext(v->vap_index) && + memcmp(v->u.sta_info.mac, mac, sizeof(mac_addr_t)) == 0) { + return v; + } + } + } + return NULL; +} + +static void em_handle_backhaul_steer(void *data, unsigned int len) +{ + bh_steering_req_t *req; + wifi_mgr_t *mgr; + wifi_ctrl_t *ctrl; + vap_svc_t *ext_svc; + wifi_vap_info_t *sta_vap; + wifi_vap_info_t steer_vap; + mac_addr_str_t sta_str, bssid_str; + + if (data == NULL) { + wifi_util_error_print(WIFI_EM, "%s:%d NULL data pointer\n", __func__, __LINE__); + return; + } + + if (len != sizeof(bh_steering_req_t)) { + wifi_util_error_print(WIFI_EM, "%s:%d Invalid length %u, expected %zu\n", + __func__, __LINE__, len, sizeof(bh_steering_req_t)); + return; + } + + req = (bh_steering_req_t *)data; + to_mac_str(req->bh_sta_mac_addr, sta_str); + to_mac_str(req->target_bssid, bssid_str); + wifi_util_info_print(WIFI_EM, + "%s:%d BH Steer Request received: sta=%s target_bssid=%s op_class=%d channel=%d\n", + __func__, __LINE__, sta_str, bssid_str, req->op_class, req->channel_num); + + mgr = (wifi_mgr_t *)get_wifimgr_obj(); + if (mgr == NULL) { + wifi_util_error_print(WIFI_EM, "%s:%d wifi mgr object is NULL\n", + __func__, __LINE__); + return; + } + + sta_vap = get_mesh_sta_vap_by_mac(mgr, req->bh_sta_mac_addr); + if (sta_vap == NULL) { + wifi_util_error_print(WIFI_EM, + "%s:%d No mesh STA vap found for sta=%s\n", + __func__, __LINE__, sta_str); + return; + } + + wifi_util_info_print(WIFI_EM, + "%s:%d Mesh STA vap_index=%d ssid='%s' -> target_bssid=%s\n", + __func__, __LINE__, sta_vap->vap_index, + sta_vap->u.sta_info.ssid, bssid_str); + + // Trigger the mesh STA connection state machine with the target BSSID. + steer_vap = *sta_vap; + memcpy(steer_vap.u.sta_info.bssid, req->target_bssid, sizeof(bssid_t)); + + ctrl = (wifi_ctrl_t *)get_wifictrl_obj(); + if (ctrl == NULL) { + wifi_util_error_print(WIFI_EM, "%s:%d wifi ctrl object is NULL\n", + __func__, __LINE__); + return; + } + + ext_svc = get_svc_by_type(ctrl, vap_svc_type_mesh_ext); + if (ext_svc == NULL) { + wifi_util_error_print(WIFI_EM, + "%s:%d mesh ext service not available\n", __func__, __LINE__); + return; + } + + ext_svc->event_fn(ext_svc, wifi_event_type_webconfig, + wifi_event_webconfig_set_data_sta_bssid, vap_svc_event_none, &steer_vap); +} + +bus_error_t em_backhaul_steer(char *name, raw_data_t *p_data) +{ + char *pTmp = NULL; + + if (!name) { + wifi_util_error_print(WIFI_EM, "%s:%d Property name is not found\n", + __func__, __LINE__); + return bus_error_element_name_missing; + } + + if (p_data == NULL) { + wifi_util_error_print(WIFI_EM, "%s:%d NULL p_data\n", __func__, __LINE__); + return bus_error_invalid_input; + } + + pTmp = (char *)p_data->raw_data.bytes; + if ((p_data->data_type != bus_data_type_bytes) || (pTmp == NULL)) { + wifi_util_error_print(WIFI_EM, "%s:%d Wrong bus data_type:%x or null data\n", + __func__, __LINE__, p_data->data_type); + return bus_error_invalid_input; + } + + if (p_data->raw_data_len != sizeof(bh_steering_req_t)) { + wifi_util_error_print(WIFI_EM, + "%s:%d Invalid raw_data_len %u, expected %zu\n", + __func__, __LINE__, p_data->raw_data_len, sizeof(bh_steering_req_t)); + return bus_error_invalid_input; + } + + wifi_util_info_print(WIFI_EM, "%s:%d Pushing event to ctrl queue (len=%u)\n", + __func__, __LINE__, p_data->raw_data_len); + push_event_to_ctrl_queue(pTmp, p_data->raw_data_len, wifi_event_type_command, + wifi_event_type_backhaul_steer, NULL); + + return bus_error_success; +} + void handle_em_command_event(wifi_app_t *app, wifi_event_t *event) { switch (event->sub_type) { @@ -2907,6 +3044,11 @@ void handle_em_command_event(wifi_app_t *app, wifi_event_t *event) case wifi_event_type_toggle_disconn_steady_state: em_toggle_disconn_steady_state(event->u.core_data.msg, event->u.core_data.len); break; + + case wifi_event_type_backhaul_steer: + em_handle_backhaul_steer(event->u.core_data.msg, event->u.core_data.len); + break; + default: break; } @@ -3379,7 +3521,10 @@ int em_init(wifi_app_t *app, unsigned int create_flag) { bus_data_type_bytes, true, 0, 0, 0, NULL } }, { WIFI_EM_FAILED_CONNECTION, bus_element_type_event, { NULL, NULL, NULL, NULL, NULL, NULL }, slow_speed, ZERO_TABLE, - { bus_data_type_string, false, 0, 0, 0, NULL } } + { bus_data_type_string, false, 0, 0, 0, NULL } }, + { WIFI_EM_BACKHAUL_STEER, bus_element_type_method, + { NULL, em_backhaul_steer, NULL, NULL, NULL, NULL}, slow_speed, ZERO_TABLE, + { bus_data_type_bytes, true, 0, 0, 0, NULL } } }; policy_config->btm_steering_dslw_policy.sta_count = 0; diff --git a/source/apps/em/wifi_em.h b/source/apps/em/wifi_em.h index e87ca7516..695f9e55e 100644 --- a/source/apps/em/wifi_em.h +++ b/source/apps/em/wifi_em.h @@ -37,6 +37,7 @@ extern "C" { #define WIFI_SET_DISCONN_SCAN_NONE_STATE "Device.WiFi.EM.SetDisconnScanNoneState" #define WIFI_EM_CLIENT_ASSOC_CTRL_REQ "Device.WiFi.EM.ClientAssocCtrlRequest" #define WIFI_EM_FAILED_CONNECTION "Device.WiFi.EM.FailedConnection" +#define WIFI_EM_BACKHAUL_STEER "Device.WiFi.EM.BackhaulSteer" #define WNM_CATEGORY 10 #define IEEE80211_HDRLEN 24 diff --git a/source/core/wifi_ctrl_queue_handlers.c b/source/core/wifi_ctrl_queue_handlers.c index 1ffdd74e2..5231cc4c0 100644 --- a/source/core/wifi_ctrl_queue_handlers.c +++ b/source/core/wifi_ctrl_queue_handlers.c @@ -4531,7 +4531,8 @@ void handle_command_event(wifi_ctrl_t *ctrl, void *data, unsigned int len, case wifi_event_type_stop_inst_msmt: case wifi_event_type_xfinity_rrm: case wifi_event_type_sm_app_enable: - // not handle here + case wifi_event_type_backhaul_steer: + // not handled here, forwarded to apps break; default: wifi_util_error_print(WIFI_CTRL, "[%s]:WIFI hal handler not supported this event %s\r\n", diff --git a/source/core/wifi_events.c b/source/core/wifi_events.c index a2b3544a6..dbbca7ea3 100644 --- a/source/core/wifi_events.c +++ b/source/core/wifi_events.c @@ -164,6 +164,7 @@ const char *wifi_event_subtype_to_string(wifi_event_subtype_t type) DOC2S(wifi_event_type_sta_client_info) DOC2S(wifi_event_type_sm_app_enable) DOC2S(wifi_event_type_send_btm_req) + DOC2S(wifi_event_type_backhaul_steer) DOC2S(wifi_event_command_max) DOC2S(wifi_event_monitor_diagnostics) DOC2S(wifi_event_monitor_connect)