self.routes = new_routes
def _add_default_gw_virtual_route(self, ex_gw_port, interface_name):
- subnets = ex_gw_port.get('subnets', [])
default_gw_rts = []
- for subnet in subnets:
- gw_ip = subnet['gateway_ip']
- if gw_ip:
+ gateway_ips, enable_ra_on_gw = 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.
default_gw = (n_consts.IPv4_ANY if
default_gw, gw_ip, interface_name))
instance.virtual_routes.gateway_routes = default_gw_rts
+ 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
namespace=ns_name,
prefix=EXTERNAL_DEV_PREFIX)
- def _external_gateway_added(self, ex_gw_port, interface_name,
- ns_name, preserve_ips):
- self._plug_external_gateway(ex_gw_port, interface_name, ns_name)
-
- # Build up the interface and gateway IP addresses that
- # will be added to the interface.
- ip_cidrs = common_utils.fixed_ip_cidrs(ex_gw_port['fixed_ips'])
+ def _get_external_gw_ips(self, ex_gw_port):
gateway_ips = []
enable_ra_on_gw = False
if 'subnets' in ex_gw_port:
# 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,
+ ns_name, preserve_ips):
+ self._plug_external_gateway(ex_gw_port, interface_name, ns_name)
+
+ # Build up the interface and gateway IP addresses that
+ # 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)
self.driver.init_l3(interface_name,
ip_cidrs,
namespace=ns_name,
device.route.add_gateway(gateway_ip)
if enable_ra_on_gw:
- self._configure_ipv6_ra(namespace, device_name)
+ self.configure_ipv6_ra(namespace, device_name)
new_onlink_routes = set(s['cidr'] for s in extra_subnets)
existing_onlink_routes = set(
return (self.DEV_NAME_PREFIX + port.id)[:self.DEV_NAME_LEN]
@staticmethod
- def _configure_ipv6_ra(namespace, dev_name):
+ def configure_ipv6_ra(namespace, dev_name):
"""Configure acceptance of IPv6 route advertisements on an intf."""
# Learn the default router's IP address via RAs
ip_lib.IPWrapper(namespace=namespace).netns.execute(
enable_fip = False
extra_routes = False
- if not v6_ext_gw_with_sub:
- self.agent.conf.set_override('ipv6_gateway',
- 'fe80::f816:3eff:fe2e:1')
return test_l3_agent.prepare_router_data(ip_version=ip_version,
enable_snat=enable_snat,
enable_floating_ip=enable_fip,
self._router_lifecycle(enable_ha=False, dual_stack=True)
def test_legacy_router_lifecycle_with_no_gateway_subnet(self):
+ self.agent.conf.set_override('ipv6_gateway',
+ 'fe80::f816:3eff:fe2e:1')
self._router_lifecycle(enable_ha=False, dual_stack=True,
v6_ext_gw_with_sub=False)
def test_ipv6_ha_router_lifecycle(self):
self._router_lifecycle(enable_ha=True, ip_version=6)
+ def test_ipv6_ha_router_lifecycle_with_no_gw_subnet(self):
+ self.agent.conf.set_override('ipv6_gateway',
+ 'fe80::f816:3eff:fe2e:1')
+ self._router_lifecycle(enable_ha=True, ip_version=6,
+ v6_ext_gw_with_sub=False)
+
+ def test_ipv6_ha_router_lifecycle_with_no_gw_subnet_for_router_advts(self):
+ # Verify that router gw interface is configured to receive Router
+ # Advts from upstream router when no external gateway is configured.
+ self._router_lifecycle(enable_ha=True, dual_stack=True,
+ v6_ext_gw_with_sub=False)
+
def test_keepalived_configuration(self):
router_info = self.generate_router_info(enable_ha=True)
router = self.manage_router(self.agent, router_info)
self._assert_extra_routes(router)
self._assert_metadata_chains(router)
+ # Verify router gateway interface is configured to receive Router Advts
+ # when IPv6 is enabled and no IPv6 gateway is configured.
+ if router.use_ipv6 and not v6_ext_gw_with_sub:
+ if not self.agent.conf.ipv6_gateway:
+ external_port = router.get_ex_gw_port()
+ external_device_name = router.get_external_device_name(
+ external_port['id'])
+ ip_wrapper = ip_lib.IPWrapper(namespace=router.ns_name)
+ ra_state = ip_wrapper.netns.execute(['sysctl', '-b',
+ 'net.ipv6.conf.%s.accept_ra' % external_device_name])
+ self.assertEqual('2', ra_state)
+
if enable_ha:
self._assert_ha_device(router)
self.assertTrue(router.keepalived_manager.get_process().active)
v6_ext_gw_with_sub=True, **kwargs):
fixed_ips = []
subnets = []
+ gateway_mac = kwargs.get('gateway_mac', 'ca:fe:de:ad:be:ee')
for loop_version in (4, 6):
if loop_version == 4 and (ip_version == 4 or dual_stack):
ip_address = kwargs.get('ip_address', '19.4.4.4')
prefixlen = 24
subnet_cidr = kwargs.get('subnet_cidr', '19.4.4.0/24')
gateway_ip = kwargs.get('gateway_ip', '19.4.4.1')
- gateway_mac = kwargs.get('gateway_mac', 'ca:fe:de:ad:be:ee')
elif (loop_version == 6 and (ip_version == 6 or dual_stack) and
v6_ext_gw_with_sub):
ip_address = kwargs.get('ip_address', 'fd00::4')
prefixlen = 64
subnet_cidr = kwargs.get('subnet_cidr', 'fd00::/64')
gateway_ip = kwargs.get('gateway_ip', 'fd00::1')
- gateway_mac = kwargs.get('gateway_mac', 'ca:fe:de:ad:be:ee')
else:
continue
subnet_id = _uuid()
subnets.append({'id': subnet_id,
'cidr': subnet_cidr,
'gateway_ip': gateway_ip})
- if not fixed_ips:
+ if not fixed_ips and v6_ext_gw_with_sub:
raise ValueError("Invalid ip_version: %s" % ip_version)
router_id = _uuid()