Browse Source

qcacld-3.0: Add support for sae auth retry

Host retransmits WPA3 SAE authentication frames after 1 second
if there is no response for previous auth frames from AP.
Host keep retransmitting SAE auth frames for max WLAN_SAE_AUTH_RETRY
times.

Change-Id: I1be0bd5354586518781876646b063592e667b0bb
CRs-Fixed: 2716719
Abhishek Ambure 4 years ago
parent
commit
e5b5a03aeb

+ 28 - 0
components/mlme/core/inc/wlan_mlme_main.h

@@ -59,6 +59,16 @@ struct wlan_disconnect_info {
 	bool from_ap;
 };
 
+/**
+ * struct sae_auth_retry - SAE auth retry Information
+ * @sae_auth_max_retry: Max number of sae auth retries
+ * @sae_auth: SAE auth frame information
+ */
+struct sae_auth_retry {
+	uint8_t sae_auth_max_retry;
+	struct wlan_ies sae_auth;
+};
+
 /**
  * struct peer_mlme_priv_obj - peer MLME component object
  * @last_pn_valid if last PN is valid
@@ -147,6 +157,7 @@ struct wlan_mlme_roam {
  * @vdev_stop_type: vdev stop type request
  * @roam_off_state: Roam offload state
  * @bigtk_vdev_support: BIGTK feature support for this vdev (SAP)
+ * @sae_auth_retry: SAE auth retry information
  */
 struct mlme_legacy_priv {
 	bool chan_switch_in_progress;
@@ -165,6 +176,7 @@ struct mlme_legacy_priv {
 	uint32_t vdev_stop_type;
 	struct wlan_mlme_roam mlme_roam;
 	bool bigtk_vdev_support;
+	struct sae_auth_retry sae_retry;
 };
 
 /**
@@ -270,6 +282,22 @@ struct wlan_mlme_psoc_ext_obj *mlme_get_psoc_ext_obj_fl(struct wlan_objmgr_psoc
 							const char *func,
 							uint32_t line);
 
+/**
+ * mlme_get_sae_auth_retry() - Get sae_auth_retry pointer
+ * @vdev: vdev pointer
+ *
+ * Return: Pointer to struct sae_auth_retry or NULL
+ */
+struct sae_auth_retry *mlme_get_sae_auth_retry(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * mlme_free_sae_auth_retry() - Free the SAE auth info
+ * @vdev: vdev pointer
+ *
+ * Return: None
+ */
+void mlme_free_sae_auth_retry(struct wlan_objmgr_vdev *vdev);
+
 /**
  * mlme_set_self_disconnect_ies() - Set diconnect IEs configured from userspace
  * @vdev: vdev pointer

+ 30 - 0
components/mlme/core/src/wlan_mlme_main.c

@@ -2253,6 +2253,36 @@ QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc)
 	return status;
 }
 
+struct sae_auth_retry *mlme_get_sae_auth_retry(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 NULL;
+	}
+
+	return &mlme_priv->sae_retry;
+}
+
+void mlme_free_sae_auth_retry(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;
+	}
+
+	mlme_priv->sae_retry.sae_auth_max_retry = 0;
+	if (mlme_priv->sae_retry.sae_auth.data)
+		qdf_mem_free(mlme_priv->sae_retry.sae_auth.data);
+	mlme_priv->sae_retry.sae_auth.data = NULL;
+	mlme_priv->sae_retry.sae_auth.len = 0;
+}
+
 void mlme_set_self_disconnect_ies(struct wlan_objmgr_vdev *vdev,
 				  struct wlan_ies *ie)
 {

+ 1 - 0
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -973,6 +973,7 @@ QDF_STATUS vdevmgr_mlme_ext_hdl_destroy(struct vdev_mlme_obj *vdev_mlme)
 
 	mlme_free_self_disconnect_ies(vdev_mlme->vdev);
 	mlme_free_peer_disconnect_ies(vdev_mlme->vdev);
+	mlme_free_sae_auth_retry(vdev_mlme->vdev);
 	qdf_mem_free(vdev_mlme->ext_vdev_ptr);
 	vdev_mlme->ext_vdev_ptr = NULL;
 

+ 23 - 0
core/mac/src/pe/lim/lim_process_auth_frame.c

@@ -338,6 +338,22 @@ static void lim_external_auth_add_pre_auth_node(struct mac_context *mac_ctx,
 	lim_add_pre_auth_node(mac_ctx, auth_node);
 }
 
+void lim_sae_auth_cleanup_retry(struct mac_context *mac_ctx,
+				uint8_t vdev_id)
+{
+	struct pe_session *pe_session;
+
+	pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
+	if (!pe_session) {
+		pe_err("session not found for given vdev_id %d", vdev_id);
+		return;
+	}
+
+	pe_debug("sae auth cleanup for vdev_id %d", vdev_id);
+	lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_RETRY_TIMER);
+	mlme_free_sae_auth_retry(pe_session->vdev);
+}
+
 /**
  * lim_process_sae_auth_frame()-Process SAE authentication frame
  * @mac_ctx: MAC context
@@ -353,6 +369,7 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
 	uint32_t frame_len;
 	uint8_t *body_ptr;
 	enum rxmgmt_flags rx_flags = RXMGMT_FLAG_NONE;
+	struct sae_auth_retry *sae_retry;
 
 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
@@ -389,6 +406,12 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
 		}
 	}
 
+	sae_retry = mlme_get_sae_auth_retry(pe_session->vdev);
+	if (LIM_IS_STA_ROLE(pe_session) && sae_retry &&
+	    sae_retry->sae_auth.data)
+		lim_sae_auth_cleanup_retry(mac_ctx,
+					   pe_session->vdev_id);
+
 	lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
 				    (uint8_t *)mac_hdr,
 				    frame_len + sizeof(tSirMacMgmtHdr),

+ 43 - 7
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -1627,6 +1627,36 @@ static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ct
 	}
 }
 
+static void lim_handle_sae_auth_timeout(struct mac_context *mac_ctx,
+					struct pe_session *session_entry)
+{
+	struct sae_auth_retry *sae_retry;
+
+	sae_retry = mlme_get_sae_auth_retry(session_entry->vdev);
+	if (!(sae_retry && sae_retry->sae_auth.data)) {
+		pe_debug("sae auth frame is not buffered vdev id %d",
+			 session_entry->vdev_id);
+		return;
+	}
+
+	pe_debug("retry sae auth for seq num %d vdev id %d",
+		 mac_ctx->mgmtSeqNum, session_entry->vdev_id);
+	lim_send_frame(mac_ctx, session_entry->vdev_id,
+		       sae_retry->sae_auth.data, sae_retry->sae_auth.len);
+
+	sae_retry->sae_auth_max_retry--;
+	/* Activate Auth Retry timer if max_retries are not done */
+	if (!sae_retry->sae_auth_max_retry || (tx_timer_activate(
+	    &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) !=
+	    TX_SUCCESS))
+		goto free_and_deactivate_timer;
+
+	return;
+
+free_and_deactivate_timer:
+	lim_sae_auth_cleanup_retry(mac_ctx, session_entry->vdev_id);
+}
+
 /**
  * lim_process_auth_retry_timer()- function to Retry Auth when auth timeout
  * occurs
@@ -1639,15 +1669,19 @@ static void lim_process_auth_retry_timer(struct mac_context *mac_ctx)
 	struct pe_session *session_entry;
 	tAniAuthType auth_type;
 	tLimTimers *lim_timers = &mac_ctx->lim.lim_timers;
-	uint16_t vdev_id =
+	uint16_t pe_session_id =
 		lim_timers->g_lim_periodic_auth_retry_timer.sessionId;
 
-	session_entry = pe_find_session_by_session_id(mac_ctx, vdev_id);
+	session_entry = pe_find_session_by_session_id(mac_ctx, pe_session_id);
 	if (!session_entry) {
-		pe_err("session does not exist for vdev_id: %d", vdev_id);
+		pe_err("session does not exist for pe_session_id: %d",
+		       pe_session_id);
 		return;
 	}
 
+	/** For WPA3 SAE gLimAuthFailureTimer is not running hence
+	 *  we don't enter in below "if" block in case of wpa3 sae
+	 */
 	if (tx_timer_running(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer) &&
 	    (session_entry->limMlmState == eLIM_MLM_WT_AUTH_FRAME2_STATE) &&
 	     (LIM_AUTH_ACK_RCD_SUCCESS != mac_ctx->auth_ack_status)) {
@@ -1684,12 +1718,14 @@ static void lim_process_auth_retry_timer(struct mac_context *mac_ctx)
 		/* Activate Auth Retry timer */
 		if (tx_timer_activate
 		     (&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer)
-			 != TX_SUCCESS) {
+			 != TX_SUCCESS)
 			pe_err("could not activate Auth Retry failure timer");
-			return;
-		}
+
+		return;
 	}
