diff --git a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c index db70cac88e49..e6a6e34d2791 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -1212,6 +1212,18 @@ vdevmgr_vdev_start_rsp_handle(struct vdev_mlme_obj *vdev_mlme, return status; } +static QDF_STATUS +vdevmgr_vdev_peer_delete_all_rsp_handle(struct vdev_mlme_obj *vdev_mlme, + struct peer_delete_all_response *rsp) +{ + QDF_STATUS status; + + status = lim_process_mlm_del_all_sta_rsp(vdev_mlme, rsp); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("Failed to call lim_process_mlm_del_all_sta_rsp"); + return status; +} + QDF_STATUS mlme_vdev_self_peer_create(struct wlan_objmgr_vdev *vdev) { struct vdev_mlme_obj *vdev_mlme; @@ -1462,6 +1474,8 @@ static struct vdev_mlme_ops sta_mlme_ops = { * to INIT state * @mlme_vdev_is_newchan_no_cac: callback to check if new channel is DFS * and cac is not required + * @mlme_vdev_ext_peer_delete_all_rsp: callback to handle vdev delete all peer + * response and send result to upper layer */ static struct vdev_mlme_ops ap_mlme_ops = { .mlme_vdev_start_send = ap_mlme_vdev_start_send, @@ -1481,6 +1495,8 @@ static struct vdev_mlme_ops ap_mlme_ops = { .mlme_vdev_is_newchan_no_cac = ap_mlme_vdev_is_newchan_no_cac, .mlme_vdev_ext_stop_rsp = vdevmgr_vdev_stop_rsp_handle, .mlme_vdev_ext_start_rsp = vdevmgr_vdev_start_rsp_handle, + .mlme_vdev_ext_peer_delete_all_rsp = + vdevmgr_vdev_peer_delete_all_rsp_handle, }; static struct vdev_mlme_ops mon_mlme_ops = { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 45059a79b898..730c69d9a408 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -20690,6 +20690,7 @@ QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter, struct hdd_hostapd_state *hapd_state, struct csr_del_sta_params *param) { + uint8_t index = 0; qdf_event_t *disassoc_event = &hapd_state->qdf_sta_disassoc_event; struct hdd_context *hdd_ctx; QDF_STATUS qdf_status; @@ -20714,7 +20715,13 @@ QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter, qdf_status = hdd_softap_sta_deauth(adapter, param); if (QDF_IS_STATUS_SUCCESS(qdf_status)) { - sta_info->is_deauth_in_progress = true; + if(qdf_is_macaddr_broadcast(&sta_info->sta_mac)) { + hdd_for_each_station(adapter->sta_info_list, + sta_info, index) + sta_info->is_deauth_in_progress = true; + } else { + sta_info->is_deauth_in_progress = true; + } qdf_status = qdf_wait_for_event_completion( disassoc_event, SME_PEER_DISCONNECT_TIMEOUT); @@ -20758,8 +20765,15 @@ QDF_STATUS hdd_softap_deauth_all_sta(struct hdd_adapter *adapter, ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc, &is_sap_bcast_deauth_enabled); - if (is_sap_bcast_deauth_enabled) - return QDF_STATUS_E_INVAL; + hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled); + + if (is_sap_bcast_deauth_enabled) { + struct hdd_station_info bcast_sta_info; + + qdf_set_macaddr_broadcast(&bcast_sta_info.sta_mac); + return hdd_softap_deauth_current_sta(adapter, &bcast_sta_info, + hapd_state, param); + } hdd_for_each_station(adapter->sta_info_list, sta_info, index) { if (!sta_info->is_deauth_in_progress) { diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 530dc9416b3f..6923d0d5554c 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -13826,12 +13826,25 @@ QDF_STATUS hdd_softap_sta_deauth(struct hdd_adapter *adapter, struct csr_del_sta_params *param) { QDF_STATUS qdf_status = QDF_STATUS_E_FAULT; + struct hdd_context *hdd_ctx; + bool is_sap_bcast_deauth_enabled = false; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) { + hdd_err("hdd_ctx is NULL"); + return QDF_STATUS_E_INVAL; + } + + ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc, + &is_sap_bcast_deauth_enabled); hdd_enter(); + hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled); /* Ignore request to deauth bcmc station */ - if (param->peerMacAddr.bytes[0] & 0x1) - return qdf_status; + if (!is_sap_bcast_deauth_enabled) + if (param->peerMacAddr.bytes[0] & 0x1) + return qdf_status; qdf_status = wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter), diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index ceaf07523785..10f7045e968d 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -55,6 +55,10 @@ #include "wlan_utility.h" #include "wlan_mlme_api.h" #include "wma.h" +#include "../../core/src/vdev_mgr_ops.h" + +#include +#include #ifdef FEATURE_WLAN_TDLS #define IS_TDLS_PEER(type) ((type) == STA_ENTRY_TDLS_PEER) @@ -301,6 +305,80 @@ uint8_t lim_check_mcs_set(struct mac_context *mac, uint8_t *supportedMCSSet) #define SECURITY_SUITE_TYPE_GCMP 0x8 #define SECURITY_SUITE_TYPE_GCMP_256 0x9 +/** + *lim_del_peer_info() - remove all peer information from host driver and fw + * @mac: Pointer to Global MAC structure + * @pe_session: Pointer to PE Session entry + * + * @Return: QDF_STATUS + */ + +QDF_STATUS lim_del_peer_info(struct mac_context *mac, + struct pe_session *pe_session) +{ + void *soc = cds_get_context(QDF_MODULE_ID_SOC); + uint16_t i; + uint32_t bitmap = 1 << CDP_PEER_DELETE_NO_SPECIAL; + bool peer_unmap_conf_support_enabled; + + peer_unmap_conf_support_enabled = + cdp_cfg_get_peer_unmap_conf_support(soc); + + for (i = 0; i < pe_session->dph.dphHashTable.size; i++) { + tpDphHashNode sta_ds; + + sta_ds = dph_get_hash_entry(mac, i, + &pe_session->dph.dphHashTable); + if (!sta_ds) + continue; + + cdp_peer_teardown(soc, pe_session->vdev_id, sta_ds->staAddr); + if (peer_unmap_conf_support_enabled) + cdp_peer_delete_sync(soc, pe_session->vdev_id, + sta_ds->staAddr, + wma_peer_unmap_conf_cb, + bitmap); + else + cdp_peer_delete(soc, pe_session->vdev_id, + sta_ds->staAddr, bitmap); + } + return QDF_STATUS_SUCCESS; +} + +/** + * lim_del_sta_all(): Cleanup all peers associated with VDEV + * @mac: Pointer to Global MAC structure + * @pe_session: Pointer to PE Session entry + * + * @Return: QDF Status of operation + */ + +QDF_STATUS lim_del_sta_all(struct mac_context *mac, + struct pe_session *pe_session) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct vdev_mlme_obj *mlme_obj; + + if (!LIM_IS_AP_ROLE(pe_session)) + return QDF_STATUS_E_INVAL; + + mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev); + if (!mlme_obj) { + pe_err("vdev component object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + status = vdev_mgr_peer_delete_all_send(mlme_obj); + if (status != QDF_STATUS_SUCCESS) { + pe_err("failed status = %d", status); + return status; + } + + status = lim_del_peer_info(mac, pe_session); + + return status; +} + /** * lim_cleanup_rx_path() * @@ -4051,6 +4129,47 @@ returnFailure: return retCode; } +/** + * lim_prepare_and_send_del_all_sta_cnf() - prepares and send del all sta cnf + * @mac: mac global context + * @status_code: status code + * @pe_session: session context + * + * deletes DPH entry, changes the MLM mode for station, calls + * lim_send_del_sta_cnf + * + * Return: void + */ +void lim_prepare_and_send_del_all_sta_cnf(struct mac_context *mac, + tSirResultCodes status_code, + struct pe_session *pe_session) +{ + tLimMlmDeauthCnf mlm_deauth; + tpDphHashNode sta_ds = NULL; + uint32_t i; + + if (!LIM_IS_AP_ROLE(pe_session)) + return; + + for (i = 1; i < pe_session->dph.dphHashTable.size; i++) { + sta_ds = dph_get_hash_entry(mac, i, + &pe_session->dph.dphHashTable); + if (!sta_ds) + continue; + lim_delete_dph_hash_entry(mac, sta_ds->staAddr, + sta_ds->assocId, pe_session); + lim_release_peer_idx(mac, sta_ds->assocId, pe_session); + } + + qdf_set_macaddr_broadcast(&mlm_deauth.peer_macaddr); + mlm_deauth.resultCode = status_code; + mlm_deauth.deauthTrigger = eLIM_HOST_DEAUTH; + mlm_deauth.sessionId = pe_session->peSessionId; + + lim_post_sme_message(mac, LIM_MLM_DEAUTH_CNF, + (uint32_t *)&mlm_deauth); +} + /** * lim_prepare_and_send_del_sta_cnf() - prepares and send del sta cnf * diff --git a/core/mac/src/pe/lim/lim_assoc_utils.h b/core/mac/src/pe/lim/lim_assoc_utils.h index 793d0d0371aa..f73313a3519d 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.h +++ b/core/mac/src/pe/lim/lim_assoc_utils.h @@ -104,6 +104,26 @@ QDF_STATUS lim_del_bss(struct mac_context *, tpDphHashNode, uint16_t, struct pe_ QDF_STATUS lim_del_sta(struct mac_context *, tpDphHashNode, bool, struct pe_session *); QDF_STATUS lim_add_sta_self(struct mac_context *, uint8_t, struct pe_session *); +/** + *lim_del_peer_info() - remove all peer information from host driver and fw + * @mac: Pointer to Global MAC structure + * @pe_session: Pointer to PE Session entry + * + * @Return: QDF_STATUS + */ +QDF_STATUS lim_del_peer_info(struct mac_context *mac, + struct pe_session *pe_session); + +/** + * lim_del_sta_all() - Cleanup all peers associated with VDEV + * @mac: Pointer to Global MAC structure + * @pe_session: Pointer to PE Session entry + * + * @Return: QDF Status of operation. + */ +QDF_STATUS lim_del_sta_all(struct mac_context *mac, + struct pe_session *pe_session); + #ifdef WLAN_FEATURE_HOST_ROAM void lim_restore_pre_reassoc_state(struct mac_context *, tSirResultCodes, uint16_t, struct pe_session *); @@ -228,6 +248,10 @@ QDF_STATUS lim_sta_send_add_bss(struct mac_context *mac, QDF_STATUS lim_sta_send_add_bss_pre_assoc(struct mac_context *mac, struct pe_session *pe_session); +void lim_prepare_and_send_del_all_sta_cnf(struct mac_context *mac, + tSirResultCodes status_code, + struct pe_session *pe_session); + void lim_prepare_and_send_del_sta_cnf(struct mac_context *mac, tpDphHashNode sta, tSirResultCodes status_code, diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index 579b95e48640..64224423eaf6 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -1232,7 +1232,7 @@ static void lim_process_mlm_deauth_req_ntf(struct mac_context *mac_ctx, QDF_STATUS suspend_status, uint32_t *msg_buf) { - uint16_t aid; + uint16_t aid, i; tSirMacAddr curr_bssId; tpDphHashNode sta_ds; struct tLimPreAuthNode *auth_node; @@ -1366,56 +1366,90 @@ lim_process_mlm_deauth_req_ntf(struct mac_context *mac_ctx, */ sta_ds = dph_lookup_hash_entry(mac_ctx, mlm_deauth_req->peer_macaddr.bytes, - &aid, &session->dph.dphHashTable); + &aid, + &session->dph.dphHashTable); - if (!sta_ds) { + if (!sta_ds && (!mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled + || (mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled && + !qdf_is_macaddr_broadcast(&mlm_deauth_req->peer_macaddr)))) { /* Check if there exists pre-auth context for this STA */ - auth_node = lim_search_pre_auth_list(mac_ctx, - mlm_deauth_req->peer_macaddr.bytes); + auth_node = lim_search_pre_auth_list(mac_ctx, mlm_deauth_req-> + peer_macaddr.bytes); if (!auth_node) { /* * Received DEAUTH REQ for a STA that is neither * Associated nor Pre-authenticated. Log error, * Prepare and Send LIM_MLM_DEAUTH_CNF */ - pe_warn("received MLM_DEAUTH_REQ in mlme state %d for STA that " - "does not have context, Addr=" - QDF_MAC_ADDR_STR, - session->limMlmState, + pe_warn("rcvd MLM_DEAUTH_REQ in mlme state %d", + session->limMlmState); + pe_warn("STA does not have context, Addr=" + QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY( - mlm_deauth_req->peer_macaddr.bytes)); + mlm_deauth_req->peer_macaddr.bytes)); mlm_deauth_cnf.resultCode = eSIR_SME_STA_NOT_AUTHENTICATED; } else { mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS; /* Delete STA from pre-auth STA list */ lim_delete_pre_auth_node(mac_ctx, - mlm_deauth_req->peer_macaddr.bytes); - /* Send Deauthentication frame to peer entity */ + mlm_deauth_req-> + peer_macaddr.bytes); + /*Send Deauthentication frame to peer entity*/ lim_send_deauth_mgmt_frame(mac_ctx, - mlm_deauth_req->reasonCode, - mlm_deauth_req->peer_macaddr.bytes, - session, false); + mlm_deauth_req->reasonCode, + mlm_deauth_req-> + peer_macaddr.bytes, + session, false); } goto end; - } else if ((sta_ds->mlmStaContext.mlmState != - eLIM_MLM_LINK_ESTABLISHED_STATE) && + } else if (sta_ds && (sta_ds->mlmStaContext.mlmState != + eLIM_MLM_LINK_ESTABLISHED_STATE) && (sta_ds->mlmStaContext.mlmState != - eLIM_MLM_WT_ASSOC_CNF_STATE)) { + eLIM_MLM_WT_ASSOC_CNF_STATE)) { /* - * received MLM_DEAUTH_REQ for STA that either has no context or - * in some transit state + * received MLM_DEAUTH_REQ for STA that either has no + * context or in some transit state */ - pe_warn("Invalid MLM_DEAUTH_REQ, Addr="QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(mlm_deauth_req->peer_macaddr.bytes)); + pe_warn("Invalid MLM_DEAUTH_REQ, Addr=" QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(mlm_deauth_req-> + peer_macaddr.bytes)); /* Prepare and Send LIM_MLM_DEAUTH_CNF */ mlm_deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; + } else if (sta_ds) { + /* sta_ds->mlmStaContext.rxPurgeReq = 1; */ + sta_ds->mlmStaContext.disassocReason = (tSirMacReasonCodes) + mlm_deauth_req->reasonCode; + sta_ds->mlmStaContext.cleanupTrigger = + mlm_deauth_req->deauthTrigger; + + /* + * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE + * This is to address the issue of race condition between + * disconnect request from the HDD and disassoc from + * inactivity timer. This will make sure that we will not + * process disassoc if deauth is in progress for the station + * and thus mlmStaContext.cleanupTrigger will not be + * overwritten. + */ + sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + } else if (mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled && + qdf_is_macaddr_broadcast(&mlm_deauth_req->peer_macaddr)) { + for (i = 0; i < session->dph.dphHashTable.size; i++) { + sta_ds = dph_get_hash_entry(mac_ctx, i, + &session->dph.dphHashTable); + if (!sta_ds) + continue; + + sta_ds->mlmStaContext.disassocReason = + (tSirMacReasonCodes)mlm_deauth_req->reasonCode; + sta_ds->mlmStaContext.cleanupTrigger = + mlm_deauth_req->deauthTrigger; + sta_ds->mlmStaContext.mlmState = + eLIM_MLM_WT_DEL_STA_RSP_STATE; + } } - /* sta_ds->mlmStaContext.rxPurgeReq = 1; */ - sta_ds->mlmStaContext.disassocReason = (tSirMacReasonCodes) - mlm_deauth_req->reasonCode; - sta_ds->mlmStaContext.cleanupTrigger = mlm_deauth_req->deauthTrigger; if (mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq) { pe_err("pMlmDeauthReq is not NULL, freeing"); @@ -1424,15 +1458,6 @@ lim_process_mlm_deauth_req_ntf(struct mac_context *mac_ctx, } mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = mlm_deauth_req; - /* - * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE - * This is to address the issue of race condition between - * disconnect request from the HDD and disassoc from - * inactivity timer. This will make sure that we will not - * process disassoc if deauth is in progress for the station - * and thus mlmStaContext.cleanupTrigger will not be overwritten. - */ - sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; /* Send Deauthentication frame to peer entity */ lim_send_deauth_mgmt_frame(mac_ctx, mlm_deauth_req->reasonCode, mlm_deauth_req->peer_macaddr.bytes, diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index b5cbf6c1d8b7..e1b8953bb0d8 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1648,6 +1648,43 @@ end: pe_delete_session(mac, pe_session); } +/** + * lim_process_mlm_del_all_sta_rsp() - Process DEL STA response + * @mac_ctx: Pointer to Global MAC structure + * @msg: The MsgQ header, which contains the response buffer + * + * This function is called to process a WMA_DEL_ALL_STA_RSP from + * WMA Upon receipt of this message from FW. + * + * Return: QDF_STATUS + */ +QDF_STATUS +lim_process_mlm_del_all_sta_rsp(struct vdev_mlme_obj *vdev_mlme, + struct peer_delete_all_response *rsp) +{ + struct pe_session *session_entry; + tSirResultCodes status_code = eSIR_SME_SUCCESS; + struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE); + struct wlan_objmgr_vdev *vdev; + uint8_t vdev_id; + + vdev = vdev_mlme->vdev; + vdev_id = wlan_vdev_get_id(vdev); + + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); + + session_entry = pe_find_session_by_vdev_id(mac_ctx, + vdev_id); + if (!session_entry) { + pe_err("Session Doesn't exist: %d", vdev_id); + return QDF_STATUS_E_INVAL; + } + + lim_prepare_and_send_del_all_sta_cnf(mac_ctx, status_code, + session_entry); + return QDF_STATUS_SUCCESS; +} + /** * lim_process_mlm_del_sta_rsp() - Process DEL STA response * @mac_ctx: Pointer to Global MAC structure diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index e07e6d6e13d4..283942565db3 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -2896,6 +2896,7 @@ QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac_ctx) tLimMlmDeauthReq *deauth_req; tLimMlmDeauthCnf deauth_cnf; struct pe_session *session_entry; + QDF_STATUS qdf_status; deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; if (deauth_req) { @@ -2912,12 +2913,21 @@ QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac_ctx) eSIR_SME_INVALID_PARAMETERS; goto end; } + if (qdf_is_macaddr_broadcast(&deauth_req->peer_macaddr) && + mac_ctx->mlme_cfg->sap_cfg.is_sap_bcast_deauth_enabled) { + qdf_status = lim_del_sta_all(mac_ctx, session_entry); + qdf_mem_free(deauth_req); + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = + NULL; + return qdf_status; + } sta_ds = dph_lookup_hash_entry(mac_ctx, deauth_req->peer_macaddr.bytes, &aid, - &session_entry->dph.dphHashTable); + &session_entry-> + dph.dphHashTable); if (!sta_ds) { deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index 738bc0e7ab20..8f11393f5919 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -818,6 +818,9 @@ void lim_process_mlm_add_sta_rsp(struct mac_context *mac, void lim_process_mlm_del_sta_rsp(struct mac_context *mac, struct scheduler_msg *limMsgQ); +QDF_STATUS +lim_process_mlm_del_all_sta_rsp(struct vdev_mlme_obj *vdev_mlme, + struct peer_delete_all_response *rsp); /** * lim_process_mlm_del_bss_rsp () - API to process delete bss response * @mac: Pointer to Global MAC structure