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