]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Preserve packet:byte counts in iptables_manager.
authorBrian Haley <brian.haley@hp.com>
Thu, 14 Mar 2013 14:35:49 +0000 (10:35 -0400)
committerBrian Haley <brian.haley@hp.com>
Mon, 8 Jul 2013 16:41:21 +0000 (12:41 -0400)
Ported the nova iptables manager code to neutron, so that we
use iptables-save/restore with the -c flag to save/restore
the chains and rules with their packet:byte counts.  All other
changes were ported as well to keep the code as similar as
possible between the two, although they will be different as
I had to fix other bugs found during testing.

Updated tests accordingly to account for new calls and
input/output changes in formatting.

Changed iptables_firewall code to add iptables rules in the same
order that iptables-save will print them: source/dest, protocol,
sport, dport, target; else iptables_manager won't be able
to find them to preserve their [packet:byte] counts.
Tweaked other rules accordingly as necessary.

Fixed a bug introduced in an earlier version of this patch where
_modify_rules() sometimes wouldn't match an existing rule correctly
if not top=true.

Fixes bug 1125393

Change-Id: I858c552d8a7ae24f52f8e8daa05ac37026705773

neutron/agent/linux/iptables_firewall.py
neutron/agent/linux/iptables_manager.py
neutron/tests/unit/test_iptables_firewall.py
neutron/tests/unit/test_iptables_manager.py
neutron/tests/unit/test_security_groups_rpc.py

index 7773ace631e051d89ddd87c9fc76b7c22a436a46..bacdbe6aece04fd21f396e2e1ab9a41475d038e1 100644 (file)
@@ -142,17 +142,17 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
 
         # jump to the security group chain
         device = self._get_device_name(port)
-        jump_rule = ['-m physdev --physdev-is-bridged --%s '
-                     '%s -j $%s' % (self.IPTABLES_DIRECTION[direction],
-                                    device,
-                                    SG_CHAIN)]
+        jump_rule = ['-m physdev --%s %s --physdev-is-bridged '
+                     '-j $%s' % (self.IPTABLES_DIRECTION[direction],
+                                 device,
+                                 SG_CHAIN)]
         self._add_rule_to_chain_v4v6('FORWARD', jump_rule, jump_rule)
 
         # jump to the chain based on the device
-        jump_rule = ['-m physdev --physdev-is-bridged --%s '
-                     '%s -j $%s' % (self.IPTABLES_DIRECTION[direction],
-                                    device,
-                                    chain_name)]
+        jump_rule = ['-m physdev --%s %s --physdev-is-bridged '
+                     '-j $%s' % (self.IPTABLES_DIRECTION[direction],
+                                 device,
+                                 chain_name)]
         self._add_rule_to_chain_v4v6(SG_CHAIN, jump_rule, jump_rule)
 
         if direction == EGRESS_DIRECTION:
@@ -191,7 +191,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
 
     def _ip_spoofing_rule(self, port, ipv4_rules, ipv6_rules):
         #Note(nati) allow dhcp or RA packet
-        ipv4_rules += ['-p udp --sport 68 --dport 67 -j RETURN']
+        ipv4_rules += ['-p udp -m udp --sport 68 --dport 67 -j RETURN']
         ipv6_rules += ['-p icmpv6 -j RETURN']
         ipv4_addresses = []
         ipv6_addresses = []
@@ -207,7 +207,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
 
     def _drop_dhcp_rule(self):
         #Note(nati) Drop dhcp packet from VM
-        return ['-p udp --sport 67 --dport 68 -j DROP']
+        return ['-p udp -m udp --sport 67 --dport 68 -j DROP']
 
     def _add_rule_by_security_group(self, port, direction):
         chain_name = self._port_chain_name(port, direction)
@@ -240,20 +240,24 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
         self._drop_invalid_packets(iptables_rules)
         self._allow_established(iptables_rules)
         for rule in security_group_rules:
-            args = ['-j RETURN']
+            # These arguments MUST be in the format iptables-save will
+            # display them: source/dest, protocol, sport, dport, target
+            # Otherwise the iptables_manager code won't be able to find
+            # them to preserve their [packet:byte] counts.
+            args = self._ip_prefix_arg('s',
+                                       rule.get('source_ip_prefix'))
+            args += self._ip_prefix_arg('d',
+                                        rule.get('dest_ip_prefix'))
             args += self._protocol_arg(rule.get('protocol'))
-            args += self._port_arg('dport',
-                                   rule.get('protocol'),
-                                   rule.get('port_range_min'),
-                                   rule.get('port_range_max'))
             args += self._port_arg('sport',
                                    rule.get('protocol'),
                                    rule.get('source_port_range_min'),
                                    rule.get('source_port_range_max'))
-            args += self._ip_prefix_arg('s',
-                                        rule.get('source_ip_prefix'))
-            args += self._ip_prefix_arg('d',
-                                        rule.get('dest_ip_prefix'))
+            args += self._port_arg('dport',
+                                   rule.get('protocol'),
+                                   rule.get('port_range_min'),
+                                   rule.get('port_range_max'))
+            args += ['-j RETURN']
             iptables_rules += [' '.join(args)]
 
         iptables_rules += ['-j $sg-fallback']
@@ -267,13 +271,18 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
 
     def _allow_established(self, iptables_rules):
         # Allow established connections
-        iptables_rules += ['-m state --state ESTABLISHED,RELATED -j RETURN']
+        iptables_rules += ['-m state --state RELATED,ESTABLISHED -j RETURN']
         return iptables_rules
 
     def _protocol_arg(self, protocol):
-        if protocol:
-            return ['-p', protocol]
-        return []
+        if not protocol:
+            return []
+
+        iptables_rule = ['-p', protocol]
+        # iptables always adds '-m protocol' for udp and tcp
+        if protocol in ['udp', 'tcp']:
+            iptables_rule += ['-m', protocol]
+        return iptables_rule
 
     def _port_arg(self, direction, protocol, port_range_min, port_range_max):
         if not (protocol in ['udp', 'tcp'] and port_range_min):
index 64245dc1fe055b095965e4ec49051d5d25dc8fdc..acd669d59dbdace58175e246e8cf5c5e8dfbded2 100644 (file)
@@ -29,11 +29,18 @@ from neutron.common import utils
 from neutron.openstack.common import log as logging
 
 LOG = logging.getLogger(__name__)
+
+
 # NOTE(vish): Iptables supports chain names of up to 28 characters,  and we
 #             add up to 12 characters to binary_name which is used as a prefix,
 #             so we limit it to 16 characters.
 #             (max_chain_name_length - len('-POSTROUTING') == 16)
-binary_name = os.path.basename(inspect.stack()[-1][1])[:16]
+def get_binary_name():
+    """Grab the name of the binary we're running in."""
+    return os.path.basename(inspect.stack()[-1][1])[:16]
+
+binary_name = get_binary_name()
+
 # A length of a chain name must be less than or equal to 11 characters.
 # <max length of iptables chain name> - (<binary_name> + '-') = 28-(16+1) = 11
 MAX_CHAIN_LEN_WRAP = 11
@@ -83,8 +90,10 @@ class IptablesTable(object):
 
     def __init__(self):
         self.rules = []
+        self.remove_rules = []
         self.chains = set()
         self.unwrapped_chains = set()
+        self.remove_chains = set()
 
     def add_chain(self, name, wrap=True):
         """Adds a named chain to the table.
@@ -141,13 +150,29 @@ class IptablesTable(object):
             return
 
         chain_set.remove(name)
-        self.rules = filter(lambda r: r.chain != name, self.rules)
-        if wrap:
-            jump_snippet = '-j %s-%s' % (binary_name, name)
+
+        if not wrap:
+            # non-wrapped chains and rules need to be dealt with specially,
+            # so we keep a list of them to be iterated over in apply()
+            self.remove_chains.add(name)
+
+            # first, add rules to remove that have a matching chain name
+            self.remove_rules += [r for r in self.rules if r.chain == name]
+
+        # next, remove rules from list that have a matching chain name
+        self.rules = [r for r in self.rules if r.chain != name]
+
+        if not wrap:
+            jump_snippet = '-j %s' % name
+            # next, add rules to remove that have a matching jump chain
+            self.remove_rules += [r for r in self.rules
+                                  if jump_snippet in r.rule]
         else:
-            jump_snippet = '-j %s' % (name,)
+            jump_snippet = '-j %s-%s' % (binary_name, name)
 
-        self.rules = filter(lambda r: jump_snippet not in r.rule, self.rules)
+        # finally, remove rules from list that have a matching jump chain
+        self.rules = [r for r in self.rules
+                      if jump_snippet not in r.rule]
 
     def add_rule(self, chain, rule, wrap=True, top=False):
         """Add a rule to the table.
@@ -185,6 +210,8 @@ class IptablesTable(object):
         chain = get_chain_name(chain, wrap)
         try:
             self.rules.remove(IptablesRule(chain, rule, wrap, top))
