Parcourir la source

qcacmn: Add support to RNR and multi link IE parsing for ML scoring

Add support to parse RNS and ML IE and fill ml info in the scan
cache entry.

Change-Id: Ia5fdd0310e20d4435343f0535c071ea3d8510ef8
CRs-Fixed: 2961893
Bapiraju Alla il y a 4 ans
Parent
commit
561025df10

+ 4 - 0
umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h

@@ -470,6 +470,7 @@ enum element_ie {
  * @WLAN_EXTN_ELEMID_HE_6G_CAP: HE 6GHz Band Capabilities IE
  * @WLAN_EXTN_ELEMID_SRP:    spatial reuse parameter IE
  * @WLAN_EXTN_ELEMID_NONINHERITANCE: Non inheritance IE
+ * @WLAN_EXTN_ELEMID_MULTI_LINK: Multi link IE
  * @WLAN_EXTN_ELEMID_EHTCAP: EHT Capabilities IE
  * @WLAN_EXTN_ELEMID_EHTOP: EHT Operation IE
  */
@@ -482,6 +483,9 @@ enum extn_element_ie {
 	WLAN_EXTN_ELEMID_NONINHERITANCE = 56,
 	WLAN_EXTN_ELEMID_HE_6G_CAP   = 59,
 	WLAN_EXTN_ELEMID_ESP         = 11,
+#ifdef WLAN_FEATURE_11BE_MLO
+	WLAN_EXTN_ELEMID_MULTI_LINK  = 252,
+#endif
 #ifdef WLAN_FEATURE_11BE
 	WLAN_EXTN_ELEMID_EHTCAP      = 253,
 	WLAN_EXTN_ELEMID_EHTOP       = 254,

+ 30 - 1
umac/scan/dispatcher/inc/wlan_scan_public_structs.h

@@ -184,6 +184,7 @@ struct channel_info {
  * @rsnxe: Pointer to rsnxe IE
  * @ehtcap: pointer to ehtcap ie
  * @ehtop: pointer to eht op ie
+ * @multi_link: pointer to multi lik IE
  */
 struct ie_list {
 	uint8_t *tim;
@@ -242,6 +243,9 @@ struct ie_list {
 	uint8_t *ehtcap;
 	uint8_t *ehtop;
 #endif
+#ifdef WLAN_FEATURE_11BE_MLO
+	uint8_t *multi_link;
+#endif
 };
 
 enum scan_entry_connection_state {
@@ -373,6 +377,20 @@ struct non_inheritance_ie {
 	bool non_inh_ie_found;
 };
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * struct rnr_mld_info - Reduced Neighbor Report MLD information
+ * @mld_id: MLD ID
+ * @link_id: Link ID
+ * @bss_param_change_cnt: BSS parameters change count
+ */
+struct rnr_mld_info {
+	uint8_t mld_id;
+	uint16_t link_id: 4,
+		 bss_param_change_cnt: 8,
+		 reserved: 4;
+};
+#endif
 /**
  * struct rnr_bss_info - Reduced Neighbor Report BSS information
  * @neighbor_ap_tbtt_offset: Neighbor AP TBTT offset
@@ -382,6 +400,7 @@ struct non_inheritance_ie {
  * @short_ssid: short ssid
  * @bss_params: BSS parameters
  * @psd_20mhz: 20MHz power spectral density
+ * @mld_info: MLD information
  */
 struct rnr_bss_info {
 	uint8_t neighbor_ap_tbtt_offset;
@@ -391,6 +410,9 @@ struct rnr_bss_info {
 	uint32_t short_ssid;
 	uint8_t bss_params;
 	uint8_t psd_20mhz;
+#ifdef WLAN_FEATURE_11BE_MLO
+	struct rnr_mld_info mld_info;
+#endif
 };
 
 /**
@@ -424,29 +446,36 @@ struct neighbor_ap_info_field {
  * enum tbtt_information_field - TBTT information field
  * @TBTT_NEIGHBOR_AP_OFFSET_ONLY: TBTT information field type
  * @TBTT_NEIGHBOR_AP_BSS_PARAM: neighbor AP and bss param
+ * @TBTT_NEIGHBOR_AP_MLD_PARAM: neighbor AP and MLD param
  * @TBTT_NEIGHBOR_AP_SHORTSSID: neighbor AP and Short ssid
  * @TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM: neighbor AP, short ssid and bss param
  * @TBTT_NEIGHBOR_AP_BSSID: neighbor AP and bssid
  * @TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM: neighbor AP, bssid and bss param
  * @TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM_20MHZ_PSD: neighbor AP, bssid and bss
  * param and 20MHz PSD
+ * @TBTT_NEIGHBOR_AP_BSSID_MLD_PARAM:  neighbor AP, bssid and MLD param
  * @TBTT_NEIGHBOR_AP_BSSSID_S_SSID: neighbor AP, bssid and short ssid
  * @TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM: neighbor AP, bssid, short ssid
  * and bss params
  * @TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD: neighbor AP, bssid,
  * short ssid, bss params and 20MHz PSD
+ * @TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM: neighbor AP,
+ * bssid, short ssid, bss params, 20MHz PSD and MLD param
  */
 enum tbtt_information_field {
 	TBTT_NEIGHBOR_AP_OFFSET_ONLY = 1,
 	TBTT_NEIGHBOR_AP_BSS_PARAM = 2,
+	TBTT_NEIGHBOR_AP_MLD_PARAM = 4,
 	TBTT_NEIGHBOR_AP_SHORTSSID = 5,
 	TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM = 6,
 	TBTT_NEIGHBOR_AP_BSSID = 7,
 	TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM = 8,
 	TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM_20MHZ_PSD = 9,
+	TBTT_NEIGHBOR_AP_BSSID_MLD_PARAM = 10,
 	TBTT_NEIGHBOR_AP_BSSSID_S_SSID = 11,
 	TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM = 12,
-	TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD = 13
+	TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD = 13,
+	TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM = 16
 };
 
 /**

+ 14 - 0
umac/scan/dispatcher/inc/wlan_scan_utils_api.h

@@ -615,6 +615,18 @@ util_scan_entry_copy_ie_data(struct scan_cache_entry *scan_entry,
 	return QDF_STATUS_E_NOMEM;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+static inline void util_scan_free_ml_info(struct scan_cache_entry *scan_entry)
+{
+	if (scan_entry->ml_info)
+		qdf_mem_free(scan_entry->ml_info);
+}
+#else
+static inline void util_scan_free_ml_info(struct scan_cache_entry *scan_entry)
+{
+}
+#endif
+
 /**
  * util_scan_free_cache_entry() - function to free scan
  * cache entry
@@ -633,6 +645,8 @@ util_scan_free_cache_entry(struct scan_cache_entry *scan_entry)
 		qdf_mem_free(scan_entry->alt_wcn_ie.ptr);
 	if (scan_entry->raw_frame.ptr)
 		qdf_mem_free(scan_entry->raw_frame.ptr);
+
+	util_scan_free_ml_info(scan_entry);
 	qdf_mem_free(scan_entry);
 }
 

+ 189 - 1
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -729,6 +729,58 @@ util_scan_is_hidden_ssid(struct ie_ssid *ssid)
 	return true;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+static void
+util_scan_update_rnr_mld(struct rnr_bss_info *rnr,
+			 struct neighbor_ap_info_field *ap_info, uint8_t *data)
+{
+	uint8_t tbtt_info_length;
+	bool mld_info_present = false;
+
+	tbtt_info_length = ap_info->tbtt_header.tbtt_info_length;
+	if (tbtt_info_length >=
+		TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM)
+		tbtt_info_length =
+		   TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM;
+
+	switch (tbtt_info_length) {
+	case TBTT_NEIGHBOR_AP_MLD_PARAM:
+		rnr->channel_number = ap_info->channel_number;
+		rnr->operating_class = ap_info->operting_class;
+		qdf_mem_copy(&rnr->mld_info, &data[1],
+			     sizeof(struct rnr_mld_info));
+		mld_info_present = true;
+		break;
+	case TBTT_NEIGHBOR_AP_BSSID_MLD_PARAM:
+		rnr->channel_number = ap_info->channel_number;
+		rnr->operating_class = ap_info->operting_class;
+		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
+		qdf_mem_copy(&rnr->mld_info, &data[1 + QDF_MAC_ADDR_SIZE],
+			     sizeof(struct rnr_mld_info));
+		mld_info_present = true;
+		break;
+	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM:
+		rnr->channel_number = ap_info->channel_number;
+		rnr->operating_class = ap_info->operting_class;
+		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
+		qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
+		rnr->bss_params = data[11];
+		rnr->psd_20mhz = data[12];
+		qdf_mem_copy(&rnr->mld_info, &data[13],
+			     sizeof(struct rnr_mld_info));
+		mld_info_present = true;
+		break;
+	};
+}
+#else
+static void
+util_scan_update_rnr_mld(struct rnr_bss_info *rnr,
+			 struct neighbor_ap_info_field *ap_info, uint8_t *data)
+{
+	scm_debug("Wrong fieldtype");
+}
+#endif
+
 static QDF_STATUS
 util_scan_update_rnr(struct rnr_bss_info *rnr,
 		     struct neighbor_ap_info_field *ap_info,
@@ -806,7 +858,7 @@ util_scan_update_rnr(struct rnr_bss_info *rnr,
 		break;
 
 	default:
-		scm_debug("Wrong fieldtype");
+		util_scan_update_rnr_mld(rnr, ap_info, data);
 	}
 
 	return QDF_STATUS_SUCCESS;
@@ -853,6 +905,25 @@ util_scan_parse_rnr_ie(struct scan_cache_entry *scan_entry,
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params,
+				   struct extn_ie_header *extn_ie)
+{
+	switch (extn_ie->ie_extn_id) {
+	case WLAN_EXTN_ELEMID_MULTI_LINK:
+		scan_params->ie_list.multi_link = (uint8_t *)extn_ie;
+		break;
+	default:
+		break;
+	}
+}
+#else
+static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params,
+				   struct extn_ie_header *extn_ie)
+{
+}
+#endif
+
 static QDF_STATUS
 util_scan_parse_extn_ie(struct scan_cache_entry *scan_params,
 	struct ie_header *ie)
@@ -902,6 +973,8 @@ util_scan_parse_extn_ie(struct scan_cache_entry *scan_params,
 	default:
 		break;
 	}
+	util_scan_parse_eht_ie(scan_params, extn_ie);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -1679,6 +1752,119 @@ static void util_scan_set_security(struct scan_cache_entry *scan_params)
 		scan_params->security_type |= SCAN_SECURITY_TYPE_WEP;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * Multi link IE field offsets
+ *  ------------------------------------------------------------------------
+ * | EID(1) | Len (1) | EID_EXT (1) | ML_CONTROL (2) | CMN_INFO (var) | ... |
+ *  ------------------------------------------------------------------------
+ */
+#define ML_CONTROL_OFFSET 3
+#define ML_CMN_INFO_OFFSET ML_CONTROL_OFFSET + 2
+
+#define CMN_INFO_MLD_ADDR_PRESENT_BIT     BIT(0)
+#define CMN_INFO_LINK_ID_PRESENT_BIT      BIT(1)
+#define LINK_INFO_MAC_ADDR_PRESENT_BIT    BIT(5)
+
+static uint8_t util_get_link_info_offset(uint8_t *ml_ie)
+{
+	uint8_t offset = ML_CMN_INFO_OFFSET;
+	uint8_t ml_ie_len = ml_ie[1];
+	uint16_t multi_link_ctrl = *(uint16_t *)(ml_ie + ML_CONTROL_OFFSET);
+
+	offset += (BIT(0) & multi_link_ctrl) * 6 +
+		  (BIT(1) & multi_link_ctrl) * 1 +
+		  (BIT(2) & multi_link_ctrl) * 1 +
+		  (BIT(3) & multi_link_ctrl) * 2 +
+		  (BIT(4) & multi_link_ctrl) * 2 +
+		  (BIT(5) & multi_link_ctrl) * 2;
+
+	if (offset < ml_ie_len)
+		return offset;
+
+	return 0;
+}
+
+static void util_get_partner_link_info(struct scan_cache_entry *scan_entry)
+{
+	uint8_t *ml_ie = scan_entry->ie_list.multi_link;
+	uint8_t offset = util_get_link_info_offset(ml_ie);
+	uint16_t sta_ctrl;
+
+	if (!offset) {
+		scm_err("Per STA profile is not present in the ML_IE ");
+		return;
+	}
+	/* TODO: loop through all the STA info fields */
+
+	/* Sub element ID 0 represents Per-STA Profile */
+	if (ml_ie[offset] == 0) {
+		/* Skip sub element ID and length fields */
+		offset += 2;
+		sta_ctrl = *(uint16_t *)(ml_ie + offset);
+		/* Skip STA control field */
+		offset += 2;
+
+		scan_entry->ml_info->link_info[1].link_id =
+						ml_ie[offset] & 0xF;
+		if (sta_ctrl & LINK_INFO_MAC_ADDR_PRESENT_BIT) {
+			qdf_mem_copy(
+				&scan_entry->ml_info->link_info[1].link_addr,
+				ml_ie + offset, 6);
+			scm_debug("Found partner info in ML IE");
+			return;
+		}
+	}
+
+	qdf_mem_copy(&scan_entry->ml_info->link_info[1].link_addr,
+		     &scan_entry->rnr.bss_info[0].bssid, 6);
+
+	scan_entry->ml_info->link_info[1].link_id =
+				scan_entry->rnr.bss_info[0].mld_info.link_id;
+}
+
+static void util_scan_update_ml_info(struct scan_cache_entry *scan_entry)
+{
+	uint8_t *ml_ie = scan_entry->ie_list.multi_link;
+	uint16_t multi_link_ctrl = *(uint16_t *)(ml_ie + ML_CONTROL_OFFSET);
+	uint8_t offset;
+
+	if (!scan_entry->ie_list.multi_link)
+		return;
+
+	scan_entry->ml_info = qdf_mem_malloc_atomic(
+					sizeof(*scan_entry->ml_info));
+	/* TODO: update ml_info based on ML IE */
+
+	offset = ML_CMN_INFO_OFFSET;
+	/* TODO: Add proper parsing based on presense bitmap */
+	if (multi_link_ctrl & CMN_INFO_MLD_ADDR_PRESENT_BIT) {
+		qdf_mem_copy(&scan_entry->ml_info->mld_mac_addr,
+			     ml_ie + offset, 6);
+		offset += 6;
+	}
+
+	/* TODO: Decode it from ML IE */
+	scan_entry->ml_info->num_links = 2;
+
+	/**
+	 * Copy Link ID & MAC address of the scan cache entry as first entry
+	 * in the partner info list
+	 */
+	if (multi_link_ctrl & CMN_INFO_LINK_ID_PRESENT_BIT)
+		scan_entry->ml_info->link_info[0].link_id = ml_ie[offset];
+
+	qdf_mem_copy(&scan_entry->ml_info->link_info[0].link_addr,
+		     &scan_entry->mac_addr, 6);
+
+	util_get_partner_link_info(scan_entry);
+}
+#else
+static void util_scan_update_ml_info(struct scan_cache_entry *scan_entry)
+{
+}
+#endif
+
 static QDF_STATUS
 util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
 			 uint8_t *frame, qdf_size_t frame_len,
@@ -1854,6 +2040,8 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	util_scan_update_ml_info(scan_entry);
+
 	scan_node->entry = scan_entry;
 	qdf_list_insert_front(scan_list, &scan_node->node);