diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 15f8dbed3e363..50de87a5ea860 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -1,9 +1,6 @@ /* * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all @@ -19,12 +16,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - #ifndef _ANIGLOBAL_H #define _ANIGLOBAL_H @@ -875,6 +866,28 @@ struct vdev_type_nss { uint8_t ocb; }; +/** + * struct mgmt_beacon_probe_filter + * @bcn_filter_lock: Spinlock for the filter structure + * @num_sta_sessions: Number of active PE STA sessions + * @sta_bssid: Array of PE STA session's peer BSSIDs + * @num_ibss_sessions: Number of active PE IBSS sessions + * @ibss_ssid: Array of PE IBSS session's SSID + * @num_sap_session: Number of active PE SAP sessions + * @sap_channel: Array of PE SAP session's channels + * + * Used to filter the STA/IBSS/SAP beacons/probes required in PE and + * drop other unwanted beacon/probe response frames + */ +struct mgmt_beacon_probe_filter { + uint8_t num_sta_sessions; + tSirMacAddr sta_bssid[SIR_MAX_SUPPORTED_BSS]; + uint8_t num_ibss_sessions; + tSirMacSSid ibss_ssid[SIR_MAX_SUPPORTED_BSS]; + uint8_t num_sap_sessions; + uint8_t sap_channel[SIR_MAX_SUPPORTED_BSS]; +}; + /* ------------------------------------------------------------------- */ /* / MAC Sirius parameter structure */ typedef struct sAniSirGlobal { @@ -949,6 +962,7 @@ typedef struct sAniSirGlobal { uint16_t usr_cfg_ba_buff_size; uint8_t no_ack_policy_cfg[MAX_NUM_AC]; uint32_t he_sgi_ltf_cfg_bit_mask; + struct mgmt_beacon_probe_filter bcn_filter; } tAniSirGlobal; diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 14e29c6dbad6d..a17917e3e4b3b 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -1,9 +1,6 @@ /* * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all @@ -19,12 +16,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - #if !defined(__LIM_SESSION_H) #define __LIM_SESSION_H @@ -697,4 +688,46 @@ uint8_t pe_get_active_session_count(tpAniSirGlobal mac_ctx); */ void pe_delete_fils_info(tpPESession session); #endif + +/** + * lim_set_bcn_probe_filter - set the beacon/probe filter in mac context + * + * @mac_ctx: pointer to global mac context + * @session: pointer to the PE session + * @ibss_ssid: SSID of the session for IBSS sessions + * @sap_channel: Operating Channel of the session for SAP sessions + * + * Sets the beacon/probe filter in the global mac context to filter + * and drop beacon/probe frames before posting it to PE queue + * + * Return: None + */ +void lim_set_bcn_probe_filter(tpAniSirGlobal mac_ctx, + tpPESession session, + tSirMacSSid *ibss_ssid, + uint8_t sap_channel); + +/** + * lim_reset_bcn_probe_filter - clear the beacon/probe filter in mac context + * + * @mac_ctx: pointer to the global mac context + * @session: pointer to the PE session whose filter is to be cleared + * + * Return: None + */ +void lim_reset_bcn_probe_filter(tpAniSirGlobal mac_ctx, tpPESession session); + +/** + * lim_update_bcn_probe_filter - Update the beacon/probe filter in mac context + * + * @mac_ctx: pointer to the global mac context + * @session: pointer to the PE session whose filter is to be cleared + * + * This API is applicable only for SAP sessions to update the SAP channel + * in the filter during a channel switch + * + * Return: None + */ +void lim_update_bcn_probe_filter(tpAniSirGlobal mac_ctx, tpPESession session); + #endif /* #if !defined( __LIM_SESSION_H ) */ diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index ba0908a5f64cf..f8afcce400607 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1,9 +1,6 @@ /* * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all @@ -19,12 +16,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - /* * This file lim_api.cc contains the functions that are * exported by LIM to other modules. @@ -77,6 +68,8 @@ #include "os_if_nan.h" #include #include +#include "wlan_utility.h" + static void __lim_init_scan_vars(tpAniSirGlobal pMac) { @@ -1214,6 +1207,87 @@ static QDF_STATUS pe_drop_pending_rx_mgmt_frames(tpAniSirGlobal mac_ctx, return QDF_STATUS_SUCCESS; } +/** + * pe_filter_drop_bcn_probe_frame - Apply filter on the received frame + * + * @mac_ctx: pointer to the global mac context + * @hdr: pointer to the 802.11 header of the frame + * @rx_pkt_info: pointer to the rx packet meta + * + * Applies the filter from global mac context on the received beacon/ + * probe response frame before posting it to the PE queue + * + * Return: true if frame is allowed, false if frame is to be dropped. + */ +static bool pe_filter_bcn_probe_frame(tpAniSirGlobal mac_ctx, + tpSirMacMgmtHdr hdr, + uint8_t *rx_pkt_info) +{ + uint8_t session_id; + uint8_t *body; + const uint8_t *ssid_ie; + uint16_t frame_len; + struct mgmt_beacon_probe_filter *filter; + tpSirMacCapabilityInfo bcn_caps; + tSirMacSSid bcn_ssid; + + filter = &mac_ctx->bcn_filter; + + /* + * If any STA session exists and beacon source matches any of the + * STA BSSIDs, allow the frame + */ + if (filter->num_sta_sessions) { + for (session_id = 0; session_id < SIR_MAX_SUPPORTED_BSS; + session_id++) { + if (sir_compare_mac_addr(filter->sta_bssid[session_id], + hdr->bssId)) { + return true; + } + } + } + + /* + * If any IBSS session exists and beacon is has IBSS capability set + * and SSID matches the IBSS SSID, allow the frame + */ + if (filter->num_ibss_sessions) { + body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); + frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); + if (frame_len < SIR_MAC_B_PR_SSID_OFFSET) + return false; + + bcn_caps = (tpSirMacCapabilityInfo) + (body + SIR_MAC_B_PR_CAPAB_OFFSET); + if (!bcn_caps->ibss) + return false; + + ssid_ie = wlan_get_ie_ptr_from_eid(SIR_MAC_SSID_EID, + body + SIR_MAC_B_PR_SSID_OFFSET, + frame_len); + + if (!ssid_ie) + return false; + + bcn_ssid.length = ssid_ie[1]; + qdf_mem_copy(&bcn_ssid.ssId, + &ssid_ie[2], + bcn_ssid.length); + + for (session_id = 0; session_id < SIR_MAX_SUPPORTED_BSS; + session_id++) { + if (filter->ibss_ssid[session_id].length == + bcn_ssid.length && + (!qdf_mem_cmp(filter->ibss_ssid[session_id].ssId, + bcn_ssid.ssId, bcn_ssid.length))) { + return true; + } + } + } + + return false; +} + /* --------------------------------------------------------------------------- */ /** * pe_handle_mgmt_frame() - Process the Management frames from TXRX @@ -1277,6 +1351,18 @@ static QDF_STATUS pe_handle_mgmt_frame(struct wlan_objmgr_psoc *psoc, mHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + /* + * Filter the beacon/probe response frames before posting it + * on the PE queue + */ + if ((mHdr->fc.subType == SIR_MAC_MGMT_BEACON || + mHdr->fc.subType == SIR_MAC_MGMT_PROBE_RSP) && + !pe_filter_bcn_probe_frame(pMac, mHdr, pRxPacketInfo)) { + cds_pkt_return_packet(pVosPkt); + pVosPkt = NULL; + return QDF_STATUS_SUCCESS; + } + if (QDF_STATUS_SUCCESS != pe_drop_pending_rx_mgmt_frames(pMac, mHdr, pVosPkt)) return QDF_STATUS_E_FAILURE; @@ -2269,12 +2355,13 @@ QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx, lim_print_mac_addr(mac_ctx, bss_desc->bssId, LOGE); return status; } - ft_session_ptr->peSessionId = session_id; + /* Update the beacon/probe filter in mac_ctx */ + lim_set_bcn_probe_filter(mac_ctx, ft_session_ptr, NULL, 0); + sir_copy_mac_addr(ft_session_ptr->selfMacAddr, session_ptr->selfMacAddr); sir_copy_mac_addr(roam_sync_ind_ptr->self_mac.bytes, session_ptr->selfMacAddr); sir_copy_mac_addr(ft_session_ptr->limReAssocbssId, bss_desc->bssId); - ft_session_ptr->bssType = eSIR_INFRASTRUCTURE_MODE; session_ptr->bRoamSynchInProgress = true; ft_session_ptr->bRoamSynchInProgress = true; ft_session_ptr->limSystemRole = eLIM_STA_ROLE; diff --git a/core/mac/src/pe/lim/lim_ft_preauth.c b/core/mac/src/pe/lim/lim_ft_preauth.c index 4aa0129820b2b..5626cf72b892f 100644 --- a/core/mac/src/pe/lim/lim_ft_preauth.c +++ b/core/mac/src/pe/lim/lim_ft_preauth.c @@ -1,8 +1,6 @@ /* * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all @@ -450,13 +448,17 @@ void lim_handle_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status, psessionEntry->ftPEContext.ftPreAuthStatus = status; goto send_rsp; } - pftSessionEntry->peSessionId = sessionId; + pftSessionEntry->smeSessionId = psessionEntry->smeSessionId; sir_copy_mac_addr(pftSessionEntry->selfMacAddr, psessionEntry->selfMacAddr); sir_copy_mac_addr(pftSessionEntry->limReAssocbssId, pbssDescription->bssId); - pftSessionEntry->bssType = psessionEntry->bssType; + + /* Update the beacon/probe filter in mac_ctx */ + lim_set_bcn_probe_filter(pMac, + pftSessionEntry, + NULL, 0); if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) pftSessionEntry->limSystemRole = eLIM_STA_ROLE; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 8ccba3ce9b509..83d21c5198e2f 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1,9 +1,6 @@ /* * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all @@ -19,12 +16,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - /* * This file lim_process_sme_req_messages.cc contains the code * for processing SME request messages. @@ -643,6 +634,11 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; goto free; } + + /* Update the beacon/probe filter in mac_ctx */ + lim_set_bcn_probe_filter(mac_ctx, session, + &sme_start_bss_req->ssId, + sme_start_bss_req->channelId); } if (QDF_NDI_MODE != sme_start_bss_req->bssPersona) { @@ -676,9 +672,6 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) /* Store the session related params in newly created session */ session->pLimStartBssReq = sme_start_bss_req; - /* Store PE session_id in session Table */ - session->peSessionId = session_id; - /* Store SME session Id in sessionTable */ session->smeSessionId = sme_start_bss_req->sessionId; @@ -1328,17 +1321,21 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) pe_err("Session Can not be created"); ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; - } else + } else { pe_debug("SessionId:%d New session created", session_id); + } + + /* Update the beacon/probe filter in mac_ctx */ + lim_set_bcn_probe_filter(mac_ctx, session, + &sme_join_req->ssId, + bss_desc->channelId); } session->max_amsdu_num = sme_join_req->max_amsdu_num; /* * Store Session related parameters - * Store PE session Id in session Table */ - session->peSessionId = session_id; /* store the smejoin req handle in session table */ session->pLimJoinReq = sme_join_req; diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index 265657113c415..9383c96ae36f0 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -1,9 +1,6 @@ /* * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all @@ -19,12 +16,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ - /**========================================================================= \file lim_session.c @@ -379,6 +370,152 @@ lim_get_peer_idxpool_size(uint16_t num_sta, tSirBssType bss_type) } #endif +void lim_set_bcn_probe_filter(tpAniSirGlobal mac_ctx, + tpPESession session, + tSirMacSSid *ibss_ssid, + uint8_t sap_channel) +{ + struct mgmt_beacon_probe_filter *filter; + tSirBssType bss_type; + uint8_t session_id; + tSirMacAddr *bssid; + + if (!session) { + pe_err("Invalid session pointer"); + return; + } + + bss_type = session->bssType; + session_id = session->peSessionId; + bssid = &session->bssId; + + if (session_id >= SIR_MAX_SUPPORTED_BSS) { + pe_err("Invalid session_id %d of type %d", + session_id, bss_type); + return; + } + + filter = &mac_ctx->bcn_filter; + + if (eSIR_INFRASTRUCTURE_MODE == bss_type) { + filter->num_sta_sessions++; + sir_copy_mac_addr(filter->sta_bssid[session_id], *bssid); + pe_debug("Set filter for STA Session %d bssid "MAC_ADDRESS_STR, + session_id, MAC_ADDR_ARRAY(*bssid)); + } else if (eSIR_IBSS_MODE == bss_type) { + if (!ibss_ssid) { + pe_err("IBSS Type with NULL SSID"); + goto done; + } + filter->num_ibss_sessions++; + filter->ibss_ssid[session_id].length = ibss_ssid->length; + qdf_mem_copy(&filter->ibss_ssid[session_id].length, + ibss_ssid->ssId, + ibss_ssid->length); + pe_debug("Set filter for IBSS session %d ssid %s", + session_id, ibss_ssid->ssId); + } else if (eSIR_INFRA_AP_MODE == bss_type) { + if (!sap_channel) { + pe_err("SAP Type with invalid channel"); + goto done; + } + filter->num_sap_sessions++; + filter->sap_channel[session_id] = sap_channel; + pe_debug("Set filter for SAP session %d channel %d", + session_id, sap_channel); + } + +done: + pe_debug("sta %d ibss %d sap %d", + filter->num_sta_sessions, filter->num_ibss_sessions, + filter->num_sap_sessions); +} + +void lim_reset_bcn_probe_filter(tpAniSirGlobal mac_ctx, + tpPESession session) +{ + struct mgmt_beacon_probe_filter *filter; + tSirBssType bss_type; + uint8_t session_id; + + if (!session) { + pe_err("Invalid session pointer"); + return; + } + + bss_type = session->bssType; + session_id = session->peSessionId; + + if (session_id >= SIR_MAX_SUPPORTED_BSS) { + pe_err("Invalid session_id %d of type %d", + session_id, bss_type); + return; + } + + filter = &mac_ctx->bcn_filter; + + if (eSIR_INFRASTRUCTURE_MODE == bss_type) { + if (filter->num_sta_sessions) + filter->num_sta_sessions--; + qdf_mem_set(&filter->sta_bssid[session_id], + sizeof(tSirMacAddr), 0); + pe_debug("Cleared STA Filter for session %d", session_id); + } else if (eSIR_IBSS_MODE == bss_type) { + if (filter->num_ibss_sessions) + filter->num_ibss_sessions--; + filter->ibss_ssid[session_id].length = 0; + qdf_mem_set(&filter->ibss_ssid[session_id].ssId, + SIR_MAC_MAX_SSID_LENGTH, 0); + pe_debug("Cleared IBSS Filter for session %d", session_id); + } else if (eSIR_INFRA_AP_MODE == bss_type) { + if (filter->num_sap_sessions) + filter->num_sap_sessions--; + filter->sap_channel[session_id] = 0; + pe_debug("Cleared SAP Filter for session %d", session_id); + } + + pe_debug("sta %d ibss %d sap %d", + filter->num_sta_sessions, filter->num_ibss_sessions, + filter->num_sap_sessions); +} + +void lim_update_bcn_probe_filter(tpAniSirGlobal mac_ctx, + tpPESession session) +{ + struct mgmt_beacon_probe_filter *filter; + tSirBssType bss_type; + uint8_t session_id; + + if (!session) { + pe_err("Invalid session pointer"); + return; + } + + bss_type = session->bssType; + session_id = session->peSessionId; + + if (session_id >= SIR_MAX_SUPPORTED_BSS) { + pe_err("Invalid session_id %d of type %d", + session_id, bss_type); + return; + } + + filter = &mac_ctx->bcn_filter; + + if (eSIR_INFRA_AP_MODE == bss_type) { + filter->sap_channel[session_id] = session->currentOperChannel; + pe_debug("Updated SAP Filter for session %d channel %d", + session_id, filter->sap_channel[session_id]); + } else { + pe_debug("Invalid session type %d session id %d", + bss_type, session_id); + } + + pe_debug("sta %d ibss %d sap %d", + filter->num_sta_sessions, filter->num_ibss_sessions, + filter->num_sap_sessions); +} + /** * pe_create_session() creates a new PE session given the BSSID * @param pMac: pointer to global adapter context @@ -459,6 +596,8 @@ pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId, session_ptr->isFastTransitionEnabled = false; session_ptr->isFastRoamIniFeatureEnabled = false; *sessionId = i; + session_ptr->peSessionId = i; + session_ptr->bssType = bssType; session_ptr->gLimPhyMode = WNI_CFG_PHY_MODE_11G; /* Initialize CB mode variables when session is created */ session_ptr->htSupportedChannelWidthSet = 0; @@ -689,6 +828,9 @@ void pe_delete_session(tpAniSirGlobal mac_ctx, tpPESession session) session->peSessionId, session->operMode, session->bssIdx, MAC_ADDR_ARRAY(session->bssId)); + + lim_reset_bcn_probe_filter(mac_ctx, session); + for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) { timer_ptr = &mac_ctx->lim.limTimers.gpLimCnfWaitTimer[n]; if (session->peSessionId == timer_ptr->sessionId)