Skip to content

Commit d6b1aeb

Browse files
lxingregkh
authored andcommitted
ip6_gre: update dst pmtu if dev mtu has been updated by toobig in __gre6_xmit
[ Upstream commit 8aec495 ] When receiving a Toobig icmpv6 packet, ip6gre_err would just set tunnel dev's mtu, that's not enough. For skb_dst(skb)'s pmtu may still be using the old value, it has no chance to be updated with tunnel dev's mtu. Jianlin found this issue by reducing route's mtu while running netperf, the performance went to 0. ip6ip6 and ip4ip6 tunnel can work well with this, as they lookup the upper dst and update_pmtu it's pmtu or icmpv6_send a Toobig to upper socket after setting tunnel dev's mtu. We couldn't do that for ip6_gre, as gre's inner packet could be any protocol, it's difficult to handle them (like lookup upper dst) in a good way. So this patch is to fix it by updating skb_dst(skb)'s pmtu when dev->mtu < skb_dst(skb)'s pmtu in tx path. It's safe to do this update there, as usually dev->mtu <= skb_dst(skb)'s pmtu and no performance regression can be caused by this. Fixes: c12b395 ("gre: Support GRE over IPv6") Reported-by: Jianlin Shi <jishi@redhat.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 6d428bc commit d6b1aeb

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

net/ipv6/ip6_gre.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,8 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
508508
__u32 *pmtu, __be16 proto)
509509
{
510510
struct ip6_tnl *tunnel = netdev_priv(dev);
511-
__be16 protocol = (dev->type == ARPHRD_ETHER) ?
512-
htons(ETH_P_TEB) : proto;
511+
struct dst_entry *dst = skb_dst(skb);
512+
__be16 protocol;
513513

514514
if (dev->type == ARPHRD_ETHER)
515515
IPCB(skb)->flags = 0;
@@ -523,9 +523,14 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
523523
tunnel->o_seqno++;
524524

525525
/* Push GRE header. */
526+
protocol = (dev->type == ARPHRD_ETHER) ? htons(ETH_P_TEB) : proto;
526527
gre_build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags,
527528
protocol, tunnel->parms.o_key, htonl(tunnel->o_seqno));
528529

530+
/* TooBig packet may have updated dst->dev's mtu */
531+
if (dst && dst_mtu(dst) > dst->dev->mtu)
532+
dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu);
533+
529534
return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu,
530535
NEXTHDR_GRE);
531536
}

0 commit comments

Comments
 (0)