ordered_set_remove(req->manager->request_queue, req);
req->manager = NULL;
+ req->netlink_slot = sd_netlink_slot_unref(req->netlink_slot);
return req;
}
static int request_netlink_handler(sd_netlink *nl, sd_netlink_message *m, Request *req) {
assert(req);
+ assert(req->netlink_slot);
+ assert_se(sd_netlink_slot_set_floating(req->netlink_slot, true) >= 0);
+ req->netlink_slot = sd_netlink_slot_unref(req->netlink_slot);
+
if (req->counter) {
assert(*req->counter > 0);
(*req->counter)--;
assert(m);
assert(req);
- r = netlink_call_async(nl, NULL, m, request_netlink_handler, request_destroy_callback, req);
+ r = netlink_call_async(nl, &req->netlink_slot, m, request_netlink_handler, request_destroy_callback, req);
if (r < 0)
return r;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include <net/if.h>
+
+#include "sd-netlink.h"
+
#include "alloc-util.h"
#include "hashmap.h"
#include "hostname-setup.h"
+#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-manager.h"
+#include "networkd-queue.h"
#include "networkd-route-util.h"
+#include "ordered-set.h"
#include "strv.h"
#include "tests.h"
#include "vrf.h"
ASSERT_EQ(vrf.table, 5678U);
}
+static int test_request_process(Request *req, Link *link, void *userdata) {
+ assert_not_reached();
+}
+
+static int test_request_netlink_handler(
+ sd_netlink *rtnl,
+ sd_netlink_message *message,
+ Request *req,
+ Link *link,
+ void *userdata) {
+
+ assert(rtnl);
+ assert(message);
+ assert(req);
+ assert(!link);
+ assert(userdata);
+
+ *(bool*) userdata = true;
+ return 0;
+}
+
+static void test_request_netlink_handler_one(bool detach) {
+ _cleanup_(manager_freep) Manager *manager = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
+ bool handler_called = false;
+ unsigned counter = 0;
+ Request *req;
+
+ ASSERT_OK(manager_new(&manager, /* test_mode= */ true));
+ ASSERT_OK(sd_netlink_open(&rtnl));
+
+ ASSERT_OK_POSITIVE(manager_queue_request_full(
+ manager,
+ REQUEST_TYPE_ADDRESS_LABEL,
+ &handler_called,
+ /* free_func= */ NULL,
+ /* hash_func= */ NULL,
+ /* compare_func= */ NULL,
+ test_request_process,
+ &counter,
+ test_request_netlink_handler,
+ &req));
+ ASSERT_EQ(counter, 1U);
+
+ int ifindex = (int) if_nametoindex("lo");
+ ASSERT_GT(ifindex, 0);
+ ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex));
+ ASSERT_OK(request_call_netlink_async(rtnl, message, req));
+ ASSERT_EQ(netlink_get_reply_callback_count(rtnl), 1U);
+
+ if (detach) {
+ request_detach(req);
+ ASSERT_EQ(counter, 0U);
+ ASSERT_EQ(netlink_get_reply_callback_count(rtnl), 0U);
+ }
+
+ ASSERT_OK(sd_netlink_wait(rtnl, 0));
+ ASSERT_OK_POSITIVE(sd_netlink_process(rtnl, /* ret= */ NULL));
+
+ ASSERT_EQ(handler_called, !detach);
+ ASSERT_EQ(counter, 0U);
+ ASSERT_EQ(netlink_get_reply_callback_count(rtnl), 0U);
+ ASSERT_TRUE(ordered_set_isempty(manager->request_queue));
+}
+
+TEST(request_netlink_handler_called) {
+ test_request_netlink_handler_one(/* detach= */ false);
+}
+
+TEST(request_netlink_handler_detached) {
+ test_request_netlink_handler_one(/* detach= */ true);
+}
+
TEST(manager_enumerate) {
_cleanup_(manager_freep) Manager *manager = NULL;