Browse Source

Merge "Force arp_responder to True when DVR and tunneling enabled" into stable/train

tags/15.0.2
Zuul 2 weeks ago
parent
commit
91b368add3
5 changed files with 76 additions and 34 deletions
  1. +5
    -1
      neutron/conf/plugins/ml2/drivers/ovs_conf.py
  2. +13
    -22
      neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py
  3. +7
    -4
      neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py
  4. +43
    -7
      neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py
  5. +8
    -0
      releasenotes/notes/force-arp-responder-true-for-dvr-5aabbfa51945dd5a.yaml

+ 5
- 1
neutron/conf/plugins/ml2/drivers/ovs_conf.py View File

@@ -152,7 +152,11 @@ agent_opts = [
"Requires OVS 2.1 and ML2 l2population driver. "
"Allows the switch (when supporting an overlay) "
"to respond to an ARP request locally without "
"performing a costly ARP broadcast into the overlay.")),
"performing a costly ARP broadcast into the overlay. "
"NOTE: If enable_distributed_routing is set to True "
"then arp_responder will automatically be set to True "
"in the agent, regardless of the setting in the config "
"file.")),
cfg.BoolOpt('dont_fragment', default=True,
help=_("Set or un-set the don't fragment (DF) bit on "
"outgoing IP packet carrying GRE/VXLAN tunnel.")),

+ 13
- 22
neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py View File

@@ -121,8 +121,7 @@ class OVSDVRNeutronAgent(object):
patch_int_ofport=constants.OFPORT_INVALID,
patch_tun_ofport=constants.OFPORT_INVALID,
host=None, enable_tunneling=False,
enable_distributed_routing=False,
arp_responder_enabled=False):
enable_distributed_routing=False):
self.context = context
self.plugin_rpc = plugin_rpc
self.host = host
@@ -136,7 +135,6 @@ class OVSDVRNeutronAgent(object):
patch_int_ofport, patch_tun_ofport)
self.reset_dvr_parameters()
self.dvr_mac_address = None
self.arp_responder_enabled = arp_responder_enabled
if self.enable_distributed_routing:
self.get_dvr_mac_address()
self.conf = cfg.CONF
@@ -441,15 +439,12 @@ class OVSDVRNeutronAgent(object):
gateway_mac=subnet_info['gateway_mac'],
dst_mac=comp_ovsport.get_mac(),
dst_port=comp_ovsport.get_ofport())
# Add the following flow rule only when ARP RESPONDER is
# enabled
if self.arp_responder_enabled:
self.int_br.install_dvr_dst_mac_for_arp(
lvm.network_type,
vlan_tag=lvm.vlan,
gateway_mac=port.vif_mac,
dvr_mac=self.dvr_mac_address,
rtr_port=port.ofport)
self.int_br.install_dvr_dst_mac_for_arp(
lvm.network_type,
vlan_tag=lvm.vlan,
gateway_mac=port.vif_mac,
dvr_mac=self.dvr_mac_address,
rtr_port=port.ofport)

if lvm.network_type == n_const.TYPE_VLAN:
# TODO(vivek) remove the IPv6 related flows once SNAT is not
@@ -644,16 +639,12 @@ class OVSDVRNeutronAgent(object):
network_type=network_type,
vlan_tag=vlan_to_use, dst_mac=comp_port.get_mac())
ldm.remove_all_compute_ofports()
# If ARP Responder enabled, remove the rule that redirects
# the dvr_mac_address destination to the router port, since
# the router port is removed or unbound.
if self.arp_responder_enabled:
self.int_br.delete_dvr_dst_mac_for_arp(
network_type=network_type,
vlan_tag=vlan_to_use,
gateway_mac=port.vif_mac,
dvr_mac=self.dvr_mac_address,
rtr_port=port.ofport)
self.int_br.delete_dvr_dst_mac_for_arp(
network_type=network_type,
vlan_tag=vlan_to_use,
gateway_mac=port.vif_mac,
dvr_mac=self.dvr_mac_address,
rtr_port=port.ofport)
if ldm.get_csnat_ofport() == constants.OFPORT_INVALID:
# if there is no csnat port for this subnet, remove
# this subnet from local_dvr_map, as no dvr (or) csnat

