Commit 12b0004d1d1e2a9aa667412d479041e403bcafae
Committed by
David S. Miller
1 parent
25060d8f3f
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
net: adjust skb_gso_segment() for calling in rx path
skb_gso_segment() is almost always called in tx path, except for openvswitch. It calls this function when it receives the packet and tries to queue it to user-space. In this special case, the ->ip_summed check inside skb_gso_segment() is no longer true, as ->ip_summed value has different meanings on rx path. This patch adjusts skb_gso_segment() so that we can at least avoid such warnings on checksum. Cc: Jesse Gross <jesse@nicira.com> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Cong Wang <amwang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 3 changed files with 26 additions and 8 deletions Side-by-side Diff
include/linux/netdevice.h
... | ... | @@ -2662,8 +2662,15 @@ |
2662 | 2662 | extern void netdev_upper_dev_unlink(struct net_device *dev, |
2663 | 2663 | struct net_device *upper_dev); |
2664 | 2664 | extern int skb_checksum_help(struct sk_buff *skb); |
2665 | -extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, | |
2666 | - netdev_features_t features); | |
2665 | +extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb, | |
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 | 2674 | #ifdef CONFIG_BUG |
2668 | 2675 | extern void netdev_rx_csum_fault(struct net_device *dev); |
2669 | 2676 | #else |
net/core/dev.c
... | ... | @@ -2327,18 +2327,29 @@ |
2327 | 2327 | } |
2328 | 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 | 2342 | * @skb: buffer to segment |
2333 | 2343 | * @features: features for the output path (see dev->features) |
2344 | + * @tx_path: whether it is called in TX path | |
2334 | 2345 | * |
2335 | 2346 | * This function segments the given skb and returns a list of segments. |
2336 | 2347 | * |
2337 | 2348 | * It may return NULL if the skb requires no segmentation. This is |
2338 | 2349 | * only possible when GSO is used for verifying header integrity. |
2339 | 2350 | */ |
2340 | -struct sk_buff *skb_gso_segment(struct sk_buff *skb, | |
2341 | - netdev_features_t features) | |
2351 | +struct sk_buff *__skb_gso_segment(struct sk_buff *skb, | |
2352 | + netdev_features_t features, bool tx_path) | |
2342 | 2353 | { |
2343 | 2354 | struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); |
2344 | 2355 | struct packet_offload *ptype; |
... | ... | @@ -2361,7 +2372,7 @@ |
2361 | 2372 | skb->mac_len = skb->network_header - skb->mac_header; |
2362 | 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 | 2376 | skb_warn_bad_offload(skb); |
2366 | 2377 | |
2367 | 2378 | if (skb_header_cloned(skb) && |
... | ... | @@ -2390,7 +2401,7 @@ |
2390 | 2401 | |
2391 | 2402 | return segs; |
2392 | 2403 | } |
2393 | -EXPORT_SYMBOL(skb_gso_segment); | |
2404 | +EXPORT_SYMBOL(__skb_gso_segment); | |
2394 | 2405 | |
2395 | 2406 | /* Take action when hardware reception checksum errors are detected. */ |
2396 | 2407 | #ifdef CONFIG_BUG |
net/openvswitch/datapath.c