Merge "Make agent interface plugging utilize network MTU"

This commit is contained in:
Jenkins 2016-03-02 05:57:00 +00:00 committed by Gerrit Code Review
commit 855aaee40d
12 changed files with 101 additions and 37 deletions

View File

@ -117,4 +117,5 @@ class DvrEdgeHaRouter(DvrEdgeRouter, HaRouter):
self.driver.plug(port['network_id'], port['id'],
interface_name, port['mac_address'],
namespace=self.snat_namespace.name,
prefix=dvr_snat_ns.SNAT_INT_DEV_PREFIX)
prefix=dvr_snat_ns.SNAT_INT_DEV_PREFIX,
mtu=port.get('mtu'))

View File

@ -104,7 +104,8 @@ class DvrEdgeRouter(dvr_local_router.DvrLocalRouter):
sn_port['fixed_ips'],
sn_port['mac_address'],
interface_name,
dvr_snat_ns.SNAT_INT_DEV_PREFIX)
dvr_snat_ns.SNAT_INT_DEV_PREFIX,
mtu=sn_port.get('mtu'))
def _dvr_internal_network_removed(self, port):
super(DvrEdgeRouter, self)._dvr_internal_network_removed(port)
@ -132,7 +133,8 @@ class DvrEdgeRouter(dvr_local_router.DvrLocalRouter):
self.snat_namespace.name, port['network_id'],
port['id'], port['fixed_ips'],
port['mac_address'], interface_name,
dvr_snat_ns.SNAT_INT_DEV_PREFIX)
dvr_snat_ns.SNAT_INT_DEV_PREFIX,
mtu=port.get('mtu'))
def _create_dvr_gateway(self, ex_gw_port, gw_interface_name):
"""Create SNAT namespace."""

View File

@ -106,7 +106,8 @@ class FipNamespace(namespaces.Namespace):
ex_gw_port['mac_address'],
bridge=self.agent_conf.external_network_bridge,
namespace=ns_name,
prefix=FIP_EXT_DEV_PREFIX)
prefix=FIP_EXT_DEV_PREFIX,
mtu=ex_gw_port.get('mtu'))
ip_cidrs = common_utils.fixed_ip_cidrs(ex_gw_port['fixed_ips'])
self.driver.init_l3(interface_name, ip_cidrs, namespace=ns_name,
@ -257,9 +258,11 @@ class FipNamespace(namespaces.Namespace):
self._internal_ns_interface_added(str(fip_2_rtr),
fip_2_rtr_name,
fip_ns_name)
if self.agent_conf.network_device_mtu:
int_dev[0].link.set_mtu(self.agent_conf.network_device_mtu)
int_dev[1].link.set_mtu(self.agent_conf.network_device_mtu)
mtu = (self.agent_conf.network_device_mtu or
ri.get_ex_gw_port().get('mtu'))
if mtu:
int_dev[0].link.set_mtu(mtu)
int_dev[1].link.set_mtu(mtu)
int_dev[0].link.set_up()
int_dev[1].link.set_up()

View File

@ -144,7 +144,8 @@ class HaRouter(router.RouterInfo):
interface_name,
self.ha_port['mac_address'],
namespace=self.ha_namespace,
prefix=HA_DEV_PREFIX)
prefix=HA_DEV_PREFIX,
mtu=self.ha_port.get('mtu'))
ip_cidrs = common_utils.fixed_ip_cidrs(self.ha_port['fixed_ips'])
self.driver.init_l3(interface_name, ip_cidrs,
namespace=self.ha_namespace,
@ -268,13 +269,13 @@ class HaRouter(router.RouterInfo):
def _plug_ha_router_port(self, port, name_getter, prefix):
port_id = port['id']
interface_name = name_getter(port_id)
self.driver.plug(port['network_id'],
port_id,
interface_name,
port['mac_address'],
namespace=self.ha_namespace,
prefix=prefix)
prefix=prefix,
mtu=port.get('mtu'))
self._disable_ipv6_addressing_on_interface(interface_name)
self._add_vips(port, interface_name)

View File

@ -361,12 +361,12 @@ class RouterInfo(object):
def _internal_network_added(self, ns_name, network_id, port_id,
fixed_ips, mac_address,
interface_name, prefix):
interface_name, prefix, mtu=None):
LOG.debug("adding internal network: prefix(%s), port(%s)",
prefix, port_id)
self.driver.plug(network_id, port_id, interface_name, mac_address,
namespace=ns_name,
prefix=prefix)
prefix=prefix, mtu=mtu)
ip_cidrs = common_utils.fixed_ip_cidrs(fixed_ips)
self.driver.init_router_port(
@ -391,7 +391,8 @@ class RouterInfo(object):
fixed_ips,
mac_address,
interface_name,
INTERNAL_DEV_PREFIX)
INTERNAL_DEV_PREFIX,
mtu=port.get('mtu'))
def internal_network_removed(self, port):
interface_name = self.get_internal_device_name(port['id'])
@ -557,7 +558,8 @@ class RouterInfo(object):
ex_gw_port['mac_address'],
bridge=self.agent_conf.external_network_bridge,
namespace=ns_name,
prefix=EXTERNAL_DEV_PREFIX)
prefix=EXTERNAL_DEV_PREFIX,
mtu=ex_gw_port.get('mtu'))
def _get_external_gw_ips(self, ex_gw_port):
gateway_ips = []

