Browse Source

qcacld-3.0: Trigger STA deletion after deauth is transmitted

In case of STA kickout on SAP interface, host driver sends
deauth frame and initiates peer delete without waiting for
ACK or tx completion status of the deauth frame. In the
firmware, the deauth frame seems to get flushed, if peer
delete is being queued. To fix this, send peer delete only
if the deauth tx completion status is received.

Changes involved are:
1. To handle the sta deletion from the deauth tx complete path:
	- Get the vdev id and peer address from the mgmt desc params
	  to initiate the deletion.
2. To handle the sta deletion from deauth tx completion timeout:
	- Mark a flag in sta entry if STA kickout deauth is in progress.
	- Add changes to get vdev id upon deauth ack timer expiry.
	- Trigger deletion for all the STAs for which has STA kickout
          is in progress, since the timer is not started per peer.
          Therefore, upon the expiry of the deauth ack timer, initiate
          all the STA deletion.
Change-Id: I44a802237723866b05a986ed760a065ac4697044
CRs-Fixed: 3556353
Surya Prakash Sivaraj 1 year ago
parent
commit
496290a384

+ 1 - 1
core/mac/src/include/sir_params.h

@@ -713,7 +713,7 @@ enum halmsgtype {
 /* currently unused                     (SIR_LIM_TIMEOUT_MSG_START + 0x25) */
 
 #define SIR_LIM_DISASSOC_ACK_TIMEOUT       (SIR_LIM_TIMEOUT_MSG_START + 0x26)
-#define SIR_LIM_DEAUTH_ACK_TIMEOUT       (SIR_LIM_TIMEOUT_MSG_START + 0x27)
+/*#define SIR_LIM_DEAUTH_ACK_TIMEOUT       (SIR_LIM_TIMEOUT_MSG_START + 0x27) */
 #define SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT \
 					 (SIR_LIM_TIMEOUT_MSG_START + 0x28)
 

+ 4 - 2
core/mac/src/pe/lim/lim_link_monitoring_algo.c

@@ -99,14 +99,16 @@ static void lim_delete_sta_util(struct mac_context *mac_ctx, tpDeleteStaContext
 						mac_ctx,
 						REASON_PREV_AUTH_NOT_VALID,
 						stads->staAddr,
-						session_entry, false);
+						session_entry, true);
+				stads->is_disassoc_deauth_in_progress = 1;
 			} else {
 				lim_send_disassoc_mgmt_frame(
 					mac_ctx,
 					REASON_DISASSOC_DUE_TO_INACTIVITY,
 					stads->staAddr, session_entry, false);
+				lim_trigger_sta_deletion(mac_ctx, stads,
+							 session_entry);
 			}
-			lim_trigger_sta_deletion(mac_ctx, stads, session_entry);
 		}
 	} else {
 #ifdef FEATURE_WLAN_TDLS

+ 2 - 1
core/mac/src/pe/lim/lim_process_auth_frame.c

@@ -968,7 +968,8 @@ static void lim_process_auth_frame_type1(struct mac_context *mac_ctx,
 				QDF_MAC_ADDR_FMT,
 				QDF_MAC_ADDR_REF(
 					pMlmDeauthReq->peer_macaddr.bytes));
-			lim_process_deauth_ack_timeout(mac_ctx);
+			lim_process_deauth_ack_timeout(mac_ctx,
+						       pe_session->vdev_id);
 			is_connected = false;
 		}
 