-	return;
+
+	/* Auth retry time out for wpa3 sae */
+	lim_handle_sae_auth_timeout(mac_ctx, session_entry);
 } /*** lim_process_auth_retry_timer() ***/
 
 void lim_process_auth_failure_timeout(struct mac_context *mac_ctx)

+ 88 - 24
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -5294,28 +5294,28 @@ error_delba:
 	return qdf_status;
 }
 
+#define WLAN_SAE_AUTH_TIMEOUT 1000
+#define WLAN_SAE_AUTH_RETRY 1
+
 /**
  * lim_tx_mgmt_frame() - Transmits Auth mgmt frame
  * @mac_ctx Pointer to Global MAC structure
- * @mb_msg: Received message info
+ * @vdev_id: vdev id
  * @msg_len: Received message length
  * @packet: Packet to be transmitted
  * @frame: Received frame
  *
  * Return: None
  */
-static void lim_tx_mgmt_frame(struct mac_context *mac_ctx,
-	struct sir_mgmt_msg *mb_msg, uint32_t msg_len,
-	void *packet, uint8_t *frame)
+static void lim_tx_mgmt_frame(struct mac_context *mac_ctx, uint8_t vdev_id,
+			      uint32_t msg_len, void *packet, uint8_t *frame)
 {
-	tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data;
+	tpSirMacFrameCtl fc = (tpSirMacFrameCtl)frame;
 	QDF_STATUS qdf_status;
-	uint8_t vdev_id = 0;
 	struct pe_session *session;
 	uint16_t auth_ack_status;
 	enum rateid min_rid = RATEID_DEFAULT;
 
-	vdev_id = mb_msg->vdev_id;
 	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
 	if (!session) {
 		cds_packet_free((void *)packet);
@@ -5349,35 +5349,99 @@ static void lim_tx_mgmt_frame(struct mac_context *mac_ctx,
 	}
 }
 
-void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx,
-		struct scheduler_msg *msg)
+static void
+lim_handle_sae_auth_retry(struct mac_context *mac_ctx, uint8_t vdev_id,
+			  uint8_t *frame, uint32_t frame_len)
+{
+	struct pe_session *session;
+	struct sae_auth_retry *sae_retry;
+
+	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
+	if (!session) {
+		pe_err("session not found for given vdev_id %d",
+		       vdev_id);
+		return;
+	}
+
+	sae_retry = mlme_get_sae_auth_retry(session->vdev);
+	if (!sae_retry) {
+		pe_err("sae retry pointer is NULL for vdev_id %d",
+		       vdev_id);
+		return;
+	}
+
+	if (sae_retry->sae_auth.data)
+		lim_sae_auth_cleanup_retry(mac_ctx, vdev_id);
+
+	sae_retry->sae_auth.data = qdf_mem_malloc(frame_len);
+	if (!sae_retry->sae_auth.data) {
+		pe_err("failed to alloc memory for sae auth");
+		return;
+	}
+
+	pe_debug("SAE auth frame queued vdev_id %d seq_num %d",
+		 vdev_id, mac_ctx->mgmtSeqNum);
+	qdf_mem_copy(sae_retry->sae_auth.data, frame, frame_len);
+	mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId =
+					session->peSessionId;
+	sae_retry->sae_auth.len = frame_len;
+	sae_retry->sae_auth_max_retry = WLAN_SAE_AUTH_RETRY;
+
+	tx_timer_change(
+		&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer,
+		SYS_MS_TO_TICKS(WLAN_SAE_AUTH_TIMEOUT), 0);
+	/* Activate Auth Retry timer */
+	if (tx_timer_activate(
+	    &mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) !=
+	    TX_SUCCESS) {
+		pe_err("failed to start periodic auth retry timer");
+		lim_sae_auth_cleanup_retry(mac_ctx, vdev_id);
+	}
+}
+
+void lim_send_frame(struct mac_context *mac_ctx, uint8_t vdev_id, uint8_t *buf,
+		    uint16_t buf_len)
 {
-	struct sir_mgmt_msg *mb_msg = (struct sir_mgmt_msg *)msg->bodyptr;
-	uint32_t msg_len;
-	tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data;
-	uint8_t vdev_id;
 	QDF_STATUS qdf_status;
 	uint8_t *frame;
 	void *packet;
-	tpSirMacMgmtHdr mac_hdr;
+	tpSirMacFrameCtl fc = (tpSirMacFrameCtl)buf;
+	tpSirMacMgmtHdr mac_hdr = (tpSirMacMgmtHdr)buf;
 
-	msg_len = mb_msg->msg_len - sizeof(*mb_msg);
 	pe_debug("sending fc->type: %d fc->subType: %d",
-		fc->type, fc->subType);
-
-	vdev_id = mb_msg->vdev_id;
-	mac_hdr = (tpSirMacMgmtHdr)mb_msg->data;
+		 fc->type, fc->subType);
 
 	lim_add_mgmt_seq_num(mac_ctx, mac_hdr);
