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
This commit is contained in:
Slawek Kaplonski 2019-09-17 14:20:31 +02:00
parent 3ad6af7626
commit 5b341150e2
7 changed files with 66 additions and 5 deletions

View File

@ -266,6 +266,18 @@ class OVSBridge(BaseOVS):
protocol, protocol,
key=version_from_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): def create(self, secure_mode=False):
other_config = { other_config = {
'mac-table-size': str(cfg.CONF.OVS.bridge_mac_table_size)} 'mac-table-size': str(cfg.CONF.OVS.bridge_mac_table_size)}

View File

@ -33,6 +33,17 @@ OPTS = [
'outside a reasonable range (10 to 1,000,000) might be ' 'outside a reasonable range (10 to 1,000,000) might be '
'overridden by Open vSwitch according to the ' 'overridden by Open vSwitch according to the '
'documentation.')), '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.')),
] ]

View File

@ -1234,6 +1234,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
self.int_br.create() self.int_br.create()
self.int_br.set_secure_mode() self.int_br.set_secure_mode()
self.int_br.setup_controllers(self.conf) 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: if self.conf.AGENT.drop_flows_on_start:
# Delete the patch port between br-int and br-tun if we're deleting # Delete the patch port between br-int and br-tun if we're deleting

View File

@ -30,6 +30,7 @@ from neutron.agent.l2 import l2_agent_extensions_manager as ext_manager
from neutron.agent.linux import interface from neutron.agent.linux import interface
from neutron.common import utils from neutron.common import utils
from neutron.conf.agent import common as agent_config 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 import common as common_config
from neutron.conf.plugins.ml2.drivers import agent from neutron.conf.plugins.ml2.drivers import agent
from neutron.conf.plugins.ml2.drivers import ovs_conf from neutron.conf.plugins.ml2.drivers import ovs_conf
@ -137,6 +138,7 @@ class OVSAgentTestFramework(base.BaseOVSLinuxTestCase, OVSOFControllerHelper):
agent_config.register_interface_opts(config) agent_config.register_interface_opts(config)
agent_config.register_interface_driver_opts_helper(config) agent_config.register_interface_driver_opts_helper(config)
agent_config.register_agent_state_opts_helper(config) agent_config.register_agent_state_opts_helper(config)
ovs_agent_config.register_ovs_agent_opts(config)
ext_manager.register_opts(config) ext_manager.register_opts(config)
return config return config

View File

@ -186,6 +186,25 @@ class OVSBridgeTestCase(OVSBridgeTestBase):
self.br.db_get_val('Bridge', self.br.br_name, 'protocols'), self.br.db_get_val('Bridge', self.br.br_name, 'protocols'),
['OpenFlow10', 'OpenFlow12', 'OpenFlow13']) ['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): def test_get_datapath_id(self):
brdev = ip_lib.IPDevice(self.br.br_name) brdev = ip_lib.IPDevice(self.br.br_name)
dpid = brdev.link.attributes['link/ether'].replace(':', '') dpid = brdev.link.attributes['link/ether'].replace(':', '')

View File

@ -195,7 +195,7 @@ class TunnelTest(object):
'_check_bridge_datapath_id').start() '_check_bridge_datapath_id').start()
self._define_expected_calls() 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 = [ self.mock_int_bridge_cls_expected = [
mock.call(self.INT_BRIDGE, mock.call(self.INT_BRIDGE,
datapath_type=mock.ANY), datapath_type=mock.ANY),
@ -214,6 +214,7 @@ class TunnelTest(object):
mock.call.create(), mock.call.create(),
mock.call.set_secure_mode(), mock.call.set_secure_mode(),
mock.call.setup_controllers(mock.ANY), mock.call.setup_controllers(mock.ANY),
mock.call.set_igmp_snooping_state(igmp_snooping),
mock.call.setup_default_table(), mock.call.setup_default_table(),
] ]
@ -349,7 +350,13 @@ class TunnelTest(object):
# The next two tests use l2_pop flag to test ARP responder # The next two tests use l2_pop flag to test ARP responder
def test_construct_with_arp_responder(self): def test_construct_with_arp_responder(self):
self._build_agent(l2_population=True, arp_responder=True) 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() self._verify_mock_calls()
def test_construct_without_arp_responder(self): def test_construct_without_arp_responder(self):
@ -655,7 +662,7 @@ class TunnelTestOSKen(TunnelTest, ovs_test_base.OVSOSKenTestBase):
class TunnelTestUseVethInterco(TunnelTest): class TunnelTestUseVethInterco(TunnelTest):
USE_VETH_INTERCONNECTION = True 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 = [ self.mock_int_bridge_cls_expected = [
mock.call(self.INT_BRIDGE, mock.call(self.INT_BRIDGE,
datapath_type=mock.ANY), datapath_type=mock.ANY),
@ -673,6 +680,7 @@ class TunnelTestUseVethInterco(TunnelTest):
mock.call.create(), mock.call.create(),
mock.call.set_secure_mode(), mock.call.set_secure_mode(),
mock.call.setup_controllers(mock.ANY), mock.call.setup_controllers(mock.ANY),
mock.call.set_igmp_snooping_state(igmp_snooping),
mock.call.setup_default_table(), mock.call.setup_default_table(),
] ]
@ -749,8 +757,9 @@ class TunnelTestUseVethIntercoOSKen(TunnelTestUseVethInterco,
class TunnelTestWithMTU(TunnelTestUseVethInterco): class TunnelTestWithMTU(TunnelTestUseVethInterco):
VETH_MTU = 1500 VETH_MTU = 1500
def _define_expected_calls(self, arp_responder=False): def _define_expected_calls(self, arp_responder=False, igmp_snooping=False):
super(TunnelTestWithMTU, self)._define_expected_calls(arp_responder) super(TunnelTestWithMTU, self)._define_expected_calls(
arp_responder, igmp_snooping)
self.inta_expected.append(mock.call.link.set_mtu(self.VETH_MTU)) self.inta_expected.append(mock.call.link.set_mtu(self.VETH_MTU))
self.intb_expected.append(mock.call.link.set_mtu(self.VETH_MTU)) self.intb_expected.append(mock.call.link.set_mtu(self.VETH_MTU))

View File

@ -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.