diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h index 9ace901887..782af230c3 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h +++ b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h @@ -803,6 +803,16 @@ struct frame_pn_params { uint8_t prev_pn[WLAN_MGMT_TXRX_HOST_MAX_PN_LEN]; }; +/** + * struct frm_conn_ap - connected ap + * @mgmt_frm_sub_type: type of frame + * @is_conn_ap_frm: set if frm is from connected ap + */ +struct frm_conn_ap { + uint8_t mgmt_frm_sub_type; + uint8_t is_conn_ap_frm; +}; + /** * struct mgmt_rx_event_ext_params - Host mgmt extended params * @ba_win_size: Block-Ack window size @@ -838,6 +848,7 @@ struct mgmt_rx_event_ext_params { * @reo_params: Pointer to MGMT Rx REO params * @pn_params: Frame PN params * @ext_params: Extended params + * @frm_con_ap: Frame is from connected ap */ struct mgmt_rx_event_params { uint32_t chan_freq; @@ -859,6 +870,7 @@ struct mgmt_rx_event_params { #endif struct frame_pn_params pn_params; struct mgmt_rx_event_ext_params *ext_params; + struct frm_conn_ap is_conn_ap; }; #ifdef WLAN_MGMT_RX_REO_SUPPORT diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c index c7a1e90fef..b4b8c0ad73 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c @@ -1052,6 +1052,49 @@ static QDF_STATUS simulation_frame_update(struct wlan_objmgr_psoc *psoc, } #endif +/** + * wlan_mgmt_rx_beacon_rate_limit() - rate limiting mgmt beacons + * @psoc - pointer to psoc struct + * @mgmt_rx_params - rx params + * + * This function will drop the beacons if the number of beacons + * received is greater than the percentage of limit of beacons to max + * count of beacons, when beacon rate limiting is enabled + * + * Return : QDF_STATUS if success, else QDF_STATUS_E_RESOURCES + */ +static QDF_STATUS wlan_mgmt_rx_beacon_rate_limit(struct wlan_objmgr_psoc *psoc, + struct mgmt_rx_event_params + *mgmt_rx_params) +{ + struct wlan_objmgr_pdev *pdev = NULL; + + pdev = wlan_objmgr_get_pdev_by_id(psoc, mgmt_rx_params->pdev_id, + WLAN_MGMT_SB_ID); + + if (pdev && pdev->pdev_objmgr.bcn.bcn_rate_limit) { + uint64_t b_limit = qdf_do_div( + (wlan_pdev_get_max_beacon_count(pdev) * + wlan_pdev_get_max_beacon_limit(pdev)), 100); + wlan_pdev_incr_wlan_beacon_count(pdev); + + if (wlan_pdev_get_wlan_beacon_count(pdev) >= + wlan_pdev_get_max_beacon_count(pdev)) + wlan_pdev_set_wlan_beacon_count(pdev, 0); + + if (wlan_pdev_get_wlan_beacon_count(pdev) >= b_limit) { + wlan_pdev_incr_dropped_beacon_count(pdev); + wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID); + return QDF_STATUS_E_RESOURCES; + } + } + + if (pdev) + wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID); + + return QDF_STATUS_SUCCESS; +} + /** * wlan_mgmt_txrx_rx_handler_list_copy() - copies rx handler list * @rx_handler: pointer to rx handler list @@ -1317,6 +1360,15 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( } qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); + if (mgmt_subtype == MGMT_SUBTYPE_BEACON && + mgmt_rx_params->is_conn_ap.is_conn_ap_frm == 0) { + status = wlan_mgmt_rx_beacon_rate_limit(psoc, mgmt_rx_params); + if (QDF_IS_STATUS_ERROR(status)) { + qdf_nbuf_free(buf); + goto rx_handler_mem_free; + } + } + mac_addr = (uint8_t *)wh->i_addr2; /* * peer can be NULL in following 2 scenarios: diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h index 0c0ede1eed..ad149249e4 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h @@ -181,6 +181,22 @@ struct wlan_objmgr_pdev_mlme { uint32_t pdev_op_flags; }; +/** + * struct wlan_beacon_process - wlan beacon structure + * @bcn_rate_limit: To indicate if beacon ratelimiting is enabled or not + * @wlan_beacon_count: Per pdev beacon count received + * @max_beacon_count: Per vdev max beacon count, defaults to 100 + * @max_beacon_limit: Limit of beacons to be processed + * @dropped_beacon: Dropped beacons + */ +struct wlan_beacon_process { + bool bcn_rate_limit; + uint64_t wlan_beacon_count; + uint64_t max_beacon_count; + uint8_t max_beacon_limit; + uint64_t dropped_beacon; +}; + /** * struct wlan_objmgr_pdev_objmgr - pdev object object manager structure * @wlan_pdev_id: PDEV id @@ -196,6 +212,7 @@ struct wlan_objmgr_pdev_mlme { * @ref_cnt: Ref count * @ref_id_dbg: Array to track Ref count * @wlan_mlo_vdev_count: MLO VDEVs count + * @bcn: Struct to keep track of beacon count */ struct wlan_objmgr_pdev_objmgr { uint8_t wlan_pdev_id; @@ -213,6 +230,7 @@ struct wlan_objmgr_pdev_objmgr { #ifdef WLAN_FEATURE_11BE_MLO qdf_atomic_t wlan_mlo_vdev_count; #endif + struct wlan_beacon_process bcn; }; /** @@ -1039,6 +1057,151 @@ static inline uint16_t wlan_pdev_get_max_peer_count( return pdev->pdev_objmgr.max_peer_count; } +/** + * wlan_pdev_set_max_beacon_count() - set max beacon count + * @pdev: pdev object + * @count: Max beacon count + * + * API to set max beacon count of pdev + * + * Return: void + */ +static inline void wlan_pdev_set_max_beacon_count( + struct wlan_objmgr_pdev *pdev, + uint64_t count) +{ + pdev->pdev_objmgr.bcn.max_beacon_count = count; +} + +/** + * wlan_pdev_get_max_beacon_count() - get max beacon count + * @pdev: pdev object + * + * API to get max beacon count of pdev + * + * Return: max beacon count + */ +static inline uint64_t wlan_pdev_get_max_beacon_count( + struct wlan_objmgr_pdev *pdev) +{ + return pdev->pdev_objmgr.bcn.max_beacon_count; +} + +/** + * wlan_pdev_incr_beacon_count() - incr beacon count for rx beacon frames + * @pdev: pdev object + * + * API to incr beacon count of pdev + * + * Return: void + */ +static inline void wlan_pdev_incr_wlan_beacon_count( + struct wlan_objmgr_pdev *pdev) +{ + pdev->pdev_objmgr.bcn.wlan_beacon_count++; +} + +/** + * wlan_pdev_get_wlan_beacon_count() - set wlan beacon count + * @pdev: pdev object + * @count: count to reset beacon count + * + * API to get wlan beacon count of pdev + * + */ +static inline void wlan_pdev_set_wlan_beacon_count( + struct wlan_objmgr_pdev *pdev, + uint64_t count) +{ + pdev->pdev_objmgr.bcn.wlan_beacon_count = count; +} + +/** + * wlan_pdev_get_wlan_beacon_limit() - get wlan beacon limit + * @pdev: pdev object + * + * API to get wlan beacon limit of pdev + * + * Return: beacon limit + */ +static inline uint64_t wlan_pdev_get_wlan_beacon_count( + struct wlan_objmgr_pdev *pdev) +{ + return pdev->pdev_objmgr.bcn.wlan_beacon_count; +} + +/** + * wlan_pdev_set_wlan_beacon_count() - set wlan beacon limit + * @pdev: pdev object + * @limit: limit for thresholding + * + * API to set wlan beacon limit of pdev + * + */ +static inline void wlan_pdev_set_max_beacon_limit( + struct wlan_objmgr_pdev *pdev, + uint64_t limit) +{ + pdev->pdev_objmgr.bcn.max_beacon_limit = limit; +} + +/** + * wlan_pdev_get_wlan_beacon_limit() - get wlan beacon limit + * @pdev: pdev object + * + * API to get wlan beacon limit of pdev + * + * Return: beacon limit + */ +static inline uint64_t wlan_pdev_get_max_beacon_limit( + struct wlan_objmgr_pdev *pdev) +{ + return pdev->pdev_objmgr.bcn.max_beacon_limit; +} + +/** + * wlan_pdev_incr_dropped_beacon_count() - increment dropped bcn cnt + * @pdev: pdev object + * + * API to increment dropped beacon count + * + * Return: beacon limit + */ +static inline void wlan_pdev_incr_dropped_beacon_count( + struct wlan_objmgr_pdev *pdev) +{ + pdev->pdev_objmgr.bcn.dropped_beacon++; +} + +/** + * wlan_pdev_set_dropped_beacon_count() - reset dropped beacon count + * @pdev: pdev object + * @count: count value + * + * API to set beacon drop count + * + */ +static inline void wlan_pdev_set_dropped_beacon_count( + struct wlan_objmgr_pdev *pdev, + uint64_t count) +{ + pdev->pdev_objmgr.bcn.dropped_beacon = count; +} + +/** + * wlan_pdev_get_dropped_beacon_count() - get drop beacon count + * @pdev: pdev object + * + * API to get dropped beacon count + * + * Return: beacon limit + */ +static inline uint64_t wlan_pdev_get_dropped_beacon_count( + struct wlan_objmgr_pdev *pdev) +{ + return pdev->pdev_objmgr.bcn.dropped_beacon; +} + /** * wlan_pdev_set_max_monitor_vdev_count() - set max monitor vdev count * @pdev: PDEV object diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 8308b0cb4b..f868e8a1dc 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -2993,6 +2993,18 @@ QDF_STATUS wmi_extract_frame_pn_params(wmi_unified_t wmi_handle, void *evt_buf, struct frame_pn_params *pn_params); +/** + * wmi_extract_is_conn_ap_frame() - extract is_conn_ap_frame param from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @is_conn_ap: is_conn_ap param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_is_conn_ap_frame(wmi_unified_t wmi_handle, void *evt_buf, + struct frm_conn_ap *is_conn_ap); + /** * wmi_extract_vdev_roam_param() - extract vdev roam param from event * @wmi_handle: wmi handle diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 6dcd476732..2e74931bdd 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -5749,6 +5749,7 @@ typedef enum { #endif wmi_service_tdls_wideband_support, #endif + wmi_service_is_my_mgmt_frame, wmi_services_max, } wmi_conv_service_ids; #define WMI_SERVICE_UNAVAILABLE 0xFFFF diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index c1c6c2e2e1..1f65d3d5bb 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1885,6 +1885,10 @@ QDF_STATUS (*extract_mgmt_rx_params)(wmi_unified_t wmi_handle, void *evt_buf, QDF_STATUS (*extract_frame_pn_params)(wmi_unified_t wmi_handle, void *evt_buf, struct frame_pn_params *pn_params); +QDF_STATUS (*extract_is_conn_ap_frame)(wmi_unified_t wmi_handle, + void *evt_buf, + struct frm_conn_ap *is_conn_ap); + QDF_STATUS (*extract_vdev_stopped_param)(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *vdev_id); diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 2f393ffe84..1be14961ec 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -2118,6 +2118,18 @@ wmi_extract_frame_pn_params(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_E_FAILURE; } +QDF_STATUS +wmi_extract_is_conn_ap_frame(wmi_unified_t wmi_handle, void *evt_buf, + struct frm_conn_ap *is_conn_ap_frm) +{ + if (wmi_handle->ops->extract_is_conn_ap_frame) + return wmi_handle->ops->extract_is_conn_ap_frame(wmi_handle, + evt_buf, + is_conn_ap_frm); + + return QDF_STATUS_E_FAILURE; +} + QDF_STATUS wmi_extract_vdev_roam_param(wmi_unified_t wmi_handle, void *evt_buf, wmi_host_roam_event *param) diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 19cedfde02..3cee72d2e3 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -11943,6 +11943,43 @@ static QDF_STATUS extract_frame_pn_params_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } +/** + * extract_is_conn_ap_param_tlv() - extract is_conn_ap_frame param from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @is_conn_ap: Pointer for is_conn_ap frame + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +static QDF_STATUS extract_is_conn_ap_frm_param_tlv( + wmi_unified_t wmi_handle, + void *evt_buf, + struct frm_conn_ap *is_conn_ap) +{ + WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs; + wmi_is_my_mgmt_frame *my_frame_tlv; + + param_tlvs = evt_buf; + if (!param_tlvs) { + wmi_err("Got NULL point message from FW"); + return QDF_STATUS_E_INVAL; + } + + if (!is_conn_ap) { + wmi_err(" is connected ap param is NULL"); + return QDF_STATUS_E_INVAL; + } + + my_frame_tlv = param_tlvs->my_frame; + if (!my_frame_tlv) + return QDF_STATUS_SUCCESS; + + is_conn_ap->mgmt_frm_sub_type = my_frame_tlv->mgmt_frm_sub_type; + is_conn_ap->is_conn_ap_frm = my_frame_tlv->is_my_frame; + + return QDF_STATUS_SUCCESS; +} + /** * extract_vdev_roam_param_tlv() - extract vdev roam param from event * @wmi_handle: wmi handle @@ -18375,6 +18412,7 @@ struct wmi_ops tlv_ops = { .extract_dbglog_data_len = extract_dbglog_data_len_tlv, .extract_mgmt_rx_params = extract_mgmt_rx_params_tlv, .extract_frame_pn_params = extract_frame_pn_params_tlv, + .extract_is_conn_ap_frame = extract_is_conn_ap_frm_param_tlv, .extract_vdev_roam_param = extract_vdev_roam_param_tlv, .extract_vdev_scan_ev_param = extract_vdev_scan_ev_param_tlv, #ifdef FEATURE_WLAN_SCAN_PNO