-
-	qdf_status = cds_packet_alloc((uint16_t) msg_len, (void **)&frame,
-				 (void **)&packet);
+	qdf_status = cds_packet_alloc(buf_len, (void **)&frame,
+				      (void **)&packet);
 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
 		pe_err("call to bufAlloc failed for AUTH frame");
 		return;
 	}
 
-	qdf_mem_copy(frame, mb_msg->data, msg_len);
+	qdf_mem_copy(frame, buf, buf_len);
+	lim_tx_mgmt_frame(mac_ctx, vdev_id, buf_len, packet, frame);
+}
+
+void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx,
+			    struct scheduler_msg *msg)
+{
+	struct sir_mgmt_msg *mb_msg = (struct sir_mgmt_msg *)msg->bodyptr;
+	uint32_t msg_len;
+	tpSirMacFrameCtl fc = (tpSirMacFrameCtl)mb_msg->data;
+	uint8_t vdev_id;
+	uint16_t auth_algo;
+
+	msg_len = mb_msg->msg_len - sizeof(*mb_msg);
+	vdev_id = mb_msg->vdev_id;
+
+	if (fc->subType == SIR_MAC_MGMT_AUTH) {
+		auth_algo = *(uint16_t *)(mb_msg->data +
+					sizeof(tSirMacMgmtHdr));
+		if (auth_algo == eSIR_AUTH_TYPE_SAE)
+			lim_handle_sae_auth_retry(mac_ctx, vdev_id,
+						  mb_msg->data, msg_len);
+	}
 
-	lim_tx_mgmt_frame(mac_ctx, mb_msg, msg_len, packet, frame);
+	lim_send_frame(mac_ctx, vdev_id, mb_msg->data, msg_len);
 }

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

