diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index 90ee0c9b99..2ffeb2f436 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -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 }; /** diff --git a/components/son/dispatcher/inc/son_api.h b/components/son/dispatcher/inc/son_api.h index e44a76a286..ce2b973580 100644 --- a/components/son/dispatcher/inc/son_api.h +++ b/components/son/dispatcher/inc/son_api.h @@ -21,6 +21,7 @@ #define _SON_API_H_ #include +#include #include #include @@ -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 diff --git a/components/son/dispatcher/inc/son_ucfg_api.h b/components/son/dispatcher/inc/son_ucfg_api.h index f164995e7e..0dbfb2d027 100644 --- a/components/son/dispatcher/inc/son_ucfg_api.h +++ b/components/son/dispatcher/inc/son_ucfg_api.h @@ -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 diff --git a/components/son/dispatcher/src/son_api.c b/components/son/dispatcher/src/son_api.c index 1e404142db..b82b365fd4 100644 --- a/components/son/dispatcher/src/son_api.c +++ b/components/son/dispatcher/src/son_api.c @@ -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; +} diff --git a/components/son/dispatcher/src/son_ucfg_api.c b/components/son/dispatcher/src/son_ucfg_api.c index 7914044c07..e0aa79ea3c 100644 --- a/components/son/dispatcher/src/son_ucfg_api.c +++ b/components/son/dispatcher/src/son_ucfg_api.c @@ -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); +} 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 5e290ee161..7aa4deeb90 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 @@ -46,6 +46,7 @@ #include #include #include "wlan_mlo_mgr_peer.h" +#include 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, diff --git a/os_if/son/inc/os_if_son.h b/os_if/son/inc/os_if_son.h index f3a7725cf5..4cbde763c8 100644 --- a/os_if/son/inc/os_if_son.h +++ b/os_if/son/inc/os_if_son.h @@ -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 diff --git a/os_if/son/src/os_if_son.c b/os_if/son/src/os_if_son.c index 00808ab824..ec50610902 100644 --- a/os_if/son/src/os_if_son.c +++ b/os_if/son/src/os_if_son.c @@ -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);