Skip to content

Commit

Permalink
Merge branch 'ovs-tunnel-mtu'
Browse files Browse the repository at this point in the history
David Wragg says:

====================
Set a large MTU on ovs-created tunnel devices

Prior to 4.3, openvswitch tunnel vports (vxlan, gre and geneve) could
transmit vxlan packets of any size, constrained only by the ability to
send out the resulting packets.  4.3 introduced netdevs corresponding
to tunnel vports.  These netdevs have an MTU, which limits the size of
a packet that can be successfully encapsulated.  The default MTU
values are low (1500 or less), which is awkwardly small in the context
of physical networks supporting jumbo frames, and leads to a
conspicuous change in behaviour for userspace.

This patch series sets the MTU on openvswitch-created netdevs to be
the relevant maximum (i.e. the maximum IP packet size minus any
relevant overhead), effectively restoring the behaviour prior to 4.3.

Where relevant, the limits on MTU values that can be directly set on
the netdevs are also relaxed.

Changes in v2:
* Extend to all openvswitch tunnel types, i.e. gre and geneve as well
* Use IP_MAX_MTU

Changes in v3:
* Fix block comment style
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Feb 10, 2016
2 parents 461547f + 7e05915 commit 1902750
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 22 deletions.
31 changes: 26 additions & 5 deletions drivers/net/geneve.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,17 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
return geneve_xmit_skb(skb, dev, info);
}

static int geneve_change_mtu(struct net_device *dev, int new_mtu)
{
/* GENEVE overhead is not fixed, so we can't enforce a more
* precise max MTU.
*/
if (new_mtu < 68 || new_mtu > IP_MAX_MTU)
return -EINVAL;
dev->mtu = new_mtu;
return 0;
}

static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
{
struct ip_tunnel_info *info = skb_tunnel_info(skb);
Expand Down Expand Up @@ -1083,7 +1094,7 @@ static const struct net_device_ops geneve_netdev_ops = {
.ndo_stop = geneve_stop,
.ndo_start_xmit = geneve_xmit,
.ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_change_mtu = eth_change_mtu,
.ndo_change_mtu = geneve_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_fill_metadata_dst = geneve_fill_metadata_dst,
Expand Down Expand Up @@ -1442,11 +1453,21 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,

err = geneve_configure(net, dev, &geneve_remote_unspec,
0, 0, 0, htons(dst_port), true, 0);
if (err) {
free_netdev(dev);
return ERR_PTR(err);
}
if (err)
goto err;

/* openvswitch users expect packet sizes to be unrestricted,
* so set the largest MTU we can.
*/
err = geneve_change_mtu(dev, IP_MAX_MTU);
if (err)
goto err;

return dev;

err:
free_netdev(dev);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(geneve_dev_create_fb);

Expand Down
47 changes: 33 additions & 14 deletions drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -2367,29 +2367,43 @@ static void vxlan_set_multicast_list(struct net_device *dev)
{
}

static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
static int __vxlan_change_mtu(struct net_device *dev,
struct net_device *lowerdev,
struct vxlan_rdst *dst, int new_mtu, bool strict)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_rdst *dst = &vxlan->default_dst;
struct net_device *lowerdev;
int max_mtu;
int max_mtu = IP_MAX_MTU;

lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex);
if (lowerdev == NULL)
return eth_change_mtu(dev, new_mtu);
if (lowerdev)
max_mtu = lowerdev->mtu;

if (dst->remote_ip.sa.sa_family == AF_INET6)
max_mtu = lowerdev->mtu - VXLAN6_HEADROOM;
max_mtu -= VXLAN6_HEADROOM;
else
max_mtu = lowerdev->mtu - VXLAN_HEADROOM;
max_mtu -= VXLAN_HEADROOM;

if (new_mtu < 68 || new_mtu > max_mtu)
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 vxlan_change_mtu(struct net_device *dev, int new_mtu)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_rdst *dst = &vxlan->default_dst;
struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
dst->remote_ifindex);
return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true);
}

static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
struct ip_tunnel_info *info,
__be16 sport, __be16 dport)
Expand Down Expand Up @@ -2765,6 +2779,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
int err;
bool use_ipv6 = false;
__be16 default_port = vxlan->cfg.dst_port;
struct net_device *lowerdev = NULL;

vxlan->net = src_net;

Expand All @@ -2785,9 +2800,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
}

if (conf->remote_ifindex) {
struct net_device *lowerdev
= __dev_get_by_index(src_net, conf->remote_ifindex);

lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex);
dst->remote_ifindex = conf->remote_ifindex;

if (!lowerdev) {
Expand All @@ -2811,6 +2824,12 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
needed_headroom = lowerdev->hard_header_len;
}

if (conf->mtu) {
err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false);
if (err)
return err;
}

if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
needed_headroom += VXLAN6_HEADROOM;
else
Expand Down
1 change: 1 addition & 0 deletions include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
u8 *protocol, struct flowi4 *fl4);
int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);

struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
Expand Down
8 changes: 8 additions & 0 deletions net/ipv4/ip_gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,14 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
err = ipgre_newlink(net, dev, tb, NULL);
if (err < 0)
goto out;

/* openvswitch users expect packet sizes to be unrestricted,
* so set the largest MTU we can.
*/
err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
if (err)
goto out;

return dev;
out:
free_netdev(dev);
Expand Down
20 changes: 17 additions & 3 deletions net/ipv4/ip_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -943,17 +943,31 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
}
EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);

int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
int t_hlen = tunnel->hlen + sizeof(struct iphdr);
int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;

if (new_mtu < 68 ||
new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen)
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;
}
EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);

int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
{
return __ip_tunnel_change_mtu(dev, new_mtu, true);
}
EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);

static void ip_tunnel_dev_free(struct net_device *dev)
Expand Down
2 changes: 2 additions & 0 deletions net/openvswitch/vport-vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
struct vxlan_config conf = {
.no_share = true,
.flags = VXLAN_F_COLLECT_METADATA,
/* Don't restrict the packets that can be sent by MTU */
.mtu = IP_MAX_MTU,
};

if (!options) {
Expand Down

0 comments on commit 1902750

Please sign in to comment.