]> git.proxmox.com Git - mirror_frr.git/blob - pathd/path_pcep_controller.c
Merge pull request #10447 from ton31337/fix/json_with_whitespaces
[mirror_frr.git] / pathd / path_pcep_controller.c
1 /*
2 * Copyright (C) 2020 NetDEF, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <zebra.h>
20
21 #include "log.h"
22 #include "command.h"
23 #include "libfrr.h"
24 #include "printfrr.h"
25 #include "lib/version.h"
26 #include "northbound.h"
27 #include "frr_pthread.h"
28 #include "jhash.h"
29 #include "network.h"
30
31 #include "pathd/pathd.h"
32 #include "pathd/path_errors.h"
33 #include "pathd/path_pcep.h"
34 #include "pathd/path_pcep_controller.h"
35 #include "pathd/path_pcep_pcc.h"
36 #include "pathd/path_pcep_config.h"
37 #include "pathd/path_pcep_debug.h"
38
39 #define MAX_RECONNECT_DELAY 120
40
41 /* Event handling data structures */
42 enum pcep_ctrl_event_type {
43 EV_UPDATE_PCC_OPTS = 1,
44 EV_UPDATE_PCE_OPTS,
45 EV_REMOVE_PCC,
46 EV_PATHD_EVENT,
47 EV_SYNC_PATH,
48 EV_SYNC_DONE,
49 EV_PCEPLIB_EVENT,
50 EV_RESET_PCC_SESSION,
51 EV_SEND_REPORT,
52 EV_SEND_ERROR,
53 EV_PATH_REFINED
54 };
55
56 struct pcep_ctrl_event_data {
57 struct ctrl_state *ctrl_state;
58 enum pcep_ctrl_event_type type;
59 uint32_t sub_type;
60 int pcc_id;
61 void *payload;
62 };
63
64 struct pcep_main_event_data {
65 pcep_main_event_handler_t handler;
66 int pcc_id;
67 enum pcep_main_event_type type;
68 void *payload;
69 };
70
71 struct pcep_refine_path_event_data {
72 struct ctrl_state *ctrl_state;
73 int pcc_id;
74 pcep_refine_callback_t continue_lsp_update_handler;
75 struct path *path;
76 void *payload;
77 };
78
79 /* Synchronous call arguments */
80
81 struct get_counters_args {
82 struct ctrl_state *ctrl_state;
83 int pcc_id;
84 struct counters_group *counters;
85 };
86
87 struct get_pcep_session_args {
88 struct ctrl_state *ctrl_state;
89 int pcc_id;
90 pcep_session *pcep_session;
91 };
92
93 /* Internal Functions Called From Main Thread */
94 static int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res);
95 static void pcep_refine_path_event_cb(struct thread *thread);
96
97 /* Internal Functions Called From Controller Thread */
98 static void pcep_thread_finish_event_handler(struct thread *thread);
99
100 /* Controller Thread Timer Handler */
101 static int schedule_thread_timer(struct ctrl_state *ctrl_state, int pcc_id,
102 enum pcep_ctrl_timer_type timer_type,
103 enum pcep_ctrl_timeout_type timeout_type,
104 uint32_t delay, void *payload,
105 struct thread **thread);
106 static int schedule_thread_timer_with_cb(
107 struct ctrl_state *ctrl_state, int pcc_id,
108 enum pcep_ctrl_timer_type timer_type,
109 enum pcep_ctrl_timeout_type timeout_type, uint32_t delay, void *payload,
110 struct thread **thread, pcep_ctrl_thread_callback timer_cb);
111 static void pcep_thread_timer_handler(struct thread *thread);
112
113 /* Controller Thread Socket read/write Handler */
114 static int schedule_thread_socket(struct ctrl_state *ctrl_state, int pcc_id,
115 enum pcep_ctrl_socket_type type, bool is_read,
116 void *payload, int fd, struct thread **thread,
117 pcep_ctrl_thread_callback cb);
118
119 /* Controller Thread Event Handler */
120 static int send_to_thread(struct ctrl_state *ctrl_state, int pcc_id,
121 enum pcep_ctrl_event_type type, uint32_t sub_type,
122 void *payload);
123 static int send_to_thread_with_cb(struct ctrl_state *ctrl_state, int pcc_id,
124 enum pcep_ctrl_event_type type,
125 uint32_t sub_type, void *payload,
126 pcep_ctrl_thread_callback event_cb);
127 static void pcep_thread_event_handler(struct thread *thread);
128 static int pcep_thread_event_update_pcc_options(struct ctrl_state *ctrl_state,
129 struct pcc_opts *opts);
130 static int pcep_thread_event_update_pce_options(struct ctrl_state *ctrl_state,
131 int pcc_id,
132 struct pce_opts *opts);
133 static int pcep_thread_event_remove_pcc_by_id(struct ctrl_state *ctrl_state,
134 int pcc_id);
135 static int pcep_thread_event_remove_pcc_all(struct ctrl_state *ctrl_state);
136 static int pcep_thread_event_remove_pcc(struct ctrl_state *ctrl_state,
137 struct pce_opts *pce_opts);
138 static int pcep_thread_event_sync_path(struct ctrl_state *ctrl_state,
139 int pcc_id, struct path *path);
140 static int pcep_thread_event_sync_done(struct ctrl_state *ctrl_state,
141 int pcc_id);
142 static int pcep_thread_event_pathd_event(struct ctrl_state *ctrl_state,
143 enum pcep_pathd_event_type type,
144 struct path *path);
145 static void
146 pcep_thread_path_refined_event(struct ctrl_state *ctrl_state,
147 struct pcep_refine_path_event_data *data);
148
149 /* Main Thread Event Handler */
150 static int send_to_main(struct ctrl_state *ctrl_state, int pcc_id,
151 enum pcep_main_event_type type, void *payload);
152 static void pcep_main_event_handler(struct thread *thread);
153
154 /* Helper functions */
155 static void set_ctrl_state(struct frr_pthread *fpt,
156 struct ctrl_state *ctrl_state);
157 static struct ctrl_state *get_ctrl_state(struct frr_pthread *fpt);
158 int get_next_id(struct ctrl_state *ctrl_state);
159 int set_pcc_state(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state);
160 void remove_pcc_state(struct ctrl_state *ctrl_state,
161 struct pcc_state *pcc_state);
162 static uint32_t backoff_delay(uint32_t max, uint32_t base, uint32_t attempt);
163 static const char *timer_type_name(enum pcep_ctrl_timer_type type);
164 static const char *timeout_type_name(enum pcep_ctrl_timeout_type type);
165
166
167 /* ------------ API Functions Called from Main Thread ------------ */
168
169 int pcep_ctrl_initialize(struct thread_master *main_thread,
170 struct frr_pthread **fpt,
171 pcep_main_event_handler_t event_handler)
172 {
173 assert(fpt != NULL);
174
175 int ret = 0;
176 struct ctrl_state *ctrl_state;
177 struct frr_pthread_attr attr = {
178 .start = frr_pthread_attr_default.start,
179 .stop = pcep_ctrl_halt_cb,
180 };
181
182 PCEP_DEBUG("Initializing pcep module controller");
183
184 /* Create and start the FRR pthread */
185 *fpt = frr_pthread_new(&attr, "PCEP thread", "pcep_controller");
186 if (*fpt == NULL) {
187 flog_err(EC_PATH_SYSTEM_CALL,
188 "failed to initialize PCEP thread");
189 return 1;
190 }
191 ret = frr_pthread_run(*fpt, NULL);
192 if (ret < 0) {
193 flog_err(EC_PATH_SYSTEM_CALL, "failed to create PCEP thread");
194 return ret;
195 }
196 frr_pthread_wait_running(*fpt);
197
198 /* Initialize the thread state */
199 ctrl_state = XCALLOC(MTYPE_PCEP, sizeof(*ctrl_state));
200 ctrl_state->main = main_thread;
201 ctrl_state->self = (*fpt)->master;
202 ctrl_state->main_event_handler = event_handler;
203 ctrl_state->pcc_count = 0;
204 ctrl_state->pcc_last_id = 0;
205 ctrl_state->pcc_opts =
206 XCALLOC(MTYPE_PCEP, sizeof(*ctrl_state->pcc_opts));
207 /* Default to no PCC address defined */
208 ctrl_state->pcc_opts->addr.ipa_type = IPADDR_NONE;
209 ctrl_state->pcc_opts->port = PCEP_DEFAULT_PORT;
210
211 /* Keep the state reference for events */
212 set_ctrl_state(*fpt, ctrl_state);
213
214 return ret;
215 }
216
217 int pcep_ctrl_finalize(struct frr_pthread **fpt)
218 {
219 assert(fpt != NULL);
220
221 int ret = 0;
222
223 PCEP_DEBUG("Finalizing pcep module controller");
224
225 if (*fpt != NULL) {
226 frr_pthread_stop(*fpt, NULL);
227 *fpt = NULL;
228 }
229
230 return ret;
231 }
232
233 int pcep_ctrl_update_pcc_options(struct frr_pthread *fpt, struct pcc_opts *opts)
234 {
235 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
236 return send_to_thread(ctrl_state, 0, EV_UPDATE_PCC_OPTS, 0, opts);
237 }
238
239 int pcep_ctrl_update_pce_options(struct frr_pthread *fpt, struct pce_opts *opts)
240 {
241 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
242 return send_to_thread(ctrl_state, 0, EV_UPDATE_PCE_OPTS, 0, opts);
243 }
244
245 int pcep_ctrl_remove_pcc(struct frr_pthread *fpt, struct pce_opts *pce_opts)
246 {
247 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
248 return send_to_thread(ctrl_state, 0, EV_REMOVE_PCC, 0, pce_opts);
249 }
250
251 int pcep_ctrl_reset_pcc_session(struct frr_pthread *fpt, char *pce_name)
252 {
253 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
254 return send_to_thread(ctrl_state, 0, EV_RESET_PCC_SESSION, 0, pce_name);
255 }
256
257 int pcep_ctrl_pathd_event(struct frr_pthread *fpt,
258 enum pcep_pathd_event_type type, struct path *path)
259 {
260 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
261 return send_to_thread(ctrl_state, 0, EV_PATHD_EVENT, type, path);
262 }
263
264 int pcep_ctrl_sync_path(struct frr_pthread *fpt, int pcc_id, struct path *path)
265 {
266 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
267 return send_to_thread(ctrl_state, pcc_id, EV_SYNC_PATH, 0, path);
268 }
269
270 int pcep_ctrl_sync_done(struct frr_pthread *fpt, int pcc_id)
271 {
272 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
273 return send_to_thread(ctrl_state, pcc_id, EV_SYNC_DONE, 0, NULL);
274 }
275
276 struct counters_group *pcep_ctrl_get_counters(struct frr_pthread *fpt,
277 int pcc_id)
278 {
279 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
280 struct counters_group *counters = NULL;
281 struct pcc_state *pcc_state;
282 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
283 if (pcc_state) {
284 counters = pcep_lib_copy_counters(pcc_state->sess);
285 }
286 return counters;
287 }
288
289 pcep_session *pcep_ctrl_get_pcep_session(struct frr_pthread *fpt, int pcc_id)
290 {
291 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
292 struct pcc_state *pcc_state;
293 pcep_session *session = NULL;
294
295 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
296 if (pcc_state) {
297 session = pcep_lib_copy_pcep_session(pcc_state->sess);
298 }
299 return session;
300 }
301
302 struct pcep_pcc_info *pcep_ctrl_get_pcc_info(struct frr_pthread *fpt,
303 const char *pce_name)
304 {
305 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
306 struct pcep_pcc_info *pcc_info = XCALLOC(MTYPE_PCEP, sizeof(*pcc_info));
307 if( pcc_info && ctrl_state){
308 strlcpy(pcc_info->pce_name, pce_name, sizeof(pcc_info->pce_name));
309 pcep_pcc_copy_pcc_info(ctrl_state->pcc, pcc_info);
310 }
311
312 return pcc_info;
313 }
314
315 int pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id,
316 struct path *path, bool is_stable)
317 {
318 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
319 return send_to_thread(ctrl_state, pcc_id, EV_SEND_REPORT, is_stable,
320 path);
321 }
322
323
324 int pcep_ctrl_send_error(struct frr_pthread *fpt, int pcc_id,
325 struct pcep_error *error)
326 {
327 struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
328 return send_to_thread(ctrl_state, pcc_id, EV_SEND_ERROR, 0, error);
329 }
330
331
332 /* ------------ Internal Functions Called from Main Thread ------------ */
333
334 int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res)
335 {
336 thread_add_event(fpt->master, pcep_thread_finish_event_handler,
337 (void *)fpt, 0, NULL);
338 pthread_join(fpt->thread, res);
339
340 return 0;
341 }
342
343 void pcep_refine_path_event_cb(struct thread *thread)
344 {
345 struct pcep_refine_path_event_data *data = THREAD_ARG(thread);
346 assert(data != NULL);
347 struct ctrl_state *ctrl_state = data->ctrl_state;
348 struct path *path = data->path;
349 assert(path != NULL);
350 int pcc_id = data->pcc_id;
351
352
353 path_pcep_refine_path(path);
354 send_to_thread(ctrl_state, pcc_id, EV_PATH_REFINED, 0, data);
355 }
356
357
358 /* ------------ API Functions Called From Controller Thread ------------ */
359
360 void pcep_thread_start_sync(struct ctrl_state *ctrl_state, int pcc_id)
361 {
362 send_to_main(ctrl_state, pcc_id, PCEP_MAIN_EVENT_START_SYNC, NULL);
363 }
364
365 void pcep_thread_update_path(struct ctrl_state *ctrl_state, int pcc_id,
366 struct path *path)
367 {
368 send_to_main(ctrl_state, pcc_id, PCEP_MAIN_EVENT_UPDATE_CANDIDATE,
369 path);
370 }
371
372 void pcep_thread_initiate_path(struct ctrl_state *ctrl_state, int pcc_id,
373 struct path *path)
374 {
375 send_to_main(ctrl_state, pcc_id, PCEP_MAIN_EVENT_INITIATE_CANDIDATE,
376 path);
377 }
378
379 void pcep_thread_remove_candidate_path_segments(struct ctrl_state *ctrl_state,
380 struct pcc_state *pcc_state)
381 {
382 if (!pcc_state)
383 return;
384 /* Will be deleted when the event is handled */
385 char *originator = XSTRDUP(MTYPE_PCEP, pcc_state->originator);
386 PCEP_DEBUG("schedule candidate path segments removal for originator %s",
387 originator);
388 send_to_main(ctrl_state, pcep_pcc_get_pcc_id(pcc_state),
389 PCEP_MAIN_EVENT_REMOVE_CANDIDATE_LSP, originator);
390 }
391
392 void pcep_thread_schedule_sync_best_pce(struct ctrl_state *ctrl_state,
393 int pcc_id, int delay,
394 struct thread **thread)
395 {
396
397 schedule_thread_timer(ctrl_state, pcc_id, TM_CALCULATE_BEST_PCE,
398 TO_UNDEFINED, delay, NULL, thread);
399 }
400
401 void pcep_thread_cancel_timer(struct thread **thread)
402 {
403 if (thread == NULL || *thread == NULL) {
404 return;
405 }
406
407 struct pcep_ctrl_timer_data *data = THREAD_ARG(*thread);
408 PCEP_DEBUG("Timer %s / %s canceled", timer_type_name(data->timer_type),
409 timeout_type_name(data->timeout_type));
410 if (data != NULL) {
411 XFREE(MTYPE_PCEP, data);
412 }
413
414 if ((*thread)->master->owner == pthread_self()) {
415 thread_cancel(thread);
416 } else {
417 thread_cancel_async((*thread)->master, thread, NULL);
418 }
419 }
420
421 void pcep_thread_schedule_reconnect(struct ctrl_state *ctrl_state, int pcc_id,
422 int retry_count, struct thread **thread)
423 {
424 uint32_t delay = backoff_delay(MAX_RECONNECT_DELAY, 1, retry_count);
425 PCEP_DEBUG("Schedule RECONNECT_PCC for %us (retry %u)", delay,
426 retry_count);
427 schedule_thread_timer(ctrl_state, pcc_id, TM_RECONNECT_PCC,
428 TO_UNDEFINED, delay, NULL, thread);
429 }
430
431 void pcep_thread_schedule_timeout(struct ctrl_state *ctrl_state, int pcc_id,
432 enum pcep_ctrl_timeout_type timeout_type,
433 uint32_t delay, void *param,
434 struct thread **thread)
435 {
436 assert(timeout_type > TO_UNDEFINED);
437 assert(timeout_type < TO_MAX);
438 PCEP_DEBUG("Schedule timeout %s for %us",
439 timeout_type_name(timeout_type), delay);
440 schedule_thread_timer(ctrl_state, pcc_id, TM_TIMEOUT, timeout_type,
441 delay, param, thread);
442 }
443
444 void pcep_thread_schedule_pceplib_timer(struct ctrl_state *ctrl_state,
445 int delay, void *payload,
446 struct thread **thread,
447 pcep_ctrl_thread_callback timer_cb)
448 {
449 PCEP_DEBUG("Schedule PCEPLIB_TIMER for %us", delay);
450 schedule_thread_timer_with_cb(ctrl_state, 0, TM_PCEPLIB_TIMER,
451 TO_UNDEFINED, delay, payload, thread,
452 timer_cb);
453 }
454
455 void pcep_thread_schedule_session_timeout(struct ctrl_state *ctrl_state,
456 int pcc_id, int delay,
457 struct thread **thread)
458 {
459 PCEP_DEBUG("Schedule session_timeout interval for %us", delay);
460 schedule_thread_timer(ctrl_state, pcc_id, TM_SESSION_TIMEOUT_PCC,
461 TO_UNDEFINED, delay, NULL, thread);
462 }
463
464 int pcep_thread_pcc_count(struct ctrl_state *ctrl_state)
465 {
466 if (ctrl_state == NULL) {
467 return 0;
468 }
469
470 return ctrl_state->pcc_count;
471 }
472
473 int pcep_thread_refine_path(struct ctrl_state *ctrl_state, int pcc_id,
474 pcep_refine_callback_t cb, struct path *path,
475 void *payload)
476 {
477 struct pcep_refine_path_event_data *data;
478
479 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
480 data->ctrl_state = ctrl_state;
481 data->path = path;
482 data->pcc_id = pcc_id;
483 data->continue_lsp_update_handler = cb;
484 data->payload = payload;
485
486 thread_add_event(ctrl_state->main, pcep_refine_path_event_cb,
487 (void *)data, 0, NULL);
488 return 0;
489 }
490
491 void pcep_thread_path_refined_event(struct ctrl_state *ctrl_state,
492 struct pcep_refine_path_event_data *data)
493 {
494 assert(data != NULL);
495 int pcc_id = data->pcc_id;
496 pcep_refine_callback_t continue_lsp_update_handler = data->continue_lsp_update_handler;
497 assert(continue_lsp_update_handler != NULL);
498 struct path *path = data->path;
499 void *payload = data->payload;
500 struct pcc_state *pcc_state = NULL;
501 XFREE(MTYPE_PCEP, data);
502
503 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
504 continue_lsp_update_handler(ctrl_state, pcc_state, path, payload);
505 }
506
507
508 /* ------------ Internal Functions Called From Controller Thread ------------ */
509
510 void pcep_thread_finish_event_handler(struct thread *thread)
511 {
512 int i;
513 struct frr_pthread *fpt = THREAD_ARG(thread);
514 struct ctrl_state *ctrl_state = fpt->data;
515
516 assert(ctrl_state != NULL);
517
518 for (i = 0; i < MAX_PCC; i++) {
519 if (ctrl_state->pcc[i]) {
520 pcep_pcc_finalize(ctrl_state, ctrl_state->pcc[i]);
521 ctrl_state->pcc[i] = NULL;
522 }
523 }
524
525 XFREE(MTYPE_PCEP, ctrl_state->pcc_opts);
526 XFREE(MTYPE_PCEP, ctrl_state);
527 fpt->data = NULL;
528
529 atomic_store_explicit(&fpt->running, false, memory_order_relaxed);
530 }
531
532 /* ------------ Controller Thread Timer Handler ------------ */
533
534 int schedule_thread_timer_with_cb(struct ctrl_state *ctrl_state, int pcc_id,
535 enum pcep_ctrl_timer_type timer_type,
536 enum pcep_ctrl_timeout_type timeout_type,
537 uint32_t delay, void *payload,
538 struct thread **thread,
539 pcep_ctrl_thread_callback timer_cb)
540 {
541 assert(thread != NULL);
542
543 struct pcep_ctrl_timer_data *data;
544
545 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
546 data->ctrl_state = ctrl_state;
547 data->timer_type = timer_type;
548 data->timeout_type = timeout_type;
549 data->pcc_id = pcc_id;
550 data->payload = payload;
551
552 thread_add_timer(ctrl_state->self, timer_cb, (void *)data, delay,
553 thread);
554
555 return 0;
556 }
557
558 int schedule_thread_timer(struct ctrl_state *ctrl_state, int pcc_id,
559 enum pcep_ctrl_timer_type timer_type,
560 enum pcep_ctrl_timeout_type timeout_type,
561 uint32_t delay, void *payload, struct thread **thread)
562 {
563 return schedule_thread_timer_with_cb(ctrl_state, pcc_id, timer_type,
564 timeout_type, delay, payload,
565 thread, pcep_thread_timer_handler);
566 }
567
568 void pcep_thread_timer_handler(struct thread *thread)
569 {
570 /* data unpacking */
571 struct pcep_ctrl_timer_data *data = THREAD_ARG(thread);
572 assert(data != NULL);
573 struct ctrl_state *ctrl_state = data->ctrl_state;
574 assert(ctrl_state != NULL);
575 enum pcep_ctrl_timer_type timer_type = data->timer_type;
576 enum pcep_ctrl_timeout_type timeout_type = data->timeout_type;
577 int pcc_id = data->pcc_id;
578 void *param = data->payload;
579 XFREE(MTYPE_PCEP, data);
580
581 struct pcc_state *pcc_state = NULL;
582
583 switch (timer_type) {
584 case TM_RECONNECT_PCC:
585 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
586 if (!pcc_state)
587 return;
588 pcep_pcc_reconnect(ctrl_state, pcc_state);
589 break;
590 case TM_TIMEOUT:
591 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
592 if (!pcc_state)
593 return;
594 pcep_pcc_timeout_handler(ctrl_state, pcc_state, timeout_type,
595 param);
596 break;
597 case TM_CALCULATE_BEST_PCE:
598 /* Previous best disconnect so new best should be synced */
599 pcep_pcc_timer_update_best_pce(ctrl_state, pcc_id);
600 break;
601 case TM_SESSION_TIMEOUT_PCC:
602 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
603 pcep_thread_remove_candidate_path_segments(ctrl_state,
604 pcc_state);
605 break;
606 default:
607 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
608 "Unknown controller timer triggered: %u", timer_type);
609 break;
610 }
611 }
612
613 void pcep_thread_pcep_event(struct thread *thread)
614 {
615 struct pcep_ctrl_event_data *data = THREAD_ARG(thread);
616 assert(data != NULL);
617 struct ctrl_state *ctrl_state = data->ctrl_state;
618 pcep_event *event = data->payload;
619 XFREE(MTYPE_PCEP, data);
620 int i;
621
622 for (i = 0; i < MAX_PCC; i++) {
623 if (ctrl_state->pcc[i]) {
624 struct pcc_state *pcc_state = ctrl_state->pcc[i];
625 if (pcc_state->sess != event->session)
626 continue;
627 pcep_pcc_pcep_event_handler(ctrl_state, pcc_state,
628 event);
629 break;
630 }
631 }
632 destroy_pcep_event(event);
633 }
634
635 /* ------------ Controller Thread Socket Functions ------------ */
636
637 int schedule_thread_socket(struct ctrl_state *ctrl_state, int pcc_id,
638 enum pcep_ctrl_socket_type type, bool is_read,
639 void *payload, int fd, struct thread **thread,
640 pcep_ctrl_thread_callback socket_cb)
641 {
642 assert(thread != NULL);
643
644 struct pcep_ctrl_socket_data *data;
645
646 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
647 data->ctrl_state = ctrl_state;
648 data->type = type;
649 data->is_read = is_read;
650 data->fd = fd;
651 data->pcc_id = pcc_id;
652 data->payload = payload;
653
654 if (is_read) {
655 thread_add_read(ctrl_state->self, socket_cb, (void *)data, fd,
656 thread);
657 } else {
658 thread_add_write(ctrl_state->self, socket_cb, (void *)data, fd,
659 thread);
660 }
661
662 return 0;
663 }
664
665 int pcep_thread_socket_write(void *fpt, void **thread, int fd, void *payload,
666 pcep_ctrl_thread_callback socket_cb)
667 {
668 struct ctrl_state *ctrl_state = ((struct frr_pthread *)fpt)->data;
669
670 return schedule_thread_socket(ctrl_state, 0, SOCK_PCEPLIB, false,
671 payload, fd, (struct thread **)thread,
672 socket_cb);
673 }
674
675 int pcep_thread_socket_read(void *fpt, void **thread, int fd, void *payload,
676 pcep_ctrl_thread_callback socket_cb)
677 {
678 struct ctrl_state *ctrl_state = ((struct frr_pthread *)fpt)->data;
679
680 return schedule_thread_socket(ctrl_state, 0, SOCK_PCEPLIB, true,
681 payload, fd, (struct thread **)thread,
682 socket_cb);
683 }
684
685 int pcep_thread_send_ctrl_event(void *fpt, void *payload,
686 pcep_ctrl_thread_callback cb)
687 {
688 struct ctrl_state *ctrl_state = ((struct frr_pthread *)fpt)->data;
689
690 return send_to_thread_with_cb(ctrl_state, 0, EV_PCEPLIB_EVENT, 0,
691 payload, cb);
692 }
693
694 /* ------------ Controller Thread Event Handler ------------ */
695
696 int send_to_thread(struct ctrl_state *ctrl_state, int pcc_id,
697 enum pcep_ctrl_event_type type, uint32_t sub_type,
698 void *payload)
699 {
700 return send_to_thread_with_cb(ctrl_state, pcc_id, type, sub_type,
701 payload, pcep_thread_event_handler);
702 }
703
704 int send_to_thread_with_cb(struct ctrl_state *ctrl_state, int pcc_id,
705 enum pcep_ctrl_event_type type, uint32_t sub_type,
706 void *payload, pcep_ctrl_thread_callback event_cb)
707 {
708 struct pcep_ctrl_event_data *data;
709
710 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
711 data->ctrl_state = ctrl_state;
712 data->type = type;
713 data->sub_type = sub_type;
714 data->pcc_id = pcc_id;
715 data->payload = payload;
716
717 thread_add_event(ctrl_state->self, event_cb, (void *)data, 0, NULL);
718
719 return 0;
720 }
721
722 void pcep_thread_event_handler(struct thread *thread)
723 {
724 /* data unpacking */
725 struct pcep_ctrl_event_data *data = THREAD_ARG(thread);
726 assert(data != NULL);
727 struct ctrl_state *ctrl_state = data->ctrl_state;
728 assert(ctrl_state != NULL);
729 enum pcep_ctrl_event_type type = data->type;
730 uint32_t sub_type = data->sub_type;
731 int pcc_id = data->pcc_id;
732 void *payload = data->payload;
733 XFREE(MTYPE_PCEP, data);
734
735 /* Possible sub-type values */
736 enum pcep_pathd_event_type path_event_type = PCEP_PATH_UNDEFINED;
737
738 /* Possible payload values, maybe an union would be better... */
739 struct path *path = NULL;
740 struct pcc_opts *pcc_opts = NULL;
741 struct pce_opts *pce_opts = NULL;
742 struct pcc_state *pcc_state = NULL;
743 struct pcep_refine_path_event_data *refine_data = NULL;
744
745 struct path *path_copy = NULL;
746 struct pcep_error *error = NULL;
747
748 switch (type) {
749 case EV_UPDATE_PCC_OPTS:
750 assert(payload != NULL);
751 pcc_opts = (struct pcc_opts *)payload;
752 pcep_thread_event_update_pcc_options(ctrl_state, pcc_opts);
753 break;
754 case EV_UPDATE_PCE_OPTS:
755 assert(payload != NULL);
756 pce_opts = (struct pce_opts *)payload;
757 pcep_thread_event_update_pce_options(ctrl_state, pcc_id,
758 pce_opts);
759 break;
760 case EV_REMOVE_PCC:
761 pce_opts = (struct pce_opts *)payload;
762 if (pcep_thread_event_remove_pcc(ctrl_state, pce_opts) == 0)
763 pcep_pcc_multi_pce_remove_pcc(ctrl_state,
764 ctrl_state->pcc);
765 break;
766 case EV_PATHD_EVENT:
767 assert(payload != NULL);
768 path_event_type = (enum pcep_pathd_event_type)sub_type;
769 path = (struct path *)payload;
770 pcep_thread_event_pathd_event(ctrl_state, path_event_type,
771 path);
772 break;
773 case EV_SYNC_PATH:
774 assert(payload != NULL);
775 path = (struct path *)payload;
776 pcep_pcc_multi_pce_sync_path(ctrl_state, pcc_id,
777 ctrl_state->pcc);
778 pcep_thread_event_sync_path(ctrl_state, pcc_id, path);
779 break;
780 case EV_SYNC_DONE:
781 pcep_thread_event_sync_done(ctrl_state, pcc_id);
782 break;
783 case EV_RESET_PCC_SESSION:
784 pcc_state = pcep_pcc_get_pcc_by_name(ctrl_state->pcc,
785 (const char *)payload);
786 if (pcc_state) {
787 pcep_pcc_disable(ctrl_state, pcc_state);
788 pcep_pcc_enable(ctrl_state, pcc_state);
789 } else {
790 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
791 "Cannot reset state for PCE: %s",
792 (const char *)payload);
793 }
794 break;
795 case EV_SEND_REPORT:
796 assert(payload != NULL);
797 path = (struct path *)payload;
798 if (pcc_id == 0) {
799 for (int i = 0; i < MAX_PCC; i++) {
800 if (ctrl_state->pcc[i]) {
801 path_copy = pcep_copy_path(path);
802 pcep_pcc_send_report(
803 ctrl_state, ctrl_state->pcc[i],
804 path_copy, (bool)sub_type);
805 }
806 }
807 } else {
808 pcc_state =
809 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
810 pcep_pcc_send_report(ctrl_state, pcc_state, path,
811 (bool)sub_type);
812 }
813 break;
814 case EV_PATH_REFINED:
815 assert(payload != NULL);
816 refine_data = (struct pcep_refine_path_event_data *)payload;
817 pcep_thread_path_refined_event(ctrl_state, refine_data);
818 break;
819 case EV_SEND_ERROR:
820 assert(payload != NULL);
821 error = (struct pcep_error *)payload;
822 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
823 pcep_pcc_send_error(ctrl_state, pcc_state, error,
824 (bool)sub_type);
825 break;
826 default:
827 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
828 "Unexpected event received in controller thread: %u",
829 type);
830 break;
831 }
832 }
833
834 int pcep_thread_event_update_pcc_options(struct ctrl_state *ctrl_state,
835 struct pcc_opts *opts)
836 {
837 assert(opts != NULL);
838 if (ctrl_state->pcc_opts != NULL) {
839 XFREE(MTYPE_PCEP, ctrl_state->pcc_opts);
840 }
841 ctrl_state->pcc_opts = opts;
842 return 0;
843 }
844
845 int pcep_thread_event_update_pce_options(struct ctrl_state *ctrl_state,
846 int pcc_id, struct pce_opts *pce_opts)
847 {
848 if (!pce_opts || !ctrl_state) {
849 return 0;
850 }
851 struct pcc_state *pcc_state;
852 struct pcc_opts *pcc_opts;
853
854 int current_pcc_id =
855 pcep_pcc_get_pcc_id_by_ip_port(ctrl_state->pcc, pce_opts);
856 if (current_pcc_id) {
857 pcc_state =
858 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, current_pcc_id);
859 } else {
860 pcc_state = pcep_pcc_initialize(ctrl_state,
861 get_next_id(ctrl_state));
862 if (set_pcc_state(ctrl_state, pcc_state)) {
863 XFREE(MTYPE_PCEP, pcc_state);
864 return 0;
865 }
866 }
867
868 /* Copy the pcc options to delegate it to the update function */
869 pcc_opts = XCALLOC(MTYPE_PCEP, sizeof(*pcc_opts));
870 memcpy(pcc_opts, ctrl_state->pcc_opts, sizeof(*pcc_opts));
871
872 if (pcep_pcc_update(ctrl_state, pcc_state, pcc_opts, pce_opts)) {
873 flog_err(EC_PATH_PCEP_PCC_CONF_UPDATE,
874 "failed to update PCC configuration");
875 }
876
877
878 return 0;
879 }
880
881 int pcep_thread_event_remove_pcc_by_id(struct ctrl_state *ctrl_state,
882 int pcc_id)
883 {
884 if (pcc_id) {
885 struct pcc_state *pcc_state =
886 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
887 if (pcc_state) {
888 remove_pcc_state(ctrl_state, pcc_state);
889 pcep_pcc_finalize(ctrl_state, pcc_state);
890 }
891 }
892 return 0;
893 }
894
895 int pcep_thread_event_remove_pcc_all(struct ctrl_state *ctrl_state)
896 {
897 assert(ctrl_state != NULL);
898
899 for (int i = 0; i < MAX_PCC; i++) {
900 pcep_thread_event_remove_pcc_by_id(
901 ctrl_state,
902 pcep_pcc_get_pcc_id_by_idx(ctrl_state->pcc, i));
903 }
904 return 0;
905 }
906
907 int pcep_thread_event_remove_pcc(struct ctrl_state *ctrl_state,
908 struct pce_opts *pce_opts)
909 {
910 assert(ctrl_state != NULL);
911
912 if (pce_opts) {
913 int pcc_id = pcep_pcc_get_pcc_id_by_ip_port(ctrl_state->pcc,
914 pce_opts);
915 if (pcc_id) {
916 pcep_thread_event_remove_pcc_by_id(ctrl_state, pcc_id);
917 } else {
918 return -1;
919 }
920 XFREE(MTYPE_PCEP, pce_opts);
921 } else {
922 pcep_thread_event_remove_pcc_all(ctrl_state);
923 }
924
925 return 0;
926 }
927
928 int pcep_thread_event_sync_path(struct ctrl_state *ctrl_state, int pcc_id,
929 struct path *path)
930 {
931 struct pcc_state *pcc_state =
932 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
933 pcep_pcc_sync_path(ctrl_state, pcc_state, path);
934 pcep_free_path(path);
935 return 0;
936 }
937
938 int pcep_thread_event_sync_done(struct ctrl_state *ctrl_state, int pcc_id)
939 {
940 struct pcc_state *pcc_state =
941 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
942 pcep_pcc_sync_done(ctrl_state, pcc_state);
943 return 0;
944 }
945
946 int pcep_thread_event_pathd_event(struct ctrl_state *ctrl_state,
947 enum pcep_pathd_event_type type,
948 struct path *path)
949 {
950 int i;
951
952 for (i = 0; i < MAX_PCC; i++) {
953 if (ctrl_state->pcc[i]) {
954 struct pcc_state *pcc_state = ctrl_state->pcc[i];
955 pcep_pcc_pathd_event_handler(ctrl_state, pcc_state,
956 type, path);
957 }
958 }
959
960 pcep_free_path(path);
961
962 return 0;
963 }
964
965
966 /* ------------ Main Thread Event Handler ------------ */
967
968 int send_to_main(struct ctrl_state *ctrl_state, int pcc_id,
969 enum pcep_main_event_type type, void *payload)
970 {
971 struct pcep_main_event_data *data;
972
973 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
974 data->handler = ctrl_state->main_event_handler;
975 data->type = type;
976 data->pcc_id = pcc_id;
977 data->payload = payload;
978
979 thread_add_event(ctrl_state->main, pcep_main_event_handler,
980 (void *)data, 0, NULL);
981 return 0;
982 }
983
984 void pcep_main_event_handler(struct thread *thread)
985 {
986 /* data unpacking */
987 struct pcep_main_event_data *data = THREAD_ARG(thread);
988 assert(data != NULL);
989 pcep_main_event_handler_t handler = data->handler;
990 enum pcep_main_event_type type = data->type;
991 int pcc_id = data->pcc_id;
992 void *payload = data->payload;
993 XFREE(MTYPE_PCEP, data);
994
995 handler(type, pcc_id, payload);
996 }
997
998
999 /* ------------ Helper functions ------------ */
1000
1001 void set_ctrl_state(struct frr_pthread *fpt, struct ctrl_state *ctrl_state)
1002 {
1003 assert(fpt != NULL);
1004 fpt->data = ctrl_state;
1005 }
1006
1007 struct ctrl_state *get_ctrl_state(struct frr_pthread *fpt)
1008 {
1009 assert(fpt != NULL);
1010 assert(fpt->data != NULL);
1011
1012 struct ctrl_state *ctrl_state;
1013 ctrl_state = (struct ctrl_state *)fpt->data;
1014 assert(ctrl_state != NULL);
1015 return ctrl_state;
1016 }
1017
1018 int get_next_id(struct ctrl_state *ctrl_state)
1019 {
1020 return ++ctrl_state->pcc_last_id;
1021 }
1022
1023 int set_pcc_state(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state)
1024 {
1025 assert(ctrl_state != NULL);
1026 assert(pcep_pcc_get_pcc_id(pcc_state) != 0);
1027
1028 int current_pcc_idx = pcep_pcc_get_free_pcc_idx(ctrl_state->pcc);
1029 if (current_pcc_idx >= 0) {
1030 ctrl_state->pcc[current_pcc_idx] = pcc_state;
1031 ctrl_state->pcc_count++;
1032 PCEP_DEBUG("added pce pcc_id (%d) idx (%d)",
1033 pcep_pcc_get_pcc_id(pcc_state), current_pcc_idx);
1034 return 0;
1035 } else {
1036 PCEP_DEBUG("Max number of pce ");
1037 return 1;
1038 }
1039 }
1040
1041 void remove_pcc_state(struct ctrl_state *ctrl_state,
1042 struct pcc_state *pcc_state)
1043 {
1044 assert(ctrl_state != NULL);
1045 assert(pcep_pcc_get_pcc_id(pcc_state) != 0);
1046
1047 int idx = 0;
1048 idx = pcep_pcc_get_pcc_idx_by_id(ctrl_state->pcc,
1049 pcep_pcc_get_pcc_id(pcc_state));
1050 if (idx != -1) {
1051 ctrl_state->pcc[idx] = NULL;
1052 ctrl_state->pcc_count--;
1053 PCEP_DEBUG("removed pce pcc_id (%d)",
1054 pcep_pcc_get_pcc_id(pcc_state));
1055 }
1056 }
1057
1058 uint32_t backoff_delay(uint32_t max, uint32_t base, uint32_t retry_count)
1059 {
1060 uint32_t a = MIN(max, base * (1 << retry_count));
1061 uint64_t r = frr_weak_random(), m = RAND_MAX;
1062 uint32_t b = (a / 2) + (r * (a / 2)) / m;
1063 return b;
1064 }
1065
1066 const char *timer_type_name(enum pcep_ctrl_timer_type type)
1067 {
1068 switch (type) {
1069 case TM_UNDEFINED:
1070 return "UNDEFINED";
1071 case TM_RECONNECT_PCC:
1072 return "RECONNECT_PCC";
1073 case TM_PCEPLIB_TIMER:
1074 return "PCEPLIB_TIMER";
1075 case TM_TIMEOUT:
1076 return "TIMEOUT";
1077 default:
1078 return "UNKNOWN";
1079 }
1080 };
1081
1082 const char *timeout_type_name(enum pcep_ctrl_timeout_type type)
1083 {
1084 switch (type) {
1085 case TO_UNDEFINED:
1086 return "UNDEFINED";
1087 case TO_COMPUTATION_REQUEST:
1088 return "COMPUTATION_REQUEST";
1089 default:
1090 return "UNKNOWN";
1091 }
1092 }