Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 82fba8d1 authored by Balaji Pothunoori's avatar Balaji Pothunoori Committed by Gerrit - the friendly Code Review server
Browse files

qcacld-3.0: vendor command changes to configure parameters for monitor mode

Add new vendor command aims to indicate the driver to configure
monitor mode parameters for an interface on which this command is
issued. Once enabled, the frames (both TX and RX) on this interface
are sent to an active coexisting monitor interface.

Change-Id: Ieb01d5f928d4e414f46bd00524ad683ad889963e
CRs-Fixed: 3025473
parent d82f8b8f
Loading
Loading
Loading
Loading
+228 −0
Original line number Original line Diff line number Diff line
@@ -163,6 +163,8 @@
#include "wlan_if_mgr_public_struct.h"
#include "wlan_if_mgr_public_struct.h"
#include "wlan_wfa_ucfg_api.h"
#include "wlan_wfa_ucfg_api.h"
#include "wlan_roam_debug.h"
#include "wlan_roam_debug.h"
#include "wlan_pkt_capture_ucfg_api.h"
#define g_mode_rates_size (12)
#define g_mode_rates_size (12)
#define a_mode_rates_size (8)
#define a_mode_rates_size (8)
@@ -14986,6 +14988,36 @@ get_usable_channel_policy[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1] = {
	},
	},
};
};
#ifdef WLAN_FEATURE_PKT_CAPTURE
static const struct nla_policy
set_monitor_mode_policy[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX + 1] = {
	[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID] = {
		.type = NLA_U32
	},
	[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] = {
		.type = NLA_U32
	},
	[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] = {
		.type = NLA_U32
	},
	[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] = {
		.type = NLA_U32
	},
	[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] = {
		.type = NLA_U32
	},
	[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] = {
		.type = NLA_U32
	},
	[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] = {
		.type = NLA_U32
	},
	[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL] = {
		.type = NLA_U32
	},
};
#endif
#ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
#ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
static enum nl80211_chan_width
static enum nl80211_chan_width
hdd_convert_phy_bw_to_nl_bw(enum phy_ch_width bw)
hdd_convert_phy_bw_to_nl_bw(enum phy_ch_width bw)
@@ -15431,6 +15463,189 @@ static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
}
}
#endif
#endif
#ifdef WLAN_FEATURE_PKT_CAPTURE
/**
 * hdd_monitor_mode_configure - Process monitor mode configuration
 * operation in the received vendor command
 * @adapter: adapter pointer
 * @tb: nl attributes
 *
 * Handles QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE
 *
 * Return: 0 for Success and negative value for failure
 */
static int hdd_monitor_mode_configure(struct hdd_adapter *adapter,
				      struct nlattr **tb)
{
	struct pkt_capture_frame_filter frame_filter = {0};
	struct wlan_objmgr_vdev *vdev;
	QDF_STATUS status;
	hdd_enter();
	vdev = hdd_objmgr_get_vdev(adapter);
	if (!vdev)
		return QDF_STATUS_E_FAILURE;
	if (tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID])
		return QDF_STATUS_E_FAILURE;
	if (tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE] &&
	    nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]) <
	    PACKET_CAPTURE_DATA_MAX_FILTER) {
		frame_filter.data_tx_frame_filter =
			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE]);
		frame_filter.vendor_attr_to_set =
			BIT(QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE);
	}
	if (tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE] &&
	    nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]) <
	    PACKET_CAPTURE_DATA_MAX_FILTER) {
		frame_filter.data_rx_frame_filter =
			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE]);
		frame_filter.vendor_attr_to_set |=
			BIT(QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE);
	}
	if (tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE] &&
	    nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]) <
	    PACKET_CAPTURE_MGMT_MAX_FILTER) {
		frame_filter.mgmt_tx_frame_filter =
			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE]);
		frame_filter.vendor_attr_to_set |=
			BIT(QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE);
	}
	if (tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE] &&
	    nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]) <
	    PACKET_CAPTURE_MGMT_MAX_FILTER) {
		frame_filter.mgmt_rx_frame_filter =
			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE]);
		frame_filter.vendor_attr_to_set |=
			BIT(QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE);
	}
	if (tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE] &&
	    nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]) <
	    PACKET_CAPTURE_CTRL_MAX_FILTER) {
		frame_filter.ctrl_tx_frame_filter =
			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE]);
		frame_filter.vendor_attr_to_set |=
			BIT(QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE);
	}
	if (tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE] &&
	    nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]) <
	    PACKET_CAPTURE_CTRL_MAX_FILTER) {
		frame_filter.ctrl_rx_frame_filter =
			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE]);
		frame_filter.vendor_attr_to_set |=
			BIT(QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE);
	}
	if (tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL]) {
		frame_filter.connected_beacon_interval =
			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL]);
		frame_filter.vendor_attr_to_set |=
			BIT(QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL);
	}
	hdd_debug("Monitor mode config %s data tx %d data rx %d mgmt tx %d mgmt rx %d ctrl tx %d ctrl rx %d beacon interval %d\n",
		  __func__, frame_filter.data_tx_frame_filter,
		  frame_filter.data_rx_frame_filter, frame_filter.mgmt_tx_frame_filter,
		  frame_filter.mgmt_rx_frame_filter, frame_filter.ctrl_tx_frame_filter,
		  frame_filter.ctrl_rx_frame_filter, frame_filter.connected_beacon_interval);
	status = ucfg_pkt_capture_set_filter(frame_filter, vdev);
	hdd_objmgr_put_vdev(vdev);
	hdd_exit();
	return status;
}
/**
 * __wlan_hdd_cfg80211_set_monitor_mode() - Wifi monitor mode configuration
 * vendor command
 * @wiphy: wiphy device pointer
 * @wdev: wireless device pointer
 * @data: Vendor command data buffer
 * @data_len: Buffer length
 *
 * Handles .
 *
 * Return: 0 for Success and negative value for failure
 */
