diff options
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 8 | ||||
-rw-r--r-- | include/linux/netdevice.h | 20 | ||||
-rw-r--r-- | include/net/vxlan.h | 28 | ||||
-rw-r--r-- | net/core/dev.c | 23 |
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 | ||
12556 | static bool bnx2x_gso_check(struct sk_buff *skb, struct net_device *dev) | 12556 | static 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 | ||
12561 | static const struct net_device_ops bnx2x_netdev_ops = { | 12563 | static 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 | ||
12595 | static int bnx2x_set_coherency_mask(struct bnx2x *bp) | 12597 | static 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 | ||
4462 | static bool be_gso_check(struct sk_buff *skb, struct net_device *dev) | 4462 | static 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 | ||
2368 | static bool mlx4_en_gso_check(struct sk_buff *skb, struct net_device *dev) | 2368 | static 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 | ||
508 | static bool qlcnic_gso_check(struct sk_buff *skb, struct net_device *dev) | 508 | static 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 | ||
54 | static inline bool vxlan_gso_check(struct sk_buff *skb) | 57 | static 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 | ||
2564 | netdev_features_t netif_skb_features(struct sk_buff *skb) | 2564 | netdev_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 | ||
2605 | finalize: | ||
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 | } |
2600 | EXPORT_SYMBOL(netif_skb_features); | 2612 | EXPORT_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 | ||