From 75c881a748941bc6637f3eb10dd5828f32ec6830 Mon Sep 17 00:00:00 2001 From: Cedric Brandily Date: Mon, 26 Oct 2015 09:50:20 +0900 Subject: [PATCH] Optimize get_bridge_for_tap_device Currently get_bridge_for_tap_device[1] iterates over all neutron bridges and their interfaces. This change proposes to deduce interface bridge from: /sys/class/net/%(interface)s/brif/bridge which is a symlink to bridge interface path to improve performance. [1] neutron.plugins.ml2.drivers.linuxbridge.agent.linuxbridge_neutron_agent Closes-Bug: #1508789 Change-Id: Ia40cd81f47ff082a90d17f58514942ec50553241 --- .../agent/linuxbridge_neutron_agent.py | 14 +++++++---- .../functional/agent/test_l2_lb_agent.py | 12 ++++++++++ .../agent/test_linuxbridge_neutron_agent.py | 24 ++++++++++++------- 3 files changed, 37 insertions(+), 13 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 76e4f1a72..b2b67285f 100644 --- a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py @@ -65,6 +65,7 @@ BRIDGE_FS = "/sys/class/net/" BRIDGE_INTERFACE_FS = BRIDGE_FS + "%(bridge)s/brif/%(interface)s" BRIDGE_INTERFACES_FS = BRIDGE_FS + "%s/brif/" BRIDGE_PORT_FS_FOR_DEVICE = BRIDGE_FS + "%s/brport" +BRIDGE_PATH_FOR_DEVICE = BRIDGE_PORT_FS_FOR_DEVICE + '/bridge' VXLAN_INTERFACE_PREFIX = "vxlan-" @@ -201,12 +202,15 @@ class LinuxBridgeManager(object): return 0 def get_bridge_for_tap_device(self, tap_device_name): - bridges = self.get_all_neutron_bridges() - for bridge in bridges: - interfaces = self.get_interfaces_on_bridge(bridge) - if tap_device_name in interfaces: + try: + path = os.readlink(BRIDGE_PATH_FOR_DEVICE % tap_device_name) + except OSError: + pass + else: + bridge = path.rpartition('/')[-1] + if (bridge.startswith(BRIDGE_NAME_PREFIX) + or bridge in self.bridge_mappings.values()): return bridge - return None def is_device_on_bridge(self, device_name): diff --git a/neutron/tests/functional/agent/test_l2_lb_agent.py b/neutron/tests/functional/agent/test_l2_lb_agent.py index ebabc4905..13939e022 100644 --- a/neutron/tests/functional/agent/test_l2_lb_agent.py +++ b/neutron/tests/functional/agent/test_l2_lb_agent.py @@ -76,3 +76,15 @@ class LinuxBridgeAgentTests(test_ip_lib.IpLibTestFramework): self.assertFalse( lba.LinuxBridgeManager.interface_exists_on_bridge( port_fixture.bridge.name, port_fixture.port.name)) + + def test_get_bridge_for_tap_device(self): + port_fixture = self.create_bridge_port_fixture() + mappings = {'physnet1': port_fixture.bridge.name} + lbm = lba.LinuxBridgeManager(mappings, {}) + self.assertEqual( + port_fixture.bridge.name, + lbm.get_bridge_for_tap_device(port_fixture.br_port.name)) + + def test_get_no_bridge_for_tap_device(self): + lbm = lba.LinuxBridgeManager({}, {}) + self.assertIsNone(lbm.get_bridge_for_tap_device('fake')) 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 3c5ee4131..a789190c1 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 @@ -32,7 +32,8 @@ from neutron.tests import base LOCAL_IP = '192.168.0.33' DEVICE_1 = 'tapabcdef01-12' -BRIDGE_MAPPINGS = {'physnet0': 'br-eth2'} +BRIDGE_MAPPING_VALUE = 'br-eth2' +BRIDGE_MAPPINGS = {'physnet0': BRIDGE_MAPPING_VALUE} INTERFACE_MAPPINGS = {'physnet1': 'eth1'} FAKE_DEFAULT_DEV = mock.Mock() FAKE_DEFAULT_DEV.name = 'eth1' @@ -492,14 +493,21 @@ class TestLinuxBridgeManager(base.BaseTestCase): self.assertEqual(self.lbm.get_tap_devices_count('br0'), 0) def test_get_bridge_for_tap_device(self): - with mock.patch.object(self.lbm, - "get_all_neutron_bridges") as get_all_qbr_fn,\ - mock.patch.object(self.lbm, - "get_interfaces_on_bridge") as get_if_fn: - get_all_qbr_fn.return_value = ["br-int", "br-ex"] - get_if_fn.return_value = ["tap1", "tap2", "tap3"] + + with mock.patch.object(os, 'readlink') as readlink: + readlink.return_value = ( + 'blah/%s-fake' % linuxbridge_neutron_agent.BRIDGE_NAME_PREFIX) self.assertEqual(self.lbm.get_bridge_for_tap_device("tap1"), - "br-int") + "brq-fake") + + readlink.return_value = 'blah/%s' % BRIDGE_MAPPING_VALUE + self.assertEqual(self.lbm.get_bridge_for_tap_device("tap2"), + BRIDGE_MAPPING_VALUE) + + readlink.return_value = 'blah/notneutronbridge' + self.assertIsNone(self.lbm.get_bridge_for_tap_device("tap3")) + + readlink.side_effect = OSError() self.assertIsNone(self.lbm.get_bridge_for_tap_device("tap4")) def test_is_device_on_bridge(self): -- 2.45.2