]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Use diffs for iptables restore instead of all rules
authorKevin Benton <blak111@gmail.com>
Sat, 3 Oct 2015 14:25:19 +0000 (07:25 -0700)
committerKevin Benton <kevinbenton@buttewifi.com>
Mon, 23 Nov 2015 06:09:28 +0000 (06:09 +0000)
This patch changes our iptables logic to generate a delta of
iptables commands (inserts + deletes) to get from the current
iptables state to the new state. This will significantly reduce
the amount of data that we have to shell out to iptables-restore
on every call (and reduce the amount of data iptables-restore has
to parse).

We no longer have to worry about preserving counters since
we are adding and deleting specific rules, so the rule modification
code got a nice cleanup to get rid of the old rule matching.

This also gives us a new method of functionally testing that we are
generating rules in the correct manner. After applying new rules
once, a subsequent call should always have no work to do. The new
functional tests added leverage that property heavily and should
protect us from regressions in how rules are formed.

Performance metrics relative to HEAD~1:
+====================================+============+=======+
|               Scenario             | This patch | HEAD~1|
|------------------------------------|------------|-------|
| 200 VMs*22 rules existing - startup|            |       |
|                       _modify_rules|   0.67s    | 1.05s |
|                 _apply_synchronized|   1.87s    | 2.89s |
|------------------------------------|------------|-------|
| 200 VMs*22 rules existing - add VM |            |       |
|                       _modify_rules|   0.68s    | 1.05s |
|                 _apply_synchronized|   2.07s    | 2.92s |
|------------------------------------+------------+-------+
|200 VMs*422 rules existing - startup|            |       |
|                       _modify_rules|   5.43s    | 8.17s |
|                 _apply_synchronized|  12.77s    |28.00s |
|------------------------------------|------------|-------|
|200 VMs*422 rules existing - add VM |            |       |
|                       _modify_rules|   6.41s    | 8.33s |
|                 _apply_synchronized|  33.09s    |33.80s |
+------------------------------------+------------+-------+

The _apply_synchronized times seem to converge when dealing
with ~85k rules. In the profile I can see that both approaches
seem to wait on iptables-restore for approximately the same
amount of time so it could be hitting the performance limits
of iptables-restore.

DocImpact
Partial-Bug: #1502297
Change-Id: Ia6470c85b6b71979006ffe5da9095fdcce3122c1

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

index 02661b9693f80f61845edcbd100199c63c3f6adc..5a5a51a7098364c6f722b10ce8ea3c5f5799361a 100644 (file)
@@ -167,7 +167,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
         self._enable_netfilter_for_bridges()
         # each security group has it own chains
         self._setup_chains()
-        self.iptables.apply()
+        return self.iptables.apply()
 
     def update_port_filter(self, port):
         LOG.debug("Updating device (%s) filter", port['device'])
@@ -178,7 +178,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
         self._remove_chains()
         self._set_ports(port)
         self._setup_chains()
-        self.iptables.apply()
+        return self.iptables.apply()
 
     def remove_port_filter(self, port):
         LOG.debug("Removing device (%s) filter", port['device'])
@@ -189,7 +189,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
         self._remove_chains()
         self._unset_ports(port)
         self._setup_chains()
-        self.iptables.apply()
+        return self.iptables.apply()
 
     def _add_accept_rule_port_sec(self, port, direction):
         self._update_port_sec_rules(port, direction, add=True)
@@ -212,7 +212,10 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
 
     def _setup_chains_apply(self, ports, unfiltered_ports):
         self._add_chain_by_name_v4v6(SG_CHAIN)
-        for port in ports.values():
+        # sort by port so we always do this deterministically between
+        # agent restarts and don't cause unnecessary rule differences
+        for pname in sorted(ports):
+            port = ports[pname]
             self._setup_chain(port, firewall.INGRESS_DIRECTION)
             self._setup_chain(port, firewall.EGRESS_DIRECTION)
         self.iptables.ipv4['filter'].add_rule(SG_CHAIN, '-j ACCEPT')
index 4735ac771a1dc9656d6bdc67b9d3379c86c135f3..251f920e4a3544cb782de65bf8407d1eead56f33 100644 (file)
@@ -20,6 +20,7 @@
 
 import collections
 import contextlib
+import difflib
 import os
 import re
 import sys
@@ -180,7 +181,8 @@ class IptablesTable(object):
             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]
+            self.remove_rules += [str(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]
@@ -188,7 +190,7 @@ class IptablesTable(object):
         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
+            self.remove_rules += [str(r) for r in self.rules
                                   if jump_snippet in r.rule]
         else:
             jump_snippet = '-j %s-%s' % (self.wrap_name, name)
@@ -244,9 +246,9 @@ class IptablesTable(object):
                                            self.wrap_name,
                                            comment=comment))
             if not wrap:
