diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 4ab003280a..4194dcb1bb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1157,6 +1157,11 @@ void link_check_ready(Link *link) { return; } + if (!link->bridge_mdb_configured) { + log_link_debug(link, "%s(): Bridge MDB is not configured.", __func__); + return; + } + if (link_has_carrier(link) || !link->network->configure_without_carrier) { bool has_ndisc_address = false; NDiscAddress *n; @@ -1254,22 +1259,6 @@ static int link_set_bridge_fdb(Link *link) { return 0; } -static int link_set_bridge_mdb(Link *link) { - MdbEntry *mdb_entry; - int r; - - if (!link->network) - return 0; - - LIST_FOREACH(static_mdb_entries, mdb_entry, link->network->static_mdb_entries) { - r = mdb_entry_configure(link, mdb_entry); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add entry to multicast group database: %m"); - } - - return 0; -} - static int static_address_ready_callback(Address *address) { Address *a; Link *link; @@ -1402,6 +1391,10 @@ static int link_request_set_addresses(Link *link) { if (r < 0) return r; + r = link_set_bridge_mdb(link); + if (r < 0) + return r; + r = link_request_set_neighbors(link); if (r < 0) return r; @@ -3923,9 +3916,24 @@ static int link_carrier_gained(Link *link) { if (r < 0) return r; - r = link_set_bridge_mdb(link); - if (r < 0) - return r; + if (!link->bridge_mdb_configured) { + r = link_set_bridge_mdb(link); + if (r < 0) + return r; + } + + if (streq_ptr(link->kind, "bridge")) { + Link *slave; + + SET_FOREACH(slave, link->slaves) { + if (slave->bridge_mdb_configured) + continue; + + r = link_set_bridge_mdb(slave); + if (r < 0) + link_enter_failed(slave); + } + } return 0; } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index a0c5661149..1550db8a23 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -85,6 +85,7 @@ typedef struct Link { unsigned tc_messages; unsigned sr_iov_messages; unsigned enslaving; + unsigned bridge_mdb_messages; Set *addresses; Set *addresses_foreign; @@ -124,6 +125,7 @@ typedef struct Link { bool setting_mtu:1; bool setting_genmode:1; bool ipv6_mtu_set:1; + bool bridge_mdb_configured:1; LIST_HEAD(Address, pool_addresses); diff --git a/src/network/networkd-mdb.c b/src/network/networkd-mdb.c index fa9daa3472..5d400c3a28 100644 --- a/src/network/networkd-mdb.c +++ b/src/network/networkd-mdb.c @@ -94,6 +94,9 @@ static int set_mdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) int r; assert(link); + assert(link->bridge_mdb_messages > 0); + + link->bridge_mdb_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; @@ -105,11 +108,16 @@ static int set_mdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) return 1; } + if (link->bridge_mdb_messages == 0) { + link->bridge_mdb_configured = true; + link_check_ready(link); + } + return 1; } /* send a request to the kernel to add an MDB entry */ -int mdb_entry_configure(Link *link, MdbEntry *mdb_entry) { +static int mdb_entry_configure(Link *link, MdbEntry *mdb_entry) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; struct br_mdb_entry entry; int r; @@ -159,6 +167,49 @@ int mdb_entry_configure(Link *link, MdbEntry *mdb_entry) { return 1; } +int link_set_bridge_mdb(Link *link) { + MdbEntry *mdb_entry; + Link *master; + int r; + + assert(link); + + link->bridge_mdb_configured = false; + + if (!link->network) + return 0; + + if (!link->network->bridge) { + link->bridge_mdb_configured = true; + return 0; + } + + if (!link_has_carrier(link)) + return log_link_debug(link, "Link does not have carrier yet, setting MDB entries later."); + + r = link_get(link->manager, link->network->bridge->ifindex, &master); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get Link object for Bridge=%s", link->network->bridge->ifname); + + if (!link_has_carrier(master)) + return log_link_debug(link, "Bridge interface %s does not have carrier yet, setting MDB entries later.", link->network->bridge->ifname); + + LIST_FOREACH(static_mdb_entries, mdb_entry, link->network->static_mdb_entries) { + r = mdb_entry_configure(link, mdb_entry); + if (r < 0) + return log_link_error_errno(link, r, "Failed to add MDB entry to multicast group database: %m"); + + link->bridge_mdb_messages++; + } + + if (link->bridge_mdb_messages == 0) { + link->bridge_mdb_configured = true; + link_check_ready(link); + } + + return 0; +} + /* parse the VLAN Id from config files. */ int config_parse_mdb_vlan_id( const char *unit, diff --git a/src/network/networkd-mdb.h b/src/network/networkd-mdb.h index 9ac8a18188..d46ab4a50e 100644 --- a/src/network/networkd-mdb.h +++ b/src/network/networkd-mdb.h @@ -24,7 +24,7 @@ struct MdbEntry { int mdb_entry_verify(MdbEntry *mdb_entry); MdbEntry *mdb_entry_free(MdbEntry *mdb_entry); -int mdb_entry_configure(Link *link, MdbEntry *mdb_entry); +int link_set_bridge_mdb(Link *link); DEFINE_NETWORK_SECTION_FUNCTIONS(MdbEntry, mdb_entry_free);