From 796c684186813815b3fb3c8e3ad562c78908ab06 Mon Sep 17 00:00:00 2001 From: Liangwei Dong Date: Fri, 18 Dec 2020 19:15:25 +0800 Subject: [PATCH] qcacld-3.0: clear pmkid cache when ap off In AP side power off/on case, AP security has been cleanup. The STA side might still cache PMK ID in driver and it will always use PMK cache to connect to AP and get continuously connect failure in SAE security. This function is to detect AP off based on FW reported BMISS event. Meanwhile judge FW reported last RSSI > roaming Low rssi and not less than 20db of host cached RSSI to avoid some false alarm such as normal DUT roll in/out roaming. Change-Id: I5d8ec9e9d4f8a44178b113d370799fe2bc0373fb CRs-Fixed: 2841481 --- .../dispatcher/inc/wlan_mlme_public_struct.h | 7 +++ core/hdd/src/wlan_hdd_assoc.c | 57 ++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 513bf98e2f8e..8f5f5e58d3c9 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -86,6 +86,13 @@ #define CFG_VALID_CHANNEL_LIST_STRING_LEN (CFG_VALID_CHANNEL_LIST_LEN * 4) #define DEFAULT_ROAM_TRIGGER_BITMAP 0xFFFFFFFF + +/** + * detect AP off based FW reported last RSSI > roaming Low rssi + * and not less than 20db of host cached RSSI + */ +#define AP_OFF_RSSI_OFFSET 20 + /** * struct mlme_cfg_str - generic structure for all mlme CFG string items * diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index eed21dee3aaa..941f265e9dca 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1807,6 +1807,57 @@ static void hdd_print_bss_info(struct hdd_station_ctx *hdd_sta_ctx) conn_info->hs20vendor_ie.release_num : 0); } +/** + * hdd_pmkid_clear_on_ap_off() - clear pmkid cache when ap off + * @adapter: pointer to adapter + * + * In AP side power off/on case, AP security has been cleanup. + * The STA side might still cache PMK ID in driver and it will always use + * PMK cache to connect to AP and get continuously connect failure in SAE + * security. This function is to detect AP off based on FW reported BMISS + * event. Meanwhile judge FW reported last RSSI > roaming Low rssi + * and not less than 20db of host cached RSSI to avoid some false + * alarm such as normal DUT roll in/out roaming. + * + * Return: void + */ +static void hdd_pmkid_clear_on_ap_off(struct hdd_adapter *adapter) +{ + struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + int8_t cache_rssi = 0; + int32_t bmiss_rssi; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + uint8_t lookup_threshold = 0; + struct wlan_crypto_pmksa *pmksa; + + if (sta_ctx->conn_info.auth_type != eCSR_AUTH_TYPE_SAE) + return; + hdd_get_rssi_snr_by_bssid(adapter, sta_ctx->conn_info.bssid.bytes, + &cache_rssi, NULL); + sme_get_neighbor_lookup_rssi_threshold(hdd_ctx->mac_handle, + adapter->vdev_id, + &lookup_threshold); + bmiss_rssi = adapter->rssi_on_disconnect; + if (!bmiss_rssi || !lookup_threshold || !cache_rssi) + return; + hdd_nofl_debug("sta bmiss on rssi %d scan rssi %d th %d", bmiss_rssi, + cache_rssi, lookup_threshold); + if (bmiss_rssi > (lookup_threshold * (-1))) { + if (bmiss_rssi + AP_OFF_RSSI_OFFSET > cache_rssi) { + pmksa = qdf_mem_malloc(sizeof(*pmksa)); + if (!pmksa) + return; + qdf_mem_copy(pmksa->bssid.bytes, + sta_ctx->conn_info.bssid.bytes, + sizeof(tSirMacAddr)); + sme_roam_del_pmkid_from_cache(hdd_ctx->mac_handle, + adapter->vdev_id, + pmksa, false); + qdf_mem_free(pmksa); + } + } +} + /** * hdd_dis_connect_handler() - disconnect event handler * @adapter: pointer to adapter @@ -1893,7 +1944,6 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, eConnectionState_Disconnecting); } - hdd_clear_roam_profile_ie(adapter); hdd_wmm_dscp_initial_state(adapter); wlan_deregister_txrx_packetdump(OL_TXRX_PDEV_ID); @@ -1953,7 +2003,12 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, disconnect_ies.data, disconnect_ies.len); } + if (adapter->device_mode == QDF_STA_MODE && + roam_status == eCSR_ROAM_LOSTLINK && + reason_code == REASON_BEACON_MISSED) + hdd_pmkid_clear_on_ap_off(adapter); + hdd_clear_roam_profile_ie(adapter); /* update P2P connection status */ ucfg_p2p_status_disconnect(adapter->vdev);