From 0985ef78d43ae7d910669c3ca968fd977f2ea2ae Mon Sep 17 00:00:00 2001 From: rajeev Date: Fri, 22 Aug 2014 18:54:46 -0400 Subject: [PATCH] Stop tracking connections in DVR FIP Namespace For DVR, connections to external network using floating IPs do not need to be tracked in FIP namespace because they are being already tracked in router namespace. This fix adds iptable rules to not track connections. Change-Id: I378039e311763d114860cb70ded7349d6580855a Closes-bug: #1360395 --- neutron/agent/l3_agent.py | 7 ++ neutron/agent/linux/iptables_manager.py | 4 + neutron/tests/unit/test_iptables_manager.py | 109 ++++++++++++++++-- .../tests/unit/test_security_groups_rpc.py | 12 +- 4 files changed, 119 insertions(+), 13 deletions(-) diff --git a/neutron/agent/l3_agent.py b/neutron/agent/l3_agent.py index f632996d2..113af79bb 100644 --- a/neutron/agent/l3_agent.py +++ b/neutron/agent/l3_agent.py @@ -1482,6 +1482,13 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager): fip_ns_name = ( self.get_fip_ns_name(str(network_id))) self._create_namespace(fip_ns_name) + ri.fip_iptables_manager = iptables_manager.IptablesManager( + root_helper=self.root_helper, namespace=fip_ns_name, + use_ipv6=self.use_ipv6) + # no connection tracking needed in fip namespace + ri.fip_iptables_manager.ipv4['raw'].add_rule('PREROUTING', + '-j CT --notrack') + ri.fip_iptables_manager.apply() interface_name = ( self.get_fip_ext_device_name(self.agent_gateway_port['id'])) self.agent_gateway_added(fip_ns_name, self.agent_gateway_port, diff --git a/neutron/agent/linux/iptables_manager.py b/neutron/agent/linux/iptables_manager.py index ebb34d091..1a858fd5d 100644 --- a/neutron/agent/linux/iptables_manager.py +++ b/neutron/agent/linux/iptables_manager.py @@ -321,6 +321,10 @@ class IptablesManager(object): {'nat': IptablesTable(binary_name=self.wrap_name)}) builtin_chains[4].update({'nat': ['PREROUTING', 'OUTPUT', 'POSTROUTING']}) + self.ipv4.update( + {'raw': IptablesTable(binary_name=self.wrap_name)}) + builtin_chains[4].update({'raw': ['PREROUTING', + 'OUTPUT']}) for ip_version in builtin_chains: if ip_version == 4: diff --git a/neutron/tests/unit/test_iptables_manager.py b/neutron/tests/unit/test_iptables_manager.py index 48173262f..cc3abeaeb 100644 --- a/neutron/tests/unit/test_iptables_manager.py +++ b/neutron/tests/unit/test_iptables_manager.py @@ -62,6 +62,19 @@ FILTER_DUMP = ('# Generated by iptables_manager\n' '# Completed by iptables_manager\n' % IPTABLES_ARG) +def _generate_raw_dump(iptables_args): + return ('# Generated by iptables_manager\n' + '*raw\n' + ':%(bn)s-OUTPUT - [0:0]\n' + ':%(bn)s-PREROUTING - [0:0]\n' + '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n' + '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n' + 'COMMIT\n' + '# Completed by iptables_manager\n' % iptables_args) + +RAW_DUMP = _generate_raw_dump(IPTABLES_ARG) + + class IptablesManagerStateFulTestCase(base.BaseTestCase): def setUp(self): @@ -185,19 +198,21 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): 'COMMIT\n' '# Completed by iptables_manager\n' % iptables_args) + raw_dump = _generate_raw_dump(iptables_args) + expected_calls_and_values = [ (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=nat_dump + filter_dump_mod, + process_input=raw_dump + nat_dump + filter_dump_mod, root_helper=self.root_helper), None), (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=nat_dump + filter_dump, + process_input=raw_dump + nat_dump + filter_dump, root_helper=self.root_helper), None), ] @@ -285,19 +300,21 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): 'COMMIT\n' '# Completed by iptables_manager\n' % iptables_args) + raw_dump = _generate_raw_dump(iptables_args) + expected_calls_and_values = [ (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=nat_dump + filter_dump_mod, + process_input=raw_dump + nat_dump + filter_dump_mod, root_helper=self.root_helper), None), (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=nat_dump + filter_dump, + process_input=raw_dump + nat_dump + filter_dump, root_helper=self.root_helper), None), ] @@ -352,14 +369,14 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=NAT_DUMP + filter_dump_mod, + process_input=RAW_DUMP + NAT_DUMP + filter_dump_mod, root_helper=self.root_helper), None), (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=NAT_DUMP + FILTER_DUMP, + process_input=RAW_DUMP + NAT_DUMP + FILTER_DUMP, root_helper=self.root_helper), None), ] @@ -415,14 +432,14 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=NAT_DUMP + filter_dump_mod, + process_input=RAW_DUMP + NAT_DUMP + filter_dump_mod, root_helper=self.root_helper), None), (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=NAT_DUMP + FILTER_DUMP, + process_input=RAW_DUMP + NAT_DUMP + FILTER_DUMP, root_helper=self.root_helper ), None), @@ -495,14 +512,14 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=NAT_DUMP + filter_dump_mod, + process_input=RAW_DUMP + NAT_DUMP + filter_dump_mod, root_helper=self.root_helper), None), (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=NAT_DUMP + FILTER_DUMP, + process_input=RAW_DUMP + NAT_DUMP + FILTER_DUMP, root_helper=self.root_helper), None), ] @@ -585,14 +602,14 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=nat_dump_mod + FILTER_DUMP, + process_input=RAW_DUMP + nat_dump_mod + FILTER_DUMP, root_helper=self.root_helper), None), (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=nat_dump + FILTER_DUMP, + process_input=RAW_DUMP + nat_dump + FILTER_DUMP, root_helper=self.root_helper), None), ] @@ -630,6 +647,66 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): def test_add_nat_rule_with_ipv6(self): self._test_add_nat_rule_helper(True) + def _test_add_raw_rule_helper(self, use_ipv6): + self.iptables = iptables_manager.IptablesManager( + root_helper=self.root_helper, + use_ipv6=use_ipv6) + self.execute = mock.patch.object(self.iptables, "execute").start() + + raw_dump_mod = ('# Generated by iptables_manager\n' + '*raw\n' + ':%(bn)s-OUTPUT - [0:0]\n' + ':%(bn)s-PREROUTING - [0:0]\n' + ':%(bn)s-raw - [0:0]\n' + '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n' + '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n' + '[0:0] -A %(bn)s-PREROUTING -j CT --notrack\n' + 'COMMIT\n' + '# Completed by iptables_manager\n' + % IPTABLES_ARG) + + expected_calls_and_values = [ + (mock.call(['iptables-save', '-c'], + root_helper=self.root_helper), + ''), + (mock.call(['iptables-restore', '-c'], + process_input=raw_dump_mod + NAT_DUMP + FILTER_DUMP, + root_helper=self.root_helper), + None), + (mock.call(['iptables-save', '-c'], + root_helper=self.root_helper), + ''), + (mock.call(['iptables-restore', '-c'], + process_input=RAW_DUMP + NAT_DUMP + FILTER_DUMP, + root_helper=self.root_helper), + None), + ] + if use_ipv6: + self._extend_with_ip6tables_filter(expected_calls_and_values, + FILTER_DUMP) + + tools.setup_mock_calls(self.execute, expected_calls_and_values) + + self.iptables.ipv4['raw'].add_chain('raw') + self.iptables.ipv4['raw'].add_rule('PREROUTING', + '-j CT --notrack') + + self.iptables.apply() + + self.iptables.ipv4['raw'].remove_rule('PREROUTING', + '-j CT --notrack') + self.iptables.ipv4['raw'].remove_chain('raw') + + self.iptables.apply() + + tools.verify_mock_calls(self.execute, expected_calls_and_values) + + def test_add_raw_rule(self): + self._test_add_raw_rule_helper(False) + + def test_add_raw_rule_with_ipv6(self): + self._test_add_raw_rule_helper(True) + def test_add_rule_to_a_nonexistent_chain(self): self.assertRaises(LookupError, self.iptables.ipv4['filter'].add_rule, 'nonexistent', '-j DROP') @@ -744,6 +821,10 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): '-n', '-v', '-x'], root_helper=self.root_helper), iptables_dump), + (mock.call(['iptables', '-t', 'raw', '-L', 'OUTPUT', '-n', + '-v', '-x'], + root_helper=self.root_helper), + ''), (mock.call(['iptables', '-t', 'nat', '-L', 'OUTPUT', '-n', '-v', '-x'], root_helper=self.root_helper), @@ -795,6 +876,10 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): '-n', '-v', '-x', '-Z'], root_helper=self.root_helper), iptables_dump), + (mock.call(['iptables', '-t', 'raw', '-L', 'OUTPUT', '-n', + '-v', '-x', '-Z'], + root_helper=self.root_helper), + ''), (mock.call(['iptables', '-t', 'nat', '-L', 'OUTPUT', '-n', '-v', '-x', '-Z'], root_helper=self.root_helper), diff --git a/neutron/tests/unit/test_security_groups_rpc.py b/neutron/tests/unit/test_security_groups_rpc.py index c841bf322..cd42bb76e 100644 --- a/neutron/tests/unit/test_security_groups_rpc.py +++ b/neutron/tests/unit/test_security_groups_rpc.py @@ -1477,6 +1477,16 @@ COMMIT # Completed by iptables_manager """ % IPTABLES_ARG +IPTABLES_RAW = """# Generated by iptables_manager +*raw +:%(bn)s-(%(chains)s) - [0:0] +:%(bn)s-(%(chains)s) - [0:0] +[0:0] -A PREROUTING -j %(bn)s-PREROUTING +[0:0] -A OUTPUT -j %(bn)s-OUTPUT +COMMIT +# Completed by iptables_manager +""" % IPTABLES_ARG + CHAINS_EMPTY = 'FORWARD|INPUT|OUTPUT|local|sg-chain|sg-fallback' CHAINS_1 = CHAINS_EMPTY + '|i_port1|o_port1|s_port1' CHAINS_2 = CHAINS_1 + '|i_port2|o_port2|s_port2' @@ -2157,7 +2167,7 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): return_value='') self._register_mock_call( ['iptables-restore', '-c'], - process_input=self._regex(IPTABLES_NAT + v4_filter), + process_input=self._regex(IPTABLES_RAW + IPTABLES_NAT + v4_filter), root_helper=self.root_helper, return_value='') self._register_mock_call( -- 2.45.2