]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
ipv6: set OtherConfig flag for DHCPv6 stateless subnets
authorIhar Hrachyshka <ihrachys@redhat.com>
Thu, 27 Nov 2014 14:43:48 +0000 (15:43 +0100)
committerIhar Hrachyshka <ihrachys@redhat.com>
Mon, 22 Dec 2014 10:37:38 +0000 (11:37 +0100)
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

neutron/agent/linux/ra.py
neutron/tests/unit/test_l3_agent.py

index 6bdfea57c5179f23a026f4eca344aae27abd8420..af721cca1b4d64fc80b60d444b93567d941821a8 100644 (file)
@@ -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
index aac84b28ca19d9b1a57475866de57fdc83db2e32..28a5568fe115fc64f74d73a9606995ca7e5114d0 100644 (file)
@@ -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):