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) { |
