summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubhani Shaik <subhanis@codeaurora.org>2016-01-19 17:56:50 +0530
committerSubhani Shaik <subhanis@codeaurora.org>2016-01-25 09:57:06 -0800
commitcdbde22981846f02ce30a940b22a3f3c44ebba0d (patch)
treec252b1a4e032528882bc3aeee0e3dc2e2fb3d0d5
parent0562eeb882b461595155d6ef3e10e563b0e451f5 (diff)
downloadwlan-cdbde22981846f02ce30a940b22a3f3c44ebba0d.tar.gz
WiFi-HAL: Support for packet filtering APIs
These APIs allow driver/firmware to start packet filtering when framework enables filters Change-Id: I10a5ef17e7266a520854061f0a2aa24a5f77db03
-rw-r--r--qcwcn/wifi_hal/common.h1
-rwxr-xr-xqcwcn/wifi_hal/ifaceeventhandler.cpp65
-rwxr-xr-xqcwcn/wifi_hal/ifaceeventhandler.h6
-rw-r--r--qcwcn/wifi_hal/vendor_definitions.h32
-rw-r--r--qcwcn/wifi_hal/wifi_hal.cpp184
5 files changed, 287 insertions, 1 deletions
diff --git a/qcwcn/wifi_hal/common.h b/qcwcn/wifi_hal/common.h
index c7dbf6e..20c0c41 100644
--- a/qcwcn/wifi_hal/common.h
+++ b/qcwcn/wifi_hal/common.h
@@ -133,6 +133,7 @@ typedef struct hal_info_s {
pthread_mutex_t lh_lock;
/* mutex for the alert_handler access*/
pthread_mutex_t ah_lock;
+ u32 firmware_bus_max_size;
} hal_info;
wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg);
diff --git a/qcwcn/wifi_hal/ifaceeventhandler.cpp b/qcwcn/wifi_hal/ifaceeventhandler.cpp
index 39f5710..3a60844 100755
--- a/qcwcn/wifi_hal/ifaceeventhandler.cpp
+++ b/qcwcn/wifi_hal/ifaceeventhandler.cpp
@@ -208,6 +208,9 @@ WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
mSetSizeMax = 0;
mSetSizePtr = NULL;
mConcurrencySet = 0;
+ filterVersion = 0;
+ filterLength = 0;
+ firmware_bus_max_size = 0;
}
WifihalGeneric::~WifihalGeneric()
@@ -291,6 +294,56 @@ int WifihalGeneric::handleResponse(WifiEvent &reply)
}
}
break;
+ case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER:
+ {
+ struct nlattr *tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ filterVersion = nla_get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]);
+ ALOGI("Current version : %u", filterVersion);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ filterLength = nla_get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]);
+ ALOGI("Max filter length Supported : %u", filterLength);
+
+ }
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE:
+ {
+ struct nlattr *tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
+ (struct nlattr *)mVendorData,
+ mDataLen, NULL);
+
+ if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_BUS_SIZE_MAX])
+ {
+ ALOGE("%s: QCA_WLAN_VENDOR_ATTR_BUS_SIZE_MAX"
+ " not found", __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+ firmware_bus_max_size = nla_get_u32(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_BUS_SIZE_MAX]);
+ ALOGI("Max BUS size Supported: %d", firmware_bus_max_size);
+
+ }
+ break;
default :
ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
}
@@ -313,3 +366,15 @@ void WifihalGeneric::setConcurrencySet(feature_set set[]) {
void WifihalGeneric::setSizePtr(int *set_size) {
mSetSizePtr = set_size;
}
+
+int WifihalGeneric::getFilterVersion() {
+ return filterVersion;
+}
+
+int WifihalGeneric::getFilterLength() {
+ return filterLength;
+}
+
+int WifihalGeneric::getBusSize() {
+ return firmware_bus_max_size;
+}
diff --git a/qcwcn/wifi_hal/ifaceeventhandler.h b/qcwcn/wifi_hal/ifaceeventhandler.h
index e30966b..3ad03ed 100755
--- a/qcwcn/wifi_hal/ifaceeventhandler.h
+++ b/qcwcn/wifi_hal/ifaceeventhandler.h
@@ -88,6 +88,9 @@ private:
int mSetSizeMax;
int *mSetSizePtr;
feature_set *mConcurrencySet;
+ int filterVersion;
+ int filterLength;
+ int firmware_bus_max_size;
public:
WifihalGeneric(wifi_handle handle, int id, u32 vendor_id, u32 subcmd);
@@ -98,6 +101,9 @@ public:
virtual void setMaxSetSize(int set_size_max);
virtual void setSizePtr(int *set_size);
virtual void setConcurrencySet(feature_set set[]);
+ virtual int getFilterVersion();
+ virtual int getFilterLength();
+ virtual int getBusSize();
};
#ifdef __cplusplus
}
diff --git a/qcwcn/wifi_hal/vendor_definitions.h b/qcwcn/wifi_hal/vendor_definitions.h
index 6e2088a..e3de742 100644
--- a/qcwcn/wifi_hal/vendor_definitions.h
+++ b/qcwcn/wifi_hal/vendor_definitions.h
@@ -94,7 +94,10 @@
#define QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS 79
/* RSSI monitoring*/
#define QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI 80
-
+/* Set packet filter for BPF*/
+#define QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER 83
+/* Get Driver-firmware interface maximum supported size*/
+#define QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE 84
#endif
enum qca_wlan_vendor_attr_ll_stats_set
@@ -1188,4 +1191,31 @@ enum qca_wlan_vendor_attr_rssi_monitoring
QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST - 1,
};
+
+#define PACKET_FILTER_ID 0
+
+enum packet_filter_sub_cmd
+{
+ QCA_WLAN_SET_PACKET_FILTER = 1,
+ QCA_WLAN_GET_PACKET_FILTER_SIZE = 2,
+};
+
+enum qca_wlan_vendor_attr_packet_filter
+{
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID = 0,
+
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION,
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
+ QCA_WLAN_VENDOR_ATTR_BUS_SIZE_MAX,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX =
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST - 1,
+
+};
#endif
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp
index 48be8c7..06effbe 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/qcwcn/wifi_hal/wifi_hal.cpp
@@ -71,6 +71,10 @@ static int wifi_get_multicast_id(wifi_handle handle, const char *name,
const char *group);
static int wifi_add_membership(wifi_handle handle, const char *group);
static wifi_error wifi_init_interfaces(wifi_handle handle);
+static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
+ const u8 *program, u32 len);
+static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
+ u32 *version, u32 *max_len);
/* Initialize/Cleanup */
@@ -191,6 +195,38 @@ cleanup:
return (wifi_error)ret;
}
+static wifi_error get_firmware_bus_max_size_supported(
+ wifi_interface_handle iface)
+{
+ int ret = 0;
+ interface_info *iinfo = getIfaceInfo(iface);
+ wifi_handle handle = getWifiHandle(iface);
+ hal_info *info = (hal_info *)handle;
+
+ WifihalGeneric busSizeSupported(handle, 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
+
+ /* create the message */
+ ret = busSizeSupported.create();
+ if (ret < 0)
+ goto cleanup;
+
+ ret = busSizeSupported.set_iface_id(iinfo->name);
+ if (ret < 0)
+ goto cleanup;
+
+ ret = busSizeSupported.requestResponse();
+ if (ret != 0) {
+ ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
+ goto cleanup;
+ }
+ info->firmware_bus_max_size = busSizeSupported.getBusSize();
+
+cleanup:
+ return (wifi_error)ret;
+}
+
static wifi_error wifi_init_user_sock(hal_info *info)
{
struct nl_sock *user_sock =
@@ -309,6 +345,8 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
fn->wifi_nan_register_handler = nan_register_handler;
fn->wifi_nan_get_version = nan_get_version;
+ fn->wifi_set_packet_filter = wifi_set_packet_filter;
+ fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
return WIFI_SUCCESS;
}
@@ -467,6 +505,12 @@ wifi_error wifi_initialize(wifi_handle *handle)
ret = WIFI_SUCCESS;
}
+ ret = get_firmware_bus_max_size_supported(iface_handle);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("Failed to get supported bus size, error : %d", ret);
+ info->firmware_bus_max_size = 1520;
+ }
+
ret = wifi_logger_ring_buffers_init(info);
if (ret != WIFI_SUCCESS) {
ALOGE("Wifi Logger Ring Initialization Failed");
@@ -1188,3 +1232,143 @@ cleanup:
delete vCommand;
return (wifi_error)ret;
}
+
+static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
+ const u8 *program, u32 len)
+{
+ int ret = WIFI_SUCCESS;
+ struct nlattr *nlData;
+ WifiVendorCommand *vCommand = NULL;
+ u32 current_offset = 0;
+ wifi_handle wifiHandle = getWifiHandle(iface);
+ hal_info *info = getHalInfo(wifiHandle);
+
+ /* len=0 clears the filters in driver/firmware */
+ if (len != 0 && program == NULL) {
+ ALOGE("%s: No valid program provided. Exit.",
+ __func__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ ret = initialize_vendor_cmd(iface, get_requestid(),
+ QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
+ &vCommand);
+ if (ret != WIFI_SUCCESS) {
+ ALOGE("%s: Initialization failed", __FUNCTION__);
+ return (wifi_error)ret;
+ }
+
+ do {
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData)
+ goto cleanup;
+
+ if (vCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
+ QCA_WLAN_SET_PACKET_FILTER) ||
+ vCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
+ PACKET_FILTER_ID) ||
+ vCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
+ len) ||
+ vCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
+ current_offset)) {
+ ALOGE("%s: failed to put subcmd/program", __FUNCTION__);
+ goto cleanup;
+ }
+
+ if (len) {
+ if(vCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
+ (char *)&program[current_offset],
+ min(info->firmware_bus_max_size,
+ len-current_offset))) {
+ ALOGE("%s: failed to put subcmd", __FUNCTION__);
+ goto cleanup;
+ }
+ }
+
+ vCommand->attr_end(nlData);
+
+ ret = vCommand->requestResponse();
+ if (ret < 0) {
+ ALOGE("%s: requestResponse Error:%d",__func__, ret);
+ goto cleanup;
+ }
+
+ current_offset += min(info->firmware_bus_max_size, len);
+ } while (current_offset < len);
+
+cleanup:
+ delete vCommand;
+ return (wifi_error)ret;
+}
+
+static wifi_error wifi_get_packet_filter_capabilities(
+ wifi_interface_handle handle, u32 *version, u32 *max_len)
+{
+ int ret = 0;
+ struct nlattr *nlData;
+ WifihalGeneric *vCommand = NULL;
+ interface_info *ifaceInfo = getIfaceInfo(handle);
+ wifi_handle wifiHandle = getWifiHandle(handle);
+
+ if (version == NULL || max_len == NULL) {
+ ALOGE("%s: NULL version/max_len pointer provided. Exit.",
+ __FUNCTION__);
+ return WIFI_ERROR_INVALID_ARGS;
+ }
+
+ vCommand = new WifihalGeneric(wifiHandle, 0,
+ OUI_QCA,
+ QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
+ if (vCommand == NULL) {
+ ALOGE("%s: Error vCommand NULL", __FUNCTION__);
+ return WIFI_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Create the message */
+ ret = vCommand->create();
+ if (ret < 0)
+ goto cleanup;
+
+ ret = vCommand->set_iface_id(ifaceInfo->name);
+ if (ret < 0)
+ goto cleanup;
+
+ /* Add the vendor specific attributes for the NL command. */
+ nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
+ if (!nlData)
+ goto cleanup;
+
+ if (vCommand->put_u32(
+ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
+ QCA_WLAN_GET_PACKET_FILTER_SIZE))
+ {
+ goto cleanup;
+ }
+ vCommand->attr_end(nlData);
+
+ ret = vCommand->requestResponse();
+ if (ret) {
+ ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
+ if (ret == -ENOTSUP) {
+ /* Packet filtering is not supported currently, so return version
+ * and length as 0
+ */
+ ALOGI("Packet filtering is not supprted");
+ *version = 0;
+ *max_len = 0;
+ ret = WIFI_SUCCESS;
+ }
+ goto cleanup;
+ }
+
+ *version = vCommand->getFilterVersion();
+ *max_len = vCommand->getFilterLength();
+cleanup:
+ delete vCommand;
+ return (wifi_error)ret;
+}