diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index 8cc378a243..97fbe4b1fa 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -385,6 +385,9 @@ struct wait_for_key_timer { * @connect_info: mlme connect information * @wait_key_timer: wait key timer * @eht_config: Eht capability configuration + * @last_delba_sent_time: Last delba sent time to handle back to back delba + * requests from some IOT APs + * @ba_2k_jump_iot_ap: This is set to true if connected to the ba 2k jump IOT AP */ struct mlme_legacy_priv { bool chan_switch_in_progress; @@ -421,6 +424,8 @@ struct mlme_legacy_priv { #ifdef WLAN_FEATURE_11BE tDot11fIEeht_cap eht_config; #endif + qdf_time_t last_delba_sent_time; + bool ba_2k_jump_iot_ap; }; /** diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h index 41e5b03644..6b9c01437c 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -3240,4 +3240,43 @@ wlan_mlme_is_data_stall_recovery_fw_supported(struct wlan_objmgr_psoc *psoc); */ QDF_STATUS mlme_cfg_get_eht_caps(struct wlan_objmgr_psoc *psoc, tDot11fIEeht_cap *eht_cap); + +/** + * wlan_mlme_set_ba_2k_jump_iot_ap() - Set a flag if ba 2k jump IOT AP is found + * @vdev: vdev pointer + * @found: Carries the value true if ba 2k jump IOT AP is found + * + * Return: QDF Status + */ +QDF_STATUS +wlan_mlme_set_ba_2k_jump_iot_ap(struct wlan_objmgr_vdev *vdev, bool found); + +/** + * wlan_mlme_is_ba_2k_jump_iot_ap() - Check if ba 2k jump IOT AP is found + * @vdev: vdev pointer + * + * Return: true if ba 2k jump IOT AP is found + */ +bool +wlan_mlme_is_ba_2k_jump_iot_ap(struct wlan_objmgr_vdev *vdev); + +/** + * wlan_mlme_set_last_delba_sent_time() - Cache the last delba sent ts + * @vdev: vdev pointer + * @delba_sent_time: Last delba sent timestamp + * + * Return: QDF Status + */ +QDF_STATUS +wlan_mlme_set_last_delba_sent_time(struct wlan_objmgr_vdev *vdev, + qdf_time_t delba_sent_time); + +/** + * wlan_mlme_get_last_delba_sent_time() - Get the last delba sent ts + * @vdev: vdev pointer + * + * Return: Last delba timestamp if cached, 0 otherwise + */ +qdf_time_t +wlan_mlme_get_last_delba_sent_time(struct wlan_objmgr_vdev *vdev); #endif /* _WLAN_MLME_API_H_ */ diff --git a/components/mlme/dispatcher/src/wlan_mlme_api.c b/components/mlme/dispatcher/src/wlan_mlme_api.c index 33218530fb..74c5a99897 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -4985,3 +4985,63 @@ QDF_STATUS mlme_cfg_get_eht_caps(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } #endif + +QDF_STATUS +wlan_mlme_set_ba_2k_jump_iot_ap(struct wlan_objmgr_vdev *vdev, bool found) +{ + struct mlme_legacy_priv *mlme_priv; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + mlme_priv->ba_2k_jump_iot_ap = found; + + return QDF_STATUS_SUCCESS; +} + +bool wlan_mlme_is_ba_2k_jump_iot_ap(struct wlan_objmgr_vdev *vdev) +{ + struct mlme_legacy_priv *mlme_priv; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return false; + } + + return mlme_priv->ba_2k_jump_iot_ap; +} + +QDF_STATUS +wlan_mlme_set_last_delba_sent_time(struct wlan_objmgr_vdev *vdev, + qdf_time_t delba_sent_time) +{ + struct mlme_legacy_priv *mlme_priv; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + mlme_priv->last_delba_sent_time = delba_sent_time; + + return QDF_STATUS_SUCCESS; +} + +qdf_time_t +wlan_mlme_get_last_delba_sent_time(struct wlan_objmgr_vdev *vdev) +{ + struct mlme_legacy_priv *mlme_priv; + + mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); + if (!mlme_priv) { + mlme_legacy_err("vdev legacy private object is NULL"); + return 0; + } + + return mlme_priv->last_delba_sent_time; +} diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 8249a03c70..ca8a9dc6f1 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -339,6 +339,9 @@ #define SIR_MAC_VENDOR_AP_4_OUI "\x8C\xFD\xF0" #define SIR_MAC_VENDOR_AP_4_OUI_LEN 3 +#define SIR_MAC_BA_2K_JUMP_AP_VENDOR_OUI "\x00\x14\x6C" +#define SIR_MAC_BA_2K_JUMP_AP_VENDOR_OUI_LEN 3 + /* Maximum allowable size of a beacon and probe rsp frame */ #define SIR_MAX_BEACON_SIZE 512 #define SIR_MAX_PROBE_RESP_SIZE 512 diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index bcdbec6132..6df89be9b8 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1740,6 +1740,12 @@ static void lim_check_oui_and_update_session(struct mac_context *mac_ctx, lim_handle_iot_ap_no_common_he_rates(mac_ctx, session, ie_struct); lim_update_he_caps_mcs(mac_ctx, session); lim_update_eht_caps_mcs(mac_ctx, session); + + is_vendor_ap_present = wlan_get_vendor_ie_ptr_from_oui( + SIR_MAC_BA_2K_JUMP_AP_VENDOR_OUI, + SIR_MAC_BA_2K_JUMP_AP_VENDOR_OUI_LEN, + vendor_ap_search_attr.ie_data, ie_len); + wlan_mlme_set_ba_2k_jump_iot_ap(session->vdev, is_vendor_ap_present); } static enum mlme_dot11_mode diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index a38ff010b0..3865c68e81 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -3099,6 +3099,39 @@ uint8_t wma_rx_invalid_peer_ind(uint8_t vdev_id, void *wh) return 0; } +static bool +wma_drop_delba(tp_wma_handle wma, uint8_t vdev_id, + enum cdp_delba_rcode cdp_reason_code) +{ + struct wlan_objmgr_vdev *vdev; + qdf_time_t last_ts, ts = qdf_mc_timer_get_system_time(); + bool drop = false; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id, + WLAN_MLME_CM_ID); + if (!vdev) { + wma_err("vdev is NULL"); + return drop; + } + if (!wlan_mlme_is_ba_2k_jump_iot_ap(vdev)) + goto done; + + last_ts = wlan_mlme_get_last_delba_sent_time(vdev); + if ((last_ts && cdp_reason_code == CDP_DELBA_2K_JUMP) && + (ts - last_ts) < CDP_DELBA_INTERVAL_MS) { + wma_debug("Drop DELBA, last sent ts: %lu current ts: %lu", + last_ts, ts); + drop = true; + } + + wlan_mlme_set_last_delba_sent_time(vdev, ts); + +done: + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); + + return drop; +} + int wma_dp_send_delba_ind(uint8_t vdev_id, uint8_t *peer_macaddr, uint8_t tid, uint8_t reason_code, enum cdp_delba_rcode cdp_reason_code) @@ -3110,6 +3143,10 @@ int wma_dp_send_delba_ind(uint8_t vdev_id, uint8_t *peer_macaddr, wma_err("wma handle or mac addr is NULL"); return -EINVAL; } + + if (wma_drop_delba(wma, vdev_id, cdp_reason_code)) + return 0; + req = qdf_mem_malloc(sizeof(*req)); if (!req) return -ENOMEM;