introduces MTU support for vhost-user

- This change introduces the ability
  to set the MTU for vhost-user interface
  if supported by ovs.
- This change leverages the mtu_request
  option added to the ovs interface in ovs 2.6.
- MTU support enable the use of jumbo frames
  with vhost-user interfaces.

Change-Id: Ide3435b74809605692fa6153c3be3294db80182f
This commit is contained in:
Sean Mooney 2016-12-13 10:07:07 +00:00 committed by sean mooney
parent 01da454fc8
commit 9a14c18c21
3 changed files with 91 additions and 14 deletions

View File

@ -0,0 +1,10 @@
---
features:
- In the ocata cycle support was added for setting
the MTU of vhost-user port with ovs.
- vhost-user MTU support enable jumbo frames to
be used with vhost-user interfaces.
other:
- vhost-user MTU support requires ovs 2.6 or newer.
On older versions of ovs, the MTU request will
not be made and jumbo frames are not supported.

View File

@ -75,12 +75,12 @@ def create_ovs_vif_port(bridge, dev, iface_id, mac, instance_id,
_ovs_vsctl(_create_ovs_vif_cmd(bridge, dev, iface_id,
mac, instance_id, interface_type,
vhost_server_path), timeout=timeout)
_update_device_mtu(dev, mtu, interface_type)
_update_device_mtu(dev, mtu, interface_type, timeout=timeout)
@privsep.vif_plug.entrypoint
def update_ovs_vif_port(dev, mtu=None, interface_type=None):
_update_device_mtu(dev, mtu, interface_type)
def update_ovs_vif_port(dev, mtu=None, interface_type=None, timeout=None):
_update_device_mtu(dev, mtu, interface_type, timeout=timeout)
@privsep.vif_plug.entrypoint
@ -168,13 +168,15 @@ def add_bridge_port(bridge, dev):
processutils.execute('brctl', 'addif', bridge, dev)
def _update_device_mtu(dev, mtu, interface_type=None):
# Note at present there is no support for setting the
# mtu for vhost-user type ports.
if mtu and interface_type not in [
constants.OVS_VHOSTUSER_INTERFACE_TYPE,
constants.OVS_VHOSTUSER_CLIENT_INTERFACE_TYPE]:
def _update_device_mtu(dev, mtu, interface_type=None, timeout=120):
if not mtu:
return
if interface_type not in [
constants.OVS_VHOSTUSER_INTERFACE_TYPE,
constants.OVS_VHOSTUSER_CLIENT_INTERFACE_TYPE]:
_set_device_mtu(dev, mtu)
elif _ovs_supports_mtu_requests(timeout=timeout):
_set_mtu_request(dev, mtu, timeout=timeout)
else:
LOG.debug("MTU not set on %(interface_name)s interface "
"of type %(interface_type)s.",
@ -182,7 +184,25 @@ def _update_device_mtu(dev, mtu, interface_type=None):
'interface_type': interface_type})
@privsep.vif_plug.entrypoint
def _set_device_mtu(dev, mtu):
"""Set the device MTU."""
processutils.execute('ip', 'link', 'set', dev, 'mtu', mtu,
check_exit_code=[0, 2, 254])
@privsep.vif_plug.entrypoint
def _set_mtu_request(dev, mtu, timeout=None):
args = ['--', 'set', 'interface', dev,
'mtu_request=%s' % mtu]
_ovs_vsctl(args, timeout=timeout)
@privsep.vif_plug.entrypoint
def _ovs_supports_mtu_requests(timeout=None):
args = ['--columns=mtu_request', 'list', 'interface']
_, error = _ovs_vsctl(args, timeout=timeout)
if (error == 'ovs-vsctl: Interface does not contain' +
' a column whose name matches "mtu_request"'):
return False
return True

View File

