]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pathd: Handle PCInitiated configuration, main thread. (3/4)
authorJavier Garcia <javier.garcia@voltanet.io>
Fri, 21 May 2021 07:17:22 +0000 (09:17 +0200)
committerJavier Garcia <javier.garcia@voltanet.io>
Tue, 22 Jun 2021 10:04:03 +0000 (12:04 +0200)
Co-authored-by: Javier Garcia <javier.garcia@voltanet.io>
Signed-off-by: Sebastien Merle <sebastien@netdef.org>
pathd/path_errors.c
pathd/path_errors.h
pathd/path_nb_config.c
pathd/path_pcep.c
pathd/path_pcep.h
pathd/path_pcep_config.c
pathd/path_pcep_config.h
pathd/pathd.c
pathd/pathd.h

index f8560a848c2c498c1b442733173b9840f8ef4bfe..112a3d5ee9e68e36c125648f50717d82bd54e849 100644 (file)
@@ -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",
index 72e127f26b1564927b98fdd82e62a344ff2df6a6..5d05b6650b644d2b4155d9666a2a0c868ae06a34 100644 (file)
@@ -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,
index 5b0f5b44e5c894312253e88267d7d01999ff60b1..e1fbb37f55c723bdfa298f7fab2bf7a409cb907d 100644 (file)
@@ -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);
 
index ad24c2eb02b3aacdc33c8918866de6cd6d17ea9f..ce631eb7b040933484c13e0c0bfe4f0dfe3a88f3 100644 (file)
@@ -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;
 }
 
index d0af674ff9036c3e2fe4153121d6c7b12e793b51..597a4b6c83f9609c8629492f10ef4405570c8945 100644 (file)
@@ -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);
index 609f0915598e1985e301237bf8e9c057be53ce7c..0349618304286d595d89a82d7502c2c413c94af9 100644 (file)
@@ -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
index 223dd10c82097a6e00fb417b28c48946ab368a11..e56d497aa0259046bf76b35762eeca15597e9df3 100644 (file)
@@ -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);
 
index 9dc3a41638effe16ed7024fadbaec04f8da3da3f..022813a497164aa1a2831bcc48ce38ec1184a52a 100644 (file)
@@ -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;
 
index 7d38272e856d6c623c5e359b10dfb99a7820bfb8..f790a0e3c909e908dbb2ba056830e9c811a5e6ac 100644 (file)
@@ -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);