diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index a122ea84fed..4312c6c7bbc 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1045,7 +1045,7 @@ static int link_configure(Link *link) { return link_request_to_activate(link); } - r = link_configure_sr_iov(link); + r = link_request_sr_iov_vfs(link); if (r < 0) return r; diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 1463f610b25..cf2ffa0327e 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -295,6 +295,7 @@ static const char *const request_type_table[_REQUEST_TYPE_MAX] = { [REQUEST_TYPE_SET_LINK_MAC] = "MAC address", [REQUEST_TYPE_SET_LINK_MASTER] = "master interface", [REQUEST_TYPE_SET_LINK_MTU] = "MTU", + [REQUEST_TYPE_SRIOV] = "SR-IOV", [REQUEST_TYPE_TC_QDISC] = "QDisc", [REQUEST_TYPE_TC_CLASS] = "TClass", [REQUEST_TYPE_UP_DOWN] = "bring link up or down", diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index d1110119ccc..6db0005e619 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -44,6 +44,7 @@ typedef enum RequestType { REQUEST_TYPE_SET_LINK_MAC, /* Setting MAC address. */ REQUEST_TYPE_SET_LINK_MASTER, /* Setting IFLA_MASTER. */ REQUEST_TYPE_SET_LINK_MTU, /* Setting MTU. */ + REQUEST_TYPE_SRIOV, REQUEST_TYPE_TC_CLASS, REQUEST_TYPE_TC_QDISC, REQUEST_TYPE_UP_DOWN, diff --git a/src/network/networkd-sriov.c b/src/network/networkd-sriov.c index cf138c73702..09980b42562 100644 --- a/src/network/networkd-sriov.c +++ b/src/network/networkd-sriov.c @@ -1,20 +1,16 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later * Copyright © 2020 VMware, Inc. */ -#include "netlink-util.h" #include "networkd-link.h" #include "networkd-manager.h" +#include "networkd-queue.h" #include "networkd-sriov.h" -static int sr_iov_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int sr_iov_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, SRIOV *sr_iov) { int r; + assert(m); assert(link); - assert(link->sr_iov_messages > 0); - link->sr_iov_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) { @@ -32,61 +28,77 @@ static int sr_iov_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { return 1; } -static int sr_iov_configure(Link *link, SRIOV *sr_iov) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; +static int sr_iov_configure(SRIOV *sr_iov, Link *link, Request *req) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; + assert(sr_iov); assert(link); assert(link->manager); assert(link->manager->rtnl); assert(link->ifindex > 0); + assert(req); - log_link_debug(link, "Setting SR-IOV virtual function %"PRIu32, sr_iov->vf); + log_link_debug(link, "Setting SR-IOV virtual function %"PRIu32".", sr_iov->vf); - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex); if (r < 0) return r; - r = sr_iov_set_netlink_message(sr_iov, req); + r = sr_iov_set_netlink_message(sr_iov, m); if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, req, sr_iov_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - link->sr_iov_messages++; - - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } -int link_configure_sr_iov(Link *link) { +static int sr_iov_process_request(Request *req, Link *link, SRIOV *sr_iov) { + int r; + + assert(req); + assert(link); + assert(sr_iov); + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return 0; + + r = sr_iov_configure(sr_iov, link, req); + if (r < 0) + return log_link_warning_errno(link, r, + "Failed to configure SR-IOV virtual function %"PRIu32": %m", + sr_iov->vf); + + return 1; +} + +int link_request_sr_iov_vfs(Link *link) { SRIOV *sr_iov; int r; assert(link); assert(link->network); - if (link->sr_iov_messages != 0) { - log_link_debug(link, "SR-IOV is configuring."); - return 0; - } - link->sr_iov_configured = false; ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) { - r = sr_iov_configure(link, sr_iov); + r = link_queue_request_safe(link, REQUEST_TYPE_SRIOV, + sr_iov, NULL, + sr_iov_hash_func, + sr_iov_compare_func, + sr_iov_process_request, + &link->sr_iov_messages, + sr_iov_handler, + NULL); if (r < 0) return log_link_warning_errno(link, r, - "Failed to configure SR-IOV virtual function %"PRIu32": %m", + "Failed to request SR-IOV virtual function %"PRIu32": %m", sr_iov->vf); } - if (link->sr_iov_messages == 0) + if (link->sr_iov_messages == 0) { link->sr_iov_configured = true; - else + link_check_ready(link); + } else log_link_debug(link, "Configuring SR-IOV"); return 0; diff --git a/src/network/networkd-sriov.h b/src/network/networkd-sriov.h index 4251fddf88b..539fa060992 100644 --- a/src/network/networkd-sriov.h +++ b/src/network/networkd-sriov.h @@ -6,4 +6,4 @@ typedef struct Link Link; -int link_configure_sr_iov(Link *link); +int link_request_sr_iov_vfs(Link *link); diff --git a/src/shared/netif-sriov.c b/src/shared/netif-sriov.c index 720aa65f4c0..9edc1741242 100644 --- a/src/shared/netif-sriov.c +++ b/src/shared/netif-sriov.c @@ -80,6 +80,26 @@ SRIOV *sr_iov_free(SRIOV *sr_iov) { return mfree(sr_iov); } +void sr_iov_hash_func(const SRIOV *sr_iov, struct siphash *state) { + assert(sr_iov); + assert(state); + + siphash24_compress(&sr_iov->vf, sizeof(sr_iov->vf), state); +} + +int sr_iov_compare_func(const SRIOV *s1, const SRIOV *s2) { + assert(s1); + assert(s2); + + return CMP(s1->vf, s2->vf); +} + +DEFINE_PRIVATE_HASH_OPS( + sr_iov_hash_ops, + SRIOV, + sr_iov_hash_func, + sr_iov_compare_func); + int sr_iov_set_netlink_message(SRIOV *sr_iov, sd_netlink_message *req) { int r; @@ -296,7 +316,7 @@ static int sr_iov_section_verify(uint32_t num_vfs, SRIOV *sr_iov) { } int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_section) { - _cleanup_hashmap_free_ Hashmap *hashmap = NULL; + _cleanup_set_free_ Set *set = NULL; SRIOV *sr_iov; int r; @@ -308,9 +328,7 @@ int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_sec continue; } - assert(sr_iov->vf < INT_MAX); - - dup = hashmap_remove(hashmap, UINT32_TO_PTR(sr_iov->vf + 1)); + dup = set_remove(set, sr_iov); if (dup) { log_warning("%s: Conflicting [SR-IOV] section is specified at line %u and %u, " "dropping the [SR-IOV] section specified at line %u.", @@ -319,7 +337,7 @@ int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_sec sr_iov_free(dup); } - r = hashmap_ensure_put(&hashmap, NULL, UINT32_TO_PTR(sr_iov->vf + 1), sr_iov); + r = set_ensure_put(&set, &sr_iov_hash_ops, sr_iov); if (r < 0) return log_oom(); assert(r > 0); diff --git a/src/shared/netif-sriov.h b/src/shared/netif-sriov.h index 4c85f101c7b..ee769575e5b 100644 --- a/src/shared/netif-sriov.h +++ b/src/shared/netif-sriov.h @@ -33,6 +33,8 @@ typedef struct SRIOV { } SRIOV; SRIOV *sr_iov_free(SRIOV *sr_iov); +void sr_iov_hash_func(const SRIOV *sr_iov, struct siphash *state); +int sr_iov_compare_func(const SRIOV *s1, const SRIOV *s2); int sr_iov_set_netlink_message(SRIOV *sr_iov, sd_netlink_message *req); int sr_iov_get_num_vfs(sd_device *device, uint32_t *ret); int sr_iov_set_num_vfs(sd_device *device, uint32_t num_vfs, OrderedHashmap *sr_iov_by_section);