aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c8
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c10
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c8
-rw-r--r--include/linux/netdevice.h20
-rw-r--r--include/net/vxlan.h28
-rw-r--r--net/core/dev.c23
7 files changed, 70 insertions, 35 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 9f5e38769a29..72eef9fc883e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12553,9 +12553,11 @@ static int bnx2x_get_phys_port_id(struct net_device *netdev,
12553 return 0; 12553 return 0;
12554} 12554}
12555 12555
12556static bool bnx2x_gso_check(struct sk_buff *skb, struct net_device *dev) 12556static netdev_features_t bnx2x_features_check(struct sk_buff *skb,
12557 struct net_device *dev,
12558 netdev_features_t features)
12557{ 12559{
12558 return vxlan_gso_check(skb); 12560 return vxlan_features_check(skb, features);
12559} 12561}
12560 12562
12561static const struct net_device_ops bnx2x_netdev_ops = { 12563static const struct net_device_ops bnx2x_netdev_ops = {
@@ -12589,7 +12591,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
12589#endif 12591#endif
12590 .ndo_get_phys_port_id = bnx2x_get_phys_port_id, 12592 .ndo_get_phys_port_id = bnx2x_get_phys_port_id,
12591 .ndo_set_vf_link_state = bnx2x_set_vf_link_state, 12593 .ndo_set_vf_link_state = bnx2x_set_vf_link_state,
12592 .ndo_gso_check = bnx2x_gso_check, 12594 .ndo_features_check = bnx2x_features_check,
12593}; 12595};
12594 12596
12595static int bnx2x_set_coherency_mask(struct bnx2x *bp) 12597static int bnx2x_set_coherency_mask(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 196073110e32..41a0a5498da7 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -4459,9 +4459,11 @@ done:
4459 adapter->vxlan_port_count--; 4459 adapter->vxlan_port_count--;
4460} 4460}
4461 4461
4462static bool be_gso_check(struct sk_buff *skb, struct net_device *dev) 4462static netdev_features_t be_features_check(struct sk_buff *skb,
4463 struct net_device *dev,
4464 netdev_features_t features)
4463{ 4465{
4464 return vxlan_gso_check(skb); 4466 return vxlan_features_check(skb, features);
4465} 4467}
4466#endif 4468#endif
4467 4469
@@ -4492,7 +4494,7 @@ static const struct net_device_ops be_netdev_ops = {
4492#ifdef CONFIG_BE2NET_VXLAN 4494#ifdef CONFIG_BE2NET_VXLAN
4493 .ndo_add_vxlan_port = be_add_vxlan_port, 4495 .ndo_add_vxlan_port = be_add_vxlan_port,
4494 .ndo_del_vxlan_port = be_del_vxlan_port, 4496 .ndo_del_vxlan_port = be_del_vxlan_port,
4495 .ndo_gso_check = be_gso_check, 4497 .ndo_features_check = be_features_check,
4496#endif 4498#endif
4497}; 4499};
4498 4500
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 190cbd931f6b..d0d6dc1b8e46 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2365,9 +2365,11 @@ static void mlx4_en_del_vxlan_port(struct net_device *dev,
2365 queue_work(priv->mdev->workqueue, &priv->vxlan_del_task); 2365 queue_work(priv->mdev->workqueue, &priv->vxlan_del_task);
2366} 2366}
2367 2367
2368static bool mlx4_en_gso_check(struct sk_buff *skb, struct net_device *dev) 2368static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
2369 struct net_device *dev,
2370 netdev_features_t features)
2369{ 2371{
2370 return vxlan_gso_check(skb); 2372 return vxlan_features_check(skb, features);
2371} 2373}
2372#endif 2374#endif
2373 2375
@@ -2400,7 +2402,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
2400#ifdef CONFIG_MLX4_EN_VXLAN 2402#ifdef CONFIG_MLX4_EN_VXLAN
2401 .ndo_add_vxlan_port = mlx4_en_add_vxlan_port, 2403 .ndo_add_vxlan_port = mlx4_en_add_vxlan_port,
2402 .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, 2404 .ndo_del_vxlan_port = mlx4_en_del_vxlan_port,
2403 .ndo_gso_check = mlx4_en_gso_check, 2405 .ndo_features_check = mlx4_en_features_check,
2404#endif 2406#endif
2405}; 2407};
2406 2408
@@ -2434,7 +2436,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
2434#ifdef CONFIG_MLX4_EN_VXLAN 2436#ifdef CONFIG_MLX4_EN_VXLAN
2435 .ndo_add_vxlan_port = mlx4_en_add_vxlan_port, 2437 .ndo_add_vxlan_port = mlx4_en_add_vxlan_port,
2436 .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, 2438 .ndo_del_vxlan_port = mlx4_en_del_vxlan_port,
2437 .ndo_gso_check = mlx4_en_gso_check, 2439 .ndo_features_check = mlx4_en_features_check,
2438#endif 2440#endif
2439}; 2441};
2440 2442
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 1aa25b13ace1..9929b97cfb36 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -505,9 +505,11 @@ static void qlcnic_del_vxlan_port(struct net_device *netdev,
505 adapter->flags |= QLCNIC_DEL_VXLAN_PORT; 505 adapter->flags |= QLCNIC_DEL_VXLAN_PORT;
506} 506}
507 507
508static bool qlcnic_gso_check(struct sk_buff *skb, struct net_device *dev) 508static netdev_features_t qlcnic_features_check(struct sk_buff *skb,
509 struct net_device *dev,
510 netdev_features_t features)
509{ 511{
510 return vxlan_gso_check(skb); 512 return vxlan_features_check(skb, features);
511} 513}
512#endif 514#endif
513 515
@@ -532,7 +534,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
532#ifdef CONFIG_QLCNIC_VXLAN 534#ifdef CONFIG_QLCNIC_VXLAN
533 .ndo_add_vxlan_port = qlcnic_add_vxlan_port, 535 .ndo_add_vxlan_port = qlcnic_add_vxlan_port,
534 .ndo_del_vxlan_port = qlcnic_del_vxlan_port, 536 .ndo_del_vxlan_port = qlcnic_del_vxlan_port,
535 .ndo_gso_check = qlcnic_gso_check, 537 .ndo_features_check = qlcnic_features_check,
536#endif 538#endif
537#ifdef CONFIG_NET_POLL_CONTROLLER 539#ifdef CONFIG_NET_POLL_CONTROLLER
538 .ndo_poll_controller = qlcnic_poll_controller, 540 .ndo_poll_controller = qlcnic_poll_controller,
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c31f74d76ebd..679e6e90aa4c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1012,12 +1012,15 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
1012 * Callback to use for xmit over the accelerated station. This 1012 * Callback to use for xmit over the accelerated station. This
1013 * is used in place of ndo_start_xmit on accelerated net 1013 * is used in place of ndo_start_xmit on accelerated net
1014 * devices. 1014 * devices.
1015 * bool (*ndo_gso_check) (struct sk_buff *skb, 1015 * netdev_features_t (*ndo_features_check) (struct sk_buff *skb,
1016 * struct net_device *dev); 1016 * struct net_device *dev
1017 * netdev_features_t features);
1017 * Called by core transmit path to determine if device is capable of 1018 * Called by core transmit path to determine if device is capable of
1018 * performing GSO on a packet. The device returns true if it is 1019 * performing offload operations on a given packet. This is to give
1019 * able to GSO the packet, false otherwise. If the return value is 1020 * the device an opportunity to implement any restrictions that cannot
1020 * false the stack will do software GSO. 1021 * be otherwise expressed by feature flags. The check is called with
1022 * the set of features that the stack has calculated and it returns
1023 * those the driver believes to be appropriate.
1021 * 1024 *
1022 * int (*ndo_switch_parent_id_get)(struct net_device *dev, 1025 * int (*ndo_switch_parent_id_get)(struct net_device *dev,
1023 * struct netdev_phys_item_id *psid); 1026 * struct netdev_phys_item_id *psid);
@@ -1178,8 +1181,9 @@ struct net_device_ops {
1178 struct net_device *dev, 1181 struct net_device *dev,
1179 void *priv); 1182 void *priv);
1180 int (*ndo_get_lock_subclass)(struct net_device *dev); 1183 int (*ndo_get_lock_subclass)(struct net_device *dev);
1181 bool (*ndo_gso_check) (struct sk_buff *skb, 1184 netdev_features_t (*ndo_features_check) (struct sk_buff *skb,
1182 struct net_device *dev); 1185 struct net_device *dev,
1186 netdev_features_t features);
1183#ifdef CONFIG_NET_SWITCHDEV 1187#ifdef CONFIG_NET_SWITCHDEV
1184 int (*ndo_switch_parent_id_get)(struct net_device *dev, 1188 int (*ndo_switch_parent_id_get)(struct net_device *dev,
1185 struct netdev_phys_item_id *psid); 1189 struct netdev_phys_item_id *psid);
@@ -3611,8 +3615,6 @@ static inline bool netif_needs_gso(struct net_device *dev, struct sk_buff *skb,
3611 netdev_features_t features) 3615 netdev_features_t features)
3612{ 3616{
3613 return skb_is_gso(skb) && (!skb_gso_ok(skb, features) || 3617 return skb_is_gso(skb) && (!skb_gso_ok(skb, features) ||
3614 (dev->netdev_ops->ndo_gso_check &&
3615 !dev->netdev_ops->ndo_gso_check(skb, dev)) ||
3616 unlikely((skb->ip_summed != CHECKSUM_PARTIAL) && 3618 unlikely((skb->ip_summed != CHECKSUM_PARTIAL) &&
3617 (skb->ip_summed != CHECKSUM_UNNECESSARY))); 3619 (skb->ip_summed != CHECKSUM_UNNECESSARY)));
3618} 3620}
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 57cccd0052e5..903461aa5644 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -1,6 +1,9 @@
1#ifndef __NET_VXLAN_H 1#ifndef __NET_VXLAN_H
2#define __NET_VXLAN_H 1 2#define __NET_VXLAN_H 1
3 3
4#include <linux/ip.h>
5#include <linux/ipv6.h>
6#include <linux/if_vlan.h>
4#include <linux/skbuff.h> 7#include <linux/skbuff.h>
5#include <linux/netdevice.h> 8#include <linux/netdevice.h>
6#include <linux/udp.h> 9#include <linux/udp.h>
@@ -51,16 +54,33 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
51 __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, 54 __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
52 __be16 src_port, __be16 dst_port, __be32 vni, bool xnet); 55 __be16 src_port, __be16 dst_port, __be32 vni, bool xnet);
53 56
54static inline bool vxlan_gso_check(struct sk_buff *skb) 57static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
58 netdev_features_t features)
55{ 59{
56 if ((skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) && 60 u8 l4_hdr = 0;
61
62 if (!skb->encapsulation)
63 return features;
64
65 switch (vlan_get_protocol(skb)) {
66 case htons(ETH_P_IP):
67 l4_hdr = ip_hdr(skb)->protocol;
68 break;
69 case htons(ETH_P_IPV6):
70 l4_hdr = ipv6_hdr(skb)->nexthdr;
71 break;
72 default:
73 return features;;
74 }
75
76 if ((l4_hdr == IPPROTO_UDP) &&
57 (skb->inner_protocol_type != ENCAP_TYPE_ETHER || 77 (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
58 skb->inner_protocol != htons(ETH_P_TEB) || 78 skb->inner_protocol != htons(ETH_P_TEB) ||
59 (skb_inner_mac_header(skb) - skb_transport_header(skb) != 79 (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
60 sizeof(struct udphdr) + sizeof(struct vxlanhdr)))) 80 sizeof(struct udphdr) + sizeof(struct vxlanhdr))))
61 return false; 81 return features & ~(NETIF_F_ALL_CSUM | NETIF_F_GSO_MASK);
62 82
63 return true; 83 return features;
64} 84}
65 85
66/* IP header + UDP + VXLAN + Ethernet header */ 86/* IP header + UDP + VXLAN + Ethernet header */
diff --git a/net/core/dev.c b/net/core/dev.c
index 0094562b732a..683d493aa1bf 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2563,7 +2563,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
2563 2563
2564netdev_features_t netif_skb_features(struct sk_buff *skb) 2564netdev_features_t netif_skb_features(struct sk_buff *skb)
2565{ 2565{
2566 const struct net_device *dev = skb->dev; 2566 struct net_device *dev = skb->dev;
2567 netdev_features_t features = dev->features; 2567 netdev_features_t features = dev->features;
2568 u16 gso_segs = skb_shinfo(skb)->gso_segs; 2568 u16 gso_segs = skb_shinfo(skb)->gso_segs;
2569 __be16 protocol = skb->protocol; 2569 __be16 protocol = skb->protocol;
@@ -2571,13 +2571,20 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
2571 if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) 2571 if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs)
2572 features &= ~NETIF_F_GSO_MASK; 2572 features &= ~NETIF_F_GSO_MASK;
2573 2573
2574 /* If encapsulation offload request, verify we are testing
2575 * hardware encapsulation features instead of standard
2576 * features for the netdev
2577 */
2578 if (skb->encapsulation)
2579 features &= dev->hw_enc_features;
2580
2574 if (!vlan_tx_tag_present(skb)) { 2581 if (!vlan_tx_tag_present(skb)) {
2575 if (unlikely(protocol == htons(ETH_P_8021Q) || 2582 if (unlikely(protocol == htons(ETH_P_8021Q) ||
2576 protocol == htons(ETH_P_8021AD))) { 2583 protocol == htons(ETH_P_8021AD))) {
2577 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; 2584 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
2578 protocol = veh->h_vlan_encapsulated_proto; 2585 protocol = veh->h_vlan_encapsulated_proto;
2579 } else { 2586 } else {
2580 return harmonize_features(skb, features); 2587 goto finalize;
2581 } 2588 }
2582 } 2589 }
2583 2590
@@ -2595,6 +2602,11 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
2595 NETIF_F_HW_VLAN_CTAG_TX | 2602 NETIF_F_HW_VLAN_CTAG_TX |
2596 NETIF_F_HW_VLAN_STAG_TX); 2603 NETIF_F_HW_VLAN_STAG_TX);
2597 2604
2605finalize:
2606 if (dev->netdev_ops->ndo_features_check)
2607 features &= dev->netdev_ops->ndo_features_check(skb, dev,
2608 features);
2609
2598 return harmonize_features(skb, features); 2610 return harmonize_features(skb, features);
2599} 2611}
2600EXPORT_SYMBOL(netif_skb_features); 2612EXPORT_SYMBOL(netif_skb_features);
@@ -2665,13 +2677,6 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
2665 if (unlikely(!skb)) 2677 if (unlikely(!skb))
2666 goto out_null; 2678 goto out_null;
2667 2679
2668 /* If encapsulation offload request, verify we are testing
2669 * hardware encapsulation features instead of standard
2670 * features for the netdev
2671 */
2672 if (skb->encapsulation)
2673 features &= dev->hw_enc_features;
2674
2675 if (netif_needs_gso(dev, skb, features)) { 2680 if (netif_needs_gso(dev, skb, features)) {
2676 struct sk_buff *segs; 2681 struct sk_buff *segs;
2677 2682