Commit f5a7fb88 authored by Toshiaki Makita's avatar Toshiaki Makita Committed by David S. Miller

vlan: Introduce helper functions to check if skb is tagged

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: default avatarToshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8d463504
...@@ -561,4 +561,49 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, ...@@ -561,4 +561,49 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
skb->protocol = htons(ETH_P_802_2); 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_) */ #endif /* !(_LINUX_IF_VLAN_H_) */
...@@ -2567,7 +2567,6 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) ...@@ -2567,7 +2567,6 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
netdev_features_t features = dev->features; netdev_features_t features = dev->features;
u16 gso_segs = skb_shinfo(skb)->gso_segs; 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) if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs)
features &= ~NETIF_F_GSO_MASK; features &= ~NETIF_F_GSO_MASK;
...@@ -2579,22 +2578,15 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) ...@@ -2579,22 +2578,15 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
if (skb->encapsulation) if (skb->encapsulation)
features &= dev->hw_enc_features; features &= dev->hw_enc_features;
if (!skb_vlan_tag_present(skb)) { if (skb_vlan_tagged(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, features = netdev_intersect_features(features,
dev->vlan_features | dev->vlan_features |
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_STAG_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, features = netdev_intersect_features(features,
NETIF_F_SG | NETIF_F_SG |
NETIF_F_HIGHDMA | NETIF_F_HIGHDMA |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment