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