]> git.proxmox.com Git - mirror_frr.git/blob - pathd/path_pcep_controller.c
Merge pull request #10033 from donaldsharp/bgp_max_no_go
[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 int pcep_refine_path_event_cb(struct thread *thread);
96
97 /* Internal Functions Called From Controller Thread */
98 static int 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 int 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 int 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 int 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 int 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 return 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 int 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 return 0;
531 }
532
533 /* ------------ Controller Thread Timer Handler ------------ */
534
535 int schedule_thread_timer_with_cb(struct ctrl_state *ctrl_state, int pcc_id,
536 enum pcep_ctrl_timer_type timer_type,
537 enum pcep_ctrl_timeout_type timeout_type,
538 uint32_t delay, void *payload,
539 struct thread **thread,
540 pcep_ctrl_thread_callback timer_cb)
541 {
542 assert(thread != NULL);
543
544 struct pcep_ctrl_timer_data *data;
545
546 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
547 data->ctrl_state = ctrl_state;
548 data->timer_type = timer_type;
549 data->timeout_type = timeout_type;
550 data->pcc_id = pcc_id;
551 data->payload = payload;
552
553 thread_add_timer(ctrl_state->self, timer_cb, (void *)data, delay,
554 thread);
555
556 return 0;
557 }
558
559 int schedule_thread_timer(struct ctrl_state *ctrl_state, int pcc_id,
560 enum pcep_ctrl_timer_type timer_type,
561 enum pcep_ctrl_timeout_type timeout_type,
562 uint32_t delay, void *payload, struct thread **thread)
563 {
564 return schedule_thread_timer_with_cb(ctrl_state, pcc_id, timer_type,
565 timeout_type, delay, payload,
566 thread, pcep_thread_timer_handler);
567 }
568
569 int pcep_thread_timer_handler(struct thread *thread)
570 {
571 /* data unpacking */
572 struct pcep_ctrl_timer_data *data = THREAD_ARG(thread);
573 assert(data != NULL);
574 struct ctrl_state *ctrl_state = data->ctrl_state;
575 assert(ctrl_state != NULL);
576 enum pcep_ctrl_timer_type timer_type = data->timer_type;
577 enum pcep_ctrl_timeout_type timeout_type = data->timeout_type;
578 int pcc_id = data->pcc_id;
579 void *param = data->payload;
580 XFREE(MTYPE_PCEP, data);
581
582 int ret = 0;
583 struct pcc_state *pcc_state = NULL;
584
585 switch (timer_type) {
586 case TM_RECONNECT_PCC:
587 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
588 if (!pcc_state)
589 return ret;
590 pcep_pcc_reconnect(ctrl_state, pcc_state);
591 break;
592 case TM_TIMEOUT:
593 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
594 if (!pcc_state)
595 return ret;
596 pcep_pcc_timeout_handler(ctrl_state, pcc_state, timeout_type,
597 param);
598 break;
599 case TM_CALCULATE_BEST_PCE:
600 /* Previous best disconnect so new best should be synced */
601 ret = pcep_pcc_timer_update_best_pce(ctrl_state, pcc_id);
602 break;
603 case TM_SESSION_TIMEOUT_PCC:
604 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
605 pcep_thread_remove_candidate_path_segments(ctrl_state,
606 pcc_state);
607 break;
608 default:
609 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
610 "Unknown controller timer triggered: %u", timer_type);
611 break;
612 }
613
614 return ret;
615 }
616
617 int pcep_thread_pcep_event(struct thread *thread)
618 {
619 struct pcep_ctrl_event_data *data = THREAD_ARG(thread);
620 assert(data != NULL);
621 struct ctrl_state *ctrl_state = data->ctrl_state;
622 pcep_event *event = data->payload;
623 XFREE(MTYPE_PCEP, data);
624 int i;
625
626 for (i = 0; i < MAX_PCC; i++) {
627 if (ctrl_state->pcc[i]) {
628 struct pcc_state *pcc_state = ctrl_state->pcc[i];
629 if (pcc_state->sess != event->session)
630 continue;
631 pcep_pcc_pcep_event_handler(ctrl_state, pcc_state,
632 event);
633 break;
634 }
635 }
636 destroy_pcep_event(event);
637
638 return 0;
639 }
640
641 /* ------------ Controller Thread Socket Functions ------------ */
642
643 int schedule_thread_socket(struct ctrl_state *ctrl_state, int pcc_id,
644 enum pcep_ctrl_socket_type type, bool is_read,
645 void *payload, int fd, struct thread **thread,
646 pcep_ctrl_thread_callback socket_cb)
647 {
648 assert(thread != NULL);
649
650 struct pcep_ctrl_socket_data *data;
651
652 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
653 data->ctrl_state = ctrl_state;
654 data->type = type;
655 data->is_read = is_read;
656 data->fd = fd;
657 data->pcc_id = pcc_id;
658 data->payload = payload;
659
660 if (is_read) {
661 thread_add_read(ctrl_state->self, socket_cb, (void *)data, fd,
662 thread);
663 } else {
664 thread_add_write(ctrl_state->self, socket_cb, (void *)data, fd,
665 thread);
666 }
667
668 return 0;
669 }
670
671 int pcep_thread_socket_write(void *fpt, void **thread, int fd, void *payload,
672 pcep_ctrl_thread_callback socket_cb)
673 {
674 struct ctrl_state *ctrl_state = ((struct frr_pthread *)fpt)->data;
675
676 return schedule_thread_socket(ctrl_state, 0, SOCK_PCEPLIB, false,
677 payload, fd, (struct thread **)thread,
678 socket_cb);
679 }
680
681 int pcep_thread_socket_read(void *fpt, void **thread, int fd, void *payload,
682 pcep_ctrl_thread_callback socket_cb)
683 {
684 struct ctrl_state *ctrl_state = ((struct frr_pthread *)fpt)->data;
685
686 return schedule_thread_socket(ctrl_state, 0, SOCK_PCEPLIB, true,
687 payload, fd, (struct thread **)thread,
688 socket_cb);
689 }
690
691 int pcep_thread_send_ctrl_event(void *fpt, void *payload,
692 pcep_ctrl_thread_callback cb)
693 {
694 struct ctrl_state *ctrl_state = ((struct frr_pthread *)fpt)->data;
695
696 return send_to_thread_with_cb(ctrl_state, 0, EV_PCEPLIB_EVENT, 0,
697 payload, cb);
698 }
699
700 /* ------------ Controller Thread Event Handler ------------ */
701
702 int send_to_thread(struct ctrl_state *ctrl_state, int pcc_id,
703 enum pcep_ctrl_event_type type, uint32_t sub_type,
704 void *payload)
705 {
706 return send_to_thread_with_cb(ctrl_state, pcc_id, type, sub_type,
707 payload, pcep_thread_event_handler);
708 }
709
710 int send_to_thread_with_cb(struct ctrl_state *ctrl_state, int pcc_id,
711 enum pcep_ctrl_event_type type, uint32_t sub_type,
712 void *payload, pcep_ctrl_thread_callback event_cb)
713 {
714 struct pcep_ctrl_event_data *data;
715
716 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
717 data->ctrl_state = ctrl_state;
718 data->type = type;
719 data->sub_type = sub_type;
720 data->pcc_id = pcc_id;
721 data->payload = payload;
722
723 thread_add_event(ctrl_state->self, event_cb, (void *)data, 0, NULL);
724
725 return 0;
726 }
727
728 int pcep_thread_event_handler(struct thread *thread)
729 {
730 /* data unpacking */
731 struct pcep_ctrl_event_data *data = THREAD_ARG(thread);
732 assert(data != NULL);
733 struct ctrl_state *ctrl_state = data->ctrl_state;
734 assert(ctrl_state != NULL);
735 enum pcep_ctrl_event_type type = data->type;
736 uint32_t sub_type = data->sub_type;
737 int pcc_id = data->pcc_id;
738 void *payload = data->payload;
739 XFREE(MTYPE_PCEP, data);
740
741 int ret = 0;
742
743 /* Possible sub-type values */
744 enum pcep_pathd_event_type path_event_type = PCEP_PATH_UNDEFINED;
745
746 /* Possible payload values, maybe an union would be better... */
747 struct path *path = NULL;
748 struct pcc_opts *pcc_opts = NULL;
749 struct pce_opts *pce_opts = NULL;
750 struct pcc_state *pcc_state = NULL;
751 struct pcep_refine_path_event_data *refine_data = NULL;
752
753 struct path *path_copy = NULL;
754 struct pcep_error *error = NULL;
755
756 switch (type) {
757 case EV_UPDATE_PCC_OPTS:
758 assert(payload != NULL);
759 pcc_opts = (struct pcc_opts *)payload;
760 ret = pcep_thread_event_update_pcc_options(ctrl_state,
761 pcc_opts);
762 break;
763 case EV_UPDATE_PCE_OPTS:
764 assert(payload != NULL);
765 pce_opts = (struct pce_opts *)payload;
766 ret = pcep_thread_event_update_pce_options(ctrl_state, pcc_id,
767 pce_opts);
768 break;
769 case EV_REMOVE_PCC:
770 pce_opts = (struct pce_opts *)payload;
771 ret = pcep_thread_event_remove_pcc(ctrl_state, pce_opts);
772 if (ret == 0) {
773 ret = pcep_pcc_multi_pce_remove_pcc(ctrl_state,
774 ctrl_state->pcc);
775 }
776 break;
777 case EV_PATHD_EVENT:
778 assert(payload != NULL);
779 path_event_type = (enum pcep_pathd_event_type)sub_type;
780 path = (struct path *)payload;
781 ret = pcep_thread_event_pathd_event(ctrl_state, path_event_type,
782 path);
783 break;
784 case EV_SYNC_PATH:
785 assert(payload != NULL);
786 path = (struct path *)payload;
787 pcep_pcc_multi_pce_sync_path(ctrl_state, pcc_id,
788 ctrl_state->pcc);
789 pcep_thread_event_sync_path(ctrl_state, pcc_id, path);
790 break;
791 case EV_SYNC_DONE:
792 ret = pcep_thread_event_sync_done(ctrl_state, pcc_id);
793 break;
794 case EV_RESET_PCC_SESSION:
795 pcc_state = pcep_pcc_get_pcc_by_name(ctrl_state->pcc,
796 (const char *)payload);
797 if (pcc_state) {
798 pcep_pcc_disable(ctrl_state, pcc_state);
799 ret = pcep_pcc_enable(ctrl_state, pcc_state);
800 } else {
801 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
802 "Cannot reset state for PCE: %s",
803 (const char *)payload);
804 }
805 break;
806 case EV_SEND_REPORT:
807 assert(payload != NULL);
808 path = (struct path *)payload;
809 if (pcc_id == 0) {
810 for (int i = 0; i < MAX_PCC; i++) {
811 if (ctrl_state->pcc[i]) {
812 path_copy = pcep_copy_path(path);
813 pcep_pcc_send_report(
814 ctrl_state, ctrl_state->pcc[i],
815 path_copy, (bool)sub_type);
816 }
817 }
818 } else {
819 pcc_state =
820 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
821 pcep_pcc_send_report(ctrl_state, pcc_state, path,
822 (bool)sub_type);
823 }
824 break;
825 case EV_PATH_REFINED:
826 assert(payload != NULL);
827 refine_data = (struct pcep_refine_path_event_data *)payload;
828 pcep_thread_path_refined_event(ctrl_state, refine_data);
829 break;
830 case EV_SEND_ERROR:
831 assert(payload != NULL);
832 error = (struct pcep_error *)payload;
833 pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
834 pcep_pcc_send_error(ctrl_state, pcc_state, error,
835 (bool)sub_type);
836 break;
837 default:
838 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
839 "Unexpected event received in controller thread: %u",
840 type);
841 break;
842 }
843
844 return ret;
845 }
846
847 int pcep_thread_event_update_pcc_options(struct ctrl_state *ctrl_state,
848 struct pcc_opts *opts)
849 {
850 assert(opts != NULL);
851 if (ctrl_state->pcc_opts != NULL) {
852 XFREE(MTYPE_PCEP, ctrl_state->pcc_opts);
853 }
854 ctrl_state->pcc_opts = opts;
855 return 0;
856 }
857
858 int pcep_thread_event_update_pce_options(struct ctrl_state *ctrl_state,
859 int pcc_id, struct pce_opts *pce_opts)
860 {
861 if (!pce_opts || !ctrl_state) {
862 return 0;
863 }
864 struct pcc_state *pcc_state;
865 struct pcc_opts *pcc_opts;
866
867 int current_pcc_id =
868 pcep_pcc_get_pcc_id_by_ip_port(ctrl_state->pcc, pce_opts);
869 if (current_pcc_id) {
870 pcc_state =
871 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, current_pcc_id);
872 } else {
873 pcc_state = pcep_pcc_initialize(ctrl_state,
874 get_next_id(ctrl_state));
875 if (set_pcc_state(ctrl_state, pcc_state)) {
876 XFREE(MTYPE_PCEP, pcc_state);
877 return 0;
878 }
879 }
880
881 /* Copy the pcc options to delegate it to the update function */
882 pcc_opts = XCALLOC(MTYPE_PCEP, sizeof(*pcc_opts));
883 memcpy(pcc_opts, ctrl_state->pcc_opts, sizeof(*pcc_opts));
884
885 if (pcep_pcc_update(ctrl_state, pcc_state, pcc_opts, pce_opts)) {
886 flog_err(EC_PATH_PCEP_PCC_CONF_UPDATE,
887 "failed to update PCC configuration");
888 }
889
890
891 return 0;
892 }
893
894 int pcep_thread_event_remove_pcc_by_id(struct ctrl_state *ctrl_state,
895 int pcc_id)
896 {
897 if (pcc_id) {
898 struct pcc_state *pcc_state =
899 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
900 if (pcc_state) {
901 remove_pcc_state(ctrl_state, pcc_state);
902 pcep_pcc_finalize(ctrl_state, pcc_state);
903 }
904 }
905 return 0;
906 }
907
908 int pcep_thread_event_remove_pcc_all(struct ctrl_state *ctrl_state)
909 {
910 assert(ctrl_state != NULL);
911
912 for (int i = 0; i < MAX_PCC; i++) {
913 pcep_thread_event_remove_pcc_by_id(
914 ctrl_state,
915 pcep_pcc_get_pcc_id_by_idx(ctrl_state->pcc, i));
916 }
917 return 0;
918 }
919
920 int pcep_thread_event_remove_pcc(struct ctrl_state *ctrl_state,
921 struct pce_opts *pce_opts)
922 {
923 assert(ctrl_state != NULL);
924
925 if (pce_opts) {
926 int pcc_id = pcep_pcc_get_pcc_id_by_ip_port(ctrl_state->pcc,
927 pce_opts);
928 if (pcc_id) {
929 pcep_thread_event_remove_pcc_by_id(ctrl_state, pcc_id);
930 } else {
931 return -1;
932 }
933 XFREE(MTYPE_PCEP, pce_opts);
934 } else {
935 pcep_thread_event_remove_pcc_all(ctrl_state);
936 }
937
938 return 0;
939 }
940
941 int pcep_thread_event_sync_path(struct ctrl_state *ctrl_state, int pcc_id,
942 struct path *path)
943 {
944 struct pcc_state *pcc_state =
945 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
946 pcep_pcc_sync_path(ctrl_state, pcc_state, path);
947 pcep_free_path(path);
948 return 0;
949 }
950
951 int pcep_thread_event_sync_done(struct ctrl_state *ctrl_state, int pcc_id)
952 {
953 struct pcc_state *pcc_state =
954 pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
955 pcep_pcc_sync_done(ctrl_state, pcc_state);
956 return 0;
957 }
958
959 int pcep_thread_event_pathd_event(struct ctrl_state *ctrl_state,
960 enum pcep_pathd_event_type type,
961 struct path *path)
962 {
963 int i;
964
965 for (i = 0; i < MAX_PCC; i++) {
966 if (ctrl_state->pcc[i]) {
967 struct pcc_state *pcc_state = ctrl_state->pcc[i];
968 pcep_pcc_pathd_event_handler(ctrl_state, pcc_state,
969 type, path);
970 }
971 }
972
973 pcep_free_path(path);
974
975 return 0;
976 }
977
978
979 /* ------------ Main Thread Event Handler ------------ */
980
981 int send_to_main(struct ctrl_state *ctrl_state, int pcc_id,
982 enum pcep_main_event_type type, void *payload)
983 {
984 struct pcep_main_event_data *data;
985
986 data = XCALLOC(MTYPE_PCEP, sizeof(*data));
987 data->handler = ctrl_state->main_event_handler;
988 data->type = type;
989 data->pcc_id = pcc_id;
990 data->payload = payload;
991
992 thread_add_event(ctrl_state->main, pcep_main_event_handler,
993 (void *)data, 0, NULL);
994 return 0;
995 }
996
997 int pcep_main_event_handler(struct thread *thread)
998 {
999 /* data unpacking */
1000 struct pcep_main_event_data *data = THREAD_ARG(thread);
1001 assert(data != NULL);
1002 pcep_main_event_handler_t handler = data->handler;
1003 enum pcep_main_event_type type = data->type;
1004 int pcc_id = data->pcc_id;
1005 void *payload = data->payload;
1006 XFREE(MTYPE_PCEP, data);
1007
1008 return handler(type, pcc_id, payload);
1009 }
1010
1011
1012 /* ------------ Helper functions ------------ */
1013
1014 void set_ctrl_state(struct frr_pthread *fpt, struct ctrl_state *ctrl_state)
1015 {
1016 assert(fpt != NULL);
1017 fpt->data = ctrl_state;
1018 }
1019
1020 struct ctrl_state *get_ctrl_state(struct frr_pthread *fpt)
1021 {
1022 assert(fpt != NULL);
1023 assert(fpt->data != NULL);
1024
1025 struct ctrl_state *ctrl_state;
1026 ctrl_state = (struct ctrl_state *)fpt->data;
1027 assert(ctrl_state != NULL);
1028 return ctrl_state;
1029 }
1030
1031 int get_next_id(struct ctrl_state *ctrl_state)
1032 {
1033 return ++ctrl_state->pcc_last_id;
1034 }
1035
1036 int set_pcc_state(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state)
1037 {
1038 assert(ctrl_state != NULL);
1039 assert(pcep_pcc_get_pcc_id(pcc_state) != 0);
1040
1041 int current_pcc_idx = pcep_pcc_get_free_pcc_idx(ctrl_state->pcc);
1042 if (current_pcc_idx >= 0) {
1043 ctrl_state->pcc[current_pcc_idx] = pcc_state;
1044 ctrl_state->pcc_count++;
1045 PCEP_DEBUG("added pce pcc_id (%d) idx (%d)",
1046 pcep_pcc_get_pcc_id(pcc_state), current_pcc_idx);
1047 return 0;
1048 } else {
1049 PCEP_DEBUG("Max number of pce ");
1050 return 1;
1051 }
1052 }
1053
1054 void remove_pcc_state(struct ctrl_state *ctrl_state,
1055 struct pcc_state *pcc_state)
1056 {
1057 assert(ctrl_state != NULL);
1058 assert(pcep_pcc_get_pcc_id(pcc_state) != 0);
1059
1060 int idx = 0;
1061 idx = pcep_pcc_get_pcc_idx_by_id(ctrl_state->pcc,
1062 pcep_pcc_get_pcc_id(pcc_state));
1063 if (idx != -1) {
1064 ctrl_state->pcc[idx] = NULL;
1065 ctrl_state->pcc_count--;
1066 PCEP_DEBUG("removed pce pcc_id (%d)",
1067 pcep_pcc_get_pcc_id(pcc_state));
1068 }
1069 }
1070
1071 uint32_t backoff_delay(uint32_t max, uint32_t base, uint32_t retry_count)
1072 {
1073 uint32_t a = MIN(max, base * (1 << retry_count));
1074 uint64_t r = frr_weak_random(), m = RAND_MAX;
1075 uint32_t b = (a / 2) + (r * (a / 2)) / m;
1076 return b;
1077 }
1078
1079 const char *timer_type_name(enum pcep_ctrl_timer_type type)
1080 {
1081 switch (type) {
1082 case TM_UNDEFINED:
1083 return "UNDEFINED";
1084 case TM_RECONNECT_PCC:
1085 return "RECONNECT_PCC";
1086 case TM_PCEPLIB_TIMER:
1087 return "PCEPLIB_TIMER";
1088 case TM_TIMEOUT:
1089 return "TIMEOUT";
1090 default:
1091 return "UNKNOWN";
1092 }
1093 };
1094
1095 const char *timeout_type_name(enum pcep_ctrl_timeout_type type)
1096 {
1097 switch (type) {
1098 case TO_UNDEFINED:
1099 return "UNDEFINED";
1100 case TO_COMPUTATION_REQUEST:
1101 return "COMPUTATION_REQUEST";
1102 default:
1103 return "UNKNOWN";
1104 }
1105 }