diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 916c370d4ce2..404faf600f92 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -73,6 +73,7 @@ #include #include "cfg_ucfg_api.h" #include "wlan_mlme_public_struct.h" +#include "wlan_scan_utils_api.h" static void __lim_init_bss_vars(struct mac_context *mac) { @@ -1893,71 +1894,243 @@ static void sir_parse_bcn_fixed_fields(struct mac_context *mac_ctx, sir_copy_caps_info(mac_ctx, dst, beacon_struct); } +static QDF_STATUS +lim_roam_gen_mbssid_beacon(struct mac_context *mac, + struct roam_offload_synch_ind *roam_ind, + tpSirProbeRespBeacon parsed_frm) +{ + qdf_list_t *scan_list; + struct mgmt_rx_event_params rx_param; + uint8_t list_count = 0, i; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + qdf_list_node_t *next_node = NULL, *cur_node = NULL; + struct scan_cache_node *scan_node; + struct scan_cache_entry *scan_entry; + uint8_t *bcn_prb_ptr; + uint32_t nontx_bcn_prbrsp_len = 0, offset, length; + uint8_t *nontx_bcn_prbrsp = NULL; + + bcn_prb_ptr = (uint8_t *)roam_ind + + roam_ind->beaconProbeRespOffset; + + rx_param.channel = wlan_freq_to_chan(roam_ind->chan_freq); + rx_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(mac->pdev); + rx_param.rssi = roam_ind->rssi; + + scan_list = util_scan_unpack_beacon_frame(mac->pdev, bcn_prb_ptr, + roam_ind->beaconProbeRespLength, + MGMT_SUBTYPE_BEACON, &rx_param); + if (!scan_list) { + pe_err("failed to parse"); + return QDF_STATUS_E_FAILURE; + } + + list_count = qdf_list_size(scan_list); + status = qdf_list_peek_front(scan_list, &cur_node); + if (QDF_IS_STATUS_ERROR(status) || !cur_node) { + pe_debug("list peek front failure. list size %d", list_count); + goto error; + } + + for (i = 1; i < list_count; i++) { + scan_node = qdf_container_of(cur_node, + struct scan_cache_node, node); + scan_entry = scan_node->entry; + if (qdf_is_macaddr_equal(&roam_ind->bssid, + &scan_entry->bssid)) { + pe_debug("matched BSSID %pM bcn len %d profiles %d", + scan_entry->bssid.bytes, + scan_entry->raw_frame.len, + list_count); + nontx_bcn_prbrsp = scan_entry->raw_frame.ptr; + nontx_bcn_prbrsp_len = scan_entry->raw_frame.len; + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, + QDF_TRACE_LEVEL_DEBUG, + scan_entry->raw_frame.ptr, + nontx_bcn_prbrsp_len); + break; + } + status = qdf_list_peek_next(scan_list, cur_node, &next_node); + if (QDF_IS_STATUS_ERROR(status) || !next_node) { + pe_debug("list remove failure i:%d, lsize:%d", + i, list_count); + goto error; + } + cur_node = next_node; + } + + if (!nontx_bcn_prbrsp_len) { + pe_debug("failed to generate/find MBSSID beacon"); + goto error; + } + + if (roam_ind->isBeacon) { + offset = SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET; + length = nontx_bcn_prbrsp_len - SIR_MAC_HDR_LEN_3A; + if (sir_parse_beacon_ie(mac, parsed_frm, + &nontx_bcn_prbrsp[offset], + length) != QDF_STATUS_SUCCESS || + !parsed_frm->ssidPresent) { + pe_err("Parse error Beacon, length: %d", + roam_ind->beaconProbeRespLength); + status = QDF_STATUS_E_FAILURE; + goto error; + } + } else { + offset = SIR_MAC_HDR_LEN_3A; + length = nontx_bcn_prbrsp_len - SIR_MAC_HDR_LEN_3A; + if (sir_convert_probe_frame2_struct(mac, + &nontx_bcn_prbrsp[offset], + length, + parsed_frm) != QDF_STATUS_SUCCESS || + !parsed_frm->ssidPresent) { + pe_err("Parse error ProbeResponse, length: %d", + roam_ind->beaconProbeRespLength); + status = QDF_STATUS_E_FAILURE; + goto error; + } + } + +error: + for (i = 0; i < list_count; i++) { + status = qdf_list_remove_front(scan_list, &next_node); + if (QDF_IS_STATUS_ERROR(status) || !next_node) { + pe_debug("list remove failure i:%d, lsize:%d", + i, list_count); + break; + } + scan_node = qdf_container_of(next_node, + struct scan_cache_node, node); + util_scan_free_cache_entry(scan_node->entry); + qdf_mem_free(scan_node); + } + if (scan_list) + qdf_mem_free(scan_list); + + return status; +} + +static QDF_STATUS +lim_roam_gen_beacon_descr(struct mac_context *mac, + struct roam_offload_synch_ind *roam_ind, + tpSirProbeRespBeacon parsed_frm) +{ + QDF_STATUS status; + uint8_t *bcn_prb_ptr; + tpSirMacMgmtHdr mac_hdr; + + bcn_prb_ptr = (uint8_t *)roam_ind + + roam_ind->beaconProbeRespOffset; + mac_hdr = (tpSirMacMgmtHdr)bcn_prb_ptr; + + if (qdf_is_macaddr_zero((struct qdf_mac_addr *)mac_hdr->bssId)) { + pe_debug("bssid is 0 in beacon/probe update it with bssId %pM in sync ind", + roam_ind->bssid.bytes); + qdf_mem_copy(mac_hdr->bssId, roam_ind->bssid.bytes, + sizeof(tSirMacAddr)); + } + + if (qdf_mem_cmp(&roam_ind->bssid.bytes, + &mac_hdr->bssId, QDF_MAC_ADDR_SIZE) != 0) { + pe_debug("LFR3:MBSSID Beacon/Prb Rsp: %d bssid %pM", + roam_ind->isBeacon, + mac_hdr->bssId); + /* + * Its a MBSSID non-tx BSS roaming scenario. + * Generate non tx BSS beacon/probe response + */ + status = lim_roam_gen_mbssid_beacon(mac, + roam_ind, + parsed_frm); + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("failed to gen mbssid beacon"); + qdf_mem_free(parsed_frm); + return QDF_STATUS_E_FAILURE; + } + } else { + if (roam_ind->isBeacon) { + if (sir_parse_beacon_ie(mac, parsed_frm, + &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A + + SIR_MAC_B_PR_SSID_OFFSET], + roam_ind->beaconProbeRespLength - + SIR_MAC_HDR_LEN_3A) != QDF_STATUS_SUCCESS || + !parsed_frm->ssidPresent) { + pe_err("Parse error Beacon, length: %d", + roam_ind->beaconProbeRespLength); + qdf_mem_free(parsed_frm); + return QDF_STATUS_E_FAILURE; + } + } else { + if (sir_convert_probe_frame2_struct(mac, + &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A], + roam_ind->beaconProbeRespLength - + SIR_MAC_HDR_LEN_3A, parsed_frm) != + QDF_STATUS_SUCCESS || + !parsed_frm->ssidPresent) { + pe_err("Parse error ProbeResponse, length: %d", + roam_ind->beaconProbeRespLength); + qdf_mem_free(parsed_frm); + return QDF_STATUS_E_FAILURE; + } + } + } + /* + * For probe response, unpack core parses beacon interval, capabilities, + * timestamp. For beacon IEs, these fields are not parsed. + */ + if (roam_ind->isBeacon) + sir_parse_bcn_fixed_fields(mac, parsed_frm, + &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A]); + + return QDF_STATUS_SUCCESS; +} + static QDF_STATUS lim_roam_fill_bss_descr(struct mac_context *mac, - struct roam_offload_synch_ind *roam_offload_synch_ind_ptr, + struct roam_offload_synch_ind *roam_synch_ind_ptr, struct bss_description *bss_desc_ptr) { uint32_t ie_len = 0; tpSirProbeRespBeacon parsed_frm_ptr; tpSirMacMgmtHdr mac_hdr; uint8_t *bcn_proberesp_ptr; + QDF_STATUS status; - bcn_proberesp_ptr = (uint8_t *)roam_offload_synch_ind_ptr + - roam_offload_synch_ind_ptr->beaconProbeRespOffset; + bcn_proberesp_ptr = (uint8_t *)roam_synch_ind_ptr + + roam_synch_ind_ptr->beaconProbeRespOffset; mac_hdr = (tpSirMacMgmtHdr)bcn_proberesp_ptr; parsed_frm_ptr = qdf_mem_malloc(sizeof(tSirProbeRespBeacon)); if (!parsed_frm_ptr) return QDF_STATUS_E_NOMEM; - if (roam_offload_synch_ind_ptr->beaconProbeRespLength <= + if (roam_synch_ind_ptr->beaconProbeRespLength <= SIR_MAC_HDR_LEN_3A) { - pe_err("%s: very few bytes in synchInd beacon / probe resp frame! length: %d", - __func__, roam_offload_synch_ind_ptr->beaconProbeRespLength); + pe_err("very few bytes in synchInd beacon / probe resp frame! length: %d", + roam_synch_ind_ptr->beaconProbeRespLength); + qdf_mem_free(parsed_frm_ptr); + return QDF_STATUS_E_FAILURE; + } + pe_debug("LFR3:Beacon/Prb Rsp: %d bssid %pM beacon %pM", + roam_synch_ind_ptr->isBeacon, + roam_synch_ind_ptr->bssid.bytes, + mac_hdr->bssId); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, + bcn_proberesp_ptr, + roam_synch_ind_ptr->beaconProbeRespLength); + + status = lim_roam_gen_beacon_descr(mac, + roam_synch_ind_ptr, + parsed_frm_ptr); + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("Failed to parse beacon"); qdf_mem_free(parsed_frm_ptr); return QDF_STATUS_E_FAILURE; } - pe_debug("LFR3:Beacon/Prb Rsp: %d", roam_offload_synch_ind_ptr->isBeacon); - QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, - bcn_proberesp_ptr, roam_offload_synch_ind_ptr->beaconProbeRespLength); - if (roam_offload_synch_ind_ptr->isBeacon) { - if (sir_parse_beacon_ie(mac, parsed_frm_ptr, - &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A + - SIR_MAC_B_PR_SSID_OFFSET], - roam_offload_synch_ind_ptr->beaconProbeRespLength - - SIR_MAC_HDR_LEN_3A) != QDF_STATUS_SUCCESS || - !parsed_frm_ptr->ssidPresent) { - pe_err("Parse error Beacon, length: %d", - roam_offload_synch_ind_ptr->beaconProbeRespLength); - qdf_mem_free(parsed_frm_ptr); - return QDF_STATUS_E_FAILURE; - } - } else { - if (sir_convert_probe_frame2_struct(mac, - &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A], - roam_offload_synch_ind_ptr->beaconProbeRespLength - - SIR_MAC_HDR_LEN_3A, parsed_frm_ptr) != QDF_STATUS_SUCCESS || - !parsed_frm_ptr->ssidPresent) { - pe_err("Parse error ProbeResponse, length: %d", - roam_offload_synch_ind_ptr->beaconProbeRespLength); - qdf_mem_free(parsed_frm_ptr); - return QDF_STATUS_E_FAILURE; - } - } - - /* - * For probe response, unpack core parses beacon interval, capabilities, - * timestamp. For beacon IEs, these fields are not parsed. - */ - if (roam_offload_synch_ind_ptr->isBeacon) - sir_parse_bcn_fixed_fields(mac, parsed_frm_ptr, - &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A]); - /* 24 byte MAC header and 12 byte to ssid IE */ - if (roam_offload_synch_ind_ptr->beaconProbeRespLength > + if (roam_synch_ind_ptr->beaconProbeRespLength > (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) { - ie_len = roam_offload_synch_ind_ptr->beaconProbeRespLength - + ie_len = roam_synch_ind_ptr->beaconProbeRespLength - (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); } /* @@ -1976,7 +2149,7 @@ lim_roam_fill_bss_descr(struct mac_context *mac, ieFields[0]) - sizeof(bss_desc_ptr->length) + ie_len); - bss_desc_ptr->fProbeRsp = !roam_offload_synch_ind_ptr->isBeacon; + bss_desc_ptr->fProbeRsp = !roam_synch_ind_ptr->isBeacon; /* Copy Timestamp */ bss_desc_ptr->scansystimensec = qdf_get_monotonic_boottime_ns(); if (parsed_frm_ptr->dsParamsPresent) { @@ -1989,7 +2162,7 @@ lim_roam_fill_bss_descr(struct mac_context *mac, * beacon, then use the channel frequency provided by firmware * to fill the channel in the BSS descriptor.*/ bss_desc_ptr->channelId = - cds_freq_to_chan(roam_offload_synch_ind_ptr->chan_freq); + cds_freq_to_chan(roam_synch_ind_ptr->chan_freq); } bss_desc_ptr->channelIdSelf = bss_desc_ptr->channelId; @@ -2004,17 +2177,9 @@ lim_roam_fill_bss_descr(struct mac_context *mac, qdf_mem_copy(&bss_desc_ptr->capabilityInfo, &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_CAPAB_OFFSET], 2); - if (qdf_is_macaddr_zero((struct qdf_mac_addr *)mac_hdr->bssId)) { - pe_debug("bssid is 0 in beacon/probe update it with bssId %pM in sync ind", - roam_offload_synch_ind_ptr->bssid.bytes); - qdf_mem_copy(mac_hdr->bssId, - roam_offload_synch_ind_ptr->bssid.bytes, - sizeof(tSirMacAddr)); - } - qdf_mem_copy((uint8_t *) &bss_desc_ptr->bssId, - (uint8_t *) mac_hdr->bssId, - sizeof(tSirMacAddr)); + (uint8_t *)roam_synch_ind_ptr->bssid.bytes, + sizeof(tSirMacAddr)); bss_desc_ptr->received_time = (uint64_t)qdf_mc_timer_get_system_time(); if (parsed_frm_ptr->mdiePresent) {