Browse Source

qcacld-3.0: Add support of pmf comeback timer for SAE assoc retry

If STA DUT receives assoc response with assoc response status as
eSIR_MAC_TRY_AGAIN_LATER, host starts a pmf comeback timer to
send assoc request again on pmf comeback timer timeout.

Change-Id: Ifb28e44af86daef90db7146572cdfae26dfcaa20
CRs-Fixed: 2728459
Abhishek Ambure 4 years ago
parent
commit
7c07f228f6

+ 6 - 1
core/mac/src/pe/include/lim_session.h

@@ -37,7 +37,8 @@ typedef struct sPowersaveoffloadInfo {
 #ifdef WLAN_FEATURE_11W
 struct comeback_timer_info {
 	struct mac_context *mac;
-	uint8_t session_id;
+	uint8_t vdev_id;
+	uint8_t retried;
 	tLimMlmStates lim_prev_mlm_state;  /* Previous MLM State */
 	tLimMlmStates lim_mlm_state;       /* MLM State */
 };
@@ -476,6 +477,10 @@ struct pe_session {
 	/* Fast Transition (FT) */
 	tftPEContext ftPEContext;
 	bool isNonRoamReassoc;
+#ifdef WLAN_FEATURE_11W
+	qdf_mc_timer_t pmf_retry_timer;
+	struct comeback_timer_info pmf_retry_timer_info;
+#endif /* WLAN_FEATURE_11W */
 	uint8_t  is_key_installed;
 	/* timer for resetting protection fileds at regular intervals */
 	qdf_mc_timer_t protection_fields_reset_timer;

+ 16 - 0
core/mac/src/pe/lim/lim_api.c

@@ -592,6 +592,21 @@ static inline void lim_nan_register_callbacks(struct mac_context *mac_ctx)
 }
 #endif
 
+#ifdef WLAN_FEATURE_11W
+static void lim_stop_pmfcomeback_timer(struct pe_session *session)
+{
+	if (session->opmode != QDF_STA_MODE)
+		return;
+
+	qdf_mc_timer_stop(&session->pmf_retry_timer);
+	session->pmf_retry_timer_info.retried = false;
+}
+#else
+static void lim_stop_pmfcomeback_timer(struct pe_session *session)
+{
+}
+#endif
+
 /*
  * pe_shutdown_notifier_cb - Shutdown notifier callback
  * @ctx: Pointer to Global MAC structure
@@ -611,6 +626,7 @@ static void pe_shutdown_notifier_cb(void *ctx)
 			if (LIM_IS_AP_ROLE(session))
 				qdf_mc_timer_stop(&session->
 						 protection_fields_reset_timer);
+			lim_stop_pmfcomeback_timer(session);
 		}
 	}
 }

+ 72 - 0
core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c

@@ -560,6 +560,68 @@ static inline void lim_process_he_info(tpSirProbeRespBeacon beacon,
 }
 #endif
 
+#ifdef WLAN_FEATURE_11W
+
+#define MAX_RETRY_TIMER 1500
+static QDF_STATUS
+lim_handle_pmfcomeback_timer(struct pe_session *session_entry,
+			     tpSirAssocRsp assoc_rsp)
+{
+	uint16_t timeout_value;
+
+	if (session_entry->opmode != QDF_STA_MODE)
+		return QDF_STATUS_E_FAILURE;
+
+	if (session_entry->limRmfEnabled &&
+	    session_entry->pmf_retry_timer_info.retried &&
+	    assoc_rsp->status_code == eSIR_MAC_TRY_AGAIN_LATER) {
+		pe_debug("Already retry in progress");
+		return QDF_STATUS_SUCCESS;
+	}
+
+	/*
+	 * Handle association Response for sta mode with RMF enabled and TRY
+	 * again later with timeout interval and Assoc comeback type
+	 */
+	if (!session_entry->limRmfEnabled || assoc_rsp->status_code !=
+	    eSIR_MAC_TRY_AGAIN_LATER || !assoc_rsp->TimeoutInterval.present ||
+	    assoc_rsp->TimeoutInterval.timeoutType !=
+	    SIR_MAC_TI_TYPE_ASSOC_COMEBACK ||
+	    session_entry->pmf_retry_timer_info.retried)
+		return QDF_STATUS_E_FAILURE;
+
+	timeout_value = assoc_rsp->TimeoutInterval.timeoutValue;
+	if (timeout_value < 10) {
+		/*
+		 * if this value is less than 10 then our timer
+		 * will fail to start and due to this we will
+		 * never re-attempt. Better modify the timer
+		 * value here.
+		 */
+		timeout_value = 10;
+	}
+	timeout_value = QDF_MIN(MAX_RETRY_TIMER, timeout_value);
+	pe_debug("ASSOC res with eSIR_MAC_TRY_AGAIN_LATER recvd.Starting timer to wait timeout: %d",
+		 timeout_value);
+	if (QDF_STATUS_SUCCESS !=
+	    qdf_mc_timer_start(&session_entry->pmf_retry_timer,
+			       timeout_value)) {
+		pe_err("Failed to start comeback timer");
+		return QDF_STATUS_E_FAILURE;
+	}
+	session_entry->pmf_retry_timer_info.retried = true;
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static QDF_STATUS
+lim_handle_pmfcomeback_timer(struct pe_session *session_entry,
+			     tpSirAssocRsp assoc_rsp)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
+
 /**
  * lim_process_assoc_rsp_frame() - Processes assoc response
  * @mac_ctx: Pointer to Global MAC structure
@@ -593,6 +655,7 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx,
 #endif
 	uint8_t ap_nss;
 	int8_t rssi;
+	QDF_STATUS status;
 
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	vdev_id = session_entry->vdev_id;
@@ -802,6 +865,15 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx,
 		qdf_mem_copy(ap_info.bssid.bytes, hdr->sa, QDF_MAC_ADDR_SIZE);
 		lim_add_bssid_to_reject_list(mac_ctx->pdev, &ap_info);
 	}
+
+	status = lim_handle_pmfcomeback_timer(session_entry, assoc_rsp);
+	/* return if retry again timer is started and ignore this assoc resp */
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		qdf_mem_free(beacon);
+		qdf_mem_free(assoc_rsp);
+		return;
+	}
+
 	if (assoc_rsp->status_code != eSIR_MAC_SUCCESS_STATUS) {
 		/*
 		 *Re/Association response was received

+ 22 - 0
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -798,6 +798,27 @@ end:
 			     (uint32_t *) &mlm_auth_cnf);
 }
 
+#ifdef WLAN_FEATURE_11W
+static void lim_store_pmfcomeback_timerinfo(struct pe_session *session_entry)
+{
+	if (session_entry->opmode != QDF_STA_MODE ||
+	    !session_entry->limRmfEnabled)
+		return;
+	/*
+	 * Store current MLM state in case ASSOC response returns with
+	 * TRY_AGAIN_LATER return code.
+	 */
+	session_entry->pmf_retry_timer_info.lim_prev_mlm_state =
+		session_entry->limPrevMlmState;
+	session_entry->pmf_retry_timer_info.lim_mlm_state =
+		session_entry->limMlmState;
+}
+#else
+static void lim_store_pmfcomeback_timerinfo(struct pe_session *session_entry)
+{
+}
+#endif /* WLAN_FEATURE_11W */
+
 /**
  * lim_process_mlm_assoc_req() - This function is called to process
  * MLM_ASSOC_REQ message from SME
@@ -858,6 +879,7 @@ static void lim_process_mlm_assoc_req(struct mac_context *mac_ctx, uint32_t *msg
 	/* map the session entry pointer to the AssocFailureTimer */
 	mac_ctx->lim.lim_timers.gLimAssocFailureTimer.sessionId =
 		mlm_assoc_req->sessionId;
