From: Yu Watanabe Date: Mon, 17 May 2021 20:45:28 +0000 (+0900) Subject: network: use request queue to configure bridge MDB X-Git-Tag: v249-rc1~76^2~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a038aaced754f633273a0edb2f68d669fccda60;p=thirdparty%2Fsystemd.git network: use request queue to configure bridge MDB --- diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index 7c3ef596efc..3bf1e068f00 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -7,6 +7,7 @@ #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-network.h" +#include "networkd-queue.h" #include "string-util.h" #include "vlan-util.h" @@ -79,7 +80,7 @@ static int bridge_mdb_new_static( return 0; } -static int set_mdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(link); @@ -94,7 +95,7 @@ static int set_mdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) if (r == -EINVAL && streq_ptr(link->kind, "bridge") && (!link->network || !link->network->bridge)) { /* 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 configuring bridge MDB entries on bridge master, ignoring: %m"); + 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) { @@ -124,15 +125,16 @@ static int link_get_bridge_master_ifindex(Link *link) { } /* send a request to the kernel to add an MDB entry */ -static int bridge_mdb_configure(Link *link, BridgeMDB *mdb) { +static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; struct br_mdb_entry entry; int master, r; + assert(mdb); assert(link); assert(link->network); assert(link->manager); - assert(mdb); + assert(callback); if (DEBUG_LOGGING) { _cleanup_free_ char *a = NULL; @@ -154,11 +156,6 @@ static int bridge_mdb_configure(Link *link, BridgeMDB *mdb) { .vid = mdb->vlan_id, }; - /* create new RTM message */ - r = sd_rtnl_message_new_mdb(link->manager->rtnl, &req, RTM_NEWMDB, master); - if (r < 0) - return log_link_error_errno(link, r, "Could not create RTM_NEWMDB message: %m"); - switch (mdb->family) { case AF_INET: entry.addr.u.ip4 = mdb->group_addr.in.s_addr; @@ -174,11 +171,16 @@ static int bridge_mdb_configure(Link *link, BridgeMDB *mdb) { assert_not_reached("Invalid address family"); } + /* create new RTM message */ + r = sd_rtnl_message_new_mdb(link->manager->rtnl, &req, RTM_NEWMDB, master); + if (r < 0) + return log_link_error_errno(link, r, "Could not create RTM_NEWMDB message: %m"); + r = sd_netlink_message_append_data(req, MDBA_SET_ENTRY, &entry, sizeof(entry)); if (r < 0) return log_link_error_errno(link, r, "Could not append MDBA_SET_ENTRY attribute: %m"); - r = netlink_call_async(link->manager->rtnl, NULL, req, set_mdb_handler, + r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); @@ -188,18 +190,13 @@ static int bridge_mdb_configure(Link *link, BridgeMDB *mdb) { return 1; } -int link_set_bridge_mdb(Link *link) { +int link_request_static_bridge_mdb(Link *link) { BridgeMDB *mdb; int r; assert(link); assert(link->manager); - if (link->static_bridge_mdb_messages != 0) { - log_link_debug(link, "MDB entries are configuring."); - return 0; - } - link->static_bridge_mdb_configured = false; if (!link->network) @@ -208,48 +205,77 @@ int link_set_bridge_mdb(Link *link) { if (hashmap_isempty(link->network->bridge_mdb_entries_by_section)) goto finish; - if (!link_has_carrier(link)) { - log_link_debug(link, "Link does not have carrier yet, setting MDB entries later."); - return 0; - } - - if (link->network->bridge) { - Link *master; - - 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)) { - log_link_debug(link, "Bridge interface %s does not have carrier yet, setting MDB entries later.", link->network->bridge->ifname); - return 0; + if (!link->network->bridge) { + if (!streq_ptr(link->kind, "bridge")) { + log_link_warning(link, "Link is neither a bridge master nor a bridge port, ignoring [BridgeMDB] sections."); + goto finish; + } else if (link->manager->bridge_mdb_on_master_not_supported) { + log_link_debug(link, "Kernel seems not to support bridge MDB entries on bridge master, ignoring [BridgeMDB] sections."); + goto finish; } - - } else if (!streq_ptr(link->kind, "bridge")) { - log_link_warning(link, "Link is neither a bridge master nor a bridge port, ignoring [BridgeMDB] sections."); - goto finish; - } else if (link->manager->bridge_mdb_on_master_not_supported) { - log_link_debug(link, "Kernel seems not to support configuring bridge MDB entries on bridge master, ignoring [BridgeMDB] sections."); - goto finish; } HASHMAP_FOREACH(mdb, link->network->bridge_mdb_entries_by_section) { - r = bridge_mdb_configure(link, mdb); + r = link_queue_request(link, REQUEST_TYPE_BRIDGE_MDB, mdb, false, + &link->static_bridge_mdb_messages, bridge_mdb_configure_handler, NULL); if (r < 0) - return log_link_error_errno(link, r, "Failed to add MDB entry to multicast group database: %m"); - - link->static_bridge_mdb_messages++; + return log_link_error_errno(link, r, "Failed to request MDB entry to multicast group database: %m"); } finish: if (link->static_bridge_mdb_messages == 0) { link->static_bridge_mdb_configured = true; link_check_ready(link); + } else { + log_link_debug(link, "Setting bridge MDB entries."); + link_set_state(link, LINK_STATE_CONFIGURING); } return 0; } +static bool bridge_mdb_is_ready_to_configure(Link *link) { + Link *master; + + if (!link_is_ready_to_configure(link, false)) + return false; + + if (!link->network->bridge) + return true; /* The interface is bridge master. */ + + if (link->master_ifindex <= 0) + return false; + + if (link->master_ifindex != link->network->bridge->ifindex) + return false; + + if (link_get(link->manager, link->master_ifindex, &master) < 0) + return false; + + if (!streq_ptr(master->kind, "bridge")) + return false; + + if (!IN_SET(master->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return false; + + if (!link_has_carrier(master)) + return false; + + return true; +} + +int request_process_bridge_mdb(Request *req) { + assert(req); + assert(req->link); + assert(req->mdb); + assert(req->type == REQUEST_TYPE_BRIDGE_MDB); + + if (!bridge_mdb_is_ready_to_configure(req->link)) + return 0; + + return bridge_mdb_configure(req->mdb, req->link, req->netlink_handler); +} + static int bridge_mdb_verify(BridgeMDB *mdb) { if (section_is_invalid(mdb->section)) return -EINVAL; diff --git a/src/network/networkd-bridge-mdb.h b/src/network/networkd-bridge-mdb.h index efdfa4eae9f..9ca262e0ce9 100644 --- a/src/network/networkd-bridge-mdb.h +++ b/src/network/networkd-bridge-mdb.h @@ -9,6 +9,7 @@ typedef struct Link Link; typedef struct Network Network; +typedef struct Request Request; typedef struct BridgeMDB { Network *network; @@ -23,7 +24,8 @@ BridgeMDB *bridge_mdb_free(BridgeMDB *mdb); void network_drop_invalid_bridge_mdb_entries(Network *network); -int link_set_bridge_mdb(Link *link); +int link_request_static_bridge_mdb(Link *link); +int request_process_bridge_mdb(Request *req); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 05b1658e15f..23c751a39f4 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -826,10 +826,6 @@ static int link_set_static_configs(Link *link) { assert(link->network); assert(link->state != _LINK_STATE_INVALID); - r = link_set_bridge_mdb(link); - if (r < 0) - return r; - r = link_set_ipv6_proxy_ndp_addresses(link); if (r < 0) return r; @@ -846,6 +842,10 @@ static int link_set_static_configs(Link *link) { if (r < 0) return r; + r = link_request_static_bridge_mdb(link); + if (r < 0) + return r; + r = link_request_static_neighbors(link); if (r < 0) return r; @@ -2802,30 +2802,7 @@ static int link_carrier_gained(Link *link) { return r; } - r = link_handle_bound_by_list(link); - if (r < 0) - return r; - - if (!link->static_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->static_bridge_mdb_configured) - continue; - - r = link_set_bridge_mdb(slave); - if (r < 0) - link_enter_failed(slave); - } - } - - return 0; + return link_handle_bound_by_list(link); } static int link_carrier_lost(Link *link) { diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 758cd4de2a4..563cdc4f950 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -2,6 +2,7 @@ #include "networkd-address.h" #include "networkd-bridge-fdb.h" +#include "networkd-bridge-mdb.h" #include "networkd-dhcp-server.h" #include "networkd-manager.h" #include "networkd-neighbor.h" @@ -18,6 +19,9 @@ static void request_free_object(RequestType type, void *object) { case REQUEST_TYPE_BRIDGE_FDB: bridge_fdb_free(object); break; + case REQUEST_TYPE_BRIDGE_MDB: + bridge_mdb_free(object); + break; case REQUEST_TYPE_DHCP_SERVER: break; case REQUEST_TYPE_NEIGHBOR: @@ -131,6 +135,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { case REQUEST_TYPE_BRIDGE_FDB: r = request_process_bridge_fdb(req); break; + case REQUEST_TYPE_BRIDGE_MDB: + r = request_process_bridge_mdb(req); + break; case REQUEST_TYPE_DHCP_SERVER: r = request_process_dhcp_server(req); break; diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 9eab751da42..f963d18d744 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -7,6 +7,7 @@ typedef struct Address Address; typedef struct BridgeFDB BridgeFDB; +typedef struct BridgeMDB BridgeMDB; typedef struct Neighbor Neighbor; typedef struct NextHop NextHop; typedef struct Route Route; @@ -20,6 +21,7 @@ typedef void (*request_on_free_handler_t)(Request*); typedef enum RequestType { REQUEST_TYPE_ADDRESS, REQUEST_TYPE_BRIDGE_FDB, + REQUEST_TYPE_BRIDGE_MDB, REQUEST_TYPE_DHCP_SERVER, REQUEST_TYPE_NEIGHBOR, REQUEST_TYPE_NEXTHOP, @@ -36,6 +38,7 @@ typedef struct Request { union { Address *address; BridgeFDB *fdb; + BridgeMDB *mdb; Neighbor *neighbor; NextHop *nexthop; Route *route;