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 int pcep_refine_path_event_cb(struct thread
*thread
);
97 /* Internal Functions Called From Controller Thread */
98 static int 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 int 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 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
,
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 int 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 int 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 return 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 int 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
);
533 /* ------------ Controller Thread Timer Handler ------------ */
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
)
542 assert(thread
!= NULL
);
544 struct pcep_ctrl_timer_data
*data
;
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
;
553 thread_add_timer(ctrl_state
->self
, timer_cb
, (void *)data
, delay
,
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
)
564 return schedule_thread_timer_with_cb(ctrl_state
, pcc_id
, timer_type
,
565 timeout_type
, delay
, payload
,
566 thread
, pcep_thread_timer_handler
);
569 int pcep_thread_timer_handler(struct thread
*thread
)
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
);
583 struct pcc_state
*pcc_state
= NULL
;
585 switch (timer_type
) {
586 case TM_RECONNECT_PCC
:
587 pcc_state
= pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
590 pcep_pcc_reconnect(ctrl_state
, pcc_state
);
593 pcc_state
= pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
596 pcep_pcc_timeout_handler(ctrl_state
, pcc_state
, timeout_type
,
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
);
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
,
609 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR
,
610 "Unknown controller timer triggered: %u", timer_type
);
617 int pcep_thread_pcep_event(struct thread
*thread
)
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
);
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
)
631 pcep_pcc_pcep_event_handler(ctrl_state
, pcc_state
,
636 destroy_pcep_event(event
);
641 /* ------------ Controller Thread Socket Functions ------------ */
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
)
648 assert(thread
!= NULL
);
650 struct pcep_ctrl_socket_data
*data
;
652 data
= XCALLOC(MTYPE_PCEP
, sizeof(*data
));
653 data
->ctrl_state
= ctrl_state
;
655 data
->is_read
= is_read
;
657 data
->pcc_id
= pcc_id
;
658 data
->payload
= payload
;
661 thread_add_read(ctrl_state
->self
, socket_cb
, (void *)data
, fd
,
664 thread_add_write(ctrl_state
->self
, socket_cb
, (void *)data
, fd
,
671 int pcep_thread_socket_write(void *fpt
, void **thread
, int fd
, void *payload
,
672 pcep_ctrl_thread_callback socket_cb
)
674 struct ctrl_state
*ctrl_state
= ((struct frr_pthread
*)fpt
)->data
;
676 return schedule_thread_socket(ctrl_state
, 0, SOCK_PCEPLIB
, false,
677 payload
, fd
, (struct thread
**)thread
,
681 int pcep_thread_socket_read(void *fpt
, void **thread
, int fd
, void *payload
,
682 pcep_ctrl_thread_callback socket_cb
)
684 struct ctrl_state
*ctrl_state
= ((struct frr_pthread
*)fpt
)->data
;
686 return schedule_thread_socket(ctrl_state
, 0, SOCK_PCEPLIB
, true,
687 payload
, fd
, (struct thread
**)thread
,
691 int pcep_thread_send_ctrl_event(void *fpt
, void *payload
,
692 pcep_ctrl_thread_callback cb
)
694 struct ctrl_state
*ctrl_state
= ((struct frr_pthread
*)fpt
)->data
;
696 return send_to_thread_with_cb(ctrl_state
, 0, EV_PCEPLIB_EVENT
, 0,
700 /* ------------ Controller Thread Event Handler ------------ */
702 int send_to_thread(struct ctrl_state
*ctrl_state
, int pcc_id
,
703 enum pcep_ctrl_event_type type
, uint32_t sub_type
,
706 return send_to_thread_with_cb(ctrl_state
, pcc_id
, type
, sub_type
,
707 payload
, pcep_thread_event_handler
);
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
)
714 struct pcep_ctrl_event_data
*data
;
716 data
= XCALLOC(MTYPE_PCEP
, sizeof(*data
));
717 data
->ctrl_state
= ctrl_state
;
719 data
->sub_type
= sub_type
;
720 data
->pcc_id
= pcc_id
;
721 data
->payload
= payload
;
723 thread_add_event(ctrl_state
->self
, event_cb
, (void *)data
, 0, NULL
);
728 int pcep_thread_event_handler(struct thread
*thread
)
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
);
743 /* Possible sub-type values */
744 enum pcep_pathd_event_type path_event_type
= PCEP_PATH_UNDEFINED
;
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
;
753 struct path
*path_copy
= NULL
;
754 struct pcep_error
*error
= NULL
;
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
,
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
,
770 pce_opts
= (struct pce_opts
*)payload
;
771 ret
= pcep_thread_event_remove_pcc(ctrl_state
, pce_opts
);
773 ret
= pcep_pcc_multi_pce_remove_pcc(ctrl_state
,
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
,
785 assert(payload
!= NULL
);
786 path
= (struct path
*)payload
;
787 pcep_pcc_multi_pce_sync_path(ctrl_state
, pcc_id
,
789 pcep_thread_event_sync_path(ctrl_state
, pcc_id
, path
);
792 ret
= pcep_thread_event_sync_done(ctrl_state
, pcc_id
);
794 case EV_RESET_PCC_SESSION
:
795 pcc_state
= pcep_pcc_get_pcc_by_name(ctrl_state
->pcc
,
796 (const char *)payload
);
798 pcep_pcc_disable(ctrl_state
, pcc_state
);
799 ret
= pcep_pcc_enable(ctrl_state
, pcc_state
);
801 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR
,
802 "Cannot reset state for PCE: %s",
803 (const char *)payload
);
807 assert(payload
!= NULL
);
808 path
= (struct path
*)payload
;
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
);
820 pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
821 pcep_pcc_send_report(ctrl_state
, pcc_state
, path
,
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
);
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
,
838 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR
,
839 "Unexpected event received in controller thread: %u",
847 int pcep_thread_event_update_pcc_options(struct ctrl_state
*ctrl_state
,
848 struct pcc_opts
*opts
)
850 assert(opts
!= NULL
);
851 if (ctrl_state
->pcc_opts
!= NULL
) {
852 XFREE(MTYPE_PCEP
, ctrl_state
->pcc_opts
);
854 ctrl_state
->pcc_opts
= opts
;
858 int pcep_thread_event_update_pce_options(struct ctrl_state
*ctrl_state
,
859 int pcc_id
, struct pce_opts
*pce_opts
)
861 if (!pce_opts
|| !ctrl_state
) {
864 struct pcc_state
*pcc_state
;
865 struct pcc_opts
*pcc_opts
;
868 pcep_pcc_get_pcc_id_by_ip_port(ctrl_state
->pcc
, pce_opts
);
869 if (current_pcc_id
) {
871 pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, current_pcc_id
);
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
);
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
));
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");
894 int pcep_thread_event_remove_pcc_by_id(struct ctrl_state
*ctrl_state
,
898 struct pcc_state
*pcc_state
=
899 pcep_pcc_get_pcc_by_id(ctrl_state
->pcc
, pcc_id
);
901 remove_pcc_state(ctrl_state
, pcc_state
);
902 pcep_pcc_finalize(ctrl_state
, pcc_state
);
908 int pcep_thread_event_remove_pcc_all(struct ctrl_state
*ctrl_state
)
910 assert(ctrl_state
!= NULL
);
912 for (int i
= 0; i
< MAX_PCC
; i
++) {
913 pcep_thread_event_remove_pcc_by_id(
915 pcep_pcc_get_pcc_id_by_idx(ctrl_state
->pcc
, i
));
920 int pcep_thread_event_remove_pcc(struct ctrl_state
*ctrl_state
,
921 struct pce_opts
*pce_opts
)
923 assert(ctrl_state
!= NULL
);
926 int pcc_id
= pcep_pcc_get_pcc_id_by_ip_port(ctrl_state
->pcc
,
929 pcep_thread_event_remove_pcc_by_id(ctrl_state
, pcc_id
);
933 XFREE(MTYPE_PCEP
, pce_opts
);
935 pcep_thread_event_remove_pcc_all(ctrl_state
);
941 int pcep_thread_event_sync_path(struct ctrl_state
*ctrl_state
, int pcc_id
,
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
);
951 int pcep_thread_event_sync_done(struct ctrl_state
*ctrl_state
, int pcc_id
)
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
);
959 int pcep_thread_event_pathd_event(struct ctrl_state
*ctrl_state
,
960 enum pcep_pathd_event_type type
,
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
,
973 pcep_free_path(path
);
979 /* ------------ Main Thread Event Handler ------------ */
981 int send_to_main(struct ctrl_state
*ctrl_state
, int pcc_id
,
982 enum pcep_main_event_type type
, void *payload
)
984 struct pcep_main_event_data
*data
;
986 data
= XCALLOC(MTYPE_PCEP
, sizeof(*data
));
987 data
->handler
= ctrl_state
->main_event_handler
;
989 data
->pcc_id
= pcc_id
;
990 data
->payload
= payload
;
992 thread_add_event(ctrl_state
->main
, pcep_main_event_handler
,
993 (void *)data
, 0, NULL
);
997 int pcep_main_event_handler(struct thread
*thread
)
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
);
1008 return handler(type
, pcc_id
, payload
);
1012 /* ------------ Helper functions ------------ */
1014 void set_ctrl_state(struct frr_pthread
*fpt
, struct ctrl_state
*ctrl_state
)
1016 assert(fpt
!= NULL
);
1017 fpt
->data
= ctrl_state
;
1020 struct ctrl_state
*get_ctrl_state(struct frr_pthread
*fpt
)
1022 assert(fpt
!= NULL
);
1023 assert(fpt
->data
!= NULL
);
1025 struct ctrl_state
*ctrl_state
;
1026 ctrl_state
= (struct ctrl_state
*)fpt
->data
;
1027 assert(ctrl_state
!= NULL
);
1031 int get_next_id(struct ctrl_state
*ctrl_state
)
1033 return ++ctrl_state
->pcc_last_id
;
1036 int set_pcc_state(struct ctrl_state
*ctrl_state
, struct pcc_state
*pcc_state
)
1038 assert(ctrl_state
!= NULL
);
1039 assert(pcep_pcc_get_pcc_id(pcc_state
) != 0);
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
);
1049 PCEP_DEBUG("Max number of pce ");
1054 void remove_pcc_state(struct ctrl_state
*ctrl_state
,
1055 struct pcc_state
*pcc_state
)
1057 assert(ctrl_state
!= NULL
);
1058 assert(pcep_pcc_get_pcc_id(pcc_state
) != 0);
1061 idx
= pcep_pcc_get_pcc_idx_by_id(ctrl_state
->pcc
,
1062 pcep_pcc_get_pcc_id(pcc_state
));
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
));
1071 uint32_t backoff_delay(uint32_t max
, uint32_t base
, uint32_t retry_count
)
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
;
1079 const char *timer_type_name(enum pcep_ctrl_timer_type type
)
1084 case TM_RECONNECT_PCC
:
1085 return "RECONNECT_PCC";
1086 case TM_PCEPLIB_TIMER
:
1087 return "PCEPLIB_TIMER";
1095 const char *timeout_type_name(enum pcep_ctrl_timeout_type type
)
1100 case TO_COMPUTATION_REQUEST
:
1101 return "COMPUTATION_REQUEST";