]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: introduce request_call_netlink_async()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 28 Feb 2022 00:20:42 +0000 (09:20 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 11 Mar 2022 05:20:31 +0000 (14:20 +0900)
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.

22 files changed:
src/network/netdev/netdev.c
src/network/networkd-address-label.c
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-bridge-fdb.c
src/network/networkd-bridge-mdb.c
src/network/networkd-dhcp-prefix-delegation.c
src/network/networkd-dhcp4.c
src/network/networkd-dhcp6.c
src/network/networkd-ipv4ll.c
src/network/networkd-ipv6-proxy-ndp.c
src/network/networkd-ndisc.c
src/network/networkd-neighbor.c
src/network/networkd-nexthop.c
src/network/networkd-queue.c
src/network/networkd-queue.h
src/network/networkd-route.c
src/network/networkd-route.h
src/network/networkd-routing-policy-rule.c
src/network/networkd-setlink.c
src/network/tc/qdisc.c
src/network/tc/tclass.c

index d296d799c3fd17e6fb083475db7b3981c559accb..ee3b883b5cafd4755deaa60f8e209f6d48e285df 100644 (file)
@@ -595,13 +595,10 @@ static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) {
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(netdev->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
+        r = request_call_netlink_async(netdev->manager->rtnl, m, req);
         if (r < 0)
                 return r;
 
-        link_ref(link);
-
         netdev->state = NETDEV_STATE_CREATING;
         log_netdev_debug(netdev, "Creating");
         return 0;
@@ -650,17 +647,11 @@ int stacked_netdev_process_request(Request *req, Link *link, void *userdata) {
         return 1;
 }
 
-static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
         int r;
 
         assert(m);
         assert(link);
-        assert(link->create_stacked_netdev_messages > 0);
-
-        link->create_stacked_netdev_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 0;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -693,7 +684,7 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) {
         link->stacked_netdevs_created = false;
         r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true,
                                &link->create_stacked_netdev_messages,
-                               link_create_stacked_netdev_handler,
+                               create_stacked_netdev_handler,
                                NULL);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to request stacked netdev '%s': %m",
index c165cde092e92484e5fcdf8463ff5da0ef84a10e..5c31a44ce4253e21e55ce2a4ac17aea6b9c289c1 100644 (file)
@@ -65,19 +65,17 @@ static int address_label_new_static(Network *network, const char *filename, unsi
         return 0;
 }
 
-static int address_label_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int address_label_configure_handler(
+                sd_netlink *rtnl,
+                sd_netlink_message *m,
+                Request *req,
+                Link *link,
+                void *userdata) {
+
         int r;
 
-        assert(rtnl);
         assert(m);
         assert(link);
-        assert(link->ifname);
-        assert(link->static_address_label_messages > 0);
-
-        link->static_address_label_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -123,13 +121,7 @@ static int address_label_configure(AddressLabel *label, Link *link, Request *req
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 int address_label_process_request(Request *req, Link *link, void *userdata) {
index 63b40da4328b1f9dbce3c0b5bae1619bb6644d80..e9a79d352d1ef978cbc4210bb512559f3ed9d4dd 100644 (file)
@@ -1023,9 +1023,6 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m,
         assert(link);
         assert(error_msg);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 0;
-
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
                 log_link_message_warning_errno(link, m, r, error_msg);
@@ -1087,12 +1084,7 @@ static int address_configure(const Address *address, Link *link, Request *req) {
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static bool address_is_ready_to_configure(Link *link, const Address *address) {
@@ -1135,7 +1127,7 @@ int link_request_address(
                 Address *address,
                 bool consume_object,
                 unsigned *message_counter,
-                link_netlink_message_handler_t netlink_handler,
+                address_netlink_handler_t netlink_handler,
                 Request **ret) {
 
         Address *acquired, *existing;
@@ -1205,7 +1197,7 @@ int link_request_address(
 
         log_address_debug(existing, "Requesting", link);
         r = link_queue_request(link, REQUEST_TYPE_ADDRESS, existing, false,
-                               message_counter, netlink_handler, ret);
+                               message_counter, (request_netlink_handler_t) netlink_handler, ret);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to request address: %m");
         if (r == 0)
@@ -1216,13 +1208,10 @@ int link_request_address(
         return 1;
 }
 
-static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
         int r;
 
         assert(link);
-        assert(link->static_address_messages > 0);
-
-        link->static_address_messages--;
 
         r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address");
         if (r <= 0)
index a90dbceb64945d03d599f9d4cf06f7d2e1d0a515..a41274a1fc3598395da442a6f18e3bf6f5b28744 100644 (file)
@@ -18,6 +18,12 @@ typedef struct Manager Manager;
 typedef struct Network Network;
 typedef struct Request Request;
 typedef int (*address_ready_callback_t)(Address *address);
+typedef int (*address_netlink_handler_t)(
+                sd_netlink *rtnl,
+                sd_netlink_message *m,
+                Request *req,
+                Link *link,
+                Address *address);
 
 struct Address {
         Link *link;
@@ -97,7 +103,7 @@ int link_request_address(
                 Address *address,
                 bool consume_object,
                 unsigned *message_counter,
-                link_netlink_message_handler_t netlink_handler,
+                address_netlink_handler_t netlink_handler,
                 Request **ret);
 int link_request_static_address(Link *link, Address *address, bool consume);
 int link_request_static_addresses(Link *link);
index e8a05e5e133c1dca3e01a349fe10218e1106b1c8..cc02213c28a6ca6d70f2e9367af9f1717c29e622 100644 (file)
@@ -93,16 +93,11 @@ static int bridge_fdb_new_static(
         return 0;
 }
 
-static int bridge_fdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int bridge_fdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
         int r;
 
+        assert(m);
         assert(link);
-        assert(link->static_bridge_fdb_messages > 0);
-
-        link->static_bridge_fdb_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 0;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -185,13 +180,7 @@ static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, Request *req) {
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) {
index b9320f7ea2ca9cba7bb236cac525a36e359900c5..88ae091c1a598a79b5678012360b58b7f144cb3e 100644 (file)
@@ -81,16 +81,11 @@ static int bridge_mdb_new_static(
         return 0;
 }
 
-static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
         int r;
 
+        assert(m);
         assert(link);
-        assert(link->static_bridge_mdb_messages > 0);
-
-        link->static_bridge_mdb_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
 
         r = sd_netlink_message_get_errno(m);
         if (r == -EINVAL && streq_ptr(link->kind, "bridge") && link->master_ifindex <= 0) {
@@ -164,13 +159,7 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, Request *req) {
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static bool bridge_mdb_is_ready_to_configure(Link *link) {
index bba66f71ed5d93170720dd4d47692a1cfe8737b5..edc893e9f6913cdc77cc515b0f53c21ba4429997 100644 (file)
@@ -288,13 +288,10 @@ static int dhcp_pd_check_ready(Link *link) {
         return 1;
 }
 
-static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
         int r;
 
         assert(link);
-        assert(link->dhcp_pd_messages > 0);
-
-        link->dhcp_pd_messages--;
 
         r = route_configure_handler_internal(rtnl, m, link, "Failed to add prefix route for DHCP delegated subnet prefix");
         if (r <= 0)
@@ -344,13 +341,10 @@ static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, usec
         return 0;
 }
 
-static int dhcp_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int dhcp_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
         int r;
 
         assert(link);
-        assert(link->dhcp_pd_messages > 0);
-
-        link->dhcp_pd_messages--;
 
         r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCP-PD address");
         if (r <= 0)
@@ -658,13 +652,10 @@ void dhcp4_pd_prefix_lost(Link *uplink) {
                 (void) link_remove(tunnel);
 }
 
-static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
         int r;
 
         assert(link);
-        assert(link->dhcp4_messages > 0);
-
-        link->dhcp4_messages--;
 
         r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv4 delegated prefix");
         if (r <= 0)
@@ -677,13 +668,10 @@ static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message
         return 1;
 }
 
-static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
         int r;
 
         assert(link);
-        assert(link->dhcp6_messages > 0);
-
-        link->dhcp6_messages--;
 
         r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv6 delegated prefix");
         if (r <= 0)
@@ -704,7 +692,7 @@ static int dhcp_request_unreachable_route(
                 NetworkConfigSource source,
                 const union in_addr_union *server_address,
                 unsigned *counter,
-                link_netlink_message_handler_t callback) {
+                route_netlink_handler_t callback) {
 
         _cleanup_(route_freep) Route *route = NULL;
         Route *existing;
index 1aa389bb53b9dfe741e0a1ef0542aa7ced48e8f4..dcde7f9bedb41d0959e2393ac3952104e815096f 100644 (file)
@@ -177,16 +177,11 @@ static int dhcp4_retry(Link *link) {
         return dhcp4_request_address_and_routes(link, false);
 }
 
-static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
         int r;
 
+        assert(m);
         assert(link);
-        assert(link->dhcp4_messages > 0);
-
-        link->dhcp4_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
 
         r = sd_netlink_message_get_errno(m);
         if (r == -ENETUNREACH && !link->dhcp4_route_retrying) {
@@ -829,13 +824,10 @@ int dhcp4_lease_lost(Link *link) {
         return link_request_static_routes(link, true);
 }
 
-static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
         int r;
 
         assert(link);
-        assert(link->dhcp4_messages > 0);
-
-        link->dhcp4_messages--;
 
         r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv4 address");
         if (r <= 0)
index 3bb013ebaf86d6a6c2b880c03a39f4fd30c9b7e7..bceae735b090ec25228907d48275738ec2f8ff41 100644 (file)
@@ -136,13 +136,10 @@ int dhcp6_check_ready(Link *link) {
         return 0;
 }
 
-static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
         int r;
 
         assert(link);
-        assert(link->dhcp6_messages > 0);
-
-        link->dhcp6_messages--;
 
         r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv6 address");
         if (r <= 0)
index 5e3854281c5627521082030a390597ba2cd3b7bd..67eb9d2aa1cd139fd2b8675ec2dffcd76b18b674 100644 (file)
@@ -70,7 +70,7 @@ static int ipv4ll_address_lost(Link *link) {
         return address_remove(existing);
 }
 
-static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
         int r;
 
         assert(link);
index def456c9aa2890963b2c38eb64fa931be6cbbded..b245a9eba2678aac617450df3929c4c895549b8a 100644 (file)
@@ -26,13 +26,17 @@ void network_adjust_ipv6_proxy_ndp(Network *network) {
         }
 }
 
-static int ipv6_proxy_ndp_address_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int ipv6_proxy_ndp_address_configure_handler(
+                sd_netlink *rtnl,
+                sd_netlink_message *m,
+                Request *req,
+                Link *link,
+                struct in6_addr *address) {
+
         int r;
 
+        assert(m);
         assert(link);
-        assert(link->static_ipv6_proxy_ndp_messages > 0);
-
-        link->static_ipv6_proxy_ndp_messages--;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0)
@@ -71,13 +75,7 @@ static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address) {
@@ -109,7 +107,8 @@ int link_request_static_ipv6_proxy_ndp_addresses(Link *link) {
         SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) {
                 r = link_queue_request(link, REQUEST_TYPE_IPV6_PROXY_NDP, address, false,
                                        &link->static_ipv6_proxy_ndp_messages,
-                                       ipv6_proxy_ndp_address_configure_handler, NULL);
+                                       (request_netlink_handler_t) ipv6_proxy_ndp_address_configure_handler,
+                                       NULL);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Failed to request IPv6 proxy NDP address: %m");
         }
index 2f86ade325ac069dae0f008bc222944f005b00c9..2a85fb3cfb1f57d69de4caaf647bd65e9cd71453 100644 (file)
@@ -203,13 +203,10 @@ static int ndisc_check_ready(Link *link) {
         return 0;
 }
 
-static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
         int r;
 
         assert(link);
-        assert(link->ndisc_messages > 0);
-
-        link->ndisc_messages--;
 
         r = route_configure_handler_internal(rtnl, m, link, "Could not set NDisc route");
         if (r <= 0)
@@ -254,13 +251,10 @@ static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
                                   ndisc_route_handler, NULL);
 }
 
-static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
         int r;
 
         assert(link);
-        assert(link->ndisc_messages > 0);
-
-        link->ndisc_messages--;
 
         r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address");
         if (r <= 0)
index 33fa5e21ecfa964abed5373a92168e946b8c114a..1cb5333b66187f46448dd9b735d3c0357a83a980 100644 (file)
@@ -215,14 +215,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) {
@@ -243,17 +236,11 @@ int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) {
         return 1;
 }
 
-static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Neighbor *neighbor) {
         int r;
 
         assert(m);
         assert(link);
-        assert(link->static_neighbor_messages > 0);
-
-        link->static_neighbor_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -271,13 +258,7 @@ static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_messag
         return 1;
 }
 
-static int link_request_neighbor(
-                Link *link,
-                const Neighbor *neighbor,
-                unsigned *message_counter,
-                link_netlink_message_handler_t netlink_handler,
-                Request **ret) {
-
+static int link_request_neighbor(Link *link, const Neighbor *neighbor) {
         Neighbor *existing;
         int r;
 
@@ -302,7 +283,9 @@ static int link_request_neighbor(
 
         log_neighbor_debug(existing, "Requesting", link);
         r = link_queue_request(link, REQUEST_TYPE_NEIGHBOR, existing, false,
-                               message_counter, netlink_handler, ret);
+                               &link->static_neighbor_messages,
+                               (request_netlink_handler_t) static_neighbor_configure_handler,
+                               NULL);
         if (r <= 0)
                 return r;
 
@@ -321,8 +304,7 @@ int link_request_static_neighbors(Link *link) {
         link->static_neighbors_configured = false;
 
         HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) {
-                r = link_request_neighbor(link, neighbor, &link->static_neighbor_messages,
-                                          static_neighbor_configure_handler, NULL);
+                r = link_request_neighbor(link, neighbor);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Could not request neighbor: %m");
         }
index 143ecce6c49fe7e74c89e872b8e052e7da1b89db..219a08e1597eee10d3dc64c516d82ec61b947b15 100644 (file)
@@ -485,25 +485,14 @@ static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) {
                 }
         }
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
-static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, NextHop *nexthop) {
         int r;
 
+        assert(m);
         assert(link);
-        assert(link->static_nexthop_messages > 0);
-
-        link->static_nexthop_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -583,13 +572,7 @@ int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) {
         return 1;
 }
 
-static int link_request_nexthop(
-                Link *link,
-                NextHop *nexthop,
-                unsigned *message_counter,
-                link_netlink_message_handler_t netlink_handler,
-                Request **ret) {
-
+static int link_request_nexthop(Link *link, NextHop *nexthop) {
         NextHop *existing;
         int r;
 
@@ -618,7 +601,9 @@ static int link_request_nexthop(
 
         log_nexthop_debug(existing, "Requesting", link);
         r = link_queue_request(link, REQUEST_TYPE_NEXTHOP, existing, false,
-                               message_counter, netlink_handler, ret);
+                               &link->static_nexthop_messages,
+                               (request_netlink_handler_t) static_nexthop_handler,
+                               NULL);
         if (r <= 0)
                 return r;
 
@@ -639,8 +624,7 @@ int link_request_static_nexthops(Link *link, bool only_ipv4) {
                 if (only_ipv4 && nh->family != AF_INET)
                         continue;
 
-                r = link_request_nexthop(link, nh, &link->static_nexthop_messages,
-                                         static_nexthop_handler, NULL);
+                r = link_request_nexthop(link, nh);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Could not request nexthop: %m");
         }
index 70edc27fcdf2cfb586597ee132f5226523001f40..a509cd4d4b60be68e5b3e93a10a338b3391fd366 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "netlink-util.h"
 #include "networkd-address.h"
 #include "networkd-address-label.h"
 #include "networkd-bridge-fdb.h"
@@ -89,12 +90,16 @@ static Request *request_free(Request *req) {
         if (req->consume_object)
                 request_free_object(req->type, req->object);
 
+        if (req->counter)
+                (*req->counter)--;
+
         link_unref(req->link); /* link may be NULL, but link_unref() can handle it gracefully. */
 
         return mfree(req);
 }
 
 DEFINE_TRIVIAL_REF_UNREF_FUNC(Request, request, request_free);
+DEFINE_TRIVIAL_DESTRUCTOR(request_destroy_callback, Request, request_unref);
 
 void request_detach(Manager *manager, Request *req) {
         assert(manager);
@@ -107,13 +112,6 @@ void request_detach(Manager *manager, Request *req) {
                 return;
 
         req->manager = NULL;
-
-        if (req->message_counter) {
-                assert(*req->message_counter > 0);
-                (*req->message_counter)--;
-                req->message_counter = NULL; /* To prevent double decrement. */
-        }
-
         request_unref(req);
 }
 
@@ -301,8 +299,8 @@ int link_queue_request(
                 RequestType type,
                 void *object,
                 bool consume_object,
-                unsigned *message_counter,
-                link_netlink_message_handler_t netlink_handler,
+                unsigned *counter,
+                request_netlink_handler_t netlink_handler,
                 Request **ret) {
 
         _cleanup_(request_unrefp) Request *req = NULL;
@@ -343,7 +341,6 @@ int link_queue_request(
                 .type = type,
                 .object = object,
                 .consume_object = consume_object,
-                .message_counter = message_counter,
                 .netlink_handler = netlink_handler,
         };
 
@@ -359,8 +356,9 @@ int link_queue_request(
                 return r;
 
         req->manager = link->manager;
-        if (req->message_counter)
-                (*req->message_counter)++;
+        req->counter = counter;
+        if (req->counter)
+                (*req->counter)++;
 
         if (ret)
                 *ret = req;
@@ -447,14 +445,14 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
                         default:
                                 return -EINVAL;
                         }
-                        if (r < 0) {
-                                if (req->link)
-                                        link_enter_failed(req->link);
-                        } else if (r > 0) {
-                                req->message_counter = NULL;
-                                request_detach(manager, req);
-                                processed = true;
-                        }
+                        if (r == 0)
+                                continue;
+
+                        processed = true;
+                        request_detach(manager, req);
+
+                        if (r < 0 && req->link)
+                                link_enter_failed(req->link);
                 }
 
                 if (!processed)
@@ -463,3 +461,36 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
 
         return 0;
 }
+
+static int request_netlink_handler(sd_netlink *nl, sd_netlink_message *m, Request *req) {
+        assert(req);
+
+        if (req->counter) {
+                assert(*req->counter > 0);
+                (*req->counter)--;
+                req->counter = NULL; /* To prevent double decrement on free. */
+        }
+
+        if (req->link && IN_SET(req->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 0;
+
+        if (req->netlink_handler)
+                return req->netlink_handler(nl, m, req, req->link, req->object);
+
+        return 0;
+}
+
+int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req) {
+        int r;
+
+        assert(nl);
+        assert(m);
+        assert(req);
+
+        r = netlink_call_async(nl, NULL, m, request_netlink_handler, request_destroy_callback, req);
+        if (r < 0)
+                return r;
+
+        request_ref(req);
+        return 0;
+}
index 14403efdd084d6e7ec171ebbd8165a7fa88e7a36..ac4c5c13af3fbcd61c35d0119490ec219ef5c275 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include "sd-event.h"
+#include "sd-netlink.h"
 
 #include "networkd-link.h"
 
@@ -16,6 +17,9 @@ typedef struct Route Route;
 typedef struct RoutingPolicyRule RoutingPolicyRule;
 typedef struct QDisc QDisc;
 typedef struct TClass TClass;
+typedef struct Request Request;
+
+typedef int (*request_netlink_handler_t)(sd_netlink *nl, sd_netlink_message *m, Request *req, Link *link, void *userdata);
 
 typedef enum RequestType {
         REQUEST_TYPE_ACTIVATE_LINK,
@@ -43,7 +47,7 @@ typedef enum RequestType {
         _REQUEST_TYPE_INVALID = -EINVAL,
 } RequestType;
 
-typedef struct Request {
+struct Request {
         unsigned n_ref;
 
         Manager *manager; /* must be non-NULL */
@@ -68,9 +72,15 @@ typedef struct Request {
                 void *object;
         };
         void *userdata;
-        unsigned *message_counter;
-        link_netlink_message_handler_t netlink_handler;
-} Request;
+
+        /* incremented when requested, decremented when request is completed or failed. */
+        unsigned *counter;
+        /* called in netlink handler, the 'counter' is decremented before this is called.
+         * If this is specified, then the 'process' function must increment the reference of this
+         * request, and pass this request to the netlink_call_async(), and set the destroy function
+         * to the slot. */
+        request_netlink_handler_t netlink_handler;
+};
 
 Request *request_ref(Request *req);
 Request *request_unref(Request *req);
@@ -87,8 +97,9 @@ int link_queue_request(
                 RequestType type,
                 void *object,
                 bool consume_object,
-                unsigned *message_counter,
-                link_netlink_message_handler_t netlink_handler,
+                unsigned *counter,
+                request_netlink_handler_t netlink_handler,
                 Request **ret);
 
 int manager_process_requests(sd_event_source *s, void *userdata);
+int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req);
index 9be1190655e992776e5dcc8830978a7491ae0ad1..cfc69679632bb5f1a3a68b2fec4e89a12da690c9 100644 (file)
@@ -1141,9 +1141,6 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li
         assert(link);
         assert(error_msg);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 0;
-
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
                 log_link_message_warning_errno(link, m, r, "Could not set route");
@@ -1246,13 +1243,7 @@ static int route_configure(const Route *route, Link *link, Request *req) {
                         return r;
         }
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static int route_is_ready_to_configure(const Route *route, Link *link) {
@@ -1385,7 +1376,7 @@ int link_request_route(
                 Route *route,
                 bool consume_object,
                 unsigned *message_counter,
-                link_netlink_message_handler_t netlink_handler,
+                route_netlink_handler_t netlink_handler,
                 Request **ret) {
 
         Route *existing;
@@ -1433,7 +1424,7 @@ int link_request_route(
 
         log_route_debug(existing, "Requesting", link, link->manager);
         r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false,
-                               message_counter, netlink_handler, ret);
+                               message_counter, (request_netlink_handler_t) netlink_handler, ret);
         if (r <= 0)
                 return r;
 
@@ -1441,13 +1432,10 @@ int link_request_route(
         return 1;
 }
 
-static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
         int r;
 
         assert(link);
-        assert(link->static_route_messages > 0);
-
-        link->static_route_messages--;
 
         r = route_configure_handler_internal(rtnl, m, link, "Could not set route");
         if (r <= 0)
@@ -1473,7 +1461,9 @@ static int link_request_static_route(Link *link, Route *route) {
 
         log_route_debug(route, "Requesting", link, link->manager);
         return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false,
-                                  &link->static_route_messages, static_route_handler, NULL);
+                                  &link->static_route_messages,
+                                  (request_netlink_handler_t) static_route_handler,
+                                  NULL);
 }
 
 static int link_request_wireguard_routes(Link *link, bool only_ipv4) {
index 634ed16176a4a388bd7a67ab4f1c5aeb23ba050d..8c1c5cf6809d37a157a244b58368353e9f46da55 100644 (file)
 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);
index a90c176f7694bcea182d986b89f4e826879f39cc..535af175a32a0da3a358f6798a6dfcc6e3d331e9 100644 (file)
@@ -626,13 +626,7 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, Re
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) {
@@ -742,19 +736,17 @@ int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyR
         return 1;
 }
 
-static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int static_routing_policy_rule_configure_handler(
+                sd_netlink *rtnl,
+                sd_netlink_message *m,
+                Request *req,
+                Link *link,
+                RoutingPolicyRule *rule) {
+
         int r;
 
-        assert(rtnl);
         assert(m);
         assert(link);
-        assert(link->ifname);
-        assert(link->static_routing_policy_rule_messages > 0);
-
-        link->static_routing_policy_rule_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -772,13 +764,7 @@ static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_net
         return 1;
 }
 
-static int link_request_routing_policy_rule(
-                Link *link,
-                RoutingPolicyRule *rule,
-                unsigned *message_counter,
-                link_netlink_message_handler_t netlink_handler,
-                Request **ret) {
-
+static int link_request_routing_policy_rule(Link *link, RoutingPolicyRule *rule) {
         RoutingPolicyRule *existing;
         int r;
 
@@ -808,7 +794,9 @@ static int link_request_routing_policy_rule(
 
         log_routing_policy_rule_debug(existing, "Requesting", link, link->manager);
         r = link_queue_request(link, REQUEST_TYPE_ROUTING_POLICY_RULE, existing, false,
-                               message_counter, netlink_handler, ret);
+                               &link->static_routing_policy_rule_messages,
+                               (request_netlink_handler_t) static_routing_policy_rule_configure_handler,
+                               NULL);
         if (r <= 0)
                 return r;
 
@@ -820,26 +808,17 @@ static int link_request_static_routing_policy_rule(Link *link, RoutingPolicyRule
         int r;
 
         if (IN_SET(rule->family, AF_INET, AF_INET6))
-                return link_request_routing_policy_rule(link, rule,
-                                                        &link->static_routing_policy_rule_messages,
-                                                        static_routing_policy_rule_configure_handler,
-                                                        NULL);
+                return link_request_routing_policy_rule(link, rule);
 
         rule->family = AF_INET;
-        r = link_request_routing_policy_rule(link, rule,
-                                             &link->static_routing_policy_rule_messages,
-                                             static_routing_policy_rule_configure_handler,
-                                             NULL);
+        r = link_request_routing_policy_rule(link, rule);
         if (r < 0) {
                 rule->family = AF_UNSPEC;
                 return r;
         }
 
         rule->family = AF_INET6;
-        r = link_request_routing_policy_rule(link, rule,
-                                             &link->static_routing_policy_rule_messages,
-                                             static_routing_policy_rule_configure_handler,
-                                             NULL);
+        r = link_request_routing_policy_rule(link, rule);
         rule->family = AF_UNSPEC;
         return r;
 }
index f5d879af78ae3e2c721b6ba5824fa9f788468ca5..b012967462f9935069c4e8b9607f8c8048c117b2 100644 (file)
@@ -54,22 +54,19 @@ static int get_link_update_flag_handler(sd_netlink *rtnl, sd_netlink_message *m,
 static int set_link_handler_internal(
                 sd_netlink *rtnl,
                 sd_netlink_message *m,
+                Request *req,
                 Link *link,
-                SetLinkOperation op,
                 bool ignore,
                 link_netlink_message_handler_t get_link_handler) {
 
+        SetLinkOperation op;
         int r;
 
         assert(m);
+        assert(req);
         assert(link);
-        assert(link->set_link_messages > 0);
-        assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
-
-        link->set_link_messages--;
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                goto on_error;
+        op = PTR_TO_INT(req->set_link_operation_ptr);
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0) {
@@ -80,7 +77,7 @@ static int set_link_handler_internal(
 
                 if (!ignore)
                         link_enter_failed(link);
-                goto on_error;
+                return 0;
         }
 
         log_link_debug(link, "%s set.", set_link_operation_to_string(op));
@@ -89,7 +86,7 @@ static int set_link_handler_internal(
                 r = link_call_getlink(link, get_link_handler);
                 if (r < 0) {
                         link_enter_failed(link);
-                        goto on_error;
+                        return 0;
                 }
         }
 
@@ -97,27 +94,12 @@ static int set_link_handler_internal(
                 link_check_ready(link);
 
         return 1;
-
-on_error:
-        switch (op) {
-        case SET_LINK_FLAGS:
-                assert(link->set_flags_messages > 0);
-                link->set_flags_messages--;
-                break;
-        case SET_LINK_MASTER:
-                link->master_set = true;
-                break;
-        default:
-                break;
-        }
-
-        return 0;
 }
 
-static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
         int r;
 
-        r = set_link_handler_internal(rtnl, m, link, SET_LINK_ADDRESS_GENERATION_MODE, /* ignore = */ true, NULL);
+        r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
         if (r <= 0)
                 return r;
 
@@ -130,49 +112,43 @@ static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m
         return 0;
 }
 
-static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_BOND, /* ignore = */ false, NULL);
+static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
 }
 
-static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_BRIDGE, /* ignore = */ true, NULL);
+static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
 }
 
-static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_BRIDGE_VLAN, /* ignore = */ false, NULL);
+static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
 }
 
-static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_CAN, /* ignore = */ false, NULL);
+static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
 }
 
