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