Message ID | 1513265870-29851-1-git-send-email-alexey.kodanev@oracle.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
Series | [net-next,v3] ip6_vti: adjust vti mtu according to mtu of output device | expand |
From: Alexey Kodanev <alexey.kodanev@oracle.com> Date: Thu, 14 Dec 2017 18:37:50 +0300 Two minor pieces of feedback: > LTP/udp6_ipsec_vti tests fail when sending large UDP datagrams that > require fragmentation and the underlying device has MTU <= 1500. This > happens because ip6_vti sets mtu to ETH_DATA_LEN and not updating it > depending on a destination address or link parameter. > > Further attempts to send UDP packets may succeed because pmtu gets > updated on ICMPV6_PKT_TOOBIG in vti6_err(). > > Here is the example when the output device MTU is set to 9000: You are fixing a problem that occurs when the underlying device has an MTU smaller than 1500, yet you show an example involving an MTU of 9000. Care to adjust that inconsistency or explain why it's legit here? > + if (p->flags & IP6_TNL_F_CAP_XMIT) { > + int strict = (ipv6_addr_type(&p->raddr) & > + (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); > + > + struct rt6_info *rt = rt6_lookup(t->net, > + &p->raddr, &p->laddr, > + p->link, strict); Please do not place empty lines between local variable declarations. Thank you.
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index dbb74f3..5404443 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -626,6 +626,7 @@ static void vti6_link_config(struct ip6_tnl *t) { struct net_device *dev = t->dev; struct __ip6_tnl_parm *p = &t->parms; + struct net_device *tdev = NULL; memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); @@ -638,6 +639,26 @@ static void vti6_link_config(struct ip6_tnl *t) dev->flags |= IFF_POINTOPOINT; else dev->flags &= ~IFF_POINTOPOINT; + + if (p->flags & IP6_TNL_F_CAP_XMIT) { + int strict = (ipv6_addr_type(&p->raddr) & + (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); + + struct rt6_info *rt = rt6_lookup(t->net, + &p->raddr, &p->laddr, + p->link, strict); + + if (rt) + tdev = rt->dst.dev; + ip6_rt_put(rt); + } + + if (!tdev && p->link) + tdev = __dev_get_by_index(t->net, p->link); + + if (tdev) + dev->mtu = max_t(int, tdev->mtu - dev->hard_header_len, + IPV6_MIN_MTU); } /**