lkml.org 
[lkml]   [2021]   [Jul]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 59/71] net: ip_tunnel: fix mtu calculation for ETHER tunnel devices
    Date
    From: Hangbin Liu <liuhangbin@gmail.com>

    commit 9992a078b1771da354ac1f9737e1e639b687caa2 upstream.

    Commit 28e104d00281 ("net: ip_tunnel: fix mtu calculation") removed
    dev->hard_header_len subtraction when calculate MTU for tunnel devices
    as there is an overhead for device that has header_ops.

    But there are ETHER tunnel devices, like gre_tap or erspan, which don't
    have header_ops but set dev->hard_header_len during setup. This makes
    pkts greater than (MTU - ETH_HLEN) could not be xmited. Fix it by
    subtracting the ETHER tunnel devices' dev->hard_header_len for MTU
    calculation.

    Fixes: 28e104d00281 ("net: ip_tunnel: fix mtu calculation")
    Reported-by: Jianlin Shi <jishi@redhat.com>
    Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/ipv4/ip_tunnel.c | 18 +++++++++++++++---
    1 file changed, 15 insertions(+), 3 deletions(-)

    --- a/net/ipv4/ip_tunnel.c
    +++ b/net/ipv4/ip_tunnel.c
    @@ -317,7 +317,7 @@ static int ip_tunnel_bind_dev(struct net
    }

    dev->needed_headroom = t_hlen + hlen;
    - mtu -= t_hlen;
    + mtu -= t_hlen + (dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0);

    if (mtu < IPV4_MIN_MTU)
    mtu = IPV4_MIN_MTU;
    @@ -348,6 +348,9 @@ static struct ip_tunnel *ip_tunnel_creat
    t_hlen = nt->hlen + sizeof(struct iphdr);
    dev->min_mtu = ETH_MIN_MTU;
    dev->max_mtu = IP_MAX_MTU - t_hlen;
    + if (dev->type == ARPHRD_ETHER)
    + dev->max_mtu -= dev->hard_header_len;
    +
    ip_tunnel_add(itn, nt);
    return nt;

    @@ -495,11 +498,14 @@ static int tnl_update_pmtu(struct net_de

    tunnel_hlen = md ? tunnel_hlen : tunnel->hlen;
    pkt_size = skb->len - tunnel_hlen;
    + pkt_size -= dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0;

    - if (df)
    + if (df) {
    mtu = dst_mtu(&rt->dst) - (sizeof(struct iphdr) + tunnel_hlen);
    - else
    + mtu -= dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0;
    + } else {
    mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
    + }

    if (skb_valid_dst(skb))
    skb_dst_update_pmtu_no_confirm(skb, mtu);
    @@ -965,6 +971,9 @@ int __ip_tunnel_change_mtu(struct net_de
    int t_hlen = tunnel->hlen + sizeof(struct iphdr);
    int max_mtu = IP_MAX_MTU - t_hlen;

    + if (dev->type == ARPHRD_ETHER)
    + max_mtu -= dev->hard_header_len;
    +
    if (new_mtu < ETH_MIN_MTU)
    return -EINVAL;

    @@ -1142,6 +1151,9 @@ int ip_tunnel_newlink(struct net_device
    if (tb[IFLA_MTU]) {
    unsigned int max = IP_MAX_MTU - (nt->hlen + sizeof(struct iphdr));

    + if (dev->type == ARPHRD_ETHER)
    + max -= dev->hard_header_len;
    +
    mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, max);
    }


    \
     
     \ /
      Last update: 2021-07-22 19:36    [W:4.112 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site