From: Yu Watanabe Date: Tue, 25 May 2021 07:02:38 +0000 (+0900) Subject: network: introduce link_request_to_create_stacked_netdev() X-Git-Tag: v249-rc1~76^2~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=71a754f70f215558a77143cbe8dc3967a7bb070a;p=thirdparty%2Fsystemd.git network: introduce link_request_to_create_stacked_netdev() This will be used in later commits. --- diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 81d9260c123..a0b6706aad9 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -25,6 +25,7 @@ #include "netdevsim.h" #include "netlink-util.h" #include "networkd-manager.h" +#include "networkd-queue.h" #include "nlmon.h" #include "path-lookup.h" #include "siphash24.h" @@ -654,6 +655,140 @@ int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t callb return 0; } +static bool netdev_is_ready_to_create(NetDev *netdev, Link *link) { + Request req; + + assert(netdev); + assert(link); + + if (netdev->state != NETDEV_STATE_LOADING) + return false; + if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return false; + if (netdev_get_create_type(netdev) == NETDEV_CREATE_AFTER_CONFIGURED && + link->state != LINK_STATE_CONFIGURED) + return false; + + req = (Request) { + .link = link, + .type = REQUEST_TYPE_SET_LINK, + .set_link_operation = SET_LINK_MTU, + }; + + if (ordered_set_contains(link->manager->request_queue, &req)) + return false; + + return true; +} + +int request_process_create_stacked_netdev(Request *req) { + int r; + + assert(req); + assert(req->link); + assert(req->type == REQUEST_TYPE_CREATE_STACKED_NETDEV); + assert(req->netdev); + assert(req->netlink_handler); + + if (!netdev_is_ready_to_create(req->netdev, req->link)) + return 0; + + r = netdev_join(req->netdev, req->link, req->netlink_handler); + if (r < 0) + return log_link_error_errno(req->link, r, "Failed to create stacked netdev '%s': %m", req->netdev->ifname); + + return 1; +} + +static int link_create_stacked_netdev_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 0; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_message_warning_errno(link, m, r, "Could not create stacked netdev"); + link_enter_failed(link); + return 0; + } + + return 1; +} + +static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + assert(link); + assert(link->create_stacked_netdev_messages > 0); + + link->create_stacked_netdev_messages--; + + if (link_create_stacked_netdev_handler_internal(rtnl, m, link) <= 0) + return 0; + + if (link->create_stacked_netdev_messages == 0) { + link->stacked_netdevs_created = true; + log_link_debug(link, "Stacked netdevs created."); + } + + return 0; +} + +static int link_create_stacked_netdev_after_configured_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + assert(link); + assert(link->create_stacked_netdev_after_configured_messages > 0); + + link->create_stacked_netdev_after_configured_messages--; + + if (link_create_stacked_netdev_handler_internal(rtnl, m, link) <= 0) + return 0; + + if (link->create_stacked_netdev_after_configured_messages == 0) { + link->stacked_netdevs_after_configured_created = true; + log_link_debug(link, "Stacked netdevs created."); + } + + return 0; +} + +int link_request_to_crate_stacked_netdev(Link *link, NetDev *netdev) { + NetDevCreateType create_type; + int r; + + assert(link); + assert(netdev); + + create_type = netdev_get_create_type(netdev); + if (!IN_SET(create_type, NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED)) + return -EINVAL; + + if (netdev->state != NETDEV_STATE_LOADING || netdev->ifindex > 0) + /* Already created (or removed?) */ + return 0; + + if (create_type == NETDEV_CREATE_STACKED) { + link->stacked_netdevs_created = false; + r = link_queue_request(link, REQUEST_TYPE_CREATE_STACKED_NETDEV, netdev, false, + &link->create_stacked_netdev_messages, + link_create_stacked_netdev_handler, + NULL); + } else { + link->stacked_netdevs_after_configured_created = false; + r = link_queue_request(link, REQUEST_TYPE_CREATE_STACKED_NETDEV, netdev, false, + &link->create_stacked_netdev_after_configured_messages, + link_create_stacked_netdev_after_configured_handler, + NULL); + } + if (r < 0) + return log_link_error_errno(link, r, "Failed to request to create stacked netdev '%s': %m", + netdev->ifname); + + log_link_debug(link, "Requested to create stacked netdev '%s'", netdev->ifname); + return 0; +} + int netdev_load_one(Manager *manager, const char *filename) { _cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL; const char *dropin_dirname; diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 08070abd0a6..edc1a77af19 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -112,6 +112,7 @@ typedef enum NetDevCreateType { typedef struct Manager Manager; typedef struct Condition Condition; +typedef struct Request Request; typedef struct NetDev { Manager *manager; @@ -207,6 +208,9 @@ int netdev_get_mac(const char *ifname, struct ether_addr **ret); int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t cb); int netdev_join_after_configured(NetDev *netdev, Link *link, link_netlink_message_handler_t callback); +int request_process_create_stacked_netdev(Request *req); +int link_request_to_crate_stacked_netdev(Link *link, NetDev *netdev); + const char *netdev_kind_to_string(NetDevKind d) _const_; NetDevKind netdev_kind_from_string(const char *d) _pure_; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 5a1dba18d33..97bbe97305c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -154,6 +154,11 @@ bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) { if (link->set_link_messages > 0) return false; + /* TODO: enable this check when link_request_to_create_stacked_netdev() is used. + if (!link->stacked_netdevs_created) + return false; + */ + return true; } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 7da33113931..0d60ac682c1 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -96,6 +96,8 @@ typedef struct Link { unsigned sr_iov_messages; unsigned enslaving; unsigned set_link_messages; + unsigned create_stacked_netdev_messages; + unsigned create_stacked_netdev_after_configured_messages; Set *addresses; Set *addresses_foreign; @@ -138,6 +140,8 @@ typedef struct Link { bool can_configured:1; bool activated:1; bool entering_to_join_netdev:1; + bool stacked_netdevs_created:1; + bool stacked_netdevs_after_configured_created:1; sd_dhcp_server *dhcp_server; diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index f05fb2221e9..3a17a06b2c2 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -27,6 +27,8 @@ static void request_free_object(RequestType type, void *object) { case REQUEST_TYPE_BRIDGE_MDB: bridge_mdb_free(object); break; + case REQUEST_TYPE_CREATE_STACKED_NETDEV: + break; case REQUEST_TYPE_DHCP_SERVER: break; case REQUEST_TYPE_IPV6_PROXY_NDP: @@ -93,6 +95,7 @@ static void request_hash_func(const Request *req, struct siphash *state) { case REQUEST_TYPE_ADDRESS_LABEL: case REQUEST_TYPE_BRIDGE_FDB: case REQUEST_TYPE_BRIDGE_MDB: + case REQUEST_TYPE_CREATE_STACKED_NETDEV: /* TODO: Currently, these types do not have any specific hash and compare functions. * Fortunately, all these objects are 'static', thus we can use the trivial functions. */ trivial_hash_func(req->object, state); @@ -145,6 +148,7 @@ static int request_compare_func(const struct Request *a, const struct Request *b case REQUEST_TYPE_ADDRESS_LABEL: case REQUEST_TYPE_BRIDGE_FDB: case REQUEST_TYPE_BRIDGE_MDB: + case REQUEST_TYPE_CREATE_STACKED_NETDEV: return trivial_compare_func(a->object, b->object); case REQUEST_TYPE_DHCP_SERVER: return 0; @@ -255,6 +259,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { case REQUEST_TYPE_BRIDGE_MDB: r = request_process_bridge_mdb(req); break; + case REQUEST_TYPE_CREATE_STACKED_NETDEV: + r = request_process_create_stacked_netdev(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 5d7c85b8a45..697fbf3bfd1 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -11,6 +11,7 @@ typedef struct AddressLabel AddressLabel; typedef struct BridgeFDB BridgeFDB; typedef struct BridgeMDB BridgeMDB; typedef struct Neighbor Neighbor; +typedef struct NetDev NetDev; typedef struct NextHop NextHop; typedef struct Route Route; typedef struct RoutingPolicyRule RoutingPolicyRule; @@ -25,6 +26,7 @@ typedef enum RequestType { REQUEST_TYPE_ADDRESS_LABEL, REQUEST_TYPE_BRIDGE_FDB, REQUEST_TYPE_BRIDGE_MDB, + REQUEST_TYPE_CREATE_STACKED_NETDEV, REQUEST_TYPE_DHCP_SERVER, REQUEST_TYPE_IPV6_PROXY_NDP, REQUEST_TYPE_NEIGHBOR, @@ -53,6 +55,7 @@ typedef struct Request { Route *route; RoutingPolicyRule *rule; SetLinkOperation set_link_operation; + NetDev *netdev; void *object; }; void *userdata;