diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c index dd0015d01..f443a1b03 100644 --- a/datapath/linux/compat/vxlan.c +++ b/datapath/linux/compat/vxlan.c @@ -1608,27 +1608,41 @@ static void vxlan_set_multicast_list(struct net_device *dev) { } +static int __vxlan_change_mtu(struct net_device *dev, + struct net_device *lowerdev, + struct vxlan_rdst *dst, int new_mtu, bool strict) +{ + int max_mtu = IP_MAX_MTU; + + if (lowerdev) + max_mtu = lowerdev->mtu; + + if (dst->remote_ip.sa.sa_family == AF_INET6) + max_mtu -= VXLAN6_HEADROOM; + else + max_mtu -= VXLAN_HEADROOM; + + 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; - int max_mtu; - - lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex); - if (lowerdev == NULL) - return eth_change_mtu(dev, new_mtu); - - if (dst->remote_ip.sa.sa_family == AF_INET6) - max_mtu = lowerdev->mtu - VXLAN6_HEADROOM; - else - max_mtu = lowerdev->mtu - VXLAN_HEADROOM; - - if (new_mtu < 68 || new_mtu > max_mtu) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; + struct net_device *lowerdev = __dev_get_by_index(vxlan->net, + dst->remote_ifindex); + return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true); } static netdev_tx_t vxlan_dev_xmit(struct sk_buff *skb, struct net_device *dev)