qcacld-3.0: Refactor APF related modules in separate files
File wlan_hdd_cfg80211.c is bloated and adding support for
upcoming Android Packet Filter v3 is going to increase its
size even more.
Create a new source file for APF related HDD modules and a
header file for declaring the API's.
Change-Id: I2fb3d7e017f4befbad7aacab3575ae2b48e88a45
CRs-Fixed: 2189825
diff --git a/Kbuild b/Kbuild
index 721b5a5..641d755 100644
--- a/Kbuild
+++ b/Kbuild
@@ -89,6 +89,10 @@
HDD_OBJS+= $(HDD_SRC_DIR)/wlan_hdd_green_ap.o
endif
+ifeq ($(CONFIG_QCACLD_FEATURE_APF), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_apf.o
+endif
+
ifeq ($(CONFIG_WLAN_FEATURE_LPSS), y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_lpass.o
endif
@@ -835,6 +839,10 @@
WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_pmo_api.o
endif
+ifeq ($(CONFIG_QCACLD_FEATURE_APF), y)
+WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_apf_tlv.o
+endif
+
ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y)
ifeq ($(CONFIG_OCB_UT_FRAMEWORK), y)
WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_ocb_ut.o
@@ -1818,6 +1826,10 @@
#Green AP feature
cppflags-$(CONFIG_QCACLD_FEATURE_GREEN_AP) += -DWLAN_SUPPORT_GREEN_AP
+ifeq ($(CONFIG_QCACLD_FEATURE_APF), y)
+cppflags-$(CONFIG_QCACLD_FEATURE_APF) += -DFEATURE_WLAN_APF
+endif
+
#Stats & Quota Metering feature
ifeq ($(CONFIG_IPA_OFFLOAD), y)
ifeq ($(CONFIG_QCACLD_FEATURE_METERING), y)
diff --git a/configs/default_defconfig b/configs/default_defconfig
index e1a7c3b..2849745 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -80,6 +80,9 @@
CONFIG_QCACLD_FEATURE_GREEN_AP := y
+#Flag to enable Android Packet Filtering
+CONFIG_QCACLD_FEATURE_APF := y
+
ifeq ($(CONFIG_ARCH_MSM8998), y)
CONFIG_QCACLD_FEATURE_METERING := y
endif
diff --git a/configs/genoa.snoc.debug_defconfig b/configs/genoa.snoc.debug_defconfig
index 7a94a2d..138657a 100644
--- a/configs/genoa.snoc.debug_defconfig
+++ b/configs/genoa.snoc.debug_defconfig
@@ -162,6 +162,7 @@
ifeq ($(CONFIG_POWER_MANAGEMENT_OFFLOAD), y)
CONFIG_GTK_OFFLOAD := y
endif
+CONFIG_QCACLD_FEATURE_APF := y
ifneq ($(DEVELOPER_DISABLE_BUILD_TIMESTAMP), y)
ifneq ($(WLAN_DISABLE_BUILD_TAG), y)
diff --git a/core/hdd/inc/wlan_hdd_apf.h b/core/hdd/inc/wlan_hdd_apf.h
new file mode 100644
index 0000000..e5a8fe9
--- /dev/null
+++ b/core/hdd/inc/wlan_hdd_apf.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012-2018 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+/**
+ * DOC: wlan_hdd_apf.h
+ *
+ * Android Packet Filter related API's and definitions
+ */
+
+#ifndef __WLAN_HDD_APF_H
+#define __WLAN_HDD_APF_H
+
+#include "sir_api.h"
+#include "wlan_hdd_main.h"
+
+/**
+ * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
+ * @wiphy: wiphy structure pointer
+ * @wdev: Wireless device structure pointer
+ * @data: Pointer to the data received
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success; errno on failure
+ */
+
+int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len);
+#endif /* WLAN_HDD_APF_H */
diff --git a/core/hdd/src/wlan_hdd_apf.c b/core/hdd/src/wlan_hdd_apf.c
new file mode 100644
index 0000000..9a1c724
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_apf.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2012-2018 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_hdd_apf.c
+ *
+ * Android Packet Filter support and implementation
+ */
+
+#include "wlan_hdd_apf.h"
+#include "qca_vendor.h"
+#include "wlan_hdd_request_manager.h"
+
+/*
+ * define short names for the global vendor params
+ * used by __wlan_hdd_cfg80211_bpf_offload()
+ */
+#define BPF_INVALID \
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
+#define BPF_SET_RESET \
+ QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
+#define BPF_VERSION \
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
+#define BPF_FILTER_ID \
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
+#define BPF_PACKET_SIZE \
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
+#define BPF_CURRENT_OFFSET \
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
+#define BPF_PROGRAM \
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
+#define BPF_MAX \
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
+
+static const struct nla_policy
+wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
+ [BPF_SET_RESET] = {.type = NLA_U32},
+ [BPF_VERSION] = {.type = NLA_U32},
+ [BPF_FILTER_ID] = {.type = NLA_U32},
+ [BPF_PACKET_SIZE] = {.type = NLA_U32},
+ [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
+ [BPF_PROGRAM] = {.type = NLA_U8},
+};
+
+struct bpf_offload_priv {
+ struct sir_bpf_get_offload bpf_get_offload;
+};
+
+static void hdd_get_bpf_offload_cb(void *context,
+ struct sir_bpf_get_offload *data)
+{
+ struct hdd_request *request;
+ struct bpf_offload_priv *priv;
+
+ hdd_enter();
+
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request");
+ return;
+ }
+
+ priv = hdd_request_priv(request);
+ priv->bpf_get_offload = *data;
+ hdd_request_complete(request);
+ hdd_request_put(request);
+}
+
+/**
+ * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
+ * @hdd_context: hdd_context
+ * @bpf_get_offload: struct for get offload
+ *
+ * Return: 0 on success, error number otherwise.
+ */
+static int hdd_post_get_bpf_capabilities_rsp(struct hdd_context *hdd_ctx,
+ struct sir_bpf_get_offload *bpf_get_offload)
+{
+ struct sk_buff *skb;
+ uint32_t nl_buf_len;
+
+ hdd_enter();
+
+ nl_buf_len = NLMSG_HDRLEN;
+ nl_buf_len +=
+ (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
+ (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
+
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
+ if (!skb) {
+ hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+ return -ENOMEM;
+ }
+
+ hdd_debug("BPF Version: %u BPF max bytes: %u",
+ bpf_get_offload->bpf_version,
+ bpf_get_offload->max_bytes_for_bpf_inst);
+
+ if (nla_put_u32(skb, BPF_PACKET_SIZE,
+ bpf_get_offload->max_bytes_for_bpf_inst) ||
+ nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
+ hdd_err("nla put failure");
+ goto nla_put_failure;
+ }
+
+ cfg80211_vendor_cmd_reply(skb);
+ hdd_exit();
+ return 0;
+
+nla_put_failure:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+/**
+ * hdd_get_bpf_offload - Get BPF offload Capabilities
+ * @hdd_ctx: Hdd context
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int hdd_get_bpf_offload(struct hdd_context *hdd_ctx)
+{
+ QDF_STATUS status;
+ int ret;
+ void *cookie;
+ struct hdd_request *request;
+ struct bpf_offload_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_BPF,
+ };
+
+ hdd_enter();
+
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Unable to allocate request");
+ return -EINVAL;
+ }
+ cookie = hdd_request_cookie(request);
+
+ status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
+ hdd_get_bpf_offload_cb,
+ cookie);
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
+ hdd_err("Unable to retrieve BPF caps");
+ ret = qdf_status_to_os_return(status);
+ goto cleanup;
+ }
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
+ hdd_err("Target response timed out");
+ goto cleanup;
+ }
+ priv = hdd_request_priv(request);
+ ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
+ &priv->bpf_get_offload);
+ if (ret)
+ hdd_err("Failed to post get bpf capabilities");
+
+cleanup:
+ /*
+ * either we never sent a request to SME, we sent a request to
+ * SME and timed out, or we sent a request to SME, received a
+ * response from SME, and posted the response to userspace.
+ * regardless we are done with the request.
+ */
+ hdd_request_put(request);
+ hdd_exit();
+
+ return ret;
+}
+
+/**
+ * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
+ * @hdd_ctx: Hdd context
+ * @tb: Length of @data
+ * @adapter: pointer to adapter struct
+ *
+ * Return: 0 on success; errno on failure
+ */
+static int hdd_set_reset_bpf_offload(struct hdd_context *hdd_ctx,
+ struct nlattr **tb,
+ struct hdd_adapter *adapter)
+{
+ struct sir_bpf_set_offload *bpf_set_offload;
+ QDF_STATUS status;
+ int prog_len;
+ int ret = 0;
+
+ hdd_enter();
+
+ if (adapter->device_mode == QDF_STA_MODE ||
+ adapter->device_mode == QDF_P2P_CLIENT_MODE) {
+ if (!hdd_conn_is_connected(
+ WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
+ hdd_err("Not in Connected state!");
+ return -ENOTSUPP;
+ }
+ }
+
+ bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
+ if (bpf_set_offload == NULL) {
+ hdd_err("qdf_mem_malloc failed for bpf_set_offload");
+ return -ENOMEM;
+ }
+
+ /* Parse and fetch bpf packet size */
+ if (!tb[BPF_PACKET_SIZE]) {
+ hdd_err("attr bpf packet size failed");
+ ret = -EINVAL;
+ goto fail;
+ }
+ bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
+
+ if (!bpf_set_offload->total_length) {
+ hdd_debug("BPF reset packet filter received");
+ goto post_sme;
+ }
+
+ /* Parse and fetch bpf program */
+ if (!tb[BPF_PROGRAM]) {
+ hdd_err("attr bpf program failed");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ prog_len = nla_len(tb[BPF_PROGRAM]);
+ bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
+
+ if (bpf_set_offload->program == NULL) {
+ hdd_err("qdf_mem_malloc failed for bpf offload program");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ bpf_set_offload->current_length = prog_len;
+ nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
+ bpf_set_offload->session_id = adapter->session_id;
+
+ hdd_debug("BPF set instructions");
+ QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
+ bpf_set_offload->program, prog_len);
+
+ /* Parse and fetch filter Id */
+ if (!tb[BPF_FILTER_ID]) {
+ hdd_err("attr filter id failed");
+ ret = -EINVAL;
+ goto fail;
+ }
+ bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
+
+ /* Parse and fetch current offset */
+ if (!tb[BPF_CURRENT_OFFSET]) {
+ hdd_err("attr current offset failed");
+ ret = -EINVAL;
+ goto fail;
+ }
+ bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
+
+post_sme:
+ hdd_debug("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
+ bpf_set_offload->session_id,
+ bpf_set_offload->version,
+ bpf_set_offload->filter_id,
+ bpf_set_offload->total_length,
+ bpf_set_offload->current_length,
+ bpf_set_offload->current_offset);
+
+ status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
+ hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
+ ret = -EINVAL;
+ goto fail;
+ }
+ hdd_exit();
+
+fail:
+ if (bpf_set_offload->current_length)
+ qdf_mem_free(bpf_set_offload->program);
+ qdf_mem_free(bpf_set_offload);
+ return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
+ * @wiphy: wiphy structure pointer
+ * @wdev: Wireless device structure pointer
+ * @data: Pointer to the data received
+ * @data_len: Length of @data
+ *
+ * Return: 0 on success; errno on failure
+ */
+static int
+__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+ struct net_device *dev = wdev->netdev;
+ struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ struct nlattr *tb[BPF_MAX + 1];
+ int ret_val, packet_filter_subcmd;
+
+ hdd_enter();
+
+ ret_val = wlan_hdd_validate_context(hdd_ctx);
+ if (ret_val)
+ return ret_val;
+
+ if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+ hdd_err("Command not allowed in FTM mode");
+ return -EINVAL;
+ }
+
+ if (!hdd_ctx->bpf_enabled) {
+ hdd_err("BPF offload is not supported/enabled");
+ return -ENOTSUPP;
+ }
+
+ if (wlan_cfg80211_nla_parse(tb, BPF_MAX, data, data_len,
+ wlan_hdd_bpf_offload_policy)) {
+ hdd_err("Invalid ATTR");
+ return -EINVAL;
+ }
+
+ if (!tb[BPF_SET_RESET]) {
+ hdd_err("attr bpf set reset failed");
+ return -EINVAL;
+ }
+
+ packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
+
+ if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
+ return hdd_get_bpf_offload(hdd_ctx);
+ else
+ return hdd_set_reset_bpf_offload(hdd_ctx, tb,
+ adapter);
+}
+
+int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ int ret;
+
+ cds_ssr_protect(__func__);
+ ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
+ cds_ssr_unprotect(__func__);
+
+ return ret;
+}
+
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 387f854..8fafa19 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -92,6 +92,7 @@
#include "wlan_hdd_disa.h"
#include "wlan_hdd_request_manager.h"
#include "wlan_hdd_he.h"
+#include "wlan_hdd_apf.h"
#include <cdp_txrx_cmn.h>
#include <cdp_txrx_misc.h>
@@ -9594,368 +9595,6 @@
return ret;
}
-/*
- * define short names for the global vendor params
- * used by __wlan_hdd_cfg80211_bpf_offload()
- */
-#define BPF_INVALID \
- QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
-#define BPF_SET_RESET \
- QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
-#define BPF_VERSION \
- QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
-#define BPF_FILTER_ID \
- QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
-#define BPF_PACKET_SIZE \
- QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
-#define BPF_CURRENT_OFFSET \
- QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
-#define BPF_PROGRAM \
- QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
-#define BPF_MAX \
- QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
-
-static const struct nla_policy
-wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
- [BPF_SET_RESET] = {.type = NLA_U32},
- [BPF_VERSION] = {.type = NLA_U32},
- [BPF_FILTER_ID] = {.type = NLA_U32},
- [BPF_PACKET_SIZE] = {.type = NLA_U32},
- [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
- [BPF_PROGRAM] = {.type = NLA_U8},
-};
-
-struct bpf_offload_priv {
- struct sir_bpf_get_offload bpf_get_offload;
-};
-
-/**
- * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
- * @context: opaque context originally passed to SME. HDD always passes
- * a cookie for the request context
- * @bpf_get_offload: struct for get offload
- *
- * This function receives the response/data from the lower layer and
- * checks to see if the thread is still waiting then post the results to
- * upper layer, if the request has timed out then ignore.
- *
- * Return: None
- */
-static void hdd_get_bpf_offload_cb(void *context,
- struct sir_bpf_get_offload *data)
-{
- struct hdd_request *request;
- struct bpf_offload_priv *priv;
-
- hdd_enter();
-
- request = hdd_request_get(context);
- if (!request) {
- hdd_err("Obsolete request");
- return;
- }
-
- priv = hdd_request_priv(request);
- priv->bpf_get_offload = *data;
- hdd_request_complete(request);
- hdd_request_put(request);
-}
-
-/**
- * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
- * @hdd_context: hdd_context
- * @bpf_get_offload: struct for get offload
- *
- * Return: 0 on success, error number otherwise.
- */
-static int hdd_post_get_bpf_capabilities_rsp(struct hdd_context *hdd_ctx,
- struct sir_bpf_get_offload *bpf_get_offload)
-{
- struct sk_buff *skb;
- uint32_t nl_buf_len;
-
- hdd_enter();
-
- nl_buf_len = NLMSG_HDRLEN;
- nl_buf_len +=
- (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
- (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
-
- skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
- if (!skb) {
- hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
- return -ENOMEM;
- }
-
- hdd_debug("BPF Version: %u BPF max bytes: %u",
- bpf_get_offload->bpf_version,
- bpf_get_offload->max_bytes_for_bpf_inst);
-
- if (nla_put_u32(skb, BPF_PACKET_SIZE,
- bpf_get_offload->max_bytes_for_bpf_inst) ||
- nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
- hdd_err("nla put failure");
- goto nla_put_failure;
- }
-
- cfg80211_vendor_cmd_reply(skb);
- hdd_exit();
- return 0;
-
-nla_put_failure:
- kfree_skb(skb);
- return -EINVAL;
-}
-
-/**
- * hdd_get_bpf_offload - Get BPF offload Capabilities
- * @hdd_ctx: Hdd context
- *
- * Return: 0 on success, errno on failure
- */
-static int hdd_get_bpf_offload(struct hdd_context *hdd_ctx)
-{
- QDF_STATUS status;
- int ret;
- void *cookie;
- struct hdd_request *request;
- struct bpf_offload_priv *priv;
- static const struct hdd_request_params params = {
- .priv_size = sizeof(*priv),
- .timeout_ms = WLAN_WAIT_TIME_BPF,
- };
-
- hdd_enter();
-
- request = hdd_request_alloc(¶ms);
- if (!request) {
- hdd_err("Unable to allocate request");
- return -EINVAL;
- }
- cookie = hdd_request_cookie(request);
-
- status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
- hdd_get_bpf_offload_cb,
- cookie);
- if (!QDF_IS_STATUS_SUCCESS(status)) {
- hdd_err("Unable to retrieve BPF caps");
- ret = qdf_status_to_os_return(status);
- goto cleanup;
- }
- ret = hdd_request_wait_for_response(request);
- if (ret) {
- hdd_err("Target response timed out");
- goto cleanup;
- }
- priv = hdd_request_priv(request);
- ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
- &priv->bpf_get_offload);
- if (ret)
- hdd_err("Failed to post get bpf capabilities");
-
-cleanup:
- /*
- * either we never sent a request to SME, we sent a request to
- * SME and timed out, or we sent a request to SME, received a
- * response from SME, and posted the response to userspace.
- * regardless we are done with the request.
- */
- hdd_request_put(request);
- hdd_exit();
-
- return ret;
-}
-
-/**
- * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
- * @hdd_ctx: Hdd context
- * @tb: Length of @data
- * @adapter: pointer to adapter struct
- *
- * Return: 0 on success; errno on failure
- */
-static int hdd_set_reset_bpf_offload(struct hdd_context *hdd_ctx,
- struct nlattr **tb,
- struct hdd_adapter *adapter)
-{
- struct sir_bpf_set_offload *bpf_set_offload;
- QDF_STATUS status;
- int prog_len;
- int ret = 0;
-
- hdd_enter();
-
- if (adapter->device_mode == QDF_STA_MODE ||
- adapter->device_mode == QDF_P2P_CLIENT_MODE) {
- if (!hdd_conn_is_connected(
- WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
- hdd_err("Not in Connected state!");
- return -ENOTSUPP;
- }
- }
-
- bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
- if (bpf_set_offload == NULL) {
- hdd_err("qdf_mem_malloc failed for bpf_set_offload");
- return -ENOMEM;
- }
-
- /* Parse and fetch bpf packet size */
- if (!tb[BPF_PACKET_SIZE]) {
- hdd_err("attr bpf packet size failed");
- ret = -EINVAL;
- goto fail;
- }
- bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
-
- if (!bpf_set_offload->total_length) {
- hdd_debug("BPF reset packet filter received");
- goto post_sme;
- }
-
- /* Parse and fetch bpf program */
- if (!tb[BPF_PROGRAM]) {
- hdd_err("attr bpf program failed");
- ret = -EINVAL;
- goto fail;
- }
-
- prog_len = nla_len(tb[BPF_PROGRAM]);
- bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
-
- if (bpf_set_offload->program == NULL) {
- hdd_err("qdf_mem_malloc failed for bpf offload program");
- ret = -ENOMEM;
- goto fail;
- }
-
- bpf_set_offload->current_length = prog_len;
- nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
- bpf_set_offload->session_id = adapter->session_id;
-
- hdd_debug("BPF set instructions");
- QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
- bpf_set_offload->program, prog_len);
-
- /* Parse and fetch filter Id */
- if (!tb[BPF_FILTER_ID]) {
- hdd_err("attr filter id failed");
- ret = -EINVAL;
- goto fail;
- }
- bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
-
- /* Parse and fetch current offset */
- if (!tb[BPF_CURRENT_OFFSET]) {
- hdd_err("attr current offset failed");
- ret = -EINVAL;
- goto fail;
- }
- bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
-
-post_sme:
- hdd_debug("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
- bpf_set_offload->session_id,
- bpf_set_offload->version,
- bpf_set_offload->filter_id,
- bpf_set_offload->total_length,
- bpf_set_offload->current_length,
- bpf_set_offload->current_offset);
-
- status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
- if (!QDF_IS_STATUS_SUCCESS(status)) {
- hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
- ret = -EINVAL;
- goto fail;
- }
- hdd_exit();
-
-fail:
- if (bpf_set_offload->current_length)
- qdf_mem_free(bpf_set_offload->program);
- qdf_mem_free(bpf_set_offload);
- return ret;
-}
-
-/**
- * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
- * @wiphy: wiphy structure pointer
- * @wdev: Wireless device structure pointer
- * @data: Pointer to the data received
- * @data_len: Length of @data
- *
- * Return: 0 on success; errno on failure
- */
-static int
-__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
- struct wireless_dev *wdev,
- const void *data, int data_len)
-{
- struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
- struct net_device *dev = wdev->netdev;
- struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
- struct nlattr *tb[BPF_MAX + 1];
- int ret_val, packet_filter_subcmd;
-
- hdd_enter();
-
- ret_val = wlan_hdd_validate_context(hdd_ctx);
- if (ret_val)
- return ret_val;
-
- if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
- hdd_err("Command not allowed in FTM mode");
- return -EINVAL;
- }
-
- if (!hdd_ctx->bpf_enabled) {
- hdd_err("BPF offload is not supported/enabled");
- return -ENOTSUPP;
- }
-
- if (wlan_cfg80211_nla_parse(tb, BPF_MAX, data, data_len,
- wlan_hdd_bpf_offload_policy)) {
- hdd_err("Invalid ATTR");
- return -EINVAL;
- }
-
- if (!tb[BPF_SET_RESET]) {
- hdd_err("attr bpf set reset failed");
- return -EINVAL;
- }
-
- packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
-
- if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
- return hdd_get_bpf_offload(hdd_ctx);
- else
- return hdd_set_reset_bpf_offload(hdd_ctx, tb,
- adapter);
-}
-
-/**
- * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
- * @wiphy: wiphy structure pointer
- * @wdev: Wireless device structure pointer
- * @data: Pointer to the data received
- * @data_len: Length of @data
- *
- * Return: 0 on success; errno on failure
- */
-
-static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
- struct wireless_dev *wdev,
- const void *data, int data_len)
-{
- int ret;
-
- cds_ssr_protect(__func__);
- ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
- cds_ssr_unprotect(__func__);
-
- return ret;
-}
-
/**
* wlan_hdd_set_pre_cac_status() - Set the pre cac status
* @pre_cac_adapter: AP adapter used for pre cac
@@ -14772,6 +14411,7 @@
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlan_hdd_cfg80211_txpower_scale_decr_db
},
+#ifdef FEATURE_WLAN_APF
{
.info.vendor_id = QCA_NL80211_VENDOR_ID,
.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
@@ -14780,6 +14420,7 @@
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlan_hdd_cfg80211_bpf_offload
},
+#endif /* FEATURE_WLAN_APF */
{
.info.vendor_id = QCA_NL80211_VENDOR_ID,
.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 76a7086..5397f91 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -130,6 +130,7 @@
#include "wlan_ipa_ucfg_api.h"
#include <target_if.h>
#include "wlan_hdd_nud_tracking.h"
+#include "wlan_hdd_apf.h"
#ifdef CNSS_GENL
#include <net/cnss_nl.h>