View File

@ -1230,7 +1230,8 @@ class DeviceManager(object):
port.id,
interface_name,
port.mac_address,
namespace=network.namespace)
namespace=network.namespace,
mtu=network.get('mtu'))
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception(_LE('Unable to plug DHCP port for '

View File

@ -20,7 +20,7 @@ from oslo_config import cfg
from oslo_log import log as logging
import six
from neutron._i18n import _, _LE, _LI
from neutron._i18n import _, _LE, _LI, _LW
from neutron.agent.common import ovs_lib
from neutron.agent.linux import ip_lib
from neutron.agent.linux import utils
@ -237,15 +237,15 @@ class LinuxInterfaceDriver(object):
@abc.abstractmethod
def plug_new(self, network_id, port_id, device_name, mac_address,
bridge=None, namespace=None, prefix=None):
bridge=None, namespace=None, prefix=None, mtu=None):
"""Plug in the interface only for new devices that don't exist yet."""
def plug(self, network_id, port_id, device_name, mac_address,
bridge=None, namespace=None, prefix=None):
bridge=None, namespace=None, prefix=None, mtu=None):
if not ip_lib.device_exists(device_name,
namespace=namespace):
self.plug_new(network_id, port_id, device_name, mac_address,
bridge, namespace, prefix)
bridge, namespace, prefix, mtu)
else:
LOG.info(_LI("Device %s already exists"), device_name)
@ -273,7 +273,7 @@ class LinuxInterfaceDriver(object):
class NullDriver(LinuxInterfaceDriver):
def plug_new(self, network_id, port_id, device_name, mac_address,
bridge=None, namespace=None, prefix=None):
bridge=None, namespace=None, prefix=None, mtu=None):
pass
def unplug(self, device_name, bridge=None, namespace=None, prefix=None):
@ -308,7 +308,7 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
ovs.replace_port(device_name, *attrs)
def plug_new(self, network_id, port_id, device_name, mac_address,
bridge=None, namespace=None, prefix=None):
bridge=None, namespace=None, prefix=None, mtu=None):
"""Plug in the interface."""
if not bridge:
bridge = self.conf.ovs_integration_bridge
@ -333,11 +333,13 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
ns_dev.link.set_address(mac_address)
if self.conf.network_device_mtu:
ns_dev.link.set_mtu(self.conf.network_device_mtu)
mtu = self.conf.network_device_mtu or mtu
if mtu:
ns_dev.link.set_mtu(mtu)
if self.conf.ovs_use_veth:
root_dev.link.set_mtu(self.conf.network_device_mtu)
root_dev.link.set_mtu(mtu)
else:
LOG.warning(_LW("No MTU configured for port %s"), port_id)
# Add an interface created by ovs to the namespace.
if not self.conf.ovs_use_veth and namespace:
namespace_obj = ip.ensure_namespace(namespace)
@ -386,7 +388,7 @@ class IVSInterfaceDriver(LinuxInterfaceDriver):
utils.execute(cmd, run_as_root=True)
def plug_new(self, network_id, port_id, device_name, mac_address,
bridge=None, namespace=None, prefix=None):
bridge=None, namespace=None, prefix=None, mtu=None):
"""Plug in the interface."""
ip = ip_lib.IPWrapper()
tap_name = self._get_tap_name(device_name, prefix)
@ -399,9 +401,12 @@ class IVSInterfaceDriver(LinuxInterfaceDriver):
ns_dev = ip.device(device_name)
ns_dev.link.set_address(mac_address)
if self.conf.network_device_mtu:
ns_dev.link.set_mtu(self.conf.network_device_mtu)
root_dev.link.set_mtu(self.conf.network_device_mtu)
mtu = self.conf.network_device_mtu or mtu
if mtu:
ns_dev.link.set_mtu(mtu)
root_dev.link.set_mtu(mtu)
else:
LOG.warning(_LW("No MTU configured for port %s"), port_id)
if namespace:
namespace_obj = ip.ensure_namespace(namespace)
@ -430,7 +435,7 @@ class BridgeInterfaceDriver(LinuxInterfaceDriver):
DEV_NAME_PREFIX = 'ns-'
def plug_new(self, network_id, port_id, device_name, mac_address,
bridge=None, namespace=None, prefix=None):
bridge=None, namespace=None, prefix=None, mtu=None):
"""Plugin the interface."""
ip = ip_lib.IPWrapper()
@ -443,9 +448,12 @@ class BridgeInterfaceDriver(LinuxInterfaceDriver):
root_veth.disable_ipv6()
ns_veth.link.set_address(mac_address)
if self.conf.network_device_mtu:
root_veth.link.set_mtu(self.conf.network_device_mtu)
ns_veth.link.set_mtu(self.conf.network_device_mtu)
mtu = self.conf.network_device_mtu or mtu
if mtu:
root_veth.link.set_mtu(mtu)
ns_veth.link.set_mtu(mtu)
else:
LOG.warning(_LW("No MTU configured for port %s"), port_id)
root_veth.link.set_up()
ns_veth.link.set_up()

