From 2bb7fe554f29c9b790708665d9372724594d691e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 16 Sep 2024 02:36:13 +0900 Subject: [PATCH 1/2] network: introduce link_up_now() This is currently not used. Preparation for later commit. --- src/network/networkd-setlink.c | 21 +++++++++++++++------ src/network/networkd-setlink.h | 9 ++++++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 8519e6e7a0..8ef523dfdc 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -1211,7 +1211,7 @@ int link_request_to_bring_up_or_down(Link *link, bool up) { return 0; } -static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int link_up_or_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *msg) { int r; assert(m); @@ -1225,7 +1225,7 @@ static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * r = sd_netlink_message_get_errno(m); if (r < 0) - log_link_message_warning_errno(link, m, r, "Could not bring down interface, ignoring"); + log_link_message_warning_errno(link, m, r, msg); r = link_call_getlink(link, get_link_update_flag_handler); if (r < 0) { @@ -1237,7 +1237,15 @@ static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * return 0; } -int link_down_now(Link *link) { +static int link_up_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + return link_up_or_down_now_handler(rtnl, m, link, "Could not bring up interface, ignoring"); +} + +static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + return link_up_or_down_now_handler(rtnl, m, link, "Could not bring down interface, ignoring"); +} + +int link_up_or_down_now(Link *link, bool up) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -1245,17 +1253,18 @@ int link_down_now(Link *link) { assert(link->manager); assert(link->manager->rtnl); - log_link_debug(link, "Bringing link down"); + log_link_debug(link, "Bringing link %s", up ? "up" : "down"); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) return log_link_warning_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); - r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP); + r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP); if (r < 0) return log_link_warning_errno(link, r, "Could not set link flags: %m"); - r = netlink_call_async(link->manager->rtnl, NULL, req, link_down_now_handler, + r = netlink_call_async(link->manager->rtnl, NULL, req, + up ? link_up_now_handler : link_down_now_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h index 841e5eeb9c..df617f2167 100644 --- a/src/network/networkd-setlink.h +++ b/src/network/networkd-setlink.h @@ -24,6 +24,13 @@ int link_request_to_activate(Link *link); int link_request_to_bring_up_or_down(Link *link, bool up); -int link_down_now(Link *link); +int link_up_or_down_now(Link *link, bool up); +static inline int link_up_now(Link *link) { + return link_up_or_down_now(link, true); +} +static inline int link_down_now(Link *link) { + return link_up_or_down_now(link, false); +} + int link_down_slave_links(Link *link); int link_remove(Link *link); From 2dfde4b8f819588f4fda92925fa4520f40238ac2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 16 Sep 2024 02:36:13 +0900 Subject: [PATCH 2/2] network: optionally bring up interface before joining bridge Closes #34247. --- rules.d/81-net-bridge.rules | 16 ++++++++++++++++ rules.d/meson.build | 1 + src/network/networkd-setlink.c | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 rules.d/81-net-bridge.rules diff --git a/rules.d/81-net-bridge.rules b/rules.d/81-net-bridge.rules new file mode 100644 index 0000000000..defb31fe31 --- /dev/null +++ b/rules.d/81-net-bridge.rules @@ -0,0 +1,16 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="net_bridge_end" +SUBSYSTEM!="net", GOTO="net_bridge_end" + +# Some devices require the port to be up before joining the bridge. +# In such cases, set ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE to "1". + +# Texas Instruments Ethernet device with switchdev mode: +# https://docs.kernel.org/networking/device_drivers/ethernet/ti/am65_nuss_cpsw_switchdev.html#enabling-switch +ENV{ID_NET_DRIVER}=="am65-cpsw-nuss", SUBSYSTEMS=="platform", DRIVERS=="am65-cpsw-nuss", \ + PROGRAM="/usr/sbin/devlink dev param show platform/%b name switch_mode", \ + RESULT=="*cmode runtime value true*", \ + ENV{ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE}="1" + +LABEL="net_bridge_end" diff --git a/rules.d/meson.build b/rules.d/meson.build index 3040fae8a4..61165fd86f 100644 --- a/rules.d/meson.build +++ b/rules.d/meson.build @@ -29,6 +29,7 @@ rules = [ '75-probe_mtd.rules', '78-sound-card.rules', '80-net-setup-link.rules', + '81-net-bridge.rules', '81-net-dhcp.rules', '90-iocost.rules', )], diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 8ef523dfdc..467fadb3ea 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -6,6 +6,7 @@ #include #include +#include "device-private.h" #include "missing_network.h" #include "netif-util.h" #include "netlink-util.h" @@ -581,6 +582,25 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { return r; } + if (link->network->bridge && !FLAGS_SET(link->flags, IFF_UP) && link->dev) { + /* Some devices require the port to be up before joining the bridge. + * + * E.g. Texas Instruments SoC Ethernet running in switch mode: + * https://docs.kernel.org/networking/device_drivers/ethernet/ti/am65_nuss_cpsw_switchdev.html#enabling-switch + * > Port’s netdev devices have to be in UP before joining to the bridge to avoid + * > overwriting of bridge configuration as CPSW switch driver completely reloads its + * > configuration when first port changes its state to UP. */ + + r = device_get_property_bool(link->dev, "ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE"); + if (r < 0 && r != -ENOENT) + log_link_warning_errno(link, r, "Failed to get or parse ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE property, ignoring: %m"); + else if (r > 0) { + r = link_up_now(link); + if (r < 0) + return r; + } + } + req->userdata = UINT32_TO_PTR(m); break; }