diff --git a/neutron/agent/linux/ra.py b/neutron/agent/linux/ra.py index e1060cec8b6..9c252a25e89 100644 --- a/neutron/agent/linux/ra.py +++ b/neutron/agent/linux/ra.py @@ -65,13 +65,21 @@ CONFIG_TEMPLATE = jinja2.Template("""interface {{ interface_name }} RDNSS {% for dns in dns_servers %} {{ dns }} {% endfor %} {}; {% endif %} - {% for prefix in prefixes %} + {% for prefix in auto_config_prefixes %} prefix {{ prefix }} { AdvOnLink on; AdvAutonomous on; }; {% endfor %} + + {% for prefix in stateful_config_prefixes %} + prefix {{ prefix }} + { + AdvOnLink on; + AdvAutonomous off; + }; + {% endfor %} }; """) @@ -103,6 +111,8 @@ class DaemonMonitor(object): auto_config_prefixes = [subnet['cidr'] for subnet in v6_subnets if subnet['ipv6_ra_mode'] == constants.IPV6_SLAAC or subnet['ipv6_ra_mode'] == constants.DHCPV6_STATELESS] + stateful_config_prefixes = [subnet['cidr'] for subnet in v6_subnets + if subnet['ipv6_ra_mode'] == constants.DHCPV6_STATEFUL] interface_name = self._dev_name_helper(p['id']) slaac_subnets = [subnet for subnet in v6_subnets if subnet['ipv6_ra_mode'] == constants.IPV6_SLAAC] @@ -111,7 +121,8 @@ class DaemonMonitor(object): buf.write('%s' % CONFIG_TEMPLATE.render( ra_modes=list(ra_modes), interface_name=interface_name, - prefixes=auto_config_prefixes, + auto_config_prefixes=auto_config_prefixes, + stateful_config_prefixes=stateful_config_prefixes, dns_servers=dns_servers[0:MAX_RDNSS_ENTRIES], constants=constants, min_rtr_adv_interval=self._agent_conf.min_rtr_adv_interval, diff --git a/neutron/tests/unit/agent/l3/test_agent.py b/neutron/tests/unit/agent/l3/test_agent.py index 1ab835c5293..b0737a66641 100644 --- a/neutron/tests/unit/agent/l3/test_agent.py +++ b/neutron/tests/unit/agent/l3/test_agent.py @@ -1332,8 +1332,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): ri = self._process_router_ipv6_interface_added(router) self._assert_ri_process_enabled(ri) # Expect radvd configured without prefix - self.assertNotIn('prefix', - self.utils_replace_file.call_args[0][1].split()) + self.assertNotIn('prefix', self.utils_replace_file.call_args[0][1]) def test_process_router_ipv6_slaac_interface_added(self): router = l3_test_common.prepare_router_data() @@ -1341,8 +1340,19 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): router, ra_mode=l3_constants.IPV6_SLAAC) self._assert_ri_process_enabled(ri) # Expect radvd configured with prefix - self.assertIn('prefix', - self.utils_replace_file.call_args[0][1].split()) + radvd_config_str = self.utils_replace_file.call_args[0][1] + self.assertIn('prefix', radvd_config_str) + self.assertIn('AdvAutonomous on', radvd_config_str) + + def test_process_router_ipv6_dhcpv6_stateful_interface_added(self): + router = l3_test_common.prepare_router_data() + ri = self._process_router_ipv6_interface_added( + router, ra_mode=l3_constants.DHCPV6_STATEFUL) + self._assert_ri_process_enabled(ri) + # Expect radvd configured with prefix + radvd_config_str = self.utils_replace_file.call_args[0][1] + self.assertIn('prefix', radvd_config_str) + self.assertIn('AdvAutonomous off', radvd_config_str) def test_process_router_ipv6_subnets_added(self): router = l3_test_common.prepare_router_data() @@ -1354,11 +1364,13 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): {'ra_mode': l3_constants.DHCPV6_STATEFUL, 'address_mode': l3_constants.DHCPV6_STATEFUL}]) self._assert_ri_process_enabled(ri) - radvd_config = self.utils_replace_file.call_args[0][1].split() + radvd_config_str = self.utils_replace_file.call_args[0][1] # Assert we have a prefix from IPV6_SLAAC and a prefix from # DHCPV6_STATELESS on one interface - self.assertEqual(2, radvd_config.count("prefix")) - self.assertEqual(1, radvd_config.count("interface")) + self.assertEqual(3, radvd_config_str.count("prefix")) + self.assertEqual(1, radvd_config_str.count("interface")) + self.assertEqual(2, radvd_config_str.count("AdvAutonomous on")) + self.assertEqual(1, radvd_config_str.count("AdvAutonomous off")) def test_process_router_ipv6_subnets_added_to_existing_port(self): agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)