}
#endif
+#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+int slsi_set_abnormal_multicast_pkt_filter(struct net_device *dev, u8 enabled)
+{
+ struct netdev_vif *netdev_vif = netdev_priv(dev);
+ struct slsi_dev *sdev = netdev_vif->sdev;
+ int ret = 0;
+ int is_suspend = 0;
+
+ SLSI_MUTEX_LOCK(sdev->device_config_mutex);
+ is_suspend = sdev->device_config.user_suspend_mode;
+ SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
+
+ if (is_suspend) {
+ SLSI_ERR(sdev, "Host is in early suspend state.\n");
+ return -EPERM; /* set_enhanced_pkt_filter should not be called after suspend */
+ }
+
+ sdev->abnormal_multicast_pkt_filter_enabled = enabled;
+ SLSI_INFO(sdev, "Abnormal multicast packet filter is %s", (enabled ? "enabled" : "disabled"));
+ return ret;
+}
+
+static int slsi_set_opt_out_abnormal_multicast_packet_filter(struct slsi_dev *sdev, struct net_device *dev)
+{
+ struct slsi_mlme_pattern_desc pattern_desc[3];
+ u8 pkt_filters_len = 0;
+ int ret = 0;
+ struct slsi_mlme_pkt_filter_elem pkt_filter_elem;
+
+ /* IPv4 packet */
+ pattern_desc[0].offset = 0; /* destination mac address*/
+ pattern_desc[0].mask_length = ETH_ALEN;
+ memset(pattern_desc[0].mask, 0xff, ETH_ALEN);
+ memcpy(pattern_desc[0].pattern, sdev->hw_addr, ETH_ALEN);
+
+ pattern_desc[1].offset = ETH_ALEN + ETH_ALEN; /* ethhdr->h_proto == IPv4 */
+ pattern_desc[1].mask_length = 2;
+ pattern_desc[1].mask[0] = 0xff; /* Big endian 0xffff */
+ pattern_desc[1].mask[1] = 0xff;
+ pattern_desc[1].pattern[0] = 0x08; /* Big endian 0x0800 */
+ pattern_desc[1].pattern[1] = 0x00;
+
+ pattern_desc[2].offset = sizeof(struct ethhdr) + offsetof(struct iphdr, daddr); /* iphdr->daddr starts with 1110 */
+ pattern_desc[2].mask_length = 1;
+ pattern_desc[2].mask[0] = 0xf0;
+ pattern_desc[2].pattern[0] = 0xe0; /* 224 */
+
+ slsi_create_packet_filter_element(SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID,
+ FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP,
+ 3, pattern_desc,
+ &pkt_filter_elem, &pkt_filters_len);
+
+ ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, 1, &pkt_filter_elem);
+
+ return ret;
+}
+#endif
+
static int slsi_set_multicast_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
{
struct slsi_mlme_pattern_desc pattern_desc;
num_filters++; /*TCP IPv6 OPT IN*/
}
#endif
-
+#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+ if (sdev->abnormal_multicast_pkt_filter_enabled)
+ num_filters++;/* clear abnormal multicast packet */
+#endif
pkt_filter_elem = kmalloc((num_filters * sizeof(struct slsi_mlme_pkt_filter_elem)), GFP_KERNEL);
if (!pkt_filter_elem) {
SLSI_NET_ERR(dev, "ERROR Memory allocation failure");
&pkt_filter_elem[num_filters], &pkt_filters_len);
num_filters++;
}
+#endif
+#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+ if (sdev->abnormal_multicast_pkt_filter_enabled) {
+ slsi_create_packet_filter_element(SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, 0, 0, NULL,
+ &pkt_filter_elem[num_filters], &pkt_filters_len);
+ num_filters++;
+ }
#endif
ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem);
kfree(pkt_filter_elem);
if (ret)
return ret;
}
+#endif
+ /* install abnormal multicast packet filter */
+#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+ if (sdev->abnormal_multicast_pkt_filter_enabled) {
+ ret = slsi_set_opt_out_abnormal_multicast_packet_filter(sdev, dev);
+ if (ret)
+ return ret;
+ }
#endif
return slsi_set_common_packet_filters(sdev, dev);
}
if (ie) {
SLSI_NET_DBG1(dev, SLSI_CFG80211, "Connected to HS2 AP ");
- if (slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) {
- SLSI_NET_DBG1(dev, SLSI_CFG80211, "Proxy ARP service supported on HS2 AP ");
+ if (slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) {
+ SLSI_NET_DBG1(dev, SLSI_CFG80211, "Proxy ARP service supported on HS2 AP ");
- /* Opt out Gratuitous ARP packets (ARP Announcement) in active and suspended mode.
- * For suspended mode, gratituous ARP is dropped by "opt out all broadcast" that will be
- * set in slsi_set_common_packet_filters on screen off
- */
- num_pattern_desc = 0;
- pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
- pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
- SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask);
- SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, addr_mask);
- num_pattern_desc++;
+ /* Opt out Gratuitous ARP packets (ARP Announcement) in active and suspended mode.
+ * For suspended mode, gratituous ARP is dropped by "opt out all broadcast" that will be
+ * set in slsi_set_common_packet_filters on screen off
+ */
+ num_pattern_desc = 0;
+ pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
+ pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
+ SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask);
+ SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, addr_mask);
+ num_pattern_desc++;
- SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP);
- num_pattern_desc++;
+ SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP);
+ num_pattern_desc++;
- slsi_create_packet_filter_element(SLSI_PROXY_ARP_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT,
- num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters],
- &pkt_filters_len);
- num_filters++;
+ slsi_create_packet_filter_element(SLSI_PROXY_ARP_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT,
+ num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len);
+ num_filters++;
#ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6
- /* Opt out unsolicited Neighbor Advertisement packets .For suspended mode, NA is dropped by
- * "opt out all IPv6 multicast" already set in slsi_create_common_packet_filters
- */
+ /* Opt out unsolicited Neighbor Advertisement packets .For suspended mode, NA is dropped by
+ * "opt out all IPv6 multicast" already set in slsi_create_common_packet_filters
+ */
+ num_pattern_desc = 0;
+
+ pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
+ pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
+ SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask);
+ SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, solicited_node_addr_mask);
+ num_pattern_desc++;
- num_pattern_desc = 0;
-
- pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/
- pattern_desc[num_pattern_desc].mask_length = ETH_ALEN;
- SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask);
- SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, solicited_node_addr_mask);
- num_pattern_desc++;
-
- SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], 0x86DD);
- num_pattern_desc++;
-
- pattern_desc[num_pattern_desc].offset = 0x14; /*filtering on next header*/
- pattern_desc[num_pattern_desc].mask_length = 1;
- pattern_desc[num_pattern_desc].mask[0] = 0xff;
- pattern_desc[num_pattern_desc].pattern[0] = 0x3a;
- num_pattern_desc++;
-
- pattern_desc[num_pattern_desc].offset = 0x36; /*filtering on ICMP6 packet type*/
- pattern_desc[num_pattern_desc].mask_length = 1;
- pattern_desc[num_pattern_desc].mask[0] = 0xff;
- pattern_desc[num_pattern_desc].pattern[0] = 0x88; /* Neighbor Advertisement type in ICMPv6 */
- num_pattern_desc++;
-
- slsi_create_packet_filter_element(SLSI_PROXY_ARP_NA_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT,
- num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters],
- &pkt_filters_len);
- num_filters++;
+ SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], 0x86DD);
+ num_pattern_desc++;
+
+ pattern_desc[num_pattern_desc].offset = 0x14; /*filtering on next header*/
+ pattern_desc[num_pattern_desc].mask_length = 1;
+ pattern_desc[num_pattern_desc].mask[0] = 0xff;
+ pattern_desc[num_pattern_desc].pattern[0] = 0x3a;
+ num_pattern_desc++;
+
+ pattern_desc[num_pattern_desc].offset = 0x36; /*filtering on ICMP6 packet type*/
+ pattern_desc[num_pattern_desc].mask_length = 1;
+ pattern_desc[num_pattern_desc].mask[0] = 0xff;
+ pattern_desc[num_pattern_desc].pattern[0] = 0x88; /* Neighbor Advertisement type in ICMPv6 */
+ num_pattern_desc++;
+
+ slsi_create_packet_filter_element(SLSI_PROXY_ARP_NA_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT,
+ num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len);
+ num_filters++;
#endif
}
}