From 034b69d8b8fb28305bd4c8fb6ad68d63c259af3e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Feb 2025 04:54:50 +0900 Subject: [PATCH 1/8] network: assume nexthop is supported by the kernel It is supported since kernel v5.3 (65ee00a9409f751188a8cdc0988167858eb4a536), but our base line is now v5.4. --- README | 3 ++- src/network/networkd-manager.c | 6 +----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/README b/README index 02a3e39052..2f89fffe0b 100644 --- a/README +++ b/README @@ -42,7 +42,8 @@ REQUIREMENTS: ≥ 4.17 for cgroup-bpf socket address hooks and /sys/power/resume_offset ≥ 4.20 for PSI (used by systemd-oomd) ≥ 5.2 for cgroup freezer and new mount API - ≥ 5.3 for bounded loops in BPF program and keyring namespacing + ≥ 5.3 for bounded loops in BPF program, keyring namespacing, + and nexthop support ≥ 5.4 for pidfd and signed Verity images ⛔ Kernel versions below 5.4 ("minimum baseline") are not supported at all, diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 1592e258ec..d2e81415c1 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1069,12 +1069,8 @@ int manager_enumerate(Manager *m) { if (r < 0) return log_error_errno(r, "Could not enumerate neighbors: %m"); - /* NextHop support is added in kernel v5.3 (65ee00a9409f751188a8cdc0988167858eb4a536), - * and older kernels return -EOPNOTSUPP, or -EINVAL if SELinux is enabled. */ r = manager_enumerate_nexthop(m); - if (r == -EOPNOTSUPP || (r == -EINVAL && mac_selinux_enforcing())) - log_debug_errno(r, "Could not enumerate nexthops, ignoring: %m"); - else if (r < 0) + if (r < 0) return log_error_errno(r, "Could not enumerate nexthops: %m"); r = manager_enumerate_routes(m); From 6698795edaf68f99354cf73d04307e1e2f4598c0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Feb 2025 05:09:14 +0900 Subject: [PATCH 2/8] network: add/update comments about required kernel configs --- 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 d2e81415c1..c2625d548b 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -277,6 +277,7 @@ static int manager_connect_genl(Manager *m) { if (r < 0) return r; + /* If the kernel is built without CONFIG_WIRELESS, the belows will fail with -EOPNOTSUPP. */ r = genl_add_match(m->genl, NULL, NL80211_GENL_NAME, NL80211_MULTICAST_GROUP_CONFIG, 0, &manager_genl_process_nl80211_config, NULL, m, "network-genl_process_nl80211_config"); if (r < 0 && r != -EOPNOTSUPP) @@ -1049,12 +1050,14 @@ int manager_enumerate(Manager *m) { if (r < 0) return log_error_errno(r, "Could not enumerate links: %m"); + /* If the kernel is built without CONFIG_NET_SCHED, the below will fail with -EOPNOTSUPP. */ r = manager_enumerate_qdisc(m); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not enumerate QDiscs, ignoring: %m"); else if (r < 0) return log_error_errno(r, "Could not enumerate QDisc: %m"); + /* If the kernel is built without CONFIG_NET_CLS, the below will fail with -EOPNOTSUPP. */ r = manager_enumerate_tclass(m); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not enumerate TClasses, ignoring: %m"); @@ -1077,13 +1080,14 @@ int manager_enumerate(Manager *m) { if (r < 0) return log_error_errno(r, "Could not enumerate routes: %m"); - /* If kernel is built with CONFIG_FIB_RULES=n, it returns -EOPNOTSUPP. */ + /* If the kernel is built without CONFIG_FIB_RULES, the below will fail with -EOPNOTSUPP. */ r = manager_enumerate_rules(m); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not enumerate routing policy rules, ignoring: %m"); else if (r < 0) return log_error_errno(r, "Could not enumerate routing policy rules: %m"); + /* If the kernel is built without CONFIG_WIRELESS, the belows will fail with -EOPNOTSUPP. */ r = manager_enumerate_nl80211_wiphy(m); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not enumerate wireless LAN phy, ignoring: %m"); From 49625caaa911eee439b3c0cf86f099326911554b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Feb 2025 05:26:25 +0900 Subject: [PATCH 3/8] network/routing-policy-rule: assume FRA_PROTOCOL attribute is always set Since kernel v4.17 (1b71af6053af1bd2f849e9fda4f71c1e3f145dcf), the attribute is always set in each netlink message for routing policy rule. Now, our base line is v5.4. Hence, we can drop the workaround. --- README | 3 +- src/network/networkd-routing-policy-rule.c | 32 ++-------------------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/README b/README index 2f89fffe0b..346f1aad42 100644 --- a/README +++ b/README @@ -39,7 +39,8 @@ REQUIREMENTS: ≥ 4.11 for nsfs NS_GET_NSTYPE ≥ 4.13 for TIOCGPTPEER ≥ 4.15 for cgroup-bpf device hook and cpu controller in cgroup v2 - ≥ 4.17 for cgroup-bpf socket address hooks and /sys/power/resume_offset + ≥ 4.17 for cgroup-bpf socket address hooks, /sys/power/resume_offset, + and FRA_PROTOCOL attribute for fib rules ≥ 4.20 for PSI (used by systemd-oomd) ≥ 5.2 for cgroup freezer and new mount API ≥ 5.3 for bounded loops in BPF program, keyring namespacing, diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 2cac730a41..9811f60dcb 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -1059,26 +1059,6 @@ int link_request_static_routing_policy_rules(Link *link) { return 0; } -static const RoutingPolicyRule kernel_rules[] = { - { .family = AF_INET, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, - { .family = AF_INET, .priority_set = true, .priority = 1000, .table = RT_TABLE_UNSPEC, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, .l3mdev = true }, - { .family = AF_INET, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, - { .family = AF_INET, .priority_set = true, .priority = 32767, .table = RT_TABLE_DEFAULT, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, - { .family = AF_INET6, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, - { .family = AF_INET6, .priority_set = true, .priority = 1000, .table = RT_TABLE_UNSPEC, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, .l3mdev = true }, - { .family = AF_INET6, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, -}; - -static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule *rule) { - assert(rule); - - FOREACH_ELEMENT(i, kernel_rules) - if (routing_policy_rule_equal(rule, i, i->family, i->priority)) - return true; - - return false; -} - int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { int r; @@ -1258,16 +1238,10 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man return 0; } - /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended. If the received - * message does not have FRA_PROTOCOL, then we need to adjust the protocol of the rule. That requires - * all properties compared in the routing_policy_rule_compare_func(), hence it must be done after - * reading them. */ + /* The kernel always sets the FRA_PROTOCOL attribute, and it is necessary for comparing rules. + * Hence, -ENODATA here is critical. */ r = sd_netlink_message_read_u8(message, FRA_PROTOCOL, &tmp->protocol); - if (r == -ENODATA) - /* As .network files does not have setting to specify protocol, we can assume the - * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */ - tmp->protocol = routing_policy_rule_is_created_by_kernel(tmp) ? RTPROT_KERNEL : RTPROT_STATIC; - else if (r < 0) { + if (r < 0) { log_warning_errno(r, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m"); return 0; } From 0d73214cae1082852f91bbb087f2e8722538302c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Feb 2025 05:38:20 +0900 Subject: [PATCH 4/8] network: mention IFLA_PERM_ADDRESS is since kernel v5.6 --- src/network/networkd-link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 67fc725f98..14cf7197bb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2321,7 +2321,7 @@ static int link_update_permanent_hardware_address(Link *link, sd_netlink_message if (r != -ENODATA) return log_link_debug_errno(link, r, "Failed to read IFLA_PERM_ADDRESS attribute: %m"); - /* Fallback to ethtool for older kernels. */ + /* Fallback to ethtool for kernels older than v5.6 (f74877a5457d34d604dba6dbbb13c4c05bac8b93). */ r = link_update_permanent_hardware_address_from_ethtool(link, message); if (r < 0) return r; From 7d1a8da71968d0b41a40d815332e0f764cf597f1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Feb 2025 05:40:56 +0900 Subject: [PATCH 5/8] network/bridge-mdb: drop workaround for MDB entry on bridge Our kernel base line is now v5.4. --- src/network/networkd-bridge-mdb.c | 8 +------- src/network/networkd-manager.h | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index 358ca4d294..80ef3c1458 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -90,13 +90,7 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, assert(link); r = sd_netlink_message_get_errno(m); - if (r == -EINVAL && streq_ptr(link->kind, "bridge") && link->master_ifindex <= 0) { - /* To configure bridge MDB entries on bridge master, 1bc844ee0faa1b92e3ede00bdd948021c78d7088 (v5.4) is required. */ - if (!link->manager->bridge_mdb_on_master_not_supported) { - log_link_warning_errno(link, r, "Kernel seems not to support bridge MDB entries on bridge master, ignoring: %m"); - link->manager->bridge_mdb_on_master_not_supported = true; - } - } else if (r < 0 && r != -EEXIST) { + if (r < 0 && r != -EEXIST) { log_link_message_warning_errno(link, m, r, "Could not add MDB entry"); link_enter_failed(link); return 1; diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 9891b8c1fc..59e07748c6 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -118,8 +118,6 @@ struct Manager { usec_t speed_meter_usec_new; usec_t speed_meter_usec_old; - bool bridge_mdb_on_master_not_supported; - FirewallContext *fw_ctx; bool request_queued; From 29c2d4e1587e03a4d7589d045b81f7bea91c283e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Feb 2025 06:03:38 +0900 Subject: [PATCH 6/8] network/address: IFA_FLAGS is supported since kernel v3.14 Our kernel base line is now v5.4. --- src/network/networkd-address.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index d0f0282075..3857aad047 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1148,7 +1148,6 @@ static void address_forget(Link *link, Address *address, bool removed_by_us, con } static int address_set_netlink_message(const Address *address, sd_netlink_message *m, Link *link) { - uint32_t flags; int r; assert(address); @@ -1163,12 +1162,8 @@ static int address_set_netlink_message(const Address *address, sd_netlink_messag * flags except tentative flag here unconditionally. Without setting the flag, the template * addresses generated by kernel will not be removed automatically when the main address is * removed. */ - flags = address->flags & ~IFA_F_TENTATIVE; - r = sd_rtnl_message_addr_set_flags(m, flags & 0xff); - if (r < 0) - return r; - - if ((flags & ~0xff) != 0) { + uint32_t flags = address->flags & ~IFA_F_TENTATIVE; + if (flags != 0) { r = sd_netlink_message_append_u32(m, IFA_FLAGS, flags); if (r < 0) return r; @@ -1339,7 +1334,7 @@ int link_drop_ipv6ll_addresses(Link *link) { for (sd_netlink_message *addr = reply; addr; addr = sd_netlink_message_next(addr)) { _cleanup_(address_unrefp) Address *a = NULL; - unsigned char flags, prefixlen; + unsigned char prefixlen; struct in6_addr address; int ifindex; @@ -1352,9 +1347,10 @@ int link_drop_ipv6ll_addresses(Link *link) { } else if (link->ifindex != ifindex) continue; - r = sd_rtnl_message_addr_get_flags(addr, &flags); + uint32_t flags; + r = sd_netlink_message_read_u32(addr, IFA_FLAGS, &flags); if (r < 0) { - log_link_debug_errno(link, r, "rtnl: received address message without valid flags, ignoring: %m"); + log_link_debug_errno(link, r, "rtnl: Failed to read IFA_FLAGS attribute, ignoring: %m"); continue; } @@ -1971,14 +1967,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, } r = sd_netlink_message_read_u32(message, IFA_FLAGS, &address->flags); - if (r == -ENODATA) { - unsigned char flags; - - /* For old kernels. */ - r = sd_rtnl_message_addr_get_flags(message, &flags); - if (r >= 0) - address->flags = flags; - } else if (r < 0) + if (r < 0) log_link_debug_errno(link, r, "rtnl: failed to read IFA_FLAGS attribute, ignoring: %m"); struct ifa_cacheinfo cinfo; From eb381e65f1dbdb17a7d76f1850fcacfea4b329d1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Feb 2025 06:04:46 +0900 Subject: [PATCH 7/8] network/address: update comment As commented in the code, the check is now redundant. But let's keep that to make IPv6LL addresses on other interfaces not removed accidentally. --- src/network/networkd-address.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 3857aad047..d35d2ed521 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1338,8 +1338,8 @@ int link_drop_ipv6ll_addresses(Link *link) { struct in6_addr address; int ifindex; - /* NETLINK_GET_STRICT_CHK socket option is supported since kernel 4.20. To support - * older kernels, we need to check ifindex here. */ + /* We set ifindex in the request, and NETLINK_GET_STRICT_CHK socket option is set. Hence the + * check below is redundant, but let's do that for safety. */ r = sd_rtnl_message_addr_get_ifindex(addr, &ifindex); if (r < 0) { log_link_debug_errno(link, r, "rtnl: received address message without valid ifindex, ignoring: %m"); From f9c03297c5ad84439c519ab700cfdbc09f1b7790 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Feb 2025 06:16:26 +0900 Subject: [PATCH 8/8] network: update outdated comment Now, our kernel base line supports ambient capabilities, hence the comment is outdated. --- src/network/networkd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/network/networkd.c b/src/network/networkd.c index 883f16d81b..2e1b242da2 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -70,9 +70,8 @@ static int run(int argc, char *argv[]) { return log_error_errno(r, "Failed to drop privileges: %m"); } - /* Always create the directories people can create inotify watches in. - * It is necessary to create the following subdirectories after drop_privileges() - * to support old kernels not supporting AmbientCapabilities=. */ + /* Always create the directories people can create inotify watches in. It is necessary to create the + * following subdirectories after drop_privileges() to make them owned by systemd-network. */ FOREACH_STRING(p, "/run/systemd/netif/links/", "/run/systemd/netif/leases/") {