lkml.org 
[lkml]   [2017]   [May]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 24/54] gso: Validate assumption of frag_list segementation
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Ilan Tayari <ilant@mellanox.com>


    [ 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>
    ---
    net/core/skbuff.c | 18 ++++++++++++++----
    1 file changed, 14 insertions(+), 4 deletions(-)

    --- a/net/core/skbuff.c
    +++ b/net/core/skbuff.c
    @@ -3076,22 +3076,32 @@ struct sk_buff *skb_segment(struct sk_bu
    if (sg && csum && (mss != GSO_BY_FRAGS)) {
    if (!(features & NETIF_F_GSO_PARTIAL)) {
    struct sk_buff *iter;
    + unsigned int frag_len;

    if (!list_skb ||
    !net_gso_ok(features, skb_shinfo(head_skb)->gso_type))
    goto normal;

    - /* Split the buffer at the frag_list pointer.
    - * This is based on the assumption that all
    - * buffers in the chain excluding the last
    - * containing the same amount of data.
    + /* If we get here then all the required
    + * GSO features except frag_list are supported.
    + * Try to split the SKB to multiple GSO SKBs
    + * with no frag_list.
    + * Currently we can do that only when the buffers don't
    + * have a linear part and all the buffers except
    + * the last are of the same length.
    */
    + frag_len = list_skb->len;
    skb_walk_frags(head_skb, iter) {
    + if (frag_len != iter->len && iter->next)
    + goto normal;
    if (skb_headlen(iter))
    goto normal;

    len -= iter->len;
    }
    +
    + if (len != frag_len)
    + goto normal;
    }

    /* GSO partial only requires that we trim off any excess that

    \
     
     \ /
      Last update: 2017-05-01 23:57    [W:5.983 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site