]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Optimize get_bridge_for_tap_device
authorCedric Brandily <zzelle@gmail.com>
Mon, 26 Oct 2015 00:50:20 +0000 (09:50 +0900)
committerCedric Brandily <zzelle@gmail.com>
Mon, 26 Oct 2015 01:08:29 +0000 (10:08 +0900)
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

neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py
neutron/tests/functional/agent/test_l2_lb_agent.py
neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py

index 76e4f1a721bd4467fabddf4e718ce4e7f8dc5994..b2b67285f06a5c331ee680be7967a13f39dfc824 100644 (file)
@@ -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):
index ebabc49051ecc78041e0a49e44061040cd118c9d..13939e02277a08d2e20b776f8548742974461dc2 100644 (file)
@@ -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'))
index 3c5ee4131dc4649b17013b45ee1adf602e68e229..a789190c108c780182db41e2e6436c1941a0ce0d 100644 (file)
@@ -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):