diff --git a/pathd/path_pcep.c b/pathd/path_pcep.c index 0d03805ba3b8..6779bd4af320 100644 --- a/pathd/path_pcep.c +++ b/pathd/path_pcep.c @@ -644,10 +644,10 @@ int pcep_module_late_init(struct thread_master *tm) struct frr_pthread *fpt; - if (pcep_lib_initialize()) + if (pcep_ctrl_initialize(tm, &fpt, pcep_main_event_handler)) return 1; - if (pcep_ctrl_initialize(tm, &fpt, pcep_main_event_handler)) + if (pcep_lib_initialize(fpt)) return 1; pcep_g->master = tm; diff --git a/pathd/path_pcep_controller.c b/pathd/path_pcep_controller.c index 6b5411c28d51..bc50442b4c57 100644 --- a/pathd/path_pcep_controller.c +++ b/pathd/path_pcep_controller.c @@ -33,7 +33,6 @@ #include "pathd/path_pcep.h" #include "pathd/path_pcep_controller.h" #include "pathd/path_pcep_pcc.h" -#include "pathd/path_pcep_lib.h" #include "pathd/path_pcep_nb.h" #include "pathd/path_pcep_debug.h" @@ -74,17 +73,6 @@ struct pcep_main_event_data { void *payload; }; -/* Timer handling data structures */ - -enum pcep_ctrl_timer_type { TM_POLL = 1, TM_RECONNECT_PCC }; - -struct pcep_ctrl_timer_data { - struct ctrl_state *ctrl_state; - enum pcep_ctrl_timer_type type; - int pcc_id; - void *payload; -}; - /* Synchronous call arguments */ struct get_counters_args { @@ -110,12 +98,21 @@ static int pcep_thread_get_counters_callback(struct thread *t); static int pcep_thread_send_report_callback(struct thread *t); /* Controller Thread Timer Handler */ -static int schedule_thread(struct ctrl_state *ctrl_state, int pcc_id, - enum pcep_ctrl_timer_type type, uint32_t delay, - void *payload, struct thread **thread); +static int schedule_thread_timer(struct ctrl_state *ctrl_state, int pcc_id, + enum pcep_ctrl_timer_type type, uint32_t delay, + void *payload, struct thread **thread); +static int schedule_thread_timer_with_cb(struct ctrl_state *ctrl_state, + int pcc_id, enum pcep_ctrl_timer_type type, uint32_t delay, + void *payload, struct thread **thread, pcep_ctrl_thread_callback timer_cb); static int pcep_thread_timer_handler(struct thread *thread); static int pcep_thread_timer_poll(struct ctrl_state *ctrl_state); +/* Controller Thread Socket read/write Handler */ +static int schedule_thread_socket(struct ctrl_state *ctrl_state, int pcc_id, + enum pcep_ctrl_socket_type type, bool is_read, + void *payload, int fd, struct thread **thread, + pcep_ctrl_thread_callback cb); + /* Controller Thread Event Handler */ static int send_to_thread(struct ctrl_state *ctrl_state, int pcc_id, enum pcep_ctrl_event_type type, uint32_t sub_type, @@ -316,10 +313,39 @@ void pcep_thread_schedule_reconnect(struct ctrl_state *ctrl_state, int pcc_id, uint32_t delay = backoff_delay(MAX_RECONNECT_DELAY, 1, retry_count); PCEP_DEBUG("Schedule reconnection in %us (retry %u)", delay, retry_count); - schedule_thread(ctrl_state, pcc_id, TM_RECONNECT_PCC, delay, NULL, - thread); + schedule_thread_timer(ctrl_state, pcc_id, TM_RECONNECT_PCC, delay, NULL, + thread); +} + +void pcep_thread_schedule_pceplib_timer(struct ctrl_state *ctrl_state, + int delay, void *payload, struct thread **thread, + pcep_ctrl_thread_callback timer_cb) +{ + PCEP_DEBUG("Schedule pceplib timer for %us", delay); + schedule_thread_timer_with_cb( + ctrl_state, 0, TM_PCEPLIB_TIMER, delay, payload, thread, + timer_cb); } +void pcep_thread_cancel_pceplib_timer(struct thread **thread) +{ + PCEP_DEBUG("Cancel pceplib timer"); + + if (thread == NULL) { + return; + } + + struct pcep_ctrl_timer_data *data = THREAD_ARG(*thread); + if (data != NULL) { + XFREE(MTYPE_PCEP, data); + } + + if ((*thread)->master->owner == pthread_self()) { + thread_cancel(*thread); + } else { + thread_cancel_async((*thread)->master, thread, NULL); + } +} /* ------------ Internal Functions Called From Controller Thread ------------ */ @@ -351,8 +377,8 @@ int pcep_thread_finish_event_handler(struct thread *thread) void pcep_thread_schedule_poll(struct ctrl_state *ctrl_state) { assert(ctrl_state->t_poll == NULL); - schedule_thread(ctrl_state, 0, TM_POLL, POLL_INTERVAL, NULL, - &ctrl_state->t_poll); + schedule_thread_timer(ctrl_state, 0, TM_POLL, POLL_INTERVAL, NULL, + &ctrl_state->t_poll); } int pcep_thread_get_counters_callback(struct thread *t) @@ -397,9 +423,10 @@ int pcep_thread_send_report_callback(struct thread *t) /* ------------ Controller Thread Timer Handler ------------ */ -int schedule_thread(struct ctrl_state *ctrl_state, int pcc_id, - enum pcep_ctrl_timer_type type, uint32_t delay, - void *payload, struct thread **thread) +int schedule_thread_timer_with_cb(struct ctrl_state *ctrl_state, int pcc_id, + enum pcep_ctrl_timer_type type, uint32_t delay, + void *payload, struct thread **thread, + pcep_ctrl_thread_callback timer_cb) { assert(thread != NULL); @@ -411,12 +438,21 @@ int schedule_thread(struct ctrl_state *ctrl_state, int pcc_id, data->pcc_id = pcc_id; data->payload = payload; - thread_add_timer(ctrl_state->self, pcep_thread_timer_handler, + thread_add_timer(ctrl_state->self, timer_cb, (void *)data, delay, thread); return 0; } +int schedule_thread_timer(struct ctrl_state *ctrl_state, int pcc_id, + enum pcep_ctrl_timer_type type, uint32_t delay, + void *payload, struct thread **thread) +{ + return schedule_thread_timer_with_cb( + ctrl_state, pcc_id, type, delay, payload, thread, + pcep_thread_timer_handler); +} + int pcep_thread_timer_handler(struct thread *thread) { /* data unpacking */ @@ -448,7 +484,6 @@ int pcep_thread_timer_handler(struct thread *thread) return ret; } - int pcep_thread_timer_poll(struct ctrl_state *ctrl_state) { int i; @@ -473,6 +508,53 @@ int pcep_thread_timer_poll(struct ctrl_state *ctrl_state) return 0; } +/* ------------ Controller Thread Socket Functions ------------ */ + +int schedule_thread_socket(struct ctrl_state *ctrl_state, int pcc_id, + enum pcep_ctrl_socket_type type, bool is_read, + void *payload, int fd, struct thread **thread, + pcep_ctrl_thread_callback socket_cb) +{ + assert(thread != NULL); + + struct pcep_ctrl_socket_data *data; + + data = XCALLOC(MTYPE_PCEP, sizeof(*data)); + data->ctrl_state = ctrl_state; + data->type = type; + data->is_read = is_read; + data->fd = fd; + data->pcc_id = pcc_id; + data->payload = payload; + + if (is_read) { + thread_add_read(ctrl_state->self, socket_cb, + (void *)data, fd, thread); + } else { + thread_add_write(ctrl_state->self, socket_cb, + (void *)data, fd, thread); + } + + return 0; +} + +int pcep_thread_socket_write(void *fpt, void **thread, int fd, void *payload, + pcep_ctrl_thread_callback socket_cb) +{ + struct ctrl_state *ctrl_state = ((struct frr_pthread *)fpt)->data; + + return schedule_thread_socket(ctrl_state, 0, SOCK_PCEPLIB, false, + payload, fd, (struct thread **)thread, socket_cb); +} + +int pcep_thread_socket_read(void *fpt, void **thread, int fd, void *payload, + pcep_ctrl_thread_callback socket_cb) +{ + struct ctrl_state *ctrl_state = ((struct frr_pthread *)fpt)->data; + + return schedule_thread_socket(ctrl_state, 0, SOCK_PCEPLIB, true, + payload, fd, (struct thread **)thread, socket_cb); +} /* ------------ Controller Thread Event Handler ------------ */ diff --git a/pathd/path_pcep_controller.h b/pathd/path_pcep_controller.h index 711acb68d630..a6fe658a112b 100644 --- a/pathd/path_pcep_controller.h +++ b/pathd/path_pcep_controller.h @@ -49,6 +49,32 @@ struct ctrl_state { struct pcc_state *pcc[MAX_PCC]; }; +/* Timer handling data structures */ + +enum pcep_ctrl_timer_type { TM_POLL = 1, TM_RECONNECT_PCC, TM_PCEPLIB_TIMER }; + +struct pcep_ctrl_timer_data { + struct ctrl_state *ctrl_state; + enum pcep_ctrl_timer_type type; + int pcc_id; + void *payload; +}; + +/* Socket handling data structures */ + +enum pcep_ctrl_socket_type { SOCK_PCEPLIB = 1 }; + +struct pcep_ctrl_socket_data { + struct ctrl_state *ctrl_state; + enum pcep_ctrl_socket_type type; + bool is_read; + int fd; + int pcc_id; + void *payload; +}; + +typedef int (*pcep_ctrl_thread_callback)(struct thread *); + /* Functions called from the main thread */ int pcep_ctrl_initialize(struct thread_master *main_thread, struct frr_pthread **fpt, @@ -77,4 +103,13 @@ void pcep_thread_update_path(struct ctrl_state *ctrl_state, int pcc_id, void pcep_thread_schedule_reconnect(struct ctrl_state *ctrl_state, int pcc_id, int retry_count, struct thread **thread); +void pcep_thread_schedule_pceplib_timer(struct ctrl_state *ctrl_state, + int delay, void *payload, struct thread **thread, + pcep_ctrl_thread_callback cb); +void pcep_thread_cancel_pceplib_timer(struct thread **thread); +int pcep_thread_socket_read(void *fpt, void **thread, int fd, + void *payload, pcep_ctrl_thread_callback cb); +int pcep_thread_socket_write(void *fpt, void **thread, int fd, + void *payload, pcep_ctrl_thread_callback cb); + #endif // _PATH_PCEP_CONTROLLER_H_ diff --git a/pathd/path_pcep_lib.c b/pathd/path_pcep_lib.c index 6d0b6937c120..74037535d47d 100644 --- a/pathd/path_pcep_lib.c +++ b/pathd/path_pcep_lib.c @@ -19,6 +19,7 @@ #include #include +#include #include "pathd/path_errors.h" #include "pathd/path_memory.h" #include "pathd/path_pcep.h" @@ -31,6 +32,20 @@ /* pceplib logging callback */ static int pceplib_logging_cb(int level, const char *fmt, va_list args); +/* Timer callbacks */ +static void pcep_lib_pceplib_timer_create_cb(void *fpt, void **thread, + int delay, void *payload); +static void pcep_lib_pceplib_timer_cancel_cb(void **thread); +static int pcep_lib_timer_expire(struct thread *thread); + +/* Socket callbacks */ +static int pcep_lib_pceplib_socket_read_cb(void *fpt, void **thread, int fd, + void *payload); +static int pcep_lib_pceplib_socket_write_cb(void *fpt, void **thread, int fd, + void *payload); +static int pcep_lib_socket_read_ready(struct thread *thread); +static int pcep_lib_socket_write_ready(struct thread *thread); + /* Internal functions */ static double_linked_list *pcep_lib_format_path(struct path *path); static void pcep_lib_parse_open(struct pcep_caps *caps, @@ -54,28 +69,37 @@ static void free_counter(struct counter *counter); /* ------------ API Functions ------------ */ -int pcep_lib_initialize(void) +int pcep_lib_initialize(struct frr_pthread *fpt) { PCEP_DEBUG("Initializing pceplib"); + /* Register pceplib logging callback */ + register_logger(pceplib_logging_cb); + /* Its ok that this object goes out of scope, as it * wont be stored, and its values will be copied */ struct pceplib_infra_config infra = { + /* Memory infrastructure */ .pceplib_infra_mt = MTYPE_PCEPLIB_INFRA, .pceplib_messages_mt = MTYPE_PCEPLIB_MESSAGES, - .mfunc = (pceplib_malloc_func) qmalloc, - .cfunc = (pceplib_calloc_func) qcalloc, - .rfunc = (pceplib_realloc_func) qrealloc, - .sfunc = (pceplib_strdup_func) qstrdup, - .ffunc = (pceplib_free_func) qfree + .malloc_func = (pceplib_malloc_func)qmalloc, + .calloc_func = (pceplib_calloc_func)qcalloc, + .realloc_func = (pceplib_realloc_func)qrealloc, + .strdup_func = (pceplib_strdup_func)qstrdup, + .free_func = (pceplib_free_func)qfree, + /* Timers infrastructure */ + .external_infra_data = fpt, + .timer_create_func = pcep_lib_pceplib_timer_create_cb, + .timer_cancel_func = pcep_lib_pceplib_timer_cancel_cb, + /* Timers infrastructure */ + .socket_read_func = pcep_lib_pceplib_socket_read_cb, + .socket_write_func = pcep_lib_pceplib_socket_write_cb }; if (!initialize_pcc_infra(&infra)) { flog_err(EC_PATH_PCEP_PCC_INIT, "failed to initialize pceplib"); return 1; } - /* Register pceplib logging callback */ - register_logger(pceplib_logging_cb); return 0; } @@ -133,6 +157,86 @@ void pcep_lib_disconnect(pcep_session *sess) disconnect_pce(sess); } +/* Callback passed to pceplib to create a timer. + * When the timer expires, pcep_lib_timer_expire() will be called */ + +void pcep_lib_pceplib_timer_create_cb(void *fpt, void **thread, int delay, + void *payload) +{ + struct ctrl_state *ctrl_state = ((struct frr_pthread *) fpt)->data; + + pcep_thread_schedule_pceplib_timer( + ctrl_state, delay, payload, (struct thread **) thread, + pcep_lib_timer_expire); +} + +/* Callback passed to pceplib to cancel a timer */ + +void pcep_lib_pceplib_timer_cancel_cb(void **thread) +{ + pcep_thread_cancel_pceplib_timer((struct thread **)thread); +} + +/* Callback called by path_pcep_controller when a timer expires */ + +int pcep_lib_timer_expire(struct thread *thread) +{ + struct pcep_ctrl_timer_data *data = THREAD_ARG(thread); + assert(data != NULL); + + pceplib_external_timer_expire_handler(data->payload); + + XFREE(MTYPE_PCEP, data); + + return 0; +} + +/* Callback passed to pceplib to write to a socket. + * When the socket is ready to be written to, + * pcep_lib_socket_write_ready() will be called */ + +int pcep_lib_pceplib_socket_write_cb(void *fpt, void **thread, int fd, + void *payload) +{ + return pcep_thread_socket_write(fpt, thread, fd, payload, + pcep_lib_socket_write_ready); +} + +/* Callback passed to pceplib to read from a socket. + * When the socket is ready to be read from, + * pcep_lib_socket_read_ready() will be called */ + +int pcep_lib_pceplib_socket_read_cb(void *fpt, void **thread, int fd, + void *payload) +{ + return pcep_thread_socket_read(fpt, thread, fd, payload, + pcep_lib_socket_read_ready); +} + +/* Callbacks called by path_pcep_controller when a socket is ready to read/write */ + +int pcep_lib_socket_write_ready(struct thread *thread) +{ + struct pcep_ctrl_socket_data *data = THREAD_ARG(thread); + assert(data != NULL); + + int retval = pceplib_external_socket_write(data->fd, data->payload); + XFREE(MTYPE_PCEP, data); + + return retval; +} + +int pcep_lib_socket_read_ready(struct thread *thread) +{ + struct pcep_ctrl_socket_data *data = THREAD_ARG(thread); + assert(data != NULL); + + int retval = pceplib_external_socket_read(data->fd, data->payload); + XFREE(MTYPE_PCEP, data); + + return retval; +} + struct pcep_message *pcep_lib_format_report(struct path *path) { double_linked_list *objs = pcep_lib_format_path(path); @@ -294,7 +398,6 @@ int pceplib_logging_cb(int priority, const char *fmt, va_list args) return 0; } - /* ------------ Internal Functions ------------ */ double_linked_list *pcep_lib_format_path(struct path *path) diff --git a/pathd/path_pcep_lib.h b/pathd/path_pcep_lib.h index ac2bffb3f6c6..337106539bdd 100644 --- a/pathd/path_pcep_lib.h +++ b/pathd/path_pcep_lib.h @@ -22,9 +22,10 @@ #include #include +#include "frr_pthread.h" #include "pathd/path_pcep.h" -int pcep_lib_initialize(void); +int pcep_lib_initialize(struct frr_pthread *fpt); void pcep_lib_finalize(void); pcep_session *pcep_lib_connect(struct ipaddr *src_addr, int src_port, struct ipaddr *dst_addr, int dst_port,