From de322da9e0d91a321823332d89c4e17072641e61 Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Tue, 17 Sep 2019 14:20:31 +0200 Subject: [PATCH] Add "igmp_snooping_enable" config option for OVS agent Neutron-ovs-agent can now enable IGMP snooping in integration bridge if config option "igmp_snooping_enable" in OVS section in config will be set to True. It will also set mcast-snooping-disable-flood-unregistered=true so flooding of multicast packets to all unregistered ports will be disabled also. Both changes are applied on integration bridge. Change-Id: I12f4030a35d10d1715d3b4bfb3ed5efb9aa28f2b Closes-Bug: #1840136 (cherry picked from commit 5b341150e29137e3dab671453a9a6c0908e74585) --- neutron/agent/common/ovs_lib.py | 12 ++++++++++++ neutron/conf/agent/ovs_conf.py | 11 +++++++++++ .../openvswitch/agent/ovs_neutron_agent.py | 1 + neutron/tests/functional/agent/l2/base.py | 2 ++ .../tests/functional/agent/test_ovs_lib.py | 19 +++++++++++++++++++ .../openvswitch/agent/test_ovs_tunnel.py | 19 ++++++++++++++----- ...enable-config-option-6a0e15e4ed0a2cf7.yaml | 7 +++++++ 7 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/add-igmp_snooping_enable-config-option-6a0e15e4ed0a2cf7.yaml diff --git a/neutron/agent/common/ovs_lib.py b/neutron/agent/common/ovs_lib.py index 0a50c8fde07..2de22d330c0 100644 --- a/neutron/agent/common/ovs_lib.py +++ b/neutron/agent/common/ovs_lib.py @@ -269,6 +269,18 @@ class OVSBridge(BaseOVS): protocol, key=version_from_protocol) + def set_igmp_snooping_state(self, state): + state = bool(state) + other_config = { + 'mcast-snooping-disable-flood-unregistered': str(state)} + with self.ovsdb.transaction() as txn: + txn.add( + self.ovsdb.db_set('Bridge', self.br_name, + ('mcast_snooping_enable', state))) + txn.add( + self.ovsdb.db_set('Bridge', self.br_name, + ('other_config', other_config))) + def create(self, secure_mode=False): other_config = { 'mac-table-size': str(cfg.CONF.OVS.bridge_mac_table_size)} diff --git a/neutron/conf/agent/ovs_conf.py b/neutron/conf/agent/ovs_conf.py index f81d20fce4f..ff69c2f1753 100644 --- a/neutron/conf/agent/ovs_conf.py +++ b/neutron/conf/agent/ovs_conf.py @@ -34,6 +34,17 @@ OPTS = [ 'outside a reasonable range (10 to 1,000,000) might be ' 'overridden by Open vSwitch according to the ' 'documentation.')), + cfg.BoolOpt('igmp_snooping_enable', default=False, + help=_('Enable IGMP snooping for integration bridge. If this ' + 'option is set to True, support for Internet Group ' + 'Management Protocol (IGMP) is enabled in integration ' + 'bridge. ' + 'Setting this option to True will also enable Open ' + 'vSwitch mcast-snooping-disable-flood-unregistered ' + 'flag. This option will disable flooding of ' + 'unregistered multicast packets to all ports. ' + 'The switch will send unregistered multicast packets ' + 'only to ports connected to multicast routers.')), ] 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 160ce5cc7ff..ea96d59b35d 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -1101,6 +1101,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, self.int_br.create() self.int_br.set_secure_mode() self.int_br.setup_controllers(self.conf) + self.int_br.set_igmp_snooping_state(self.conf.OVS.igmp_snooping_enable) if self.conf.AGENT.drop_flows_on_start: # Delete the patch port between br-int and br-tun if we're deleting diff --git a/neutron/tests/functional/agent/l2/base.py b/neutron/tests/functional/agent/l2/base.py index 94d1692d1c1..979d230fd4b 100644 --- a/neutron/tests/functional/agent/l2/base.py +++ b/neutron/tests/functional/agent/l2/base.py @@ -29,6 +29,7 @@ from neutron.agent.linux import interface from neutron.agent.linux import polling from neutron.common import utils from neutron.conf.agent import common as agent_config +from neutron.conf.agent import ovs_conf as ovs_agent_config from neutron.conf import common as common_config from neutron.conf.plugins.ml2.drivers import agent from neutron.conf.plugins.ml2.drivers import ovs_conf @@ -75,6 +76,7 @@ class OVSAgentTestFramework(base.BaseOVSLinuxTestCase): agent_config.register_interface_opts(config) agent_config.register_interface_driver_opts_helper(config) agent_config.register_agent_state_opts_helper(config) + ovs_agent_config.register_ovs_agent_opts(config) ext_manager.register_opts(config) return config diff --git a/neutron/tests/functional/agent/test_ovs_lib.py b/neutron/tests/functional/agent/test_ovs_lib.py index 331c3e8677f..45aa364cb0b 100644 --- a/neutron/tests/functional/agent/test_ovs_lib.py +++ b/neutron/tests/functional/agent/test_ovs_lib.py @@ -186,6 +186,25 @@ class OVSBridgeTestCase(OVSBridgeTestBase): self.br.db_get_val('Bridge', self.br.br_name, 'protocols'), ['OpenFlow10', 'OpenFlow12', 'OpenFlow13']) + def _test_set_igmp_snooping_state(self, state): + self.br.set_igmp_snooping_state(state) + self.assertEqual( + state, + self.br.db_get_val( + 'Bridge', self.br.br_name, 'mcast_snooping_enable')) + br_other_config = self.ovs.ovsdb.db_find( + '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']) + + def test_set_igmp_snooping_enabled(self): + self._test_set_igmp_snooping_state(True) + + def test_set_igmp_snooping_disabled(self): + self._test_set_igmp_snooping_state(False) + def test_get_datapath_id(self): brdev = ip_lib.IPDevice(self.br.br_name) dpid = brdev.link.attributes['link/ether'].replace(':', '') 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 48100f7b3cf..f8c62168c04 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 @@ -193,7 +193,7 @@ class TunnelTest(object): '_check_bridge_datapath_id').start() self._define_expected_calls() - def _define_expected_calls(self, arp_responder=False): + def _define_expected_calls(self, arp_responder=False, igmp_snooping=False): self.mock_int_bridge_cls_expected = [ mock.call(self.INT_BRIDGE, datapath_type=mock.ANY), @@ -212,6 +212,7 @@ class TunnelTest(object): mock.call.create(), mock.call.set_secure_mode(), mock.call.setup_controllers(mock.ANY), + mock.call.set_igmp_snooping_state(igmp_snooping), mock.call.setup_default_table(), ] @@ -345,7 +346,13 @@ class TunnelTest(object): # The next two tests use l2_pop flag to test ARP responder def test_construct_with_arp_responder(self): self._build_agent(l2_population=True, arp_responder=True) - self._define_expected_calls(True) + self._define_expected_calls(arp_responder=True) + self._verify_mock_calls() + + def test_construct_with_igmp_snooping(self): + cfg.CONF.set_override('igmp_snooping_enable', True, 'OVS') + self._build_agent() + self._define_expected_calls(igmp_snooping=True) self._verify_mock_calls() def test_construct_without_arp_responder(self): @@ -661,7 +668,7 @@ class TunnelTestRyu(TunnelTest, ovs_test_base.OVSRyuTestBase): class TunnelTestUseVethInterco(TunnelTest): USE_VETH_INTERCONNECTION = True - def _define_expected_calls(self, arp_responder=False): + def _define_expected_calls(self, arp_responder=False, igmp_snooping=False): self.mock_int_bridge_cls_expected = [ mock.call(self.INT_BRIDGE, datapath_type=mock.ANY), @@ -679,6 +686,7 @@ class TunnelTestUseVethInterco(TunnelTest): mock.call.create(), mock.call.set_secure_mode(), mock.call.setup_controllers(mock.ANY), + mock.call.set_igmp_snooping_state(igmp_snooping), mock.call.setup_default_table(), ] @@ -760,8 +768,9 @@ class TunnelTestUseVethIntercoRyu(TunnelTestUseVethInterco, class TunnelTestWithMTU(TunnelTestUseVethInterco): VETH_MTU = 1500 - def _define_expected_calls(self, arp_responder=False): - super(TunnelTestWithMTU, self)._define_expected_calls(arp_responder) + def _define_expected_calls(self, arp_responder=False, igmp_snooping=False): + super(TunnelTestWithMTU, self)._define_expected_calls( + arp_responder, igmp_snooping) self.inta_expected.append(mock.call.link.set_mtu(self.VETH_MTU)) self.intb_expected.append(mock.call.link.set_mtu(self.VETH_MTU)) diff --git a/releasenotes/notes/add-igmp_snooping_enable-config-option-6a0e15e4ed0a2cf7.yaml b/releasenotes/notes/add-igmp_snooping_enable-config-option-6a0e15e4ed0a2cf7.yaml new file mode 100644 index 00000000000..1421ebb8faf --- /dev/null +++ b/releasenotes/notes/add-igmp_snooping_enable-config-option-6a0e15e4ed0a2cf7.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Add new configuration option ``igmp_snooping_enable``. New option is in + ``OVS`` config section and is used by openvswitch agent. + This option is used to enable support for Internet Group Management + Protocol (IGMP) in integration bridge.