summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeev Kumar <rajekuma@qca.qualcomm.com>2015-09-02 22:56:09 -0700
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2015-09-09 15:11:02 +0530
commit24e1ca65136a579b854084b0fc4e66a6d5bfad3f (patch)
treeba608c563506fa5f01896684e0157262e8730179
parentd7d28b4a67813d4aff6c08683321d6de0e793564 (diff)
qcacld-2.0: Add support for RXFILTER driver command
- Add support for RXFILTER driver command for IPV4 multicast data packets - Enable/disable IP V4 MC packet filtering in FW based MC/BC list received from kernel Change-Id: I55f5806544bbdcb43b9af58f9875126f8a62afd4 CRs-Fixed: 904247
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h1
-rwxr-xr-xCORE/HDD/src/wlan_hdd_main.c163
2 files changed, 161 insertions, 3 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 2c7b3851b5ed..0b9b4aa53c27 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1000,6 +1000,7 @@ struct hdd_adapter_s
#ifdef WLAN_FEATURE_PACKET_FILTERING
t_multicast_add_list mc_addr_list;
#endif
+ uint8_t addr_filter_pattern;
//Magic cookie for adapter sanity verification
v_U32_t magic;
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 62343ce09895..4c298569ed81 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -3936,6 +3936,146 @@ static int drv_cmd_set_fcc_channel(hdd_context_t *hdd_ctx, uint8_t *cmd,
return ret;
}
+/**
+ * hdd_set_rx_filter() - set RX filter
+ * @adapter: Pointer to adapter
+ * @action: Filter action
+ * @pattern: Address pattern
+ *
+ * Address pattern is most significant byte of address for example
+ * 0x01 for IPV4 multicast address
+ * 0x33 for IPV6 multicast address
+ * 0xFF for broadcast address
+ *
+ * Return: 0 for success, non-zero for failure
+ */
+static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action,
+ uint8_t pattern)
+{
+ int ret;
+ uint8_t i;
+ tHalHandle handle;
+ tSirRcvFltMcAddrList *filter;
+ hdd_context_t* hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+ ret = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != ret)
+ return ret;
+
+ handle = hdd_ctx->hHal;
+
+ if (NULL == handle) {
+ hddLog(LOGE, FL("HAL Handle is NULL"));
+ return -EINVAL;
+ }
+
+ /*
+ * If action is false it means start dropping packets
+ * Set addr_filter_pattern which will be used when sending
+ * MC/BC address list to target
+ */
+ if (!action)
+ adapter->addr_filter_pattern = pattern;
+ else
+ adapter->addr_filter_pattern = 0;
+
+ if (((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
+ (adapter->device_mode == WLAN_HDD_P2P_CLIENT)) &&
+ adapter->mc_addr_list.mc_cnt &&
+ hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
+
+
+ filter = vos_mem_malloc(sizeof(*filter));
+ if (NULL == filter) {
+ hddLog(LOGE, FL("Could not allocate Memory"));
+ return -ENOMEM;
+ }
+ vos_mem_zero(filter, sizeof(*filter));
+ filter->action = action;
+ for (i = 0; i < adapter->mc_addr_list.mc_cnt; i++) {
+ if (!memcmp(adapter->mc_addr_list.addr[i],
+ &pattern, 1)) {
+ memcpy(filter->multicastAddr[i],
+ adapter->mc_addr_list.addr[i],
+ sizeof(adapter->mc_addr_list.addr[i]));
+ filter->ulMulticastAddrCnt++;
+ hddLog(LOGE, "%s RX filter : addr ="
+ MAC_ADDRESS_STR,
+ action ? "setting" : "clearing",
+ MAC_ADDR_ARRAY(filter->multicastAddr[i]));
+ }
+ }
+ /* Set rx filter */
+ sme_8023MulticastList(handle, adapter->sessionId, filter);
+ vos_mem_free(filter);
+ } else {
+ hddLog(LOGE, FL("mode %d mc_cnt %d"),
+ adapter->device_mode, adapter->mc_addr_list.mc_cnt);
+ }
+
+ return 0;
+}
+
+/**
+ * hdd_driver_rxfilter_comand_handler() - RXFILTER driver command handler
+ * @command: Pointer to input string driver command
+ * @adapter: Pointer to adapter
+ * @action: Action to enable/disable filtering
+ *
+ * If action == false
+ * Start filtering out data packets based on type
+ * RXFILTER-REMOVE 0 -> Start filtering out unicast data packets
+ * RXFILTER-REMOVE 1 -> Start filtering out broadcast data packets
+ * RXFILTER-REMOVE 2 -> Start filtering out IPV4 mcast data packets
+ * RXFILTER-REMOVE 3 -> Start filtering out IPV6 mcast data packets
+ *
+ * if action == true
+ * Stop filtering data packets based on type
+ * RXFILTER-ADD 0 -> Stop filtering unicast data packets
+ * RXFILTER-ADD 1 -> Stop filtering broadcast data packets
+ * RXFILTER-ADD 2 -> Stop filtering IPV4 mcast data packets
+ * RXFILTER-ADD 3 -> Stop filtering IPV6 mcast data packets
+ *
+ * Current implementation only supports IPV4 address filtering by
+ * selectively allowing IPV4 multicast data packest based on
+ * address list received in .ndo_set_rx_mode
+ *
+ * Return: 0 for success, non-zero for failure
+ */
+static int hdd_driver_rxfilter_comand_handler(uint8_t *command,
+ hdd_adapter_t *adapter,
+ bool action)
+{
+ int ret = 0;
+ uint8_t *value;
+ uint8_t type;
+
+ value = command;
+ /* Skip space after RXFILTER-REMOVE OR RXFILTER-ADD based on action */
+ if (!action)
+ value = command + 16;
+ else
+ value = command + 13;
+ ret = kstrtou8(value, 10, &type);
+ if (ret < 0) {
+ hddLog(LOGE,
+ FL("kstrtou8 failed invalid input value %d"), type);
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case 2:
+ /* Set rx filter for IPV4 multicast data packets */
+ ret = hdd_set_rx_filter(adapter, action, 0x01);
+ break;
+ default:
+ hddLog(LOG1, FL("Unsupported RXFILTER type %d"), type);
+ break;
+ }
+
+ return ret;
+}
+
static int hdd_driver_command(hdd_adapter_t *pAdapter,
hdd_priv_data_t *ppriv_data)
{
@@ -6120,6 +6260,14 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter,
ret = drv_cmd_set_fcc_channel(pHddCtx, command, 15);
+ } else if (strncmp(command, "RXFILTER-REMOVE", 15) == 0) {
+
+ ret = hdd_driver_rxfilter_comand_handler(command, pAdapter, false);
+
+ } else if (strncmp(command, "RXFILTER-ADD", 12) == 0) {
+
+ ret = hdd_driver_rxfilter_comand_handler(command, pAdapter, true);
+
} else {
MTRACE(vos_trace(VOS_MODULE_ID_HDD,
TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
@@ -7759,9 +7907,18 @@ static void __hdd_set_multicast_list(struct net_device *dev)
netdev_for_each_mc_addr(ha, dev) {
if (i == mc_count)
break;
- /* Skip IPv6 router solicitation address */
- if (!memcmp(ha->addr, ipv6_router_solicitation, ETH_ALEN)) {
- hddLog(LOG1, FL("skip ipv6 router solicitation address"));
+ /*
+ * Skip following addresses:
+ * 1)IPv6 router solicitation address
+ * 2)Any other address pattern if its set during RXFILTER REMOVE
+ * driver command based on addr_filter_pattern
+ */
+ if ((!memcmp(ha->addr, ipv6_router_solicitation, ETH_ALEN)) ||
+ (pAdapter->addr_filter_pattern && (!memcmp(ha->addr,
+ &pAdapter->addr_filter_pattern, 1)))) {
+ hddLog(LOGE, FL("MC/BC filtering Skip addr ="MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(ha->addr));
+
pAdapter->mc_addr_list.mc_cnt--;
continue;
}