+ 0 - 1
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -1852,7 +1852,6 @@ static void lim_process_messages(struct mac_context *mac_ctx,
 	case SIR_LIM_REASSOC_FAIL_TIMEOUT:
 	case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:
 	case SIR_LIM_DISASSOC_ACK_TIMEOUT:
-	case SIR_LIM_DEAUTH_ACK_TIMEOUT:
 	case SIR_LIM_AUTH_RETRY_TIMEOUT:
 	case SIR_LIM_AUTH_SAE_TIMEOUT:
 		/* These timeout messages are handled by MLM sub module */

+ 9 - 8
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -188,9 +188,6 @@ void lim_process_mlm_req_messages(struct mac_context *mac_ctx,
 	case SIR_LIM_DISASSOC_ACK_TIMEOUT:
 		lim_process_disassoc_ack_timeout(mac_ctx);
 		break;
-	case SIR_LIM_DEAUTH_ACK_TIMEOUT:
-		lim_process_deauth_ack_timeout(mac_ctx);
-		break;
 	case SIR_LIM_AUTH_RETRY_TIMEOUT:
 		lim_process_auth_retry_timer(mac_ctx);
 		break;
@@ -1257,7 +1254,8 @@ void lim_clean_up_disassoc_deauth_req(struct mac_context *mac_ctx,
 			     (uint8_t *) &mlm_deauth_req->peer_macaddr.bytes,
 			     QDF_MAC_ADDR_SIZE))) {
 		if (clean_rx_path) {
-			lim_process_deauth_ack_timeout(mac_ctx);
+			lim_process_deauth_ack_timeout(mac_ctx,
+						       mlm_deauth_req->sessionId);
 		} else {
 			if (tx_timer_running(
 				&mac_ctx->lim.lim_timers.gLimDeauthAckTimer)) {
@@ -1569,16 +1567,19 @@ end:
  * lim_process_deauth_ack_timeout() - wrapper function around
  * lim_send_deauth_cnf
  *
- * @mac_ctx:        mac_ctx
+ * @pMacGlobal:     mac_ctx
+ * @vdev_id:        vdev id
  *
  * wrapper function around lim_send_deauth_cnf
  *
  * Return: void
  */
-void lim_process_deauth_ack_timeout(struct mac_context *mac_ctx)
+void lim_process_deauth_ack_timeout(void *pMacGlobal, uint32_t vdev_id)
 {
-	pe_debug("Deauth Ack timeout");
-	lim_send_deauth_cnf(mac_ctx);
+	struct mac_context *mac_ctx = (struct mac_context *)pMacGlobal;
+
+	pe_debug("Deauth Ack timeout for vdev id %d", vdev_id);
+	lim_send_deauth_cnf(mac_ctx, vdev_id);
 }
 
 /*

+ 118 - 10
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -3729,7 +3729,42 @@ alloc_packet:
 	return;
 }
 
-QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac_ctx)
+static
+void lim_delete_deauth_all_pending_sta(struct mac_context *mac_ctx,
+				       struct pe_session *session)
+{
+	int i = 0;
+	tpDphHashNode sta_ds = NULL;
+
+	if (!session)
+		return;
+
+	for (i = 0; i < session->dph.dphHashTable.size; i++) {
+		sta_ds = dph_get_hash_entry(mac_ctx, i,
+					    &session->dph.dphHashTable);
+		/*
+		 * In case of multiple STA kickout on SAP interface,
+		 * DeauthAckTimer would be started only for the first
+		 * deauth queued. So, the ack timeout would not be
+		 * fired for other deauth frames. Therefore as part of
+		 * of this timer expiry(of first queued deauth), trigger
+		 * sta deletion for all the peers with deauth in progress.
+		 *
+		 * Do not trigger deletion if sta_deletion is already in
+		 * progress.
+		 */
+
+		if (!sta_ds || !sta_ds->valid ||
+		    sta_ds->sta_deletion_in_progress ||
+		    !sta_ds->is_disassoc_deauth_in_progress)
+			continue;
+
+		sta_ds->is_disassoc_deauth_in_progress = 0;
+		lim_trigger_sta_deletion(mac_ctx, sta_ds, session);
+	}
+}
+
+QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac_ctx, uint8_t vdev_id)
 {
 	uint16_t aid;
 	tpDphHashNode sta_ds;
@@ -3835,6 +3870,17 @@ QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac_ctx)
 		/* Free up buffer allocated for mlmDeauthReq */
 		qdf_mem_free(deauth_req);
 		mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL;
+	} else  {
+		session_entry =  pe_find_session_by_vdev_id(mac_ctx, vdev_id);
+		if (!session_entry || (session_entry->opmode != QDF_SAP_MODE &&
+				       session_entry->opmode !=QDF_P2P_GO_MODE))
+			return QDF_STATUS_SUCCESS;
+		/*
+		 * If deauth request is not present, then the deauth could
+		 * be from the SB STA kickout queued in SAP context.
+		 * Cleanup all the STA which has is_disassoc_deauth_in_progress
+		 */
+		lim_delete_deauth_all_pending_sta(mac_ctx, session_entry);
 	}
 	return QDF_STATUS_SUCCESS;
 end:
