Compare commits

...

2 Commits

4 changed files with 57 additions and 7 deletions

View File

@ -0,0 +1,13 @@
# 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 is up before joining the bridge.
# In such cases, ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE to "1".
# Texas Instruments Ethernet device with switchdev mode
# https://software-dl.ti.com/jacinto7/esd/processor-sdk-linux-j721s2/latest/exports/docs/linux/Foundational_Components/Kernel/Kernel_Drivers/Network/CPSWng-Native-Ethernet.html#switch-mode
ENV{ID_NET_DRIVER}=="am65-cpsw-nuss", ENV{ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE}="1"
LABEL="net_bridge_end"

View File

@ -29,6 +29,7 @@ rules = [
'75-probe_mtd.rules', '75-probe_mtd.rules',
'78-sound-card.rules', '78-sound-card.rules',
'80-net-setup-link.rules', '80-net-setup-link.rules',
'81-net-bridge.rules',
'81-net-dhcp.rules', '81-net-dhcp.rules',
'90-iocost.rules', '90-iocost.rules',
)], )],

View File

@ -6,6 +6,7 @@
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include "device-private.h"
#include "missing_network.h" #include "missing_network.h"
#include "netif-util.h" #include "netif-util.h"
#include "netlink-util.h" #include "netlink-util.h"
@ -585,6 +586,25 @@ static int link_is_ready_to_set_link(Link *link, Request *req) {
return r; return r;
} }
if (link->network->bridge && !FLAGS_SET(link->flags, IFF_UP) && link->dev) {
/* Some devices require the port is up before joining the bridge.
*
* E.g. Texas Instruments SoC Ethernet running in switch mode:
* https://software-dl.ti.com/jacinto7/esd/processor-sdk-linux-j721s2/latest/exports/docs/linux/Foundational_Components/Kernel/Kernel_Drivers/Network/CPSWng-Native-Ethernet.html#switch-mode
* > Ports netdev devices have to be in UP state before joining the bridge. This is
* > 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); req->userdata = UINT32_TO_PTR(m);
break; break;
} }
@ -1215,7 +1235,7 @@ int link_request_to_bring_up_or_down(Link *link, bool up) {
return 0; 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; int r;
assert(m); assert(m);
@ -1229,7 +1249,7 @@ static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0) 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); r = link_call_getlink(link, get_link_update_flag_handler);
if (r < 0) { if (r < 0) {
@ -1241,7 +1261,15 @@ static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
return 0; 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; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r; int r;
@ -1249,17 +1277,18 @@ int link_down_now(Link *link) {
assert(link->manager); assert(link->manager);
assert(link->manager->rtnl); 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); r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); 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) if (r < 0)
return log_link_warning_errno(link, r, "Could not set link flags: %m"); 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); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m");

View File

@ -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_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_down_slave_links(Link *link);
int link_remove(Link *link); int link_remove(Link *link);