Ver código fonte

qcacmn: FT over DS association support

Add support for MLD MAC address table to MLD.
This MLD address table allows API to add/delete/find entries by MLD MAC
address. This framework would be used for implementing FT over DS,
where Assoc request is received by AP without receiving Auth request.

Change-Id: I3dbc4c0507f2113d2c0cc5e58f41d69243a4cfc8
CRs-Fixed: 3608944
Srinivas Pitla 1 ano atrás
pai
commit
f1bb50be1b

+ 37 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_peer.h

@@ -881,4 +881,41 @@ QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer);
  * Return: SUCCESS, if peer details deleted from WSI link stats
  */
 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer);
+
+/**
+ * wlan_mlo_ap_vdev_add_assoc_entry() - Add mlo ap vdev assoc entry
+ * @vdev: vdev object
+ * @mld_addr: MLD mac address
+ *
+ * API to add mlo ap vdev in assoc list
+ *
+ * Return: void
+ */
+void wlan_mlo_ap_vdev_add_assoc_entry(struct wlan_objmgr_vdev *vdev,
+				      struct qdf_mac_addr *mld_addr);
+
+/**
+ * wlan_mlo_ap_vdev_del_assoc_entry() - Delete mlo ap vdev assoc entry
+ * @vdev: vdev object
+ * @mld_addr: MLD mac address
+ *
+ * API to delete mlo ap vdev in assoc list
+ *
+ * Return: void
+ */
+void wlan_mlo_ap_vdev_del_assoc_entry(struct wlan_objmgr_vdev *vdev,
+				      struct qdf_mac_addr *mld_addr);
+
+/**
+ * wlan_mlo_ap_vdev_find_assoc_entry() - Find mlo ap vdev assoc entry
+ * @vdev: vdev object
+ * @mld_addr: MLD mac address
+ *
+ * API to find mlo ap vdev in assoc list
+ *
+ * Return: sta entry
+ */
+struct wlan_mlo_sta_entry *
+wlan_mlo_ap_vdev_find_assoc_entry(struct wlan_objmgr_vdev *vdev,
+				  struct qdf_mac_addr *mld_addr);
 #endif

+ 24 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -650,6 +650,16 @@ struct emlsr_capability {
 };
 #endif
 
+/**
+ * struct wlan_mlo_sta_assoc_pending_list - MLO sta assoc pending list entry
+ * @peer_list: MLO peer list
+ * @list_lock: lock to access members of structure
+ */
+struct wlan_mlo_sta_assoc_pending_list {
+	qdf_list_t peer_list;
+	qdf_spinlock_t list_lock;
+};
+
 /**
  * struct wlan_mlo_sta - MLO sta additional info
  * @wlan_connect_req_links: list of vdevs selected for connection with the MLAP
@@ -711,6 +721,7 @@ struct wlan_mlo_sta {
  * @mlo_ap_lock: lock to sync VDEV SM event
  * @mlo_vdev_quiet_bmap: Bitmap of vdevs for which quiet ie needs to enabled
  * @mlo_vdev_up_bmap: Bitmap of vdevs for which sync complete can be dispatched
+ * @assoc_list: MLO sta assoc pending list entry (for FT-over-DS)
  */
 struct wlan_mlo_ap {
 	uint8_t num_ml_vdevs;
@@ -722,6 +733,7 @@ struct wlan_mlo_ap {
 #endif
 	qdf_bitmap(mlo_vdev_quiet_bmap, WLAN_UMAC_MLO_MAX_VDEVS);
 	qdf_bitmap(mlo_vdev_up_bmap, WLAN_UMAC_MLO_MAX_VDEVS);
+	struct wlan_mlo_sta_assoc_pending_list assoc_list;
 };
 
 /**
@@ -1608,4 +1620,16 @@ struct peer_entry_ptqm_migrate_event_params {
 	enum primary_link_peer_migration_evenr_status status;
 };
 #endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
+
+/**
+ * struct wlan_mlo_sta_entry - MLO sta entry
+ * @mac_node: QDF list mac_node member
+ * @peer_mld_addr: MLO peer MAC address
+ */
+
+struct wlan_mlo_sta_entry {
+	qdf_list_node_t mac_node;
+	struct qdf_mac_addr peer_mld_addr;
+};
+
 #endif

+ 126 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_peer.c

@@ -2663,3 +2663,129 @@ QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
 	return QDF_STATUS_SUCCESS;
 }
 #endif
