Browse Source

qcacmn: Update Priority access ML IE parsing

Update Priority access ML IE processing with below.
1. Check for ie header before updating sub elements
2. Add WME vendor IE parsing support

Change-Id: If479f95517946511d5e94feadf92a10c61efd2a6
CRs-Fixed: 3508861
Venkateswara Swamy Bandaru 2 years ago
parent
commit
2a20dc67d1
2 changed files with 112 additions and 10 deletions
  1. 11 1
      umac/mlo_mgr/inc/wlan_mlo_epcs.h
  2. 101 9
      umac/mlo_mgr/src/utils_mlo.c

+ 11 - 1
umac/mlo_mgr/inc/wlan_mlo_epcs.h

@@ -49,12 +49,22 @@ enum wlan_epcs_category {
 /**
 /**
  * struct ml_pa_partner_link_info - Priority Access ML partner information
  * struct ml_pa_partner_link_info - Priority Access ML partner information
  * @link_id: Link ID
  * @link_id: Link ID
+ * @edca_ie_present: EDCA IE present
+ * @muedca_ie_present: MU EDCA IE present
+ * @ven_wme_ie_present: WME IE present
  * @edca: EDCA IE
  * @edca: EDCA IE
  * @muedca: MU EDCA IE
  * @muedca: MU EDCA IE
+ * @ven_wme_ie_bytes: WME IE
  */
  */
 struct ml_pa_partner_link_info {
 struct ml_pa_partner_link_info {
 	uint8_t link_id;
 	uint8_t link_id;
-	struct edca_ie edca;
+	uint8_t edca_ie_present:1,
+		muedca_ie_present:1,
+		ven_wme_ie_present:1;
+	union {
+		struct edca_ie edca;
+		uint8_t ven_wme_ie_bytes[WLAN_VENDOR_WME_IE_LEN + 2];
+	};
 	struct muedca_ie muedca;
 	struct muedca_ie muedca;
 };
 };
 
 

+ 101 - 9
umac/mlo_mgr/src/utils_mlo.c

@@ -4762,6 +4762,8 @@ util_parse_pamlie_perstaprofile_stactrl(uint8_t *subelempayload,
 {
 {
 	qdf_size_t parsed_payload_len = 0;
 	qdf_size_t parsed_payload_len = 0;
 	uint16_t stacontrol;
 	uint16_t stacontrol;
+	struct ie_header *ie;
+	struct extn_ie_header *extn_ie;
 
 
 	/* This helper returns the location(s) and where required, the length(s)
 	/* This helper returns the location(s) and where required, the length(s)
 	 * of (sub)field(s) inferable after parsing the STA Control field in the
 	 * of (sub)field(s) inferable after parsing the STA Control field in the
@@ -4817,18 +4819,108 @@ util_parse_pamlie_perstaprofile_stactrl(uint8_t *subelempayload,
 		return QDF_STATUS_E_PROTO;
 		return QDF_STATUS_E_PROTO;
 	}
 	}
 
 
-	qdf_mem_copy(&pa_link_info->edca, subelempayload,
-		     sizeof(struct edca_ie));
-	subelempayload += sizeof(struct edca_ie);
-	parsed_payload_len += sizeof(struct edca_ie);
+	pa_link_info->edca_ie_present = false;
+	pa_link_info->ven_wme_ie_present = false;
+	pa_link_info->muedca_ie_present = false;
 
 
-	qdf_mem_copy(&pa_link_info->muedca, subelempayload,
-		     sizeof(struct muedca_ie));
-	subelempayload += sizeof(struct muedca_ie);
-	parsed_payload_len += sizeof(struct muedca_ie);
+	do {
+		if (subelempayloadlen <
+			(parsed_payload_len +
+			sizeof(struct ie_header))) {
+			mlo_err_rl("Length of subelement payload %zu octets not sufficient to contain min ie length %zu after parsed payload length of %zu octets",
+				   subelempayloadlen,
+				   sizeof(struct ie_header),
+				   parsed_payload_len);
+			return QDF_STATUS_E_PROTO;
+		}
+
+		ie = (struct ie_header *)subelempayload;
+
+		if (subelempayloadlen <
+			(parsed_payload_len +
+			(sizeof(struct ie_header) + ie->ie_len))) {
+			mlo_err_rl("Length of subelement payload %zu octets not sufficient to contain ie length %zu after parsed payload length of %zu octets",
+				   subelempayloadlen,
+				   sizeof(struct ie_header) + ie->ie_len,
+				   parsed_payload_len);
+			return QDF_STATUS_E_PROTO;
+		}
+
+		switch (ie->ie_id) {
+		case WLAN_ELEMID_EDCAPARMS:
+			if (pa_link_info->ven_wme_ie_present) {
+				/* WME parameters already present
+				 * use that one instead of EDCA */
+				break;
+			}
+			if (ie->ie_len == (sizeof(struct edca_ie) -
+			    sizeof(struct ie_header))) {
+				pa_link_info->edca_ie_present = true;
+				qdf_mem_copy(&pa_link_info->edca,
+					     subelempayload,
+					     sizeof(struct edca_ie));
+			} else {
+				epcs_debug("Invalid edca length %d in PAV IE",
+					   ie->ie_len);
+			}
+			break;
+		case WLAN_ELEMID_VENDOR:
+			if (is_wme_param((uint8_t *)ie) &&
+			    (ie->ie_len == WLAN_VENDOR_WME_IE_LEN)) {
+				pa_link_info->ven_wme_ie_present = true;
+				qdf_mem_copy(&pa_link_info->ven_wme_ie_bytes,
+					     subelempayload,
+					     sizeof(WLAN_VENDOR_WME_IE_LEN +
+						    sizeof(struct ie_header)));
+				pa_link_info->edca_ie_present = false;
+			} else {
+				epcs_debug("Unrelated Venfor IE reecived ie_id %d ie_len %d",
+					   ie->ie_id,
+					   ie->ie_len);
+			}
+			break;
+		case WLAN_ELEMID_EXTN_ELEM:
+			extn_ie = (struct extn_ie_header *)ie;
+			switch (extn_ie->ie_extn_id) {
+			case WLAN_EXTN_ELEMID_MUEDCA:
+				if (extn_ie->ie_len == WLAN_MAX_MUEDCA_IE_LEN) {
+					pa_link_info->muedca_ie_present = true;
+					qdf_mem_copy(&pa_link_info->muedca,
+						     subelempayload,
+						     sizeof(struct muedca_ie));
+				} else {
+					epcs_debug("Invalid muedca length %d in PAV IE",
+						   ie->ie_len);
+				}
+				break;
+			default:
+				epcs_debug("Unrelated Extn IE reecived ie_id %d ie_len %d extid %d IN PAV IE",
+					   ie->ie_id,
+					   ie->ie_len,
+					   extn_ie->ie_extn_id);
+				break;
+			}
+			break;
+		default:
+			epcs_debug("Unrelated IE reecived ie_id %d ie_len %d in PAV IE",
+				   ie->ie_id,
+				   ie->ie_len);
+			break;
+		}
+		subelempayload += ie->ie_len + sizeof(struct ie_header);
+		parsed_payload_len += ie->ie_len + sizeof(struct ie_header);
+	} while (parsed_payload_len < subelempayloadlen);
 
 
 	if (parsed_payload_len != subelempayloadlen)
 	if (parsed_payload_len != subelempayloadlen)
-		epcs_debug("Error in processing per sta profile of PA ML IE %zu %zu", parsed_payload_len, subelempayloadlen);
+		epcs_debug("Error in processing per sta profile of PA ML IE %zu %zu",
+			   parsed_payload_len,
+			   subelempayloadlen);
+
+	epcs_debug("Link id %d presence of edca %d muedca %d wme %d",
+		   pa_link_info->link_id,
+		   pa_link_info->edca_ie_present,
+		   pa_link_info->muedca_ie_present,
+		   pa_link_info->ven_wme_ie_present);
 
 
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }