diff options
Diffstat (limited to 'pathd')
-rw-r--r-- | pathd/path_pcep.c | 25 | ||||
-rw-r--r-- | pathd/path_pcep.h | 4 | ||||
-rw-r--r-- | pathd/path_pcep_cli.c | 22 | ||||
-rw-r--r-- | pathd/path_pcep_config.c | 25 | ||||
-rw-r--r-- | pathd/path_pcep_config.h | 9 | ||||
-rw-r--r-- | pathd/path_pcep_controller.c | 227 | ||||
-rw-r--r-- | pathd/path_pcep_controller.h | 22 | ||||
-rw-r--r-- | pathd/path_pcep_debug.c | 4 | ||||
-rw-r--r-- | pathd/path_pcep_debug.h | 4 | ||||
-rw-r--r-- | pathd/path_pcep_lib.c | 14 | ||||
-rw-r--r-- | pathd/path_pcep_lib.h | 2 | ||||
-rw-r--r-- | pathd/path_pcep_pcc.c | 73 | ||||
-rw-r--r-- | pathd/path_pcep_pcc.h | 9 | ||||
-rw-r--r-- | pathd/subdir.am | 13 |
14 files changed, 254 insertions, 199 deletions
diff --git a/pathd/path_pcep.c b/pathd/path_pcep.c index 2f9ff4f0f..8b5ca8aff 100644 --- a/pathd/path_pcep.c +++ b/pathd/path_pcep.c @@ -17,7 +17,7 @@ */ #include <zebra.h> -#include <pcep_utils_counters.h> +#include "pceplib/pcep_utils_counters.h" #include "log.h" #include "command.h" @@ -215,29 +215,10 @@ int pcep_main_event_update_candidate(struct path *path) ret = path_pcep_config_update_path(path); if (ret != PATH_NB_ERR && path->srp_id != 0) { - /* ODL and Cisco requires the first reported - * LSP to have a DOWN status, the later status changes - * will be comunicated through hook calls. - */ - enum pcep_lsp_operational_status real_status; if ((resp = path_pcep_config_get_path(&path->nbkey))) { resp->srp_id = path->srp_id; - real_status = resp->status; - resp->status = PCEP_LSP_OPERATIONAL_DOWN; - pcep_ctrl_send_report(pcep_g->fpt, path->pcc_id, resp); - /* If the update did not have any effect and the real - * status is not DOWN, we need to send a second report - * so the PCE is aware of the real status. This is due - * to the fact that NO notification will be received - * if the update did not apply any changes */ - if ((ret == PATH_NB_NO_CHANGE) - && (real_status != PCEP_LSP_OPERATIONAL_DOWN)) { - resp->status = real_status; - resp->srp_id = 0; - pcep_ctrl_send_report(pcep_g->fpt, path->pcc_id, - resp); - } - pcep_free_path(resp); + pcep_ctrl_send_report(pcep_g->fpt, path->pcc_id, resp, + ret == PATH_NB_NO_CHANGE); } } return ret; diff --git a/pathd/path_pcep.h b/pathd/path_pcep.h index 1896c265c..b131b3144 100644 --- a/pathd/path_pcep.h +++ b/pathd/path_pcep.h @@ -22,8 +22,8 @@ #include <stdbool.h> #include <debug.h> #include <netinet/tcp.h> -#include <pcep_utils_logging.h> -#include <pcep_pcc_api.h> +#include "pceplib/pcep_utils_logging.h" +#include "pceplib/pcep_pcc_api.h" #include "mpls.h" #include "pathd/pathd.h" #include "pathd/path_pcep_memory.h" diff --git a/pathd/path_pcep_cli.c b/pathd/path_pcep_cli.c index add3391f2..7bbed9464 100644 --- a/pathd/path_pcep_cli.c +++ b/pathd/path_pcep_cli.c @@ -18,8 +18,8 @@ */ #include <zebra.h> -#include <pcep_utils_counters.h> -#include <pcep_session_logic.h> +#include "pceplib/pcep_utils_counters.h" +#include "pceplib/pcep_session_logic.h" #include "log.h" #include "command.h" @@ -321,8 +321,9 @@ pcep_cli_merge_pcep_pce_config_options(struct pce_opts_cli *pce_opts_cli) default_pcep_config_group_opts_g.tcp_md5_auth; } } - strncpy(pce_opts_cli->pce_opts.config_opts.tcp_md5_auth, - tcp_md5_auth_str, TCP_MD5SIG_MAXKEYLEN); + strlcpy(pce_opts_cli->pce_opts.config_opts.tcp_md5_auth, + tcp_md5_auth_str, + sizeof(pce_opts_cli->pce_opts.config_opts.tcp_md5_auth)); struct ipaddr *source_ip = &pce_opts_cli->pce_config_group_opts.source_ip; @@ -525,8 +526,9 @@ static int path_pcep_cli_show_srte_pcep_counters(struct vty *vty) tm_info = localtime(&group->start_time); strftime(tm_buffer, sizeof(tm_buffer), "%Y-%m-%d %H:%M:%S", tm_info); - vty_out(vty, "PCEP counters since %s (%luh %lum %lus):\n", tm_buffer, - diff_time / 3600, (diff_time / 60) % 60, diff_time % 60); + vty_out(vty, "PCEP counters since %s (%uh %um %us):\n", tm_buffer, + (uint32_t)(diff_time / 3600), (uint32_t)((diff_time / 60) % 60), + (uint32_t)(diff_time % 60)); /* Prepare table. */ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); @@ -815,7 +817,8 @@ static int path_pcep_cli_peer_tcp_md5_auth(struct vty *vty, return CMD_ERR_NO_MATCH; } - strncpy(pce_config->tcp_md5_auth, tcp_md5_auth, TCP_MD5SIG_MAXKEYLEN); + strlcpy(pce_config->tcp_md5_auth, tcp_md5_auth, + sizeof(pce_config->tcp_md5_auth)); return CMD_SUCCESS; } @@ -1220,8 +1223,9 @@ static void print_pcep_session(struct vty *vty, struct pce_opts *pce_opts, localtime_r(¤t_time, <); gmtime_r(&session->time_connected, <); vty_out(vty, - " Connected for %ld seconds, since %d-%02d-%02d %02d:%02d:%02d UTC\n", - (current_time - session->time_connected), + " Connected for %u seconds, since %d-%02d-%02d %02d:%02d:%02d UTC\n", + (uint32_t)(current_time + - session->time_connected), lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec); } diff --git a/pathd/path_pcep_config.c b/pathd/path_pcep_config.c index 989223ebc..107475bec 100644 --- a/pathd/path_pcep_config.c +++ b/pathd/path_pcep_config.c @@ -19,7 +19,7 @@ #include <northbound.h> #include <yang.h> #include <printfrr.h> -#include <pcep-objects.h> +#include "pceplib/pcep_msg_objects.h" #include "pathd/pathd.h" #include "pathd/path_pcep.h" #include "pathd/path_pcep_config.h" @@ -45,14 +45,13 @@ status_int_to_ext(enum srte_policy_status status); static enum pcep_sr_subobj_nai pcep_nai_type(enum srte_segment_nai_type type); static enum srte_segment_nai_type srte_nai_type(enum pcep_sr_subobj_nai type); -static int path_pcep_config_lookup_cb(struct thread *t) +void path_pcep_refine_path(struct path *path) { - struct path *path = THREAD_ARG(t); struct srte_candidate *candidate = lookup_candidate(&path->nbkey); struct srte_lsp *lsp; if (candidate == NULL) - return 0; + return; lsp = candidate->lsp; @@ -65,16 +64,6 @@ static int path_pcep_config_lookup_cb(struct thread *t) if ((path->update_origin == SRTE_ORIGIN_UNDEFINED) && (lsp->segment_list != NULL)) path->update_origin = lsp->segment_list->protocol_origin; - - return 0; -} - -void path_pcep_config_lookup(struct path *path) -{ - /* - * Configuration access is strictly done via the main thread - */ - thread_execute(master, path_pcep_config_lookup_cb, path, 0); } struct path *path_pcep_config_get_path(struct lsp_nb_key *key) @@ -346,9 +335,11 @@ int path_pcep_config_update_path(struct path *path) SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED); for (metric = path->first_metric; metric != NULL; metric = metric->next) - srte_lsp_set_metric(candidate->lsp, metric->type, metric->value, - metric->enforce, metric->is_bound, - metric->is_computed); + srte_lsp_set_metric( + candidate->lsp, + (enum srte_candidate_metric_type)metric->type, + metric->value, metric->enforce, metric->is_bound, + metric->is_computed); if (path->has_bandwidth) srte_lsp_set_bandwidth(candidate->lsp, path->bandwidth, diff --git a/pathd/path_pcep_config.h b/pathd/path_pcep_config.h index de29ab29c..223dd10c8 100644 --- a/pathd/path_pcep_config.h +++ b/pathd/path_pcep_config.h @@ -31,10 +31,11 @@ typedef int (*path_list_cb_t)(struct path *path, void *arg); /* Lookup the candidate path and fill up the missing path attributes like name - and type. Used for path generated from PCEP message received from the PCE - so they contains more information about the candidate path. If no matching - policy or candidate path is found, nothing is changed */ -void path_pcep_config_lookup(struct path *path); + * and type. Used for path generated from PCEP message received from the PCE + * so they contains more information about the candidate path. If no matching + * policy or candidate path is found, nothing is changed. + * MUST BE CALLED FROM THE MAIN THREAD */ +void path_pcep_refine_path(struct path *path); struct path *path_pcep_config_get_path(struct lsp_nb_key *key); void path_pcep_config_list_path(path_list_cb_t cb, void *arg); int path_pcep_config_update_path(struct path *path); diff --git a/pathd/path_pcep_controller.c b/pathd/path_pcep_controller.c index f4871a4d8..db7d2b55a 100644 --- a/pathd/path_pcep_controller.c +++ b/pathd/path_pcep_controller.c @@ -55,7 +55,9 @@ enum pcep_ctrl_event_type { EV_SYNC_PATH, EV_SYNC_DONE, EV_PCEPLIB_EVENT, - EV_RESET_PCC_SESSION + EV_RESET_PCC_SESSION, + EV_SEND_REPORT, + EV_PATH_REFINED }; struct pcep_ctrl_event_data { @@ -73,18 +75,20 @@ struct pcep_main_event_data { void *payload; }; -/* Synchronous call arguments */ - -struct get_counters_args { +struct pcep_refine_path_event_data { struct ctrl_state *ctrl_state; int pcc_id; - struct counters_group *counters; + pcep_refine_callback_t continue_lsp_update_handler; + struct path *path; + void *payload; }; -struct send_report_args { +/* Synchronous call arguments */ + +struct get_counters_args { struct ctrl_state *ctrl_state; int pcc_id; - struct path *path; + struct counters_group *counters; }; struct get_pcep_session_args { @@ -95,13 +99,10 @@ struct get_pcep_session_args { /* Internal Functions Called From Main Thread */ static int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res); +static int pcep_refine_path_event_cb(struct thread *thread); /* Internal Functions Called From Controller Thread */ static int pcep_thread_finish_event_handler(struct thread *thread); -static int pcep_thread_get_counters_callback(struct thread *t); -static int pcep_thread_send_report_callback(struct thread *t); -static int pcep_thread_get_pcep_session_callback(struct thread *t); -static int pcep_thread_get_pcc_info_callback(struct thread *t); /* Controller Thread Timer Handler */ static int schedule_thread_timer(struct ctrl_state *ctrl_state, int pcc_id, @@ -148,6 +149,9 @@ static int pcep_thread_event_sync_done(struct ctrl_state *ctrl_state, static int pcep_thread_event_pathd_event(struct ctrl_state *ctrl_state, enum pcep_pathd_event_type type, struct path *path); +static void +pcep_thread_path_refined_event(struct ctrl_state *ctrl_state, + struct pcep_refine_path_event_data *data); /* Main Thread Event Handler */ static int send_to_main(struct ctrl_state *ctrl_state, int pcc_id, @@ -280,48 +284,50 @@ struct counters_group *pcep_ctrl_get_counters(struct frr_pthread *fpt, int pcc_id) { struct ctrl_state *ctrl_state = get_ctrl_state(fpt); - struct get_counters_args args = { - .ctrl_state = ctrl_state, .pcc_id = pcc_id, .counters = NULL}; - thread_execute(ctrl_state->self, pcep_thread_get_counters_callback, - &args, 0); - return args.counters; + struct counters_group *counters = NULL; + struct pcc_state *pcc_state; + pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id); + if (pcc_state) { + counters = pcep_lib_copy_counters(pcc_state->sess); + } + return counters; } pcep_session *pcep_ctrl_get_pcep_session(struct frr_pthread *fpt, int pcc_id) { struct ctrl_state *ctrl_state = get_ctrl_state(fpt); - struct get_pcep_session_args args = {.ctrl_state = ctrl_state, - .pcc_id = pcc_id, - .pcep_session = NULL}; - thread_execute(ctrl_state->self, pcep_thread_get_pcep_session_callback, - &args, 0); - return args.pcep_session; + struct pcc_state *pcc_state; + pcep_session *session = NULL; + + pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id); + if (pcc_state) { + session = pcep_lib_copy_pcep_session(pcc_state->sess); + } + return session; } struct pcep_pcc_info *pcep_ctrl_get_pcc_info(struct frr_pthread *fpt, const char *pce_name) { struct ctrl_state *ctrl_state = get_ctrl_state(fpt); - struct pcep_pcc_info *args = XCALLOC(MTYPE_PCEP, sizeof(*args)); - args->ctrl_state = ctrl_state; - strncpy(args->pce_name, pce_name, sizeof(args->pce_name)); - thread_execute(ctrl_state->self, pcep_thread_get_pcc_info_callback, - args, 0); + struct pcep_pcc_info *pcc_info = XCALLOC(MTYPE_PCEP, sizeof(*pcc_info)); + if( pcc_info && ctrl_state){ + strlcpy(pcc_info->pce_name, pce_name, sizeof(pcc_info->pce_name)); + pcep_pcc_copy_pcc_info(ctrl_state->pcc, pcc_info); + } - return args; + return pcc_info; } -void pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id, - struct path *path) +int pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id, + struct path *path, bool is_stable) { - /* Sends a report stynchronously */ struct ctrl_state *ctrl_state = get_ctrl_state(fpt); - struct send_report_args args = { - .ctrl_state = ctrl_state, .pcc_id = pcc_id, .path = path}; - thread_execute(ctrl_state->self, pcep_thread_send_report_callback, - &args, 0); + return send_to_thread(ctrl_state, pcc_id, EV_SEND_REPORT, is_stable, + path); } + /* ------------ Internal Functions Called from Main Thread ------------ */ int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res) @@ -333,6 +339,20 @@ int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res) return 0; } +int pcep_refine_path_event_cb(struct thread *thread) +{ + struct pcep_refine_path_event_data *data = THREAD_ARG(thread); + assert(data != NULL); + struct ctrl_state *ctrl_state = data->ctrl_state; + struct path *path = data->path; + assert(path != NULL); + int pcc_id = data->pcc_id; + + + path_pcep_refine_path(path); + return send_to_thread(ctrl_state, pcc_id, EV_PATH_REFINED, 0, data); +} + /* ------------ API Functions Called From Controller Thread ------------ */ @@ -442,6 +462,41 @@ int pcep_thread_pcc_count(struct ctrl_state *ctrl_state) return ctrl_state->pcc_count; } +int pcep_thread_refine_path(struct ctrl_state *ctrl_state, int pcc_id, + pcep_refine_callback_t cb, struct path *path, + void *payload) +{ + struct pcep_refine_path_event_data *data; + + data = XCALLOC(MTYPE_PCEP, sizeof(*data)); + data->ctrl_state = ctrl_state; + data->path = path; + data->pcc_id = pcc_id; + data->continue_lsp_update_handler = cb; + data->payload = payload; + + thread_add_event(ctrl_state->main, pcep_refine_path_event_cb, + (void *)data, 0, NULL); + return 0; +} + +void pcep_thread_path_refined_event(struct ctrl_state *ctrl_state, + struct pcep_refine_path_event_data *data) +{ + assert(data != NULL); + int pcc_id = data->pcc_id; + pcep_refine_callback_t continue_lsp_update_handler = data->continue_lsp_update_handler; + assert(continue_lsp_update_handler != NULL); + struct path *path = data->path; + void *payload = data->payload; + struct pcc_state *pcc_state = NULL; + XFREE(MTYPE_PCEP, data); + + pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id); + continue_lsp_update_handler(ctrl_state, pcc_state, path, payload); +} + + /* ------------ Internal Functions Called From Controller Thread ------------ */ int pcep_thread_finish_event_handler(struct thread *thread) @@ -467,78 +522,6 @@ int pcep_thread_finish_event_handler(struct thread *thread) return 0; } -int pcep_thread_get_counters_callback(struct thread *t) -{ - struct get_counters_args *args = THREAD_ARG(t); - assert(args != NULL); - struct ctrl_state *ctrl_state = args->ctrl_state; - assert(ctrl_state != NULL); - struct pcc_state *pcc_state; - - pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, args->pcc_id); - if (pcc_state) { - args->counters = pcep_lib_copy_counters(pcc_state->sess); - } else { - args->counters = NULL; - } - - return 0; -} - -int pcep_thread_send_report_callback(struct thread *t) -{ - struct send_report_args *args = THREAD_ARG(t); - assert(args != NULL); - struct ctrl_state *ctrl_state = args->ctrl_state; - assert(ctrl_state != NULL); - struct pcc_state *pcc_state; - - if (args->pcc_id == 0) { - for (int i = 0; i < MAX_PCC; i++) { - if (ctrl_state->pcc[i]) { - pcep_pcc_send_report(ctrl_state, - ctrl_state->pcc[i], - args->path); - } - } - } else { - pcc_state = - pcep_pcc_get_pcc_by_id(ctrl_state->pcc, args->pcc_id); - pcep_pcc_send_report(ctrl_state, pcc_state, args->path); - } - - return 0; -} - -int pcep_thread_get_pcep_session_callback(struct thread *t) -{ - struct get_pcep_session_args *args = THREAD_ARG(t); - assert(args != NULL); - struct ctrl_state *ctrl_state = args->ctrl_state; - assert(ctrl_state != NULL); - struct pcc_state *pcc_state; - - pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, args->pcc_id); - if (pcc_state) { - args->pcep_session = - pcep_lib_copy_pcep_session(pcc_state->sess); - } - - return 0; -} - -int pcep_thread_get_pcc_info_callback(struct thread *t) -{ - struct pcep_pcc_info *args = THREAD_ARG(t); - assert(args != NULL); - struct ctrl_state *ctrl_state = args->ctrl_state; - assert(ctrl_state != NULL); - - pcep_pcc_copy_pcc_info(ctrl_state->pcc, args); - - return 0; -} - /* ------------ Controller Thread Timer Handler ------------ */ int schedule_thread_timer_with_cb(struct ctrl_state *ctrl_state, int pcc_id, @@ -752,11 +735,14 @@ int pcep_thread_event_handler(struct thread *thread) /* Possible sub-type values */ enum pcep_pathd_event_type path_event_type = PCEP_PATH_UNDEFINED; - /* Possible payload values */ + /* Possible payload values, maybe an union would be better... */ struct path *path = NULL; struct pcc_opts *pcc_opts = NULL; struct pce_opts *pce_opts = NULL; struct pcc_state *pcc_state = NULL; + struct pcep_refine_path_event_data *refine_data = NULL; + + struct path *path_copy = NULL; switch (type) { case EV_UPDATE_PCC_OPTS: @@ -808,6 +794,30 @@ int pcep_thread_event_handler(struct thread *thread) (const char *)payload); } break; + case EV_SEND_REPORT: + assert(payload != NULL); + path = (struct path *)payload; + if (pcc_id == 0) { + for (int i = 0; i < MAX_PCC; i++) { + if (ctrl_state->pcc[i]) { + path_copy = pcep_copy_path(path); + pcep_pcc_send_report( + ctrl_state, ctrl_state->pcc[i], + path_copy, (bool)sub_type); + } + } + } else { + pcc_state = + pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id); + pcep_pcc_send_report(ctrl_state, pcc_state, path, + (bool)sub_type); + } + break; + case EV_PATH_REFINED: + assert(payload != NULL); + refine_data = (struct pcep_refine_path_event_data *)payload; + pcep_thread_path_refined_event(ctrl_state, refine_data); + break; default: flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR, "Unexpected event received in controller thread: %u", @@ -984,6 +994,7 @@ int pcep_main_event_handler(struct thread *thread) /* ------------ Helper functions ------------ */ + void set_ctrl_state(struct frr_pthread *fpt, struct ctrl_state *ctrl_state) { assert(fpt != NULL); diff --git a/pathd/path_pcep_controller.h b/pathd/path_pcep_controller.h index f6eaa0ca2..1b7c3a4c7 100644 --- a/pathd/path_pcep_controller.h +++ b/pathd/path_pcep_controller.h @@ -21,16 +21,21 @@ #include "pathd/path_pcep.h" +struct ctrl_state; +struct pcc_state; enum pcep_main_event_type { PCEP_MAIN_EVENT_UNDEFINED = 0, PCEP_MAIN_EVENT_START_SYNC, PCEP_MAIN_EVENT_UPDATE_CANDIDATE, - PCEP_MAIN_EVENT_REMOVE_CANDIDATE_LSP + PCEP_MAIN_EVENT_REMOVE_CANDIDATE_LSP, }; typedef int (*pcep_main_event_handler_t)(enum pcep_main_event_type type, int pcc_id, void *payload); +typedef void (*pcep_refine_callback_t)(struct ctrl_state *ctrl_state, + struct pcc_state *pcc_state, + struct path *path, void *payload); enum pcep_pathd_event_type { PCEP_PATH_UNDEFINED = 0, @@ -124,10 +129,13 @@ pcep_session *pcep_ctrl_get_pcep_session(struct frr_pthread *fpt, int pcc_id); struct pcep_pcc_info *pcep_ctrl_get_pcc_info(struct frr_pthread *fpt, const char *pce_name); -/* Synchronously send a report, the caller is responsible to free the path, - * If `pcc_id` is `0` the report is sent by all PCCs */ -void pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id, - struct path *path); +/* Asynchronously send a report. The caller is giving away the path structure, + * it shouldn't be allocated on the stack. If `pcc_id` is `0` the report is + * sent by all PCCs. The parameter is_stable is used to hint wether the status + * will soon change, this is used to ensure all report updates are sent even + * when missing status update events */ +int pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id, + struct path *path, bool is_stable); /* Functions called from the controller thread */ void pcep_thread_start_sync(struct ctrl_state *ctrl_state, int pcc_id); @@ -162,5 +170,9 @@ int pcep_thread_send_ctrl_event(void *fpt, void *payload, pcep_ctrl_thread_callback cb); int pcep_thread_pcep_event(struct thread *thread); int pcep_thread_pcc_count(struct ctrl_state *ctrl_state); +/* Called by the PCC to refine a path in the main thread */ +int pcep_thread_refine_path(struct ctrl_state *ctrl_state, int pcc_id, + pcep_refine_callback_t cb, struct path *path, + void *payload); #endif // _PATH_PCEP_CONTROLLER_H_ diff --git a/pathd/path_pcep_debug.c b/pathd/path_pcep_debug.c index bcaadfe4d..2dfe2130b 100644 --- a/pathd/path_pcep_debug.c +++ b/pathd/path_pcep_debug.c @@ -636,8 +636,8 @@ const char *pcep_message_type_name(enum pcep_message_types pcep_message_type) return "UPDATE"; case PCEP_TYPE_INITIATE: return "INITIATE"; - case PCEP_TYPE_UNKOWN_MSG: - return "UNKOWN_MSG"; + case PCEP_TYPE_START_TLS: + return "START_TLS"; default: return "UNKNOWN"; } diff --git a/pathd/path_pcep_debug.h b/pathd/path_pcep_debug.h index 68b29ab65..5a504e4e1 100644 --- a/pathd/path_pcep_debug.h +++ b/pathd/path_pcep_debug.h @@ -20,8 +20,8 @@ #define _PATH_PCEP_DEBUG_H_ #include "pathd/path_debug.h" -#include <pcep_pcc_api.h> -#include <pcep-objects.h> +#include "pceplib/pcep_pcc_api.h" +#include "pceplib/pcep_msg_objects.h" #include "pathd/path_pcep.h" #include "pathd/path_pcep_controller.h" #include "pathd/path_pcep_pcc.h" diff --git a/pathd/path_pcep_lib.c b/pathd/path_pcep_lib.c index bb6bfb133..1d2f25889 100644 --- a/pathd/path_pcep_lib.c +++ b/pathd/path_pcep_lib.c @@ -16,9 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <zebra.h> + #include <debug.h> -#include <pcep_utils_counters.h> -#include <pcep_timers.h> +#include "pceplib/pcep_utils_counters.h" +#include "pceplib/pcep_timers.h" #include "pathd/path_errors.h" #include "pathd/path_memory.h" #include "pathd/path_pcep.h" @@ -176,11 +178,11 @@ pcep_lib_connect(struct ipaddr *src_addr, int src_port, struct ipaddr *dst_addr, /* TODO when available in the pceplib, set it here pcep_options->state_timeout_inteval_seconds;*/ - if (pcep_options->tcp_md5_auth != NULL - && pcep_options->tcp_md5_auth[0] != '\0') { + if (pcep_options->tcp_md5_auth[0] != '\0') { config->is_tcp_auth_md5 = true; - strncpy(config->tcp_authentication_str, - pcep_options->tcp_md5_auth, TCP_MD5SIG_MAXKEYLEN); + strlcpy(config->tcp_authentication_str, + pcep_options->tcp_md5_auth, + sizeof(config->tcp_authentication_str)); } else { config->is_tcp_auth_md5 = false; } diff --git a/pathd/path_pcep_lib.h b/pathd/path_pcep_lib.h index 3bea28432..3f34edcb3 100644 --- a/pathd/path_pcep_lib.h +++ b/pathd/path_pcep_lib.h @@ -20,7 +20,7 @@ #define _PATH_PCEP_LIB_H_ #include <stdbool.h> -#include <pcep_pcc_api.h> +#include "pceplib/pcep_pcc_api.h" #include "frr_pthread.h" #include "pathd/path_pcep.h" diff --git a/pathd/path_pcep_pcc.c b/pathd/path_pcep_pcc.c index c1f60edd2..9de3ba781 100644 --- a/pathd/path_pcep_pcc.c +++ b/pathd/path_pcep_pcc.c @@ -55,6 +55,7 @@ #define MAX_ERROR_MSG_SIZE 256 #define MAX_COMPREQ_TRIES 3 +pthread_mutex_t g_pcc_info_mtx = PTHREAD_MUTEX_INITIALIZER; /* PCEP Event Handler */ static void handle_pcep_open(struct ctrl_state *ctrl_state, @@ -63,12 +64,15 @@ static void handle_pcep_open(struct ctrl_state *ctrl_state, static void handle_pcep_message(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state, struct pcep_message *msg); +static void handle_pcep_lsp_initiate(struct ctrl_state *ctrl_state, + struct pcc_state *pcc_state, + struct pcep_message *msg); static void handle_pcep_lsp_update(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state, struct pcep_message *msg); -static void handle_pcep_lsp_initiate(struct ctrl_state *ctrl_state, +static void continue_pcep_lsp_update(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state, - struct pcep_message *msg); + struct path *path, void *payload); static void handle_pcep_comp_reply(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state, struct pcep_message *msg); @@ -543,23 +547,43 @@ void pcep_pcc_sync_done(struct ctrl_state *ctrl_state, } void pcep_pcc_send_report(struct ctrl_state *ctrl_state, - struct pcc_state *pcc_state, struct path *path) + struct pcc_state *pcc_state, struct path *path, + bool is_stable) { - if (pcc_state->status != PCEP_PCC_OPERATING) + if ((pcc_state->status != PCEP_PCC_OPERATING) + || (!pcc_state->caps.is_stateful)) { + pcep_free_path(path); return; + } - if (pcc_state->caps.is_stateful) { - PCEP_DEBUG("%s Send report for candidate path %s", - pcc_state->tag, path->name); + PCEP_DEBUG("%s Send report for candidate path %s", pcc_state->tag, + path->name); + + /* ODL and Cisco requires the first reported + * LSP to have a DOWN status, the later status changes + * will be comunicated through hook calls. + */ + enum pcep_lsp_operational_status real_status = path->status; + path->status = PCEP_LSP_OPERATIONAL_DOWN; + send_report(pcc_state, path); + + /* If no update is expected and the real status wasn't down, we need to + * send a second report with the real status */ + if (is_stable && (real_status != PCEP_LSP_OPERATIONAL_DOWN)) { + path->srp_id = 0; + path->status = real_status; send_report(pcc_state, path); } + + pcep_free_path(path); } + /* ------------ Timeout handler ------------ */ void pcep_pcc_timeout_handler(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state, - enum pcep_ctrl_timer_type type, void *param) + enum pcep_ctrl_timeout_type type, void *param) { struct req_entry *req; @@ -926,6 +950,7 @@ int pcep_pcc_calculate_best_pce(struct pcc_state **pcc) // Changed of state so ... if (step_0_best != best_pce) { + pthread_mutex_lock(&g_pcc_info_mtx); // Calculate previous previous_best_pce = step_0_best; // Clean state @@ -970,6 +995,7 @@ int pcep_pcc_calculate_best_pce(struct pcc_state **pcc) } } } + pthread_mutex_unlock(&g_pcc_info_mtx); } return ((best_pce == -1) ? 0 : pcc[best_pce]->id); @@ -1094,18 +1120,24 @@ void pcep_pcc_copy_pcc_info(struct pcc_state **pcc, } pcc_info->ctrl_state = NULL; - pcc_info->msd = pcc_state->pcc_opts->msd; - pcc_info->pcc_port = pcc_state->pcc_opts->port; + if(pcc_state->pcc_opts){ + pcc_info->msd = pcc_state->pcc_opts->msd; + pcc_info->pcc_port = pcc_state->pcc_opts->port; + } pcc_info->next_plspid = pcc_state->next_plspid; pcc_info->next_reqid = pcc_state->next_reqid; pcc_info->status = pcc_state->status; pcc_info->pcc_id = pcc_state->id; + pthread_mutex_lock(&g_pcc_info_mtx); pcc_info->is_best_multi_pce = pcc_state->is_best; pcc_info->previous_best = pcc_state->previous_best; + pthread_mutex_unlock(&g_pcc_info_mtx); pcc_info->precedence = pcc_state->pce_opts ? pcc_state->pce_opts->precedence : 0; - memcpy(&pcc_info->pcc_addr, &pcc_state->pcc_addr_tr, - sizeof(struct ipaddr)); + if(pcc_state->pcc_addr_tr.ipa_type != IPADDR_NONE){ + memcpy(&pcc_info->pcc_addr, &pcc_state->pcc_addr_tr, + sizeof(struct ipaddr)); + } } @@ -1154,12 +1186,19 @@ void handle_pcep_lsp_update(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state, struct pcep_message *msg) { - char err[MAX_ERROR_MSG_SIZE] = ""; struct path *path; path = pcep_lib_parse_path(msg); lookup_nbkey(pcc_state, path); - /* TODO: Investigate if this is safe to do in the controller thread */ - path_pcep_config_lookup(path); + pcep_thread_refine_path(ctrl_state, pcc_state->id, + &continue_pcep_lsp_update, path, NULL); +} + +void continue_pcep_lsp_update(struct ctrl_state *ctrl_state, + struct pcc_state *pcc_state, struct path *path, + void *payload) +{ + char err[MAX_ERROR_MSG_SIZE] = {0}; + specialize_incoming_path(pcc_state, path); PCEP_DEBUG("%s Received LSP update", pcc_state->tag); PCEP_DEBUG_PATH("%s", format_path(path)); @@ -1309,13 +1348,13 @@ void select_transport_address(struct pcc_state *pcc_state) * address */ if (IS_IPADDR_V4(&pcc_state->pce_opts->addr)) { if (CHECK_FLAG(pcc_state->flags, F_PCC_STATE_HAS_IPV4)) { - taddr->ipa_type = IPADDR_V4; taddr->ipaddr_v4 = pcc_state->pcc_addr_v4; + taddr->ipa_type = IPADDR_V4; } } else { if (CHECK_FLAG(pcc_state->flags, F_PCC_STATE_HAS_IPV6)) { - taddr->ipa_type = IPADDR_V6; taddr->ipaddr_v6 = pcc_state->pcc_addr_v6; + taddr->ipa_type = IPADDR_V6; } } } diff --git a/pathd/path_pcep_pcc.h b/pathd/path_pcep_pcc.h index a466d92d5..c07a6ae54 100644 --- a/pathd/path_pcep_pcc.h +++ b/pathd/path_pcep_pcc.h @@ -113,13 +113,18 @@ void pcep_pcc_pathd_event_handler(struct ctrl_state *ctrl_state, struct path *path); void pcep_pcc_timeout_handler(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state, - enum pcep_ctrl_timer_type type, void *param); + enum pcep_ctrl_timeout_type type, void *param); void pcep_pcc_sync_path(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state, struct path *path); void pcep_pcc_sync_done(struct ctrl_state *ctrl_state, struct pcc_state *pcc_state); +/* Send a report explicitly. When doing so the PCC may send multiple reports + * due to expectations from vendors for the first report to be with a DOWN + * status. The parameter is_stable is used for that purpose as a hint wheter + * to expect an update for the report */ void pcep_pcc_send_report(struct ctrl_state *ctrl_state, - struct pcc_state *pcc_state, struct path *path); + struct pcc_state *pcc_state, struct path *path, + bool is_stable); int pcep_pcc_multi_pce_sync_path(struct ctrl_state *ctrl_state, int pcc_id, struct pcc_state **pcc_state_list); int pcep_pcc_multi_pce_remove_pcc(struct ctrl_state *ctrl_state, diff --git a/pathd/subdir.am b/pathd/subdir.am index 520a8c696..452d82466 100644 --- a/pathd/subdir.am +++ b/pathd/subdir.am @@ -11,7 +11,7 @@ vtysh_daemons += pathd # TODO add man page #man8 += $(MANBUILD)/pathd.8 -if HAVE_PATHD_PCEP +if PATHD_PCEP vtysh_scan += $(top_srcdir)/pathd/path_pcep_cli.c module_LTLIBRARIES += pathd/pathd_pcep.la endif @@ -69,6 +69,15 @@ pathd_pathd_pcep_la_SOURCES = \ pathd/path_pcep_config.c \ pathd/path_pcep_pcc.c \ # end + +if PATHD_PCEP +pathd_pathd_pcep_la_CPPFLAGS = -I./pceplib $(AM_CPPFLAGS) +pathd_pathd_pcep_la_LIBADD = pceplib/libpcep_pcc.la +else +pathd_pathd_pcep_la_CPPFLAGS = $(AM_CPPFLAGS) +pathd_pathd_pcep_la_LIBADD = +endif + + pathd_pathd_pcep_la_CFLAGS = $(WERROR) pathd_pathd_pcep_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -pathd_pathd_pcep_la_LIBADD = @PATHD_PCEP_LIBS@ |