فهرست منبع

qcacmn: Introduce API to modify MAC address in action frame

Introduce two APIs which will change the RA, DA and BSSID fields
of 802.11 MAC header.

For any non-public action frame, supplicant will send RA, DA and BSSID
with MLD address which needs to be translated to link addresses to
transmit over the air. wlan_mlo_update_action_frame_from_user() API
will do the address translation from MLD to link.

If any non-public action frame is received over the air that needs
to be sent to userspace, the kernel expects MLD address in RA, DA
and BSSID fields. wlan_mlo_update_action_frame_to_user() API will
do the address translation from link to MLD.

Change-Id: Iab93dd1301003b78edf6d619cfbf552afa53ae7a
CRs-Fixed: 3394706
Vinod Kumar Pirla 2 سال پیش
والد
کامیت
cad19e4fc7
2فایلهای تغییر یافته به همراه162 افزوده شده و 0 حذف شده
  1. 50 0
      umac/mlo_mgr/inc/wlan_mlo_mgr_main.h
  2. 112 0
      umac/mlo_mgr/src/wlan_mlo_mgr_main.c

+ 50 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_main.h

@@ -918,6 +918,42 @@ QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
  */
 bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr,
 					  uint8_t *peer_vdev_id);
+
+/**
+ * wlan_mlo_update_action_frame_from_user() - Change MAC address in WLAN frame
+ * received from userspace.
+ * @vdev: VDEV objmgr pointer.
+ * @frame: Pointer to start of WLAN MAC frame.
+ * @frame_len: Length of the frame.
+ *
+ * The API will translate MLD address in the SA, DA, BSSID for the action
+ * frames received from userspace with link address to send over the air.
+ * The API will not modify if the frame is a Public Action category frame and
+ * for VDEV other then STA mode.
+ *
+ * Return: void
+ */
+void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev,
+					    uint8_t *frame,
+					    uint32_t frame_len);
+
+/**
+ * wlan_mlo_update_action_frame_to_user() - Change MAC address in WLAN frame
+ * received over the air.
+ * @vdev: VDEV objmgr pointer.
+ * @frame: Pointer to start of WLAN MAC frame.
+ * @frame_len: Length of the frame.
+ *
+ * The API will translate link address in the SA, DA, BSSID for the action
+ * frames received over the air with MLD address to send to userspace.
+ * The API will not modify if the frame is a Public Action category frame and
+ * for VDEV other then STA mode.
+ *
+ * Return: void
+ */
+void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev,
+					  uint8_t *frame,
+					  uint32_t frame_len);
 #else
 static inline QDF_STATUS wlan_mlo_mgr_init(void)
 {
@@ -943,6 +979,20 @@ bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr,
 	return false;
 }
 
+static inline
+void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev,
+					    uint8_t *frame,
+					    uint32_t frame_len)
+{
+}
+
+static inline
+void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev,
+					  uint8_t *frame,
+					  uint32_t frame_len)
+{
+}
+
 static inline
 uint8_t wlan_mlo_get_sta_mld_ctx_count(void)
 {

+ 112 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_main.c

@@ -382,6 +382,118 @@ g_ml_ref:
 	ml_link_lock_release(g_mlo_ctx);
 	return ret_status;
 }
+
+#define WLAN_HDD_MGMT_FRAME_DA_OFFSET 4
+#define WLAN_HDD_MGMT_FRAME_SA_OFFSET (WLAN_HDD_MGMT_FRAME_DA_OFFSET + 6)
+#define WLAN_HDD_MGMT_FRAME_BSSID_OFFSET (WLAN_HDD_MGMT_FRAME_SA_OFFSET + 6)
+#define WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET \
+				(WLAN_HDD_MGMT_FRAME_BSSID_OFFSET + 6 + 2)
+#define WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET \
+				(WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET + 1)
+#define WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC 0x04
+
+/*
+ * Typical 802.11 Action Frame Format
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+ * | FC | DUR |  DA  |   SA  | BSSID |Seq.|Cat.|Act|   Elements   | FCS |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+ *    2    2     6       6       6     2    1    1   Variable Len    4
+ */
+void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev,
+					    uint8_t *frame,
+					    uint32_t frame_len)
+{
+	struct wlan_objmgr_peer *peer;
+	uint8_t *da, *sa, *bssid;
+
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev) ||
+	    (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE))
+		return;
+
+	if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) {
+		mlo_debug("Not a valid Action frame len: %d", frame_len);
+		return;
+	}
+
+	/* Translate address only for action frames
+	 * which are not of public category.
+	 * Reference: 802.11-2012, Subclause: 8.5
+	 */
+
+	if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] ==
+				WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC)
+		return;
+
+	da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET;
+	sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET;
+	bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET;
+
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
+	if (!peer) {
+		mlo_debug("Peer not found");
+		return;
+	}
+
+	mlo_debug("Change MLD addr to link addr for non-Public action frame");
+	/* DA = VDEV's BSS peer's link address.
+	 * SA = VDEV's link address.
+	 * BSSID = VDEV's BSS peer's link address.
+	 */
+
+	qdf_ether_addr_copy(da, wlan_peer_get_macaddr(peer));
+	qdf_ether_addr_copy(sa, wlan_vdev_mlme_get_macaddr(vdev));
+	qdf_ether_addr_copy(bssid, wlan_peer_get_macaddr(peer));
+
+	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
+}
+
+void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev,
+					  uint8_t *frame,
+					  uint32_t frame_len)
+{
+	struct wlan_objmgr_peer *peer;
+	uint8_t *da, *sa, *bssid;
+
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev) ||
+	    (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE))
+		return;
+
+	if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) {
+		mlo_debug("Not a valid Action frame len: %d", frame_len);
+		return;
+	}
+
+	/* Translate address only for action frames
+	 * which are not of public category.
+	 * Reference: 802.11-2012, Subclause: 8.5
+	 */
+
+	if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] ==
+				WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC)
+		return;
+
+	da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET;
+	sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET;
+	bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET;
+
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
+	if (!peer) {
+		mlo_debug("Peer not found");
+		return;
+	}
+
+	mlo_debug("Change link addr to MLD addr for non-Public action frame");
+	/* DA = VDEV's MLD address.
+	 * SA = VDEV's BSS peer's MLD address.
+	 * BSSID = VDEV's BSS peer's MLD address.
+	 */
+
+	qdf_ether_addr_copy(da, wlan_vdev_mlme_get_mldaddr(vdev));
+	qdf_ether_addr_copy(sa, wlan_peer_mlme_get_mldaddr(peer));
+	qdf_ether_addr_copy(bssid, wlan_peer_mlme_get_mldaddr(peer));
+
+	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
+}
 #endif
 
 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev)