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
Этот коммит содержится в:
Alok Kumar
2019-07-23 12:27:18 +05:30
коммит произвёл nshrivas
родитель 025ea586c8
Коммит 5730524bdc
4 изменённых файлов: 366 добавлений и 6 удалений

Просмотреть файл

@@ -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);