From: Yu Watanabe Date: Mon, 28 Feb 2022 00:20:42 +0000 (+0900) Subject: network: introduce request_call_netlink_async() X-Git-Tag: v251-rc1~164^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80d62d4f1aa62c03828e4cbe2c2dfb2a19765af8;p=thirdparty%2Fsystemd.git network: introduce request_call_netlink_async() In most netlink handlers, we do the following, 1. decrease the message counter, 2. check the link state, 3. error handling, 4. update link state via e.g. link_check_ready(). The first two steps are mostly common, hence let's extract it. Moreover, this is not only extracting the common logic, but provide a strong advantage; `request_call_netlink_async()` assigns the relevant Request object to the userdata of the netlink slot, and the request object has full information about the message we sent. Hence, in the future, netlink handler can print more detailed error message. E.g. when an address is failed to configure, then currently we only show an address is failed to configure, but with this commit, potentially we can show which address is failed explicitly. This does not change such error handling yet. But let's do that later. --- diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index d296d799c3f..ee3b883b5ca 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -595,13 +595,10 @@ static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) { if (r < 0) return r; - r = netlink_call_async(netdev->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); + r = request_call_netlink_async(netdev->manager->rtnl, m, req); if (r < 0) return r; - link_ref(link); - netdev->state = NETDEV_STATE_CREATING; log_netdev_debug(netdev, "Creating"); return 0; @@ -650,17 +647,11 @@ int stacked_netdev_process_request(Request *req, Link *link, void *userdata) { return 1; } -static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { int r; assert(m); assert(link); - assert(link->create_stacked_netdev_messages > 0); - - link->create_stacked_netdev_messages--; - - 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) { @@ -693,7 +684,7 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) { link->stacked_netdevs_created = false; r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true, &link->create_stacked_netdev_messages, - link_create_stacked_netdev_handler, + create_stacked_netdev_handler, NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request stacked netdev '%s': %m", diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index c165cde092e..5c31a44ce42 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -65,19 +65,17 @@ static int address_label_new_static(Network *network, const char *filename, unsi return 0; } -static int address_label_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int address_label_configure_handler( + sd_netlink *rtnl, + sd_netlink_message *m, + Request *req, + Link *link, + void *userdata) { + int r; - assert(rtnl); assert(m); assert(link); - assert(link->ifname); - assert(link->static_address_label_messages > 0); - - link->static_address_label_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) { @@ -123,13 +121,7 @@ static int address_label_configure(AddressLabel *label, Link *link, Request *req if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } int address_label_process_request(Request *req, Link *link, void *userdata) { diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 63b40da4328..e9a79d352d1 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1023,9 +1023,6 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, assert(link); assert(error_msg); - 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, error_msg); @@ -1087,12 +1084,7 @@ static int address_configure(const Address *address, Link *link, Request *req) { if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static bool address_is_ready_to_configure(Link *link, const Address *address) { @@ -1135,7 +1127,7 @@ int link_request_address( Address *address, bool consume_object, unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, + address_netlink_handler_t netlink_handler, Request **ret) { Address *acquired, *existing; @@ -1205,7 +1197,7 @@ int link_request_address( log_address_debug(existing, "Requesting", link); r = link_queue_request(link, REQUEST_TYPE_ADDRESS, existing, false, - message_counter, netlink_handler, ret); + message_counter, (request_netlink_handler_t) netlink_handler, ret); if (r < 0) return log_link_warning_errno(link, r, "Failed to request address: %m"); if (r == 0) @@ -1216,13 +1208,10 @@ int link_request_address( return 1; } -static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) { int r; assert(link); - assert(link->static_address_messages > 0); - - link->static_address_messages--; r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address"); if (r <= 0) diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index a90dbceb649..a41274a1fc3 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -18,6 +18,12 @@ typedef struct Manager Manager; typedef struct Network Network; typedef struct Request Request; typedef int (*address_ready_callback_t)(Address *address); +typedef int (*address_netlink_handler_t)( + sd_netlink *rtnl, + sd_netlink_message *m, + Request *req, + Link *link, + Address *address); struct Address { Link *link; @@ -97,7 +103,7 @@ int link_request_address( Address *address, bool consume_object, unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, + address_netlink_handler_t netlink_handler, Request **ret); int link_request_static_address(Link *link, Address *address, bool consume); int link_request_static_addresses(Link *link); diff --git a/src/network/networkd-bridge-fdb.c b/src/network/networkd-bridge-fdb.c index e8a05e5e133..cc02213c28a 100644 --- a/src/network/networkd-bridge-fdb.c +++ b/src/network/networkd-bridge-fdb.c @@ -93,16 +93,11 @@ static int bridge_fdb_new_static( return 0; } -static int bridge_fdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int bridge_fdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { int r; + assert(m); assert(link); - assert(link->static_bridge_fdb_messages > 0); - - link->static_bridge_fdb_messages--; - - 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) { @@ -185,13 +180,7 @@ static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, Request *req) { if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) { diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index b9320f7ea2c..88ae091c1a5 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -81,16 +81,11 @@ static int bridge_mdb_new_static( return 0; } -static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { int r; + assert(m); assert(link); - assert(link->static_bridge_mdb_messages > 0); - - link->static_bridge_mdb_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; r = sd_netlink_message_get_errno(m); if (r == -EINVAL && streq_ptr(link->kind, "bridge") && link->master_ifindex <= 0) { @@ -164,13 +159,7 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, Request *req) { if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static bool bridge_mdb_is_ready_to_configure(Link *link) { diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index bba66f71ed5..edc893e9f69 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -288,13 +288,10 @@ static int dhcp_pd_check_ready(Link *link) { return 1; } -static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) { int r; assert(link); - assert(link->dhcp_pd_messages > 0); - - link->dhcp_pd_messages--; r = route_configure_handler_internal(rtnl, m, link, "Failed to add prefix route for DHCP delegated subnet prefix"); if (r <= 0) @@ -344,13 +341,10 @@ static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, usec return 0; } -static int dhcp_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int dhcp_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) { int r; assert(link); - assert(link->dhcp_pd_messages > 0); - - link->dhcp_pd_messages--; r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCP-PD address"); if (r <= 0) @@ -658,13 +652,10 @@ void dhcp4_pd_prefix_lost(Link *uplink) { (void) link_remove(tunnel); } -static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) { int r; assert(link); - assert(link->dhcp4_messages > 0); - - link->dhcp4_messages--; r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv4 delegated prefix"); if (r <= 0) @@ -677,13 +668,10 @@ static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message return 1; } -static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) { int r; assert(link); - assert(link->dhcp6_messages > 0); - - link->dhcp6_messages--; r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv6 delegated prefix"); if (r <= 0) @@ -704,7 +692,7 @@ static int dhcp_request_unreachable_route( NetworkConfigSource source, const union in_addr_union *server_address, unsigned *counter, - link_netlink_message_handler_t callback) { + route_netlink_handler_t callback) { _cleanup_(route_freep) Route *route = NULL; Route *existing; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 1aa389bb53b..dcde7f9bedb 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -177,16 +177,11 @@ static int dhcp4_retry(Link *link) { return dhcp4_request_address_and_routes(link, false); } -static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) { int r; + assert(m); assert(link); - assert(link->dhcp4_messages > 0); - - link->dhcp4_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; r = sd_netlink_message_get_errno(m); if (r == -ENETUNREACH && !link->dhcp4_route_retrying) { @@ -829,13 +824,10 @@ int dhcp4_lease_lost(Link *link) { return link_request_static_routes(link, true); } -static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) { int r; assert(link); - assert(link->dhcp4_messages > 0); - - link->dhcp4_messages--; r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv4 address"); if (r <= 0) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 3bb013ebaf8..bceae735b09 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -136,13 +136,10 @@ int dhcp6_check_ready(Link *link) { return 0; } -static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) { int r; assert(link); - assert(link->dhcp6_messages > 0); - - link->dhcp6_messages--; r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv6 address"); if (r <= 0) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 5e3854281c5..67eb9d2aa1c 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -70,7 +70,7 @@ static int ipv4ll_address_lost(Link *link) { return address_remove(existing); } -static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) { int r; assert(link); diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index def456c9aa2..b245a9eba26 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -26,13 +26,17 @@ void network_adjust_ipv6_proxy_ndp(Network *network) { } } -static int ipv6_proxy_ndp_address_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int ipv6_proxy_ndp_address_configure_handler( + sd_netlink *rtnl, + sd_netlink_message *m, + Request *req, + Link *link, + struct in6_addr *address) { + int r; + assert(m); assert(link); - assert(link->static_ipv6_proxy_ndp_messages > 0); - - link->static_ipv6_proxy_ndp_messages--; r = sd_netlink_message_get_errno(m); if (r < 0) @@ -71,13 +75,7 @@ static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address) { @@ -109,7 +107,8 @@ int link_request_static_ipv6_proxy_ndp_addresses(Link *link) { SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) { r = link_queue_request(link, REQUEST_TYPE_IPV6_PROXY_NDP, address, false, &link->static_ipv6_proxy_ndp_messages, - ipv6_proxy_ndp_address_configure_handler, NULL); + (request_netlink_handler_t) ipv6_proxy_ndp_address_configure_handler, + NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request IPv6 proxy NDP address: %m"); } diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 2f86ade325a..2a85fb3cfb1 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -203,13 +203,10 @@ static int ndisc_check_ready(Link *link) { return 0; } -static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) { int r; assert(link); - assert(link->ndisc_messages > 0); - - link->ndisc_messages--; r = route_configure_handler_internal(rtnl, m, link, "Could not set NDisc route"); if (r <= 0) @@ -254,13 +251,10 @@ static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) { ndisc_route_handler, NULL); } -static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) { int r; assert(link); - assert(link->ndisc_messages > 0); - - link->ndisc_messages--; r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address"); if (r <= 0) diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 33fa5e21ecf..1cb5333b661 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -215,14 +215,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) { if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) { @@ -243,17 +236,11 @@ int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) { return 1; } -static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Neighbor *neighbor) { int r; assert(m); assert(link); - assert(link->static_neighbor_messages > 0); - - 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) { @@ -271,13 +258,7 @@ static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_messag return 1; } -static int link_request_neighbor( - Link *link, - const Neighbor *neighbor, - unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, - Request **ret) { - +static int link_request_neighbor(Link *link, const Neighbor *neighbor) { Neighbor *existing; int r; @@ -302,7 +283,9 @@ static int link_request_neighbor( log_neighbor_debug(existing, "Requesting", link); r = link_queue_request(link, REQUEST_TYPE_NEIGHBOR, existing, false, - message_counter, netlink_handler, ret); + &link->static_neighbor_messages, + (request_netlink_handler_t) static_neighbor_configure_handler, + NULL); if (r <= 0) return r; @@ -321,8 +304,7 @@ int link_request_static_neighbors(Link *link) { link->static_neighbors_configured = false; HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) { - r = link_request_neighbor(link, neighbor, &link->static_neighbor_messages, - static_neighbor_configure_handler, NULL); + r = link_request_neighbor(link, neighbor); if (r < 0) return log_link_warning_errno(link, r, "Could not request neighbor: %m"); } diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 143ecce6c49..219a08e1597 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -485,25 +485,14 @@ static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) { } } - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } -static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, NextHop *nexthop) { int r; + assert(m); assert(link); - assert(link->static_nexthop_messages > 0); - - link->static_nexthop_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) { @@ -583,13 +572,7 @@ int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) { return 1; } -static int link_request_nexthop( - Link *link, - NextHop *nexthop, - unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, - Request **ret) { - +static int link_request_nexthop(Link *link, NextHop *nexthop) { NextHop *existing; int r; @@ -618,7 +601,9 @@ static int link_request_nexthop( log_nexthop_debug(existing, "Requesting", link); r = link_queue_request(link, REQUEST_TYPE_NEXTHOP, existing, false, - message_counter, netlink_handler, ret); + &link->static_nexthop_messages, + (request_netlink_handler_t) static_nexthop_handler, + NULL); if (r <= 0) return r; @@ -639,8 +624,7 @@ int link_request_static_nexthops(Link *link, bool only_ipv4) { if (only_ipv4 && nh->family != AF_INET) continue; - r = link_request_nexthop(link, nh, &link->static_nexthop_messages, - static_nexthop_handler, NULL); + r = link_request_nexthop(link, nh); if (r < 0) return log_link_warning_errno(link, r, "Could not request nexthop: %m"); } diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 70edc27fcdf..a509cd4d4b6 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "netlink-util.h" #include "networkd-address.h" #include "networkd-address-label.h" #include "networkd-bridge-fdb.h" @@ -89,12 +90,16 @@ static Request *request_free(Request *req) { if (req->consume_object) request_free_object(req->type, req->object); + if (req->counter) + (*req->counter)--; + link_unref(req->link); /* link may be NULL, but link_unref() can handle it gracefully. */ return mfree(req); } DEFINE_TRIVIAL_REF_UNREF_FUNC(Request, request, request_free); +DEFINE_TRIVIAL_DESTRUCTOR(request_destroy_callback, Request, request_unref); void request_detach(Manager *manager, Request *req) { assert(manager); @@ -107,13 +112,6 @@ void request_detach(Manager *manager, Request *req) { return; req->manager = NULL; - - if (req->message_counter) { - assert(*req->message_counter > 0); - (*req->message_counter)--; - req->message_counter = NULL; /* To prevent double decrement. */ - } - request_unref(req); } @@ -301,8 +299,8 @@ int link_queue_request( RequestType type, void *object, bool consume_object, - unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, + unsigned *counter, + request_netlink_handler_t netlink_handler, Request **ret) { _cleanup_(request_unrefp) Request *req = NULL; @@ -343,7 +341,6 @@ int link_queue_request( .type = type, .object = object, .consume_object = consume_object, - .message_counter = message_counter, .netlink_handler = netlink_handler, }; @@ -359,8 +356,9 @@ int link_queue_request( return r; req->manager = link->manager; - if (req->message_counter) - (*req->message_counter)++; + req->counter = counter; + if (req->counter) + (*req->counter)++; if (ret) *ret = req; @@ -447,14 +445,14 @@ int manager_process_requests(sd_event_source *s, void *userdata) { default: return -EINVAL; } - if (r < 0) { - if (req->link) - link_enter_failed(req->link); - } else if (r > 0) { - req->message_counter = NULL; - request_detach(manager, req); - processed = true; - } + if (r == 0) + continue; + + processed = true; + request_detach(manager, req); + + if (r < 0 && req->link) + link_enter_failed(req->link); } if (!processed) @@ -463,3 +461,36 @@ int manager_process_requests(sd_event_source *s, void *userdata) { return 0; } + +static int request_netlink_handler(sd_netlink *nl, sd_netlink_message *m, Request *req) { + assert(req); + + if (req->counter) { + assert(*req->counter > 0); + (*req->counter)--; + req->counter = NULL; /* To prevent double decrement on free. */ + } + + if (req->link && IN_SET(req->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 0; + + if (req->netlink_handler) + return req->netlink_handler(nl, m, req, req->link, req->object); + + return 0; +} + +int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req) { + int r; + + assert(nl); + assert(m); + assert(req); + + r = netlink_call_async(nl, NULL, m, request_netlink_handler, request_destroy_callback, req); + if (r < 0) + return r; + + request_ref(req); + return 0; +} diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 14403efdd08..ac4c5c13af3 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -2,6 +2,7 @@ #pragma once #include "sd-event.h" +#include "sd-netlink.h" #include "networkd-link.h" @@ -16,6 +17,9 @@ typedef struct Route Route; typedef struct RoutingPolicyRule RoutingPolicyRule; typedef struct QDisc QDisc; typedef struct TClass TClass; +typedef struct Request Request; + +typedef int (*request_netlink_handler_t)(sd_netlink *nl, sd_netlink_message *m, Request *req, Link *link, void *userdata); typedef enum RequestType { REQUEST_TYPE_ACTIVATE_LINK, @@ -43,7 +47,7 @@ typedef enum RequestType { _REQUEST_TYPE_INVALID = -EINVAL, } RequestType; -typedef struct Request { +struct Request { unsigned n_ref; Manager *manager; /* must be non-NULL */ @@ -68,9 +72,15 @@ typedef struct Request { void *object; }; void *userdata; - unsigned *message_counter; - link_netlink_message_handler_t netlink_handler; -} Request; + + /* incremented when requested, decremented when request is completed or failed. */ + unsigned *counter; + /* called in netlink handler, the 'counter' is decremented before this is called. + * If this is specified, then the 'process' function must increment the reference of this + * request, and pass this request to the netlink_call_async(), and set the destroy function + * to the slot. */ + request_netlink_handler_t netlink_handler; +}; Request *request_ref(Request *req); Request *request_unref(Request *req); @@ -87,8 +97,9 @@ int link_queue_request( RequestType type, void *object, bool consume_object, - unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, + unsigned *counter, + request_netlink_handler_t netlink_handler, Request **ret); int manager_process_requests(sd_event_source *s, void *userdata); +int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 9be1190655e..cfc69679632 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1141,9 +1141,6 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li assert(link); assert(error_msg); - 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 set route"); @@ -1246,13 +1243,7 @@ static int route_configure(const Route *route, Link *link, Request *req) { return r; } - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static int route_is_ready_to_configure(const Route *route, Link *link) { @@ -1385,7 +1376,7 @@ int link_request_route( Route *route, bool consume_object, unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, + route_netlink_handler_t netlink_handler, Request **ret) { Route *existing; @@ -1433,7 +1424,7 @@ int link_request_route( log_route_debug(existing, "Requesting", link, link->manager); r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false, - message_counter, netlink_handler, ret); + message_counter, (request_netlink_handler_t) netlink_handler, ret); if (r <= 0) return r; @@ -1441,13 +1432,10 @@ int link_request_route( return 1; } -static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) { int r; assert(link); - assert(link->static_route_messages > 0); - - link->static_route_messages--; r = route_configure_handler_internal(rtnl, m, link, "Could not set route"); if (r <= 0) @@ -1473,7 +1461,9 @@ static int link_request_static_route(Link *link, Route *route) { log_route_debug(route, "Requesting", link, link->manager); return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false, - &link->static_route_messages, static_route_handler, NULL); + &link->static_route_messages, + (request_netlink_handler_t) static_route_handler, + NULL); } static int link_request_wireguard_routes(Link *link, bool only_ipv4) { diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 634ed16176a..8c1c5cf6809 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -14,8 +14,15 @@ typedef struct Manager Manager; typedef struct Network Network; typedef struct Request Request; +typedef struct Route Route; +typedef int (*route_netlink_handler_t)( + sd_netlink *rtnl, + sd_netlink_message *m, + Request *req, + Link *link, + Route *route); -typedef struct Route { +struct Route { Link *link; Manager *manager; Network *network; @@ -66,7 +73,7 @@ typedef struct Route { usec_t lifetime_usec; /* Used when kernel does not support RTA_EXPIRES attribute. */ sd_event_source *expire; -} Route; +}; void route_hash_func(const Route *route, struct siphash *state); int route_compare_func(const Route *a, const Route *b); @@ -92,7 +99,7 @@ int link_request_route( Route *route, bool consume_object, unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, + route_netlink_handler_t netlink_handler, Request **ret); int link_request_static_routes(Link *link, bool only_ipv4); int route_process_request(Request *req, Link *link, Route *route); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index a90c176f769..535af175a32 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -626,13 +626,7 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, Re if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) { @@ -742,19 +736,17 @@ int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyR return 1; } -static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int static_routing_policy_rule_configure_handler( + sd_netlink *rtnl, + sd_netlink_message *m, + Request *req, + Link *link, + RoutingPolicyRule *rule) { + int r; - assert(rtnl); assert(m); assert(link); - assert(link->ifname); - assert(link->static_routing_policy_rule_messages > 0); - - link->static_routing_policy_rule_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) { @@ -772,13 +764,7 @@ static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_net return 1; } -static int link_request_routing_policy_rule( - Link *link, - RoutingPolicyRule *rule, - unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, - Request **ret) { - +static int link_request_routing_policy_rule(Link *link, RoutingPolicyRule *rule) { RoutingPolicyRule *existing; int r; @@ -808,7 +794,9 @@ static int link_request_routing_policy_rule( log_routing_policy_rule_debug(existing, "Requesting", link, link->manager); r = link_queue_request(link, REQUEST_TYPE_ROUTING_POLICY_RULE, existing, false, - message_counter, netlink_handler, ret); + &link->static_routing_policy_rule_messages, + (request_netlink_handler_t) static_routing_policy_rule_configure_handler, + NULL); if (r <= 0) return r; @@ -820,26 +808,17 @@ static int link_request_static_routing_policy_rule(Link *link, RoutingPolicyRule int r; if (IN_SET(rule->family, AF_INET, AF_INET6)) - return link_request_routing_policy_rule(link, rule, - &link->static_routing_policy_rule_messages, - static_routing_policy_rule_configure_handler, - NULL); + return link_request_routing_policy_rule(link, rule); rule->family = AF_INET; - r = link_request_routing_policy_rule(link, rule, - &link->static_routing_policy_rule_messages, - static_routing_policy_rule_configure_handler, - NULL); + r = link_request_routing_policy_rule(link, rule); if (r < 0) { rule->family = AF_UNSPEC; return r; } rule->family = AF_INET6; - r = link_request_routing_policy_rule(link, rule, - &link->static_routing_policy_rule_messages, - static_routing_policy_rule_configure_handler, - NULL); + r = link_request_routing_policy_rule(link, rule); rule->family = AF_UNSPEC; return r; } diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index f5d879af78a..b012967462f 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -54,22 +54,19 @@ static int get_link_update_flag_handler(sd_netlink *rtnl, sd_netlink_message *m, static int set_link_handler_internal( sd_netlink *rtnl, sd_netlink_message *m, + Request *req, Link *link, - SetLinkOperation op, bool ignore, link_netlink_message_handler_t get_link_handler) { + SetLinkOperation op; int r; assert(m); + assert(req); assert(link); - assert(link->set_link_messages > 0); - assert(op >= 0 && op < _SET_LINK_OPERATION_MAX); - - link->set_link_messages--; - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - goto on_error; + op = PTR_TO_INT(req->set_link_operation_ptr); r = sd_netlink_message_get_errno(m); if (r < 0) { @@ -80,7 +77,7 @@ static int set_link_handler_internal( if (!ignore) link_enter_failed(link); - goto on_error; + return 0; } log_link_debug(link, "%s set.", set_link_operation_to_string(op)); @@ -89,7 +86,7 @@ static int set_link_handler_internal( r = link_call_getlink(link, get_link_handler); if (r < 0) { link_enter_failed(link); - goto on_error; + return 0; } } @@ -97,27 +94,12 @@ static int set_link_handler_internal( link_check_ready(link); return 1; - -on_error: - switch (op) { - case SET_LINK_FLAGS: - assert(link->set_flags_messages > 0); - link->set_flags_messages--; - break; - case SET_LINK_MASTER: - link->master_set = true; - break; - default: - break; - } - - return 0; } -static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { int r; - r = set_link_handler_internal(rtnl, m, link, SET_LINK_ADDRESS_GENERATION_MODE, /* ignore = */ true, NULL); + r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL); if (r <= 0) return r; @@ -130,49 +112,43 @@ static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m return 0; } -static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_BOND, /* ignore = */ false, NULL); +static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL); } -static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_BRIDGE, /* ignore = */ true, NULL); +static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL); } -static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_BRIDGE_VLAN, /* ignore = */ false, NULL); +static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL); } -static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_CAN, /* ignore = */ false, NULL); +static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL); } -static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_FLAGS, /* ignore = */ false, get_link_update_flag_handler); +static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_default_handler); } -static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_GROUP, /* ignore = */ false, NULL); +static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL); } -static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_IPOIB, /* ignore = */ true, NULL); +static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL); } -static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_MAC, /* ignore = */ true, get_link_default_handler); +static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler); } -static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { int r; assert(m); assert(link); - assert(link->set_link_messages > 0); - - link->set_link_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 0; r = sd_netlink_message_get_errno(m); if (r == -EBUSY) { @@ -189,24 +165,22 @@ static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message return 0; } - /* set_link_mac_handler() also decrements set_link_messages, so increment the value once. */ - link->set_link_messages++; - return link_set_mac_handler(rtnl, m, link); + return link_set_mac_handler(rtnl, m, req, link, userdata); } -static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return set_link_handler_internal(rtnl, m, link, SET_LINK_MASTER, /* ignore = */ false, get_link_master_handler); +static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_master_handler); } -static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { /* Some devices do not support setting master ifindex. Let's ignore error on unsetting master ifindex. */ - return set_link_handler_internal(rtnl, m, link, SET_LINK_MASTER, /* ignore = */ true, get_link_master_handler); + return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_master_handler); } -static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { int r; - r = set_link_handler_internal(rtnl, m, link, SET_LINK_MTU, /* ignore = */ true, get_link_default_handler); + r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler); if (r <= 0) return r; @@ -460,44 +434,34 @@ static int link_configure_fill_message( return 0; } -static int link_configure( - Link *link, - SetLinkOperation op, - void *userdata, - link_netlink_message_handler_t callback) { - - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; +static int link_configure(Link *link, Request *req) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + SetLinkOperation op; int r; assert(link); assert(link->manager); assert(link->manager->rtnl); - assert(link->network); - assert(op >= 0 && op < _SET_LINK_OPERATION_MAX); - assert(callback); + assert(req); + + op = PTR_TO_INT(req->set_link_operation_ptr); log_link_debug(link, "Setting %s", set_link_operation_to_string(op)); if (op == SET_LINK_BOND) - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->master_ifindex); + r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->master_ifindex); else if (IN_SET(op, SET_LINK_CAN, SET_LINK_IPOIB)) - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->ifindex); + r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex); else - 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 log_link_debug_errno(link, r, "Could not allocate netlink message: %m"); + return r; - r = link_configure_fill_message(link, req, op, userdata); + r = link_configure_fill_message(link, m, op, req->userdata); if (r < 0) - return log_link_debug_errno(link, r, "Could not create netlink message: %m"); - - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, - link_netlink_destroy_callback, link); - if (r < 0) - return log_link_debug_errno(link, r, "Could not send netlink message: %m"); + return r; - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static bool netdev_is_ready(NetDev *netdev) { @@ -641,21 +605,18 @@ int request_process_set_link(Request *req) { if (!link_is_ready_to_call_set_link(req)) return 0; - r = link_configure(req->link, op, req->userdata, req->netlink_handler); + r = link_configure(req->link, req); if (r < 0) return log_link_error_errno(req->link, r, "Failed to set %s: %m", set_link_operation_to_string(op)); - if (op == SET_LINK_FLAGS) - req->link->set_flags_messages++; - return 1; } static int link_request_set_link( Link *link, SetLinkOperation op, - link_netlink_message_handler_t netlink_handler, + request_netlink_handler_t netlink_handler, Request **ret) { Request *req; @@ -991,14 +952,16 @@ static int link_up_dsa_slave(Link *link) { return 1; } -static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool up, bool on_activate) { +static int link_up_or_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) { + bool on_activate, up; int r; assert(m); + assert(req); assert(link); - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - goto on_error; + on_activate = req->type == REQUEST_TYPE_ACTIVATE_LINK; + up = PTR_TO_INT(req->userdata); r = sd_netlink_message_get_errno(m); if (r == -ENETDOWN && up && link_up_dsa_slave(link) > 0) @@ -1012,45 +975,25 @@ static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message log_link_message_warning_errno(link, m, r, error_msg); if (on_activate) - goto on_error; + return 0; } r = link_call_getlink(link, get_link_update_flag_handler); if (r < 0) { link_enter_failed(link); - goto on_error; + return 0; } + link->set_flags_messages++; + if (on_activate) { link->activated = true; link_check_ready(link); } - return 1; - -on_error: - assert(link->set_flags_messages > 0); - link->set_flags_messages--; - return 0; } -static int link_activate_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ true); -} - -static int link_activate_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ true); -} - -static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ false); -} - -static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ false); -} - static const char *up_or_down(bool up) { return up ? "up" : "down"; } @@ -1074,14 +1017,7 @@ static int link_up_or_down(Link *link, bool up, Request *req) { if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static bool link_is_ready_to_activate(Link *link) { @@ -1146,7 +1082,7 @@ int link_request_to_activate(Link *link) { link->activated = false; r = link_queue_request(link, REQUEST_TYPE_ACTIVATE_LINK, NULL, false, &link->set_flags_messages, - up ? link_activate_up_handler : link_activate_down_handler, &req); + link_up_or_down_handler, &req); if (r < 0) return log_link_error_errno(link, r, "Failed to request to activate link: %m"); @@ -1210,7 +1146,7 @@ int link_request_to_bring_up_or_down(Link *link, bool up) { assert(link); r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages, - up ? link_up_handler : link_down_handler, &req); + link_up_or_down_handler, &req); if (r < 0) return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m", up_or_down(up)); diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index fa3b0925b92..6ec6ed0aff7 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -293,15 +293,11 @@ int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *ki return -ENOENT; } -static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, QDisc *qdisc) { int r; + assert(m); assert(link); - assert(link->tc_messages > 0); - link->tc_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) { @@ -347,12 +343,7 @@ static int qdisc_configure(QDisc *qdisc, Link *link, Request *req) { return r; } - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) { @@ -410,7 +401,9 @@ int link_request_qdisc(Link *link, QDisc *qdisc) { log_qdisc_debug(existing, link, "Requesting"); r = link_queue_request(link, REQUEST_TYPE_TC_QDISC, existing, false, - &link->tc_messages, qdisc_handler, NULL); + &link->tc_messages, + (request_netlink_handler_t) qdisc_handler, + NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request QDisc: %m"); if (r == 0) diff --git a/src/network/tc/tclass.c b/src/network/tc/tclass.c index b5b3615d988..42011a93e8f 100644 --- a/src/network/tc/tclass.c +++ b/src/network/tc/tclass.c @@ -255,15 +255,11 @@ static void log_tclass_debug(TClass *tclass, Link *link, const char *str) { strna(tclass_get_tca_kind(tclass))); } -static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, TClass *tclass) { int r; + assert(m); assert(link); - assert(link->tc_messages > 0); - link->tc_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) { @@ -309,12 +305,7 @@ static int tclass_configure(TClass *tclass, Link *link, Request *req) { return r; } - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); - if (r < 0) - return r; - - link_ref(link); - return 0; + return request_call_netlink_async(link->manager->rtnl, m, req); } static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) { @@ -369,7 +360,9 @@ int link_request_tclass(Link *link, TClass *tclass) { log_tclass_debug(existing, link, "Requesting"); r = link_queue_request(link, REQUEST_TYPE_TC_CLASS, existing, false, - &link->tc_messages, tclass_handler, NULL); + &link->tc_messages, + (request_netlink_handler_t) tclass_handler, + NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request TClass: %m"); if (r == 0)