1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-09 01:18:19 +03:00

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.
This commit is contained in:
Yu Watanabe 2022-02-28 09:20:42 +09:00
parent e26d3d407c
commit 80d62d4f1a
22 changed files with 237 additions and 405 deletions

View File

@ -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",

View File

@ -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) {

View File

@ -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)

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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");
}

View File

@ -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)

View File

@ -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");
}

View File

@ -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");
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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");
return r;
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");
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));

View File

@ -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)

View File

@ -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)