-static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_FLAGS, /* ignore = */ false, get_link_update_flag_handler);
+static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_default_handler);
 }
 
-static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_GROUP, /* ignore = */ false, NULL);
+static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
 }
 
-static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_IPOIB, /* ignore = */ true, NULL);
+static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
 }
 
-static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_MAC, /* ignore = */ true, get_link_default_handler);
+static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
 }
 
-static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
         int r;
 
         assert(m);
         assert(link);
-        assert(link->set_link_messages > 0);
-
-        link->set_link_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 0;
 
         r = sd_netlink_message_get_errno(m);
         if (r == -EBUSY) {
@@ -189,24 +165,22 @@ static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message
                 return 0;
         }
 
-        /* set_link_mac_handler() also decrements set_link_messages, so increment the value once. */
-        link->set_link_messages++;
-        return link_set_mac_handler(rtnl, m, link);
+        return link_set_mac_handler(rtnl, m, req, link, userdata);
 }
 
-static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_MASTER, /* ignore = */ false, get_link_master_handler);
+static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_master_handler);
 }
 
-static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
         /* Some devices do not support setting master ifindex. Let's ignore error on unsetting master ifindex. */
-        return set_link_handler_internal(rtnl, m, link, SET_LINK_MASTER, /* ignore = */ true, get_link_master_handler);
+        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_master_handler);
 }
 
