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);