diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c index 2124a1f935..dc465e152d 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c @@ -1439,6 +1439,67 @@ static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } + +static QDF_STATUS cm_remove_mbssid_links_without_scan_entry( + qdf_list_t *candidate_list) +{ + struct scan_cache_node *scan_node = NULL; + struct scan_cache_entry *partner_entry = NULL, *scan_entry = NULL; + qdf_list_node_t *cur_node = NULL, *next_node = NULL; + struct partner_link_info *partner_info; + struct qdf_mac_addr *mld_addr; + uint8_t i = 0; + + if (qdf_list_peek_front(candidate_list, + &cur_node) != QDF_STATUS_SUCCESS) { + mlme_err("Failed to dequeue"); + return QDF_STATUS_E_FAILURE; + } + + while (cur_node) { + qdf_list_peek_next(candidate_list, cur_node, &next_node); + scan_node = qdf_container_of(cur_node, struct scan_cache_node, + node); + scan_entry = scan_node->entry; + mld_addr = util_scan_entry_mldaddr(scan_entry); + + if (!scan_entry->mbssid_info.profile_num || !mld_addr) + goto next_entry; + + /* + * Mark the links of an MBSSID partner as invalid if there + * is no scan entry for the link at the time of the candidate + * selection. + * + * For MBSSID candidates, ML-probe request would not be sent, + * during join phase, therefore the scan entry would not be + * created anytime before the association. + * + */ + for (i = 0; i < scan_entry->ml_info.num_links; i++) { + if (!scan_entry->ml_info.link_info[i].is_valid_link) + continue; + + partner_info = &scan_entry->ml_info.link_info[i]; + partner_entry = cm_get_entry(candidate_list, + &partner_info->link_addr); + + if (!partner_entry || + !qdf_is_macaddr_equal(mld_addr, + &partner_entry->ml_info.mld_mac_addr)) { + scan_entry->ml_info.link_info[i].is_valid_link = false; + mlme_debug("Scan entry is not present for link idx %d, drop the link", + scan_entry->ml_info.link_info[i].link_id); + } + } +next_entry: + cur_node = next_node; + next_node = NULL; + } + + return QDF_STATUS_SUCCESS; +} + #else static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev, struct cm_connect_req *cm_req, @@ -1446,6 +1507,12 @@ static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev, { return QDF_STATUS_SUCCESS; } + +static QDF_STATUS cm_remove_mbssid_links_without_scan_entry( + qdf_list_t *candidate_list) +{ + return QDF_STATUS_SUCCESS; +} #endif static QDF_STATUS @@ -1500,6 +1567,10 @@ cm_connect_fetch_candidates(struct wlan_objmgr_pdev *pdev, CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss); } *num_bss_found = num_bss; + + if (num_bss && !wlan_vdev_mlme_is_mlo_link_vdev(cm_ctx->vdev)) + cm_remove_mbssid_links_without_scan_entry(candidate_list); + op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev); if (num_bss && op_mode == QDF_STA_MODE && !cm_req->req.is_non_assoc_link) diff --git a/umac/mlo_mgr/inc/utils_mlo.h b/umac/mlo_mgr/inc/utils_mlo.h index 6413b3d51a..04a2f97d86 100644 --- a/umac/mlo_mgr/inc/utils_mlo.h +++ b/umac/mlo_mgr/inc/utils_mlo.h @@ -106,47 +106,6 @@ util_gen_link_assoc_rsp(uint8_t *frame, qdf_size_t frame_len, bool isreassoc, qdf_size_t link_frame_maxsize, qdf_size_t *link_frame_len); -/** - * util_gen_link_probe_rsp_from_assoc_rsp() - Generate link specific - * probe response from assoc response. - * @frame: Pointer to original association response. This should not contain the - * 802.11 header, and must start from the fixed fields in the association - * response. This is required due to some caller semantics built into the end to - * end design. - * @frame_len: Length of original association response - * @link_id: Link ID for secondary links - * @link_addr: Secondary link's MAC address - * @link_frame: Generated secondary link specific association response. Note - * that this will start from the 802.11 header (unlike the original association - * response). This should be ignored in the case of failure. - * @link_frame_maxsize: Maximum size of generated secondary link specific - * association response - * @link_frame_len: Pointer to location where populated length of generated - * secondary link specific association response should be written. This should - * be ignored in the case of failure. - * @bcn_prb_ptr: Pointer to probe response of the current link on which assoc - * response is received, This should not contain the 802.11 header, and must - * start from the fixed fields in the probe response. - * @bcn_prb_len: Length of probe response of @bcn_prb_ptr. - * - * Generate a link specific logically equivalent probe response for the - * secondary link from the original association response containing a Multi-Link - * element. - * Currently, only two link MLO is supported. - * - * Return: QDF_STATUS_SUCCESS in the case of success, QDF_STATUS value giving - * the reason for error in the case of failure. - */ -QDF_STATUS -util_gen_link_probe_rsp_from_assoc_rsp(uint8_t *frame, qdf_size_t frame_len, - uint8_t link_id, - struct qdf_mac_addr link_addr, - uint8_t *link_frame, - qdf_size_t link_frame_maxsize, - qdf_size_t *link_frame_len, - uint8_t *bcn_prb_ptr, - qdf_size_t bcn_prb_len); - /** * util_gen_link_probe_rsp() - Generate link specific probe response * @frame: Pointer to original probe response. This should not contain the @@ -639,19 +598,6 @@ util_gen_link_assoc_rsp(uint8_t *frame, qdf_size_t frame_len, bool isreassoc, return QDF_STATUS_E_NOSUPPORT; } -static inline QDF_STATUS -util_gen_link_probe_rsp_from_assoc_rsp(uint8_t *frame, qdf_size_t frame_len, - uint8_t link_id, - struct qdf_mac_addr link_addr, - uint8_t *link_frame, - qdf_size_t link_frame_maxsize, - qdf_size_t *link_frame_len, - uint8_t *bcn_prb_ptr, - qdf_size_t bcn_prb_len) -{ - return QDF_STATUS_E_NOSUPPORT; -} - static inline QDF_STATUS util_find_mlie(uint8_t *buf, qdf_size_t buflen, uint8_t **mlieseq, qdf_size_t *mlieseqlen) diff --git a/umac/mlo_mgr/src/utils_mlo.c b/umac/mlo_mgr/src/utils_mlo.c index 3311151655..ff3d47e5e5 100644 --- a/umac/mlo_mgr/src/utils_mlo.c +++ b/umac/mlo_mgr/src/utils_mlo.c @@ -1850,972 +1850,6 @@ util_find_bvmlie_persta_prof_for_linkid(uint8_t req_link_id, return QDF_STATUS_E_PROTO; } -static -QDF_STATUS util_gen_link_prb_rsp_from_assoc_rsp_cmn(uint8_t *frame, - qdf_size_t frame_len, - uint8_t orig_subtype, - uint8_t gen_subtype, - uint8_t req_link_id, - struct qdf_mac_addr link_addr, - uint8_t *link_frame, - qdf_size_t link_frame_maxsize, - qdf_size_t *link_frame_len, - uint8_t *bcn_prb_ptr, - qdf_size_t bcn_prb_len) -{ - /* Pointer to Multi-Link element/Multi-Link element fragment sequence */ - uint8_t *mlieseq; - /* Total length of Multi-Link element sequence (including fragments if - * any) - */ - qdf_size_t mlieseqlen; - /* Variant (i.e. type) of the Multi-Link element */ - enum wlan_ml_variant variant; - - /* Length of the payload of the Multi-Link element (inclusive of - * fragment payloads if any) without IE headers and element ID extension - */ - qdf_size_t mlieseqpayloadlen; - /* Pointer to copy of the payload of the Multi-Link element (inclusive - * of fragment payloads if any) without IE headers and element ID - * extension - */ - uint8_t *mlieseqpayload_copy; - - /* Pointer to start of Link Info within the copy of the payload of the - * Multi-Link element - */ - uint8_t *link_info; - /* Length of the Link Info */ - qdf_size_t link_info_len; - - /* Pointer to the IE section that occurs after the fixed fields in the - * original frame for the reporting STA. - */ - uint8_t *frame_iesection; - /* Offset to the start of the IE section in the original frame for the - * reporting STA. - */ - qdf_size_t frame_iesection_offset; - /* Total length of the IE section in the original frame for the - * reporting STA. - */ - qdf_size_t frame_iesection_len; - - /* Pointer to the IEEE802.11 frame header in the link specific frame - * being generated for the reported STA. - */ - struct wlan_frame_hdr *link_frame_hdr; - /* Current position in the link specific frame being generated for the - * reported STA. - */ - uint8_t *link_frame_currpos; - /* Current length of the link specific frame being generated for the - * reported STA. - */ - qdf_size_t link_frame_currlen; - - /* Pointer to IE for reporting STA */ - const uint8_t *reportingsta_ie; - /* Total size of IE for reporting STA, inclusive of the element header - */ - qdf_size_t reportingsta_ie_size; - - /* Pointer to current position in STA profile */ - uint8_t *sta_prof_currpos; - /* Remaining length of STA profile */ - qdf_size_t sta_prof_remlen; - /* Pointer to start of IE section in STA profile that occurs after fixed - * fields. - */ - uint8_t *sta_prof_iesection; - /* Total length of IE section in STA profile */ - qdf_size_t sta_prof_iesection_len; - /* Pointer to current position being processed in IE section in STA - * profile. - */ - uint8_t *sta_prof_iesection_currpos; - /* Remaining length of IE section in STA profile */ - qdf_size_t sta_prof_iesection_remlen; - - /* Pointer to IE in STA profile, that occurs within IE section */ - uint8_t *sta_prof_ie; - /* Total size of IE in STA profile, inclusive of the element header */ - qdf_size_t sta_prof_ie_size; - - /* Pointer to element ID list in Non-Inheritance IE */ - uint8_t *ninherit_elemlist; - /* Length of element ID list in Non-Inheritance IE */ - qdf_size_t ninherit_elemlist_len; - /* Pointer to element ID extension list in Non-Inheritance IE */ - uint8_t *ninherit_elemextlist; - /* Length of element ID extension list in Non-Inheritance IE */ - qdf_size_t ninherit_elemextlist_len; - /* Whether a given IE is in a non-inheritance list */ - bool is_in_noninheritlist; - - /* Whether MAC address of reported STA is valid */ - bool is_reportedmacaddr_valid; - /* MAC address of reported STA */ - struct qdf_mac_addr reportedmacaddr; - - /* Pointer to per-STA profile */ - uint8_t *persta_prof; - /* Length of the containing buffer which starts with the per-STA profile - */ - qdf_size_t persta_prof_bufflen; - - /* Other variables for temporary purposes */ - - /* Variable into which API for determining fragment information will - * indicate whether the element is the start of a fragment sequence or - * not. - */ - bool is_elemfragseq; - /* De-fragmented payload length returned by API for element - * defragmentation. - */ - qdf_size_t defragpayload_len; - /* Pointer to Beacon interval in STA info field */ - uint16_t beaconinterval; - /* Whether Beacon interval value valid */ - bool is_beaconinterval_valid; - /* TSF offset of the reproted AP */ - uint64_t tsfoffset; - /* TSF offset value valid */ - bool is_tsfoffset_valid; - /* If Complete Profile or not*/ - bool is_completeprofile; - qdf_size_t tmplen; - QDF_STATUS ret; - uint8_t ie_idx, linkid = 0xFF; - /* List of IEs to add from @bcn_prb_ptr */ - uint8_t missing_ie_list[] = {WLAN_ELEMID_SSID, WLAN_ELEMID_RSN}; - /* No.of IEs in @missing_ie_list array */ - uint8_t missing_ie_len = sizeof(missing_ie_list); - /* List of Extn IEs to add from @bcn_prb_ptr */ - uint8_t *missing_ext_ie_list = NULL; - /* No.of IEs in @missing_ext_ie_list array */ - uint8_t missing_ext_ie_len = 0x0; - uint8_t *bcn_prb_ies_ptr, *secondary_ie; - qdf_size_t bcn_prb_ies_len; - - if (!frame) { - mlo_err("Pointer to original frame is NULL"); - return QDF_STATUS_E_NULL_VALUE; - } - - if (!frame_len) { - mlo_err("Length of original frame is zero"); - return QDF_STATUS_E_INVAL; - } - - if (!link_frame) { - mlo_err("Pointer to secondary link specific frame is NULL"); - return QDF_STATUS_E_NULL_VALUE; - } - - if (!link_frame_maxsize) { - mlo_err("Maximum size of secondary link specific frame is zero"); - return QDF_STATUS_E_INVAL; - } - - if (!link_frame_len) { - mlo_err("Pointer to populated length of secondary link specific frame is NULL"); - return QDF_STATUS_E_NULL_VALUE; - } - - frame_iesection_offset = 0; - - /* This is a (re)association response */ - frame_iesection_offset = WLAN_ASSOC_RSP_IES_OFFSET; - - if (frame_len < frame_iesection_offset) { - /* The caller is supposed to have confirmed that this is a valid - * frame containing a Multi-Link element. Hence we treat this as - * a case of invalid argument being passed to us. - */ - mlo_err("Frame length %zu is smaller than the IE section offset %zu for orig_subtype %u", - frame_len, frame_iesection_offset, orig_subtype); - return QDF_STATUS_E_INVAL; - } - - frame_iesection_len = frame_len - frame_iesection_offset; - - if (frame_iesection_len == 0) { - /* The caller is supposed to have confirmed that this is a valid - * frame containing a Multi-Link element. Hence we treat this as - * a case of invalid argument being passed to us. - */ - mlo_err("No space left in frame for IE section"); - return QDF_STATUS_E_INVAL; - } - - frame_iesection = frame + frame_iesection_offset; - - bcn_prb_ies_ptr = bcn_prb_ptr + WLAN_PROBE_RESP_IES_OFFSET; - bcn_prb_ies_len = bcn_prb_len - WLAN_PROBE_RESP_IES_OFFSET; - - mlieseq = NULL; - mlieseqlen = 0; - - ret = util_find_mlie(frame_iesection, frame_iesection_len, &mlieseq, - &mlieseqlen); - if (QDF_IS_STATUS_ERROR(ret)) - return ret; - - if (!mlieseq) { - /* The caller is supposed to have confirmed that a Multi-Link - * element is present in the frame. Hence we treat this as a - * case of invalid argument being passed to us. - */ - mlo_err("Invalid original frame since no Multi-Link element found"); - return QDF_STATUS_E_INVAL; - } - - /* Sanity check the Multi-Link element sequence length */ - if (!mlieseqlen) { - mlo_err("Length of Multi-Link element sequence is zero. Investigate."); - return QDF_STATUS_E_FAILURE; - } - - if (mlieseqlen < sizeof(struct wlan_ie_multilink)) { - mlo_err_rl("Multi-Link element sequence length %zu octets is smaller than required for the fixed portion of Multi-Link element (%zu octets)", - mlieseqlen, sizeof(struct wlan_ie_multilink)); - return QDF_STATUS_E_PROTO; - } - - ret = util_get_mlie_variant(mlieseq, mlieseqlen, (int *)&variant); - if (QDF_IS_STATUS_ERROR(ret)) - return ret; - - if (variant != WLAN_ML_VARIANT_BASIC) { - mlo_err_rl("Unexpected variant %u of Multi-Link element.", - variant); - return QDF_STATUS_E_PROTO; - } - - mlieseqpayloadlen = 0; - tmplen = 0; - is_elemfragseq = false; - - ret = wlan_get_elem_fragseq_info(mlieseq, - mlieseqlen, - &is_elemfragseq, - &tmplen, - &mlieseqpayloadlen); - if (QDF_IS_STATUS_ERROR(ret)) - return ret; - - if (is_elemfragseq) { - if (tmplen != mlieseqlen) { - mlo_err_rl("Mismatch in values of element fragment sequence total length. Val per frag info determination: %zu octets, val per Multi-Link element search: %zu octets", - tmplen, mlieseqlen); - return QDF_STATUS_E_FAILURE; - } - - if (!mlieseqpayloadlen) { - mlo_err_rl("Multi-Link element fragment sequence payload is reported as 0, investigate"); - return QDF_STATUS_E_FAILURE; - } - - mlo_debug("ML IE fragment sequence found with payload len %zu", - mlieseqpayloadlen); - } else { - if (mlieseqlen > (sizeof(struct ie_header) + WLAN_MAX_IE_LEN)) { - mlo_err_rl("Expected presence of valid fragment sequence since Multi-Link element sequence length %zu octets is larger than frag threshold of %zu octets, however no valid fragment sequence found", - mlieseqlen, - sizeof(struct ie_header) + WLAN_MAX_IE_LEN); - return QDF_STATUS_E_FAILURE; - } - - mlieseqpayloadlen = mlieseqlen - (sizeof(struct ie_header) + 1); - } - - mlieseqpayload_copy = qdf_mem_malloc(mlieseqpayloadlen); - - if (!mlieseqpayload_copy) { - mlo_err_rl("Could not allocate memory for Multi-Link element payload copy"); - return QDF_STATUS_E_NOMEM; - } - - if (is_elemfragseq) { - ret = wlan_defrag_elem_fragseq(false, - mlieseq, - mlieseqlen, - mlieseqpayload_copy, - mlieseqpayloadlen, - &defragpayload_len); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - if (defragpayload_len != mlieseqpayloadlen) { - mlo_err_rl("Length of de-fragmented payload %zu octets is not equal to length of Multi-Link element fragment sequence payload %zu octets", - defragpayload_len, mlieseqpayloadlen); - ret = QDF_STATUS_E_FAILURE; - goto mem_free; - } - } else { - qdf_mem_copy(mlieseqpayload_copy, - mlieseq + sizeof(struct ie_header) + 1, - mlieseqpayloadlen); - } - - link_info = NULL; - link_info_len = 0; - - ret = util_parse_multi_link_ctrl(mlieseqpayload_copy, - mlieseqpayloadlen, - &link_info, - &link_info_len); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - /* As per the standard, the sender must include Link Info for - * association request/response. Throw an error if we are unable to - * obtain this. - */ - if (!link_info) { - mlo_err_rl("Unable to successfully obtain Link Info"); - ret = QDF_STATUS_E_PROTO; - goto mem_free; - } - - /* Note: We may have a future change to skip subelements which are not - * Per-STA Profile, handle more than two links in MLO, handle cases - * where we unexpectedly find more Per-STA Profiles than expected, etc. - */ - - persta_prof = NULL; - persta_prof_bufflen = 0; - - ret = util_find_bvmlie_persta_prof_for_linkid(req_link_id, - link_info, - link_info_len, - &persta_prof, - &persta_prof_bufflen); - - if (QDF_IS_STATUS_ERROR(ret)) { - mlo_err_rl("Per STA profile not found for link id %d", - req_link_id); - goto mem_free; - } - - sta_prof_remlen = 0; - sta_prof_currpos = NULL; - is_reportedmacaddr_valid = false; - is_beaconinterval_valid = false; - is_completeprofile = false; - is_tsfoffset_valid = false; - - /* Parse per-STA profile */ - ret = util_parse_bvmlie_perstaprofile_stactrl(persta_prof + - sizeof(struct subelem_header), - persta_prof_bufflen, - &linkid, - &beaconinterval, - &is_beaconinterval_valid, - &tsfoffset, - &is_tsfoffset_valid, - &is_completeprofile, - &is_reportedmacaddr_valid, - &reportedmacaddr, - true, - &sta_prof_currpos, - &sta_prof_remlen, - NULL, - NULL); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - if (!is_completeprofile) { - mlo_err("Complete profile information is not present in per-STA profile"); - ret = QDF_STATUS_E_NOSUPPORT; - goto mem_free; - } - - /* We double check for a NULL STA Profile, though the helper function - * above would have taken care of this. We need to get a non-NULL STA - * profile, because we need to get at least the expected fixed fields, - * even if there is an (improbable) total inheritance. - */ - if (!sta_prof_currpos) { - mlo_err_rl("STA profile is NULL"); - ret = QDF_STATUS_E_PROTO; - goto mem_free; - } - - /* As per the standard, the sender sets the MAC address in the per-STA - * profile in association request/response. Without this, we cannot - * generate the link specific frame. - */ - if (!is_reportedmacaddr_valid) { - mlo_err_rl("Unable to get MAC address from per-STA profile"); - ret = QDF_STATUS_E_PROTO; - goto mem_free; - } - - link_frame_currpos = link_frame; - *link_frame_len = 0; - link_frame_currlen = 0; - - if (link_frame_maxsize < WLAN_MAC_HDR_LEN_3A) { - mlo_err("Insufficient space in link specific frame for 802.11 header. Required: %u octets, available: %zu octets", - WLAN_MAC_HDR_LEN_3A, link_frame_maxsize); - - ret = QDF_STATUS_E_NOMEM; - goto mem_free; - } - - link_frame_currpos += WLAN_MAC_HDR_LEN_3A; - link_frame_currlen += WLAN_MAC_HDR_LEN_3A; - - /* This is a (re)association response */ - mlo_debug("Populating fixed fields for (re)assoc resp in link specific frame"); - if (sta_prof_remlen < (WLAN_CAPABILITYINFO_LEN + WLAN_STATUSCODE_LEN)) { - mlo_err_rl("Remaining length of STA profile %zu octets is less than length of Capability Info + length of Status Code %u", - sta_prof_remlen, - WLAN_CAPABILITYINFO_LEN + WLAN_STATUSCODE_LEN); - - ret = QDF_STATUS_E_PROTO; - goto mem_free; - } - - /* TODO: */ - qdf_mem_copy(link_frame_currpos, bcn_prb_ptr, WLAN_TIMESTAMP_LEN); - link_frame_currpos += WLAN_TIMESTAMP_LEN; - link_frame_currlen += WLAN_TIMESTAMP_LEN; - - if (is_beaconinterval_valid) { - qdf_mem_copy(link_frame_currpos, &beaconinterval, - WLAN_BEACONINTERVAL_LEN); - } else { - /* Use the BI from input frame if per-STA doesn't have valid - * BI - */ - qdf_mem_copy(link_frame_currpos, - bcn_prb_ptr + WLAN_TIMESTAMP_LEN, - WLAN_BEACONINTERVAL_LEN); - } - link_frame_currpos += WLAN_BEACONINTERVAL_LEN; - link_frame_currlen += WLAN_BEACONINTERVAL_LEN; - - /* Capability information and Status Code are specific to the - * link. Copy these from the STA profile. - */ - - if ((link_frame_maxsize - link_frame_currlen) < - WLAN_CAPABILITYINFO_LEN) { - mlo_err("Insufficient space in link specific frame for Capability Info and Status Code fields. Required: %u octets, available: %zu octets", - WLAN_CAPABILITYINFO_LEN + WLAN_STATUSCODE_LEN, - (link_frame_maxsize - link_frame_currlen)); - - ret = QDF_STATUS_E_NOMEM; - goto mem_free; - } - - qdf_mem_copy(link_frame_currpos, sta_prof_currpos, - WLAN_CAPABILITYINFO_LEN); - link_frame_currpos += WLAN_CAPABILITYINFO_LEN; - link_frame_currlen += WLAN_CAPABILITYINFO_LEN; - mlo_debug("Added Capability Info (%u octets) to link specific frame", - WLAN_CAPABILITYINFO_LEN); - - sta_prof_currpos += WLAN_CAPABILITYINFO_LEN + WLAN_STATUSCODE_LEN; - sta_prof_remlen -= WLAN_CAPABILITYINFO_LEN + WLAN_STATUSCODE_LEN; - - sta_prof_iesection = sta_prof_currpos; - sta_prof_iesection_len = sta_prof_remlen; - - /* Populate non-inheritance lists if applicable */ - ninherit_elemlist_len = 0; - ninherit_elemlist = NULL; - ninherit_elemextlist_len = 0; - ninherit_elemextlist = NULL; - - ret = util_get_noninheritlists(sta_prof_iesection, - sta_prof_iesection_len, - &ninherit_elemlist, - &ninherit_elemlist_len, - &ninherit_elemextlist, - &ninherit_elemextlist_len); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - /* Go through IEs of the reporting STA, and those in STA profile, merge - * them into link_frame (except for elements in the Non-Inheritance - * list). - * - * Note: Currently, only 2-link MLO is supported here. We may have a - * future change to expand to more links. - */ - reportingsta_ie = util_find_eid(WLAN_ELEMID_SSID, frame_iesection, - frame_iesection_len); - - /* This is a (re)association response. Sanity check that the - * SSID element is present neither for the reporting STA nor in - * the STA profile. - */ - if (reportingsta_ie) { - mlo_err_rl("SSID element found for reporting STA for (re)association response. It should not be present."); - ret = QDF_STATUS_E_PROTO; - goto mem_free; - } - - sta_prof_ie = util_find_eid(WLAN_ELEMID_SSID, - sta_prof_iesection, - sta_prof_iesection_len); - - if (sta_prof_ie) { - mlo_err_rl("SSID element found in STA profile for (re)association response. It should not be present."); - ret = QDF_STATUS_E_PROTO; - goto mem_free; - } - - reportingsta_ie = reportingsta_ie ? reportingsta_ie : frame_iesection; - - ret = util_validate_reportingsta_ie(reportingsta_ie, frame_iesection, - frame_iesection_len); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - reportingsta_ie_size = reportingsta_ie[TAG_LEN_POS] + MIN_IE_LEN; - - while (((reportingsta_ie + reportingsta_ie_size) - frame_iesection) - <= frame_iesection_len) { - if (reportingsta_ie[ID_POS] != WLAN_ELEMID_EXTN_ELEM) { - for (ie_idx = 0; ie_idx < missing_ie_len; ie_idx++) { - if (missing_ie_list[ie_idx] == - reportingsta_ie[ID_POS]) { - missing_ie_list[ie_idx] = - WLAN_ELEMID_EXTN_ELEM; - } - } - } else { - for (ie_idx = 0; ie_idx < missing_ext_ie_len; ie_idx++) { - if (missing_ext_ie_list[ie_idx] == - reportingsta_ie[IDEXT_POS]) { - missing_ext_ie_list[ie_idx] = - WLAN_ELEMID_EXTN_ELEM; - } - } - } - - /* Skip Multi-Link element */ - if ((reportingsta_ie[ID_POS] == WLAN_ELEMID_EXTN_ELEM) && - (reportingsta_ie[IDEXT_POS] == - WLAN_EXTN_ELEMID_MULTI_LINK)) { - if (((reportingsta_ie + reportingsta_ie_size) - - frame_iesection) == frame_iesection_len) - break; - - /* Add BV ML IE for link specific probe response */ - ret = util_add_mlie_for_prb_rsp_gen( - reportingsta_ie, - reportingsta_ie[TAG_LEN_POS], - &link_frame_currpos, - &link_frame_currlen, - link_frame_maxsize, - linkid); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - reportingsta_ie += reportingsta_ie_size; - - ret = util_validate_reportingsta_ie(reportingsta_ie, - frame_iesection, - frame_iesection_len); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - reportingsta_ie_size = reportingsta_ie[TAG_LEN_POS] + - MIN_IE_LEN; - - continue; - } - - sta_prof_ie = NULL; - sta_prof_ie_size = 0; - - if (sta_prof_iesection_len) { - if (reportingsta_ie[ID_POS] == WLAN_ELEMID_EXTN_ELEM) { - sta_prof_ie = (uint8_t *)util_find_extn_eid(reportingsta_ie[ID_POS], - reportingsta_ie[IDEXT_POS], - sta_prof_iesection, - sta_prof_iesection_len); - } else { - sta_prof_ie = (uint8_t *)util_find_eid(reportingsta_ie[ID_POS], - sta_prof_iesection, - sta_prof_iesection_len); - } - } - - if (!sta_prof_ie) { - /* IE is present for reporting STA, but not in STA - * profile. - */ - - is_in_noninheritlist = false; - - ret = util_eval_ie_in_noninheritlist((uint8_t *)reportingsta_ie, - reportingsta_ie_size, - ninherit_elemlist, - ninherit_elemlist_len, - ninherit_elemextlist, - ninherit_elemextlist_len, - &is_in_noninheritlist); - - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - if (!is_in_noninheritlist) { - if ((link_frame_currpos + - reportingsta_ie_size) <= - (link_frame + link_frame_maxsize)) { - qdf_mem_copy(link_frame_currpos, - reportingsta_ie, - reportingsta_ie_size); - - link_frame_currpos += - reportingsta_ie_size; - link_frame_currlen += - reportingsta_ie_size; - - if (reportingsta_ie[ID_POS] == WLAN_ELEMID_EXTN_ELEM) { - mlo_etrace_debug("IE with element ID : %u extension element ID : %u (%zu octets) present for reporting STA but not in STA profile. Copied IE from reporting frame to link specific frame", - reportingsta_ie[ID_POS], - reportingsta_ie[IDEXT_POS], - reportingsta_ie_size); - } else { - mlo_etrace_debug("IE with element ID : %u (%zu octets) present for reporting STA but not in STA profile. Copied IE from reporting frame to link specific frame", - reportingsta_ie[ID_POS], - reportingsta_ie_size); - } - } else { - if (reportingsta_ie[ID_POS] == WLAN_ELEMID_EXTN_ELEM) { - mlo_etrace_err_rl("Insufficient space in link specific frame for IE with element ID : %u extension element ID : %u. Required: %zu octets, available: %zu octets", - reportingsta_ie[ID_POS], - reportingsta_ie[IDEXT_POS], - reportingsta_ie_size, - link_frame_maxsize - - link_frame_currlen); - } else { - mlo_etrace_err_rl("Insufficient space in link specific frame for IE with element ID : %u. Required: %zu octets, available: %zu octets", - reportingsta_ie[ID_POS], - reportingsta_ie_size, - link_frame_maxsize - - link_frame_currlen); - } - - ret = QDF_STATUS_E_NOMEM; - goto mem_free; - } - } else { - if (reportingsta_ie[ID_POS] == WLAN_ELEMID_EXTN_ELEM) { - mlo_etrace_debug("IE with element ID : %u extension element ID : %u (%zu octets) present for reporting STA but not in STA profile. However it is in Non-Inheritance list, hence ignoring.", - reportingsta_ie[ID_POS], - reportingsta_ie[IDEXT_POS], - reportingsta_ie_size); - } else { - mlo_etrace_debug("IE with element ID : %u (%zu octets) present for reporting STA but not in STA profile. However it is in Non-Inheritance list, hence ignoring.", - reportingsta_ie[ID_POS], - reportingsta_ie_size); - } - } - } else { - /* IE is present for reporting STA and also in STA - * profile, copy from STA profile and flag the IE in STA - * profile as copied (by setting EID field to 0). The - * SSID element (with EID 0) is processed first to - * enable this. For vendor IE, compare OUI + type + - * subType to determine if they are the same IE. - */ - /* Note: This may be revisited in a future change, to - * adhere to provisions in the standard for multiple - * occurrences of a given element ID/extension element - * ID. - */ - - ret = util_validate_sta_prof_ie(sta_prof_ie, - sta_prof_iesection, - sta_prof_iesection_len); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - sta_prof_ie_size = sta_prof_ie[TAG_LEN_POS] + - MIN_IE_LEN; - - sta_prof_iesection_remlen = - sta_prof_iesection_len - - (sta_prof_ie - sta_prof_iesection); - - if ((reportingsta_ie[ID_POS] == WLAN_ELEMID_VENDOR) && - (sta_prof_iesection_remlen >= MIN_VENDOR_TAG_LEN)) { - /* If Vendor IE also presents in STA profile, - * then ignore the Vendor IE which is for - * reporting STA. It only needs to copy Vendor - * IE from STA profile to link specific frame. - * The copy happens when going through the - * remaining IEs. - */ - ; - } else { - /* Copy IE from STA profile into link specific - * frame. - */ - if ((link_frame_currpos + sta_prof_ie_size) <= - (link_frame + link_frame_maxsize)) { - qdf_mem_copy(link_frame_currpos, - sta_prof_ie, - sta_prof_ie_size); - - link_frame_currpos += sta_prof_ie_size; - link_frame_currlen += - sta_prof_ie_size; - - if (reportingsta_ie[ID_POS] == - WLAN_ELEMID_EXTN_ELEM) { - mlo_etrace_debug("IE with element ID : %u extension element ID : %u (%zu octets) for reporting STA also present in STA profile. Copied IE from STA profile to link specific frame", - sta_prof_ie[ID_POS], - sta_prof_ie[IDEXT_POS], - sta_prof_ie_size); - } else { - mlo_etrace_debug("IE with element ID : %u (%zu octets) for reporting STA also present in STA profile. Copied IE from STA profile to link specific frame", - sta_prof_ie[ID_POS], - sta_prof_ie_size); - } - - sta_prof_ie[0] = 0; - } else { - if (sta_prof_ie[ID_POS] == - WLAN_ELEMID_EXTN_ELEM) { - mlo_etrace_err_rl("Insufficient space in link specific frame for IE with element ID : %u extension element ID : %u. Required: %zu octets, available: %zu octets", - sta_prof_ie[ID_POS], - sta_prof_ie[IDEXT_POS], - sta_prof_ie_size, - link_frame_maxsize - - link_frame_currlen); - } else { - mlo_etrace_err_rl("Insufficient space in link specific frame for IE with element ID : %u. Required: %zu octets, available: %zu octets", - sta_prof_ie[ID_POS], - sta_prof_ie_size, - link_frame_maxsize - - link_frame_currlen); - } - - ret = QDF_STATUS_E_NOMEM; - goto mem_free; - } - } - } - - if (((reportingsta_ie + reportingsta_ie_size) - - frame_iesection) == frame_iesection_len) - break; - - reportingsta_ie += reportingsta_ie_size; - - ret = util_validate_reportingsta_ie(reportingsta_ie, - frame_iesection, - frame_iesection_len); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - reportingsta_ie_size = reportingsta_ie[TAG_LEN_POS] + - MIN_IE_LEN; - } - - /* Go through the remaining unprocessed IEs in STA profile and copy them - * to the link specific frame. The processed ones are marked with 0 in - * the first octet. The first octet corresponds to the element ID. In - * the case of (re)association request, the element with actual ID - * WLAN_ELEMID_SSID(0) has already been copied to the link specific - * frame. In the case of (re)association response, it has been verified - * that the element with actual ID WLAN_ELEMID_SSID(0) is present - * neither for the reporting STA nor in the STA profile. - */ - sta_prof_iesection_currpos = sta_prof_iesection; - sta_prof_iesection_remlen = sta_prof_iesection_len; - - while (sta_prof_iesection_remlen > 0) { - sta_prof_ie = sta_prof_iesection_currpos; - ret = util_validate_sta_prof_ie(sta_prof_ie, - sta_prof_iesection_currpos, - sta_prof_iesection_remlen); - if (QDF_IS_STATUS_ERROR(ret)) - goto mem_free; - - sta_prof_ie_size = sta_prof_ie[TAG_LEN_POS] + MIN_IE_LEN; - - if (!sta_prof_ie[0] || (sta_prof_ie[0] == 0xff && sta_prof_ie[1] > 0 && sta_prof_ie[2] == 0x38)) { - /* Skip this, since it has already been processed - * or it is non inheritance IE which is not required - */ - sta_prof_iesection_currpos += sta_prof_ie_size; - sta_prof_iesection_remlen -= sta_prof_ie_size; - continue; - } - - /* Copy IE from STA profile into link specific frame. */ - if ((link_frame_currpos + sta_prof_ie_size) <= - (link_frame + link_frame_maxsize)) { - if (sta_prof_ie[ID_POS] != WLAN_ELEMID_EXTN_ELEM) { - for (ie_idx = 0; ie_idx < missing_ie_len; ie_idx++) { - if (missing_ie_list[ie_idx] == - sta_prof_ie[ID_POS]) { - missing_ie_list[ie_idx] = - WLAN_ELEMID_EXTN_ELEM; - } - } - } else { - for (ie_idx = 0; ie_idx < missing_ext_ie_len; ie_idx++) { - if (missing_ext_ie_list[ie_idx] == - sta_prof_ie[IDEXT_POS]) { - missing_ext_ie_list[ie_idx] = - WLAN_ELEMID_EXTN_ELEM; - } - } - } - - qdf_mem_copy(link_frame_currpos, - sta_prof_ie, - sta_prof_ie_size); - - link_frame_currpos += sta_prof_ie_size; - link_frame_currlen += - sta_prof_ie_size; - - if (reportingsta_ie[ID_POS] == - WLAN_ELEMID_EXTN_ELEM) { - mlo_etrace_debug("IE with element ID : %u extension element ID : %u (%zu octets) is present only in STA profile. Copied IE from STA profile to link specific frame", - sta_prof_ie[ID_POS], - sta_prof_ie[IDEXT_POS], - sta_prof_ie_size); - } else { - mlo_etrace_debug("IE with element ID : %u (%zu octets) is present only in STA profile. Copied IE from STA profile to link specific frame", - sta_prof_ie[ID_POS], - sta_prof_ie_size); - } - - sta_prof_ie[0] = 0; - } else { - if (sta_prof_ie[ID_POS] == WLAN_ELEMID_EXTN_ELEM) { - mlo_etrace_err_rl("Insufficient space in link specific frame for IE with element ID : %u extension element ID : %u. Required: %zu octets, available: %zu octets", - sta_prof_ie[ID_POS], - sta_prof_ie[IDEXT_POS], - sta_prof_ie_size, - link_frame_maxsize - - link_frame_currlen); - } else { - mlo_etrace_err_rl("Insufficient space in link specific frame for IE with element ID : %u. Required: %zu octets, available: %zu octets", - sta_prof_ie[ID_POS], - sta_prof_ie_size, - link_frame_maxsize - - link_frame_currlen); - } - - ret = QDF_STATUS_E_NOMEM; - goto mem_free; - } - - sta_prof_iesection_currpos += sta_prof_ie_size; - sta_prof_iesection_remlen -= sta_prof_ie_size; - } - - /* Copy missing IEs from probe resp of original link */ - for (ie_idx = 0; ie_idx < missing_ie_len; ie_idx++) { - if (missing_ie_list[ie_idx] == WLAN_ELEMID_EXTN_ELEM) - continue; - - secondary_ie = util_find_eid(missing_ie_list[ie_idx], - bcn_prb_ies_ptr, bcn_prb_ies_len); - if (!secondary_ie) { - mlo_etrace_err_rl("IE %u not found in secondary probe resp buffer", - missing_ie_list[ie_idx]); - continue; - } - - if ((link_frame_currpos + secondary_ie[TAG_LEN_POS]) > - (link_frame + link_frame_maxsize)) { - mlo_etrace_err_rl("Insufficient space in link specific frame for IE with element ID : %u. Required: %zu octets, available: %zu octets", - secondary_ie[ID_POS], - secondary_ie[TAG_LEN_POS], - link_frame_maxsize - - link_frame_currlen); - continue; - } - - qdf_mem_copy(link_frame_currpos, secondary_ie, - secondary_ie[TAG_LEN_POS] + MIN_IE_LEN); - link_frame_currpos += secondary_ie[TAG_LEN_POS] + MIN_IE_LEN; - link_frame_currlen += secondary_ie[TAG_LEN_POS] + MIN_IE_LEN; - } - - /* Copy missing extn IEs from probe resp of original link */ - for (ie_idx = 0; ie_idx < missing_ext_ie_len; ie_idx++) { - if (missing_ext_ie_list[ie_idx] == WLAN_ELEMID_EXTN_ELEM) - continue; - - secondary_ie = util_find_extn_eid(WLAN_ELEMID_EXTN_ELEM, - missing_ext_ie_list[ie_idx], - bcn_prb_ies_ptr, - bcn_prb_ies_len); - if (!secondary_ie) { - mlo_etrace_err_rl("Extn IE %u not found in secondary probe resp buffer", - missing_iext_ie_list[ie_idx]); - continue; - } - - if ((link_frame_currpos + secondary_ie[TAG_LEN_POS]) > - (link_frame + link_frame_maxsize)) { - mlo_etrace_err_rl("Insufficient space in link specific frame for IE with extn element ID : %u. Required: %zu octets, available: %zu octets", - secondary_ie[IDEXT_POS], - secondary_ie[TAG_LEN_POS], - link_frame_maxsize - - link_frame_currlen); - continue; - } - - qdf_mem_copy(link_frame_currpos, secondary_ie, - secondary_ie[TAG_LEN_POS] + MIN_IE_LEN); - link_frame_currpos += secondary_ie[TAG_LEN_POS] + MIN_IE_LEN; - link_frame_currlen += secondary_ie[TAG_LEN_POS] + MIN_IE_LEN; - } - - /* Copy the link MAC addr */ - link_frame_hdr = (struct wlan_frame_hdr *)link_frame; - - qdf_mem_copy(link_frame_hdr->i_addr3, reportedmacaddr.bytes, - QDF_MAC_ADDR_SIZE); - qdf_mem_copy(link_frame_hdr->i_addr2, reportedmacaddr.bytes, - QDF_MAC_ADDR_SIZE); - qdf_mem_copy(link_frame_hdr->i_addr1, &link_addr, QDF_MAC_ADDR_SIZE); - - link_frame_hdr->i_fc[0] = MLO_LINKSPECIFIC_PROBE_RESP_FC0; - link_frame_hdr->i_fc[1] = MLO_LINKSPECIFIC_PROBE_RESP_FC1; - - mlo_debug("subtype:%u addr3:" QDF_MAC_ADDR_FMT " addr2:" - QDF_MAC_ADDR_FMT " addr1:" QDF_MAC_ADDR_FMT, - gen_subtype, - QDF_MAC_ADDR_REF(link_frame_hdr->i_addr3), - QDF_MAC_ADDR_REF(link_frame_hdr->i_addr2), - QDF_MAC_ADDR_REF(link_frame_hdr->i_addr1)); - - /* Seq num not used so not populated */ - - *link_frame_len = link_frame_currlen; - - qdf_err("Generated ML Probe from assoc resp"); - qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, - link_frame, link_frame_currlen); - - ret = QDF_STATUS_SUCCESS; - -mem_free: - qdf_mem_free(mlieseqpayload_copy); - return ret; -} - static QDF_STATUS util_gen_link_reqrsp_cmn(uint8_t *frame, qdf_size_t frame_len, uint8_t subtype, @@ -3927,25 +2961,6 @@ util_gen_link_assoc_req(uint8_t *frame, qdf_size_t frame_len, bool isreassoc, link_frame_maxsize, link_frame_len); } -QDF_STATUS -util_gen_link_probe_rsp_from_assoc_rsp(uint8_t *frame, qdf_size_t frame_len, - uint8_t link_id, struct qdf_mac_addr link_addr, - uint8_t *link_frame, qdf_size_t link_frame_maxsize, - qdf_size_t *link_frame_len, - uint8_t *bcn_prb_ptr, - qdf_size_t bcn_prb_len) -{ - return util_gen_link_prb_rsp_from_assoc_rsp_cmn(frame, frame_len, - WLAN_FC0_STYPE_ASSOC_RESP, - WLAN_FC0_STYPE_PROBE_RESP, - link_id, link_addr, - link_frame, - link_frame_maxsize, - link_frame_len, - bcn_prb_ptr, - bcn_prb_len); -} - QDF_STATUS util_gen_link_assoc_rsp(uint8_t *frame, qdf_size_t frame_len, bool isreassoc, uint8_t link_id, diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index 55c1c1f1e5..171fc4102b 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -529,8 +529,6 @@ struct reduced_neighbor_report { * @ecsa_ie: Pointer to eCSA IE * @max_cst_ie: Pointer to Max Channel Switch Time IE * @is_valid_link: The partner link can be used if true - * @is_scan_entry_not_found: If set to true, the partner link scan entry is - * not present in scan DB (currently using for non-TxMBSSID MLO AP) * @op_class: Operating class */ struct partner_link_info { @@ -542,7 +540,6 @@ struct partner_link_info { const uint8_t *ecsa_ie; const uint8_t *max_cst_ie; bool is_valid_link; - bool is_scan_entry_not_found; uint8_t op_class; };