-static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
         int r;
 
-        r = set_link_handler_internal(rtnl, m, link, SET_LINK_MTU, /* ignore = */ true, get_link_default_handler);
+        r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
         if (r <= 0)
                 return r;
 
@@ -460,44 +434,34 @@ static int link_configure_fill_message(
         return 0;
 }
 
-static int link_configure(
-                Link *link,
-                SetLinkOperation op,
-                void *userdata,
-                link_netlink_message_handler_t callback) {
-
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+static int link_configure(Link *link, Request *req) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+        SetLinkOperation op;
         int r;
 
         assert(link);
         assert(link->manager);
         assert(link->manager->rtnl);
-        assert(link->network);
-        assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
-        assert(callback);
+        assert(req);
+
+        op = PTR_TO_INT(req->set_link_operation_ptr);
 
         log_link_debug(link, "Setting %s", set_link_operation_to_string(op));
 
         if (op == SET_LINK_BOND)
-                r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->master_ifindex);
+                r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->master_ifindex);
         else if (IN_SET(op, SET_LINK_CAN, SET_LINK_IPOIB))
-                r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->ifindex);
+                r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
         else
-                r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+                r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
         if (r < 0)
-                return log_link_debug_errno(link, r, "Could not allocate netlink message: %m");
+                return r;
 
