qcacld-3.0: Register network interface for pktcapture mode
For packet capture mode, register an interface through hdd_add_virtual_intf and delete using hdd_del_virtual_intf. During register, remove the P2P interface and add it back during deregister. Change-Id: I79d933c96591cd462e27eda73f5aed2cc7cad8af CRs-Fixed: 2528549
Этот коммит содержится в:

коммит произвёл
nshrivas

родитель
025ea586c8
Коммит
5730524bdc
@@ -4097,4 +4097,82 @@ QDF_STATUS hdd_common_roam_callback(struct wlan_objmgr_psoc *psoc,
|
||||
uint32_t roam_id,
|
||||
eRoamCmdStatus roam_status,
|
||||
eCsrRoamResult roam_result);
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
|
||||
/**
|
||||
* wlan_hdd_is_session_type_monitor() - check if session type is MONITOR
|
||||
* @session_type: session type
|
||||
*
|
||||
* Return: True - if session type for adapter is monitor, else False
|
||||
*
|
||||
*/
|
||||
bool wlan_hdd_is_session_type_monitor(uint8_t session_type);
|
||||
|
||||
/**
|
||||
* wlan_hdd_check_mon_concurrency() - check if MONITOR and STA concurrency
|
||||
* is UP when packet capture mode is enabled.
|
||||
*
|
||||
* Return: True - if STA and monitor concurrency is there, else False
|
||||
*
|
||||
*/
|
||||
bool wlan_hdd_check_mon_concurrency(void);
|
||||
|
||||
/**
|
||||
* wlan_hdd_add_monitor_check() - check for monitor intf and add if needed
|
||||
* @hdd_ctx: pointer to hdd context
|
||||
* @adapter: output pointer to hold created monitor adapter
|
||||
* @type: type of the interface
|
||||
* @name: name of the interface
|
||||
* @rtnl_held: True if RTNL lock is held
|
||||
* @name_assign_type: the name of assign type of the netdev
|
||||
*
|
||||
* Return: 0 - on success
|
||||
* err code - on failure
|
||||
*/
|
||||
int wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter **adapter,
|
||||
enum nl80211_iftype type, const char *name,
|
||||
bool rtnl_held, unsigned char name_assign_type);
|
||||
|
||||
/**
|
||||
* wlan_hdd_del_monitor() - delete monitor interface
|
||||
* @hdd_ctx: pointer to hdd context
|
||||
* @adapter: adapter to be deleted
|
||||
* @rtnl_held: rtnl lock held
|
||||
*
|
||||
* This function is invoked to delete monitor interface.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter *adapter, bool rtnl_held);
|
||||
#else
|
||||
static inline
|
||||
bool wlan_hdd_is_session_type_monitor(uint8_t session_type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool wlan_hdd_check_mon_concurrency(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline
|
||||
int wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter **adapter,
|
||||
enum nl80211_iftype type, const char *name,
|
||||
bool rtnl_held, unsigned char name_assign_type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter *adapter, bool rtnl_held)
|
||||
{
|
||||
}
|
||||
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
||||
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */
|
||||
|
@@ -16053,6 +16053,9 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
|
||||
if (errno)
|
||||
return errno;
|
||||
|
||||
if (wlan_hdd_check_mon_concurrency())
|
||||
return -EINVAL;
|
||||
|
||||
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
|
||||
TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
|
||||
adapter->vdev_id, type);
|
||||
|
@@ -2541,6 +2541,61 @@ static int hdd_mon_open(struct net_device *net_dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
/**
|
||||
* __hdd_pktcapture_open() - HDD Open function
|
||||
* @dev: Pointer to net_device structure
|
||||
*
|
||||
* This is called in response to ifconfig up
|
||||
*
|
||||
* Return: 0 for success; non-zero for failure
|
||||
*/
|
||||
static int __hdd_pktcapture_open(struct net_device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
||||
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
||||
|
||||
hdd_enter_dev(dev);
|
||||
|
||||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdd_mon_mode_ether_setup(dev);
|
||||
|
||||
if (!ret)
|
||||
set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_pktcapture_open() - Wrapper function for __hdd_mon_open to
|
||||
* protect it from SSR
|
||||
* @dev: Pointer to net_device structure
|
||||
*
|
||||
* This is called in response to ifconfig up
|
||||
*
|
||||
* Return: 0 for success; non-zero for failure
|
||||
*/
|
||||
static int hdd_pktcapture_open(struct net_device *net_dev)
|
||||
{
|
||||
int errno;
|
||||
struct osif_vdev_sync *vdev_sync;
|
||||
|
||||
errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
|
||||
if (errno)
|
||||
return errno;
|
||||
|
||||
errno = __hdd_pktcapture_open(net_dev);
|
||||
|
||||
osif_vdev_sync_trans_stop(vdev_sync);
|
||||
|
||||
return errno;
|
||||
}
|
||||
#endif
|
||||
|
||||
static QDF_STATUS
|
||||
wlan_hdd_update_dbs_scan_and_fw_mode_config(void)
|
||||
{
|
||||
@@ -4294,11 +4349,30 @@ void hdd_set_station_ops(struct net_device *dev)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
/* Packet Capture mode net_device_ops, doesnot Tx and most of operations. */
|
||||
static const struct net_device_ops wlan_pktcapture_drv_ops = {
|
||||
.ndo_open = hdd_pktcapture_open,
|
||||
.ndo_stop = hdd_stop,
|
||||
.ndo_get_stats = hdd_get_stats,
|
||||
};
|
||||
|
||||
static void hdd_set_pktcapture_ops(struct net_device *dev)
|
||||
{
|
||||
dev->netdev_ops = &wlan_pktcapture_drv_ops;
|
||||
}
|
||||
#else
|
||||
static void hdd_set_pktcapture_ops(struct net_device *dev)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hdd_alloc_station_adapter() - allocate the station hdd adapter
|
||||
* @hdd_ctx: global hdd context
|
||||
* @mac_addr: mac address to assign to the interface
|
||||
* @name: User-visible name of the interface
|
||||
* @session_type: interface type to be created
|
||||
*
|
||||
* hdd adapter pointer would point to the netdev->priv space, this function
|
||||
* would retrieve the pointer, and setup the hdd adapter configuration.
|
||||
@@ -4307,7 +4381,8 @@ void hdd_set_station_ops(struct net_device *dev)
|
||||
*/
|
||||
static struct hdd_adapter *
|
||||
hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr,
|
||||
unsigned char name_assign_type, const char *name)
|
||||
unsigned char name_assign_type, const char *name,
|
||||
uint8_t session_type)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct hdd_adapter *adapter;
|
||||
@@ -4319,7 +4394,8 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr,
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
|
||||
name_assign_type,
|
||||
#endif
|
||||
(cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE ?
|
||||
((cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE ||
|
||||
wlan_hdd_is_session_type_monitor(session_type)) ?
|
||||
hdd_mon_mode_ether_setup : ether_setup),
|
||||
NUM_TX_QUEUES);
|
||||
|
||||
@@ -4360,7 +4436,10 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr,
|
||||
qdf_mem_copy(adapter->mac_addr.bytes, mac_addr, sizeof(tSirMacAddr));
|
||||
dev->watchdog_timeo = HDD_TX_TIMEOUT;
|
||||
|
||||
hdd_set_station_ops(adapter->dev);
|
||||
if (wlan_hdd_is_session_type_monitor(session_type))
|
||||
hdd_set_pktcapture_ops(adapter->dev);
|
||||
else
|
||||
hdd_set_station_ops(adapter->dev);
|
||||
|
||||
hdd_dev_setup_destructor(dev);
|
||||
dev->ieee80211_ptr = &adapter->wdev;
|
||||
@@ -5542,7 +5621,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
|
||||
case QDF_NAN_DISC_MODE:
|
||||
adapter = hdd_alloc_station_adapter(hdd_ctx, mac_addr,
|
||||
name_assign_type,
|
||||
iface_name);
|
||||
iface_name, session_type);
|
||||
|
||||
if (!adapter) {
|
||||
hdd_err("failed to allocate adapter for session %d",
|
||||
@@ -5650,7 +5729,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
|
||||
case QDF_FTM_MODE:
|
||||
adapter = hdd_alloc_station_adapter(hdd_ctx, mac_addr,
|
||||
name_assign_type,
|
||||
iface_name);
|
||||
iface_name, session_type);
|
||||
if (!adapter) {
|
||||
hdd_err("Failed to allocate adapter for FTM mode");
|
||||
return NULL;
|
||||
@@ -16160,6 +16239,190 @@ void hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle, uint8_t vdev_id)
|
||||
wlan_hdd_enable_roaming(adapter, RSO_START_BSS);
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_PKT_CAPTURE
|
||||
|
||||
/**
|
||||
* wlan_hdd_is_session_type_monitor() - check if session type is MONITOR
|
||||
* @session_type: session type
|
||||
*
|
||||
* Return: True - if session type for adapter is monitor, else False
|
||||
*
|
||||
*/
|
||||
bool wlan_hdd_is_session_type_monitor(uint8_t session_type)
|
||||
{
|
||||
if (cds_is_pktcapture_enabled() &&
|
||||
cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE &&
|
||||
session_type == QDF_MONITOR_MODE)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_check_mon_concurrency() - check if MONITOR and STA concurrency
|
||||
* is UP when packet capture mode is enabled.
|
||||
* @void
|
||||
*
|
||||
* Return: True - if STA and monitor concurrency is there, else False
|
||||
*
|
||||
*/
|
||||
bool wlan_hdd_check_mon_concurrency(void)
|
||||
{
|
||||
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
|
||||
|
||||
if (!hdd_ctx) {
|
||||
hdd_err("HDD context is null");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cds_is_pktcapture_enabled()) {
|
||||
if (policy_mgr_get_concurrency_mode(hdd_ctx->psoc) ==
|
||||
(QDF_STA_MASK | QDF_MONITOR_MASK)) {
|
||||
hdd_err("STA + MON mode is UP");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_del_monitor() - delete monitor interface
|
||||
* @hdd_ctx: pointer to hdd context
|
||||
* @adapter: adapter to be deleted
|
||||
* @rtnl_held: rtnl lock held
|
||||
*
|
||||
* This function is invoked to delete monitor interface.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter *adapter, bool rtnl_held)
|
||||
{
|
||||
wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes);
|
||||
hdd_stop_adapter(hdd_ctx, adapter);
|
||||
hdd_close_adapter(hdd_ctx, adapter, true);
|
||||
|
||||
hdd_open_p2p_interface(hdd_ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_add_monitor_check() - check for monitor intf and add if needed
|
||||
* @hdd_ctx: pointer to hdd context
|
||||
* @adapter: output pointer to hold created monitor adapter
|
||||
* @type: type of the interface
|
||||
* @name: name of the interface
|
||||
* @rtnl_held: True if RTNL lock is held
|
||||
* @name_assign_type: the name of assign type of the netdev
|
||||
*
|
||||
* Return: 0 - on success
|
||||
* err code - on failure
|
||||
*/
|
||||
int
|
||||
wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter **adapter,
|
||||
enum nl80211_iftype type, const char *name,
|
||||
bool rtnl_held, unsigned char name_assign_type)
|
||||
{
|
||||
struct hdd_adapter *sta_adapter;
|
||||
struct hdd_adapter *mon_adapter;
|
||||
uint32_t mode;
|
||||
uint8_t num_open_session = 0;
|
||||
|
||||
if (!cds_is_pktcapture_enabled())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If add interface request is for monitor mode, then it can run in
|
||||
* parallel with only one station interface.
|
||||
* If there is no existing station interface return error
|
||||
*/
|
||||
if (type != NL80211_IFTYPE_MONITOR)
|
||||
return 0;
|
||||
|
||||
if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions(
|
||||
hdd_ctx->psoc,
|
||||
QDF_MONITOR_MODE,
|
||||
&num_open_session))
|
||||
return -EINVAL;
|
||||
|
||||
if (num_open_session) {
|
||||
hdd_err("monitor mode already exists, only one is possible");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Ensure there is only one station interface */
|
||||
if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions(
|
||||
hdd_ctx->psoc,
|
||||
QDF_STA_MODE,
|
||||
&num_open_session))
|
||||
return -EINVAL;
|
||||
|
||||
if (num_open_session != 1) {
|
||||
hdd_err("cannot add monitor mode, due to %u sta interfaces",
|
||||
num_open_session);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
|
||||
if (!sta_adapter) {
|
||||
hdd_err("No station adapter");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions(
|
||||
hdd_ctx->psoc,
|
||||
QDF_SAP_MODE,
|
||||
&num_open_session))
|
||||
return -EINVAL;
|
||||
|
||||
if (num_open_session) {
|
||||
hdd_err("cannot add monitor mode, due to SAP concurrency");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* delete p2p interface */
|
||||
for (mode = QDF_P2P_CLIENT_MODE; mode <= QDF_P2P_DEVICE_MODE; mode++) {
|
||||
struct hdd_adapter *adapter;
|
||||
|
||||
if (mode == QDF_FTM_MODE ||
|
||||
mode == QDF_MONITOR_MODE ||
|
||||
mode == QDF_IBSS_MODE)
|
||||
continue;
|
||||
|
||||
adapter = hdd_get_adapter(hdd_ctx, mode);
|
||||
if (adapter) {
|
||||
struct osif_vdev_sync *vdev_sync;
|
||||
|
||||
vdev_sync = osif_vdev_sync_unregister(adapter->dev);
|
||||
if (vdev_sync)
|
||||
osif_vdev_sync_wait_for_ops(vdev_sync);
|
||||
|
||||
wlan_hdd_release_intf_addr(hdd_ctx,
|
||||
adapter->mac_addr.bytes);
|
||||
hdd_stop_adapter(hdd_ctx, adapter);
|
||||
hdd_deinit_adapter(hdd_ctx, adapter, true);
|
||||
hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
|
||||
|
||||
if (vdev_sync)
|
||||
osif_vdev_sync_destroy(vdev_sync);
|
||||
}
|
||||
}
|
||||
|
||||
mon_adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, name,
|
||||
wlan_hdd_get_intf_addr(
|
||||
hdd_ctx,
|
||||
QDF_MONITOR_MODE),
|
||||
name_assign_type, rtnl_held);
|
||||
if (!mon_adapter) {
|
||||
hdd_err("hdd_open_adapter failed");
|
||||
hdd_open_p2p_interface(hdd_ctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*adapter = mon_adapter;
|
||||
return 0;
|
||||
}
|
||||
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
||||
/* Register the module init/exit functions */
|
||||
module_init(hdd_module_init);
|
||||
module_exit(hdd_module_exit);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -689,6 +689,9 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (wlan_hdd_check_mon_concurrency())
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
|
||||
TRACE_CODE_HDD_ADD_VIRTUAL_INTF,
|
||||
NO_SESSION, type);
|
||||
@@ -719,6 +722,16 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
|
||||
}
|
||||
}
|
||||
|
||||
adapter = NULL;
|
||||
ret = wlan_hdd_add_monitor_check(hdd_ctx, &adapter, type, name,
|
||||
true, name_assign_type);
|
||||
if (ret)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (adapter) {
|
||||
hdd_exit();
|
||||
return adapter->dev->ieee80211_ptr;
|
||||
}
|
||||
|
||||
if (mode == QDF_SAP_MODE) {
|
||||
struct wireless_dev *sap_dev;
|
||||
bool allow_add_sap = wlan_hdd_allow_sap_add(hdd_ctx, name,
|
||||
@@ -883,6 +896,9 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
if (adapter->device_mode == QDF_SAP_MODE &&
|
||||
wlan_sap_is_pre_cac_active(hdd_ctx->mac_handle)) {
|
||||
hdd_clean_up_pre_cac_interface(hdd_ctx);
|
||||
} else if (wlan_hdd_is_session_type_monitor(
|
||||
adapter->device_mode)) {
|
||||
wlan_hdd_del_monitor(hdd_ctx, adapter, TRUE);
|
||||
} else {
|
||||
wlan_hdd_release_intf_addr(hdd_ctx,
|
||||
adapter->mac_addr.bytes);
|
||||
|
Ссылка в новой задаче
Block a user