From 69ec718b62db5766e43552cadfc7b659c7025ba4 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Mon, 22 Feb 2016 18:35:48 -0800 Subject: [PATCH] Use MTU value from Neutron in OVS/LB VIF wiring This patch adds the MTU attached to a Neutron network to the network model so the VIF plugging code can reference the MTU and set the correct value for the Neutron network it is attaching to. Closes-Bug: #1549408 Change-Id: Ibd4de83e1af193eb2dcd997e6528d2fccaa2979a --- nova/network/linux_net.py | 8 ++++---- nova/network/neutronv2/api.py | 5 ++++- nova/tests/unit/network/test_neutronv2.py | 4 +++- nova/tests/unit/virt/libvirt/test_vif.py | 24 +++++++++++++---------- nova/virt/libvirt/vif.py | 16 ++++++++++----- 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 088948544d..55d52998da 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -1339,7 +1339,7 @@ def _set_device_mtu(dev, mtu=None): check_exit_code=[0, 2, 254]) -def _create_veth_pair(dev1_name, dev2_name): +def _create_veth_pair(dev1_name, dev2_name, mtu=None): """Create a pair of veth devices with the specified names, deleting any previous devices with those names. """ @@ -1352,7 +1352,7 @@ def _create_veth_pair(dev1_name, dev2_name): utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True) utils.execute('ip', 'link', 'set', dev, 'promisc', 'on', run_as_root=True) - _set_device_mtu(dev) + _set_device_mtu(dev, mtu) def _ovs_vsctl(args): @@ -1365,7 +1365,7 @@ def _ovs_vsctl(args): raise exception.AgentError(method=full_args) -def create_ovs_vif_port(bridge, dev, iface_id, mac, instance_id): +def create_ovs_vif_port(bridge, dev, iface_id, mac, instance_id, mtu=None): _ovs_vsctl(['--', '--if-exists', 'del-port', dev, '--', 'add-port', bridge, dev, '--', 'set', 'Interface', dev, @@ -1373,7 +1373,7 @@ def create_ovs_vif_port(bridge, dev, iface_id, mac, instance_id): 'external-ids:iface-status=active', 'external-ids:attached-mac=%s' % mac, 'external-ids:vm-uuid=%s' % instance_id]) - _set_device_mtu(dev) + _set_device_mtu(dev, mtu) def delete_ovs_vif_port(bridge, dev, delete_dev=True): diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py index c8c49ebf6a..88d3c023e7 100644 --- a/nova/network/neutronv2/api.py +++ b/nova/network/neutronv2/api.py @@ -1580,10 +1580,12 @@ class API(base_api.NetworkAPI): def _nw_info_build_network(self, port, networks, subnets): network_name = None + network_mtu = None for net in networks: if port['network_id'] == net['id']: network_name = net['name'] tenant_id = net['tenant_id'] + network_mtu = net.get('mtu') break else: tenant_id = port['tenant_id'] @@ -1627,7 +1629,8 @@ class API(base_api.NetworkAPI): bridge=bridge, injected=CONF.flat_injected, label=network_name, - tenant_id=tenant_id + tenant_id=tenant_id, + mtu=network_mtu ) network['subnets'] = subnets port_profile = port.get('binding:profile') diff --git a/nova/tests/unit/network/test_neutronv2.py b/nova/tests/unit/network/test_neutronv2.py index 85304c3ff5..2f36e02840 100644 --- a/nova/tests/unit/network/test_neutronv2.py +++ b/nova/tests/unit/network/test_neutronv2.py @@ -2470,7 +2470,8 @@ class TestNeutronv2(TestNeutronv2Base): 'binding:vif_type': vif_type, } fake_subnets = [model.Subnet(cidr='1.0.0.0/8')] - fake_nets = [{'id': 'net-id', 'name': 'foo', 'tenant_id': 'tenant'}] + fake_nets = [{'id': 'net-id', 'name': 'foo', 'tenant_id': 'tenant', + 'mtu': 9000}] api = neutronapi.API() self.mox.ReplayAll() neutronapi.get_client('fake') @@ -2480,6 +2481,7 @@ class TestNeutronv2(TestNeutronv2Base): self.assertEqual('net-id', net['id']) self.assertEqual('foo', net['label']) self.assertEqual('tenant', net.get_meta('tenant_id')) + self.assertEqual(9000, net.get_meta('mtu')) self.assertEqual(CONF.flat_injected, net.get_meta('injected')) return net, iid diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index 003141becf..bf33eab910 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -60,7 +60,7 @@ class LibvirtVifTestCase(test.NoDBTestCase): subnets=[subnet_bridge_4, subnet_bridge_6], bridge_interface='eth0', - vlan=99) + vlan=99, mtu=9000) vif_bridge = network_model.VIF(id='vif-xxx-yyy-zzz', address='ca:fe:de:ad:be:ef', @@ -90,7 +90,7 @@ class LibvirtVifTestCase(test.NoDBTestCase): subnets=[subnet_bridge_4, subnet_bridge_6], bridge_interface=None, - vlan=99) + vlan=99, mtu=1000) network_ivs = network_model.Network(id='network-id-xxx-yyy-zzz', bridge='br0', @@ -302,7 +302,7 @@ class LibvirtVifTestCase(test.NoDBTestCase): network_model.VIF_DETAILS_VHOSTUSER_SOCKET: '/tmp/usv-xxx-yyy-zzz', network_model.VIF_DETAILS_VHOSTUSER_OVS_PLUG: True}, - ovs_interfaceid='aaa-bbb-ccc' + ovs_interfaceid='aaa-bbb-ccc', mtu=1500 ) vif_vhostuser_ovs_fp = network_model.VIF(id='vif-xxx-yyy-zzz', @@ -697,7 +697,7 @@ class LibvirtVifTestCase(test.NoDBTestCase): 'device_exists': [mock.call('qbrvif-xxx-yyy'), mock.call('qvovif-xxx-yyy')], '_create_veth_pair': [mock.call('qvbvif-xxx-yyy', - 'qvovif-xxx-yyy')], + 'qvovif-xxx-yyy', 1000)], 'execute': [mock.call('brctl', 'addbr', 'qbrvif-xxx-yyy', run_as_root=True), mock.call('brctl', 'setfd', 'qbrvif-xxx-yyy', 0, @@ -711,7 +711,8 @@ class LibvirtVifTestCase(test.NoDBTestCase): 'create_ovs_vif_port': [mock.call( 'br0', 'qvovif-xxx-yyy', 'aaa-bbb-ccc', 'ca:fe:de:ad:be:ef', - 'f0000000-0000-0000-0000-000000000001')] + 'f0000000-0000-0000-0000-000000000001', + 1000)] } # The disable_ipv6 call needs to be added in the middle, if required if ipv6_exists: @@ -831,7 +832,7 @@ class LibvirtVifTestCase(test.NoDBTestCase): 'device_exists': [mock.call('qbrvif-xxx-yyy'), mock.call('qvovif-xxx-yyy')], '_create_veth_pair': [mock.call('qvbvif-xxx-yyy', - 'qvovif-xxx-yyy')], + 'qvovif-xxx-yyy', None)], 'execute': [mock.call('brctl', 'addbr', 'qbrvif-xxx-yyy', run_as_root=True), mock.call('brctl', 'setfd', 'qbrvif-xxx-yyy', 0, @@ -1315,7 +1316,8 @@ class LibvirtVifTestCase(test.NoDBTestCase): 'create_ovs_vif_port': [mock.call( 'br0', 'usv-xxx-yyy-zzz', 'aaa-bbb-ccc', 'ca:fe:de:ad:be:ef', - 'f0000000-0000-0000-0000-000000000001')], + 'f0000000-0000-0000-0000-000000000001', + 9000)], 'ovs_set_vhostuser_port_type': [mock.call('usv-xxx-yyy-zzz')] } with test.nested( @@ -1346,7 +1348,8 @@ class LibvirtVifTestCase(test.NoDBTestCase): 'create_ovs_vif_port': [mock.call( 'br0', 'tap-xxx-yyy-zzz', 'aaa-bbb-ccc', 'ca:fe:de:ad:be:ef', - 'f0000000-0000-0000-0000-000000000001')] + 'f0000000-0000-0000-0000-000000000001', + 9000)] } with test.nested( mock.patch.object(linux_net, 'create_fp_dev'), @@ -1381,7 +1384,7 @@ class LibvirtVifTestCase(test.NoDBTestCase): mock.call('qbrvif-xxx-yyy'), mock.call('qvovif-xxx-yyy')], '_create_veth_pair': [mock.call('qvbvif-xxx-yyy', - 'qvovif-xxx-yyy')], + 'qvovif-xxx-yyy', 9000)], 'execute': [mock.call('brctl', 'addbr', 'qbrvif-xxx-yyy', run_as_root=True), mock.call('brctl', 'setfd', 'qbrvif-xxx-yyy', 0, @@ -1401,7 +1404,8 @@ class LibvirtVifTestCase(test.NoDBTestCase): 'create_ovs_vif_port': [mock.call( 'br0', 'qvovif-xxx-yyy', 'aaa-bbb-ccc', 'ca:fe:de:ad:be:ef', - 'f0000000-0000-0000-0000-000000000001')] + 'f0000000-0000-0000-0000-000000000001', + 9000)] } with test.nested( mock.patch.object(linux_net, 'create_fp_dev'), diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index afc46a0e00..ec05a53e74 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -501,13 +501,15 @@ class LibvirtGenericVIFDriver(object): check_exit_code=[0, 1]) if not linux_net.device_exists(v2_name): - linux_net._create_veth_pair(v1_name, v2_name) + mtu = vif['network'].get_meta('mtu') + linux_net._create_veth_pair(v1_name, v2_name, mtu) utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True) utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True) if port == 'ovs': linux_net.create_ovs_vif_port(self.get_bridge_name(vif), v2_name, iface_id, - vif['address'], instance.uuid) + vif['address'], instance.uuid, + mtu) elif port == 'ivs': linux_net.create_ivs_vif_port(v2_name, iface_id, vif['address'], instance.uuid) @@ -634,7 +636,9 @@ class LibvirtGenericVIFDriver(object): dev = self.get_vif_devname(vif) mac = vif['details'].get(network_model.VIF_DETAILS_TAP_MAC_ADDRESS) linux_net.create_tap_dev(dev, mac) - linux_net._set_device_mtu(dev) + network = vif.get('network') + mtu = network.get_meta('mtu') if network else None + linux_net._set_device_mtu(dev, mtu) def plug_vhostuser_fp(self, instance, vif): """Create a fp netdevice interface with a vhostuser socket""" @@ -659,10 +663,11 @@ class LibvirtGenericVIFDriver(object): dev, run_as_root=True) else: iface_id = self.get_ovs_interfaceid(vif) + mtu = vif['network'].get_meta('mtu') linux_net.create_ovs_vif_port(self.get_bridge_name(vif), dev, iface_id, vif['address'], - instance.uuid) + instance.uuid, mtu) except processutils.ProcessExecutionError: LOG.exception(_LE("Failed while plugging vif"), instance=instance) @@ -671,9 +676,10 @@ class LibvirtGenericVIFDriver(object): iface_id = self.get_ovs_interfaceid(vif) port_name = os.path.basename( vif['details'][network_model.VIF_DETAILS_VHOSTUSER_SOCKET]) + mtu = vif['network'].get_meta('mtu') linux_net.create_ovs_vif_port(self.get_bridge_name(vif), port_name, iface_id, vif['address'], - instance.uuid) + instance.uuid, mtu) linux_net.ovs_set_vhostuser_port_type(port_name) def plug_vhostuser(self, instance, vif):