-                self.remove_rules.append(IptablesRule(chain, rule, wrap, top,
-                                                      self.wrap_name,
-                                                      comment=comment))
+                self.remove_rules.append(str(IptablesRule(chain, rule, wrap,
+                                                          top, self.wrap_name,
+                                                          comment=comment)))
         except ValueError:
             LOG.warn(_LW('Tried to remove rule that was not there:'
                          ' %(chain)r %(rule)r %(wrap)r %(top)r'),
@@ -418,7 +420,7 @@ class IptablesManager(object):
         if self.iptables_apply_deferred:
             return
 
-        self._apply()
+        return self._apply()
 
     def _apply(self):
         lock_name = 'iptables'
@@ -438,33 +440,50 @@ class IptablesManager(object):
     def _apply_synchronized(self):
         """Apply the current in-memory set of iptables rules.
 
-        This will blow away any rules left over from previous runs of the
-        same component of Nova, and replace them with our current set of
-        rules. This happens atomically, thanks to iptables-restore.
+        This will create a diff between the rules from the previous runs
+        and replace them with the current set of rules.
+        This happens atomically, thanks to iptables-restore.
 
+        Returns a list of the changes that were sent to iptables-save.
         """
         s = [('iptables', self.ipv4)]
         if self.use_ipv6:
             s += [('ip6tables', self.ipv6)]
-
+        all_commands = []  # variable to keep track all commands for return val
         for cmd, tables in s:
-            args = ['%s-save' % (cmd,), '-c']
+            args = ['%s-save' % (cmd,)]
             if self.namespace:
                 args = ['ip', 'netns', 'exec', self.namespace] + args
-            all_tables = self.execute(args, run_as_root=True)
-            all_lines = all_tables.split('\n')
+            save_output = self.execute(args, run_as_root=True)
+            all_lines = save_output.split('\n')
+            commands = []
             # Traverse tables in sorted order for predictable dump output
             for table_name in sorted(tables):
                 table = tables[table_name]
+                # isolate the lines of the table we are modifying
                 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']
+                old_rules = all_lines[start:end]
+                # generate the new table state we want
+                new_rules = self._modify_rules(old_rules, table, table_name)
+                # generate the iptables commands to get between the old state
+                # and the new state
+                changes = _generate_path_between_rules(old_rules, new_rules)
+                if changes:
+                    # if there are changes to the table, we put on the header
+                    # and footer that iptables-save needs
+                    commands += (['# Generated by iptables_manager'] +
+                                 ['*%s' % table_name] + changes +
+                                 ['COMMIT', '# Completed by iptables_manager'])
+            if not commands:
+                continue
+            all_commands += commands
+            args = ['%s-restore' % (cmd,), '-n']
             if self.namespace:
                 args = ['ip', 'netns', 'exec', self.namespace] + args
             try:
-                self.execute(args, process_input='\n'.join(all_lines),
+                # always end with a new line
+                commands.append('')
+                self.execute(args, process_input='\n'.join(commands),
                              run_as_root=True)
             except RuntimeError as r_error:
                 with excutils.save_and_reraise_exception():
@@ -478,28 +497,30 @@ class IptablesManager(object):
                     except AttributeError:
                         # line error wasn't found, print all lines instead
                         log_start = 0
-                        log_end = len(all_lines)
+                        log_end = len(commands)
                     log_lines = ('%7d. %s' % (idx, l)
                                  for idx, l in enumerate(
-                                     all_lines[log_start:log_end],
+                                     commands[log_start:log_end],
                                      log_start + 1)
                                  )
                     LOG.error(_LE("IPTablesManager.apply failed to apply the "
                                   "following set of iptables rules:\n%s"),
                               '\n'.join(log_lines))
-        LOG.debug("IPTablesManager.apply completed with success")
+        LOG.debug("IPTablesManager.apply completed with success. %d iptables "
+                  "commands were issued", len(all_commands))
+        return all_commands
 
     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
+            start = lines.index('*%s' % table_name)
         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
+        end = lines[start:].index('COMMIT') + start + 1
         return (start, end)
 
     def _find_rules_index(self, lines):
@@ -518,172 +539,92 @@ class IptablesManager(object):
 
         return rules_index
 
-    def _find_last_entry(self, filter_map, match_str):
-        # find last matching entry
-        try:
-            return filter_map[match_str][-1]
-        except KeyError:
-            pass
-
     def _modify_rules(self, current_lines, table, table_name):
         # Chains are stored as sets to avoid duplicates.
         # Sort the output chains here to make their order predictable.
         unwrapped_chains = sorted(table.unwrapped_chains)
         chains = sorted(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 self.wrap_name in line else
-             new_filter).append(line.strip())
-
-        old_filter_map = make_filter_map(old_filter)
-        new_filter_map = make_filter_map(new_filter)
-
-        rules_index = self._find_rules_index(new_filter)
 
-        all_chains = [':%s' % name for name in unwrapped_chains]
-        all_chains += [':%s-%s' % (self.wrap_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()
-
-            old = self._find_last_entry(old_filter_map, chain_str)
-            if not old:
-                dup = self._find_last_entry(new_filter_map, chain_str)
-            new_filter = [s for s in new_filter if chain_str not in s.strip()]
-
-            # if no old or duplicates, use original chain
-            if old or dup:
-                chain_str = str(old or dup)
-            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).strip()
-            # Further down, we weed out duplicates from the bottom of the
-            # list, so here we remove the dupes ahead of time.
-
-            old = self._find_last_entry(old_filter_map, rule_str)
-            if not old:
-                dup = self._find_last_entry(new_filter_map, rule_str)
-            new_filter = [s for s in new_filter if rule_str not in s.strip()]
-
-            # if no old or duplicates, use original rule
-            if old or dup:
-                rule_str = str(old or dup)
-                # backup one index so we write the array correctly
-                if not old:
-                    rules_index -= 1
-            else:
-                # add-on the [packet:bytes]
-                rule_str = '[0:0] ' + rule_str
+        # we don't want to change any rules that don't belong to us so we start
+        # the new_filter with these rules
+        new_filter = [line.strip() for line in current_lines
+                      if self.wrap_name not in line]
+
+        # generate our list of chain names
+        our_chains = [':%s-%s' % (self.wrap_name, name) for name in chains]
+
+        # the unwrapped chains (e.g. neutron-filter-top) may already exist in
+        # the new_filter since they aren't marked by the wrap_name so we only
+        # want to add them if they arent' already there
+        our_chains += [':%s' % name for name in unwrapped_chains
+                       if not any(':%s' % name in s for s in new_filter)]
+
+        our_top_rules = []
+        our_bottom_rules = []
+        for rule in table.rules:
+            rule_str = str(rule)
+            # similar to the unwrapped chains, there are some rules that belong
+            # to us but they don't have the wrap name. we want to remove them
+            # from the new_filter and then add them in the right location in
+            # case our new rules changed the order.
+            # (e.g. '-A FORWARD -j neutron-filter-top')
+            new_filter = [s for s in new_filter if rule_str not in s]
 
             if rule.top:
                 # rule.top == True means we want this rule to be at the top.
-                our_rules += [rule_str]
+                our_top_rules += [rule_str]
             else:
-                bot_rules += [rule_str]
+                our_bottom_rules += [rule_str]
 
-        our_rules += bot_rules
+        our_chains_and_rules = our_chains + our_top_rules + our_bottom_rules
 
-        new_filter[rules_index:rules_index] = our_rules
-        new_filter[rules_index:rules_index] = our_chains
+        # locate the position immediately after the existing chains to insert
+        # our chains and rules
+        rules_index = self._find_rules_index(new_filter)
+        new_filter[rules_index:rules_index] = our_chains_and_rules
 
-        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()
-            return line
-
-        seen_chains = set()
-
-        def _weed_out_duplicate_chains(line):
-            # ignore [packet:byte] counts at end of lines
+        def _weed_out_removes(line):
+            # remove any rules or chains from the filter that were slated
+            # for removal
             if line.startswith(':'):
-                line = _strip_packets_bytes(line)
-                if line in seen_chains:
+                chain = line[1:]
+                if chain in table.remove_chains:
+                    table.remove_chains.remove(chain)
                     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:
+            else:
+                if line in table.remove_rules:
+                    table.remove_rules.remove(line)
                     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
-
+        seen_lines = set()
+
+        # TODO(kevinbenton): remove this function and the next one. They are
+        # just oversized brooms to sweep bugs under the rug!!! We generate the
+        # rules and we shouldn't be generating duplicates.
+        def _weed_out_duplicates(line):
+            if line in seen_lines:
+                thing = 'chain' if line.startswith(':') else 'rule'
+                LOG.warning(_LW("Duplicate iptables %(thing)s detected. This "
+                                "may indicate a bug in the the iptables "
+                                "%(thing)s generation code. Line: %(line)s"),
+                            {'thing': thing, 'line': line})
+                return False
+            seen_lines.add(line)
             # Leave it alone
             return True
 
-        # We filter duplicates.  Go through the chains and rules, letting
-        # the *last* occurrence take precedence 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 = [line for line in new_filter
-                      if _weed_out_duplicate_chains(line) and
-                      _weed_out_duplicate_rules(line) and
+                      if _weed_out_duplicates(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)
+        # flush lists, just in case a rule or chain marked for removal
+        # was already gone. (chains is a set, rules is a list)
+        table.remove_chains.clear()
+        table.remove_rules = []
 
         return new_filter
 
@@ -735,27 +676,73 @@ class IptablesManager(object):
         return acc
 
 
-def make_filter_map(filter_list):
-    filter_map = collections.defaultdict(list)
-    for data in filter_list:
-        # strip any [packet:byte] counts at start or end of lines,
-        # for example, chains look like ":neutron-foo - [0:0]"
-        # and rules look like "[0:0] -A neutron-foo..."
-        if data.startswith('['):
-            key = data.rpartition('] ')[2]
-        elif data.endswith(']'):
-            key = data.rsplit(' [', 1)[0]
-            if key.endswith(' -'):
-                key = key[:-2]
+def _generate_path_between_rules(old_rules, new_rules):
+    """Generates iptables commands to get from old_rules to new_rules.
+
+    This function diffs the two rule sets and then calculates the iptables
+    commands necessary to get from the old rules to the new rules using
+    insert and delete commands.
+    """
+    old_by_chain = _get_rules_by_chain(old_rules)
+    new_by_chain = _get_rules_by_chain(new_rules)
+    old_chains, new_chains = set(old_by_chain.keys()), set(new_by_chain.keys())
+    # all referenced chains should be declared at the top before rules.
+
+    # NOTE(kevinbenton): sorting and grouping chains is for determinism in
+    # tests. iptables doesn't care about the order here
+    statements = [':%s - [0:0]' % c for c in sorted(new_chains - old_chains)]
+    sg_chains = []
+    other_chains = []
+    for chain in sorted(old_chains | new_chains):
+        if '-sg-' in chain:
+            sg_chains.append(chain)
         else:
-            # things like COMMIT, *filter, and *nat land here
+            other_chains.append(chain)
+
+    for chain in other_chains + sg_chains:
+        statements += _generate_chain_diff_iptables_commands(
+            chain, old_by_chain[chain], new_by_chain[chain])
+    # unreferenced chains get the axe
+    for chain in sorted(old_chains - new_chains):
+        statements += ['-X %s' % chain]
+    return statements
+
+
+def _get_rules_by_chain(rules):
+    by_chain = collections.defaultdict(list)
+    for line in rules:
+        if line.startswith(':'):
+            chain = line[1:].split(' ', 1)[0]
+            # even though this is a default dict, we need to manually add
+            # chains to ensure that ones without rules are included because
+            # they might be a jump reference
+            if chain not in by_chain:
+                by_chain[chain] = []
+        elif line.startswith('-A'):
+            chain = line[3:].split(' ', 1)[0]
+            by_chain[chain].append(line)
+    return by_chain
+
+
+def _generate_chain_diff_iptables_commands(chain, old_chain_rules,
+                                          new_chain_rules):
+    # keep track of the old index because we have to insert rules
+    # in the right position
+    old_index = 1
+    statements = []
+    for line in difflib.ndiff(old_chain_rules, new_chain_rules):
+        if line.startswith('?'):
+            # skip ? because that's a guide string for intraline differences
             continue
-        filter_map[key].append(data)
-        # regular IP(v6) entries are translated into /32s or /128s so we
-        # include a lookup without the CIDR here to match as well
-        for cidr in ('/32', '/128'):
-            if cidr in key:
-                alt_key = key.replace(cidr, '')
-                filter_map[alt_key].append(data)
-    # return a regular dict so readers don't accidentally add entries
-    return dict(filter_map)
+        elif line.startswith('-'):  # line deleted
+            statements.append('-D %s %d' % (chain, old_index))
+            # since we are removing a line from the old rules, we
+            # backup the index by 1
+            old_index -= 1
+        elif line.startswith('+'):  # line added
+            # strip the chain name since we have to add it before the index
+            rule = line[5:].split(' ', 1)[-1]
+            # rule inserted at this position
+            statements.append('-I %s %d %s' % (chain, old_index, rule))
+        old_index += 1
+    return statements
index 2d82fdd73b8e4dc84b5daa8baf81f76b25f74d3c..c852888f90de134329df93392f0b9f346f40437a 100644 (file)
@@ -15,6 +15,7 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import copy
 
 from neutron.agent.linux import iptables_firewall
 from neutron.agent import securitygroups_rpc as sg_cfg
@@ -82,3 +83,112 @@ class IptablesFirewallTestCase(base.BaseSudoTestCase):
         self.src_port_desc['port_security_enabled'] = False
         self.firewall.update_port_filter(self.src_port_desc)
         self.client.assert_ping(self.server.ip)
+
+    def test_rule_application_converges(self):
+        sg_rules = [{'ethertype': 'IPv4', 'direction': 'egress'},
+                    {'ethertype': 'IPv6', 'direction': 'egress'},
+                    {'ethertype': 'IPv4', 'direction': 'ingress',
+                     'source_ip_prefix': '0.0.0.0/0', 'protocol': 'icmp'},
+                    {'ethertype': 'IPv6', 'direction': 'ingress',
+                     'source_ip_prefix': '0::0/0', 'protocol': 'ipv6-icmp'}]
+        # make sure port ranges converge on all protocols with and without
+        # port ranges (prevents regression of bug 1502924)
+        for proto in ('tcp', 'udp', 'icmp'):
+            for version in ('IPv4', 'IPv6'):
+                if proto == 'icmp' and version == 'IPv6':
+                    proto = 'ipv6-icmp'
+                base = {'ethertype': version, 'direction': 'ingress',
+                        'protocol': proto}
+                sg_rules.append(copy.copy(base))
+                base['port_range_min'] = 50
+                base['port_range_max'] = 50
+                sg_rules.append(copy.copy(base))
+                base['port_range_max'] = 55
+                sg_rules.append(copy.copy(base))
+                base['source_port_range_min'] = 60
+                base['source_port_range_max'] = 60
+                sg_rules.append(copy.copy(base))
+                base['source_port_range_max'] = 65
+                sg_rules.append(copy.copy(base))
+
+        # add some single-host rules to prevent regression of bug 1502917
+        sg_rules.append({'ethertype': 'IPv4', 'direction': 'ingress',
+                         'source_ip_prefix': '77.77.77.77/32'})
+        sg_rules.append({'ethertype': 'IPv6', 'direction': 'ingress',
+                         'source_ip_prefix': 'fe80::1/128'})
+        self.firewall.update_security_group_rules(
+            self.FAKE_SECURITY_GROUP_ID, sg_rules)
+        self.firewall.prepare_port_filter(self.src_port_desc)
+        # after one prepare call, another apply should be a NOOP
+        self.assertEqual([], self.firewall.iptables._apply())
+
+        orig_sg_rules = copy.copy(sg_rules)
+        for proto in ('tcp', 'udp', 'icmp'):
+            for version in ('IPv4', 'IPv6'):
+                if proto == 'icmp' and version == 'IPv6':
+                    proto = 'ipv6-icmp'
+                # make sure firewall is in converged state
+                self.firewall.update_security_group_rules(
+                    self.FAKE_SECURITY_GROUP_ID, orig_sg_rules)
+                self.firewall.update_port_filter(self.src_port_desc)
+                sg_rules = copy.copy(orig_sg_rules)
+
+                # remove one rule and add another to make sure it results in
+                # exactly one delete and insert
+                sg_rules.pop(0 if version == 'IPv4' else 1)
+                sg_rules.append({'ethertype': version, 'direction': 'egress',
+                                 'protocol': proto})
+                self.firewall.update_security_group_rules(
+                    self.FAKE_SECURITY_GROUP_ID, sg_rules)
+                result = self.firewall.update_port_filter(self.src_port_desc)
+                deletes = [r for r in result if r.startswith('-D ')]
+                creates = [r for r in result if r.startswith('-I ')]
+                self.assertEqual(1, len(deletes))
+                self.assertEqual(1, len(creates))
+                # quick sanity check to make sure the insert was for the
+                # correct proto
+                self.assertIn('-p %s' % proto, creates[0])
+                # another apply should be a NOOP if the right rule was removed
+                # and the new one was inserted in the correct position
+                self.assertEqual([], self.firewall.iptables._apply())
+
+    def test_rule_ordering_correct(self):
+        sg_rules = [
+            {'ethertype': 'IPv4', 'direction': 'egress', 'protocol': 'tcp',
+             'port_range_min': i, 'port_range_max': i}
+            for i in range(50, 61)
+        ]
+        self.firewall.update_security_group_rules(
+            self.FAKE_SECURITY_GROUP_ID, sg_rules)
+        self.firewall.prepare_port_filter(self.src_port_desc)
+        self._assert_sg_out_tcp_rules_appear_in_order(sg_rules)
+        # remove a rule and add a new one
+        sg_rules.pop(5)
+        sg_rules.insert(8, {'ethertype': 'IPv4', 'direction': 'egress',
+                            'protocol': 'tcp', 'port_range_min': 400,
+                            'port_range_max': 400})
+        self.firewall.update_security_group_rules(
+            self.FAKE_SECURITY_GROUP_ID, sg_rules)
+        self.firewall.prepare_port_filter(self.src_port_desc)
+        self._assert_sg_out_tcp_rules_appear_in_order(sg_rules)
+
+        # reverse all of the rules (requires lots of deletes and inserts)
+        sg_rules = list(reversed(sg_rules))
+        self.firewall.update_security_group_rules(
+            self.FAKE_SECURITY_GROUP_ID, sg_rules)
+        self.firewall.prepare_port_filter(self.src_port_desc)
+        self._assert_sg_out_tcp_rules_appear_in_order(sg_rules)
+
+    def _assert_sg_out_tcp_rules_appear_in_order(self, sg_rules):
+        outgoing_rule_pref = '-A %s-o%s' % (self.firewall.iptables.wrap_name,
+                                            self.src_port_desc['device'][3:13])
+        rules = [
+            r for r in self.firewall.iptables.get_rules_for_table('filter')
+            if r.startswith(outgoing_rule_pref)
+        ]
+        # we want to ensure the rules went in in the same order we sent
+        indexes = [rules.index('%s -p tcp -m tcp --dport %s -j RETURN' %
+                               (outgoing_rule_pref, i['port_range_min']))
+                   for i in sg_rules]
+        # all indexes should be in order with no unexpected rules in between
+        self.assertEqual(range(indexes[0], indexes[-1] + 1), indexes)
index 8d0afde3d9110c8656e33cb3b1768ce0876efbe9..76bb89cee0bf25a54c14e6f21797c9939e933d85 100644 (file)
@@ -35,18 +35,21 @@ IPTABLES_ARG = {'bn': iptables_manager.binary_name,
 
 NAT_TEMPLATE = ('# Generated by iptables_manager\n'
                 '*nat\n'
+                ':OUTPUT - [0:0]\n'
+                ':POSTROUTING - [0:0]\n'
+                ':PREROUTING - [0:0]\n'
                 ':neutron-postrouting-bottom - [0:0]\n'
                 ':%(bn)s-OUTPUT - [0:0]\n'
                 ':%(bn)s-POSTROUTING - [0:0]\n'
                 ':%(bn)s-PREROUTING - [0:0]\n'
                 ':%(bn)s-float-snat - [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 '
+                '-I OUTPUT 1 -j %(bn)s-OUTPUT\n'
+                '-I POSTROUTING 1 -j %(bn)s-POSTROUTING\n'
+                '-I POSTROUTING 2 -j neutron-postrouting-bottom\n'
+                '-I PREROUTING 1 -j %(bn)s-PREROUTING\n'
+                '-I neutron-postrouting-bottom 1 -j %(bn)s-snat\n'
+                '-I %(bn)s-snat 1 -j '
                 '%(bn)s-float-snat\n'
                 'COMMIT\n'
                 '# Completed by iptables_manager\n')
@@ -55,17 +58,20 @@ NAT_DUMP = NAT_TEMPLATE % IPTABLES_ARG
 
 FILTER_TEMPLATE = ('# Generated by iptables_manager\n'
                    '*filter\n'
+                   ':FORWARD - [0:0]\n'
+                   ':INPUT - [0:0]\n'
+                   ':OUTPUT - [0:0]\n'
                    ':neutron-filter-top - [0:0]\n'
                    ':%(bn)s-FORWARD - [0:0]\n'
                    ':%(bn)s-INPUT - [0:0]\n'
                    ':%(bn)s-OUTPUT - [0:0]\n'
                    ':%(bn)s-local - [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'
+                   '-I FORWARD 1 -j neutron-filter-top\n'
+                   '-I FORWARD 2 -j %(bn)s-FORWARD\n'
+                   '-I INPUT 1 -j %(bn)s-INPUT\n'
+                   '-I OUTPUT 1 -j neutron-filter-top\n'
+                   '-I OUTPUT 2 -j %(bn)s-OUTPUT\n'
+                   '-I neutron-filter-top 1 -j %(bn)s-local\n'
                    'COMMIT\n'
                    '# Completed by iptables_manager\n')
 
@@ -74,18 +80,21 @@ FILTER_DUMP = FILTER_TEMPLATE % IPTABLES_ARG
 FILTER_WITH_RULES_TEMPLATE = (
     '# Generated by iptables_manager\n'
     '*filter\n'
+    ':FORWARD - [0:0]\n'
+    ':INPUT - [0:0]\n'
+    ':OUTPUT - [0:0]\n'
     ':neutron-filter-top - [0:0]\n'
     ':%(bn)s-FORWARD - [0:0]\n'
     ':%(bn)s-INPUT - [0:0]\n'
     ':%(bn)s-OUTPUT - [0:0]\n'
     ':%(bn)s-filter - [0:0]\n'
     ':%(bn)s-local - [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'
+    '-I FORWARD 1 -j neutron-filter-top\n'
+    '-I FORWARD 2 -j %(bn)s-FORWARD\n'
+    '-I INPUT 1 -j %(bn)s-INPUT\n'
+    '-I OUTPUT 1 -j neutron-filter-top\n'
+    '-I OUTPUT 2 -j %(bn)s-OUTPUT\n'
+    '-I neutron-filter-top 1 -j %(bn)s-local\n'
     '%(filter_rules)s'
     'COMMIT\n'
     '# Completed by iptables_manager\n')
@@ -93,19 +102,22 @@ FILTER_WITH_RULES_TEMPLATE = (
 COMMENTED_NAT_DUMP = (
     '# Generated by iptables_manager\n'
     '*nat\n'
+    ':OUTPUT - [0:0]\n'
+    ':POSTROUTING - [0:0]\n'
+    ':PREROUTING - [0:0]\n'
     ':neutron-postrouting-bottom - [0:0]\n'
     ':%(bn)s-OUTPUT - [0:0]\n'
     ':%(bn)s-POSTROUTING - [0:0]\n'
     ':%(bn)s-PREROUTING - [0:0]\n'
     ':%(bn)s-float-snat - [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 '
+    '-I OUTPUT 1 -j %(bn)s-OUTPUT\n'
+    '-I POSTROUTING 1 -j %(bn)s-POSTROUTING\n'
+    '-I POSTROUTING 2 -j neutron-postrouting-bottom\n'
+    '-I PREROUTING 1 -j %(bn)s-PREROUTING\n'
+    '-I neutron-postrouting-bottom 1 '
     '-m comment --comment "%(snat_out_comment)s" -j %(bn)s-snat\n'
-    '[0:0] -A %(bn)s-snat -j '
+    '-I %(bn)s-snat 1 -j '
     '%(bn)s-float-snat\n'
     'COMMIT\n'
     '# Completed by iptables_manager\n' % IPTABLES_ARG)
@@ -160,9 +172,9 @@ class IptablesCommentsTestCase(base.BaseTestCase):
     def test_add_filter_rule(self):
         iptables_args = {}
         iptables_args.update(IPTABLES_ARG)
-        filter_rules = ('[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' % iptables_args)
+        filter_rules = ('-I %(bn)s-INPUT 1 -s 0/0 -d 192.168.0.2 -j '
+                        '%(bn)s-filter\n-I %(bn)s-filter 1 -j DROP\n'
+                        % iptables_args)
         iptables_args['filter_rules'] = filter_rules
         filter_dump_mod = FILTER_WITH_RULES_TEMPLATE % iptables_args
 
@@ -170,20 +182,20 @@ class IptablesCommentsTestCase(base.BaseTestCase):
         mangle_dump = _generate_mangle_dump(IPTABLES_ARG)
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(raw_dump + COMMENTED_NAT_DUMP +
-                                      mangle_dump + filter_dump_mod),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(filter_dump_mod + mangle_dump +
+                                      COMMENTED_NAT_DUMP + raw_dump),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(raw_dump + COMMENTED_NAT_DUMP +
-                                      mangle_dump + FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + mangle_dump +
+                                      COMMENTED_NAT_DUMP + raw_dump),
                        run_as_root=True
                        ),
              None),
@@ -212,18 +224,23 @@ class IptablesCommentsTestCase(base.BaseTestCase):
 def _generate_mangle_dump(iptables_args):
     return ('# Generated by iptables_manager\n'
             '*mangle\n'
+            ':FORWARD - [0:0]\n'
+            ':INPUT - [0:0]\n'
+            ':OUTPUT - [0:0]\n'
+            ':POSTROUTING - [0:0]\n'
+            ':PREROUTING - [0:0]\n'
             ':%(bn)s-FORWARD - [0:0]\n'
             ':%(bn)s-INPUT - [0:0]\n'
             ':%(bn)s-OUTPUT - [0:0]\n'
             ':%(bn)s-POSTROUTING - [0:0]\n'
             ':%(bn)s-PREROUTING - [0:0]\n'
             ':%(bn)s-mark - [0:0]\n'
-            '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
-            '[0:0] -A INPUT -j %(bn)s-INPUT\n'
-            '[0:0] -A FORWARD -j %(bn)s-FORWARD\n'
-            '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
-            '[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n'
-            '[0:0] -A %(bn)s-PREROUTING -j %(bn)s-mark\n'
+            '-I FORWARD 1 -j %(bn)s-FORWARD\n'
+            '-I INPUT 1 -j %(bn)s-INPUT\n'
+            '-I OUTPUT 1 -j %(bn)s-OUTPUT\n'
+            '-I POSTROUTING 1 -j %(bn)s-POSTROUTING\n'
+            '-I PREROUTING 1 -j %(bn)s-PREROUTING\n'
+            '-I %(bn)s-PREROUTING 1 -j %(bn)s-mark\n'
             'COMMIT\n'
             '# Completed by iptables_manager\n' % iptables_args)
 
@@ -231,13 +248,16 @@ def _generate_mangle_dump(iptables_args):
 def _generate_raw_dump(iptables_args):
     return ('# Generated by iptables_manager\n'
             '*raw\n'
+            ':OUTPUT - [0:0]\n'
+            ':PREROUTING - [0:0]\n'
             ':%(bn)s-OUTPUT - [0:0]\n'
             ':%(bn)s-PREROUTING - [0:0]\n'
-            '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
-            '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
+            '-I OUTPUT 1 -j %(bn)s-OUTPUT\n'
+            '-I PREROUTING 1 -j %(bn)s-PREROUTING\n'
             'COMMIT\n'
             '# Completed by iptables_manager\n' % iptables_args)
 
+
 MANGLE_DUMP = _generate_mangle_dump(IPTABLES_ARG)
 RAW_DUMP = _generate_raw_dump(IPTABLES_ARG)
 
@@ -272,25 +292,25 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
 
     def _extend_with_ip6tables_filter(self, expected_calls, filter_dump):
         expected_calls.insert(2, (
-            mock.call(['ip6tables-save', '-c'],
+            mock.call(['ip6tables-save'],
                       run_as_root=True),
             ''))
         expected_calls.insert(3, (
-            mock.call(['ip6tables-restore', '-c'],
+            mock.call(['ip6tables-restore', '-n'],
                       process_input=filter_dump,
                       run_as_root=True),
             None))
         expected_calls.extend([
-            (mock.call(['ip6tables-save', '-c'],
+            (mock.call(['ip6tables-save'],
                       run_as_root=True),
              ''),
-            (mock.call(['ip6tables-restore', '-c'],
+            (mock.call(['ip6tables-restore', '-n'],
                       process_input=filter_dump,
                       run_as_root=True),
              None)])
 
     def _test_add_and_remove_chain_custom_binary_name_helper(self, use_ipv6):
-        bn = ("abcdef" * 5)
+        bn = ("xbcdef" * 5)
 
         self.iptables = iptables_manager.IptablesManager(
             binary_name=bn,
@@ -311,26 +331,26 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
         mangle_dump = _generate_mangle_dump(iptables_args)
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(raw_dump + nat_dump + mangle_dump +
-                                      filter_dump_mod),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(filter_dump_mod + mangle_dump +
+                                      nat_dump + raw_dump),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(raw_dump + nat_dump + mangle_dump +
-                                      filter_dump),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(filter_dump + mangle_dump +
+                                      nat_dump + raw_dump),
                        run_as_root=True),
              None),
         ]
         if use_ipv6:
             self._extend_with_ip6tables_filter(expected_calls_and_values,
-                                               raw_dump + filter_dump_ipv6)
+                                               filter_dump_ipv6 + raw_dump)
 
         tools.setup_mock_calls(self.execute, expected_calls_and_values)
 
@@ -349,7 +369,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
         self._test_add_and_remove_chain_custom_binary_name_helper(True)
 
     def _test_empty_chain_custom_binary_name_helper(self, use_ipv6):
-        bn = ("abcdef" * 5)[:16]
+        bn = ("xbcdef" * 5)[:16]
 
         self.iptables = iptables_manager.IptablesManager(
             binary_name=bn,
@@ -360,7 +380,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
 
         filter_dump = FILTER_TEMPLATE % iptables_args
 
-        filter_rules = ('[0:0] -A %(bn)s-filter -s 0/0 -d 192.168.0.2\n'
+        filter_rules = ('-I %(bn)s-filter 1 -s 0/0 -d 192.168.0.2\n'
                         % iptables_args)
         iptables_args['filter_rules'] = filter_rules
         filter_dump_mod = FILTER_WITH_RULES_TEMPLATE % iptables_args
@@ -371,26 +391,26 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
         mangle_dump = _generate_mangle_dump(iptables_args)
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(raw_dump + nat_dump + mangle_dump +
-                                      filter_dump_mod),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(filter_dump_mod + mangle_dump +
+                                      nat_dump + raw_dump),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(raw_dump + nat_dump + mangle_dump +
-                                      filter_dump),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(filter_dump + mangle_dump +
+                                      nat_dump + raw_dump),
                        run_as_root=True),
              None),
         ]
         if use_ipv6:
             self._extend_with_ip6tables_filter(expected_calls_and_values,
-                                               raw_dump + filter_dump)
+                                               filter_dump + raw_dump)
 
         tools.setup_mock_calls(self.execute, expected_calls_and_values)
 
@@ -418,26 +438,26 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
         filter_dump_mod = FILTER_WITH_RULES_TEMPLATE % IPTABLES_ARG
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP +
-                                      filter_dump_mod),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(filter_dump_mod + MANGLE_DUMP +
+                                      NAT_DUMP + RAW_DUMP),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + MANGLE_DUMP + NAT_DUMP +
+                                      RAW_DUMP),
                        run_as_root=True),
              None),
         ]
         if use_ipv6:
             self._extend_with_ip6tables_filter(expected_calls_and_values,
-                                               RAW_DUMP + FILTER_DUMP)
+                                               FILTER_DUMP + RAW_DUMP)
 
         tools.setup_mock_calls(self.execute, expected_calls_and_values)
 
