1
0
mirror of https://github.com/systemd/systemd.git synced 2025-09-01 13:59:26 +03:00

network: support reconfiguring netdev (#34909)

Closes #9627
Closes #27177.
Closes #34907.
Replaces #22557.
This commit is contained in:
Yu Watanabe
2024-10-31 07:01:46 +09:00
committed by GitHub
6 changed files with 339 additions and 49 deletions

View File

@ -413,14 +413,23 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
<term>
<command>reload</command>
</term>
<listitem><para>Reload <filename>.netdev</filename> and <filename>.network</filename> files.
If a new <filename>.netdev</filename> file is found, then the corresponding netdev is created.
Note that even if an existing <filename>.netdev</filename> is modified or removed,
<command>systemd-networkd</command> does not update or remove the netdev.
If a new, modified or removed <filename>.network</filename> file is found, then all interfaces
which match the file are reconfigured.</para>
<listitem>
<para>Reload <filename>.netdev</filename> and <filename>.network</filename> files.</para>
<xi:include href="version-info.xml" xpointer="v244"/></listitem>
<para>If a new or modified <filename>.netdev</filename> file is found, then the corresponding
netdev is created or updated, respectively. Note, if the corresponding interface already exists,
then some of new settings may not be applied. E.g., VLAN ID cannot be changed after the interface
was created, so changing [VLAN] <varname>Id=</varname> will not take effect if the matching VLAN
interface already exists. To apply such settings, the interfaces need to be removed manually before
reload. Also note that even if a <filename>.netdev</filename> file is removed,
<command>systemd-networkd</command> does not remove the existing netdev corresponding to the file.
</para>
<para>If a new, modified, or removed <filename>.network</filename> file is found, then all
interfaces that matched the file are reconfigured.</para>
<xi:include href="version-info.xml" xpointer="v244"/>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -10,6 +10,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
_cleanup_(manager_freep) Manager *manager = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_(unlink_tempfilep) char netdev_config[] = "/tmp/fuzz-networkd.XXXXXX";
_cleanup_(netdev_unrefp) NetDev *netdev = NULL;
if (outside_size_range(size, 0, 65536))
return 0;
@ -22,6 +23,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
fflush(f);
assert_se(manager_new(&manager, /* test_mode = */ true) >= 0);
(void) netdev_load_one(manager, netdev_config);
(void) netdev_load_one(manager, netdev_config, &netdev);
return 0;
}

View File

