Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -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_) */
+8 −16
Original line number Diff line number Diff line
@@ -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;
		}
	}

	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 |