[L3-HA] Disable automatic link-local address assignment for HA routers

In order to get both [1] and [2] fixed, we set
`net.ipv6.conf.all.addr_gen_mode=1` in HA router namespace to
prevent auto-assigning link-local address(lla) to the interfaces.
We don't need lla auto-assignment as keepalived manages them.
With this change, we will have link-local addresses only on active
router, which will prevent 'dadfailed' and MLD packets will not be
sent from standby router.

Previously we also reverted [3] to always keep qg-* interface up on both
active&standby router's instance, no matter if keepalived is started or
not.
Without link-local address assigned, backup router's instance won't
send any packets, so I see no reason to keep qg-* interface down.

[1] https://bugs.launchpad.net/neutron/+bug/1952907
[2] https://bugs.launchpad.net/neutron/+bug/1859832
[3] https://review.opendev.org/c/openstack/neutron/+/834162

Closes-Bug: #1952907
Related-Bug: #1859832
Depends-On: https://review.opendev.org/c/openstack/neutron/+/834162
Change-Id: I306f14aa6b7e8bb69a81f441be337bc1a584d3b2
This commit is contained in:
Damian Dabrowski 2022-04-28 02:54:25 +02:00 committed by Damian Dąbrowski
parent 36bf1df46d
commit 5288593faf
3 changed files with 49 additions and 0 deletions

View File

@ -63,6 +63,11 @@ class HaRouterNamespace(namespaces.RouterNamespace):
super(HaRouterNamespace, self).create(ipv6_forwarding=False)
# HA router namespaces should not have ip_nonlocal_bind enabled
ip_lib.set_ip_nonlocal_bind_for_namespace(self.name, 0)
# Linux should not automatically assign link-local addr for HA routers
# They are managed by keepalived
ip_wrapper = ip_lib.IPWrapper(namespace=self.name)
cmd = ['sysctl', '-w', 'net.ipv6.conf.all.addr_gen_mode=1']
ip_wrapper.netns.execute(cmd, privsep_exec=True)
class HaRouter(router.RouterInfo):

View File

@ -276,6 +276,19 @@ class L3AgentTestFramework(base.BaseSudoTestCase):
def _assert_external_device(self, router):
self.assertTrue(self._check_external_device(router))
def _wait_until_addr_gen_mode_has_state(
self, ns_name, state):
ip_wrapper = ip_lib.IPWrapper(namespace=ns_name)
def _addr_gen_mode_state():
addr_gen_mode_state = ip_wrapper.netns.execute(
['sysctl', '-b', 'net.ipv6.conf.all.addr_gen_mode'],
privsep_exec=True)
return (
state == int(addr_gen_mode_state))
common_utils.wait_until_true(_addr_gen_mode_state)
def _wait_until_ipv6_accept_ra_has_state(
self, ns_name, device_name, enabled):
ip_wrapper = ip_lib.IPWrapper(namespace=ns_name)

View File

@ -352,6 +352,37 @@ class L3HATestCase(framework.L3AgentTestFramework):
raise
self.assertEqual(0, ip_nonlocal_bind_value)
@testtools.skipUnless(netutils.is_ipv6_enabled(), "IPv6 is not enabled")
def test_ha_router_addr_gen_mode(self):
router_info = self.generate_router_info(enable_ha=True)
router_info[constants.HA_INTERFACE_KEY]['status'] = (
constants.PORT_STATUS_DOWN)
router = self.manage_router(self.agent, router_info)
external_port = router.get_ex_gw_port()
external_device_name = router.get_external_device_name(
external_port['id'])
def check_gw_lla_status(expected):
lladdr = ip_lib.get_ipv6_lladdr(
external_port['mac_address'])
exists = ip_lib.device_exists_with_ips_and_mac(
external_device_name, [lladdr],
external_port['mac_address'], router.ns_name)
self.assertEqual(expected, exists)
self.wait_until_ha_router_has_state(router, 'backup')
self._wait_until_addr_gen_mode_has_state(
router.ns_name, 1)
check_gw_lla_status(False)
router.router[constants.HA_INTERFACE_KEY]['status'] = (
constants.PORT_STATUS_ACTIVE)
self.agent._process_updated_router(router.router)
self.wait_until_ha_router_has_state(router, 'primary')
self._wait_until_addr_gen_mode_has_state(
router.ns_name, 1)
check_gw_lla_status(True)
@testtools.skipUnless(netutils.is_ipv6_enabled(), "IPv6 is not enabled")
def test_ha_router_namespace_has_ipv6_forwarding_disabled(self):
router_info = self.generate_router_info(enable_ha=True)