+	lim_store_pmfcomeback_timerinfo(session_entry);
 	session_entry->limPrevMlmState = session_entry->limMlmState;
 	session_entry->limMlmState = eLIM_MLM_WT_ASSOC_RSP_STATE;
 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,

+ 32 - 0
core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c

@@ -416,6 +416,38 @@ static void lim_send_mlm_assoc_req(struct mac_context *mac_ctx,
 		(uint32_t *) assoc_req);
 }
 
+#ifdef WLAN_FEATURE_11W
+/**
+ * lim_pmf_comeback_timer_callback() -PMF callback handler
+ * @context: Timer context
+ *
+ * This function is called to processes the PMF comeback
+ * callback
+ *
+ * Return: None
+ */
+void lim_pmf_comeback_timer_callback(void *context)
+{
+	struct comeback_timer_info *info =
+			(struct comeback_timer_info *)context;
+	struct mac_context *mac_ctx = info->mac;
+	struct pe_session *session;
+
+	session = pe_find_session_by_vdev_id(mac_ctx, info->vdev_id);
+	if (!session) {
+		pe_err("no session found for vdev %d", info->vdev_id);
+		return;
+	}
+
+	pe_info("comeback later timer expired. sending MLM ASSOC req for vdev %d",
+		session->vdev_id);
+	/* set MLM state such that ASSOC REQ packet will be sent out */
+	session->limPrevMlmState = info->lim_prev_mlm_state;
+	session->limMlmState = info->lim_mlm_state;
+	lim_send_mlm_assoc_req(mac_ctx, session);
+}
+#endif /* WLAN_FEATURE_11W */
+
 /**
  * lim_process_mlm_auth_cnf()-Process Auth confirmation
  * @mac_ctx:  Pointer to Global MAC structure

+ 18 - 2
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -1872,7 +1872,7 @@ lim_send_assoc_req_mgmt_frame(struct mac_context *mac_ctx,
 	void *packet;
 	QDF_STATUS qdf_status;
 	uint16_t add_ie_len, current_len = 0, vendor_ie_len = 0;
-	uint8_t *add_ie;
+	uint8_t *add_ie = NULL;
 	const uint8_t *wps_ie = NULL;
 	uint8_t power_caps = false;
 	uint8_t tx_flag = 0;
@@ -1907,11 +1907,26 @@ lim_send_assoc_req_mgmt_frame(struct mac_context *mac_ctx,
 		return;
 	}
 	add_ie_len = pe_session->lim_join_req->addIEAssoc.length;
-	add_ie = pe_session->lim_join_req->addIEAssoc.addIEdata;
+	if (add_ie_len) {
+		add_ie = qdf_mem_malloc(add_ie_len);
+		if (!add_ie) {
+			qdf_mem_free(mlm_assoc_req);
+			return;
+		}
+		/*
+		 * copy the additional ie to local, as this func modify
+		 * the IE, these IE will be required in assoc/re-assoc
+		 * retry. So do not modify the original IE.
+		 */
+		qdf_mem_copy(add_ie, pe_session->lim_join_req->addIEAssoc.addIEdata,
+			     add_ie_len);
+
+	}
 
 	frm = qdf_mem_malloc(sizeof(tDot11fAssocRequest));
 	if (!frm) {
 		qdf_mem_free(mlm_assoc_req);
+		qdf_mem_free(add_ie);
 		return;
 	}
 	qdf_mem_zero((uint8_t *) frm, sizeof(tDot11fAssocRequest));
