From: Ihar Hrachyshka Date: Thu, 27 Nov 2014 14:43:48 +0000 (+0100) Subject: ipv6: set OtherConfig flag for DHCPv6 stateless subnets X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=4f3a9135acb561172f7af45bc82739d6dc49f23c;p=openstack-build%2Fneutron-build.git ipv6: set OtherConfig flag for DHCPv6 stateless subnets In case of DHCPv6 stateless subnets, we should inform DHCP clients about other configuration values available from DHCP server. This is done by setting O (other) flag in RAs, which is controlled by AdvOtherConfigFlag setting in radvd case. Since radvd configuration file becomes quite complex, migrated its generation to Jinja2. Added a basic unit test that checks that flag is set for stateless mode and not SLAAC. For stateful, it doesn't really matter whether other flag is set, so no need to expect any value of it. No more unit tests seem to be needed: conditional prefix generation is already covered in test_l3_agent, and other statements are common for all ipv6_ra_modes. Change-Id: I1ddad3e1f5efce2b6da4ec00b9294e08fe1e85dd Closes-Bug: #1397022 --- diff --git a/neutron/agent/linux/ra.py b/neutron/agent/linux/ra.py index 6bdfea57c..af721cca1 100644 --- a/neutron/agent/linux/ra.py +++ b/neutron/agent/linux/ra.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import jinja2 import netaddr from oslo.config import cfg import six @@ -33,31 +34,25 @@ OPTS = [ cfg.CONF.register_opts(OPTS) -prefix_fmt = """interface %s +CONFIG_TEMPLATE = jinja2.Template("""interface {{ interface_name }} { AdvSendAdvert on; MinRtrAdvInterval 3; MaxRtrAdvInterval 10; - prefix %s + + {% if ra_mode == constants.DHCPV6_STATELESS %} + AdvOtherConfigFlag on; + {% endif %} + + {% if ra_mode in (constants.IPV6_SLAAC, constants.DHCPV6_STATELESS) %} + prefix {{ prefix }} { AdvOnLink on; AdvAutonomous on; }; + {% endif %} }; -""" - -default_fmt = """interface %s -{ - AdvSendAdvert on; - MinRtrAdvInterval 3; - MaxRtrAdvInterval 10; -}; -""" - - -def _is_slaac(ra_mode): - return (ra_mode == constants.IPV6_SLAAC or - ra_mode == constants.DHCPV6_STATELESS) +""") def _generate_radvd_conf(router_id, router_ports, dev_name_helper): @@ -67,14 +62,15 @@ def _generate_radvd_conf(router_id, router_ports, dev_name_helper): True) buf = six.StringIO() for p in router_ports: - if netaddr.IPNetwork(p['subnet']['cidr']).version == 6: + prefix = p['subnet']['cidr'] + if netaddr.IPNetwork(prefix).version == 6: interface_name = dev_name_helper(p['id']) - if _is_slaac(p['subnet']['ipv6_ra_mode']): - conf_str = prefix_fmt % (interface_name, - p['subnet']['cidr']) - else: - conf_str = default_fmt % interface_name - buf.write('%s' % conf_str) + ra_mode = p['subnet']['ipv6_ra_mode'] + buf.write('%s' % CONFIG_TEMPLATE.render( + ra_mode=ra_mode, + interface_name=interface_name, + prefix=prefix, + constants=constants)) utils.replace_file(radvd_conf, buf.getvalue()) return radvd_conf diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py index aac84b28c..28a5568fe 100644 --- a/neutron/tests/unit/test_l3_agent.py +++ b/neutron/tests/unit/test_l3_agent.py @@ -2195,6 +2195,24 @@ vrrp_instance VR_1 { self.assertIn(_join('-p', pidfile), cmd) self.assertIn(_join('-m', 'syslog'), cmd) + def test_generate_radvd_conf_other_flag(self): + # we don't check other flag for stateful since it's redundant + # for this mode and can be ignored by clients, as per RFC4861 + expected = {l3_constants.IPV6_SLAAC: False, + l3_constants.DHCPV6_STATELESS: True} + + for ra_mode, flag_set in expected.iteritems(): + router = prepare_router_data() + ri = self._process_router_ipv6_interface_added(router, + ra_mode=ra_mode) + + ra._generate_radvd_conf(ri.router['id'], + router[l3_constants.INTERFACE_KEY], + mock.Mock()) + asserter = self.assertIn if flag_set else self.assertNotIn + asserter('AdvOtherConfigFlag on;', + self.utils_replace_file.call_args[0][1]) + class TestL3AgentEventHandler(base.BaseTestCase):