static int
__wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
				     struct wireless_dev *wdev,
				     const void *data, int data_len)
{
	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 nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX + 1];
	int errno;
	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
		hdd_err("Command not allowed in FTM mode");
		return -EPERM;
	}
	errno = wlan_hdd_validate_context(hdd_ctx);
	if (errno)
		return errno;
	if (!ucfg_pkt_capture_get_mode(hdd_ctx->psoc))
		return QDF_STATUS_E_FAILURE;
	errno = hdd_validate_adapter(adapter);
	if (errno)
		return errno;
	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX,
				    data, data_len, set_monitor_mode_policy)) {
		hdd_err("invalid monitor attr");
		return -EINVAL;
	}
	errno = hdd_monitor_mode_configure(adapter, tb);
	return errno;
}
/**
 * wlan_hdd_cfg80211_set_monitor_mode() - set monitor mode
 * @wiphy: wiphy pointer
 * @wdev: pointer to struct wireless_dev
 * @data: pointer to incoming NL vendor data
 * @data_len: length of @data
 *
 * Return: 0 on success; error number otherwise.
 */
static int wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
					      struct wireless_dev *wdev,
					      const void *data, int data_len)
{
	int errno;
	struct osif_vdev_sync *vdev_sync;
	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
	if (errno)
		return errno;
	errno = __wlan_hdd_cfg80211_set_monitor_mode(wiphy, wdev,
						     data, data_len);
	osif_vdev_sync_op_stop(vdev_sync);
	return errno;
}
#endif
/**
/**
 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
 * @wiphy: wiphy pointer
 * @wiphy: wiphy pointer
@@ -16305,6 +16520,19 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
	FEATURE_THERMAL_VENDOR_COMMANDS
	FEATURE_THERMAL_VENDOR_COMMANDS
	FEATURE_BTC_CHAIN_MODE_COMMANDS
	FEATURE_BTC_CHAIN_MODE_COMMANDS
	FEATURE_WMM_COMMANDS
	FEATURE_WMM_COMMANDS
#ifdef WLAN_FEATURE_PKT_CAPTURE
	{
	.info.vendor_id = QCA_NL80211_VENDOR_ID,
	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE,
	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
		 WIPHY_VENDOR_CMD_NEED_NETDEV |
		 WIPHY_VENDOR_CMD_NEED_RUNNING,
	.doit = wlan_hdd_cfg80211_set_monitor_mode,
	vendor_command_policy(set_monitor_mode_policy,
			      QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX)
	},
#endif
};
};
struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
struct hdd_context *hdd_cfg80211_wiphy_alloc(void)