@@ -462,36 +482,36 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
 
         iptables_args = {}
         iptables_args.update(IPTABLES_ARG)
-        filter_rules = ('[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' % iptables_args)
+        filter_rules = ('-I %(bn)s-INPUT 1 -s 0/0 -d 192.168.0.2 -j '
+                        '%(bn)s-filter\n-I %(bn)s-filter 1 -j DROP\n'
+                        % iptables_args)
         iptables_args['filter_rules'] = filter_rules
         filter_dump_mod = FILTER_WITH_RULES_TEMPLATE % iptables_args
 
         raw_dump = RAW_DUMP % IPTABLES_ARG
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP +
-                                      filter_dump_mod),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(filter_dump_mod + MANGLE_DUMP +
+                                      NAT_DUMP + RAW_DUMP),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + MANGLE_DUMP + NAT_DUMP +
+                                      RAW_DUMP),
                        run_as_root=True
                        ),
              None),
         ]
         if use_ipv6:
             self._extend_with_ip6tables_filter(expected_calls_and_values,
-                                               raw_dump + FILTER_DUMP)
+                                               FILTER_DUMP + raw_dump)
 
         tools.setup_mock_calls(self.execute, expected_calls_and_values)
 
@@ -533,19 +553,22 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
 
         filter_dump_mod = ('# Generated by iptables_manager\n'
                            '*filter\n'
+                           ':FORWARD - [0:0]\n'
+                           ':INPUT - [0:0]\n'
+                           ':OUTPUT - [0:0]\n'
                            ':neutron-filter-top - [0:0]\n'
                            ':%(wrap)s - [0:0]\n'
                            ':%(bn)s-FORWARD - [0:0]\n'
                            ':%(bn)s-INPUT - [0:0]\n'
                            ':%(bn)s-OUTPUT - [0:0]\n'
                            ':%(bn)s-local - [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-INPUT -s 0/0 -d 192.168.0.2 -j '
+                           '-I FORWARD 1 -j neutron-filter-top\n'
+                           '-I FORWARD 2 -j %(bn)s-FORWARD\n'
+                           '-I INPUT 1 -j %(bn)s-INPUT\n'
+                           '-I OUTPUT 1 -j neutron-filter-top\n'
+                           '-I OUTPUT 2 -j %(bn)s-OUTPUT\n'
+                           '-I neutron-filter-top 1 -j %(bn)s-local\n'
+                           '-I %(bn)s-INPUT 1 -s 0/0 -d 192.168.0.2 -j '
                            '%(wrap)s\n'
                            'COMMIT\n'
                            '# Completed by iptables_manager\n'
@@ -554,26 +577,26 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
         raw_dump = RAW_DUMP % IPTABLES_ARG
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP +
-                                      filter_dump_mod),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(filter_dump_mod + MANGLE_DUMP +
+                                      NAT_DUMP + RAW_DUMP),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + MANGLE_DUMP +
+                                      NAT_DUMP + RAW_DUMP),
                        run_as_root=True),
              None),
         ]
         if use_ipv6:
             self._extend_with_ip6tables_filter(expected_calls_and_values,
-                                               raw_dump + FILTER_DUMP)
+                                               FILTER_DUMP + raw_dump)
 
         tools.setup_mock_calls(self.execute, expected_calls_and_values)
 