@@ -2456,6 +2471,7 @@ end:
 	/* Free up buffer allocated for mlm_assoc_req */
 	qdf_mem_free(adaptive_11r_ie);
 	qdf_mem_free(mlm_assoc_req);
+	qdf_mem_free(add_ie);
 	mlm_assoc_req = NULL;
 	qdf_mem_free(frm);
 	return;

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

@@ -269,6 +269,41 @@ restart_timer:
 	}
 }
 
+#ifdef WLAN_FEATURE_11W
+/**
+ * pe_init_pmf_comeback_timer: init PMF comeback timer
+ * @mac_ctx: pointer to global adapter context
+ * @session: pe session
+ *
+ * Return: void
+ */
+static void
+pe_init_pmf_comeback_timer(tpAniSirGlobal mac_ctx, struct pe_session *session)
+{
+	QDF_STATUS status;
+
+	if (session->opmode != QDF_STA_MODE)
+		return;
+
+	pe_debug("init pmf comeback timer for vdev %d", session->vdev_id);
+	session->pmf_retry_timer_info.mac = mac_ctx;
+	session->pmf_retry_timer_info.vdev_id = session->vdev_id;
+	session->pmf_retry_timer_info.retried = false;
+	status = qdf_mc_timer_init(
+			&session->pmf_retry_timer, QDF_TIMER_TYPE_SW,
+			lim_pmf_comeback_timer_callback,
+			(void *)&session->pmf_retry_timer_info);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		pe_err("cannot init pmf comeback timer");
+}
+#else
+static inline void
+pe_init_pmf_comeback_timer(tpAniSirGlobal mac_ctx, struct pe_session *session,
+			   uint8_t vdev_id)
+{
+}
+#endif
+
 #ifdef WLAN_FEATURE_FILS_SK
 /**
  * pe_delete_fils_info: API to delete fils session info
@@ -653,6 +688,7 @@ struct pe_session *pe_create_session(struct mac_context *mac,
 			pe_err("cannot create ap_ecsa_timer");
 	}
 	pe_init_fils_info(session_ptr);
+	pe_init_pmf_comeback_timer(mac, session_ptr);
 	session_ptr->ht_client_cnt = 0;
 	/* following is invalid value since seq number is 12 bit */
 	session_ptr->prev_auth_seq_num = 0xFFFF;
