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:
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
|
Reference in New Issue
Block a user