Browse Source

qcacld-3.0: Add support to send TDLS avail and no. connected peer

Add support to send whether currently TDLS is available or not.

Vendor subcmd: QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS
Vendor attr: QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AVAILABLE

Also add support to get the TDLS number of active sessions
using below vendor attr.

Vendor subcmd: QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS
Vendor attr: QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_NUM_SESSIONS

Change-Id: Ie9ad09de9593559c4d57599a9af58a95af99e60f
CRs-Fixed: 3554429
Deeksha Gupta 1 year ago
parent
commit
167488b437

+ 14 - 0
components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h

@@ -30,6 +30,7 @@
 #include <wlan_mlme_api.h>
 #include <wlan_mlme_main.h>
 #include "wma_tgt_cfg.h"
+#include "wlan_mlme_vdev_mgr_interface.h"
 
 /**
  * ucfg_mlme_init() - initialize mlme_ctx context.
@@ -282,6 +283,19 @@ ucfg_mlme_peer_config_vlan(struct wlan_objmgr_vdev *vdev,
 	return wlan_mlme_peer_config_vlan(vdev, macaddr);
 }
 
+/**
+ * ucfg_mlme_get_tdls_prohibited() - get if TDLS prohibited is advertised by
+ * the connected AP.
+ * @vdev: vdev pointer
+ *
+ * Return: bool
+ */
+static inline
+bool ucfg_mlme_get_tdls_prohibited(struct wlan_objmgr_vdev *vdev)
+{
+	return mlme_get_tdls_prohibited(vdev);
+}
+
 #ifdef MULTI_CLIENT_LL_SUPPORT
 /**
  * ucfg_mlme_get_wlm_multi_client_ll_caps() - Get multi client latency level

+ 15 - 0
components/tdls/dispatcher/inc/wlan_tdls_cfg_api.h

@@ -274,6 +274,14 @@ cfg_tdls_set_scan_enable(struct wlan_objmgr_psoc *psoc,
  * This function gets tdls max peer count
  */
 uint16_t cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * cfg_tdls_get_connected_peer_count() - get tdls connected peer count
+ * @psoc: pointer to psoc object
+ *
+ * This function gets tdls connected peer count
+ */
+uint16_t cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc);
 #else
 static inline QDF_STATUS
 cfg_tdls_get_support_enable(struct wlan_objmgr_psoc *psoc,
@@ -450,5 +458,12 @@ cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc)
 {
 	return 0;
 }
+
+static inline uint16_t
+cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc)
+{
+	return 0;
+}
+
 #endif /* FEATURE_WLAN_TDLS */
 #endif /* _WLAN_TDLS_CFG_API_H_ */

+ 16 - 0
components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h

@@ -459,6 +459,16 @@ uint16_t ucfg_get_tdls_conn_peer_count(struct wlan_objmgr_vdev *vdev);
 struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc,
 					    wlan_objmgr_ref_dbgid dbg_id);
 
+/**
+ * ucfg_tdls_check_is_tdls_allowed() - Ucfg api to check is tdls allowed or not
+ * @vdev: vdev object
+ *
+ * Function determines the whether TDLS allowed in the system
+ *
+ * Return: true or false
+ */
+bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev);
+
 #else
 static inline
 bool ucfg_tdls_link_vdev_is_matching(struct wlan_objmgr_vdev *vdev)
@@ -560,6 +570,12 @@ struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc,
 	return NULL;
 }
 
+static inline
+bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
+{
+	return false;
+}
+
 static inline
 void ucfg_tdls_update_fw_11ax_capability(struct wlan_objmgr_psoc *psoc,
 					 bool is_fw_tdls_11ax_capable)

+ 14 - 0
components/tdls/dispatcher/src/wlan_tdls_cfg.c

@@ -413,3 +413,17 @@ cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc)
 
 	return soc_obj->max_num_tdls_sta;
 }
+
+uint16_t
+cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc)
+{
+	struct tdls_soc_priv_obj *soc_obj;
+
+	soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
+	if (!soc_obj) {
+		tdls_err("tdls soc null");
+		return 0;
+	}
+
+	return soc_obj->connected_peer_count;
+}

+ 5 - 0
components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c

@@ -1287,3 +1287,8 @@ struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc,
 {
 	return tdls_get_vdev(psoc, dbg_id);
 }
+
+bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
+{
+	return tdls_check_is_tdls_allowed(vdev);
+}