@@ -803,6 +803,7 @@ void pe_delete_session(struct mac_context *mac_ctx, struct pe_session *session)
 		 QDF_MAC_ADDR_ARRAY(session->bssId));
 
 	lim_reset_bcn_probe_filter(mac_ctx, session);
+	lim_sae_auth_cleanup_retry(mac_ctx, session->vdev_id);
 
 	/* Restore default failure timeout */
 	if (session->defaultAuthFailureTimeout) {

+ 23 - 0
core/mac/src/pe/lim/lim_types.h

@@ -420,6 +420,17 @@ bool lim_fill_lim_assoc_ind_params(
 		tpDphHashNode sta_ds,
 		struct pe_session *session_entry);
 
+/**
+ * lim_sae_auth_cleanup_retry() - API to cleanup sae auth frmae stored
+ * and deactivate the timer
+ * @mac_ctx: Pointer to mac context
+ * @vdev_id: vdev id
+ *
+ * Return: none
+ */
+void lim_sae_auth_cleanup_retry(struct mac_context *mac_ctx,
+				uint8_t vdev_id);
+
 /**
  * lim_fill_sme_assoc_ind_params() - Initialize association indication
  * @mac_ctx: Pointer to Global MAC structure
@@ -1220,6 +1231,18 @@ void lim_process_auth_failure_timeout(struct mac_context *mac_ctx);
 void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx,
 				       uint32_t msg_type);
 
+/**
+ * lim_send_frame() - API to send frame
+ * @mac_ctx Pointer to Global MAC structure
+ * @vdev_id: vdev id
+ * @buf: Pointer to SAE auth retry frame
+ * @buf_len: length of frame
+ *
+ * Return: None
+ */
+void lim_send_frame(struct mac_context *mac_ctx, uint8_t vdev_id, uint8_t *buf,
+		    uint16_t buf_len);
+
 /**
  * lim_send_mgmt_frame_tx() - Sends mgmt frame
  * @mac_ctx Pointer to Global MAC structure