aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/skbuff.c')
-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