← Back to team overview

netplan-developers team mailing list archive

[Merge] ~raharper/netplan:fix/accept-ra-no-default into netplan:master

 

Ryan Harper has proposed merging ~raharper/netplan:fix/accept-ra-no-default into netplan:master.

Commit message:
accept-ra: do not enable by default, default to unset
    
Do not always emit an IPv6AcceptRA value into network configurations.
Systemd-networkd defaults to kernel value as long as the value stays
unset in the configuration.  When IPv6AcceptRA is enabled in systemd
this makes networkd wait 10 seconds for potential RAs to arrive.  This
delays boot by 10 seconds always whether or not the network has an
IPV6 Router running.  Leaving things unsets keeps existing behavior
of Ubuntu systems where RAs are accepted and processed at the time
they are received and boot is not delayed by waiting for an RA to arrive.
    
If users want to forcibly enable or disable, they may do so by including
a value for accept-ra in their yaml configuraion.
    
LP: #1732002


Requested reviews:
  Mathieu Trudel-Lapierre (cyphermox)
Related bugs:
  Bug #1732002 in nplan (Ubuntu): "cloud images in lxc get ipv6 address"
  https://bugs.launchpad.net/ubuntu/+source/nplan/+bug/1732002

For more details, see:
https://code.launchpad.net/~raharper/netplan/+git/netplan/+merge/342976
-- 
Your team Developers of netplan is subscribed to branch netplan:master.
diff --git a/doc/netplan.md b/doc/netplan.md
index 146ae01..978eb6b 100644
--- a/doc/netplan.md
+++ b/doc/netplan.md
@@ -168,7 +168,8 @@ Virtual devices
 ``accept-ra`` (bool)
 
 :   Accept Router Advertisement that would have the kernel configure IPv6 by itself.
-    On by default.
+    When enabled, accept Router Advertisements. When disabled, do not respond to
+    Router Advertisements.  If unset use the host kernel default setting.
 
 ``addresses`` (sequence of scalars)
 
diff --git a/src/networkd.c b/src/networkd.c
index 7b9d2be..c092c22 100644
--- a/src/networkd.c
+++ b/src/networkd.c
@@ -286,7 +286,9 @@ write_network_file(net_definition* def, const char* rootdir, const char* path)
     if (def->ip6_addresses)
         for (unsigned i = 0; i < def->ip6_addresses->len; ++i)
             g_string_append_printf(s, "Address=%s\n", g_array_index(def->ip6_addresses, char*, i));
-    if (!def->accept_ra)
+    if (def->accept_ra == ACCEPT_RA_ENABLED)
+        g_string_append_printf(s, "IPv6AcceptRA=yes\n");
+    else if (def->accept_ra == ACCEPT_RA_DISABLED)
         g_string_append_printf(s, "IPv6AcceptRA=no\n");
     if (def->gateway4)
         g_string_append_printf(s, "Gateway=%s\n", def->gateway4);
@@ -305,8 +307,12 @@ write_network_file(net_definition* def, const char* rootdir, const char* path)
         g_string_append(s, "\n");
     }
     if (def->bridge) {
-        g_string_append_printf(s, "Bridge=%s\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n", def->bridge);
+        g_string_append_printf(s, "Bridge=%s\nLinkLocalAddressing=no\n", def->bridge);
 
+        if (def->accept_ra == ACCEPT_RA_ENABLED)
+            g_string_append_printf(s, "IPv6AcceptRA=yes\n");
+        else if (def->accept_ra == ACCEPT_RA_DISABLED)
+            g_string_append_printf(s, "IPv6AcceptRA=no\n");
         if (def->bridge_params.path_cost || def->bridge_params.port_priority)
             g_string_append_printf(s, "\n[Bridge]\n");
         if (def->bridge_params.path_cost)
@@ -315,8 +321,12 @@ write_network_file(net_definition* def, const char* rootdir, const char* path)
             g_string_append_printf(s, "Priority=%u\n", def->bridge_params.port_priority);
     }
     if (def->bond) {
-        g_string_append_printf(s, "Bond=%s\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n", def->bond);
+        g_string_append_printf(s, "Bond=%s\nLinkLocalAddressing=no\n", def->bond);
 
+        if (def->accept_ra == ACCEPT_RA_ENABLED)
+            g_string_append_printf(s, "IPv6AcceptRA=yes\n");
+        else if (def->accept_ra == ACCEPT_RA_DISABLED)
+            g_string_append_printf(s, "IPv6AcceptRA=no\n");
         if (def->bond_params.primary_slave)
             g_string_append_printf(s, "PrimarySlave=true\n");
     }