+            if not wrap:
+                self.remove_rules.append(IptablesRule(chain, rule, wrap, top))
         except ValueError:
             LOG.warn(_('Tried to remove rule that was not there:'
                        ' %(chain)r %(rule)r %(wrap)r %(top)r'),
@@ -321,35 +348,40 @@ class IptablesManager(object):
             s += [('ip6tables', self.ipv6)]
 
         for cmd, tables in s:
-            for table in tables:
-                args = ['%s-save' % cmd, '-t', table]
-                if self.namespace:
-                    args = ['ip', 'netns', 'exec', self.namespace] + args
-                current_table = (self.execute(args,
-                                 root_helper=self.root_helper))
-                current_lines = current_table.split('\n')
-                new_filter = self._modify_rules(current_lines,
-                                                tables[table])
-                args = ['%s-restore' % (cmd)]
-                if self.namespace:
-                    args = ['ip', 'netns', 'exec', self.namespace] + args
-                self.execute(args,
-                             process_input='\n'.join(new_filter),
-                             root_helper=self.root_helper)
+            args = ['%s-save' % (cmd,), '-c']
+            if self.namespace:
+                args = ['ip', 'netns', 'exec', self.namespace] + args
+            all_tables = self.execute(args, root_helper=self.root_helper)
+            all_lines = all_tables.split('\n')
+            for table_name, table in tables.iteritems():
+                start, end = self._find_table(all_lines, table_name)
+                all_lines[start:end] = self._modify_rules(
+                    all_lines[start:end], table, table_name)
+
+            args = ['%s-restore' % (cmd,), '-c']
+            if self.namespace:
+                args = ['ip', 'netns', 'exec', self.namespace] + args
+            self.execute(args, process_input='\n'.join(all_lines),
+                         root_helper=self.root_helper)
         LOG.debug(_("IPTablesManager.apply completed with success"))
 
-    def _modify_rules(self, current_lines, table, binary=None):
-        unwrapped_chains = table.unwrapped_chains
-        chains = table.chains
-        rules = table.rules
-
-        # Remove any trace of our rules
-        new_filter = filter(lambda line: binary_name
-                            not in line, current_lines)
+    def _find_table(self, lines, table_name):
+        if len(lines) < 3:
+            # length only <2 when fake iptables
+            return (0, 0)
+        try:
+            start = lines.index('*%s' % table_name) - 1
+        except ValueError:
+            # Couldn't find table_name
+            LOG.debug(_('Unable to find table %s'), table_name)
+            return (0, 0)
+        end = lines[start:].index('COMMIT') + start + 2
+        return (start, end)
 
+    def _find_rules_index(self, lines):
         seen_chains = False
         rules_index = 0
-        for rules_index, rule in enumerate(new_filter):
+        for rules_index, rule in enumerate(lines):
             if not seen_chains:
                 if rule.startswith(':'):
                     seen_chains = True
@@ -357,38 +389,173 @@ class IptablesManager(object):
                 if not rule.startswith(':'):
                     break
 
+        if not seen_chains:
+            rules_index = 2
+
+        return rules_index
+
+    def _modify_rules(self, current_lines, table, table_name):
+        unwrapped_chains = table.unwrapped_chains
+        chains = table.chains
+        remove_chains = table.remove_chains
+        rules = table.rules
+        remove_rules = table.remove_rules
+
+        if not current_lines:
+            fake_table = ['# Generated by iptables_manager',
+                          '*' + table_name, 'COMMIT',
+                          '# Completed by iptables_manager']
+            current_lines = fake_table
+
+        # Fill old_filter with any chains or rules we might have added,
+        # they could have a [packet:byte] count we want to preserve.
+        # Fill new_filter with any chains or rules without our name in them.
+        old_filter, new_filter = [], []
+        for line in current_lines:
+            (old_filter if binary_name in line else
+             new_filter).append(line.strip())
+
+        rules_index = self._find_rules_index(new_filter)
+
+        all_chains = [':%s' % name for name in unwrapped_chains]
+        all_chains += [':%s-%s' % (binary_name, name) for name in chains]
+
+        # Iterate through all the chains, trying to find an existing
+        # match.
+        our_chains = []
+        for chain in all_chains:
+            chain_str = str(chain).strip()
+
+            orig_filter = [s for s in old_filter if chain_str in s.strip()]
+            dup_filter = [s for s in new_filter if chain_str in s.strip()]
+            new_filter = [s for s in new_filter if chain_str not in s.strip()]
+
+            # if no old or duplicates, use original chain
+            if orig_filter:
+                # grab the last entry, if there is one
+                old = orig_filter[-1]
+                chain_str = str(old).strip()
+            elif dup_filter:
+                # grab the last entry, if there is one
+                dup = dup_filter[-1]
+                chain_str = str(dup).strip()
+            else:
+                # add-on the [packet:bytes]
+                chain_str += ' - [0:0]'
+
+            our_chains += [chain_str]
+
+        # Iterate through all the rules, trying to find an existing
+        # match.
         our_rules = []
+        bot_rules = []
         for rule in rules:
-            rule_str = str(rule)
+            rule_str = str(rule).strip()
+            # Further down, we weed out duplicates from the bottom of the
+            # list, so here we remove the dupes ahead of time.
+
+            orig_filter = [s for s in old_filter if rule_str in s.strip()]
+            dup_filter = [s for s in new_filter if rule_str in s.strip()]
+            new_filter = [s for s in new_filter if rule_str not in s.strip()]
+
+            # if no old or duplicates, use original rule
+            if orig_filter:
+                # grab the last entry, if there is one
+                old = orig_filter[-1]
+                rule_str = str(old).strip()
+            elif dup_filter:
+                # grab the last entry, if there is one
+                dup = dup_filter[-1]
+                rule_str = str(dup).strip()
+                # backup one index so we write the array correctly
+                rules_index -= 1
+            else:
+                # add-on the [packet:bytes]
+                rule_str = '[0:0] ' + rule_str
+
             if rule.top:
                 # rule.top == True means we want this rule to be at the top.
-                # Further down, we weed out duplicates from the bottom of the
-                # list, so here we remove the dupes ahead of time.
-                new_filter = filter(lambda s: s.strip() != rule_str.strip(),
-                                    new_filter)
-            our_rules += [rule_str]
-
-        new_filter[rules_index:rules_index] = our_rules
-
-        new_filter[rules_index:rules_index] = [':%s - [0:0]' % (name)
-                                               for name in unwrapped_chains]
-        new_filter[rules_index:rules_index] = [':%s-%s - [0:0]' %
-                                               (binary_name, name)
-                                               for name in chains]
+                our_rules += [rule_str]
+            else:
+                bot_rules += [rule_str]
 
-        seen_lines = set()
+        our_rules += bot_rules
 
-        def _weed_out_duplicates(line):
+        new_filter[rules_index:rules_index] = our_rules
+        new_filter[rules_index:rules_index] = our_chains
+
+        def _strip_packets_bytes(line):
+            # strip any [packet:byte] counts at start or end of lines
+            if line.startswith(':'):
+                # it's a chain, for example, ":neutron-billing - [0:0]"
+                line = line.split(':')[1]
+                line = line.split(' - [', 1)[0]
+            elif line.startswith('['):
+                # it's a rule, for example, "[0:0] -A neutron-billing..."
+                line = line.split('] ', 1)[1]
             line = line.strip()
-            if line in seen_lines:
-                return False
-            else:
-                seen_lines.add(line)
-                return True
-
-        # We filter duplicates, letting the *last* occurrence take
-        # precedence.
+            return line
+
+        seen_chains = set()
+
+        def _weed_out_duplicate_chains(line):
+            # ignore [packet:byte] counts at end of lines
+            if line.startswith(':'):
+                line = _strip_packets_bytes(line)
+                if line in seen_chains:
+                    return False
+                else:
+                    seen_chains.add(line)
+
+            # Leave it alone
+            return True
+
+        seen_rules = set()
+
+        def _weed_out_duplicate_rules(line):
+            if line.startswith('['):
+                line = _strip_packets_bytes(line)
+                if line in seen_rules:
+                    return False
+                else:
+                    seen_rules.add(line)
+
+            # Leave it alone
+            return True
+
+        def _weed_out_removes(line):
+            # We need to find exact matches here
+            if line.startswith(':'):
+                line = _strip_packets_bytes(line)
+                for chain in remove_chains:
+                    if chain == line:
+                        remove_chains.remove(chain)
+                        return False
+            elif line.startswith('['):
+                line = _strip_packets_bytes(line)
+                for rule in remove_rules:
+                    rule_str = _strip_packets_bytes(str(rule))
+                    if rule_str == line:
+                        remove_rules.remove(rule)
+                        return False
+
+            # Leave it alone
+            return True
+
+        # We filter duplicates.  Go throught the chains and rules, letting
+        # the *last* occurrence take precendence since it could have a
+        # non-zero [packet:byte] count we want to preserve.  We also filter
+        # out anything in the "remove" list.
         new_filter.reverse()
-        new_filter = filter(_weed_out_duplicates, new_filter)
+        new_filter = [line for line in new_filter
+                      if _weed_out_duplicate_chains(line) and
+                      _weed_out_duplicate_rules(line) and
+                      _weed_out_removes(line)]
         new_filter.reverse()
+
+        # flush lists, just in case we didn't find something
+        remove_chains.clear()
+        for rule in remove_rules:
+            remove_rules.remove(rule)
+
         return new_filter
index 508af2069144b2071c0a4b5558f51cb03adfbe93..e012096e392e0c7833d7aac04684698546048fdc 100644 (file)
@@ -69,46 +69,46 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                  call.add_chain('sg-chain'),
                  call.add_chain('ifake_dev'),
                  call.add_rule('FORWARD',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-out tapfake_dev '
+                               '-m physdev --physdev-out tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $sg-chain'),
                  call.add_rule('sg-chain',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-out tapfake_dev '
+                               '-m physdev --physdev-out tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $ifake_dev'),
                  call.add_rule(
                      'ifake_dev', '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ifake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN'),
+                     '-m state --state RELATED,ESTABLISHED -j RETURN'),
                  call.add_rule('ifake_dev', '-j $sg-fallback'),
                  call.add_chain('ofake_dev'),
                  call.add_rule('FORWARD',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-in tapfake_dev '
+                               '-m physdev --physdev-in tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $sg-chain'),
                  call.add_rule('sg-chain',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-in tapfake_dev '
+                               '-m physdev --physdev-in tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $ofake_dev'),
                  call.add_rule('INPUT',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-in tapfake_dev '
+                               '-m physdev --physdev-in tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $ofake_dev'),
                  call.add_rule(
                      'ofake_dev', '-m mac ! --mac-source ff:ff:ff:ff -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-p udp --sport 68 --dport 67 -j RETURN'),
+                     '-p udp -m udp --sport 68 --dport 67 -j RETURN'),
                  call.add_rule('ofake_dev', '! -s 10.0.0.1 -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-p udp --sport 67 --dport 68 -j DROP'),
+                     '-p udp -m udp --sport 67 --dport 68 -j DROP'),
                  call.add_rule(
                      'ofake_dev', '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN'),
+                     '-m state --state RELATED,ESTABLISHED -j RETURN'),
                  call.add_rule('ofake_dev', '-j $sg-fallback'),
                  call.add_rule('sg-chain', '-j ACCEPT')]
 
@@ -126,7 +126,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv4',
                 'direction': 'ingress',
                 'source_ip_prefix': prefix}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -s %s' % prefix)
+        ingress = call.add_rule('ifake_dev', '-s %s -j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -134,7 +134,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv4',
                 'direction': 'ingress',
                 'protocol': 'tcp'}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p tcp')