+ 132 - 2
core/hdd/src/wlan_hdd_tdls.c

@@ -189,6 +189,70 @@ const struct nla_policy
 						.type = NLA_S32},
 };
 
+static bool wlan_hdd_is_tdls_allowed(struct hdd_context *hdd_ctx,
+				     struct wlan_objmgr_vdev *vdev)
+{
+	bool tdls_support;
+
+	if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
+		QDF_STATUS_SUCCESS) && !tdls_support) {
+		hdd_debug("TDLS feature not Enabled or Not supported in FW");
+		return false;
+	}
+
+	if (!wlan_cm_is_vdev_connected(vdev)) {
+		hdd_debug("Failed due to Not associated");
+		return false;
+	}
+
+	if (wlan_cm_roaming_in_progress(hdd_ctx->pdev,
+					wlan_vdev_get_id(vdev))) {
+		hdd_debug("Failed due to Roaming is in progress");
+		return false;
+	}
+
+	if (!ucfg_tdls_check_is_tdls_allowed(vdev)) {
+		hdd_debug("TDLS is not allowed");
+		return false;
+	}
+
+	if (ucfg_mlme_get_tdls_prohibited(vdev)) {
+		hdd_debug("TDLS is prohobited by AP");
+		return false;
+	}
+
+	return true;
+}
+
+static bool wlan_hdd_get_tdls_allowed(struct hdd_context *hdd_ctx,
+				      struct hdd_adapter *adapter)
+{
+	struct wlan_hdd_link_info *link_info;
+	struct wlan_objmgr_vdev *vdev;
+	bool is_tdls_avail = false;
+
+	hdd_adapter_for_each_active_link_info(adapter, link_info) {
+		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_TDLS_NB_ID);
+		if (!vdev)
+			return false;
+
+		is_tdls_avail = wlan_hdd_is_tdls_allowed(hdd_ctx, vdev);
+
+		/* Return is_tdls_avail for non-MLO case */
+		if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+			hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
+			return is_tdls_avail;
+		}
+
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
+
+		if (is_tdls_avail)
+			return is_tdls_avail;
+	}
+
+	return false;
+}
+
 /**
  * __wlan_hdd_cfg80211_exttdls_get_status() - handle get status cfg80211 command
  * @wiphy: wiphy
@@ -202,8 +266,74 @@ __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
 					 const void *data,
 					 int data_len)
 {
-	/* TODO */
-	return 0;
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct sk_buff *skb;
+	uint32_t connected_peer_count = 0;
+	int status;
+	bool is_tdls_avail = true;
+	int ret = 0;
+	int attr;
+
+	hdd_enter_dev(wdev->netdev);
+	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	status = wlan_hdd_validate_context(hdd_ctx);
+	if (status)
+		return -EINVAL;
+
+	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+						sizeof(u32) + sizeof(bool) +
+						NLMSG_HDRLEN);
+
+	if (!skb) {
+		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
+		return -ENOMEM;
+	}
+
+	if (adapter->device_mode != QDF_STA_MODE &&
+	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
+		hdd_debug("Failed to get TDLS info due to opmode:%d",
+			  adapter->device_mode);
+		ret = -EOPNOTSUPP;
+		goto fail;
+	}
+
+	connected_peer_count = cfg_tdls_get_connected_peer_count(hdd_ctx->psoc);
+	is_tdls_avail = wlan_hdd_get_tdls_allowed(hdd_ctx, adapter);
+
+	if (connected_peer_count >=
+			cfg_tdls_get_max_peer_count(hdd_ctx->psoc)) {
+		hdd_debug("Failed due to max no. of connected peer:%d reached",
+			  connected_peer_count);
+		is_tdls_avail = false;
+	}
+
+	hdd_debug("Send TDLS_available: %d, no. of connected peer:%d to userspace",
+		  is_tdls_avail, connected_peer_count);
+
+	attr = QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_NUM_SESSIONS;
+	if (nla_put_u32(skb, attr, connected_peer_count)) {
+		hdd_err("nla put fail");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	attr = QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AVAILABLE;
+	if (is_tdls_avail && nla_put_flag(skb, attr)) {
+		hdd_err("nla put fail");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	return wlan_cfg80211_vendor_cmd_reply(skb);
+fail:
+	wlan_cfg80211_vendor_free_skb(skb);
+	return ret;
 }
 
 static int