Skip to content

Commit

Permalink
Plugin FRR socket infra into PCEPlib
Browse files Browse the repository at this point in the history
  • Loading branch information
Brady Johnson committed May 14, 2020
1 parent fc9850b commit 649958e
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 23 deletions.
122 changes: 112 additions & 10 deletions pathd/path_pcep_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ struct pcep_ctrl_timer_data {
void *payload;
};

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;
};

/* Synchronous call arguments */

struct get_counters_args {
Expand All @@ -110,12 +121,18 @@ 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,
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 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);
static int pcep_thread_socket_handler(struct thread *thread);

/* 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,
Expand Down Expand Up @@ -316,21 +333,35 @@ 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,
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_DEBUG("Schedule pceplib timer for %us", delay);
schedule_thread(ctrl_state, 0, TM_PCEPLIB_TIMER, delay, payload, thread);
schedule_thread_timer(ctrl_state, 0, TM_PCEPLIB_TIMER, delay, payload, thread);
}

void pcep_thread_cancel_pceplib_timer(struct thread *thread)
void pcep_thread_cancel_pceplib_timer(struct thread **thread)
{
PCEP_DEBUG("Cancel pceplib timer");
thread_cancel_async(thread->master, &thread, NULL);

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 ------------ */
Expand Down Expand Up @@ -363,7 +394,7 @@ 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,
schedule_thread_timer(ctrl_state, 0, TM_POLL, POLL_INTERVAL, NULL,
&ctrl_state->t_poll);
}

Expand Down Expand Up @@ -409,22 +440,22 @@ int pcep_thread_send_report_callback(struct thread *t)

/* ------------ Controller Thread Timer Handler ------------ */

int schedule_thread(struct ctrl_state *ctrl_state, int pcc_id,
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)
{
assert(thread != NULL);

struct pcep_ctrl_timer_data *data;

data = XCALLOC(MTYPE_PCEP, sizeof(*data));
data = XCALLOC(MTYPE_PCEP, sizeof(struct pcep_ctrl_timer_data));
data->ctrl_state = ctrl_state;
data->type = type;
data->pcc_id = pcc_id;
data->payload = payload;

thread_add_timer(ctrl_state->self, pcep_thread_timer_handler,
(void *)data, delay, thread);
(void *) data, delay, thread);

return 0;
}
Expand Down Expand Up @@ -464,7 +495,6 @@ int pcep_thread_timer_handler(struct thread *thread)
return ret;
}


int pcep_thread_timer_poll(struct ctrl_state *ctrl_state)
{
int i;
Expand All @@ -489,6 +519,78 @@ 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)
{
assert(thread != NULL);

struct pcep_ctrl_socket_data *data;

data = XCALLOC(MTYPE_PCEP, sizeof(struct pcep_ctrl_socket_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, pcep_thread_socket_handler,
(void *) data, fd, thread);
} else {
thread_add_write(ctrl_state->self, pcep_thread_socket_handler,
(void *) data, fd, thread);
}

return 0;
}

int pcep_thread_socket_handler(struct thread *thread)
{
/* data unpacking */
struct pcep_ctrl_socket_data *data = THREAD_ARG(thread);
assert(data != NULL);

struct ctrl_state *ctrl_state = data->ctrl_state;
assert(ctrl_state != NULL);

int retval = 0;
switch (data->type) {
case SOCK_PCEPLIB:
retval = pcep_lib_socket_ready(data->fd, data->is_read, data->payload);
break;

default:
flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
"Unknown controller socket event triggered: %u", data->type);
break;
}

XFREE(MTYPE_PCEP, data);

return retval;
}

int pcep_thread_socket_write(void *fpt, void **thread, int fd, void *payload)
{
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);
}

int pcep_thread_socket_read(void *fpt, void **thread, int fd, void *payload)
{
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);
}

/* ------------ Controller Thread Event Handler ------------ */