@ -157,11 +157,14 @@ class LinuxNetTest(testtools.TestCase):
actual = linux_net._create_ovs_bridge_cmd(bridge, dp_type)
self.assertEqual(expected, actual)
@mock.patch.object(linux_net, '_ovs_supports_mtu_requests')
@mock.patch.object(linux_net, '_ovs_vsctl')
@mock.patch.object(linux_net, '_create_ovs_vif_cmd')
@mock.patch.object(linux_net, '_set_device_mtu')
def test_ovs_vif_port_with_type_vhostuser(self, mock_set_device_mtu,
mock_create_cmd, mock_vsctl):
mock_create_cmd, mock_vsctl,
mock_ovs_supports_mtu_requests):
mock_ovs_supports_mtu_requests.return_value = True
linux_net.create_ovs_vif_port(
'fake-bridge',
'fake-dev', 'fake-iface-id', 'fake-mac',
@ -174,11 +177,14 @@ class LinuxNetTest(testtools.TestCase):
self.assertFalse(mock_set_device_mtu.called)
self.assertTrue(mock_vsctl.called)
@mock.patch.object(linux_net, '_ovs_supports_mtu_requests')
@mock.patch.object(linux_net, '_ovs_vsctl')
@mock.patch.object(linux_net, '_create_ovs_vif_cmd')
@mock.patch.object(linux_net, '_set_device_mtu')
def test_ovs_vif_port_with_type_vhostuserclient(self,
mock_set_device_mtu, mock_create_cmd, mock_vsctl):
mock_set_device_mtu, mock_create_cmd,
mock_vsctl, mock_ovs_supports_mtu_requests):
mock_ovs_supports_mtu_requests.return_value = True
linux_net.create_ovs_vif_port(
'fake-bridge',
'fake-dev', 'fake-iface-id', 'fake-mac',
@ -193,11 +199,14 @@ class LinuxNetTest(testtools.TestCase):
self.assertFalse(mock_set_device_mtu.called)
self.assertTrue(mock_vsctl.called)
@mock.patch.object(linux_net, '_ovs_supports_mtu_requests')
@mock.patch.object(linux_net, '_ovs_vsctl')
@mock.patch.object(linux_net, '_create_ovs_vif_cmd')
@mock.patch.object(linux_net, '_set_device_mtu')
def test_ovs_vif_port_with_no_mtu(self, mock_set_device_mtu,
mock_create_cmd, mock_vsctl):
mock_create_cmd, mock_vsctl,
mock_ovs_supports_mtu_requests):
mock_ovs_supports_mtu_requests.return_value = True
linux_net.create_ovs_vif_port(
'fake-bridge',
'fake-dev', 'fake-iface-id', 'fake-mac',
@ -208,12 +217,18 @@ class LinuxNetTest(testtools.TestCase):
self.assertFalse(mock_set_device_mtu.called)
self.assertTrue(mock_vsctl.called)
@mock.patch.object(linux_net, '_ovs_supports_mtu_requests')
@mock.patch.object(linux_net, '_set_mtu_request')
@mock.patch.object(linux_net, '_ovs_vsctl')
@mock.patch.object(linux_net, '_create_ovs_vif_cmd',
return_value='ovs_command')
@mock.patch.object(linux_net, '_set_device_mtu')
def test_ovs_vif_port_with_timeout(self, mock_set_device_mtu,
mock_create_cmd, mock_vsctl):
mock_create_cmd, mock_vsctl,
mock_set_mtu_request,
mock_ovs_supports_mtu_requests):
mock_ovs_supports_mtu_requests.return_value = True
linux_net.create_ovs_vif_port(
'fake-bridge',
'fake-dev', 'fake-iface-id', 'fake-mac',
@ -222,12 +237,17 @@ class LinuxNetTest(testtools.TestCase):
self.assertFalse(mock_set_device_mtu.called)
mock_vsctl.assert_called_with('ovs_command', timeout=42)
@mock.patch.object(linux_net, '_ovs_supports_mtu_requests')
@mock.patch.object(linux_net, '_set_mtu_request')
@mock.patch.object(linux_net, '_ovs_vsctl')
@mock.patch.object(linux_net, '_create_ovs_vif_cmd',
return_value='ovs_command')
@mock.patch.object(linux_net, '_set_device_mtu')
def test_ovs_vif_port_with_no_timeout(self, mock_set_device_mtu,
mock_create_cmd, mock_vsctl):
mock_create_cmd, mock_vsctl,
mock_set_mtu_request,
mock_ovs_supports_mtu_requests):
mock_ovs_supports_mtu_requests.return_value = True
linux_net.create_ovs_vif_port(
'fake-bridge',
'fake-dev', 'fake-iface-id', 'fake-mac',
@ -246,3 +266,30 @@ class LinuxNetTest(testtools.TestCase):
[mock.call('ovs-vsctl', *args),
mock.call('ovs-vsctl', '--timeout=%s' % timeout, *args)],
mock_execute.mock_calls)
@mock.patch.object(linux_net, '_ovs_vsctl')
def test_set_mtu_request(self, mock_vsctl):
dev = 'fake-dev'
mtu = 'fake-mtu'
timeout = 120
linux_net._set_mtu_request(dev, mtu, timeout=timeout)
args = ['--', 'set', 'interface', dev,
'mtu_request=%s' % mtu]
mock_vsctl.assert_called_with(args, timeout=timeout)
@mock.patch.object(linux_net, '_ovs_vsctl')
def test_ovs_supports_mtu_requests(self, mock_vsctl):
args = ['--columns=mtu_request', 'list', 'interface']
timeout = 120
msg = 'ovs-vsctl: Interface does not contain' + \
' a column whose name matches "mtu_request"'
mock_vsctl.return_value = (None, msg)
result = linux_net._ovs_supports_mtu_requests(timeout=timeout)
mock_vsctl.assert_called_with(args, timeout=timeout)
self.assertFalse(result)
mock_vsctl.return_value = (None, None)
result = linux_net._ovs_supports_mtu_requests(timeout=timeout)
mock_vsctl.assert_called_with(args, timeout=timeout)
self.assertTrue(result)