Ver Fonte

qcacld-3.0: Cache standby link beacon during 3link roam

If FW roams with 3-links, assoc beacon and link beacons
are sent by the firmware in roam sync frame event.
However, driver parses the per-sta link info of the
assoc beacon and caches the individual per-link probe
responses only if the link beacon is not present.

Therefore, in 3-link roaming cases, if both assoc link
ML probe response(assoc link + one partner link) and link
probe/beacon are received, then the per-sta profile present
in the ML assoc link probe is not saved to the scan cache
and this leads to bss retrieval failures.

To fix this, parse per-sta profile and generate individual
probe responses directly from the roam sync frame event for
both link and assoc beacon/ML probe responses. This caches
all the partner links individually.

Also, set the assoc state for the standby link bss after the
completion of roam sync processing on assoc vdev. This prevents
the age out of the standby link scan entry.

Change-Id: Ib349aedb826d5037c6015434557d909477e87e5a
CRs-Fixed: 3613058
Surya Prakash Sivaraj há 1 ano atrás
pai
commit
8005c96788

+ 3 - 0
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c

@@ -954,6 +954,9 @@ cm_update_scan_db_on_roam_success(struct wlan_objmgr_vdev *vdev,
 
 	cm_update_scan_mlme_on_roam(vdev, &resp->bssid,
 				    SCAN_ENTRY_CON_STATE_ASSOC);
+
+	cm_standby_link_update_mlme_by_bssid(vdev, SCAN_ENTRY_CON_STATE_ASSOC,
+					     resp->ssid);
 }
 
 #ifdef WLAN_FEATURE_11BE_MLO

+ 27 - 3
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c

@@ -393,6 +393,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 	struct rso_config *rso_cfg;
 	struct roam_synch_frame_ind *sync_frame_ind = frame_ind;
 	struct roam_synch_frame_ind *roam_synch_frame_ind;
+	struct roam_scan_candidate_frame roam_candidate = {0};
 	uint8_t vdev_id;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
@@ -411,7 +412,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 	rso_cfg = wlan_cm_get_rso_config(vdev);
 	if (!rso_cfg) {
 		status = QDF_STATUS_E_FAILURE;
-		goto err;
+		goto complete;
 	}
 
 	roam_synch_frame_ind = &rso_cfg->roam_sync_frame_ind;
@@ -420,7 +421,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 		mlme_err("Ignoring this event as it is unexpected");
 		wlan_cm_free_roam_synch_frame_ind(rso_cfg);
 		status = QDF_STATUS_E_FAILURE;
-		goto err;
+		goto complete;
 	}
 
 	if (sync_frame_ind->bcn_probe_rsp_len) {
@@ -463,7 +464,30 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 			sync_frame_ind->reassoc_rsp;
 	}
 
-err:
+	if (!sync_frame_ind->bcn_probe_rsp_len &&
+	    !sync_frame_ind->link_bcn_probe_rsp_len)
+		goto complete;
+
+	roam_candidate.vdev_id = vdev_id;
+
+	if (sync_frame_ind->bcn_probe_rsp_len) {
+		roam_candidate.frame_length = sync_frame_ind->bcn_probe_rsp_len;
+		roam_candidate.frame = sync_frame_ind->bcn_probe_rsp;
+		roam_candidate.roam_offload_candidate_frm = false;
+		wlan_cm_add_all_link_probe_rsp_to_scan_db(psoc,
+							  &roam_candidate);
+	}
+
+	if (sync_frame_ind->link_bcn_probe_rsp_len) {
+		roam_candidate.frame_length =
+					sync_frame_ind->link_bcn_probe_rsp_len;
+		roam_candidate.frame = sync_frame_ind->link_bcn_probe_rsp;
+		roam_candidate.roam_offload_candidate_frm = false;
+		wlan_cm_add_all_link_probe_rsp_to_scan_db(psoc,
+							  &roam_candidate);
+	}
+
+complete:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
 	return status;
 }

+ 19 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h

@@ -1351,6 +1351,18 @@ wlan_cm_update_offload_ssid_from_candidate(struct wlan_objmgr_pdev *pdev,
 QDF_STATUS
 wlan_cm_add_frame_to_scan_db(struct wlan_objmgr_psoc *psoc,
 			     struct roam_scan_candidate_frame *frame);
+
+/**
+ * wlan_cm_add_all_link_probe_rsp_to_scan_db() - Parse and generate
+ * probe responses for each of the per-sta profile
+ *
+ * @psoc: psoc objmgr ptr
+ * @candidate: roam scan candidate info
+ */
+QDF_STATUS
+wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
+				struct roam_scan_candidate_frame *candidate);
+
 #else
 static inline
 void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc,
