qcacld-3.0: Add support for the new NAN EXT vendor command

As part of the NAN Discovery DBS support, a new vendor command
- QCA_NL80211_VENDOR_SUBCMD_NAN_EXT - has been defined that can
carry the binary blob encapsulated within an attribute and can
carry additional attributes to enhance the NAN command interface.
Add related data structures in NAN component and add modules in
OSIF to parse and sanitize this new command data and forward
the NAN message to the NAN component.

Add support for the new NAN EXT vendor command.

Change-Id: I0e6bb833b01a8cbd65e4d42700b5b70599f3ef99
CRs-Fixed: 2339029
This commit is contained in:
Nachiket Kukade 2018-10-09 20:07:21 +05:30 • committed by nshrivas
commit a6a70a98f1
7 changed files with 432 additions and 61 deletions

View file

@ -24,14 +24,10 @@
#define _OS_IF_NAN_H_
#include "qdf_types.h"
#ifdef WLAN_FEATURE_NAN_CONVERGENCE
#include "nan_public_structs.h"
#include "nan_ucfg_api.h"
struct wlan_objmgr_psoc;
struct wlan_objmgr_vdev;
#ifdef WLAN_FEATURE_NAN_CONVERGENCE
/**
* os_if_nan_process_ndp_cmd: os_if api to handle nan request message
* @psoc: pointer to psoc object
@ -150,6 +146,16 @@ static inline QDF_STATUS os_if_nan_set_ndp_delete_transaction_id(
return ucfg_nan_set_ndp_delete_transaction_id(vdev, val);
}
/**
* os_if_process_nan_req: os_if api to handle nan request message
* @psoc: pointer to psoc object
* @data: request data. contains vendor cmd tlvs
* @data_len: length of data
*
* Return: status of operation
*/
int os_if_process_nan_req(struct wlan_objmgr_psoc *psoc,
const void *data, int data_len);
#else
static inline void os_if_nan_post_ndi_create_rsp(struct wlan_objmgr_psoc *psoc,

View file

@ -26,7 +26,6 @@
#include "os_if_nan.h"
#include "wlan_nan_api.h"
#include "nan_ucfg_api.h"
#include "nan_public_structs.h"
#include "wlan_osif_priv.h"
#include <net/cfg80211.h>
#include "wlan_cfg80211.h"
@ -35,6 +34,30 @@
#include "wlan_objmgr_vdev_obj.h"
#include "wlan_objmgr_peer_obj.h"
#include "wlan_utility.h"
#include "wlan_osif_request_manager.h"
#define NAN_CMD_MAX_SIZE 300
/* NLA policy */
static const struct nla_policy
nan_attr_policy[QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX + 1] = {
[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA] = {
.type = NLA_BINARY,
.len = NAN_CMD_MAX_SIZE
},
[QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE] = {
.type = NLA_U32,
.len = sizeof(uint32_t)
},
[QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ] = {
.type = NLA_U32,
.len = sizeof(uint32_t)
},
[QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ] = {
.type = NLA_U32,
.len = sizeof(uint32_t)
},
};
/* NLA policy */
static const struct nla_policy
@ -2168,3 +2191,156 @@ void os_if_nan_ndi_session_end(struct wlan_objmgr_vdev *vdev)
failure:
kfree_skb(vendor_event);
}
static int os_if_nan_generic_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
struct nan_generic_req *nan_req;
uint32_t buf_len;
QDF_STATUS status;
buf_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA]);
nan_req = qdf_mem_malloc(sizeof(*nan_req) + buf_len);
if (!nan_req) {
cfg80211_err("Request allocation failure");
return -ENOMEM;
}
nan_req->psoc = psoc;
nan_req->params.request_data_len = buf_len;
nla_memcpy(nan_req->params.request_data,
tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA], buf_len);
cfg80211_debug("sending NAN Req");
status = ucfg_nan_discovery_req(nan_req, NAN_GENERIC_REQ);
if (QDF_IS_STATUS_SUCCESS(status))
cfg80211_err("Successfully sent a NAN request");
else
cfg80211_err("Unable to send a NAN request");
qdf_mem_free(nan_req);
return qdf_status_to_os_return(status);
}
static int os_if_process_nan_disable_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
struct nan_disable_req *nan_req;
uint32_t buf_len;
QDF_STATUS status;
buf_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA]);
nan_req = qdf_mem_malloc(sizeof(*nan_req) + buf_len);
if (!nan_req) {
cfg80211_err("Request allocation failure");
return -ENOMEM;
}
nan_req->psoc = psoc;
nan_req->params.request_data_len = buf_len;
nla_memcpy(nan_req->params.request_data,
tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA], buf_len);
cfg80211_debug("sending NAN Disable Req");
status = ucfg_nan_discovery_req(nan_req, NAN_DISABLE_REQ);
if (QDF_IS_STATUS_SUCCESS(status))
cfg80211_err("Successfully sent NAN Disable request");
else
cfg80211_err("Unable to disable NAN Discovery");
qdf_mem_free(nan_req);
return qdf_status_to_os_return(status);
}
static int os_if_process_nan_enable_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
uint32_t chan_freq_2g, chan_freq_5g = 0;
uint32_t buf_len;
QDF_STATUS status;
struct nan_enable_req *nan_req;
if (!ucfg_is_nan_enable_allowed(psoc)) {
cfg80211_err("NAN Enable not allowed at this moment");
return -EINVAL;
}
if (!tb[QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ]) {
cfg80211_err("NAN Social channel for 2.4Gz is unavailable!");
return -EINVAL;
}
chan_freq_2g =
nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ]);
if (tb[QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ])
chan_freq_5g =
nla_get_u32(tb[
QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ]);
buf_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA]);
nan_req = qdf_mem_malloc(sizeof(*nan_req) + buf_len);
if (!nan_req) {
cfg80211_err("Request allocation failure");
return -ENOMEM;
}
nan_req->social_chan_2g = wlan_freq_to_chan(chan_freq_2g);
nan_req->social_chan_5g = wlan_freq_to_chan(chan_freq_5g);
nan_req->psoc = psoc;
nan_req->params.request_data_len = buf_len;
nla_memcpy(nan_req->params.request_data,
tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA], buf_len);
cfg80211_debug("Sending NAN Enable Req");
status = ucfg_nan_discovery_req(nan_req, NAN_ENABLE_REQ);
if (QDF_IS_STATUS_SUCCESS(status))
cfg80211_err("Successfully sent NAN Enable");
else
cfg80211_err("Unable to enable NAN Discovery");
qdf_mem_free(nan_req);
return qdf_status_to_os_return(status);
}
int os_if_process_nan_req(struct wlan_objmgr_psoc *psoc,
const void *data, int data_len)
{
uint32_t nan_subcmd;
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX + 1];
if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX,
data, data_len, nan_attr_policy)) {
cfg80211_err("Invalid NAN vendor command attributes");
return -EINVAL;
}
if (!tb[QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA]) {
cfg80211_err("NAN cmd data missing!");
return -EINVAL;
}
if (!ucfg_is_nan_dbs_supported(psoc))
return os_if_nan_generic_req(psoc, tb);
if (!tb[QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE])
return os_if_nan_generic_req(psoc, tb);
nan_subcmd = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE]);
switch (nan_subcmd) {
case QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ:
return os_if_process_nan_enable_req(psoc, tb);
case QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ:
return os_if_process_nan_disable_req(psoc, tb);
default:
cfg80211_err("Unrecognized NAN subcmd type(%d)", nan_subcmd);
return -EINVAL;
}
}