<varlistentry>
<term><varname>IPv6AcceptRA=</varname></term>
<listitem>
- <para>Takes a boolean. Controls IPv6 Router Advertisement (RA) reception support for the
- interface. If true, RAs are accepted; if false, RAs are ignored. When RAs are accepted, they
- may trigger the start of the DHCPv6 client if the relevant flags are set in the RA data, or
- if no routers are found on the link. The default is to disable RA reception for bridge
- devices or when IP forwarding is enabled, and to enable it otherwise. Cannot be enabled on
- devices aggregated in a bond device or when link-local addressing is disabled.</para>
+ <para>Takes a boolean. Controls IPv6 Router Advertisement (RA) reception support for the interface.
+ If true, RAs are accepted; if false, RAs are ignored. When RAs are accepted, they may trigger the
+ start of the DHCPv6 client if the relevant flags are set in the RA data, or if no routers are found
+ on the link. Defaults to false for bridge devices, when IP forwarding is enabled,
+ <varname>IPv6SendRA=</varname> or <varname>KeepMaster=</varname> is enabled. Otherwise, enabled by
+ default. Cannot be enabled on devices aggregated in a bond device or when link-local addressing is
+ disabled.</para>
<para>Further settings for the IPv6 RA support may be configured in the [IPv6AcceptRA]
section, see below.</para>
r = sd_ndisc_router_solicit_get_sender_address(rs, &src);
if (r < 0 && r != -ENODATA) /* null address is allowed */
return log_radv_errno(ra, r, "Failed to get sender address of RS, ignoring: %m");
+ if (r >= 0 && in6_addr_equal(&src, &ra->ipv6ll))
+ /* This should be definitely caused by a misconfiguration. If we send RA to ourself, the
+ * kernel complains about that. Let's ignore the packet. */
+ return log_radv_errno(ra, SYNTHETIC_ERRNO(EADDRINUSE), "Received RS from the same interface, ignoring.");
r = radv_send_router(ra, &src);
if (r < 0)
return 0;
}
+int sd_radv_set_link_local_address(sd_radv *ra, const struct in6_addr *addr) {
+ assert_return(ra, -EINVAL);
+ assert_return(!addr || in6_addr_is_link_local(addr), -EINVAL);
+
+ if (addr)
+ ra->ipv6ll = *addr;
+ else
+ zero(ra->ipv6ll);
+
+ return 0;
+}
+
int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr) {
assert_return(ra, -EINVAL);
print(output)
self.assertRegex(output, r'.*elements = { [^}]*' + contents + r'[^}]* }.*')
+ def check_networkd_log(self, contents, since=None, trial=20):
+ for _ in range(trial):
+ if contents in read_networkd_log(since=since):
+ break
+ time.sleep(0.5)
+ else:
+ self.fail(f'"{contents}" not found in journal.')
+
class NetworkctlTests(unittest.TestCase, Utilities):
def setUp(self):
self.assertIn('Network File: /run/systemd/network/11-test-unit-file.network', output)
self.assertIn('/run/systemd/network/11-test-unit-file.network.d/dropin.conf', output)
- output = read_networkd_log()
- self.assertIn('test1: Configuring with /run/systemd/network/11-test-unit-file.network (dropins: /run/systemd/network/11-test-unit-file.network.d/dropin.conf).', output)
+ self.check_networkd_log('test1: Configuring with /run/systemd/network/11-test-unit-file.network (dropins: /run/systemd/network/11-test-unit-file.network.d/dropin.conf).')
# This test may be run on the system that has older udevd than 70f32a260b5ebb68c19ecadf5d69b3844896ba55 (v249).
# In that case, the udev DB for the loopback network interface may already have ID_NET_LINK_FILE property.
self.wait_online('bond99:off')
self.wait_operstate('vlan99', operstate='off', setup_state='configuring', setup_timeout=10)
- # The commit b05e52000b4eee764b383cc3031da0a3739e996e adds ", ignoring". To make it easily confirmed
- # that the issue is fixed by the commit, let's allow to match both string.
- log_re = re.compile('vlan99: Could not bring up interface(, ignoring|): Network is down$', re.MULTILINE)
- for i in range(20):
- if i > 0:
- time.sleep(0.5)
- if log_re.search(read_networkd_log()):
- break
- else:
- self.fail()
+ self.check_networkd_log('vlan99: Could not bring up interface, ignoring: Network is down')
copy_network_unit('11-dummy.netdev', '12-dummy.netdev', '21-dummy-bond-slave.network')
networkctl_reload()
self.assertIn('2002:da8:1:1:1a:2b:3c:4d via fe80::1 proto redirect', output)
self.assertIn('2002:da8:1:2:1a:2b:3c:4d via fe80::2 proto redirect', output)
+ # Check if sd-radv refuses RS from the same interface.
+ # See https://github.com/systemd/systemd/pull/32267#discussion_r1566721306
+ since = datetime.datetime.now()
+ check_output(f'{test_ndisc_send} --interface veth-peer --type rs --dest {veth_peer_ipv6ll}')
+ self.check_networkd_log('veth-peer: RADV: Received RS from the same interface, ignoring.', since=since)
+
def check_ndisc_mtu(self, mtu):
for _ in range(20):
output = read_ipv6_sysctl_attr('veth99', 'mtu')
start_networkd()
self.wait_online('veth-peer:degraded')
- for _ in range(20):
- output = read_networkd_log()
- if 'veth99: NDISC: Started IPv6 Router Solicitation client' in output:
- break
- time.sleep(0.5)
- else:
- self.fail('sd-ndisc does not started on veth99.')
+ self.check_networkd_log('veth99: NDISC: Started IPv6 Router Solicitation client')
check_output(f'{test_ndisc_send} --interface veth-peer --type ra --lifetime 1hour --mtu 1400')
self.check_ndisc_mtu(1400)
self.wait_online('bridge-relay:routable', 'client-peer:enslaved')
# For issue #30763.
- expect = 'bridge-relay: DHCPv4 server: STARTED'
- for _ in range(20):
- if expect in read_networkd_log():
- break
- time.sleep(0.5)
- else:
- self.fail()
+ self.check_networkd_log('bridge-relay: DHCPv4 server: STARTED')
class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
since = datetime.datetime.now()
start_dnsmasq()
- expect = 'veth99: DHCPv4 server IP address 192.168.5.1 not found in allow-list, ignoring offer.'
- for _ in range(20):
- if expect in read_networkd_log(since=since):
- break
- time.sleep(0.5)
- else:
- self.fail()
+ self.check_networkd_log('veth99: DHCPv4 server IP address 192.168.5.1 not found in allow-list, ignoring offer.', since=since)
copy_network_unit('25-dhcp-client-allow-list.network.d/00-allow-list.conf')
since = datetime.datetime.now()
networkctl_reload()
- expect = 'veth99: DHCPv4 server IP address 192.168.5.1 not found in allow-list, ignoring offer.'
- for _ in range(20):
- if expect in read_networkd_log(since=since):
- break
- time.sleep(0.5)
- else:
- self.fail()
+ self.check_networkd_log('veth99: DHCPv4 server IP address 192.168.5.1 not found in allow-list, ignoring offer.', since=since)
copy_network_unit('25-dhcp-client-allow-list.network.d/10-deny-list.conf')
since = datetime.datetime.now()
networkctl_reload()
- expect = 'veth99: DHCPv4 server IP address 192.168.5.1 found in deny-list, ignoring offer.'
- for _ in range(20):
- if expect in read_networkd_log(since=since):
- break
- time.sleep(0.5)
- else:
- self.fail()
+ self.check_networkd_log('veth99: DHCPv4 server IP address 192.168.5.1 found in deny-list, ignoring offer.', since=since)
@unittest.skipUnless("--dhcp-rapid-commit" in run("dnsmasq --help").stdout, reason="dnsmasq is missing dhcp-rapid-commit support")
def test_dhcp_client_rapid_commit(self):
check(self, True, False)
check(self, False, True)
check(self, False, False)
-
- def test_dhcp_client_default_use_domains(self):
+
+ def test_dhcp_client_default_use_domains(self):
def check(self, ipv4, ipv6):
mkdir_p(networkd_conf_dropin_dir)
with open(os.path.join(networkd_conf_dropin_dir, 'default_use_domains.conf'), mode='w', encoding='utf-8') as f:
f.write('yes\n' if ipv4 else 'no\n')
f.write('[DHCPv6]\nUseDomains=')
f.write('yes\n' if ipv6 else 'no\n')
-
+
restart_networkd()
self.wait_online('veth-peer:carrier')
start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1',
else:
print(output)
self.fail('unexpected domain setting in resolved...')
-
+
stop_dnsmasq()
remove_networkd_conf_dropin('default_use_domains.conf')