+        ingress = call.add_rule('ifake_dev', '-p tcp -m tcp -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -144,7 +144,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'direction': 'ingress',
                 'protocol': 'tcp',
                 'source_ip_prefix': prefix}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p tcp -s %s' % prefix)
+        ingress = call.add_rule('ifake_dev',
+                                '-s %s -p tcp -m tcp -j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -152,7 +153,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv4',
                 'direction': 'ingress',
                 'protocol': 'icmp'}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p icmp')
+        ingress = call.add_rule('ifake_dev', '-p icmp -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -163,7 +164,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'icmp',
                 'source_ip_prefix': prefix}
         ingress = call.add_rule(
-            'ifake_dev', '-j RETURN -p icmp -s %s' % prefix)
+            'ifake_dev', '-s %s -p icmp -j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -173,7 +174,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'tcp',
                 'port_range_min': 10,
                 'port_range_max': 10}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p tcp --dport 10')
+        ingress = call.add_rule('ifake_dev',
+                                '-p tcp -m tcp --dport 10 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -185,7 +187,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'port_range_max': 100}
         ingress = call.add_rule(
             'ifake_dev',
-            '-j RETURN -p tcp -m multiport --dports 10:100')
+            '-p tcp -m tcp -m multiport --dports 10:100 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -199,8 +201,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'source_ip_prefix': prefix}
         ingress = call.add_rule(
             'ifake_dev',
-            '-j RETURN -p tcp -m multiport '
-            '--dports 10:100 -s %s' % prefix)
+            '-s %s -p tcp -m tcp -m multiport --dports 10:100 '
+            '-j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -208,7 +210,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv4',
                 'direction': 'ingress',
                 'protocol': 'udp'}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p udp')
+        ingress = call.add_rule('ifake_dev', '-p udp -m udp -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -218,7 +220,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'direction': 'ingress',
                 'protocol': 'udp',
                 'source_ip_prefix': prefix}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p udp -s %s' % prefix)
+        ingress = call.add_rule('ifake_dev',
+                                '-s %s -p udp -m udp -j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -228,7 +231,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'udp',
                 'port_range_min': 10,
                 'port_range_max': 10}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p udp --dport 10')
+        ingress = call.add_rule('ifake_dev',
+                                '-p udp -m udp --dport 10 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -240,7 +244,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'port_range_max': 100}
         ingress = call.add_rule(
             'ifake_dev',
-            '-j RETURN -p udp -m multiport --dports 10:100')
+            '-p udp -m udp -m multiport --dports 10:100 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -254,8 +258,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'source_ip_prefix': prefix}
         ingress = call.add_rule(
             'ifake_dev',
-            '-j RETURN -p udp -m multiport '
-            '--dports 10:100 -s %s' % prefix)
+            '-s %s -p udp -m udp -m multiport --dports 10:100 '
+            '-j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -271,7 +275,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv4',
                 'direction': 'egress',
                 'source_ip_prefix': prefix}
-        egress = call.add_rule('ofake_dev', '-j RETURN -s %s' % prefix)
+        egress = call.add_rule('ofake_dev', '-s %s -j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -279,7 +283,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv4',
                 'direction': 'egress',
                 'protocol': 'tcp'}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p tcp')
+        egress = call.add_rule('ofake_dev', '-p tcp -m tcp -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -289,7 +293,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'direction': 'egress',
                 'protocol': 'tcp',
                 'source_ip_prefix': prefix}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p tcp -s %s' % prefix)
+        egress = call.add_rule('ofake_dev',
+                               '-s %s -p tcp -m tcp -j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -297,7 +302,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv4',
                 'direction': 'egress',
                 'protocol': 'icmp'}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p icmp')
+        egress = call.add_rule('ofake_dev', '-p icmp -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -308,7 +313,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'icmp',
                 'source_ip_prefix': prefix}
         egress = call.add_rule(
-            'ofake_dev', '-j RETURN -p icmp -s %s' % prefix)
+            'ofake_dev', '-s %s -p icmp -j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -318,7 +323,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'tcp',
                 'port_range_min': 10,
                 'port_range_max': 10}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p tcp --dport 10')
+        egress = call.add_rule('ofake_dev',
+                               '-p tcp -m tcp --dport 10 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -330,7 +336,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'port_range_max': 100}
         egress = call.add_rule(
             'ofake_dev',
-            '-j RETURN -p tcp -m multiport --dports 10:100')
+            '-p tcp -m tcp -m multiport --dports 10:100 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -344,8 +350,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'source_ip_prefix': prefix}
         egress = call.add_rule(
             'ofake_dev',
-            '-j RETURN -p tcp -m multiport '
-            '--dports 10:100 -s %s' % prefix)
+            '-s %s -p tcp -m tcp -m multiport --dports 10:100 '
+            '-j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -353,7 +359,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv4',
                 'direction': 'egress',
                 'protocol': 'udp'}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p udp')
+        egress = call.add_rule('ofake_dev', '-p udp -m udp -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -363,7 +369,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'direction': 'egress',
                 'protocol': 'udp',
                 'source_ip_prefix': prefix}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p udp -s %s' % prefix)
+        egress = call.add_rule('ofake_dev',
+                               '-s %s -p udp -m udp -j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -373,7 +380,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'udp',
                 'port_range_min': 10,
                 'port_range_max': 10}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p udp --dport 10')
+        egress = call.add_rule('ofake_dev',
+                               '-p udp -m udp --dport 10 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -385,7 +393,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'port_range_max': 100}
         egress = call.add_rule(
             'ofake_dev',
-            '-j RETURN -p udp -m multiport --dports 10:100')
+            '-p udp -m udp -m multiport --dports 10:100 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -399,8 +407,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'source_ip_prefix': prefix}
         egress = call.add_rule(
             'ofake_dev',
-            '-j RETURN -p udp -m multiport '
-            '--dports 10:100 -s %s' % prefix)
+            '-s %s -p udp -m udp -m multiport --dports 10:100 '
+            '-j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -416,7 +424,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv6',
                 'direction': 'ingress',
                 'source_ip_prefix': prefix}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -s %s' % prefix)
+        ingress = call.add_rule('ifake_dev', '-s %s -j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -424,7 +432,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv6',
                 'direction': 'ingress',
                 'protocol': 'tcp'}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p tcp')
+        ingress = call.add_rule('ifake_dev', '-p tcp -m tcp -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -434,7 +442,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'direction': 'ingress',
                 'protocol': 'tcp',
                 'source_ip_prefix': prefix}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p tcp -s %s' % prefix)
+        ingress = call.add_rule('ifake_dev',
+                                '-s %s -p tcp -m tcp -j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -444,7 +453,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'tcp',
                 'port_range_min': 10,
                 'port_range_max': 10}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p tcp --dport 10')
+        ingress = call.add_rule('ifake_dev',
+                                '-p tcp -m tcp --dport 10 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -452,7 +462,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv6',
                 'direction': 'ingress',
                 'protocol': 'icmp'}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p icmpv6')
+        ingress = call.add_rule('ifake_dev', '-p icmpv6 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -463,7 +473,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'icmp',
                 'source_ip_prefix': prefix}
         ingress = call.add_rule(
-            'ifake_dev', '-j RETURN -p icmpv6 -s %s' % prefix)
+            'ifake_dev', '-s %s -p icmpv6 -j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -475,7 +485,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'port_range_max': 100}
         ingress = call.add_rule(
             'ifake_dev',
-            '-j RETURN -p tcp -m multiport --dports 10:100')
+            '-p tcp -m tcp -m multiport --dports 10:100 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -489,8 +499,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'source_ip_prefix': prefix}
         ingress = call.add_rule(
             'ifake_dev',
-            '-j RETURN -p tcp -m multiport '
-            '--dports 10:100 -s %s' % prefix)
+            '-s %s -p tcp -m tcp -m multiport --dports 10:100 '
+            '-j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -498,7 +508,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv6',
                 'direction': 'ingress',
                 'protocol': 'udp'}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p udp')
+        ingress = call.add_rule('ifake_dev', '-p udp -m udp -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -508,7 +518,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'direction': 'ingress',
                 'protocol': 'udp',
                 'source_ip_prefix': prefix}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p udp -s %s' % prefix)
+        ingress = call.add_rule('ifake_dev',
+                                '-s %s -p udp -m udp -j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -518,7 +529,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'udp',
                 'port_range_min': 10,
                 'port_range_max': 10}
-        ingress = call.add_rule('ifake_dev', '-j RETURN -p udp --dport 10')
+        ingress = call.add_rule('ifake_dev',
+                                '-p udp -m udp --dport 10 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -530,7 +542,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'port_range_max': 100}
         ingress = call.add_rule(
             'ifake_dev',
-            '-j RETURN -p udp -m multiport --dports 10:100')
+            '-p udp -m udp -m multiport --dports 10:100 -j RETURN')
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -544,8 +556,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'source_ip_prefix': prefix}
         ingress = call.add_rule(
             'ifake_dev',
-            '-j RETURN -p udp -m multiport '
-            '--dports 10:100 -s %s' % prefix)
+            '-s %s -p udp -m udp -m multiport --dports 10:100 '
+            '-j RETURN' % prefix)
         egress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -561,7 +573,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv6',
                 'direction': 'egress',
                 'source_ip_prefix': prefix}
-        egress = call.add_rule('ofake_dev', '-j RETURN -s %s' % prefix)
+        egress = call.add_rule('ofake_dev', '-s %s -j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -569,7 +581,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv6',
                 'direction': 'egress',
                 'protocol': 'tcp'}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p tcp')
+        egress = call.add_rule('ofake_dev', '-p tcp -m tcp -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -579,7 +591,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'direction': 'egress',
                 'protocol': 'tcp',
                 'source_ip_prefix': prefix}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p tcp -s %s' % prefix)
+        egress = call.add_rule('ofake_dev',
+                               '-s %s -p tcp -m tcp -j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -587,7 +600,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv6',
                 'direction': 'egress',
                 'protocol': 'icmp'}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p icmpv6')
+        egress = call.add_rule('ofake_dev', '-p icmpv6 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -598,7 +611,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'icmp',
                 'source_ip_prefix': prefix}
         egress = call.add_rule(
-            'ofake_dev', '-j RETURN -p icmpv6 -s %s' % prefix)
+            'ofake_dev', '-s %s -p icmpv6 -j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -608,7 +621,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'tcp',
                 'port_range_min': 10,
                 'port_range_max': 10}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p tcp --dport 10')
