From 917b3b453b787f5433f5b589ba49f2bbe9221cc9 Mon Sep 17 00:00:00 2001 From: David Wragg Date: Thu, 18 Feb 2016 17:43:29 +0000 Subject: [PATCH] datapath: geneve: Refine MTU limit. Upstream commit: Calculate the maximum MTU taking into account the size of headers involved in GENEVE encapsulation, as for other tunnel types. Changes in v3: - Correct comment style Changes in v2: - Conform more closely to ip_tunnel_change_mtu - Exclude GENEVE options from max MTU calculation Signed-off-by: David Wragg Acked-by: Jesse Gross Signed-off-by: David S. Miller Upstream: aeee0e66c6b4 ("geneve: Refine MTU limit") Signed-off-by: Joe Stringer Acked-by: Jesse Gross --- datapath/linux/compat/geneve.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c index 50ed3936d..92feeef09 100644 --- a/datapath/linux/compat/geneve.c +++ b/datapath/linux/compat/geneve.c @@ -742,17 +742,34 @@ static netdev_tx_t geneve_dev_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int geneve_change_mtu(struct net_device *dev, int new_mtu) +static int __geneve_change_mtu(struct net_device *dev, int new_mtu, bool strict) { - /* GENEVE overhead is not fixed, so we can't enforce a more - * precise max MTU. + /* The max_mtu calculation does not take account of GENEVE + * options, to avoid excluding potentially valid + * configurations. */ - if (new_mtu < 68 || new_mtu > IP_MAX_MTU) + int max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - sizeof(struct iphdr) + - dev->hard_header_len; + + if (new_mtu < 68) return -EINVAL; + + if (new_mtu > max_mtu) { + if (strict) + return -EINVAL; + + new_mtu = max_mtu; + } + dev->mtu = new_mtu; return 0; } +static int geneve_change_mtu(struct net_device *dev, int new_mtu) +{ + return __geneve_change_mtu(dev, new_mtu, true); +} + static const struct net_device_ops geneve_netdev_ops = { #ifdef HAVE_DEV_TSTATS .ndo_init = geneve_init, @@ -1045,7 +1062,7 @@ struct net_device *rpl_geneve_dev_create_fb(struct net *net, const char *name, /* openvswitch users expect packet sizes to be unrestricted, * so set the largest MTU we can. */ - err = geneve_change_mtu(dev, IP_MAX_MTU); + err = __geneve_change_mtu(dev, IP_MAX_MTU, false); if (err) goto err; -- 2.20.1