]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pathd: Handle PCInitiated messages, thread controller. (2/4)
authorJavier Garcia <javier.garcia@voltanet.io>
Fri, 21 May 2021 07:15:52 +0000 (09:15 +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>
Signed-off-by: Javier Garcia <javier.garcia@voltanet.io>
pathd/path_pcep_controller.c
pathd/path_pcep_controller.h
pathd/path_pcep_debug.c
pathd/path_pcep_lib.c
pathd/path_pcep_lib.h
pathd/path_pcep_pcc.c
pathd/path_pcep_pcc.h

index 528dcc3539923d7eb66de22a06091401fb314f41..449c40c16c23fad50f19b5dba189067e2abf3efb 100644 (file)
@@ -57,6 +57,7 @@ enum pcep_ctrl_event_type {
        EV_PCEPLIB_EVENT,
        EV_RESET_PCC_SESSION,
        EV_SEND_REPORT,
+       EV_SEND_ERROR,
        EV_PATH_REFINED
 };
 
@@ -328,6 +329,14 @@ int pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id,
 }
 
 
+int pcep_ctrl_send_error(struct frr_pthread *fpt, int pcc_id,
+                        struct pcep_error *error)
+{
+       struct ctrl_state *ctrl_state = get_ctrl_state(fpt);
+       return send_to_thread(ctrl_state, pcc_id, EV_SEND_ERROR, 0, error);
+}
+
+
 /* ------------ Internal Functions Called from Main Thread ------------ */
 
 int pcep_ctrl_halt_cb(struct frr_pthread *fpt, void **res)
@@ -368,6 +377,13 @@ void pcep_thread_update_path(struct ctrl_state *ctrl_state, int pcc_id,
                     path);
 }
 
