Commit c40e89fd authored by Alexey Kodanev's avatar Alexey Kodanev Committed by David S. Miller

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: default avatarAlexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 321acc1c
...@@ -1387,6 +1387,48 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[], ...@@ -1387,6 +1387,48 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
return -EOPNOTSUPP; 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, static int geneve_newlink(struct net *net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[], struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
...@@ -1402,8 +1444,14 @@ static int geneve_newlink(struct net *net, struct net_device *dev, ...@@ -1402,8 +1444,14 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
if (err) if (err)
return err; return err;
return geneve_configure(net, dev, extack, &info, metadata, err = geneve_configure(net, dev, extack, &info, metadata,
use_udp6_rx_checksums); 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. /* 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[], ...@@ -1477,8 +1525,10 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
if (err) if (err)
return 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); dst_cache_reset(&info.dst_cache);
geneve_link_config(dev, &info, tb);
}
geneve_quiesce(geneve, &gs4, &gs6); geneve_quiesce(geneve, &gs4, &gs6);
geneve->info = info; geneve->info = info;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment