From 5b25bdd1a3a46941b3047b8efd70c6ca479f5bab Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 18 Feb 2022 15:24:23 +0900 Subject: [PATCH 01/12] alloc-util: introduce mfree_func_type_t --- src/basic/alloc-util.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h index 65d5175619..57f1b186ee 100644 --- a/src/basic/alloc-util.h +++ b/src/basic/alloc-util.h @@ -13,6 +13,7 @@ #endif typedef void (*free_func_t)(void *p); +typedef void* (*mfree_func_t)(void *p); /* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than * proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */ From f1eef3675c59278a111c1d5f9a9b418d9a02025e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 Mar 2022 10:38:59 +0900 Subject: [PATCH 02/12] network: tc: assign netlink handlers into Request object This should not change any behavior, as req->netlink_handler is always qdisc_handler or tclass_handler. This is just a preparation for a later commit which introduces request_call_netlink_async(). --- src/network/networkd-queue.c | 4 +--- src/network/tc/qdisc.c | 9 +++++---- src/network/tc/tclass.c | 9 +++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 5f420c08c3..b30d0532d1 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -313,9 +313,7 @@ int link_queue_request( REQUEST_TYPE_DHCP4_CLIENT, REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_NDISC, - REQUEST_TYPE_RADV, - REQUEST_TYPE_TC_QDISC, - REQUEST_TYPE_TC_CLASS) || + REQUEST_TYPE_RADV) || netlink_handler); req = new(Request, 1); diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index 7b2dacbd5c..9220299c95 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -319,7 +319,7 @@ static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { return 1; } -static int qdisc_configure(QDisc *qdisc, Link *link) { +static int qdisc_configure(QDisc *qdisc, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -328,6 +328,7 @@ static int qdisc_configure(QDisc *qdisc, Link *link) { assert(link->manager); assert(link->manager->rtnl); assert(link->ifindex > 0); + assert(req); log_qdisc_debug(qdisc, link, "Configuring"); @@ -346,7 +347,7 @@ static int qdisc_configure(QDisc *qdisc, Link *link) { return r; } - r = netlink_call_async(link->manager->rtnl, NULL, m, qdisc_handler, link_netlink_destroy_callback, link); + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -379,7 +380,7 @@ int request_process_qdisc(Request *req) { if (!qdisc_is_ready_to_configure(qdisc, link)) return 0; - r = qdisc_configure(qdisc, link); + r = qdisc_configure(qdisc, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure QDisc: %m"); @@ -411,7 +412,7 @@ 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, NULL, NULL); + &link->tc_messages, 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 e01e151d8f..937727796e 100644 --- a/src/network/tc/tclass.c +++ b/src/network/tc/tclass.c @@ -281,7 +281,7 @@ static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { return 1; } -static int tclass_configure(TClass *tclass, Link *link) { +static int tclass_configure(TClass *tclass, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -290,6 +290,7 @@ static int tclass_configure(TClass *tclass, Link *link) { assert(link->manager); assert(link->manager->rtnl); assert(link->ifindex > 0); + assert(req); log_tclass_debug(tclass, link, "Configuring"); @@ -308,7 +309,7 @@ static int tclass_configure(TClass *tclass, Link *link) { return r; } - r = netlink_call_async(link->manager->rtnl, NULL, m, tclass_handler, link_netlink_destroy_callback, link); + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -338,7 +339,7 @@ int request_process_tclass(Request *req) { if (!tclass_is_ready_to_configure(tclass, link)) return 0; - r = tclass_configure(tclass, link); + r = tclass_configure(tclass, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure TClass: %m"); @@ -370,7 +371,7 @@ 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, NULL, NULL); + &link->tc_messages, tclass_handler, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request TClass: %m"); if (r == 0) From 54ff39f7aecbefeb6f480ea61fbacc4ee554dacc Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 Mar 2022 10:40:59 +0900 Subject: [PATCH 03/12] network: make address_configure() and friends take Request object This should not change any behavior. Just a preparation for a later commit which introduces request_call_netlink_async(). --- src/network/netdev/netdev.c | 9 ++++----- src/network/networkd-address-label.c | 8 ++++---- src/network/networkd-address.c | 12 ++++-------- src/network/networkd-bridge-fdb.c | 8 ++++---- src/network/networkd-bridge-mdb.c | 8 ++++---- src/network/networkd-ipv6-proxy-ndp.c | 12 ++++-------- src/network/networkd-neighbor.c | 12 ++++-------- src/network/networkd-nexthop.c | 12 ++++-------- src/network/networkd-route.c | 12 ++++-------- src/network/networkd-routing-policy-rule.c | 12 ++++-------- src/network/networkd-setlink.c | 17 ++++++++--------- 11 files changed, 48 insertions(+), 74 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index c3cdb4f621..30b2970712 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -578,14 +578,14 @@ static int independent_netdev_create(NetDev *netdev) { return 0; } -static int stacked_netdev_create(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) { +static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(netdev); assert(netdev->manager); assert(link); - assert(callback); + assert(req); r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0); if (r < 0) @@ -595,7 +595,7 @@ static int stacked_netdev_create(NetDev *netdev, Link *link, link_netlink_messag if (r < 0) return r; - r = netlink_call_async(netdev->manager->rtnl, NULL, m, callback, + r = netlink_call_async(netdev->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -639,7 +639,6 @@ int request_process_stacked_netdev(Request *req) { assert(req); assert(req->type == REQUEST_TYPE_NETDEV_STACKED); - assert(req->netlink_handler); netdev = ASSERT_PTR(req->netdev); link = ASSERT_PTR(req->link); @@ -648,7 +647,7 @@ int request_process_stacked_netdev(Request *req) { if (r <= 0) return r; - r = stacked_netdev_create(netdev, link, req->netlink_handler); + r = stacked_netdev_create(netdev, link, req); if (r < 0) return log_netdev_warning_errno(netdev, r, "Failed to create netdev: %m"); diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index da9a1794b7..3447d96cf9 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -95,7 +95,7 @@ static int address_label_configure_handler(sd_netlink *rtnl, sd_netlink_message return 1; } -static int address_label_configure(AddressLabel *label, Link *link, link_netlink_message_handler_t callback) { +static int address_label_configure(AddressLabel *label, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -104,7 +104,7 @@ static int address_label_configure(AddressLabel *label, Link *link, link_netlink assert(link->ifindex > 0); assert(link->manager); assert(link->manager->rtnl); - assert(callback); + assert(req); r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &m, RTM_NEWADDRLABEL, link->ifindex, AF_INET6); @@ -123,7 +123,7 @@ static int address_label_configure(AddressLabel *label, Link *link, link_netlink if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -145,7 +145,7 @@ int request_process_address_label(Request *req) { if (!link_is_ready_to_configure(link, false)) return 0; - r = address_label_configure(req->label, link, req->netlink_handler); + r = address_label_configure(req->label, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure address label: %m"); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index f883c79a9e..bf56335e31 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1036,11 +1036,7 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, return 1; } -static int address_configure( - const Address *address, - Link *link, - link_netlink_message_handler_t callback) { - +static int address_configure(const Address *address, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -1050,7 +1046,7 @@ static int address_configure( assert(link->ifindex > 0); assert(link->manager); assert(link->manager->rtnl); - assert(callback); + assert(req); log_address_debug(address, "Configuring", link); @@ -1091,7 +1087,7 @@ static int address_configure( if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -1130,7 +1126,7 @@ int request_process_address(Request *req) { if (!address_is_ready_to_configure(link, address)) return 0; - r = address_configure(address, link, req->netlink_handler); + r = address_configure(address, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure address: %m"); diff --git a/src/network/networkd-bridge-fdb.c b/src/network/networkd-bridge-fdb.c index b09b2ad735..a7ba2239c6 100644 --- a/src/network/networkd-bridge-fdb.c +++ b/src/network/networkd-bridge-fdb.c @@ -168,14 +168,14 @@ static int bridge_fdb_configure_message(const BridgeFDB *fdb, Link *link, sd_net return 0; } -static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, link_netlink_message_handler_t callback) { +static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(fdb); assert(link); assert(link->manager); - assert(callback); + assert(req); r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_BRIDGE); if (r < 0) @@ -185,7 +185,7 @@ static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, link_netlink_message if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -232,7 +232,7 @@ int request_process_bridge_fdb(Request *req) { if (!bridge_fdb_is_ready_to_configure(fdb, link)) return 0; - r = bridge_fdb_configure(fdb, link, req->netlink_handler); + r = bridge_fdb_configure(fdb, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure bridge FDB: %m"); diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index af01a89f47..4cd98f3545 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -114,7 +114,7 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, } /* send a request to the kernel to add an MDB entry */ -static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) { +static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; struct br_mdb_entry entry; int r; @@ -122,7 +122,7 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message assert(mdb); assert(link); assert(link->manager); - assert(callback); + assert(req); if (DEBUG_LOGGING) { _cleanup_free_ char *a = NULL; @@ -164,7 +164,7 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -217,7 +217,7 @@ int request_process_bridge_mdb(Request *req) { if (!bridge_mdb_is_ready_to_configure(link)) return 0; - r = bridge_mdb_configure(req->mdb, link, req->netlink_handler); + r = bridge_mdb_configure(req->mdb, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure bridge MDB: %m"); diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index 22a75bf56b..5844273be9 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -48,11 +48,7 @@ static int ipv6_proxy_ndp_address_configure_handler(sd_netlink *rtnl, sd_netlink } /* send a request to the kernel to add an IPv6 Proxy entry to the neighbour table */ -static int ipv6_proxy_ndp_address_configure( - const struct in6_addr *address, - Link *link, - link_netlink_message_handler_t callback) { - +static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -60,7 +56,7 @@ static int ipv6_proxy_ndp_address_configure( assert(link); assert(link->manager); assert(link->manager->rtnl); - assert(callback); + assert(req); /* create new netlink message */ r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_INET6); @@ -75,7 +71,7 @@ static int ipv6_proxy_ndp_address_configure( if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -96,7 +92,7 @@ int request_process_ipv6_proxy_ndp_address(Request *req) { if (!link_is_ready_to_configure(link, false)) return 0; - r = ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, link, req->netlink_handler); + r = ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure IPv6 proxy NDP address: %m"); diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 8887389807..13dcba8286 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -193,11 +193,7 @@ static int neighbor_configure_message(Neighbor *neighbor, Link *link, sd_netlink return 0; } -static int neighbor_configure( - Neighbor *neighbor, - Link *link, - link_netlink_message_handler_t callback) { - +static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -206,7 +202,7 @@ static int neighbor_configure( assert(link->ifindex > 0); assert(link->manager); assert(link->manager->rtnl); - assert(callback); + assert(req); log_neighbor_debug(neighbor, "Configuring", link); @@ -219,7 +215,7 @@ static int neighbor_configure( if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -243,7 +239,7 @@ int request_process_neighbor(Request *req) { if (!link_is_ready_to_configure(link, false)) return 0; - r = neighbor_configure(neighbor, link, req->netlink_handler); + r = neighbor_configure(neighbor, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure neighbor: %m"); diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 8f555d9685..ed9d621587 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -425,11 +425,7 @@ static int nexthop_remove(NextHop *nexthop) { return 0; } -static int nexthop_configure( - NextHop *nexthop, - Link *link, - link_netlink_message_handler_t callback) { - +static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -439,7 +435,7 @@ static int nexthop_configure( assert(link->manager); assert(link->manager->rtnl); assert(link->ifindex > 0); - assert(callback); + assert(req); log_nexthop_debug(nexthop, "Configuring", link); @@ -489,7 +485,7 @@ static int nexthop_configure( } } - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -583,7 +579,7 @@ int request_process_nexthop(Request *req) { if (!nexthop_is_ready_to_configure(link, nexthop)) return 0; - r = nexthop_configure(nexthop, link, req->netlink_handler); + r = nexthop_configure(nexthop, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure nexthop"); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 2de75f2485..a33ab92f3a 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1154,11 +1154,7 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li return 1; } -static int route_configure( - const Route *route, - Link *link, - link_netlink_message_handler_t callback) { - +static int route_configure(const Route *route, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -1168,7 +1164,7 @@ static int route_configure( assert(link->manager); assert(link->manager->rtnl); assert(link->ifindex > 0); - assert(callback); + assert(req); log_route_debug(route, "Configuring", link, link->manager); @@ -1250,7 +1246,7 @@ static int route_configure( return r; } - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -1373,7 +1369,7 @@ int request_process_route(Request *req) { } } - r = route_configure(route, link, req->netlink_handler); + r = route_configure(route, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure route: %m"); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 5812aee03b..8ff6b0980c 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -604,11 +604,7 @@ static int routing_policy_rule_remove(RoutingPolicyRule *rule) { return 0; } -static int routing_policy_rule_configure( - RoutingPolicyRule *rule, - Link *link, - link_netlink_message_handler_t callback) { - +static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; @@ -618,7 +614,7 @@ static int routing_policy_rule_configure( assert(link->ifindex > 0); assert(link->manager); assert(link->manager->rtnl); - assert(callback); + assert(req); log_routing_policy_rule_debug(rule, "Configuring", link, link->manager); @@ -630,7 +626,7 @@ static int routing_policy_rule_configure( if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -742,7 +738,7 @@ int request_process_routing_policy_rule(Request *req) { if (!link_is_ready_to_configure(link, false)) return 0; - r = routing_policy_rule_configure(rule, link, req->netlink_handler); + r = routing_policy_rule_configure(rule, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure routing policy rule: %m"); diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 8878de3a2c..69bbff061d 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -1055,26 +1055,26 @@ static const char *up_or_down(bool up) { return up ? "up" : "down"; } -static int link_up_or_down(Link *link, bool up, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; +static int link_up_or_down(Link *link, bool up, Request *req) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(link); assert(link->manager); assert(link->manager->rtnl); - assert(callback); + assert(req); log_link_debug(link, "Bringing link %s", up_or_down(up)); - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex); if (r < 0) return r; - r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP); + r = sd_rtnl_message_link_set_flags(m, up ? IFF_UP : 0, IFF_UP); if (r < 0) return r; - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link); if (r < 0) return r; @@ -1104,7 +1104,6 @@ int request_process_activation(Request *req) { assert(req); assert(req->link); assert(req->type == REQUEST_TYPE_ACTIVATE_LINK); - assert(req->netlink_handler); link = req->link; up = PTR_TO_INT(req->userdata); @@ -1112,7 +1111,7 @@ int request_process_activation(Request *req) { if (!link_is_ready_to_activate(link)) return 0; - r = link_up_or_down(link, up, req->netlink_handler); + r = link_up_or_down(link, up, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to activate link: %m"); @@ -1207,7 +1206,7 @@ int request_process_link_up_or_down(Request *req) { if (!link_is_ready_to_bring_up_or_down(link, up)) return 0; - r = link_up_or_down(link, up, req->netlink_handler); + r = link_up_or_down(link, up, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to bring link %s: %m", up_or_down(up)); From ff51134c93a748524b75b4fd492f9c03cb02f65c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 26 Feb 2022 15:56:39 +0900 Subject: [PATCH 04/12] network: make request_process_address() and friends take Link and corresponding object This also renames e.g. request_process_address() -> address_process_request(). Also, this drops type checks such as `assert(req->type == REQUEST_TYPE_ADDRESS)`, as in the later commits, the function of processing request, e.g. `address_process_request()`, will be assigned to the Request object when it is created. And the request type will be used to distinguish and to avoid deduplicating requests which do not have any assigned objects, like REQUEST_TYPE_DHCP4_CLIENT. Hence, the type checks in process functions are mostly not necessary and redundant. This is mostly cleanups and preparation for later commits, and should not change any behavior. --- src/network/netdev/netdev.c | 19 ++++------ src/network/netdev/netdev.h | 4 +-- src/network/networkd-address-label.c | 11 +++--- src/network/networkd-address-label.h | 2 +- src/network/networkd-address.c | 10 ++---- src/network/networkd-address.h | 2 +- src/network/networkd-bridge-fdb.c | 9 ++--- src/network/networkd-bridge-fdb.h | 2 +- src/network/networkd-bridge-mdb.c | 10 +++--- src/network/networkd-bridge-mdb.h | 2 +- src/network/networkd-dhcp-server.c | 7 ++-- src/network/networkd-dhcp-server.h | 2 +- src/network/networkd-dhcp4.c | 12 ++----- src/network/networkd-dhcp4.h | 2 +- src/network/networkd-dhcp6.c | 10 ++---- src/network/networkd-dhcp6.h | 2 +- src/network/networkd-ipv6-proxy-ndp.c | 10 +++--- src/network/networkd-ipv6-proxy-ndp.h | 2 +- src/network/networkd-ndisc.c | 9 ++--- src/network/networkd-ndisc.h | 2 +- src/network/networkd-neighbor.c | 10 ++---- src/network/networkd-neighbor.h | 2 +- src/network/networkd-nexthop.c | 10 ++---- src/network/networkd-nexthop.h | 2 +- src/network/networkd-queue.c | 40 +++++++++++----------- src/network/networkd-radv.c | 9 ++--- src/network/networkd-radv.h | 2 +- src/network/networkd-route.c | 12 ++----- src/network/networkd-route.h | 2 +- src/network/networkd-routing-policy-rule.c | 10 ++---- src/network/networkd-routing-policy-rule.h | 2 +- src/network/networkd-setlink.c | 22 ++++-------- src/network/networkd-setlink.h | 4 +-- src/network/tc/qdisc.c | 8 ++--- src/network/tc/qdisc.h | 2 +- src/network/tc/tclass.c | 8 ++--- src/network/tc/tclass.h | 2 +- 37 files changed, 99 insertions(+), 177 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 30b2970712..d296d799c3 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -632,16 +632,12 @@ static int netdev_is_ready_to_create(NetDev *netdev, Link *link) { return true; } -int request_process_stacked_netdev(Request *req) { - NetDev *netdev; - Link *link; +int stacked_netdev_process_request(Request *req, Link *link, void *userdata) { + NetDev *netdev = ASSERT_PTR(userdata); int r; assert(req); - assert(req->type == REQUEST_TYPE_NETDEV_STACKED); - - netdev = ASSERT_PTR(req->netdev); - link = ASSERT_PTR(req->link); + assert(link); r = netdev_is_ready_to_create(netdev, link); if (r <= 0) @@ -707,14 +703,11 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) { return 0; } -int request_process_independent_netdev(Request *req) { - NetDev *netdev; +int independent_netdev_process_request(Request *req, Link *link, void *userdata) { + NetDev *netdev = ASSERT_PTR(userdata); int r; - assert(req); - assert(req->type == REQUEST_TYPE_NETDEV_INDEPENDENT); - - netdev = ASSERT_PTR(req->netdev); + assert(!link); r = netdev_is_ready_to_create(netdev, NULL); if (r <= 0) diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index ccf58f7ccb..4c2e949fb2 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -209,8 +209,8 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink); int netdev_generate_hw_addr(NetDev *netdev, Link *link, const char *name, const struct hw_addr_data *hw_addr, struct hw_addr_data *ret); -int request_process_independent_netdev(Request *req); -int request_process_stacked_netdev(Request *req); +int independent_netdev_process_request(Request *req, Link *link, void *userdata); +int stacked_netdev_process_request(Request *req, Link *link, void *userdata); int link_request_stacked_netdev(Link *link, NetDev *netdev); const char *netdev_kind_to_string(NetDevKind d) _const_; diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 3447d96cf9..c165cde092 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -132,20 +132,17 @@ static int address_label_configure(AddressLabel *label, Link *link, Request *req return 0; } -int request_process_address_label(Request *req) { - Link *link; +int address_label_process_request(Request *req, Link *link, void *userdata) { + AddressLabel *label = ASSERT_PTR(userdata); int r; assert(req); - assert(req->label); - assert(req->type == REQUEST_TYPE_ADDRESS_LABEL); - - link = ASSERT_PTR(req->link); + assert(link); if (!link_is_ready_to_configure(link, false)) return 0; - r = address_label_configure(req->label, link, req); + r = address_label_configure(label, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure address label: %m"); diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index 582dd05b88..19bb0383e6 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -26,7 +26,7 @@ AddressLabel *address_label_free(AddressLabel *label); void network_drop_invalid_address_labels(Network *network); int link_request_static_address_labels(Link *link); -int request_process_address_label(Request *req); +int address_label_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_address_label); CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index bf56335e31..3164f82c30 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1112,16 +1112,12 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) { return true; } -int request_process_address(Request *req) { - Address *address; - Link *link; +int address_process_request(Request *req, Link *link, Address *address) { int r; assert(req); - assert(req->type == REQUEST_TYPE_ADDRESS); - - address = ASSERT_PTR(req->address); - link = ASSERT_PTR(req->link); + assert(link); + assert(address); if (!address_is_ready_to_configure(link, address)) return 0; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index b116237638..a90dbceb64 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -101,7 +101,7 @@ int link_request_address( Request **ret); int link_request_static_address(Link *link, Address *address, bool consume); int link_request_static_addresses(Link *link); -int request_process_address(Request *req); +int address_process_request(Request *req, Link *link, Address *address); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-bridge-fdb.c b/src/network/networkd-bridge-fdb.c index a7ba2239c6..e8a05e5e13 100644 --- a/src/network/networkd-bridge-fdb.c +++ b/src/network/networkd-bridge-fdb.c @@ -219,15 +219,12 @@ static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) { return true; } -int request_process_bridge_fdb(Request *req) { - BridgeFDB *fdb; - Link *link; +int bridge_fdb_process_request(Request *req, Link *link, void *userdata) { + BridgeFDB *fdb = ASSERT_PTR(userdata); int r; assert(req); - assert(req->type == REQUEST_TYPE_BRIDGE_FDB); - assert_se(link = req->link); - assert_se(fdb = req->fdb); + assert(link); if (!bridge_fdb_is_ready_to_configure(fdb, link)) return 0; diff --git a/src/network/networkd-bridge-fdb.h b/src/network/networkd-bridge-fdb.h index b1098760d2..6a6e80384e 100644 --- a/src/network/networkd-bridge-fdb.h +++ b/src/network/networkd-bridge-fdb.h @@ -47,7 +47,7 @@ void network_drop_invalid_bridge_fdb_entries(Network *network); int link_request_static_bridge_fdb(Link *link); -int request_process_bridge_fdb(Request *req); +int bridge_fdb_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id); diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index 4cd98f3545..b9320f7ea2 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -205,19 +205,17 @@ static bool bridge_mdb_is_ready_to_configure(Link *link) { return true; } -int request_process_bridge_mdb(Request *req) { - Link *link; +int bridge_mdb_process_request(Request *req, Link *link, void *userdata) { + BridgeMDB *mdb = ASSERT_PTR(userdata); int r; assert(req); - assert(req->mdb); - assert(req->type == REQUEST_TYPE_BRIDGE_MDB); - assert_se(link = req->link); + assert(link); if (!bridge_mdb_is_ready_to_configure(link)) return 0; - r = bridge_mdb_configure(req->mdb, link, req); + r = bridge_mdb_configure(mdb, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure bridge MDB: %m"); diff --git a/src/network/networkd-bridge-mdb.h b/src/network/networkd-bridge-mdb.h index ce91e3f572..c9a34af88a 100644 --- a/src/network/networkd-bridge-mdb.h +++ b/src/network/networkd-bridge-mdb.h @@ -25,7 +25,7 @@ BridgeMDB *bridge_mdb_free(BridgeMDB *mdb); void network_drop_invalid_bridge_mdb_entries(Network *network); int link_request_static_bridge_mdb(Link *link); -int request_process_bridge_mdb(Request *req); +int bridge_mdb_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 795ad686af..b11ff073bc 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -567,13 +567,10 @@ static bool dhcp_server_is_ready_to_configure(Link *link) { return true; } -int request_process_dhcp_server(Request *req) { - Link *link; +int dhcp_server_process_request(Request *req, Link *link, void *userdata) { int r; - assert(req); - assert(req->type == REQUEST_TYPE_DHCP_SERVER); - assert_se(link = req->link); + assert(link); if (!dhcp_server_is_ready_to_configure(link)) return 0; diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h index 1af1c65c66..7a204e7d0a 100644 --- a/src/network/networkd-dhcp-server.h +++ b/src/network/networkd-dhcp-server.h @@ -11,7 +11,7 @@ void network_adjust_dhcp_server(Network *network); int link_request_dhcp_server_address(Link *link); int link_request_dhcp_server(Link *link); -int request_process_dhcp_server(Request *req); +int dhcp_server_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 2b985f361a..1aa389bb53 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1597,15 +1597,10 @@ static int dhcp4_configure_duid(Link *link) { return dhcp_configure_duid(link, link_get_dhcp4_duid(link)); } -int request_process_dhcp4_client(Request *req) { - Link *link; +int dhcp4_process_request(Request *req, Link *link, void *userdata) { int r; - assert(req); - assert(req->link); - assert(req->type == REQUEST_TYPE_DHCP4_CLIENT); - - link = req->link; + assert(link); if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return 0; @@ -1619,7 +1614,7 @@ int request_process_dhcp4_client(Request *req) { if (r <= 0) return r; - r = dhcp4_configure(req->link); + r = dhcp4_configure(link); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure DHCPv4 client: %m"); @@ -1629,7 +1624,6 @@ int request_process_dhcp4_client(Request *req) { log_link_debug(link, "DHCPv4 client is configured%s.", r > 0 ? ", acquiring DHCPv4 lease" : ""); - return 1; } diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 830e39f66a..4e466ca4f9 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -25,7 +25,7 @@ int dhcp4_start(Link *link); int dhcp4_lease_lost(Link *link); int dhcp4_check_ready(Link *link); -int request_process_dhcp4_client(Request *req); +int dhcp4_process_request(Request *req, Link *link, void *userdata); int link_request_dhcp4_client(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 244c3a2a4d..3bb013ebaf 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -715,15 +715,10 @@ int dhcp6_update_mac(Link *link) { return 0; } -int request_process_dhcp6_client(Request *req) { - Link *link; +int dhcp6_process_request(Request *req, Link *link, void *userdata) { int r; - assert(req); - assert(req->link); - assert(req->type == REQUEST_TYPE_DHCP6_CLIENT); - - link = req->link; + assert(link); if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return 0; @@ -751,7 +746,6 @@ int request_process_dhcp6_client(Request *req) { log_link_debug(link, "DHCPv6 client is configured%s.", r > 0 ? ", acquiring DHCPv6 lease" : ""); - return 1; } diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index 52347c5e7b..e3bc57cc30 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -21,7 +21,7 @@ int dhcp6_update_mac(Link *link); int dhcp6_start(Link *link); int dhcp6_start_on_ra(Link *link, bool information_request); -int request_process_dhcp6_client(Request *req); +int dhcp6_process_request(Request *req, Link *link, void *userdata); int link_request_dhcp6_client(Link *link); int link_serialize_dhcp6_client(Link *link, FILE *f); diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index 5844273be9..def456c9aa 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -80,19 +80,17 @@ static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link return 0; } -int request_process_ipv6_proxy_ndp_address(Request *req) { - Link *link; +int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address) { int r; assert(req); - assert(req->ipv6_proxy_ndp); - assert(req->type == REQUEST_TYPE_IPV6_PROXY_NDP); - assert_se(link = req->link); + assert(link); + assert(address); if (!link_is_ready_to_configure(link, false)) return 0; - r = ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, link, req); + r = ipv6_proxy_ndp_address_configure(address, link, req); if (r < 0) return log_link_warning_errno(link, r, "Failed to configure IPv6 proxy NDP address: %m"); diff --git a/src/network/networkd-ipv6-proxy-ndp.h b/src/network/networkd-ipv6-proxy-ndp.h index b35cd56182..39a7820599 100644 --- a/src/network/networkd-ipv6-proxy-ndp.h +++ b/src/network/networkd-ipv6-proxy-ndp.h @@ -10,6 +10,6 @@ typedef struct Request Request; void network_adjust_ipv6_proxy_ndp(Network *network); int link_request_static_ipv6_proxy_ndp_addresses(Link *link); -int request_process_ipv6_proxy_ndp_address(Request *req); +int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 7f2366ba70..2f86ade325 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1122,14 +1122,10 @@ int ndisc_start(Link *link) { return 1; } -int request_process_ndisc(Request *req) { - Link *link; +int ndisc_process_request(Request *req, Link *link, void *userdata) { int r; - assert(req); - assert(req->type == REQUEST_TYPE_NDISC); - - link = ASSERT_PTR(req->link); + assert(link); if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return 0; @@ -1148,7 +1144,6 @@ int request_process_ndisc(Request *req) { log_link_debug(link, "IPv6 Router Discovery is configured%s.", r > 0 ? " and started" : ""); - return 1; } diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 1958652778..5a7eb58a56 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -48,7 +48,7 @@ int ndisc_start(Link *link); void ndisc_vacuum(Link *link); void ndisc_flush(Link *link); -int request_process_ndisc(Request *req); +int ndisc_process_request(Request *req, Link *link, void *userdata); int link_request_ndisc(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client); diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 13dcba8286..33fa5e21ec 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -225,16 +225,12 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) { return 0; } -int request_process_neighbor(Request *req) { - Neighbor *neighbor; - Link *link; +int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) { int r; assert(req); - assert(req->type == REQUEST_TYPE_NEIGHBOR); - - neighbor = ASSERT_PTR(req->neighbor); - link = ASSERT_PTR(req->link); + assert(link); + assert(neighbor); if (!link_is_ready_to_configure(link, false)) return 0; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index ac1678de18..52a7733a89 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -39,7 +39,7 @@ int link_drop_foreign_neighbors(Link *link); void link_foreignize_neighbors(Link *link); int link_request_static_neighbors(Link *link); -int request_process_neighbor(Request *req); +int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor); int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index ed9d621587..143ecce6c4 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -565,16 +565,12 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) { return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw); } -int request_process_nexthop(Request *req) { - NextHop *nexthop; - Link *link; +int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) { int r; assert(req); - assert(req->type == REQUEST_TYPE_NEXTHOP); - - nexthop = ASSERT_PTR(req->nexthop); - link = ASSERT_PTR(req->link); + assert(link); + assert(nexthop); if (!nexthop_is_ready_to_configure(link, nexthop)) return 0; diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 16eb02f7eb..c5b58e5d38 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -49,7 +49,7 @@ int link_drop_foreign_nexthops(Link *link); void link_foreignize_nexthops(Link *link); int link_request_static_nexthops(Link *link, bool only_ipv4); -int request_process_nexthop(Request *req); +int nexthop_process_request(Request *req, Link *link, NextHop *nexthop); int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index b30d0532d1..830802324e 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -369,67 +369,67 @@ int manager_process_requests(sd_event_source *s, void *userdata) { ORDERED_SET_FOREACH(req, manager->request_queue) { switch (req->type) { case REQUEST_TYPE_ACTIVATE_LINK: - r = request_process_activation(req); + r = link_process_activation(req, req->link, req->userdata); break; case REQUEST_TYPE_ADDRESS: - r = request_process_address(req); + r = address_process_request(req, req->link, req->address); break; case REQUEST_TYPE_ADDRESS_LABEL: - r = request_process_address_label(req); + r = address_label_process_request(req, req->link, req->label); break; case REQUEST_TYPE_BRIDGE_FDB: - r = request_process_bridge_fdb(req); + r = bridge_fdb_process_request(req, req->link, req->fdb); break; case REQUEST_TYPE_BRIDGE_MDB: - r = request_process_bridge_mdb(req); + r = bridge_mdb_process_request(req, req->link, req->mdb); break; case REQUEST_TYPE_DHCP_SERVER: - r = request_process_dhcp_server(req); + r = dhcp_server_process_request(req, req->link, NULL); break; case REQUEST_TYPE_DHCP4_CLIENT: - r = request_process_dhcp4_client(req); + r = dhcp4_process_request(req, req->link, NULL); break; case REQUEST_TYPE_DHCP6_CLIENT: - r = request_process_dhcp6_client(req); + r = dhcp6_process_request(req, req->link, NULL); break; case REQUEST_TYPE_IPV6_PROXY_NDP: - r = request_process_ipv6_proxy_ndp_address(req); + r = ipv6_proxy_ndp_address_process_request(req, req->link, req->ipv6_proxy_ndp); break; case REQUEST_TYPE_NDISC: - r = request_process_ndisc(req); + r = ndisc_process_request(req, req->link, NULL); break; case REQUEST_TYPE_NEIGHBOR: - r = request_process_neighbor(req); + r = neighbor_process_request(req, req->link, req->neighbor); break; case REQUEST_TYPE_NETDEV_INDEPENDENT: - r = request_process_independent_netdev(req); + r = independent_netdev_process_request(req, req->link, req->netdev); break; case REQUEST_TYPE_NETDEV_STACKED: - r = request_process_stacked_netdev(req); + r = stacked_netdev_process_request(req, req->link, req->netdev); break; case REQUEST_TYPE_NEXTHOP: - r = request_process_nexthop(req); + r = nexthop_process_request(req, req->link, req->nexthop); break; case REQUEST_TYPE_RADV: - r = request_process_radv(req); + r = radv_process_request(req, req->link, NULL); break; case REQUEST_TYPE_ROUTE: - r = request_process_route(req); + r = route_process_request(req, req->link, req->route); break; case REQUEST_TYPE_ROUTING_POLICY_RULE: - r = request_process_routing_policy_rule(req); + r = routing_policy_rule_process_request(req, req->link, req->rule); break; case REQUEST_TYPE_SET_LINK: r = request_process_set_link(req); break; case REQUEST_TYPE_TC_QDISC: - r = request_process_qdisc(req); + r = qdisc_process_request(req, req->link, NULL); break; case REQUEST_TYPE_TC_CLASS: - r = request_process_tclass(req); + r = tclass_process_request(req, req->link, NULL); break; case REQUEST_TYPE_UP_DOWN: - r = request_process_link_up_or_down(req); + r = link_process_up_or_down(req, req->link, req->userdata); break; default: return -EINVAL; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 507f0a0ccc..f6e1841c05 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -582,15 +582,10 @@ static int radv_is_ready_to_configure(Link *link) { return true; } -int request_process_radv(Request *req) { - Link *link; +int radv_process_request(Request *req, Link *link, void *userdata) { int r; - assert(req); - assert(req->link); - assert(req->type == REQUEST_TYPE_RADV); - - link = req->link; + assert(link); r = radv_is_ready_to_configure(link); if (r <= 0) diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 952fa8ae58..0d340c955e 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -68,7 +68,7 @@ int radv_update_mac(Link *link); int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, usec_t lifetime_preferred_usec, usec_t lifetime_valid_usec); -int request_process_radv(Request *req); +int radv_process_request(Request *req, Link *link, void *userdata); int link_request_radv(Link *link); const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index a33ab92f3a..1c5ace643e 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1319,19 +1319,13 @@ static int route_is_ready_to_configure(const Route *route, Link *link) { return true; } -int request_process_route(Request *req) { +int route_process_request(Request *req, Link *link, Route *route) { _cleanup_(converted_routes_freep) ConvertedRoutes *converted = NULL; - Route *route; - Link *link; int r; assert(req); - assert(req->link); - assert(req->route); - assert(req->type == REQUEST_TYPE_ROUTE); - - link = req->link; - route = req->route; + assert(link); + assert(route); r = route_is_ready_to_configure(route, link); if (r < 0) diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index ee8e36f83d..634ed16176 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -95,7 +95,7 @@ int link_request_route( link_netlink_message_handler_t netlink_handler, Request **ret); int link_request_static_routes(Link *link, bool only_ipv4); -int request_process_route(Request *req); +int route_process_request(Request *req, Link *link, Route *route); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 8ff6b0980c..a90c176f76 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -724,16 +724,12 @@ void link_foreignize_routing_policy_rules(Link *link) { } } -int request_process_routing_policy_rule(Request *req) { - RoutingPolicyRule *rule; - Link *link; +int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) { int r; assert(req); - assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE); - - link = ASSERT_PTR(req->link); - rule = ASSERT_PTR(req->rule); + assert(link); + assert(rule); if (!link_is_ready_to_configure(link, false)) return 0; diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 2d1ce19165..2d60e59565 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -64,7 +64,7 @@ int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPo void network_drop_invalid_routing_policy_rules(Network *network); int link_request_static_routing_policy_rules(Link *link); -int request_process_routing_policy_rule(Request *req); +int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule); int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except); diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 69bbff061d..f5d879af78 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -1096,17 +1096,12 @@ static bool link_is_ready_to_activate(Link *link) { return true; } -int request_process_activation(Request *req) { - Link *link; - bool up; +int link_process_activation(Request *req, Link *link, void *userdata) { + bool up = PTR_TO_INT(userdata); int r; assert(req); - assert(req->link); - assert(req->type == REQUEST_TYPE_ACTIVATE_LINK); - - link = req->link; - up = PTR_TO_INT(req->userdata); + assert(link); if (!link_is_ready_to_activate(link)) return 0; @@ -1191,17 +1186,12 @@ static bool link_is_ready_to_bring_up_or_down(Link *link, bool up) { return true; } -int request_process_link_up_or_down(Request *req) { - Link *link; - bool up; +int link_process_up_or_down(Request *req, Link *link, void *userdata) { + bool up = PTR_TO_INT(userdata); int r; assert(req); - assert(req->link); - assert(req->type == REQUEST_TYPE_UP_DOWN); - - link = req->link; - up = PTR_TO_INT(req->userdata); + assert(link); if (!link_is_ready_to_bring_up_or_down(link, up)) return 0; diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h index e943f2012a..3c9853e3ad 100644 --- a/src/network/networkd-setlink.h +++ b/src/network/networkd-setlink.h @@ -42,10 +42,10 @@ int link_configure_mtu(Link *link); int request_process_set_link(Request *req); -int request_process_activation(Request *req); +int link_process_activation(Request *req, Link *link, void *userdata); int link_request_to_activate(Link *link); -int request_process_link_up_or_down(Request *req); +int link_process_up_or_down(Request *req, Link *link, void *userdata); int link_request_to_bring_up_or_down(Link *link, bool up); int link_down_now(Link *link); diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index 9220299c95..fa3b0925b9 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -368,14 +368,12 @@ static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) { return link_find_tclass(link, qdisc->parent, NULL) >= 0; } -int request_process_qdisc(Request *req) { - QDisc *qdisc; - Link *link; +int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) { int r; assert(req); - assert_se(link = req->link); - assert_se(qdisc = req->qdisc); + assert(link); + assert(qdisc); if (!qdisc_is_ready_to_configure(qdisc, link)) return 0; diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h index 54afe97ced..37ec61cbc7 100644 --- a/src/network/tc/qdisc.h +++ b/src/network/tc/qdisc.h @@ -82,7 +82,7 @@ int qdisc_compare_func(const QDisc *a, const QDisc *b); int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **qdisc); -int request_process_qdisc(Request *req); +int qdisc_process_request(Request *req, Link *link, QDisc *qdisc); int link_request_qdisc(Link *link, QDisc *qdisc); void network_drop_invalid_qdisc(Network *network); diff --git a/src/network/tc/tclass.c b/src/network/tc/tclass.c index 937727796e..b5b3615d98 100644 --- a/src/network/tc/tclass.c +++ b/src/network/tc/tclass.c @@ -327,14 +327,12 @@ static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) { return link_find_qdisc(link, tclass->classid, tclass->parent, tclass_get_tca_kind(tclass), NULL) >= 0; } -int request_process_tclass(Request *req) { - TClass *tclass; - Link *link; +int tclass_process_request(Request *req, Link *link, TClass *tclass) { int r; assert(req); - assert_se(link = req->link); - assert_se(tclass = req->tclass); + assert(link); + assert(tclass); if (!tclass_is_ready_to_configure(tclass, link)) return 0; diff --git a/src/network/tc/tclass.h b/src/network/tc/tclass.h index c588b38abe..f7b724b002 100644 --- a/src/network/tc/tclass.h +++ b/src/network/tc/tclass.h @@ -64,7 +64,7 @@ int tclass_compare_func(const TClass *a, const TClass *b); int link_find_tclass(Link *link, uint32_t classid, TClass **ret); -int request_process_tclass(Request *req); +int tclass_process_request(Request *req, Link *link, TClass *tclass); int link_request_tclass(Link *link, TClass *tclass); void network_drop_invalid_tclass(Network *network); From e9ef9a1484e39c468b372f75058fef8c59009deb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 27 Feb 2022 15:18:01 +0900 Subject: [PATCH 05/12] network: introduce reference counter for Request object Currently, all Request object are always owned by Manager, and freed when it is processed, especially, soon after a netlink message is sent. So, it is not necessary to introduce the reference counter. In a later commit, the Request object will _not_ be freed at the time when a netlink message is sent, but assigned to the relevant netlink slot as a userdata, and will be freed when a reply is received. So, the owner of the Request object is changed in its lifetime. In that case, it is convenient that the object has reference counter to avoid memleak or double free. --- src/network/networkd-queue.c | 14 ++++++++------ src/network/networkd-queue.h | 6 ++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 830802324e..06a0cb066e 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -92,7 +92,7 @@ static Request *request_free(Request *req) { return mfree(req); } -DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free); +DEFINE_TRIVIAL_REF_UNREF_FUNC(Request, request, request_free); void request_drop(Request *req) { if (!req) @@ -101,7 +101,7 @@ void request_drop(Request *req) { if (req->message_counter) (*req->message_counter)--; - request_free(req); + request_unref(req); } static void request_hash_func(const Request *req, struct siphash *state) { @@ -238,13 +238,13 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( Request, request_hash_func, request_compare_func, - request_free); + request_unref); int netdev_queue_request( NetDev *netdev, Request **ret) { - _cleanup_(request_freep) Request *req = NULL; + _cleanup_(request_unrefp) Request *req = NULL; Request *existing; int r; @@ -256,6 +256,7 @@ int netdev_queue_request( return -ENOMEM; *req = (Request) { + .n_ref = 1, .netdev = netdev_ref(netdev), .type = REQUEST_TYPE_NETDEV_INDEPENDENT, .consume_object = true, @@ -291,7 +292,7 @@ int link_queue_request( link_netlink_message_handler_t netlink_handler, Request **ret) { - _cleanup_(request_freep) Request *req = NULL; + _cleanup_(request_unrefp) Request *req = NULL; Request *existing; int r; @@ -324,6 +325,7 @@ int link_queue_request( } *req = (Request) { + .n_ref = 1, .link = link_ref(link), .type = type, .object = object, @@ -439,7 +441,7 @@ int manager_process_requests(sd_event_source *s, void *userdata) { link_enter_failed(req->link); } else if (r > 0) { ordered_set_remove(manager->request_queue, req); - request_free(req); + request_unref(req); processed = true; } } diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 593f3dde6e..7410e5c861 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -44,6 +44,8 @@ typedef enum RequestType { } RequestType; typedef struct Request { + unsigned n_ref; + Link *link; RequestType type; bool consume_object; @@ -68,6 +70,10 @@ typedef struct Request { link_netlink_message_handler_t netlink_handler; } Request; +Request *request_ref(Request *req); +Request *request_unref(Request *req); +DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_unref); + void request_drop(Request *req); int netdev_queue_request( From e26d3d407cbdf9138139ca9526573c494ed55e81 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 27 Feb 2022 15:39:16 +0900 Subject: [PATCH 06/12] network: make Request object take Manager* Previously, even though all Request object are owned by Manager, they do not have direct reference to Manager, but through Link or NetDev object. But, as Link or NetDev can be NULL, we need to conditionalize how to access Manager from Request with the type of the request. This makes the way simpler, as now Request object has direct reference to Manager. This also rename request_drop() -> request_detach(), as in the previous commit, the reference counter is introduced, so even if a reference of a Request object from Manager is dropped, the object may still alive. The naming `request_drop()` sounds the object will freed by the function. But it may not. And `request_detach()` suggests the object will not be managed by Manager any more, and I think it is more appropreate. This is just a cleanup, and should not change any behavior. --- src/network/networkd-address.c | 2 +- src/network/networkd-link.c | 2 +- src/network/networkd-queue.c | 41 +++++++++++++++++++++------------- src/network/networkd-queue.h | 6 +++-- src/network/networkd-route.c | 2 +- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 3164f82c30..63b40da432 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1295,7 +1295,7 @@ void address_cancel_request(Address *address) { .address = address, }; - request_drop(ordered_set_get(address->link->manager->request_queue, &req)); + request_detach(address->link->manager, &req); address_cancel_requesting(address); } diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 48f8e40fb4..e925739d06 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -906,7 +906,7 @@ static void link_drop_requests(Link *link) { ORDERED_SET_FOREACH(req, link->manager->request_queue) if (req->link == link) - request_drop(req); + request_detach(link->manager, req); } static Link *link_drop(Link *link) { diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 06a0cb066e..70edc27fcd 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -81,25 +81,38 @@ static Request *request_free(Request *req) { if (!req) return NULL; - if (req->link && req->link->manager) - /* To prevent from triggering assertions in hash functions, remove this request before - * freeing object below. */ - ordered_set_remove(req->link->manager->request_queue, req); + /* To prevent from triggering assertions in the hash and compare functions, remove this request + * before freeing userdata below. */ + if (req->manager) + ordered_set_remove(req->manager->request_queue, req); + if (req->consume_object) request_free_object(req->type, req->object); - link_unref(req->link); + + 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); -void request_drop(Request *req) { +void request_detach(Manager *manager, Request *req) { + assert(manager); + if (!req) return; - if (req->message_counter) + req = ordered_set_remove(manager->request_queue, req); + if (!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); } @@ -257,6 +270,7 @@ int netdev_queue_request( *req = (Request) { .n_ref = 1, + .manager = netdev->manager, .netdev = netdev_ref(netdev), .type = REQUEST_TYPE_NETDEV_INDEPENDENT, .consume_object = true, @@ -264,9 +278,6 @@ int netdev_queue_request( existing = ordered_set_get(netdev->manager->request_queue, req); if (existing) { - /* To prevent from removing the existing request. */ - req->netdev = netdev_unref(req->netdev); - if (ret) *ret = existing; return 0; @@ -276,6 +287,8 @@ int netdev_queue_request( if (r < 0) return r; + req->manager = netdev->manager; + if (ret) *ret = req; @@ -336,9 +349,6 @@ int link_queue_request( existing = ordered_set_get(link->manager->request_queue, req); if (existing) { - /* To prevent from removing the existing request. */ - req->link = link_unref(req->link); - if (ret) *ret = existing; return 0; @@ -348,6 +358,7 @@ int link_queue_request( if (r < 0) return r; + req->manager = link->manager; if (req->message_counter) (*req->message_counter)++; @@ -440,8 +451,8 @@ int manager_process_requests(sd_event_source *s, void *userdata) { if (req->link) link_enter_failed(req->link); } else if (r > 0) { - ordered_set_remove(manager->request_queue, req); - request_unref(req); + req->message_counter = NULL; + request_detach(manager, req); processed = true; } } diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 7410e5c861..14403efdd0 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -46,7 +46,9 @@ typedef enum RequestType { typedef struct Request { unsigned n_ref; - Link *link; + Manager *manager; /* must be non-NULL */ + Link *link; /* can be NULL */ + RequestType type; bool consume_object; union { @@ -74,7 +76,7 @@ Request *request_ref(Request *req); Request *request_unref(Request *req); DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_unref); -void request_drop(Request *req); +void request_detach(Manager *manager, Request *req); int netdev_queue_request( NetDev *netdev, diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 1c5ace643e..9be1190655 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1560,7 +1560,7 @@ void route_cancel_request(Route *route, Link *link) { .route = route, }; - request_drop(ordered_set_get(link->manager->request_queue, &req)); + request_detach(link->manager, &req); route_cancel_requesting(route); } From 80d62d4f1aa62c03828e4cbe2c2dfb2a19765af8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 28 Feb 2022 09:20:42 +0900 Subject: [PATCH 07/12] 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. --- src/network/netdev/netdev.c | 15 +- src/network/networkd-address-label.c | 24 +-- src/network/networkd-address.c | 19 +- src/network/networkd-address.h | 8 +- src/network/networkd-bridge-fdb.c | 17 +- src/network/networkd-bridge-mdb.c | 17 +- src/network/networkd-dhcp-prefix-delegation.c | 22 +-- src/network/networkd-dhcp4.c | 14 +- src/network/networkd-dhcp6.c | 5 +- src/network/networkd-ipv4ll.c | 2 +- src/network/networkd-ipv6-proxy-ndp.c | 23 ++- src/network/networkd-ndisc.c | 10 +- src/network/networkd-neighbor.c | 32 +-- src/network/networkd-nexthop.c | 32 +-- src/network/networkd-queue.c | 71 +++++-- src/network/networkd-queue.h | 23 ++- src/network/networkd-route.c | 24 +-- src/network/networkd-route.h | 13 +- src/network/networkd-routing-policy-rule.c | 51 ++--- src/network/networkd-setlink.c | 182 ++++++------------ src/network/tc/qdisc.c | 19 +- src/network/tc/tclass.c | 19 +- 22 files changed, 237 insertions(+), 405 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index d296d799c3..ee3b883b5c 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 c165cde092..5c31a44ce4 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 63b40da432..e9a79d352d 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 a90dbceb64..a41274a1fc 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 e8a05e5e13..cc02213c28 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 b9320f7ea2..88ae091c1a 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 bba66f71ed..edc893e9f6 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 1aa389bb53..dcde7f9bed 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 3bb013ebaf..bceae735b0 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 5e3854281c..67eb9d2aa1 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 def456c9aa..b245a9eba2 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 2f86ade325..2a85fb3cfb 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 33fa5e21ec..1cb5333b66 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 143ecce6c4..219a08e159 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 70edc27fcd..a509cd4d4b 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 14403efdd0..ac4c5c13af 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 9be1190655..cfc6967963 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 634ed16176..8c1c5cf680 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 a90c176f76..535af175a3 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 f5d879af78..b012967462 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"); + 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)); diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index fa3b0925b9..6ec6ed0aff 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 b5b3615d98..42011a93e8 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) From e51928640720bb9e1464203ab50625afe6a7523f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 28 Feb 2022 11:00:56 +0900 Subject: [PATCH 08/12] network: drop unnecessary link_enter_failed() As returning negative errno makes the link will enter the failed state. --- src/network/networkd-setlink.c | 42 +++++++++++++++------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index b012967462..a3b52dc8d2 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -475,17 +475,15 @@ static bool netdev_is_ready(NetDev *netdev) { return true; } -static bool link_is_ready_to_call_set_link(Request *req) { +static int link_is_ready_to_set_link(Link *link, Request *req) { SetLinkOperation op; - Link *link; int r; + assert(link); + assert(link->manager); + assert(link->network); assert(req); - assert(req->link); - assert(req->link->manager); - assert(req->link->network); - link = req->link; op = PTR_TO_INT(req->set_link_operation_ptr); if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) @@ -511,10 +509,8 @@ static bool link_is_ready_to_call_set_link(Request *req) { if (FLAGS_SET(link->flags, IFF_UP)) { /* The CAN interface must be down to configure bitrate, etc... */ r = link_down_now(link); - if (r < 0) { - link_enter_failed(link); - return false; - } + if (r < 0) + return r; } break; case SET_LINK_MAC: @@ -523,10 +519,8 @@ static bool link_is_ready_to_call_set_link(Request *req) { * req->netlink_handler points to link_set_mac_allow_retry_handler(). * The first attempt failed as the interface was up. */ r = link_down_now(link); - if (r < 0) { - link_enter_failed(link); - return false; - } + if (r < 0) + return r; } break; case SET_LINK_MASTER: { @@ -553,10 +547,8 @@ static bool link_is_ready_to_call_set_link(Request *req) { if (FLAGS_SET(link->flags, IFF_UP)) { /* link must be down when joining to bond master. */ r = link_down_now(link); - if (r < 0) { - link_enter_failed(link); - return false; - } + if (r < 0) + return r; } } else if (link->network->bridge) { if (ordered_set_contains(link->manager->request_queue, &req_mac)) @@ -591,24 +583,26 @@ static bool link_is_ready_to_call_set_link(Request *req) { int request_process_set_link(Request *req) { SetLinkOperation op; + Link *link; int r; assert(req); - assert(req->link); assert(req->type == REQUEST_TYPE_SET_LINK); assert(req->netlink_handler); + assert_se(link = req->link); op = PTR_TO_INT(req->set_link_operation_ptr); assert(op >= 0 && op < _SET_LINK_OPERATION_MAX); - if (!link_is_ready_to_call_set_link(req)) - return 0; + r = link_is_ready_to_set_link(link, req); + if (r <= 0) + return r; - r = link_configure(req->link, req); + r = link_configure(link, req); if (r < 0) - return log_link_error_errno(req->link, r, "Failed to set %s: %m", - set_link_operation_to_string(op)); + return log_link_warning_errno(link, r, "Failed to set %s: %m", + set_link_operation_to_string(op)); return 1; } From a48ffe47cf1db98694d2013bf97f62f55e4c3d27 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 28 Feb 2022 11:15:01 +0900 Subject: [PATCH 09/12] network: refuse to configure link properties when in initialized state The condition should be satisfied only when users request to reconfigure the link, and in that case, all request will be cancelled. Hence, it is not necessary to process the request. --- src/network/networkd-setlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index a3b52dc8d2..47dc6720ac 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -486,7 +486,7 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { op = PTR_TO_INT(req->set_link_operation_ptr); - if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return false; switch (op) { @@ -1017,7 +1017,7 @@ static int link_up_or_down(Link *link, bool up, Request *req) { static bool link_is_ready_to_activate(Link *link) { assert(link); - if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return false; if (link->set_link_messages > 0) From eb93dc9bde7447bb519d69c0e3bc077767936c93 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 28 Feb 2022 11:03:11 +0900 Subject: [PATCH 10/12] network: merge RequestType and SetLinkOperation These two enum indicate how we process the request. Hence, it is not necessary to introduce two separated indicators. --- src/network/networkd-queue.c | 102 ++++++++++++++++++-- src/network/networkd-queue.h | 14 ++- src/network/networkd-setlink.c | 166 ++++++++++++++++----------------- src/network/networkd-setlink.h | 23 +---- 4 files changed, 187 insertions(+), 118 deletions(-) diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index a509cd4d4b..ac378ba675 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -18,6 +18,7 @@ #include "networkd-queue.h" #include "networkd-setlink.h" #include "qdisc.h" +#include "string-table.h" #include "tclass.h" static void request_free_object(RequestType type, void *object) { @@ -63,7 +64,17 @@ static void request_free_object(RequestType type, void *object) { case REQUEST_TYPE_ROUTING_POLICY_RULE: routing_policy_rule_free(object); break; - case REQUEST_TYPE_SET_LINK: + case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: + case REQUEST_TYPE_SET_LINK_BOND: + case REQUEST_TYPE_SET_LINK_BRIDGE: + case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: + case REQUEST_TYPE_SET_LINK_CAN: + case REQUEST_TYPE_SET_LINK_FLAGS: + case REQUEST_TYPE_SET_LINK_GROUP: + case REQUEST_TYPE_SET_LINK_IPOIB: + case REQUEST_TYPE_SET_LINK_MAC: + case REQUEST_TYPE_SET_LINK_MASTER: + case REQUEST_TYPE_SET_LINK_MTU: break; case REQUEST_TYPE_TC_QDISC: qdisc_free(object); @@ -166,8 +177,17 @@ static void request_hash_func(const Request *req, struct siphash *state) { case REQUEST_TYPE_ROUTING_POLICY_RULE: routing_policy_rule_hash_func(req->rule, state); break; - case REQUEST_TYPE_SET_LINK: - trivial_hash_func(req->set_link_operation_ptr, state); + case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: + case REQUEST_TYPE_SET_LINK_BOND: + case REQUEST_TYPE_SET_LINK_BRIDGE: + case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: + case REQUEST_TYPE_SET_LINK_CAN: + case REQUEST_TYPE_SET_LINK_FLAGS: + case REQUEST_TYPE_SET_LINK_GROUP: + case REQUEST_TYPE_SET_LINK_IPOIB: + case REQUEST_TYPE_SET_LINK_MAC: + case REQUEST_TYPE_SET_LINK_MASTER: + case REQUEST_TYPE_SET_LINK_MTU: break; case REQUEST_TYPE_TC_QDISC: qdisc_hash_func(req->qdisc, state); @@ -231,8 +251,18 @@ static int request_compare_func(const struct Request *a, const struct Request *b return 0; case REQUEST_TYPE_ROUTING_POLICY_RULE: return routing_policy_rule_compare_func(a->rule, b->rule); - case REQUEST_TYPE_SET_LINK: - return trivial_compare_func(a->set_link_operation_ptr, b->set_link_operation_ptr); + case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: + case REQUEST_TYPE_SET_LINK_BOND: + case REQUEST_TYPE_SET_LINK_BRIDGE: + case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: + case REQUEST_TYPE_SET_LINK_CAN: + case REQUEST_TYPE_SET_LINK_FLAGS: + case REQUEST_TYPE_SET_LINK_GROUP: + case REQUEST_TYPE_SET_LINK_IPOIB: + case REQUEST_TYPE_SET_LINK_MAC: + case REQUEST_TYPE_SET_LINK_MASTER: + case REQUEST_TYPE_SET_LINK_MTU: + return 0; case REQUEST_TYPE_TC_QDISC: return qdisc_compare_func(a->qdisc, b->qdisc); case REQUEST_TYPE_TC_CLASS: @@ -317,7 +347,17 @@ int link_queue_request( REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_NDISC, REQUEST_TYPE_RADV, - REQUEST_TYPE_SET_LINK, + REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, + REQUEST_TYPE_SET_LINK_BOND, + REQUEST_TYPE_SET_LINK_BRIDGE, + REQUEST_TYPE_SET_LINK_BRIDGE_VLAN, + REQUEST_TYPE_SET_LINK_CAN, + REQUEST_TYPE_SET_LINK_FLAGS, + REQUEST_TYPE_SET_LINK_GROUP, + REQUEST_TYPE_SET_LINK_IPOIB, + REQUEST_TYPE_SET_LINK_MAC, + REQUEST_TYPE_SET_LINK_MASTER, + REQUEST_TYPE_SET_LINK_MTU, REQUEST_TYPE_UP_DOWN) || object); assert(IN_SET(type, @@ -430,8 +470,18 @@ int manager_process_requests(sd_event_source *s, void *userdata) { case REQUEST_TYPE_ROUTING_POLICY_RULE: r = routing_policy_rule_process_request(req, req->link, req->rule); break; - case REQUEST_TYPE_SET_LINK: - r = request_process_set_link(req); + case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: + case REQUEST_TYPE_SET_LINK_BOND: + case REQUEST_TYPE_SET_LINK_BRIDGE: + case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: + case REQUEST_TYPE_SET_LINK_CAN: + case REQUEST_TYPE_SET_LINK_FLAGS: + case REQUEST_TYPE_SET_LINK_GROUP: + case REQUEST_TYPE_SET_LINK_IPOIB: + case REQUEST_TYPE_SET_LINK_MAC: + case REQUEST_TYPE_SET_LINK_MASTER: + case REQUEST_TYPE_SET_LINK_MTU: + r = link_process_set_link(req, req->link, NULL); break; case REQUEST_TYPE_TC_QDISC: r = qdisc_process_request(req, req->link, NULL); @@ -494,3 +544,39 @@ int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *r request_ref(req); return 0; } + +static const char *const request_type_table[_REQUEST_TYPE_MAX] = { + [REQUEST_TYPE_ACTIVATE_LINK] = "activate link", + [REQUEST_TYPE_ADDRESS] = "address", + [REQUEST_TYPE_ADDRESS_LABEL] = "address label", + [REQUEST_TYPE_BRIDGE_FDB] = "bridge FDB", + [REQUEST_TYPE_BRIDGE_MDB] = "bridge MDB", + [REQUEST_TYPE_DHCP_SERVER] = "DHCP server", + [REQUEST_TYPE_DHCP4_CLIENT] = "DHCPv4 client", + [REQUEST_TYPE_DHCP6_CLIENT] = "DHCPv6 client", + [REQUEST_TYPE_IPV6_PROXY_NDP] = "IPv6 proxy NDP", + [REQUEST_TYPE_NDISC] = "NDisc", + [REQUEST_TYPE_NEIGHBOR] = "neighbor", + [REQUEST_TYPE_NETDEV_INDEPENDENT] = "independent netdev", + [REQUEST_TYPE_NETDEV_STACKED] = "stacked netdev", + [REQUEST_TYPE_NEXTHOP] = "nexthop", + [REQUEST_TYPE_RADV] = "RADV", + [REQUEST_TYPE_ROUTE] = "route", + [REQUEST_TYPE_ROUTING_POLICY_RULE] = "routing policy rule", + [REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE] = "IPv6LL address generation mode", + [REQUEST_TYPE_SET_LINK_BOND] = "bond configurations", + [REQUEST_TYPE_SET_LINK_BRIDGE] = "bridge configurations", + [REQUEST_TYPE_SET_LINK_BRIDGE_VLAN] = "bridge VLAN configurations", + [REQUEST_TYPE_SET_LINK_CAN] = "CAN interface configurations", + [REQUEST_TYPE_SET_LINK_FLAGS] = "link flags", + [REQUEST_TYPE_SET_LINK_GROUP] = "interface group", + [REQUEST_TYPE_SET_LINK_IPOIB] = "IPoIB configurations", + [REQUEST_TYPE_SET_LINK_MAC] = "MAC address", + [REQUEST_TYPE_SET_LINK_MASTER] = "master interface", + [REQUEST_TYPE_SET_LINK_MTU] = "MTU", + [REQUEST_TYPE_TC_QDISC] = "QDisc", + [REQUEST_TYPE_TC_CLASS] = "TClass", + [REQUEST_TYPE_UP_DOWN] = "bring link up or down", +}; + +DEFINE_STRING_TABLE_LOOKUP_TO_STRING(request_type, RequestType); diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index ac4c5c13af..0c822094e8 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -39,7 +39,17 @@ typedef enum RequestType { REQUEST_TYPE_RADV, REQUEST_TYPE_ROUTE, REQUEST_TYPE_ROUTING_POLICY_RULE, - REQUEST_TYPE_SET_LINK, + REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */ + REQUEST_TYPE_SET_LINK_BOND, /* Setting bond configs. */ + REQUEST_TYPE_SET_LINK_BRIDGE, /* Setting bridge configs. */ + REQUEST_TYPE_SET_LINK_BRIDGE_VLAN, /* Setting bridge VLAN configs. */ + REQUEST_TYPE_SET_LINK_CAN, /* Setting CAN interface configs. */ + REQUEST_TYPE_SET_LINK_FLAGS, /* Setting IFF_NOARP or friends. */ + REQUEST_TYPE_SET_LINK_GROUP, /* Setting interface group. */ + REQUEST_TYPE_SET_LINK_IPOIB, /* Setting IPoIB configs. */ + REQUEST_TYPE_SET_LINK_MAC, /* Setting MAC address. */ + REQUEST_TYPE_SET_LINK_MASTER, /* Setting IFLA_MASTER. */ + REQUEST_TYPE_SET_LINK_MTU, /* Setting MTU. */ REQUEST_TYPE_TC_CLASS, REQUEST_TYPE_TC_QDISC, REQUEST_TYPE_UP_DOWN, @@ -103,3 +113,5 @@ int link_queue_request( int manager_process_requests(sd_event_source *s, void *userdata); int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req); + +const char* request_type_to_string(RequestType t) _const_; diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 47dc6720ac..5128c33719 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -14,23 +14,6 @@ #include "networkd-manager.h" #include "networkd-queue.h" #include "networkd-setlink.h" -#include "string-table.h" - -static const char *const set_link_operation_table[_SET_LINK_OPERATION_MAX] = { - [SET_LINK_ADDRESS_GENERATION_MODE] = "IPv6LL address generation mode", - [SET_LINK_BOND] = "bond configurations", - [SET_LINK_BRIDGE] = "bridge configurations", - [SET_LINK_BRIDGE_VLAN] = "bridge VLAN configurations", - [SET_LINK_CAN] = "CAN interface configurations", - [SET_LINK_FLAGS] = "link flags", - [SET_LINK_GROUP] = "interface group", - [SET_LINK_IPOIB] = "IPoIB configurations", - [SET_LINK_MAC] = "MAC address", - [SET_LINK_MASTER] = "master interface", - [SET_LINK_MTU] = "MTU", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(set_link_operation, SetLinkOperation); static int get_link_default_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { return link_getlink_handler_internal(rtnl, m, link, "Failed to sync link information"); @@ -59,20 +42,17 @@ static int set_link_handler_internal( bool ignore, link_netlink_message_handler_t get_link_handler) { - SetLinkOperation op; int r; assert(m); assert(req); assert(link); - op = PTR_TO_INT(req->set_link_operation_ptr); - r = sd_netlink_message_get_errno(m); if (r < 0) { const char *error_msg; - error_msg = strjoina("Failed to set ", set_link_operation_to_string(op), ignore ? ", ignoring" : ""); + error_msg = strjoina("Failed to set ", request_type_to_string(req->type), ignore ? ", ignoring" : ""); log_link_message_warning_errno(link, m, r, error_msg); if (!ignore) @@ -80,7 +60,7 @@ static int set_link_handler_internal( return 0; } - log_link_debug(link, "%s set.", set_link_operation_to_string(op)); + log_link_debug(link, "%s set.", request_type_to_string(req->type)); if (get_link_handler) { r = link_call_getlink(link, get_link_handler); @@ -196,17 +176,17 @@ static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request static int link_configure_fill_message( Link *link, sd_netlink_message *req, - SetLinkOperation op, + RequestType type, void *userdata) { int r; - switch (op) { - case SET_LINK_ADDRESS_GENERATION_MODE: + switch (type) { + case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: r = ipv6ll_addrgen_mode_fill_message(req, PTR_TO_UINT8(userdata)); if (r < 0) return r; break; - case SET_LINK_BOND: + case REQUEST_TYPE_SET_LINK_BOND: r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK); if (r < 0) return r; @@ -240,7 +220,7 @@ static int link_configure_fill_message( return r; break; - case SET_LINK_BRIDGE: + case REQUEST_TYPE_SET_LINK_BRIDGE: r = sd_rtnl_message_link_set_family(req, AF_BRIDGE); if (r < 0) return r; @@ -343,7 +323,7 @@ static int link_configure_fill_message( if (r < 0) return r; break; - case SET_LINK_BRIDGE_VLAN: + case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: r = sd_rtnl_message_link_set_family(req, AF_BRIDGE); if (r < 0) return r; @@ -368,12 +348,12 @@ static int link_configure_fill_message( return r; break; - case SET_LINK_CAN: + case REQUEST_TYPE_SET_LINK_CAN: r = can_set_netlink_message(link, req); if (r < 0) return r; break; - case SET_LINK_FLAGS: { + case REQUEST_TYPE_SET_LINK_FLAGS: { unsigned ifi_change = 0, ifi_flags = 0; if (link->network->arp >= 0) { @@ -402,27 +382,27 @@ static int link_configure_fill_message( break; } - case SET_LINK_GROUP: + case REQUEST_TYPE_SET_LINK_GROUP: r = sd_netlink_message_append_u32(req, IFLA_GROUP, (uint32_t) link->network->group); if (r < 0) return r; break; - case SET_LINK_MAC: + case REQUEST_TYPE_SET_LINK_MAC: r = netlink_message_append_hw_addr(req, IFLA_ADDRESS, &link->requested_hw_addr); if (r < 0) return r; break; - case SET_LINK_IPOIB: + case REQUEST_TYPE_SET_LINK_IPOIB: r = ipoib_set_netlink_message(link, req); if (r < 0) return r; break; - case SET_LINK_MASTER: + case REQUEST_TYPE_SET_LINK_MASTER: r = sd_netlink_message_append_u32(req, IFLA_MASTER, PTR_TO_UINT32(userdata)); if (r < 0) return r; break; - case SET_LINK_MTU: + case REQUEST_TYPE_SET_LINK_MTU: r = sd_netlink_message_append_u32(req, IFLA_MTU, PTR_TO_UINT32(userdata)); if (r < 0) return r; @@ -436,7 +416,6 @@ static int link_configure_fill_message( static int link_configure(Link *link, Request *req) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; - SetLinkOperation op; int r; assert(link); @@ -444,20 +423,18 @@ static int link_configure(Link *link, Request *req) { assert(link->manager->rtnl); assert(req); - op = PTR_TO_INT(req->set_link_operation_ptr); + log_link_debug(link, "Setting %s", request_type_to_string(req->type)); - log_link_debug(link, "Setting %s", set_link_operation_to_string(op)); - - if (op == SET_LINK_BOND) + if (req->type == REQUEST_TYPE_SET_LINK_BOND) 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)) + else if (IN_SET(req->type, REQUEST_TYPE_SET_LINK_CAN, REQUEST_TYPE_SET_LINK_IPOIB)) r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex); else r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex); if (r < 0) return r; - r = link_configure_fill_message(link, m, op, req->userdata); + r = link_configure_fill_message(link, m, req->type, req->userdata); if (r < 0) return r; @@ -476,7 +453,6 @@ static bool netdev_is_ready(NetDev *netdev) { } static int link_is_ready_to_set_link(Link *link, Request *req) { - SetLinkOperation op; int r; assert(link); @@ -484,26 +460,29 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { assert(link->network); assert(req); - op = PTR_TO_INT(req->set_link_operation_ptr); - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) return false; - switch (op) { - case SET_LINK_BOND: - case SET_LINK_BRIDGE: + switch (req->type) { + case REQUEST_TYPE_SET_LINK_BOND: + case REQUEST_TYPE_SET_LINK_BRIDGE: if (!link->master_set) return false; + if (link->network->keep_master && link->master_ifindex <= 0) return false; break; - case SET_LINK_BRIDGE_VLAN: + + case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: if (!link->master_set) return false; + if (link->network->keep_master && link->master_ifindex <= 0 && !streq_ptr(link->kind, "bridge")) return false; + break; - case SET_LINK_CAN: + + case REQUEST_TYPE_SET_LINK_CAN: /* Do not check link->set_flgas_messages here, as it is ok even if link->flags * is outdated, and checking the counter causes a deadlock. */ if (FLAGS_SET(link->flags, IFF_UP)) { @@ -513,7 +492,8 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { return r; } break; - case SET_LINK_MAC: + + case REQUEST_TYPE_SET_LINK_MAC: if (req->netlink_handler == link_set_mac_handler) { /* This is the second attempt to set hardware address. On the first attempt * req->netlink_handler points to link_set_mac_allow_retry_handler(). @@ -523,12 +503,12 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { return r; } break; - case SET_LINK_MASTER: { + + case REQUEST_TYPE_SET_LINK_MASTER: { uint32_t m = 0; Request req_mac = { .link = link, - .type = REQUEST_TYPE_SET_LINK, - .set_link_operation_ptr = INT_TO_PTR(SET_LINK_MAC), + .type = REQUEST_TYPE_SET_LINK_MAC, }; if (link->network->batadv) { @@ -565,11 +545,10 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { req->userdata = UINT32_TO_PTR(m); break; } - case SET_LINK_MTU: { + case REQUEST_TYPE_SET_LINK_MTU: { Request req_ipoib = { .link = link, - .type = REQUEST_TYPE_SET_LINK, - .set_link_operation_ptr = INT_TO_PTR(SET_LINK_IPOIB), + .type = REQUEST_TYPE_SET_LINK_IPOIB, }; return !ordered_set_contains(link->manager->request_queue, &req_ipoib); @@ -581,19 +560,11 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { return true; } -int request_process_set_link(Request *req) { - SetLinkOperation op; - Link *link; +int link_process_set_link(Request *req, Link *link, void *userdata) { int r; assert(req); - assert(req->type == REQUEST_TYPE_SET_LINK); - assert(req->netlink_handler); - assert_se(link = req->link); - - op = PTR_TO_INT(req->set_link_operation_ptr); - - assert(op >= 0 && op < _SET_LINK_OPERATION_MAX); + assert(link); r = link_is_ready_to_set_link(link, req); if (r <= 0) @@ -601,15 +572,14 @@ int request_process_set_link(Request *req) { r = link_configure(link, req); if (r < 0) - return log_link_warning_errno(link, r, "Failed to set %s: %m", - set_link_operation_to_string(op)); + return log_link_warning_errno(link, r, "Failed to set %s", request_type_to_string(req->type)); return 1; } static int link_request_set_link( Link *link, - SetLinkOperation op, + RequestType type, request_netlink_handler_t netlink_handler, Request **ret) { @@ -617,16 +587,15 @@ static int link_request_set_link( int r; assert(link); - assert(op >= 0 && op < _SET_LINK_OPERATION_MAX); assert(netlink_handler); - r = link_queue_request(link, REQUEST_TYPE_SET_LINK, INT_TO_PTR(op), false, + r = link_queue_request(link, type, NULL, false, &link->set_link_messages, netlink_handler, &req); if (r < 0) - return log_link_error_errno(link, r, "Failed to request to set %s: %m", - set_link_operation_to_string(op)); + return log_link_warning_errno(link, r, "Failed to request to set %s: %m", + request_type_to_string(type)); - log_link_debug(link, "Requested to set %s", set_link_operation_to_string(op)); + log_link_debug(link, "Requested to set %s", request_type_to_string(type)); if (ret) *ret = req; @@ -662,7 +631,9 @@ int link_request_to_set_addrgen_mode(Link *link) { return 0; } - r = link_request_set_link(link, SET_LINK_ADDRESS_GENERATION_MODE, link_set_addrgen_mode_handler, &req); + r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, + link_set_addrgen_mode_handler, + &req); if (r < 0) return r; @@ -687,7 +658,8 @@ int link_request_to_set_bond(Link *link) { return 0; } - return link_request_set_link(link, SET_LINK_BOND, link_set_bond_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BOND, + link_set_bond_handler, NULL); } int link_request_to_set_bridge(Link *link) { @@ -707,7 +679,9 @@ int link_request_to_set_bridge(Link *link) { return 0; } - return link_request_set_link(link, SET_LINK_BRIDGE, link_set_bridge_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE, + link_set_bridge_handler, + NULL); } int link_request_to_set_bridge_vlan(Link *link) { @@ -730,7 +704,9 @@ int link_request_to_set_bridge_vlan(Link *link) { return 0; } - return link_request_set_link(link, SET_LINK_BRIDGE_VLAN, link_set_bridge_vlan_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE_VLAN, + link_set_bridge_vlan_handler, + NULL); } int link_request_to_set_can(Link *link) { @@ -743,7 +719,9 @@ int link_request_to_set_can(Link *link) { if (!streq_ptr(link->kind, "can")) return 0; - return link_request_set_link(link, SET_LINK_CAN, link_set_can_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_CAN, + link_set_can_handler, + NULL); } int link_request_to_set_flags(Link *link) { @@ -756,7 +734,9 @@ int link_request_to_set_flags(Link *link) { link->network->promiscuous < 0) return 0; - return link_request_set_link(link, SET_LINK_FLAGS, link_set_flags_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_FLAGS, + link_set_flags_handler, + NULL); } int link_request_to_set_group(Link *link) { @@ -766,7 +746,9 @@ int link_request_to_set_group(Link *link) { if (link->network->group < 0) return 0; - return link_request_set_link(link, SET_LINK_GROUP, link_set_group_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_GROUP, + link_set_group_handler, + NULL); } int link_request_to_set_mac(Link *link, bool allow_retry) { @@ -787,7 +769,7 @@ int link_request_to_set_mac(Link *link, bool allow_retry) { if (hw_addr_equal(&link->hw_addr, &link->requested_hw_addr)) return 0; - return link_request_set_link(link, SET_LINK_MAC, + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MAC, allow_retry ? link_set_mac_allow_retry_handler : link_set_mac_handler, NULL); } @@ -803,7 +785,9 @@ int link_request_to_set_ipoib(Link *link) { link->network->ipoib_umcast < 0) return 0; - return link_request_set_link(link, SET_LINK_IPOIB, link_set_ipoib_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_IPOIB, + link_set_ipoib_handler, + NULL); } int link_request_to_set_master(Link *link) { @@ -818,15 +802,19 @@ int link_request_to_set_master(Link *link) { link->master_set = false; if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf) - return link_request_set_link(link, SET_LINK_MASTER, link_set_master_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER, + link_set_master_handler, + NULL); else - return link_request_set_link(link, SET_LINK_MASTER, link_unset_master_handler, NULL); + return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER, + link_unset_master_handler, + NULL); } int link_request_to_set_mtu(Link *link, uint32_t mtu) { - Request *req; const char *origin; uint32_t min_mtu; + Request *req; int r; assert(link); @@ -862,7 +850,9 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu) { if (link->mtu == mtu) return 0; - r = link_request_set_link(link, SET_LINK_MTU, link_set_mtu_handler, &req); + r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_MTU, + link_set_mtu_handler, + &req); if (r < 0) return r; diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h index 3c9853e3ad..5dce0c7b5f 100644 --- a/src/network/networkd-setlink.h +++ b/src/network/networkd-setlink.h @@ -2,30 +2,11 @@ #pragma once #include +#include typedef struct Link Link; typedef struct Request Request; -typedef enum SetLinkOperation { - SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */ - SET_LINK_BOND, /* Setting bond configs. */ - SET_LINK_BRIDGE, /* Setting bridge configs. */ - SET_LINK_BRIDGE_VLAN, /* Setting bridge VLAN configs. */ - SET_LINK_CAN, /* Setting CAN interface configs. */ - SET_LINK_FLAGS, /* Setting IFF_NOARP or friends. */ - SET_LINK_GROUP, /* Setting interface group. */ - SET_LINK_IPOIB, /* Setting IPoIB configs. */ - SET_LINK_MAC, /* Setting MAC address. */ - SET_LINK_MASTER, /* Setting IFLA_MASTER. */ - SET_LINK_MTU, /* Setting MTU. */ - _SET_LINK_OPERATION_MAX, - _SET_LINK_OPERATION_INVALID = -EINVAL, -} SetLinkOperation; - -/* SetLinkOperation is casted to int, then stored in void* with INT_TO_PTR(). */ -assert_cc(sizeof(SetLinkOperation) <= sizeof(void*)); -assert_cc(sizeof(SetLinkOperation) <= sizeof(int)); - int link_request_to_set_addrgen_mode(Link *link); int link_request_to_set_bond(Link *link); int link_request_to_set_bridge(Link *link); @@ -40,7 +21,7 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu); int link_configure_mtu(Link *link); -int request_process_set_link(Request *req); +int link_process_set_link(Request *req, Link *link, void *userdata); int link_process_activation(Request *req, Link *link, void *userdata); int link_request_to_activate(Link *link); From 4c8b81caa518df34d4e69f6660fc4fbdf0b42ce4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 28 Feb 2022 11:21:24 +0900 Subject: [PATCH 11/12] network: increment reference counters of Link and Request before processing requests To prevent the request or link is freed while processing requests. --- src/network/networkd-queue.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index ac378ba675..ecfb7acdd2 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -418,6 +418,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { Request *req; ORDERED_SET_FOREACH(req, manager->request_queue) { + _unused_ _cleanup_(request_unrefp) Request *ref = request_ref(req); + _cleanup_(link_unrefp) Link *link = link_ref(req->link); + switch (req->type) { case REQUEST_TYPE_ACTIVATE_LINK: r = link_process_activation(req, req->link, req->userdata); @@ -501,10 +504,15 @@ int manager_process_requests(sd_event_source *s, void *userdata) { processed = true; request_detach(manager, req); - if (r < 0 && req->link) - link_enter_failed(req->link); + if (r < 0 && link) { + link_enter_failed(link); + /* link_enter_failed() may remove multiple requests, + * hence we need to exit from the loop. */ + break; + } } + /* When at least one request is processed, then another request may be ready now. */ if (!processed) break; } From 09d09207dece533ced25c91024ce7a1c0ed660d8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 28 Feb 2022 10:55:51 +0900 Subject: [PATCH 12/12] network: re-design request queue This makes Request object takes hash, compare, free, and process functions. With this change, the logic in networkd-queue.c can be mostly independent of the type of the request or the object (e.g. Address) assigned to the request, and it becomes simpler. --- src/network/netdev/netdev.c | 18 +- src/network/netdev/netdev.h | 3 - src/network/networkd-address-label.c | 9 +- src/network/networkd-address-label.h | 2 - src/network/networkd-address.c | 16 +- src/network/networkd-address.h | 2 - src/network/networkd-bridge-fdb.c | 12 +- src/network/networkd-bridge-fdb.h | 3 - src/network/networkd-bridge-mdb.c | 12 +- src/network/networkd-bridge-mdb.h | 2 - src/network/networkd-dhcp-server.c | 4 +- src/network/networkd-dhcp-server.h | 2 - src/network/networkd-dhcp4.c | 4 +- src/network/networkd-dhcp4.h | 2 - src/network/networkd-dhcp6.c | 4 +- src/network/networkd-dhcp6.h | 2 - src/network/networkd-ipv6-proxy-ndp.c | 14 +- src/network/networkd-ipv6-proxy-ndp.h | 2 - src/network/networkd-ndisc.c | 4 +- src/network/networkd-ndisc.h | 2 - src/network/networkd-neighbor.c | 18 +- src/network/networkd-neighbor.h | 5 - src/network/networkd-nexthop.c | 20 +- src/network/networkd-nexthop.h | 5 - src/network/networkd-queue.c | 445 ++++----------------- src/network/networkd-queue.h | 83 ++-- src/network/networkd-radv.c | 4 +- src/network/networkd-radv.h | 2 - src/network/networkd-route.c | 26 +- src/network/networkd-route.h | 3 - src/network/networkd-routing-policy-rule.c | 18 +- src/network/networkd-routing-policy-rule.h | 5 - src/network/networkd-setlink.c | 35 +- src/network/networkd-setlink.h | 5 - src/network/tc/qdisc.c | 18 +- src/network/tc/qdisc.h | 5 - src/network/tc/tclass.c | 18 +- src/network/tc/tclass.h | 5 - 38 files changed, 285 insertions(+), 554 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index ee3b883b5c..187b24c558 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -629,7 +629,7 @@ static int netdev_is_ready_to_create(NetDev *netdev, Link *link) { return true; } -int stacked_netdev_process_request(Request *req, Link *link, void *userdata) { +static int stacked_netdev_process_request(Request *req, Link *link, void *userdata) { NetDev *netdev = ASSERT_PTR(userdata); int r; @@ -682,10 +682,12 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) { return 0; /* Already created. */ link->stacked_netdevs_created = false; - r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true, - &link->create_stacked_netdev_messages, - create_stacked_netdev_handler, - NULL); + r = link_queue_request_full(link, REQUEST_TYPE_NETDEV_STACKED, + netdev_ref(netdev), (mfree_func_t) netdev_unref, + trivial_hash_func, trivial_compare_func, + stacked_netdev_process_request, + &link->create_stacked_netdev_messages, + create_stacked_netdev_handler, NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request stacked netdev '%s': %m", netdev->ifname); @@ -694,7 +696,7 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) { return 0; } -int independent_netdev_process_request(Request *req, Link *link, void *userdata) { +static int independent_netdev_process_request(Request *req, Link *link, void *userdata) { NetDev *netdev = ASSERT_PTR(userdata); int r; @@ -730,9 +732,9 @@ static int netdev_request_to_create(NetDev *netdev) { } else { /* Otherwise, wait for the dependencies being resolved. */ - r = netdev_queue_request(netdev, NULL); + r = netdev_queue_request(netdev, independent_netdev_process_request, NULL); if (r < 0) - return log_netdev_warning_errno(netdev, r, "Failed to request to create: %m"); + return log_netdev_warning_errno(netdev, r, "Failed to request to create netdev: %m"); } return 0; diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 4c2e949fb2..6054e322d6 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -109,7 +109,6 @@ typedef enum NetDevCreateType { typedef struct Manager Manager; typedef struct Condition Condition; -typedef struct Request Request; typedef struct NetDev { Manager *manager; @@ -209,8 +208,6 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink); int netdev_generate_hw_addr(NetDev *netdev, Link *link, const char *name, const struct hw_addr_data *hw_addr, struct hw_addr_data *ret); -int independent_netdev_process_request(Request *req, Link *link, void *userdata); -int stacked_netdev_process_request(Request *req, Link *link, void *userdata); int link_request_stacked_netdev(Link *link, NetDev *netdev); const char *netdev_kind_to_string(NetDevKind d) _const_; diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 5c31a44ce4..745b959f77 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -124,7 +124,7 @@ static int address_label_configure(AddressLabel *label, Link *link, Request *req return request_call_netlink_async(link->manager->rtnl, m, req); } -int address_label_process_request(Request *req, Link *link, void *userdata) { +static int address_label_process_request(Request *req, Link *link, void *userdata) { AddressLabel *label = ASSERT_PTR(userdata); int r; @@ -151,8 +151,11 @@ int link_request_static_address_labels(Link *link) { link->static_address_labels_configured = false; HASHMAP_FOREACH(label, link->network->address_labels_by_section) { - r = link_queue_request(link, REQUEST_TYPE_ADDRESS_LABEL, label, false, - &link->static_address_label_messages, address_label_configure_handler, NULL); + r = link_queue_request_full(link, REQUEST_TYPE_ADDRESS_LABEL, + label, NULL, trivial_hash_func, trivial_compare_func, + address_label_process_request, + &link->static_address_label_messages, + address_label_configure_handler, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request address label: %m"); } diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index 19bb0383e6..1e2ee70dee 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -9,7 +9,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef struct AddressLabel { Network *network; @@ -26,7 +25,6 @@ AddressLabel *address_label_free(AddressLabel *label); void network_drop_invalid_address_labels(Network *network); int link_request_static_address_labels(Link *link); -int address_label_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_address_label); CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index e9a79d352d..19a357130b 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -316,7 +316,7 @@ DEFINE_PRIVATE_HASH_OPS( address_kernel_hash_func, address_kernel_compare_func); -void address_hash_func(const Address *a, struct siphash *state) { +static void address_hash_func(const Address *a, struct siphash *state) { assert(a); siphash24_compress(&a->family, sizeof(a->family), state); @@ -1104,7 +1104,7 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) { return true; } -int address_process_request(Request *req, Link *link, Address *address) { +static int address_process_request(Request *req, Link *link, Address *address) { int r; assert(req); @@ -1196,8 +1196,12 @@ int link_request_address( return r; log_address_debug(existing, "Requesting", link); - r = link_queue_request(link, REQUEST_TYPE_ADDRESS, existing, false, - message_counter, (request_netlink_handler_t) netlink_handler, ret); + r = link_queue_request_safe(link, REQUEST_TYPE_ADDRESS, + existing, NULL, + address_hash_func, + address_compare_func, + address_process_request, + message_counter, netlink_handler, ret); if (r < 0) return log_link_warning_errno(link, r, "Failed to request address: %m"); if (r == 0) @@ -1281,7 +1285,9 @@ void address_cancel_request(Address *address) { req = (Request) { .link = address->link, .type = REQUEST_TYPE_ADDRESS, - .address = address, + .userdata = address, + .hash_func = (hash_func_t) address_hash_func, + .compare_func = (compare_func_t) address_compare_func, }; request_detach(address->link->manager, &req); diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index a41274a1fc..563a3de4e2 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -107,13 +107,11 @@ int link_request_address( Request **ret); int link_request_static_address(Link *link, Address *address, bool consume); int link_request_static_addresses(Link *link); -int address_process_request(Request *req, Link *link, Address *address); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); int network_drop_invalid_addresses(Network *network); -void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Address, address); diff --git a/src/network/networkd-bridge-fdb.c b/src/network/networkd-bridge-fdb.c index cc02213c28..803e27cdae 100644 --- a/src/network/networkd-bridge-fdb.c +++ b/src/network/networkd-bridge-fdb.c @@ -208,7 +208,7 @@ static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) { return true; } -int bridge_fdb_process_request(Request *req, Link *link, void *userdata) { +static int bridge_fdb_process_request(Request *req, Link *link, void *userdata) { BridgeFDB *fdb = ASSERT_PTR(userdata); int r; @@ -235,8 +235,14 @@ int link_request_static_bridge_fdb(Link *link) { link->static_bridge_fdb_configured = false; HASHMAP_FOREACH(fdb, link->network->bridge_fdb_entries_by_section) { - r = link_queue_request(link, REQUEST_TYPE_BRIDGE_FDB, fdb, false, - &link->static_bridge_fdb_messages, bridge_fdb_configure_handler, NULL); + r = link_queue_request_full(link, REQUEST_TYPE_BRIDGE_FDB, + fdb, NULL, + trivial_hash_func, + trivial_compare_func, + bridge_fdb_process_request, + &link->static_bridge_fdb_messages, + bridge_fdb_configure_handler, + NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request static bridge FDB entry: %m"); } diff --git a/src/network/networkd-bridge-fdb.h b/src/network/networkd-bridge-fdb.h index 6a6e80384e..b59d673d04 100644 --- a/src/network/networkd-bridge-fdb.h +++ b/src/network/networkd-bridge-fdb.h @@ -14,7 +14,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef enum NeighborCacheEntryFlags { NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE, @@ -47,8 +46,6 @@ void network_drop_invalid_bridge_fdb_entries(Network *network); int link_request_static_bridge_fdb(Link *link); -int bridge_fdb_process_request(Request *req, Link *link, void *userdata); - CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination); diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index 88ae091c1a..3af4afe4a1 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -194,7 +194,7 @@ static bool bridge_mdb_is_ready_to_configure(Link *link) { return true; } -int bridge_mdb_process_request(Request *req, Link *link, void *userdata) { +static int bridge_mdb_process_request(Request *req, Link *link, void *userdata) { BridgeMDB *mdb = ASSERT_PTR(userdata); int r; @@ -227,8 +227,14 @@ int link_request_static_bridge_mdb(Link *link) { goto finish; HASHMAP_FOREACH(mdb, link->network->bridge_mdb_entries_by_section) { - r = link_queue_request(link, REQUEST_TYPE_BRIDGE_MDB, mdb, false, - &link->static_bridge_mdb_messages, bridge_mdb_configure_handler, NULL); + r = link_queue_request_full(link, REQUEST_TYPE_BRIDGE_MDB, + mdb, NULL, + trivial_hash_func, + trivial_compare_func, + bridge_mdb_process_request, + &link->static_bridge_mdb_messages, + bridge_mdb_configure_handler, + NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request MDB entry to multicast group database: %m"); } diff --git a/src/network/networkd-bridge-mdb.h b/src/network/networkd-bridge-mdb.h index c9a34af88a..edea255769 100644 --- a/src/network/networkd-bridge-mdb.h +++ b/src/network/networkd-bridge-mdb.h @@ -9,7 +9,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef struct BridgeMDB { Network *network; @@ -25,7 +24,6 @@ BridgeMDB *bridge_mdb_free(BridgeMDB *mdb); void network_drop_invalid_bridge_mdb_entries(Network *network); int link_request_static_bridge_mdb(Link *link); -int bridge_mdb_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index b11ff073bc..3d24cbaf3c 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -567,7 +567,7 @@ static bool dhcp_server_is_ready_to_configure(Link *link) { return true; } -int dhcp_server_process_request(Request *req, Link *link, void *userdata) { +static int dhcp_server_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -594,7 +594,7 @@ int link_request_dhcp_server(Link *link) { return 0; log_link_debug(link, "Requesting DHCP server."); - r = link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, dhcp_server_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuration of DHCP server: %m"); diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h index 7a204e7d0a..cb2a8b6a34 100644 --- a/src/network/networkd-dhcp-server.h +++ b/src/network/networkd-dhcp-server.h @@ -5,13 +5,11 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; void network_adjust_dhcp_server(Network *network); int link_request_dhcp_server_address(Link *link); int link_request_dhcp_server(Link *link); -int dhcp_server_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index dcde7f9bed..2fcb9c853f 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1589,7 +1589,7 @@ static int dhcp4_configure_duid(Link *link) { return dhcp_configure_duid(link, link_get_dhcp4_duid(link)); } -int dhcp4_process_request(Request *req, Link *link, void *userdata) { +static int dhcp4_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -1630,7 +1630,7 @@ int link_request_dhcp4_client(Link *link) { if (link->dhcp_client) return 0; - r = link_queue_request(link, REQUEST_TYPE_DHCP4_CLIENT, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_DHCP4_CLIENT, dhcp4_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv4 client: %m"); diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 4e466ca4f9..1d30cd15df 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -5,7 +5,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef enum DHCPClientIdentifier { DHCP_CLIENT_ID_MAC, @@ -25,7 +24,6 @@ int dhcp4_start(Link *link); int dhcp4_lease_lost(Link *link); int dhcp4_check_ready(Link *link); -int dhcp4_process_request(Request *req, Link *link, void *userdata); int link_request_dhcp4_client(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index bceae735b0..c443098889 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -712,7 +712,7 @@ int dhcp6_update_mac(Link *link) { return 0; } -int dhcp6_process_request(Request *req, Link *link, void *userdata) { +static int dhcp6_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -757,7 +757,7 @@ int link_request_dhcp6_client(Link *link) { if (link->dhcp6_client) return 0; - r = link_queue_request(link, REQUEST_TYPE_DHCP6_CLIENT, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_DHCP6_CLIENT, dhcp6_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv6 client: %m"); diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index e3bc57cc30..81267c255f 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -13,7 +13,6 @@ typedef enum DHCP6ClientStartMode { } DHCP6ClientStartMode; typedef struct Link Link; -typedef struct Request Request; bool link_dhcp6_with_address_enabled(Link *link); int dhcp6_check_ready(Link *link); @@ -21,7 +20,6 @@ int dhcp6_update_mac(Link *link); int dhcp6_start(Link *link); int dhcp6_start_on_ra(Link *link, bool information_request); -int dhcp6_process_request(Request *req, Link *link, void *userdata); int link_request_dhcp6_client(Link *link); int link_serialize_dhcp6_client(Link *link, FILE *f); diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index b245a9eba2..8166851ed3 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -78,7 +78,7 @@ static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link 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) { +static int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address) { int r; assert(req); @@ -105,10 +105,14 @@ int link_request_static_ipv6_proxy_ndp_addresses(Link *link) { link->static_ipv6_proxy_ndp_configured = false; 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, - (request_netlink_handler_t) ipv6_proxy_ndp_address_configure_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_IPV6_PROXY_NDP, + address, NULL, + in6_addr_hash_func, + in6_addr_compare_func, + ipv6_proxy_ndp_address_process_request, + &link->static_ipv6_proxy_ndp_messages, + 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-ipv6-proxy-ndp.h b/src/network/networkd-ipv6-proxy-ndp.h index 39a7820599..e57d28f99d 100644 --- a/src/network/networkd-ipv6-proxy-ndp.h +++ b/src/network/networkd-ipv6-proxy-ndp.h @@ -5,11 +5,9 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; void network_adjust_ipv6_proxy_ndp(Network *network); int link_request_static_ipv6_proxy_ndp_addresses(Link *link); -int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 2a85fb3cfb..8cbc67f542 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1116,7 +1116,7 @@ int ndisc_start(Link *link) { return 1; } -int ndisc_process_request(Request *req, Link *link, void *userdata) { +static int ndisc_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -1152,7 +1152,7 @@ int link_request_ndisc(Link *link) { if (link->ndisc) return 0; - r = link_queue_request(link, REQUEST_TYPE_NDISC, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_NDISC, ndisc_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m"); diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 5a7eb58a56..f88a002c73 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -6,7 +6,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef enum IPv6AcceptRAStartDHCP6Client { IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO, @@ -48,7 +47,6 @@ int ndisc_start(Link *link); void ndisc_vacuum(Link *link); void ndisc_flush(Link *link); -int ndisc_process_request(Request *req, Link *link, void *userdata); int link_request_ndisc(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client); diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 1cb5333b66..435fa7002e 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -87,7 +87,7 @@ static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) { return 0; } -void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) { +static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) { assert(neighbor); siphash24_compress(&neighbor->family, sizeof(neighbor->family), state); @@ -106,7 +106,7 @@ void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) { hw_addr_hash_func(&neighbor->ll_addr, state); } -int neighbor_compare_func(const Neighbor *a, const Neighbor *b) { +static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) { int r; r = CMP(a->family, b->family); @@ -218,7 +218,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) { return request_call_netlink_async(link->manager->rtnl, m, req); } -int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) { +static int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) { int r; assert(req); @@ -282,10 +282,14 @@ static int link_request_neighbor(Link *link, const Neighbor *neighbor) { existing->source = neighbor->source; log_neighbor_debug(existing, "Requesting", link); - r = link_queue_request(link, REQUEST_TYPE_NEIGHBOR, existing, false, - &link->static_neighbor_messages, - (request_netlink_handler_t) static_neighbor_configure_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_NEIGHBOR, + existing, NULL, + neighbor_hash_func, + neighbor_compare_func, + neighbor_process_request, + &link->static_neighbor_messages, + static_neighbor_configure_handler, + NULL); if (r <= 0) return r; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 52a7733a89..758475a8ff 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -13,7 +13,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef struct Neighbor { Network *network; @@ -29,9 +28,6 @@ typedef struct Neighbor { Neighbor *neighbor_free(Neighbor *neighbor); -void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state); -int neighbor_compare_func(const Neighbor *a, const Neighbor *b); - void network_drop_invalid_neighbors(Network *network); int link_drop_managed_neighbors(Link *link); @@ -39,7 +35,6 @@ int link_drop_foreign_neighbors(Link *link); void link_foreignize_neighbors(Link *link); int link_request_static_neighbors(Link *link); -int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor); int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 219a08e159..3eb9d62f7c 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -104,7 +104,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s return 0; } -void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { +static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { assert(nexthop); siphash24_compress(&nexthop->protocol, sizeof(nexthop->protocol), state); @@ -124,7 +124,7 @@ void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { } } -int nexthop_compare_func(const NextHop *a, const NextHop *b) { +static int nexthop_compare_func(const NextHop *a, const NextHop *b) { int r; r = CMP(a->protocol, b->protocol); @@ -546,7 +546,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) { ORDERED_SET_FOREACH(req, link->manager->request_queue) { if (req->type != REQUEST_TYPE_NEXTHOP) continue; - if (req->nexthop->id != 0) + if (((NextHop*) req->userdata)->id != 0) return false; /* first configure nexthop with id. */ } } @@ -554,7 +554,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) { return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw); } -int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) { +static int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) { int r; assert(req); @@ -600,10 +600,14 @@ static int link_request_nexthop(Link *link, NextHop *nexthop) { existing->source = nexthop->source; log_nexthop_debug(existing, "Requesting", link); - r = link_queue_request(link, REQUEST_TYPE_NEXTHOP, existing, false, - &link->static_nexthop_messages, - (request_netlink_handler_t) static_nexthop_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_NEXTHOP, + existing, NULL, + nexthop_hash_func, + nexthop_compare_func, + nexthop_process_request, + &link->static_nexthop_messages, + static_nexthop_handler, + NULL); if (r <= 0) return r; diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index c5b58e5d38..6f2aa6f6dc 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -16,7 +16,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef struct NextHop { Network *network; @@ -39,9 +38,6 @@ typedef struct NextHop { NextHop *nexthop_free(NextHop *nexthop); -void nexthop_hash_func(const NextHop *nexthop, struct siphash *state); -int nexthop_compare_func(const NextHop *a, const NextHop *b); - void network_drop_invalid_nexthops(Network *network); int link_drop_managed_nexthops(Link *link); @@ -49,7 +45,6 @@ int link_drop_foreign_nexthops(Link *link); void link_foreignize_nexthops(Link *link); int link_request_static_nexthops(Link *link, bool only_ipv4); -int nexthop_process_request(Request *req, Link *link, NextHop *nexthop); int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index ecfb7acdd2..1463f610b2 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -1,93 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "netdev.h" #include "netlink-util.h" -#include "networkd-address.h" -#include "networkd-address-label.h" -#include "networkd-bridge-fdb.h" -#include "networkd-bridge-mdb.h" -#include "networkd-dhcp-server.h" -#include "networkd-dhcp4.h" -#include "networkd-dhcp6.h" -#include "networkd-ipv6-proxy-ndp.h" +#include "networkd-link.h" #include "networkd-manager.h" -#include "networkd-ndisc.h" -#include "networkd-neighbor.h" -#include "networkd-nexthop.h" -#include "networkd-route.h" -#include "networkd-routing-policy-rule.h" #include "networkd-queue.h" -#include "networkd-setlink.h" -#include "qdisc.h" #include "string-table.h" -#include "tclass.h" - -static void request_free_object(RequestType type, void *object) { - switch (type) { - case REQUEST_TYPE_ACTIVATE_LINK: - break; - case REQUEST_TYPE_ADDRESS: - address_free(object); - break; - case REQUEST_TYPE_ADDRESS_LABEL: - address_label_free(object); - break; - case REQUEST_TYPE_BRIDGE_FDB: - bridge_fdb_free(object); - break; - case REQUEST_TYPE_BRIDGE_MDB: - bridge_mdb_free(object); - break; - case REQUEST_TYPE_DHCP_SERVER: - case REQUEST_TYPE_DHCP4_CLIENT: - case REQUEST_TYPE_DHCP6_CLIENT: - break; - case REQUEST_TYPE_IPV6_PROXY_NDP: - free(object); - break; - case REQUEST_TYPE_NDISC: - break; - case REQUEST_TYPE_NEIGHBOR: - neighbor_free(object); - break; - case REQUEST_TYPE_NETDEV_INDEPENDENT: - case REQUEST_TYPE_NETDEV_STACKED: - netdev_unref(object); - break; - case REQUEST_TYPE_NEXTHOP: - nexthop_free(object); - break; - case REQUEST_TYPE_RADV: - break; - case REQUEST_TYPE_ROUTE: - route_free(object); - break; - case REQUEST_TYPE_ROUTING_POLICY_RULE: - routing_policy_rule_free(object); - break; - case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: - case REQUEST_TYPE_SET_LINK_BOND: - case REQUEST_TYPE_SET_LINK_BRIDGE: - case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: - case REQUEST_TYPE_SET_LINK_CAN: - case REQUEST_TYPE_SET_LINK_FLAGS: - case REQUEST_TYPE_SET_LINK_GROUP: - case REQUEST_TYPE_SET_LINK_IPOIB: - case REQUEST_TYPE_SET_LINK_MAC: - case REQUEST_TYPE_SET_LINK_MASTER: - case REQUEST_TYPE_SET_LINK_MTU: - break; - case REQUEST_TYPE_TC_QDISC: - qdisc_free(object); - break; - case REQUEST_TYPE_TC_CLASS: - tclass_free(object); - break; - case REQUEST_TYPE_UP_DOWN: - break; - default: - assert_not_reached(); - } -} static Request *request_free(Request *req) { if (!req) @@ -98,8 +16,8 @@ static Request *request_free(Request *req) { if (req->manager) ordered_set_remove(req->manager->request_queue, req); - if (req->consume_object) - request_free_object(req->type, req->object); + if (req->free_func) + req->free_func(req->userdata); if (req->counter) (*req->counter)--; @@ -136,70 +54,11 @@ static void request_hash_func(const Request *req, struct siphash *state) { siphash24_compress(&req->type, sizeof(req->type), state); - switch (req->type) { - case REQUEST_TYPE_ACTIVATE_LINK: - break; - case REQUEST_TYPE_ADDRESS: - address_hash_func(req->address, state); - break; - case REQUEST_TYPE_ADDRESS_LABEL: - case REQUEST_TYPE_BRIDGE_FDB: - case REQUEST_TYPE_BRIDGE_MDB: - case REQUEST_TYPE_NETDEV_INDEPENDENT: - case REQUEST_TYPE_NETDEV_STACKED: - /* TODO: Currently, these types do not have any specific hash and compare functions. - * Fortunately, all these objects are 'static', thus we can use the trivial functions. */ - trivial_hash_func(req->object, state); - break; - case REQUEST_TYPE_DHCP_SERVER: - case REQUEST_TYPE_DHCP4_CLIENT: - case REQUEST_TYPE_DHCP6_CLIENT: - /* These types do not have an object. */ - break; - case REQUEST_TYPE_IPV6_PROXY_NDP: - in6_addr_hash_func(req->ipv6_proxy_ndp, state); - break; - case REQUEST_TYPE_NDISC: - /* This type does not have an object. */ - break; - case REQUEST_TYPE_NEIGHBOR: - neighbor_hash_func(req->neighbor, state); - break; - case REQUEST_TYPE_NEXTHOP: - nexthop_hash_func(req->nexthop, state); - break; - case REQUEST_TYPE_RADV: - /* This type does not have an object. */ - break; - case REQUEST_TYPE_ROUTE: - route_hash_func(req->route, state); - break; - case REQUEST_TYPE_ROUTING_POLICY_RULE: - routing_policy_rule_hash_func(req->rule, state); - break; - case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: - case REQUEST_TYPE_SET_LINK_BOND: - case REQUEST_TYPE_SET_LINK_BRIDGE: - case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: - case REQUEST_TYPE_SET_LINK_CAN: - case REQUEST_TYPE_SET_LINK_FLAGS: - case REQUEST_TYPE_SET_LINK_GROUP: - case REQUEST_TYPE_SET_LINK_IPOIB: - case REQUEST_TYPE_SET_LINK_MAC: - case REQUEST_TYPE_SET_LINK_MASTER: - case REQUEST_TYPE_SET_LINK_MTU: - break; - case REQUEST_TYPE_TC_QDISC: - qdisc_hash_func(req->qdisc, state); - break; - case REQUEST_TYPE_TC_CLASS: - tclass_hash_func(req->tclass, state); - break; - case REQUEST_TYPE_UP_DOWN: - break; - default: - assert_not_reached(); - } + siphash24_compress(&req->hash_func, sizeof(req->hash_func), state); + siphash24_compress(&req->compare_func, sizeof(req->compare_func), state); + + if (req->hash_func) + req->hash_func(req->userdata, state); } static int request_compare_func(const struct Request *a, const struct Request *b) { @@ -222,56 +81,18 @@ static int request_compare_func(const struct Request *a, const struct Request *b if (r != 0) return r; - switch (a->type) { - case REQUEST_TYPE_ACTIVATE_LINK: - return 0; - case REQUEST_TYPE_ADDRESS: - return address_compare_func(a->address, b->address); - case REQUEST_TYPE_ADDRESS_LABEL: - case REQUEST_TYPE_BRIDGE_FDB: - case REQUEST_TYPE_BRIDGE_MDB: - case REQUEST_TYPE_NETDEV_INDEPENDENT: - case REQUEST_TYPE_NETDEV_STACKED: - return trivial_compare_func(a->object, b->object); - case REQUEST_TYPE_DHCP_SERVER: - case REQUEST_TYPE_DHCP4_CLIENT: - case REQUEST_TYPE_DHCP6_CLIENT: - return 0; - case REQUEST_TYPE_IPV6_PROXY_NDP: - return in6_addr_compare_func(a->ipv6_proxy_ndp, b->ipv6_proxy_ndp); - case REQUEST_TYPE_NDISC: - return 0; - case REQUEST_TYPE_NEIGHBOR: - return neighbor_compare_func(a->neighbor, b->neighbor); - case REQUEST_TYPE_NEXTHOP: - return nexthop_compare_func(a->nexthop, b->nexthop); - case REQUEST_TYPE_ROUTE: - return route_compare_func(a->route, b->route); - case REQUEST_TYPE_RADV: - return 0; - case REQUEST_TYPE_ROUTING_POLICY_RULE: - return routing_policy_rule_compare_func(a->rule, b->rule); - case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: - case REQUEST_TYPE_SET_LINK_BOND: - case REQUEST_TYPE_SET_LINK_BRIDGE: - case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: - case REQUEST_TYPE_SET_LINK_CAN: - case REQUEST_TYPE_SET_LINK_FLAGS: - case REQUEST_TYPE_SET_LINK_GROUP: - case REQUEST_TYPE_SET_LINK_IPOIB: - case REQUEST_TYPE_SET_LINK_MAC: - case REQUEST_TYPE_SET_LINK_MASTER: - case REQUEST_TYPE_SET_LINK_MTU: - return 0; - case REQUEST_TYPE_TC_QDISC: - return qdisc_compare_func(a->qdisc, b->qdisc); - case REQUEST_TYPE_TC_CLASS: - return tclass_compare_func(a->tclass, b->tclass); - case REQUEST_TYPE_UP_DOWN: - return 0; - default: - assert_not_reached(); - } + r = CMP(PTR_TO_UINT64(a->hash_func), PTR_TO_UINT64(b->hash_func)); + if (r != 0) + return r; + + r = CMP(PTR_TO_UINT64(a->compare_func), PTR_TO_UINT64(b->compare_func)); + if (r != 0) + return r; + + if (a->compare_func) + return a->compare_func(a->userdata, b->userdata); + + return 0; } DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( @@ -281,54 +102,15 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( request_compare_func, request_unref); -int netdev_queue_request( - NetDev *netdev, - Request **ret) { - - _cleanup_(request_unrefp) Request *req = NULL; - Request *existing; - int r; - - assert(netdev); - assert(netdev->manager); - - req = new(Request, 1); - if (!req) - return -ENOMEM; - - *req = (Request) { - .n_ref = 1, - .manager = netdev->manager, - .netdev = netdev_ref(netdev), - .type = REQUEST_TYPE_NETDEV_INDEPENDENT, - .consume_object = true, - }; - - existing = ordered_set_get(netdev->manager->request_queue, req); - if (existing) { - if (ret) - *ret = existing; - return 0; - } - - r = ordered_set_ensure_put(&netdev->manager->request_queue, &request_hash_ops, req); - if (r < 0) - return r; - - req->manager = netdev->manager; - - if (ret) - *ret = req; - - TAKE_PTR(req); - return 1; -} - -int link_queue_request( +static int request_new( + Manager *manager, Link *link, RequestType type, - void *object, - bool consume_object, + void *userdata, + mfree_func_t free_func, + hash_func_t hash_func, + compare_func_t compare_func, + request_process_func_t process, unsigned *counter, request_netlink_handler_t netlink_handler, Request **ret) { @@ -337,65 +119,40 @@ int link_queue_request( Request *existing; int r; - assert(link); - assert(link->manager); - assert(type >= 0 && type < _REQUEST_TYPE_MAX); - assert(IN_SET(type, - REQUEST_TYPE_ACTIVATE_LINK, - REQUEST_TYPE_DHCP_SERVER, - REQUEST_TYPE_DHCP4_CLIENT, - REQUEST_TYPE_DHCP6_CLIENT, - REQUEST_TYPE_NDISC, - REQUEST_TYPE_RADV, - REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, - REQUEST_TYPE_SET_LINK_BOND, - REQUEST_TYPE_SET_LINK_BRIDGE, - REQUEST_TYPE_SET_LINK_BRIDGE_VLAN, - REQUEST_TYPE_SET_LINK_CAN, - REQUEST_TYPE_SET_LINK_FLAGS, - REQUEST_TYPE_SET_LINK_GROUP, - REQUEST_TYPE_SET_LINK_IPOIB, - REQUEST_TYPE_SET_LINK_MAC, - REQUEST_TYPE_SET_LINK_MASTER, - REQUEST_TYPE_SET_LINK_MTU, - REQUEST_TYPE_UP_DOWN) || - object); - assert(IN_SET(type, - REQUEST_TYPE_DHCP_SERVER, - REQUEST_TYPE_DHCP4_CLIENT, - REQUEST_TYPE_DHCP6_CLIENT, - REQUEST_TYPE_NDISC, - REQUEST_TYPE_RADV) || - netlink_handler); + assert(manager); + assert(process); req = new(Request, 1); if (!req) { - if (consume_object) - request_free_object(type, object); + if (free_func) + free_func(userdata); return -ENOMEM; } *req = (Request) { .n_ref = 1, - .link = link_ref(link), + .link = link_ref(link), /* link may be NULL, but link_ref() handles it gracefully. */ .type = type, - .object = object, - .consume_object = consume_object, + .userdata = userdata, + .free_func = free_func, + .hash_func = hash_func, + .compare_func = compare_func, + .process = process, .netlink_handler = netlink_handler, }; - existing = ordered_set_get(link->manager->request_queue, req); + existing = ordered_set_get(manager->request_queue, req); if (existing) { if (ret) *ret = existing; return 0; } - r = ordered_set_ensure_put(&link->manager->request_queue, &request_hash_ops, req); + r = ordered_set_ensure_put(&manager->request_queue, &request_hash_ops, req); if (r < 0) return r; - req->manager = link->manager; + req->manager = manager; req->counter = counter; if (req->counter) (*req->counter)++; @@ -407,11 +164,41 @@ int link_queue_request( return 1; } -int manager_process_requests(sd_event_source *s, void *userdata) { - Manager *manager = userdata; - int r; +int netdev_queue_request( + NetDev *netdev, + request_process_func_t process, + Request **ret) { - assert(manager); + assert(netdev); + + return request_new(netdev->manager, NULL, REQUEST_TYPE_NETDEV_INDEPENDENT, + netdev_ref(netdev), (mfree_func_t) netdev_unref, + trivial_hash_func, trivial_compare_func, + process, NULL, NULL, ret); +} + +int link_queue_request_full( + Link *link, + RequestType type, + void *userdata, + mfree_func_t free_func, + hash_func_t hash_func, + compare_func_t compare_func, + request_process_func_t process, + unsigned *counter, + request_netlink_handler_t netlink_handler, + Request **ret) { + + assert(link); + + return request_new(link->manager, link, type, + userdata, free_func, hash_func, compare_func, + process, counter, netlink_handler, ret); +} + +int manager_process_requests(sd_event_source *s, void *userdata) { + Manager *manager = ASSERT_PTR(userdata); + int r; for (;;) { bool processed = false; @@ -421,83 +208,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { _unused_ _cleanup_(request_unrefp) Request *ref = request_ref(req); _cleanup_(link_unrefp) Link *link = link_ref(req->link); - switch (req->type) { - case REQUEST_TYPE_ACTIVATE_LINK: - r = link_process_activation(req, req->link, req->userdata); - break; - case REQUEST_TYPE_ADDRESS: - r = address_process_request(req, req->link, req->address); - break; - case REQUEST_TYPE_ADDRESS_LABEL: - r = address_label_process_request(req, req->link, req->label); - break; - case REQUEST_TYPE_BRIDGE_FDB: - r = bridge_fdb_process_request(req, req->link, req->fdb); - break; - case REQUEST_TYPE_BRIDGE_MDB: - r = bridge_mdb_process_request(req, req->link, req->mdb); - break; - case REQUEST_TYPE_DHCP_SERVER: - r = dhcp_server_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_DHCP4_CLIENT: - r = dhcp4_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_DHCP6_CLIENT: - r = dhcp6_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_IPV6_PROXY_NDP: - r = ipv6_proxy_ndp_address_process_request(req, req->link, req->ipv6_proxy_ndp); - break; - case REQUEST_TYPE_NDISC: - r = ndisc_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_NEIGHBOR: - r = neighbor_process_request(req, req->link, req->neighbor); - break; - case REQUEST_TYPE_NETDEV_INDEPENDENT: - r = independent_netdev_process_request(req, req->link, req->netdev); - break; - case REQUEST_TYPE_NETDEV_STACKED: - r = stacked_netdev_process_request(req, req->link, req->netdev); - break; - case REQUEST_TYPE_NEXTHOP: - r = nexthop_process_request(req, req->link, req->nexthop); - break; - case REQUEST_TYPE_RADV: - r = radv_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_ROUTE: - r = route_process_request(req, req->link, req->route); - break; - case REQUEST_TYPE_ROUTING_POLICY_RULE: - r = routing_policy_rule_process_request(req, req->link, req->rule); - break; - case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: - case REQUEST_TYPE_SET_LINK_BOND: - case REQUEST_TYPE_SET_LINK_BRIDGE: - case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: - case REQUEST_TYPE_SET_LINK_CAN: - case REQUEST_TYPE_SET_LINK_FLAGS: - case REQUEST_TYPE_SET_LINK_GROUP: - case REQUEST_TYPE_SET_LINK_IPOIB: - case REQUEST_TYPE_SET_LINK_MAC: - case REQUEST_TYPE_SET_LINK_MASTER: - case REQUEST_TYPE_SET_LINK_MTU: - r = link_process_set_link(req, req->link, NULL); - break; - case REQUEST_TYPE_TC_QDISC: - r = qdisc_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_TC_CLASS: - r = tclass_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_UP_DOWN: - r = link_process_up_or_down(req, req->link, req->userdata); - break; - default: - return -EINVAL; - } + assert(req->process); + + r = req->process(req, link, req->userdata); if (r == 0) continue; @@ -533,7 +246,7 @@ static int request_netlink_handler(sd_netlink *nl, sd_netlink_message *m, Reques return 0; if (req->netlink_handler) - return req->netlink_handler(nl, m, req, req->link, req->object); + return req->netlink_handler(nl, m, req, req->link, req->userdata); return 0; } diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 0c822094e8..d1110119cc 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -4,21 +4,15 @@ #include "sd-event.h" #include "sd-netlink.h" -#include "networkd-link.h" +#include "alloc-util.h" +#include "hash-funcs.h" -typedef struct Address Address; -typedef struct AddressLabel AddressLabel; -typedef struct BridgeFDB BridgeFDB; -typedef struct BridgeMDB BridgeMDB; -typedef struct Neighbor Neighbor; +typedef struct Link Link; typedef struct NetDev NetDev; -typedef struct NextHop NextHop; -typedef struct Route Route; -typedef struct RoutingPolicyRule RoutingPolicyRule; -typedef struct QDisc QDisc; -typedef struct TClass TClass; +typedef struct Manager Manager; typedef struct Request Request; +typedef int (*request_process_func_t)(Request *req, Link *link, void *userdata); typedef int (*request_netlink_handler_t)(sd_netlink *nl, sd_netlink_message *m, Request *req, Link *link, void *userdata); typedef enum RequestType { @@ -64,24 +58,19 @@ struct Request { Link *link; /* can be NULL */ RequestType type; - bool consume_object; - union { - Address *address; - AddressLabel *label; - BridgeFDB *fdb; - BridgeMDB *mdb; - struct in6_addr *ipv6_proxy_ndp; - Neighbor *neighbor; - NextHop *nexthop; - Route *route; - RoutingPolicyRule *rule; - void *set_link_operation_ptr; - NetDev *netdev; - QDisc *qdisc; - TClass *tclass; - void *object; - }; + + /* Target object, e.g. Address, Route, NetDev, and so on. */ void *userdata; + /* freeing userdata when the request is completed or failed. */ + mfree_func_t free_func; + + /* hash and compare functions for userdata, used for dedup requests. */ + hash_func_t hash_func; + compare_func_t compare_func; + + /* Checks the request dependencies, and then processes this request, e.g. call address_configure(). + * Return 1 when processed, 0 when its dependencies not resolved, and negative errno on failure. */ + request_process_func_t process; /* incremented when requested, decremented when request is completed or failed. */ unsigned *counter; @@ -100,17 +89,49 @@ void request_detach(Manager *manager, Request *req); int netdev_queue_request( NetDev *netdev, + request_process_func_t process, Request **ret); -int link_queue_request( +int link_queue_request_full( Link *link, RequestType type, - void *object, - bool consume_object, + void *userdata, + mfree_func_t free_func, + hash_func_t hash_func, + compare_func_t compare_func, + request_process_func_t process, unsigned *counter, request_netlink_handler_t netlink_handler, Request **ret); +static inline int link_queue_request( + Link *link, + RequestType type, + request_process_func_t process, + Request **ret) { + + return link_queue_request_full(link, type, NULL, NULL, NULL, NULL, + process, NULL, NULL, ret); +} + +#define link_queue_request_safe(link, type, userdata, free_func, hash_func, compare_func, process, counter, netlink_handler, ret) \ + ({ \ + typeof(userdata) (*_f)(typeof(userdata)) = (free_func); \ + void (*_h)(const typeof(*userdata)*, struct siphash*) = (hash_func); \ + int (*_c)(const typeof(*userdata)*, const typeof(*userdata)*) = (compare_func); \ + int (*_p)(Request*, Link*, typeof(userdata)) = (process); \ + int (*_n)(sd_netlink*, sd_netlink_message*, Request*, Link*, typeof(userdata)) = (netlink_handler); \ + \ + link_queue_request_full(link, type, userdata, \ + (mfree_func_t) _f, \ + (hash_func_t) _h, \ + (compare_func_t) _c, \ + (request_process_func_t) _p, \ + counter, \ + (request_netlink_handler_t) _n, \ + 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-radv.c b/src/network/networkd-radv.c index f6e1841c05..b9f5c55f4c 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -582,7 +582,7 @@ static int radv_is_ready_to_configure(Link *link) { return true; } -int radv_process_request(Request *req, Link *link, void *userdata) { +static int radv_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -617,7 +617,7 @@ int link_request_radv(Link *link) { if (link->radv) return 0; - r = link_queue_request(link, REQUEST_TYPE_RADV, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_RADV, radv_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Advertisement engine: %m"); diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 0d340c955e..ebebb3942b 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -16,7 +16,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef enum RADVPrefixDelegation { RADV_PREFIX_DELEGATION_NONE = 0, @@ -68,7 +67,6 @@ int radv_update_mac(Link *link); int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, usec_t lifetime_preferred_usec, usec_t lifetime_valid_usec); -int radv_process_request(Request *req, Link *link, void *userdata); int link_request_radv(Link *link); const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index cfc6967963..c9fb872ae5 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -110,7 +110,7 @@ Route *route_free(Route *route) { return mfree(route); } -void route_hash_func(const Route *route, struct siphash *state) { +static void route_hash_func(const Route *route, struct siphash *state) { assert(route); siphash24_compress(&route->family, sizeof(route->family), state); @@ -152,7 +152,7 @@ void route_hash_func(const Route *route, struct siphash *state) { } } -int route_compare_func(const Route *a, const Route *b) { +static int route_compare_func(const Route *a, const Route *b) { int r; r = CMP(a->family, b->family); @@ -1310,7 +1310,7 @@ static int route_is_ready_to_configure(const Route *route, Link *link) { return true; } -int route_process_request(Request *req, Link *link, Route *route) { +static int route_process_request(Request *req, Link *link, Route *route) { _cleanup_(converted_routes_freep) ConvertedRoutes *converted = NULL; int r; @@ -1423,8 +1423,12 @@ int link_request_route( } log_route_debug(existing, "Requesting", link, link->manager); - r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false, - message_counter, (request_netlink_handler_t) netlink_handler, ret); + r = link_queue_request_safe(link, REQUEST_TYPE_ROUTE, + existing, NULL, + route_hash_func, + route_compare_func, + route_process_request, + message_counter, netlink_handler, ret); if (r <= 0) return r; @@ -1460,10 +1464,10 @@ static int link_request_static_route(Link *link, Route *route) { static_route_handler, NULL); log_route_debug(route, "Requesting", link, link->manager); - return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false, - &link->static_route_messages, - (request_netlink_handler_t) static_route_handler, - NULL); + return link_queue_request_safe(link, REQUEST_TYPE_ROUTE, + route, NULL, route_hash_func, route_compare_func, + route_process_request, + &link->static_route_messages, static_route_handler, NULL); } static int link_request_wireguard_routes(Link *link, bool only_ipv4) { @@ -1547,7 +1551,9 @@ void route_cancel_request(Route *route, Link *link) { req = (Request) { .link = link, .type = REQUEST_TYPE_ROUTE, - .route = route, + .userdata = route, + .hash_func = (hash_func_t) route_hash_func, + .compare_func = (compare_func_t) route_compare_func, }; request_detach(link->manager, &req); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 8c1c5cf680..b431e1a30f 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -75,8 +75,6 @@ struct Route { sd_event_source *expire; }; -void route_hash_func(const Route *route, struct siphash *state); -int route_compare_func(const Route *a, const Route *b); extern const struct hash_ops route_hash_ops; int route_new(Route **ret); @@ -102,7 +100,6 @@ int link_request_route( 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); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 535af175a3..8f4297a86a 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -153,7 +153,7 @@ static int routing_policy_rule_dup(const RoutingPolicyRule *src, RoutingPolicyRu return 0; } -void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) { +static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) { assert(rule); siphash24_compress(&rule->family, sizeof(rule->family), state); @@ -194,7 +194,7 @@ void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash } } -int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b) { +static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b) { int r; r = CMP(a->family, b->family); @@ -718,7 +718,7 @@ void link_foreignize_routing_policy_rules(Link *link) { } } -int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) { +static int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) { int r; assert(req); @@ -793,10 +793,14 @@ static int link_request_routing_policy_rule(Link *link, RoutingPolicyRule *rule) existing->source = rule->source; log_routing_policy_rule_debug(existing, "Requesting", link, link->manager); - r = link_queue_request(link, REQUEST_TYPE_ROUTING_POLICY_RULE, existing, false, - &link->static_routing_policy_rule_messages, - (request_netlink_handler_t) static_routing_policy_rule_configure_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_ROUTING_POLICY_RULE, + existing, NULL, + routing_policy_rule_hash_func, + routing_policy_rule_compare_func, + routing_policy_rule_process_request, + &link->static_routing_policy_rule_messages, + static_routing_policy_rule_configure_handler, + NULL); if (r <= 0) return r; diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 2d60e59565..b6ce2fa19c 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -12,7 +12,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef struct RoutingPolicyRule { Manager *manager; @@ -58,13 +57,9 @@ const char *fr_act_type_full_to_string(int t) _const_; RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule); -void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state); -int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b); - void network_drop_invalid_routing_policy_rules(Network *network); int link_request_static_routing_policy_rules(Link *link); -int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule); int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except); diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 5128c33719..148277685e 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -420,7 +420,6 @@ static int link_configure(Link *link, Request *req) { assert(link); assert(link->manager); - assert(link->manager->rtnl); assert(req); log_link_debug(link, "Setting %s", request_type_to_string(req->type)); @@ -560,7 +559,7 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { return true; } -int link_process_set_link(Request *req, Link *link, void *userdata) { +static int link_process_set_link(Request *req, Link *link, void *userdata) { int r; assert(req); @@ -587,10 +586,12 @@ static int link_request_set_link( int r; assert(link); - assert(netlink_handler); - r = link_queue_request(link, type, NULL, false, - &link->set_link_messages, netlink_handler, &req); + r = link_queue_request_full(link, type, NULL, NULL, NULL, NULL, + link_process_set_link, + &link->set_link_messages, + netlink_handler, + &req); if (r < 0) return log_link_warning_errno(link, r, "Failed to request to set %s: %m", request_type_to_string(type)); @@ -1016,7 +1017,7 @@ static bool link_is_ready_to_activate(Link *link) { return true; } -int link_process_activation(Request *req, Link *link, void *userdata) { +static int link_process_activation(Request *req, Link *link, void *userdata) { bool up = PTR_TO_INT(userdata); int r; @@ -1034,7 +1035,6 @@ int link_process_activation(Request *req, Link *link, void *userdata) { } int link_request_to_activate(Link *link) { - Request *req; bool up; int r; @@ -1065,13 +1065,14 @@ 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, - link_up_or_down_handler, &req); + r = link_queue_request_full(link, REQUEST_TYPE_ACTIVATE_LINK, + INT_TO_PTR(up), NULL, NULL, NULL, + link_process_activation, + &link->set_flags_messages, + link_up_or_down_handler, NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request to activate link: %m"); - req->userdata = INT_TO_PTR(up); - log_link_debug(link, "Requested to activate link"); return 0; } @@ -1106,7 +1107,7 @@ static bool link_is_ready_to_bring_up_or_down(Link *link, bool up) { return true; } -int link_process_up_or_down(Request *req, Link *link, void *userdata) { +static int link_process_up_or_down(Request *req, Link *link, void *userdata) { bool up = PTR_TO_INT(userdata); int r; @@ -1124,19 +1125,19 @@ int link_process_up_or_down(Request *req, Link *link, void *userdata) { } int link_request_to_bring_up_or_down(Link *link, bool up) { - Request *req; int r; assert(link); - r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages, - link_up_or_down_handler, &req); + r = link_queue_request_full(link, REQUEST_TYPE_UP_DOWN, + INT_TO_PTR(up), NULL, NULL, NULL, + link_process_up_or_down, + &link->set_flags_messages, + link_up_or_down_handler, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m", up_or_down(up)); - req->userdata = INT_TO_PTR(up); - log_link_debug(link, "Requested to bring link %s", up_or_down(up)); return 0; } diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h index 5dce0c7b5f..7e5ba32ef1 100644 --- a/src/network/networkd-setlink.h +++ b/src/network/networkd-setlink.h @@ -5,7 +5,6 @@ #include typedef struct Link Link; -typedef struct Request Request; int link_request_to_set_addrgen_mode(Link *link); int link_request_to_set_bond(Link *link); @@ -21,12 +20,8 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu); int link_configure_mtu(Link *link); -int link_process_set_link(Request *req, Link *link, void *userdata); - -int link_process_activation(Request *req, Link *link, void *userdata); int link_request_to_activate(Link *link); -int link_process_up_or_down(Request *req, Link *link, void *userdata); int link_request_to_bring_up_or_down(Link *link, bool up); int link_down_now(Link *link); diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index 6ec6ed0aff..6aef268d1f 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -151,7 +151,7 @@ static const char *qdisc_get_tca_kind(const QDisc *qdisc) { QDISC_VTABLE(qdisc)->tca_kind : qdisc->tca_kind; } -void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) { +static void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) { assert(qdisc); assert(state); @@ -160,7 +160,7 @@ void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) { siphash24_compress_string(qdisc_get_tca_kind(qdisc), state); } -int qdisc_compare_func(const QDisc *a, const QDisc *b) { +static int qdisc_compare_func(const QDisc *a, const QDisc *b) { int r; assert(a); @@ -359,7 +359,7 @@ static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) { return link_find_tclass(link, qdisc->parent, NULL) >= 0; } -int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) { +static int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) { int r; assert(req); @@ -400,10 +400,14 @@ int link_request_qdisc(Link *link, QDisc *qdisc) { existing->source = qdisc->source; log_qdisc_debug(existing, link, "Requesting"); - r = link_queue_request(link, REQUEST_TYPE_TC_QDISC, existing, false, - &link->tc_messages, - (request_netlink_handler_t) qdisc_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_TC_QDISC, + existing, NULL, + qdisc_hash_func, + qdisc_compare_func, + qdisc_process_request, + &link->tc_messages, + 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/qdisc.h b/src/network/tc/qdisc.h index 37ec61cbc7..adaaf260c4 100644 --- a/src/network/tc/qdisc.h +++ b/src/network/tc/qdisc.h @@ -8,7 +8,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef enum QDiscKind { QDISC_KIND_BFIFO, @@ -77,12 +76,8 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(QDisc, qdisc); QDisc* qdisc_free(QDisc *qdisc); int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret); -void qdisc_hash_func(const QDisc *qdisc, struct siphash *state); -int qdisc_compare_func(const QDisc *a, const QDisc *b); - int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **qdisc); -int qdisc_process_request(Request *req, Link *link, QDisc *qdisc); int link_request_qdisc(Link *link, QDisc *qdisc); void network_drop_invalid_qdisc(Network *network); diff --git a/src/network/tc/tclass.c b/src/network/tc/tclass.c index 42011a93e8..d3b3c19bdf 100644 --- a/src/network/tc/tclass.c +++ b/src/network/tc/tclass.c @@ -121,7 +121,7 @@ static const char *tclass_get_tca_kind(const TClass *tclass) { TCLASS_VTABLE(tclass)->tca_kind : tclass->tca_kind; } -void tclass_hash_func(const TClass *tclass, struct siphash *state) { +static void tclass_hash_func(const TClass *tclass, struct siphash *state) { assert(tclass); assert(state); @@ -130,7 +130,7 @@ void tclass_hash_func(const TClass *tclass, struct siphash *state) { siphash24_compress_string(tclass_get_tca_kind(tclass), state); } -int tclass_compare_func(const TClass *a, const TClass *b) { +static int tclass_compare_func(const TClass *a, const TClass *b) { int r; assert(a); @@ -318,7 +318,7 @@ static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) { return link_find_qdisc(link, tclass->classid, tclass->parent, tclass_get_tca_kind(tclass), NULL) >= 0; } -int tclass_process_request(Request *req, Link *link, TClass *tclass) { +static int tclass_process_request(Request *req, Link *link, TClass *tclass) { int r; assert(req); @@ -359,10 +359,14 @@ int link_request_tclass(Link *link, TClass *tclass) { existing->source = tclass->source; log_tclass_debug(existing, link, "Requesting"); - r = link_queue_request(link, REQUEST_TYPE_TC_CLASS, existing, false, - &link->tc_messages, - (request_netlink_handler_t) tclass_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_TC_CLASS, + existing, NULL, + tclass_hash_func, + tclass_compare_func, + tclass_process_request, + &link->tc_messages, + tclass_handler, + NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request TClass: %m"); if (r == 0) diff --git a/src/network/tc/tclass.h b/src/network/tc/tclass.h index f7b724b002..606bb3fef3 100644 --- a/src/network/tc/tclass.h +++ b/src/network/tc/tclass.h @@ -8,7 +8,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef enum TClassKind { TCLASS_KIND_DRR, @@ -59,12 +58,8 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(TClass, tclass); TClass* tclass_free(TClass *tclass); int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret); -void tclass_hash_func(const TClass *qdisc, struct siphash *state); -int tclass_compare_func(const TClass *a, const TClass *b); - int link_find_tclass(Link *link, uint32_t classid, TClass **ret); -int tclass_process_request(Request *req, Link *link, TClass *tclass); int link_request_tclass(Link *link, TClass *tclass); void network_drop_invalid_tclass(Network *network);