diff options
author | Subhani Shaik <subhanis@codeaurora.org> | 2016-01-19 17:56:50 +0530 |
---|---|---|
committer | Subhani Shaik <subhanis@codeaurora.org> | 2016-01-25 09:57:06 -0800 |
commit | cdbde22981846f02ce30a940b22a3f3c44ebba0d (patch) | |
tree | c252b1a4e032528882bc3aeee0e3dc2e2fb3d0d5 | |
parent | 0562eeb882b461595155d6ef3e10e563b0e451f5 (diff) | |
download | wlan-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.h | 1 | ||||
-rwxr-xr-x | qcwcn/wifi_hal/ifaceeventhandler.cpp | 65 | ||||
-rwxr-xr-x | qcwcn/wifi_hal/ifaceeventhandler.h | 6 | ||||
-rw-r--r-- | qcwcn/wifi_hal/vendor_definitions.h | 32 | ||||
-rw-r--r-- | qcwcn/wifi_hal/wifi_hal.cpp | 184 |
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; +} |