]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-queue.c
Merge pull request #19672 from yuwata/strextend
[thirdparty/systemd.git] / src / network / networkd-queue.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "networkd-address.h"
4 #include "networkd-bridge-fdb.h"
5 #include "networkd-manager.h"
6 #include "networkd-neighbor.h"
7 #include "networkd-nexthop.h"
8 #include "networkd-route.h"
9 #include "networkd-routing-policy-rule.h"
10 #include "networkd-queue.h"
11
12 static void request_free_object(RequestType type, void *object) {
13 switch(type) {
14 case REQUEST_TYPE_ADDRESS:
15 address_free(object);
16 break;
17 case REQUEST_TYPE_BRIDGE_FDB:
18 bridge_fdb_free(object);
19 break;
20 case REQUEST_TYPE_NEIGHBOR:
21 neighbor_free(object);
22 break;
23 case REQUEST_TYPE_NEXTHOP:
24 nexthop_free(object);
25 break;
26 case REQUEST_TYPE_ROUTE:
27 route_free(object);
28 break;
29 case REQUEST_TYPE_ROUTING_POLICY_RULE:
30 routing_policy_rule_free(object);
31 break;
32 default:
33 assert_not_reached("invalid request type.");
34 }
35 }
36
37 Request *request_free(Request *req) {
38 if (!req)
39 return NULL;
40
41 if (req->on_free)
42 req->on_free(req);
43 if (req->consume_object)
44 request_free_object(req->type, req->object);
45 if (req->link && req->link->manager)
46 ordered_set_remove(req->link->manager->request_queue, req);
47 link_unref(req->link);
48
49 return mfree(req);
50 }
51
52 DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free);
53
54 void request_drop(Request *req) {
55 if (req->message_counter)
56 (*req->message_counter)--;
57
58 request_free(req);
59 }
60
61 int link_queue_request(
62 Link *link,
63 RequestType type,
64 void *object,
65 bool consume_object,
66 unsigned *message_counter,
67 link_netlink_message_handler_t netlink_handler,
68 Request **ret) {
69
70 _cleanup_(request_freep) Request *req = NULL;
71 int r;
72
73 assert(link);
74 assert(link->manager);
75 assert(type >= 0 && type < _REQUEST_TYPE_MAX);
76 assert(object);
77 assert(netlink_handler);
78
79 req = new(Request, 1);
80 if (!req) {
81 if (consume_object)
82 request_free_object(type, object);
83 return -ENOMEM;
84 }
85
86 *req = (Request) {
87 .link = link,
88 .type = type,
89 .object = object,
90 .consume_object = consume_object,
91 .message_counter = message_counter,
92 .netlink_handler = netlink_handler,
93 };
94
95 link_ref(link);
96
97 r = ordered_set_ensure_put(&link->manager->request_queue, NULL, req);
98 if (r < 0)
99 return r;
100
101 if (req->message_counter)
102 (*req->message_counter)++;
103
104 if (ret)
105 *ret = req;
106
107 TAKE_PTR(req);
108 return 0;
109 }
110
111 int manager_process_requests(sd_event_source *s, void *userdata) {
112 Manager *manager = userdata;
113 int r;
114
115 assert(manager);
116
117 for (;;) {
118 bool processed = false;
119 Request *req;
120
121 ORDERED_SET_FOREACH(req, manager->request_queue) {
122 switch(req->type) {
123 case REQUEST_TYPE_ADDRESS:
124 r = request_process_address(req);
125 break;
126 case REQUEST_TYPE_BRIDGE_FDB:
127 r = request_process_bridge_fdb(req);
128 break;
129 case REQUEST_TYPE_NEIGHBOR:
130 r = request_process_neighbor(req);
131 break;
132 case REQUEST_TYPE_NEXTHOP:
133 r = request_process_nexthop(req);
134 break;
135 case REQUEST_TYPE_ROUTE:
136 r = request_process_route(req);
137 break;
138 case REQUEST_TYPE_ROUTING_POLICY_RULE:
139 r = request_process_routing_policy_rule(req);
140 break;
141 default:
142 return -EINVAL;
143 }
144 if (r < 0)
145 link_enter_failed(req->link);
146 if (r > 0) {
147 ordered_set_remove(manager->request_queue, req);
148 request_free(req);
149 processed = true;
150 }
151 }
152
153 if (!processed)
154 break;
155 }
156
157 return 0;
158 }