From: Yu Watanabe Date: Fri, 7 May 2021 07:05:31 +0000 (+0900) Subject: network: use request queue to configure neighbors X-Git-Tag: v249-rc1~240^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=40ca350ea1846d28fb3403217d47ed87eac57ad7;p=thirdparty%2Fsystemd.git network: use request queue to configure neighbors --- diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index c41baec2154..abf090bc059 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -796,9 +796,6 @@ void link_check_ready(Link *link) { if (!link->addresses_configured) return (void) log_link_debug(link, "%s(): static addresses are not configured.", __func__); - if (!link->neighbors_configured) - return (void) log_link_debug(link, "%s(): static neighbors are not configured.", __func__); - SET_FOREACH(a, link->addresses) if (!address_is_ready(a)) { _cleanup_free_ char *str = NULL; @@ -807,6 +804,9 @@ void link_check_ready(Link *link) { return (void) log_link_debug(link, "%s(): an address %s is not ready.", __func__, strna(str)); } + if (!link->static_neighbors_configured) + return (void) log_link_debug(link, "%s(): static neighbors are not configured.", __func__); + if (!link->static_routes_configured) return (void) log_link_debug(link, "%s(): static routes are not configured.", __func__); @@ -881,7 +881,6 @@ static int link_set_static_configs(Link *link) { link->request_static_addresses = false; link->addresses_configured = false; link->addresses_ready = false; - link->neighbors_configured = false; link->static_routes_configured = false; link->static_nexthops_configured = false; @@ -897,11 +896,11 @@ static int link_set_static_configs(Link *link) { if (r < 0) return r; - r = link_set_neighbors(link); + r = link_set_addresses(link); if (r < 0) return r; - r = link_set_addresses(link); + r = link_request_static_neighbors(link); if (r < 0) return r; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 9fd95abc3f0..f8aff1cc8fa 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -81,10 +81,11 @@ typedef struct Link { unsigned address_messages; unsigned address_remove_messages; unsigned address_label_messages; - unsigned neighbor_messages; + unsigned static_neighbor_messages; unsigned route_messages; unsigned nexthop_messages; unsigned static_routing_policy_rule_messages; + unsigned neighbor_remove_messages; unsigned tc_messages; unsigned sr_iov_messages; unsigned enslaving; @@ -121,7 +122,7 @@ typedef struct Link { bool request_static_addresses:1; bool addresses_configured:1; bool addresses_ready:1; - bool neighbors_configured:1; + bool static_neighbors_configured:1; bool static_routes_configured:1; bool static_nexthops_configured:1; bool static_routing_policy_rules_configured:1; diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 41ce52a3eed..2afe71c5f8a 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -7,6 +7,7 @@ #include "networkd-manager.h" #include "networkd-neighbor.h" #include "networkd-network.h" +#include "networkd-queue.h" #include "set.h" Neighbor *neighbor_free(Neighbor *neighbor) { @@ -270,18 +271,17 @@ static int neighbor_configure( if (r < 0) return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); + r = neighbor_add(link, neighbor, ret); + if (r < 0) + return log_link_error_errno(link, r, "Could not add neighbor: %m"); + 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"); - link->neighbor_messages++; link_ref(link); - r = neighbor_add(link, neighbor, ret); - if (r < 0) - return log_link_error_errno(link, r, "Could not add neighbor: %m"); - return r; } @@ -290,28 +290,46 @@ static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_messag assert(m); assert(link); - assert(link->neighbor_messages > 0); + assert(link->static_neighbor_messages > 0); - link->neighbor_messages--; + link->static_neighbor_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - /* Neighbor may not exist yet. So, do not enter failed state here. */ - log_link_message_warning_errno(link, m, r, "Could not set neighbor, ignoring"); + if (r < 0 && r != -EEXIST) { + log_link_message_warning_errno(link, m, r, "Could not set neighbor"); + link_enter_failed(link); + return 1; + } - if (link->neighbor_messages == 0) { + if (link->static_neighbor_messages == 0) { log_link_debug(link, "Neighbors set"); - link->neighbors_configured = true; + link->static_neighbors_configured = true; link_check_ready(link); } return 1; } -int link_set_neighbors(Link *link) { +static int link_request_neighbor( + Link *link, + Neighbor *neighbor, + bool consume_object, + unsigned *message_counter, + link_netlink_message_handler_t netlink_handler, + Request **ret) { + + assert(link); + assert(neighbor); + + log_neighbor_debug(neighbor, "Requesting", link); + return link_queue_request(link, REQUEST_TYPE_NEIGHBOR, neighbor, consume_object, + message_counter, netlink_handler, ret); +} + +int link_request_static_neighbors(Link *link) { Neighbor *neighbor; int r; @@ -319,24 +337,20 @@ int link_set_neighbors(Link *link) { assert(link->network); assert(link->state != _LINK_STATE_INVALID); - if (link->neighbor_messages != 0) { - log_link_debug(link, "Neighbors are configuring."); - return 0; - } - - link->neighbors_configured = false; + link->static_neighbors_configured = false; HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) { - r = neighbor_configure(neighbor, link, static_neighbor_configure_handler, NULL); + r = link_request_neighbor(link, neighbor, false, &link->static_neighbor_messages, + static_neighbor_configure_handler, NULL); if (r < 0) - return log_link_warning_errno(link, r, "Could not set neighbor: %m"); + return log_link_warning_errno(link, r, "Could not request neighbor: %m"); } - if (link->neighbor_messages == 0) { - link->neighbors_configured = true; + if (link->static_neighbor_messages == 0) { + link->static_neighbors_configured = true; link_check_ready(link); } else { - log_link_debug(link, "Setting neighbors"); + log_link_debug(link, "Requesting neighbors"); link_set_state(link, LINK_STATE_CONFIGURING); } @@ -348,6 +362,9 @@ static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link assert(m); assert(link); + assert(link->neighbor_remove_messages > 0); + + link->neighbor_remove_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; @@ -387,6 +404,7 @@ static int neighbor_remove(Neighbor *neighbor, Link *link) { return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); + link->neighbor_remove_messages++; return 0; } @@ -442,6 +460,34 @@ int link_drop_neighbors(Link *link) { return r; } +int request_process_neighbor(Request *req) { + Neighbor *ret; + int r; + + assert(req); + assert(req->link); + assert(req->neighbor); + assert(req->type == REQUEST_TYPE_NEIGHBOR); + + if (!link_is_ready_to_configure(req->link, false)) + return 0; + + if (req->link->neighbor_remove_messages > 0) + return 0; + + r = neighbor_configure(req->neighbor, req->link, req->netlink_handler, &ret); + if (r < 0) + return r; + + if (req->after_configure) { + r = req->after_configure(req, ret); + if (r < 0) + return r; + } + + return 1; +} + int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(neighbor_freep) Neighbor *tmp = NULL; _cleanup_free_ void *lladdr = NULL; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 8ad790be2db..7ac2f90eb38 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -10,9 +10,10 @@ #include "in-addr-util.h" #include "networkd-util.h" -typedef Manager Manager; -typedef Network Network; -typedef Link Link; +typedef struct Link Link; +typedef struct Manager Manager; +typedef struct Network Network; +typedef struct Request Request; union lladdr_union { struct ether_addr mac; @@ -34,10 +35,12 @@ Neighbor *neighbor_free(Neighbor *neighbor); void network_drop_invalid_neighbors(Network *network); -int link_set_neighbors(Link *link); int link_drop_neighbors(Link *link); int link_drop_foreign_neighbors(Link *link); +int link_request_static_neighbors(Link *link); +int request_process_neighbor(Request *req); + int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address); diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index e06a16bbb48..c515e79716b 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -10,6 +10,9 @@ static void request_free_object(RequestType type, void *object) { switch(type) { + case REQUEST_TYPE_NEIGHBOR: + neighbor_free(object); + break; case REQUEST_TYPE_ROUTING_POLICY_RULE: routing_policy_rule_free(object); break; @@ -104,6 +107,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { ORDERED_SET_FOREACH(req, manager->request_queue) { switch(req->type) { + case REQUEST_TYPE_NEIGHBOR: + r = request_process_neighbor(req); + break; case REQUEST_TYPE_ROUTING_POLICY_RULE: r = request_process_routing_policy_rule(req); break; diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index e666d446786..369e7db3a26 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -5,6 +5,7 @@ #include "networkd-link.h" +typedef struct Neighbor Neighbor; typedef struct RoutingPolicyRule RoutingPolicyRule; typedef struct Request Request; @@ -13,6 +14,7 @@ typedef int (*request_after_configure_handler_t)(Request*, void*); typedef void (*request_on_free_handler_t)(Request*); typedef enum RequestType { + REQUEST_TYPE_NEIGHBOR, REQUEST_TYPE_ROUTING_POLICY_RULE, _REQUEST_TYPE_MAX, _REQUEST_TYPE_INVALID = -EINVAL, @@ -23,6 +25,7 @@ typedef struct Request { RequestType type; bool consume_object; union { + Neighbor *neighbor; RoutingPolicyRule *rule; void *object; };