]> git.proxmox.com Git - mirror_frr.git/blobdiff - pathd/path_pcep_config.c
Merge pull request #10050 from mjstapp/fix_mpls_queue_cleanup
[mirror_frr.git] / pathd / path_pcep_config.c
index 989223ebc3f8a5f7c7d54a0da2fdbabb9fbfa5b2..4c16b83948a5c95416b89124129bf2d54b32cceb 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #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"
@@ -30,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,
@@ -45,14 +49,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 +68,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)
@@ -156,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,
@@ -255,6 +248,10 @@ path_pcep_config_list_path_hops(struct srte_segment_list *segment_list)
                switch (segment->nai_type) {
                case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE:
                case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE:
+               case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
+               case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
+               case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
+               case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
                        memcpy(&hop->nai.local_addr, &segment->nai_local_addr,
                               sizeof(struct ipaddr));
                        break;
@@ -281,12 +278,101 @@ 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);
+                       candidate->policy->srp_id = path->srp_id;
+                       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);
        assert(path->nbkey.preference != 0);
        assert(path->nbkey.endpoint.ipa_type == IPADDR_V4);
 
+       int number_of_sid_clashed = 0;
        struct path_hop *hop;
        struct path_metric *metric;
        int index;
@@ -302,53 +388,60 @@ int path_pcep_config_update_path(struct path *path)
        if (!candidate)
                return 0;
 
+       candidate->policy->srp_id = path->srp_id;
        // first clean up old segment list if present
        if (candidate->lsp->segment_list) {
                SET_FLAG(candidate->lsp->segment_list->flags,
                         F_SEGMENT_LIST_DELETED);
+               srte_segment_list_del(candidate->lsp->segment_list);
                candidate->lsp->segment_list = NULL;
        }
 
-       if (path->first_hop != NULL) {
-               snprintf(segment_list_name_buff, sizeof(segment_list_name_buff),
-                        "%s-%u", path->name, path->plsp_id);
-               segment_list_name = segment_list_name_buff;
-
-               segment_list = srte_segment_list_add(segment_list_name);
-               segment_list->protocol_origin = path->update_origin;
-               strlcpy(segment_list->originator, path->originator,
-                       sizeof(segment_list->originator));
-               SET_FLAG(segment_list->flags, F_SEGMENT_LIST_NEW);
-               SET_FLAG(segment_list->flags, F_SEGMENT_LIST_MODIFIED);
-
-               for (hop = path->first_hop, index = 10; hop != NULL;
-                    hop = hop->next, index += 10) {
-                       assert(hop->has_sid);
-                       assert(hop->is_mpls);
-
-                       segment = srte_segment_entry_add(segment_list, index);
-
-                       segment->sid_value = (mpls_label_t)hop->sid.mpls.label;
-                       SET_FLAG(segment->segment_list->flags,
-                                F_SEGMENT_LIST_MODIFIED);
-
-                       if (hop->has_nai)
-                               srte_segment_entry_set_nai(
-                                       segment, srte_nai_type(hop->nai.type),
-                                       &hop->nai.local_addr,
-                                       hop->nai.local_iface,
-                                       &hop->nai.remote_addr,
-                                       hop->nai.remote_iface);
-               }
+       if (path->first_hop == NULL)
+               return PATH_NB_ERR;
+
+       snprintf(segment_list_name_buff, sizeof(segment_list_name_buff),
+                "%s-%u", path->name, path->plsp_id);
+       segment_list_name = segment_list_name_buff;
+
+       segment_list = srte_segment_list_add(segment_list_name);
+       segment_list->protocol_origin = path->update_origin;
+       strlcpy(segment_list->originator, path->originator,
+               sizeof(segment_list->originator));
+       SET_FLAG(segment_list->flags, F_SEGMENT_LIST_NEW);
+       SET_FLAG(segment_list->flags, F_SEGMENT_LIST_MODIFIED);
+
+       for (hop = path->first_hop, index = 10; hop != NULL;
+            hop = hop->next, index += 10) {
+               assert(hop->has_sid);
+               assert(hop->is_mpls);
+
+               segment = srte_segment_entry_add(segment_list, index);
+
+               segment->sid_value = (mpls_label_t)hop->sid.mpls.label;
+               SET_FLAG(segment->segment_list->flags, F_SEGMENT_LIST_MODIFIED);
+
+               if (!hop->has_nai)
+                       continue;
+               if (srte_segment_entry_set_nai(
+                           segment, srte_nai_type(hop->nai.type),
+                           &hop->nai.local_addr, hop->nai.local_iface,
+                           &hop->nai.remote_addr, hop->nai.remote_iface, 0, 0)
+                   == PATH_SID_ERROR)
+                       /* TED queries don't match PCE */
+                       /* Don't apply srte,zebra changes */
+                       number_of_sid_clashed++;
        }
 
        candidate->lsp->segment_list = segment_list;
        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,
@@ -359,7 +452,11 @@ int path_pcep_config_update_path(struct path *path)
                candidate->lsp->objfun = path->pce_objfun;
        }
 
-       srte_apply_changes();
+       if (number_of_sid_clashed)
+               SET_FLAG(segment->segment_list->flags,
+                        F_SEGMENT_LIST_SID_CONFLICT);
+       else
+               srte_apply_changes();
 
        return 0;
 }
@@ -375,8 +472,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
@@ -409,6 +510,16 @@ enum pcep_sr_subobj_nai pcep_nai_type(enum srte_segment_nai_type type)
                return PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY;
        case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY:
                return PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY;
+       case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY_LINK_LOCAL_ADDRESSES:
+               return PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY;
+       case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
+               return PCEP_SR_SUBOBJ_NAI_IPV4_NODE;
+       case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
+               return PCEP_SR_SUBOBJ_NAI_IPV6_NODE;
+       case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
+               return PCEP_SR_SUBOBJ_NAI_IPV4_NODE;
+       case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
+               return PCEP_SR_SUBOBJ_NAI_IPV6_NODE;
        default:
                return PCEP_SR_SUBOBJ_NAI_UNKNOWN;
        }