@@ -606,6 +629,11 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
         mangle_dump_mod = (
             '# Generated by iptables_manager\n'
             '*mangle\n'
+            ':FORWARD - [0:0]\n'
+            ':INPUT - [0:0]\n'
+            ':OUTPUT - [0:0]\n'
+            ':POSTROUTING - [0:0]\n'
+            ':PREROUTING - [0:0]\n'
             ':%(bn)s-FORWARD - [0:0]\n'
             ':%(bn)s-INPUT - [0:0]\n'
             ':%(bn)s-OUTPUT - [0:0]\n'
@@ -613,37 +641,37 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
             ':%(bn)s-PREROUTING - [0:0]\n'
             ':%(bn)s-mangle - [0:0]\n'
             ':%(bn)s-mark - [0:0]\n'
-            '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
-            '[0:0] -A INPUT -j %(bn)s-INPUT\n'
-            '[0:0] -A FORWARD -j %(bn)s-FORWARD\n'
-            '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
-            '[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n'
-            '[0:0] -A %(bn)s-PREROUTING -j %(bn)s-mark\n'
-            '[0:0] -A %(bn)s-PREROUTING -j MARK --set-xmark 0x1/%(mark)s\n'
+            '-I FORWARD 1 -j %(bn)s-FORWARD\n'
+            '-I INPUT 1 -j %(bn)s-INPUT\n'
+            '-I OUTPUT 1 -j %(bn)s-OUTPUT\n'
+            '-I POSTROUTING 1 -j %(bn)s-POSTROUTING\n'
+            '-I PREROUTING 1 -j %(bn)s-PREROUTING\n'
+            '-I %(bn)s-PREROUTING 1 -j %(bn)s-mark\n'
+            '-I %(bn)s-PREROUTING 2 -j MARK --set-xmark 0x1/%(mark)s\n'
             'COMMIT\n'
             '# Completed by iptables_manager\n' % IPTABLES_ARG)
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + mangle_dump_mod +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + mangle_dump_mod +
+                                      NAT_DUMP + RAW_DUMP),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + MANGLE_DUMP +
+                                      NAT_DUMP + RAW_DUMP),
                        run_as_root=True),
              None),
         ]
         if use_ipv6:
             self._extend_with_ip6tables_filter(expected_calls_and_values,
-                                               RAW_DUMP + FILTER_DUMP)
+                                               FILTER_DUMP + RAW_DUMP)
 
         tools.setup_mock_calls(self.execute, expected_calls_and_values)
 
