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

net: Move check for multiple vlans to drivers

To allow drivers to handle the features check for multiple tags,
move the check to ndo_features_check().
As no drivers currently handle multiple tagged TSO, introduce
dflt_features_check() and call it if the driver does not have
ndo_features_check().

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
8cb65d00 f5a7fb88

+34 -12
+1
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
··· 12557 12557 struct net_device *dev, 12558 12558 netdev_features_t features) 12559 12559 { 12560 + features = vlan_features_check(skb, features); 12560 12561 return vxlan_features_check(skb, features); 12561 12562 } 12562 12563
+1
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
··· 2373 2373 struct net_device *dev, 2374 2374 netdev_features_t features) 2375 2375 { 2376 + features = vlan_features_check(skb, features); 2376 2377 return vxlan_features_check(skb, features); 2377 2378 } 2378 2379 #endif
+1
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
··· 507 507 struct net_device *dev, 508 508 netdev_features_t features) 509 509 { 510 + features = vlan_features_check(skb, features); 510 511 return vxlan_features_check(skb, features); 511 512 } 512 513 #endif
+22
include/linux/if_vlan.h
··· 606 606 return true; 607 607 } 608 608 609 + /** 610 + * vlan_features_check - drop unsafe features for skb with multiple tags. 611 + * @skb: skbuff to query 612 + * @features: features to be checked 613 + * 614 + * Returns features without unsafe ones if the skb has multiple tags. 615 + */ 616 + static inline netdev_features_t vlan_features_check(const struct sk_buff *skb, 617 + netdev_features_t features) 618 + { 619 + if (skb_vlan_tagged_multi(skb)) 620 + features = netdev_intersect_features(features, 621 + NETIF_F_SG | 622 + NETIF_F_HIGHDMA | 623 + NETIF_F_FRAGLIST | 624 + NETIF_F_GEN_CSUM | 625 + NETIF_F_HW_VLAN_CTAG_TX | 626 + NETIF_F_HW_VLAN_STAG_TX); 627 + 628 + return features; 629 + } 630 + 609 631 #endif /* !(_LINUX_IF_VLAN_H_) */
+9 -12
net/core/dev.c
··· 2562 2562 return features; 2563 2563 } 2564 2564 2565 + static netdev_features_t dflt_features_check(const struct sk_buff *skb, 2566 + struct net_device *dev, 2567 + netdev_features_t features) 2568 + { 2569 + return vlan_features_check(skb, features); 2570 + } 2571 + 2565 2572 netdev_features_t netif_skb_features(struct sk_buff *skb) 2566 2573 { 2567 2574 struct net_device *dev = skb->dev; ··· 2590 2583 dev->vlan_features | 2591 2584 NETIF_F_HW_VLAN_CTAG_TX | 2592 2585 NETIF_F_HW_VLAN_STAG_TX); 2593 - else 2594 - goto finalize; 2595 2586 2596 - if (skb_vlan_tagged_multi(skb)) 2597 - features = netdev_intersect_features(features, 2598 - NETIF_F_SG | 2599 - NETIF_F_HIGHDMA | 2600 - NETIF_F_FRAGLIST | 2601 - NETIF_F_GEN_CSUM | 2602 - NETIF_F_HW_VLAN_CTAG_TX | 2603 - NETIF_F_HW_VLAN_STAG_TX); 2604 - 2605 - finalize: 2606 2587 if (dev->netdev_ops->ndo_features_check) 2607 2588 features &= dev->netdev_ops->ndo_features_check(skb, dev, 2608 2589 features); 2590 + else 2591 + features &= dflt_features_check(skb, dev, features); 2609 2592 2610 2593 return harmonize_features(skb, features); 2611 2594 }