Configure gw_iface for RAs only in Master HA Router

For an HA Router which does not have any IPv6 subnets in the external network
and when ipv6_gateway is not set, Neutron configures the gateway interface of
the router to receive Router Advts for default route. In an HA router, only
the Master instance has the IP addresses while the Backup instance does not
have any addresses (including LLA). In Kernel version 3.10, when the last
IPv6 address is removed from the interface, IPv6 proc entries corresponding
to the iface are also deleted. This is however reverted in the later versions
of kernel code.

This patch addresses this issue by configuring the proc entry only for the
Master HA Router instance instead of doing it un-conditionally.

Conflicts:
	neutron/agent/l3/ha_router.py
	neutron/agent/l3/router_info.py

Closes-Bug: #1494336
(cherry picked from commit c89a4fdd88)
Change-Id: Ibf8e0ff64cda00314f8fa649ef5019c95c2d6004
This commit is contained in:
sridhargaddam 2015-09-10 16:14:13 +00:00 committed by abregman
parent 767cea23de
commit 4d15b6fe12
3 changed files with 20 additions and 11 deletions

View File

@ -122,10 +122,23 @@ class AgentMixin(object):
'possibly deleted concurrently.'), router_id) 'possibly deleted concurrently.'), router_id)
return return
self._configure_ipv6_ra_on_ext_gw_port_if_necessary(ri, state)
self._update_metadata_proxy(ri, router_id, state) self._update_metadata_proxy(ri, router_id, state)
self._update_radvd_daemon(ri, state) self._update_radvd_daemon(ri, state)
self.state_change_notifier.queue_event((router_id, state)) self.state_change_notifier.queue_event((router_id, state))
def _configure_ipv6_ra_on_ext_gw_port_if_necessary(self, ri, state):
# If ipv6 is enabled on the platform, ipv6_gateway config flag is
# not set and external_network associated to the router does not
# include any IPv6 subnet, enable the gateway interface to accept
# Router Advts from upstream router for default route.
ex_gw_port_id = ri.ex_gw_port and ri.ex_gw_port['id']
if state == 'master' and ex_gw_port_id and ri.use_ipv6:
gateway_ips = ri._get_external_gw_ips(ri.ex_gw_port)
if not ri.is_v6_gateway_set(gateway_ips):
interface_name = ri.get_external_device_name(ex_gw_port_id)
ri.driver.configure_ipv6_ra(ri.ns_name, interface_name)
def _update_metadata_proxy(self, ri, router_id, state): def _update_metadata_proxy(self, ri, router_id, state):
if state == 'master': if state == 'master':
LOG.debug('Spawning metadata proxy for router %s', router_id) LOG.debug('Spawning metadata proxy for router %s', router_id)

View File

@ -192,7 +192,7 @@ class HaRouter(router.RouterInfo):
self.routes = new_routes self.routes = new_routes
def _add_default_gw_virtual_route(self, ex_gw_port, interface_name): def _add_default_gw_virtual_route(self, ex_gw_port, interface_name):
gateway_ips, enable_ra_on_gw = self._get_external_gw_ips(ex_gw_port) gateway_ips = self._get_external_gw_ips(ex_gw_port)
for gw_ip in gateway_ips: for gw_ip in gateway_ips:
# TODO(Carl) This is repeated everywhere. A method would # TODO(Carl) This is repeated everywhere. A method would
# be nice. # be nice.
@ -207,9 +207,6 @@ class HaRouter(router.RouterInfo):
keepalived.KeepalivedVirtualRoute( keepalived.KeepalivedVirtualRoute(
default_gw, gw_ip, interface_name)) default_gw, gw_ip, interface_name))
if enable_ra_on_gw:
self.driver.configure_ipv6_ra(self.ns_name, interface_name)
def _should_delete_ipv6_lladdr(self, ipv6_lladdr): def _should_delete_ipv6_lladdr(self, ipv6_lladdr):
"""Only the master should have any IP addresses configured. """Only the master should have any IP addresses configured.
Let keepalived manage IPv6 link local addresses, the same way we let Let keepalived manage IPv6 link local addresses, the same way we let

View File

@ -434,7 +434,6 @@ class RouterInfo(object):
def _get_external_gw_ips(self, ex_gw_port): def _get_external_gw_ips(self, ex_gw_port):
gateway_ips = [] gateway_ips = []
enable_ra_on_gw = False
if 'subnets' in ex_gw_port: if 'subnets' in ex_gw_port:
gateway_ips = [subnet['gateway_ip'] gateway_ips = [subnet['gateway_ip']
for subnet in ex_gw_port['subnets'] for subnet in ex_gw_port['subnets']
@ -444,11 +443,7 @@ class RouterInfo(object):
if self.agent_conf.ipv6_gateway: if self.agent_conf.ipv6_gateway:
# ipv6_gateway configured, use address for default route. # ipv6_gateway configured, use address for default route.
gateway_ips.append(self.agent_conf.ipv6_gateway) gateway_ips.append(self.agent_conf.ipv6_gateway)
else: return gateway_ips
# ipv6_gateway is also not configured.
# Use RA for default route.
enable_ra_on_gw = True
return gateway_ips, enable_ra_on_gw
def _external_gateway_added(self, ex_gw_port, interface_name, def _external_gateway_added(self, ex_gw_port, interface_name,
ns_name, preserve_ips): ns_name, preserve_ips):
@ -458,7 +453,11 @@ class RouterInfo(object):
# will be added to the interface. # will be added to the interface.
ip_cidrs = common_utils.fixed_ip_cidrs(ex_gw_port['fixed_ips']) ip_cidrs = common_utils.fixed_ip_cidrs(ex_gw_port['fixed_ips'])
gateway_ips, enable_ra_on_gw = self._get_external_gw_ips(ex_gw_port) gateway_ips = self._get_external_gw_ips(ex_gw_port)
enable_ra_on_gw = False
if self.use_ipv6 and not self.is_v6_gateway_set(gateway_ips):
# There is no IPv6 gw_ip, use RouterAdvt for default route.
enable_ra_on_gw = True
self.driver.init_l3(interface_name, self.driver.init_l3(interface_name,
ip_cidrs, ip_cidrs,
namespace=ns_name, namespace=ns_name,