From 7ececa3a20e19985b7ebcca2c629126a3900c090 Mon Sep 17 00:00:00 2001 From: Andreas Scheuring Date: Wed, 18 Nov 2015 15:33:03 +0100 Subject: [PATCH] lb: interface name hashing for too long vlan interface names The linuxbridge agent creates vlan subinterfaces for each vlan neutron network. The name for this vlan subinterface is ".". Todays code crashes if the physical interface name is too long. Therefore this hashing is being introduced. Change-Id: Ieb3c0a7282b28eed556236ead4993ab83a29a12f Closes-Bug: #1495960 --- .../agent/linuxbridge_neutron_agent.py | 30 +++++++++++++++++-- .../agent/test_linuxbridge_neutron_agent.py | 27 ++++++++++++++--- 2 files changed, 51 insertions(+), 6 deletions(-) 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"