-        r = link_configure_fill_message(link, req, op, userdata);
+        r = link_configure_fill_message(link, m, op, req->userdata);
         if (r < 0)
-                return log_link_debug_errno(link, r, "Could not create netlink message: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_debug_errno(link, r, "Could not send netlink message: %m");
+                return r;
 
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static bool netdev_is_ready(NetDev *netdev) {
@@ -641,21 +605,18 @@ int request_process_set_link(Request *req) {
         if (!link_is_ready_to_call_set_link(req))
                 return 0;
 
-        r = link_configure(req->link, op, req->userdata, req->netlink_handler);
+        r = link_configure(req->link, req);
         if (r < 0)
                 return log_link_error_errno(req->link, r, "Failed to set %s: %m",
                                             set_link_operation_to_string(op));
 
-        if (op == SET_LINK_FLAGS)
-                req->link->set_flags_messages++;
-
         return 1;
 }
 
 static int link_request_set_link(
                 Link *link,
                 SetLinkOperation op,
-                link_netlink_message_handler_t netlink_handler,
+                request_netlink_handler_t netlink_handler,
                 Request **ret) {
 
         Request *req;
@@ -991,14 +952,16 @@ static int link_up_dsa_slave(Link *link) {
         return 1;
 }
 
-static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool up, bool on_activate) {
+static int link_up_or_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+        bool on_activate, up;
         int r;
 
         assert(m);
+        assert(req);
         assert(link);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                goto on_error;
+        on_activate = req->type == REQUEST_TYPE_ACTIVATE_LINK;
+        up = PTR_TO_INT(req->userdata);
 
         r = sd_netlink_message_get_errno(m);
         if (r == -ENETDOWN && up && link_up_dsa_slave(link) > 0)
@@ -1012,45 +975,25 @@ static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message
 
                 log_link_message_warning_errno(link, m, r, error_msg);
                 if (on_activate)
-                        goto on_error;
+                        return 0;
         }
 
         r = link_call_getlink(link, get_link_update_flag_handler);
         if (r < 0) {
                 link_enter_failed(link);
-                goto on_error;
+                return 0;
         }
 
+        link->set_flags_messages++;
+
         if (on_activate) {
                 link->activated = true;
                 link_check_ready(link);
         }
 
-        return 1;
-
-on_error:
-        assert(link->set_flags_messages > 0);
-        link->set_flags_messages--;
-
         return 0;
 }
 
-static int link_activate_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ true);
-}
-
-static int link_activate_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ true);
-}
-
-static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ false);
-}
-
-static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ false);
-}
-
 static const char *up_or_down(bool up) {
         return up ? "up" : "down";
 }
