@@ -354,6 +354,7 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [IPSKB_FRAG_PMTU],
[OVS_DEFINE([HAVE_CORRECT_MRU_HANDLING])])
+ OVS_GREP_IFELSE([$KSRC/include/net/ip_tunnels.h], [__ip_tunnel_change_mtu])
OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], [hashfn.*const],
[OVS_DEFINE([HAVE_INET_FRAGS_CONST])])
OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], [last_in],
@@ -1039,11 +1039,21 @@ struct net_device *rpl_geneve_dev_create_fb(struct net *net, const char *name,
return dev;
err = geneve_configure(net, dev, 0, 0, 0, 0, htons(dst_port), true);
- 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(rpl_geneve_dev_create_fb);
@@ -327,4 +327,10 @@ int rpl_ip_tunnel_get_iflink(const struct net_device *dev);
#define ip_tunnel_get_link_net rpl_ip_tunnel_get_link_net
struct net *rpl_ip_tunnel_get_link_net(const struct net_device *dev);
#endif /* HAVE_METADATA_DST */
+
+#ifndef HAVE___IP_TUNNEL_CHANGE_MTU
+#define __ip_tunnel_change_mtu rpl___ip_tunnel_change_mtu
+int rpl___ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
+#endif
+
#endif /* __NET_IP_TUNNELS_H */
@@ -613,6 +613,14 @@ struct net_device *rpl_gretap_fb_dev_create(struct net *net, const char *name,
#endif
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);
@@ -137,18 +137,31 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
return mtu;
}
-int rpl_ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+int rpl___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;
}
+int rpl_ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+{
+ return rpl___ip_tunnel_change_mtu(dev, new_mtu, true);
+}
+
static void ip_tunnel_dev_free(struct net_device *dev)
{
#ifdef HAVE_DEV_TSTATS
@@ -1905,6 +1905,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;
@@ -1924,9 +1925,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) {
@@ -1957,6 +1956,12 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
dev->needed_headroom = ETH_HLEN + VXLAN_HEADROOM;
}
+ if (conf->mtu) {
+ err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false);
+ if (err)
+ return err;
+ }
+
memcpy(&vxlan->cfg, conf, sizeof(*conf));
if (!vxlan->cfg.dst_port)
vxlan->cfg.dst_port = default_port;
@@ -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) {