aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorIlan Tayari <ilant@mellanox.com>2017-04-19 14:26:07 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-03 11:36:36 -0400
commit7ab89b176b7a6c9366e4c3c309bf69be652e9baa (patch)
tree26f266165f92a2fb6b6e0a2d0225f1c8cd4c36e2 /net/core
parentfcbf5a71a646f03f731d67ad86acfaac2511d29a (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.c18
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