+ 7
- 4
neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py View File

@@ -164,17 +164,21 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
self.available_local_vlans = set(six.moves.range(
n_const.MIN_VLAN_TAG, n_const.MAX_VLAN_TAG + 1))
self.tunnel_types = agent_conf.tunnel_types or []
self.enable_tunneling = bool(self.tunnel_types)
self.l2_pop = agent_conf.l2_population
# TODO(ethuleau): Change ARP responder so it's not dependent on the
# ML2 l2 population mechanism driver.
self.enable_distributed_routing = agent_conf.enable_distributed_routing
self.arp_responder_enabled = agent_conf.arp_responder and self.l2_pop
if (self.enable_distributed_routing and self.enable_tunneling and
not self.arp_responder_enabled):
LOG.warning("ARP responder was not enabled but is required since "
"DVR and tunneling are enabled, setting to True.")
self.arp_responder_enabled = True

host = self.conf.host
self.agent_id = 'ovs-agent-%s' % host

self.enable_tunneling = bool(self.tunnel_types)

# Validate agent configurations
self._check_agent_configurations()

@@ -258,8 +262,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
self.patch_tun_ofport,
host,
self.enable_tunneling,
self.enable_distributed_routing,
self.arp_responder_enabled)
self.enable_distributed_routing)

if self.enable_distributed_routing:
self.dvr_agent.setup_dvr_flows()

+ 43
- 7
neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py View File

@@ -2929,14 +2929,38 @@ class TestOvsDvrNeutronAgent(object):
'ip_address': '1.1.1.3'}]

@staticmethod
def _expected_port_bound(port, lvid, is_dvr=True):
def _expected_port_bound(port, lvid, is_dvr=True,
network_type=n_const.TYPE_VXLAN):
resp = [
mock.call.db_get_val('Port', port.port_name, 'other_config'),
mock.call.set_db_attribute('Port', port.port_name, 'other_config',
mock.ANY),
]
if is_dvr:
resp = [mock.call.get_vifs_by_ids([])] + resp
resp = [
mock.call.get_vifs_by_ids([]),
mock.call.install_dvr_dst_mac_for_arp(
network_type,
dvr_mac=port.dvr_mac,
gateway_mac=port.vif_mac,
rtr_port=port.ofport,
vlan_tag=lvid)
] + resp
return resp

@staticmethod
def _expected_port_unbound(port, lvid, is_dvr=True,
network_type=n_const.TYPE_VXLAN):
resp = []
if is_dvr:
resp = [
mock.call.delete_dvr_dst_mac_for_arp(
network_type=network_type,
dvr_mac=port.dvr_mac,
gateway_mac=port.vif_mac,
rtr_port=port.ofport,
vlan_tag=lvid)
]
return resp