@ -242,6 +242,7 @@ static NetDev* netdev_free(NetDev *netdev) {
condition_free_list(netdev->conditions);
free(netdev->filename);
strv_free(netdev->dropins);
hashmap_free(netdev->stats_by_path);
free(netdev->description);
free(netdev->ifname);
@ -724,7 +725,7 @@ static int independent_netdev_create(NetDev *netdev) {
return 0;
}
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, netdev->ifindex);
if (r < 0)
return r;
@ -753,7 +754,7 @@ static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) {
assert(link);
assert(req);
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, netdev->ifindex);
if (r < 0)
return r;
@ -798,9 +799,6 @@ static bool link_is_ready_to_create_stacked_netdev(Link *link) {
static int netdev_is_ready_to_create(NetDev *netdev, Link *link) {
assert(netdev);
if (netdev->state != NETDEV_STATE_LOADING)
return false;
if (link && !link_is_ready_to_create_stacked_netdev(link))
return false;
@ -862,9 +860,6 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) {
if (!netdev_is_stacked(netdev))
return -EINVAL;
if (!IN_SET(netdev->state, NETDEV_STATE_LOADING, NETDEV_STATE_FAILED) || netdev->ifindex > 0)
return 0; /* Already created. */
if (!netdev_is_managed(netdev))
return 0; /* Already detached, due to e.g. reloading .netdev files. */
@ -921,6 +916,9 @@ static int netdev_request_to_create(NetDev *netdev) {
if (!netdev_is_managed(netdev))
return 0; /* Already detached, due to e.g. reloading .netdev files. */
if (netdev->state != NETDEV_STATE_LOADING)
return 0; /* Already configured (at least tried previously). Not necessary to reconfigure. */
r = netdev_is_ready_to_create(netdev, NULL);
if (r < 0)
return r;
@ -940,21 +938,20 @@ static int netdev_request_to_create(NetDev *netdev) {
return 0;
}
int netdev_load_one(Manager *manager, const char *filename) {
int netdev_load_one(Manager *manager, const char *filename, NetDev **ret) {
_cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL;
const char *dropin_dirname;
int r;
assert(manager);
assert(filename);
assert(ret);
r = null_or_empty_path(filename);
if (r < 0)
return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
if (r > 0) {
log_debug("Skipping empty file: %s", filename);
return 0;
}
if (r > 0)
return log_debug_errno(SYNTHETIC_ERRNO(ENOENT), "Skipping empty file: %s", filename);
netdev_raw = new(NetDev, 1);
if (!netdev_raw)
@ -979,10 +976,8 @@ int netdev_load_one(Manager *manager, const char *filename) {
return r; /* config_parse_many() logs internally. */
/* skip out early if configuration does not match the environment */
if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL)) {
log_debug("%s: Conditions in the file do not match the system environment, skipping.", filename);
return 0;
}
if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL))
return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "%s: Conditions in the file do not match the system environment, skipping.", filename);
if (netdev_raw->kind == _NETDEV_KIND_INVALID)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "NetDev has no Kind= configured in \"%s\", ignoring.", filename);
@ -1009,7 +1004,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
config_item_perf_lookup, network_netdev_gperf_lookup,
CONFIG_PARSE_WARN,
netdev,
NULL,
&netdev->stats_by_path,
&netdev->dropins);
if (r < 0)
return r; /* config_parse_many() logs internally. */
@ -1025,17 +1020,9 @@ int netdev_load_one(Manager *manager, const char *filename) {
if (!netdev->filename)
return log_oom();
r = netdev_attach(netdev);
if (r < 0)
return r;
log_syntax(/* unit = */ NULL, LOG_DEBUG, filename, /* config_line = */ 0, /* error = */ 0, "Successfully loaded.");
r = netdev_request_to_create(netdev);
if (r < 0)
return r; /* netdev_request_to_create() logs internally. */
TAKE_PTR(netdev);
*ret = TAKE_PTR(netdev);
return 0;
}
@ -1049,8 +1036,95 @@ int netdev_load(Manager *manager) {
if (r < 0)
return log_error_errno(r, "Failed to enumerate netdev files: %m");
STRV_FOREACH(f, files)
(void) netdev_load_one(manager, *f);
STRV_FOREACH(f, files) {
_cleanup_(netdev_unrefp) NetDev *netdev = NULL;
if (netdev_load_one(manager, *f, &netdev) < 0)
continue;
if (netdev_attach(netdev) < 0)
continue;
if (netdev_request_to_create(netdev) < 0)
continue;
TAKE_PTR(netdev);
}
return 0;
}
int netdev_reload(Manager *manager) {
_cleanup_hashmap_free_ Hashmap *new_netdevs = NULL;
_cleanup_strv_free_ char **files = NULL;
int r;
assert(manager);
r = conf_files_list_strv(&files, ".netdev", NULL, 0, NETWORK_DIRS);
if (r < 0)
return log_error_errno(r, "Failed to enumerate netdev files: %m");
STRV_FOREACH(f, files) {
_cleanup_(netdev_unrefp) NetDev *netdev = NULL;
NetDev *old;
if (netdev_load_one(manager, *f, &netdev) < 0)
continue;
if (netdev_get(manager, netdev->ifname, &old) < 0) {
log_netdev_debug(netdev, "Found new .netdev file: %s", netdev->filename);
if (netdev_attach_name_full(netdev, netdev->ifname, &new_netdevs) >= 0)
TAKE_PTR(netdev);
continue;
}
if (!stats_by_path_equal(netdev->stats_by_path, old->stats_by_path)) {
log_netdev_debug(netdev, "Found updated .netdev file: %s", netdev->filename);
/* Copy ifindex. */
netdev->ifindex = old->ifindex;
if (netdev_attach_name_full(netdev, netdev->ifname, &new_netdevs) >= 0)
TAKE_PTR(netdev);
continue;
}
/* Keep the original object, and drop the new one. */
if (netdev_attach_name_full(old, old->ifname, &new_netdevs) >= 0)
netdev_ref(old);
}
/* Detach old NetDev objects from Manager.
* Note, the same object may be registered with multiple names, and netdev_detach() may drop multiple
* entries. Hence, hashmap_free_with_destructor() cannot be used. */
for (NetDev *n; (n = hashmap_first(manager->netdevs)); )
netdev_detach(n);
/* Attach new NetDev objects to Manager. */
for (;;) {
_cleanup_(netdev_unrefp) NetDev *netdev = hashmap_steal_first(new_netdevs);
if (!netdev)
break;
netdev->manager = manager;
if (netdev_attach(netdev) < 0)
continue;
/* Create a new netdev or update existing netdev, */
if (netdev_request_to_create(netdev) < 0)
continue;
TAKE_PTR(netdev);
}
/* Reassign NetDev objects to Link object. */
Link *link;
HASHMAP_FOREACH(link, manager->links_by_index)
link_assign_netdev(link);
return 0;
}

