]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Ensure netfilter is enabled for bridges
authorIan Wienand <iwienand@redhat.com>
Thu, 7 May 2015 04:59:38 +0000 (14:59 +1000)
committerIan Wienand <iwienand@redhat.com>
Fri, 29 May 2015 11:09:27 +0000 (21:09 +1000)
Since security-groups use iptables rules on Linux bridges, we need to
ensure that netfilter is enabled for bridges.  Unfortunately, there
seems to be a long history of distributions having differing defaults
for this, best described in [1].

It seems at the moment everyone has to discover this for themselves;
packstack found it in Ia8c86dcb31810a8d6b133a161388604fde9bead4, then
fuel found the same thing in I8582c24706c3a7253e00569eef275f116d765bca
and then finally someone else hit it and put it into documentation
with I4ed3cec03a1b3a7d56dfe18394154ec1b2db6791.  I just spent a long
time figuring it out too when deploying with devstack.

Rather than having yet another fix in devstack, I don't see why
neutron shouldn't be ensuring the setting is correct when it starts up
-- without these settings enabled, security-groups are silently
broken.  This does that, and modifies test-cases to check we make the
calls.

[1] http://wiki.libvirt.org/page/Net.bridge-nf-call_and_sysctl.conf

Change-Id: If2d316eb8c422dc1e4f34b17a50b93dd72993a99

neutron/agent/linux/iptables_firewall.py
neutron/tests/unit/agent/test_securitygroups_rpc.py

index 840fba7f6f79a41bb39e17afd0065f3625fb3c85..5cea8e39bab17fd652dda51264c970b496e1f791 100644 (file)
@@ -22,6 +22,7 @@ from neutron.agent import firewall
 from neutron.agent.linux import ipset_manager
 from neutron.agent.linux import iptables_comments as ic
 from neutron.agent.linux import iptables_manager
+from neutron.agent.linux import utils
 from neutron.common import constants
 from neutron.common import ipv6_utils
 from neutron.extensions import portsecurity as psec
@@ -71,6 +72,32 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
             lambda: collections.defaultdict(list))
         self.pre_sg_members = None
         self.enable_ipset = cfg.CONF.SECURITYGROUP.enable_ipset
+        self._enabled_netfilter_for_bridges = False
+
+    def _enable_netfilter_for_bridges(self):
+        # we only need to set these values once, but it has to be when
+        # we create a bridge; before that the bridge module might not
+        # be loaded and the proc values aren't there.
+        if self._enabled_netfilter_for_bridges:
+            return
+        else:
+            self._enabled_netfilter_for_bridges = True
+
+        # These proc values ensure that netfilter is enabled on
+        # bridges; essential for enforcing security groups rules with
+        # OVS Hybrid.  Distributions can differ on whether this is
+        # enabled by default or not (Ubuntu - yes, Redhat - no, for
+        # example).
+        LOG.debug("Enabling netfilter for bridges")
+        utils.execute(['sysctl', '-w',
+                       'net.bridge.bridge-nf-call-arptables=1'],
+                      run_as_root=True)
+        utils.execute(['sysctl', '-w',
+                       'net.bridge.bridge-nf-call-ip6tables=1'],
+                      run_as_root=True)
+        utils.execute(['sysctl', '-w',
+                       'net.bridge.bridge-nf-call-iptables=1'],
+                      run_as_root=True)
 
     @property
     def ports(self):
@@ -103,7 +130,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
         LOG.debug("Preparing device (%s) filter", port['device'])
         self._remove_chains()
         self._set_ports(port)
-
+        self._enable_netfilter_for_bridges()
         # each security group has it own chains
         self._setup_chains()
         self.iptables.apply()
index b732b6b5af59203f3aadff04b2df08b283b32057..6d050e6cc13b32c72bb98d97f1f0f96fcfb57eba 100644 (file)
@@ -2483,6 +2483,9 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
         cfg.CONF.set_override('enable_ipset', False, group='SECURITYGROUP')
         cfg.CONF.set_override('comment_iptables_rules', False, group='AGENT')
 
+        self.utils_exec = mock.patch(
+            'neutron.agent.linux.utils.execute').start()
+
         self.rpc = mock.Mock()
         self._init_agent(defer_refresh_firewall)
 
@@ -2607,6 +2610,13 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
             self.assertThat(kwargs['process_input'],
                             matchers.MatchesRegex(expected_regex))
 
+        expected = ['net.bridge.bridge-nf-call-arptables=1',
+                    'net.bridge.bridge-nf-call-ip6tables=1',
+                    'net.bridge.bridge-nf-call-iptables=1']
+        for e in expected:
+            self.utils_exec.assert_any_call(['sysctl', '-w', e],
+                                            run_as_root=True)
+
     def _replay_iptables(self, v4_filter, v6_filter, raw):
         self._register_mock_call(
             ['iptables-save', '-c'],