diff --git a/src/parse.c b/src/parse.c
index 7627462..c0a16f3 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -462,6 +462,25 @@ handle_netdef_renderer(yaml_document_t* doc, yaml_node_t* node, const void* _, G
 }
 
 static gboolean
+handle_accept_ra(yaml_document_t* doc, yaml_node_t* node, const void* data, GError** error)
+{
+    if (g_ascii_strcasecmp(scalar(node), "true") == 0 ||
+        g_ascii_strcasecmp(scalar(node), "on") == 0 ||
+        g_ascii_strcasecmp(scalar(node), "yes") == 0 ||
+        g_ascii_strcasecmp(scalar(node), "y") == 0)
+        cur_netdef->accept_ra = ACCEPT_RA_ENABLED;
+    else if (g_ascii_strcasecmp(scalar(node), "false") == 0 ||
+        g_ascii_strcasecmp(scalar(node), "off") == 0 ||
+        g_ascii_strcasecmp(scalar(node), "no") == 0 ||
+        g_ascii_strcasecmp(scalar(node), "n") == 0)
+        cur_netdef->accept_ra = ACCEPT_RA_DISABLED;
+    else
+        return yaml_error(node, error, "invalid boolean value %s", scalar(node));
+
+    return TRUE;
+}
+
+static gboolean
 handle_match(yaml_document_t* doc, yaml_node_t* node, const void* _, GError** error)
 {
     cur_netdef->has_match = TRUE;
@@ -1219,7 +1238,7 @@ const mapping_entry_handler ethernet_def_handlers[] = {
     {"dhcp4", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp4)},
     {"dhcp6", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp6)},
     {"dhcp-identifier", YAML_SCALAR_NODE, handle_dhcp_identifier},
-    {"accept-ra", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(accept_ra)},
+    {"accept-ra", YAML_SCALAR_NODE, handle_accept_ra},
     {"gateway4", YAML_SCALAR_NODE, handle_gateway4},
     {"gateway6", YAML_SCALAR_NODE, handle_gateway6},
     {"macaddress", YAML_SCALAR_NODE, handle_netdef_mac, NULL, netdef_offset(set_mac)},
@@ -1241,7 +1260,7 @@ const mapping_entry_handler wifi_def_handlers[] = {
     {"dhcp4", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp4)},
     {"dhcp6", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp6)},
     {"dhcp-identifier", YAML_SCALAR_NODE, handle_dhcp_identifier},
-    {"accept-ra", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(accept_ra)},
+    {"accept-ra", YAML_SCALAR_NODE, handle_accept_ra},
     {"gateway4", YAML_SCALAR_NODE, handle_gateway4},
     {"gateway6", YAML_SCALAR_NODE, handle_gateway6},
     {"macaddress", YAML_SCALAR_NODE, handle_netdef_mac, NULL, netdef_offset(set_mac)},
@@ -1262,7 +1281,7 @@ const mapping_entry_handler bridge_def_handlers[] = {
     {"dhcp4", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp4)},
     {"dhcp6", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp6)},
     {"dhcp-identifier", YAML_SCALAR_NODE, handle_dhcp_identifier},
-    {"accept-ra", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(accept_ra)},
+    {"accept-ra", YAML_SCALAR_NODE, handle_accept_ra},
     {"gateway4", YAML_SCALAR_NODE, handle_gateway4},
     {"gateway6", YAML_SCALAR_NODE, handle_gateway6},
     {"interfaces", YAML_SEQUENCE_NODE, handle_bridge_interfaces, NULL, NULL},
@@ -1282,7 +1301,7 @@ const mapping_entry_handler bond_def_handlers[] = {
     {"dhcp4", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp4)},
     {"dhcp6", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp6)},
     {"dhcp-identifier", YAML_SCALAR_NODE, handle_dhcp_identifier},
-    {"accept-ra", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(accept_ra)},
+    {"accept-ra", YAML_SCALAR_NODE, handle_accept_ra},
     {"gateway4", YAML_SCALAR_NODE, handle_gateway4},
     {"gateway6", YAML_SCALAR_NODE, handle_gateway6},
     {"interfaces", YAML_SEQUENCE_NODE, handle_bond_interfaces, NULL, NULL},