@@ -1606,6 +1618,13 @@ wlan_cm_add_frame_to_scan_db(struct wlan_objmgr_psoc *psoc,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline QDF_STATUS
+wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
+				struct roam_scan_candidate_frame *candidate)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
 
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_ROAM_OFFLOAD)

+ 2 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h

@@ -2874,12 +2874,14 @@ struct roam_offload_synch_ind {
  * @frame_length : Length of the beacon/probe rsp frame
  * @frame : Pointer to the frame
  * @rssi: RSSI of the received frame, 0 if not available
+ * @roam_offload_candidate_frm: Is a roam offload candidate frame
  */
 struct roam_scan_candidate_frame {
 	uint8_t vdev_id;
 	uint32_t frame_length;
 	uint8_t *frame;
 	int32_t rssi;
+	bool roam_offload_candidate_frm;
 };
 
 /**

+ 24 - 1
components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c

@@ -4997,7 +4997,14 @@ wlan_cm_add_frame_to_scan_db(struct wlan_objmgr_psoc *psoc,
 
 	extracted_ie = (uint8_t *)wlan_get_ie_ptr_from_eid(WLAN_ELEMID_SSID,
 							   ie_ptr, ie_len);
-	if (extracted_ie && extracted_ie[0] == WLAN_ELEMID_SSID) {
+	/*
+	 * Roam offload ssid/bssid needs to be set only for SAE roam offload
+	 * candidate frames for supporting cross-ssid roaming.
+	 * This update is not needed for probe/beacons received from the
+	 * roam sync frame event.
+	 */
+	if (frame->roam_offload_candidate_frm &&
+	    extracted_ie && extracted_ie[0] == WLAN_ELEMID_SSID) {
 		wh = (struct wlan_frame_hdr *)frame->frame;
 		WLAN_ADDR_COPY(&bssid.bytes[0], wh->i_addr2);
 
@@ -5208,6 +5215,14 @@ cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc,
 {
 	return mlo_add_all_link_probe_rsp_to_scan_db(psoc, candidate);
 }
+
+QDF_STATUS
+wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
+				struct roam_scan_candidate_frame *candidate)
+{
+	return mlo_add_all_link_probe_rsp_to_scan_db(psoc, candidate);
+}
+
 #elif defined(WLAN_FEATURE_ROAM_OFFLOAD) /* end WLAN_FEATURE_11BE_MLO */
 QDF_STATUS
 cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc,
@@ -5215,4 +5230,12 @@ cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc,
 {
 	return wlan_cm_add_frame_to_scan_db(psoc, candidate);
 }
+
+QDF_STATUS
+wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
+				struct roam_scan_candidate_frame *candidate)
+{
+	return wlan_cm_add_frame_to_scan_db(psoc, candidate);
+}
+
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */

+ 1 - 0
components/wmi/src/wmi_unified_roam_tlv.c

@@ -3491,6 +3491,7 @@ extract_roam_candidate_frame_tlv(wmi_unified_t wmi_handle, uint8_t *event,
 	data->vdev_id = frame_params->vdev_id;
 	data->frame_length = frame_params->frame_length;
 	data->frame = (uint8_t *)param_buf->frame;
+	data->roam_offload_candidate_frm = true;
 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
 			   data->frame, data->frame_length);
 

+ 0 - 20
core/mac/src/pe/include/lim_api.h

@@ -684,18 +684,6 @@ lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 			     uint8_t *probe_rsp,
 			     uint32_t probe_rsp_len);
 
-/**
- * lim_gen_link_probe_rsp_roam() - Generate link prb rsp from assoc link prb rsp
- * @mac_ctx: Pointer to mac context
- * @session_entry: pe session
- * @roam_sync_ind_ptr: Roam synch parameters
- *
- * Return qdf status
- */
-QDF_STATUS
-lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx,
-			    struct pe_session *session_entry,
-			    struct roam_offload_synch_ind *roam_sync_ind);
 #else
 static inline QDF_STATUS
 lim_update_mlo_mgr_info(struct mac_context *mac_ctx,
@@ -723,14 +711,6 @@ lim_check_for_ml_probe_req(struct pe_session *session)
 	return QDF_STATUS_E_NOSUPPORT;
 }
 