View File

@ -118,6 +118,7 @@ typedef struct NetDev {
char *filename;
char **dropins;
Hashmap *stats_by_path;
LIST_HEAD(Condition, conditions);
@ -218,7 +219,8 @@ void netdev_detach(NetDev *netdev);
int netdev_set_ifindex_internal(NetDev *netdev, int ifindex);
int netdev_load(Manager *manager);
int netdev_load_one(Manager *manager, const char *filename);
int netdev_reload(Manager *manager);
int netdev_load_one(Manager *manager, const char *filename, NetDev **ret);
void netdev_drop(NetDev *netdev);
void netdev_enter_failed(NetDev *netdev);
int netdev_enter_ready(NetDev *netdev);

View File

@ -1188,7 +1188,7 @@ int manager_reload(Manager *m, sd_bus_message *message) {
(void) notify_reloading();
r = netdev_load(m);
r = netdev_reload(m);
if (r < 0)
goto finish;

View File

@ -358,6 +358,10 @@ def remove_network_unit(*units):
if has_link:
udevadm_reload()
def touch_network_unit(*units):
for unit in units:
touch(os.path.join(network_unit_dir, unit))
def clear_network_units():
has_link = False
if os.path.exists(network_unit_dir):
@ -1711,11 +1715,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.check_link_attr('bond97', 'bonding', 'arp_missed_max', '10')
self.check_link_attr('bond97', 'bonding', 'peer_notif_delay', '300000')
def test_vlan(self):
copy_network_unit('21-vlan.netdev', '11-dummy.netdev',
'21-vlan.network', '21-vlan-test1.network')
start_networkd()
def check_vlan(self, id, flags):
self.wait_online('test1:degraded', 'vlan99:routable')
self.networkctl_check_unit('vlan99', '21-vlan', '21-vlan')
self.networkctl_check_unit('test1', '11-dummy', '21-vlan-test1')
@ -1727,11 +1727,17 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
output = check_output('ip -d link show vlan99')
print(output)
self.assertIn(' mtu 2000 ', output)
self.assertIn('REORDER_HDR', output)
self.assertIn('LOOSE_BINDING', output)
self.assertIn('GVRP', output)
self.assertIn('MVRP', output)
self.assertIn(' id 99 ', output)
if flags:
self.assertIn('REORDER_HDR', output)
self.assertIn('LOOSE_BINDING', output)
self.assertIn('GVRP', output)
self.assertIn('MVRP', output)
else:
self.assertNotIn('REORDER_HDR', output)
self.assertNotIn('LOOSE_BINDING', output)
self.assertNotIn('GVRP', output)
self.assertNotIn('MVRP', output)
self.assertIn(f' id {id} ', output)
self.assertIn('ingress-qos-map { 4:100 7:13 }', output)
self.assertIn('egress-qos-map { 0:1 1:3 6:6 7:7 10:3 }', output)
@ -1744,6 +1750,32 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
def test_vlan(self):
copy_network_unit('21-vlan.netdev', '11-dummy.netdev',
'21-vlan.network', '21-vlan-test1.network')
start_networkd()
self.check_vlan(id=99, flags=True)
# Test for reloading .netdev file. See issue #34907.
with open(os.path.join(network_unit_dir, '21-vlan.netdev.d/override.conf'), mode='a', encoding='utf-8') as f:
f.write('[VLAN]\nId=42\n')
# VLAN ID cannot be changed, so we need to remove the existing netdev.
check_output("ip link del vlan99")
networkctl_reload()
self.check_vlan(id=42, flags=True)
with open(os.path.join(network_unit_dir, '21-vlan.netdev.d/override.conf'), mode='a', encoding='utf-8') as f:
f.write('[VLAN]\n'
'GVRP=no\n'
'MVRP=no\n'
'LooseBinding=no\n'
'ReorderHeader=no\n')
# flags can be changed, hence it is not necessary to remove the existing netdev.
networkctl_reload()
self.check_vlan(id=42, flags=False)
def test_vlan_on_bond(self):
# For issue #24377 (https://github.com/systemd/systemd/issues/24377),
# which is fixed by b05e52000b4eee764b383cc3031da0a3739e996e (PR#24020).
@ -1787,6 +1819,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'macvtap mode ' + mode + ' ')
touch_network_unit('21-macvtap.netdev')
networkctl_reload()
self.wait_online('macvtap99:degraded',
'test1:carrier' if mode == 'passthru' else 'test1:degraded')
@expectedFailureIfModuleIsNotAvailable('macvlan')
def test_macvlan(self):
first = True
@ -1837,6 +1874,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
if ' bclim ' in output: # This is new in kernel and iproute2 v6.4
self.assertIn(' bclim 2147483647 ', output)
touch_network_unit('21-macvlan.netdev')
networkctl_reload()
self.wait_online('macvlan99:degraded',
'test1:carrier' if mode == 'passthru' else 'test1:degraded')
@expectedFailureIfModuleIsNotAvailable('ipvlan')
def test_ipvlan(self):
first = True
@ -1862,6 +1904,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
touch_network_unit('25-ipvlan.netdev')
networkctl_reload()
self.wait_online('ipvlan99:degraded', 'test1:degraded')
@expectedFailureIfModuleIsNotAvailable('ipvtap')
def test_ipvtap(self):
first = True
@ -1887,6 +1933,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
touch_network_unit('25-ipvtap.netdev')
networkctl_reload()
self.wait_online('ipvtap99:degraded', 'test1:degraded')
def test_veth(self):
copy_network_unit('25-veth.netdev', '26-netdev-link-local-addressing-yes.network',
'25-veth-mtu.netdev')
@ -2197,6 +2247,19 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
touch_network_unit(
'25-ipip-tunnel.netdev',
'25-ipip-tunnel-local-any.netdev',
'25-ipip-tunnel-remote-any.netdev',
'25-ipip-tunnel-any-any.netdev')
networkctl_reload()
self.wait_online(
'ipiptun99:routable',
'ipiptun98:routable',
'ipiptun97:routable',
'ipiptun96:routable',
'dummy98:degraded')
def test_gre_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-gretun.network',
'25-gre-tunnel.netdev', '25-tunnel.network',
@ -2240,6 +2303,19 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertNotRegex(output, 'iseq')
self.assertNotRegex(output, 'oseq')
touch_network_unit(
'25-gre-tunnel.netdev',
'25-gre-tunnel-local-any.netdev',
'25-gre-tunnel-remote-any.netdev',
'25-gre-tunnel-any-any.netdev')
networkctl_reload()
self.wait_online(
'gretun99:routable',
'gretun98:routable',
'gretun97:routable',
'gretun96:routable',
'dummy98:degraded')
def test_ip6gre_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-ip6gretun.network',
'25-ip6gre-tunnel.netdev', '25-tunnel.network',
@ -2265,6 +2341,19 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
touch_network_unit(
'25-ip6gre-tunnel.netdev',
'25-ip6gre-tunnel-local-any.netdev',
'25-ip6gre-tunnel-remote-any.netdev',
'25-ip6gre-tunnel-any-any.netdev')
networkctl_reload()
self.wait_links(
'dummy98',
'ip6gretun99',
'ip6gretun98',
'ip6gretun97',
'ip6gretun96')
def test_gretap_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-gretap.network',
'25-gretap-tunnel.netdev', '25-tunnel.network',
@ -2292,6 +2381,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'iseq')
self.assertRegex(output, 'oseq')
touch_network_unit(
'25-gretap-tunnel.netdev',
'25-gretap-tunnel-local-any.netdev')
networkctl_reload()
self.wait_online(
'gretap99:routable',
'gretap98:routable',
'dummy98:degraded')
def test_ip6gretap_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-ip6gretap.network',
'25-ip6gretap-tunnel.netdev', '25-tunnel.network',
@ -2309,6 +2407,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
touch_network_unit(
'25-ip6gretap-tunnel.netdev',
'25-ip6gretap-tunnel-local-any.netdev')
networkctl_reload()
self.wait_online(
'ip6gretap99:routable',
'ip6gretap98:routable',
'dummy98:degraded')
def test_vti_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-vti.network',
'25-vti-tunnel.netdev', '25-tunnel.network',
@ -2336,6 +2443,19 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'vti remote any local any dev dummy98')
touch_network_unit(
'25-vti-tunnel.netdev',
'25-vti-tunnel-local-any.netdev',
'25-vti-tunnel-remote-any.netdev',
'25-vti-tunnel-any-any.netdev')
networkctl_reload()
self.wait_online(
'vtitun99:routable',
'vtitun98:routable',
'vtitun97:routable',
'vtitun96:routable',
'dummy98:degraded')
def test_vti6_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-vti6.network',
'25-vti6-tunnel.netdev', '25-tunnel.network',
@ -2358,6 +2478,17 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
touch_network_unit(
'25-vti6-tunnel.netdev',
'25-vti6-tunnel-local-any.netdev',
'25-vti6-tunnel-remote-any.netdev')
networkctl_reload()
self.wait_online(
'vti6tun99:routable',
'vti6tun98:routable',
'vti6tun97:routable',
'dummy98:degraded')
def test_ip6tnl_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-ip6tnl.network',
'25-ip6tnl-tunnel.netdev', '25-tunnel.network',
@ -2404,6 +2535,23 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertIn('default dev ip6tnl-slaac proto static', output)
touch_network_unit(
'25-ip6tnl-tunnel.netdev',
'25-ip6tnl-tunnel-local-any.netdev',
'25-ip6tnl-tunnel-remote-any.netdev',
'25-ip6tnl-tunnel-local-slaac.netdev',
'25-ip6tnl-tunnel-external.netdev')
networkctl_reload()
self.wait_online(
'ip6tnl99:routable',
'ip6tnl98:routable',
'ip6tnl97:routable',
'ip6tnl-slaac:degraded',
'ip6tnl-external:degraded',
'dummy98:degraded',
'veth99:routable',
'veth-peer:degraded')
def test_sit_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-sit.network',
'25-sit-tunnel.netdev', '25-tunnel.network',
@ -2431,6 +2579,19 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
touch_network_unit(
'25-sit-tunnel.netdev',
'25-sit-tunnel-local-any.netdev',
'25-sit-tunnel-remote-any.netdev',
'25-sit-tunnel-any-any.netdev')
networkctl_reload()
self.wait_online(
'sittun99:routable',
'sittun98:routable',
'sittun97:routable',
'sittun96:routable',
'dummy98:degraded')
def test_isatap_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-isatap.network',
'25-isatap-tunnel.netdev', '25-tunnel.network')
@ -2443,6 +2604,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, "isatap ")
touch_network_unit('25-isatap-tunnel.netdev')
networkctl_reload()
self.wait_online('isataptun99:routable', 'dummy98:degraded')
def test_6rd_tunnel(self):
copy_network_unit('12-dummy.netdev', '25-6rd.network',
'25-6rd-tunnel.netdev', '25-tunnel.network')
@ -2455,6 +2620,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, '6rd-prefix 2602::/24')
touch_network_unit('25-6rd-tunnel.netdev')
networkctl_reload()
self.wait_online('sittun99:routable', 'dummy98:degraded')
@expectedFailureIfERSPANv0IsNotSupported()
def test_erspan_tunnel_v0(self):
copy_network_unit('12-dummy.netdev', '25-erspan.network',
@ -2487,6 +2656,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertIn('ikey 0.0.0.102', output)
self.assertIn('iseq', output)
touch_network_unit(
'25-erspan0-tunnel.netdev',
'25-erspan0-tunnel-local-any.netdev')
networkctl_reload()
self.wait_online(
'erspan99:routable',
'erspan98:routable',
'dummy98:degraded')
def test_erspan_tunnel_v1(self):
copy_network_unit('12-dummy.netdev', '25-erspan.network',
'25-erspan1-tunnel.netdev', '25-tunnel.network',
@ -2520,6 +2698,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertIn('iseq', output)
self.assertIn('oseq', output)
touch_network_unit(
'25-erspan1-tunnel.netdev',
'25-erspan1-tunnel-local-any.netdev')
networkctl_reload()
self.wait_online(
'erspan99:routable',
'erspan98:routable',
'dummy98:degraded')
@expectedFailureIfERSPANv2IsNotSupported()
def test_erspan_tunnel_v2(self):
copy_network_unit('12-dummy.netdev', '25-erspan.network',
@ -2554,6 +2741,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertIn('iseq', output)
self.assertIn('oseq', output)
touch_network_unit(
'25-erspan2-tunnel.netdev',
'25-erspan2-tunnel-local-any.netdev')
networkctl_reload()
self.wait_online(
'erspan99:routable',
'erspan98:routable',
'dummy98:degraded')
def test_tunnel_independent(self):
copy_network_unit('25-ipip-tunnel-independent.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
@ -2590,6 +2786,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertIn('xfrm99@lo:', output)
self.assertIn('xfrm if_id 0x99 ', output)
touch_network_unit('25-xfrm.netdev')
networkctl_reload()
self.wait_online('dummy98:degraded', 'xfrm98:degraded', 'xfrm99:degraded')
@expectedFailureIfModuleIsNotAvailable('fou')
def test_fou(self):
# The following redundant check is necessary for CentOS CI.
@ -2718,6 +2918,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
touch_network_unit('25-macsec.netdev')
networkctl_reload()
self.wait_online('dummy98:degraded', 'macsec99:routable')
def test_nlmon(self):
copy_network_unit('25-nlmon.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()