]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: add skeleton of request queue
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 7 May 2021 06:39:16 +0000 (15:39 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 12 May 2021 02:26:06 +0000 (11:26 +0900)
This will be used in later commits.

src/network/meson.build
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-queue.c [new file with mode: 0644]
src/network/networkd-queue.h [new file with mode: 0644]

index 4fca3106dc9431ad32f0af3fed74a34d194346ad..a8b9232e64d8318ede91da6d1332b9a951549a01 100644 (file)
@@ -105,6 +105,8 @@ sources = files('''
         networkd-network.h
         networkd-nexthop.c
         networkd-nexthop.h
+        networkd-queue.c
+        networkd-queue.h
         networkd-route.c
         networkd-route.h
         networkd-routing-policy-rule.c
index 34359b2541ceb0678abb0ae51c42dfa806aadf1e..2f33305a27367b6926bdbfbf3e942f460aa74710 100644 (file)
 #include "networkd-ndisc.h"
 #include "networkd-neighbor.h"
 #include "networkd-nexthop.h"
-#include "networkd-sriov.h"
-#include "networkd-sysctl.h"
+#include "networkd-queue.h"
 #include "networkd-radv.h"
 #include "networkd-routing-policy-rule.h"
+#include "networkd-sriov.h"
 #include "networkd-state-file.h"
+#include "networkd-sysctl.h"
 #include "networkd-wifi.h"
 #include "set.h"
 #include "socket-util.h"
@@ -2078,6 +2079,17 @@ static int link_drop_config(Link *link) {
         return r;
 }
 
+static void link_drop_requests(Link *link) {
+        Request *req;
+
+        assert(link);
+        assert(link->manager);
+
+        ORDERED_SET_FOREACH(req, link->manager->request_queue)
+                if (req->link == link)
+                        request_drop(req);
+}
+
 int link_configure(Link *link) {
         int r;
 
@@ -2232,6 +2244,8 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
         if (r < 0)
                 return r;
 
+        link_drop_requests(link);
+
         r = link_drop_config(link);
         if (r < 0)
                 return r;
@@ -2664,6 +2678,8 @@ static int link_carrier_lost(Link *link) {
                 return r;
         }
 
+        link_drop_requests(link);
+
         r = link_drop_config(link);
         if (r < 0)
                 return r;
index 562ce5ca54292723dc7cbbe037e52cd8388763db..fd576169a94cd2309af8c69f6b100dec5fab0429 100644 (file)
@@ -34,6 +34,7 @@
 #include "networkd-neighbor.h"
 #include "networkd-network-bus.h"
 #include "networkd-nexthop.h"
+#include "networkd-queue.h"
 #include "networkd-routing-policy-rule.h"
 #include "networkd-speed-meter.h"
 #include "networkd-state-file.h"
@@ -406,6 +407,10 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
+        r = sd_event_add_post(m->event, NULL, manager_process_requests, m);
+        if (r < 0)
+                return r;
+
         r = manager_connect_rtnl(m);
         if (r < 0)
                 return r;
@@ -446,6 +451,8 @@ Manager* manager_free(Manager *m) {
         HASHMAP_FOREACH(link, m->links)
                 (void) link_stop_engines(link, true);
 
+        m->request_queue = ordered_set_free_with_destructor(m->request_queue, request_free);
+
         m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free);
         m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free);
 
index 301b97c1a100789f4ca3410877f57cfae374eb81..26e88028719f482ea5e22f1d4863f9e5cdd8b7cf 100644 (file)
@@ -91,6 +91,8 @@ struct Manager {
         bool bridge_mdb_on_master_not_supported;
 
         FirewallContext *fw_ctx;
+
+        OrderedSet *request_queue;
 };
 
 int manager_new(Manager **ret);
diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c
new file mode 100644 (file)
index 0000000..24bb2c8
--- /dev/null
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "networkd-address.h"
+#include "networkd-manager.h"
+#include "networkd-neighbor.h"
+#include "networkd-nexthop.h"
+#include "networkd-route.h"
+#include "networkd-routing-policy-rule.h"
+#include "networkd-queue.h"
+
+static void request_free_object(RequestType type, void *object) {
+        switch(type) {
+        default:
+                assert_not_reached("invalid request type.");
+        }
+}
+
+Request *request_free(Request *req) {
+        if (!req)
+                return NULL;
+
+        if (req->on_free)
+                req->on_free(req);
+        if (req->consume_object)
+                request_free_object(req->type, req->object);
+        if (req->link && req->link->manager)
+                ordered_set_remove(req->link->manager->request_queue, req);
+        link_unref(req->link);
+
+        return mfree(req);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free);
+
+void request_drop(Request *req) {
+        if (req->message_counter)
+                (*req->message_counter)--;
+
+        request_free(req);
+}
+
+int link_queue_request(
+                Link *link,
+                RequestType type,
+                void *object,
+                bool consume_object,
+                unsigned *message_counter,
+                link_netlink_message_handler_t netlink_handler,
+                Request **ret) {
+
+        _cleanup_(request_freep) Request *req = NULL;
+        int r;
+
+        assert(link);
+        assert(link->manager);
+        assert(type >= 0 && type < _REQUEST_TYPE_MAX);
+        assert(object);
+        assert(netlink_handler);
+
+        req = new(Request, 1);
+        if (!req) {
+                if (consume_object)
+                        request_free_object(type, object);
+                return -ENOMEM;
+        }
+
+        *req = (Request) {
+                .link = link,
+                .type = type,
+                .object = object,
+                .consume_object = consume_object,
+                .message_counter = message_counter,
+                .netlink_handler = netlink_handler,
+        };
+
+        link_ref(link);
+
+        r = ordered_set_ensure_put(&link->manager->request_queue, NULL, req);
+        if (r < 0)
+                return r;
+
+        if (req->message_counter)
+                (*req->message_counter)++;
+
+        if (ret)
+                *ret = req;
+
+        TAKE_PTR(req);
+        return 0;
+}
+
+int manager_process_requests(sd_event_source *s, void *userdata) {
+        Manager *manager = userdata;
+        int r;
+
+        assert(manager);
+
+        for (;;) {
+                bool processed = false;
+                Request *req;
+
+                ORDERED_SET_FOREACH(req, manager->request_queue) {
+                        switch(req->type) {
+                        default:
+                                return -EINVAL;
+                        }
+                        if (r < 0)
+                                link_enter_failed(req->link);
+                        if (r > 0) {
+                                ordered_set_remove(manager->request_queue, req);
+                                request_free(req);
+                                processed = true;
+                        }
+                }
+
+                if (!processed)
+                        break;
+        }
+
+        return 0;
+}
diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h
new file mode 100644 (file)
index 0000000..4558ae5
--- /dev/null
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "sd-event.h"
+
+#include "networkd-link.h"
+
+typedef struct Request Request;
+
+typedef int (*request_after_configure_handler_t)(Request*, void*);
+typedef void (*request_on_free_handler_t)(Request*);
+
+typedef enum RequestType {
+        _REQUEST_TYPE_MAX,
+        _REQUEST_TYPE_INVALID = -EINVAL,
+} RequestType;
+
+typedef struct Request {
+        Link *link;
+        RequestType type;
+        bool consume_object;
+        void *object;
+        void *userdata;
+        unsigned *message_counter;
+        link_netlink_message_handler_t netlink_handler;
+        request_after_configure_handler_t after_configure;
+        request_on_free_handler_t on_free;
+} Request;
+
+Request *request_free(Request *req);
+void request_drop(Request *req);
+
+int link_queue_request(
+                Link *link,
+                RequestType type,
+                void *object,
+                bool consume_object,
+                unsigned *message_counter,
+                link_netlink_message_handler_t netlink_handler,
+                Request **ret);
+
+int manager_process_requests(sd_event_source *s, void *userdata);