diff --git a/neutron/agent/linux/ip_conntrack.py b/neutron/agent/linux/ip_conntrack.py index 9549d5baf2b..33c08678184 100644 --- a/neutron/agent/linux/ip_conntrack.py +++ b/neutron/agent/linux/ip_conntrack.py @@ -29,14 +29,13 @@ MAX_CONNTRACK_ZONES = 65535 @lockutils.synchronized('conntrack') def get_conntrack(get_rules_for_table_func, filtered_ports, unfiltered_ports, - execute=None, namespace=None): - + execute=None, namespace=None, zone_per_port=False): try: return CONTRACK_MGRS[namespace] except KeyError: ipconntrack = IpConntrackManager(get_rules_for_table_func, filtered_ports, unfiltered_ports, - execute, namespace) + execute, namespace, zone_per_port) CONTRACK_MGRS[namespace] = ipconntrack return CONTRACK_MGRS[namespace] @@ -45,12 +44,14 @@ class IpConntrackManager(object): """Smart wrapper for ip conntrack.""" def __init__(self, get_rules_for_table_func, filtered_ports, - unfiltered_ports, execute=None, namespace=None): + unfiltered_ports, execute=None, namespace=None, + zone_per_port=False): self.get_rules_for_table_func = get_rules_for_table_func self.execute = execute or linux_utils.execute self.namespace = namespace self.filtered_ports = filtered_ports self.unfiltered_ports = unfiltered_ports + self.zone_per_port = zone_per_port # zone per port vs per network self._populate_initial_zone_map() @staticmethod @@ -74,8 +75,7 @@ class IpConntrackManager(object): cmd = self._generate_conntrack_cmd_by_rule(rule, self.namespace) ethertype = rule.get('ethertype') for device_info in device_info_list: - zone_id = self._device_zone_map.get( - self._port_key(device_info['device']), None) + zone_id = self.get_device_zone(device_info, create=False) if not zone_id: LOG.debug("No zone for device %(dev)s. Will not try to " "clear conntrack state. Zone map: %(zm)s", @@ -139,26 +139,30 @@ class IpConntrackManager(object): self._device_zone_map[short_port_id] = int(match.group('zone')) LOG.debug("Populated conntrack zone map: %s", self._device_zone_map) - @staticmethod - def _port_key(port_id): - # we have to key the device_zone_map based on the fragment of the port + def _device_key(self, port): + # we have to key the device_zone_map based on the fragment of the # UUID that shows up in the interface name. This is because the initial # map is populated strictly based on interface names that we don't know # the full UUID of. - return port_id[:(n_const.LINUX_DEV_LEN - - n_const.LINUX_DEV_PREFIX_LEN)] + if self.zone_per_port: + identifier = port['device'][n_const.LINUX_DEV_PREFIX_LEN:] + else: + identifier = port['network_id'] + return identifier[:(n_const.LINUX_DEV_LEN - + n_const.LINUX_DEV_PREFIX_LEN)] - def get_device_zone(self, port_id): - short_port_id = self._port_key(port_id) + def get_device_zone(self, port, create=True): + device_key = self._device_key(port) try: - return self._device_zone_map[short_port_id] + return self._device_zone_map[device_key] except KeyError: - return self._generate_device_zone(short_port_id) + if create: + return self._generate_device_zone(device_key) def _free_zones_from_removed_ports(self): """Clears any entries from the zone map of removed ports.""" existing_ports = [ - self._port_key(port['device']) + self._device_key(port) for port in (list(self.filtered_ports.values()) + list(self.unfiltered_ports.values())) ] @@ -166,7 +170,7 @@ class IpConntrackManager(object): for dev in removed: self._device_zone_map.pop(dev, None) - def _generate_device_zone(self, short_port_id): + def _generate_device_zone(self, short_device_id): """Generates a unique conntrack zone for the passed in ID.""" try: zone = self._find_open_zone() @@ -175,10 +179,10 @@ class IpConntrackManager(object): self._free_zones_from_removed_ports() zone = self._find_open_zone() - self._device_zone_map[short_port_id] = zone - LOG.debug("Assigned CT zone %(z)s to port %(dev)s.", - {'z': zone, 'dev': short_port_id}) - return self._device_zone_map[short_port_id] + self._device_zone_map[short_device_id] = zone + LOG.debug("Assigned CT zone %(z)s to device %(dev)s.", + {'z': zone, 'dev': short_device_id}) + return self._device_zone_map[short_device_id] def _find_open_zone(self): # call set to dedup because old ports may be mapped to the same zone. diff --git a/neutron/agent/linux/iptables_firewall.py b/neutron/agent/linux/iptables_firewall.py index daa400d23d7..82ae44907f7 100644 --- a/neutron/agent/linux/iptables_firewall.py +++ b/neutron/agent/linux/iptables_firewall.py @@ -57,6 +57,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver): """Driver which enforces security groups through iptables rules.""" IPTABLES_DIRECTION = {firewall.INGRESS_DIRECTION: 'physdev-out', firewall.EGRESS_DIRECTION: 'physdev-in'} + CONNTRACK_ZONE_PER_PORT = False def __init__(self, namespace=None): self.iptables = iptables_manager.IptablesManager(state_less=True, @@ -70,7 +71,8 @@ class IptablesFirewallDriver(firewall.FirewallDriver): self.unfiltered_ports = {} self.ipconntrack = ip_conntrack.get_conntrack( self.iptables.get_rules_for_table, self.filtered_ports, - self.unfiltered_ports, namespace=namespace) + self.unfiltered_ports, namespace=namespace, + zone_per_port=self.CONNTRACK_ZONE_PER_PORT) self._add_fallback_chain_v4v6() self._defer_apply = False self._pre_defer_filtered_ports = None @@ -204,6 +206,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver): # agent restarts and don't cause unnecessary rule differences for pname in sorted(ports): port = ports[pname] + self._add_conntrack_jump(port) self._setup_chain(port, firewall.INGRESS_DIRECTION) self._setup_chain(port, firewall.EGRESS_DIRECTION) self.iptables.ipv4['filter'].add_rule(SG_CHAIN, '-j ACCEPT') @@ -224,6 +227,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver): self._remove_chain(port, firewall.INGRESS_DIRECTION) self._remove_chain(port, firewall.EGRESS_DIRECTION) self._remove_chain(port, SPOOF_FILTER) + self._remove_conntrack_jump(port) for port in unfiltered_ports.values(): self._remove_rule_port_sec(port, firewall.INGRESS_DIRECTION) self._remove_rule_port_sec(port, firewall.EGRESS_DIRECTION) @@ -325,6 +329,43 @@ class IptablesFirewallDriver(firewall.FirewallDriver): self._add_rules_to_chain_v4v6('INPUT', jump_rule, jump_rule, comment=ic.INPUT_TO_SG) + def _get_br_device_name(self, port): + return ('brq' + port['network_id'])[:n_const.LINUX_DEV_LEN] + + def _get_jump_rules(self, port): + zone = self.ipconntrack.get_device_zone(port) + br_dev = self._get_br_device_name(port) + port_dev = self._get_device_name(port) + # match by interface for bridge input + match_interface = '-i %s' + match_physdev = '-m physdev --physdev-in %s' + # comment to prevent duplicate warnings for different devices using + # same bridge. truncate start to remove prefixes + comment = '-m comment --comment "Set zone for %s"' % port['device'][4:] + rules = [] + for dev, match in ((br_dev, match_physdev), (br_dev, match_interface), + (port_dev, match_physdev)): + match = match % dev + rule = '%s %s -j CT --zone %s' % (match, comment, zone) + rules.append(rule) + return rules + + def _add_conntrack_jump(self, port): + for jump_rule in self._get_jump_rules(port): + self._add_raw_rule('PREROUTING', jump_rule) + + def _remove_conntrack_jump(self, port): + for jump_rule in self._get_jump_rules(port): + self._remove_raw_rule('PREROUTING', jump_rule) + + def _add_raw_rule(self, chain, rule, comment=None): + self.iptables.ipv4['raw'].add_rule(chain, rule, comment=comment) + self.iptables.ipv6['raw'].add_rule(chain, rule, comment=comment) + + def _remove_raw_rule(self, chain, rule): + self.iptables.ipv4['raw'].remove_rule(chain, rule) + self.iptables.ipv6['raw'].remove_rule(chain, rule) + def _split_sgr_by_ethertype(self, security_group_rules): ipv4_sg_rules = [] ipv6_sg_rules = [] @@ -828,6 +869,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver): class OVSHybridIptablesFirewallDriver(IptablesFirewallDriver): OVS_HYBRID_PLUG_REQUIRED = True + CONNTRACK_ZONE_PER_PORT = True def _port_chain_name(self, port, direction): return iptables_manager.get_chain_name( @@ -838,37 +880,3 @@ class OVSHybridIptablesFirewallDriver(IptablesFirewallDriver): def _get_device_name(self, port): return get_hybrid_port_name(port['device']) - - def _get_jump_rule(self, port, direction): - if direction == firewall.INGRESS_DIRECTION: - device = self._get_br_device_name(port) - else: - device = self._get_device_name(port) - jump_rule = '-m physdev --physdev-in %s -j CT --zone %s' % ( - device, self.ipconntrack.get_device_zone( - port['device'])) - return jump_rule - - def _add_raw_chain_rules(self, port, direction): - jump_rule = self._get_jump_rule(port, direction) - self.iptables.ipv4['raw'].add_rule('PREROUTING', jump_rule) - self.iptables.ipv6['raw'].add_rule('PREROUTING', jump_rule) - - def _remove_raw_chain_rules(self, port, direction): - jump_rule = self._get_jump_rule(port, direction) - self.iptables.ipv4['raw'].remove_rule('PREROUTING', jump_rule) - self.iptables.ipv6['raw'].remove_rule('PREROUTING', jump_rule) - - def _add_chain(self, port, direction): - super(OVSHybridIptablesFirewallDriver, self)._add_chain(port, - direction) - if direction in [firewall.INGRESS_DIRECTION, - firewall.EGRESS_DIRECTION]: - self._add_raw_chain_rules(port, direction) - - def _remove_chain(self, port, direction): - super(OVSHybridIptablesFirewallDriver, self)._remove_chain(port, - direction) - if direction in [firewall.INGRESS_DIRECTION, - firewall.EGRESS_DIRECTION]: - self._remove_raw_chain_rules(port, direction) diff --git a/neutron/tests/common/conn_testers.py b/neutron/tests/common/conn_testers.py index 5b5973fde2f..ada66c49567 100644 --- a/neutron/tests/common/conn_testers.py +++ b/neutron/tests/common/conn_testers.py @@ -513,9 +513,18 @@ class LinuxBridgeConnectionTester(ConnectionTester): """ + def __init__(self, *args, **kwargs): + self.bridge_name = kwargs.pop('bridge_name', None) + super(LinuxBridgeConnectionTester, self).__init__(*args, **kwargs) + def _setUp(self): super(LinuxBridgeConnectionTester, self)._setUp() - self.bridge = self.useFixture(net_helpers.LinuxBridgeFixture()).bridge + bridge_args = {} + if self.bridge_name: + bridge_args = {'prefix': self.bridge_name, + 'prefix_is_full_name': True} + self.bridge = self.useFixture( + net_helpers.LinuxBridgeFixture(**bridge_args)).bridge machines = self.useFixture( machine_fixtures.PeerMachines( self.bridge, self.ip_cidr)).machines diff --git a/neutron/tests/functional/agent/test_firewall.py b/neutron/tests/functional/agent/test_firewall.py index fcc5e6c4a73..6c2604db817 100644 --- a/neutron/tests/functional/agent/test_firewall.py +++ b/neutron/tests/functional/agent/test_firewall.py @@ -24,12 +24,14 @@ import netaddr from neutron_lib import constants from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import uuidutils import testscenarios from neutron.agent import firewall from neutron.agent.linux import iptables_firewall from neutron.agent.linux import openvswitch_firewall from neutron.cmd.sanity import checks +from neutron.common import constants as n_const from neutron.conf.agent import securitygroups_rpc as security_config from neutron.tests.common import conn_testers from neutron.tests.common import helpers @@ -95,6 +97,7 @@ class BaseFirewallTestCase(base.BaseSudoTestCase): def setUp(self): security_config.register_securitygroups_opts() + self.net_id = uuidutils.generate_uuid() super(BaseFirewallTestCase, self).setUp() self.tester, self.firewall = getattr(self, self.initialize)() if self.firewall_name == "openvswitch": @@ -103,7 +106,8 @@ class BaseFirewallTestCase(base.BaseSudoTestCase): self.tester.vm_port_id, [self.tester.vm_ip_address], self.tester.vm_mac_address, - [self.FAKE_SECURITY_GROUP_ID]) + [self.FAKE_SECURITY_GROUP_ID], + self.net_id) # FIXME(jlibosva): We should consider to call prepare_port_filter with # deferred bridge depending on its performance self.firewall.prepare_port_filter(self.src_port_desc) @@ -111,8 +115,10 @@ class BaseFirewallTestCase(base.BaseSudoTestCase): def initialize_iptables(self): cfg.CONF.set_override('enable_ipset', self.enable_ipset, 'SECURITYGROUP') + br_name = ('brq' + self.net_id)[:n_const.LINUX_DEV_LEN] tester = self.useFixture( - conn_testers.LinuxBridgeConnectionTester(self.ip_cidr)) + conn_testers.LinuxBridgeConnectionTester(self.ip_cidr, + bridge_name=br_name)) firewall_drv = iptables_firewall.IptablesFirewallDriver( namespace=tester.bridge_namespace) return tester, firewall_drv @@ -140,7 +146,8 @@ class BaseFirewallTestCase(base.BaseSudoTestCase): self.tester.set_peer_tag(vlan) @staticmethod - def _create_port_description(port_id, ip_addresses, mac_address, sg_ids): + def _create_port_description(port_id, ip_addresses, mac_address, sg_ids, + net_id): return {'admin_state_up': True, 'device': port_id, 'device_owner': DEVICE_OWNER_COMPUTE, @@ -148,7 +155,8 @@ class BaseFirewallTestCase(base.BaseSudoTestCase): 'mac_address': mac_address, 'port_security_enabled': True, 'security_groups': sg_ids, - 'status': 'ACTIVE'} + 'status': 'ACTIVE', + 'network_id': net_id} def _apply_security_group_rules(self, sg_id, sg_rules): with self.firewall.defer_apply(): @@ -539,7 +547,8 @@ class FirewallTestCase(BaseFirewallTestCase): self.tester.peer_port_id, [self.tester.peer_ip_address], self.tester.peer_mac_address, - [remote_sg_id]) + [remote_sg_id], + self.net_id) vm_sg_members = {'IPv4': [self.tester.peer_ip_address]} peer_sg_rules = [{'ethertype': 'IPv4', 'direction': 'egress', diff --git a/neutron/tests/unit/agent/linux/test_ip_conntrack.py b/neutron/tests/unit/agent/linux/test_ip_conntrack.py index 3771d9ae7cc..163b06dc2c9 100644 --- a/neutron/tests/unit/agent/linux/test_ip_conntrack.py +++ b/neutron/tests/unit/agent/linux/test_ip_conntrack.py @@ -27,14 +27,15 @@ class IPConntrackTestCase(base.BaseTestCase): self.unfiltered_port = {} self.mgr = ip_conntrack.IpConntrackManager( self._get_rule_for_table, self.filtered_port, - self.unfiltered_port, self.execute) + self.unfiltered_port, self.execute, + zone_per_port=True) def _get_rule_for_table(self, table): return ['test --physdev-in tapdevice -j CT --zone 100'] def test_delete_conntrack_state_dedupes(self): rule = {'ethertype': 'IPv4', 'direction': 'ingress'} - dev_info = {'device': 'device', 'fixed_ips': ['1.2.3.4']} + dev_info = {'device': 'tapdevice', 'fixed_ips': ['1.2.3.4']} dev_info_list = [dev_info for _ in range(10)] self.mgr._delete_conntrack_state(dev_info_list, rule) self.assertEqual(1, len(self.execute.mock_calls)) diff --git a/neutron/tests/unit/agent/linux/test_iptables_firewall.py b/neutron/tests/unit/agent/linux/test_iptables_firewall.py index e75c27df51d..84745589ca2 100644 --- a/neutron/tests/unit/agent/linux/test_iptables_firewall.py +++ b/neutron/tests/unit/agent/linux/test_iptables_firewall.py @@ -126,6 +126,12 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): 'sg-fallback', '-j DROP', comment=ic.UNMATCH_DROP), mock.call.add_chain('sg-chain'), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), mock.call.add_chain('ifake_dev'), mock.call.add_rule('FORWARD', '-m physdev --physdev-out tapfake_dev ' @@ -1015,6 +1021,12 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): '-j DROP', comment=ic.UNMATCH_DROP), mock.call.add_chain('sg-chain'), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), mock.call.add_chain('ifake_dev'), mock.call.add_rule('FORWARD', '-m physdev --physdev-out tapfake_dev ' @@ -1137,7 +1149,7 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): 'protocol': protocol}] with mock.patch.dict(self.firewall.ipconntrack._device_zone_map, - {port['device']: ct_zone}): + {port['network_id']: ct_zone}): self.firewall.filter_defer_apply_on() self.firewall.sg_rules['fake_sg_id'] = [] self.firewall.filter_defer_apply_off() @@ -1222,7 +1234,7 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): self.firewall.filtered_ports[port['device']] = port self.firewall.updated_sg_members = set(['tapfake_dev']) with mock.patch.dict(self.firewall.ipconntrack._device_zone_map, - {port['device']: ct_zone}): + {port['network_id']: ct_zone}): self.firewall.filter_defer_apply_on() new_port = copy.deepcopy(port) new_port['security_groups'] = ['fake_sg_id2'] @@ -1284,7 +1296,7 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): members_after_delete = {'IPv6': ['fe80::3']} with mock.patch.dict(self.firewall.ipconntrack._device_zone_map, - {port['device']: ct_zone}): + {port['network_id']: ct_zone}): # add ['10.0.0.2', '10.0.0.3'] or ['fe80::2', 'fe80::3'] self.firewall.security_group_updated('sg_member', ['fake_sg_id2']) self.firewall.update_security_group_members( @@ -1341,6 +1353,12 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): '-j DROP', comment=ic.UNMATCH_DROP), mock.call.add_chain('sg-chain'), + mock.call.add_rule('PREROUTING', mock.ANY, + comment=None), # zone set + mock.call.add_rule('PREROUTING', mock.ANY, + comment=None), # zone set + mock.call.add_rule('PREROUTING', mock.ANY, + comment=None), # zone set mock.call.add_chain('ifake_dev'), mock.call.add_rule( 'FORWARD', @@ -1418,8 +1436,17 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): mock.call.remove_chain('ifake_dev'), mock.call.remove_chain('ofake_dev'), mock.call.remove_chain('sfake_dev'), + mock.call.remove_rule('PREROUTING', mock.ANY), # zone set + mock.call.remove_rule('PREROUTING', mock.ANY), # zone set + mock.call.remove_rule('PREROUTING', mock.ANY), # zone set mock.call.remove_chain('sg-chain'), mock.call.add_chain('sg-chain'), + mock.call.add_rule('PREROUTING', mock.ANY, + comment=None), # zone set + mock.call.add_rule('PREROUTING', mock.ANY, + comment=None), # zone set + mock.call.add_rule('PREROUTING', mock.ANY, + comment=None), # zone set mock.call.add_chain('ifake_dev'), mock.call.add_rule( 'FORWARD', @@ -1497,6 +1524,9 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): mock.call.remove_chain('ifake_dev'), mock.call.remove_chain('ofake_dev'), mock.call.remove_chain('sfake_dev'), + mock.call.remove_rule('PREROUTING', mock.ANY), # zone set + mock.call.remove_rule('PREROUTING', mock.ANY), # zone set + mock.call.remove_rule('PREROUTING', mock.ANY), # zone set mock.call.remove_chain('sg-chain'), mock.call.add_chain('sg-chain')] @@ -1520,11 +1550,8 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): new_port['fixed_ips'] = ['10.0.0.2', 'fe80::2'] self.firewall.sg_members['fake_sg_id2'] = {'IPv4': ['10.0.0.2'], 'IPv6': ['fe80::2']} - if ct_zone: - self.firewall.ipconntrack._device_zone_map['tapfake_dev'] = ct_zone - else: - self.firewall.ipconntrack._device_zone_map.pop('tapfake_dev', None) - + mock.patch.object(self.firewall.ipconntrack, 'get_device_zone', + return_value=ct_zone).start() self.firewall.remove_port_filter(port) if not ct_zone: self.assertFalse(self.utils_exec.called) @@ -1574,8 +1601,10 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): def test_mock_chain_applies(self): chain_applies = self._mock_chain_applies() - port_prepare = {'device': 'd1', 'mac_address': 'prepare'} - port_update = {'device': 'd1', 'mac_address': 'update'} + port_prepare = {'device': 'd1', 'mac_address': 'prepare', + 'network_id': 'fake_net'} + port_update = {'device': 'd1', 'mac_address': 'update', + 'network_id': 'fake_net'} self.firewall.prepare_port_filter(port_prepare) self.firewall.update_port_filter(port_update) self.firewall.remove_port_filter(port_update) @@ -1629,6 +1658,12 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): 'sg-fallback', '-j DROP', comment=ic.UNMATCH_DROP), mock.call.add_chain('sg-chain'), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), mock.call.add_chain('ifake_dev'), mock.call.add_rule('FORWARD', '-m physdev --physdev-out tapfake_dev ' @@ -1713,6 +1748,12 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): 'sg-fallback', '-j DROP', comment=ic.UNMATCH_DROP), mock.call.add_chain('sg-chain'), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), + mock.call.add_rule('PREROUTING', mock.ANY, # zone set + comment=None), mock.call.add_chain('ifake_dev'), mock.call.add_rule('FORWARD', '-m physdev --physdev-out tapfake_dev ' @@ -2098,9 +2139,9 @@ class OVSHybridIptablesFirewallTestCase(BaseIptablesFirewallTestCase): self.firewall.ipconntrack._device_zone_map) def test_get_device_zone(self): + dev = {'device': 'tap1234', 'network_id': '12345678901234567'} # initial data has 1, 2, and 9 in use. - self.assertEqual(10, - self.firewall.ipconntrack.get_device_zone('12345678901234567')) + self.assertEqual(10, self.firewall.ipconntrack.get_device_zone(dev)) # should have been truncated to 11 chars self._dev_zone_map.update({'12345678901': 10}) self.assertEqual(self._dev_zone_map, diff --git a/neutron/tests/unit/agent/test_securitygroups_rpc.py b/neutron/tests/unit/agent/test_securitygroups_rpc.py index 8321d971bb1..33ed18c4a8b 100644 --- a/neutron/tests/unit/agent/test_securitygroups_rpc.py +++ b/neutron/tests/unit/agent/test_securitygroups_rpc.py @@ -27,6 +27,7 @@ from testtools import matchers import webob.exc from neutron.agent import firewall as firewall_base +from neutron.agent.linux import ip_conntrack from neutron.agent.linux import iptables_manager from neutron.agent import securitygroups_rpc as sg_rpc from neutron.api.rpc.handlers import securitygroups_rpc @@ -1429,6 +1430,48 @@ COMMIT # Completed by iptables_manager """ % IPTABLES_ARG +IPTABLES_RAW_BRIDGE_NET_1 = """# Generated by iptables_manager +*raw +:OUTPUT - [0:0] +:PREROUTING - [0:0] +:%(bn)s-OUTPUT - [0:0] +:%(bn)s-PREROUTING - [0:0] +-I OUTPUT 1 -j %(bn)s-OUTPUT +-I PREROUTING 1 -j %(bn)s-PREROUTING +-I %(bn)s-PREROUTING 1 -m physdev --physdev-in brqfakenet1 \ +-m comment --comment "Set zone for port1" -j CT --zone 1 +-I %(bn)s-PREROUTING 2 -i brqfakenet1 \ +-m comment --comment "Set zone for port1" -j CT --zone 1 +-I %(bn)s-PREROUTING 3 -m physdev --physdev-in tap_port1 \ +-m comment --comment "Set zone for port1" -j CT --zone 1 +COMMIT +# Completed by iptables_manager +""" % IPTABLES_ARG + +IPTABLES_RAW_BRIDGE_NET_2 = """# Generated by iptables_manager +*raw +:OUTPUT - [0:0] +:PREROUTING - [0:0] +:%(bn)s-OUTPUT - [0:0] +:%(bn)s-PREROUTING - [0:0] +-I OUTPUT 1 -j %(bn)s-OUTPUT +-I PREROUTING 1 -j %(bn)s-PREROUTING +-I %(bn)s-PREROUTING 1 -m physdev --physdev-in brqfakenet1 \ +-m comment --comment "Set zone for port1" -j CT --zone 1 +-I %(bn)s-PREROUTING 2 -i brqfakenet1 \ +-m comment --comment "Set zone for port1" -j CT --zone 1 +-I %(bn)s-PREROUTING 3 -m physdev --physdev-in tap_port1 \ +-m comment --comment "Set zone for port1" -j CT --zone 1 +-I %(bn)s-PREROUTING 4 -m physdev --physdev-in brqfakenet2 \ +-m comment --comment "Set zone for port2" -j CT --zone 2 +-I %(bn)s-PREROUTING 5 -i brqfakenet2 \ +-m comment --comment "Set zone for port2" -j CT --zone 2 +-I %(bn)s-PREROUTING 6 -m physdev --physdev-in tap_port2 \ +-m comment --comment "Set zone for port2" -j CT --zone 2 +COMMIT +# Completed by iptables_manager +""" % IPTABLES_ARG + IPTABLES_RAW_DEVICE_1 = """# Generated by iptables_manager *raw :OUTPUT - [0:0] @@ -1437,8 +1480,12 @@ IPTABLES_RAW_DEVICE_1 = """# Generated by iptables_manager :%(bn)s-PREROUTING - [0:0] -I OUTPUT 1 -j %(bn)s-OUTPUT -I PREROUTING 1 -j %(bn)s-PREROUTING --I %(bn)s-PREROUTING 1 -m physdev --physdev-in qvbtap_port1 -j CT --zone 1 --I %(bn)s-PREROUTING 2 -m physdev --physdev-in tap_port1 -j CT --zone 1 +-I %(bn)s-PREROUTING 1 -m physdev --physdev-in qvbtap_port1 \ +-m comment --comment "Set zone for %(port1)s" -j CT --zone 1 +-I %(bn)s-PREROUTING 2 -i qvbtap_port1 \ +-m comment --comment "Set zone for %(port1)s" -j CT --zone 1 +-I %(bn)s-PREROUTING 3 -m physdev --physdev-in tap_port1 \ +-m comment --comment "Set zone for %(port1)s" -j CT --zone 1 COMMIT # Completed by iptables_manager """ % IPTABLES_ARG @@ -1452,11 +1499,17 @@ IPTABLES_RAW_DEVICE_2 = """# Generated by iptables_manager -I OUTPUT 1 -j %(bn)s-OUTPUT -I PREROUTING 1 -j %(bn)s-PREROUTING -I %(bn)s-PREROUTING 1 -m physdev --physdev-in qvbtap_%(port1)s \ --j CT --zone 1 --I %(bn)s-PREROUTING 2 -m physdev --physdev-in tap_%(port1)s -j CT --zone 1 --I %(bn)s-PREROUTING 3 -m physdev --physdev-in qvbtap_%(port2)s \ --j CT --zone 2 --I %(bn)s-PREROUTING 4 -m physdev --physdev-in tap_%(port2)s -j CT --zone 2 +-m comment --comment "Set zone for %(port1)s" -j CT --zone 1 +-I %(bn)s-PREROUTING 2 -i qvbtap_%(port1)s \ +-m comment --comment "Set zone for %(port1)s" -j CT --zone 1 +-I %(bn)s-PREROUTING 3 -m physdev --physdev-in tap_%(port1)s \ +-m comment --comment "Set zone for %(port1)s" -j CT --zone 1 +-I %(bn)s-PREROUTING 4 -m physdev --physdev-in qvbtap_%(port2)s \ +-m comment --comment "Set zone for %(port2)s" -j CT --zone 2 +-I %(bn)s-PREROUTING 5 -i qvbtap_%(port2)s \ +-m comment --comment "Set zone for %(port2)s" -j CT --zone 2 +-I %(bn)s-PREROUTING 6 -m physdev --physdev-in tap_%(port2)s \ +-m comment --comment "Set zone for %(port2)s" -j CT --zone 2 COMMIT # Completed by iptables_manager """ % IPTABLES_ARG @@ -2292,6 +2345,9 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): PHYSDEV_EGRESS = 'physdev-in' def setUp(self, defer_refresh_firewall=False, test_rpc_v1_1=True): + clear_mgrs = lambda: ip_conntrack.CONTRACK_MGRS.clear() + self.addCleanup(clear_mgrs) + clear_mgrs() # clear before start in case other tests didn't clean up super(TestSecurityGroupAgentWithIptables, self).setUp() set_firewall_driver(self.FIREWALL_DRIVER) cfg.CONF.set_override('enable_ipset', False, group='SECURITYGROUP') @@ -2395,7 +2451,7 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): def _device(self, device, ip, mac_address, rule): return {'device': device, - 'network_id': 'fakenet', + 'network_id': 'fakenet%s' % device[-1:], 'fixed_ips': [ip], 'mac_address': mac_address, 'security_groups': ['security_group1'], @@ -2467,7 +2523,7 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): self.ipconntrack._device_zone_map = {} self.rpc.security_group_rules_for_devices.return_value = self.devices1 self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY, IPTABLES_RAW_DEFAULT) @@ -2479,15 +2535,15 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): def test_security_group_member_updated(self): self.rpc.security_group_rules_for_devices.return_value = self.devices1 self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_1_2, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPTABLES_FILTER_2_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY, IPTABLES_RAW_DEFAULT) @@ -2505,9 +2561,9 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase): def test_security_group_rule_updated(self): self.rpc.security_group_rules_for_devices.return_value = self.devices2 self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPTABLES_FILTER_2_3, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self.agent.prepare_devices_filter(['tap_port1', 'tap_port3']) self.rpc.security_group_rules_for_devices.return_value = self.devices3 @@ -2582,7 +2638,7 @@ class TestSecurityGroupAgentEnhancedRpcWithIptables( self.ipconntrack._device_zone_map = {} self.sg_info.return_value = self.devices_info1 self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY, IPTABLES_RAW_DEFAULT) @@ -2594,15 +2650,15 @@ class TestSecurityGroupAgentEnhancedRpcWithIptables( def test_security_group_member_updated(self): self.sg_info.return_value = self.devices_info1 self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_1_2, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPTABLES_FILTER_2_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY, IPTABLES_RAW_DEFAULT) @@ -2622,9 +2678,9 @@ class TestSecurityGroupAgentEnhancedRpcWithIptables( def test_security_group_rule_updated(self): self.sg_info.return_value = self.devices_info2 self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPTABLES_FILTER_2_3, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self.agent.prepare_devices_filter(['tap_port1', 'tap_port3']) self.sg_info.return_value = self.devices_info3 @@ -2649,7 +2705,7 @@ class TestSecurityGroupAgentEnhancedIpsetWithIptables( self.ipconntrack._device_zone_map = {} self.sg_info.return_value = self.devices_info1 self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY, IPTABLES_RAW_DEFAULT) @@ -2663,15 +2719,15 @@ class TestSecurityGroupAgentEnhancedIpsetWithIptables( self.ipset._get_new_set_ips = mock.Mock(return_value=['10.0.0.3']) self.ipset._get_deleted_set_ips = mock.Mock(return_value=[]) self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_1) self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY, IPTABLES_RAW_DEFAULT) @@ -2693,9 +2749,9 @@ class TestSecurityGroupAgentEnhancedIpsetWithIptables( self.ipset._get_deleted_set_ips = mock.Mock(return_value=[]) self.sg_info.return_value = self.devices_info2 self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self._replay_iptables(IPSET_FILTER_2_3, IPTABLES_FILTER_V6_2, - IPTABLES_RAW_DEFAULT) + IPTABLES_RAW_BRIDGE_NET_2) self.agent.prepare_devices_filter(['tap_port1', 'tap_port3']) self.sg_info.return_value = self.devices_info3