@@ -3989,10 +4035,47 @@ QDF_STATUS lim_deauth_tx_complete_cnf(void *context,
 				      void *params)
 {
 	struct mac_context *mac_ctx = (struct mac_context *)context;
+	struct wmi_mgmt_params *mgmt_params =
+				(struct wmi_mgmt_params *)params;
+	uint8_t vdev_id = WLAN_INVALID_VDEV_ID;
 
 	pe_debug("tx_success: %d", tx_success);
+	if (mgmt_params)
+		vdev_id = mgmt_params->vdev_id;
+
+	return lim_send_deauth_cnf(mac_ctx, vdev_id);
+}
+
+static QDF_STATUS lim_ap_delete_sta_upon_deauth_tx(struct mac_context *mac_ctx,
+						   struct pe_session *session,
+						   tSirMacAddr peer)
+{
+	tpDphHashNode stads;
+	uint16_t aid;
 
-	return lim_send_deauth_cnf(mac_ctx);
+	if (!session || (session->opmode != QDF_SAP_MODE &&
+			 session->opmode != QDF_P2P_GO_MODE))
+		return QDF_STATUS_E_FAILURE;
+
+	stads = dph_lookup_hash_entry(mac_ctx, peer, &aid,
+				      &session->dph.dphHashTable);
+
+	if (!stads || !stads->ocv_enabled ||
+	    stads->last_ocv_done_freq == session->curr_op_freq)
+		return QDF_STATUS_E_FAILURE;
+
+	/*
+	 * Proceed with sta deletion only if
+	 * is_disassoc_deauth_in_progress is set. If unset,
+	 * sta deletion will be handled by the deauth ack
+	 * timeout handler.
+	 */
+	if (!stads->is_disassoc_deauth_in_progress ||
+	    stads->sta_deletion_in_progress)
+		return QDF_STATUS_SUCCESS;
+
+	lim_trigger_sta_deletion(mac_ctx, stads, session);
+	return QDF_STATUS_SUCCESS;
 }
 
 static QDF_STATUS lim_deauth_tx_complete_cnf_handler(void *context,
@@ -4001,10 +4084,14 @@ static QDF_STATUS lim_deauth_tx_complete_cnf_handler(void *context,
 						     void *params)
 {
 	struct mac_context *mac_ctx = (struct mac_context *)context;
-	QDF_STATUS status_code;
+	QDF_STATUS status_code = QDF_STATUS_E_FAILURE;
 	struct scheduler_msg msg = {0};
 	tLimMlmDeauthReq *deauth_req;
 	struct pe_session *session = NULL;
+	tSirMacMgmtHdr *mac_hdr;
+	uint8_t vdev_id = WLAN_INVALID_VDEV_ID;
+	struct wmi_mgmt_params *mgmt_params =
+			(struct wmi_mgmt_params *)params;
 
 	if (params)
 		wlan_send_tx_complete_event(context, buf, params, tx_success,
@@ -4016,8 +4103,24 @@ static QDF_STATUS lim_deauth_tx_complete_cnf_handler(void *context,
 		(tx_success == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK) ?
 		 "success" : "fail", tx_success);
 
+	if (buf && (qdf_nbuf_len(buf) > sizeof(struct wlan_frame_hdr) + 2))
+		mac_hdr = (tSirMacMgmtHdr *)qdf_nbuf_data(buf);
+
+	if (!deauth_req && mac_hdr) {
+		if (mgmt_params)
+			vdev_id = mgmt_params->vdev_id;
+		session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
+		status_code = lim_ap_delete_sta_upon_deauth_tx(mac_ctx, session,
+							       (uint8_t *)mac_hdr->da);
+	}
+
 	if (buf)
 		qdf_nbuf_free(buf);
+
+	/* Cleanup has been handled for SAP/GO context, return */
+	if (QDF_IS_STATUS_SUCCESS(status_code))
+		return QDF_STATUS_SUCCESS;
+
 	if (deauth_req)
 		session = pe_find_session_by_session_id(mac_ctx,
 				deauth_req->sessionId);
@@ -4344,7 +4447,7 @@ lim_send_deauth_mgmt_frame(struct mac_context *mac,
 		}
 		if (drop_deauth) {
 			if (waitForAck)
-				lim_send_deauth_cnf(mac);
+				lim_send_deauth_cnf(mac, pe_session->vdev_id);
 			return;
 		}
 	} else if (lim_is_ml_peer_state_disconn(mac, pe_session, peer)) {
@@ -4356,7 +4459,7 @@ lim_send_deauth_mgmt_frame(struct mac_context *mac,
 		 */
 		pe_debug("Deauth tx not required for vdev id %d",
 			 pe_session->vdev_id);
-		lim_send_deauth_cnf(mac);
+		lim_send_deauth_cnf(mac, pe_session->vdev_id);
 		return;
 	}
 	smeSessionId = pe_session->smeSessionId;
@@ -4387,7 +4490,7 @@ lim_send_deauth_mgmt_frame(struct mac_context *mac,
 		pe_err("Failed to allocate %d bytes for a De-Authentication",
 			nBytes);
 		if (waitForAck)
-			lim_send_deauth_cnf(mac);
+			lim_send_deauth_cnf(mac, pe_session->vdev_id);
 		return;
 	}
 	/* Paranoia: */
@@ -4410,7 +4513,7 @@ lim_send_deauth_mgmt_frame(struct mac_context *mac,
 			nStatus);
 		cds_packet_free((void *)pPacket);
 		if (waitForAck)
-			lim_send_deauth_cnf(mac);
+			lim_send_deauth_cnf(mac, pe_session->vdev_id);
 		return;
 	} else if (DOT11F_WARNED(nStatus)) {
 		pe_warn("There were warnings while packing a De-Authentication (0x%08x)",
@@ -4476,13 +4579,18 @@ lim_send_deauth_mgmt_frame(struct mac_context *mac,
 			/* Call lim_process_deauth_ack_timeout which will send
 			 * DeauthCnf for this frame
 			 */
-			lim_process_deauth_ack_timeout(mac);
+			lim_process_deauth_ack_timeout(mac,
+						       pe_session->peSessionId);
 			return;
 		}
 
 		val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT);
-
-		if (tx_timer_change
+		if (tx_timer_change_context(
+				&mac->lim.lim_timers.gLimDeauthAckTimer,
+				pe_session->vdev_id) != TX_SUCCESS) {
+			pe_err("Unable to update the vdev id in the Deauth ack timer");
+			return;
+		} else if (tx_timer_change
 			    (&mac->lim.lim_timers.gLimDeauthAckTimer, val, 0)
 		    != TX_SUCCESS) {
 			pe_err("Unable to change Deauth ack Timer val");

+ 3 - 2
core/mac/src/pe/lim/lim_timer_utils.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -228,7 +228,8 @@ uint32_t lim_create_timers(struct mac_context *mac)
 	cfgValue = SYS_MS_TO_TICKS(cfgValue);
 	if (tx_timer_create(mac, &mac->lim.lim_timers.gLimDeauthAckTimer,
 			    "DISASSOC ACK TIMEOUT",
-			    lim_timer_handler, SIR_LIM_DEAUTH_ACK_TIMEOUT,
+			    lim_process_deauth_ack_timeout,
+			    WLAN_INVALID_VDEV_ID,
 			    cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
 		pe_err("could not create DEAUTH ACK TIMEOUT timer");
 		goto err_timer;

+ 2 - 2
core/mac/src/pe/lim/lim_types.h

@@ -1352,9 +1352,9 @@ void lim_wpspbc_close(struct mac_context *mac, struct pe_session *pe_session);
 #define LIM_WPS_OVERLAP_TIMER_MS                 10000
 
 void lim_process_disassoc_ack_timeout(struct mac_context *mac);
-void lim_process_deauth_ack_timeout(struct mac_context *mac);
+void lim_process_deauth_ack_timeout(void *pMacGlobal, uint32_t vdev_id);
 QDF_STATUS lim_send_disassoc_cnf(struct mac_context *mac);
-QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac);
+QDF_STATUS lim_send_deauth_cnf(struct mac_context *mac, uint8_t vdev_id);
 
 /**
  * lim_disassoc_tx_complete_cnf() - callback to indicate Tx completion

+ 1 - 1
core/mac/src/pe/lim/lim_utils.c

@@ -487,7 +487,7 @@ void lim_deactivate_timers(struct mac_context *mac_ctx)
 
 	if (tx_timer_running(&lim_timer->gLimDeauthAckTimer)) {
 		pe_err("Deauth timer running call the timeout API");
-		lim_timer_handler(mac_ctx, SIR_LIM_DEAUTH_ACK_TIMEOUT);
+		lim_process_deauth_ack_timeout(mac_ctx, WLAN_INVALID_VDEV_ID);
 	}
 	tx_timer_deactivate(&lim_timer->gLimDeauthAckTimer);
 

+ 0 - 1
core/mac/src/sys/legacy/src/utils/src/mac_trace.c

@@ -583,7 +583,6 @@ uint8_t *mac_trace_get_lim_msg_string(uint16_t lim_msg)
 		CASE_RETURN_STRING(SIR_LIM_WPS_OVERLAP_TIMEOUT);
 		CASE_RETURN_STRING(SIR_LIM_FT_PREAUTH_RSP_TIMEOUT);
 		CASE_RETURN_STRING(SIR_LIM_DISASSOC_ACK_TIMEOUT);
-		CASE_RETURN_STRING(SIR_LIM_DEAUTH_ACK_TIMEOUT);
 		CASE_RETURN_STRING(SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT);
 		CASE_RETURN_STRING(SIR_LIM_AUTH_RETRY_TIMEOUT);
 		CASE_RETURN_STRING(SIR_LIM_AUTH_SAE_TIMEOUT);