diff options
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1 | ||||
-rw-r--r-- | include/linux/if_vlan.h | 22 | ||||
-rw-r--r-- | net/core/dev.c | 21 |
5 files changed, 34 insertions, 12 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 9677431c582a..039b0c1f480e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -12557,6 +12557,7 @@ static netdev_features_t bnx2x_features_check(struct sk_buff *skb, | |||
12557 | struct net_device *dev, | 12557 | struct net_device *dev, |
12558 | netdev_features_t features) | 12558 | netdev_features_t features) |
12559 | { | 12559 | { |
12560 | features = vlan_features_check(skb, features); | ||
12560 | return vxlan_features_check(skb, features); | 12561 | return vxlan_features_check(skb, features); |
12561 | } | 12562 | } |
12562 | 12563 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index a8339e98ad24..ebc93a101c93 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -2373,6 +2373,7 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb, | |||
2373 | struct net_device *dev, | 2373 | struct net_device *dev, |
2374 | netdev_features_t features) | 2374 | netdev_features_t features) |
2375 | { | 2375 | { |
2376 | features = vlan_features_check(skb, features); | ||
2376 | return vxlan_features_check(skb, features); | 2377 | return vxlan_features_check(skb, features); |
2377 | } | 2378 | } |
2378 | #endif | 2379 | #endif |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index a430a34a4434..367f3976df56 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -507,6 +507,7 @@ static netdev_features_t qlcnic_features_check(struct sk_buff *skb, | |||
507 | struct net_device *dev, | 507 | struct net_device *dev, |
508 | netdev_features_t features) | 508 | netdev_features_t features) |
509 | { | 509 | { |
510 | features = vlan_features_check(skb, features); | ||
510 | return vxlan_features_check(skb, features); | 511 | return vxlan_features_check(skb, features); |
511 | } | 512 | } |
512 | #endif | 513 | #endif |
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 4265d440ec4d..920e4457ce6e 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h | |||
@@ -606,4 +606,26 @@ static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb) | |||
606 | return true; | 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 | #endif /* !(_LINUX_IF_VLAN_H_) */ | 631 | #endif /* !(_LINUX_IF_VLAN_H_) */ |
diff --git a/net/core/dev.c b/net/core/dev.c index 04bffcd4a48d..cb46badbef5a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2562,6 +2562,13 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, | |||
2562 | return features; | 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 | netdev_features_t netif_skb_features(struct sk_buff *skb) | 2572 | netdev_features_t netif_skb_features(struct sk_buff *skb) |
2566 | { | 2573 | { |
2567 | struct net_device *dev = skb->dev; | 2574 | struct net_device *dev = skb->dev; |
@@ -2583,22 +2590,12 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
2583 | dev->vlan_features | | 2590 | dev->vlan_features | |
2584 | NETIF_F_HW_VLAN_CTAG_TX | | 2591 | NETIF_F_HW_VLAN_CTAG_TX | |
2585 | NETIF_F_HW_VLAN_STAG_TX); | 2592 | NETIF_F_HW_VLAN_STAG_TX); |
2586 | else | ||
2587 | goto finalize; | ||
2588 | 2593 | ||
2589 | if (skb_vlan_tagged_multi(skb)) | ||
2590 | features = netdev_intersect_features(features, | ||
2591 | NETIF_F_SG | | ||
2592 | NETIF_F_HIGHDMA | | ||
2593 | NETIF_F_FRAGLIST | | ||
2594 | NETIF_F_GEN_CSUM | | ||
2595 | NETIF_F_HW_VLAN_CTAG_TX | | ||
2596 | NETIF_F_HW_VLAN_STAG_TX); | ||
2597 | |||
2598 | finalize: | ||
2599 | if (dev->netdev_ops->ndo_features_check) | 2594 | if (dev->netdev_ops->ndo_features_check) |
2600 | features &= dev->netdev_ops->ndo_features_check(skb, dev, | 2595 | features &= dev->netdev_ops->ndo_features_check(skb, dev, |
2601 | features); | 2596 | features); |
2597 | else | ||
2598 | features &= dflt_features_check(skb, dev, features); | ||
2602 | 2599 | ||
2603 | return harmonize_features(skb, features); | 2600 | return harmonize_features(skb, features); |
2604 | } | 2601 | } |