From 1788c3462853e8bb955ff656007e20f402dd9af2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 00:12:41 +0900 Subject: [PATCH 01/18] network/netdev: also check ifindex, iftype, and kind when assigning NetDev to Link Even when a NetDev object with the same name found, its iftype or kind may be different. For safety, let's also check them. --- src/network/netdev/netdev.c | 37 +++++++++++++++++++++++++++++++++++++ src/network/netdev/netdev.h | 1 + src/network/networkd-link.c | 10 ++-------- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index cc32e6d1a6..21b897a65f 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -266,6 +266,43 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) { return 0; } +void link_assign_netdev(Link *link) { + _unused_ _cleanup_(netdev_unrefp) NetDev *old = NULL; + NetDev *netdev; + + assert(link); + assert(link->manager); + assert(link->ifname); + + old = TAKE_PTR(link->netdev); + + if (netdev_get(link->manager, link->ifname, &netdev) < 0) + return; + + if (netdev->ifindex != link->ifindex) + return; + + if (NETDEV_VTABLE(netdev)->iftype != link->iftype) + return; + + if (!NETDEV_VTABLE(netdev)->skip_netdev_kind_check) { + const char *kind; + + if (netdev->kind == NETDEV_KIND_TAP) + kind = "tun"; /* the kernel does not distinguish between tun and tap */ + else + kind = netdev_kind_to_string(netdev->kind); + + if (!streq_ptr(kind, link->kind)) + return; + } + + link->netdev = netdev_ref(netdev); + + if (netdev != old) + log_link_debug(link, "Found matching .netdev file: %s", netdev->filename); +} + void netdev_enter_failed(NetDev *netdev) { netdev->state = NETDEV_STATE_FAILED; } diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index d6b363d4f1..3bb4acf6c2 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -207,6 +207,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref); bool netdev_is_managed(NetDev *netdev); int netdev_get(Manager *manager, const char *name, NetDev **ret); +void link_assign_netdev(Link *link); int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink); int netdev_generate_hw_addr(NetDev *netdev, Link *link, const char *name, const struct hw_addr_data *hw_addr, struct hw_addr_data *ret); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 1c6f20695f..f3131a6195 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1307,18 +1307,15 @@ static int link_get_network(Link *link, Network **ret) { int link_reconfigure_impl(Link *link, bool force) { Network *network = NULL; - NetDev *netdev = NULL; int r; assert(link); + link_assign_netdev(link); + if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER)) return 0; - r = netdev_get(link->manager, link->ifname, &netdev); - if (r < 0 && r != -ENOENT) - return r; - r = link_get_network(link, &network); if (r < 0 && r != -ENOENT) return r; @@ -1383,9 +1380,6 @@ int link_reconfigure_impl(Link *link, bool force) { link_free_engines(link); link->network = network_unref(link->network); - netdev_unref(link->netdev); - link->netdev = netdev_ref(netdev); - if (!network) { link_set_state(link, LINK_STATE_UNMANAGED); return 0; From 72fd133dca7c6adfc9956281b51bc5548bc9235e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 00:17:11 +0900 Subject: [PATCH 02/18] network/route: use NetDev object assigned to Link --- src/network/networkd-route.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 9e383ee6e8..859a3cf4cd 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1008,19 +1008,15 @@ static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request } static int link_request_wireguard_routes(Link *link, bool only_ipv4) { - NetDev *netdev; Route *route; int r; assert(link); - if (!streq_ptr(link->kind, "wireguard")) + if (!link->netdev || link->netdev->kind != NETDEV_KIND_WIREGUARD) return 0; - if (netdev_get(link->manager, link->ifname, &netdev) < 0) - return 0; - - Wireguard *w = WIREGUARD(netdev); + Wireguard *w = WIREGUARD(link->netdev); SET_FOREACH(route, w->routes) { if (only_ipv4 && route->family != AF_INET) From 5d7de25052fa7d086c4763af81353f7e4eb8429d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 22:46:27 +0900 Subject: [PATCH 03/18] network/netdev: check family of received NEWLINK message For safety. No functional change, just refactoring and preparation for later commits. --- src/network/netdev/netdev.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 21b897a65f..6a59a8f2df 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -351,7 +351,7 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { const char *kind; const char *received_kind; const char *received_name; - int r, ifindex; + int r, ifindex, family; assert(netdev); assert(message); @@ -363,6 +363,13 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { if (type != RTM_NEWLINK) return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Cannot set ifindex from unexpected rtnl message type."); + r = sd_rtnl_message_get_family(message, &family); + if (r < 0) + return log_netdev_warning_errno(netdev, r, "Failed to get family from received rtnl message: %m"); + + if (family != AF_UNSPEC) + return 0; /* IFLA_LINKINFO is only contained in the message with AF_UNSPEC. */ + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); if (r < 0) { log_netdev_error_errno(netdev, r, "Could not get ifindex: %m"); From bc0d3f384291a958b1bca7a46098cede3a3750fe Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 22:39:50 +0900 Subject: [PATCH 04/18] network/netdev: downgrade log level in netdev_set_ifindex() This also makes netdev_enter_failed() called on caller side. No functional change, just refactoring. --- src/network/netdev/netdev.c | 67 ++++++++++++++----------------------- src/network/networkd-link.c | 1 + 2 files changed, 27 insertions(+), 41 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 6a59a8f2df..f24ec02f7f 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -358,10 +358,10 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { r = sd_netlink_message_get_type(message, &type); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not get rtnl message type: %m"); + return log_netdev_warning_errno(netdev, r, "Could not get rtnl message type: %m"); if (type != RTM_NEWLINK) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Cannot set ifindex from unexpected rtnl message type."); + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Cannot set ifindex from unexpected rtnl message type."); r = sd_rtnl_message_get_family(message, &family); if (r < 0) @@ -371,69 +371,54 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { return 0; /* IFLA_LINKINFO is only contained in the message with AF_UNSPEC. */ r = sd_rtnl_message_link_get_ifindex(message, &ifindex); - if (r < 0) { - log_netdev_error_errno(netdev, r, "Could not get ifindex: %m"); - netdev_enter_failed(netdev); - return r; - } else if (ifindex <= 0) { - log_netdev_error(netdev, "Got invalid ifindex: %d", ifindex); - netdev_enter_failed(netdev); - return -EINVAL; - } + if (r < 0) + return log_netdev_warning_errno(netdev, r, "Could not get ifindex: %m"); + if (ifindex <= 0) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Got invalid ifindex: %d", ifindex); if (netdev->ifindex > 0) { - if (netdev->ifindex != ifindex) { - log_netdev_error(netdev, "Could not set ifindex to %d, already set to %d", - ifindex, netdev->ifindex); - netdev_enter_failed(netdev); - return -EEXIST; - } else - /* ifindex already set to the same for this netdev */ - return 0; + if (netdev->ifindex != ifindex) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST), + "Could not set ifindex to %d, already set to %d", + ifindex, netdev->ifindex); + + /* ifindex already set to the same for this netdev */ + return 0; } r = sd_netlink_message_read_string(message, IFLA_IFNAME, &received_name); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not get IFNAME: %m"); + return log_netdev_warning_errno(netdev, r, "Could not get IFNAME: %m"); - if (!streq(netdev->ifname, received_name)) { - log_netdev_error(netdev, "Received newlink with wrong IFNAME %s", received_name); - netdev_enter_failed(netdev); - return -EINVAL; - } + if (!streq(netdev->ifname, received_name)) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Received newlink with wrong IFNAME %s", received_name); if (!NETDEV_VTABLE(netdev)->skip_netdev_kind_check) { r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not get LINKINFO: %m"); + return log_netdev_warning_errno(netdev, r, "Could not get LINKINFO: %m"); r = sd_netlink_message_read_string(message, IFLA_INFO_KIND, &received_kind); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not get KIND: %m"); + return log_netdev_warning_errno(netdev, r, "Could not get KIND: %m"); r = sd_netlink_message_exit_container(message); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not exit container: %m"); + return log_netdev_warning_errno(netdev, r, "Could not exit container: %m"); if (netdev->kind == NETDEV_KIND_TAP) /* the kernel does not distinguish between tun and tap */ kind = "tun"; - else { + else kind = netdev_kind_to_string(netdev->kind); - if (!kind) { - log_netdev_error(netdev, "Could not get kind"); - netdev_enter_failed(netdev); - return -EINVAL; - } - } + if (!kind) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Could not get netdev kind."); - if (!streq(kind, received_kind)) { - log_netdev_error(netdev, "Received newlink with wrong KIND %s, expected %s", - received_kind, kind); - netdev_enter_failed(netdev); - return -EINVAL; - } + if (!streq(kind, received_kind)) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "Received newlink with wrong KIND %s, expected %s", + received_kind, kind); } netdev->ifindex = ifindex; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index f3131a6195..0eeab6e8b0 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2804,6 +2804,7 @@ int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Man r = netdev_set_ifindex(netdev, message); if (r < 0) { log_netdev_warning_errno(netdev, r, "Could not process new link message for netdev, ignoring: %m"); + netdev_enter_failed(netdev); return 0; } } From 0dc71b9584d36c691e28a227f6ffad732b6e8c95 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 15:17:54 +0900 Subject: [PATCH 05/18] network/netdev: use hashmap_remove_value() on detaching NetDev from manager Then, it is not necessary to free NetDev.ifname when a conflicting .netdev file is already loaded. This also split out netdev_detach_name() and netdev_detach_impl(). No functional change, just refactoring. --- src/network/netdev/netdev.c | 36 +++++++++++++++++++++++++----------- src/network/netdev/netdev.h | 3 +++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index f24ec02f7f..1b01f7e453 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -191,12 +191,31 @@ static bool netdev_is_stacked(NetDev *netdev) { return true; } -static void netdev_detach_from_manager(NetDev *netdev) { - if (netdev->ifname && netdev->manager) - hashmap_remove(netdev->manager->netdevs, netdev->ifname); +NetDev* netdev_detach_name(NetDev *netdev, const char *name) { + assert(netdev); + + if (!netdev->manager || !name) + return NULL; /* Already detached or not attached yet. */ + + return hashmap_remove_value(netdev->manager->netdevs, name, netdev); } -static NetDev *netdev_free(NetDev *netdev) { +static NetDev* netdev_detach_impl(NetDev *netdev) { + assert(netdev); + + NetDev *n = netdev_detach_name(netdev, netdev->ifname); + + netdev->manager = NULL; + return n; /* Return NULL when it is not attached yet, or already detached. */ +} + +void netdev_detach(NetDev *netdev) { + assert(netdev); + + netdev_unref(netdev_detach_impl(netdev)); +} + +static NetDev* netdev_free(NetDev *netdev) { assert(netdev); /* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that @@ -211,7 +230,7 @@ static NetDev *netdev_free(NetDev *netdev) { NETDEV_VTABLE(netdev)->done) NETDEV_VTABLE(netdev)->done(netdev); - netdev_detach_from_manager(netdev); + netdev_detach_impl(netdev); condition_free_list(netdev->conditions); free(netdev->filename); @@ -245,9 +264,7 @@ void netdev_drop(NetDev *netdev) { log_netdev_debug(netdev, "netdev removed"); - netdev_detach_from_manager(netdev); - netdev_unref(netdev); - return; + netdev_detach(netdev); } int netdev_get(Manager *manager, const char *name, NetDev **ret) { @@ -891,9 +908,6 @@ int netdev_load_one(Manager *manager, const char *filename) { "Device was already configured by \"%s\", ignoring %s.", n->filename, netdev->filename); - /* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is - * removed from the hashmap 'manager->netdevs'. */ - netdev->ifname = mfree(netdev->ifname); return -EEXIST; } assert(r > 0); diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 3bb4acf6c2..2d19c2f042 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -195,6 +195,9 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; /* For casting the various netdev kinds into a netdev */ #define NETDEV(n) (&(n)->meta) +NetDev* netdev_detach_name(NetDev *netdev, const char *name); +void netdev_detach(NetDev *netdev); + int netdev_load(Manager *manager, bool reload); int netdev_load_one(Manager *manager, const char *filename); void netdev_drop(NetDev *netdev); From bfacb8fe1dfd0e46e115f70acb761c8f8366ad05 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 17:41:00 +0900 Subject: [PATCH 06/18] network/netdev: split out netdev_attach() and netdev_attach_name() from netdev_load_one() No functional change, just refactoring and preparation for later commits. --- src/network/netdev/netdev.c | 57 +++++++++++++++++++++++++++---------- src/network/netdev/netdev.h | 2 ++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 1b01f7e453..9949ade363 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -267,6 +267,45 @@ void netdev_drop(NetDev *netdev) { netdev_detach(netdev); } +int netdev_attach_name(NetDev *netdev, const char *name) { + int r; + + assert(netdev); + assert(netdev->manager); + assert(name); + + r = hashmap_ensure_put(&netdev->manager->netdevs, &string_hash_ops, name, netdev); + if (r == -ENOMEM) + return log_oom(); + if (r == -EEXIST) { + NetDev *n = hashmap_get(netdev->manager->netdevs, name); + + assert(n); + if (!streq(netdev->filename, n->filename)) + log_netdev_warning_errno(netdev, r, + "Device \"%s\" was already configured by \"%s\", ignoring %s.", + name, n->filename, netdev->filename); + + return -EEXIST; + } + assert(r > 0); + + return 0; +} + +static int netdev_attach(NetDev *netdev) { + int r; + + assert(netdev); + assert(netdev->ifname); + + r = netdev_attach_name(netdev, netdev->ifname); + if (r < 0) + return r; + + return 0; +} + int netdev_get(Manager *manager, const char *name, NetDev **ret) { NetDev *netdev; @@ -896,21 +935,9 @@ int netdev_load_one(Manager *manager, const char *filename) { if (!netdev->filename) return log_oom(); - r = hashmap_ensure_put(&netdev->manager->netdevs, &string_hash_ops, netdev->ifname, netdev); - if (r == -ENOMEM) - return log_oom(); - if (r == -EEXIST) { - NetDev *n = hashmap_get(netdev->manager->netdevs, netdev->ifname); - - assert(n); - if (!streq(netdev->filename, n->filename)) - log_netdev_warning_errno(netdev, r, - "Device was already configured by \"%s\", ignoring %s.", - n->filename, netdev->filename); - - return -EEXIST; - } - assert(r > 0); + r = netdev_attach(netdev); + if (r < 0) + return r; log_netdev_debug(netdev, "loaded \"%s\"", netdev_kind_to_string(netdev->kind)); diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 2d19c2f042..c173ed3fd5 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -5,6 +5,7 @@ #include "conf-parser.h" #include "ether-addr-util.h" +#include "hash-funcs.h" #include "list.h" #include "log-link.h" #include "networkd-link.h" @@ -195,6 +196,7 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; /* For casting the various netdev kinds into a netdev */ #define NETDEV(n) (&(n)->meta) +int netdev_attach_name(NetDev *netdev, const char *name); NetDev* netdev_detach_name(NetDev *netdev, const char *name); void netdev_detach(NetDev *netdev); From 5dc20e1acdfc729c732b23fcec44cf07f4a5212e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 00:57:25 +0900 Subject: [PATCH 07/18] network/netdev: split out netdev_set_ifindex_internal() and _impl() No functional change, just refactoring and preparation for later commits. --- src/network/netdev/netdev.c | 59 ++++++++++++++++++++++++------------- src/network/netdev/netdev.h | 2 ++ 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 9949ade363..d6c78c318d 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -363,7 +363,7 @@ void netdev_enter_failed(NetDev *netdev) { netdev->state = NETDEV_STATE_FAILED; } -static int netdev_enter_ready(NetDev *netdev) { +int netdev_enter_ready(NetDev *netdev) { assert(netdev); assert(netdev->ifname); @@ -402,6 +402,42 @@ static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev return 1; } +int netdev_set_ifindex_internal(NetDev *netdev, int ifindex) { + assert(netdev); + assert(ifindex > 0); + + if (netdev->ifindex == ifindex) + return 0; /* Already set. */ + + if (netdev->ifindex > 0 && netdev->ifindex != ifindex) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST), + "Could not set ifindex to %i, already set to %i.", + ifindex, netdev->ifindex); + + netdev->ifindex = ifindex; + log_netdev_debug(netdev, "Gained index %i.", ifindex); + return 1; /* set new ifindex. */ +} + +static int netdev_set_ifindex_impl(NetDev *netdev, const char *name, int ifindex) { + int r; + + assert(netdev); + assert(name); + assert(ifindex > 0); + + if (!streq(netdev->ifname, name)) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "Received netlink message with unexpected interface name %s (ifindex=%i).", + name, ifindex); + + r = netdev_set_ifindex_internal(netdev, ifindex); + if (r <= 0) + return r; + + return netdev_enter_ready(netdev); +} + int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { uint16_t type; const char *kind; @@ -432,23 +468,10 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { if (ifindex <= 0) return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Got invalid ifindex: %d", ifindex); - if (netdev->ifindex > 0) { - if (netdev->ifindex != ifindex) - return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST), - "Could not set ifindex to %d, already set to %d", - ifindex, netdev->ifindex); - - /* ifindex already set to the same for this netdev */ - return 0; - } - r = sd_netlink_message_read_string(message, IFLA_IFNAME, &received_name); if (r < 0) return log_netdev_warning_errno(netdev, r, "Could not get IFNAME: %m"); - if (!streq(netdev->ifname, received_name)) - return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Received newlink with wrong IFNAME %s", received_name); - if (!NETDEV_VTABLE(netdev)->skip_netdev_kind_check) { r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); @@ -477,13 +500,7 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { received_kind, kind); } - netdev->ifindex = ifindex; - - log_netdev_debug(netdev, "netdev has index %d", netdev->ifindex); - - netdev_enter_ready(netdev); - - return 0; + return netdev_set_ifindex_impl(netdev, received_name, ifindex); } #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48) diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index c173ed3fd5..0b942caa4b 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -199,11 +199,13 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; int netdev_attach_name(NetDev *netdev, const char *name); NetDev* netdev_detach_name(NetDev *netdev, const char *name); void netdev_detach(NetDev *netdev); +int netdev_set_ifindex_internal(NetDev *netdev, int ifindex); int netdev_load(Manager *manager, bool reload); int netdev_load_one(Manager *manager, const char *filename); void netdev_drop(NetDev *netdev); void netdev_enter_failed(NetDev *netdev); +int netdev_enter_ready(NetDev *netdev); NetDev *netdev_unref(NetDev *netdev); NetDev *netdev_ref(NetDev *netdev); From 36ca0164ab78e1ecd0fdfbede890378448c9b79e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 23:55:46 +0900 Subject: [PATCH 08/18] network/netdev: allow to register the same NetDev object with multiple names Preparation for later commits. --- src/network/networkd-manager.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 4ebecaac59..2c2956f465 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -633,7 +633,11 @@ Manager* manager_free(Manager *m) { m->dhcp_pd_subnet_ids = set_free(m->dhcp_pd_subnet_ids); m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref); - m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref); + /* 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(m->netdevs)); ) + netdev_detach(n); + m->netdevs = hashmap_free(m->netdevs); m->tuntap_fds_by_name = hashmap_free(m->tuntap_fds_by_name); From c60cd572bdac896dfda70e86aca3c0ead30807f9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 17:37:42 +0900 Subject: [PATCH 09/18] network/netdev: add attach(), detach(), set_ifindex(), and get_ifindex() to netdev vtable Currently no vtable sets these functions, but will be used later. --- src/network/netdev/netdev.c | 23 ++++++++++++++++++++--- src/network/netdev/netdev.h | 10 ++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index d6c78c318d..d37476bb71 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -203,6 +203,11 @@ NetDev* netdev_detach_name(NetDev *netdev, const char *name) { static NetDev* netdev_detach_impl(NetDev *netdev) { assert(netdev); + if (netdev->state != _NETDEV_STATE_INVALID && + NETDEV_VTABLE(netdev) && + NETDEV_VTABLE(netdev)->detach) + NETDEV_VTABLE(netdev)->detach(netdev); + NetDev *n = netdev_detach_name(netdev, netdev->ifname); netdev->manager = NULL; @@ -218,6 +223,8 @@ void netdev_detach(NetDev *netdev) { static NetDev* netdev_free(NetDev *netdev) { assert(netdev); + netdev_detach_impl(netdev); + /* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that * because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure * allocation, with no room for per-kind fields), and once to read the kind's properties (with a full, @@ -230,8 +237,6 @@ static NetDev* netdev_free(NetDev *netdev) { NETDEV_VTABLE(netdev)->done) NETDEV_VTABLE(netdev)->done(netdev); - netdev_detach_impl(netdev); - condition_free_list(netdev->conditions); free(netdev->filename); strv_free(netdev->dropins); @@ -303,6 +308,12 @@ static int netdev_attach(NetDev *netdev) { if (r < 0) return r; + if (NETDEV_VTABLE(netdev)->attach) { + r = NETDEV_VTABLE(netdev)->attach(netdev); + if (r < 0) + return r; + } + return 0; } @@ -335,7 +346,10 @@ void link_assign_netdev(Link *link) { if (netdev_get(link->manager, link->ifname, &netdev) < 0) return; - if (netdev->ifindex != link->ifindex) + int ifindex = NETDEV_VTABLE(netdev)->get_ifindex ? + NETDEV_VTABLE(netdev)->get_ifindex(netdev, link->ifname) : + netdev->ifindex; + if (ifindex != link->ifindex) return; if (NETDEV_VTABLE(netdev)->iftype != link->iftype) @@ -426,6 +440,9 @@ static int netdev_set_ifindex_impl(NetDev *netdev, const char *name, int ifindex assert(name); assert(ifindex > 0); + if (NETDEV_VTABLE(netdev)->set_ifindex) + return NETDEV_VTABLE(netdev)->set_ifindex(netdev, name, ifindex); + if (!streq(netdev->ifname, name)) return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Received netlink message with unexpected interface name %s (ifindex=%i).", diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 0b942caa4b..10b9d0dd77 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -169,6 +169,16 @@ typedef struct NetDevVTable { /* verify that compulsory configuration options were specified */ int (*config_verify)(NetDev *netdev, const char *filename); + /* attach/detach additional interfaces, e.g. veth peer or L2TP sessions. */ + int (*attach)(NetDev *netdev); + void (*detach)(NetDev *netdev); + + /* set ifindex of the created interface. */ + int (*set_ifindex)(NetDev *netdev, const char *name, int ifindex); + + /* get ifindex of the netdev. */ + int (*get_ifindex)(NetDev *netdev, const char *name); + /* expected iftype, e.g. ARPHRD_ETHER. */ uint16_t iftype; From 98fbb3b5b00ab0f00611814972beeffc6116b089 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 03:00:09 +0900 Subject: [PATCH 10/18] network/veth: refuse when peer and the main interface names are equivalent --- src/network/netdev/veth.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/network/netdev/veth.c b/src/network/netdev/veth.c index 78555286d1..c9831b21b9 100644 --- a/src/network/netdev/veth.c +++ b/src/network/netdev/veth.c @@ -62,6 +62,10 @@ static int netdev_veth_verify(NetDev *netdev, const char *filename) { "Veth NetDev without peer name configured in %s. Ignoring", filename); + if (streq(v->ifname_peer, netdev->ifname)) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "Veth peer name cannot be the same as the main interface name."); + return 0; } From 909acd37b8c1a5dea447a5cc5ed3d6b03523e1b8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 17:38:16 +0900 Subject: [PATCH 11/18] network/veth: also manage peer name by Manager Then, the Link object for the peer interface can have a reference to the corresponding NetDev object. --- src/network/netdev/veth.c | 66 +++++++++++++++++++++++++++++++++++++++ src/network/netdev/veth.h | 1 + 2 files changed, 67 insertions(+) diff --git a/src/network/netdev/veth.c b/src/network/netdev/veth.c index c9831b21b9..edebcf0a74 100644 --- a/src/network/netdev/veth.c +++ b/src/network/netdev/veth.c @@ -69,6 +69,68 @@ static int netdev_veth_verify(NetDev *netdev, const char *filename) { return 0; } +static int netdev_veth_attach(NetDev *netdev) { + Veth *v = VETH(netdev); + + assert(v->ifname_peer); + return netdev_attach_name(netdev, v->ifname_peer); +} + +static void netdev_veth_detach(NetDev *netdev) { + Veth *v = VETH(netdev); + + netdev_detach_name(netdev, v->ifname_peer); +} + +static int netdev_veth_set_ifindex(NetDev *netdev, const char *name, int ifindex) { + Veth *v = VETH(netdev); + int r; + + assert(name); + assert(ifindex > 0); + + if (streq(netdev->ifname, name)) { + r = netdev_set_ifindex_internal(netdev, ifindex); + if (r <= 0) + return r; + + } else if (streq(v->ifname_peer, name)) { + if (v->ifindex_peer == ifindex) + return 0; /* already set. */ + + if (v->ifindex_peer > 0 && v->ifindex_peer != ifindex) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST), + "Could not set ifindex %i for peer %s, already set to %i.", + ifindex, v->ifname_peer, v->ifindex_peer); + + v->ifindex_peer = ifindex; + log_netdev_debug(netdev, "Peer interface %s gained index %i.", v->ifname_peer, ifindex); + + } else + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "Received netlink message with unexpected interface name %s (index=%i).", + name, ifindex); + + if (netdev->ifindex > 0 && v->ifindex_peer > 0) + return netdev_enter_ready(netdev); + + return 0; +} + +static int netdev_veth_get_ifindex(NetDev *netdev, const char *name) { + Veth *v = VETH(netdev); + + assert(name); + + if (streq(netdev->ifname, name)) + return netdev->ifindex; + + if (streq(v->ifname_peer, name)) + return v->ifindex_peer; + + return -ENODEV; +} + static void veth_done(NetDev *netdev) { Veth *v = VETH(netdev); @@ -82,6 +144,10 @@ const NetDevVTable veth_vtable = { .fill_message_create = netdev_veth_fill_message_create, .create_type = NETDEV_CREATE_INDEPENDENT, .config_verify = netdev_veth_verify, + .attach = netdev_veth_attach, + .detach = netdev_veth_detach, + .set_ifindex = netdev_veth_set_ifindex, + .get_ifindex = netdev_veth_get_ifindex, .iftype = ARPHRD_ETHER, .generate_mac = true, }; diff --git a/src/network/netdev/veth.h b/src/network/netdev/veth.h index e0d6fd4352..8ee973385b 100644 --- a/src/network/netdev/veth.h +++ b/src/network/netdev/veth.h @@ -10,6 +10,7 @@ struct Veth { char *ifname_peer; struct hw_addr_data hw_addr_peer; + int ifindex_peer; }; DEFINE_NETDEV_CAST(VETH, Veth); From c480e4cd66a1759f7521ad093d28cbf737195f7a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 03:05:18 +0900 Subject: [PATCH 12/18] network/l2tp: downgrade log level of several messages Also, use log_section_warning_errno() where applicable. --- src/network/netdev/l2tp-tunnel.c | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c index 3194f3f785..9f8287cb91 100644 --- a/src/network/netdev/l2tp-tunnel.c +++ b/src/network/netdev/l2tp-tunnel.c @@ -752,28 +752,28 @@ static void l2tp_tunnel_init(NetDev *netdev) { t->udp6_csum_tx = true; } -static int l2tp_session_verify(L2tpSession *session) { - NetDev *netdev; +#define log_session(session, fmt, ...) \ + ({ \ + const L2tpSession *_session = (session); \ + log_section_warning_errno( \ + _session ? _session->section : NULL, \ + SYNTHETIC_ERRNO(EINVAL), \ + fmt " Ignoring [L2TPSession] section.", \ + ##__VA_ARGS__); \ + }) +static int l2tp_session_verify(L2tpSession *session) { assert(session); assert(session->tunnel); - netdev = NETDEV(session->tunnel); - if (section_is_invalid(session->section)) return -EINVAL; if (!session->name) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), - "%s: L2TP session without name configured. " - "Ignoring [L2TPSession] section from line %u", - session->section->filename, session->section->line); + return log_session(session, "L2TP session without name configured."); if (session->session_id == 0 || session->peer_session_id == 0) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), - "%s: L2TP session without session IDs configured. " - "Ignoring [L2TPSession] section from line %u", - session->section->filename, session->section->line); + return log_session(session, "L2TP session without session IDs configured."); return 0; } @@ -785,19 +785,19 @@ static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) { L2tpSession *session; if (!IN_SET(t->family, AF_INET, AF_INET6)) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), - "%s: L2TP tunnel with invalid address family configured. Ignoring", - filename); + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: L2TP tunnel with invalid address family configured. Ignoring", + filename); if (!in_addr_is_set(t->family, &t->remote)) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), - "%s: L2TP tunnel without a remote address configured. Ignoring", - filename); + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: L2TP tunnel without a remote address configured. Ignoring", + filename); if (t->tunnel_id == 0 || t->peer_tunnel_id == 0) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), - "%s: L2TP tunnel without tunnel IDs configured. Ignoring", - filename); + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: L2TP tunnel without tunnel IDs configured. Ignoring", + filename); ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) if (l2tp_session_verify(session) < 0) From 121d32b09c1675aa2dbe561f33f1695a1ae3fe26 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 03:18:19 +0900 Subject: [PATCH 13/18] network/l2tp: refuse duplicated session name --- src/network/netdev/l2tp-tunnel.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c index 9f8287cb91..b9be66c113 100644 --- a/src/network/netdev/l2tp-tunnel.c +++ b/src/network/netdev/l2tp-tunnel.c @@ -762,9 +762,12 @@ static void l2tp_tunnel_init(NetDev *netdev) { ##__VA_ARGS__); \ }) -static int l2tp_session_verify(L2tpSession *session) { +static int l2tp_session_verify(L2tpSession *session, Set **names) { + int r; + assert(session); assert(session->tunnel); + assert(names); if (section_is_invalid(session->section)) return -EINVAL; @@ -775,6 +778,15 @@ static int l2tp_session_verify(L2tpSession *session) { if (session->session_id == 0 || session->peer_session_id == 0) return log_session(session, "L2TP session without session IDs configured."); + if (streq(session->name, NETDEV(session->tunnel)->ifname)) + return log_session(session, "L2TP session name %s cannot be the same as the netdev name.", session->name); + + r = set_ensure_put(names, &string_hash_ops, session->name); + if (r < 0) + return log_oom(); + if (r == 0) + return log_session(session, "L2TP session name %s is duplicated.", session->name); + return 0; } @@ -799,8 +811,9 @@ static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) { "%s: L2TP tunnel without tunnel IDs configured. Ignoring", filename); + _cleanup_set_free_ Set *names = NULL; ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) - if (l2tp_session_verify(session) < 0) + if (l2tp_session_verify(session, &names) < 0) l2tp_session_free(session); return 0; From 2d5f58cf41a55116c303c76765f8071855ee6c81 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 17:54:01 +0900 Subject: [PATCH 14/18] network/l2tp: manage l2tp session name by Manager Then, Link object for an L2TP session can have reference to the corresponding NetDev object. --- src/network/netdev/l2tp-tunnel.c | 79 ++++++++++++++++++++++++++++++++ src/network/netdev/l2tp-tunnel.h | 1 + 2 files changed, 80 insertions(+) diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c index b9be66c113..c1372bb1e0 100644 --- a/src/network/netdev/l2tp-tunnel.c +++ b/src/network/netdev/l2tp-tunnel.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include +#include #include #include @@ -819,6 +820,78 @@ static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) { return 0; } +static int netdev_l2tp_tunnel_attach(NetDev *netdev) { + L2tpTunnel *t = L2TP(netdev); + L2tpSession *session; + int r; + + ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) { + assert(session->name); + + r = netdev_attach_name(netdev, session->name); + if (r < 0) + return r; + } + + return 0; +} + +static void netdev_l2tp_tunnel_detach(NetDev *netdev) { + L2tpTunnel *t = L2TP(netdev); + L2tpSession *session; + + ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) + netdev_detach_name(netdev, session->name); +} + +static int netdev_l2tp_tunnel_set_ifindex(NetDev *netdev, const char *name, int ifindex) { + L2tpTunnel *t = L2TP(netdev); + L2tpSession *session; + bool found = false; + + assert(name); + assert(ifindex > 0); + + ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) + if (streq(session->name, name)) { + if (session->ifindex == ifindex) + return 0; /* already set. */ + if (session->ifindex > 0 && session->ifindex != ifindex) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST), + "Could not set ifindex %i for session %s, already set to %i.", + ifindex, session->name, session->ifindex); + + session->ifindex = ifindex; + log_netdev_debug(netdev, "Session %s gained ifindex %i.", session->name, session->ifindex); + found = true; + break; + } + + if (!found) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "Received netlink message with unexpected interface name %s (ifindex=%i).", + name, ifindex); + + ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) + if (session->ifindex <= 0) + return 0; /* This session is not ready yet. */ + + return netdev_enter_ready(netdev); +} + +static int netdev_l2tp_tunnel_get_ifindex(NetDev *netdev, const char *name) { + L2tpTunnel *t = L2TP(netdev); + L2tpSession *session; + + assert(name); + + ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) + if (streq(session->name, name)) + return session->ifindex; + + return -ENODEV; +} + static void l2tp_tunnel_done(NetDev *netdev) { L2tpTunnel *t = L2TP(netdev); @@ -835,4 +908,10 @@ const NetDevVTable l2tptnl_vtable = { .create_type = NETDEV_CREATE_INDEPENDENT, .is_ready_to_create = netdev_l2tp_is_ready_to_create, .config_verify = netdev_l2tp_tunnel_verify, + .attach = netdev_l2tp_tunnel_attach, + .detach = netdev_l2tp_tunnel_detach, + .set_ifindex = netdev_l2tp_tunnel_set_ifindex, + .get_ifindex = netdev_l2tp_tunnel_get_ifindex, + .iftype = ARPHRD_ETHER, + .skip_netdev_kind_check = true, }; diff --git a/src/network/netdev/l2tp-tunnel.h b/src/network/netdev/l2tp-tunnel.h index 6028b35205..c558ed49de 100644 --- a/src/network/netdev/l2tp-tunnel.h +++ b/src/network/netdev/l2tp-tunnel.h @@ -37,6 +37,7 @@ typedef struct L2tpSession { ConfigSection *section; char *name; + int ifindex; uint32_t session_id; uint32_t peer_session_id; From 971c0ce85c558bfb85ef04550b6e95b52e4b5b82 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 03:01:14 +0900 Subject: [PATCH 15/18] network/vxcan: refuse when peer and the main interface names are equivalent --- src/network/netdev/vxcan.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/network/netdev/vxcan.c b/src/network/netdev/vxcan.c index c0343f45b6..c129d24734 100644 --- a/src/network/netdev/vxcan.c +++ b/src/network/netdev/vxcan.c @@ -38,6 +38,10 @@ static int netdev_vxcan_verify(NetDev *netdev, const char *filename) { return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "VxCan NetDev without peer name configured in %s. Ignoring", filename); + if (streq(v->ifname_peer, netdev->ifname)) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "VxCan peer name cannot be the same as the main interface name."); + return 0; } From d0899c6a55060a9d50d3e5e4b7fe0ba3fa715d88 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 9 Sep 2024 18:00:28 +0900 Subject: [PATCH 16/18] network/vxcan: also manage peer interface name by manager Then, the Link object for the peer interface can have a reference to the corresponding NetDev object. --- src/network/netdev/vxcan.c | 65 ++++++++++++++++++++++++++++++++++++++ src/network/netdev/vxcan.h | 1 + 2 files changed, 66 insertions(+) diff --git a/src/network/netdev/vxcan.c b/src/network/netdev/vxcan.c index c129d24734..929d70f61a 100644 --- a/src/network/netdev/vxcan.c +++ b/src/network/netdev/vxcan.c @@ -45,6 +45,67 @@ static int netdev_vxcan_verify(NetDev *netdev, const char *filename) { return 0; } +static int netdev_vxcan_attach(NetDev *netdev) { + VxCan *v = VXCAN(netdev); + assert(v->ifname_peer); + + return netdev_attach_name(netdev, v->ifname_peer); +} + +static void netdev_vxcan_detach(NetDev *netdev) { + VxCan *v = VXCAN(netdev); + + netdev_detach_name(netdev, v->ifname_peer); +} + +static int netdev_vxcan_set_ifindex(NetDev *netdev, const char *name, int ifindex) { + VxCan *v = VXCAN(netdev); + int r; + + assert(name); + assert(ifindex > 0); + + if (streq(netdev->ifname, name)) { + r = netdev_set_ifindex_internal(netdev, ifindex); + if (r <= 0) + return r; + + } else if (streq(v->ifname_peer, name)) { + if (v->ifindex_peer == ifindex) + return 0; /* already set */ + if (v->ifindex_peer > 0 && v->ifindex_peer != ifindex) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST), + "Could not set ifindex %i for peer %s, already set to %i.", + ifindex, v->ifname_peer, v->ifindex_peer); + + v->ifindex_peer = ifindex; + log_netdev_debug(netdev, "Peer interface %s gained index %i.", v->ifname_peer, ifindex); + + } else + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "Received netlink message with unexpected interface name %s (ifindex=%i).", + name, ifindex); + + if (netdev->ifindex > 0 && v->ifindex_peer > 0) + return netdev_enter_ready(netdev); + + return 0; +} + +static int netdev_vxcan_get_ifindex(NetDev *netdev, const char *name) { + VxCan *v = VXCAN(netdev); + + assert(name); + + if (streq(netdev->ifname, name)) + return netdev->ifindex; + + if (streq(v->ifname_peer, name)) + return v->ifindex_peer; + + return -ENODEV; +} + static void vxcan_done(NetDev *netdev) { VxCan *v = VXCAN(netdev); @@ -58,5 +119,9 @@ const NetDevVTable vxcan_vtable = { .fill_message_create = netdev_vxcan_fill_message_create, .create_type = NETDEV_CREATE_INDEPENDENT, .config_verify = netdev_vxcan_verify, + .attach = netdev_vxcan_attach, + .detach = netdev_vxcan_detach, + .set_ifindex = netdev_vxcan_set_ifindex, + .get_ifindex = netdev_vxcan_get_ifindex, .iftype = ARPHRD_CAN, }; diff --git a/src/network/netdev/vxcan.h b/src/network/netdev/vxcan.h index 47be3f017d..b835ce2c91 100644 --- a/src/network/netdev/vxcan.h +++ b/src/network/netdev/vxcan.h @@ -9,6 +9,7 @@ struct VxCan { NetDev meta; char *ifname_peer; + int ifindex_peer; }; DEFINE_NETDEV_CAST(VXCAN, VxCan); From f49c8e6553cc8362f8da6d17eb2a63d58476926e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 16:35:27 +0900 Subject: [PATCH 17/18] network/state-file: save assigned .netdev file even if the interface is unmanaged Follow-up for 2cf9b1a0eed7bcd85543e19ba6f0d26767fe1163. --- src/network/networkd-state-file.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-state-file.c b/src/network/networkd-state-file.c index d89097b428..481e2d930b 100644 --- a/src/network/networkd-state-file.c +++ b/src/network/networkd-state-file.c @@ -623,6 +623,12 @@ static int link_save(Link *link) { "IPV6_ADDRESS_STATE=%s\n", admin_state, oper_state, carrier_state, address_state, ipv4_address_state, ipv6_address_state); + if (link->netdev) { + r = serialize_config_files(f, "NETDEV", link->netdev->filename, link->netdev->dropins); + if (r < 0) + return r; + } + if (link->network) { const char *online_state, *captive_portal; bool space = false; @@ -650,12 +656,6 @@ static int link_save(Link *link) { if (r < 0) return r; - if (link->netdev) { - r = serialize_config_files(f, "NETDEV", link->netdev->filename, link->netdev->dropins); - if (r < 0) - return r; - } - /************************************************************/ fputs("DNS=", f); From 8f28d342465524d9d52a2b89582083d2ff200b76 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2024 16:37:55 +0900 Subject: [PATCH 18/18] test-network: add test more cases for assigned units for each interface --- test/test-network/systemd-networkd-tests.py | 135 ++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 3989fc0401..a596537ffa 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1240,6 +1240,20 @@ class Utilities(): else: self.fail(f'"{contents}" not found in journal.') + def networkctl_check_unit(self, ifname, netdev_file=None, network_file=None, link_file=None): + output = networkctl_status(ifname) + print(output) + if netdev_file: + self.assertRegex(output, rf'NetDev File: .*/{netdev_file}\.netdev') + else: + self.assertNotIn('NetDev File:', output) + if network_file: + self.assertRegex(output, rf'Network File: .*/{network_file}\.network') + else: + self.assertIn('Network File: n/a', output) + if link_file: + self.assertRegex(output, rf'Link File: .*/{link_file}\.link') + class NetworkctlTests(unittest.TestCase, Utilities): def setUp(self): @@ -1551,6 +1565,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('bareudp99:degraded') + self.networkctl_check_unit('bareudp99', '25-bareudp', '26-netdev-link-local-addressing-yes') output = check_output('ip -d link show bareudp99') print(output) @@ -1564,6 +1579,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('batadv99:degraded') + self.networkctl_check_unit('batadv99', '25-batadv', '26-netdev-link-local-addressing-yes') output = check_output('ip -d link show batadv99') print(output) @@ -1574,6 +1590,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('bridge99:no-carrier') + self.networkctl_check_unit('bridge99', '25-bridge', '25-bridge-configure-without-carrier') tick = os.sysconf('SC_CLK_TCK') self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick)) @@ -1607,6 +1624,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('bond99:off', 'bond98:off', 'bond97:off', setup_state='unmanaged') + self.networkctl_check_unit('bond99', '25-bond') + self.networkctl_check_unit('bond98', '25-bond-balanced-tlb') + self.networkctl_check_unit('bond97', '25-bond-property') self.check_link_attr('bond99', 'bonding', 'mode', '802.3ad 4') self.check_link_attr('bond99', 'bonding', 'xmit_hash_policy', 'layer3+4 1') @@ -1646,6 +1666,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() 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') output = check_output('ip -d link show test1') print(output) @@ -1680,6 +1702,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('bond99:off') self.wait_operstate('vlan99', operstate='off', setup_state='configuring', setup_timeout=10) + self.networkctl_check_unit('vlan99', '21-vlan-on-bond', '21-vlan-on-bond') + self.networkctl_check_unit('bond99', '21-bond-802.3ad', '21-bond-802.3ad') self.check_networkd_log('vlan99: Could not bring up interface, ignoring: Network is down') @@ -1705,6 +1729,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.wait_online('macvtap99:degraded', 'test1:carrier' if mode == 'passthru' else 'test1:degraded') + self.networkctl_check_unit('macvtap99', '21-macvtap', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('test1', '11-dummy', '25-macvtap') output = check_output('ip -d link show macvtap99') print(output) @@ -1729,6 +1755,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.wait_online('macvlan99:degraded', 'test1:carrier' if mode == 'passthru' else 'test1:degraded') + self.networkctl_check_unit('macvlan99', '21-macvlan', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('test1', '11-dummy', '25-macvlan') output = check_output('ip -d link show test1') print(output) @@ -1776,6 +1804,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('ipvlan99:degraded', 'test1:degraded') + self.networkctl_check_unit('ipvlan99', '25-ipvlan', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('test1', '11-dummy', '25-ipvlan') output = check_output('ip -d link show ipvlan99') print(output) @@ -1799,6 +1829,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('ipvtap99:degraded', 'test1:degraded') + self.networkctl_check_unit('ipvtap99', '25-ipvtap', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('test1', '11-dummy', '25-ipvtap') output = check_output('ip -d link show ipvtap99') print(output) @@ -1810,6 +1842,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('veth99:degraded', 'veth-peer:degraded', 'veth-mtu:degraded', 'veth-mtu-peer:degraded') + self.networkctl_check_unit('veth99', '25-veth', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('veth-peer', '25-veth', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('veth-mtu', '25-veth-mtu', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('veth-mtu-peer', '25-veth-mtu', '26-netdev-link-local-addressing-yes') output = check_output('ip -d link show veth99') print(output) @@ -1881,12 +1917,16 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): copy_network_unit('25-tun.netdev', '25-tap.netdev', '26-netdev-link-local-addressing-yes.network') start_networkd() self.wait_online('testtun99:degraded', 'testtap99:degraded') + self.networkctl_check_unit('testtap99', '25-tap', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('testtun99', '25-tun', '26-netdev-link-local-addressing-yes') self.check_tuntap(True) remove_network_unit('26-netdev-link-local-addressing-yes.network') restart_networkd() self.wait_online('testtun99:degraded', 'testtap99:degraded', setup_state='unmanaged') + self.networkctl_check_unit('testtap99', '25-tap') + self.networkctl_check_unit('testtun99', '25-tun') self.check_tuntap(True) @@ -1894,6 +1934,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): unmanage_existing_links() restart_networkd() self.wait_online('testtun99:off', 'testtap99:off', setup_state='unmanaged') + self.networkctl_check_unit('testtap99') + self.networkctl_check_unit('testtun99') self.check_tuntap(False) @@ -1903,6 +1945,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('vrf99:carrier') + self.networkctl_check_unit('vrf99', '25-vrf', '26-netdev-link-local-addressing-yes') @expectedFailureIfModuleIsNotAvailable('vcan') def test_vcan(self): @@ -1913,6 +1956,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.wait_online('vcan99:carrier', 'vcan98:carrier') # For can devices, 'carrier' is the default required operational state. self.wait_online('vcan99', 'vcan98') + self.networkctl_check_unit('vcan99', '25-vcan', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('vcan98', '25-vcan98', '25-vcan98') # https://github.com/systemd/systemd/issues/30140 output = check_output('ip -d link show vcan99') @@ -1931,6 +1976,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.wait_online('vxcan99:carrier', 'vxcan-peer:carrier') # For can devices, 'carrier' is the default required operational state. self.wait_online('vxcan99', 'vxcan-peer') + self.networkctl_check_unit('vxcan99', '25-vxcan', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('vxcan-peer', '25-vxcan', '26-netdev-link-local-addressing-yes') @expectedFailureIfModuleIsNotAvailable('wireguard') def test_wireguard(self): @@ -1944,6 +1991,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network') start_networkd() self.wait_online('wg99:routable', 'wg98:routable', 'wg97:carrier') + self.networkctl_check_unit('wg99', '25-wireguard', '25-wireguard') + self.networkctl_check_unit('wg98', '25-wireguard-23-peers', '25-wireguard-23-peers') + self.networkctl_check_unit('wg97', '25-wireguard-no-peer', '25-wireguard-no-peer') output = check_output('ip -4 address show dev wg99') print(output) @@ -2065,6 +2115,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('geneve99:degraded') + self.networkctl_check_unit('geneve99', '25-geneve', '26-netdev-link-local-addressing-yes') output = check_output('ip -d link show geneve99') print(output) @@ -2103,6 +2154,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network') start_networkd() self.wait_online('gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded') + self.networkctl_check_unit('gretun99', '25-gre-tunnel', '25-tunnel') + self.networkctl_check_unit('gretun98', '25-gre-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('gretun97', '25-gre-tunnel-remote-any', '25-tunnel-remote-any') + self.networkctl_check_unit('gretun96', '25-gre-tunnel-any-any', '25-tunnel-any-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-gretun') output = check_output('ip -d link show gretun99') print(output) @@ -2164,6 +2220,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network') start_networkd() self.wait_online('gretap99:routable', 'gretap98:routable', 'dummy98:degraded') + self.networkctl_check_unit('gretap99', '25-gretap-tunnel', '25-tunnel') + self.networkctl_check_unit('gretap98', '25-gretap-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-gretap') output = check_output('ip -d link show gretap99') print(output) @@ -2188,6 +2247,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network') start_networkd() self.wait_online('ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded') + self.networkctl_check_unit('ip6gretap99', '25-ip6gretap-tunnel', '25-tunnel') + self.networkctl_check_unit('ip6gretap98', '25-ip6gretap-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-ip6gretap') output = check_output('ip -d link show ip6gretap99') print(output) @@ -2204,6 +2266,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network') start_networkd() self.wait_online('vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded') + self.networkctl_check_unit('vtitun99', '25-vti-tunnel', '25-tunnel') + self.networkctl_check_unit('vtitun98', '25-vti-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('vtitun97', '25-vti-tunnel-remote-any', '25-tunnel-remote-any') + self.networkctl_check_unit('vtitun96', '25-vti-tunnel-any-any', '25-tunnel-any-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-vti') output = check_output('ip -d link show vtitun99') print(output) @@ -2225,6 +2292,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network') start_networkd() self.wait_online('vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded') + self.networkctl_check_unit('vti6tun99', '25-vti6-tunnel', '25-tunnel') + self.networkctl_check_unit('vti6tun98', '25-vti6-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('vti6tun97', '25-vti6-tunnel-remote-any', '25-tunnel-remote-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-vti6') output = check_output('ip -d link show vti6tun99') print(output) @@ -2248,6 +2319,14 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.wait_online('ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'ip6tnl-slaac:degraded', 'ip6tnl-external:degraded', 'dummy98:degraded', 'veth99:routable', 'veth-peer:degraded') + self.networkctl_check_unit('ip6tnl99', '25-ip6tnl-tunnel', '25-tunnel') + self.networkctl_check_unit('ip6tnl98', '25-ip6tnl-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('ip6tnl97', '25-ip6tnl-tunnel-remote-any', '25-tunnel-remote-any') + self.networkctl_check_unit('ip6tnl-slaac', '25-ip6tnl-tunnel-local-slaac', '25-ip6tnl-tunnel-local-slaac') + self.networkctl_check_unit('ip6tnl-external', '25-ip6tnl-tunnel-external', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('dummy98', '12-dummy', '25-ip6tnl') + self.networkctl_check_unit('veth99', '25-veth', '25-ip6tnl-slaac') + self.networkctl_check_unit('veth-peer', '25-veth', '25-ipv6-prefix') output = check_output('ip -d link show ip6tnl99') print(output) @@ -2282,6 +2361,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network') start_networkd() self.wait_online('sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded') + self.networkctl_check_unit('sittun99', '25-sit-tunnel', '25-tunnel') + self.networkctl_check_unit('sittun98', '25-sit-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('sittun97', '25-sit-tunnel-remote-any', '25-tunnel-remote-any') + self.networkctl_check_unit('sittun96', '25-sit-tunnel-any-any', '25-tunnel-any-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-sit') output = check_output('ip -d link show sittun99') print(output) @@ -2301,6 +2385,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-isatap-tunnel.netdev', '25-tunnel.network') start_networkd() self.wait_online('isataptun99:routable', 'dummy98:degraded') + self.networkctl_check_unit('isataptun99', '25-isatap-tunnel', '25-tunnel') + self.networkctl_check_unit('dummy98', '12-dummy', '25-isatap') output = check_output('ip -d link show isataptun99') print(output) @@ -2311,6 +2397,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-6rd-tunnel.netdev', '25-tunnel.network') start_networkd() self.wait_online('sittun99:routable', 'dummy98:degraded') + self.networkctl_check_unit('sittun99', '25-6rd-tunnel', '25-tunnel') + self.networkctl_check_unit('dummy98', '12-dummy', '25-6rd') output = check_output('ip -d link show sittun99') print(output) @@ -2323,6 +2411,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-erspan0-tunnel-local-any.netdev', '25-tunnel-local-any.network') start_networkd() self.wait_online('erspan99:routable', 'erspan98:routable', 'dummy98:degraded') + self.networkctl_check_unit('erspan99', '25-erspan0-tunnel', '25-tunnel') + self.networkctl_check_unit('erspan98', '25-erspan0-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-erspan') output = check_output('ip -d link show erspan99') print(output) @@ -2351,6 +2442,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-erspan1-tunnel-local-any.netdev', '25-tunnel-local-any.network') start_networkd() self.wait_online('erspan99:routable', 'erspan98:routable', 'dummy98:degraded') + self.networkctl_check_unit('erspan99', '25-erspan1-tunnel', '25-tunnel') + self.networkctl_check_unit('erspan98', '25-erspan1-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-erspan') output = check_output('ip -d link show erspan99') print(output) @@ -2382,6 +2476,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-erspan2-tunnel-local-any.netdev', '25-tunnel-local-any.network') start_networkd() self.wait_online('erspan99:routable', 'erspan98:routable', 'dummy98:degraded') + self.networkctl_check_unit('erspan99', '25-erspan2-tunnel', '25-tunnel') + self.networkctl_check_unit('erspan98', '25-erspan2-tunnel-local-any', '25-tunnel-local-any') + self.networkctl_check_unit('dummy98', '12-dummy', '25-erspan') output = check_output('ip -d link show erspan99') print(output) @@ -2411,12 +2508,14 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('ipiptun99:carrier') + self.networkctl_check_unit('ipiptun99', '25-ipip-tunnel-independent', '26-netdev-link-local-addressing-yes') def test_tunnel_independent_loopback(self): copy_network_unit('25-ipip-tunnel-independent-loopback.netdev', '26-netdev-link-local-addressing-yes.network') start_networkd() self.wait_online('ipiptun99:carrier') + self.networkctl_check_unit('ipiptun99', '25-ipip-tunnel-independent-loopback', '26-netdev-link-local-addressing-yes') @expectedFailureIfModuleIsNotAvailable('xfrm_interface') def test_xfrm(self): @@ -2426,6 +2525,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('dummy98:degraded', 'xfrm98:degraded', 'xfrm99:degraded') + self.networkctl_check_unit('dummy98', '12-dummy', '25-xfrm') + self.networkctl_check_unit('xfrm98', '25-xfrm', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('xfrm99', '25-xfrm-independent', '26-netdev-link-local-addressing-yes') output = check_output('ip -d link show dev xfrm98') print(output) @@ -2449,6 +2551,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off', setup_state='unmanaged') + self.networkctl_check_unit('ipiptun96', '25-fou-ipip') + self.networkctl_check_unit('sittun96', '25-fou-sit') + self.networkctl_check_unit('gretun96', '25-fou-gre') + self.networkctl_check_unit('gretap96', '25-fou-gretap') output = check_output('ip fou show') print(output) @@ -2479,6 +2585,13 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.wait_online('test1:degraded', 'veth99:routable', 'veth-peer:degraded', 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded', 'vxlan-slaac:degraded') + self.networkctl_check_unit('test1', '11-dummy', '25-vxlan-test1') + self.networkctl_check_unit('veth99', '25-veth', '25-vxlan-veth99') + self.networkctl_check_unit('veth-peer', '25-veth', '25-ipv6-prefix') + self.networkctl_check_unit('vxlan99', '25-vxlan', '25-vxlan') + self.networkctl_check_unit('vxlan98', '25-vxlan-independent', '26-netdev-link-local-addressing-yes') + self.networkctl_check_unit('vxlan97', '25-vxlan-ipv6', '25-vxlan-ipv6') + self.networkctl_check_unit('vxlan-slaac', '25-vxlan-local-slaac', '25-vxlan-local-slaac') output = check_output('ip -d -d link show vxlan99') print(output) @@ -2530,6 +2643,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('dummy98:degraded', 'macsec99:routable') + self.networkctl_check_unit('dummy98', '12-dummy', '26-macsec') + self.networkctl_check_unit('macsec99', '25-macsec', '25-macsec') output = check_output('ip -d link show macsec99') print(output) @@ -2557,6 +2672,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('nlmon99:carrier') + self.networkctl_check_unit('nlmon99', '25-nlmon', '26-netdev-link-local-addressing-yes') @expectedFailureIfModuleIsNotAvailable('ifb') def test_ifb(self): @@ -2564,6 +2680,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('ifb99:degraded') + self.networkctl_check_unit('ifb99', '25-ifb', '26-netdev-link-local-addressing-yes') @unittest.skipUnless(os.cpu_count() >= 2, reason="CPU count should be >= 2 to pass this test") def test_rps_cpu_1(self): @@ -2571,6 +2688,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('dummy98:carrier') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-1') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) @@ -2582,6 +2700,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('dummy98:carrier') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-0-1') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) @@ -2593,6 +2712,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('dummy98:carrier') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-multi') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) @@ -2605,10 +2725,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('dummy98:carrier') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy') # 0 copy_network_unit('25-rps-cpu-0.link') udevadm_trigger('/sys/class/net/dummy98') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-0') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) self.assertEqual(int(output.replace(',', ''), base=16), 1) @@ -2617,6 +2739,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): # all copy_network_unit('25-rps-cpu-all.link') udevadm_trigger('/sys/class/net/dummy98') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-all') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) self.assertEqual(f"{int(output.replace(',', ''), base=16):x}", f'{(1 << cpu_count) - 1:x}') @@ -2625,6 +2748,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): # disable copy_network_unit('24-rps-cpu-disable.link') udevadm_trigger('/sys/class/net/dummy98') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '24-rps-cpu-disable') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) self.assertEqual(int(output.replace(',', ''), base=16), 0) @@ -2633,6 +2757,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): # set all again copy_network_unit('25-rps-cpu-all.link') udevadm_trigger('/sys/class/net/dummy98') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-all') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) self.assertEqual(f"{int(output.replace(',', ''), base=16):x}", f'{(1 << cpu_count) - 1:x}') @@ -2641,6 +2766,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): # empty -> unchanged copy_network_unit('24-rps-cpu-empty.link') udevadm_trigger('/sys/class/net/dummy98') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '24-rps-cpu-empty') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) self.assertEqual(f"{int(output.replace(',', ''), base=16):x}", f'{(1 << cpu_count) - 1:x}') @@ -2649,6 +2775,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): # 0, then empty -> unchanged copy_network_unit('25-rps-cpu-0-empty.link') udevadm_trigger('/sys/class/net/dummy98') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-0-empty') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) self.assertEqual(f"{int(output.replace(',', ''), base=16):x}", f'{(1 << cpu_count) - 1:x}') @@ -2657,6 +2784,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): # 0, then invalid -> 0 copy_network_unit('25-rps-cpu-0-invalid.link') udevadm_trigger('/sys/class/net/dummy98') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-0-invalid') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) self.assertEqual(int(output.replace(',', ''), base=16), 1) @@ -2665,6 +2793,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): # invalid -> unchanged copy_network_unit('24-rps-cpu-invalid.link') udevadm_trigger('/sys/class/net/dummy98') + self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '24-rps-cpu-invalid') output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus') print(output) self.assertEqual(int(output.replace(',', ''), base=16), 1) @@ -2685,6 +2814,9 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded') + self.networkctl_check_unit('test1', '11-dummy', '25-l2tp-dummy') + self.networkctl_check_unit('l2tp-ses1', '25-l2tp-udp', '25-l2tp') + self.networkctl_check_unit('l2tp-ses2', '25-l2tp-udp', '25-l2tp') output = check_output('ip l2tp show tunnel tunnel_id 10') print(output) @@ -2713,6 +2845,9 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities): start_networkd() self.wait_online('test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded') + self.networkctl_check_unit('test1', '11-dummy', '25-l2tp-dummy') + self.networkctl_check_unit('l2tp-ses3', '25-l2tp-ip', '25-l2tp') + self.networkctl_check_unit('l2tp-ses4', '25-l2tp-ip', '25-l2tp') output = check_output('ip l2tp show tunnel tunnel_id 10') print(output)