2 * Copyright (C) 2020 NetDEF, Inc.
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)
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
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
25 #include "lib/version.h"
26 #include "northbound.h"
27 #include "frr_pthread.h"
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"
39 #define MAX_RECONNECT_DELAY 120
41 /* Event handling data structures */
42 enum pcep_ctrl_event_type
{
43 EV_UPDATE_PCC_OPTS
= 1,
56 struct pcep_ctrl_event_data
{
57 struct ctrl_state
*ctrl_state
;
58 enum pcep_ctrl_event_type type
;
64 struct pcep_main_event_data
{
65 pcep_main_event_handler_t handler
;
67 enum pcep_main_event_type type
;
71 struct pcep_refine_path_event_data
{
72 struct ctrl_state
*ctrl_state
;
74 pcep_refine_callback_t continue_lsp_update_handler
;
79 /* Synchronous call arguments */
81 struct get_counters_args
{
82 struct ctrl_state
*ctrl_state
;
84 struct counters_group
*counters
;
87 struct get_pcep_session_args
{
88 struct ctrl_state
*ctrl_state
;
90 pcep_session
*pcep_session
;
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
);
97 /* Internal Functions Called From Controller Thread */
98 static void pcep_thread_finish_event_handler(struct thread
*thread
);
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
);
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
);
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
,
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
,
132 struct pce_opts
*opts
);
133 static int pcep_thread_event_remove_pcc_by_id(struct ctrl_state
*ctrl_state
,
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
,
142 static int pcep_thread_event_pathd_event(struct ctrl_state
*ctrl_state
,
143 enum pcep_pathd_event_type type
,
146 pcep_thread_path_refined_event(struct ctrl_state
*ctrl_state
,
147 struct pcep_refine_path_event_data
*data
);
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
);
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
);
167 /* ------------ API Functions Called from Main Thread ------------ */
169 int pcep_ctrl_initialize(struct thread_master
*main_thread
,
170 struct frr_pthread
**fpt
,
171 pcep_main_event_handler_t event_handler
)
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
,
182 PCEP_DEBUG("Initializing pcep module controller");
184 /* Create and start the FRR pthread */
185 *fpt
= frr_pthread_new(&attr
, "PCEP thread", "pcep_controller");
187 flog_err(EC_PATH_SYSTEM_CALL
,
188 "failed to initialize PCEP thread");
191 ret
= frr_pthread_run(*fpt
, NULL
);
193 flog_err(EC_PATH_SYSTEM_CALL
, "failed to create PCEP thread");
196 frr_pthread_wait_running(*fpt
);
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
;
211 /* Keep the state reference for events */
212 set_ctrl_state(*fpt
, ctrl_state
);
217 int pcep_ctrl_finalize(struct frr_pthread
**fpt
)
223 PCEP_DEBUG("Finalizing pcep module controller");
226 frr_pthread_stop(*fpt
, NULL
);
233 int pcep_ctrl_update_pcc_options(struct frr_pthread
*fpt
, struct pcc_opts
*opts
)
235 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
236 return send_to_thread(ctrl_state
, 0, EV_UPDATE_PCC_OPTS
, 0, opts
);
239 int pcep_ctrl_update_pce_options(struct frr_pthread
*fpt
, struct pce_opts
*opts
)
241 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
242 return send_to_thread(ctrl_state
, 0, EV_UPDATE_PCE_OPTS
, 0, opts
);
245 int pcep_ctrl_remove_pcc(struct frr_pthread
*fpt
, struct pce_opts
*pce_opts
)
247 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
248 return send_to_thread(ctrl_state
, 0, EV_REMOVE_PCC
, 0, pce_opts
);
251 int pcep_ctrl_reset_pcc_session(struct frr_pthread
*fpt
, char *pce_name
)
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
);
257 int pcep_ctrl_pathd_event(struct frr_pthread
*fpt
,
258 enum pcep_pathd_event_type type
, struct path
*path
)
260 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
261 return send_to_thread(ctrl_state
, 0, EV_PATHD_EVENT
, type
, path
);
264 int pcep_ctrl_sync_path(struct frr_pthread
*fpt
, int pcc_id
, struct path
*path
)
266 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
267 return send_to_thread(ctrl_state
, pcc_id
, EV_SYNC_PATH
, 0, path
);
270 int pcep_ctrl_sync_done(struct frr_pthread
*fpt
, int pcc_id
)
272 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
273 return send_to_thread(ctrl_state
, pcc_id
, EV_SYNC_DONE
, 0, NULL
);
276 struct counters_group
*pcep_ctrl_get_counters(struct frr_pthread
*fpt
,
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
);
284 counters
= pcep_lib_copy_counters(pcc_state
->sess
);
289 pcep_session
*pcep_ctrl_get_pcep_session(struct frr_pthread
*fpt
, int pcc_id
)
291 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
292 struct pcc_state
*pcc_state
;
293 pcep_session
*session
= NULL
;
295 pcc_state
= pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
297 session
= pcep_lib_copy_pcep_session(pcc_state
->sess
);
302 struct pcep_pcc_info
*pcep_ctrl_get_pcc_info(struct frr_pthread
*fpt
,
303 const char *pce_name
)
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
);
315 int pcep_ctrl_send_report(struct frr_pthread
*fpt
, int pcc_id
,
316 struct path
*path
, bool is_stable
)
318 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
319 return send_to_thread(ctrl_state
, pcc_id
, EV_SEND_REPORT
, is_stable
,
324 int pcep_ctrl_send_error(struct frr_pthread
*fpt
, int pcc_id
,
325 struct pcep_error
*error
)
327 struct ctrl_state
*ctrl_state
= get_ctrl_state(fpt
);
328 return send_to_thread(ctrl_state
, pcc_id
, EV_SEND_ERROR
, 0, error
);
332 /* ------------ Internal Functions Called from Main Thread ------------ */
334 int pcep_ctrl_halt_cb(struct frr_pthread
*fpt
, void **res
)
336 thread_add_event(fpt
->master
, pcep_thread_finish_event_handler
,
337 (void *)fpt
, 0, NULL
);
338 pthread_join(fpt
->thread
, res
);
343 void pcep_refine_path_event_cb(struct thread
*thread
)
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
;
353 path_pcep_refine_path(path
);
354 send_to_thread(ctrl_state
, pcc_id
, EV_PATH_REFINED
, 0, data
);
358 /* ------------ API Functions Called From Controller Thread ------------ */
360 void pcep_thread_start_sync(struct ctrl_state
*ctrl_state
, int pcc_id
)
362 send_to_main(ctrl_state
, pcc_id
, PCEP_MAIN_EVENT_START_SYNC
, NULL
);
365 void pcep_thread_update_path(struct ctrl_state
*ctrl_state
, int pcc_id
,
368 send_to_main(ctrl_state
, pcc_id
, PCEP_MAIN_EVENT_UPDATE_CANDIDATE
,
372 void pcep_thread_initiate_path(struct ctrl_state
*ctrl_state
, int pcc_id
,
375 send_to_main(ctrl_state
, pcc_id
, PCEP_MAIN_EVENT_INITIATE_CANDIDATE
,
379 void pcep_thread_remove_candidate_path_segments(struct ctrl_state
*ctrl_state
,
380 struct pcc_state
*pcc_state
)
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",
388 send_to_main(ctrl_state
, pcep_pcc_get_pcc_id(pcc_state
),
389 PCEP_MAIN_EVENT_REMOVE_CANDIDATE_LSP
, originator
);
392 void pcep_thread_schedule_sync_best_pce(struct ctrl_state
*ctrl_state
,
393 int pcc_id
, int delay
,
394 struct thread
**thread
)
397 schedule_thread_timer(ctrl_state
, pcc_id
, TM_CALCULATE_BEST_PCE
,
398 TO_UNDEFINED
, delay
, NULL
, thread
);
401 void pcep_thread_cancel_timer(struct thread
**thread
)
403 if (thread
== NULL
|| *thread
== NULL
) {
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
));
411 XFREE(MTYPE_PCEP
, data
);
414 if ((*thread
)->master
->owner
== pthread_self()) {
415 thread_cancel(thread
);
417 thread_cancel_async((*thread
)->master
, thread
, NULL
);
421 void pcep_thread_schedule_reconnect(struct ctrl_state
*ctrl_state
, int pcc_id
,
422 int retry_count
, struct thread
**thread
)
424 uint32_t delay
= backoff_delay(MAX_RECONNECT_DELAY
, 1, retry_count
);
425 PCEP_DEBUG("Schedule RECONNECT_PCC for %us (retry %u)", delay
,
427 schedule_thread_timer(ctrl_state
, pcc_id
, TM_RECONNECT_PCC
,
428 TO_UNDEFINED
, delay
, NULL
, thread
);
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
)
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
);
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
)
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
,
455 void pcep_thread_schedule_session_timeout(struct ctrl_state
*ctrl_state
,
456 int pcc_id
, int delay
,
457 struct thread
**thread
)
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
);
464 int pcep_thread_pcc_count(struct ctrl_state
*ctrl_state
)
466 if (ctrl_state
== NULL
) {
470 return ctrl_state
->pcc_count
;
473 int pcep_thread_refine_path(struct ctrl_state
*ctrl_state
, int pcc_id
,
474 pcep_refine_callback_t cb
, struct path
*path
,
477 struct pcep_refine_path_event_data
*data
;
479 data
= XCALLOC(MTYPE_PCEP
, sizeof(*data
));
480 data
->ctrl_state
= ctrl_state
;
482 data
->pcc_id
= pcc_id
;
483 data
->continue_lsp_update_handler
= cb
;
484 data
->payload
= payload
;
486 thread_add_event(ctrl_state
->main
, pcep_refine_path_event_cb
,
487 (void *)data
, 0, NULL
);
491 void pcep_thread_path_refined_event(struct ctrl_state
*ctrl_state
,
492 struct pcep_refine_path_event_data
*data
)
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
);
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
);
508 /* ------------ Internal Functions Called From Controller Thread ------------ */
510 void pcep_thread_finish_event_handler(struct thread
*thread
)
513 struct frr_pthread
*fpt
= THREAD_ARG(thread
);
514 struct ctrl_state
*ctrl_state
= fpt
->data
;
516 assert(ctrl_state
!= NULL
);
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
;
525 XFREE(MTYPE_PCEP
, ctrl_state
->pcc_opts
);
526 XFREE(MTYPE_PCEP
, ctrl_state
);
529 atomic_store_explicit(&fpt
->running
, false, memory_order_relaxed
);
532 /* ------------ Controller Thread Timer Handler ------------ */
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
)
541 assert(thread
!= NULL
);
543 struct pcep_ctrl_timer_data
*data
;
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
;
552 thread_add_timer(ctrl_state
->self
, timer_cb
, (void *)data
, delay
,
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
)
563 return schedule_thread_timer_with_cb(ctrl_state
, pcc_id
, timer_type
,
564 timeout_type
, delay
, payload
,
565 thread
, pcep_thread_timer_handler
);
568 void pcep_thread_timer_handler(struct thread
*thread
)
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
);
581 struct pcc_state
*pcc_state
= NULL
;
583 switch (timer_type
) {
584 case TM_RECONNECT_PCC
:
585 pcc_state
= pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
588 pcep_pcc_reconnect(ctrl_state
, pcc_state
);
591 pcc_state
= pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
594 pcep_pcc_timeout_handler(ctrl_state
, pcc_state
, timeout_type
,
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
);
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
,
607 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR
,
608 "Unknown controller timer triggered: %u", timer_type
);
613 void pcep_thread_pcep_event(struct thread
*thread
)
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
);
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
)
627 pcep_pcc_pcep_event_handler(ctrl_state
, pcc_state
,
632 destroy_pcep_event(event
);
635 /* ------------ Controller Thread Socket Functions ------------ */
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
)
642 assert(thread
!= NULL
);
644 struct pcep_ctrl_socket_data
*data
;
646 data
= XCALLOC(MTYPE_PCEP
, sizeof(*data
));
647 data
->ctrl_state
= ctrl_state
;
649 data
->is_read
= is_read
;
651 data
->pcc_id
= pcc_id
;
652 data
->payload
= payload
;
655 thread_add_read(ctrl_state
->self
, socket_cb
, (void *)data
, fd
,
658 thread_add_write(ctrl_state
->self
, socket_cb
, (void *)data
, fd
,
665 int pcep_thread_socket_write(void *fpt
, void **thread
, int fd
, void *payload
,
666 pcep_ctrl_thread_callback socket_cb
)
668 struct ctrl_state
*ctrl_state
= ((struct frr_pthread
*)fpt
)->data
;
670 return schedule_thread_socket(ctrl_state
, 0, SOCK_PCEPLIB
, false,
671 payload
, fd
, (struct thread
**)thread
,
675 int pcep_thread_socket_read(void *fpt
, void **thread
, int fd
, void *payload
,
676 pcep_ctrl_thread_callback socket_cb
)
678 struct ctrl_state
*ctrl_state
= ((struct frr_pthread
*)fpt
)->data
;
680 return schedule_thread_socket(ctrl_state
, 0, SOCK_PCEPLIB
, true,
681 payload
, fd
, (struct thread
**)thread
,
685 int pcep_thread_send_ctrl_event(void *fpt
, void *payload
,
686 pcep_ctrl_thread_callback cb
)
688 struct ctrl_state
*ctrl_state
= ((struct frr_pthread
*)fpt
)->data
;
690 return send_to_thread_with_cb(ctrl_state
, 0, EV_PCEPLIB_EVENT
, 0,
694 /* ------------ Controller Thread Event Handler ------------ */
696 int send_to_thread(struct ctrl_state
*ctrl_state
, int pcc_id
,
697 enum pcep_ctrl_event_type type
, uint32_t sub_type
,
700 return send_to_thread_with_cb(ctrl_state
, pcc_id
, type
, sub_type
,
701 payload
, pcep_thread_event_handler
);
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
)
708 struct pcep_ctrl_event_data
*data
;
710 data
= XCALLOC(MTYPE_PCEP
, sizeof(*data
));
711 data
->ctrl_state
= ctrl_state
;
713 data
->sub_type
= sub_type
;
714 data
->pcc_id
= pcc_id
;
715 data
->payload
= payload
;
717 thread_add_event(ctrl_state
->self
, event_cb
, (void *)data
, 0, NULL
);
722 void pcep_thread_event_handler(struct thread
*thread
)
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
);
735 /* Possible sub-type values */
736 enum pcep_pathd_event_type path_event_type
= PCEP_PATH_UNDEFINED
;
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
;
745 struct path
*path_copy
= NULL
;
746 struct pcep_error
*error
= NULL
;
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
);
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
,
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
,
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
,
774 assert(payload
!= NULL
);
775 path
= (struct path
*)payload
;
776 pcep_pcc_multi_pce_sync_path(ctrl_state
, pcc_id
,
778 pcep_thread_event_sync_path(ctrl_state
, pcc_id
, path
);
781 pcep_thread_event_sync_done(ctrl_state
, pcc_id
);
783 case EV_RESET_PCC_SESSION
:
784 pcc_state
= pcep_pcc_get_pcc_by_name(ctrl_state
->pcc
,
785 (const char *)payload
);
787 pcep_pcc_disable(ctrl_state
, pcc_state
);
788 pcep_pcc_enable(ctrl_state
, pcc_state
);
790 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR
,
791 "Cannot reset state for PCE: %s",
792 (const char *)payload
);
796 assert(payload
!= NULL
);
797 path
= (struct path
*)payload
;
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
);
809 pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
810 pcep_pcc_send_report(ctrl_state
, pcc_state
, path
,
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
);
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
,
827 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR
,
828 "Unexpected event received in controller thread: %u",
834 int pcep_thread_event_update_pcc_options(struct ctrl_state
*ctrl_state
,
835 struct pcc_opts
*opts
)
837 assert(opts
!= NULL
);
838 if (ctrl_state
->pcc_opts
!= NULL
) {
839 XFREE(MTYPE_PCEP
, ctrl_state
->pcc_opts
);
841 ctrl_state
->pcc_opts
= opts
;
845 int pcep_thread_event_update_pce_options(struct ctrl_state
*ctrl_state
,
846 int pcc_id
, struct pce_opts
*pce_opts
)
848 if (!pce_opts
|| !ctrl_state
) {
851 struct pcc_state
*pcc_state
;
852 struct pcc_opts
*pcc_opts
;
855 pcep_pcc_get_pcc_id_by_ip_port(ctrl_state
->pcc
, pce_opts
);
856 if (current_pcc_id
) {
858 pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, current_pcc_id
);
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
);
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
));
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");
881 int pcep_thread_event_remove_pcc_by_id(struct ctrl_state
*ctrl_state
,
885 struct pcc_state
*pcc_state
=
886 pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
888 remove_pcc_state(ctrl_state
, pcc_state
);
889 pcep_pcc_finalize(ctrl_state
, pcc_state
);
895 int pcep_thread_event_remove_pcc_all(struct ctrl_state
*ctrl_state
)
897 assert(ctrl_state
!= NULL
);
899 for (int i
= 0; i
< MAX_PCC
; i
++) {
900 pcep_thread_event_remove_pcc_by_id(
902 pcep_pcc_get_pcc_id_by_idx(ctrl_state
->pcc
, i
));
907 int pcep_thread_event_remove_pcc(struct ctrl_state
*ctrl_state
,
908 struct pce_opts
*pce_opts
)
910 assert(ctrl_state
!= NULL
);
913 int pcc_id
= pcep_pcc_get_pcc_id_by_ip_port(ctrl_state
->pcc
,
916 pcep_thread_event_remove_pcc_by_id(ctrl_state
, pcc_id
);
920 XFREE(MTYPE_PCEP
, pce_opts
);
922 pcep_thread_event_remove_pcc_all(ctrl_state
);
928 int pcep_thread_event_sync_path(struct ctrl_state
*ctrl_state
, int pcc_id
,
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
);
938 int pcep_thread_event_sync_done(struct ctrl_state
*ctrl_state
, int pcc_id
)
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
);
946 int pcep_thread_event_pathd_event(struct ctrl_state
*ctrl_state
,
947 enum pcep_pathd_event_type type
,
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
,
960 pcep_free_path(path
);
966 /* ------------ Main Thread Event Handler ------------ */
968 int send_to_main(struct ctrl_state
*ctrl_state
, int pcc_id
,
969 enum pcep_main_event_type type
, void *payload
)
971 struct pcep_main_event_data
*data
;
973 data
= XCALLOC(MTYPE_PCEP
, sizeof(*data
));
974 data
->handler
= ctrl_state
->main_event_handler
;
976 data
->pcc_id
= pcc_id
;
977 data
->payload
= payload
;
979 thread_add_event(ctrl_state
->main
, pcep_main_event_handler
,
980 (void *)data
, 0, NULL
);
984 void pcep_main_event_handler(struct thread
*thread
)
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
);
995 handler(type
, pcc_id
, payload
);
999 /* ------------ Helper functions ------------ */
1001 void set_ctrl_state(struct frr_pthread
*fpt
, struct ctrl_state
*ctrl_state
)
1003 assert(fpt
!= NULL
);
1004 fpt
->data
= ctrl_state
;
1007 struct ctrl_state
*get_ctrl_state(struct frr_pthread
*fpt
)
1009 assert(fpt
!= NULL
);
1010 assert(fpt
->data
!= NULL
);
1012 struct ctrl_state
*ctrl_state
;
1013 ctrl_state
= (struct ctrl_state
*)fpt
->data
;
1014 assert(ctrl_state
!= NULL
);
1018 int get_next_id(struct ctrl_state
*ctrl_state
)
1020 return ++ctrl_state
->pcc_last_id
;
1023 int set_pcc_state(struct ctrl_state
*ctrl_state
, struct pcc_state
*pcc_state
)
1025 assert(ctrl_state
!= NULL
);
1026 assert(pcep_pcc_get_pcc_id(pcc_state
) != 0);
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
);
1036 PCEP_DEBUG("Max number of pce ");
1041 void remove_pcc_state(struct ctrl_state
*ctrl_state
,
1042 struct pcc_state
*pcc_state
)
1044 assert(ctrl_state
!= NULL
);
1045 assert(pcep_pcc_get_pcc_id(pcc_state
) != 0);
1048 idx
= pcep_pcc_get_pcc_idx_by_id(ctrl_state
->pcc
,
1049 pcep_pcc_get_pcc_id(pcc_state
));
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
));
1058 uint32_t backoff_delay(uint32_t max
, uint32_t base
, uint32_t retry_count
)
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
;
1066 const char *timer_type_name(enum pcep_ctrl_timer_type type
)
1071 case TM_RECONNECT_PCC
:
1072 return "RECONNECT_PCC";
1073 case TM_PCEPLIB_TIMER
:
1074 return "PCEPLIB_TIMER";
1082 const char *timeout_type_name(enum pcep_ctrl_timeout_type type
)
1087 case TO_COMPUTATION_REQUEST
:
1088 return "COMPUTATION_REQUEST";