@@ -1302,7 +1321,7 @@ const mapping_entry_handler vlan_def_handlers[] = {
     {"dhcp4", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp4)},
     {"dhcp6", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(dhcp6)},
     {"dhcp-identifier", YAML_SCALAR_NODE, handle_dhcp_identifier},
-    {"accept-ra", YAML_SCALAR_NODE, handle_netdef_bool, NULL, netdef_offset(accept_ra)},
+    {"accept-ra", YAML_SCALAR_NODE, handle_accept_ra},
     {"gateway4", YAML_SCALAR_NODE, handle_gateway4},
     {"gateway6", YAML_SCALAR_NODE, handle_gateway6},
     {"id", YAML_SCALAR_NODE, handle_netdef_guint, NULL, netdef_offset(vlan_id)},
@@ -1414,7 +1433,6 @@ handle_network_type(yaml_document_t* doc, yaml_node_t* node, const void* data, G
             cur_netdef->backend = backend_cur_type ?: BACKEND_NONE;
             cur_netdef->id = g_strdup(scalar(key));
             cur_netdef->vlan_id = G_MAXUINT; /* 0 is a valid ID */
-            cur_netdef->accept_ra = TRUE; /* By default, accept RAs */
             cur_netdef->dhcp_identifier = g_strdup("duid"); /* keep networkd's default */
             g_hash_table_insert(netdefs, cur_netdef->id, cur_netdef);
         }
diff --git a/src/parse.h b/src/parse.h
index 510f09f..8cf5e12 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -49,6 +49,12 @@ static const char* const netdef_backend_to_name[_BACKEND_MAX] = {
         [BACKEND_NM] = "NetworkManager",
 };
 
+typedef enum {
+    ACCEPT_RA_KERNEL,
+    ACCEPT_RA_ENABLED,
+    ACCEPT_RA_DISABLED,
+} ra_mode;
+
 typedef struct missing_node {
     char* netdef_id;
     const yaml_node_t* node;
@@ -71,7 +77,7 @@ typedef struct net_definition {
     gboolean dhcp4;
     gboolean dhcp6;
     char* dhcp_identifier;
-    gboolean accept_ra;
+    ra_mode accept_ra;
     GArray* ip4_addresses;
     GArray* ip6_addresses;
     char* gateway4;
diff --git a/tests/generate.py b/tests/generate.py
index b168c47..29cd2f6 100755
--- a/tests/generate.py
+++ b/tests/generate.py
@@ -345,7 +345,7 @@ unmanaged-devices+=interface-name:eth0,''')
             'bond0.netdev': '[NetDev]\nName=bond0\nMTUBytes=9000\nKind=bond\n',
             'bond0.network': '[Match]\nName=bond0\n\n[Network]\nVLAN=bond0.108\n',
             'eth1.link': '[Match]\nOriginalName=eth1\n\n[Link]\nWakeOnLan=off\nMTUBytes=1280\n',
-            'eth1.network': '[Match]\nName=eth1\n\n[Network]\nBond=bond0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'
+            'eth1.network': '[Match]\nName=eth1\n\n[Network]\nBond=bond0\nLinkLocalAddressing=no\n'
         })
 
     def test_eth_match_by_driver_rename(self):
@@ -592,6 +592,42 @@ UseMTU=true
 RouteMetric=100
 '''})
 