@@ -777,6 +813,25 @@ struct pe_session *pe_find_session_by_session_id(struct mac_context *mac,
 	return NULL;
 }
 
+#ifdef WLAN_FEATURE_11W
+static void lim_clear_pmfcomeback_timer(struct pe_session *session)
+{
+	if (session->opmode != QDF_STA_MODE)
+		return;
+
+	pe_debug("deinit pmf comeback timer for vdev %d", session->vdev_id);
+	if (QDF_TIMER_STATE_RUNNING ==
+	    qdf_mc_timer_get_current_state(&session->pmf_retry_timer))
+		qdf_mc_timer_stop(&session->pmf_retry_timer);
+	qdf_mc_timer_destroy(&session->pmf_retry_timer);
+	session->pmf_retry_timer_info.retried = false;
+}
+#else
+static void lim_clear_pmfcomeback_timer(struct pe_session *session)
+{
+}
+#endif
+
 /**
  * pe_delete_session() - deletes the PE session given the session ID.
  * @mac_ctx: pointer to global adapter context
@@ -957,6 +1012,7 @@ void pe_delete_session(struct mac_context *mac_ctx, struct pe_session *session)
 		session->add_ie_params.probeRespBCNDataLen = 0;
 	}
 	pe_delete_fils_info(session);
+	lim_clear_pmfcomeback_timer(session);
 	session->valid = false;
 
 	session->mac_ctx = NULL;

+ 1 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -833,6 +833,7 @@ bool lim_check_disassoc_deauth_ack_pending(struct mac_context *mac,
 
 #ifdef WLAN_FEATURE_11W
 void lim_pmf_sa_query_timer_handler(void *pMacGlobal, uint32_t param);
+void lim_pmf_comeback_timer_callback(void *context);
 void lim_set_protected_bit(struct mac_context *mac,
 	struct pe_session *pe_session,
 	tSirMacAddr peer, tpSirMacMgmtHdr pMacHdr);