Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Toshiaki Makita and committed by
David S. Miller
f5a7fb88 8d463504

+53 -16
+45
include/linux/if_vlan.h
··· 561 561 skb->protocol = htons(ETH_P_802_2); 562 562 } 563 563 564 + /** 565 + * skb_vlan_tagged - check if skb is vlan tagged. 566 + * @skb: skbuff to query 567 + * 568 + * Returns true if the skb is tagged, regardless of whether it is hardware 569 + * accelerated or not. 570 + */ 571 + static inline bool skb_vlan_tagged(const struct sk_buff *skb) 572 + { 573 + if (!skb_vlan_tag_present(skb) && 574 + likely(skb->protocol != htons(ETH_P_8021Q) && 575 + skb->protocol != htons(ETH_P_8021AD))) 576 + return false; 577 + 578 + return true; 579 + } 580 + 581 + /** 582 + * skb_vlan_tagged_multi - check if skb is vlan tagged with multiple headers. 583 + * @skb: skbuff to query 584 + * 585 + * Returns true if the skb is tagged with multiple vlan headers, regardless 586 + * of whether it is hardware accelerated or not. 587 + */ 588 + static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb) 589 + { 590 + __be16 protocol = skb->protocol; 591 + 592 + if (!skb_vlan_tag_present(skb)) { 593 + struct vlan_ethhdr *veh; 594 + 595 + if (likely(protocol != htons(ETH_P_8021Q) && 596 + protocol != htons(ETH_P_8021AD))) 597 + return false; 598 + 599 + veh = (struct vlan_ethhdr *)skb->data; 600 + protocol = veh->h_vlan_encapsulated_proto; 601 + } 602 + 603 + if (protocol != htons(ETH_P_8021Q) && protocol != htons(ETH_P_8021AD)) 604 + return false; 605 + 606 + return true; 607 + } 608 + 564 609 #endif /* !(_LINUX_IF_VLAN_H_) */
+8 -16
net/core/dev.c
··· 2567 2567 struct net_device *dev = skb->dev; 2568 2568 netdev_features_t features = dev->features; 2569 2569 u16 gso_segs = skb_shinfo(skb)->gso_segs; 2570 - __be16 protocol = skb->protocol; 2571 2570 2572 2571 if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) 2573 2572 features &= ~NETIF_F_GSO_MASK; ··· 2578 2579 if (skb->encapsulation) 2579 2580 features &= dev->hw_enc_features; 2580 2581 2581 - if (!skb_vlan_tag_present(skb)) { 2582 - if (unlikely(protocol == htons(ETH_P_8021Q) || 2583 - protocol == htons(ETH_P_8021AD))) { 2584 - struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; 2585 - protocol = veh->h_vlan_encapsulated_proto; 2586 - } else { 2587 - goto finalize; 2588 - } 2589 - } 2582 + if (skb_vlan_tagged(skb)) 2583 + features = netdev_intersect_features(features, 2584 + dev->vlan_features | 2585 + NETIF_F_HW_VLAN_CTAG_TX | 2586 + NETIF_F_HW_VLAN_STAG_TX); 2587 + else 2588 + goto finalize; 2590 2589 2591 - features = netdev_intersect_features(features, 2592 - dev->vlan_features | 2593 - NETIF_F_HW_VLAN_CTAG_TX | 2594 - NETIF_F_HW_VLAN_STAG_TX); 2595 - 2596 - if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) 2590 + if (skb_vlan_tagged_multi(skb)) 2597 2591 features = netdev_intersect_features(features, 2598 2592 NETIF_F_SG | 2599 2593 NETIF_F_HIGHDMA |