diff options
author | Ilan Tayari <ilant@mellanox.com> | 2017-04-19 14:26:07 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-03 11:36:36 -0400 |
commit | 7ab89b176b7a6c9366e4c3c309bf69be652e9baa (patch) | |
tree | 26f266165f92a2fb6b6e0a2d0225f1c8cd4c36e2 /net/core | |
parent | fcbf5a71a646f03f731d67ad86acfaac2511d29a (diff) |
gso: Validate assumption of frag_list segementation
[ Upstream commit 43170c4e0ba709c79130c3fe5a41e66279950cd0 ]
Commit 07b26c9454a2 ("gso: Support partial splitting at the frag_list
pointer") assumes that all SKBs in a frag_list (except maybe the last
one) contain the same amount of GSO payload.
This assumption is not always correct, resulting in the following
warning message in the log:
skb_segment: too many frags
For example, mlx5 driver in Striding RQ mode creates some RX SKBs with
one frag, and some with 2 frags.
After GRO, the frag_list SKBs end up having different amounts of payload.
If this frag_list SKB is then forwarded, the aforementioned assumption
is violated.
Validate the assumption, and fall back to software GSO if it not true.
Change-Id: Ia03983f4a47b6534dd987d7a2aad96d54d46d212
Fixes: 07b26c9454a2 ("gso: Support partial splitting at the frag_list pointer")
Signed-off-by: Ilan Tayari <ilant@mellanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/skbuff.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5ec34eae3f0a..fe008f1bd930 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -3076,22 +3076,32 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, | |||
3076 | if (sg && csum && (mss != GSO_BY_FRAGS)) { | 3076 | if (sg && csum && (mss != GSO_BY_FRAGS)) { |
3077 | if (!(features & NETIF_F_GSO_PARTIAL)) { | 3077 | if (!(features & NETIF_F_GSO_PARTIAL)) { |
3078 | struct sk_buff *iter; | 3078 | struct sk_buff *iter; |
3079 | unsigned int frag_len; | ||
3079 | 3080 | ||
3080 | if (!list_skb || | 3081 | if (!list_skb || |
3081 | !net_gso_ok(features, skb_shinfo(head_skb)->gso_type)) | 3082 | !net_gso_ok(features, skb_shinfo(head_skb)->gso_type)) |
3082 | goto normal; | 3083 | goto normal; |
3083 | 3084 | ||
3084 | /* Split the buffer at the frag_list pointer. | 3085 | /* If we get here then all the required |
3085 | * This is based on the assumption that all | 3086 | * GSO features except frag_list are supported. |
3086 | * buffers in the chain excluding the last | 3087 | * Try to split the SKB to multiple GSO SKBs |
3087 | * containing the same amount of data. | 3088 | * with no frag_list. |
3089 | * Currently we can do that only when the buffers don't | ||
3090 | * have a linear part and all the buffers except | ||
3091 | * the last are of the same length. | ||
3088 | */ | 3092 | */ |
3093 | frag_len = list_skb->len; | ||
3089 | skb_walk_frags(head_skb, iter) { | 3094 | skb_walk_frags(head_skb, iter) { |
3095 | if (frag_len != iter->len && iter->next) | ||
3096 | goto normal; | ||
3090 | if (skb_headlen(iter)) | 3097 | if (skb_headlen(iter)) |
3091 | goto normal; | 3098 | goto normal; |
3092 | 3099 | ||
3093 | len -= iter->len; | 3100 | len -= iter->len; |
3094 | } | 3101 | } |
3102 | |||
3103 | if (len != frag_len) | ||
3104 | goto normal; | ||
3095 | } | 3105 | } |
3096 | 3106 | ||
3097 | /* GSO partial only requires that we trim off any excess that | 3107 | /* GSO partial only requires that we trim off any excess that |