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