-static inline QDF_STATUS
-lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx,
-			    struct pe_session *session_entry,
-			    struct roam_offload_synch_ind *roam_sync_ind)
-{
-	return QDF_STATUS_E_NOSUPPORT;
-}
-
 static inline QDF_STATUS
 lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 			     struct pe_session *session,

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

@@ -2195,15 +2195,6 @@ lim_roam_fill_bss_descr(struct mac_context *mac,
 				roam_synch_ind->link_beacon_probe_resp_length;
 			}
 		} else {
-			/*
-			 * This indicates that firmware hasn't sent link beacon,
-			 * which means assoc probe rsp is an ML probe rsp.
-			 * Extract the link probe rsp also from that.
-			 */
-			status = lim_gen_link_probe_rsp_roam(mac,
-						session, roam_synch_ind);
-			if (QDF_IS_STATUS_ERROR(status))
-				return status;
 			mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind,
 						  &bssid);
 			status = wlan_scan_get_entry_by_mac_addr(mac->pdev,
@@ -4251,188 +4242,6 @@ end:
 	return status;
 }
 
-QDF_STATUS
-lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx,
-			    struct pe_session *session,
-			    struct roam_offload_synch_ind *roam_sync_ind)
-{
-	struct element_info rcvd_probe_rsp, gen_probe_rsp = {0, NULL}, frame;
-	struct qdf_mac_addr sta_link_addr;
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	tSirProbeRespBeacon *probe_rsp;
-	uint8_t *src_addr;
-	struct wlan_frame_hdr *hdr;
-	uint16_t gen_frame_len;
-	uint32_t idx, link_id, ml_probe_link_id;
-	struct roam_scan_candidate_frame rcvd_frame;
-	qdf_freq_t freq;
-
-	if (!session || !roam_sync_ind)
-		return QDF_STATUS_E_NULL_VALUE;
-
-	if (!roam_sync_ind->num_setup_links)
-		return status;
-
-	if (roam_sync_ind->link_beacon_probe_resp_length) {
-		pe_debug("Firmware sent link beacon also. No need to generate a new one from assoc bcn/prb rsp");
-		return QDF_STATUS_SUCCESS;
-	}
-
-	frame.ptr = (uint8_t *)roam_sync_ind +
-				roam_sync_ind->beacon_probe_resp_offset;
-	frame.len = roam_sync_ind->beacon_probe_resp_length;
-
-	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
-			   frame.ptr, frame.len);
-
-	/* Strip the header */
-	rcvd_probe_rsp.ptr = frame.ptr + sizeof(*hdr);
-	rcvd_probe_rsp.len = frame.len - sizeof(*hdr);
-
-
-	probe_rsp = qdf_mem_malloc(sizeof(tSirProbeRespBeacon));
-	if (!probe_rsp)
-		return QDF_STATUS_E_NOMEM;
-
-	probe_rsp->ssId.length = 0;
-	probe_rsp->wpa.length = 0;
-	/* Enforce Mandatory IEs */
-	status = sir_convert_probe_frame2_struct(mac_ctx, rcvd_probe_rsp.ptr,
-						 rcvd_probe_rsp.len, probe_rsp);
-	if (status == QDF_STATUS_E_FAILURE ||
-	    !probe_rsp->ssidPresent) {
-		pe_err("Parse error ProbeResponse, length=%d",
-		       rcvd_probe_rsp.len);
-		qdf_mem_free(probe_rsp);
-		return QDF_STATUS_E_INVAL;
-	}
-
-	if (!probe_rsp->mlo_ie.mlo_ie_present)
-		goto err1;
-
-	/* Add received ml bcn/probe rsp to scan db */
-	src_addr = wlan_mlme_get_src_addr_from_frame(&frame);
-	if (!src_addr) {
-		pe_err("MLO: Failed to fetch src address");
-		status = QDF_STATUS_E_FAILURE;
-		goto err1;
-	}
-	freq = mlo_roam_get_link_freq_from_mac_addr(roam_sync_ind,
-						    src_addr);
-	/*
-	 * Frequency corresponds to a link mac address might not be
-	 * present in the ml roam info if firmware hadn't roamed to
-	 * the link where ML probe response is received. It might have
-	 * roamed to other links. This happens frequently when roamed
-	 * to a 3-link(2+5+6) AP. As STA can do only 2-link association,
-	 * it chooses best two links(5+6) due to scoring but it might
-	 * have got ML probe response from 2ghz link.
-	 */
-	if (!freq) {
-		pe_debug("MLO: Failed to fetch freq");
-		status = QDF_STATUS_E_FAILURE;
-		goto err1;
-	}
-	lim_add_bcn_probe(session->vdev, frame.ptr, frame.len,
-			  freq, roam_sync_ind->rssi);
-	/*
-	 * When STA roams to an MLO AP, non-assoc link might be superior
-	 * in features compared to  assoc link and the per-STA profile
-	 * info may carry corresponding IEs. These IEs are extracted
-	 * and added to IE list of link probe response while generating
-	 * it. So, the link probe response generated from assoc link
-	 * probe response might be of more size than assoc link probe
-	 * rsp. Allocate buffer for the bss descriptor to accommodate
-	 * all of the IEs got generated as part of link probe rsp
-	 * generation. Allocate MAX_MGMT_MPDU_LEN bytes for IEs as the
-	 * max frame size that can be received from AP is
-	 * MAX_MGMT_MPDU_LEN bytes.
-	 */
-	gen_frame_len = MAX_MGMT_MPDU_LEN;
-
-	gen_probe_rsp.ptr = qdf_mem_malloc(gen_frame_len);
-	if (!gen_probe_rsp.ptr) {
-		status = QDF_STATUS_E_NOMEM;
-		goto err1;
-	}
-
-	/*
-	 * It's ok to keep assoc vdev mac address as DA as link vdev
-	 * is just cleanedup and it may not be an ML vdev till the
-	 * flags are set again
-	 */
-	qdf_mem_copy(&sta_link_addr, session->self_mac_addr,
-		     QDF_MAC_ADDR_SIZE);
-
-	gen_probe_rsp.len = gen_frame_len;
-	src_addr = wlan_mlme_get_src_addr_from_frame(&frame);
-	status = mlo_roam_get_link_id_from_mac_addr(roam_sync_ind,
-						    src_addr,
-						    &ml_probe_link_id);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		pe_debug("Invalid link id for mac_addr: " QDF_MAC_ADDR_FMT,
-			 QDF_MAC_ADDR_REF(src_addr));
-		goto done;
-	}
-	for (idx = 0; idx < roam_sync_ind->num_setup_links; idx++) {
-		link_id =  roam_sync_ind->ml_link[idx].link_id;
-		if (link_id == ml_probe_link_id)
-			continue;
-		status = util_gen_link_probe_rsp(rcvd_probe_rsp.ptr,
-					rcvd_probe_rsp.len,
-					link_id,
-					sta_link_addr,
-					gen_probe_rsp.ptr,
-					gen_frame_len,
-					(qdf_size_t *)&gen_probe_rsp.len);
-		if (QDF_IS_STATUS_ERROR(status)) {
-			pe_err("MLO: Link %d probe resp gen failed %d",
-			       link_id, status);
-			status = QDF_STATUS_E_FAILURE;
-			goto done;
-		}
-
-		pe_debug("MLO: link probe rsp size:%u orig probe rsp :%u",
-			 gen_probe_rsp.len, rcvd_probe_rsp.len);
-
-		src_addr = wlan_mlme_get_src_addr_from_frame(
-						&gen_probe_rsp);
-		if (!src_addr) {
-			pe_err("MLO: Failed to fetch src address");
-			status = QDF_STATUS_E_FAILURE;
-			goto done;
-		}
-
-		if (gen_probe_rsp.len > gen_frame_len) {
-			pe_err("MLO: gen probe rsp len %u larger than buffer size: %u",
-			       gen_probe_rsp.len, gen_frame_len);
-			status = QDF_STATUS_E_FAILURE;
-			goto done;
-		}
-
-		lim_add_bcn_probe(session->vdev, gen_probe_rsp.ptr,
-				  gen_probe_rsp.len,
-				  mlo_roam_get_link_freq_from_mac_addr(
-					       roam_sync_ind, src_addr),
-				  roam_sync_ind->rssi);
-	}
-
-done:
-	qdf_mem_free(gen_probe_rsp.ptr);
-err1:
-	qdf_mem_free(probe_rsp);
-
-	if (QDF_IS_STATUS_ERROR(status)) {
-		rcvd_frame.vdev_id = roam_sync_ind->roamed_vdev_id;
-		rcvd_frame.frame = frame.ptr;
-		rcvd_frame.frame_length = frame.len;
-		rcvd_frame.rssi = roam_sync_ind->rssi;
-		status = mlo_add_all_link_probe_rsp_to_scan_db(mac_ctx->psoc,
-							       &rcvd_frame);
-	}
-	return status;
-}
-
 QDF_STATUS
 lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 			     struct pe_session *session,