+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2020 NetDEF, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "pceplib/pcep_utils_counters.h"
+#include "memory.h"
#include "log.h"
#include "command.h"
#include "libfrr.h"
#include "printfrr.h"
-#include "version.h"
+#include "lib/version.h"
#include "northbound.h"
#include "frr_pthread.h"
#include "jhash.h"
#include "pathd/pathd.h"
#include "pathd/path_errors.h"
-#include "pathd/path_pcep_memory.h"
#include "pathd/path_pcep.h"
#include "pathd/path_pcep_cli.h"
#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");
/*
* Globals.
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);
ret = pcep_main_event_remove_candidate_segments(
(const char *)payload, true);
break;
- default:
+ case PCEP_MAIN_EVENT_UNDEFINED:
flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
"Unexpected event received in the main thread: %u",
type);
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;
}
/* ------------ Module Functions ------------ */
-int pcep_module_late_init(struct thread_master *tm)
+/* this creates threads, therefore must run after fork(). but it must also
+ * run before config load, so the CLI commands don't try to touch things that
+ * aren't set up yet...
+ */
+static int pcep_module_config_pre(struct thread_master *tm)
{
assert(pcep_g->fpt == NULL);
assert(pcep_g->master == NULL);
pcep_g->master = tm;
pcep_g->fpt = fpt;
+ return 0;
+}
+
+static int pcep_module_late_init(struct thread_master *tm)
+{
hook_register(pathd_candidate_created, pathd_candidate_created_handler);
hook_register(pathd_candidate_updated, pathd_candidate_updated_handler);
hook_register(pathd_candidate_removed, pathd_candidate_removed_handler);
+ hook_register(frr_config_pre, pcep_module_config_pre);
hook_register(frr_fini, pcep_module_finish);
pcep_cli_init();