From: Yu Watanabe Date: Tue, 15 Jun 2021 14:24:46 +0000 (+0900) Subject: network: use request queue to configure DHCP{4,6} clients X-Git-Tag: v250-rc1~856^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ccffa166d8fa6019c472b4d118516841f1b947e4;p=thirdparty%2Fsystemd.git network: use request queue to configure DHCP{4,6} clients Previously, when UUID is requested for DUID, then the clients are configured in callback of bus methods. But now, 'request queue' was implemented, so we can use it to wait until the product UUID is obtained. --- diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index dd1dc78dae0..3d00802b200 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -96,113 +96,64 @@ const DUID *link_get_duid(Link *link, int family) { return duid; } -static int link_configure_and_start_dhcp_delayed(Link *link) { - int r; - - assert(link); - - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) - return 0; - - if (!link->dhcp_client) { - r = dhcp4_configure(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DHCP4 client: %m"); - } - - if (!link->dhcp6_client) { - r = dhcp6_configure(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DHCP6 client: %m"); - } - - if (link->set_flags_messages > 0) - return 0; - - if (!link_has_carrier(link)) - return 0; - - r = dhcp4_start(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m"); - - r = ndisc_start(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m"); - - r = dhcp6_start(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m"); - - return 0; -} - static int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { Manager *manager = userdata; const sd_bus_error *e; const void *a; size_t sz; - Link *link; int r; assert(m); assert(manager); + /* To avoid calling GetProductUUID() bus method so frequently, set the flag below + * even if the method fails. */ + manager->has_product_uuid = true; + e = sd_bus_message_get_error(m); if (e) { r = sd_bus_error_get_errno(e); log_warning_errno(r, "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s", bus_error_message(e, r)); - goto configure; + return 0; } r = sd_bus_message_read_array(m, 'y', &a, &sz); if (r < 0) { log_warning_errno(r, "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m"); - goto configure; + return 0; } if (sz != sizeof(sd_id128_t)) { log_warning("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID."); - goto configure; + return 0; } + log_debug("Successfully obtained product UUID"); + memcpy(&manager->duid_product_uuid.raw_data, a, sz); manager->duid_product_uuid.raw_data_len = sz; -configure: - /* To avoid calling GetProductUUID() bus method so frequently, set the flag below - * even if the method fails. */ - manager->has_product_uuid = true; - - while ((link = set_steal_first(manager->links_requesting_uuid))) { - r = link_configure_and_start_dhcp_delayed(link); - if (r < 0) - link_enter_failed(link); - - link_unref(link); - } - - manager->links_requesting_uuid = set_free(manager->links_requesting_uuid); - - return 1; + return 0; } int manager_request_product_uuid(Manager *m) { + static bool bus_method_is_called = false; int r; assert(m); - if (m->product_uuid_requested) + if (bus_method_is_called) return 0; - log_debug("Requesting product UUID"); - - if (sd_bus_is_ready(m->bus) <= 0) { + if (sd_bus_is_ready(m->bus) <= 0 && !m->product_uuid_requested) { log_debug("Not connected to system bus, requesting product UUID later."); + m->product_uuid_requested = true; return 0; } + m->product_uuid_requested = false; + r = sd_bus_call_method_async( m->bus, NULL, @@ -217,7 +168,9 @@ int manager_request_product_uuid(Manager *m) { if (r < 0) return log_warning_errno(r, "Failed to get product UUID: %m"); - m->product_uuid_requested = true; + log_debug("Requesting product UUID."); + + bus_method_is_called = true; return 0; } @@ -247,12 +200,6 @@ int dhcp_configure_duid(Link *link, const DUID *duid) { return 1; } - r = set_ensure_put(&m->links_requesting_uuid, NULL, link); - if (r < 0) - return log_oom(); - if (r > 0) - link_ref(link); - return 0; } diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 135aeace7ec..cc6d1988516 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1395,15 +1395,6 @@ static int dhcp4_set_client_identifier(Link *link) { return 0; } -static int dhcp4_configure_duid(Link *link) { - assert(link); - - if (!IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY)) - return 1; - - return dhcp_configure_duid(link, link_get_dhcp4_duid(link)); -} - static int dhcp4_set_request_address(Link *link) { Address *a; @@ -1453,7 +1444,7 @@ static bool link_needs_dhcp_broadcast(Link *link) { return r == true; } -int dhcp4_configure(Link *link) { +static int dhcp4_configure(Link *link) { sd_dhcp_option *send_option; void *request_options; int r; @@ -1461,16 +1452,9 @@ int dhcp4_configure(Link *link) { assert(link); assert(link->network); - if (!link_dhcp4_enabled(link)) - return 0; - if (link->dhcp_client) return log_link_debug_errno(link, SYNTHETIC_ERRNO(EBUSY), "DHCP4 client is already configured."); - r = dhcp4_configure_duid(link); - if (r <= 0) - return r; - r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize); if (r < 0) return log_link_debug_errno(link, r, "DHCP4 CLIENT: Failed to allocate DHCP4 client: %m"); @@ -1642,17 +1626,83 @@ int dhcp4_update_mac(Link *link) { } int dhcp4_start(Link *link) { + int r; + assert(link); if (!link->dhcp_client) return 0; + if (!link_has_carrier(link)) + return 0; + if (sd_dhcp_client_is_running(link->dhcp_client) > 0) return 0; - log_link_debug(link, "Acquiring DHCPv4 lease"); + r = sd_dhcp_client_start(link->dhcp_client); + if (r < 0) + return r; - return sd_dhcp_client_start(link->dhcp_client); + return 1; +} + +static int dhcp4_configure_duid(Link *link) { + assert(link); + + if (!IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY)) + return 1; + + return dhcp_configure_duid(link, link_get_dhcp4_duid(link)); +} + +int request_process_dhcp4_client(Request *req) { + Link *link; + int r; + + assert(req); + assert(req->link); + assert(req->type == REQUEST_TYPE_DHCP4_CLIENT); + + link = req->link; + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return 0; + + r = dhcp4_configure_duid(link); + if (r <= 0) + return r; + + r = dhcp4_configure(req->link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure DHCPv4 client: %m"); + + r = dhcp4_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m"); + + log_link_debug(link, "DHCPv4 client is configured%s.", + r > 0 ? ", acquiring DHCPv4 lease" : ""); + + return 1; +} + +int link_request_dhcp4_client(Link *link) { + int r; + + assert(link); + + if (!link_dhcp4_enabled(link)) + return 0; + + if (link->dhcp_client) + return 0; + + r = link_queue_request(link, REQUEST_TYPE_DHCP4_CLIENT, NULL, false, NULL, NULL, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv4 client: %m"); + + log_link_debug(link, "Requested configuring of the DHCPv4 client."); + return 0; } int config_parse_dhcp_max_attempts( diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index e41e39fc6e9..152c2213b49 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -4,6 +4,8 @@ #include "conf-parser.h" typedef struct Link Link; +typedef struct Network Network; +typedef struct Request Request; typedef enum DHCPClientIdentifier { DHCP_CLIENT_ID_MAC, @@ -18,11 +20,13 @@ typedef enum DHCPClientIdentifier { } DHCPClientIdentifier; void network_adjust_dhcp4(Network *network); -int dhcp4_configure(Link *link); int dhcp4_update_mac(Link *link); int dhcp4_start(Link *link); int dhcp4_lease_lost(Link *link); +int request_process_dhcp4_client(Request *req); +int link_request_dhcp4_client(Link *link); + CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 605ee7dd112..163af103e49 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -1393,6 +1393,8 @@ int dhcp6_request_information(Link *link, int ir) { } int dhcp6_start(Link *link) { + int r; + assert(link); if (!link->dhcp6_client) @@ -1401,6 +1403,9 @@ int dhcp6_start(Link *link) { if (!link_dhcp6_enabled(link)) return 0; + if (!link_has_carrier(link)) + return 0; + if (link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_NO) return 0; @@ -1412,9 +1417,11 @@ int dhcp6_start(Link *link) { if (sd_dhcp6_client_is_running(link->dhcp6_client) > 0) return 0; - log_link_debug(link, "Acquiring DHCPv6 lease"); + r = dhcp6_request_information(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST); + if (r < 0) + return r; - return dhcp6_request_information(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST); + return 1; } int dhcp6_request_prefix_delegation(Link *link) { @@ -1571,7 +1578,7 @@ static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) { return 0; } -int dhcp6_configure(Link *link) { +static int dhcp6_configure(Link *link) { _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; sd_dhcp6_option *vendor_option; sd_dhcp6_option *send_option; @@ -1581,16 +1588,9 @@ int dhcp6_configure(Link *link) { assert(link); assert(link->network); - if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link)) - return 0; - if (link->dhcp6_client) return log_link_debug_errno(link, SYNTHETIC_ERRNO(EBUSY), "DHCP6 client is already configured."); - r = dhcp_configure_duid(link, link_get_dhcp6_duid(link)); - if (r <= 0) - return r; - r = sd_dhcp6_client_new(&client); if (r == -ENOMEM) return log_oom_debug(); @@ -1716,6 +1716,60 @@ int dhcp6_update_mac(Link *link) { return 0; } +int request_process_dhcp6_client(Request *req) { + Link *link; + int r; + + assert(req); + assert(req->link); + assert(req->type == REQUEST_TYPE_DHCP6_CLIENT); + + link = req->link; + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return 0; + + r = dhcp_configure_duid(link, link_get_dhcp6_duid(link)); + if (r <= 0) + return r; + + r = dhcp6_configure(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure DHCPv6 client: %m"); + + r = ndisc_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m"); + + r = dhcp6_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m"); + + log_link_debug(link, "DHCPv6 client is configured%s.", + r > 0 ? ", acquiring DHCPv6 lease" : ""); + + return 1; +} + +int link_request_dhcp6_client(Link *link) { + int r; + + assert(link); + + if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link)) + return 0; + + if (link->dhcp6_client) + return 0; + + r = link_queue_request(link, REQUEST_TYPE_DHCP6_CLIENT, NULL, false, NULL, NULL, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv6 client: %m"); + + log_link_debug(link, "Requested configuring of the DHCPv6 client."); + return 0; +} + int link_serialize_dhcp6_client(Link *link, FILE *f) { _cleanup_free_ char *duid = NULL; uint32_t iaid; diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index 82becb03217..23612454d94 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -1,9 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include "sd-dhcp6-client.h" - #include "conf-parser.h" +#include "in-addr-util.h" #include "macro.h" typedef enum DHCP6ClientStartMode { @@ -15,7 +14,7 @@ typedef enum DHCP6ClientStartMode { } DHCP6ClientStartMode; typedef struct Link Link; -typedef struct Manager Manager; +typedef struct Request Request; typedef struct DHCP6DelegatedPrefix { struct in6_addr prefix; /* Prefix assigned to the link */ @@ -29,12 +28,14 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6DelegatedPrefix*, dhcp6_pd_free); bool link_dhcp6_with_address_enabled(Link *link); bool link_dhcp6_pd_is_enabled(Link *link); int dhcp6_pd_remove(Link *link); -int dhcp6_configure(Link *link); int dhcp6_update_mac(Link *link); int dhcp6_start(Link *link); int dhcp6_request_information(Link *link, int ir); int dhcp6_request_prefix_delegation(Link *link); +int request_process_dhcp6_client(Request *req); +int link_request_dhcp6_client(Link *link); + int link_serialize_dhcp6_client(Link *link, FILE *f); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index b4d5155b4a3..041a53e97b3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -650,12 +650,14 @@ static int link_acquire_dynamic_ipv4_conf(Link *link) { if (r < 0) return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m"); - } else if (link->ipv4ll) { - log_link_debug(link, "Acquiring IPv4 link-local address"); + log_link_debug(link, "Acquiring DHCPv4 lease."); + } else if (link->ipv4ll) { r = sd_ipv4ll_start(link->ipv4ll); if (r < 0) return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m"); + + log_link_debug(link, "Acquiring IPv4 link-local address."); } if (link->dhcp_server) { @@ -975,8 +977,6 @@ static Link *link_drop(Link *link) { link_drop_from_master(link); - link_unref(set_remove(link->manager->links_requesting_uuid, link)); - (void) unlink(link->state_file); link_clean(link); @@ -1127,13 +1127,13 @@ static int link_configure(Link *link) { if (r < 0) return r; - r = dhcp4_configure(link); + r = link_request_dhcp4_client(link); if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DHCP4 client: %m"); + return r; - r = dhcp6_configure(link); + r = link_request_dhcp6_client(link); if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure DHCP6 client: %m"); + return r; r = ndisc_configure(link); if (r < 0) @@ -1263,7 +1263,6 @@ static int link_reconfigure_impl(Link *link, bool force) { link_free_carrier_maps(link); link_free_engines(link); link->network = network_unref(link->network); - link_unref(set_remove(link->manager->links_requesting_uuid, link)); /* Then, apply new .network file */ link->network = network_ref(network); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 374d27bef34..c8df49a4900 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -103,7 +103,7 @@ static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *r (void) manager_set_hostname(m, m->dynamic_hostname); if (m->dynamic_timezone) (void) manager_set_timezone(m, m->dynamic_timezone); - if (!set_isempty(m->links_requesting_uuid)) + if (m->product_uuid_requested) (void) manager_request_product_uuid(m); return 0; @@ -460,7 +460,6 @@ Manager* manager_free(Manager *m) { m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free); m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref); - m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref); m->links_by_name = hashmap_free(m->links_by_name); m->links_by_hw_addr = hashmap_free(m->links_by_hw_addr); m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref); diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 4ee48f3468b..4e789045380 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -60,7 +60,6 @@ struct Manager { DUID duid_product_uuid; bool has_product_uuid; bool product_uuid_requested; - Set *links_requesting_uuid; char* dynamic_hostname; char* dynamic_timezone; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index e5e6f5ac7f6..bfdae0bc19f 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1396,6 +1396,9 @@ int ndisc_start(Link *link) { if (!link->ndisc || !link->dhcp6_client) return 0; + if (!link_has_carrier(link)) + return 0; + log_link_debug(link, "Discovering IPv6 routers"); return sd_ndisc_start(link->ndisc); diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 27a16f29517..7f2481997da 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -5,6 +5,8 @@ #include "networkd-bridge-fdb.h" #include "networkd-bridge-mdb.h" #include "networkd-dhcp-server.h" +#include "networkd-dhcp4.h" +#include "networkd-dhcp6.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-manager.h" #include "networkd-neighbor.h" @@ -33,6 +35,8 @@ static void request_free_object(RequestType type, void *object) { case REQUEST_TYPE_CREATE_STACKED_NETDEV: break; case REQUEST_TYPE_DHCP_SERVER: + case REQUEST_TYPE_DHCP4_CLIENT: + case REQUEST_TYPE_DHCP6_CLIENT: break; case REQUEST_TYPE_IPV6_PROXY_NDP: free(object); @@ -112,7 +116,9 @@ static void request_hash_func(const Request *req, struct siphash *state) { trivial_hash_func(req->object, state); break; case REQUEST_TYPE_DHCP_SERVER: - /* This type does not have an object. */ + case REQUEST_TYPE_DHCP4_CLIENT: + case REQUEST_TYPE_DHCP6_CLIENT: + /* These types do not have an object. */ break; case REQUEST_TYPE_IPV6_PROXY_NDP: in6_addr_hash_func(req->ipv6_proxy_ndp, state); @@ -170,6 +176,8 @@ static int request_compare_func(const struct Request *a, const struct Request *b case REQUEST_TYPE_CREATE_STACKED_NETDEV: return trivial_compare_func(a->object, b->object); case REQUEST_TYPE_DHCP_SERVER: + case REQUEST_TYPE_DHCP4_CLIENT: + case REQUEST_TYPE_DHCP6_CLIENT: return 0; case REQUEST_TYPE_IPV6_PROXY_NDP: return in6_addr_compare_func(a->ipv6_proxy_ndp, b->ipv6_proxy_ndp); @@ -218,12 +226,16 @@ int link_queue_request( assert(IN_SET(type, REQUEST_TYPE_ACTIVATE_LINK, REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_DHCP4_CLIENT, + REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_RADV, REQUEST_TYPE_SET_LINK, REQUEST_TYPE_UP_DOWN) || object); assert(IN_SET(type, REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_DHCP4_CLIENT, + REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_RADV) || netlink_handler); @@ -300,6 +312,12 @@ int manager_process_requests(sd_event_source *s, void *userdata) { case REQUEST_TYPE_DHCP_SERVER: r = request_process_dhcp_server(req); break; + case REQUEST_TYPE_DHCP4_CLIENT: + r = request_process_dhcp4_client(req); + break; + case REQUEST_TYPE_DHCP6_CLIENT: + r = request_process_dhcp6_client(req); + break; case REQUEST_TYPE_IPV6_PROXY_NDP: r = request_process_ipv6_proxy_ndp_address(req); break; diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 85d2be7367d..1fdd07d60a3 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -28,6 +28,8 @@ typedef enum RequestType { REQUEST_TYPE_BRIDGE_MDB, REQUEST_TYPE_CREATE_STACKED_NETDEV, REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_DHCP4_CLIENT, + REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_IPV6_PROXY_NDP, REQUEST_TYPE_NEIGHBOR, REQUEST_TYPE_NEXTHOP,