Răsfoiți Sursa

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
Liangwei Dong 4 ani în urmă
părinte
comite
74222be804

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

+ 55 - 0
core/hdd/src/wlan_hdd_assoc.c

@@ -1751,6 +1751,57 @@ void hdd_clear_roam_profile_ie(struct hdd_adapter *adapter)
 }
 
 #ifndef FEATURE_CM_ENABLE
+/**
+ * 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
@@ -1856,6 +1907,10 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
 						disconnect_ies.ptr,
 						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);
 
 	if (adapter->device_mode == QDF_STA_MODE) {
 		/* Inform BLM about the disconnection with the AP */

+ 1 - 1
core/hdd/src/wlan_hdd_cm_disconnect.c

@@ -129,7 +129,6 @@ void __hdd_cm_disconnect_handler_pre_user_update(struct hdd_adapter *adapter)
 		QDF_TRACE_DEFAULT_PDEV_ID,
 		QDF_PROTO_TYPE_MGMT, QDF_PROTO_MGMT_DISASSOC));
 
-	hdd_clear_roam_profile_ie(adapter);
 	hdd_wmm_dscp_initial_state(adapter);
 	wlan_deregister_txrx_packetdump(OL_TXRX_PDEV_ID);
 
@@ -150,6 +149,7 @@ void __hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter)
 	mac_handle = hdd_ctx->mac_handle;
 	sme_ft_reset(mac_handle, adapter->vdev_id);
 	sme_reset_key(mac_handle, adapter->vdev_id);
+	hdd_clear_roam_profile_ie(adapter);
 
 	if (adapter->device_mode == QDF_STA_MODE) {
 		vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_ID);