+        egress = call.add_rule('ofake_dev',
+                               '-p tcp -m tcp --dport 10 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -620,7 +634,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'port_range_max': 100}
         egress = call.add_rule(
             'ofake_dev',
-            '-j RETURN -p tcp -m multiport --dports 10:100')
+            '-p tcp -m tcp -m multiport --dports 10:100 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -634,8 +648,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'source_ip_prefix': prefix}
         egress = call.add_rule(
             'ofake_dev',
-            '-j RETURN -p tcp -m multiport '
-            '--dports 10:100 -s %s' % prefix)
+            '-s %s -p tcp -m tcp -m multiport --dports 10:100 '
+            '-j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -643,7 +657,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         rule = {'ethertype': 'IPv6',
                 'direction': 'egress',
                 'protocol': 'udp'}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p udp')
+        egress = call.add_rule('ofake_dev', '-p udp -m udp -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -653,7 +667,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'direction': 'egress',
                 'protocol': 'udp',
                 'source_ip_prefix': prefix}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p udp -s %s' % prefix)
+        egress = call.add_rule('ofake_dev',
+                               '-s %s -p udp -m udp -j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -663,7 +678,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'protocol': 'udp',
                 'port_range_min': 10,
                 'port_range_max': 10}
-        egress = call.add_rule('ofake_dev', '-j RETURN -p udp --dport 10')
+        egress = call.add_rule('ofake_dev',
+                               '-p udp -m udp --dport 10 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -675,7 +691,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'port_range_max': 100}
         egress = call.add_rule(
             'ofake_dev',
-            '-j RETURN -p udp -m multiport --dports 10:100')
+            '-p udp -m udp -m multiport --dports 10:100 -j RETURN')
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -689,8 +705,8 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                 'source_ip_prefix': prefix}
         egress = call.add_rule(
             'ofake_dev',
-            '-j RETURN -p udp -m multiport '
-            '--dports 10:100 -s %s' % prefix)
+            '-s %s -p udp -m udp -m multiport --dports 10:100 '
+            '-j RETURN' % prefix)
         ingress = None
         self._test_prepare_port_filter(rule, ingress, egress)
 
@@ -704,7 +720,7 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         filter_inst = self.v4filter_inst
         dhcp_rule = call.add_rule(
             'ofake_dev',
-            '-p udp --sport 68 --dport 67 -j RETURN')
+            '-p udp -m udp --sport 68 --dport 67 -j RETURN')
 
         if ethertype == 'IPv6':
             filter_inst = self.v6filter_inst
@@ -719,18 +735,18 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                  call.add_chain('sg-chain'),
                  call.add_chain('ifake_dev'),
                  call.add_rule('FORWARD',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-out tapfake_dev '
+                               '-m physdev --physdev-out tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $sg-chain'),
                  call.add_rule('sg-chain',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-out tapfake_dev '
+                               '-m physdev --physdev-out tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $ifake_dev'),
                  call.add_rule(
                      'ifake_dev', '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ifake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN')]
+                     '-m state --state RELATED,ESTABLISHED -j RETURN')]
 
         if ingress_expected_call:
             calls.append(ingress_expected_call)
@@ -738,16 +754,16 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         calls += [call.add_rule('ifake_dev', '-j $sg-fallback'),
                   call.add_chain('ofake_dev'),
                   call.add_rule('FORWARD',
-                                '-m physdev --physdev-is-bridged '
-                                '--physdev-in tapfake_dev '
+                                '-m physdev --physdev-in tapfake_dev '
+                                '--physdev-is-bridged '
                                 '-j $sg-chain'),
                   call.add_rule('sg-chain',
-                                '-m physdev --physdev-is-bridged '
-                                '--physdev-in tapfake_dev '
+                                '-m physdev --physdev-in tapfake_dev '
+                                '--physdev-is-bridged '
                                 '-j $ofake_dev'),
                   call.add_rule('INPUT',
-                                '-m physdev --physdev-is-bridged '
-                                '--physdev-in tapfake_dev '
+                                '-m physdev --physdev-in tapfake_dev '
+                                '--physdev-is-bridged '
                                 '-j $ofake_dev'),
                   call.add_rule(
                       'ofake_dev',
@@ -758,13 +774,13 @@ class IptablesFirewallTestCase(base.BaseTestCase):
         if ethertype == 'IPv4':
             calls.append(call.add_rule(
                 'ofake_dev',
-                '-p udp --sport 67 --dport 68 -j DROP'))
+                '-p udp -m udp --sport 67 --dport 68 -j DROP'))
 
         calls += [call.add_rule(
                   'ofake_dev', '-m state --state INVALID -j DROP'),
                   call.add_rule(
                   'ofake_dev',
-                  '-m state --state ESTABLISHED,RELATED -j RETURN')]
+                  '-m state --state RELATED,ESTABLISHED -j RETURN')]
 
         if egress_expected_call:
             calls.append(egress_expected_call)
@@ -792,49 +808,49 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                  call.add_chain('ifake_dev'),
                  call.add_rule(
                      'FORWARD',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-out tapfake_dev -j $sg-chain'),
+                     '-m physdev --physdev-out tapfake_dev '
+                     '--physdev-is-bridged -j $sg-chain'),
                  call.add_rule(
                      'sg-chain',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-out tapfake_dev -j $ifake_dev'),
+                     '-m physdev --physdev-out tapfake_dev '
+                     '--physdev-is-bridged -j $ifake_dev'),
                  call.add_rule(
                      'ifake_dev', '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ifake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN'),
+                     '-m state --state RELATED,ESTABLISHED -j RETURN'),
                  call.add_rule('ifake_dev', '-j RETURN'),
                  call.add_rule('ifake_dev', '-j $sg-fallback'),
                  call.add_chain('ofake_dev'),
                  call.add_rule(
                      'FORWARD',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-in tapfake_dev -j $sg-chain'),
+                     '-m physdev --physdev-in tapfake_dev '
+                     '--physdev-is-bridged -j $sg-chain'),
                  call.add_rule(
                      'sg-chain',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-in tapfake_dev -j $ofake_dev'),
+                     '-m physdev --physdev-in tapfake_dev '
+                     '--physdev-is-bridged -j $ofake_dev'),
                  call.add_rule(
                      'INPUT',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-in tapfake_dev -j $ofake_dev'),
+                     '-m physdev --physdev-in tapfake_dev '
+                     '--physdev-is-bridged -j $ofake_dev'),
                  call.add_rule(
                      'ofake_dev',
                      '-m mac ! --mac-source ff:ff:ff:ff -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-p udp --sport 68 --dport 67 -j RETURN'),
+                     '-p udp -m udp --sport 68 --dport 67 -j RETURN'),
                  call.add_rule(
                      'ofake_dev',
                      '! -s 10.0.0.1 -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-p udp --sport 67 --dport 68 -j DROP'),
+                     '-p udp -m udp --sport 67 --dport 68 -j DROP'),
                  call.add_rule(
                      'ofake_dev', '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN'),
+                     '-m state --state RELATED,ESTABLISHED -j RETURN'),
                  call.add_rule('ofake_dev', '-j $sg-fallback'),
                  call.add_rule('sg-chain', '-j ACCEPT'),
                  call.ensure_remove_chain('ifake_dev'),
@@ -845,46 +861,48 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                  call.add_chain('ifake_dev'),
                  call.add_rule(
                      'FORWARD',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-out tapfake_dev -j $sg-chain'),
+                     '-m physdev --physdev-out tapfake_dev '
+                     '--physdev-is-bridged -j $sg-chain'),
                  call.add_rule(
                      'sg-chain',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-out tapfake_dev -j $ifake_dev'),
+                     '-m physdev --physdev-out tapfake_dev '
+                     '--physdev-is-bridged -j $ifake_dev'),
                  call.add_rule(
                      'ifake_dev',
                      '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ifake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN'),
+                     '-m state --state RELATED,ESTABLISHED -j RETURN'),
                  call.add_rule('ifake_dev', '-j $sg-fallback'),
                  call.add_chain('ofake_dev'),
                  call.add_rule(
                      'FORWARD',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-in tapfake_dev -j $sg-chain'),
+                     '-m physdev --physdev-in tapfake_dev '
+                     '--physdev-is-bridged -j $sg-chain'),
                  call.add_rule(
                      'sg-chain',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-in tapfake_dev -j $ofake_dev'),
+                     '-m physdev --physdev-in tapfake_dev '
+                     '--physdev-is-bridged -j $ofake_dev'),
                  call.add_rule(
                      'INPUT',
-                     '-m physdev --physdev-is-bridged '
-                     '--physdev-in tapfake_dev -j $ofake_dev'),
+                     '-m physdev --physdev-in tapfake_dev '
+                     '--physdev-is-bridged -j $ofake_dev'),
                  call.add_rule(
                      'ofake_dev',
                      '-m mac ! --mac-source ff:ff:ff:ff -j DROP'),
                  call.add_rule(
-                     'ofake_dev', '-p udp --sport 68 --dport 67 -j RETURN'),
+                     'ofake_dev',
+                     '-p udp -m udp --sport 68 --dport 67 -j RETURN'),
                  call.add_rule(
                      'ofake_dev', '! -s 10.0.0.1 -j DROP'),
                  call.add_rule(
-                     'ofake_dev', '-p udp --sport 67 --dport 68 -j DROP'),
+                     'ofake_dev',
+                     '-p udp -m udp --sport 67 --dport 68 -j DROP'),
                  call.add_rule(
                      'ofake_dev', '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN'),
+                     '-m state --state RELATED,ESTABLISHED -j RETURN'),
                  call.add_rule('ofake_dev', '-j RETURN'),
                  call.add_rule('ofake_dev', '-j $sg-fallback'),
                  call.add_rule('sg-chain', '-j ACCEPT'),
@@ -928,31 +946,31 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                  call.add_chain('sg-chain'),
                  call.add_chain('ifake_dev'),
                  call.add_rule('FORWARD',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-out tapfake_dev '
+                               '-m physdev --physdev-out tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $sg-chain'),
                  call.add_rule('sg-chain',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-out tapfake_dev '
+                               '-m physdev --physdev-out tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $ifake_dev'),
                  call.add_rule(
                      'ifake_dev', '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ifake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN'),
