qcacld-3.0: Add support for peer_delete_all in sap

Currently, only broadcast disassociation is supported
and deauth is sent in a unicast manner.
With peer delete all support, HDD sends a single call
to PE for broadcast deauth request. PE module sends a
single broadcast deauth frame and on TX completion,
calls vdev_mgr_peer_delete_all_send. This issues the
new WMI_VDEV_DELETE_ALL_PEER_CMDID to FW to cleanup
peers entries corresponding to VDEV ID and also flush
TIDS internally.
On receiving the peer delete all response, target_if
cleans object manager entries and datapath cleans up.
But PEER unmap is done iterating through all peer entries
individually. After this a single eSAP_STA_DISASSOC_EVENT
is received in HDD signalling the completion of broadcast
deauth procedure.

Change-Id: I928461606154380eef21a02cc7306921ceb9e16e
CRs-Fixed: 2585005
This commit is contained in:
Gururaj Pandurangi 2020-02-13 13:35:02 -08:00 • committed by nshrivas
commit 8ccb6a72e2
9 changed files with 302 additions and 41 deletions

View file

@ -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 = {

View file

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

View file

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

View file

@ -55,6 +55,10 @@
#include "wlan_utility.h"
#include "wlan_mlme_api.h"
#include "wma.h"
#include "../../core/src/vdev_mgr_ops.h"
#include <cdp_txrx_cfg.h>
#include <cdp_txrx_cmn.h>
#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
*

View file

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

View file

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

View file

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

View file

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

View file

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