+void pcep_thread_initiate_path(struct ctrl_state *ctrl_state, int pcc_id,
+                              struct path *path)
+{
+       send_to_main(ctrl_state, pcc_id, PCEP_MAIN_EVENT_INITIATE_CANDIDATE,
+                    path);
+}
+
 void pcep_thread_remove_candidate_path_segments(struct ctrl_state *ctrl_state,
                                                struct pcc_state *pcc_state)
 {
@@ -743,6 +759,7 @@ int pcep_thread_event_handler(struct thread *thread)
        struct pcep_refine_path_event_data *refine_data = NULL;
 
        struct path *path_copy = NULL;
+       struct pcep_error *error = NULL;
 
        switch (type) {
        case EV_UPDATE_PCC_OPTS:
@@ -818,6 +835,13 @@ int pcep_thread_event_handler(struct thread *thread)
                refine_data = (struct pcep_refine_path_event_data *)payload;
                pcep_thread_path_refined_event(ctrl_state, refine_data);
                break;
+       case EV_SEND_ERROR:
+               assert(payload != NULL);
+               error = (struct pcep_error *)payload;
+               pcc_state = pcep_pcc_get_pcc_by_id(ctrl_state->pcc, pcc_id);
+               pcep_pcc_send_error(ctrl_state, pcc_state, error,
+                                   (bool)sub_type);
+               break;
        default:
                flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
                          "Unexpected event received in controller thread: %u",
index 1b7c3a4c72a5d83b22c51aa3c87c597e72921c5f..f55cc0db72e635181541f44c92da6e2a2bddcfee 100644 (file)
@@ -27,6 +27,7 @@ struct pcc_state;
 enum pcep_main_event_type {
        PCEP_MAIN_EVENT_UNDEFINED = 0,
        PCEP_MAIN_EVENT_START_SYNC,
+       PCEP_MAIN_EVENT_INITIATE_CANDIDATE,
        PCEP_MAIN_EVENT_UPDATE_CANDIDATE,
        PCEP_MAIN_EVENT_REMOVE_CANDIDATE_LSP,
 };
@@ -137,10 +138,15 @@ struct pcep_pcc_info *pcep_ctrl_get_pcc_info(struct frr_pthread *fpt,
 int pcep_ctrl_send_report(struct frr_pthread *fpt, int pcc_id,
                          struct path *path, bool is_stable);
 
+int pcep_ctrl_send_error(struct frr_pthread *fpt, int pcc_id,
+                        struct pcep_error *error);
+
 /* Functions called from the controller thread */
 void pcep_thread_start_sync(struct ctrl_state *ctrl_state, int pcc_id);
 void pcep_thread_update_path(struct ctrl_state *ctrl_state, int pcc_id,
                             struct path *path);
+void pcep_thread_initiate_path(struct ctrl_state *ctrl_state, int pcc_id,
+                              struct path *path);
 void pcep_thread_cancel_timer(struct thread **thread);
 void pcep_thread_schedule_reconnect(struct ctrl_state *ctrl_state, int pcc_id,
                                    int retry_count, struct thread **thread);
index e14f6bc4a5703fb61a4f49c6656e8d714bf255ee..b0802ae6c3ecb0c19bb37675396a6f4477aea2db 100644 (file)
@@ -780,6 +780,10 @@ const char *pcep_tlv_type_name(enum pcep_object_tlv_types tlv_type)
        switch (tlv_type) {
        case PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR:
                return "NO_PATH_VECTOR";
+       case PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST:
+               return "OBJECTIVE_FUNCTION_LIST";
+       case PCEP_OBJ_TLV_TYPE_VENDOR_INFO:
+               return "VENDOR_INFO";
        case PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY:
                return "STATEFUL_PCE_CAPABILITY";
        case PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME:
@@ -802,6 +806,18 @@ const char *pcep_tlv_type_name(enum pcep_object_tlv_types tlv_type)
                return "PATH_SETUP_TYPE";
        case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY:
                return "PATH_SETUP_TYPE_CAPABILITY";
+       case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID:
+               return "SRPOLICY_POL_ID";
+       case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME:
+               return "SRPOLICY_POL_NAME";
+       case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID:
+               return "SRPOLICY_CPATH_ID";
+       case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE:
+               return "SRPOLICY_CPATH_PREFERENCE";
+       case PCEP_OBJ_TLV_TYPE_UNKNOWN:
+               return "UNKNOWN";
+       case PCEP_OBJ_TLV_TYPE_ARBITRARY:
+               return "ARBITRARY";
        default:
                return "UNKNOWN";
        }
index e9d699de47137a906c95e7543da4ad2ba4a22ba0..d7e544b3f0b9cce6683cbd0eec46828cdf9c6ab4 100644 (file)
@@ -35,6 +35,7 @@ DEFINE_MTYPE_STATIC(PATHD, PCEPLIB_MESSAGES, "PCEPlib PCEP Messages");
 #define DEFAULT_LSAP_SETUP_PRIO 4
 #define DEFAULT_LSAP_HOLDING_PRIO 4
 #define DEFAULT_LSAP_LOCAL_PRETECTION false
+#define MAX_PATH_NAME_SIZE 255
 
 /* pceplib logging callback */
 static int pceplib_logging_cb(int level, const char *fmt, va_list args);
@@ -76,8 +77,18 @@ static void pcep_lib_parse_srp(struct path *path, struct pcep_object_srp *srp);
 static void pcep_lib_parse_lsp(struct path *path, struct pcep_object_lsp *lsp);
 static void pcep_lib_parse_lspa(struct path *path,
                                struct pcep_object_lspa *lspa);
+static void pcep_lib_parse_lsp_symbolic_name(
+       struct path *path, struct pcep_object_tlv_symbolic_path_name *tlv);
 static void pcep_lib_parse_metric(struct path *path,
                                  struct pcep_object_metric *obj);
+static void
+pcep_lib_parse_endpoints_ipv4(struct path *path,
+                             struct pcep_object_endpoints_ipv4 *obj);
+static void
+pcep_lib_parse_endpoints_ipv6(struct path *path,
+                             struct pcep_object_endpoints_ipv6 *obj);
+static void pcep_lib_parse_vendor_info(struct path *path,
+                                      struct pcep_object_vendor_info *obj);
 static void pcep_lib_parse_ero(struct path *path, struct pcep_object_ro *ero);
 static struct path_hop *pcep_lib_parse_ero_sr(struct path_hop *next,
                                              struct pcep_ro_subobj_sr *sr);
@@ -160,7 +171,7 @@ pcep_lib_connect(struct ipaddr *src_addr, int src_port, struct ipaddr *dst_addr,
        }
 
        config->support_stateful_pce_lsp_update = true;
-       config->support_pce_lsp_instantiation = false;
+       config->support_pce_lsp_instantiation = pcep_options->pce_initiated;
        config->support_include_db_version = false;
        config->support_lsp_triggered_resync = false;
        config->support_lsp_delta_sync = false;
@@ -381,9 +392,25 @@ struct pcep_message *pcep_lib_format_request(struct pcep_caps *caps,
        }
 }
 
-struct pcep_message *pcep_lib_format_error(int error_type, int error_value)
+struct pcep_message *pcep_lib_format_error(int error_type, int error_value,
+                                          struct path *path)
 {
-       return pcep_msg_create_error(error_type, error_value);
+       double_linked_list *objs, *srp_tlvs;
+       struct pcep_object_srp *srp;
+       struct pcep_object_tlv_header *tlv;
+
+       if ((path == NULL) || (path->srp_id == 0))
+               return pcep_msg_create_error(error_type, error_value);
+
+       objs = dll_initialize();
+       srp_tlvs = dll_initialize();
+       tlv = (struct pcep_object_tlv_header *)pcep_tlv_create_path_setup_type(
+               SR_TE_PST);
+       dll_append(srp_tlvs, tlv);
+       srp = pcep_obj_create_srp(path->do_remove, path->srp_id, srp_tlvs);
+       dll_append(objs, srp);
+       return pcep_msg_create_error_with_objects(error_type, error_value,
+                                                 objs);
 }
 
 struct pcep_message *pcep_lib_format_request_cancelled(uint32_t reqid)
@@ -417,6 +444,9 @@ struct path *pcep_lib_parse_path(struct pcep_message *msg)
        struct pcep_object_metric *metric = NULL;
        struct pcep_object_bandwidth *bandwidth = NULL;
        struct pcep_object_objective_function *of = NULL;
+       struct pcep_object_endpoints_ipv4 *epv4 = NULL;
+       struct pcep_object_endpoints_ipv6 *epv6 = NULL;
+       struct pcep_object_vendor_info *vendor_info = NULL;
 
        path = pcep_new_path();
 
@@ -470,6 +500,21 @@ struct path *pcep_lib_parse_path(struct pcep_message *msg)
                        path->has_pce_objfun = true;
                        path->pce_objfun = of->of_code;
                        break;
+               case CLASS_TYPE(PCEP_OBJ_CLASS_ENDPOINTS,
+                               PCEP_OBJ_TYPE_ENDPOINT_IPV4):
+                       epv4 = (struct pcep_object_endpoints_ipv4 *)obj;
+                       pcep_lib_parse_endpoints_ipv4(path, epv4);
+                       break;
+               case CLASS_TYPE(PCEP_OBJ_CLASS_ENDPOINTS,
+                               PCEP_OBJ_TYPE_ENDPOINT_IPV6):
+                       epv6 = (struct pcep_object_endpoints_ipv6 *)obj;
+                       pcep_lib_parse_endpoints_ipv6(path, epv6);
+                       break;
+               case CLASS_TYPE(PCEP_OBJ_CLASS_VENDOR_INFO,
+                               PCEP_OBJ_TYPE_VENDOR_INFO):
+                       vendor_info = (struct pcep_object_vendor_info *)obj;
+                       pcep_lib_parse_vendor_info(path, vendor_info);
+                       break;
                default:
                        flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_OBJECT,
                                  "Unexpected PCEP object %s (%u) / %s (%u)",
@@ -632,7 +677,8 @@ double_linked_list *pcep_lib_format_path(struct pcep_caps *caps,
                tlv = (struct pcep_object_tlv_header *)
                        pcep_tlv_create_tlv_arbitrary(
                                binding_sid_lsp_tlv_data,
-                               sizeof(binding_sid_lsp_tlv_data), 65505);
+                               sizeof(binding_sid_lsp_tlv_data),
+                               PCEP_OBJ_TYPE_CISCO_BSID);
                assert(tlv != NULL);
                dll_append(lsp_tlvs, tlv);
        }
@@ -904,6 +950,8 @@ void pcep_lib_parse_lsp(struct path *path, struct pcep_object_lsp *lsp)
        double_linked_list *tlvs = lsp->header.tlv_list;
        double_linked_list_node *node;
        struct pcep_object_tlv_header *tlv;
+       struct pcep_object_tlv_symbolic_path_name *name;
+       struct pcep_object_tlv_arbitrary *arb_tlv;
 
        path->plsp_id = lsp->plsp_id;
        path->status = lsp->operational_status;
@@ -919,6 +967,17 @@ void pcep_lib_parse_lsp(struct path *path, struct pcep_object_lsp *lsp)
        for (node = tlvs->head; node != NULL; node = node->next_node) {
                tlv = (struct pcep_object_tlv_header *)node->data;
                switch (tlv->type) {
+               case PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME:
+                       name = (struct pcep_object_tlv_symbolic_path_name *)tlv;
+                       pcep_lib_parse_lsp_symbolic_name(path, name);
+                       break;
+               case PCEP_OBJ_TYPE_CISCO_BSID:
+                       arb_tlv = (struct pcep_object_tlv_arbitrary *)tlv;
+                       memcpy(&path->binding_sid, arb_tlv->data + 2,
+                              sizeof(path->binding_sid));
+                       path->binding_sid = ntohl(path->binding_sid);
+                       path->binding_sid = (path->binding_sid >> 12);
+                       break;
                default:
                        flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
                                  "Unexpected LSP TLV %s (%u)",
@@ -928,6 +987,16 @@ void pcep_lib_parse_lsp(struct path *path, struct pcep_object_lsp *lsp)
        }
 }
 
+void pcep_lib_parse_lsp_symbolic_name(
+       struct path *path, struct pcep_object_tlv_symbolic_path_name *tlv)
+{
+       uint16_t size = tlv->symbolic_path_name_length;
+       assert(path->name == NULL);
+       size = size > MAX_PATH_NAME_SIZE ? MAX_PATH_NAME_SIZE : size;
+       path->name = XCALLOC(MTYPE_PCEP, size);
+       strlcpy((char *)path->name, tlv->symbolic_path_name, size + 1);
+}
+
 void pcep_lib_parse_lspa(struct path *path, struct pcep_object_lspa *lspa)
 {
        path->has_affinity_filters = true;
@@ -952,6 +1021,34 @@ void pcep_lib_parse_metric(struct path *path, struct pcep_object_metric *obj)
        path->first_metric = metric;
 }
 
+void pcep_lib_parse_endpoints_ipv4(struct path *path,
+                                  struct pcep_object_endpoints_ipv4 *obj)
+{
+       SET_IPADDR_V4(&path->pcc_addr);
+       path->pcc_addr.ipaddr_v4 = obj->src_ipv4;
+       SET_IPADDR_V4(&path->nbkey.endpoint);
+       path->nbkey.endpoint.ipaddr_v4 = obj->dst_ipv4;
+}
+
+void pcep_lib_parse_endpoints_ipv6(struct path *path,
+                                  struct pcep_object_endpoints_ipv6 *obj)
+{
+       SET_IPADDR_V6(&path->pcc_addr);
+       path->pcc_addr.ipaddr_v6 = obj->src_ipv6;
+       SET_IPADDR_V6(&path->nbkey.endpoint);
+       path->nbkey.endpoint.ipaddr_v6 = obj->dst_ipv6;
+}
+
+void pcep_lib_parse_vendor_info(struct path *path,
+                               struct pcep_object_vendor_info *obj)
+{
+       if (obj->enterprise_number == ENTERPRISE_NUMBER_CISCO
+           && obj->enterprise_specific_info == ENTERPRISE_COLOR_CISCO)
+               path->nbkey.color = obj->enterprise_specific_info1;
+       else
+               path->nbkey.color = 0;
+}
+
 void pcep_lib_parse_ero(struct path *path, struct pcep_object_ro *ero)
 {
        struct path_hop *hop = NULL;
index 3f34edcb3fbc7df051a1f736b19519b7becf81a4..524f385d140da3a652d3455dce60e42f843de29d 100644 (file)
@@ -37,7 +37,8 @@ struct pcep_message *pcep_lib_format_request(struct pcep_caps *caps,
                                             struct path *path);
 struct pcep_message *pcep_lib_format_request_cancelled(uint32_t reqid);
 
-struct pcep_message *pcep_lib_format_error(int error_type, int error_value);
+struct pcep_message *pcep_lib_format_error(int error_type, int error_value,
+                                          struct path *path);
 struct path *pcep_lib_parse_path(struct pcep_message *msg);
 void pcep_lib_parse_capabilities(struct pcep_message *msg,
                                 struct pcep_caps *caps);
index 779c400b8650ee2f554f19f4926926167fd0fb0d..81a338ac633bd11262422cf5189f69ba73114208 100644 (file)
@@ -93,7 +93,8 @@ static void send_pcep_message(struct pcc_state *pcc_state,
                              struct pcep_message *msg);
 static void send_pcep_error(struct pcc_state *pcc_state,
                            enum pcep_error_type error_type,
-                           enum pcep_error_value error_value);
+                           enum pcep_error_value error_value,
+                           struct path *trigger_path);
 static void send_report(struct pcc_state *pcc_state, struct path *path);
 static void send_comp_request(struct ctrl_state *ctrl_state,
                              struct pcc_state *pcc_state,
@@ -541,8 +542,8 @@ void pcep_pcc_send_report(struct ctrl_state *ctrl_state,
                return;
        }
 
-       PCEP_DEBUG("%s Send report for candidate path %s", pcc_state->tag,
-                  path->name);
+       PCEP_DEBUG("(%s)%s Send report for candidate path %s", __func__,
+                  pcc_state->tag, path->name);
 
        /* ODL and Cisco requires the first reported
         * LSP to have a DOWN status, the later status changes
@@ -555,6 +556,8 @@ void pcep_pcc_send_report(struct ctrl_state *ctrl_state,
        /* 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)) {
+               PCEP_DEBUG("(%s)%s Send report for candidate path (!DOWN) %s",
+                          __func__, pcc_state->tag, path->name);
                path->srp_id = 0;
                path->status = real_status;
                send_report(pcc_state, path);
@@ -564,6 +567,19 @@ void pcep_pcc_send_report(struct ctrl_state *ctrl_state,
 }
 
 
+void pcep_pcc_send_error(struct ctrl_state *ctrl_state,
+                        struct pcc_state *pcc_state, struct pcep_error *error,
+                        bool sub_type)
+{
+
+       PCEP_DEBUG("(%s) Send error after PcInitiated ", __func__);
+
+
+       send_pcep_error(pcc_state, error->error_type, error->error_value,
+                       error->path);
+       pcep_free_path(error->path);
+       XFREE(MTYPE_PCEP, error);
+}
 /* ------------ Timeout handler ------------ */
 
 void pcep_pcc_timeout_handler(struct ctrl_state *ctrl_state,
@@ -651,6 +667,9 @@ void pcep_pcc_pathd_event_handler(struct ctrl_state *ctrl_state,
                PCEP_DEBUG("%s Candidate path %s removed", pcc_state->tag,
                           path->name);
                path->was_removed = true;
+               /* Removed as response to a PcInitiated 'R'emove*/
+               /* RFC 8281 #5.4 LSP Deletion*/
+               path->do_remove = path->was_removed;
                if (pcc_state->caps.is_stateful)
                        send_report(pcc_state, path);
                return;
@@ -1203,14 +1222,113 @@ void handle_pcep_lsp_initiate(struct ctrl_state *ctrl_state,
                              struct pcc_state *pcc_state,
                              struct pcep_message *msg)
 {
-       PCEP_DEBUG("%s Received LSP initiate, not supported yet",
-                  pcc_state->tag);
+       char err[MAX_ERROR_MSG_SIZE] = "";
+       struct path *path;
+
+       path = pcep_lib_parse_path(msg);
+
+       if (!pcc_state->pce_opts->config_opts.pce_initiated) {
+               /* PCE Initiated is not enabled */
+               flog_warn(EC_PATH_PCEP_UNSUPPORTED_PCEP_FEATURE,
+                         "Not allowed PCE initiated path received: %s",
+                         format_pcep_message(msg));
+               send_pcep_error(pcc_state, PCEP_ERRT_LSP_INSTANTIATE_ERROR,
+                               PCEP_ERRV_UNACCEPTABLE_INSTANTIATE_ERROR, path);
+               return;
+       }
 
-       /* TODO when we support both PCC and PCE initiated sessions,
-        *      we should first check the session type before
-        *      rejecting this message. */
-       send_pcep_error(pcc_state, PCEP_ERRT_INVALID_OPERATION,
-                       PCEP_ERRV_LSP_NOT_PCE_INITIATED);
+       if (path->do_remove) {
+               // lookup in nbkey sequential as no endpoint
+               struct nbkey_map_data *key;
+               char endpoint[46];
+
+               frr_each (nbkey_map, &pcc_state->nbkey_map, key) {
+                       ipaddr2str(&key->nbkey.endpoint, endpoint,
+                                  sizeof(endpoint));
+                       flog_warn(
+                               EC_PATH_PCEP_UNSUPPORTED_PCEP_FEATURE,
+                               "FOR_EACH nbkey [color (%d) endpoint (%s)] path [plsp_id (%d)] ",
+                               key->nbkey.color, endpoint, path->plsp_id);
+                       if (path->plsp_id == key->plspid) {
+                               flog_warn(
+                                       EC_PATH_PCEP_UNSUPPORTED_PCEP_FEATURE,
+                                       "FOR_EACH MATCH nbkey [color (%d) endpoint (%s)] path [plsp_id (%d)] ",
+                                       key->nbkey.color, endpoint,
+                                       path->plsp_id);
+                               path->nbkey = key->nbkey;
+                               break;
+                       }
+               }
+       } else {
+               if (path->first_hop == NULL /*ero sets first_hop*/) {
+                       /* If the PCC receives a PCInitiate message without an
+                        * ERO and the R flag in the SRP object != zero, then it
+                        * MUST send a PCErr message with Error-type=6
+                        * (Mandatory Object missing) and Error-value=9 (ERO
+                        * object missing). */
+                       flog_warn(EC_PATH_PCEP_UNSUPPORTED_PCEP_FEATURE,
+                                 "ERO object missing or incomplete : %s",
+                                 format_pcep_message(msg));
+                       send_pcep_error(pcc_state,
+                                       PCEP_ERRT_LSP_INSTANTIATE_ERROR,
+                                       PCEP_ERRV_INTERNAL_ERROR, path);
+                       return;
+               }
+
+               if (path->plsp_id != 0) {
+                       /* If the PCC receives a PCInitiate message with a
+                        * non-zero PLSP-ID and the R flag in the SRP object set
+                        * to zero, then it MUST send a PCErr message with
+                        * Error-type=19 (Invalid Operation) and Error-value=8
+                        * (Non-zero PLSP-ID in the LSP Initiate Request) */
+                       flog_warn(
+                               EC_PATH_PCEP_PROTOCOL_ERROR,
+                               "PCE initiated path with non-zero PLSP ID: %s",
+                               format_pcep_message(msg));
+                       send_pcep_error(pcc_state, PCEP_ERRT_INVALID_OPERATION,
+                                       PCEP_ERRV_LSP_INIT_NON_ZERO_PLSP_ID,
+                                       path);
+                       return;
+               }
+
+               if (path->name == NULL) {
+                       /* If the PCC receives a PCInitiate message without a
+                        * SYMBOLIC-PATH-NAME TLV, then it MUST send a PCErr
+                        * message with Error-type=10 (Reception of an invalid
+                        * object) and Error-value=8 (SYMBOLIC-PATH-NAME TLV
+                        * missing) */
+                       flog_warn(
+                               EC_PATH_PCEP_PROTOCOL_ERROR,
+                               "PCE initiated path without symbolic name: %s",
+                               format_pcep_message(msg));
+                       send_pcep_error(
+                               pcc_state, PCEP_ERRT_RECEPTION_OF_INV_OBJECT,
+                               PCEP_ERRV_SYMBOLIC_PATH_NAME_TLV_MISSING, path);
+                       return;
+               }
+       }
+
+       /* TODO: If there is a conflict with the symbolic path name of an
+        * existing LSP, the PCC MUST send a PCErr message with Error-type=23
+        * (Bad Parameter value) and Error-value=1 (SYMBOLIC-PATH-NAME in
+        * use) */
+
+       specialize_incoming_path(pcc_state, path);
+       /* TODO: Validate the PCC address received from the PCE is valid */
+       PCEP_DEBUG("%s Received LSP initiate", pcc_state->tag);
+       PCEP_DEBUG_PATH("%s", format_path(path));
+
+       if (validate_incoming_path(pcc_state, path, err, sizeof(err))) {
+               pcep_thread_initiate_path(ctrl_state, pcc_state->id, path);
+       } else {
+               /* FIXME: Monitor the amount of errors from the PCE and
+                * possibly disconnect and blacklist */
+               flog_warn(EC_PATH_PCEP_UNSUPPORTED_PCEP_FEATURE,
+                         "Unsupported PCEP protocol feature: %s", err);
+               pcep_free_path(path);
+               send_pcep_error(pcc_state, PCEP_ERRT_INVALID_OPERATION,
+                               PCEP_ERRV_LSP_NOT_PCE_INITIATED, path);
+       }
 }
 
 void handle_pcep_comp_reply(struct ctrl_state *ctrl_state,
@@ -1232,7 +1350,7 @@ void handle_pcep_comp_reply(struct ctrl_state *ctrl_state,
                        pcc_state->tag, path->req_id);
                PCEP_DEBUG_PATH("%s", format_path(path));
                send_pcep_error(pcc_state, PCEP_ERRT_UNKNOWN_REQ_REF,
-                               PCEP_ERRV_UNASSIGNED);
+                               PCEP_ERRV_UNASSIGNED, NULL);
                return;
        }
 
@@ -1447,13 +1565,14 @@ void send_pcep_message(struct pcc_state *pcc_state, struct pcep_message *msg)
 
 void send_pcep_error(struct pcc_state *pcc_state,
                     enum pcep_error_type error_type,
-                    enum pcep_error_value error_value)
+                    enum pcep_error_value error_value,
+                    struct path *trigger_path)
 {
        struct pcep_message *msg;
        PCEP_DEBUG("%s Sending PCEP error type %s (%d) value %s (%d)",
                   pcc_state->tag, pcep_error_type_name(error_type), error_type,
                   pcep_error_value_name(error_type, error_value), error_value);
-       msg = pcep_lib_format_error(error_type, error_value);
+       msg = pcep_lib_format_error(error_type, error_value, trigger_path);
        send_pcep_message(pcc_state, msg);
 }
 
@@ -1504,7 +1623,8 @@ void specialize_outgoing_path(struct pcc_state *pcc_state, struct path *path)
 /* Updates the path for the PCC */
 void specialize_incoming_path(struct pcc_state *pcc_state, struct path *path)
 {
-       set_pcc_address(pcc_state, &path->nbkey, &path->pcc_addr);
+       if (IS_IPADDR_NONE(&path->pcc_addr))
+               set_pcc_address(pcc_state, &path->nbkey, &path->pcc_addr);
        path->sender = pcc_state->pce_opts->addr;
        path->pcc_id = pcc_state->id;
        path->update_origin = SRTE_ORIGIN_PCEP;
@@ -1538,7 +1658,7 @@ bool validate_incoming_path(struct pcc_state *pcc_state, struct path *path,
        }
 
        if (err_type != 0) {
-               send_pcep_error(pcc_state, err_type, err_value);
+               send_pcep_error(pcc_state, err_type, err_value, NULL);
                return false;
        }
 
@@ -1564,7 +1684,6 @@ void send_comp_request(struct ctrl_state *ctrl_state,
        if (!pcc_state->is_best) {
                return;
        }
-       /* TODO: Add a timer to retry the computation request ? */
 
        specialize_outgoing_path(pcc_state, req->path);
 
@@ -1579,10 +1698,7 @@ void send_comp_request(struct ctrl_state *ctrl_state,
        send_pcep_message(pcc_state, msg);
        req->was_sent = true;
 
-       /* TODO: Enable this back when the pcep config changes are merged back
-        */
-       // timeout = pcc_state->pce_opts->config_opts.pcep_request_time_seconds;
-       timeout = 30;
+       timeout = pcc_state->pce_opts->config_opts.pcep_request_time_seconds;
        pcep_thread_schedule_timeout(ctrl_state, pcc_state->id,
                                     TO_COMPUTATION_REQUEST, timeout,
                                     (void *)req, &req->t_retry);
@@ -1641,7 +1757,6 @@ void set_pcc_address(struct pcc_state *pcc_state, struct lsp_nb_key *nbkey,
        }
 }
 
-
 /* ------------ Data Structure Helper Functions ------------ */
 
 void lookup_plspid(struct pcc_state *pcc_state, struct path *path)
index ceac6f32781013c169103a3bcb3cc63bf0678b96..9e712baf16a5ad94b163a9fc02dc468729eaeea9 100644 (file)
@@ -125,6 +125,9 @@ 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,
                          bool is_stable);
+void pcep_pcc_send_error(struct ctrl_state *ctrl_state,
+                        struct pcc_state *pcc_state, struct pcep_error *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,