aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c1
-rw-r--r--include/linux/if_vlan.h22
-rw-r--r--net/core/dev.c21
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 */
616static 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
2565static 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
2565netdev_features_t netif_skb_features(struct sk_buff *skb) 2572netdev_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
2598finalize:
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}