diff --git a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py index c5d3e945900..9fc9cbcb8ab 100644 --- a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py @@ -40,6 +40,7 @@ from neutron.common import exceptions from neutron.common import topics from neutron.common import utils as n_utils from neutron.plugins.common import constants as p_const +from neutron.plugins.common import utils as p_utils from neutron.plugins.ml2.drivers.agent import _agent_manager_base as amb from neutron.plugins.ml2.drivers.agent import _common_agent as ca from neutron.plugins.ml2.drivers.agent import config as cagt_config # noqa @@ -55,6 +56,7 @@ LOG = logging.getLogger(__name__) LB_AGENT_BINARY = 'neutron-linuxbridge-agent' BRIDGE_NAME_PREFIX = "brq" +MAX_VLAN_POSTFIX_LEN = 5 VXLAN_INTERFACE_PREFIX = "vxlan-" @@ -141,8 +143,32 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase): if not vlan_id: LOG.warning(_LW("Invalid VLAN ID, will lead to incorrect " "subinterface name")) - subinterface_name = '%s.%s' % (physical_interface, vlan_id) - return subinterface_name + vlan_postfix = '.%s' % vlan_id + + # For the vlan subinterface name prefix we use: + # * the physical_interface, if len(physical_interface) + + # len(vlan_postifx) <= 15 for backward compatibility reasons + # Example: physical_interface = eth0 + # prefix = eth0.1 + # prefix = eth0.1111 + # + # * otherwise a unique hash per physical_interface to help debugging + # Example: physical_interface = long_interface + # prefix = longHASHED.1 + # prefix = longHASHED.1111 + # + # Remark: For some physical_interface values, the used prefix can be + # both, the physical_interface itself or a hash, depending + # on the vlan_postfix length. + # Example: physical_interface = mix_interface + # prefix = mix_interface.1 (backward compatible) + # prefix = mix_iHASHED.1111 + if (len(physical_interface) + len(vlan_postfix) > + constants.DEVICE_NAME_MAX_LEN): + physical_interface = p_utils.get_interface_name( + physical_interface, max_len=(constants.DEVICE_NAME_MAX_LEN - + MAX_VLAN_POSTFIX_LEN)) + return "%s%s" % (physical_interface, vlan_postfix) @staticmethod def get_tap_device_name(interface_id): diff --git a/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py index c64bc109098..3b9b2fc0916 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py @@ -175,10 +175,29 @@ class TestLinuxBridgeManager(base.BaseTestCase): nw_id = "" self.assertEqual("brq", self.lbm.get_bridge_name(nw_id)) - def test_get_subinterface_name(self): - self.assertEqual("eth0.0", - self.lbm.get_subinterface_name("eth0", "0")) - self.assertEqual("eth0.", self.lbm.get_subinterface_name("eth0", "")) + def test_get_subinterface_name_backwards_compatibility(self): + self.assertEqual("abcdefghijklm.1", + self.lbm.get_subinterface_name("abcdefghijklm", "1")) + self.assertEqual("abcdefghijkl.11", + self.lbm.get_subinterface_name("abcdefghijkl", "11")) + self.assertEqual("abcdefghij.1111", + self.lbm.get_subinterface_name("abcdefghij", + "1111")) + + def test_get_subinterface_name_advanced(self): + """Ensure the same hash is used for long interface names. + + If the generated vlan device name would be too long, make sure that + everything before the '.' is equal. This might be helpful when + debugging problems. + """ + + max_device_name = "abcdefghijklmno" + vlan_dev_name1 = self.lbm.get_subinterface_name(max_device_name, "1") + vlan_dev_name2 = self.lbm.get_subinterface_name(max_device_name, + "1111") + self.assertEqual(vlan_dev_name1.partition(".")[0], + vlan_dev_name2.partition(".")[0]) def test_get_tap_device_name(self): if_id = "123456789101112"