+
+void wlan_mlo_ap_vdev_add_assoc_entry(struct wlan_objmgr_vdev *vdev,
+				      struct qdf_mac_addr *mld_addr)
+{
+	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
+	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
+	struct wlan_mlo_sta_entry *sta_entry = NULL;
+
+	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
+		return;
+
+	assoc_list = &mld_ctx->ap_ctx->assoc_list;
+
+	sta_entry = wlan_mlo_ap_vdev_find_assoc_entry(vdev, mld_addr);
+	if (sta_entry) {
+		mlo_err("Duplicate entry " QDF_MAC_ADDR_FMT,
+			QDF_MAC_ADDR_REF(mld_addr->bytes));
+		return;
+	}
+
+	sta_entry = qdf_mem_malloc(sizeof(*sta_entry));
+	if (!sta_entry)
+		return;
+
+	qdf_copy_macaddr((struct qdf_mac_addr *)&sta_entry->peer_mld_addr,
+			 (struct qdf_mac_addr *)&mld_addr[0]);
+
+	qdf_spin_lock_bh(&assoc_list->list_lock);
+	qdf_list_insert_back(&assoc_list->peer_list, &sta_entry->mac_node);
+	qdf_spin_unlock_bh(&assoc_list->list_lock);
+}
+
+void wlan_mlo_ap_vdev_del_assoc_entry(struct wlan_objmgr_vdev *vdev,
+				      struct qdf_mac_addr *mld_addr)
+{
+	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
+	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
+	struct wlan_mlo_sta_entry *sta_entry = NULL;
+
+	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
+		return;
+
+	assoc_list = &mld_ctx->ap_ctx->assoc_list;
+	sta_entry = wlan_mlo_ap_vdev_find_assoc_entry(vdev, mld_addr);
+	if (!sta_entry)
+		return;
+
+	qdf_spin_lock_bh(&assoc_list->list_lock);
+	qdf_list_remove_node(&assoc_list->peer_list, &sta_entry->mac_node);
+	qdf_spin_unlock_bh(&assoc_list->list_lock);
+
+	qdf_mem_free(sta_entry);
+}
+
+static inline struct wlan_mlo_sta_entry *
+wlan_mlo_assoc_list_peek_head(qdf_list_t *assoc_list)
+{
+	struct wlan_mlo_sta_entry *sta_entry = NULL;
+	qdf_list_node_t *list_node = NULL;
+
+	/* This API is invoked with lock acquired, do not add log prints */
+	if (qdf_list_peek_front(assoc_list, &list_node) != QDF_STATUS_SUCCESS)
+		return NULL;
+
+	sta_entry = qdf_container_of(list_node,
+				     struct wlan_mlo_sta_entry, mac_node);
+	return sta_entry;
+}
+
+static inline struct wlan_mlo_sta_entry *
+wlan_mlo_sta_get_next_sta_entry(qdf_list_t *assoc_list,
+				struct wlan_mlo_sta_entry *sta_entry)
+{
+	struct wlan_mlo_sta_entry *next_sta_entry = NULL;
+	qdf_list_node_t *node = &sta_entry->mac_node;
+	qdf_list_node_t *next_node = NULL;
+
+	/* This API is invoked with lock acquired, do not add log prints */
+	if (!node)
+		return NULL;
+
+	if (qdf_list_peek_next(assoc_list, node, &next_node) !=
+				QDF_STATUS_SUCCESS)
+		return NULL;
+
+	next_sta_entry = qdf_container_of(next_node,
+					  struct wlan_mlo_sta_entry, mac_node);
+	return next_sta_entry;
+}
+
+struct wlan_mlo_sta_entry *
+wlan_mlo_ap_vdev_find_assoc_entry(struct wlan_objmgr_vdev *vdev,
+				  struct qdf_mac_addr *mld_addr)
+{
+	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
+	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
+	struct wlan_mlo_sta_entry *sta_entry = NULL;
+	struct wlan_mlo_sta_entry *next_sta_entry = NULL;
+
+	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
+		return NULL;
+
+	assoc_list = &mld_ctx->ap_ctx->assoc_list;
+	if (qdf_list_empty(&assoc_list->peer_list)) {
+		mlo_info("list is empty");
+		return NULL;
+	}
+	qdf_spin_lock_bh(&assoc_list->list_lock);
+
+	sta_entry = wlan_mlo_assoc_list_peek_head(&assoc_list->peer_list);
+	while (sta_entry) {
+		if (qdf_is_macaddr_equal(&sta_entry->peer_mld_addr, mld_addr)) {
+			qdf_spin_unlock_bh(&assoc_list->list_lock);
+			return sta_entry;
+		}
+
+		next_sta_entry =
+		wlan_mlo_sta_get_next_sta_entry(&assoc_list->peer_list,
+						sta_entry);
+		sta_entry = next_sta_entry;
+	}
+	qdf_spin_unlock_bh(&assoc_list->list_lock);
+
+	return NULL;
+}
+

+ 12 - 2
umac/mlo_mgr/src/wlan_mlo_mgr_peer_list.c

@@ -459,6 +459,12 @@ QDF_STATUS mlo_dev_mlpeer_list_init(struct wlan_mlo_dev_context *ml_dev)
 				WLAN_UMAC_PSOC_MAX_PEERS +
 				WLAN_MAX_PSOC_TEMP_PEERS);
 
+	if (ml_dev->ap_ctx) {
+		qdf_spinlock_create(&ml_dev->ap_ctx->assoc_list.list_lock);
+		qdf_list_create(&ml_dev->ap_ctx->assoc_list.peer_list,
+				WLAN_UMAC_PSOC_MAX_PEERS);
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -467,11 +473,15 @@ QDF_STATUS mlo_dev_mlpeer_list_deinit(struct wlan_mlo_dev_context *ml_dev)
 	uint16_t i;
 	struct wlan_mlo_peer_list *mlo_peer_list;
 
-	/* deinit the lock */
+	if (ml_dev->ap_ctx) {
+		qdf_list_destroy(&ml_dev->ap_ctx->assoc_list.peer_list);
+		qdf_spinlock_destroy(&ml_dev->ap_ctx->assoc_list.list_lock);
+	}
+
 	mlo_peer_list = &ml_dev->mlo_peer_list;
-	ml_peerlist_lock_destroy(mlo_peer_list);
 	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
 		qdf_list_destroy(&mlo_peer_list->peer_hash[i]);
 
+	ml_peerlist_lock_destroy(mlo_peer_list);
 	return QDF_STATUS_SUCCESS;
 }