1
0
Fork 0

geneve: configure MTU based on a lower device

Currently, on a new link creation or when 'remote' address parameter
is updated, an MTU is not changed and always equals 1500. When a lower
device has a larger MTU, it might not be efficient, e.g. for UDP, and
requires the manual MTU adjustments to match the MTU of the lower
device.

This patch tries to automate this process, finds a lower device using
the 'remote' address parameter, then uses its MTU to tune GENEVE's MTU:
  * on a new link creation
  * when 'remote' parameter is changed

Also with this patch, the MTU from a user, on a new link creation, is
passed to geneve_change_mtu() where it is verified, and MTU adjustments
with a lower device is skipped in that case. Prior that change, it was
possible to set the invalid MTU values on a new link creation.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
hifive-unleashed-5.1
Alexey Kodanev 2018-04-19 15:42:32 +03:00 committed by David S. Miller
parent 321acc1c68
commit c40e89fd35
1 changed files with 53 additions and 3 deletions

View File

@ -1387,6 +1387,48 @@ change_notsup:
return -EOPNOTSUPP;
}
static void geneve_link_config(struct net_device *dev,
struct ip_tunnel_info *info, struct nlattr *tb[])
{
struct geneve_dev *geneve = netdev_priv(dev);
int ldev_mtu = 0;
if (tb[IFLA_MTU]) {
geneve_change_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
return;
}
switch (ip_tunnel_info_af(info)) {
case AF_INET: {
struct flowi4 fl4 = { .daddr = info->key.u.ipv4.dst };
struct rtable *rt = ip_route_output_key(geneve->net, &fl4);
if (!IS_ERR(rt) && rt->dst.dev) {
ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV4_HLEN;
ip_rt_put(rt);
}
break;
}
#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6: {
struct rt6_info *rt = rt6_lookup(geneve->net,
&info->key.u.ipv6.dst, NULL, 0,
NULL, 0);
if (rt && rt->dst.dev)
ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN;
ip6_rt_put(rt);
break;
}
#endif
}
if (ldev_mtu <= 0)
return;
geneve_change_mtu(dev, ldev_mtu - info->options_len);
}
static int geneve_newlink(struct net *net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
@ -1402,8 +1444,14 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
if (err)
return err;
return geneve_configure(net, dev, extack, &info, metadata,
use_udp6_rx_checksums);
err = geneve_configure(net, dev, extack, &info, metadata,
use_udp6_rx_checksums);
if (err)
return err;
geneve_link_config(dev, &info, tb);
return 0;
}
/* Quiesces the geneve device data path for both TX and RX.
@ -1477,8 +1525,10 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
if (err)
return err;
if (!geneve_dst_addr_equal(&geneve->info, &info))
if (!geneve_dst_addr_equal(&geneve->info, &info)) {
dst_cache_reset(&info.dst_cache);
geneve_link_config(dev, &info, tb);
}
geneve_quiesce(geneve, &gs4, &gs6);
geneve->info = info;