summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRavi Joshi <ravij@codeaurora.org>2016-08-22 10:14:52 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-25 22:18:19 -0700
commitbb8d451c63bd9c1bff1ccdea424149b4687405ec (patch)
treed7aeb361ea17e18f535b7a052878985ae26ab00b
parent896fbae52aa5caab37fed2b27a92ead8f45f3f03 (diff)
qcacld-3.0: Drop replayed multicast packets
Integration from qcacld-2.0 to qcacld-3.0 IPv6 Multicast (Neighbor Solicitation) frames are not rejected by the WLAN driver when these frames are bounced back from the AP. This causes network stack to assume the duplicate IP address on the network and fails to assign the IPv6 address. Currently, this is a workaround till the issue is root caused. Change-Id: If5d48ed903f484805e7f4be9df52582e50bd6ce5 CRs-Fixed: 748105
-rw-r--r--core/hdd/inc/wlan_hdd_cfg.h14
-rw-r--r--core/hdd/src/wlan_hdd_cfg.c11
-rw-r--r--core/hdd/src/wlan_hdd_tx_rx.c31
3 files changed, 56 insertions, 0 deletions
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 672a1297d534..2d51b340304c 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -3481,6 +3481,19 @@ enum dot11p_mode {
#define CFG_INDOOR_CHANNEL_SUPPORT_MAX (1)
#define CFG_INDOOR_CHANNEL_SUPPORT_DEFAULT (0)
+/*
+ * Enable filtering of replayed multicast packets
+ * In a typical infrastructure setup, it is quite normal to receive
+ * replayed multicast packets. These packets may cause more harm than
+ * help if not handled properly. Providing a configuration option
+ * to enable filtering of such packets
+ */
+#define CFG_FILTER_MULTICAST_REPLAY_NAME "enable_multicast_replay_filter"
+#define CFG_FILTER_MULTICAST_REPLAY_MIN (0)
+#define CFG_FILTER_MULTICAST_REPLAY_MAX (1)
+#define CFG_FILTER_MULTICAST_REPLAY_DEFAULT (1)
+
+
/*---------------------------------------------------------------------------
Type declarations
-------------------------------------------------------------------------*/
@@ -4141,6 +4154,7 @@ struct hdd_config {
uint32_t iface_change_wait_time;
enum cfg_sub_20_channel_width enable_sub_20_channel_width;
bool indoor_channel_support;
+ bool multicast_replay_filter;
};
#define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index 29fc5aa8f16b..b9bebdc0e1bb 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -4007,6 +4007,14 @@ REG_TABLE_ENTRY g_registry_table[] = {
CFG_INTERFACE_CHANGE_WAIT_DEFAULT,
CFG_INTERFACE_CHANGE_WAIT_MIN,
CFG_INTERFACE_CHANGE_WAIT_MAX),
+
+ REG_VARIABLE(CFG_FILTER_MULTICAST_REPLAY_NAME,
+ WLAN_PARAM_Integer,
+ struct hdd_config, multicast_replay_filter,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_FILTER_MULTICAST_REPLAY_DEFAULT,
+ CFG_FILTER_MULTICAST_REPLAY_MIN,
+ CFG_FILTER_MULTICAST_REPLAY_MAX),
};
/**
@@ -5686,6 +5694,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
hdd_info("Name = [%s] Value = [%d]",
CFG_BPF_PACKET_FILTER_OFFLOAD,
pHddCtx->config->bpf_packet_filter_enable);
+ hdd_info("Name = [%s] Value = [%d]",
+ CFG_FILTER_MULTICAST_REPLAY_NAME,
+ pHddCtx->config->multicast_replay_filter);
}
diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c
index 5c4d503489a5..53bfa38f9c4e 100644
--- a/core/hdd/src/wlan_hdd_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_tx_rx.c
@@ -37,6 +37,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
#include <cds_sched.h>
#include <wlan_hdd_p2p.h>
@@ -851,6 +852,25 @@ int hdd_get_peer_idx(hdd_station_ctx_t *sta_ctx, struct qdf_mac_addr *addr)
return INVALID_PEER_IDX;
}
+/*
+ * hdd_is_mcast_replay() - checks if pkt is multicast replay
+ * @skb: packet skb
+ *
+ * Return: true if replayed multicast pkt, false otherwise
+ */
+static bool hdd_is_mcast_replay(struct sk_buff *skb)
+{
+ struct ethhdr *eth;
+
+ eth = eth_hdr(skb);
+ if (unlikely(skb->pkt_type == PACKET_MULTICAST)) {
+ if (unlikely(ether_addr_equal(eth->h_source,
+ skb->dev->dev_addr)))
+ return true;
+ }
+ return false;
+}
+
/**
* hdd_rx_packet_cbk() - Receive packet handler
* @context: pointer to HDD context
@@ -926,6 +946,17 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
++pAdapter->stats.rx_packets;
pAdapter->stats.rx_bytes += skb->len;
+
+ /* Check & drop replayed mcast packets (for IPV6) */
+ if (pHddCtx->config->multicast_replay_filter &&
+ hdd_is_mcast_replay(skb)) {
+ ++pAdapter->hdd_stats.hddTxRxStats.rxDropped[cpu_index];
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO,
+ "%s: Dropping multicast replay pkt", __func__);
+ kfree_skb(skb);
+ return QDF_STATUS_SUCCESS;
+ }
+
#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
qdf_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
HDD_WAKE_LOCK_DURATION,