+                     '-m state --state RELATED,ESTABLISHED -j RETURN'),
                  call.add_rule('ifake_dev', '-j $sg-fallback'),
                  call.add_chain('ofake_dev'),
                  call.add_rule('FORWARD',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-in tapfake_dev '
+                               '-m physdev --physdev-in tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $sg-chain'),
                  call.add_rule('sg-chain',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-in tapfake_dev '
+                               '-m physdev --physdev-in tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $ofake_dev'),
                  call.add_rule('INPUT',
-                               '-m physdev --physdev-is-bridged '
-                               '--physdev-in tapfake_dev '
+                               '-m physdev --physdev-in tapfake_dev '
+                               '--physdev-is-bridged '
                                '-j $ofake_dev'),
                  call.add_chain('sfake_dev'),
                  call.add_rule('sfake_dev', '-s 10.0.0.1 -j RETURN'),
@@ -962,16 +980,16 @@ class IptablesFirewallTestCase(base.BaseTestCase):
                      'ofake_dev', '-m mac ! --mac-source ff:ff:ff:ff -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-p udp --sport 68 --dport 67 -j RETURN'),
+                     '-p udp -m udp --sport 68 --dport 67 -j RETURN'),
                  call.add_rule('ofake_dev', '-j $sfake_dev'),
                  call.add_rule(
                      'ofake_dev',
-                     '-p udp --sport 67 --dport 68 -j DROP'),
+                     '-p udp -m udp --sport 67 --dport 68 -j DROP'),
                  call.add_rule(
                      'ofake_dev', '-m state --state INVALID -j DROP'),
                  call.add_rule(
                      'ofake_dev',
-                     '-m state --state ESTABLISHED,RELATED -j RETURN'),
+                     '-m state --state RELATED,ESTABLISHED -j RETURN'),
                  call.add_rule('ofake_dev', '-j $sg-fallback'),
                  call.add_rule('sg-chain', '-j ACCEPT')]
         self.v4filter_inst.assert_has_calls(calls)
index 0adf4509fd47f4e6536ab490219fde1c88128aa0..8fd64056334539e03611eaf9900bed7531d8d28b 100644 (file)
@@ -26,6 +26,43 @@ from neutron.agent.linux import iptables_manager
 from neutron.tests import base
 
 
+IPTABLES_ARG = {'bn': iptables_manager.binary_name}
+
+NAT_DUMP = ('# Generated by iptables_manager\n'
+            '*nat\n'
+            ':neutron-postrouting-bottom - [0:0]\n'
+            ':%(bn)s-OUTPUT - [0:0]\n'
+            ':%(bn)s-snat - [0:0]\n'
+            ':%(bn)s-PREROUTING - [0:0]\n'
+            ':%(bn)s-float-snat - [0:0]\n'
+            ':%(bn)s-POSTROUTING - [0:0]\n'
+            '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
+            '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
+            '[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n'
+            '[0:0] -A POSTROUTING -j neutron-postrouting-bottom\n'
+            '[0:0] -A neutron-postrouting-bottom -j %(bn)s-snat\n'
+            '[0:0] -A %(bn)s-snat -j '
+            '%(bn)s-float-snat\n'
+            'COMMIT\n'
+            '# Completed by iptables_manager\n' % IPTABLES_ARG)
+
+FILTER_DUMP = ('# Generated by iptables_manager\n'
+               '*filter\n'
+               ':neutron-filter-top - [0:0]\n'
+               ':%(bn)s-FORWARD - [0:0]\n'
+               ':%(bn)s-INPUT - [0:0]\n'
+               ':%(bn)s-local - [0:0]\n'
+               ':%(bn)s-OUTPUT - [0:0]\n'
+               '[0:0] -A FORWARD -j neutron-filter-top\n'
+               '[0:0] -A OUTPUT -j neutron-filter-top\n'
+               '[0:0] -A neutron-filter-top -j %(bn)s-local\n'
+               '[0:0] -A INPUT -j %(bn)s-INPUT\n'
+               '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
+               '[0:0] -A FORWARD -j %(bn)s-FORWARD\n'
+               'COMMIT\n'
+               '# Completed by iptables_manager\n' % IPTABLES_ARG)
+
+
 class IptablesManagerStateFulTestCase(base.BaseTestCase):
 
     def setUp(self):
@@ -41,7 +78,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
         self.assertEqual(iptables_manager.binary_name,
                          os.path.basename(inspect.stack()[-1][1])[:16])
 
-    def test_get_chanin_name(self):
+    def test_get_chain_name(self):
         name = '0123456789' * 5
         # 28 chars is the maximum length of iptables chain name.
         self.assertEqual(iptables_manager.get_chain_name(name, wrap=False),
@@ -52,56 +89,36 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
                          name[:11])
 
     def test_add_and_remove_chain(self):
