Эх сурвалжийг харах

qcacmn: Add beacon ratelimiting

Rate-limiting will be based on number of beacons received.
When the beacon is not from connected AP, the beacons
are dropped on a percentage of received beacons and
rate limit, which is configured by the user.

CRs-Fixed: 3230508
Change-Id: Iac591c37129fda6923ef254c2950cb0bdbb44ce9
Kani M 3 жил өмнө
parent
commit
c9f08ae24b

+ 12 - 0
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

+ 52 - 0
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:

+ 163 - 0
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

+ 12 - 0
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

+ 1 - 0
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

+ 4 - 0
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);
 

+ 12 - 0
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)

+ 38 - 0
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