summaryrefslogtreecommitdiffstats
path: root/pathd/path_pcep_pcc.c
diff options
context:
space:
mode:
authorJavier Garcia <javier.garcia@voltanet.io>2021-05-21 09:15:52 +0200
committerJavier Garcia <javier.garcia@voltanet.io>2021-06-22 12:04:03 +0200
commit56634922390ff08d2ae06ecb0c32f94c07028561 (patch)
tree2c1fb1080e2b0dbd5397c8bbfba2d668d9fb116a /pathd/path_pcep_pcc.c
parentpceplib: Extract fields needed for PcInitiated with Cisco pce. (1/4) (diff)
downloadfrr-56634922390ff08d2ae06ecb0c32f94c07028561.tar.xz
frr-56634922390ff08d2ae06ecb0c32f94c07028561.zip
pathd: Handle PCInitiated messages, thread controller. (2/4)
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>
Diffstat (limited to 'pathd/path_pcep_pcc.c')
-rw-r--r--pathd/path_pcep_pcc.c157
1 files changed, 136 insertions, 21 deletions
diff --git a/pathd/path_pcep_pcc.c b/pathd/path_pcep_pcc.c
index 779c400b8..81a338ac6 100644
--- a/pathd/path_pcep_pcc.c
+++ b/pathd/path_pcep_pcc.c
@@ -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)