diff options
-rw-r--r-- | drivers/net/geneve.c | 31 | ||||
-rw-r--r-- | drivers/net/vxlan.c | 47 | ||||
-rw-r--r-- | include/net/ip_tunnels.h | 1 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 8 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 20 | ||||
-rw-r--r-- | net/openvswitch/vport-vxlan.c | 2 |
6 files changed, 87 insertions, 22 deletions
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 0b14ac3b8d11..028e3873c310 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c | |||
@@ -1039,6 +1039,17 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1039 | return geneve_xmit_skb(skb, dev, info); | 1039 | return geneve_xmit_skb(skb, dev, info); |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | static int geneve_change_mtu(struct net_device *dev, int new_mtu) | ||
1043 | { | ||
1044 | /* GENEVE overhead is not fixed, so we can't enforce a more | ||
1045 | * precise max MTU. | ||
1046 | */ | ||
1047 | if (new_mtu < 68 || new_mtu > IP_MAX_MTU) | ||
1048 | return -EINVAL; | ||
1049 | dev->mtu = new_mtu; | ||
1050 | return 0; | ||
1051 | } | ||
1052 | |||
1042 | static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) | 1053 | static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) |
1043 | { | 1054 | { |
1044 | struct ip_tunnel_info *info = skb_tunnel_info(skb); | 1055 | struct ip_tunnel_info *info = skb_tunnel_info(skb); |
@@ -1083,7 +1094,7 @@ static const struct net_device_ops geneve_netdev_ops = { | |||
1083 | .ndo_stop = geneve_stop, | 1094 | .ndo_stop = geneve_stop, |
1084 | .ndo_start_xmit = geneve_xmit, | 1095 | .ndo_start_xmit = geneve_xmit, |
1085 | .ndo_get_stats64 = ip_tunnel_get_stats64, | 1096 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
1086 | .ndo_change_mtu = eth_change_mtu, | 1097 | .ndo_change_mtu = geneve_change_mtu, |
1087 | .ndo_validate_addr = eth_validate_addr, | 1098 | .ndo_validate_addr = eth_validate_addr, |
1088 | .ndo_set_mac_address = eth_mac_addr, | 1099 | .ndo_set_mac_address = eth_mac_addr, |
1089 | .ndo_fill_metadata_dst = geneve_fill_metadata_dst, | 1100 | .ndo_fill_metadata_dst = geneve_fill_metadata_dst, |
@@ -1442,11 +1453,21 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, | |||
1442 | 1453 | ||
1443 | err = geneve_configure(net, dev, &geneve_remote_unspec, | 1454 | err = geneve_configure(net, dev, &geneve_remote_unspec, |
1444 | 0, 0, 0, htons(dst_port), true, 0); | 1455 | 0, 0, 0, htons(dst_port), true, 0); |
1445 | if (err) { | 1456 | if (err) |
1446 | free_netdev(dev); | 1457 | goto err; |
1447 | return ERR_PTR(err); | 1458 | |
1448 | } | 1459 | /* openvswitch users expect packet sizes to be unrestricted, |
1460 | * so set the largest MTU we can. | ||
1461 | */ | ||
1462 | err = geneve_change_mtu(dev, IP_MAX_MTU); | ||
1463 | if (err) | ||
1464 | goto err; | ||
1465 | |||
1449 | return dev; | 1466 | return dev; |
1467 | |||
1468 | err: | ||
1469 | free_netdev(dev); | ||
1470 | return ERR_PTR(err); | ||
1450 | } | 1471 | } |
1451 | EXPORT_SYMBOL_GPL(geneve_dev_create_fb); | 1472 | EXPORT_SYMBOL_GPL(geneve_dev_create_fb); |
1452 | 1473 | ||
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 65439188c582..a31cd954b308 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -2367,29 +2367,43 @@ static void vxlan_set_multicast_list(struct net_device *dev) | |||
2367 | { | 2367 | { |
2368 | } | 2368 | } |
2369 | 2369 | ||
2370 | static int vxlan_change_mtu(struct net_device *dev, int new_mtu) | 2370 | static int __vxlan_change_mtu(struct net_device *dev, |
2371 | struct net_device *lowerdev, | ||
2372 | struct vxlan_rdst *dst, int new_mtu, bool strict) | ||
2371 | { | 2373 | { |
2372 | struct vxlan_dev *vxlan = netdev_priv(dev); | 2374 | int max_mtu = IP_MAX_MTU; |
2373 | struct vxlan_rdst *dst = &vxlan->default_dst; | ||
2374 | struct net_device *lowerdev; | ||
2375 | int max_mtu; | ||
2376 | 2375 | ||
2377 | lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex); | 2376 | if (lowerdev) |
2378 | if (lowerdev == NULL) | 2377 | max_mtu = lowerdev->mtu; |
2379 | return eth_change_mtu(dev, new_mtu); | ||
2380 | 2378 | ||
2381 | if (dst->remote_ip.sa.sa_family == AF_INET6) | 2379 | if (dst->remote_ip.sa.sa_family == AF_INET6) |
2382 | max_mtu = lowerdev->mtu - VXLAN6_HEADROOM; | 2380 | max_mtu -= VXLAN6_HEADROOM; |
2383 | else | 2381 | else |
2384 | max_mtu = lowerdev->mtu - VXLAN_HEADROOM; | 2382 | max_mtu -= VXLAN_HEADROOM; |
2385 | 2383 | ||
2386 | if (new_mtu < 68 || new_mtu > max_mtu) | 2384 | if (new_mtu < 68) |
2387 | return -EINVAL; | 2385 | return -EINVAL; |
2388 | 2386 | ||
2387 | if (new_mtu > max_mtu) { | ||
2388 | if (strict) | ||
2389 | return -EINVAL; | ||
2390 | |||
2391 | new_mtu = max_mtu; | ||
2392 | } | ||
2393 | |||
2389 | dev->mtu = new_mtu; | 2394 | dev->mtu = new_mtu; |
2390 | return 0; | 2395 | return 0; |
2391 | } | 2396 | } |
2392 | 2397 | ||
2398 | static int vxlan_change_mtu(struct net_device *dev, int new_mtu) | ||
2399 | { | ||
2400 | struct vxlan_dev *vxlan = netdev_priv(dev); | ||
2401 | struct vxlan_rdst *dst = &vxlan->default_dst; | ||
2402 | struct net_device *lowerdev = __dev_get_by_index(vxlan->net, | ||
2403 | dst->remote_ifindex); | ||
2404 | return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true); | ||
2405 | } | ||
2406 | |||
2393 | static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb, | 2407 | static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb, |
2394 | struct ip_tunnel_info *info, | 2408 | struct ip_tunnel_info *info, |
2395 | __be16 sport, __be16 dport) | 2409 | __be16 sport, __be16 dport) |
@@ -2765,6 +2779,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, | |||
2765 | int err; | 2779 | int err; |
2766 | bool use_ipv6 = false; | 2780 | bool use_ipv6 = false; |
2767 | __be16 default_port = vxlan->cfg.dst_port; | 2781 | __be16 default_port = vxlan->cfg.dst_port; |
2782 | struct net_device *lowerdev = NULL; | ||
2768 | 2783 | ||
2769 | vxlan->net = src_net; | 2784 | vxlan->net = src_net; |
2770 | 2785 | ||
@@ -2785,9 +2800,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, | |||
2785 | } | 2800 | } |
2786 | 2801 | ||
2787 | if (conf->remote_ifindex) { | 2802 | if (conf->remote_ifindex) { |
2788 | struct net_device *lowerdev | 2803 | lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); |
2789 | = __dev_get_by_index(src_net, conf->remote_ifindex); | ||
2790 | |||
2791 | dst->remote_ifindex = conf->remote_ifindex; | 2804 | dst->remote_ifindex = conf->remote_ifindex; |
2792 | 2805 | ||
2793 | if (!lowerdev) { | 2806 | if (!lowerdev) { |
@@ -2811,6 +2824,12 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, | |||
2811 | needed_headroom = lowerdev->hard_header_len; | 2824 | needed_headroom = lowerdev->hard_header_len; |
2812 | } | 2825 | } |
2813 | 2826 | ||
2827 | if (conf->mtu) { | ||
2828 | err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false); | ||
2829 | if (err) | ||
2830 | return err; | ||
2831 | } | ||
2832 | |||
2814 | if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) | 2833 | if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) |
2815 | needed_headroom += VXLAN6_HEADROOM; | 2834 | needed_headroom += VXLAN6_HEADROOM; |
2816 | else | 2835 | else |
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 6db96ea0144f..dda9abf6b89c 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h | |||
@@ -230,6 +230,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
230 | int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); | 230 | int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); |
231 | int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t, | 231 | int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t, |
232 | u8 *protocol, struct flowi4 *fl4); | 232 | u8 *protocol, struct flowi4 *fl4); |
233 | int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); | ||
233 | int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu); | 234 | int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu); |
234 | 235 | ||
235 | struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, | 236 | struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 7c51c4e1661f..56fdf4e0dce4 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -1240,6 +1240,14 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, | |||
1240 | err = ipgre_newlink(net, dev, tb, NULL); | 1240 | err = ipgre_newlink(net, dev, tb, NULL); |
1241 | if (err < 0) | 1241 | if (err < 0) |
1242 | goto out; | 1242 | goto out; |
1243 | |||
1244 | /* openvswitch users expect packet sizes to be unrestricted, | ||
1245 | * so set the largest MTU we can. | ||
1246 | */ | ||
1247 | err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); | ||
1248 | if (err) | ||
1249 | goto out; | ||
1250 | |||
1243 | return dev; | 1251 | return dev; |
1244 | out: | 1252 | out: |
1245 | free_netdev(dev); | 1253 | free_netdev(dev); |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index c7bd72e9b544..89e8861e05fc 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -943,17 +943,31 @@ done: | |||
943 | } | 943 | } |
944 | EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); | 944 | EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); |
945 | 945 | ||
946 | int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 946 | int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict) |
947 | { | 947 | { |
948 | struct ip_tunnel *tunnel = netdev_priv(dev); | 948 | struct ip_tunnel *tunnel = netdev_priv(dev); |
949 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); | 949 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); |
950 | int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen; | ||
950 | 951 | ||
951 | if (new_mtu < 68 || | 952 | if (new_mtu < 68) |
952 | new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen) | ||
953 | return -EINVAL; | 953 | return -EINVAL; |
954 | |||
955 | if (new_mtu > max_mtu) { | ||
956 | if (strict) | ||
957 | return -EINVAL; | ||
958 | |||
959 | new_mtu = max_mtu; | ||
960 | } | ||
961 | |||
954 | dev->mtu = new_mtu; | 962 | dev->mtu = new_mtu; |
955 | return 0; | 963 | return 0; |
956 | } | 964 | } |
965 | EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu); | ||
966 | |||
967 | int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) | ||
968 | { | ||
969 | return __ip_tunnel_change_mtu(dev, new_mtu, true); | ||
970 | } | ||
957 | EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); | 971 | EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); |
958 | 972 | ||
959 | static void ip_tunnel_dev_free(struct net_device *dev) | 973 | static void ip_tunnel_dev_free(struct net_device *dev) |
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 1605691d9414..de9cb19efb6a 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c | |||
@@ -91,6 +91,8 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms) | |||
91 | struct vxlan_config conf = { | 91 | struct vxlan_config conf = { |
92 | .no_share = true, | 92 | .no_share = true, |
93 | .flags = VXLAN_F_COLLECT_METADATA, | 93 | .flags = VXLAN_F_COLLECT_METADATA, |
94 | /* Don't restrict the packets that can be sent by MTU */ | ||
95 | .mtu = IP_MAX_MTU, | ||
94 | }; | 96 | }; |
95 | 97 | ||
96 | if (!options) { | 98 | if (!options) { |