@@ -678,6 +706,9 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
 
         nat_dump_mod = ('# Generated by iptables_manager\n'
                         '*nat\n'
+                        ':OUTPUT - [0:0]\n'
+                        ':POSTROUTING - [0:0]\n'
+                        ':PREROUTING - [0:0]\n'
                         ':neutron-postrouting-bottom - [0:0]\n'
                         ':%(bn)s-OUTPUT - [0:0]\n'
                         ':%(bn)s-POSTROUTING - [0:0]\n'
@@ -685,43 +716,42 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
                         ':%(bn)s-float-snat - [0:0]\n'
                         ':%(bn)s-nat - [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 '
+                        '-I OUTPUT 1 -j %(bn)s-OUTPUT\n'
+                        '-I POSTROUTING 1 -j %(bn)s-POSTROUTING\n'
+                        '-I POSTROUTING 2 -j neutron-postrouting-bottom\n'
+                        '-I PREROUTING 1 -j %(bn)s-PREROUTING\n'
+                        '-I neutron-postrouting-bottom 1 -j %(bn)s-snat\n'
+                        '-I %(bn)s-PREROUTING 1 -d 192.168.0.3 -j '
                         '%(bn)s-nat\n'
-                        '[0:0] -A %(bn)s-nat -p tcp --dport 8080 -j '
+                        '-I %(bn)s-nat 1 -p tcp --dport 8080 -j '
                         'REDIRECT --to-port 80\n'
+                        '-I %(bn)s-snat 1 -j %(bn)s-float-snat\n'
                         'COMMIT\n'
-                        '# Completed by iptables_manager\n'
-                        % IPTABLES_ARG)
+                        '# Completed by iptables_manager\n' % IPTABLES_ARG)
 
         raw_dump = RAW_DUMP % IPTABLES_ARG
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + nat_dump_mod + MANGLE_DUMP +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + MANGLE_DUMP +
+                                      nat_dump_mod + RAW_DUMP),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + nat_dump + MANGLE_DUMP +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + MANGLE_DUMP + nat_dump +
+                                      RAW_DUMP),
                        run_as_root=True),
              None),
         ]
         if use_ipv6:
             self._extend_with_ip6tables_filter(expected_calls_and_values,
-                                               raw_dump + FILTER_DUMP)
+                                               FILTER_DUMP + raw_dump)
 
         tools.setup_mock_calls(self.execute, expected_calls_and_values)
 
@@ -760,37 +790,39 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
 
         raw_dump_mod = ('# Generated by iptables_manager\n'
                         '*raw\n'
+                        ':OUTPUT - [0:0]\n'
+                        ':PREROUTING - [0:0]\n'
                         ':%(bn)s-OUTPUT - [0:0]\n'
                         ':%(bn)s-PREROUTING - [0:0]\n'
                         ':%(bn)s-raw - [0:0]\n'
-                        '[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
-                        '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
-                        '[0:0] -A %(bn)s-PREROUTING -j CT --notrack\n'
+                        '-I OUTPUT 1 -j %(bn)s-OUTPUT\n'
+                        '-I PREROUTING 1 -j %(bn)s-PREROUTING\n'
+                        '-I %(bn)s-PREROUTING 1 -j CT --notrack\n'
                         'COMMIT\n'
                         '# Completed by iptables_manager\n'
                         % IPTABLES_ARG)
 
         expected_calls_and_values = [
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(raw_dump_mod + NAT_DUMP + MANGLE_DUMP +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + MANGLE_DUMP + NAT_DUMP +
+                                      raw_dump_mod),
                        run_as_root=True),
              None),
