Merge "qcacmn: Use only partner links with valid scan entry" into wlan-cmn.driver.lnx.2.0.14

This commit is contained in:
CNSS_WLAN Service
2024-04-19 04:18:22 -07:00
committad av Gerrit - the friendly Code Review server
förälder 1111cf6224 99f24676b4
incheckning 4004081535
4 ändrade filer med 71 tillägg och 1042 borttagningar

Visa fil

@@ -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)

Visa fil

@@ -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)

Visa fil

@@ -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,

Visa fil

@@ -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;
};