Переглянути джерело

qcacmn: parse RNR IE about MLD params for MBSSID feature

In order to reconstruct frame for MBSSID feature, per the description of
the Reduced Neighbor Report(RNR) element about MLD parameters subfield
in section 9.4.2.170 of Draft P802.11be_D1.4, the RNR IE is modified:
1\ If the reported AP is affiliated with the same MLD of the reporting AP,
the TBTT information is skipped;
2\ If the reported AP is affiliated with the same MLD of the nontransmitted
BSSID, the TBTT information is copied and the MLD ID is changed to 0.

Change-Id: Ibd4f2af28289bdb2f65c26966a92ea4df530fccb
CRs-Fixed: 3136398
Paul Zhang 3 роки тому
батько
коміт
d5a23f4cb1
1 змінених файлів з 164 додано та 3 видалено
  1. 164 3
      umac/scan/dispatcher/src/wlan_scan_utils_api.c

+ 164 - 3
umac/scan/dispatcher/src/wlan_scan_utils_api.c

@@ -2373,9 +2373,163 @@ static void util_parse_noninheritance_list(uint8_t *extn_elem,
 	}
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * util_handle_rnr_ie_for_mbssid() - parse and modify RNR IE for MBSSID feature
+ * @rnr: The pointer to RNR IE
+ * @bssid_index: BSSID index from MBSSID index IE
+ * @pos: The buffer pointer to save the transformed RNR IE, caller is expected
+ *       to supply a buffer that is at least as big as @rnr
+ *
+ * Per the description about Neighbor AP Information field about MLD
+ * parameters subfield in section 9.4.2.170.2 of Draft P802.11be_D1.4.
+ * If the reported AP is affiliated with the same MLD of the reporting AP,
+ * the TBTT information is skipped; If the reported AP is affiliated with
+ * the same MLD of the nontransmitted BSSID, the TBTT information is
+ * copied and the MLD ID is changed to 0.
+ *
+ * Return: Length of the element written to @pos
+ */
+static int util_handle_rnr_ie_for_mbssid(const uint8_t *rnr,
+					 uint8_t bssid_index, uint8_t *pos)
+{
+	size_t rnr_len;
+	const uint8_t *data, *rnr_end;
+	uint8_t *rnr_new;
+	struct neighbor_ap_info_field *neighbor_ap_info;
+	struct rnr_mld_info *mld_param;
+	uint8_t tbtt_type, tbtt_len, tbtt_count;
+	uint8_t mld_pos, mld_id;
+	int32_t i, copy_len;
+	/* The count of TBTT info field whose MLD ID equals to 0 in a neighbor
+	 * AP information field.
+	 */
+	uint32_t tbtt_info_field_count;
+	/* The total bytes of TBTT info fields whose MLD ID equals to 0 in
+	 * current RNR IE.
+	 */
+	uint32_t tbtt_info_field_len = 0;
+	uint8_t nbr_ap_info_len = sizeof(struct neighbor_ap_info_field);
+
+	rnr_len = rnr[TAG_LEN_POS];
+	rnr_end = rnr + rnr_len + MIN_IE_LEN;
+	rnr_new = pos;
+	qdf_mem_copy(pos, rnr, MIN_IE_LEN);
+	pos += MIN_IE_LEN;
+
+	data = rnr + PAYLOAD_START_POS;
+	while (data < rnr_end) {
+		neighbor_ap_info = (struct neighbor_ap_info_field *)data;
+		tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count;
+		tbtt_len = neighbor_ap_info->tbtt_header.tbtt_info_length;
+		tbtt_type = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype;
+		scm_debug("channel number %d, op class %d, bssid_index %d",
+			  neighbor_ap_info->channel_number,
+			  neighbor_ap_info->operting_class, bssid_index);
+		scm_debug("tbtt_count %d, tbtt_length %d, tbtt_type %d",
+			  tbtt_count, tbtt_len, tbtt_type);
+
+		copy_len = tbtt_len * (tbtt_count + 1) +
+			   nbr_ap_info_len;
+		if (data + copy_len > rnr_end)
+			return 0;
+
+		if (tbtt_len >=
+		    TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM)
+			mld_pos =
+			     TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD;
+		else
+			mld_pos = 0;
+
+		/* If MLD params do not exist, copy this neighbor AP
+		 * information field.
+		 * Per Draft P802.11be_D1.4, tbtt_type value 1, 2 and 3
+		 * are reserved,
+		 */
+		if (mld_pos == 0 || tbtt_type != 0) {
+			scm_debug("no MLD params, tbtt_type %d", tbtt_type);
+			qdf_mem_copy(pos, data, copy_len);
+			pos += copy_len;
+			data += copy_len;
+			continue;
+		}
+
+		qdf_mem_copy(pos, data, nbr_ap_info_len);
+		neighbor_ap_info = (struct neighbor_ap_info_field *)pos;
+		pos += nbr_ap_info_len;
+		data += nbr_ap_info_len;
+
+		tbtt_info_field_count = 0;
+		for (i = 0; i < tbtt_count + 1; i++) {
+			mld_param = (struct rnr_mld_info *)&data[mld_pos];
+			mld_id = mld_param->mld_id;
+
+			/* Refer to Draft P802.11be_D1.4
+			 * 9.4.2.170.2 Neighbor AP Information field about
+			 * MLD parameters subfield
+			 */
+			if (mld_id == 0) {
+				/* Skip this TBTT information since this
+				 * reported AP is affiliated with the same MLD
+				 * of the reporting AP who sending the frame
+				 * carrying this element.
+				 */
+				tbtt_info_field_len += tbtt_len;
+				data += tbtt_len;
+				tbtt_info_field_count++;
+			} else if (mld_id == bssid_index) {
+				/* Copy this TBTT information and change MLD
+				 * to 0 as this reported AP is affiliated with
+				 * the same MLD of the nontransmitted BSSID.
+				 */
+				qdf_mem_copy(pos, data, tbtt_len);
+				mld_param =
+					(struct rnr_mld_info *)&pos[mld_pos];
+				scm_debug("change MLD ID from %d to 0",
+					  mld_param->mld_id);
+				mld_param->mld_id = 0;
+				data += tbtt_len;
+				pos += tbtt_len;
+			} else {
+				qdf_mem_copy(pos, data, tbtt_len);
+				data += tbtt_len;
+				pos += tbtt_len;
+			}
+		}
+
+		scm_debug("skip %d neighbor info", tbtt_info_field_count);
+		if (tbtt_info_field_count == (tbtt_count + 1)) {
+			/* If all the TBTT information are skipped, then also
+			 * revert the neighbor AP info which has been copied.
+			 */
+			pos -= nbr_ap_info_len;
+			tbtt_info_field_len += nbr_ap_info_len;
+		} else {
+			neighbor_ap_info->tbtt_header.tbtt_info_count -=
+							tbtt_info_field_count;
+		}
+	}
+
+	rnr_new[TAG_LEN_POS] = rnr_len - tbtt_info_field_len;
+	if (rnr_new[TAG_LEN_POS] > 0)
+		rnr_len = rnr_new[TAG_LEN_POS] + MIN_IE_LEN;
+	else
+		rnr_len = 0;
+
+	return rnr_len;
+}
+#else
+static int util_handle_rnr_ie_for_mbssid(const uint8_t *rnr,
+					 uint8_t bssid_index, uint8_t *pos)
+{
+	return 0;
+}
+#endif
+
 static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
 				uint8_t *subelement,
-				size_t subie_len, uint8_t *new_ie)
+				size_t subie_len, uint8_t *new_ie,
+				uint8_t bssid_index)
 {
 	uint8_t *pos, *tmp;
 	const uint8_t *tmp_old, *tmp_new;
@@ -2450,7 +2604,13 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
 						   subie_len);
 		if (!tmp) {
 			/* ie in old ie but not in subelement */
-			if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) {
+			if (tmp_old[0] == WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT) {
+				/* handle rnr ie for mbssid*/
+				pos +=
+				    util_handle_rnr_ie_for_mbssid(tmp_old,
+								  bssid_index,
+								  pos);
+			} else if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) {
 				if ((pos + tmp_old[1] + MIN_IE_LEN) <=
 				    (new_ie + ielen)) {
 					qdf_mem_copy(pos, tmp_old,
@@ -2901,7 +3061,8 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
 				util_gen_new_ie(ie, ielen,
 						(nontx_profile +
 						 PAYLOAD_START_POS),
-						subie_len, new_ie);
+						subie_len, new_ie,
+						mbssid_info.profile_num);
 
 			if (!new_ie_len) {
 				if (mbssid_info.split_prof_continue) {