Fix multicast traffic with IGMP snooping enabled
In the ML2/OVS when igmp_snooping is enabled but there is no external querier multicast traffic will stop working after few minutes as packets will not be flooded to tunnel/external bridges. So this patch sets "mcast-snooping-disable-flood-unregistered" option of the br-int to False (default value) even when igmp_snooping is enabled in the neutron-ovs-agent's config file. Additionally it configures "mcast-snooping-flood-reports" and "mcast-snooping-flood" on patch ports in br-int to True. That way we can provide best effort snooping: multicast isolation where IGMP queriers are available and flood everywhere else? Closes-Bug: #1884723 Change-Id: Iefa0044dba9e92592295a79448e5d57d9e14a40b
This commit is contained in:
parent
8d6c301301
commit
b4070c9752
|
@ -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)}
|
||||
|
|
|
@ -1407,6 +1407,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)
|
||||
|
||||
|
@ -1539,6 +1542,8 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
|
|||
else:
|
||||
int_ofport = self.int_br.add_patch_port(
|
||||
int_if_name, constants.NONEXISTENT_PEER)
|
||||
self.int_br.set_igmp_snooping_flood(
|
||||
int_if_name, self.conf.OVS.igmp_snooping_enable)
|
||||
if br.port_exists(phys_if_name):
|
||||
phys_ofport = br.get_port_ofport(phys_if_name)
|
||||
else:
|
||||
|
|
|
@ -470,3 +470,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', 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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1533,7 +1533,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"),\
|
||||
|
@ -1579,6 +1580,8 @@ class TestOvsNeutronAgent(object):
|
|||
'int-br-eth', constants.NONEXISTENT_PEER),
|
||||
]
|
||||
expected_calls += [
|
||||
mock.call.int_br.set_igmp_snooping_flood(
|
||||
'int-br-eth', igmp_snooping_enabled),
|
||||
mock.call.phys_br.port_exists('phy-br-eth'),
|
||||
]
|
||||
if port_exists:
|
||||
|
@ -1620,6 +1623,10 @@ class TestOvsNeutronAgent(object):
|
|||
def test_setup_physical_bridges_dvr_enabled(self):
|
||||
self._test_setup_physical_bridges(dvr_enabled=True)
|
||||
|
||||
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"),\
|
||||
|
@ -1663,6 +1670,8 @@ class TestOvsNeutronAgent(object):
|
|||
'int-br-eth', constants.NONEXISTENT_PEER),
|
||||
]
|
||||
expected_calls += [
|
||||
mock.call.int_br.set_igmp_snooping_flood(
|
||||
'int-br-eth', False),
|
||||
mock.call.phys_br.port_exists('phy-br-eth'),
|
||||
]
|
||||
if port_exists:
|
||||
|
@ -1715,6 +1724,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()
|
||||
|
@ -1739,6 +1750,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()
|
||||
|
|
|
@ -228,6 +228,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 += [
|
||||
|
@ -257,6 +259,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,
|
||||
|
|
Loading…
Reference in New Issue