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