.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",
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,
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);
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);
#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");
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);
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);
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 ------------ */
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);
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;
}
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);
#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,
.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,
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);
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
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);
* @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;
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);
* @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;
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;
/* 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;
#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)
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);
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);