[RAMEN9610-19423] wlbt: filter abnormal ipv4 multicast packet
authordujeonglee <dujeong.lee@samsung.com>
Fri, 24 May 2019 12:05:43 +0000 (21:05 +0900)
committerKim Gunho <gunho.kim@samsung.com>
Fri, 30 Aug 2019 07:58:56 +0000 (16:58 +0900)
Change-Id: I50511db5dcec9a9959670eb843ef87c3def99bcc
Signed-off-by: dujeonglee <dujeong.lee@samsung.com>
Signed-off-by: Kim Gunho <gunho.kim@samsung.com>
drivers/net/wireless/scsc/Kconfig
drivers/net/wireless/scsc/dev.c
drivers/net/wireless/scsc/dev.h
drivers/net/wireless/scsc/ioctl.c
drivers/net/wireless/scsc/mgt.c
drivers/net/wireless/scsc/mgt.h

index 05e3b2099d3f7342e149d9f7d669f3a7127e3304..bccc2711fbef55e8dbfe27bcd05be48f9abadb31 100755 (executable)
@@ -262,3 +262,9 @@ config SCSC_WLAN_STA_ENHANCED_ARP_DETECT
         ---help---
           This option tells whether enhanced arp detection
           is enabled or not.
+
+config SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+        bool "Enable abnormal multicast packet filtering in suspend"
+        default n
+        ---help---
+          This option tells if abnormal multicast packet filtering in suspend is supported or not.
index 72591471d5b754521d6c57aef6ec497dde930cbd..a4b5d04ef942295c618ecb5d335287359366f51e 100755 (executable)
@@ -391,6 +391,9 @@ struct slsi_dev *slsi_dev_attach(struct device *dev, struct scsc_mx *core, struc
 #endif
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
        sdev->enhanced_pkt_filter_enabled = true;
+#endif
+#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+       sdev->abnormal_multicast_pkt_filter_enabled = true;
 #endif
        sdev->device_state = SLSI_DEVICE_STATE_STOPPED;
        sdev->current_tspec_id = -1;
index ea71727958932910f8104836ea35d5dfa7cecaaa..7b4582e3c1124b7e2c8aadaea2dc2953bc735137 100755 (executable)
@@ -471,6 +471,7 @@ enum slsi_filter_id {
        SLSI_OPT_IN_TCP4_FILTER_ID,                                             /* 0x87 */
        SLSI_OPT_IN_TCP6_FILTER_ID,                                             /* 0x88 */
 #endif
+       SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID,                                     /* 0x88 */
        SLSI_REGD_MC_FILTER_ID,                                                 /* 0x89 */
 };
 #else
@@ -491,7 +492,8 @@ enum slsi_filter_id {
        SLSI_OPT_IN_TCP4_FILTER_ID,                                             /* 0x88 */
        SLSI_OPT_IN_TCP6_FILTER_ID,                                             /* 0x89 */
 #endif
-       SLSI_REGD_MC_FILTER_ID,                                                 /* 0x8A */
+       SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID,                                     /* 0x89 */
+       SLSI_REGD_MC_FILTER_ID,                                                 /* 0x8a */
 };
 
 #endif
@@ -1164,6 +1166,9 @@ struct slsi_dev {
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
        bool                       enhanced_pkt_filter_enabled;
 #endif
+#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+       bool                       abnormal_multicast_pkt_filter_enabled;
+#endif
 };
 
 /* Compact representation of channels a ESS has been seen on
index 51bf1098b968cb65f1b5bc531e932e4f9a17643c..6e75aac7b78a92272252b939ba4f8744299a6f5f 100755 (executable)
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
 #define CMD_ENHANCED_PKT_FILTER "ENHANCED_PKT_FILTER"
 #endif
+#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+#define CMD_ABNORMAL_MULTICAST_PKT_FILTER "ABNORMAL_MULTICAST_PKT_FILTER"
+#endif
 
 #ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS
 #define CMD_SET_NUM_ANTENNAS "SET_NUM_ANTENNAS"
@@ -2749,6 +2752,12 @@ int slsi_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
                ret = slsi_set_enhanced_pkt_filter(dev, enable);
 #endif
+#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+       } else if ((strncasecmp(command, CMD_ABNORMAL_MULTICAST_PKT_FILTER, strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER)) == 0)) {
+               const u8 enable = *(command + strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER) + 1) - '0';
+
+               ret = slsi_set_abnormal_multicast_pkt_filter(dev, enable);
+#endif
 #ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS
        } else if (strncasecmp(command, CMD_SET_NUM_ANTENNAS, strlen(CMD_SET_NUM_ANTENNAS)) == 0) {
                struct netdev_vif *ndev_vif = netdev_priv(dev);
index d688fdb6190e6bc5ce9a9f54013b19d8f52a6951..abf334127ad127c3b428ebebe7783c52f254a1c5 100755 (executable)
@@ -3450,6 +3450,64 @@ static int  slsi_set_opt_in_tcp6_packet_filter(struct slsi_dev *sdev, struct net
 }
 #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;
@@ -3539,7 +3597,10 @@ int  slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
                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");
@@ -3578,6 +3639,13 @@ int  slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
                                                  &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);
@@ -3613,6 +3681,14 @@ int  slsi_update_packet_filters(struct slsi_dev *sdev, struct net_device *dev)
                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);
 }
@@ -3673,60 +3749,57 @@ void slsi_set_packet_filters(struct slsi_dev *sdev, struct net_device *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
                }
        }
index f44ee5abcc2437d2ca8f109ea3a75bd0587bc819..98ea8581fde69cbc14b4306bbb66db69f46dc551 100755 (executable)
@@ -483,6 +483,9 @@ int slsi_is_tcp_sync_packet(struct net_device *dev, struct sk_buff *skb);
 #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
 int slsi_set_enhanced_pkt_filter(struct net_device *dev, u8 pkt_filter_enable);
 #endif
+#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
+int slsi_set_abnormal_multicast_pkt_filter(struct net_device *dev, u8 enabled);
+#endif
 void slsi_set_packet_filters(struct slsi_dev *sdev, struct net_device *dev);
 int  slsi_update_packet_filters(struct slsi_dev *sdev, struct net_device *dev);
 int  slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev);