diff --git a/neutron/agent/common/ovs_lib.py b/neutron/agent/common/ovs_lib.py index b19dbfd6541..92966323fc0 100644 --- a/neutron/agent/common/ovs_lib.py +++ b/neutron/agent/common/ovs_lib.py @@ -278,7 +278,7 @@ class OVSBridge(BaseOVS): def set_igmp_snooping_state(self, state): state = bool(state) other_config = { - 'mcast-snooping-disable-flood-unregistered': str(state)} + 'mcast-snooping-disable-flood-unregistered': 'false'} with self.ovsdb.transaction() as txn: txn.add( self.ovsdb.db_set('Bridge', self.br_name, @@ -287,6 +287,16 @@ class OVSBridge(BaseOVS): self.ovsdb.db_set('Bridge', self.br_name, ('other_config', other_config))) + def set_igmp_snooping_flood(self, port_name, state): + state = str(state) + other_config = { + 'mcast-snooping-flood-reports': state, + 'mcast-snooping-flood': state} + self.ovsdb.db_set( + 'Port', port_name, + ('other_config', other_config)).execute( + check_error=True, log_errors=True) + def create(self, secure_mode=False): other_config = { 'mac-table-size': str(cfg.CONF.OVS.bridge_mac_table_size)} diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index 76c08e6a8de..d8b428f5850 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -1421,6 +1421,9 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, "version of OVS does not support tunnels or patch " "ports. Agent terminated!") sys.exit(1) + self.int_br.set_igmp_snooping_flood( + self.conf.OVS.int_peer_patch_port, + self.conf.OVS.igmp_snooping_enable) if self.conf.AGENT.drop_flows_on_start: self.tun_br.uninstall_flows(cookie=ovs_lib.COOKIE_ANY) @@ -1574,6 +1577,8 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, phys_ofport = br.add_patch_port( phys_if_name, constants.NONEXISTENT_PEER) + self.int_br.set_igmp_snooping_flood( + int_if_name, self.conf.OVS.igmp_snooping_enable) self.int_ofports[physical_network] = int_ofport self.phys_ofports[physical_network] = phys_ofport diff --git a/neutron/tests/functional/agent/common/test_ovs_lib.py b/neutron/tests/functional/agent/common/test_ovs_lib.py index 0ebd4b8b377..0ca34f1c40b 100644 --- a/neutron/tests/functional/agent/common/test_ovs_lib.py +++ b/neutron/tests/functional/agent/common/test_ovs_lib.py @@ -486,3 +486,27 @@ class BaseOVSTestCase(base.BaseSudoTestCase): self.assertEqual(p_const.TYPE_GRE, ipv4_port_type) self.assertEqual(ovs_lib.TYPE_GRE_IP6, ipv6_port_type) self.assertEqual('legacy_l2', ipv6_port_options.get('packet_type')) + + def test_set_igmp_snooping_flood(self): + port_name = 'test_output_port_2' + self._create_bridge() + self._create_port(port_name) + self.ovs.set_igmp_snooping_flood(port_name, True) + ports_other_config = self.ovs.db_get_val('Port', port_name, + 'other_config') + self.assertEqual( + 'true', + ports_other_config.get('mcast-snooping-flood', '').lower()) + self.assertEqual( + 'true', + ports_other_config.get('mcast-snooping-flood-reports', '').lower()) + + self.ovs.set_igmp_snooping_flood(port_name, False) + ports_other_config = self.ovs.db_get_val('Port', port_name, + 'other_config') + self.assertEqual( + 'false', + ports_other_config.get('mcast-snooping-flood', '').lower()) + self.assertEqual( + 'false', + ports_other_config.get('mcast-snooping-flood-reports', '').lower()) diff --git a/neutron/tests/functional/agent/test_ovs_lib.py b/neutron/tests/functional/agent/test_ovs_lib.py index 67728305d2f..b2c34b705b8 100644 --- a/neutron/tests/functional/agent/test_ovs_lib.py +++ b/neutron/tests/functional/agent/test_ovs_lib.py @@ -195,8 +195,9 @@ class OVSBridgeTestCase(OVSBridgeTestBase): 'Bridge', ('name', '=', self.br.br_name), columns=['other_config'] ).execute()[0]['other_config'] self.assertEqual( - str(state), - br_other_config['mcast-snooping-disable-flood-unregistered']) + 'false', + br_other_config.get( + 'mcast-snooping-disable-flood-unregistered', '').lower()) def test_set_igmp_snooping_enabled(self): self._test_set_igmp_snooping_state(True) diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index 2eb43e9b0c7..2f45390503a 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@ -1541,7 +1541,8 @@ class TestOvsNeutronAgent(object): self.assertNotIn('activated_port_id', port_info['added']) def _test_setup_physical_bridges(self, port_exists=False, - dvr_enabled=False): + dvr_enabled=False, + igmp_snooping_enabled=False): self.agent.enable_distributed_routing = dvr_enabled with mock.patch.object(ip_lib.IPDevice, "exists") as devex_fn,\ mock.patch.object(sys, "exit"),\ @@ -1599,6 +1600,8 @@ class TestOvsNeutronAgent(object): 'phy-br-eth', constants.NONEXISTENT_PEER), ] expected_calls += [ + mock.call.int_br.set_igmp_snooping_flood( + 'int-br-eth', igmp_snooping_enabled), mock.call.int_br.drop_port(in_port='int_ofport') ] if not dvr_enabled: @@ -1668,6 +1671,10 @@ class TestOvsNeutronAgent(object): int_br.add_port.assert_called_with("int-br-eth") phys_br.add_port.assert_called_with("phy-br-eth") + def test_setup_physical_bridges_igmp_snooping_enabled(self): + cfg.CONF.set_override('igmp_snooping_enable', True, 'OVS') + self._test_setup_physical_bridges(igmp_snooping_enabled=True) + def _test_setup_physical_bridges_change_from_veth_to_patch_conf( self, port_exists=False): with mock.patch.object(sys, "exit"),\ @@ -1723,6 +1730,8 @@ class TestOvsNeutronAgent(object): 'phy-br-eth', constants.NONEXISTENT_PEER), ] expected_calls += [ + mock.call.int_br.set_igmp_snooping_flood( + 'int-br-eth', False), mock.call.int_br.drop_port(in_port='int_ofport'), mock.call.phys_br.drop_port(in_port='phy_ofport'), mock.call.int_br.set_db_attribute('Interface', 'int-br-eth', @@ -1763,6 +1772,8 @@ class TestOvsNeutronAgent(object): return_value=False),\ mock.patch.object(self.agent.int_br, 'port_exists', return_value=False),\ + mock.patch.object(self.agent.int_br, + 'set_igmp_snooping_flood'),\ mock.patch.object(sys, "exit"): self.agent.setup_tunnel_br(None) self.agent.setup_tunnel_br() @@ -1787,6 +1798,8 @@ class TestOvsNeutronAgent(object): "add_patch_port") as int_patch_port,\ mock.patch.object(self.agent.tun_br, "add_patch_port") as tun_patch_port,\ + mock.patch.object(self.agent.int_br, + 'set_igmp_snooping_flood'),\ mock.patch.object(sys, "exit"): self.agent.setup_tunnel_br(None) self.agent.setup_tunnel_br() diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py index edccc6beb97..865660c057f 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py @@ -229,6 +229,8 @@ class TunnelTest(object): mock.call.port_exists('int-%s' % self.MAP_TUN_BRIDGE), mock.call.add_patch_port('int-%s' % self.MAP_TUN_BRIDGE, constants.NONEXISTENT_PEER), + mock.call.set_igmp_snooping_flood('int-%s' % self.MAP_TUN_BRIDGE, + igmp_snooping), ] self.mock_int_bridge_expected += [ @@ -258,6 +260,7 @@ class TunnelTest(object): self.mock_int_bridge_expected += [ mock.call.port_exists('patch-tun'), mock.call.add_patch_port('patch-tun', 'patch-int'), + mock.call.set_igmp_snooping_flood('patch-tun', igmp_snooping), ] self.mock_int_bridge_expected += [ mock.call.get_vif_ports((ovs_lib.INVALID_OFPORT, @@ -710,7 +713,9 @@ class TunnelTestUseVethInterco(TunnelTest): self.mock_int_bridge_expected += [ mock.call.db_get_val('Interface', 'int-%s' % self.MAP_TUN_BRIDGE, 'type', log_errors=False), - mock.call.add_port('int-%s' % self.MAP_TUN_BRIDGE) + mock.call.add_port('int-%s' % self.MAP_TUN_BRIDGE), + mock.call.set_igmp_snooping_flood('int-%s' % self.MAP_TUN_BRIDGE, + igmp_snooping), ] self.mock_int_bridge_expected += [ @@ -733,7 +738,8 @@ class TunnelTestUseVethInterco(TunnelTest): ] self.mock_int_bridge_expected += [ mock.call.port_exists('patch-tun'), - mock.call.add_patch_port('patch-tun', 'patch-int') + mock.call.add_patch_port('patch-tun', 'patch-int'), + mock.call.set_igmp_snooping_flood('patch-tun', igmp_snooping), ] self.mock_int_bridge_expected += [ mock.call.get_vif_ports((ovs_lib.INVALID_OFPORT,