From c7e533c3679a1f4a612f3b53354cb7cb5bc1ba12 Mon Sep 17 00:00:00 2001 From: Cedric Brandily Date: Tue, 18 Nov 2014 10:34:30 +0100 Subject: [PATCH] Allow IptablesManager to manage mangle table This change enables the IptablesManager to manage mangle table (used by daughter change). Partial-Bug: #1187102 Change-Id: Ic2d681f1515aaa541c6d137ce981622f2fff90e5 --- neutron/agent/linux/iptables_manager.py | 5 + neutron/tests/functional/agent/linux/base.py | 5 + .../functional/agent/linux/test_iptables.py | 13 ++ neutron/tests/unit/test_iptables_manager.py | 153 +++++++++++++++--- .../tests/unit/test_security_groups_rpc.py | 22 ++- 5 files changed, 179 insertions(+), 19 deletions(-) diff --git a/neutron/agent/linux/iptables_manager.py b/neutron/agent/linux/iptables_manager.py index 8d89a7cdd..ce8dae365 100644 --- a/neutron/agent/linux/iptables_manager.py +++ b/neutron/agent/linux/iptables_manager.py @@ -316,6 +316,11 @@ class IptablesManager(object): 6: {'filter': ['INPUT', 'OUTPUT', 'FORWARD']}} if not state_less: + self.ipv4.update( + {'mangle': IptablesTable(binary_name=self.wrap_name)}) + builtin_chains[4].update( + {'mangle': ['PREROUTING', 'INPUT', 'FORWARD', 'OUTPUT', + 'POSTROUTING']}) self.ipv4.update( {'nat': IptablesTable(binary_name=self.wrap_name)}) builtin_chains[4].update({'nat': ['PREROUTING', diff --git a/neutron/tests/functional/agent/linux/base.py b/neutron/tests/functional/agent/linux/base.py index ed2f25ebf..e8b2bf848 100644 --- a/neutron/tests/functional/agent/linux/base.py +++ b/neutron/tests/functional/agent/linux/base.py @@ -28,6 +28,11 @@ from neutron.tests import sub_base BR_PREFIX = 'test-br' PORT_PREFIX = 'test-port' +MARK_VALUE = '0x1' +MARK_MASK = '0xffffffff' +ICMP_MARK_RULE = ('-j MARK --set-xmark %(value)s/%(mask)s' + % {'value': MARK_VALUE, 'mask': MARK_MASK}) +MARKED_BLOCK_RULE = '-m mark --mark %s -j DROP' % MARK_VALUE ICMP_BLOCK_RULE = '-p icmp -j DROP' VETH_PREFIX = 'tst-vth' diff --git a/neutron/tests/functional/agent/linux/test_iptables.py b/neutron/tests/functional/agent/linux/test_iptables.py index 4e7efb69c..71da1d7ae 100644 --- a/neutron/tests/functional/agent/linux/test_iptables.py +++ b/neutron/tests/functional/agent/linux/test_iptables.py @@ -35,3 +35,16 @@ class IptablesManagerTestCase(base.BaseIPVethTestCase): base.ICMP_BLOCK_RULE) self.iptables.apply() self.pinger.assert_ping_from_ns(self.src_ns, self.DST_ADDRESS) + + def test_mangle_icmp(self): + self.pinger.assert_ping_from_ns(self.src_ns, self.DST_ADDRESS) + self.iptables.ipv4['mangle'].add_rule('INPUT', base.ICMP_MARK_RULE) + self.iptables.ipv4['filter'].add_rule('INPUT', base.MARKED_BLOCK_RULE) + self.iptables.apply() + self.pinger.assert_no_ping_from_ns(self.src_ns, self.DST_ADDRESS) + self.iptables.ipv4['mangle'].remove_rule('INPUT', + base.ICMP_MARK_RULE) + self.iptables.ipv4['filter'].remove_rule('INPUT', + base.MARKED_BLOCK_RULE) + self.iptables.apply() + self.pinger.assert_ping_from_ns(self.src_ns, self.DST_ADDRESS) diff --git a/neutron/tests/unit/test_iptables_manager.py b/neutron/tests/unit/test_iptables_manager.py index 51c7c4cfa..54fcf76dd 100644 --- a/neutron/tests/unit/test_iptables_manager.py +++ b/neutron/tests/unit/test_iptables_manager.py @@ -153,22 +153,23 @@ class IptablesCommentsTestCase(base.BaseTestCase): filter_dump_mod = FILTER_WITH_RULES_TEMPLATE % iptables_args raw_dump = _generate_raw_dump(IPTABLES_ARG) + mangle_dump = _generate_mangle_dump(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 + COMMENTED_NAT_DUMP + filter_dump_mod), + process_input=(raw_dump + COMMENTED_NAT_DUMP + + mangle_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=( - raw_dump + COMMENTED_NAT_DUMP + FILTER_DUMP), + process_input=(raw_dump + COMMENTED_NAT_DUMP + + mangle_dump + FILTER_DUMP), root_helper=self.root_helper ), None), @@ -194,6 +195,23 @@ class IptablesCommentsTestCase(base.BaseTestCase): tools.verify_mock_calls(self.execute, expected_calls_and_values) +def _generate_mangle_dump(iptables_args): + return ('# Generated by iptables_manager\n' + '*mangle\n' + ':%(bn)s-FORWARD - [0:0]\n' + ':%(bn)s-INPUT - [0:0]\n' + ':%(bn)s-OUTPUT - [0:0]\n' + ':%(bn)s-POSTROUTING - [0:0]\n' + ':%(bn)s-PREROUTING - [0:0]\n' + '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n' + '[0:0] -A INPUT -j %(bn)s-INPUT\n' + '[0:0] -A FORWARD -j %(bn)s-FORWARD\n' + '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n' + '[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n' + 'COMMIT\n' + '# Completed by iptables_manager\n' % iptables_args) + + def _generate_raw_dump(iptables_args): return ('# Generated by iptables_manager\n' '*raw\n' @@ -204,6 +222,7 @@ def _generate_raw_dump(iptables_args): 'COMMIT\n' '# Completed by iptables_manager\n' % iptables_args) +MANGLE_DUMP = _generate_mangle_dump(IPTABLES_ARG) RAW_DUMP = _generate_raw_dump(IPTABLES_ARG) @@ -271,20 +290,23 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): nat_dump = NAT_TEMPLATE % iptables_args raw_dump = _generate_raw_dump(iptables_args) + mangle_dump = _generate_mangle_dump(iptables_args) expected_calls_and_values = [ (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=raw_dump + nat_dump + filter_dump_mod, + process_input=(raw_dump + nat_dump + mangle_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=raw_dump + nat_dump + filter_dump, + process_input=(raw_dump + nat_dump + mangle_dump + + filter_dump), root_helper=self.root_helper), None), ] @@ -329,20 +351,23 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): nat_dump = NAT_TEMPLATE % iptables_args raw_dump = _generate_raw_dump(iptables_args) + mangle_dump = _generate_mangle_dump(iptables_args) expected_calls_and_values = [ (mock.call(['iptables-save', '-c'], root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=raw_dump + nat_dump + filter_dump_mod, + process_input=(raw_dump + nat_dump + mangle_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=raw_dump + nat_dump + filter_dump, + process_input=(raw_dump + nat_dump + mangle_dump + + filter_dump), root_helper=self.root_helper), None), ] @@ -381,14 +406,16 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=RAW_DUMP + NAT_DUMP + filter_dump_mod, + process_input=(RAW_DUMP + NAT_DUMP + MANGLE_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=RAW_DUMP + NAT_DUMP + FILTER_DUMP, + process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP + + FILTER_DUMP), root_helper=self.root_helper), None), ] @@ -431,14 +458,16 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=RAW_DUMP + NAT_DUMP + filter_dump_mod, + process_input=(RAW_DUMP + NAT_DUMP + MANGLE_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=RAW_DUMP + NAT_DUMP + FILTER_DUMP, + process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP + + FILTER_DUMP), root_helper=self.root_helper ), None), @@ -511,14 +540,16 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=RAW_DUMP + NAT_DUMP + filter_dump_mod, + process_input=(RAW_DUMP + NAT_DUMP + MANGLE_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=RAW_DUMP + NAT_DUMP + FILTER_DUMP, + process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP + + FILTER_DUMP), root_helper=self.root_helper), None), ] @@ -549,6 +580,77 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): def test_rule_with_wrap_target_with_ipv6(self): self._test_rule_with_wrap_target_helper(True) + def _test_add_mangle_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() + + mangle_dump_mod = ( + '# Generated by iptables_manager\n' + '*mangle\n' + ':%(bn)s-FORWARD - [0:0]\n' + ':%(bn)s-INPUT - [0:0]\n' + ':%(bn)s-OUTPUT - [0:0]\n' + ':%(bn)s-POSTROUTING - [0:0]\n' + ':%(bn)s-PREROUTING - [0:0]\n' + ':%(bn)s-mangle - [0:0]\n' + '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n' + '[0:0] -A INPUT -j %(bn)s-INPUT\n' + '[0:0] -A FORWARD -j %(bn)s-FORWARD\n' + '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n' + '[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n' + '[0:0] -A %(bn)s-PREROUTING -j MARK --set-xmark 0x1/0xffffffff\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 + NAT_DUMP + mangle_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=(RAW_DUMP + NAT_DUMP + MANGLE_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['mangle'].add_chain('mangle') + self.iptables.ipv4['mangle'].add_rule( + 'PREROUTING', + '-j MARK --set-xmark 0x1/0xffffffff') + + self.iptables.apply() + + self.iptables.ipv4['mangle'].remove_rule( + 'PREROUTING', + '-j MARK --set-xmark 0x1/0xffffffff') + self.iptables.ipv4['mangle'].remove_chain('mangle') + + self.iptables.apply() + + tools.verify_mock_calls(self.execute, expected_calls_and_values) + + def test_add_mangle_rule(self): + self._test_add_mangle_rule_helper(False) + + def test_add_mangle_rule_with_ipv6(self): + self._test_add_mangle_rule_helper(True) + def _test_add_nat_rule_helper(self, use_ipv6): self.iptables = iptables_manager.IptablesManager( root_helper=self.root_helper, @@ -585,14 +687,16 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=RAW_DUMP + nat_dump_mod + FILTER_DUMP, + process_input=(RAW_DUMP + nat_dump_mod + MANGLE_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, + process_input=(RAW_DUMP + nat_dump + MANGLE_DUMP + + FILTER_DUMP), root_helper=self.root_helper), None), ] @@ -653,14 +757,16 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): root_helper=self.root_helper), ''), (mock.call(['iptables-restore', '-c'], - process_input=raw_dump_mod + NAT_DUMP + FILTER_DUMP, + process_input=(raw_dump_mod + NAT_DUMP + MANGLE_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, + process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP + + FILTER_DUMP), root_helper=self.root_helper), None), ] @@ -799,6 +905,10 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): '-v', '-x'], root_helper=self.root_helper), ''), + (mock.call(['iptables', '-t', 'mangle', '-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), @@ -845,6 +955,10 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): '-v', '-x', '-Z'], root_helper=self.root_helper), ''), + (mock.call(['iptables', '-t', 'mangle', '-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), @@ -909,3 +1023,6 @@ class IptablesManagerStateLessTestCase(base.BaseTestCase): def test_nat_not_found(self): self.assertNotIn('nat', self.iptables.ipv4) + + def test_mangle_not_found(self): + self.assertNotIn('mangle', self.iptables.ipv4) diff --git a/neutron/tests/unit/test_security_groups_rpc.py b/neutron/tests/unit/test_security_groups_rpc.py index 865564c05..f9b2f0ffa 100644 --- a/neutron/tests/unit/test_security_groups_rpc.py +++ b/neutron/tests/unit/test_security_groups_rpc.py @@ -1678,6 +1678,25 @@ IPTABLES_ARG = {'bn': iptables_manager.binary_name, 'physdev_mod': PHYSDEV_MOD, 'physdev_is_bridged': PHYSDEV_IS_BRIDGED} +CHAINS_MANGLE = 'FORWARD|INPUT|OUTPUT|POSTROUTING|PREROUTING' +IPTABLES_ARG['chains'] = CHAINS_MANGLE + +IPTABLES_MANGLE = """# Generated by iptables_manager +*mangle +:%(bn)s-(%(chains)s) - [0:0] +:%(bn)s-(%(chains)s) - [0:0] +:%(bn)s-(%(chains)s) - [0:0] +:%(bn)s-(%(chains)s) - [0:0] +:%(bn)s-(%(chains)s) - [0:0] +[0:0] -A PREROUTING -j %(bn)s-PREROUTING +[0:0] -A INPUT -j %(bn)s-INPUT +[0:0] -A FORWARD -j %(bn)s-FORWARD +[0:0] -A OUTPUT -j %(bn)s-OUTPUT +[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING +COMMIT +# Completed by iptables_manager +""" % IPTABLES_ARG + CHAINS_NAT = 'OUTPUT|POSTROUTING|PREROUTING|float-snat|snat' # These Dicts use the same keys as devices2 and devices3 in @@ -2630,7 +2649,8 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): return_value='') self._register_mock_call( ['iptables-restore', '-c'], - process_input=self._regex(IPTABLES_RAW + IPTABLES_NAT + v4_filter), + process_input=self._regex(IPTABLES_RAW + IPTABLES_NAT + + IPTABLES_MANGLE + v4_filter), root_helper=self.root_helper, return_value='') self._register_mock_call( -- 2.45.2