-            (mock.call(['iptables-save', '-c'],
+            (mock.call(['iptables-save'],
                        run_as_root=True),
              ''),
-            (mock.call(['iptables-restore', '-c'],
-                       process_input=(RAW_DUMP + NAT_DUMP + MANGLE_DUMP +
-                                      FILTER_DUMP),
+            (mock.call(['iptables-restore', '-n'],
+                       process_input=(FILTER_DUMP + MANGLE_DUMP + NAT_DUMP +
+                                      RAW_DUMP),
                        run_as_root=True),
              None),
         ]
         if use_ipv6:
             self._extend_with_ip6tables_filter(expected_calls_and_values,
-                                               RAW_DUMP + FILTER_DUMP)
+                                               FILTER_DUMP + RAW_DUMP)
 
         tools.setup_mock_calls(self.execute, expected_calls_and_values)
 
@@ -1012,43 +1044,6 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
     def test_get_traffic_counters_with_zero_with_ipv6(self):
         self._test_get_traffic_counters_with_zero_helper(True)
 
-    def _test_find_last_entry(self, find_str):
-        filter_list = [':neutron-filter-top - [0:0]',
-                       ':%(bn)s-FORWARD - [0:0]',
-                       ':%(bn)s-INPUT - [0:0]',
-                       ':%(bn)s-local - [0:0]',
-                       ':%(wrap)s - [0:0]',
-                       ':%(bn)s-OUTPUT - [0:0]',
-                       '[0:0] -A FORWARD -j neutron-filter-top',
-                       '[0:0] -A OUTPUT -j neutron-filter-top'
-                       % IPTABLES_ARG]
-        filter_map = iptables_manager.make_filter_map(filter_list)
-        return self.iptables._find_last_entry(filter_map, find_str)
-
-    def test_find_last_entry_old_dup(self):
-        find_str = '-A OUTPUT -j neutron-filter-top'
-        match_str = '[0:0] -A OUTPUT -j neutron-filter-top'
-        ret_str = self._test_find_last_entry(find_str)
-        self.assertEqual(ret_str, match_str)
-
-    def test_find_last_entry_none(self):
-        find_str = 'neutron-filter-NOTFOUND'
-        ret_str = self._test_find_last_entry(find_str)
-        self.assertIsNone(ret_str)
-
-    def test_make_filter_map_cidr_stripping(self):
-        filter_rules = ('[0:0] -A OUTPUT -j DROP',
-                        '[0:0] -A INPUT -d 192.168.0.2/32 -j DROP',
-                        '[0:0] -A INPUT -d 1234:31::001F/128 -j DROP',
-                        'OUTPUT - [0:0]')
-        filter_map = iptables_manager.make_filter_map(filter_rules)
-        # make sure /128 works without CIDR
-        self.assertEqual(filter_rules[2],
-                         filter_map['-A INPUT -d 1234:31::001F -j DROP'][0])
-        # make sure /32 works without CIDR
-        self.assertEqual(filter_rules[1],
-                         filter_map['-A INPUT -d 192.168.0.2 -j DROP'][0])
-
 
 class IptablesManagerStateLessTestCase(base.BaseTestCase):
 
index a5a5de405a167e8a8043c80206ecb16c0ba64a7f..fc9162565ce8a745f39c70263c737050435ec9f4 100644 (file)
@@ -1648,18 +1648,23 @@ IPTABLES_ARG['chains'] = CHAINS_MANGLE
 
 IPTABLES_MANGLE = """# Generated by iptables_manager
 *mangle
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
+:POSTROUTING - [0:0]
+:PREROUTING - [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]
 :%(bn)s-(%(chains)s) - [0:0]
-[0:0] -A PREROUTING -j %(bn)s-PREROUTING
-[0:0] -A INPUT -j %(bn)s-INPUT
-[0:0] -A FORWARD -j %(bn)s-FORWARD
-[0:0] -A OUTPUT -j %(bn)s-OUTPUT
-[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING
-[0:0] -A %(bn)s-PREROUTING -j %(bn)s-mark
+-I FORWARD 1 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j %(bn)s-OUTPUT
+-I POSTROUTING 1 -j %(bn)s-POSTROUTING
+-I PREROUTING 1 -j %(bn)s-PREROUTING
+-I %(bn)s-PREROUTING 1 -j %(bn)s-mark
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -1676,56 +1681,65 @@ IPTABLES_ARG['chains'] = CHAINS_NAT
 
 IPTABLES_RAW_DEFAULT = """# Generated by iptables_manager
 *raw
+:OUTPUT - [0:0]
+:PREROUTING - [0:0]
 :%(bn)s-OUTPUT - [0:0]
 :%(bn)s-PREROUTING - [0:0]
-[0:0] -A PREROUTING -j %(bn)s-PREROUTING
-[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+-I OUTPUT 1 -j %(bn)s-OUTPUT
+-I PREROUTING 1 -j %(bn)s-PREROUTING
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_RAW_DEVICE_1 = """# Generated by iptables_manager
 *raw
+:OUTPUT - [0:0]
+:PREROUTING - [0:0]
 :%(bn)s-OUTPUT - [0:0]
 :%(bn)s-PREROUTING - [0:0]
-[0:0] -A PREROUTING -j %(bn)s-PREROUTING
-[0:0] -A OUTPUT -j %(bn)s-OUTPUT
-[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in qvbtap_port1 -j CT --zone 1
-[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in tap_port1 -j CT --zone 1
+-I OUTPUT 1 -j %(bn)s-OUTPUT
+-I PREROUTING 1 -j %(bn)s-PREROUTING
+-I %(bn)s-PREROUTING 1 -m physdev --physdev-in qvbtap_port1 -j CT --zone 1
+-I %(bn)s-PREROUTING 2 -m physdev --physdev-in tap_port1 -j CT --zone 1
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_RAW_DEVICE_2 = """# Generated by iptables_manager
 *raw
+:OUTPUT - [0:0]
+:PREROUTING - [0:0]
 :%(bn)s-OUTPUT - [0:0]
 :%(bn)s-PREROUTING - [0:0]
-[0:0] -A PREROUTING -j %(bn)s-PREROUTING
-[0:0] -A OUTPUT -j %(bn)s-OUTPUT
-[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in qvbtap_%(port1)s \
+-I OUTPUT 1 -j %(bn)s-OUTPUT
+-I PREROUTING 1 -j %(bn)s-PREROUTING
+-I %(bn)s-PREROUTING 1 -m physdev --physdev-in qvbtap_%(port1)s \
 -j CT --zone 1
-[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in tap_%(port1)s -j CT --zone 1
-[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in qvbtap_%(port2)s \
+-I %(bn)s-PREROUTING 2 -m physdev --physdev-in tap_%(port1)s -j CT --zone 1
+-I %(bn)s-PREROUTING 3 -m physdev --physdev-in qvbtap_%(port2)s \
 -j CT --zone 2
-[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in tap_%(port2)s -j CT --zone 2
+-I %(bn)s-PREROUTING 4 -m physdev --physdev-in tap_%(port2)s -j CT --zone 2
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_NAT = """# Generated by iptables_manager
 *nat
+:OUTPUT - [0:0]
+:POSTROUTING - [0:0]
+:PREROUTING - [0:0]
 :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]
 :%(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
+-I OUTPUT 1 -j %(bn)s-OUTPUT
+-I POSTROUTING 1 -j %(bn)s-POSTROUTING
+-I POSTROUTING 2 -j neutron-postrouting-bottom
+-I PREROUTING 1 -j %(bn)s-PREROUTING
+-I neutron-postrouting-bottom 1 -j %(bn)s-snat
+-I %(bn)s-snat 1 -j %(bn)s-float-snat
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -1735,10 +1749,12 @@ IPTABLES_ARG['chains'] = CHAINS_RAW
 
 IPTABLES_RAW = """# Generated by iptables_manager
 *raw
+:OUTPUT - [0:0]
+:PREROUTING - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
-[0:0] -A PREROUTING -j %(bn)s-PREROUTING
-[0:0] -A OUTPUT -j %(bn)s-OUTPUT
+-I OUTPUT 1 -j %(bn)s-OUTPUT
+-I PREROUTING 1 -j %(bn)s-PREROUTING
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -1751,6 +1767,9 @@ IPTABLES_ARG['chains'] = CHAINS_1
 
 IPSET_FILTER_1 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -1761,49 +1780,52 @@ IPSET_FILTER_1 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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 \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(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 RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_port1 -s 10.0.0.2/32 -p udp -m udp --sport 67 -m udp \
---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 -m set --match-set NIPv4security_group1 src -j \
-RETURN
-[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
-[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 \
+-I %(bn)s-FORWARD 2 %(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 \
+-I %(bn)s-INPUT 1 %(physdev_mod)s --physdev-EGRESS tap_port1 \
 %(physdev_is_bridged)s -j %(bn)s-o_port1
-[0:0] -A %(bn)s-s_port1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \
+-I %(bn)s-i_port1 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_port1 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 -m udp \
+--dport 68 -j RETURN
+-I %(bn)s-i_port1 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_port1 4 -m set --match-set NIPv4security_group1 src -j \
+RETURN
+-I %(bn)s-i_port1 5 -m state --state INVALID -j DROP
+-I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback
+-I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \
 -j RETURN
-[0:0] -A %(bn)s-s_port1 -j DROP
-[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 68 -m udp --dport 67 \
+-I %(bn)s-o_port1 2 -j %(bn)s-s_port1
+-I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_port1 5 -j RETURN
+-I %(bn)s-o_port1 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback
+-I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \
 -j RETURN
-[0:0] -A %(bn)s-o_port1 -j %(bn)s-s_port1
-[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 67 -m udp --dport 68 -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 -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-s_port1 2 -j DROP
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+-I %(bn)s-sg-chain 3 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_FILTER_1 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -1814,41 +1836,41 @@ IPTABLES_FILTER_1 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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 \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(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 RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_port1 -s 10.0.0.2/32 -p udp -m udp --sport 67 -m udp \
---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 -m state --state INVALID -j DROP
-[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 \
+-I %(bn)s-FORWARD 2 %(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 \
+-I %(bn)s-INPUT 1 %(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-s_port1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \
+-I %(bn)s-i_port1 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_port1 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 -m udp \
+--dport 68 -j RETURN
+-I %(bn)s-i_port1 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_port1 4 -m state --state INVALID -j DROP
+-I %(bn)s-i_port1 5 -j %(bn)s-sg-fallback
+-I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \
 -j RETURN
-[0:0] -A %(bn)s-s_port1 -j DROP
-[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 68 -m udp --dport 67 \
+-I %(bn)s-o_port1 2 -j %(bn)s-s_port1
+-I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_port1 5 -j RETURN
+-I %(bn)s-o_port1 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback
+-I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \
 -j RETURN
-[0:0] -A %(bn)s-o_port1 -j %(bn)s-s_port1
-[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 67 -m udp --dport 68 -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 -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-s_port1 2 -j DROP
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+-I %(bn)s-sg-chain 3 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -1856,6 +1878,9 @@ COMMIT
 
 IPTABLES_FILTER_1_2 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -1866,42 +1891,42 @@ IPTABLES_FILTER_1_2 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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 \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(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 RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_port1 -s 10.0.0.2/32 -p udp -m udp --sport 67 -m udp \
---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/32 -j RETURN
-[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
-[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 \
+-I %(bn)s-FORWARD 2 %(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 \
+-I %(bn)s-INPUT 1 %(physdev_mod)s --physdev-EGRESS tap_port1 \
 %(physdev_is_bridged)s -j %(bn)s-o_port1
-[0:0] -A %(bn)s-s_port1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \
+-I %(bn)s-i_port1 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_port1 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 -m udp \
+--dport 68 -j RETURN
+-I %(bn)s-i_port1 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_port1 4 -s 10.0.0.4/32 -j RETURN
+-I %(bn)s-i_port1 5 -m state --state INVALID -j DROP
+-I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback
+-I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \
 -j RETURN
-[0:0] -A %(bn)s-s_port1 -j DROP
-[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 68 -m udp --dport 67 \
+-I %(bn)s-o_port1 2 -j %(bn)s-s_port1
+-I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_port1 5 -j RETURN
+-I %(bn)s-o_port1 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback
+-I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \
 -j RETURN
-[0:0] -A %(bn)s-o_port1 -j %(bn)s-s_port1
-[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 67 -m udp --dport 68 -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 -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-s_port1 2 -j DROP
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-o_port1
+-I %(bn)s-sg-chain 3 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -1910,6 +1935,9 @@ IPTABLES_ARG['chains'] = CHAINS_2
 
 IPSET_FILTER_2 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -1923,78 +1951,75 @@ IPSET_FILTER_2 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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)s \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
-[0:0] -A %(bn)s-i_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m set --match-set NIPv4security_group1 src -j \
-RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+-I %(bn)s-FORWARD 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-s_%(port1)s -s %(ip1)s -m mac --mac-source %(mac1)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port1)s -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-s_%(port1)s
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
-[0:0] -A %(bn)s-i_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -m set --match-set NIPv4security_group1 src -j \
-RETURN
-[0:0] -A %(bn)s-i_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-INPUT 1 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-INPUT 2 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-i_%(port1)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port1)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port1)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port1)s 4 -m set --match-set NIPv4security_group1 src -j RETURN
+-I %(bn)s-i_%(port1)s 5 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port1)s 6 -j %(bn)s-sg-fallback
+-I %(bn)s-i_%(port2)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port2)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port2)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port2)s 4 -m set --match-set NIPv4security_group1 src -j RETURN
+-I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN
+-I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s
+-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port1)s 5 -j RETURN
+-I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN
+-I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s
+-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port2)s 5 -j RETURN
+-I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN
+-I %(bn)s-s_%(port1)s 2 -j DROP
+-I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN
+-I %(bn)s-s_%(port2)s 2 -j DROP
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-sg-chain 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
+-I %(bn)s-sg-chain 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-s_%(port2)s -s %(ip2)s -m mac --mac-source %(mac2)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port2)s -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-s_%(port2)s
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-sg-chain 5 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPSET_FILTER_2_3 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -2008,80 +2033,77 @@ IPSET_FILTER_2_3 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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)s \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
-[0:0] -A %(bn)s-i_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m set --match-set NIPv4security_group1 src -j \
-RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p icmp -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+-I %(bn)s-FORWARD 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-s_%(port1)s -s %(ip1)s -m mac --mac-source %(mac1)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port1)s -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-s_%(port1)s
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
-[0:0] -A %(bn)s-i_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -m set --match-set NIPv4security_group1 src -j \
-RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p icmp -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-INPUT 1 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-INPUT 2 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-i_%(port1)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port1)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port1)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port1)s 4 -m set --match-set NIPv4security_group1 src -j RETURN
+-I %(bn)s-i_%(port1)s 5 -p icmp -j RETURN
+-I %(bn)s-i_%(port1)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port1)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-i_%(port2)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port2)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port2)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port2)s 4 -m set --match-set NIPv4security_group1 src -j RETURN
+-I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN
+-I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN
+-I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s
+-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port1)s 5 -j RETURN
+-I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN
+-I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s
+-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port2)s 5 -j RETURN
+-I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN
+-I %(bn)s-s_%(port1)s 2 -j DROP
+-I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN
+-I %(bn)s-s_%(port2)s 2 -j DROP
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-sg-chain 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
+-I %(bn)s-sg-chain 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-s_%(port2)s -s %(ip2)s -m mac --mac-source %(mac2)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port2)s -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-s_%(port2)s
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-sg-chain 5 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_FILTER_2 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -2095,76 +2117,77 @@ IPTABLES_FILTER_2 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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)s \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
-[0:0] -A %(bn)s-i_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -s %(ip2)s -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+-I %(bn)s-FORWARD 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-s_%(port1)s -s %(ip1)s -m mac --mac-source %(mac1)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port1)s -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-s_%(port1)s
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
-[0:0] -A %(bn)s-i_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -s %(ip1)s -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-INPUT 1 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-INPUT 2 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-s_%(port2)s -s %(ip2)s -m mac --mac-source %(mac2)s \
+-I %(bn)s-i_%(port1)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port1)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port1)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port1)s 4 -s %(ip2)s -j RETURN
+-I %(bn)s-i_%(port1)s 5 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port1)s 6 -j %(bn)s-sg-fallback
+-I %(bn)s-i_%(port2)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port2)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port2)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN
+-I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \
 -j RETURN