+    def test_eth_dhcp6_accept_ra(self):
+        self.generate('''network:
+  version: 2
+  ethernets:
+    eth0:
+      dhcp6: true
+      accept-ra: yes''')
+        self.assert_networkd({'eth0.network': '''[Match]
+Name=eth0
+
+[Network]
+DHCP=ipv6
+IPv6AcceptRA=yes
+
+[DHCP]
+UseMTU=true
+RouteMetric=100
+'''})
+
+    def test_eth_dhcp6_accept_ra_unset(self):
+        self.generate('''network:
+  version: 2
+  ethernets:
+    eth0:
+      dhcp6: true''')
+        self.assert_networkd({'eth0.network': '''[Match]
+Name=eth0
+
+[Network]
+DHCP=ipv6
+
+[DHCP]
+UseMTU=true
+RouteMetric=100
+'''})
+
     def test_eth_dhcp4_and_6(self):
         self.generate('''network:
   version: 2
@@ -1222,9 +1258,9 @@ unmanaged-devices+=interface-name:br0,''')
         self.assert_networkd({'br0.netdev': '[NetDev]\nName=br0\nKind=bridge\n',
                               'br0.network': ND_DHCP4 % 'br0',
                               'eno1.network': '[Match]\nName=eno1\n\n'
-                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\n',
                               'switchports.network': '[Match]\nDriver=yayroute\n\n'
-                                                     '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                                     '[Network]\nBridge=br0\nLinkLocalAddressing=no\n'})
 
     def test_eth_bridge_nm_blacklist(self):
         self.generate('''network:
@@ -1258,9 +1294,9 @@ unmanaged-devices+=interface-name:eth42,interface-name:eth43,interface-name:mybr
         self.assert_networkd({'br0.netdev': '[NetDev]\nName=br0\nKind=bridge\n',
                               'br0.network': ND_DHCP4 % 'br0',
                               'eno1.network': '[Match]\nName=eno1\n\n'
-                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\n',
                               'switchports.network': '[Match]\nDriver=yayroute\n\n'
-                                                     '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                                     '[Network]\nBridge=br0\nLinkLocalAddressing=no\n'})
 
     def test_bridge_params(self):
         self.generate('''network:
@@ -1295,10 +1331,10 @@ unmanaged-devices+=interface-name:eth42,interface-name:eth43,interface-name:mybr
                                             'STP=true\n',
                               'br0.network': ND_DHCP4 % 'br0',
                               'eno1.network': '[Match]\nName=eno1\n\n'
-                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n\n'
+                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\n\n'
                                               '[Bridge]\nCost=70\nPriority=14\n',
                               'switchports.network': '[Match]\nDriver=yayroute\n\n'
-                                                     '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                                     '[Network]\nBridge=br0\nLinkLocalAddressing=no\n'})
 
     def test_bond_empty(self):
         self.generate('''network:
@@ -1330,9 +1366,9 @@ unmanaged-devices+=interface-name:bn0,''')
         self.assert_networkd({'bn0.netdev': '[NetDev]\nName=bn0\nKind=bond\n',
                               'bn0.network': ND_DHCP4 % 'bn0',
                               'eno1.network': '[Match]\nName=eno1\n\n'
-                                              '[Network]\nBond=bn0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                              '[Network]\nBond=bn0\nLinkLocalAddressing=no\n',
                               'switchports.network': '[Match]\nDriver=yayroute\n\n'
-                                                     '[Network]\nBond=bn0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                                     '[Network]\nBond=bn0\nLinkLocalAddressing=no\n'})
 
     def test_bond_empty_parameters(self):
         self.generate('''network:
@@ -1351,9 +1387,9 @@ unmanaged-devices+=interface-name:bn0,''')
         self.assert_networkd({'bn0.netdev': '[NetDev]\nName=bn0\nKind=bond\n',
                               'bn0.network': ND_DHCP4 % 'bn0',
                               'eno1.network': '[Match]\nName=eno1\n\n'
-                                              '[Network]\nBond=bn0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                              '[Network]\nBond=bn0\nLinkLocalAddressing=no\n',
                               'switchports.network': '[Match]\nDriver=yayroute\n\n'
-                                                     '[Network]\nBond=bn0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                                     '[Network]\nBond=bn0\nLinkLocalAddressing=no\n'})
 
     def test_bond_with_parameters(self):
         self.generate('''network:
@@ -1413,9 +1449,9 @@ unmanaged-devices+=interface-name:bn0,''')
                                             'LearnPacketIntervalSec=10\n',
                               'bn0.network': ND_DHCP4 % 'bn0',
                               'eno1.network': '[Match]\nName=eno1\n\n'
-                                              '[Network]\nBond=bn0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                              '[Network]\nBond=bn0\nLinkLocalAddressing=no\n',
                               'switchports.network': '[Match]\nDriver=yayroute\n\n'
-                                                     '[Network]\nBond=bn0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                                     '[Network]\nBond=bn0\nLinkLocalAddressing=no\n'})
 
     def test_bond_primary_slave(self):
         self.generate('''network:
@@ -1438,9 +1474,9 @@ unmanaged-devices+=interface-name:bn0,''')
                                             'Mode=active-backup\n',
                               'bn0.network': ND_DHCP4 % 'bn0',
                               'eno1.network': '[Match]\nName=eno1\n\n'
-                                              '[Network]\nBond=bn0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\nPrimarySlave=true\n',
+                                              '[Network]\nBond=bn0\nLinkLocalAddressing=no\nPrimarySlave=true\n',
                               'switchports.network': '[Match]\nDriver=yayroute\n\n'
-                                                     '[Network]\nBond=bn0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                                     '[Network]\nBond=bn0\nLinkLocalAddressing=no\n'})
 
     def test_gateway(self):
         self.generate('''network:
@@ -4181,15 +4217,15 @@ class TestForwardDeclaration(TestBase):
                               'br0.network': ND_DHCP4 % 'br0',
                               'bond0.netdev': '[NetDev]\nName=bond0\nKind=bond\n',
                               'bond0.network': '[Match]\nName=bond0\n\n'
-                                               '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                               '[Network]\nBridge=br0\nLinkLocalAddressing=no\n',
                               'eth0.link': '[Match]\nMACAddress=00:01:02:03:04:05\n\n'
                                            '[Link]\nName=eth0\nWakeOnLan=off\n',
                               'eth0.network': '[Match]\nMACAddress=00:01:02:03:04:05\nName=eth0\n\n'
-                                              '[Network]\nBond=bond0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                              '[Network]\nBond=bond0\nLinkLocalAddressing=no\n',
                               'eth1.link': '[Match]\nMACAddress=02:01:02:03:04:05\n\n'
                                            '[Link]\nName=eth1\nWakeOnLan=off\n',
                               'eth1.network': '[Match]\nMACAddress=02:01:02:03:04:05\nName=eth1\n\n'
-                                              '[Network]\nBond=bond0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                              '[Network]\nBond=bond0\nLinkLocalAddressing=no\n'})
 
     def test_fwdecl_feature_blend(self):
         self.generate('''network:
@@ -4236,22 +4272,22 @@ class TestForwardDeclaration(TestBase):
                                              '[Network]\nVLAN=vlan1\n',
                               'bond0.netdev': '[NetDev]\nName=bond0\nKind=bond\n',
                               'bond0.network': '[Match]\nName=bond0\n\n'
-                                               '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n\n'
+                                               '[Network]\nBridge=br0\nLinkLocalAddressing=no\n\n'
                                                '[Bridge]\nCost=8888\n',
                               'eth2.network': '[Match]\nName=eth2\n\n'
-                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n\n'
+                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\n\n'
                                               '[Bridge]\nCost=1000\n',
                               'br1.netdev': '[NetDev]\nName=br1\nKind=bridge\n',
                               'br1.network': '[Match]\nName=br1\n\n'
-                                             '[Network]\nBond=bond0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                             '[Network]\nBond=bond0\nLinkLocalAddressing=no\n',
                               'eth0.link': '[Match]\nMACAddress=00:01:02:03:04:05\n\n'
                                            '[Link]\nName=eth0\nWakeOnLan=off\n',
                               'eth0.network': '[Match]\nMACAddress=00:01:02:03:04:05\nName=eth0\n\n'
-                                              '[Network]\nBond=bond0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                              '[Network]\nBond=bond0\nLinkLocalAddressing=no\n',
                               'eth1.link': '[Match]\nMACAddress=02:01:02:03:04:05\n\n'
                                            '[Link]\nName=eth1\nWakeOnLan=off\n',
                               'eth1.network': '[Match]\nMACAddress=02:01:02:03:04:05\nName=eth1\n\n'
-                                              '[Network]\nBridge=br1\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                              '[Network]\nBridge=br1\nLinkLocalAddressing=no\n'})
 
 
 class TestMerging(TestBase):
@@ -4349,9 +4385,9 @@ unmanaged-devices+=interface-name:engreen,''')
         self.assert_networkd({'br0.netdev': '[NetDev]\nName=br0\nKind=bridge\n',
                               'br0.network': ND_DHCP4 % 'br0',
                               'eno1.network': '[Match]\nName=eno1\n\n'
-                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n',
+                                              '[Network]\nBridge=br0\nLinkLocalAddressing=no\n',
                               'switchports.network': '[Match]\nDriver=yayroute\n\n'
-                                                     '[Network]\nBridge=br0\nLinkLocalAddressing=no\nIPv6AcceptRA=no\n'})
+                                                     '[Network]\nBridge=br0\nLinkLocalAddressing=no\n'})
 
     def test_def_in_run(self):
         rundir = os.path.join(self.workdir.name, 'run', 'netplan')

Follow ups