diff options
-rw-r--r-- | include/linux/netdevice.h | 11 | ||||
-rw-r--r-- | net/core/dev.c | 21 | ||||
-rw-r--r-- | net/openvswitch/datapath.c | 2 |
3 files changed, 26 insertions, 8 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 85b0949d9946..ab2774eb49e8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -2662,8 +2662,15 @@ extern int netdev_master_upper_dev_link(struct net_device *dev, | |||
2662 | extern void netdev_upper_dev_unlink(struct net_device *dev, | 2662 | extern void netdev_upper_dev_unlink(struct net_device *dev, |
2663 | struct net_device *upper_dev); | 2663 | struct net_device *upper_dev); |
2664 | extern int skb_checksum_help(struct sk_buff *skb); | 2664 | extern int skb_checksum_help(struct sk_buff *skb); |
2665 | extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, | 2665 | extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb, |
2666 | netdev_features_t features); | 2666 | netdev_features_t features, bool tx_path); |
2667 | |||
2668 | static inline | ||
2669 | struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features) | ||
2670 | { | ||
2671 | return __skb_gso_segment(skb, features, true); | ||
2672 | } | ||
2673 | |||
2667 | #ifdef CONFIG_BUG | 2674 | #ifdef CONFIG_BUG |
2668 | extern void netdev_rx_csum_fault(struct net_device *dev); | 2675 | extern void netdev_rx_csum_fault(struct net_device *dev); |
2669 | #else | 2676 | #else |
diff --git a/net/core/dev.c b/net/core/dev.c index 2b275a7b8677..65da698c500b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2327,18 +2327,29 @@ out: | |||
2327 | } | 2327 | } |
2328 | EXPORT_SYMBOL(skb_checksum_help); | 2328 | EXPORT_SYMBOL(skb_checksum_help); |
2329 | 2329 | ||
2330 | /* openvswitch calls this on rx path, so we need a different check. | ||
2331 | */ | ||
2332 | static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) | ||
2333 | { | ||
2334 | if (tx_path) | ||
2335 | return skb->ip_summed != CHECKSUM_PARTIAL; | ||
2336 | else | ||
2337 | return skb->ip_summed == CHECKSUM_NONE; | ||
2338 | } | ||
2339 | |||
2330 | /** | 2340 | /** |
2331 | * skb_gso_segment - Perform segmentation on skb. | 2341 | * __skb_gso_segment - Perform segmentation on skb. |
2332 | * @skb: buffer to segment | 2342 | * @skb: buffer to segment |
2333 | * @features: features for the output path (see dev->features) | 2343 | * @features: features for the output path (see dev->features) |
2344 | * @tx_path: whether it is called in TX path | ||
2334 | * | 2345 | * |
2335 | * This function segments the given skb and returns a list of segments. | 2346 | * This function segments the given skb and returns a list of segments. |
2336 | * | 2347 | * |
2337 | * It may return NULL if the skb requires no segmentation. This is | 2348 | * It may return NULL if the skb requires no segmentation. This is |
2338 | * only possible when GSO is used for verifying header integrity. | 2349 | * only possible when GSO is used for verifying header integrity. |
2339 | */ | 2350 | */ |
2340 | struct sk_buff *skb_gso_segment(struct sk_buff *skb, | 2351 | struct sk_buff *__skb_gso_segment(struct sk_buff *skb, |
2341 | netdev_features_t features) | 2352 | netdev_features_t features, bool tx_path) |
2342 | { | 2353 | { |
2343 | struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); | 2354 | struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); |
2344 | struct packet_offload *ptype; | 2355 | struct packet_offload *ptype; |
@@ -2361,7 +2372,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, | |||
2361 | skb->mac_len = skb->network_header - skb->mac_header; | 2372 | skb->mac_len = skb->network_header - skb->mac_header; |
2362 | __skb_pull(skb, skb->mac_len); | 2373 | __skb_pull(skb, skb->mac_len); |
2363 | 2374 | ||
2364 | if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { | 2375 | if (unlikely(skb_needs_check(skb, tx_path))) { |
2365 | skb_warn_bad_offload(skb); | 2376 | skb_warn_bad_offload(skb); |
2366 | 2377 | ||
2367 | if (skb_header_cloned(skb) && | 2378 | if (skb_header_cloned(skb) && |
@@ -2390,7 +2401,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, | |||
2390 | 2401 | ||
2391 | return segs; | 2402 | return segs; |
2392 | } | 2403 | } |
2393 | EXPORT_SYMBOL(skb_gso_segment); | 2404 | EXPORT_SYMBOL(__skb_gso_segment); |
2394 | 2405 | ||
2395 | /* Take action when hardware reception checksum errors are detected. */ | 2406 | /* Take action when hardware reception checksum errors are detected. */ |
2396 | #ifdef CONFIG_BUG | 2407 | #ifdef CONFIG_BUG |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index d8c13a965459..9dc537df46c4 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -301,7 +301,7 @@ static int queue_gso_packets(struct net *net, int dp_ifindex, | |||
301 | struct sk_buff *segs, *nskb; | 301 | struct sk_buff *segs, *nskb; |
302 | int err; | 302 | int err; |
303 | 303 | ||
304 | segs = skb_gso_segment(skb, NETIF_F_SG | NETIF_F_HW_CSUM); | 304 | segs = __skb_gso_segment(skb, NETIF_F_SG | NETIF_F_HW_CSUM, false); |
305 | if (IS_ERR(segs)) | 305 | if (IS_ERR(segs)) |
306 | return PTR_ERR(segs); | 306 | return PTR_ERR(segs); |
307 | 307 | ||