qcacld-3.0: Do not kickout sta if it is in band steering

When a sta is being steered, sending a deauth may interrupt the
association/EAPOL handshake on the new BSS.

Do not kickout sta if it is being steered.

Change-Id: I15dd26bca27699087cdb790de8cb95281dade385
CRs-Fixed: 3042990
This commit is contained in:
bings 2021-07-23 10:17:01 +08:00 committed by Madan Koyyalamudi
parent 9aad58a07d
commit b6c09cbaf4
8 changed files with 202 additions and 8 deletions

View File

@ -138,6 +138,8 @@ struct sae_auth_retry {
* @last_assoc_received_time: last assoc received time
* @last_disassoc_deauth_received_time: last disassoc/deauth received time
* @twt_ctx: TWT context
* @allow_kickout: True if the peer can be kicked out. Peer can't be kicked
* out if it is being steered
*/
struct peer_mlme_priv_obj {
uint8_t last_pn_valid;
@ -149,6 +151,9 @@ struct peer_mlme_priv_obj {
#ifdef WLAN_SUPPORT_TWT
struct twt_context twt_ctx;
#endif
#ifdef WLAN_FEATURE_SON
bool allow_kickout;
#endif
};
/**

View File

@ -21,6 +21,7 @@
#define _SON_API_H_
#include <qdf_types.h>
#include <wlan_objmgr_peer_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <reg_services_public_struct.h>
@ -38,4 +39,36 @@
uint32_t wlan_son_get_chan_flag(struct wlan_objmgr_pdev *pdev,
qdf_freq_t freq, bool flag_160,
struct ch_params *chan_params);
/**
* wlan_son_peer_set_kickout_allow() - set the peer is allowed to kickout
* @vdev: pointer to vdev
* @peer: pointer to peer
* @kickout_allow: kickout_allow to set
*
* Return: QDF_STATUS_SUCCESS on Success else failure.
*/
QDF_STATUS wlan_son_peer_set_kickout_allow(struct wlan_objmgr_vdev *vdev,
struct wlan_objmgr_peer *peer,
bool kickout_allow);
#ifdef WLAN_FEATURE_SON
/**
* wlan_son_peer_is_kickout_allow() - Is peer is allowed to kickout
* @vdev: pointer to vdev
* @macaddr: mac addr of the peer
*
* Return: True if it is allowed to kickout.
*/
bool wlan_son_peer_is_kickout_allow(struct wlan_objmgr_vdev *vdev,
uint8_t *macaddr);
#else
static inline bool wlan_son_peer_is_kickout_allow(struct wlan_objmgr_vdev *vdev,
uint8_t *macaddr)
{
return true;
}
#endif /*WLAN_FEATURE_SON*/
#endif

View File

@ -76,4 +76,34 @@ uint32_t ucfg_son_get_sta_count(struct wlan_objmgr_vdev *vdev);
uint32_t ucfg_son_get_chan_flag(struct wlan_objmgr_pdev *pdev,
qdf_freq_t freq, bool flag_160,
struct ch_params *chan_params);
/**
* ucfg_son_get_he_supported() - get he supported
* @psoc: pointer to psoc
* @he_supported: he supported or not
*
* Return: void
*/
#ifdef WLAN_FEATURE_11AX
void ucfg_son_get_he_supported(struct wlan_objmgr_psoc *psoc,
bool *he_supported);
#else
static inline void ucfg_son_get_he_supported(struct wlan_objmgr_psoc *psoc,
bool *he_supported)
{
*he_supported = false;
}
#endif /*WLAN_FEATURE_11AX*/
/**
* ucfg_son_set_peer_kickout_allow() - set the peer is allowed to kickout
* @vdev: pointer to vdev
* @peer: pointer to peer
* @kickout_allow: kickout_allow to set
*
* Return: QDF_STATUS_SUCCESS on Success else failure.
*/
QDF_STATUS ucfg_son_set_peer_kickout_allow(struct wlan_objmgr_vdev *vdev,
struct wlan_objmgr_peer *peer,
bool kickout_allow);
#endif

View File

@ -203,3 +203,68 @@ uint32_t wlan_son_get_chan_flag(struct wlan_objmgr_pdev *pdev,
return flags;
}
QDF_STATUS wlan_son_peer_set_kickout_allow(struct wlan_objmgr_vdev *vdev,
struct wlan_objmgr_peer *peer,
bool kickout_allow)
{
struct peer_mlme_priv_obj *peer_priv;
if (!peer) {
qdf_err("invalid peer");
return QDF_STATUS_E_INVAL;
}
if (!vdev) {
qdf_err("invalid vdev");
return QDF_STATUS_E_INVAL;
}
peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
WLAN_UMAC_COMP_MLME);
if (!peer_priv) {
qdf_err("invalid vdev");
return QDF_STATUS_E_INVAL;
}
peer_priv->allow_kickout = kickout_allow;
return QDF_STATUS_SUCCESS;
}
bool wlan_son_peer_is_kickout_allow(struct wlan_objmgr_vdev *vdev,
uint8_t *macaddr)
{
bool kickout_allow = true;
struct wlan_objmgr_peer *peer;
struct wlan_objmgr_psoc *psoc;
struct peer_mlme_priv_obj *peer_priv;
if (!vdev) {
qdf_err("invalid vdev");
return kickout_allow;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
qdf_err("invalid psoc");
return kickout_allow;
}
peer = wlan_objmgr_get_peer_by_mac(psoc, macaddr,
WLAN_SON_ID);
if (!peer) {
qdf_err("peer is null");
return kickout_allow;
}
peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
WLAN_UMAC_COMP_MLME);
if (!peer_priv) {
qdf_err("invalid vdev");
wlan_objmgr_peer_release_ref(peer, WLAN_SON_ID);
return kickout_allow;
}
kickout_allow = peer_priv->allow_kickout;
wlan_objmgr_peer_release_ref(peer, WLAN_SON_ID);
return kickout_allow;
}

