1 /*
2 * Copyright (c) 2015-2017 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Jan Friesse (jfriesse@redhat.com)
7 *
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the Red Hat, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/types.h>
36
37 #include "qnet-config.h"
38 #include "qdevice-net-algorithm.h"
39 #include "qdevice-log.h"
40
41 #include "qdevice-net-algo-test.h"
42 #include "qdevice-net-algo-ffsplit.h"
43 #include "qdevice-net-algo-2nodelms.h"
44 #include "qdevice-net-algo-lms.h"
45
46 static struct qdevice_net_algorithm *qdevice_net_algorithm_array[QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE];
47
48 int
qdevice_net_algorithm_init(struct qdevice_net_instance * instance)49 qdevice_net_algorithm_init(struct qdevice_net_instance *instance)
50 {
51
52 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
53 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
54 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_init unhandled decision algorithm");
55 exit(1);
56 }
57
58 return (qdevice_net_algorithm_array[instance->decision_algorithm]->init(instance));
59 }
60
61 int
qdevice_net_algorithm_connected(struct qdevice_net_instance * instance,enum tlv_heuristics * heuristics,int * send_config_node_list,int * send_membership_node_list,int * send_quorum_node_list,enum tlv_vote * vote)62 qdevice_net_algorithm_connected(struct qdevice_net_instance *instance, enum tlv_heuristics *heuristics,
63 int *send_config_node_list, int *send_membership_node_list, int *send_quorum_node_list, enum tlv_vote *vote)
64 {
65
66 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
67 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
68 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_connected unhandled decision algorithm");
69 exit(1);
70 }
71
72 return (qdevice_net_algorithm_array[instance->decision_algorithm]->connected(instance,
73 heuristics, send_config_node_list, send_membership_node_list, send_quorum_node_list, vote));
74 }
75
76 int
qdevice_net_algorithm_config_node_list_changed(struct qdevice_net_instance * instance,const struct node_list * nlist,int config_version_set,uint64_t config_version,int * send_node_list,enum tlv_vote * vote)77 qdevice_net_algorithm_config_node_list_changed(struct qdevice_net_instance *instance,
78 const struct node_list *nlist, int config_version_set, uint64_t config_version,
79 int *send_node_list, enum tlv_vote *vote)
80 {
81
82 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
83 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
84 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_connected unhandled decision algorithm");
85 exit(1);
86 }
87
88 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
89 config_node_list_changed(instance, nlist, config_version_set, config_version,
90 send_node_list, vote));
91 }
92
93 int
qdevice_net_algorithm_votequorum_node_list_notify(struct qdevice_net_instance * instance,const struct tlv_ring_id * ring_id,uint32_t node_list_entries,uint32_t node_list[],int * pause_cast_vote_timer,enum tlv_vote * vote)94 qdevice_net_algorithm_votequorum_node_list_notify(struct qdevice_net_instance *instance,
95 const struct tlv_ring_id *ring_id, uint32_t node_list_entries, uint32_t node_list[],
96 int *pause_cast_vote_timer, enum tlv_vote *vote)
97 {
98
99 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
100 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
101 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_votequorum_node_list_notify "
102 "unhandled decision algorithm");
103 exit(1);
104 }
105
106 return (qdevice_net_algorithm_array[instance->decision_algorithm]->votequorum_node_list_notify(
107 instance, ring_id, node_list_entries, node_list, pause_cast_vote_timer, vote));
108 }
109
110 int
qdevice_net_algorithm_votequorum_node_list_heuristics_notify(struct qdevice_net_instance * instance,const struct tlv_ring_id * ring_id,uint32_t node_list_entries,uint32_t node_list[],int * send_node_list,enum tlv_vote * vote,enum tlv_heuristics * heuristics)111 qdevice_net_algorithm_votequorum_node_list_heuristics_notify(struct qdevice_net_instance *instance,
112 const struct tlv_ring_id *ring_id, uint32_t node_list_entries, uint32_t node_list[],
113 int *send_node_list, enum tlv_vote *vote, enum tlv_heuristics *heuristics)
114 {
115
116 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
117 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
118 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_votequorum_node_list_heuristics_notify "
119 "unhandled decision algorithm");
120 exit(1);
121 }
122
123 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
124 votequorum_node_list_heuristics_notify(
125 instance, ring_id, node_list_entries, node_list, send_node_list, vote, heuristics));
126 }
127
128 int
qdevice_net_algorithm_votequorum_quorum_notify(struct qdevice_net_instance * instance,uint32_t quorate,uint32_t node_list_entries,votequorum_node_t node_list[],int * send_node_list,enum tlv_vote * vote)129 qdevice_net_algorithm_votequorum_quorum_notify(struct qdevice_net_instance *instance,
130 uint32_t quorate, uint32_t node_list_entries, votequorum_node_t node_list[], int *send_node_list,
131 enum tlv_vote *vote)
132 {
133
134 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
135 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
136 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_votequorum_quorum_notify "
137 "unhandled decision algorithm");
138 exit(1);
139 }
140
141 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
142 votequorum_quorum_notify(instance, quorate, node_list_entries, node_list,
143 send_node_list, vote));
144 }
145
146 int
qdevice_net_algorithm_votequorum_expected_votes_notify(struct qdevice_net_instance * instance,uint32_t expected_votes,enum tlv_vote * vote)147 qdevice_net_algorithm_votequorum_expected_votes_notify(struct qdevice_net_instance *instance,
148 uint32_t expected_votes, enum tlv_vote *vote)
149 {
150
151 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
152 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
153 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_votequorum_expected_votes_notify "
154 "unhandled decision algorithm");
155 exit(1);
156 }
157
158 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
159 votequorum_expected_votes_notify(instance, expected_votes, vote));
160 }
161
162 int
qdevice_net_algorithm_config_node_list_reply_received(struct qdevice_net_instance * instance,uint32_t seq_number,int initial,const struct tlv_ring_id * ring_id,int ring_id_is_valid,enum tlv_vote * vote)163 qdevice_net_algorithm_config_node_list_reply_received(struct qdevice_net_instance *instance,
164 uint32_t seq_number, int initial, const struct tlv_ring_id *ring_id, int ring_id_is_valid,
165 enum tlv_vote *vote)
166 {
167
168 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
169 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
170 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_config_node_list_reply_received "
171 "unhandled decision algorithm");
172 exit(1);
173 }
174
175 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
176 config_node_list_reply_received(instance, seq_number, initial, ring_id,
177 ring_id_is_valid, vote));
178 }
179
180 int
qdevice_net_algorithm_membership_node_list_reply_received(struct qdevice_net_instance * instance,uint32_t seq_number,const struct tlv_ring_id * ring_id,int ring_id_is_valid,enum tlv_vote * vote)181 qdevice_net_algorithm_membership_node_list_reply_received(struct qdevice_net_instance *instance,
182 uint32_t seq_number, const struct tlv_ring_id *ring_id, int ring_id_is_valid, enum tlv_vote *vote)
183 {
184
185 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
186 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
187 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_membership_node_list_reply_received "
188 "unhandled decision algorithm");
189 exit(1);
190 }
191
192 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
193 membership_node_list_reply_received(instance, seq_number, ring_id, ring_id_is_valid,
194 vote));
195 }
196
197 int
qdevice_net_algorithm_quorum_node_list_reply_received(struct qdevice_net_instance * instance,uint32_t seq_number,const struct tlv_ring_id * ring_id,int ring_id_is_valid,enum tlv_vote * vote)198 qdevice_net_algorithm_quorum_node_list_reply_received(struct qdevice_net_instance *instance,
199 uint32_t seq_number, const struct tlv_ring_id *ring_id, int ring_id_is_valid,
200 enum tlv_vote *vote)
201 {
202
203 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
204 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
205 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_quorum_node_list_reply_received "
206 "unhandled decision algorithm");
207 exit(1);
208 }
209
210 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
211 quorum_node_list_reply_received(instance, seq_number, ring_id, ring_id_is_valid,
212 vote));
213 }
214
215 int
qdevice_net_algorithm_ask_for_vote_reply_received(struct qdevice_net_instance * instance,uint32_t seq_number,const struct tlv_ring_id * ring_id,int ring_id_is_valid,enum tlv_vote * vote)216 qdevice_net_algorithm_ask_for_vote_reply_received(struct qdevice_net_instance *instance,
217 uint32_t seq_number, const struct tlv_ring_id *ring_id, int ring_id_is_valid,
218 enum tlv_vote *vote)
219 {
220
221 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
222 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
223 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_ask_for_vote_reply_received "
224 "unhandled decision algorithm");
225 exit(1);
226 }
227
228 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
229 ask_for_vote_reply_received(instance, seq_number, ring_id, ring_id_is_valid, vote));
230 }
231
232 int
qdevice_net_algorithm_vote_info_received(struct qdevice_net_instance * instance,uint32_t seq_number,const struct tlv_ring_id * ring_id,int ring_id_is_valid,enum tlv_vote * vote)233 qdevice_net_algorithm_vote_info_received(struct qdevice_net_instance *instance,
234 uint32_t seq_number, const struct tlv_ring_id *ring_id, int ring_id_is_valid,
235 enum tlv_vote *vote)
236 {
237
238 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
239 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
240 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_vote_info_received "
241 "unhandled decision algorithm");
242 exit(1);
243 }
244
245 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
246 vote_info_received(instance, seq_number, ring_id, ring_id_is_valid, vote));
247 }
248
249 int
qdevice_net_algorithm_echo_reply_received(struct qdevice_net_instance * instance,uint32_t seq_number,int is_expected_seq_number)250 qdevice_net_algorithm_echo_reply_received(struct qdevice_net_instance *instance,
251 uint32_t seq_number, int is_expected_seq_number)
252 {
253
254 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
255 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
256 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_echo_reply_received "
257 "unhandled decision algorithm");
258 exit(1);
259 }
260
261 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
262 echo_reply_received(instance, seq_number, is_expected_seq_number));
263 }
264
265 int
qdevice_net_algorithm_echo_reply_not_received(struct qdevice_net_instance * instance)266 qdevice_net_algorithm_echo_reply_not_received(struct qdevice_net_instance *instance)
267 {
268
269 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
270 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
271 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_echo_reply_not_received "
272 "unhandled decision algorithm");
273 exit(1);
274 }
275
276 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
277 echo_reply_not_received(instance));
278 }
279
280 int
qdevice_net_algorithm_heuristics_change(struct qdevice_net_instance * instance,enum tlv_heuristics * heuristics,int * send_msg,enum tlv_vote * vote)281 qdevice_net_algorithm_heuristics_change(struct qdevice_net_instance *instance,
282 enum tlv_heuristics *heuristics, int *send_msg, enum tlv_vote *vote)
283 {
284
285 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
286 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
287 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_heuristics_change "
288 "unhandled decision algorithm");
289 exit(1);
290 }
291
292 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
293 heuristics_change(instance, heuristics, send_msg, vote));
294 }
295
296 int
qdevice_net_algorithm_heuristics_change_reply_received(struct qdevice_net_instance * instance,uint32_t seq_number,const struct tlv_ring_id * ring_id,int ring_id_is_valid,enum tlv_heuristics heuristics,enum tlv_vote * vote)297 qdevice_net_algorithm_heuristics_change_reply_received(struct qdevice_net_instance *instance,
298 uint32_t seq_number, const struct tlv_ring_id *ring_id, int ring_id_is_valid,
299 enum tlv_heuristics heuristics, enum tlv_vote *vote)
300 {
301
302 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
303 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
304 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_heuristics_change_reply_received "
305 "unhandled decision algorithm");
306 exit(1);
307 }
308
309 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
310 heuristics_change_reply_received(instance, seq_number, ring_id, ring_id_is_valid,
311 heuristics, vote));
312 }
313
314 int
qdevice_net_algorithm_disconnected(struct qdevice_net_instance * instance,enum qdevice_net_disconnect_reason disconnect_reason,int * try_reconnect,enum tlv_vote * vote)315 qdevice_net_algorithm_disconnected(struct qdevice_net_instance *instance,
316 enum qdevice_net_disconnect_reason disconnect_reason, int *try_reconnect, enum tlv_vote *vote)
317 {
318
319 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
320 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
321 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_disconnected "
322 "unhandled decision algorithm");
323 exit(1);
324 }
325
326 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
327 disconnected(instance, disconnect_reason, try_reconnect, vote));
328 }
329
330 void
qdevice_net_algorithm_destroy(struct qdevice_net_instance * instance)331 qdevice_net_algorithm_destroy(struct qdevice_net_instance *instance)
332 {
333
334 if (instance->decision_algorithm >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE ||
335 qdevice_net_algorithm_array[instance->decision_algorithm] == NULL) {
336 qdevice_log(LOG_CRIT, "qdevice_net_algorithm_destroy "
337 "unhandled decision algorithm");
338 exit(1);
339 }
340
341 return (qdevice_net_algorithm_array[instance->decision_algorithm]->
342 destroy(instance));
343 }
344
345 int
qdevice_net_algorithm_register(enum tlv_decision_algorithm_type algorithm_number,struct qdevice_net_algorithm * algorithm)346 qdevice_net_algorithm_register(enum tlv_decision_algorithm_type algorithm_number,
347 struct qdevice_net_algorithm *algorithm)
348 {
349
350 if (algorithm_number >= QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE) {
351 return (-1);
352 }
353
354 if (qdevice_net_algorithm_array[algorithm_number] != NULL) {
355 return (-1);
356 }
357
358 qdevice_net_algorithm_array[algorithm_number] = algorithm;
359
360 return (0);
361 }
362
363 int
qdevice_net_algorithm_register_all(void)364 qdevice_net_algorithm_register_all(void)
365 {
366
367 if (qdevice_net_algo_test_register() != 0) {
368 qdevice_log(LOG_CRIT, "Failed to register decision algorithm 'test' ");
369 return (-1);
370 }
371
372 if (qdevice_net_algo_ffsplit_register() != 0) {
373 qdevice_log(LOG_CRIT, "Failed to register decision algorithm 'ffsplit' ");
374 return (-1);
375 }
376
377 if (qdevice_net_algo_2nodelms_register() != 0) {
378 qdevice_log(LOG_CRIT, "Failed to register decision algorithm '2nodelms' ");
379 return (-1);
380 }
381
382 if (qdevice_net_algo_lms_register() != 0) {
383 qdevice_log(LOG_CRIT, "Failed to register decision algorithm 'lms' ");
384 return (-1);
385 }
386
387 return (0);
388 }
389