-[0:0] -A %(bn)s-s_%(port2)s -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 68 -m udp --dport 67 \
+-I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s
+-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port1)s 5 -j RETURN
+-I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \
 -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-s_%(port2)s
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s
+-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port2)s 5 -j RETURN
+-I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN
+-I %(bn)s-s_%(port1)s 2 -j DROP
+-I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN
+-I %(bn)s-s_%(port2)s 2 -j DROP
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-sg-chain 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
+-I %(bn)s-sg-chain 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
+-I %(bn)s-sg-chain 5 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_FILTER_2_2 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -2178,80 +2201,74 @@ IPTABLES_FILTER_2_2 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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)s \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
-[0:0] -A %(bn)s-i_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m state --state INVALID -j DROP
-""" % IPTABLES_ARG
-IPTABLES_FILTER_2_2 += """[0:0] -A %(bn)s-i_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+-I %(bn)s-FORWARD 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-s_%(port1)s -s %(ip1)s -m mac --mac-source %(mac1)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port1)s -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-s_%(port1)s
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
-[0:0] -A %(bn)s-i_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p tcp -m tcp --dport 22 -j RETURN
-""" % IPTABLES_ARG
-IPTABLES_FILTER_2_2 += ("[0:0] -A %(bn)s-i_%(port2)s -s %(ip1)s "
-                        "-j RETURN\n"
-                        % IPTABLES_ARG)
-IPTABLES_FILTER_2_2 += """[0:0] -A %(bn)s-i_%(port2)s -m state --state \
-INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-INPUT 1 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-INPUT 2 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-i_%(port1)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port1)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port1)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port1)s 4 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port1)s 5 -j %(bn)s-sg-fallback
+-I %(bn)s-i_%(port2)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port2)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port2)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN
+-I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN
+-I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s
+-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port1)s 5 -j RETURN
+-I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN
+-I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s
+-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port2)s 5 -j RETURN
+-I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN
+-I %(bn)s-s_%(port1)s 2 -j DROP
+-I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN
+-I %(bn)s-s_%(port2)s 2 -j DROP
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-sg-chain 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
+-I %(bn)s-sg-chain 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-s_%(port2)s -s %(ip2)s -m mac --mac-source %(mac2)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port2)s -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-s_%(port2)s
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-sg-chain 5 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
 
 IPTABLES_FILTER_2_3 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -2265,72 +2282,68 @@ IPTABLES_FILTER_2_3 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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)s \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
