"Fossies" - the Fresh Open Source Software Archive

Member "neutron-14.0.3/neutron/tests/unit/agent/linux/test_iptables_firewall.py" (22 Oct 2019, 107322 Bytes) of package /linux/misc/openstack/neutron-14.0.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "test_iptables_firewall.py": 14.0.2_vs_15.0.0.

    1 # Copyright 2012, Nachi Ueno, NTT MCL, Inc.
    2 # All Rights Reserved.
    3 #
    4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    5 #    not use this file except in compliance with the License. You may obtain
    6 #    a copy of the License at
    7 #
    8 #         http://www.apache.org/licenses/LICENSE-2.0
    9 #
   10 #    Unless required by applicable law or agreed to in writing, software
   11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   13 #    License for the specific language governing permissions and limitations
   14 #    under the License.
   15 
   16 import copy
   17 
   18 import mock
   19 from neutron_lib import constants
   20 from neutron_lib import exceptions
   21 from oslo_config import cfg
   22 import testtools
   23 
   24 from neutron.agent import firewall
   25 from neutron.agent.linux import ip_conntrack
   26 from neutron.agent.linux import ipset_manager
   27 from neutron.agent.linux import iptables_comments as ic
   28 from neutron.agent.linux import iptables_firewall
   29 from neutron.common import utils
   30 from neutron.conf.agent import common as agent_config
   31 from neutron.conf.agent import securitygroups_rpc as security_config
   32 from neutron.tests import base
   33 from neutron.tests.unit.api.v2 import test_base
   34 
   35 
   36 _uuid = test_base._uuid
   37 # TODO(mangelajo): replace all 'IPv4', 'IPv6' to constants
   38 FAKE_PREFIX = {'IPv4': '10.0.0.0/24',
   39                'IPv6': 'fe80::/48'}
   40 FAKE_IP = {'IPv4': '10.0.0.1',
   41            'IPv6': 'fe80::1'}
   42 # TODO(mangelajo): replace all '*_sgid' strings for the constants
   43 FAKE_SGID = 'fake_sgid'
   44 OTHER_SGID = 'other_sgid'
   45 _IPv6 = constants.IPv6
   46 _IPv4 = constants.IPv4
   47 
   48 RAW_TABLE_OUTPUT = """
   49 # Generated by iptables-save v1.4.21 on Fri Jul 31 16:13:28 2015
   50 *raw
   51 :PREROUTING ACCEPT [11561:3470468]
   52 :OUTPUT ACCEPT [11504:4064044]
   53 :neutron-openvswi-OUTPUT - [0:0]
   54 :neutron-openvswi-PREROUTING - [0:0]
   55 -A PREROUTING -j neutron-openvswi-PREROUTING
   56  -A OUTPUT -j neutron-openvswi-OUTPUT
   57 -A neutron-openvswi-PREROUTING -m physdev --physdev-in qvbe804433b-61 -j CT --zone 4097
   58 -A neutron-openvswi-PREROUTING -m physdev --physdev-in tape804433b-61 -j CT --zone 4097
   59 -A neutron-openvswi-PREROUTING -m physdev --physdev-in qvb95c24827-02 -j CT --zone 4098
   60 -A neutron-openvswi-PREROUTING -m physdev --physdev-in tap95c24827-02 -j CT --zone 4098
   61 -A neutron-openvswi-PREROUTING -m physdev --physdev-in qvb61634509-31 -j CT --zone 4098
   62 -A neutron-openvswi-PREROUTING -m physdev --physdev-in tap61634509-31 -j CT --zone 4098
   63 -A neutron-openvswi-PREROUTING -m physdev --physdev-in qvb8f46cf18-12 -j CT --zone 4105
   64 -A neutron-openvswi-PREROUTING -m physdev --physdev-in tap8f46cf18-12 -j CT --zone 4105
   65 COMMIT
   66 # Completed on Fri Jul 31 16:13:28 2015
   67 """  # noqa
   68 
   69 
   70 class BaseIptablesFirewallTestCase(base.BaseTestCase):
   71     def setUp(self):
   72         super(BaseIptablesFirewallTestCase, self).setUp()
   73         mock.patch('eventlet.spawn_n').start()
   74         security_config.register_securitygroups_opts()
   75         agent_config.register_root_helper(cfg.CONF)
   76         cfg.CONF.set_override('comment_iptables_rules', False, 'AGENT')
   77         self.utils_exec_p = mock.patch(
   78             'neutron.agent.linux.utils.execute')
   79         self.utils_exec = self.utils_exec_p.start()
   80         self.iptables_cls_p = mock.patch(
   81             'neutron.agent.linux.iptables_manager.IptablesManager')
   82         iptables_cls = self.iptables_cls_p.start()
   83         self.iptables_inst = mock.Mock()
   84         self.v4filter_inst = mock.Mock()
   85         self.v6filter_inst = mock.Mock()
   86         self.iptables_inst.ipv4 = {'filter': self.v4filter_inst,
   87                                    'raw': self.v4filter_inst
   88                                    }
   89         self.iptables_inst.ipv6 = {'filter': self.v6filter_inst,
   90                                    'raw': self.v6filter_inst
   91                                    }
   92         iptables_cls.return_value = self.iptables_inst
   93 
   94         self.iptables_inst.get_rules_for_table.return_value = (
   95             RAW_TABLE_OUTPUT.splitlines())
   96         self.firewall = iptables_firewall.IptablesFirewallDriver()
   97         self.firewall.iptables = self.iptables_inst
   98         # don't mess with sysctl knobs in unit tests
   99         self.firewall._enabled_netfilter_for_bridges = True
  100         # initial data has 1, 2, and 9 in use, see RAW_TABLE_OUTPUT above.
  101         self._dev_zone_map = {'61634509-31': 4098, '8f46cf18-12': 4105,
  102                               '95c24827-02': 4098, 'e804433b-61': 4097}
  103         get_rules_for_table_func = lambda x: RAW_TABLE_OUTPUT.split('\n')
  104         filtered_ports = {port_id: self._fake_port()
  105                           for port_id in self._dev_zone_map}
  106         self.firewall.ipconntrack = ip_conntrack.IpConntrackManager(
  107               get_rules_for_table_func, filtered_ports=filtered_ports,
  108               unfiltered_ports=dict())
  109 
  110     def _fake_port(self):
  111         return {'device': 'tapfake_dev',
  112                 'mac_address': 'ff:ff:ff:ff:ff:ff',
  113                 'network_id': 'fake_net',
  114                 'fixed_ips': [FAKE_IP['IPv4'],
  115                               FAKE_IP['IPv6']]}
  116 
  117 
  118 class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
  119 
  120     def test_prepare_port_filter_with_no_sg(self):
  121         port = self._fake_port()
  122         self.firewall.prepare_port_filter(port)
  123         calls = [mock.call.add_chain('sg-fallback'),
  124                  mock.call.add_rule(
  125                      'sg-fallback', '-j DROP',
  126                      comment=ic.UNMATCH_DROP),
  127                  mock.call.add_chain('sg-chain'),
  128                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
  129                                     comment=None),
  130                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
  131                                     comment=None),
  132                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
  133                                     comment=None),
  134                  mock.call.add_chain('ifake_dev'),
  135                  mock.call.add_rule('FORWARD',
  136                                     '-m physdev --physdev-out tapfake_dev '
  137                                     '--physdev-is-bridged -j $sg-chain',
  138                                     top=True, comment=ic.VM_INT_SG),
  139                  mock.call.add_rule('sg-chain',
  140                                     '-m physdev --physdev-out tapfake_dev '
  141                                     '--physdev-is-bridged -j $ifake_dev',
  142                                     top=False, comment=ic.SG_TO_VM_SG),
  143                  mock.call.add_rule(
  144                      'ifake_dev',
  145                      '-m state --state RELATED,ESTABLISHED -j RETURN',
  146                      top=False, comment=None),
  147                  mock.call.add_rule(
  148                      'ifake_dev',
  149                      '-m state --state INVALID -j DROP',
  150                      top=False, comment=None),
  151                  mock.call.add_rule('ifake_dev',
  152                                     '-j $sg-fallback',
  153                                     top=False, comment=None),
  154                  mock.call.add_chain('ofake_dev'),
  155                  mock.call.add_rule('FORWARD',
  156                                     '-m physdev --physdev-in tapfake_dev '
  157                                     '--physdev-is-bridged -j $sg-chain',
  158                                     top=True, comment=ic.VM_INT_SG),
  159                  mock.call.add_rule('sg-chain',
  160                                     '-m physdev --physdev-in tapfake_dev '
  161                                     '--physdev-is-bridged -j $ofake_dev',
  162                                     top=False, comment=ic.SG_TO_VM_SG),
  163                  mock.call.add_rule('INPUT',
  164                                     '-m physdev --physdev-in tapfake_dev '
  165                                     '--physdev-is-bridged -j $ofake_dev',
  166                                     top=False, comment=ic.INPUT_TO_SG),
  167                  mock.call.add_chain('sfake_dev'),
  168                  mock.call.add_rule(
  169                      'sfake_dev',
  170                      '-s 10.0.0.1/32 -m mac --mac-source FF:FF:FF:FF:FF:FF '
  171                      '-j RETURN',
  172                      comment=ic.PAIR_ALLOW),
  173                  mock.call.add_rule(
  174                      'sfake_dev', '-j DROP',
  175                      comment=ic.PAIR_DROP),
  176                  mock.call.add_rule(
  177                      'ofake_dev',
  178                      '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp '
  179                      '--sport 68 --dport 67 -j RETURN',
  180                      top=False, comment=None),
  181                  mock.call.add_rule('ofake_dev', '-j $sfake_dev',
  182                                     top=False, comment=None),
  183                  mock.call.add_rule(
  184                      'ofake_dev',
  185                      '-p udp -m udp --sport 68 --dport 67 -j RETURN',
  186                      top=False, comment=None),
  187                  mock.call.add_rule(
  188                      'ofake_dev',
  189                      '-p udp -m udp --sport 67 --dport 68 -j DROP',
  190                      top=False, comment=None),
  191                  mock.call.add_rule(
  192                      'ofake_dev',
  193                      '-m state --state RELATED,ESTABLISHED -j RETURN',
  194                      top=False, comment=None),
  195                  mock.call.add_rule(
  196                      'ofake_dev',
  197                      '-m state --state INVALID -j DROP',
  198                      top=False, comment=None),
  199                  mock.call.add_rule(
  200                      'ofake_dev',
  201                      '-j $sg-fallback',
  202                      top=False, comment=None),
  203                  mock.call.add_rule('sg-chain', '-j ACCEPT')]
  204 
  205         self.v4filter_inst.assert_has_calls(calls)
  206 
  207     def test_filter_ipv4_ingress(self):
  208         rule = {'ethertype': 'IPv4',
  209                 'direction': 'ingress'}
  210         ingress = mock.call.add_rule('ifake_dev', '-j RETURN',
  211                                      top=False, comment=None)
  212         egress = None
  213         self._test_prepare_port_filter(rule, ingress, egress)
  214 
  215     def test_filter_ipv4_ingress_prefix(self):
  216         prefix = FAKE_PREFIX['IPv4']
  217         rule = {'ethertype': 'IPv4',
  218                 'direction': 'ingress',
  219                 'source_ip_prefix': prefix}
  220         ingress = mock.call.add_rule(
  221             'ifake_dev', '-s %s -j RETURN' % prefix, top=False, comment=None)
  222         egress = None
  223         self._test_prepare_port_filter(rule, ingress, egress)
  224 
  225     def test_filter_ipv4_ingress_tcp(self):
  226         rule = {'ethertype': 'IPv4',
  227                 'direction': 'ingress',
  228                 'protocol': 'tcp'}
  229         ingress = mock.call.add_rule(
  230             'ifake_dev', '-p tcp -j RETURN', top=False, comment=None)
  231         egress = None
  232         self._test_prepare_port_filter(rule, ingress, egress)
  233 
  234     def test_filter_ipv4_ingress_tcp_prefix(self):
  235         prefix = FAKE_PREFIX['IPv4']
  236         rule = {'ethertype': 'IPv4',
  237                 'direction': 'ingress',
  238                 'protocol': 'tcp',
  239                 'source_ip_prefix': prefix}
  240         ingress = mock.call.add_rule('ifake_dev',
  241                                      '-s %s -p tcp -j RETURN' % prefix,
  242                                      top=False, comment=None)
  243         egress = None
  244         self._test_prepare_port_filter(rule, ingress, egress)
  245 
  246     def test_filter_ipv4_ingress_icmp(self):
  247         rule = {'ethertype': 'IPv4',
  248                 'direction': 'ingress',
  249                 'protocol': 'icmp'}
  250         ingress = mock.call.add_rule('ifake_dev', '-p icmp -j RETURN',
  251                                      top=False, comment=None)
  252         egress = None
  253         self._test_prepare_port_filter(rule, ingress, egress)
  254 
  255     def test_filter_ipv4_ingress_icmp_prefix(self):
  256         prefix = FAKE_PREFIX['IPv4']
  257         rule = {'ethertype': 'IPv4',
  258                 'direction': 'ingress',
  259                 'protocol': 'icmp',
  260                 'source_ip_prefix': prefix}
  261         ingress = mock.call.add_rule(
  262             'ifake_dev', '-s %s -p icmp -j RETURN' % prefix,
  263             top=False, comment=None)
  264         egress = None
  265         self._test_prepare_port_filter(rule, ingress, egress)
  266 
  267     def test_filter_ipv4_ingress_tcp_port(self):
  268         rule = {'ethertype': 'IPv4',
  269                 'direction': 'ingress',
  270                 'protocol': 'tcp',
  271                 'port_range_min': 10,
  272                 'port_range_max': 10}
  273         ingress = mock.call.add_rule('ifake_dev',
  274                                      '-p tcp -m tcp --dport 10 -j RETURN',
  275                                      top=False, comment=None)
  276         egress = None
  277         self._test_prepare_port_filter(rule, ingress, egress)
  278 
  279     def test_filter_bad_vrrp_with_dport(self):
  280         rule = {'ethertype': 'IPv4',
  281                 'direction': 'ingress',
  282                 'protocol': 'vrrp',
  283                 'port_range_min': 10,
  284                 'port_range_max': 10}
  285         # Dest port isn't support with VRRP, so don't send it
  286         # down to iptables.
  287         ingress = mock.call.add_rule('ifake_dev',
  288                                      '-p vrrp -j RETURN',
  289                                      top=False, comment=None)
  290         egress = None
  291         self._test_prepare_port_filter(rule, ingress, egress)
  292 
  293     def test_filter_ipv4_ingress_tcp_port_by_num(self):
  294         rule = {'ethertype': 'IPv4',
  295                 'direction': 'ingress',
  296                 'protocol': '6',
  297                 'port_range_min': 10,
  298                 'port_range_max': 10}
  299         ingress = mock.call.add_rule('ifake_dev',
  300                                      '-p tcp -m tcp --dport 10 -j RETURN',
  301                                      top=False, comment=None)
  302         egress = None
  303         self._test_prepare_port_filter(rule, ingress, egress)
  304 
  305     def test_filter_ipv4_ingress_tcp_mport(self):
  306         rule = {'ethertype': 'IPv4',
  307                 'direction': 'ingress',
  308                 'protocol': 'tcp',
  309                 'port_range_min': 10,
  310                 'port_range_max': 100}
  311         ingress = mock.call.add_rule(
  312             'ifake_dev',
  313             '-p tcp -m tcp -m multiport --dports 10:100 -j RETURN',
  314             top=False, comment=None)
  315         egress = None
  316         self._test_prepare_port_filter(rule, ingress, egress)
  317 
  318     def test_filter_ipv4_ingress_tcp_mport_prefix(self):
  319         prefix = FAKE_PREFIX['IPv4']
  320         rule = {'ethertype': 'IPv4',
  321                 'direction': 'ingress',
  322                 'protocol': 'tcp',
  323                 'port_range_min': 10,
  324                 'port_range_max': 100,
  325                 'source_ip_prefix': prefix}
  326         ingress = mock.call.add_rule(
  327             'ifake_dev',
  328             '-s %s -p tcp -m tcp -m multiport --dports 10:100 '
  329             '-j RETURN' % prefix, top=False, comment=None)
  330         egress = None
  331         self._test_prepare_port_filter(rule, ingress, egress)
  332 
  333     def test_filter_ipv4_ingress_udp(self):
  334         rule = {'ethertype': 'IPv4',
  335                 'direction': 'ingress',
  336                 'protocol': 'udp'}
  337         ingress = mock.call.add_rule(
  338             'ifake_dev', '-p udp -j RETURN', top=False, comment=None)
  339         egress = None
  340         self._test_prepare_port_filter(rule, ingress, egress)
  341 
  342     def test_filter_ipv4_ingress_udp_prefix(self):
  343         prefix = FAKE_PREFIX['IPv4']
  344         rule = {'ethertype': 'IPv4',
  345                 'direction': 'ingress',
  346                 'protocol': 'udp',
  347                 'source_ip_prefix': prefix}
  348         ingress = mock.call.add_rule('ifake_dev',
  349                                      '-s %s -p udp -j RETURN' % prefix,
  350                                      top=False, comment=None)
  351         egress = None
  352         self._test_prepare_port_filter(rule, ingress, egress)
  353 
  354     def test_filter_ipv4_ingress_udp_port(self):
  355         rule = {'ethertype': 'IPv4',
  356                 'direction': 'ingress',
  357                 'protocol': 'udp',
  358                 'port_range_min': 10,
  359                 'port_range_max': 10}
  360         ingress = mock.call.add_rule('ifake_dev',
  361                                      '-p udp -m udp --dport 10 -j RETURN',
  362                                      top=False, comment=None)
  363         egress = None
  364         self._test_prepare_port_filter(rule, ingress, egress)
  365 
  366     def test_filter_ipv4_ingress_udp_mport(self):
  367         rule = {'ethertype': 'IPv4',
  368                 'direction': 'ingress',
  369                 'protocol': 'udp',
  370                 'port_range_min': 10,
  371                 'port_range_max': 100}
  372         ingress = mock.call.add_rule(
  373             'ifake_dev',
  374             '-p udp -m udp -m multiport --dports 10:100 -j RETURN',
  375             top=False, comment=None)
  376         egress = None
  377         self._test_prepare_port_filter(rule, ingress, egress)
  378 
  379     def test_filter_ipv4_ingress_udp_mport_prefix(self):
  380         prefix = FAKE_PREFIX['IPv4']
  381         rule = {'ethertype': 'IPv4',
  382                 'direction': 'ingress',
  383                 'protocol': 'udp',
  384                 'port_range_min': 10,
  385                 'port_range_max': 100,
  386                 'source_ip_prefix': prefix}
  387         ingress = mock.call.add_rule(
  388             'ifake_dev',
  389             '-s %s -p udp -m udp -m multiport --dports 10:100 '
  390             '-j RETURN' % prefix, top=False, comment=None)
  391         egress = None
  392         self._test_prepare_port_filter(rule, ingress, egress)
  393 
  394     def test_filter_ipv4_ingress_dccp_port(self):
  395         rule = {'ethertype': 'IPv4',
  396                 'direction': 'ingress',
  397                 'protocol': 'dccp',
  398                 'port_range_min': 10,
  399                 'port_range_max': 10}
  400         ingress = mock.call.add_rule('ifake_dev',
  401                                      '-p dccp -m dccp --dport 10 -j RETURN',
  402                                      top=False, comment=None)
  403         egress = None
  404         self._test_prepare_port_filter(rule, ingress, egress)
  405 
  406     def test_filter_ipv4_ingress_sctp_port(self):
  407         rule = {'ethertype': 'IPv4',
  408                 'direction': 'ingress',
  409                 'protocol': 'sctp',
  410                 'port_range_min': 10,
  411                 'port_range_max': 10}
  412         ingress = mock.call.add_rule('ifake_dev',
  413                                      '-p sctp -m sctp --dport 10 -j RETURN',
  414                                      top=False, comment=None)
  415         egress = None
  416         self._test_prepare_port_filter(rule, ingress, egress)
  417 
  418     def test_filter_ipv4_ingress_udplite_port(self):
  419         rule = {'ethertype': 'IPv4',
  420                 'direction': 'ingress',
  421                 'protocol': 'udplite',
  422                 'port_range_min': 10,
  423                 'port_range_max': 10}
  424         ingress = mock.call.add_rule(
  425             'ifake_dev',
  426             '-p udplite -m multiport --dports 10 -j RETURN',
  427             top=False, comment=None)
  428         egress = None
  429         self._test_prepare_port_filter(rule, ingress, egress)
  430 
  431     def test_filter_ipv4_ingress_udplite_mport(self):
  432         rule = {'ethertype': 'IPv4',
  433                 'direction': 'ingress',
  434                 'protocol': 'udplite',
  435                 'port_range_min': 10,
  436                 'port_range_max': 100}
  437         ingress = mock.call.add_rule(
  438             'ifake_dev',
  439             '-p udplite -m multiport --dports 10:100 -j RETURN',
  440             top=False, comment=None)
  441         egress = None
  442         self._test_prepare_port_filter(rule, ingress, egress)
  443 
  444     def test_filter_ipv4_ingress_protocol_blank(self):
  445         rule = {'ethertype': 'IPv4',
  446                 'direction': 'ingress',
  447                 'protocol': ''}
  448         ingress = mock.call.add_rule('ifake_dev', '-j RETURN',
  449                                      top=False, comment=None)
  450         egress = None
  451         self._test_prepare_port_filter(rule, ingress, egress)
  452 
  453     def test_filter_ipv4_ingress_protocol_zero(self):
  454         rule = {'ethertype': 'IPv4',
  455                 'direction': 'ingress',
  456                 'protocol': '0'}
  457         ingress = mock.call.add_rule('ifake_dev', '-j RETURN',
  458                                      top=False, comment=None)
  459         egress = None
  460         self._test_prepare_port_filter(rule, ingress, egress)
  461 
  462     def test_filter_ipv4_ingress_protocol_encap(self):
  463         rule = {'ethertype': 'IPv4',
  464                 'direction': 'ingress',
  465                 'protocol': 'encap'}
  466         ingress = mock.call.add_rule('ifake_dev',
  467                                      '-p encap -j RETURN',
  468                                      top=False, comment=None)
  469         egress = None
  470         self._test_prepare_port_filter(rule, ingress, egress)
  471 
  472     def test_filter_ipv4_ingress_protocol_encap_by_num(self):
  473         rule = {'ethertype': 'IPv4',
  474                 'direction': 'ingress',
  475                 'protocol': '98'}
  476         ingress = mock.call.add_rule('ifake_dev',
  477                                      '-p encap -j RETURN',
  478                                      top=False, comment=None)
  479         egress = None
  480         self._test_prepare_port_filter(rule, ingress, egress)
  481 
  482     def test_filter_ipv4_ingress_protocol_999_local(self):
  483         # There is no protocol 999, so let's return a mapping
  484         # that says there is and make sure the rule is created
  485         # using the name and not the number.
  486         rule = {'ethertype': 'IPv4',
  487                 'direction': 'ingress',
  488                 'protocol': '999'}
  489         ingress = mock.call.add_rule('ifake_dev',
  490                                      '-p fooproto -j RETURN',
  491                                      top=False, comment=None)
  492         egress = None
  493         with mock.patch.object(self.firewall,
  494                                '_local_protocol_name_map') as lpnm:
  495             lpnm.return_value = {'999': 'fooproto'}
  496             self._test_prepare_port_filter(rule, ingress, egress)
  497 
  498     def test_filter_ipv4_egress(self):
  499         rule = {'ethertype': 'IPv4',
  500                 'direction': 'egress'}
  501         egress = mock.call.add_rule('ofake_dev', '-j RETURN',
  502                                     top=False, comment=None)
  503         ingress = None
  504         self._test_prepare_port_filter(rule, ingress, egress)
  505 
  506     def test_filter_ipv4_egress_dest_prefix(self):
  507         prefix = FAKE_PREFIX['IPv4']
  508         rule = {'ethertype': 'IPv4',
  509                 'direction': 'egress',
  510                 'dest_ip_prefix': prefix}
  511         egress = mock.call.add_rule(
  512             'ofake_dev', '-d %s -j RETURN' % prefix, top=False, comment=None)
  513         ingress = None
  514         self._test_prepare_port_filter(rule, ingress, egress)
  515 
  516     def test_filter_ipv4_egress_source_prefix(self):
  517         prefix = FAKE_PREFIX['IPv4']
  518         rule = {'ethertype': 'IPv4',
  519                 'direction': 'egress',
  520                 'source_ip_prefix': prefix}
  521         egress = mock.call.add_rule(
  522             'ofake_dev', '-s %s -j RETURN' % prefix, top=False, comment=None)
  523         ingress = None
  524         self._test_prepare_port_filter(rule, ingress, egress)
  525 
  526     def test_filter_ipv4_egress_tcp(self):
  527         rule = {'ethertype': 'IPv4',
  528                 'direction': 'egress',
  529                 'protocol': 'tcp'}
  530         egress = mock.call.add_rule(
  531             'ofake_dev', '-p tcp -j RETURN', top=False, comment=None)
  532         ingress = None
  533         self._test_prepare_port_filter(rule, ingress, egress)
  534 
  535     def test_filter_ipv4_egress_tcp_prefix(self):
  536         prefix = FAKE_PREFIX['IPv4']
  537         rule = {'ethertype': 'IPv4',
  538                 'direction': 'egress',
  539                 'protocol': 'tcp',
  540                 'dest_ip_prefix': prefix}
  541         egress = mock.call.add_rule('ofake_dev',
  542                                     '-d %s -p tcp -j RETURN' % prefix,
  543                                     top=False, comment=None)
  544         ingress = None
  545         self._test_prepare_port_filter(rule, ingress, egress)
  546 
  547     def test_filter_ipv4_egress_icmp(self):
  548         rule = {'ethertype': 'IPv4',
  549                 'direction': 'egress',
  550                 'protocol': 'icmp'}
  551         egress = mock.call.add_rule('ofake_dev', '-p icmp -j RETURN',
  552                                     top=False, comment=None)
  553         ingress = None
  554         self._test_prepare_port_filter(rule, ingress, egress)
  555 
  556     def test_filter_ipv4_egress_icmp_prefix(self):
  557         prefix = FAKE_PREFIX['IPv4']
  558         rule = {'ethertype': 'IPv4',
  559                 'direction': 'egress',
  560                 'protocol': 'icmp',
  561                 'dest_ip_prefix': prefix}
  562         egress = mock.call.add_rule(
  563             'ofake_dev', '-d %s -p icmp -j RETURN' % prefix,
  564             top=False, comment=None)
  565         ingress = None
  566         self._test_prepare_port_filter(rule, ingress, egress)
  567 
  568     def test_filter_ipv4_egress_icmp_type(self):
  569         prefix = FAKE_PREFIX['IPv4']
  570         rule = {'ethertype': 'IPv4',
  571                 'direction': 'egress',
  572                 'protocol': 'icmp',
  573                 'port_range_min': 8,
  574                 'dest_ip_prefix': prefix}
  575         egress = mock.call.add_rule(
  576             'ofake_dev',
  577             '-d %s -p icmp -m icmp --icmp-type 8 -j RETURN' % prefix,
  578             top=False, comment=None)
  579         ingress = None
  580         self._test_prepare_port_filter(rule, ingress, egress)
  581 
  582     def test_filter_ipv4_egress_icmp_type_name(self):
  583         prefix = FAKE_PREFIX['IPv4']
  584         rule = {'ethertype': 'IPv4',
  585                 'direction': 'egress',
  586                 'protocol': 'icmp',
  587                 'port_range_min': 'echo-request',
  588                 'dest_ip_prefix': prefix}
  589         egress = mock.call.add_rule(
  590             'ofake_dev',
  591             '-d %s -p icmp -m icmp --icmp-type echo-request '
  592             '-j RETURN' % prefix,
  593             top=False, comment=None)
  594         ingress = None
  595         self._test_prepare_port_filter(rule, ingress, egress)
  596 
  597     def test_filter_ipv4_egress_icmp_type_code(self):
  598         prefix = FAKE_PREFIX['IPv4']
  599         rule = {'ethertype': 'IPv4',
  600                 'direction': 'egress',
  601                 'protocol': 'icmp',
  602                 'port_range_min': 8,
  603                 'port_range_max': 0,
  604                 'dest_ip_prefix': prefix}
  605         egress = mock.call.add_rule(
  606             'ofake_dev',
  607             '-d %s -p icmp -m icmp --icmp-type 8/0 -j RETURN' % prefix,
  608             top=False, comment=None)
  609         ingress = None
  610         self._test_prepare_port_filter(rule, ingress, egress)
  611 
  612     def test_filter_ipv4_egress_icmp_type_code_protocol_num(self):
  613         prefix = FAKE_PREFIX['IPv4']
  614         rule = {'ethertype': 'IPv4',
  615                 'direction': 'egress',
  616                 'protocol': '1',
  617                 'port_range_min': 8,
  618                 'port_range_max': 0,
  619                 'dest_ip_prefix': prefix}
  620         egress = mock.call.add_rule(
  621             'ofake_dev',
  622             '-d %s -p icmp -m icmp --icmp-type 8/0 -j RETURN' % prefix,
  623             top=False, comment=None)
  624         ingress = None
  625         self._test_prepare_port_filter(rule, ingress, egress)
  626 
  627     def test_filter_ipv4_egress_tcp_port(self):
  628         rule = {'ethertype': 'IPv4',
  629                 'direction': 'egress',
  630                 'protocol': 'tcp',
  631                 'port_range_min': 10,
  632                 'port_range_max': 10}
  633         egress = mock.call.add_rule('ofake_dev',
  634                                     '-p tcp -m tcp --dport 10 -j RETURN',
  635                                     top=False, comment=None)
  636         ingress = None
  637         self._test_prepare_port_filter(rule, ingress, egress)
  638 
  639     def test_filter_ipv4_egress_tcp_mport(self):
  640         rule = {'ethertype': 'IPv4',
  641                 'direction': 'egress',
  642                 'protocol': 'tcp',
  643                 'port_range_min': 10,
  644                 'port_range_max': 100}
  645         egress = mock.call.add_rule(
  646             'ofake_dev',
  647             '-p tcp -m tcp -m multiport --dports 10:100 -j RETURN',
  648             top=False, comment=None)
  649         ingress = None
  650         self._test_prepare_port_filter(rule, ingress, egress)
  651 
  652     def test_filter_ipv4_egress_tcp_mport_prefix(self):
  653         prefix = FAKE_PREFIX['IPv4']
  654         rule = {'ethertype': 'IPv4',
  655                 'direction': 'egress',
  656                 'protocol': 'tcp',
  657                 'port_range_min': 10,
  658                 'port_range_max': 100,
  659                 'dest_ip_prefix': prefix}
  660         egress = mock.call.add_rule(
  661             'ofake_dev',
  662             '-d %s -p tcp -m tcp -m multiport --dports 10:100 '
  663             '-j RETURN' % prefix, top=False, comment=None)
  664         ingress = None
  665         self._test_prepare_port_filter(rule, ingress, egress)
  666 
  667     def test_filter_ipv4_egress_udp(self):
  668         rule = {'ethertype': 'IPv4',
  669                 'direction': 'egress',
  670                 'protocol': 'udp'}
  671         egress = mock.call.add_rule(
  672             'ofake_dev', '-p udp -j RETURN', top=False, comment=None)
  673         ingress = None
  674         self._test_prepare_port_filter(rule, ingress, egress)
  675 
  676     def test_filter_ipv4_egress_udp_prefix(self):
  677         prefix = FAKE_PREFIX['IPv4']
  678         rule = {'ethertype': 'IPv4',
  679                 'direction': 'egress',
  680                 'protocol': 'udp',
  681                 'dest_ip_prefix': prefix}
  682         egress = mock.call.add_rule('ofake_dev',
  683                                     '-d %s -p udp -j RETURN' % prefix,
  684                                     top=False, comment=None)
  685         ingress = None
  686         self._test_prepare_port_filter(rule, ingress, egress)
  687 
  688     def test_filter_ipv4_egress_udp_port(self):
  689         rule = {'ethertype': 'IPv4',
  690                 'direction': 'egress',
  691                 'protocol': 'udp',
  692                 'port_range_min': 10,
  693                 'port_range_max': 10}
  694         egress = mock.call.add_rule('ofake_dev',
  695                                     '-p udp -m udp --dport 10 -j RETURN',
  696                                     top=False, comment=None)
  697         ingress = None
  698         self._test_prepare_port_filter(rule, ingress, egress)
  699 
  700     def test_filter_ipv4_egress_udp_mport(self):
  701         rule = {'ethertype': 'IPv4',
  702                 'direction': 'egress',
  703                 'protocol': 'udp',
  704                 'port_range_min': 10,
  705                 'port_range_max': 100}
  706         egress = mock.call.add_rule(
  707             'ofake_dev',
  708             '-p udp -m udp -m multiport --dports 10:100 -j RETURN',
  709             top=False, comment=None)
  710         ingress = None
  711         self._test_prepare_port_filter(rule, ingress, egress)
  712 
  713     def test_filter_ipv4_egress_udp_mport_prefix(self):
  714         prefix = FAKE_PREFIX['IPv4']
  715         rule = {'ethertype': 'IPv4',
  716                 'direction': 'egress',
  717                 'protocol': 'udp',
  718                 'port_range_min': 10,
  719                 'port_range_max': 100,
  720                 'dest_ip_prefix': prefix}
  721         egress = mock.call.add_rule(
  722             'ofake_dev',
  723             '-d %s -p udp -m udp -m multiport --dports 10:100 '
  724             '-j RETURN' % prefix, top=False, comment=None)
  725         ingress = None
  726         self._test_prepare_port_filter(rule, ingress, egress)
  727 
  728     def test_filter_ipv6_ingress(self):
  729         rule = {'ethertype': 'IPv6',
  730                 'direction': 'ingress'}
  731         ingress = mock.call.add_rule('ifake_dev', '-j RETURN',
  732                                      top=False, comment=None)
  733         egress = None
  734         self._test_prepare_port_filter(rule, ingress, egress)
  735 
  736     def test_filter_ipv6_ingress_prefix(self):
  737         prefix = FAKE_PREFIX['IPv6']
  738         rule = {'ethertype': 'IPv6',
  739                 'direction': 'ingress',
  740                 'source_ip_prefix': prefix}
  741         ingress = mock.call.add_rule(
  742             'ifake_dev', '-s %s -j RETURN' % prefix, top=False, comment=None)
  743         egress = None
  744         self._test_prepare_port_filter(rule, ingress, egress)
  745 
  746     def test_filter_ipv6_ingress_tcp(self):
  747         rule = {'ethertype': 'IPv6',
  748                 'direction': 'ingress',
  749                 'protocol': 'tcp'}
  750         ingress = mock.call.add_rule(
  751             'ifake_dev', '-p tcp -j RETURN', top=False, comment=None)
  752         egress = None
  753         self._test_prepare_port_filter(rule, ingress, egress)
  754 
  755     def test_filter_ipv6_ingress_tcp_prefix(self):
  756         prefix = FAKE_PREFIX['IPv6']
  757         rule = {'ethertype': 'IPv6',
  758                 'direction': 'ingress',
  759                 'protocol': 'tcp',
  760                 'source_ip_prefix': prefix}
  761         ingress = mock.call.add_rule('ifake_dev',
  762                                      '-s %s -p tcp -j RETURN' % prefix,
  763                                      top=False, comment=None)
  764         egress = None
  765         self._test_prepare_port_filter(rule, ingress, egress)
  766 
  767     def test_filter_ipv6_ingress_tcp_port(self):
  768         rule = {'ethertype': 'IPv6',
  769                 'direction': 'ingress',
  770                 'protocol': 'tcp',
  771                 'port_range_min': 10,
  772                 'port_range_max': 10}
  773         ingress = mock.call.add_rule('ifake_dev',
  774                                      '-p tcp -m tcp --dport 10 -j RETURN',
  775                                      top=False, comment=None)
  776         egress = None
  777         self._test_prepare_port_filter(rule, ingress, egress)
  778 
  779     def test_filter_ipv6_ingress_icmp(self):
  780         rule = {'ethertype': 'IPv6',
  781                 'direction': 'ingress',
  782                 'protocol': 'icmp'}
  783         ingress = mock.call.add_rule(
  784             'ifake_dev', '-p ipv6-icmp -j RETURN', top=False, comment=None)
  785         egress = None
  786         self._test_prepare_port_filter(rule, ingress, egress)
  787 
  788     def test_filter_ipv6_ingress_icmp_prefix(self):
  789         prefix = FAKE_PREFIX['IPv6']
  790         rule = {'ethertype': 'IPv6',
  791                 'direction': 'ingress',
  792                 'protocol': 'icmp',
  793                 'source_ip_prefix': prefix}
  794         ingress = mock.call.add_rule(
  795             'ifake_dev', '-s %s -p ipv6-icmp -j RETURN' % prefix,
  796             top=False, comment=None)
  797         egress = None
  798         self._test_prepare_port_filter(rule, ingress, egress)
  799 
  800     def test_filter_ipv6_ingress_tcp_mport(self):
  801         rule = {'ethertype': 'IPv6',
  802                 'direction': 'ingress',
  803                 'protocol': 'tcp',
  804                 'port_range_min': 10,
  805                 'port_range_max': 100}
  806         ingress = mock.call.add_rule(
  807             'ifake_dev',
  808             '-p tcp -m tcp -m multiport --dports 10:100 -j RETURN',
  809             top=False, comment=None)
  810         egress = None
  811         self._test_prepare_port_filter(rule, ingress, egress)
  812 
  813     def _test_filter_ingress_tcp_min_port_0(self, ethertype):
  814         rule = {'ethertype': ethertype,
  815                 'direction': 'ingress',
  816                 'protocol': 'tcp',
  817                 'port_range_min': 0,
  818                 'port_range_max': 100}
  819         ingress = mock.call.add_rule(
  820             'ifake_dev',
  821             '-p tcp -m tcp -m multiport --dports 0:100 -j RETURN',
  822             top=False, comment=None)
  823         egress = None
  824         self._test_prepare_port_filter(rule, ingress, egress)
  825 
  826     def test_filter_ingress_tcp_min_port_0_for_ipv4(self):
  827         self._test_filter_ingress_tcp_min_port_0('IPv4')
  828 
  829     def test_filter_ingress_tcp_min_port_0_for_ipv6(self):
  830         self._test_filter_ingress_tcp_min_port_0('IPv6')
  831 
  832     def test_filter_ipv6_ingress_tcp_mport_prefix(self):
  833         prefix = FAKE_PREFIX['IPv6']
  834         rule = {'ethertype': 'IPv6',
  835                 'direction': 'ingress',
  836                 'protocol': 'tcp',
  837                 'port_range_min': 10,
  838                 'port_range_max': 100,
  839                 'source_ip_prefix': prefix}
  840         ingress = mock.call.add_rule(
  841             'ifake_dev',
  842             '-s %s -p tcp -m tcp -m multiport --dports 10:100 '
  843             '-j RETURN' % prefix, top=False, comment=None)
  844         egress = None
  845         self._test_prepare_port_filter(rule, ingress, egress)
  846 
  847     def test_filter_ipv6_ingress_udp(self):
  848         rule = {'ethertype': 'IPv6',
  849                 'direction': 'ingress',
  850                 'protocol': 'udp'}
  851         ingress = mock.call.add_rule(
  852             'ifake_dev', '-p udp -j RETURN', top=False, comment=None)
  853         egress = None
  854         self._test_prepare_port_filter(rule, ingress, egress)
  855 
  856     def test_filter_ipv6_ingress_udp_prefix(self):
  857         prefix = FAKE_PREFIX['IPv6']
  858         rule = {'ethertype': 'IPv6',
  859                 'direction': 'ingress',
  860                 'protocol': 'udp',
  861                 'source_ip_prefix': prefix}
  862         ingress = mock.call.add_rule('ifake_dev',
  863                                      '-s %s -p udp -j RETURN' % prefix,
  864                                      top=False, comment=None)
  865         egress = None
  866         self._test_prepare_port_filter(rule, ingress, egress)
  867 
  868     def test_filter_ipv6_ingress_udp_port(self):
  869         rule = {'ethertype': 'IPv6',
  870                 'direction': 'ingress',
  871                 'protocol': 'udp',
  872                 'port_range_min': 10,
  873                 'port_range_max': 10}
  874         ingress = mock.call.add_rule('ifake_dev',
  875                                      '-p udp -m udp --dport 10 -j RETURN',
  876                                      top=False, comment=None)
  877         egress = None
  878         self._test_prepare_port_filter(rule, ingress, egress)
  879 
  880     def test_filter_ipv6_ingress_udp_mport(self):
  881         rule = {'ethertype': 'IPv6',
  882                 'direction': 'ingress',
  883                 'protocol': 'udp',
  884                 'port_range_min': 10,
  885                 'port_range_max': 100}
  886         ingress = mock.call.add_rule(
  887             'ifake_dev',
  888             '-p udp -m udp -m multiport --dports 10:100 -j RETURN',
  889             top=False, comment=None)
  890         egress = None
  891         self._test_prepare_port_filter(rule, ingress, egress)
  892 
  893     def test_filter_ipv6_ingress_udp_mport_prefix(self):
  894         prefix = FAKE_PREFIX['IPv6']
  895         rule = {'ethertype': 'IPv6',
  896                 'direction': 'ingress',
  897                 'protocol': 'udp',
  898                 'port_range_min': 10,
  899                 'port_range_max': 100,
  900                 'source_ip_prefix': prefix}
  901         ingress = mock.call.add_rule(
  902             'ifake_dev',
  903             '-s %s -p udp -m udp -m multiport --dports 10:100 '
  904             '-j RETURN' % prefix, top=False, comment=None)
  905         egress = None
  906         self._test_prepare_port_filter(rule, ingress, egress)
  907 
  908     def test_filter_ipv6_egress(self):
  909         rule = {'ethertype': 'IPv6',
  910                 'direction': 'egress'}
  911         egress = mock.call.add_rule('ofake_dev', '-j RETURN',
  912                                     top=False, comment=None)
  913         ingress = None
  914         self._test_prepare_port_filter(rule, ingress, egress)
  915 
  916     def test_filter_ipv6_egress_prefix(self):
  917         prefix = FAKE_PREFIX['IPv6']
  918         rule = {'ethertype': 'IPv6',
  919                 'direction': 'egress',
  920                 'dest_ip_prefix': prefix}
  921         egress = mock.call.add_rule(
  922             'ofake_dev', '-d %s -j RETURN' % prefix, top=False, comment=None)
  923         ingress = None
  924         self._test_prepare_port_filter(rule, ingress, egress)
  925 
  926     def test_filter_ipv6_egress_tcp(self):
  927         rule = {'ethertype': 'IPv6',
  928                 'direction': 'egress',
  929                 'protocol': 'tcp'}
  930         egress = mock.call.add_rule(
  931             'ofake_dev', '-p tcp -j RETURN', top=False, comment=None)
  932         ingress = None
  933         self._test_prepare_port_filter(rule, ingress, egress)
  934 
  935     def test_filter_ipv6_egress_tcp_prefix(self):
  936         prefix = FAKE_PREFIX['IPv6']
  937         rule = {'ethertype': 'IPv6',
  938                 'direction': 'egress',
  939                 'protocol': 'tcp',
  940                 'dest_ip_prefix': prefix}
  941         egress = mock.call.add_rule('ofake_dev',
  942                                     '-d %s -p tcp -j RETURN' % prefix,
  943                                     top=False, comment=None)
  944         ingress = None
  945         self._test_prepare_port_filter(rule, ingress, egress)
  946 
  947     def test_filter_ipv6_egress_icmp(self):
  948         rule = {'ethertype': 'IPv6',
  949                 'direction': 'egress',
  950                 'protocol': 'icmp'}
  951         egress = mock.call.add_rule(
  952             'ofake_dev', '-p ipv6-icmp -j RETURN', top=False, comment=None)
  953         ingress = None
  954         self._test_prepare_port_filter(rule, ingress, egress)
  955 
  956     def test_filter_ipv6_egress_icmp_prefix(self):
  957         prefix = FAKE_PREFIX['IPv6']
  958         rule = {'ethertype': 'IPv6',
  959                 'direction': 'egress',
  960                 'protocol': 'icmp',
  961                 'dest_ip_prefix': prefix}
  962         egress = mock.call.add_rule(
  963             'ofake_dev', '-d %s -p ipv6-icmp -j RETURN' % prefix,
  964             top=False, comment=None)
  965         ingress = None
  966         self._test_prepare_port_filter(rule, ingress, egress)
  967 
  968     def test_filter_ipv6_egress_icmp_type(self):
  969         prefix = FAKE_PREFIX['IPv6']
  970         rule = {'ethertype': 'IPv6',
  971                 'direction': 'egress',
  972                 'protocol': 'icmp',
  973                 'port_range_min': 8,
  974                 'dest_ip_prefix': prefix}
  975         egress = mock.call.add_rule(
  976             'ofake_dev',
  977             '-d %s -p ipv6-icmp -m icmp6 --icmpv6-type 8 -j RETURN' % prefix,
  978             top=False, comment=None)
  979         ingress = None
  980         self._test_prepare_port_filter(rule, ingress, egress)
  981 
  982     def test_filter_ipv6_egress_icmp_type_name(self):
  983         prefix = FAKE_PREFIX['IPv6']
  984         rule = {'ethertype': 'IPv6',
  985                 'direction': 'egress',
  986                 'protocol': 'icmp',
  987                 'port_range_min': 'echo-request',
  988                 'dest_ip_prefix': prefix}
  989         egress = mock.call.add_rule(
  990             'ofake_dev',
  991             '-d %s -p ipv6-icmp -m icmp6 --icmpv6-type echo-request '
  992             '-j RETURN' % prefix,
  993             top=False, comment=None)
  994         ingress = None
  995         self._test_prepare_port_filter(rule, ingress, egress)
  996 
  997     def test_filter_ipv6_egress_icmp_type_code(self):
  998         prefix = FAKE_PREFIX['IPv6']
  999         rule = {'ethertype': 'IPv6',
 1000                 'direction': 'egress',
 1001                 'protocol': 'icmp',
 1002                 'port_range_min': 8,
 1003                 'port_range_max': 0,
 1004                 'dest_ip_prefix': prefix}
 1005         egress = mock.call.add_rule(
 1006             'ofake_dev',
 1007             '-d %s -p ipv6-icmp -m icmp6 --icmpv6-type 8/0 -j RETURN' % prefix,
 1008             top=False, comment=None)
 1009         ingress = None
 1010         self._test_prepare_port_filter(rule, ingress, egress)
 1011 
 1012     def test_filter_ipv6_egress_icmp_type_code_protocol_num(self):
 1013         prefix = FAKE_PREFIX['IPv6']
 1014         rule = {'ethertype': 'IPv6',
 1015                 'direction': 'egress',
 1016                 'protocol': '58',
 1017                 'port_range_min': 8,
 1018                 'port_range_max': 0,
 1019                 'dest_ip_prefix': prefix}
 1020         egress = mock.call.add_rule(
 1021             'ofake_dev',
 1022             '-d %s -p ipv6-icmp -m icmp6 --icmpv6-type 8/0 -j RETURN' % prefix,
 1023             top=False, comment=None)
 1024         ingress = None
 1025         self._test_prepare_port_filter(rule, ingress, egress)
 1026 
 1027     def test_filter_ipv6_egress_icmp_type_code_protocol_legacy_name(self):
 1028         prefix = FAKE_PREFIX['IPv6']
 1029         rule = {'ethertype': 'IPv6',
 1030                 'direction': 'egress',
 1031                 'protocol': 'icmpv6',
 1032                 'port_range_min': 8,
 1033                 'port_range_max': 0,
 1034                 'dest_ip_prefix': prefix}
 1035         egress = mock.call.add_rule(
 1036             'ofake_dev',
 1037             '-d %s -p ipv6-icmp -m icmp6 --icmpv6-type 8/0 -j RETURN' % prefix,
 1038             top=False, comment=None)
 1039         ingress = None
 1040         self._test_prepare_port_filter(rule, ingress, egress)
 1041 
 1042     def test_filter_ipv6_egress_tcp_port(self):
 1043         rule = {'ethertype': 'IPv6',
 1044                 'direction': 'egress',
 1045                 'protocol': 'tcp',
 1046                 'port_range_min': 10,
 1047                 'port_range_max': 10}
 1048         egress = mock.call.add_rule('ofake_dev',
 1049                                     '-p tcp -m tcp --dport 10 -j RETURN',
 1050                                     top=False, comment=None)
 1051         ingress = None
 1052         self._test_prepare_port_filter(rule, ingress, egress)
 1053 
 1054     def test_filter_ipv6_egress_tcp_mport(self):
 1055         rule = {'ethertype': 'IPv6',
 1056                 'direction': 'egress',
 1057                 'protocol': 'tcp',
 1058                 'port_range_min': 10,
 1059                 'port_range_max': 100}
 1060         egress = mock.call.add_rule(
 1061             'ofake_dev',
 1062             '-p tcp -m tcp -m multiport --dports 10:100 -j RETURN',
 1063             top=False, comment=None)
 1064         ingress = None
 1065         self._test_prepare_port_filter(rule, ingress, egress)
 1066 
 1067     def test_filter_ipv6_egress_tcp_mport_prefix(self):
 1068         prefix = FAKE_PREFIX['IPv6']
 1069         rule = {'ethertype': 'IPv6',
 1070                 'direction': 'egress',
 1071                 'protocol': 'tcp',
 1072                 'port_range_min': 10,
 1073                 'port_range_max': 100,
 1074                 'dest_ip_prefix': prefix}
 1075         egress = mock.call.add_rule(
 1076             'ofake_dev',
 1077             '-d %s -p tcp -m tcp -m multiport --dports 10:100 '
 1078             '-j RETURN' % prefix, top=False, comment=None)
 1079         ingress = None
 1080         self._test_prepare_port_filter(rule, ingress, egress)
 1081 
 1082     def test_filter_ipv6_egress_udp(self):
 1083         rule = {'ethertype': 'IPv6',
 1084                 'direction': 'egress',
 1085                 'protocol': 'udp'}
 1086         egress = mock.call.add_rule(
 1087             'ofake_dev', '-p udp -j RETURN', top=False, comment=None)
 1088         ingress = None
 1089         self._test_prepare_port_filter(rule, ingress, egress)
 1090 
 1091     def test_filter_ipv6_egress_udp_prefix(self):
 1092         prefix = FAKE_PREFIX['IPv6']
 1093         rule = {'ethertype': 'IPv6',
 1094                 'direction': 'egress',
 1095                 'protocol': 'udp',
 1096                 'dest_ip_prefix': prefix}
 1097         egress = mock.call.add_rule('ofake_dev',
 1098                                     '-d %s -p udp -j RETURN' % prefix,
 1099                                     top=False, comment=None)
 1100         ingress = None
 1101         self._test_prepare_port_filter(rule, ingress, egress)
 1102 
 1103     def test_filter_ipv6_egress_udp_port(self):
 1104         rule = {'ethertype': 'IPv6',
 1105                 'direction': 'egress',
 1106                 'protocol': 'udp',
 1107                 'port_range_min': 10,
 1108                 'port_range_max': 10}
 1109         egress = mock.call.add_rule('ofake_dev',
 1110                                     '-p udp -m udp --dport 10 -j RETURN',
 1111                                     top=False, comment=None)
 1112         ingress = None
 1113         self._test_prepare_port_filter(rule, ingress, egress)
 1114 
 1115     def test_filter_ipv6_egress_udp_mport(self):
 1116         rule = {'ethertype': 'IPv6',
 1117                 'direction': 'egress',
 1118                 'protocol': 'udp',
 1119                 'port_range_min': 10,
 1120                 'port_range_max': 100}
 1121         egress = mock.call.add_rule(
 1122             'ofake_dev',
 1123             '-p udp -m udp -m multiport --dports 10:100 -j RETURN',
 1124             top=False, comment=None)
 1125         ingress = None
 1126         self._test_prepare_port_filter(rule, ingress, egress)
 1127 
 1128     def test_filter_ipv6_egress_udp_mport_prefix(self):
 1129         prefix = FAKE_PREFIX['IPv6']
 1130         rule = {'ethertype': 'IPv6',
 1131                 'direction': 'egress',
 1132                 'protocol': 'udp',
 1133                 'port_range_min': 10,
 1134                 'port_range_max': 100,
 1135                 'dest_ip_prefix': prefix}
 1136         egress = mock.call.add_rule(
 1137             'ofake_dev',
 1138             '-d %s -p udp -m udp -m multiport --dports 10:100 '
 1139             '-j RETURN' % prefix, top=False, comment=None)
 1140         ingress = None
 1141         self._test_prepare_port_filter(rule, ingress, egress)
 1142 
 1143     def _test_process_trusted_ports(self, configured):
 1144         port = self._fake_port()
 1145         port['id'] = 'tapfake_dev'
 1146 
 1147         calls = [
 1148             mock.call.add_chain('sg-fallback'),
 1149             mock.call.add_rule('sg-fallback',
 1150                                '-j DROP', comment=ic.UNMATCH_DROP)]
 1151 
 1152         if configured:
 1153             self.firewall.trusted_ports.append(port['id'])
 1154         else:
 1155             calls.append(
 1156                 mock.call.add_rule('FORWARD',
 1157                                    '-m physdev --physdev-out tapfake_dev '
 1158                                    '--physdev-is-bridged -j ACCEPT',
 1159                                    top=False, comment=ic.TRUSTED_ACCEPT))
 1160             calls.append(
 1161                 mock.call.add_rule('FORWARD',
 1162                                    '-m physdev --physdev-in tapfake_dev '
 1163                                    '--physdev-is-bridged -j ACCEPT',
 1164                                    top=False, comment=ic.TRUSTED_ACCEPT))
 1165 
 1166         self.firewall.process_trusted_ports([port['id']])
 1167 
 1168         for filter_inst in [self.v4filter_inst, self.v6filter_inst]:
 1169             comb = zip(calls, filter_inst.mock_calls)
 1170             for (l, r) in comb:
 1171                 self.assertEqual(l, r)
 1172             filter_inst.assert_has_calls(calls)
 1173         self.assertIn(port['id'], self.firewall.trusted_ports)
 1174 
 1175     def test_process_trusted_ports(self):
 1176         self._test_process_trusted_ports(False)
 1177 
 1178     def test_process_trusted_ports_already_configured(self):
 1179         self._test_process_trusted_ports(True)
 1180 
 1181     def _test_remove_trusted_ports(self, configured):
 1182         port = self._fake_port()
 1183         port['id'] = 'tapfake_dev'
 1184 
 1185         calls = [
 1186             mock.call.add_chain('sg-fallback'),
 1187             mock.call.add_rule('sg-fallback',
 1188                                '-j DROP', comment=ic.UNMATCH_DROP)]
 1189 
 1190         if configured:
 1191             self.firewall.trusted_ports.append(port['id'])
 1192             calls.append(
 1193                 mock.call.remove_rule('FORWARD',
 1194                                       '-m physdev --physdev-out tapfake_dev '
 1195                                       '--physdev-is-bridged -j ACCEPT'))
 1196             calls.append(
 1197                 mock.call.remove_rule('FORWARD',
 1198                                       '-m physdev --physdev-in tapfake_dev '
 1199                                       '--physdev-is-bridged -j ACCEPT'))
 1200 
 1201         self.firewall.remove_trusted_ports([port['id']])
 1202 
 1203         for filter_inst in [self.v4filter_inst, self.v6filter_inst]:
 1204             comb = zip(calls, filter_inst.mock_calls)
 1205             for (l, r) in comb:
 1206                 self.assertEqual(l, r)
 1207             filter_inst.assert_has_calls(calls)
 1208         self.assertNotIn(port['id'], self.firewall.trusted_ports)
 1209 
 1210     def test_remove_trusted_ports(self):
 1211         self._test_remove_trusted_ports(True)
 1212 
 1213     def test_process_remove_ports_not_configured(self):
 1214         self._test_remove_trusted_ports(False)
 1215 
 1216     def _test_prepare_port_filter(self,
 1217                                   rule,
 1218                                   ingress_expected_call=None,
 1219                                   egress_expected_call=None):
 1220         port = self._fake_port()
 1221         ethertype = rule['ethertype']
 1222         prefix = utils.ip_to_cidr(FAKE_IP[ethertype])
 1223         filter_inst = self.v4filter_inst
 1224         dhcp_rule = [mock.call.add_rule(
 1225             'ofake_dev',
 1226             '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp '
 1227             '--sport 68 --dport 67 -j RETURN',
 1228             top=False, comment=None)]
 1229 
 1230         if ethertype == 'IPv6':
 1231             filter_inst = self.v6filter_inst
 1232 
 1233             dhcp_rule = [mock.call.add_rule('ofake_dev',
 1234                                             '-s ::/128 -d ff02::/16 '
 1235                                             '-p ipv6-icmp -m icmp6 '
 1236                                             '--icmpv6-type %s -j RETURN' %
 1237                                             icmp6_type, top=False,
 1238                                             comment=None) for icmp6_type
 1239                          in constants.ICMPV6_ALLOWED_UNSPEC_ADDR_TYPES]
 1240         sg = [rule]
 1241         port['security_group_rules'] = sg
 1242         self.firewall.prepare_port_filter(port)
 1243         calls = [mock.call.add_chain('sg-fallback'),
 1244                  mock.call.add_rule(
 1245                      'sg-fallback',
 1246                      '-j DROP',
 1247                      comment=ic.UNMATCH_DROP),
 1248                  mock.call.add_chain('sg-chain'),
 1249                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1250                                     comment=None),
 1251                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1252                                     comment=None),
 1253                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1254                                     comment=None),
 1255                  mock.call.add_chain('ifake_dev'),
 1256                  mock.call.add_rule('FORWARD',
 1257                                     '-m physdev --physdev-out tapfake_dev '
 1258                                     '--physdev-is-bridged -j $sg-chain',
 1259                                     top=True, comment=ic.VM_INT_SG),
 1260                  mock.call.add_rule('sg-chain',
 1261                                     '-m physdev --physdev-out tapfake_dev '
 1262                                     '--physdev-is-bridged -j $ifake_dev',
 1263                                     top=False, comment=ic.SG_TO_VM_SG)
 1264                  ]
 1265         if ethertype == 'IPv6':
 1266             for icmp6_type in firewall.ICMPV6_ALLOWED_INGRESS_TYPES:
 1267                 calls.append(
 1268                     mock.call.add_rule('ifake_dev',
 1269                                        '-p ipv6-icmp -m icmp6 --icmpv6-type '
 1270                                        '%s -j RETURN' %
 1271                                        icmp6_type, top=False, comment=None))
 1272         calls += [
 1273             mock.call.add_rule(
 1274                 'ifake_dev',
 1275                 '-m state --state RELATED,ESTABLISHED -j RETURN',
 1276                 top=False, comment=None
 1277             )
 1278         ]
 1279 
 1280         if ingress_expected_call:
 1281             calls.append(ingress_expected_call)
 1282 
 1283         calls += [mock.call.add_rule(
 1284                       'ifake_dev',
 1285                       '-m state --state INVALID -j DROP',
 1286                       top=False, comment=None),
 1287                   mock.call.add_rule('ifake_dev',
 1288                                      '-j $sg-fallback',
 1289                                      top=False, comment=None),
 1290                   mock.call.add_chain('ofake_dev'),
 1291                   mock.call.add_rule('FORWARD',
 1292                                      '-m physdev --physdev-in tapfake_dev '
 1293                                      '--physdev-is-bridged -j $sg-chain',
 1294                                      top=True, comment=ic.VM_INT_SG),
 1295                   mock.call.add_rule('sg-chain',
 1296                                      '-m physdev --physdev-in tapfake_dev '
 1297                                      '--physdev-is-bridged -j $ofake_dev',
 1298                                      top=False, comment=ic.SG_TO_VM_SG),
 1299                   mock.call.add_rule('INPUT',
 1300                                      '-m physdev --physdev-in tapfake_dev '
 1301                                      '--physdev-is-bridged -j $ofake_dev',
 1302                                      top=False, comment=ic.INPUT_TO_SG),
 1303                   mock.call.add_chain('sfake_dev'),
 1304                   mock.call.add_rule(
 1305                       'sfake_dev',
 1306                       '-s %s -m mac --mac-source FF:FF:FF:FF:FF:FF -j RETURN'
 1307                       % prefix,
 1308                       comment=ic.PAIR_ALLOW)]
 1309 
 1310         if ethertype == 'IPv6':
 1311             calls.append(mock.call.add_rule('sfake_dev',
 1312                 '-s fe80::fdff:ffff:feff:ffff/128 -m mac '
 1313                 '--mac-source FF:FF:FF:FF:FF:FF -j RETURN',
 1314                 comment=ic.PAIR_ALLOW))
 1315         calls.append(mock.call.add_rule('sfake_dev', '-j DROP',
 1316                                         comment=ic.PAIR_DROP))
 1317         calls += dhcp_rule
 1318         calls.append(mock.call.add_rule('ofake_dev', '-j $sfake_dev',
 1319                                         top=False, comment=None))
 1320         if ethertype == 'IPv4':
 1321             calls.append(mock.call.add_rule(
 1322                 'ofake_dev',
 1323                 '-p udp -m udp --sport 68 --dport 67 -j RETURN',
 1324                 top=False, comment=None))
 1325             calls.append(mock.call.add_rule(
 1326                 'ofake_dev',
 1327                 '-p udp -m udp --sport 67 --dport 68 -j DROP',
 1328                 top=False, comment=None))
 1329         if ethertype == 'IPv6':
 1330             calls.append(mock.call.add_rule('ofake_dev',
 1331                                             '-p ipv6-icmp -m icmp6 '
 1332                                             '--icmpv6-type %s -j DROP' %
 1333                                             constants.ICMPV6_TYPE_RA,
 1334                                             top=False, comment=None))
 1335             calls.append(mock.call.add_rule('ofake_dev',
 1336                                             '-p ipv6-icmp -j RETURN',
 1337                                             top=False, comment=None))
 1338             calls.append(mock.call.add_rule('ofake_dev', '-p udp -m udp '
 1339                                             '--sport 546 --dport 547 '
 1340                                             '-j RETURN',
 1341                                             top=False, comment=None))
 1342             calls.append(mock.call.add_rule(
 1343                 'ofake_dev',
 1344                 '-p udp -m udp --sport 547 --dport 546 -j DROP',
 1345                 top=False, comment=None))
 1346 
 1347         calls += [
 1348             mock.call.add_rule(
 1349                 'ofake_dev',
 1350                 '-m state --state RELATED,ESTABLISHED -j RETURN',
 1351                 top=False, comment=None),
 1352         ]
 1353 
 1354         if egress_expected_call:
 1355             calls.append(egress_expected_call)
 1356 
 1357         calls += [mock.call.add_rule(
 1358                       'ofake_dev',
 1359                       '-m state --state INVALID -j DROP',
 1360                       top=False, comment=None),
 1361                   mock.call.add_rule('ofake_dev',
 1362                                      '-j $sg-fallback',
 1363                                      top=False, comment=None),
 1364                   mock.call.add_rule('sg-chain', '-j ACCEPT')]
 1365         comb = zip(calls, filter_inst.mock_calls)
 1366         for (l, r) in comb:
 1367             self.assertEqual(l, r)
 1368         filter_inst.assert_has_calls(calls)
 1369 
 1370     def _test_remove_conntrack_entries(self, ethertype, protocol, direction,
 1371                                        ct_zone):
 1372         port = self._fake_port()
 1373         port['security_groups'] = 'fake_sg_id'
 1374         self.firewall.filtered_ports[port['device']] = port
 1375         self.firewall.updated_rule_sg_ids = set(['fake_sg_id'])
 1376         self.firewall.sg_rules['fake_sg_id'] = [
 1377             {'direction': direction, 'ethertype': ethertype,
 1378              'protocol': protocol}]
 1379 
 1380         with mock.patch.dict(self.firewall.ipconntrack._device_zone_map,
 1381                              {port['network_id']: ct_zone}):
 1382             self.firewall.filter_defer_apply_on()
 1383             self.firewall.sg_rules['fake_sg_id'] = []
 1384             self.firewall.filter_defer_apply_off()
 1385             if not ct_zone:
 1386                 self.assertFalse(self.utils_exec.called)
 1387                 return
 1388             # process conntrack updates in the queue
 1389             while not self.firewall.ipconntrack._queue.empty():
 1390                 self.firewall.ipconntrack._process_queue()
 1391             cmd = ['conntrack', '-D']
 1392             if protocol:
 1393                 cmd.extend(['-p', protocol])
 1394             if ethertype == 'IPv4':
 1395                 cmd.extend(['-f', 'ipv4'])
 1396                 if direction == 'ingress':
 1397                     cmd.extend(['-d', '10.0.0.1'])
 1398                 else:
 1399                     cmd.extend(['-s', '10.0.0.1'])
 1400             else:
 1401                 cmd.extend(['-f', 'ipv6'])
 1402                 if direction == 'ingress':
 1403                     cmd.extend(['-d', 'fe80::1'])
 1404                 else:
 1405                     cmd.extend(['-s', 'fe80::1'])
 1406 
 1407             cmd.extend(['-w', ct_zone])
 1408             calls = [
 1409                 mock.call(cmd, run_as_root=True, check_exit_code=True,
 1410                           extra_ok_codes=[1])]
 1411             self.utils_exec.assert_has_calls(calls)
 1412 
 1413     def test_remove_conntrack_entries_for_delete_rule_ipv4(self):
 1414         for direction in ['ingress', 'egress']:
 1415             for pro in [None, 'tcp', 'icmp', 'udp']:
 1416                 self._test_remove_conntrack_entries(
 1417                     'IPv4', pro, direction, ct_zone=10)
 1418 
 1419     def test_remove_conntrack_entries_for_delete_rule_ipv4_no_ct_zone(self):
 1420         for direction in ['ingress', 'egress']:
 1421             for pro in [None, 'tcp', 'icmp', 'udp']:
 1422                 self._test_remove_conntrack_entries(
 1423                     'IPv4', pro, direction, ct_zone=None)
 1424 
 1425     def test_remove_conntrack_entries_for_delete_rule_ipv6(self):
 1426         for direction in ['ingress', 'egress']:
 1427             for pro in [None, 'tcp', 'icmp', 'udp']:
 1428                 self._test_remove_conntrack_entries(
 1429                     'IPv6', pro, direction, ct_zone=10)
 1430 
 1431     def test_remove_conntrack_entries_for_delete_rule_ipv6_no_ct_zone(self):
 1432         for direction in ['ingress', 'egress']:
 1433             for pro in [None, 'tcp', 'icmp', 'udp']:
 1434                 self._test_remove_conntrack_entries(
 1435                     'IPv6', pro, direction, ct_zone=None)
 1436 
 1437     def test_remove_conntrack_entries_for_port_sec_group_change(self):
 1438         self._test_remove_conntrack_entries_for_port_sec_group_change(
 1439             ct_zone=10)
 1440 
 1441     def test_remove_conntrack_entries_for_port_sec_group_change_no_ct_zone(
 1442         self):
 1443 
 1444         self._test_remove_conntrack_entries_for_port_sec_group_change(
 1445             ct_zone=None)
 1446 
 1447     def _get_expected_conntrack_calls(self, ips, ct_zone):
 1448         expected_calls = []
 1449         for ip_item in ips:
 1450             proto = ip_item[0]
 1451             ip = ip_item[1]
 1452             for direction in ['-d', '-s']:
 1453                 cmd = ['conntrack', '-D', '-f', proto, direction, ip]
 1454                 if ct_zone:
 1455                     cmd.extend(['-w', ct_zone])
 1456                 expected_calls.append(
 1457                     mock.call(cmd, run_as_root=True, check_exit_code=True,
 1458                               extra_ok_codes=[1]))
 1459         return expected_calls
 1460 
 1461     def _test_remove_conntrack_entries_for_port_sec_group_change(self,
 1462                                                                  ct_zone):
 1463 
 1464         port = self._fake_port()
 1465         port['security_groups'] = ['fake_sg_id']
 1466         self.firewall.filtered_ports[port['device']] = port
 1467         self.firewall.updated_sg_members = set(['tapfake_dev'])
 1468         with mock.patch.dict(self.firewall.ipconntrack._device_zone_map,
 1469                              {port['network_id']: ct_zone}):
 1470             self.firewall.filter_defer_apply_on()
 1471             new_port = copy.deepcopy(port)
 1472             new_port['security_groups'] = ['fake_sg_id2']
 1473 
 1474             self.firewall.filtered_ports[port['device']] = new_port
 1475             self.firewall.filter_defer_apply_off()
 1476             if not ct_zone:
 1477                 self.assertFalse(self.utils_exec.called)
 1478                 return
 1479             # process conntrack updates in the queue
 1480             while not self.firewall.ipconntrack._queue.empty():
 1481                 self.firewall.ipconntrack._process_queue()
 1482             calls = self._get_expected_conntrack_calls(
 1483                 [('ipv4', '10.0.0.1'), ('ipv6', 'fe80::1')], ct_zone)
 1484             self.utils_exec.assert_has_calls(calls)
 1485 
 1486     def test_remove_conntrack_entries_for_sg_member_changed_ipv4(self):
 1487         for direction in ['ingress', 'egress']:
 1488             self._test_remove_conntrack_entries_sg_member_changed(
 1489                 'IPv4', direction, ct_zone=10)
 1490 
 1491     def test_remove_conntrack_entries_for_sg_member_changed_ipv4_no_ct_zone(
 1492         self):
 1493         for direction in ['ingress', 'egress']:
 1494             self._test_remove_conntrack_entries_sg_member_changed(
 1495                 'IPv4', direction, ct_zone=None)
 1496 
 1497     def test_remove_conntrack_entries_for_sg_member_changed_ipv6(self):
 1498         for direction in ['ingress', 'egress']:
 1499             self._test_remove_conntrack_entries_sg_member_changed(
 1500                 'IPv6', direction, ct_zone=10)
 1501 
 1502     def test_remove_conntrack_entries_for_sg_member_changed_ipv6_no_ct_zone(
 1503         self):
 1504         for direction in ['ingress', 'egress']:
 1505             self._test_remove_conntrack_entries_sg_member_changed(
 1506                 'IPv6', direction, ct_zone=None)
 1507 
 1508     def _test_remove_conntrack_entries_sg_member_changed(self, ethertype,
 1509                                                          direction, ct_zone):
 1510         port = self._fake_port()
 1511         port['security_groups'] = ['fake_sg_id']
 1512         port['security_group_source_groups'] = ['fake_sg_id2']
 1513         port['security_group_rules'] = [{'security_group_id': 'fake_sg_id',
 1514                                          'direction': direction,
 1515                                          'remote_group_id': 'fake_sg_id2',
 1516                                          'ethertype': ethertype}]
 1517         self.firewall.filtered_ports = {port['device']: port}
 1518 
 1519         if ethertype == "IPv4":
 1520             ethertype = "ipv4"
 1521             members_add = {'IPv4': ['10.0.0.2', '10.0.0.3']}
 1522             members_after_delete = {'IPv4': ['10.0.0.3']}
 1523         else:
 1524             ethertype = "ipv6"
 1525             members_add = {'IPv6': ['fe80::2', 'fe80::3']}
 1526             members_after_delete = {'IPv6': ['fe80::3']}
 1527 
 1528         with mock.patch.dict(self.firewall.ipconntrack._device_zone_map,
 1529                              {port['network_id']: ct_zone}):
 1530             # add ['10.0.0.2', '10.0.0.3'] or ['fe80::2', 'fe80::3']
 1531             self.firewall.security_group_updated('sg_member', ['fake_sg_id2'])
 1532             self.firewall.update_security_group_members(
 1533                 'fake_sg_id2', members_add)
 1534 
 1535             # delete '10.0.0.2' or 'fe80::2'
 1536             self.firewall.security_group_updated('sg_member', ['fake_sg_id2'])
 1537             self.firewall.update_security_group_members(
 1538                 'fake_sg_id2', members_after_delete)
 1539 
 1540             # check conntrack deletion from '10.0.0.1' to '10.0.0.2' or
 1541             # from 'fe80::1' to 'fe80::2'
 1542             ips = {"ipv4": ['10.0.0.1', '10.0.0.2'],
 1543                    "ipv6": ['fe80::1', 'fe80::2']}
 1544             calls = []
 1545             # process conntrack updates in the queue
 1546             while not self.firewall.ipconntrack._queue.empty():
 1547                 self.firewall.ipconntrack._process_queue()
 1548             for direction in ['ingress', 'egress']:
 1549                 direction = '-d' if direction == 'ingress' else '-s'
 1550                 remote_ip_direction = '-s' if direction == '-d' else '-d'
 1551                 conntrack_cmd = ['conntrack', '-D', '-f', ethertype,
 1552                                  direction, ips[ethertype][0]]
 1553                 if not ct_zone:
 1554                     continue
 1555                 conntrack_cmd.extend(['-w', 10])
 1556                 conntrack_cmd.extend([remote_ip_direction, ips[ethertype][1]])
 1557 
 1558                 calls.append(mock.call(conntrack_cmd,
 1559                                        run_as_root=True, check_exit_code=True,
 1560                                        extra_ok_codes=[1]))
 1561 
 1562         self.utils_exec.assert_has_calls(calls)
 1563 
 1564     def test_user_sg_rules_deduped_before_call_to_iptables_manager(self):
 1565         port = self._fake_port()
 1566         port['security_group_rules'] = [{'ethertype': 'IPv4',
 1567                                          'direction': 'ingress'}] * 2
 1568         self.firewall.prepare_port_filter(port)
 1569         rules = [''.join(c[1]) for c in self.v4filter_inst.add_rule.mock_calls]
 1570         self.assertEqual(len(set(rules)), len(rules))
 1571 
 1572     def test_update_delete_port_filter(self):
 1573         port = self._fake_port()
 1574         port['security_group_rules'] = [{'ethertype': 'IPv4',
 1575                                          'direction': 'ingress'}]
 1576         self.firewall.prepare_port_filter(port)
 1577         port['security_group_rules'] = [{'ethertype': 'IPv4',
 1578                                          'direction': 'egress'}]
 1579         self.firewall.update_port_filter(port)
 1580         self.firewall.update_port_filter({'device': 'no-exist-device'})
 1581         self.firewall.remove_port_filter(port)
 1582         self.firewall.remove_port_filter({'device': 'no-exist-device'})
 1583         calls = [mock.call.add_chain('sg-fallback'),
 1584                  mock.call.add_rule(
 1585                      'sg-fallback',
 1586                      '-j DROP',
 1587                      comment=ic.UNMATCH_DROP),
 1588                  mock.call.add_chain('sg-chain'),
 1589                  mock.call.add_rule('PREROUTING', mock.ANY,
 1590                                     comment=None),  # zone set
 1591                  mock.call.add_rule('PREROUTING', mock.ANY,
 1592                                     comment=None),  # zone set
 1593                  mock.call.add_rule('PREROUTING', mock.ANY,
 1594                                     comment=None),  # zone set
 1595                  mock.call.add_chain('ifake_dev'),
 1596                  mock.call.add_rule(
 1597                      'FORWARD',
 1598                      '-m physdev --physdev-out tapfake_dev '
 1599                      '--physdev-is-bridged -j $sg-chain',
 1600                      top=True, comment=ic.VM_INT_SG),
 1601                  mock.call.add_rule(
 1602                      'sg-chain',
 1603                      '-m physdev --physdev-out tapfake_dev '
 1604                      '--physdev-is-bridged -j $ifake_dev',
 1605                      top=False, comment=ic.SG_TO_VM_SG),
 1606                  mock.call.add_rule(
 1607                      'ifake_dev',
 1608                      '-m state --state RELATED,ESTABLISHED -j RETURN',
 1609                      top=False, comment=None),
 1610                  mock.call.add_rule('ifake_dev', '-j RETURN',
 1611                                     top=False, comment=None),
 1612                  mock.call.add_rule(
 1613                      'ifake_dev',
 1614                      '-m state --state INVALID -j DROP',
 1615                      top=False, comment=None),
 1616                  mock.call.add_rule('ifake_dev',
 1617                                     '-j $sg-fallback',
 1618                                     top=False, comment=None),
 1619                  mock.call.add_chain('ofake_dev'),
 1620                  mock.call.add_rule(
 1621                      'FORWARD',
 1622                      '-m physdev --physdev-in tapfake_dev '
 1623                      '--physdev-is-bridged -j $sg-chain',
 1624                      top=True, comment=ic.VM_INT_SG),
 1625                  mock.call.add_rule(
 1626                      'sg-chain',
 1627                      '-m physdev --physdev-in tapfake_dev '
 1628                      '--physdev-is-bridged -j $ofake_dev',
 1629                      top=False, comment=ic.SG_TO_VM_SG),
 1630                  mock.call.add_rule(
 1631                      'INPUT',
 1632                      '-m physdev --physdev-in tapfake_dev '
 1633                      '--physdev-is-bridged -j $ofake_dev',
 1634                      top=False, comment=ic.INPUT_TO_SG),
 1635                  mock.call.add_chain('sfake_dev'),
 1636                  mock.call.add_rule(
 1637                      'sfake_dev',
 1638                      '-s 10.0.0.1/32 -m mac --mac-source FF:FF:FF:FF:FF:FF '
 1639                      '-j RETURN',
 1640                      comment=ic.PAIR_ALLOW),
 1641                  mock.call.add_rule(
 1642                      'sfake_dev', '-j DROP',
 1643                      comment=ic.PAIR_DROP),
 1644                  mock.call.add_rule(
 1645                      'ofake_dev',
 1646                      '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp '
 1647                      '--sport 68 --dport 67 -j RETURN',
 1648                      top=False, comment=None),
 1649                  mock.call.add_rule('ofake_dev', '-j $sfake_dev',
 1650                                     top=False, comment=None),
 1651                  mock.call.add_rule(
 1652                      'ofake_dev',
 1653                      '-p udp -m udp --sport 68 --dport 67 -j RETURN',
 1654                      top=False, comment=None),
 1655                  mock.call.add_rule(
 1656                      'ofake_dev',
 1657                      '-p udp -m udp --sport 67 --dport 68 -j DROP',
 1658                      top=False, comment=None),
 1659                  mock.call.add_rule(
 1660                      'ofake_dev',
 1661                      '-m state --state RELATED,ESTABLISHED -j RETURN',
 1662                      top=False, comment=None),
 1663                  mock.call.add_rule(
 1664                      'ofake_dev', '-m state --state INVALID -j DROP',
 1665                      top=False, comment=None),
 1666                  mock.call.add_rule('ofake_dev',
 1667                                     '-j $sg-fallback',
 1668                                     top=False, comment=None),
 1669                  mock.call.add_rule('sg-chain', '-j ACCEPT'),
 1670                  mock.call.remove_chain('ifake_dev'),
 1671                  mock.call.remove_chain('ofake_dev'),
 1672                  mock.call.remove_chain('sfake_dev'),
 1673                  mock.call.remove_rule('PREROUTING', mock.ANY),  # zone set
 1674                  mock.call.remove_rule('PREROUTING', mock.ANY),  # zone set
 1675                  mock.call.remove_rule('PREROUTING', mock.ANY),  # zone set
 1676                  mock.call.remove_chain('sg-chain'),
 1677                  mock.call.add_chain('sg-chain'),
 1678                  mock.call.add_rule('PREROUTING', mock.ANY,
 1679                                     comment=None),  # zone set
 1680                  mock.call.add_rule('PREROUTING', mock.ANY,
 1681                                     comment=None),  # zone set
 1682                  mock.call.add_rule('PREROUTING', mock.ANY,
 1683                                     comment=None),  # zone set
 1684                  mock.call.add_chain('ifake_dev'),
 1685                  mock.call.add_rule(
 1686                      'FORWARD',
 1687                      '-m physdev --physdev-out tapfake_dev '
 1688                      '--physdev-is-bridged -j $sg-chain',
 1689                      top=True, comment=ic.VM_INT_SG),
 1690                  mock.call.add_rule(
 1691                      'sg-chain',
 1692                      '-m physdev --physdev-out tapfake_dev '
 1693                      '--physdev-is-bridged -j $ifake_dev',
 1694                      top=False, comment=ic.SG_TO_VM_SG),
 1695                  mock.call.add_rule(
 1696                      'ifake_dev',
 1697                      '-m state --state RELATED,ESTABLISHED -j RETURN',
 1698                      top=False, comment=None),
 1699                  mock.call.add_rule(
 1700                      'ifake_dev',
 1701                      '-m state --state INVALID -j DROP',
 1702                      top=False, comment=None),
 1703                  mock.call.add_rule('ifake_dev',
 1704                                     '-j $sg-fallback',
 1705                                     top=False, comment=None),
 1706                  mock.call.add_chain('ofake_dev'),
 1707                  mock.call.add_rule(
 1708                      'FORWARD',
 1709                      '-m physdev --physdev-in tapfake_dev '
 1710                      '--physdev-is-bridged -j $sg-chain',
 1711                      top=True, comment=ic.VM_INT_SG),
 1712                  mock.call.add_rule(
 1713                      'sg-chain',
 1714                      '-m physdev --physdev-in tapfake_dev '
 1715                      '--physdev-is-bridged -j $ofake_dev',
 1716                      top=False, comment=ic.SG_TO_VM_SG),
 1717                  mock.call.add_rule(
 1718                      'INPUT',
 1719                      '-m physdev --physdev-in tapfake_dev '
 1720                      '--physdev-is-bridged -j $ofake_dev',
 1721                      top=False, comment=ic.INPUT_TO_SG),
 1722                  mock.call.add_chain('sfake_dev'),
 1723                  mock.call.add_rule(
 1724                      'sfake_dev',
 1725                      '-s 10.0.0.1/32 -m mac --mac-source FF:FF:FF:FF:FF:FF '
 1726                      '-j RETURN',
 1727                      comment=ic.PAIR_ALLOW),
 1728                  mock.call.add_rule(
 1729                      'sfake_dev', '-j DROP',
 1730                      comment=ic.PAIR_DROP),
 1731                  mock.call.add_rule(
 1732                      'ofake_dev',
 1733                      '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp '
 1734                      '--sport 68 --dport 67 -j RETURN',
 1735                      top=False, comment=None),
 1736                  mock.call.add_rule('ofake_dev', '-j $sfake_dev',
 1737                                     top=False, comment=None),
 1738                  mock.call.add_rule(
 1739                      'ofake_dev',
 1740                      '-p udp -m udp --sport 68 --dport 67 -j RETURN',
 1741                      top=False, comment=None),
 1742                  mock.call.add_rule(
 1743                      'ofake_dev',
 1744                      '-p udp -m udp --sport 67 --dport 68 -j DROP',
 1745                      top=False, comment=None),
 1746                  mock.call.add_rule(
 1747                      'ofake_dev',
 1748                      '-m state --state RELATED,ESTABLISHED -j RETURN',
 1749                      top=False, comment=None),
 1750                  mock.call.add_rule('ofake_dev', '-j RETURN',
 1751                                     top=False, comment=None),
 1752                  mock.call.add_rule(
 1753                      'ofake_dev',
 1754                      '-m state --state INVALID -j DROP',
 1755                      top=False, comment=None),
 1756                  mock.call.add_rule('ofake_dev',
 1757                                     '-j $sg-fallback',
 1758                                     top=False, comment=None),
 1759                  mock.call.add_rule('sg-chain', '-j ACCEPT'),
 1760                  mock.call.remove_chain('ifake_dev'),
 1761                  mock.call.remove_chain('ofake_dev'),
 1762                  mock.call.remove_chain('sfake_dev'),
 1763                  mock.call.remove_rule('PREROUTING', mock.ANY),  # zone set
 1764                  mock.call.remove_rule('PREROUTING', mock.ANY),  # zone set
 1765                  mock.call.remove_rule('PREROUTING', mock.ANY),  # zone set
 1766                  mock.call.remove_chain('sg-chain'),
 1767                  mock.call.add_chain('sg-chain')]
 1768 
 1769         self.v4filter_inst.assert_has_calls(calls)
 1770 
 1771     def test_delete_conntrack_from_delete_port(self):
 1772         self._test_delete_conntrack_from_delete_port(ct_zone=10)
 1773 
 1774     def test_delete_conntrack_from_delete_port_no_ct_zone(self):
 1775         self._test_delete_conntrack_from_delete_port(ct_zone=None)
 1776 
 1777     def _test_delete_conntrack_from_delete_port(self, ct_zone):
 1778         port = self._fake_port()
 1779         port['security_groups'] = ['fake_sg_id']
 1780         self.firewall.filtered_ports = {'tapfake_dev': port}
 1781         self.firewall.devices_with_updated_sg_members['fake_sg_id2'
 1782                                                       ] = ['tapfake_dev']
 1783         new_port = copy.deepcopy(port)
 1784         new_port['security_groups'] = ['fake_sg_id2']
 1785         new_port['device'] = ['tapfake_dev2']
 1786         new_port['fixed_ips'] = ['10.0.0.2', 'fe80::2']
 1787         self.firewall.sg_members['fake_sg_id2'] = {'IPv4': ['10.0.0.2'],
 1788                                                    'IPv6': ['fe80::2']}
 1789         mock.patch.object(self.firewall.ipconntrack, 'get_device_zone',
 1790                           return_value=ct_zone).start()
 1791         self.firewall.remove_port_filter(port)
 1792         if not ct_zone:
 1793             self.assertFalse(self.utils_exec.called)
 1794             return
 1795         # process conntrack updates in the queue
 1796         while not self.firewall.ipconntrack._queue.empty():
 1797             self.firewall.ipconntrack._process_queue()
 1798         calls = self._get_expected_conntrack_calls(
 1799             [('ipv4', '10.0.0.1'), ('ipv6', 'fe80::1')], ct_zone)
 1800         self.utils_exec.assert_has_calls(calls)
 1801 
 1802     def test_remove_unknown_port(self):
 1803         port = self._fake_port()
 1804         self.firewall.remove_port_filter(port)
 1805         # checking no exception occurs
 1806         self.assertFalse(self.v4filter_inst.called)
 1807 
 1808     def test_defer_apply(self):
 1809         with self.firewall.defer_apply():
 1810             pass
 1811         self.iptables_inst.assert_has_calls([mock.call.defer_apply_on(),
 1812                                              mock.call.defer_apply_off()])
 1813 
 1814     def test_filter_defer_with_exception(self):
 1815         try:
 1816             with self.firewall.defer_apply():
 1817                 raise Exception("same exception")
 1818         except Exception:
 1819             pass
 1820         self.iptables_inst.assert_has_calls([mock.call.defer_apply_on(),
 1821                                              mock.call.defer_apply_off()])
 1822 
 1823     def _mock_chain_applies(self):
 1824         class CopyingMock(mock.MagicMock):
 1825             """Copies arguments so mutable arguments can be asserted on.
 1826 
 1827             Copied verbatim from unittest.mock documentation.
 1828             """
 1829             def __call__(self, *args, **kwargs):
 1830                 args = copy.deepcopy(args)
 1831                 kwargs = copy.deepcopy(kwargs)
 1832                 return super(CopyingMock, self).__call__(*args, **kwargs)
 1833         # Need to use CopyingMock because _{setup,remove}_chains_apply are
 1834         # usually called with that's modified between calls (i.e.,
 1835         # self.firewall.filtered_ports).
 1836         chain_applies = CopyingMock()
 1837         self.firewall._setup_chains_apply = chain_applies.setup
 1838         self.firewall._remove_chains_apply = chain_applies.remove
 1839         return chain_applies
 1840 
 1841     def test_mock_chain_applies(self):
 1842         chain_applies = self._mock_chain_applies()
 1843         port_prepare = {'device': 'd1', 'mac_address': 'prepare',
 1844                         'network_id': 'fake_net'}
 1845         port_update = {'device': 'd1', 'mac_address': 'update',
 1846                        'network_id': 'fake_net'}
 1847         self.firewall.prepare_port_filter(port_prepare)
 1848         self.firewall.update_port_filter(port_update)
 1849         self.firewall.remove_port_filter(port_update)
 1850         chain_applies.assert_has_calls([
 1851                                 mock.call.setup({'d1': port_prepare}, {}),
 1852                                 mock.call.remove({'d1': port_prepare}, {}),
 1853                                 mock.call.setup({'d1': port_update}, {}),
 1854                                 mock.call.remove({'d1': port_update}, {}),
 1855                                 mock.call.setup({}, {})])
 1856 
 1857     def test_defer_chain_apply_need_pre_defer_copy(self):
 1858         chain_applies = self._mock_chain_applies()
 1859         port = self._fake_port()
 1860         device2port = {port['device']: port}
 1861         self.firewall.prepare_port_filter(port)
 1862         with self.firewall.defer_apply():
 1863             self.firewall.remove_port_filter(port)
 1864         chain_applies.assert_has_calls([mock.call.setup(device2port, {}),
 1865                                         mock.call.remove(device2port, {}),
 1866                                         mock.call.setup({}, {})])
 1867 
 1868     def test_defer_chain_apply_coalesce_simple(self):
 1869         chain_applies = self._mock_chain_applies()
 1870         port = self._fake_port()
 1871         with self.firewall.defer_apply():
 1872             self.firewall.prepare_port_filter(port)
 1873             self.firewall.update_port_filter(port)
 1874             self.firewall.remove_port_filter(port)
 1875         chain_applies.assert_has_calls([mock.call.remove({}, {}),
 1876                                         mock.call.setup({}, {})])
 1877 
 1878     def test_defer_chain_apply_coalesce_multiple_ports(self):
 1879         chain_applies = self._mock_chain_applies()
 1880         port1 = {'device': 'd1', 'mac_address': 'mac1', 'network_id': 'net1'}
 1881         port2 = {'device': 'd2', 'mac_address': 'mac2', 'network_id': 'net1'}
 1882         device2port = {'d1': port1, 'd2': port2}
 1883         with self.firewall.defer_apply():
 1884             self.firewall.prepare_port_filter(port1)
 1885             self.firewall.prepare_port_filter(port2)
 1886         chain_applies.assert_has_calls([mock.call.remove({}, {}),
 1887                                         mock.call.setup(device2port, {})])
 1888 
 1889     def test_ip_spoofing_filter_with_multiple_ips(self):
 1890         port = {'device': 'tapfake_dev',
 1891                 'mac_address': 'ff:ff:ff:ff:ff:ff',
 1892                 'network_id': 'fake_net',
 1893                 'fixed_ips': ['10.0.0.1', 'fe80::1', '10.0.0.2']}
 1894         self.firewall.prepare_port_filter(port)
 1895         calls = [mock.call.add_chain('sg-fallback'),
 1896                  mock.call.add_rule(
 1897                      'sg-fallback', '-j DROP',
 1898                      comment=ic.UNMATCH_DROP),
 1899                  mock.call.add_chain('sg-chain'),
 1900                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1901                                     comment=None),
 1902                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1903                                     comment=None),
 1904                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1905                                     comment=None),
 1906                  mock.call.add_chain('ifake_dev'),
 1907                  mock.call.add_rule('FORWARD',
 1908                                     '-m physdev --physdev-out tapfake_dev '
 1909                                     '--physdev-is-bridged -j $sg-chain',
 1910                                     top=True, comment=ic.VM_INT_SG),
 1911                  mock.call.add_rule('sg-chain',
 1912                                     '-m physdev --physdev-out tapfake_dev '
 1913                                     '--physdev-is-bridged -j $ifake_dev',
 1914                                     top=False, comment=ic.SG_TO_VM_SG),
 1915                  mock.call.add_rule(
 1916                      'ifake_dev',
 1917                      '-m state --state RELATED,ESTABLISHED -j RETURN',
 1918                      top=False, comment=None),
 1919                  mock.call.add_rule(
 1920                      'ifake_dev',
 1921                      '-m state --state INVALID -j DROP',
 1922                      top=False, comment=None),
 1923                  mock.call.add_rule('ifake_dev',
 1924                                     '-j $sg-fallback',
 1925                                     top=False, comment=None),
 1926                  mock.call.add_chain('ofake_dev'),
 1927                  mock.call.add_rule('FORWARD',
 1928                                     '-m physdev --physdev-in tapfake_dev '
 1929                                     '--physdev-is-bridged -j $sg-chain',
 1930                                     top=True, comment=ic.VM_INT_SG),
 1931                  mock.call.add_rule('sg-chain',
 1932                                     '-m physdev --physdev-in tapfake_dev '
 1933                                     '--physdev-is-bridged -j $ofake_dev',
 1934                                     top=False, comment=ic.SG_TO_VM_SG),
 1935                  mock.call.add_rule('INPUT',
 1936                                     '-m physdev --physdev-in tapfake_dev '
 1937                                     '--physdev-is-bridged -j $ofake_dev',
 1938                                     top=False, comment=ic.INPUT_TO_SG),
 1939                  mock.call.add_chain('sfake_dev'),
 1940                  mock.call.add_rule(
 1941                      'sfake_dev',
 1942                      '-s 10.0.0.1/32 -m mac --mac-source FF:FF:FF:FF:FF:FF '
 1943                      '-j RETURN',
 1944                      comment=ic.PAIR_ALLOW),
 1945                  mock.call.add_rule(
 1946                      'sfake_dev',
 1947                      '-s 10.0.0.2/32 -m mac --mac-source FF:FF:FF:FF:FF:FF '
 1948                      '-j RETURN',
 1949                      comment=ic.PAIR_ALLOW),
 1950                  mock.call.add_rule(
 1951                      'sfake_dev', '-j DROP',
 1952                      comment=ic.PAIR_DROP),
 1953                  mock.call.add_rule(
 1954                      'ofake_dev',
 1955                      '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp '
 1956                      '--sport 68 --dport 67 -j RETURN',
 1957                      top=False, comment=None),
 1958                  mock.call.add_rule('ofake_dev', '-j $sfake_dev',
 1959                                     top=False, comment=None),
 1960                  mock.call.add_rule(
 1961                      'ofake_dev',
 1962                      '-p udp -m udp --sport 68 --dport 67 -j RETURN',
 1963                      top=False, comment=None),
 1964                  mock.call.add_rule(
 1965                      'ofake_dev',
 1966                      '-p udp -m udp --sport 67 --dport 68 -j DROP',
 1967                      top=False, comment=None),
 1968                  mock.call.add_rule(
 1969                      'ofake_dev',
 1970                      '-m state --state RELATED,ESTABLISHED -j RETURN',
 1971                      top=False, comment=None),
 1972                  mock.call.add_rule(
 1973                      'ofake_dev',
 1974                      '-m state --state INVALID -j DROP',
 1975                      top=False, comment=None),
 1976                  mock.call.add_rule('ofake_dev',
 1977                                     '-j $sg-fallback',
 1978                                     top=False, comment=None),
 1979                  mock.call.add_rule('sg-chain', '-j ACCEPT')]
 1980         self.v4filter_inst.assert_has_calls(calls)
 1981 
 1982     def test_ip_spoofing_no_fixed_ips(self):
 1983         port = {'device': 'tapfake_dev',
 1984                 'mac_address': 'ff:ff:ff:ff:ff:ff',
 1985                 'network_id': 'fake_net',
 1986                 'fixed_ips': []}
 1987         self.firewall.prepare_port_filter(port)
 1988         calls = [mock.call.add_chain('sg-fallback'),
 1989                  mock.call.add_rule(
 1990                      'sg-fallback', '-j DROP',
 1991                      comment=ic.UNMATCH_DROP),
 1992                  mock.call.add_chain('sg-chain'),
 1993                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1994                                     comment=None),
 1995                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1996                                     comment=None),
 1997                  mock.call.add_rule('PREROUTING', mock.ANY,  # zone set
 1998                                     comment=None),
 1999                  mock.call.add_chain('ifake_dev'),
 2000                  mock.call.add_rule('FORWARD',
 2001                                     '-m physdev --physdev-out tapfake_dev '
 2002                                     '--physdev-is-bridged -j $sg-chain',
 2003                                     top=True, comment=ic.VM_INT_SG),
 2004                  mock.call.add_rule('sg-chain',
 2005                                     '-m physdev --physdev-out tapfake_dev '
 2006                                     '--physdev-is-bridged -j $ifake_dev',
 2007                                     top=False, comment=ic.SG_TO_VM_SG),
 2008                  mock.call.add_rule(
 2009                      'ifake_dev',
 2010                      '-m state --state RELATED,ESTABLISHED -j RETURN',
 2011                      top=False, comment=None),
 2012                  mock.call.add_rule(
 2013                      'ifake_dev',
 2014                      '-m state --state INVALID -j DROP',
 2015                      top=False, comment=None),
 2016                  mock.call.add_rule('ifake_dev', '-j $sg-fallback',
 2017                                     top=False, comment=None),
 2018                  mock.call.add_chain('ofake_dev'),
 2019                  mock.call.add_rule('FORWARD',
 2020                                     '-m physdev --physdev-in tapfake_dev '
 2021                                     '--physdev-is-bridged -j $sg-chain',
 2022                                     top=True, comment=ic.VM_INT_SG),
 2023                  mock.call.add_rule('sg-chain',
 2024                                     '-m physdev --physdev-in tapfake_dev '
 2025                                     '--physdev-is-bridged -j $ofake_dev',
 2026                                     top=False, comment=ic.SG_TO_VM_SG),
 2027                  mock.call.add_rule('INPUT',
 2028                                     '-m physdev --physdev-in tapfake_dev '
 2029                                     '--physdev-is-bridged -j $ofake_dev',
 2030                                     top=False, comment=ic.INPUT_TO_SG),
 2031                  mock.call.add_chain('sfake_dev'),
 2032                  mock.call.add_rule(
 2033                      'sfake_dev',
 2034                      '-m mac --mac-source FF:FF:FF:FF:FF:FF -j RETURN',
 2035                      comment=ic.PAIR_ALLOW),
 2036                  mock.call.add_rule(
 2037                      'sfake_dev', '-j DROP',
 2038                      comment=ic.PAIR_DROP),
 2039                  mock.call.add_rule(
 2040                      'ofake_dev',
 2041                      '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp '
 2042                      '--sport 68 --dport 67 -j RETURN',
 2043                      top=False, comment=None),
 2044                  mock.call.add_rule('ofake_dev', '-j $sfake_dev',
 2045                                     top=False, comment=None),
 2046                  mock.call.add_rule(
 2047                      'ofake_dev',
 2048                      '-p udp -m udp --sport 68 --dport 67 -j RETURN',
 2049                      top=False, comment=None),
 2050                  mock.call.add_rule(
 2051                      'ofake_dev',
 2052                      '-p udp -m udp --sport 67 --dport 68 -j DROP',
 2053                      top=False, comment=None),
 2054                  mock.call.add_rule(
 2055                      'ofake_dev',
 2056                      '-m state --state RELATED,ESTABLISHED -j RETURN',
 2057                      top=False, comment=None),
 2058                  mock.call.add_rule(
 2059                      'ofake_dev',
 2060                      '-m state --state INVALID -j DROP',
 2061                      top=False, comment=None),
 2062                  mock.call.add_rule('ofake_dev', '-j $sg-fallback',
 2063                                     top=False, comment=None),
 2064                  mock.call.add_rule('sg-chain', '-j ACCEPT')]
 2065         self.v4filter_inst.assert_has_calls(calls)
 2066 
 2067 
 2068 class IptablesFirewallEnhancedIpsetTestCase(BaseIptablesFirewallTestCase):
 2069     def setUp(self):
 2070         super(IptablesFirewallEnhancedIpsetTestCase, self).setUp()
 2071         self.firewall.ipset = mock.Mock()
 2072         self.firewall.ipset.get_name.side_effect = (
 2073             ipset_manager.IpsetManager.get_name)
 2074         self.firewall.ipset.set_name_exists.return_value = True
 2075         self.firewall.ipset.set_members = mock.Mock(return_value=([], []))
 2076 
 2077     def _fake_port(self, sg_id=FAKE_SGID):
 2078         return {'device': 'tapfake_dev',
 2079                 'mac_address': 'ff:ff:ff:ff:ff:ff',
 2080                 'network_id': 'fake_net',
 2081                 'fixed_ips': [FAKE_IP['IPv4'],
 2082                               FAKE_IP['IPv6']],
 2083                 'security_groups': [sg_id],
 2084                 'security_group_source_groups': [sg_id]}
 2085 
 2086     def _fake_sg_rule_for_ethertype(self, ethertype, remote_group):
 2087         return {'direction': 'ingress', 'remote_group_id': remote_group,
 2088                 'ethertype': ethertype}
 2089 
 2090     def _fake_sg_rules(self, sg_id=FAKE_SGID, remote_groups=None):
 2091         remote_groups = remote_groups or {_IPv4: [FAKE_SGID],
 2092                                           _IPv6: [FAKE_SGID]}
 2093         rules = []
 2094         for ip_version, remote_group_list in remote_groups.items():
 2095             for remote_group in remote_group_list:
 2096                 rules.append(self._fake_sg_rule_for_ethertype(ip_version,
 2097                                                               remote_group))
 2098         return {sg_id: rules}
 2099 
 2100     def _fake_sg_members(self, sg_ids=None):
 2101         return {sg_id: copy.copy(FAKE_IP) for sg_id in (sg_ids or [FAKE_SGID])}
 2102 
 2103     def test_update_security_group_members(self):
 2104         sg_members = {'IPv4': ['10.0.0.1', '10.0.0.2'], 'IPv6': ['fe80::1']}
 2105         self.firewall.update_security_group_members('fake_sgid', sg_members)
 2106         calls = [
 2107             mock.call.set_members('fake_sgid', 'IPv4',
 2108                                   ['10.0.0.1', '10.0.0.2']),
 2109             mock.call.set_members('fake_sgid', 'IPv6',
 2110                                   ['fe80::1'])
 2111         ]
 2112         self.firewall.ipset.assert_has_calls(calls, any_order=True)
 2113 
 2114     def _setup_fake_firewall_members_and_rules(self, firewall):
 2115         firewall.sg_rules = self._fake_sg_rules()
 2116         firewall.pre_sg_rules = self._fake_sg_rules()
 2117         firewall.sg_members = self._fake_sg_members()
 2118         firewall.pre_sg_members = firewall.sg_members
 2119 
 2120     def _prepare_rules_and_members_for_removal(self):
 2121         self._setup_fake_firewall_members_and_rules(self.firewall)
 2122         self.firewall.pre_sg_members[OTHER_SGID] = (
 2123             self.firewall.pre_sg_members[FAKE_SGID])
 2124 
 2125     def test_determine_remote_sgs_to_remove(self):
 2126         self._prepare_rules_and_members_for_removal()
 2127         ports = [self._fake_port()]
 2128 
 2129         self.assertEqual(
 2130             {_IPv4: set([OTHER_SGID]), _IPv6: set([OTHER_SGID])},
 2131             self.firewall._determine_remote_sgs_to_remove(ports))
 2132 
 2133     def test_determine_remote_sgs_to_remove_ipv6_unreferenced(self):
 2134         self._prepare_rules_and_members_for_removal()
 2135         ports = [self._fake_port()]
 2136         self.firewall.sg_rules = self._fake_sg_rules(
 2137             remote_groups={_IPv4: [OTHER_SGID, FAKE_SGID],
 2138                            _IPv6: [FAKE_SGID]})
 2139         self.assertEqual(
 2140             {_IPv4: set(), _IPv6: set([OTHER_SGID])},
 2141             self.firewall._determine_remote_sgs_to_remove(ports))
 2142 
 2143     def test_get_remote_sg_ids_by_ipversion(self):
 2144         self.firewall.sg_rules = self._fake_sg_rules(
 2145             remote_groups={_IPv4: [FAKE_SGID], _IPv6: [OTHER_SGID]})
 2146 
 2147         ports = [self._fake_port()]
 2148 
 2149         self.assertEqual(
 2150             {_IPv4: set([FAKE_SGID]), _IPv6: set([OTHER_SGID])},
 2151             self.firewall._get_remote_sg_ids_sets_by_ipversion(ports))
 2152 
 2153     def test_get_remote_sg_ids(self):
 2154         self.firewall.sg_rules = self._fake_sg_rules(
 2155             remote_groups={_IPv4: [FAKE_SGID, FAKE_SGID, FAKE_SGID],
 2156                            _IPv6: [OTHER_SGID, OTHER_SGID, OTHER_SGID]})
 2157 
 2158         port = self._fake_port()
 2159 
 2160         self.assertEqual(
 2161             {_IPv4: set([FAKE_SGID]), _IPv6: set([OTHER_SGID])},
 2162             self.firewall._get_remote_sg_ids(port))
 2163 
 2164     def test_determine_sg_rules_to_remove(self):
 2165         self.firewall.pre_sg_rules = self._fake_sg_rules(sg_id=OTHER_SGID)
 2166         ports = [self._fake_port()]
 2167 
 2168         self.assertEqual(set([OTHER_SGID]),
 2169                          self.firewall._determine_sg_rules_to_remove(ports))
 2170 
 2171     def test_get_sg_ids_set_for_ports(self):
 2172         sg_ids = set([FAKE_SGID, OTHER_SGID])
 2173         ports = [self._fake_port(sg_id) for sg_id in sg_ids]
 2174 
 2175         self.assertEqual(sg_ids,
 2176                          self.firewall._get_sg_ids_set_for_ports(ports))
 2177 
 2178     def test_remove_sg_members(self):
 2179         self.firewall.sg_members = self._fake_sg_members([FAKE_SGID,
 2180                                                           OTHER_SGID])
 2181         remote_sgs_to_remove = {_IPv4: set([FAKE_SGID]),
 2182                                 _IPv6: set([FAKE_SGID, OTHER_SGID])}
 2183         self.firewall._remove_sg_members(remote_sgs_to_remove)
 2184 
 2185         self.assertIn(OTHER_SGID, self.firewall.sg_members)
 2186         self.assertNotIn(FAKE_SGID, self.firewall.sg_members)
 2187 
 2188     def test_remove_unused_security_group_info_clears_unused_rules(self):
 2189         self._setup_fake_firewall_members_and_rules(self.firewall)
 2190         self.firewall.prepare_port_filter(self._fake_port())
 2191 
 2192         # create another SG which won't be referenced by any filtered port
 2193         fake_sg_rules = self.firewall.sg_rules['fake_sgid']
 2194         self.firewall.pre_sg_rules[OTHER_SGID] = fake_sg_rules
 2195         self.firewall.sg_rules[OTHER_SGID] = fake_sg_rules
 2196 
 2197         # call the cleanup function, and check the unused sg_rules are out
 2198         self.firewall._remove_unused_security_group_info()
 2199         self.assertNotIn(OTHER_SGID, self.firewall.sg_rules)
 2200 
 2201     def test_remove_unused_security_group_info(self):
 2202         self.firewall.sg_members = {OTHER_SGID: {_IPv4: [], _IPv6: []}}
 2203         self.firewall.pre_sg_members = self.firewall.sg_members
 2204         self.firewall.sg_rules = self._fake_sg_rules(
 2205             remote_groups={_IPv4: [FAKE_SGID], _IPv6: [FAKE_SGID]})
 2206         self.firewall.pre_sg_rules = self.firewall.sg_rules
 2207         port = self._fake_port()
 2208         self.firewall.filtered_ports['tapfake_dev'] = port
 2209         self.firewall._remove_unused_security_group_info()
 2210         self.assertNotIn(OTHER_SGID, self.firewall.sg_members)
 2211 
 2212     def test_not_remove_used_security_group_info(self):
 2213         self.firewall.sg_members = {OTHER_SGID: {_IPv4: [], _IPv6: []}}
 2214         self.firewall.pre_sg_members = self.firewall.sg_members
 2215         self.firewall.sg_rules = self._fake_sg_rules(
 2216             remote_groups={_IPv4: [OTHER_SGID], _IPv6: [OTHER_SGID]})
 2217         self.firewall.pre_sg_rules = self.firewall.sg_rules
 2218         port = self._fake_port()
 2219         self.firewall.filtered_ports['tapfake_dev'] = port
 2220         self.firewall._remove_unused_security_group_info()
 2221         self.assertIn(OTHER_SGID, self.firewall.sg_members)
 2222 
 2223     def test_remove_all_unused_info(self):
 2224         self._setup_fake_firewall_members_and_rules(self.firewall)
 2225         self.firewall.filtered_ports = {}
 2226         self.firewall._remove_unused_security_group_info()
 2227         self.assertFalse(self.firewall.sg_members)
 2228         self.assertFalse(self.firewall.sg_rules)
 2229 
 2230     def test_single_fallback_accept_rule(self):
 2231         p1, p2 = self._fake_port(), self._fake_port()
 2232         self.firewall._setup_chains_apply(dict(p1=p1, p2=p2), {})
 2233         v4_adds = self.firewall.iptables.ipv4['filter'].add_rule.mock_calls
 2234         v6_adds = self.firewall.iptables.ipv6['filter'].add_rule.mock_calls
 2235         sg_chain_v4_accept = [call for call in v4_adds
 2236                               if call == mock.call('sg-chain', '-j ACCEPT')]
 2237         sg_chain_v6_accept = [call for call in v6_adds
 2238                               if call == mock.call('sg-chain', '-j ACCEPT')]
 2239         self.assertEqual(1, len(sg_chain_v4_accept))
 2240         self.assertEqual(1, len(sg_chain_v6_accept))
 2241 
 2242     def test_remove_port_filter_with_destroy_ipset_chain(self):
 2243         self.firewall.sg_rules = self._fake_sg_rules()
 2244         port = self._fake_port()
 2245         self.firewall.pre_sg_members = {'fake_sgid': {
 2246             'IPv4': [],
 2247             'IPv6': []}}
 2248         sg_members = {'IPv4': ['10.0.0.1'], 'IPv6': ['fe80::1']}
 2249         self.firewall.update_security_group_members('fake_sgid', sg_members)
 2250         self.firewall.prepare_port_filter(port)
 2251         self.firewall.filter_defer_apply_on()
 2252         self.firewall.sg_members = {'fake_sgid': {
 2253             'IPv4': [],
 2254             'IPv6': []}}
 2255         self.firewall.pre_sg_members = {'fake_sgid': {
 2256             'IPv4': ['10.0.0.1'],
 2257             'IPv6': ['fe80::1']}}
 2258         self.firewall.remove_port_filter(port)
 2259         self.firewall.filter_defer_apply_off()
 2260         calls = [
 2261             mock.call.set_members('fake_sgid', 'IPv4', ['10.0.0.1']),
 2262             mock.call.set_members('fake_sgid', 'IPv6', ['fe80::1']),
 2263             mock.call.get_name('fake_sgid', 'IPv4'),
 2264             mock.call.set_name_exists('NIPv4fake_sgid'),
 2265             mock.call.get_name('fake_sgid', 'IPv6'),
 2266             mock.call.set_name_exists('NIPv6fake_sgid'),
 2267             mock.call.destroy('fake_sgid', 'IPv4'),
 2268             mock.call.destroy('fake_sgid', 'IPv6')]
 2269 
 2270         self.firewall.ipset.assert_has_calls(calls, any_order=True)
 2271 
 2272     def test_filter_defer_apply_off_with_sg_only_ipv6_rule(self):
 2273         self.firewall.sg_rules = self._fake_sg_rules()
 2274         self.firewall.pre_sg_rules = self._fake_sg_rules()
 2275         self.firewall.ipset_chains = {'IPv4fake_sgid': ['10.0.0.2'],
 2276                                       'IPv6fake_sgid': ['fe80::1']}
 2277         self.firewall.sg_members = {'fake_sgid': {
 2278             'IPv4': ['10.0.0.2'],
 2279             'IPv6': ['fe80::1']}}
 2280         self.firewall.pre_sg_members = {'fake_sgid': {
 2281             'IPv4': ['10.0.0.2'],
 2282             'IPv6': ['fe80::1']}}
 2283         self.firewall.sg_rules['fake_sgid'].remove(
 2284             {'direction': 'ingress', 'remote_group_id': 'fake_sgid',
 2285              'ethertype': 'IPv4'})
 2286         self.firewall.sg_rules.update()
 2287         self.firewall._defer_apply = True
 2288         port = self._fake_port()
 2289         self.firewall.filtered_ports['tapfake_dev'] = port
 2290         self.firewall._pre_defer_filtered_ports = {}
 2291         self.firewall._pre_defer_unfiltered_ports = {}
 2292         self.firewall.filter_defer_apply_off()
 2293         calls = [mock.call.destroy('fake_sgid', 'IPv4')]
 2294 
 2295         self.firewall.ipset.assert_has_calls(calls, True)
 2296 
 2297     def test_sg_rule_expansion_with_remote_ips(self):
 2298         other_ips = ['10.0.0.2', '10.0.0.3', '10.0.0.4']
 2299         self.firewall.sg_members = {'fake_sgid': {
 2300             'IPv4': [FAKE_IP['IPv4']] + other_ips,
 2301             'IPv6': [FAKE_IP['IPv6']]}}
 2302 
 2303         port = self._fake_port()
 2304         rule = self._fake_sg_rule_for_ethertype(_IPv4, FAKE_SGID)
 2305         rules = self.firewall._expand_sg_rule_with_remote_ips(
 2306             rule, port, 'ingress')
 2307         self.assertEqual(list(rules),
 2308                          [dict(list(rule.items()) +
 2309                                [('source_ip_prefix', '%s/32' % ip)])
 2310                           for ip in other_ips])
 2311 
 2312     def test_build_ipv4v6_mac_ip_list(self):
 2313         mac_oth = 'ffff-ff0f-ffff'
 2314         mac_unix = 'FF:FF:FF:0F:FF:FF'
 2315         ipv4 = FAKE_IP['IPv4']
 2316         ipv6 = FAKE_IP['IPv6']
 2317         fake_ipv4_pair = []
 2318         fake_ipv4_pair.append((mac_unix, ipv4))
 2319         fake_ipv6_pair = []
 2320         fake_ipv6_pair.append((mac_unix, ipv6))
 2321         fake_ipv6_pair.append((mac_unix, 'fe80::fdff:ffff:fe0f:ffff'))
 2322 
 2323         mac_ipv4_pairs = []
 2324         mac_ipv6_pairs = []
 2325 
 2326         self.firewall._build_ipv4v6_mac_ip_list(mac_oth, ipv4,
 2327                                                 mac_ipv4_pairs, mac_ipv6_pairs)
 2328         self.assertEqual(fake_ipv4_pair, mac_ipv4_pairs)
 2329         self.firewall._build_ipv4v6_mac_ip_list(mac_oth, ipv6,
 2330                                                 mac_ipv4_pairs, mac_ipv6_pairs)
 2331         self.assertEqual(fake_ipv6_pair, mac_ipv6_pairs)
 2332         # ensure that LLA is not added again for another v6 addr
 2333         ipv62 = 'fe81::1'
 2334         self.firewall._build_ipv4v6_mac_ip_list(mac_oth, ipv62,
 2335                                                 mac_ipv4_pairs, mac_ipv6_pairs)
 2336         fake_ipv6_pair.append((mac_unix, ipv62))
 2337         self.assertEqual(fake_ipv6_pair, mac_ipv6_pairs)
 2338 
 2339 
 2340 class OVSHybridIptablesFirewallTestCase(BaseIptablesFirewallTestCase):
 2341 
 2342     def test__populate_initial_zone_map(self):
 2343         self.assertEqual(self._dev_zone_map,
 2344                    self.firewall.ipconntrack._device_zone_map)
 2345 
 2346     def test__generate_device_zone(self):
 2347         # initial data has 4097, 4098, and 4105 in use.
 2348         # we fill from top up first.
 2349         self.assertEqual(4106,
 2350                    self.firewall.ipconntrack._generate_device_zone('test'))
 2351 
 2352         # once it's maxed out, it scans for gaps
 2353         self.firewall.ipconntrack._device_zone_map['someport'] = (
 2354             ip_conntrack.MAX_CONNTRACK_ZONES)
 2355         for i in range(4099, 4105):
 2356             self.assertEqual(i,
 2357                    self.firewall.ipconntrack._generate_device_zone(i))
 2358 
 2359         # 4105 and 4106 are taken so next should be 4107
 2360         self.assertEqual(4107,
 2361                    self.firewall.ipconntrack._generate_device_zone('p11'))
 2362 
 2363         # take out zone 4097 and make sure it's selected
 2364         self.firewall.ipconntrack._device_zone_map.pop('e804433b-61')
 2365         self.assertEqual(4097,
 2366                    self.firewall.ipconntrack._generate_device_zone('p1'))
 2367 
 2368         # fill it up and then make sure an extra throws an error
 2369         for i in range(ip_conntrack.ZONE_START,
 2370             ip_conntrack.MAX_CONNTRACK_ZONES):
 2371             self.firewall.ipconntrack._device_zone_map['dev-%s' % i] = i
 2372         with testtools.ExpectedException(exceptions.CTZoneExhaustedError):
 2373             self.firewall.ipconntrack._find_open_zone()
 2374 
 2375         # with it full, try again, this should trigger a cleanup
 2376         # and return 4097
 2377         self.assertEqual(ip_conntrack.ZONE_START,
 2378                    self.firewall.ipconntrack._generate_device_zone('p12'))
 2379         self.assertEqual({'p12': ip_conntrack.ZONE_START},
 2380                    self.firewall.ipconntrack._device_zone_map)
 2381 
 2382     def test_get_device_zone(self):
 2383         dev = {'device': 'tap1234', 'network_id': '12345678901234567'}
 2384         # initial data has 4097, 4098, and 4105 in use.
 2385         self.assertEqual(4106, self.firewall.ipconntrack.get_device_zone(dev))
 2386         # should have been truncated to 11 chars
 2387         self._dev_zone_map.update({'12345678901': 4106})
 2388         self.assertEqual(self._dev_zone_map,
 2389                self.firewall.ipconntrack._device_zone_map)
 2390 
 2391     def test_multiple_firewall_with_common_conntrack(self):
 2392         self.firewall1 = iptables_firewall.OVSHybridIptablesFirewallDriver()
 2393         self.firewall2 = iptables_firewall.OVSHybridIptablesFirewallDriver()
 2394         self.assertEqual(id(self.firewall1.ipconntrack),
 2395                          id(self.firewall2.ipconntrack))