Expand Down
4 changes: 3 additions & 1 deletion pathd/path_pcep_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ void pcep_thread_schedule_reconnect(struct ctrl_state *ctrl_state, int pcc_id,

void pcep_thread_schedule_pceplib_timer(struct ctrl_state *ctrl_state,
int delay, void *payload, struct thread **thread);
void pcep_thread_cancel_pceplib_timer(struct thread *thread);
void pcep_thread_cancel_pceplib_timer(struct thread **thread);
int pcep_thread_socket_read(void *fpt, void **thread, int fd, void *payload);
int pcep_thread_socket_write(void *fpt, void **thread, int fd, void *payload);

#endif // _PATH_PCEP_CONTROLLER_H_
81 changes: 69 additions & 12 deletions pathd/path_pcep_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@
/* pceplib logging callback */
static int pceplib_logging_cb(int level, const char *fmt, va_list args);

static void *pcep_lib_pceplib_timer_create_cb(void *fpt, int delay, void *payload);
static void pcep_lib_pceplib_timer_cancel_cb(void *thread);
/* 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);

/* Socket callbacks */
int pcep_lib_pceplib_socket_read_cb(void *fpt, void **thread, int fd, void *payload);
int pcep_lib_pceplib_socket_write_cb(void *fpt, void **thread, int fd, void *payload);

/* Internal functions */
static double_linked_list *pcep_lib_format_path(struct path *path);
Expand Down Expand Up @@ -76,10 +81,17 @@ int pcep_lib_initialize(struct frr_pthread *fpt)
.realloc_func = (pceplib_realloc_func) qrealloc,
.strdup_func = (pceplib_strdup_func) qstrdup,
.free_func = (pceplib_free_func) qfree,
/* Timers infrastructure */
.external_timer_infra_data = fpt,
.timer_create_func = pcep_lib_pceplib_timer_create_cb,
.timer_cancel_func = pcep_lib_pceplib_timer_cancel_cb
/* Timers infrastructure */
.external_infra_data = fpt,
.timer_create_func = pcep_lib_pceplib_timer_create_cb,
.timer_cancel_func = pcep_lib_pceplib_timer_cancel_cb,
/*.timer_create_func = NULL,
.timer_cancel_func = NULL,*/
/* Timers infrastructure */
.socket_read_func = pcep_lib_pceplib_socket_read_cb,
.socket_write_func = pcep_lib_pceplib_socket_write_cb,
/*.socket_read_func = NULL,
.socket_write_func = NULL,*/
};
if (!initialize_pcc_infra(&infra)) {
flog_err(EC_PATH_PCEP_PCC_INIT, "failed to initialize pceplib");
Expand Down Expand Up @@ -143,26 +155,71 @@ void pcep_lib_disconnect(pcep_session *sess)
disconnect_pce(sess);
}

void *pcep_lib_pceplib_timer_create_cb(void *fpt, int delay, void *payload)
/* 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;
struct thread *thread = NULL;

pcep_thread_schedule_pceplib_timer(ctrl_state, delay, payload, &thread);
pcep_thread_schedule_pceplib_timer(ctrl_state, delay, payload, thread);

struct thread *t = (struct thread *) *thread;
flog_err(EC_PATH_PCEP_PCC_INIT,
"pcep_lib_pceplib_timer_create_cb() thread [%p] thread->master [%p] thread->master->owner [%ld]",
t, t->master, t->master->owner);

return thread;
return thread;
}

void pcep_lib_pceplib_timer_cancel_cb(void *thread)
/* Callback passed to pceplib to cancel a timer */

void pcep_lib_pceplib_timer_cancel_cb(void **thread)
{
pcep_thread_cancel_pceplib_timer(thread);
struct thread *t = (struct thread *) *thread;
flog_err(EC_PATH_PCEP_PCC_INIT,
"pcep_lib_pceplib_timer_cancel_cb() thread [%p] thread->master [%p] thread->master->owner [%ld]",
t, t->master, (t->master == NULL ? 0 : t->master->owner));

pcep_thread_cancel_pceplib_timer((struct thread **) thread);
}

/* Called by path_pcep_controller when a timer expires */

void pcep_lib_timer_expire(void *payload)
{
pceplib_external_timer_expire_handler(payload);
}

/* Callback passed to pceplib to write to a socket.
* When the socket is ready to be written to,
* pcep_lib_socket_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);
}

/* Callback passed to pceplib to read from a socket.
* When the socket is ready to be read from,
* pcep_lib_socket_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);
}

/* Called by path_pcep_controller when a socket is ready to read/write */

int pcep_lib_socket_ready(int fd, bool is_read, void *payload)
{
if (is_read) {
return pceplib_external_socket_read(fd, payload);
} else {
return pceplib_external_socket_write(fd, payload);
}
}

struct pcep_message *pcep_lib_format_report(struct path *path)
{
double_linked_list *objs = pcep_lib_format_path(path);
Expand Down
1 change: 1 addition & 0 deletions pathd/path_pcep_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ void pcep_lib_parse_capabilities(struct pcep_message *msg,
struct counters_group *pcep_lib_copy_counters(pcep_session *sess);
void pcep_lib_free_counters(struct counters_group *counters);
void pcep_lib_timer_expire(void *payload);
int pcep_lib_socket_ready(int fd, bool is_read, void *payload);

#endif // _PATH_PCEP_LIB_H_

0 comments on commit 649958e

Please sign in to comment.