net: handle 802.1P vlan 0 packets properly
authorGovindarajulu Varadarajan <gvaradar@cisco.com>
Fri, 14 Jun 2019 13:13:54 +0000 (06:13 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 16 Jun 2019 20:45:14 +0000 (13:45 -0700)
When stack receives pkt: [802.1P vlan 0][802.1AD vlan 100][IPv4],
vlan_do_receive() returns false if it does not find vlan_dev. Later
__netif_receive_skb_core() fails to find packet type handler for
skb->protocol 801.1AD and drops the packet.

801.1P header with vlan id 0 should be handled as untagged packets.
This patch fixes it by checking if vlan_id is 0 and processes next vlan
header.

Signed-off-by: Govindarajulu Varadarajan <gvaradar@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/dev.c

index eb7fb6daa1efcadf1723813161c14193785fbf83..d6edd218babdde1ee35da7c0823ddf90dd5ba7cb 100644 (file)
@@ -4923,8 +4923,36 @@ skip_classify:
        }
 
        if (unlikely(skb_vlan_tag_present(skb))) {
-               if (skb_vlan_tag_get_id(skb))
+check_vlan_id:
+               if (skb_vlan_tag_get_id(skb)) {
+                       /* Vlan id is non 0 and vlan_do_receive() above couldn't
+                        * find vlan device.
+                        */
                        skb->pkt_type = PACKET_OTHERHOST;
+               } else if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
+                          skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
+                       /* Outer header is 802.1P with vlan 0, inner header is
+                        * 802.1Q or 802.1AD and vlan_do_receive() above could
+                        * not find vlan dev for vlan id 0.
+                        */
+                       __vlan_hwaccel_clear_tag(skb);
+                       skb = skb_vlan_untag(skb);
+                       if (unlikely(!skb))
+                               goto out;
+                       if (vlan_do_receive(&skb))
+                               /* After stripping off 802.1P header with vlan 0
+                                * vlan dev is found for inner header.
+                                */
+                               goto another_round;
+                       else if (unlikely(!skb))
+                               goto out;
+                       else
+                               /* We have stripped outer 802.1P vlan 0 header.
+                                * But could not find vlan dev.
+                                * check again for vlan id to set OTHERHOST.
+                                */
+                               goto check_vlan_id;
+               }
                /* Note: we might in the future use prio bits
                 * and set skb->priority like in vlan_do_receive()
                 * For the time being, just ignore Priority Code Point