diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 30e38f6aaa96..796fbf254cbc 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -13105,6 +13105,44 @@ enum hdd_external_acs_freq_band { #define CFG_MBO_CAND_RSSI_BTC_THRESHOLD_MAX (0) +/* + * + * g_enable_packet_filter_bitmap - Enable Packet filters before going into + * suspend mode + * @Min: 0 + * @Max: 63 + * @Default: 0 + * Below is the Detailed bit map of the Filters + * bit-0 : IPv6 multicast + * bit-1 : IPv4 multicast + * bit-2 : IPv4 broadcast + * bit-3 : XID - Exchange station Identification packet, solicits the + * identification of the receiving station + * bit-4 : STP - Spanning Tree Protocol, builds logical loop free topology + * bit-5 : DTP/LLC/CDP + * DTP - Dynamic Trunking Protocol is used by Ciscoswitches to negotiate + * whether an interconnection between two switches should be put into access or + * trunk mode + * LLC - Logical link control, used for multiplexing, flow & error control + * CDP - Cisco Discovery Protocol packet contains information about the cisco + * devices in the network + * + * This ini support to enable above mentioned packet filters + * when target goes to suspend mode, clear those when resume + * + * Related: None + * + * Supported Feature: PACKET FILTERING + * + * Usage: Internal/External + * + * + */ +#define CFG_ENABLE_PACKET_FILTERS_NAME "g_enable_packet_filter_bitmap" +#define CFG_ENABLE_PACKET_FILTERS_DEFAULT (0) +#define CFG_ENABLE_PACKET_FILTERS_MIN (0) +#define CFG_ENABLE_PACKET_FILTERS_MAX (63) + /* * Type declarations */ @@ -13961,6 +13999,7 @@ struct hdd_config { int8_t mbo_current_rssi_thres; int8_t mbo_current_rssi_mcc_thres; int8_t mbo_candidate_rssi_btc_thres; + uint8_t packet_filters_bitmap; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 65950c9ca6b3..d1291489e49a 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1781,6 +1781,7 @@ struct hdd_context { eCsrBand curr_band; bool fw_mem_dump_enabled; bool imps_enabled; + int user_configured_pkt_filter_rules; }; /** diff --git a/core/hdd/inc/wlan_hdd_packet_filter_api.h b/core/hdd/inc/wlan_hdd_packet_filter_api.h new file mode 100644 index 000000000000..67c2c8fa8367 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_packet_filter_api.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017 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. + */ + +#if !defined(WLAN_HDD_PACKET_FILTER_API_H__) +#define WLAN_HDD_PACKET_FILTER_API_H__ + +/** + * DOC: wlan_hdd_packet_filter_rules.h + * + */ + +/* Include files */ + +/** + * hdd_enable_default_pkt_filters() - Enable default packet filters based + * on, filters bit map provided in INI, when target goes to suspend mode + * @adapter: Adapter context for which default filters to be configure + * + * Return: zero if success, non-zero otherwise + */ +int hdd_enable_default_pkt_filters(struct hdd_adapter *pAadapter); + +/** + * hdd_disable_default_pkt_filters() - Disable default packet filters based + * on, filters bit map provided in INI, when target resumes + * @adapter: Adapter context for which default filters to be cleared + * + * Return: zero if success, non-zero otherwise + */ +int hdd_disable_default_pkt_filters(struct hdd_adapter *adapter); + +/** + * wlan_hdd_set_filter() - Set packet filter + * @hdd_ctx: Global HDD context + * @request: Packet filter request struct + * @sessionId: Target session for the request + * + * Return: 0 on success, non-zero on error + */ +int wlan_hdd_set_filter(struct hdd_context *hdd_ctx, + struct pkt_filter_cfg *request, + uint8_t sessionId); +#endif diff --git a/core/hdd/inc/wlan_hdd_packet_filter_rules.h b/core/hdd/inc/wlan_hdd_packet_filter_rules.h new file mode 100644 index 000000000000..64739aeeeef5 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_packet_filter_rules.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2017 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. + */ + +#if !defined(WLAN_HDD_PACKET_FILTER_RULES_H__) +#define WLAN_HDD_PACKET_FILTER_RULES_H__ + +/** + * DOC: wlan_hdd_packet_filter_rules.h + * + */ + +/* Include files */ + +#define MAX_NUM_PACKET_FILTERS 6 + +/** + * @filter_action: Filter action, set/clear the filter + * Ex: filter_action = 1 set the filter + * filter_action = 2 clear the filter + * @filter_id: Filter id Ex: 1/2/3/4/5 .... MAX_NUM_FILTERS + * @num_params: Number of parameters Ex: 1/2/3/4/5 + * @params_data: Packet filter parameters details + * + * @protocol_layer: the type of protocol layer header to which the data + * being configured correspond + * Ex: protocol_layer = 1 - MAC Header + * protocol_layer = 2 - ARP Header + * protocol_layer = 3 - IP Header + * @compare_flag: comparison type + * EX: compare_flag = 0 - comparison is invalid + * compare_flag = 1 - compare for equality of the data present in received + * packet to the corresponding configured data + * compare_flag = 2 - compare for equality of the data present in received + * packet to the corresponding configured data after + * applying the mask + * compare_flag = 3 - compare for non-equality of the data present in + * received packet to the corresponding configured data + * compare_flag = 4 - compare for non-equality of the data present in + * received packet to the corresponding configured data + * after applying the mask + * @data_fffset: Offset of the data to compare from the respective protocol + * layer header start (as per the respective protocol + * specification) in terms of bytes + * @data_length: length of data to compare + * @compare_data: Array of 8 bytes + * @data_mask: Mask to be applied on the received packet data (Array of 8 bytes) + */ +static const struct pkt_filter_cfg + packet_filter_default_rules[MAX_NUM_PACKET_FILTERS] = { + { .filter_action = 1, + .filter_id = 0, + .num_params = 3, + .params_data = { + { .protocol_layer = 1, + .compare_flag = 5, + .data_offset = 0, + .data_length = 1, + .compare_data = {1, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 2, + .compare_flag = 3, + .data_offset = 6, + .data_length = 2, + .compare_data = {134, 221, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 3, + .compare_flag = 4, + .data_offset = 24, + .data_length = 2, + .compare_data = {255, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {255, 0, 0, 0, 0, 0, 0, 0} } } }, + + { .filter_action = 1, + .filter_id = 0, + .num_params = 3, + .params_data = { + { .protocol_layer = 1, + .compare_flag = 5, + .data_offset = 0, + .data_length = 1, + .compare_data = {1, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 2, + .compare_flag = 3, + .data_offset = 6, + .data_length = 2, + .compare_data = {8, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 3, + .compare_flag = 4, + .data_offset = 16, + .data_length = 1, + .compare_data = {224, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {240, 0, 0, 0, 0, 0, 0, 0} } } }, + { .filter_action = 1, + .filter_id = 0, + .num_params = 3, + .params_data = { + { .protocol_layer = 1, + .compare_flag = 5, + .data_offset = 0, + .data_length = 1, + .compare_data = {1, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 2, + .compare_flag = 3, + .data_offset = 6, + .data_length = 2, + .compare_data = {8, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 3, + .compare_flag = 4, + .data_offset = 18, + .data_length = 2, + .compare_data = {0, 255, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 255, 0, 0, 0, 0, 0, 0} } } }, + { .filter_action = 1, + .filter_id = 0, + .num_params = 2, + .params_data = { + { .protocol_layer = 1, + .compare_flag = 5, + .data_offset = 0, + .data_length = 1, + .compare_data = {1, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 2, + .compare_flag = 3, + .data_offset = 8, + .data_length = 4, + .compare_data = {0, 1, 175, 129, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} } } }, + { .filter_action = 1, + .filter_id = 0, + .num_params = 2, + .params_data = { + { .protocol_layer = 1, + .compare_flag = 5, + .data_offset = 0, + .data_length = 1, + .compare_data = {1, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 2, + .compare_flag = 3, + .data_offset = 6, + .data_length = 2, + .compare_data = {0, 39, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} } } }, + { .filter_action = 1, + .filter_id = 0, + .num_params = 2, + .params_data = { + { .protocol_layer = 1, + .compare_flag = 5, + .data_offset = 0, + .data_length = 1, + .compare_data = {1, 0, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} }, + { .protocol_layer = 2, + .compare_flag = 3, + .data_offset = 4, + .data_length = 2, + .compare_data = {0, 12, 0, 0, 0, 0, 0, 0}, + .data_mask = {0, 0, 0, 0, 0, 0, 0, 0} } } } }; +#endif diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index fd6f2a0ce77c..95a71981dfe6 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -5156,13 +5156,19 @@ struct reg_table_entry g_registry_table[] = { CFG_MBO_CAND_RSSI_BTC_THRESHOLD_DEFAULT, CFG_MBO_CAND_RSSI_BTC_THRESHOLD_MIN, CFG_MBO_CAND_RSSI_BTC_THRESHOLD_MAX), - REG_VARIABLE(CFG_IS_FILS_ENABLED_NAME, WLAN_PARAM_Integer, struct hdd_config, is_fils_enabled, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, CFG_IS_FILS_ENABLED_DEFAULT, CFG_IS_FILS_ENABLED_MIN, CFG_IS_FILS_ENABLED_MAX), + + REG_VARIABLE(CFG_ENABLE_PACKET_FILTERS_NAME, WLAN_PARAM_Integer, + struct hdd_config, packet_filters_bitmap, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_PACKET_FILTERS_DEFAULT, + CFG_ENABLE_PACKET_FILTERS_MIN, + CFG_ENABLE_PACKET_FILTERS_MAX), }; diff --git a/core/hdd/src/wlan_hdd_packet_filter.c b/core/hdd/src/wlan_hdd_packet_filter.c new file mode 100644 index 000000000000..525a45591b58 --- /dev/null +++ b/core/hdd/src/wlan_hdd_packet_filter.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 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_packet_filter.c + * + * WLAN Host Device Driver implementation + * + */ + +/* Include Files */ +#include "wlan_hdd_packet_filter_api.h" + +int hdd_enable_default_pkt_filters(struct hdd_adapter *adapter) +{ + struct hdd_context *hdd_ctx; + uint8_t filters = 0, i = 0, filter_id = 1; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (hdd_ctx == NULL) { + hdd_err("HDD context is Null!!!"); + return -EINVAL; + } + if (!hdd_ctx->user_configured_pkt_filter_rules) { + hdd_info("user has defined pkt filter run hence skipping default packet filter rule"); + return 0; + } + + filters = hdd_ctx->config->packet_filters_bitmap; + + while (filters != 0) { + if (filters & 0x1) { + hdd_err("setting filter[%d], of id = %d", + i+1, filter_id); + packet_filter_default_rules[i].filter_id = filter_id; + wlan_hdd_set_filter(hdd_ctx, + &packet_filter_default_rules[i], + adapter->sessionId); + filter_id++; + } + filters = filters >> 1; + i++; + } + + return 0; +} + +int hdd_disable_default_pkt_filters(struct hdd_adapter *adapter) +{ + struct hdd_context *hdd_ctx; + uint8_t filters = 0, i = 0, filter_id = 1; + + struct pkt_filter_cfg packet_filter_default_rules; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (hdd_ctx == NULL) { + hdd_err("HDD context is Null!!!"); + return -EINVAL; + } + + if (!hdd_ctx->user_configured_pkt_filter_rules) { + hdd_info("user has defined pkt filter run hence skipping default packet filter rule"); + return 0; + } + + filters = hdd_ctx->config->packet_filters_bitmap; + + while (filters != 0) { + if (filters & 0x1) { + hdd_err("Clearing filter[%d], of id = %d", + i+1, filter_id); + packet_filter_default_rules.filter_action = + HDD_RCV_FILTER_CLEAR; + packet_filter_default_rules.filter_id = i; + wlan_hdd_set_filter(hdd_ctx, + &packet_filter_default_rules, + adapter->sessionId); + filter_id++; + } + filters = filters >> 1; + i++; + } + + return 0; +} diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 6366faa2ce0e..0a3c8ed0d8cf 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -81,6 +81,7 @@ #include #include "scheduler_api.h" #include "cds_utils.h" +#include "wlan_hdd_packet_filter_api.h" /* Preprocessor definitions and constants */ #ifdef QCA_WIFI_NAPIER_EMULATION @@ -1098,6 +1099,9 @@ hdd_suspend_wlan(void) WLAN_STOP_ALL_NETIF_QUEUE, WLAN_CONTROL_PATH); + if (adapter->device_mode == QDF_STA_MODE) + status = hdd_enable_default_pkt_filters(adapter); + /* Configure supported OffLoads */ hdd_enable_host_offloads(adapter, pmo_apps_suspend); hdd_update_conn_state_mask(adapter, &conn_state_mask); @@ -1164,6 +1168,9 @@ static int hdd_resume_wlan(void) WLAN_WAKE_ALL_NETIF_QUEUE, WLAN_CONTROL_PATH); + if (adapter->device_mode == QDF_STA_MODE) + status = hdd_disable_default_pkt_filters(adapter); + next_adapter: status = hdd_get_next_adapter(hdd_ctx, pAdapterNode, &pNext); pAdapterNode = pNext; diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index bf4cdbc0c796..726b2cca9cd5 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -103,6 +103,7 @@ #include #include "wlan_hdd_regulatory.h" #include "wlan_reg_ucfg_api.h" +#include "wlan_hdd_packet_filter_api.h" #define HDD_FINISH_ULA_TIME_OUT 800 #define HDD_SET_MCBC_FILTERS_TO_FW 1 @@ -12049,7 +12050,7 @@ static int iw_set_keepalive_params(struct net_device *dev, * * Return: 0 on success, non-zero on error */ -static int wlan_hdd_set_filter(struct hdd_context *hdd_ctx, +int wlan_hdd_set_filter(struct hdd_context *hdd_ctx, struct pkt_filter_cfg *request, uint8_t sessionId) { @@ -12274,6 +12275,13 @@ static int __iw_set_packet_filter_params(struct net_device *dev, return -ENOMEM; } + if (request->filter_action == HDD_RCV_FILTER_SET) + hdd_ctx->user_configured_pkt_filter_rules |= + 1 << request->filter_id; + else if (request->filter_action == HDD_RCV_FILTER_CLEAR) + hdd_ctx->user_configured_pkt_filter_rules &= + ~(1 << request->filter_id); + ret = wlan_hdd_set_filter(hdd_ctx, request, adapter->sessionId); qdf_mem_free(request);