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>
This commit is contained in:
Родитель
321acc1c68
Коммит
c40e89fd35
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче