]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Setup br-tun in secure fail mode to avoid broadcast storms
authorMiguel Angel Ajo <mangelajo@redhat.com>
Thu, 12 Feb 2015 14:32:58 +0000 (14:32 +0000)
committerMiguel Angel Ajo <mangelajo@redhat.com>
Mon, 16 Feb 2015 14:37:17 +0000 (14:37 +0000)
When not creating br-tun in secure fail mode, there are chances to
get a broadcast storm from br-tun.

For example, this occurs when at least three nodes have the br-tun
OpenFlow rules reset in and a broadcast/multicast packet enters br-tun.

This can happen if:
  * openvswitch is restarted, until the agent reloads the Openflow rules.
  * during neutron-openvswitch-agent restart, br-tun is reset, and there
is a few seconds timeframe where tunnel endpoints are plugged and OF
rules are reset.

Secure fail mode doesn't forward traffic by default if no rule is hit.

Change-Id: Iba5ded14179156decb16dcd4b898c026660f9653
Closes-bug: #1421232

neutron/agent/linux/ovs_lib.py
neutron/plugins/openvswitch/agent/ovs_neutron_agent.py
neutron/tests/functional/agent/test_ovs_lib.py
neutron/tests/unit/openvswitch/test_ovs_tunnel.py

index 6895d565f0f9059b5c6efa3f60fb280c95aa227e..1c05c2220e6128d157376aaa7c4e4c8b426a49e6 100644 (file)
@@ -37,6 +37,9 @@ DEFAULT_OVS_VSCTL_TIMEOUT = 10
 INVALID_OFPORT = -1
 UNASSIGNED_OFPORT = []
 
+# OVS bridge fail modes
+FAILMODE_SECURE = 'secure'
+
 OPTS = [
     cfg.IntOpt('ovs_vsctl_timeout',
                default=DEFAULT_OVS_VSCTL_TIMEOUT,
@@ -151,7 +154,7 @@ class OVSBridge(BaseOVS):
             check_error=True)
 
     def set_secure_mode(self):
-        self.ovsdb.set_fail_mode(self.br_name, 'secure').execute(
+        self.ovsdb.set_fail_mode(self.br_name, FAILMODE_SECURE).execute(
             check_error=True)
 
     def set_protocols(self, protocols):
@@ -164,10 +167,13 @@ class OVSBridge(BaseOVS):
     def destroy(self):
         self.delete_bridge(self.br_name)
 
-    def reset_bridge(self):
+    def reset_bridge(self, secure_mode=False):
         with self.ovsdb.transaction() as txn:
             txn.add(self.ovsdb.del_br(self.br_name))
             txn.add(self.ovsdb.add_br(self.br_name))
+            if secure_mode:
+                txn.add(self.ovsdb.set_fail_mode(self.br_name,
+                                                 FAILMODE_SECURE))
 
     def add_port(self, port_name, *interface_attr_tuples):
         with self.ovsdb.transaction() as txn:
index b1a3565bb7c7a55846d8e19d6699e5f144b1cf50..333e14c90f565c8944a37ac994ff2bf634692c40 100644 (file)
@@ -770,7 +770,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
         if not self.tun_br:
             self.tun_br = ovs_lib.OVSBridge(tun_br_name, self.root_helper)
 
-        self.tun_br.reset_bridge()
+        self.tun_br.reset_bridge(secure_mode=True)
         self.patch_tun_ofport = self.int_br.add_patch_port(
             cfg.CONF.OVS.int_peer_patch_port, cfg.CONF.OVS.tun_peer_patch_port)
         self.patch_int_ofport = self.tun_br.add_patch_port(
index 89192e52f26068d89be1ec8f8a6769a5d0a251c7..4f6f2e62288576f74fd3561a904910ac332fe935 100644 (file)
@@ -93,9 +93,12 @@ class OVSBridgeTestCase(base.BaseOVSLinuxTestCase):
 
     def test_set_fail_mode(self):
         self.br.set_secure_mode()
+        self._assert_br_fail_mode(ovs_lib.FAILMODE_SECURE)
+
+    def _assert_br_fail_mode(self, fail_mode):
         self.assertEqual(
             self.br.db_get_val('Bridge', self.br.br_name, 'fail_mode'),
-            'secure')
+            fail_mode)
 
     def test_set_protocols(self):
         self.br.set_protocols('OpenFlow10')
@@ -190,6 +193,16 @@ class OVSBridgeTestCase(base.BaseOVSLinuxTestCase):
         self.br.delete_ports(all_ports=True)
         self.assertEqual(len(self.br.get_port_name_list()), 0)
 
+    def test_reset_bridge(self):
+        self.create_ovs_port()
+        self.br.reset_bridge()
+        self.assertEqual(len(self.br.get_port_name_list()), 0)
+        self._assert_br_fail_mode([])
+
+    def test_reset_bridge_secure_mode(self):
+        self.br.reset_bridge(secure_mode=True)
+        self._assert_br_fail_mode(ovs_lib.FAILMODE_SECURE)
+
 
 class OVSLibTestCase(base.BaseOVSLinuxTestCase):
     def test_bridge_lifecycle_baseovs(self):
index 53595cbd6b890fb490a833a64fe8bd40c1124fbf..4ab73e1db244ea6d614fd4ab8fcb4b99b1e284ca 100644 (file)
@@ -186,7 +186,7 @@ class TunnelTest(base.BaseTestCase):
         ]
 
         self.mock_tun_bridge_expected = [
-            mock.call.reset_bridge(),
+            mock.call.reset_bridge(secure_mode=True),
             mock.call.add_patch_port('patch-int', 'patch-tun'),
         ]
         self.mock_int_bridge_expected += [
@@ -602,7 +602,7 @@ class TunnelTestUseVethInterco(TunnelTest):
         ]
 
         self.mock_tun_bridge_expected = [
-            mock.call.reset_bridge(),
+            mock.call.reset_bridge(secure_mode=True),
             mock.call.add_patch_port('patch-int', 'patch-tun'),
         ]
         self.mock_int_bridge_expected += [