From 4d15b6fe1259f2e9b17d76bc48050c7f54aad02e Mon Sep 17 00:00:00 2001 From: sridhargaddam Date: Thu, 10 Sep 2015 16:14:13 +0000 Subject: [PATCH] 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 c89a4fdd88b0f8832b32af55f64e0d3a35c84388) Change-Id: Ibf8e0ff64cda00314f8fa649ef5019c95c2d6004 --- neutron/agent/l3/ha.py | 13 +++++++++++++ neutron/agent/l3/ha_router.py | 5 +---- neutron/agent/l3/router_info.py | 13 ++++++------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/neutron/agent/l3/ha.py b/neutron/agent/l3/ha.py index 9a55d25c256..aa77b729066 100644 --- a/neutron/agent/l3/ha.py +++ b/neutron/agent/l3/ha.py @@ -122,10 +122,23 @@ class AgentMixin(object): 'possibly deleted concurrently.'), router_id) return + self._configure_ipv6_ra_on_ext_gw_port_if_necessary(ri, state) self._update_metadata_proxy(ri, router_id, state) self._update_radvd_daemon(ri, 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): if state == 'master': LOG.debug('Spawning metadata proxy for router %s', router_id) diff --git a/neutron/agent/l3/ha_router.py b/neutron/agent/l3/ha_router.py index fd15e19b37e..92493578d84 100644 --- a/neutron/agent/l3/ha_router.py +++ b/neutron/agent/l3/ha_router.py @@ -192,7 +192,7 @@ class HaRouter(router.RouterInfo): self.routes = new_routes 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: # TODO(Carl) This is repeated everywhere. A method would # be nice. @@ -207,9 +207,6 @@ class HaRouter(router.RouterInfo): keepalived.KeepalivedVirtualRoute( 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): """Only the master should have any IP addresses configured. Let keepalived manage IPv6 link local addresses, the same way we let diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py index 66d45dd4272..8f2b930bad3 100644 --- a/neutron/agent/l3/router_info.py +++ b/neutron/agent/l3/router_info.py @@ -434,7 +434,6 @@ class RouterInfo(object): def _get_external_gw_ips(self, ex_gw_port): gateway_ips = [] - enable_ra_on_gw = False if 'subnets' in ex_gw_port: gateway_ips = [subnet['gateway_ip'] for subnet in ex_gw_port['subnets'] @@ -444,11 +443,7 @@ class RouterInfo(object): if self.agent_conf.ipv6_gateway: # ipv6_gateway configured, use address for default route. gateway_ips.append(self.agent_conf.ipv6_gateway) - else: - # ipv6_gateway is also not configured. - # Use RA for default route. - enable_ra_on_gw = True - return gateway_ips, enable_ra_on_gw + return gateway_ips def _external_gateway_added(self, ex_gw_port, interface_name, ns_name, preserve_ips): @@ -458,7 +453,11 @@ class RouterInfo(object): # will be added to the interface. 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, ip_cidrs, namespace=ns_name,