@@ -1074,14 +1017,7 @@ static int link_up_or_down(Link *link, bool up, Request *req) {
         if (r < 0)
                 return r;
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static bool link_is_ready_to_activate(Link *link) {
@@ -1146,7 +1082,7 @@ int link_request_to_activate(Link *link) {
         link->activated = false;
 
         r = link_queue_request(link, REQUEST_TYPE_ACTIVATE_LINK, NULL, false, &link->set_flags_messages,
-                               up ? link_activate_up_handler : link_activate_down_handler, &req);
+                               link_up_or_down_handler, &req);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to request to activate link: %m");
 
@@ -1210,7 +1146,7 @@ int link_request_to_bring_up_or_down(Link *link, bool up) {
         assert(link);
 
         r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages,
-                               up ? link_up_handler : link_down_handler, &req);
+                               link_up_or_down_handler, &req);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m",
                                               up_or_down(up));
index fa3b0925b92b88dd3d811e8e13aa390e790c1d91..6ec6ed0aff74ab794c40b29bcb44bbd72ab9914d 100644 (file)
@@ -293,15 +293,11 @@ int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *ki
         return -ENOENT;
 }
 
-static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, QDisc *qdisc) {
         int r;
 
+        assert(m);
         assert(link);
-        assert(link->tc_messages > 0);
-        link->tc_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -347,12 +343,7 @@ static int qdisc_configure(QDisc *qdisc, Link *link, Request *req) {
                         return r;
         }
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) {
@@ -410,7 +401,9 @@ int link_request_qdisc(Link *link, QDisc *qdisc) {
 
         log_qdisc_debug(existing, link, "Requesting");
         r = link_queue_request(link, REQUEST_TYPE_TC_QDISC, existing, false,
-                               &link->tc_messages, qdisc_handler, NULL);
+                               &link->tc_messages,
+                               (request_netlink_handler_t) qdisc_handler,
+                               NULL);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to request QDisc: %m");
         if (r == 0)
index b5b3615d9883ea524ab023dc4d044c4701bbca07..42011a93e8fcfa28c8421be4b255a919b1f83601 100644 (file)
@@ -255,15 +255,11 @@ static void log_tclass_debug(TClass *tclass, Link *link, const char *str) {
                        strna(tclass_get_tca_kind(tclass)));
 }
 
-static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, TClass *tclass) {
         int r;
 
+        assert(m);
         assert(link);
-        assert(link->tc_messages > 0);
-        link->tc_messages--;
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -309,12 +305,7 @@ static int tclass_configure(TClass *tclass, Link *link, Request *req) {
                         return r;
         }
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, link_netlink_destroy_callback, link);
-        if (r < 0)
-                return r;
-
-        link_ref(link);
-        return 0;
+        return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
 static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) {
@@ -369,7 +360,9 @@ int link_request_tclass(Link *link, TClass *tclass) {
 
         log_tclass_debug(existing, link, "Requesting");
         r = link_queue_request(link, REQUEST_TYPE_TC_CLASS, existing, false,
-                               &link->tc_messages, tclass_handler, NULL);
+                               &link->tc_messages,
+                               (request_netlink_handler_t) tclass_handler,
+                               NULL);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to request TClass: %m");
         if (r == 0)