-[0:0] -A %(bn)s-i_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -s %(ip2)s -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p icmp -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+-I %(bn)s-FORWARD 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-s_%(port1)s -s %(ip1)s -m mac --mac-source %(mac1)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port1)s -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-s_%(port1)s
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
-[0:0] -A %(bn)s-i_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -s 10.0.0.2/32 -p udp -m udp --sport 67 \
--m udp --dport 68 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p tcp -m tcp --dport 22 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -s %(ip1)s -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p icmp -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-INPUT 1 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-INPUT 2 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-i_%(port1)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port1)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port1)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port1)s 4 -s %(ip2)s -j RETURN
+-I %(bn)s-i_%(port1)s 5 -p icmp -j RETURN
+-I %(bn)s-i_%(port1)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port1)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-i_%(port2)s 1 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port2)s 2 -s 10.0.0.2/32 -p udp -m udp --sport 67 \
+-m udp --dport 68 -j RETURN
+-I %(bn)s-i_%(port2)s 3 -p tcp -m tcp --dport 22 -j RETURN
+-I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN
+-I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN
+-I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN
+-I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s
+-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port1)s 5 -j RETURN
+-I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN
+-I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s
+-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
+-I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port2)s 5 -j RETURN
+-I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN
+-I %(bn)s-s_%(port1)s 2 -j DROP
+-I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN
+-I %(bn)s-s_%(port2)s 2 -j DROP
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-sg-chain 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
+-I %(bn)s-sg-chain 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-s_%(port2)s -s %(ip2)s -m mac --mac-source %(mac2)s \
--j RETURN
-[0:0] -A %(bn)s-s_%(port2)s -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 68 -m udp --dport 67 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-s_%(port2)s
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 67 -m udp --dport 68 -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-sg-chain 5 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -2339,6 +2352,9 @@ COMMIT
 IPTABLES_ARG['chains'] = CHAINS_EMPTY
 IPTABLES_FILTER_EMPTY = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -2346,14 +2362,14 @@ IPTABLES_FILTER_EMPTY = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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-sg-chain -j ACCEPT
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-sg-chain 1 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -2361,6 +2377,9 @@ COMMIT
 IPTABLES_ARG['chains'] = CHAINS_1
 IPTABLES_FILTER_V6_1 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -2370,39 +2389,39 @@ IPTABLES_FILTER_V6_1 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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 \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(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 -p ipv6-icmp -m icmp6 --icmpv6-type 130 -j RETURN
-[0:0] -A %(bn)s-i_port1 -p ipv6-icmp -m icmp6 --icmpv6-type 131 -j RETURN
-[0:0] -A %(bn)s-i_port1 -p ipv6-icmp -m icmp6 --icmpv6-type 132 -j RETURN
-[0:0] -A %(bn)s-i_port1 -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j RETURN
-[0:0] -A %(bn)s-i_port1 -p ipv6-icmp -m icmp6 --icmpv6-type 136 -j RETURN
-[0:0] -A %(bn)s-i_port1 -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_port1 -m state --state INVALID -j DROP
-[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 \
+-I %(bn)s-FORWARD 2 %(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 \
+-I %(bn)s-INPUT 1 %(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 \
+-I %(bn)s-i_port1 1 -p ipv6-icmp -m icmp6 --icmpv6-type 130 -j RETURN
+-I %(bn)s-i_port1 2 -p ipv6-icmp -m icmp6 --icmpv6-type 131 -j RETURN
+-I %(bn)s-i_port1 3 -p ipv6-icmp -m icmp6 --icmpv6-type 132 -j RETURN
+-I %(bn)s-i_port1 4 -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j RETURN
+-I %(bn)s-i_port1 5 -p ipv6-icmp -m icmp6 --icmpv6-type 136 -j RETURN
+-I %(bn)s-i_port1 6 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_port1 7 -m state --state INVALID -j DROP
+-I %(bn)s-i_port1 8 -j %(bn)s-sg-fallback
+-I %(bn)s-o_port1 1 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
+-I %(bn)s-o_port1 2 -p ipv6-icmp -j RETURN
+-I %(bn)s-o_port1 3 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
+-I %(bn)s-o_port1 4 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
+-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_port1 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_port1 \
+%(physdev_is_bridged)s -j %(bn)s-i_port1
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_port1 \
 %(physdev_is_bridged)s -j %(bn)s-o_port1
-[0:0] -A %(bn)s-o_port1 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-[0:0] -A %(bn)s-o_port1 -p ipv6-icmp -j RETURN
-[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
-[0:0] -A %(bn)s-o_port1 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
-[0:0] -A %(bn)s-o_port1 -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_port1 -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_port1 -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-sg-chain 3 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -2412,6 +2431,9 @@ IPTABLES_ARG['chains'] = CHAINS_2
 
 IPTABLES_FILTER_V6_2 = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -2423,68 +2445,64 @@ IPTABLES_FILTER_V6_2 = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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)s \
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-FORWARD 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
-[0:0] -A %(bn)s-i_%(port1)s -p ipv6-icmp -m icmp6 --icmpv6-type 130 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p ipv6-icmp -m icmp6 --icmpv6-type 131 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p ipv6-icmp -m icmp6 --icmpv6-type 132 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -p ipv6-icmp -m icmp6 --icmpv6-type 136 -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+-I %(bn)s-FORWARD 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
-%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
-[0:0] -A %(bn)s-o_%(port1)s -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -p ipv6-icmp -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 546 -m udp --dport 547 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -p udp -m udp --sport 547 -m udp --dport 546 \
--j DROP
-[0:0] -A %(bn)s-o_%(port1)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port1)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port1)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
-%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
-[0:0] -A %(bn)s-i_%(port2)s -p ipv6-icmp -m icmp6 --icmpv6-type 130 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p ipv6-icmp -m icmp6 --icmpv6-type 131 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p ipv6-icmp -m icmp6 --icmpv6-type 132 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -p ipv6-icmp -m icmp6 --icmpv6-type 136 -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-i_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-i_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-FORWARD %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-FORWARD 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-sg-chain
-[0:0] -A %(bn)s-sg-chain %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-INPUT 1 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-INPUT 2 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-INPUT %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
+-I %(bn)s-i_%(port1)s 1 -p ipv6-icmp -m icmp6 --icmpv6-type 130 -j RETURN
+-I %(bn)s-i_%(port1)s 2 -p ipv6-icmp -m icmp6 --icmpv6-type 131 -j RETURN
+-I %(bn)s-i_%(port1)s 3 -p ipv6-icmp -m icmp6 --icmpv6-type 132 -j RETURN
+-I %(bn)s-i_%(port1)s 4 -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j RETURN
+-I %(bn)s-i_%(port1)s 5 -p ipv6-icmp -m icmp6 --icmpv6-type 136 -j RETURN
+-I %(bn)s-i_%(port1)s 6 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port1)s 7 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port1)s 8 -j %(bn)s-sg-fallback
+-I %(bn)s-i_%(port2)s 1 -p ipv6-icmp -m icmp6 --icmpv6-type 130 -j RETURN
+-I %(bn)s-i_%(port2)s 2 -p ipv6-icmp -m icmp6 --icmpv6-type 131 -j RETURN
+-I %(bn)s-i_%(port2)s 3 -p ipv6-icmp -m icmp6 --icmpv6-type 132 -j RETURN
+-I %(bn)s-i_%(port2)s 4 -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j RETURN
+-I %(bn)s-i_%(port2)s 5 -p ipv6-icmp -m icmp6 --icmpv6-type 136 -j RETURN
+-I %(bn)s-i_%(port2)s 6 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-i_%(port2)s 7 -m state --state INVALID -j DROP
+-I %(bn)s-i_%(port2)s 8 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port1)s 1 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
+-I %(bn)s-o_%(port1)s 2 -p ipv6-icmp -j RETURN
+-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
+-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
+-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-o_%(port2)s 1 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
+-I %(bn)s-o_%(port2)s 2 -p ipv6-icmp -j RETURN
+-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 546 -m udp --dport 547 -j RETURN
+-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 547 -m udp --dport 546 -j DROP
+-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN
+-I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP
+-I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback
+-I %(bn)s-sg-chain 1 %(physdev_mod)s --physdev-INGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port1)s
+-I %(bn)s-sg-chain 2 %(physdev_mod)s --physdev-EGRESS tap_%(port1)s \
+%(physdev_is_bridged)s -j %(bn)s-o_%(port1)s
+-I %(bn)s-sg-chain 3 %(physdev_mod)s --physdev-INGRESS tap_%(port2)s \
+%(physdev_is_bridged)s -j %(bn)s-i_%(port2)s
+-I %(bn)s-sg-chain 4 %(physdev_mod)s --physdev-EGRESS tap_%(port2)s \
 %(physdev_is_bridged)s -j %(bn)s-o_%(port2)s
-[0:0] -A %(bn)s-o_%(port2)s -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -p ipv6-icmp -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 546 -m udp --dport 547 \
--j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -p udp -m udp --sport 547 -m udp --dport 546 \
--j DROP
-[0:0] -A %(bn)s-o_%(port2)s -m state --state RELATED,ESTABLISHED -j RETURN
-[0:0] -A %(bn)s-o_%(port2)s -m state --state INVALID -j DROP
-[0:0] -A %(bn)s-o_%(port2)s -j %(bn)s-sg-fallback
-[0:0] -A %(bn)s-sg-chain -j ACCEPT
+-I %(bn)s-sg-chain 5 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -2492,6 +2510,9 @@ COMMIT
 IPTABLES_ARG['chains'] = CHAINS_EMPTY
 IPTABLES_FILTER_V6_EMPTY = """# Generated by iptables_manager
 *filter
+:FORWARD - [0:0]
+:INPUT - [0:0]
+:OUTPUT - [0:0]
 :neutron-filter-top - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
@@ -2499,14 +2520,14 @@ IPTABLES_FILTER_V6_EMPTY = """# Generated by iptables_manager
 :%(bn)s-(%(chains)s) - [0:0]
 :%(bn)s-(%(chains)s) - [0:0]
 :%(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-sg-chain -j ACCEPT
+-I FORWARD 1 -j neutron-filter-top
+-I FORWARD 2 -j %(bn)s-FORWARD
+-I INPUT 1 -j %(bn)s-INPUT
+-I OUTPUT 1 -j neutron-filter-top
+-I OUTPUT 2 -j %(bn)s-OUTPUT
+-I neutron-filter-top 1 -j %(bn)s-local
+-I %(bn)s-sg-chain 1 -j ACCEPT
+-I %(bn)s-sg-fallback 1 -j DROP
 COMMIT
 # Completed by iptables_manager
 """ % IPTABLES_ARG
@@ -2671,22 +2692,22 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
 
     def _replay_iptables(self, v4_filter, v6_filter, raw):
         self._register_mock_call(
-            ['iptables-save', '-c'],
+            ['iptables-save'],
             run_as_root=True,
             return_value='')
         self._register_mock_call(
-            ['iptables-restore', '-c'],
-            process_input=self._regex(raw + IPTABLES_NAT +
-                                      IPTABLES_MANGLE + v4_filter),
+            ['iptables-restore', '-n'],
+            process_input=self._regex(v4_filter + IPTABLES_MANGLE +
+                                      IPTABLES_NAT + raw),
             run_as_root=True,
             return_value='')
         self._register_mock_call(
-            ['ip6tables-save', '-c'],
+            ['ip6tables-save'],
             run_as_root=True,
             return_value='')
         self._register_mock_call(
-            ['ip6tables-restore', '-c'],
-            process_input=self._regex(raw + v6_filter),
+            ['ip6tables-restore', '-n'],
+            process_input=self._regex(v6_filter + raw),
             run_as_root=True,
             return_value='')