Skip to content

Commit

Permalink
vlan: Introduce helper functions to check if skb is tagged
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Toshiaki Makita authored and David S. Miller committed Mar 29, 2015
1 parent 8d46350 commit f5a7fb8
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 16 deletions.
45 changes: 45 additions & 0 deletions include/linux/if_vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_) */
24 changes: 8 additions & 16 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 |
Expand Down

0 comments on commit f5a7fb8

Please sign in to comment.