-        bn = iptables_manager.binary_name
-        self.iptables.execute(['iptables-save', '-t', 'filter'],
-                              root_helper=self.root_helper).AndReturn('')
-
-        nat_dump = (':%s-OUTPUT - [0:0]\n:%s-snat - [0:0]\n:%s-PREROUTING -'
-                    ' [0:0]\n:%s-float-snat - [0:0]\n:%s-POSTROUTING - [0:0]'
-                    '\n:neutron-postrouting-bottom - [0:0]\n-A PREROUTING -j'
-                    ' %s-PREROUTING\n-A OUTPUT -j %s-OUTPUT\n-A POSTROUTING '
-                    '-j %s-POSTROUTING\n-A POSTROUTING -j neutron-postroutin'
-                    'g-bottom\n-A neutron-postrouting-bottom -j %s-snat\n-A '
-                    '%s-snat -j %s-float-snat\n' % (bn, bn, bn, bn, bn, bn,
-                    bn, bn, bn, bn, bn))
-
-        self.iptables.execute(['iptables-restore'],
-                              process_input=(':%s-FORWARD - [0:0]\n:%s-INPUT'
-                              ' - [0:0]\n:%s-local - [0:0]\n:%s-filter - [0:'
-                              '0]\n:%s-OUTPUT - [0:0]\n:neutron-filter-top -'
-                              ' [0:0]\n-A FORWARD -j neutron-filter-top\n-A '
-                              'OUTPUT -j neutron-filter-top\n-A neutron-filt'
-                              'er-top -j %s-local\n-A INPUT -j %s-INPUT\n-A '
-                              'OUTPUT -j %s-OUTPUT\n-A FORWARD -j %s-FORWARD'
-                              '\n' % (bn, bn, bn, bn, bn, bn, bn, bn, bn)
-                              ), root_helper=self.root_helper).AndReturn(None)
-
-        self.iptables.execute(['iptables-save', '-t', 'nat'],
+        self.iptables.execute(['iptables-save', '-c'],
                               root_helper=self.root_helper).AndReturn('')
 
-        self.iptables.execute(['iptables-restore'],
-                              process_input=nat_dump,
+        filter_dump_mod = ('# Generated by iptables_manager\n'
+                           '*filter\n'
+                           ':neutron-filter-top - [0:0]\n'
+                           ':%(bn)s-FORWARD - [0:0]\n'
+                           ':%(bn)s-INPUT - [0:0]\n'
+                           ':%(bn)s-local - [0:0]\n'
+                           ':%(bn)s-filter - [0:0]\n'
+                           ':%(bn)s-OUTPUT - [0:0]\n'
+                           '[0:0] -A FORWARD -j neutron-filter-top\n'
+                           '[0:0] -A OUTPUT -j neutron-filter-top\n'
+                           '[0:0] -A neutron-filter-top -j %(bn)s-local\n'
+                           '[0:0] -A INPUT -j %(bn)s-INPUT\n'
+                           '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
+                           '[0:0] -A FORWARD -j %(bn)s-FORWARD\n'
+                           'COMMIT\n'
+                           '# Completed by iptables_manager\n'
+                           % IPTABLES_ARG)
+
+        self.iptables.execute(['iptables-restore', '-c'],
+                              process_input=NAT_DUMP + filter_dump_mod,
                               root_helper=self.root_helper).AndReturn(None)
 
-        self.iptables.execute(['iptables-save', '-t', 'filter'],
+        self.iptables.execute(['iptables-save', '-c'],
                               root_helper=self.root_helper).AndReturn('')
 
-        self.iptables.execute(['iptables-restore'],
-                              process_input=(':%s-FORWARD - [0:0]\n:%s-INPUT'
-                              ' - [0:0]\n:%s-local - [0:0]\n:%s-OUTPUT - [0:'
-                              '0]\n:neutron-filter-top - [0:0]\n-A FORWARD -'
-                              'j neutron-filter-top\n-A OUTPUT -j neutron-fi'
-                              'lter-top\n-A neutron-filter-top -j %s-local\n'
-                              '-A INPUT -j %s-INPUT\n-A OUTPUT -j %s-OUTPUT'
-                              '\n-A FORWARD -j %s-FORWARD\n' % (bn, bn, bn, bn,
-                              bn, bn, bn, bn)), root_helper=self.root_helper
-                              ).AndReturn(None)
-
-        self.iptables.execute(['iptables-save', '-t', 'nat'],
-                              root_helper=self.root_helper).AndReturn('')
-
-        self.iptables.execute(['iptables-restore'],
-                              process_input=nat_dump,
+        self.iptables.execute(['iptables-restore', '-c'],
+                              process_input=NAT_DUMP + FILTER_DUMP,
                               root_helper=self.root_helper).AndReturn(None)
 
         self.mox.ReplayAll()
@@ -115,144 +132,122 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
         self.mox.VerifyAll()
 
     def test_add_filter_rule(self):
-        bn = iptables_manager.binary_name
-        self.iptables.execute(['iptables-save', '-t', 'filter'],
-                              root_helper=self.root_helper).AndReturn('')
-
-        nat_dump = (':%s-OUTPUT - [0:0]\n:%s-snat - [0:0]\n:%s-PREROUTING -'
-                    ' [0:0]\n:%s-float-snat - [0:0]\n:%s-POSTROUTING - [0:0]'
-                    '\n:neutron-postrouting-bottom - [0:0]\n-A PREROUTING -j'
-                    ' %s-PREROUTING\n-A OUTPUT -j %s-OUTPUT\n-A POSTROUTING '
-                    '-j %s-POSTROUTING\n-A POSTROUTING -j neutron-postroutin'
-                    'g-bottom\n-A neutron-postrouting-bottom -j %s-snat\n-A '
-                    '%s-snat -j %s-float-snat\n' % (bn, bn, bn, bn, bn, bn,
-                    bn, bn, bn, bn, bn))
-
-        self.iptables.execute(['iptables-restore'],
-                              process_input=(':%s-FORWARD - [0:0]\n:%s-INPUT'
-                              ' - [0:0]\n:%s-local - [0:0]\n:%s-filter - [0:'
-                              '0]\n:%s-OUTPUT - [0:0]\n:neutron-filter-top -'
-                              ' [0:0]\n-A FORWARD -j neutron-filter-top\n-A '
-                              'OUTPUT -j neutron-filter-top\n-A neutron-filt'
-                              'er-top -j %s-local\n-A INPUT -j %s-INPUT\n-A '
-                              'OUTPUT -j %s-OUTPUT\n-A FORWARD -j %s-FORWARD'
-                              '\n-A %s-filter -j DROP\n-A %s-INPUT -s 0/0 -d'
-                              ' 192.168.0.2 -j %s-filter\n' % (bn, bn, bn, bn,
-                              bn, bn, bn, bn, bn, bn, bn, bn)),
-                              root_helper=self.root_helper).AndReturn(None)
-
-        self.iptables.execute(['iptables-save', '-t', 'nat'],
+        self.iptables.execute(['iptables-save', '-c'],
                               root_helper=self.root_helper).AndReturn('')
 
-        self.iptables.execute(['iptables-restore'],
-                              process_input=nat_dump,
+        filter_dump_mod = ('# Generated by iptables_manager\n'
+                           '*filter\n'
+                           ':neutron-filter-top - [0:0]\n'
+                           ':%(bn)s-FORWARD - [0:0]\n'
+                           ':%(bn)s-INPUT - [0:0]\n'
+                           ':%(bn)s-local - [0:0]\n'
+                           ':%(bn)s-filter - [0:0]\n'
+                           ':%(bn)s-OUTPUT - [0:0]\n'
+                           '[0:0] -A FORWARD -j neutron-filter-top\n'
+                           '[0:0] -A OUTPUT -j neutron-filter-top\n'
+                           '[0:0] -A neutron-filter-top -j %(bn)s-local\n'
+                           '[0:0] -A INPUT -j %(bn)s-INPUT\n'
+                           '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
+                           '[0:0] -A FORWARD -j %(bn)s-FORWARD\n'
+                           '[0:0] -A %(bn)s-filter -j DROP\n'
+                           '[0:0] -A %(bn)s-INPUT -s 0/0 -d 192.168.0.2 -j '
+                           '%(bn)s-filter\n'
+                           'COMMIT\n'
+                           '# Completed by iptables_manager\n'
+                           % IPTABLES_ARG)
+
+        self.iptables.execute(['iptables-restore', '-c'],
+                              process_input=NAT_DUMP + filter_dump_mod,
                               root_helper=self.root_helper).AndReturn(None)
 
-        self.iptables.execute(['iptables-save', '-t', 'filter'],
+        self.iptables.execute(['iptables-save', '-c'],
                               root_helper=self.root_helper).AndReturn('')
 
-        self.iptables.execute(['iptables-restore'],
-                              process_input=(':%s-FORWARD - [0:0]\n:%s-INPUT -'
-                              ' [0:0]\n:%s-local - [0:0]\n:%s-OUTPUT - [0:0]\n'
-                              ':neutron-filter-top - [0:0]\n-A FORWARD -j neut'
-                              'ron-filter-top\n-A OUTPUT -j neutron-filter-top'
-                              '\n-A neutron-filter-top -j %s-local\n-A INPUT -'
-                              'j %s-INPUT\n-A OUTPUT -j %s-OUTPUT\n-A FORWARD '
-                              '-j %s-FORWARD\n' % (bn, bn, bn, bn, bn, bn, bn,
-                              bn)), root_helper=self.root_helper
+        self.iptables.execute(['iptables-restore', '-c'],
+                              process_input=NAT_DUMP + FILTER_DUMP,
+                              root_helper=self.root_helper
                               ).AndReturn(None)
 
-        self.iptables.execute(['iptables-save', '-t', 'nat'],
-                              root_helper=self.root_helper).AndReturn('')
-
-        self.iptables.execute(['iptables-restore'],
-                              process_input=nat_dump,
-                              root_helper=self.root_helper).AndReturn(None)
-
         self.mox.ReplayAll()
 
         self.iptables.ipv4['filter'].add_chain('filter')
         self.iptables.ipv4['filter'].add_rule('filter', '-j DROP')
         self.iptables.ipv4['filter'].add_rule('INPUT',
                                               '-s 0/0 -d 192.168.0.2 -j'
-                                              ' %s-filter' %
-                                              (iptables_manager.binary_name))
+                                              ' %(bn)s-filter' % IPTABLES_ARG)
         self.iptables.apply()
 
         self.iptables.ipv4['filter'].remove_rule('filter', '-j DROP')
         self.iptables.ipv4['filter'].remove_rule('INPUT',
                                                  '-s 0/0 -d 192.168.0.2 -j'
-                                                 ' %s-filter' %
-                                                 (iptables_manager.
-                                                  binary_name))
+                                                 ' %(bn)s-filter'
+                                                 % IPTABLES_ARG)
         self.iptables.ipv4['filter'].remove_chain('filter')
 
         self.iptables.apply()
         self.mox.VerifyAll()
 
     def test_add_nat_rule(self):
-        bn = iptables_manager.binary_name
-
-        filter_dump = (':%s-FORWARD - [0:0]\n:%s-INPUT - [0:0]\n:%s-local - '
-                       '[0:0]\n:%s-OUTPUT - [0:0]\n:neutron-filter-top - [0:'
-                       '0]\n-A FORWARD -j neutron-filter-top\n-A OUTPUT -j n'
-                       'eutron-filter-top\n-A neutron-filter-top -j %s-local'
-                       '\n-A INPUT -j %s-INPUT\n-A OUTPUT -j %s-OUTPUT\n-A F'
-                       'ORWARD -j %s-FORWARD\n' % (bn, bn, bn, bn, bn,
-                       bn, bn, bn))
-
-        self.iptables.execute(['iptables-save', '-t', 'filter'],
-                              root_helper=self.root_helper).AndReturn('')
-
-        self.iptables.execute(['iptables-restore'],
-                              process_input=filter_dump,
-                              root_helper=self.root_helper).AndReturn(None)
-
-        self.iptables.execute(['iptables-save', '-t', 'nat'],
+        nat_dump = ('# Generated by iptables_manager\n'
+                    '*nat\n'
+                    ':neutron-postrouting-bottom - [0:0]\n'
+                    ':%(bn)s-float-snat - [0:0]\n'
+                    ':%(bn)s-POSTROUTING - [0:0]\n'
+                    ':%(bn)s-PREROUTING - [0:0]\n'
+                    ':%(bn)s-OUTPUT - [0:0]\n'
+                    ':%(bn)s-snat - [0:0]\n'
+                    '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
+                    '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
+                    '[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n'
+                    '[0:0] -A POSTROUTING -j neutron-postrouting-bottom\n'
+                    '[0:0] -A neutron-postrouting-bottom -j %(bn)s-snat\n'
+                    '[0:0] -A %(bn)s-snat -j %(bn)s-float-snat\n'
+                    'COMMIT\n'
+                    '# Completed by iptables_manager\n'
+                    % IPTABLES_ARG)
+
+        nat_dump_mod = ('# Generated by iptables_manager\n'
+                        '*nat\n'
+                        ':neutron-postrouting-bottom - [0:0]\n'
+                        ':%(bn)s-float-snat - [0:0]\n'
+                        ':%(bn)s-POSTROUTING - [0:0]\n'
+                        ':%(bn)s-PREROUTING - [0:0]\n'
+                        ':%(bn)s-nat - [0:0]\n'
+                        ':%(bn)s-OUTPUT - [0:0]\n'
+                        ':%(bn)s-snat - [0:0]\n'
+                        '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
+                        '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
+                        '[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n'
+                        '[0:0] -A POSTROUTING -j neutron-postrouting-bottom\n'
+                        '[0:0] -A neutron-postrouting-bottom -j %(bn)s-snat\n'
+                        '[0:0] -A %(bn)s-snat -j %(bn)s-float-snat\n'
+                        '[0:0] -A %(bn)s-PREROUTING -d 192.168.0.3 -j '
+                        '%(bn)s-nat\n'
+                        '[0:0] -A %(bn)s-nat -p tcp --dport 8080 -j '
+                        'REDIRECT --to-port 80\n'
+                        'COMMIT\n'
+                        '# Completed by iptables_manager\n'
+                        % IPTABLES_ARG)
+
+        self.iptables.execute(['iptables-save', '-c'],
                               root_helper=self.root_helper).AndReturn('')
 
-        self.iptables.execute(['iptables-restore'],
-                              process_input=(':%s-float-snat - [0:0]\n:%s-POS'
-                              'TROUTING - [0:0]\n:%s-PREROUTING - [0:0]\n:%s-'
-                              'nat - [0:0]\n:%s-OUTPUT - [0:0]\n:%s-snat - [0'
-                              ':0]\n:neutron-postrouting-bottom - [0:0]\n-A P'
-                              'REROUTING -j %s-PREROUTING\n-A OUTPUT -j %s-OU'
-                              'TPUT\n-A POSTROUTING -j %s-POSTROUTING\n-A POS'
-                              'TROUTING -j neutron-postrouting-bottom\n-A neu'
-                              'tron-postrouting-bottom -j %s-snat\n-A %s-snat'
-                              ' -j %s-float-snat\n-A %s-PREROUTING -d 192.168'
-                              '.0.3 -j %s-nat\n-A %s-nat -p tcp --dport 8080 '
-                              '-j REDIRECT --to-port 80\n' % (bn, bn, bn, bn,
-                              bn, bn, bn, bn, bn, bn, bn, bn, bn, bn, bn)),
+        self.iptables.execute(['iptables-restore', '-c'],
+                              process_input=nat_dump_mod + FILTER_DUMP,
                               root_helper=self.root_helper).AndReturn(None)
 
-        self.iptables.execute(['iptables-save', '-t', 'filter'],
+        self.iptables.execute(['iptables-save', '-c'],
                               root_helper=self.root_helper).AndReturn('')
 
-        self.iptables.execute(['iptables-restore'],
-                              process_input=filter_dump,
+        self.iptables.execute(['iptables-restore', '-c'],
+                              process_input=nat_dump + FILTER_DUMP,
                               root_helper=self.root_helper).AndReturn(None)
 
-        self.iptables.execute(['iptables-save', '-t', 'nat'],
-                              root_helper=self.root_helper).AndReturn('')
-
-        self.iptables.execute(['iptables-restore'],
-                              process_input=(':%s-float-snat - [0:0]\n:%s-POST'
-                              'ROUTING - [0:0]\n:%s-PREROUTING - [0:0]\n:%s-OU'
-                              'TPUT - [0:0]\n:%s-snat - [0:0]\n:neutron-postro'
-                              'uting-bottom - [0:0]\n-A PREROUTING -j %s-PRERO'
-                              'UTING\n-A OUTPUT -j %s-OUTPUT\n-A POSTROUTING -'
-                              'j %s-POSTROUTING\n-A POSTROUTING -j neutron-pos'
-                              'trouting-bottom\n-A neutron-postrouting-bottom '
-                              '-j %s-snat\n-A %s-snat -j %s-float-snat\n' % (
-                              bn, bn, bn, bn, bn, bn, bn, bn, bn, bn, bn)
-                              ), root_helper=self.root_helper).AndReturn(None)
-
         self.mox.ReplayAll()
         self.iptables.ipv4['nat'].add_chain('nat')
         self.iptables.ipv4['nat'].add_rule('PREROUTING',
-                                           '-d 192.168.0.3 -j %s-nat' %
-                                           (iptables_manager.binary_name))
+                                           '-d 192.168.0.3 -j '
+                                           '%(bn)s-nat' % IPTABLES_ARG)
         self.iptables.ipv4['nat'].add_rule('nat',
                                            '-p tcp --dport 8080' +
                                            ' -j REDIRECT --to-port 80')
@@ -263,8 +258,8 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
                                               '-p tcp --dport 8080 -j'
                                               ' REDIRECT --to-port 80')
         self.iptables.ipv4['nat'].remove_rule('PREROUTING',
-                                              '-d 192.168.0.3 -j %s-nat' %
-                                              (iptables_manager.binary_name))
+                                              '-d 192.168.0.3 -j '
+                                              '%(bn)s-nat' % IPTABLES_ARG)
         self.iptables.ipv4['nat'].remove_chain('nat')
 
         self.iptables.apply()
index 22d64bae006ed2a5027a6d604861379096e9829d..235100d2520ca3895300478beca3a91340e71674 100644 (file)
@@ -574,26 +574,32 @@ class SecurityGroupAgentRpcApiTestCase(base.BaseTestCase):
 #Note(nati) bn -> binary_name
 # id -> device_id
 
-PHYSDEV_RULE = '-m physdev --physdev-is-bridged'
+PHYSDEV_MOD = '-m physdev'
+PHYSDEV_IS_BRIDGED = '--physdev-is-bridged'
 
 IPTABLES_ARG = {'bn': iptables_manager.binary_name,
-                'physdev': PHYSDEV_RULE}
+                'physdev_mod': PHYSDEV_MOD,
+                'physdev_is_bridged': PHYSDEV_IS_BRIDGED}
 
 CHAINS_NAT = 'OUTPUT|POSTROUTING|PREROUTING|float-snat|snat'
 IPTABLES_ARG['chains'] = CHAINS_NAT
 
-IPTABLES_NAT = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_NAT = """# Generated by iptables_manager
+*nat
+:neutron-postrouting-bottom - [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]
-:neutron-postrouting-bottom - [0:0]
--A PREROUTING -j %(bn)s-PREROUTING
--A OUTPUT -j %(bn)s-OUTPUT
--A POSTROUTING -j %(bn)s-POSTROUTING
--A POSTROUTING -j neutron-postrouting-bottom
--A neutron-postrouting-bottom -j %(bn)s-snat
--A %(bn)s-snat -j %(bn)s-float-snat
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A PREROUTING -j %(bn)s-PREROUTING
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING
+[0:0] -A POSTROUTING -j neutron-postrouting-bottom
+[0:0] -A neutron-postrouting-bottom -j %(bn)s-snat
+[0:0] -A %(bn)s-snat -j %(bn)s-float-snat
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
 CHAINS_EMPTY = 'FORWARD|INPUT|OUTPUT|local|sg-chain|sg-fallback'
@@ -602,7 +608,9 @@ CHAINS_2 = CHAINS_1 + '|i_port2|o_port2'
 
 IPTABLES_ARG['chains'] = CHAINS_1
 
-IPTABLES_FILTER_1 = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_1 = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -610,36 +618,46 @@ IPTABLES_FILTER_1 = """:%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
--A %(bn)s-i_port1 -m state --state INVALID -j DROP
--A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
--A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
--A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
--A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
--A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
--A %(bn)s-o_port1 -p udp --sport 67 --dport 68 -j DROP
--A %(bn)s-o_port1 -m state --state INVALID -j DROP
--A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port1 -j RETURN
--A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-sg-chain -j ACCEPT
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port1 -s 10.0.0.2 -p udp -m udp --sport 67 --dport 68 \
+-j RETURN
+[0:0] -A %(bn)s-i_port1 -p tcp -m tcp --dport 22 -j RETURN
+[0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 68 --dport 67 -j RETURN
+[0:0] -A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 67 --dport 68 -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port1 -j RETURN
+[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-sg-chain -j ACCEPT
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
-IPTABLES_FILTER_1_2 = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_1_2 = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -647,39 +665,49 @@ IPTABLES_FILTER_1_2 = """:%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
--A %(bn)s-i_port1 -m state --state INVALID -j DROP
--A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
--A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
--A %(bn)s-i_port1 -j RETURN -s 10.0.0.4
--A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
--A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
--A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
--A %(bn)s-o_port1 -p udp --sport 67 --dport 68 -j DROP
--A %(bn)s-o_port1 -m state --state INVALID -j DROP
--A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port1 -j RETURN
--A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-sg-chain -j ACCEPT
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port1 -s 10.0.0.2 -p udp -m udp --sport 67 --dport 68 \
+-j RETURN
+[0:0] -A %(bn)s-i_port1 -p tcp -m tcp --dport 22 -j RETURN
+[0:0] -A %(bn)s-i_port1 -s 10.0.0.4 -j RETURN
+[0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 68 --dport 67 -j RETURN
+[0:0] -A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 67 --dport 68 -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port1 -j RETURN
+[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-sg-chain -j ACCEPT
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_ARG['chains'] = CHAINS_2
 
-IPTABLES_FILTER_2 = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_2 = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -689,56 +717,72 @@ IPTABLES_FILTER_2 = """:%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
--A %(bn)s-i_port1 -m state --state INVALID -j DROP
--A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
--A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
--A %(bn)s-i_port1 -j RETURN -s 10.0.0.4
--A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
--A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
--A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
--A %(bn)s-o_port1 -p udp --sport 67 --dport 68 -j DROP
--A %(bn)s-o_port1 -m state --state INVALID -j DROP
--A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port1 -j RETURN
--A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-i_port2
--A %(bn)s-i_port2 -m state --state INVALID -j DROP
--A %(bn)s-i_port2 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port2 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
--A %(bn)s-i_port2 -j RETURN -p tcp --dport 22
--A %(bn)s-i_port2 -j RETURN -s 10.0.0.3
--A %(bn)s-i_port2 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
--A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
--A %(bn)s-o_port2 -p udp --sport 68 --dport 67 -j RETURN
--A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
--A %(bn)s-o_port2 -p udp --sport 67 --dport 68 -j DROP
--A %(bn)s-o_port2 -m state --state INVALID -j DROP
--A %(bn)s-o_port2 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port2 -j RETURN
--A %(bn)s-o_port2 -j %(bn)s-sg-fallback
--A %(bn)s-sg-chain -j ACCEPT
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port1 -s 10.0.0.2 -p udp -m udp --sport 67 --dport 68 \
+-j RETURN
+[0:0] -A %(bn)s-i_port1 -p tcp -m tcp --dport 22 -j RETURN
+[0:0] -A %(bn)s-i_port1 -s 10.0.0.4 -j RETURN
+[0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 68 --dport 67 -j RETURN
+[0:0] -A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 67 --dport 68 -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port1 -j RETURN
+[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-i_port2
+[0:0] -A %(bn)s-i_port2 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port2 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port2 -s 10.0.0.2 -p udp -m udp --sport 67 --dport 68 \
+-j RETURN
+[0:0] -A %(bn)s-i_port2 -p tcp -m tcp --dport 22 -j RETURN
+[0:0] -A %(bn)s-i_port2 -s 10.0.0.3 -j RETURN
+[0:0] -A %(bn)s-i_port2 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-o_port2
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-o_port2
+[0:0] -A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
+[0:0] -A %(bn)s-o_port2 -p udp -m udp --sport 68 --dport 67 -j RETURN
+[0:0] -A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
+[0:0] -A %(bn)s-o_port2 -p udp -m udp --sport 67 --dport 68 -j DROP
+[0:0] -A %(bn)s-o_port2 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port2 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port2 -j RETURN
+[0:0] -A %(bn)s-o_port2 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-sg-chain -j ACCEPT
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
-IPTABLES_FILTER_2_2 = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_2_2 = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -748,55 +792,71 @@ IPTABLES_FILTER_2_2 = """:%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
--A %(bn)s-i_port1 -m state --state INVALID -j DROP
--A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
--A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
--A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
--A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
--A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
--A %(bn)s-o_port1 -p udp --sport 67 --dport 68 -j DROP
--A %(bn)s-o_port1 -m state --state INVALID -j DROP
--A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port1 -j RETURN
--A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-i_port2
--A %(bn)s-i_port2 -m state --state INVALID -j DROP
--A %(bn)s-i_port2 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port2 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
--A %(bn)s-i_port2 -j RETURN -p tcp --dport 22
--A %(bn)s-i_port2 -j RETURN -s 10.0.0.3
--A %(bn)s-i_port2 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
--A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
--A %(bn)s-o_port2 -p udp --sport 68 --dport 67 -j RETURN
--A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
--A %(bn)s-o_port2 -p udp --sport 67 --dport 68 -j DROP
--A %(bn)s-o_port2 -m state --state INVALID -j DROP
--A %(bn)s-o_port2 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port2 -j RETURN
--A %(bn)s-o_port2 -j %(bn)s-sg-fallback
--A %(bn)s-sg-chain -j ACCEPT
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port1 -s 10.0.0.2 -p udp -m udp --sport 67 --dport 68 \
+-j RETURN
+[0:0] -A %(bn)s-i_port1 -p tcp -m tcp --dport 22 -j RETURN
+[0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 68 --dport 67 -j RETURN
+[0:0] -A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 67 --dport 68 -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port1 -j RETURN
+[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-i_port2
+[0:0] -A %(bn)s-i_port2 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port2 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port2 -s 10.0.0.2 -p udp -m udp --sport 67 --dport 68 \
+-j RETURN
+[0:0] -A %(bn)s-i_port2 -p tcp -m tcp --dport 22 -j RETURN
+[0:0] -A %(bn)s-i_port2 -s 10.0.0.3 -j RETURN
+[0:0] -A %(bn)s-i_port2 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-o_port2
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-o_port2
+[0:0] -A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
+[0:0] -A %(bn)s-o_port2 -p udp -m udp --sport 68 --dport 67 -j RETURN
+[0:0] -A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
+[0:0] -A %(bn)s-o_port2 -p udp -m udp --sport 67 --dport 68 -j DROP
+[0:0] -A %(bn)s-o_port2 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port2 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port2 -j RETURN
+[0:0] -A %(bn)s-o_port2 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-sg-chain -j ACCEPT
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
-IPTABLES_FILTER_2_3 = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_2_3 = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -806,76 +866,96 @@ IPTABLES_FILTER_2_3 = """:%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
--A %(bn)s-i_port1 -m state --state INVALID -j DROP
--A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
--A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
--A %(bn)s-i_port1 -j RETURN -s 10.0.0.4
--A %(bn)s-i_port1 -j RETURN -p icmp
--A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
--A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
--A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
--A %(bn)s-o_port1 -p udp --sport 67 --dport 68 -j DROP
--A %(bn)s-o_port1 -m state --state INVALID -j DROP
--A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port1 -j RETURN
--A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-i_port2
--A %(bn)s-i_port2 -m state --state INVALID -j DROP
--A %(bn)s-i_port2 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port2 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
--A %(bn)s-i_port2 -j RETURN -p tcp --dport 22
--A %(bn)s-i_port2 -j RETURN -s 10.0.0.3
--A %(bn)s-i_port2 -j RETURN -p icmp
--A %(bn)s-i_port2 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
--A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
--A %(bn)s-o_port2 -p udp --sport 68 --dport 67 -j RETURN
--A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
--A %(bn)s-o_port2 -p udp --sport 67 --dport 68 -j DROP
--A %(bn)s-o_port2 -m state --state INVALID -j DROP
--A %(bn)s-o_port2 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port2 -j RETURN
--A %(bn)s-o_port2 -j %(bn)s-sg-fallback
--A %(bn)s-sg-chain -j ACCEPT
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port1 -s 10.0.0.2 -p udp -m udp --sport 67 --dport 68 \
+-j RETURN
+[0:0] -A %(bn)s-i_port1 -p tcp -m tcp --dport 22 -j RETURN
+[0:0] -A %(bn)s-i_port1 -s 10.0.0.4 -j RETURN
+[0:0] -A %(bn)s-i_port1 -p icmp -j RETURN
+[0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 68 --dport 67 -j RETURN
+[0:0] -A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
+[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 67 --dport 68 -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port1 -j RETURN
+[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-i_port2
+[0:0] -A %(bn)s-i_port2 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port2 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port2 -s 10.0.0.2 -p udp -m udp --sport 67 --dport 68 \
+-j RETURN
+[0:0] -A %(bn)s-i_port2 -p tcp -m tcp --dport 22 -j RETURN
+[0:0] -A %(bn)s-i_port2 -s 10.0.0.3 -j RETURN
+[0:0] -A %(bn)s-i_port2 -p icmp -j RETURN
+[0:0] -A %(bn)s-i_port2 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-o_port2
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-o_port2
+[0:0] -A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
+[0:0] -A %(bn)s-o_port2 -p udp -m udp --sport 68 --dport 67 -j RETURN
+[0:0] -A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
+[0:0] -A %(bn)s-o_port2 -p udp -m udp --sport 67 --dport 68 -j DROP
+[0:0] -A %(bn)s-o_port2 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port2 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port2 -j RETURN
+[0:0] -A %(bn)s-o_port2 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-sg-chain -j ACCEPT
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_ARG['chains'] = CHAINS_EMPTY
-IPTABLES_FILTER_EMPTY = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_EMPTY = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [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]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_ARG['chains'] = CHAINS_1
-IPTABLES_FILTER_V6_1 = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_V6_1 = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -883,32 +963,41 @@ IPTABLES_FILTER_V6_1 = """:%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
--A %(bn)s-i_port1 -m state --state INVALID -j DROP
--A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
--A %(bn)s-o_port1 -p icmpv6 -j RETURN
--A %(bn)s-o_port1 -m state --state INVALID -j DROP
--A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-sg-chain -j ACCEPT
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
+[0:0] -A %(bn)s-o_port1 -p icmpv6 -j RETURN
+[0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-sg-chain -j ACCEPT
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_ARG['chains'] = CHAINS_2
-IPTABLES_FILTER_V6_2 = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_V6_2 = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -918,58 +1007,74 @@ IPTABLES_FILTER_V6_2 = """:%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
--A %(bn)s-i_port1 -m state --state INVALID -j DROP
--A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
--A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
--A %(bn)s-o_port1 -p icmpv6 -j RETURN
--A %(bn)s-o_port1 -m state --state INVALID -j DROP
--A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-i_port2
--A %(bn)s-i_port2 -m state --state INVALID -j DROP
--A %(bn)s-i_port2 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-i_port2 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
--A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
--A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
--A %(bn)s-o_port2 -p icmpv6 -j RETURN
--A %(bn)s-o_port2 -m state --state INVALID -j DROP
--A %(bn)s-o_port2 -m state --state ESTABLISHED,RELATED -j RETURN
--A %(bn)s-o_port2 -j %(bn)s-sg-fallback
--A %(bn)s-sg-chain -j ACCEPT
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+[0:0] -A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
+[0:0] -A %(bn)s-o_port1 -p icmpv6 -j RETURN
+[0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-i_port2
+[0:0] -A %(bn)s-i_port2 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-i_port2 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-i_port2 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-sg-chain
+[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-o_port2
+[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_port2 \
+%(physdev_is_bridged)s -j %(bn)s-o_port2
+[0:0] -A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
+[0:0] -A %(bn)s-o_port2 -p icmpv6 -j RETURN
+[0:0] -A %(bn)s-o_port2 -m state --state INVALID -j DROP
+[0:0] -A %(bn)s-o_port2 -m state --state RELATED,ESTABLISHED -j RETURN
+[0:0] -A %(bn)s-o_port2 -j %(bn)s-sg-fallback
+[0:0] -A %(bn)s-sg-chain -j ACCEPT
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_ARG['chains'] = CHAINS_EMPTY
-IPTABLES_FILTER_V6_EMPTY = """:%(bn)s-(%(chains)s) - [0:0]
+IPTABLES_FILTER_V6_EMPTY = """# Generated by iptables_manager
+*filter
+:neutron-filter-top - [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]
 :%(bn)s-(%(chains)s) - [0:0]
-:neutron-filter-top - [0:0]
--A FORWARD -j neutron-filter-top
--A OUTPUT -j neutron-filter-top
--A neutron-filter-top -j %(bn)s-local
--A INPUT -j %(bn)s-INPUT
--A OUTPUT -j %(bn)s-OUTPUT
--A FORWARD -j %(bn)s-FORWARD
--A %(bn)s-sg-fallback -j DROP
+:%(bn)s-(%(chains)s) - [0:0]
+[0:0] -A FORWARD -j neutron-filter-top
+[0:0] -A OUTPUT -j neutron-filter-top
+[0:0] -A neutron-filter-top -j %(bn)s-local
+[0:0] -A INPUT -j %(bn)s-INPUT
+[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+[0:0] -A FORWARD -j %(bn)s-FORWARD
+[0:0] -A %(bn)s-sg-fallback -j DROP
+COMMIT
+# Completed by iptables_manager
 """ % IPTABLES_ARG
 
 FIREWALL_BASE_PACKAGE = 'neutron.agent.linux.iptables_firewall.'
@@ -1083,33 +1188,25 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
         value = value.replace('\n', '\\n')
         value = value.replace('[', '\[')
         value = value.replace(']', '\]')
+        value = value.replace('*', '\*')
         return mox.Regex(value)
 
     def _replay_iptables(self, v4_filter, v6_filter):
         self.iptables.execute(
-            ['iptables-save', '-t', 'filter'],
-            root_helper=self.root_helper).AndReturn('')
-
-        self.iptables.execute(
-            ['iptables-restore'],
-            process_input=self._regex(v4_filter),
-            root_helper=self.root_helper).AndReturn('')
-
-        self.iptables.execute(
-            ['iptables-save', '-t', 'nat'],
+            ['iptables-save', '-c'],
             root_helper=self.root_helper).AndReturn('')
 
         self.iptables.execute(
-            ['iptables-restore'],
-            process_input=self._regex(IPTABLES_NAT),
+            ['iptables-restore', '-c'],
+            process_input=(self._regex(IPTABLES_NAT + v4_filter)),
             root_helper=self.root_helper).AndReturn('')
 
         self.iptables.execute(
-            ['ip6tables-save', '-t', 'filter'],
+            ['ip6tables-save', '-c'],
             root_helper=self.root_helper).AndReturn('')
 
         self.iptables.execute(
-            ['ip6tables-restore'],
+            ['ip6tables-restore', '-c'],
             process_input=self._regex(v6_filter),
             root_helper=self.root_helper).AndReturn('')