From: Javier Garcia Date: Fri, 21 May 2021 07:17:22 +0000 (+0200) Subject: pathd: Handle PCInitiated configuration, main thread. (3/4) X-Git-Tag: base_8.1~394^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=ab7fe289b911bc4601da1c48542159adabf3ef60;p=mirror%2Ffrr.git pathd: Handle PCInitiated configuration, main thread. (3/4) Co-authored-by: Javier Garcia Signed-off-by: Sebastien Merle --- diff --git a/pathd/path_errors.c b/pathd/path_errors.c index f8560a848c..112a3d5ee9 100644 --- a/pathd/path_errors.c +++ b/pathd/path_errors.c @@ -60,6 +60,12 @@ static struct log_ref ferr_path_warn[] = { .description = "The PCEP module failed to connected to configured PCE", .suggestion = "Check the connectivity between the PCC and the PCE" }, + { + .code = EC_PATH_PCEP_PROTOCOL_ERROR, + .title = "PCEP protocol error", + .description = "The PCE did not respect the PCEP protocol", + .suggestion = "Open an Issue with all relevant log files" + }, { .code = EC_PATH_PCEP_MISSING_SOURCE_ADDRESS, .title = "PCC connection error", diff --git a/pathd/path_errors.h b/pathd/path_errors.h index 72e127f26b..5d05b6650b 100644 --- a/pathd/path_errors.h +++ b/pathd/path_errors.h @@ -28,6 +28,7 @@ enum path_log_refs { EC_PATH_PCEP_PCC_FINI, EC_PATH_PCEP_PCC_CONF_UPDATE, EC_PATH_PCEP_LIB_CONNECT, + EC_PATH_PCEP_PROTOCOL_ERROR, EC_PATH_PCEP_MISSING_SOURCE_ADDRESS, EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR, EC_PATH_PCEP_UNSUPPORTED_PCEP_FEATURE, diff --git a/pathd/path_nb_config.c b/pathd/path_nb_config.c index 5b0f5b44e5..e1fbb37f55 100644 --- a/pathd/path_nb_config.c +++ b/pathd/path_nb_config.c @@ -266,7 +266,7 @@ int pathd_srte_policy_create(struct nb_cb_create_args *args) color = yang_dnode_get_uint32(args->dnode, "./color"); yang_dnode_get_ip(&endpoint, args->dnode, "./endpoint"); - policy = srte_policy_add(color, &endpoint); + policy = srte_policy_add(color, &endpoint, SRTE_ORIGIN_LOCAL, NULL); nb_running_set_entry(args->dnode, policy); SET_FLAG(policy->flags, F_POLICY_NEW); @@ -388,7 +388,8 @@ int pathd_srte_policy_candidate_path_create(struct nb_cb_create_args *args) policy = nb_running_get_entry(args->dnode, NULL, true); preference = yang_dnode_get_uint32(args->dnode, "./preference"); - candidate = srte_candidate_add(policy, preference); + candidate = + srte_candidate_add(policy, preference, SRTE_ORIGIN_LOCAL, NULL); nb_running_set_entry(args->dnode, candidate); SET_FLAG(candidate->flags, F_CANDIDATE_NEW); diff --git a/pathd/path_pcep.c b/pathd/path_pcep.c index ad24c2eb02..ce631eb7b0 100644 --- a/pathd/path_pcep.c +++ b/pathd/path_pcep.c @@ -37,6 +37,7 @@ #include "pathd/path_pcep_controller.h" #include "pathd/path_pcep_lib.h" #include "pathd/path_pcep_config.h" +#include "pathd/path_pcep_debug.h" DEFINE_MTYPE(PATHD, PCEP, "PCEP module"); @@ -51,6 +52,7 @@ static int pcep_main_event_handler(enum pcep_main_event_type type, int pcc_id, void *payload); static int pcep_main_event_start_sync(int pcc_id); static int pcep_main_event_start_sync_cb(struct path *path, void *arg); +static int pcep_main_event_initiate_candidate(struct path *path); static int pcep_main_event_update_candidate(struct path *path); static int pcep_main_event_remove_candidate_segments(const char *originator, bool force); @@ -64,6 +66,9 @@ static int pathd_candidate_removed_handler(struct srte_candidate *candidate); static struct path_metric *pcep_copy_metrics(struct path_metric *metric); static struct path_hop *pcep_copy_hops(struct path_hop *hop); +/* Other static functions */ +static void notify_status(struct path *path, bool not_changed); + /* Module Functions */ static int pcep_module_finish(void); static int pcep_module_late_init(struct thread_master *tm); @@ -165,6 +170,21 @@ void pcep_free_path(struct path *path) XFREE(MTYPE_PCEP, path); } +/* ------------ Other Static Functions ------------ */ + +void notify_status(struct path *path, bool not_changed) +{ + struct path *resp = NULL; + + if ((resp = path_pcep_config_get_path(&path->nbkey))) { + resp->srp_id = path->srp_id; + flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR, + "(%s) Send report for candidate path %s", __func__, + path->name); + pcep_ctrl_send_report(pcep_g->fpt, path->pcc_id, resp, + not_changed); + } +} /* ------------ Main Thread Even Handler ------------ */ @@ -177,6 +197,11 @@ int pcep_main_event_handler(enum pcep_main_event_type type, int pcc_id, case PCEP_MAIN_EVENT_START_SYNC: ret = pcep_main_event_start_sync(pcc_id); break; + case PCEP_MAIN_EVENT_INITIATE_CANDIDATE: + assert(payload != NULL); + ret = pcep_main_event_initiate_candidate( + (struct path *)payload); + break; case PCEP_MAIN_EVENT_UPDATE_CANDIDATE: assert(payload != NULL); ret = pcep_main_event_update_candidate((struct path *)payload); @@ -209,19 +234,49 @@ int pcep_main_event_start_sync_cb(struct path *path, void *arg) return 1; } +int pcep_main_event_initiate_candidate(struct path *path) +{ + int ret = 0; + + ret = path_pcep_config_initiate_path(path); + if (path->do_remove) { + struct pcep_error *error; + error = XCALLOC(MTYPE_PCEP, sizeof(*error)); + error->path = path; + error->error_type = PCEP_ERRT_INVALID_OPERATION; + switch (ret) { + case ERROR_19_1: + error->error_value = + PCEP_ERRV_LSP_UPDATE_FOR_NON_DELEGATED_LSP; + break; + case ERROR_19_3: + error->error_value = + PCEP_ERRV_LSP_UPDATE_UNKNOWN_PLSP_ID; + break; + case ERROR_19_9: + error->error_value = PCEP_ERRV_LSP_NOT_PCE_INITIATED; + break; + default: + zlog_warn("(%s)PCE tried to REMOVE unknown error!", + __func__); + XFREE(MTYPE_PCEP, error); + pcep_free_path(path); + return ret; + break; + } + pcep_ctrl_send_error(pcep_g->fpt, path->pcc_id, error); + } else if (ret != PATH_NB_ERR && path->srp_id != 0) + notify_status(path, ret == PATH_NB_NO_CHANGE); + return ret; +} + int pcep_main_event_update_candidate(struct path *path) { - struct path *resp = NULL; int ret = 0; ret = path_pcep_config_update_path(path); - if (ret != PATH_NB_ERR && path->srp_id != 0) { - if ((resp = path_pcep_config_get_path(&path->nbkey))) { - resp->srp_id = path->srp_id; - pcep_ctrl_send_report(pcep_g->fpt, path->pcc_id, resp, - ret == PATH_NB_NO_CHANGE); - } - } + if (ret != PATH_NB_ERR && path->srp_id != 0) + notify_status(path, ret == PATH_NB_NO_CHANGE); return ret; } diff --git a/pathd/path_pcep.h b/pathd/path_pcep.h index d0af674ff9..597a4b6c83 100644 --- a/pathd/path_pcep.h +++ b/pathd/path_pcep.h @@ -317,6 +317,16 @@ struct pcep_glob { extern struct pcep_glob *pcep_g; +struct pcep_error { + struct path *path; + int error_type; + int error_value; + /* Rfc 8281 PcInitiated error on bad values */ +#define ERROR_19_1 1 +#define ERROR_19_3 2 +#define ERROR_19_9 3 +}; + /* Path Helper Functions */ struct path *pcep_new_path(void); struct path_hop *pcep_new_hop(void); diff --git a/pathd/path_pcep_config.c b/pathd/path_pcep_config.c index 609f091559..0349618304 100644 --- a/pathd/path_pcep_config.c +++ b/pathd/path_pcep_config.c @@ -32,6 +32,8 @@ #define MAX_FLOAT_LEN 22 #define INETADDR4_MAXLEN 16 #define INETADDR6_MAXLEN 40 +#define INITIATED_CANDIDATE_PREFERENCE 255 +#define INITIATED_POLICY_COLOR 1 static void copy_candidate_objfun_info(struct srte_candidate *candidate, @@ -147,7 +149,7 @@ struct path *candidate_to_path(struct srte_candidate *candidate) .plsp_id = 0, .name = name, .type = candidate->type, - .srp_id = 0, + .srp_id = policy->srp_id, .req_id = 0, .binding_sid = policy->binding_sid, .status = status, @@ -276,6 +278,93 @@ path_pcep_config_list_path_hops(struct srte_segment_list *segment_list) return hop; } +int path_pcep_config_initiate_path(struct path *path) +{ + struct srte_policy *policy; + struct srte_candidate *candidate; + + if (path->do_remove) { + zlog_warn("PCE %s tried to REMOVE pce-initiate a path ", + path->originator); + candidate = lookup_candidate(&path->nbkey); + if (candidate) { + if (!path->is_delegated) { + zlog_warn( + "(%s)PCE tried to REMOVE but it's not Delegated!", + __func__); + return ERROR_19_1; + } + if (candidate->type != SRTE_CANDIDATE_TYPE_DYNAMIC) { + zlog_warn( + "(%s)PCE tried to REMOVE but it's not PCE origin!", + __func__); + return ERROR_19_9; + } + zlog_warn( + "(%s)PCE tried to REMOVE found canidate!, let's remove", + __func__); + candidate->policy->srp_id = path->srp_id; + SET_FLAG(candidate->policy->flags, F_POLICY_DELETED); + SET_FLAG(candidate->flags, F_CANDIDATE_DELETED); + } else { + zlog_warn("(%s)PCE tried to REMOVE not existing LSP!", + __func__); + return ERROR_19_3; + } + srte_apply_changes(); + } else { + assert(!IS_IPADDR_NONE(&path->nbkey.endpoint)); + + if (path->nbkey.preference == 0) + path->nbkey.preference = INITIATED_CANDIDATE_PREFERENCE; + + if (path->nbkey.color == 0) + path->nbkey.color = INITIATED_POLICY_COLOR; + + candidate = lookup_candidate(&path->nbkey); + if (!candidate) { + policy = srte_policy_add( + path->nbkey.color, &path->nbkey.endpoint, + SRTE_ORIGIN_PCEP, path->originator); + strlcpy(policy->name, path->name, sizeof(policy->name)); + policy->binding_sid = path->binding_sid; + SET_FLAG(policy->flags, F_POLICY_NEW); + candidate = srte_candidate_add( + policy, path->nbkey.preference, + SRTE_ORIGIN_PCEP, path->originator); + strlcpy(candidate->name, path->name, + sizeof(candidate->name)); + SET_FLAG(candidate->flags, F_CANDIDATE_NEW); + } else { + policy = candidate->policy; + if ((path->originator != candidate->originator) + || (path->originator != policy->originator)) { + /* There is already an initiated path from + * another PCE, show a warning and regect the + * initiated path */ + zlog_warn( + "PCE %s tried to initiate a path already initiated by PCE %s", + path->originator, + candidate->originator); + return 1; + } + if ((policy->protocol_origin != SRTE_ORIGIN_PCEP) + || (candidate->protocol_origin + != SRTE_ORIGIN_PCEP)) { + /* There is already an initiated path from + * another PCE, show a warning and regect the + * initiated path */ + zlog_warn( + "PCE %s tried to initiate a path created localy", + path->originator); + return 1; + } + } + return path_pcep_config_update_path(path); + } + return 0; +} + int path_pcep_config_update_path(struct path *path) { assert(path != NULL); @@ -381,8 +470,12 @@ struct srte_candidate *lookup_candidate(struct lsp_nb_key *key) char *candidate_name(struct srte_candidate *candidate) { - return asprintfrr(MTYPE_PCEP, "%s-%s", candidate->policy->name, - candidate->name); + if (candidate->protocol_origin == SRTE_ORIGIN_PCEP + || candidate->protocol_origin == SRTE_ORIGIN_BGP) + return asprintfrr(MTYPE_PCEP, "%s", candidate->policy->name); + else + return asprintfrr(MTYPE_PCEP, "%s-%s", candidate->policy->name, + candidate->name); } enum pcep_lsp_operational_status diff --git a/pathd/path_pcep_config.h b/pathd/path_pcep_config.h index 223dd10c82..e56d497aa0 100644 --- a/pathd/path_pcep_config.h +++ b/pathd/path_pcep_config.h @@ -38,6 +38,7 @@ typedef int (*path_list_cb_t)(struct path *path, void *arg); 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_initiate_path(struct path *path); int path_pcep_config_update_path(struct path *path); struct path *candidate_to_path(struct srte_candidate *candidate); diff --git a/pathd/pathd.c b/pathd/pathd.c index 9dc3a41638..022813a497 100644 --- a/pathd/pathd.c +++ b/pathd/pathd.c @@ -294,7 +294,9 @@ void srte_segment_set_local_modification(struct srte_segment_list *s_list, * @param endpoint The IP address of the policy endpoint * @return The created policy */ -struct srte_policy *srte_policy_add(uint32_t color, struct ipaddr *endpoint) +struct srte_policy *srte_policy_add(uint32_t color, struct ipaddr *endpoint, + enum srte_protocol_origin origin, + const char *originator) { struct srte_policy *policy; @@ -302,6 +304,11 @@ struct srte_policy *srte_policy_add(uint32_t color, struct ipaddr *endpoint) policy->color = color; policy->endpoint = *endpoint; policy->binding_sid = MPLS_LABEL_NONE; + policy->protocol_origin = origin; + if (originator != NULL) + strlcpy(policy->originator, originator, + sizeof(policy->originator)); + RB_INIT(srte_candidate_head, &policy->candidate_paths); RB_INSERT(srte_policy_head, &srte_policies, policy); @@ -646,7 +653,9 @@ void srte_policy_apply_changes(struct srte_policy *policy) * @return The added candidate path */ struct srte_candidate *srte_candidate_add(struct srte_policy *policy, - uint32_t preference) + uint32_t preference, + enum srte_protocol_origin origin, + const char *originator) { struct srte_candidate *candidate; struct srte_lsp *lsp; @@ -657,8 +666,18 @@ struct srte_candidate *srte_candidate_add(struct srte_policy *policy, candidate->preference = preference; candidate->policy = policy; candidate->type = SRTE_CANDIDATE_TYPE_UNDEFINED; - candidate->discriminator = frr_weak_random(); + candidate->discriminator = rand(); + candidate->protocol_origin = origin; + if (originator != NULL) { + strlcpy(candidate->originator, originator, + sizeof(candidate->originator)); + lsp->protocol_origin = origin; + } + if (candidate->protocol_origin == SRTE_ORIGIN_PCEP + || candidate->protocol_origin == SRTE_ORIGIN_BGP) { + candidate->type = SRTE_CANDIDATE_TYPE_DYNAMIC; + } lsp->candidate = candidate; candidate->lsp = lsp; diff --git a/pathd/pathd.h b/pathd/pathd.h index 7d38272e85..f790a0e3c9 100644 --- a/pathd/pathd.h +++ b/pathd/pathd.h @@ -339,6 +339,12 @@ struct srte_policy { /* Binding SID */ mpls_label_t binding_sid; + /* The Protocol-Origin. */ + enum srte_protocol_origin protocol_origin; + + /* The Originator */ + char originator[64]; + /* Operational Status of the policy */ enum srte_policy_status status; @@ -352,6 +358,8 @@ struct srte_policy { #define F_POLICY_NEW 0x0002 #define F_POLICY_MODIFIED 0x0004 #define F_POLICY_DELETED 0x0008 + /* SRP id for PcInitiated support */ + int srp_id; }; RB_HEAD(srte_policy_head, srte_policy); RB_PROTOTYPE(srte_policy_head, srte_policy, entry, srte_policy_compare) @@ -385,7 +393,9 @@ int srte_segment_entry_set_nai(struct srte_segment_entry *segment, void srte_segment_set_local_modification(struct srte_segment_list *s_list, struct srte_segment_entry *s_entry, uint32_t ted_sid); -struct srte_policy *srte_policy_add(uint32_t color, struct ipaddr *endpoint); +struct srte_policy *srte_policy_add(uint32_t color, struct ipaddr *endpoint, + enum srte_protocol_origin origin, + const char *originator); void srte_policy_del(struct srte_policy *policy); struct srte_policy *srte_policy_find(uint32_t color, struct ipaddr *endpoint); int srte_policy_update_ted_sid(void); @@ -395,7 +405,9 @@ void srte_apply_changes(void); void srte_clean_zebra(void); void srte_policy_apply_changes(struct srte_policy *policy); struct srte_candidate *srte_candidate_add(struct srte_policy *policy, - uint32_t preference); + uint32_t preference, + enum srte_protocol_origin origin, + const char *originator); void srte_candidate_del(struct srte_candidate *candidate); void srte_candidate_set_bandwidth(struct srte_candidate *candidate, float bandwidth, bool required);