View File

@ -70,3 +70,10 @@ uint32_t ucfg_son_get_chan_flag(struct wlan_objmgr_pdev *pdev,
return wlan_son_get_chan_flag(pdev, freq, flag_160,
chan_params);
}
QDF_STATUS ucfg_son_set_peer_kickout_allow(struct wlan_objmgr_vdev *vdev,
struct wlan_objmgr_peer *peer,
bool kickout_allow)
{
return wlan_son_peer_set_kickout_allow(vdev, peer, kickout_allow);
}

View File

@ -46,6 +46,7 @@
#include <wlan_cm_api.h>
#include <lim_mlo.h>
#include "wlan_mlo_mgr_peer.h"
#include <son_api.h>
static void lim_process_mlm_auth_req(struct mac_context *, uint32_t *);
static void lim_process_mlm_assoc_req(struct mac_context *, uint32_t *);
@ -1522,9 +1523,18 @@ lim_process_mlm_deauth_req_ntf(struct mac_context *mac_ctx,
mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = mlm_deauth_req;
/* Send Deauthentication frame to peer entity */
lim_send_deauth_mgmt_frame(mac_ctx, mlm_deauth_req->reasonCode,
mlm_deauth_req->peer_macaddr.bytes,
session, true);
if (mlm_deauth_req->reasonCode != REASON_DISASSOC_DUE_TO_INACTIVITY ||
wlan_son_peer_is_kickout_allow(session->vdev, sta_ds->staAddr)) {
lim_send_deauth_mgmt_frame(mac_ctx, mlm_deauth_req->reasonCode,
mlm_deauth_req->peer_macaddr.bytes,
session, true);
} else {
pe_err("peer " QDF_MAC_ADDR_FMT " is in band steering, do not send deauth frame",
QDF_MAC_ADDR_REF(mlm_deauth_req->peer_macaddr.bytes));
mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
goto end;
}
return;
end:
qdf_copy_macaddr(&mlm_deauth_cnf.peer_macaddr,

View File

@ -328,14 +328,15 @@ QDF_STATUS os_if_son_vdev_ops(struct wlan_objmgr_vdev *pdev,
* os_if_son_peer_ops() - Handles PEER specific SON commands
* @peer: peer
* @type: SON command to handle
* @data: Input Data
* @ret: Output Data
* @data: Input Data. Pointer to wlan_mlme_peer_data
* @ret: Output Data. Pointer to wlan_mlme_peer_data
*
* Return: QDF_SUCCCESS_SUCCESS in case of success
*/
QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer,
enum wlan_mlme_peer_param type,
void *data, void *ret);
union wlan_mlme_peer_data *data,
union wlan_mlme_peer_data *ret);
/**
* os_if_son_scan_db_iterate() - get country code

View File

@ -763,9 +763,52 @@ qdf_export_symbol(os_if_son_vdev_ops);
QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer,
enum wlan_mlme_peer_param type,
void *data, void *ret)
union wlan_mlme_peer_data *in,
union wlan_mlme_peer_data *out)
{
return QDF_STATUS_SUCCESS;
struct wlan_objmgr_vdev *vdev;
struct wlan_objmgr_pdev *pdev;
struct wlan_objmgr_psoc *psoc;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!peer) {
osif_err("null peer");
return QDF_STATUS_E_INVAL;
}
vdev = wlan_peer_get_vdev(peer);
if (!vdev) {
osif_err("null vdev");
return QDF_STATUS_E_INVAL;
}
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
osif_err("null pdev");
return QDF_STATUS_E_INVAL;
}
psoc = wlan_pdev_get_psoc(pdev);
if (!psoc) {
osif_err("null psoc");
return QDF_STATUS_E_INVAL;
}
osif_debug("type %d", type);
/* All PEER MLME operations exported to SON component */
switch (type) {
case PEER_SET_KICKOUT_ALLOW:
if (!in) {
osif_err("invalid input parameter");
return QDF_STATUS_E_INVAL;
}
status = ucfg_son_set_peer_kickout_allow(vdev, peer,
in->enable);
break;
default:
osif_err("invalid type: %d", type);
status = QDF_STATUS_E_INVAL;
}
return status;
}
qdf_export_symbol(os_if_son_peer_ops);