def _expected_install_dvr_process(self, lvid, port, ip_version,
@@ -2971,6 +2995,7 @@ class TestOvsDvrNeutronAgent(object):
gateway_ip = '2001:100::1'
cidr = '2001:100::0/64'
self._port.vif_mac = 'aa:bb:cc:11:22:33'
self._port.dvr_mac = self.agent.dvr_agent.dvr_mac_address
gateway_mac = 'aa:bb:cc:66:66:66'
self._compute_port.vif_mac = '77:88:99:00:11:22'
physical_network = self._physical_network
@@ -3026,7 +3051,8 @@ class TestOvsDvrNeutronAgent(object):
lvid=lvid,
segmentation_id=segmentation_id,
),
] + self._expected_port_bound(self._port, lvid)
] + self._expected_port_bound(self._port, lvid,
network_type=network_type)
self.assertEqual(expected_on_int_br, int_br.mock_calls)
self.assertEqual([], tun_br.mock_calls)
self.assertEqual(expected_on_phys_br, phys_br.mock_calls)
@@ -3046,7 +3072,9 @@ class TestOvsDvrNeutronAgent(object):
dst_port=self._compute_port.ofport,
vlan_tag=segmentation_id,
),
] + self._expected_port_bound(self._compute_port, lvid, False)
] + self._expected_port_bound(self._compute_port, lvid,
is_dvr=False,
network_type=network_type)
self.assertEqual(expected_on_int_br, int_br.mock_calls)
self.assertFalse([], tun_br.mock_calls)
self.assertFalse([], phys_br.mock_calls)
@@ -3062,6 +3090,7 @@ class TestOvsDvrNeutronAgent(object):
cidr = '2001:100::0/64'
network_type = n_const.TYPE_VXLAN
self._port.vif_mac = gateway_mac = 'aa:bb:cc:11:22:33'
self._port.dvr_mac = self.agent.dvr_agent.dvr_mac_address
self._compute_port.vif_mac = '77:88:99:00:11:22'
physical_network = self._physical_network
segmentation_id = self._segmentation_id
@@ -3127,7 +3156,8 @@ class TestOvsDvrNeutronAgent(object):
dst_port=self._compute_port.ofport,
vlan_tag=lvid,
),
] + self._expected_port_bound(self._compute_port, lvid, False)
] + self._expected_port_bound(self._compute_port, lvid, False,
network_type)
self.assertEqual(expected_on_int_br, int_br.mock_calls)
self.assertEqual([], tun_br.mock_calls)
self.assertEqual([], phys_br.mock_calls)
@@ -3300,6 +3330,7 @@ class TestOvsDvrNeutronAgent(object):
else:
gateway_ip = '2001:100::1'
cidr = '2001:100::0/64'
self._port.dvr_mac = self.agent.dvr_agent.dvr_mac_address
gateway_mac = 'aa:bb:cc:11:22:33'
int_br = mock.create_autospec(self.agent.int_br)
tun_br = mock.create_autospec(self.agent.tun_br)
@@ -3390,12 +3421,16 @@ class TestOvsDvrNeutronAgent(object):
vif_mac=self._port.vif_mac),
])
if network_type == 'vlan':
self.assertEqual([], int_br.mock_calls)
expected_unbound_dvr = self._expected_port_unbound(self._port,
self._segmentation_id, network_type=network_type)
self.assertEqual(expected_unbound_dvr, int_br.mock_calls)
self.assertEqual([], tun_br.mock_calls)
self.assertEqual(expected, phys_br.mock_calls)
self.assertEqual({}, self.agent.dvr_agent.local_ports)
else:
self.assertEqual([], int_br.mock_calls)
expected_unbound_dvr = self._expected_port_unbound(self._port,
lvid, network_type=network_type)
self.assertEqual(expected_unbound_dvr, int_br.mock_calls)
self.assertEqual(expected, tun_br.mock_calls)
self.assertEqual([], phys_br.mock_calls)

@@ -3408,6 +3443,7 @@ class TestOvsDvrNeutronAgent(object):
else:
gateway_ip = '2001:100::1'
cidr = '2001:100::0/64'
self._port.dvr_mac = self.agent.dvr_agent.dvr_mac_address
gateway_mac = 'aa:bb:cc:11:22:33'
int_br = mock.create_autospec(self.agent.int_br)
tun_br = mock.create_autospec(self.agent.tun_br)

+ 8
- 0
releasenotes/notes/force-arp-responder-true-for-dvr-5aabbfa51945dd5a.yaml View File

@@ -0,0 +1,8 @@
---
other:
- |
When the ``enable_distributed_routing`` (DVR) configuration option is set
to ``True`` and tunneling is enabled, the ``arp_responder`` option will
be forced to ``True`` since it is now required in order for ARP to work
properly. For more information, see bug
`1774459 <https://bugs.launchpad.net/neutron/+bug/1774459>`_.

Loading…
Cancel
Save