Merge "[Linuxbridge] Handle properly too big VXLAN MTU values"
This commit is contained in:
commit
0e27778b06
|
@ -13,6 +13,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import errno
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
@ -25,6 +26,7 @@ from oslo_config import cfg
|
|||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
from pyroute2.netlink.rtnl import ifinfmsg
|
||||
from pyroute2 import NetlinkError
|
||||
from pyroute2 import netns
|
||||
import six
|
||||
|
||||
|
@ -65,6 +67,11 @@ class AddressNotReady(exceptions.NeutronException):
|
|||
"become ready: %(reason)s")
|
||||
|
||||
|
||||
class InvalidArgument(exceptions.NeutronException):
|
||||
message = _("Invalid value %(value)s for parameter %(parameter)s "
|
||||
"provided.")
|
||||
|
||||
|
||||
class SubProcessBase(object):
|
||||
def __init__(self, namespace=None,
|
||||
log_fail_as_error=True):
|
||||
|
@ -508,8 +515,13 @@ class IpLinkCommand(IpDeviceCommandBase):
|
|||
self.name, self._parent.namespace, ifinfmsg.IFF_ALLMULTI)
|
||||
|
||||
def set_mtu(self, mtu_size):
|
||||
privileged.set_link_attribute(
|
||||
self.name, self._parent.namespace, mtu=mtu_size)
|
||||
try:
|
||||
privileged.set_link_attribute(
|
||||
self.name, self._parent.namespace, mtu=mtu_size)
|
||||
except NetlinkError as e:
|
||||
if e.code == errno.EINVAL:
|
||||
raise InvalidArgument(parameter="MTU", value=mtu_size)
|
||||
raise
|
||||
|
||||
def set_up(self):
|
||||
privileged.set_link_attribute(
|
||||
|
|
|
@ -347,25 +347,8 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase):
|
|||
args['proxy'] = cfg.CONF.VXLAN.arp_responder
|
||||
|
||||
try:
|
||||
if mtu:
|
||||
phys_dev_mtu = ip_lib.get_device_mtu(self.local_int)
|
||||
max_mtu = phys_dev_mtu - constants.VXLAN_ENCAP_OVERHEAD
|
||||
if mtu > max_mtu:
|
||||
LOG.error("Provided MTU value %(mtu)s for VNI "
|
||||
"%(segmentation_id)s is too high. "
|
||||
"According to physical device %(dev)s "
|
||||
"MTU=%(phys_mtu)s maximum available "
|
||||
"MTU is %(max_mtu)s",
|
||||
{'mtu': mtu,
|
||||
'segmentation_id': segmentation_id,
|
||||
'dev': self.local_int,
|
||||
'phys_mtu': phys_dev_mtu,
|
||||
'max_mtu': max_mtu})
|
||||
return None
|
||||
int_vxlan = self.ip.add_vxlan(interface, segmentation_id,
|
||||
**args)
|
||||
if mtu:
|
||||
int_vxlan.link.set_mtu(mtu)
|
||||
except RuntimeError:
|
||||
with excutils.save_and_reraise_exception() as ctxt:
|
||||
# perform this check after an attempt rather than before
|
||||
|
@ -376,6 +359,20 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase):
|
|||
"VNI %s because it is in use by another "
|
||||
"interface.", segmentation_id)
|
||||
return None
|
||||
if mtu:
|
||||
try:
|
||||
int_vxlan.link.set_mtu(mtu)
|
||||
except ip_lib.InvalidArgument:
|
||||
phys_dev_mtu = ip_lib.get_device_mtu(self.local_int)
|
||||
LOG.error("Provided MTU value %(mtu)s for VNI "
|
||||
"%(segmentation_id)s is too high according "
|
||||
"to physical device %(dev)s MTU=%(phys_mtu)s.",
|
||||
{'mtu': mtu,
|
||||
'segmentation_id': segmentation_id,
|
||||
'dev': self.local_int,
|
||||
'phys_mtu': phys_dev_mtu})
|
||||
int_vxlan.link.delete()
|
||||
return None
|
||||
int_vxlan.disable_ipv6()
|
||||
int_vxlan.link.set_up()
|
||||
LOG.debug("Done creating vxlan interface %s", interface)
|
||||
|
|
|
@ -480,6 +480,10 @@ class IpLibTestCase(IpLibTestFramework):
|
|||
|
||||
self.assertEqual(1450, device.link.mtu)
|
||||
|
||||
# Check if proper exception will be raised when wrong MTU value is
|
||||
# provided
|
||||
self.assertRaises(ip_lib.InvalidArgument, device.link.set_mtu, 1)
|
||||
|
||||
def test_set_link_allmulticast_on(self):
|
||||
attr = self.generate_device_details()
|
||||
device = self.manage_device(attr)
|
||||
|
|
|
@ -442,22 +442,33 @@ class TestLinuxBridgeManager(base.BaseTestCase):
|
|||
def test_ensure_vxlan_mtu_too_big(self):
|
||||
seg_id = "12345678"
|
||||
physical_mtu = 1500
|
||||
# Any mtu value which will be higher than physical_mtu - 50 should
|
||||
# be too big
|
||||
# Any mtu value which will be higher than
|
||||
# physical_mtu - VXLAN_ENCAP_OVERHEAD should raise NetlinkError
|
||||
mtu = 1490
|
||||
self.lbm.local_int = 'eth0'
|
||||
self.lbm.vxlan_mode = lconst.VXLAN_MCAST
|
||||
with mock.patch.object(ip_lib, 'device_exists', return_value=False):
|
||||
vxlan_dev = FakeIpDevice()
|
||||
vxlan_dev = mock.Mock()
|
||||
with mock.patch.object(vxlan_dev, 'disable_ipv6') as dv6_fn,\
|
||||
mock.patch.object(self.lbm.ip, 'add_vxlan',
|
||||
return_value=vxlan_dev) as add_vxlan_fn,\
|
||||
mock.patch.object(
|
||||
vxlan_dev.link, 'set_mtu',
|
||||
side_effect=ip_lib.InvalidArgument(
|
||||
parameter="MTU", value=mtu)),\
|
||||
mock.patch.object(ip_lib, 'get_device_mtu',
|
||||
return_value=physical_mtu):
|
||||
return_value=physical_mtu),\
|
||||
mock.patch.object(vxlan_dev.link, 'delete') as delete_dev:
|
||||
|
||||
self.assertFalse(
|
||||
self.lbm.ensure_vxlan(seg_id, mtu=mtu))
|
||||
add_vxlan_fn.assert_not_called()
|
||||
add_vxlan_fn.assert_called_with("vxlan-" + seg_id, seg_id,
|
||||
group="224.0.0.1",
|
||||
srcport=(0, 0),
|
||||
dstport=None,
|
||||
ttl=None,
|
||||
dev=self.lbm.local_int)
|
||||
delete_dev.assert_called_once_with()
|
||||
dv6_fn.assert_not_called()
|
||||
|
||||
def test__update_interface_ip_details(self):
|
||||
|
|
Loading…
Reference in New Issue