View File

@ -50,6 +50,10 @@ class TestDvrRouter(framework.L3AgentTestFramework):
self.agent.conf.agent_mode = 'dvr'
self._test_update_floatingip_statuses(self.generate_dvr_router_info())
def test_dvr_router_lifecycle_ha_with_snat_with_fips_nmtu(self):
self._dvr_router_lifecycle(enable_ha=True, enable_snat=True,
use_port_mtu=True)
def test_dvr_router_lifecycle_without_ha_without_snat_with_fips(self):
self._dvr_router_lifecycle(enable_ha=False, enable_snat=False)
@ -100,7 +104,7 @@ class TestDvrRouter(framework.L3AgentTestFramework):
self._validate_fips_for_external_network(router2, fip2_ns)
def _dvr_router_lifecycle(self, enable_ha=False, enable_snat=False,
custom_mtu=2000,
custom_mtu=2000, use_port_mtu=False,
ip_version=4,
dual_stack=False):
'''Test dvr router lifecycle
@ -114,11 +118,19 @@ class TestDvrRouter(framework.L3AgentTestFramework):
# Since by definition this is a dvr (distributed = true)
# only dvr and dvr_snat are applicable
self.agent.conf.agent_mode = 'dvr_snat' if enable_snat else 'dvr'
self.agent.conf.network_device_mtu = custom_mtu
# We get the router info particular to a dvr router
router_info = self.generate_dvr_router_info(
enable_ha, enable_snat, extra_routes=True)
if use_port_mtu:
for key in ('_interfaces', '_snat_router_interfaces',
'_floatingip_agent_interfaces'):
for port in router_info[key]:
port['mtu'] = custom_mtu
router_info['gw_port']['mtu'] = custom_mtu
router_info['_ha_interface']['mtu'] = custom_mtu
else:
self.agent.conf.network_device_mtu = custom_mtu
# We need to mock the get_agent_gateway_port return value
# because the whole L3PluginApi is mocked and we need the port
@ -155,6 +167,9 @@ class TestDvrRouter(framework.L3AgentTestFramework):
router.get_internal_device_name,
router.ns_name)
utils.wait_until_true(device_exists)
name = router.get_internal_device_name(device['id'])
self.assertEqual(custom_mtu,
ip_lib.IPDevice(name, router.ns_name).link.mtu)
ext_gateway_port = router_info['gw_port']
self.assertTrue(self._namespace_exists(router.ns_name))

View File

@ -253,6 +253,15 @@ class DHCPAgentOVSTestCase(DHCPAgentOVSTestFramework):
dhcp_enabled=dhcp_enabled)
self.assert_dhcp_resources(network, dhcp_enabled)
def test_agent_mtu_set_on_interface_driver(self):
network = self.network_dict_for_dhcp()
network["mtu"] = 789
self.configure_dhcp_for_network(network=network)
port = network.ports[0]
iface_name = self.get_interface_name(network, port)
dev = ip_lib.IPDevice(iface_name, network.namespace)
self.assertEqual(789, dev.link.mtu)
def test_good_address_allocation(self):
network, port = self._get_network_port_for_allocation_test()
network.ports.append(port)

View File

@ -1309,7 +1309,8 @@ class TestDeviceManager(base.BaseTestCase):
port.id,
'tap12345678-12',
'aa:bb:cc:dd:ee:ff',
namespace=net.namespace))
namespace=net.namespace,
mtu=None))
self.mock_driver.assert_has_calls(expected)
dh._set_default_route.assert_called_once_with(net, 'tap12345678-12')

View File

@ -390,7 +390,8 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
sn_port['fixed_ips'],
sn_port['mac_address'],
ri._get_snat_int_device_name(sn_port['id']),
dvr_snat_ns.SNAT_INT_DEV_PREFIX)
dvr_snat_ns.SNAT_INT_DEV_PREFIX,
mtu=None)
elif action == 'remove':
self.device_exists.return_value = False
ri.get_snat_port_for_internal_port = mock.Mock(

View File

@ -0,0 +1,20 @@
---
features:
- Use the value of the network 'mtu' attribute for the MTU
of virtual network interfaces such as veth pairs, patch
ports, and tap devices involving a particular network.
- Enable end-to-end support for arbitrary MTUs including
jumbo frames between instances and provider networks by
moving MTU disparities between flat or VLAN networks and
overlay networks from layer-2 devices to layer-3 devices
that support path MTU discovery (PMTUD).
upgrade:
- Does not change MTU for existing virtual network interfaces.
- Actions that create virtual network interfaces on an existing
network with the 'mtu' attribute containing a value greater
than zero could cause issues for network traffic traversing
existing and new virtual network interfaces.
fixes:
- Explicitly configure MTU of virtual network interfaces
rather than using default values or incorrect values that
do not account for overlay protocol overhead.