Skip to content

Commit c40e89f

Browse files
akodanevdavem330
authored andcommitted
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>
1 parent 321acc1 commit c40e89f

File tree

1 file changed

+53
-3
lines changed

1 file changed

+53
-3
lines changed

drivers/net/geneve.c

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,48 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
13871387
return -EOPNOTSUPP;
13881388
}
13891389

1390+
static void geneve_link_config(struct net_device *dev,
1391+
struct ip_tunnel_info *info, struct nlattr *tb[])
1392+
{
1393+
struct geneve_dev *geneve = netdev_priv(dev);
1394+
int ldev_mtu = 0;
1395+
1396+
if (tb[IFLA_MTU]) {
1397+
geneve_change_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
1398+
return;
1399+
}
1400+
1401+
switch (ip_tunnel_info_af(info)) {
1402+
case AF_INET: {
1403+
struct flowi4 fl4 = { .daddr = info->key.u.ipv4.dst };
1404+
struct rtable *rt = ip_route_output_key(geneve->net, &fl4);
1405+
1406+
if (!IS_ERR(rt) && rt->dst.dev) {
1407+
ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV4_HLEN;
1408+
ip_rt_put(rt);
1409+
}
1410+
break;
1411+
}
1412+
#if IS_ENABLED(CONFIG_IPV6)
1413+
case AF_INET6: {
1414+
struct rt6_info *rt = rt6_lookup(geneve->net,
1415+
&info->key.u.ipv6.dst, NULL, 0,
1416+
NULL, 0);
1417+
1418+
if (rt && rt->dst.dev)
1419+
ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN;
1420+
ip6_rt_put(rt);
1421+
break;
1422+
}
1423+
#endif
1424+
}
1425+
1426+
if (ldev_mtu <= 0)
1427+
return;
1428+
1429+
geneve_change_mtu(dev, ldev_mtu - info->options_len);
1430+
}
1431+
13901432
static int geneve_newlink(struct net *net, struct net_device *dev,
13911433
struct nlattr *tb[], struct nlattr *data[],
13921434
struct netlink_ext_ack *extack)
@@ -1402,8 +1444,14 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
14021444
if (err)
14031445
return err;
14041446

1405-
return geneve_configure(net, dev, extack, &info, metadata,
1406-
use_udp6_rx_checksums);
1447+
err = geneve_configure(net, dev, extack, &info, metadata,
1448+
use_udp6_rx_checksums);
1449+
if (err)
1450+
return err;
1451+
1452+
geneve_link_config(dev, &info, tb);
1453+
1454+
return 0;
14071455
}
14081456

14091457
/* 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[],
14771525
if (err)
14781526
return err;
14791527

1480-
if (!geneve_dst_addr_equal(&geneve->info, &info))
1528+
if (!geneve_dst_addr_equal(&geneve->info, &info)) {
14811529
dst_cache_reset(&info.dst_cache);
1530+
geneve_link_config(dev, &info, tb);
1531+
}
14821532

14831533
geneve_quiesce(geneve, &gs4, &gs6);
14841534
geneve->info = info;

0 commit comments

Comments
 (0)