Browse Source

qcacmn: Add API to get link ID from Basic Variant ML element

Add API to get the link identifier from a given Basic variant
Multi-Link element or element fragment sequence, of the AP that
transmits the Multi-Link element/element fragment sequence or the
nontransmitted BSSID in the same multiple BSSID set as the AP that
transmits the Multi-Link element/element fragment sequence and that is
affiliated with the MLD that is described in the Multi-Link element.

Change-Id: I45039a6ed8ccd9403eae9514c60bcd8d694d2a31
CRs-Fixed: 3040407
Krishna Rao 3 years ago
parent
commit
5f1d4dd7fb
2 changed files with 100 additions and 0 deletions
  1. 34 0
      umac/mlo_mgr/inc/utils_mlo.h
  2. 66 0
      umac/mlo_mgr/src/utils_mlo.c

+ 34 - 0
umac/mlo_mgr/inc/utils_mlo.h

@@ -116,6 +116,33 @@ QDF_STATUS
 util_get_bvmlie_mldmacaddr(uint8_t *mlieseq, qdf_size_t mlieseqlen,
 util_get_bvmlie_mldmacaddr(uint8_t *mlieseq, qdf_size_t mlieseqlen,
 			   bool *mldmacaddrfound,
 			   bool *mldmacaddrfound,
 			   struct qdf_mac_addr *mldmacaddr);
 			   struct qdf_mac_addr *mldmacaddr);
+
+/**
+ * util_get_bvmlie_primary_linkid - Get the link identifier from a given Basic
+ * variant Multi-Link element or element fragment sequence, of the AP that
+ * transmits the Multi-Link element/element fragment sequence or the
+ * nontransmitted BSSID in the same multiple BSSID set as the AP that transmits
+ * the Multi-Link element/element fragment sequence and that is affiliated with
+ * the MLD that is described in the Multi-Link element.
+ *
+ * @mlieseq: Starting address of the Multi-Link element or Multi-Link element
+ * fragment sequence
+ * @mlieseqlen: Total length of the Multi-Link element or Multi-Link element
+ * fragment sequence
+ * @linkidfound: Pointer to the location where a boolean status should be
+ * updated indicating whether the link identifier was found or not. This should
+ * be ignored by the caller if the function returns error.
+ * @linkid: Pointer to the location where the value of the link identifier
+ * should be updated. This should be ignored by the caller if the function
+ * returns error, or if the function indicates that the link identifier was not
+ * found.
+ *
+ * Return: QDF_STATUS_SUCCESS in the case of success, QDF_STATUS value giving
+ * the reason for error in the case of failure
+ */
+QDF_STATUS
+util_get_bvmlie_primary_linkid(uint8_t *mlieseq, qdf_size_t mlieseqlen,
+			       bool *linkidfound, uint8_t *linkid);
 #else
 #else
 static inline QDF_STATUS
 static inline QDF_STATUS
 util_gen_link_assoc_rsp(uint8_t *frame, qdf_size_t len,
 util_gen_link_assoc_rsp(uint8_t *frame, qdf_size_t len,
@@ -145,5 +172,12 @@ util_get_bvmlie_mldmacaddr(uint8_t *mlieseq, qdf_size_t mlieseqlen,
 {
 {
 	return QDF_STATUS_E_NOSUPPORT;
 	return QDF_STATUS_E_NOSUPPORT;
 }
 }
+
+static inline QDF_STATUS
+util_get_bvmlie_primary_linkid(uint8_t *mlieseq, qdf_size_t mlieseqlen,
+			       bool *linkidfound, uint8_t *linkid)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
 #endif /* WLAN_FEATURE_11BE_MLO */
 #endif /* WLAN_FEATURE_11BE_MLO */
 #endif /* _WLAN_UTILS_MLO_H_ */
 #endif /* _WLAN_UTILS_MLO_H_ */

+ 66 - 0
umac/mlo_mgr/src/utils_mlo.c

@@ -558,4 +558,70 @@ util_get_bvmlie_mldmacaddr(uint8_t *mlieseq, qdf_size_t mlieseqlen,
 
 
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }
+
+QDF_STATUS
+util_get_bvmlie_primary_linkid(uint8_t *mlieseq, qdf_size_t mlieseqlen,
+			       bool *linkidfound, uint8_t *linkid)
+{
+	struct wlan_ie_multilink *mlie_fixed;
+	enum wlan_ml_variant variant;
+	uint16_t mlcontrol;
+	uint16_t presencebitmap;
+	uint8_t *commoninfo;
+	qdf_size_t commoninfolen;
+	uint8_t *linkidinfo;
+
+	if (!mlieseq || !mlieseqlen || !linkidfound || !linkid)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	*linkidfound = false;
+	*linkid = 0;
+
+	if (mlieseqlen < sizeof(struct wlan_ie_multilink))
+		return QDF_STATUS_E_INVAL;
+
+	mlie_fixed = (struct wlan_ie_multilink *)mlieseq;
+
+	if ((mlie_fixed->elem_id != WLAN_ELEMID_EXTN_ELEM) ||
+	    (mlie_fixed->elem_id_ext != WLAN_EXTN_ELEMID_MULTI_LINK))
+		return QDF_STATUS_E_INVAL;
+
+	mlcontrol = le16toh(mlie_fixed->mlcontrol);
+
+	variant = QDF_GET_BITS(mlcontrol, WLAN_ML_CTRL_TYPE_IDX,
+			       WLAN_ML_CTRL_TYPE_BITS);
+
+	if (variant != WLAN_ML_VARIANT_BASIC)
+		return QDF_STATUS_E_INVAL;
+
+	presencebitmap = QDF_GET_BITS(mlcontrol, WLAN_ML_CTRL_PBM_IDX,
+				      WLAN_ML_CTRL_PBM_BITS);
+
+	commoninfo = mlieseq + sizeof(struct wlan_ie_multilink);
+	commoninfolen = 0;
+
+	if (presencebitmap & WLAN_ML_BV_CTRL_PBM_MLDMACADDR_P) {
+		commoninfolen += QDF_MAC_ADDR_SIZE;
+
+		if ((sizeof(struct wlan_ie_multilink) + commoninfolen) >
+				mlieseqlen)
+			return QDF_STATUS_E_PROTO;
+	}
+
+	if (presencebitmap & WLAN_ML_BV_CTRL_PBM_LINKIDINFO_P) {
+		linkidinfo = commoninfo + commoninfolen;
+		commoninfolen += WLAN_ML_BV_CINFO_LINKIDINFO_SIZE;
+
+		if ((sizeof(struct wlan_ie_multilink) + commoninfolen) >
+				mlieseqlen)
+			return QDF_STATUS_E_PROTO;
+
+		*linkidfound = true;
+		*linkid = QDF_GET_BITS(linkidinfo[0],
+				       WLAN_ML_BV_CINFO_LINKIDINFO_LINKID_IDX,
+				       WLAN_ML_BV_CINFO_LINKIDINFO_LINKID_BITS);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 #endif