vlan: Introduce helper functions to check if skb is tagged
authorToshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Fri, 27 Mar 2015 05:31:11 +0000 (14:31 +0900)
committerDavid S. Miller <davem@davemloft.net>
Sun, 29 Mar 2015 20:33:22 +0000 (13:33 -0700)
Separate the two checks for single vlan and multiple vlans in
netif_skb_features().  This allows us to move the check for multiple
vlans to another function later.

Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/if_vlan.h
net/core/dev.c

index b11b28a30b9ee78e1f600cc076736a72dc624c72..4265d440ec4d69d1c1a892616fdedf2f35b28a2d 100644 (file)
@@ -561,4 +561,49 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
                skb->protocol = htons(ETH_P_802_2);
 }
 
+/**
+ * skb_vlan_tagged - check if skb is vlan tagged.
+ * @skb: skbuff to query
+ *
+ * Returns true if the skb is tagged, regardless of whether it is hardware
+ * accelerated or not.
+ */
+static inline bool skb_vlan_tagged(const struct sk_buff *skb)
+{
+       if (!skb_vlan_tag_present(skb) &&
+           likely(skb->protocol != htons(ETH_P_8021Q) &&
+                  skb->protocol != htons(ETH_P_8021AD)))
+               return false;
+
+       return true;
+}
+
+/**
+ * skb_vlan_tagged_multi - check if skb is vlan tagged with multiple headers.
+ * @skb: skbuff to query
+ *
+ * Returns true if the skb is tagged with multiple vlan headers, regardless
+ * of whether it is hardware accelerated or not.
+ */
+static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb)
+{
+       __be16 protocol = skb->protocol;
+
+       if (!skb_vlan_tag_present(skb)) {
+               struct vlan_ethhdr *veh;
+
+               if (likely(protocol != htons(ETH_P_8021Q) &&
+                          protocol != htons(ETH_P_8021AD)))
+                       return false;
+
+               veh = (struct vlan_ethhdr *)skb->data;
+               protocol = veh->h_vlan_encapsulated_proto;
+       }
+
+       if (protocol != htons(ETH_P_8021Q) && protocol != htons(ETH_P_8021AD))
+               return false;
+
+       return true;
+}
+
 #endif /* !(_LINUX_IF_VLAN_H_) */
index a0408d497dae04e7caa145f05c915b058aa2d356..04bffcd4a48de6300adc3354cc18efc2cb9972ce 100644 (file)
@@ -2567,7 +2567,6 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
        struct net_device *dev = skb->dev;
        netdev_features_t features = dev->features;
        u16 gso_segs = skb_shinfo(skb)->gso_segs;
-       __be16 protocol = skb->protocol;
 
        if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs)
                features &= ~NETIF_F_GSO_MASK;
@@ -2579,22 +2578,15 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
        if (skb->encapsulation)
                features &= dev->hw_enc_features;
 
-       if (!skb_vlan_tag_present(skb)) {
-               if (unlikely(protocol == htons(ETH_P_8021Q) ||
-                            protocol == htons(ETH_P_8021AD))) {
-                       struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
-                       protocol = veh->h_vlan_encapsulated_proto;
-               } else {
-                       goto finalize;
-               }
-       }
-
-       features = netdev_intersect_features(features,
-                                            dev->vlan_features |
-                                            NETIF_F_HW_VLAN_CTAG_TX |
-                                            NETIF_F_HW_VLAN_STAG_TX);
+       if (skb_vlan_tagged(skb))
+               features = netdev_intersect_features(features,
+                                                    dev->vlan_features |
+                                                    NETIF_F_HW_VLAN_CTAG_TX |
+                                                    NETIF_F_HW_VLAN_STAG_TX);
+       else
+               goto finalize;
 
-       if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
+       if (skb_vlan_tagged_multi(skb))
                features = netdev_intersect_features(features,
                                                     NETIF_F_SG |
                                                     NETIF_F_HIGHDMA |