summaryrefslogtreecommitdiffstats
path: root/pathd
diff options
context:
space:
mode:
Diffstat (limited to 'pathd')
-rw-r--r--pathd/path_pcep.c25
-rw-r--r--pathd/path_pcep.h4
-rw-r--r--pathd/path_pcep_cli.c22
-rw-r--r--pathd/path_pcep_config.c25
-rw-r--r--pathd/path_pcep_config.h9
-rw-r--r--pathd/path_pcep_controller.c227
-rw-r--r--pathd/path_pcep_controller.h22
-rw-r--r--pathd/path_pcep_debug.c4
-rw-r--r--pathd/path_pcep_debug.h4
-rw-r--r--pathd/path_pcep_lib.c14
-rw-r--r--pathd/path_pcep_lib.h2
-rw-r--r--pathd/path_pcep_pcc.c73
-rw-r--r--pathd/path_pcep_pcc.h9
-rw-r--r--pathd/subdir.am13
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(&current_time, &lt);
gmtime_r(&session->time_connected, &lt);
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@