diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h b/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h index 4356bd2a9a..272bdb7cad 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -766,14 +766,12 @@ cm_send_rso_stop(struct wlan_objmgr_vdev *vdev) /** * cm_get_ml_partner_info() - Fill ML partner info from scan entry * @pdev: PDEV object - * @scan_entry: Scan entry - * @partner_info: Partner info to be filled + * @conn_req: Connect request pointer * * Return: QDF_STATUS */ QDF_STATUS cm_get_ml_partner_info(struct wlan_objmgr_pdev *pdev, - struct scan_cache_entry *scan_entry, - struct mlo_partner_info *partner_info); + struct cm_connect_req *conn_req); #endif #endif /* __WLAN_CM_VDEV_API_H__ */ diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c index ad909e9b96..b842c23802 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1162,14 +1162,61 @@ set_partner_info_for_2link_sap(struct scan_cache_entry *scan_entry, } #endif +static void +cm_check_nontx_mbssid_partner_entries(struct cm_connect_req *conn_req) +{ + uint8_t idx; + struct scan_cache_entry *entry, *partner_entry; + qdf_list_t *candidate_list = conn_req->candidate_list; + struct qdf_mac_addr *mld_addr; + struct partner_link_info *partner_info; + + entry = conn_req->cur_candidate->entry; + mld_addr = util_scan_entry_mldaddr(entry); + + /* + * If the entry is not one of following, return gracefully: + * -AP is not ML type + * -AP is SLO + * -AP is not a member of MBSSID set + * -AP BSSID equals to TxBSSID in MBSSID set + */ + if (!mld_addr || !entry->ml_info.num_links || + !entry->mbssid_info.profile_num || + !qdf_mem_cmp(entry->mbssid_info.trans_bssid, &entry->bssid, + QDF_MAC_ADDR_SIZE)) { + return; + } + + for (idx = 0; idx < entry->ml_info.num_links; idx++) { + if (!entry->ml_info.link_info[idx].is_valid_link) + continue; + + partner_info = &entry->ml_info.link_info[idx]; + partner_entry = cm_get_entry(candidate_list, + &partner_info->link_addr); + /* + * If partner entry is not found in candidate list or if + * the MLD address of the entry is not equal to current + * candidate MLD address, treat it as entry not found. + */ + if (!partner_entry || + !qdf_is_macaddr_equal(mld_addr, + &partner_entry->ml_info.mld_mac_addr)) { + partner_info->is_scan_entry_not_found = true; + } + } +} + QDF_STATUS cm_get_ml_partner_info(struct wlan_objmgr_pdev *pdev, - struct scan_cache_entry *scan_entry, - struct mlo_partner_info *partner_info) + struct cm_connect_req *conn_req) { uint8_t i, j = 0; uint8_t mlo_support_link_num; struct wlan_objmgr_psoc *psoc; + struct scan_cache_entry *scan_entry = conn_req->cur_candidate->entry; + struct mlo_partner_info *partner_info = &conn_req->req.ml_parnter_info; /* Initialize number of partner links as zero */ partner_info->num_partner_links = 0; @@ -1208,24 +1255,23 @@ cm_get_ml_partner_info(struct wlan_objmgr_pdev *pdev, if (mlo_support_link_num && j >= mlo_support_link_num - 1) break; - if (scan_entry->ml_info.link_info[i].is_valid_link) { - partner_info->partner_link_info[j].link_addr = - scan_entry->ml_info.link_info[i].link_addr; - partner_info->partner_link_info[j].link_id = - scan_entry->ml_info.link_info[i].link_id; - partner_info->partner_link_info[j].chan_freq = - scan_entry->ml_info.link_info[i].freq; - j++; + if (!scan_entry->ml_info.link_info[i].is_valid_link) continue; - } - scan_entry->ml_info.link_info[i].is_valid_link = false; + partner_info->partner_link_info[j].link_addr = + scan_entry->ml_info.link_info[i].link_addr; + partner_info->partner_link_info[j].link_id = + scan_entry->ml_info.link_info[i].link_id; + partner_info->partner_link_info[j].chan_freq = + scan_entry->ml_info.link_info[i].freq; + j++; } partner_info->num_partner_links = j; mlme_debug("sta and ap intersect num of partner link: %d", j); set_partner_info_for_2link_sap(scan_entry, partner_info); + cm_check_nontx_mbssid_partner_entries(conn_req); return QDF_STATUS_SUCCESS; } diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index 71b224592a..25b0c7e8bb 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -649,6 +649,23 @@ lim_fill_pe_session(struct mac_context *mac_ctx, struct bss_description *bss_desc); #ifdef WLAN_FEATURE_11BE_MLO +/* + * lim_add_bcn_probe() - Add the generated probe resp to scan DB + * @vdev: VDEV object manager + * @bcn_probe: Pointer to bcn/probe + * @len: Length of frame. + * @freq: Freq on frame. + * @rssi: RSSI of the frame. + * + * Prepares the meta data to add the generated bcn/probe frame to + * scan DB. + * + * Return: QDF_STATUS + */ +QDF_STATUS +lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe, + uint32_t len, qdf_freq_t freq, int32_t rssi); + /** * lim_update_mlo_mgr_info() - API to update mlo_mgr link info * @mac_ctx: Pointer to mac context @@ -714,6 +731,13 @@ lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx, uint32_t probe_rsp_len); #else +static inline QDF_STATUS +lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe, + uint32_t len, qdf_freq_t freq, int32_t rssi) +{ + return QDF_STATUS_E_NOSUPPORT; +} + static inline QDF_STATUS lim_update_mlo_mgr_info(struct mac_context *mac_ctx, struct wlan_objmgr_vdev *vdev, diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index d9ebb89236..fa3ea60a0d 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -3818,7 +3818,7 @@ lim_match_link_info(uint8_t req_link_id, return false; } -static QDF_STATUS +QDF_STATUS lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe, uint32_t len, qdf_freq_t freq, int32_t rssi) { diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index d2b1ccb908..7b6cd46d67 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -47,6 +47,8 @@ #include "wlan_mlme_ucfg_api.h" #include "wlan_connectivity_logging.h" #include +#include +#include #include "parser_api.h" #include "wlan_twt_cfg_ext_api.h" #include "wlan_mlo_mgr_roam.h" @@ -1088,6 +1090,120 @@ void lim_send_join_fail_on_vdev(struct mac_context *mac_ctx, session_entry); } +#ifdef WLAN_FEATURE_11BE_MLO +static QDF_STATUS +lim_gen_link_specific_probe_resp_from_assoc_resp(uint8_t *rx_pkt_info, + uint32_t frame_len, + struct pe_session *session) +{ + QDF_STATUS status; + struct bss_description *bss; + struct scan_cache_entry *scan_entry; + struct mlo_partner_info *lim_partner_info; + struct partner_link_info *scan_partner_info; + struct mlo_link_info *link_info; + uint8_t link_id, idx, idx2; + struct qdf_mac_addr link_addr; + struct element_info link_probe_rsp, probe_rsp; + uint8_t *frame = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + int8_t rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); + + if (!session->lim_join_req) { + pe_debug("Session join req invalid"); + return QDF_STATUS_E_INVAL; + } + + bss = &session->lim_join_req->bssDescription; + lim_partner_info = &session->lim_join_req->partner_info; + + /* + * For link VDEV no need to generate again, as during assoc VDEv + * it is already generated. + */ + if (!bss->mbssid_info.profile_num || + !lim_partner_info->num_partner_links || + wlan_vdev_mlme_is_mlo_link_vdev(session->vdev)) { + return QDF_STATUS_SUCCESS; + } + + link_probe_rsp.ptr = qdf_mem_malloc(MAX_MGMT_MPDU_LEN); + if (!link_probe_rsp.ptr) { + pe_err("mallloc failed for %u bytes", MAX_MGMT_MPDU_LEN); + return QDF_STATUS_E_NOMEM; + } + + scan_entry = wlan_cm_get_curr_candidate_entry(session->vdev, + session->cm_id); + if (!scan_entry) { + pe_err("Curr scan entry NULL"); + qdf_mem_free(link_probe_rsp.ptr); + return QDF_STATUS_E_INVAL; + } + + probe_rsp.ptr = + util_scan_entry_frame_ptr(scan_entry) + WLAN_MAC_HDR_LEN_3A; + probe_rsp.len = + util_scan_entry_frame_len(scan_entry) - WLAN_MAC_HDR_LEN_3A; + + qdf_mem_copy(&link_addr, session->self_mac_addr, QDF_MAC_ADDR_SIZE); + + /* + * For each partner entry, check if the corresponding partner link + * is found or not to generate probe resp for the missing link. + */ + for (idx2 = 0; idx2 < lim_partner_info->num_partner_links; idx2++) { + link_info = &lim_partner_info->partner_link_info[idx2]; + for (idx = 0; idx < scan_entry->ml_info.num_links; idx++) { + scan_partner_info = &scan_entry->ml_info.link_info[idx]; + if (!scan_partner_info->is_scan_entry_not_found) + continue; + + if (link_info->link_id != scan_partner_info->link_id) + continue; + + link_id = link_info->link_id; + link_probe_rsp.len = 0; + status = util_gen_link_probe_rsp_from_assoc_rsp(frame, + frame_len, + link_id, + link_addr, + link_probe_rsp.ptr, + (qdf_size_t)MAX_MGMT_MPDU_LEN, + (qdf_size_t *)&link_probe_rsp.len, + probe_rsp.ptr, + probe_rsp.len); + + if (QDF_IS_STATUS_ERROR(status)) + goto mem_free; + + status = lim_add_bcn_probe(session->vdev, + link_probe_rsp.ptr, + link_probe_rsp.len, + link_info->chan_freq, rssi); + if (QDF_IS_STATUS_ERROR(status)) { + pe_debug("Scan entry add failed for %d", + link_id); + goto mem_free; + } + } + } + +mem_free: + qdf_mem_free(link_probe_rsp.ptr); + util_scan_free_cache_entry(scan_entry); + + return status; +} +#else /* WLAN_FEATURE_11BE_MLO */ +static inline QDF_STATUS +lim_gen_link_specific_probe_resp_from_assoc_resp(uint8_t *rx_pkt_info, + uint32_t frame_len, + struct pe_session *session) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_11BE_MLO */ + /** * lim_process_assoc_rsp_frame() - Processes assoc response * @mac_ctx: Pointer to Global MAC structure @@ -1744,6 +1860,27 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS); #endif lim_update_stads_ext_cap(mac_ctx, session_entry, assoc_rsp, sta_ds); + + /* Try to generate link probe resp from assoc resp for MBSSID AP + * as ML probe is not sent for MBSSID AP. + * + * Any failure during partner link probe resp generation, treat + * it as connect failure and send deauth to AP. + */ + status = lim_gen_link_specific_probe_resp_from_assoc_resp(rx_pkt_info, + frame_body_len, + session_entry); + if (QDF_IS_STATUS_ERROR(status)) { + assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; + assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE; + /* Send advisory Disassociation frame to AP */ + lim_send_disassoc_mgmt_frame(mac_ctx, + REASON_UNSPEC_FAILURE, + hdr->sa, session_entry, + false); + goto assocReject; + } + /* Update the BSS Entry, this entry was added during preassoc. */ if (QDF_STATUS_SUCCESS == lim_sta_send_add_bss(mac_ctx, assoc_rsp, beacon,