diff options
Diffstat (limited to 'pathd')
-rw-r--r-- | pathd/path_cli.c | 76 | ||||
-rw-r--r-- | pathd/path_main.c | 17 | ||||
-rw-r--r-- | pathd/path_nb.c | 4 | ||||
-rw-r--r-- | pathd/path_nb_config.c | 44 | ||||
-rw-r--r-- | pathd/path_pcep.h | 1 | ||||
-rw-r--r-- | pathd/path_pcep_cli.c | 356 | ||||
-rw-r--r-- | pathd/path_zebra.c | 5 |
7 files changed, 392 insertions, 111 deletions
diff --git a/pathd/path_cli.c b/pathd/path_cli.c index 45f4ac7..e22931c 100644 --- a/pathd/path_cli.c +++ b/pathd/path_cli.c @@ -287,7 +287,7 @@ void cli_show_srte_segment_list(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " segment-list %s\n", - yang_dnode_get_string(dnode, "./name")); + yang_dnode_get_string(dnode, "name")); } void cli_show_srte_segment_list_end(struct vty *vty, @@ -546,37 +546,37 @@ void cli_show_srte_segment_list_segment(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - vty_out(vty, " index %s", yang_dnode_get_string(dnode, "./index")); - if (yang_dnode_exists(dnode, "./sid-value")) { + vty_out(vty, " index %s", yang_dnode_get_string(dnode, "index")); + if (yang_dnode_exists(dnode, "sid-value")) { vty_out(vty, " mpls label %s", - yang_dnode_get_string(dnode, "./sid-value")); + yang_dnode_get_string(dnode, "sid-value")); } - if (yang_dnode_exists(dnode, "./nai")) { + if (yang_dnode_exists(dnode, "nai")) { struct ipaddr addr; struct ipaddr addr_rmt; - switch (yang_dnode_get_enum(dnode, "./nai/type")) { + switch (yang_dnode_get_enum(dnode, "nai/type")) { case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE: case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE: case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM: - yang_dnode_get_ip(&addr, dnode, "./nai/local-address"); + yang_dnode_get_ip(&addr, dnode, "nai/local-address"); vty_out(vty, " nai prefix %pI4", &addr.ipaddr_v4); break; case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE: case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE: case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM: - yang_dnode_get_ip(&addr, dnode, "./nai/local-address"); + yang_dnode_get_ip(&addr, dnode, "nai/local-address"); vty_out(vty, " nai prefix %pI6", &addr.ipaddr_v6); break; case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY: - yang_dnode_get_ip(&addr, dnode, "./nai/local-address"); + yang_dnode_get_ip(&addr, dnode, "nai/local-address"); yang_dnode_get_ip(&addr_rmt, dnode, "./nai/remote-address"); vty_out(vty, " nai adjacency %pI4", &addr.ipaddr_v4); vty_out(vty, " %pI4", &addr_rmt.ipaddr_v4); break; case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY: - yang_dnode_get_ip(&addr, dnode, "./nai/local-address"); + yang_dnode_get_ip(&addr, dnode, "nai/local-address"); yang_dnode_get_ip(&addr_rmt, dnode, "./nai/remote-address"); vty_out(vty, " nai adjacency %pI6", &addr.ipaddr_v6); @@ -585,17 +585,17 @@ void cli_show_srte_segment_list_segment(struct vty *vty, default: break; } - if (yang_dnode_exists(dnode, "./nai/local-prefix-len")) { + if (yang_dnode_exists(dnode, "nai/local-prefix-len")) { vty_out(vty, "/%s", yang_dnode_get_string( dnode, "./nai/local-prefix-len")); } - if (yang_dnode_exists(dnode, "./nai/local-interface")) { + if (yang_dnode_exists(dnode, "nai/local-interface")) { vty_out(vty, " iface %s", yang_dnode_get_string(dnode, "./nai/local-interface")); } - if (yang_dnode_exists(dnode, "./nai/algorithm")) { + if (yang_dnode_exists(dnode, "nai/algorithm")) { vty_out(vty, " algorithm %s", yang_dnode_get_string(dnode, "./nai/algorithm")); @@ -658,8 +658,8 @@ void cli_show_srte_policy(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " policy color %s endpoint %s\n", - yang_dnode_get_string(dnode, "./color"), - yang_dnode_get_string(dnode, "./endpoint")); + yang_dnode_get_string(dnode, "color"), + yang_dnode_get_string(dnode, "endpoint")); } void cli_show_srte_policy_end(struct vty *vty, const struct lyd_node *dnode) @@ -860,7 +860,7 @@ DEFPY(srte_candidate_no_affinity_filter, srte_candidate_no_affinity_filter_cmd, DEFPY(srte_candidate_metric, srte_candidate_metric_cmd, - "metric [bound$bound] <igp|te|hc|abc|lmll|cigp|cte|pigp|pte|phc|msd|pd|pdv|pl|ppd|ppdv|ppl|nap|nlp|dc|bnc>$type METRIC$value [required$required]", + "metric [bound$bound] <igp|te|hc|abc|lmll|cigp|cte|pigp|pte|phc|msd|pd|pdv|pl|ppd|ppdv|ppl|nap|nlp|dc|bnc>$type METRIC$value [required$required] [computed$computed]", "Define a metric constraint\n" "If the metric is bounded\n" "IGP metric\n" @@ -885,7 +885,8 @@ DEFPY(srte_candidate_metric, "Domain Count metric\n" "Border Node Count metric\n" "Metric value\n" - "Required constraint\n") + "Required constraint\n" + "Force the PCE to provide the computed path metric\n") { char xpath[XPATH_CANDIDATE_MAXLEN]; snprintf(xpath, sizeof(xpath), "./constraints/metrics[type='%s']/value", @@ -899,12 +900,16 @@ DEFPY(srte_candidate_metric, "./constraints/metrics[type='%s']/required", type); nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, required ? "true" : "false"); + snprintf(xpath, sizeof(xpath), + "./constraints/metrics[type='%s']/is-computed", type); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, + computed ? "true" : "false"); return nb_cli_apply_changes(vty, NULL); } DEFPY(srte_candidate_no_metric, srte_candidate_no_metric_cmd, - "no metric [bound] <igp|te|hc|abc|lmll|cigp|cte|pigp|pte|phc|msd|pd|pdv|pl|ppd|ppdv|ppl|nap|nlp|dc|bnc>$type [METRIC$value] [required$required]", + "no metric [bound] <igp|te|hc|abc|lmll|cigp|cte|pigp|pte|phc|msd|pd|pdv|pl|ppd|ppdv|ppl|nap|nlp|dc|bnc>$type [METRIC$value] [required$required] [computed$computed]", NO_STR "Remove a metric constraint\n" "If the metric is bounded\n" @@ -930,7 +935,8 @@ DEFPY(srte_candidate_no_metric, "Domain Count metric\n" "Border Node Count metric\n" "Metric value\n" - "Required constraint\n") + "Required constraint\n" + "Force the PCE to provide the computed path metric\n") { char xpath[XPATH_CANDIDATE_MAXLEN]; snprintf(xpath, sizeof(xpath), "./constraints/metrics[type='%s']", @@ -1164,7 +1170,8 @@ static void config_write_float(struct vty *vty, float value) static void config_write_metric(struct vty *vty, enum srte_candidate_metric_type type, - float value, bool required, bool is_bound) + float value, bool required, bool is_bound, + bool is_computed) { const char *name = metric_type_name(type); if (name == NULL) @@ -1173,6 +1180,7 @@ static void config_write_metric(struct vty *vty, metric_type_name(type)); config_write_float(vty, value); vty_out(vty, required ? " required" : ""); + vty_out(vty, is_computed ? " computed" : ""); vty_out(vty, "\n"); } @@ -1180,16 +1188,18 @@ static int config_write_metric_cb(const struct lyd_node *dnode, void *arg) { struct vty *vty = arg; enum srte_candidate_metric_type type; - bool required, is_bound = false; + bool required, is_bound = false, is_computed = false; float value; - type = yang_dnode_get_enum(dnode, "./type"); - value = (float)yang_dnode_get_dec64(dnode, "./value"); - required = yang_dnode_get_bool(dnode, "./required"); - if (yang_dnode_exists(dnode, "./is-bound")) - is_bound = yang_dnode_get_bool(dnode, "./is-bound"); + type = yang_dnode_get_enum(dnode, "type"); + value = (float)yang_dnode_get_dec64(dnode, "value"); + required = yang_dnode_get_bool(dnode, "required"); + if (yang_dnode_exists(dnode, "is-bound")) + is_bound = yang_dnode_get_bool(dnode, "is-bound"); + if (yang_dnode_exists(dnode, "is-computed")) + is_computed = yang_dnode_get_bool(dnode, "is-computed"); - config_write_metric(vty, type, value, required, is_bound); + config_write_metric(vty, type, value, required, is_bound, is_computed); return YANG_ITER_CONTINUE; } @@ -1201,18 +1211,18 @@ void cli_show_srte_policy_candidate_path(struct vty *vty, uint32_t affinity; bool required; enum objfun_type objfun_type; - const char *type = yang_dnode_get_string(dnode, "./type"); + const char *type = yang_dnode_get_string(dnode, "type"); vty_out(vty, " candidate-path preference %s name %s %s", - yang_dnode_get_string(dnode, "./preference"), - yang_dnode_get_string(dnode, "./name"), type); + yang_dnode_get_string(dnode, "preference"), + yang_dnode_get_string(dnode, "name"), type); if (strmatch(type, "explicit")) vty_out(vty, " segment-list %s", - yang_dnode_get_string(dnode, "./segment-list-name")); + yang_dnode_get_string(dnode, "segment-list-name")); vty_out(vty, "\n"); if (strmatch(type, "dynamic")) { - if (yang_dnode_exists(dnode, "./constraints/bandwidth")) { + if (yang_dnode_exists(dnode, "constraints/bandwidth")) { bandwidth = (float)yang_dnode_get_dec64( dnode, "./constraints/bandwidth/value"); required = yang_dnode_get_bool( @@ -1262,7 +1272,7 @@ void cli_show_srte_policy_candidate_path(struct vty *vty, void cli_show_srte_policy_candidate_path_end(struct vty *vty, const struct lyd_node *dnode) { - const char *type = yang_dnode_get_string(dnode, "./type"); + const char *type = yang_dnode_get_string(dnode, "type"); if (strmatch(type, "dynamic")) vty_out(vty, " exit\n"); diff --git a/pathd/path_main.c b/pathd/path_main.c index c333162..fe636c5 100644 --- a/pathd/path_main.c +++ b/pathd/path_main.c @@ -95,17 +95,20 @@ static const struct frr_yang_module_info *pathd_yang_modules[] = { &frr_pathd_info, }; -#define PATH_VTY_PORT 2621 +/* clang-format off */ +FRR_DAEMON_INFO(pathd, PATH, + .vty_port = PATH_VTY_PORT, + .proghelp = "Implementation of PATH.", -FRR_DAEMON_INFO(pathd, PATH, .vty_port = PATH_VTY_PORT, + .signals = path_signals, + .n_signals = array_size(path_signals), - .proghelp = "Implementation of PATH.", + .privs = &pathd_privs, - .signals = path_signals, .n_signals = array_size(path_signals), - - .privs = &pathd_privs, .yang_modules = pathd_yang_modules, - .n_yang_modules = array_size(pathd_yang_modules), + .yang_modules = pathd_yang_modules, + .n_yang_modules = array_size(pathd_yang_modules), ); +/* clang-format on */ int main(int argc, char **argv, char **envp) { diff --git a/pathd/path_nb.c b/pathd/path_nb.c index 9e91957..e1c0cc3 100644 --- a/pathd/path_nb.c +++ b/pathd/path_nb.c @@ -313,8 +313,8 @@ int iter_objfun_cb(const struct lyd_node *dnode, void *arg) pref = &of_arg->prefs[of_arg->free_slot++]; - pref->index = yang_dnode_get_uint32(dnode, "./index"); - pref->type = yang_dnode_get_enum(dnode, "./type"); + pref->index = yang_dnode_get_uint32(dnode, "index"); + pref->type = yang_dnode_get_enum(dnode, "type"); /* Simplistic insertion sort */ p = &of_arg->first; diff --git a/pathd/path_nb_config.c b/pathd/path_nb_config.c index ad24f23..48531ba 100644 --- a/pathd/path_nb_config.c +++ b/pathd/path_nb_config.c @@ -31,7 +31,7 @@ int pathd_srte_segment_list_create(struct nb_cb_create_args *args) if (args->event != NB_EV_APPLY) return NB_OK; - name = yang_dnode_get_string(args->dnode, "./name"); + name = yang_dnode_get_string(args->dnode, "name"); segment_list = srte_segment_list_add(name); nb_running_set_entry(args->dnode, segment_list); SET_FLAG(segment_list->flags, F_SEGMENT_LIST_NEW); @@ -104,7 +104,7 @@ int pathd_srte_segment_list_segment_create(struct nb_cb_create_args *args) return NB_OK; segment_list = nb_running_get_entry(args->dnode, NULL, true); - index = yang_dnode_get_uint32(args->dnode, "./index"); + index = yang_dnode_get_uint32(args->dnode, "index"); segment = srte_segment_entry_add(segment_list, index); nb_running_set_entry(args->dnode, segment); SET_FLAG(segment_list->flags, F_SEGMENT_LIST_MODIFIED); @@ -191,9 +191,9 @@ void pathd_srte_segment_list_segment_nai_apply_finish( const char *algo_buf, *local_prefix_len_buf; segment = nb_running_get_entry(args->dnode, NULL, true); - type = yang_dnode_get_enum(args->dnode, "./type"); + type = yang_dnode_get_enum(args->dnode, "type"); - yang_dnode_get_ip(&local_addr, args->dnode, "./local-address"); + yang_dnode_get_ip(&local_addr, args->dnode, "local-address"); switch (type) { case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE: @@ -208,12 +208,12 @@ void pathd_srte_segment_list_segment_nai_apply_finish( yang_dnode_get_ip(&remote_addr, args->dnode, "./remote-address"); local_iface = - yang_dnode_get_uint32(args->dnode, "./local-interface"); + yang_dnode_get_uint32(args->dnode, "local-interface"); remote_iface = yang_dnode_get_uint32(args->dnode, "./remote-interface"); break; case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM: - algo_buf = yang_dnode_get_string(args->dnode, "./algorithm"); + algo_buf = yang_dnode_get_string(args->dnode, "algorithm"); algo = atoi(algo_buf); local_prefix_len_buf = yang_dnode_get_string( args->dnode, "./local-prefix-len"); @@ -221,7 +221,7 @@ void pathd_srte_segment_list_segment_nai_apply_finish( break; case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE: local_iface = - yang_dnode_get_uint32(args->dnode, "./local-interface"); + yang_dnode_get_uint32(args->dnode, "local-interface"); local_prefix_len_buf = yang_dnode_get_string( args->dnode, "./local-prefix-len"); local_prefix_len = atoi(local_prefix_len_buf); @@ -254,8 +254,8 @@ int pathd_srte_policy_create(struct nb_cb_create_args *args) if (args->event != NB_EV_APPLY) return NB_OK; - color = yang_dnode_get_uint32(args->dnode, "./color"); - yang_dnode_get_ip(&endpoint, args->dnode, "./endpoint"); + color = yang_dnode_get_uint32(args->dnode, "color"); + yang_dnode_get_ip(&endpoint, args->dnode, "endpoint"); policy = srte_policy_add(color, &endpoint, SRTE_ORIGIN_LOCAL, NULL); nb_running_set_entry(args->dnode, policy); @@ -377,7 +377,7 @@ int pathd_srte_policy_candidate_path_create(struct nb_cb_create_args *args) return NB_OK; policy = nb_running_get_entry(args->dnode, NULL, true); - preference = yang_dnode_get_uint32(args->dnode, "./preference"); + preference = yang_dnode_get_uint32(args->dnode, "preference"); candidate = srte_candidate_add(policy, preference, SRTE_ORIGIN_LOCAL, NULL); nb_running_set_entry(args->dnode, candidate); @@ -539,7 +539,7 @@ int pathd_srte_policy_candidate_path_metrics_destroy( assert(args->context != NULL); candidate = nb_running_get_entry(args->dnode, NULL, true); - type = yang_dnode_get_enum(args->dnode, "./type"); + type = yang_dnode_get_enum(args->dnode, "type"); srte_candidate_unset_metric(candidate, type); return NB_OK; @@ -557,13 +557,13 @@ void pathd_srte_policy_candidate_path_metrics_apply_finish( candidate = nb_running_get_entry(args->dnode, NULL, true); - type = yang_dnode_get_enum(args->dnode, "./type"); - value = (float)yang_dnode_get_dec64(args->dnode, "./value"); - required = yang_dnode_get_bool(args->dnode, "./required"); - if (yang_dnode_exists(args->dnode, "./is-bound")) - is_bound = yang_dnode_get_bool(args->dnode, "./is-bound"); - if (yang_dnode_exists(args->dnode, "./is-computed")) - is_computed = yang_dnode_get_bool(args->dnode, "./is-computed"); + type = yang_dnode_get_enum(args->dnode, "type"); + value = (float)yang_dnode_get_dec64(args->dnode, "value"); + required = yang_dnode_get_bool(args->dnode, "required"); + if (yang_dnode_exists(args->dnode, "is-bound")) + is_bound = yang_dnode_get_bool(args->dnode, "is-bound"); + if (yang_dnode_exists(args->dnode, "is-computed")) + is_computed = yang_dnode_get_bool(args->dnode, "is-computed"); srte_candidate_set_metric(candidate, type, value, required, is_bound, is_computed); @@ -597,8 +597,8 @@ void pathd_srte_policy_candidate_path_objfun_apply_finish( bool required; candidate = nb_running_get_entry(args->dnode, NULL, true); - required = yang_dnode_get_bool(args->dnode, "./required"); - type = yang_dnode_get_enum(args->dnode, "./type"); + required = yang_dnode_get_bool(args->dnode, "required"); + type = yang_dnode_get_enum(args->dnode, "type"); srte_candidate_set_objfun(candidate, required, type); } @@ -739,8 +739,8 @@ void pathd_srte_policy_candidate_path_bandwidth_apply_finish( assert(args->context != NULL); candidate = nb_running_get_entry(args->dnode, NULL, true); - value = (float)yang_dnode_get_dec64(args->dnode, "./value"); - required = yang_dnode_get_bool(args->dnode, "./required"); + value = (float)yang_dnode_get_dec64(args->dnode, "value"); + required = yang_dnode_get_bool(args->dnode, "required"); srte_candidate_set_bandwidth(candidate, value, required); } diff --git a/pathd/path_pcep.h b/pathd/path_pcep.h index 5c6a023..d6dbcb5 100644 --- a/pathd/path_pcep.h +++ b/pathd/path_pcep.h @@ -25,6 +25,7 @@ DECLARE_MTYPE(PCEP); #define PCEP_DEBUG_MODE_PATH 0x02 #define PCEP_DEBUG_MODE_PCEP 0x04 #define PCEP_DEBUG_MODE_PCEPLIB 0x08 +#define PCEP_DEBUG_MODE_ALL 0x0F #define PCEP_DEBUG(fmt, ...) \ do { \ if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_BASIC)) \ diff --git a/pathd/path_pcep_cli.c b/pathd/path_pcep_cli.c index c46649b..47a811d 100644 --- a/pathd/path_pcep_cli.c +++ b/pathd/path_pcep_cli.c @@ -43,6 +43,8 @@ #define DEFAULT_TIMER_SESSION_TIMEOUT_INTERVAL 30 #define DEFAULT_DELEGATION_TIMEOUT_INTERVAL 10 +#define BUFFER_PCC_PCE_SIZE 1024 + /* CLI Function declarations */ static int pcep_cli_debug_config_write(struct vty *vty); static int pcep_cli_debug_set_all(uint32_t flags, bool set); @@ -73,6 +75,9 @@ static void print_pcep_capabilities(char *buf, size_t buf_len, pcep_configuration *config); static void print_pcep_session(struct vty *vty, struct pce_opts *pce_opts, struct pcep_pcc_info *pcc_info); +static void print_pcep_session_json(struct vty *vty, struct pce_opts *pce_opts, + struct pcep_pcc_info *pcc_info, + json_object *json); static bool pcep_cli_pcc_has_pce(const char *pce_name); static void pcep_cli_add_pce_connection(struct pce_opts *pce_opts); static void pcep_cli_remove_pce_connection(struct pce_opts *pce_opts); @@ -458,28 +463,32 @@ static void pcep_cli_remove_pce_connection(struct pce_opts *pce_opts) * VTY command implementations */ -static int path_pcep_cli_debug(struct vty *vty, const char *no_str, - const char *basic_str, const char *path_str, - const char *message_str, const char *pceplib_str) +static int path_pcep_cli_debug(struct vty *vty, const char *debug_type, bool set) { uint32_t mode = DEBUG_NODE2MODE(vty->node); - bool no = (no_str != NULL); - - DEBUG_MODE_SET(&pcep_g->dbg, mode, !no); - if (basic_str != NULL) { - DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_BASIC, !no); - } - if (path_str != NULL) { - DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PATH, !no); - } - if (message_str != NULL) { - DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEP, !no); - } - if (pceplib_str != NULL) { - DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEPLIB, !no); + /* Global Set */ + if (debug_type == NULL) { + DEBUG_MODE_SET(&pcep_g->dbg, mode, set); + DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_ALL, set); + return CMD_SUCCESS; } + DEBUG_MODE_SET(&pcep_g->dbg, mode, true); + + if (strcmp(debug_type, "basic") == 0) + DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_BASIC, set); + else if (strcmp(debug_type, "path") == 0) + DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PATH, set); + else if (strcmp(debug_type, "message") == 0) + DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEP, set); + else if (strcmp(debug_type, "pceplib") == 0) + DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEPLIB, set); + + /* Unset the pcep debug mode if there is no flag at least set*/ + if (!DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_ALL)) + DEBUG_MODE_SET(&pcep_g->dbg, mode, false); + return CMD_SUCCESS; } @@ -1022,7 +1031,7 @@ static int path_pcep_cli_pcc_pcc_msd(struct vty *vty, const char *msd_str, { if (reset) pcc_msd_configured_g = false; - else { + else if (msd_str) { pcc_msd_configured_g = true; PCEP_VTYSH_INT_ARG_CHECK(msd_str, msd, pcc_msd_g, 0, 33); } @@ -1183,10 +1192,188 @@ static void print_pcep_capabilities(char *buf, size_t buf_len, } /* Internal util function to print a pcep session */ +static void print_pcep_session_json(struct vty *vty, struct pce_opts *pce_opts, + struct pcep_pcc_info *pcc_info, + json_object *json) +{ + char buf[BUFFER_PCC_PCE_SIZE] = {}; + int index = 0; + pcep_session *session; + struct pcep_config_group_opts *config_opts; + struct counters_group *group; + + /* PCE IP */ + if (IS_IPADDR_V4(&pce_opts->addr)) + json_object_string_addf(json, "pceAddress", "%pI4", + &pce_opts->addr.ipaddr_v4); + else if (IS_IPADDR_V6(&pce_opts->addr)) + json_object_string_addf(json, "pceAddress", "%pI6", + &pce_opts->addr.ipaddr_v6); + json_object_int_add(json, "pcePort", pce_opts->port); + + /* PCC IP */ + if (IS_IPADDR_V4(&pcc_info->pcc_addr)) + json_object_string_addf(json, "pccAddress", "%pI4", + &pcc_info->pcc_addr.ipaddr_v4); + else if (IS_IPADDR_V6(&pcc_info->pcc_addr)) + json_object_string_addf(json, "pccAddress", "%pI6", + &pcc_info->pcc_addr.ipaddr_v6); + + json_object_int_add(json, "pccPort", pcc_info->pcc_port); + json_object_int_add(json, "pccMsd", pcc_info->msd); + + if (pcc_info->status == PCEP_PCC_OPERATING) + json_object_string_add(json, "sessionStatus", "UP"); + else + json_object_string_add(json, "sessionStatus", + pcc_status_name(pcc_info->status)); + + json_object_boolean_add(json, "bestMultiPce", + pcc_info->is_best_multi_pce); + json_object_int_add(json, "precedence", + pcc_info->precedence > 0 ? pcc_info->precedence + : DEFAULT_PCE_PRECEDENCE); + json_object_string_add(json, "confidence", + pcc_info->previous_best ? "low" : "normal"); + + /* PCEPlib pcep session values, get a thread safe copy of the counters + */ + session = pcep_ctrl_get_pcep_session(pcep_g->fpt, pcc_info->pcc_id); + + /* Config Options values */ + config_opts = &pce_opts->config_opts; + json_object_int_add(json, "keepaliveConfig", + config_opts->keep_alive_seconds); + json_object_int_add(json, "deadTimerConfig", + config_opts->dead_timer_seconds); + json_object_int_add(json, "pccPcepRequestTimerConfig", + config_opts->pcep_request_time_seconds); + json_object_int_add(json, "sessionTimeoutIntervalSec", + config_opts->session_timeout_inteval_seconds); + json_object_int_add(json, "delegationTimeout", + config_opts->delegation_timeout_seconds); + json_object_boolean_add(json, "tcpMd5Authentication", + (strlen(config_opts->tcp_md5_auth) > 0)); + if (strlen(config_opts->tcp_md5_auth) > 0) + json_object_string_add(json, "tcpMd5AuthenticationString", + config_opts->tcp_md5_auth); + json_object_boolean_add(json, "draft07", !!config_opts->draft07); + json_object_boolean_add(json, "draft16AndRfc8408", + !config_opts->draft07); + + json_object_int_add(json, "nextPcRequestId", pcc_info->next_reqid); + /* original identifier used by the PCC for LSP instantiation */ + json_object_int_add(json, "nextPLspId", pcc_info->next_plspid); + + if (session != NULL) { + json_object_int_add(json, "sessionKeepalivePceNegotiatedSec", + session->pcc_config + .keep_alive_pce_negotiated_timer_seconds); + json_object_int_add(json, "sessionDeadTimerPceNegotiatedSec", + session->pcc_config + .dead_timer_pce_negotiated_seconds); + if (pcc_info->status == PCEP_PCC_SYNCHRONIZING || + pcc_info->status == PCEP_PCC_OPERATING) { + time_t current_time = time(NULL); + struct tm lt = { 0 }; + /* Just for the timezone */ + localtime_r(¤t_time, <); + gmtime_r(&session->time_connected, <); + json_object_int_add(json, "sessionConnectionDurationSec", + (uint32_t)(current_time - + session->time_connected)); + json_object_string_addf(json, + "sessionConnectionStartTimeUTC", + "%d-%02d-%02d %02d:%02d:%02d", + lt.tm_year + 1900, lt.tm_mon + 1, + lt.tm_mday, lt.tm_hour, + lt.tm_min, lt.tm_sec); + } + + /* PCC capabilities */ + buf[0] = '\0'; + + if (config_opts->pce_initiated) + index += csnprintfrr(buf, sizeof(buf), "%s", + PCEP_CLI_CAP_PCC_PCE_INITIATED); + else + index += csnprintfrr(buf, sizeof(buf), "%s", + PCEP_CLI_CAP_PCC_INITIATED); + print_pcep_capabilities(buf, sizeof(buf) - index, + &session->pcc_config); + json_object_string_add(json, "pccCapabilities", buf); + + /* PCE capabilities */ + buf[0] = '\0'; + print_pcep_capabilities(buf, sizeof(buf), &session->pce_config); + if (buf[0] != '\0') + json_object_string_add(json, "pceCapabilities", buf); + XFREE(MTYPE_PCEP, session); + } else { + json_object_string_add(json, "warningSession", + "Detailed session information not available."); + } + + /* Message Counters, get a thread safe copy of the counters */ + group = pcep_ctrl_get_counters(pcep_g->fpt, pcc_info->pcc_id); + + if (group != NULL) { + struct counters_subgroup *rx_msgs = + find_subgroup(group, COUNTER_SUBGROUP_ID_RX_MSG); + struct counters_subgroup *tx_msgs = + find_subgroup(group, COUNTER_SUBGROUP_ID_TX_MSG); + json_object *json_counter; + struct counter *tx_counter, *rx_counter; + + if (rx_msgs != NULL) { + json_counter = json_object_new_object(); + for (int i = 0; i < rx_msgs->max_counters; i++) { + rx_counter = rx_msgs->counters[i]; + + if (rx_counter && + rx_counter->counter_name_json[0] != '\0') + json_object_int_add( + json_counter, + rx_counter->counter_name_json, + rx_counter->counter_value); + } + json_object_int_add(json_counter, "total", + subgroup_counters_total(rx_msgs)); + json_object_object_add(json, "messageStatisticsReceived", + json_counter); + } + if (tx_msgs != NULL) { + json_counter = json_object_new_object(); + for (int i = 0; i < tx_msgs->max_counters; i++) { + tx_counter = tx_msgs->counters[i]; + + if (tx_counter && + tx_counter->counter_name_json[0] != '\0') + json_object_int_add( + json_counter, + tx_counter->counter_name_json, + tx_counter->counter_value); + } + json_object_int_add(json_counter, "total", + subgroup_counters_total(tx_msgs)); + json_object_object_add(json, "messageStatisticsSent", + json_counter); + } + pcep_lib_free_counters(group); + } else { + json_object_string_add(json, "messageStatisticsWarning", + "Counters not available."); + } + + XFREE(MTYPE_PCEP, pcc_info); +} + +/* Internal util function to print a pcep session */ static void print_pcep_session(struct vty *vty, struct pce_opts *pce_opts, struct pcep_pcc_info *pcc_info) { char buf[1024]; + buf[0] = '\0'; vty_out(vty, "\nPCE %s\n", pce_opts->pce_name); @@ -1237,6 +1424,7 @@ static void print_pcep_session(struct vty *vty, struct pce_opts *pce_opts, /* Config Options values */ struct pcep_config_group_opts *config_opts = &pce_opts->config_opts; + if (session != NULL) { vty_out(vty, " Timer: KeepAlive config %d, pce-negotiated %d\n", config_opts->keep_alive_seconds, @@ -1352,34 +1540,66 @@ static void print_pcep_session(struct vty *vty, struct pce_opts *pce_opts, } static int path_pcep_cli_show_srte_pcep_session(struct vty *vty, - const char *pcc_peer) + const char *pcc_peer, bool uj) { struct pce_opts_cli *pce_opts_cli; struct pcep_pcc_info *pcc_info; + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); /* Only show 1 PCEP session */ if (pcc_peer != NULL) { + if (json) + json_object_string_add(json, "pceName", pcc_peer); pce_opts_cli = pcep_cli_find_pce(pcc_peer); if (pce_opts_cli == NULL) { - vty_out(vty, "%% PCE [%s] does not exist.\n", pcc_peer); + if (json) { + json_object_string_addf(json, "warning", + "PCE [%s] does not exist.", + pcc_peer); + vty_json(vty, json); + } else + vty_out(vty, "%% PCE [%s] does not exist.\n", + pcc_peer); return CMD_WARNING; } if (!pcep_cli_pcc_has_pce(pcc_peer)) { - vty_out(vty, "%% PCC is not connected to PCE [%s].\n", - pcc_peer); + if (json) { + json_object_string_addf(json, "warning", + "PCC is not connected to PCE [%s].", + pcc_peer); + vty_json(vty, json); + } else + vty_out(vty, + "%% PCC is not connected to PCE [%s].\n", + pcc_peer); return CMD_WARNING; } pcc_info = pcep_ctrl_get_pcc_info(pcep_g->fpt, pcc_peer); if (pcc_info == NULL) { - vty_out(vty, - "%% Cannot retrieve PCEP session info for PCE [%s]\n", - pcc_peer); + if (json) { + json_object_string_addf(json, "warning", + "Cannot retrieve PCEP session info for PCE [%s].", + pcc_peer); + vty_json(vty, json); + } else + vty_out(vty, + "%% Cannot retrieve PCEP session info for PCE [%s]\n", + pcc_peer); return CMD_WARNING; } - print_pcep_session(vty, &pce_opts_cli->pce_opts, pcc_info); + if (json) { + print_pcep_session_json(vty, &pce_opts_cli->pce_opts, + pcc_info, json); + vty_json(vty, json); + } else + print_pcep_session(vty, &pce_opts_cli->pce_opts, + pcc_info); return CMD_SUCCESS; } @@ -1388,29 +1608,56 @@ static int path_pcep_cli_show_srte_pcep_session(struct vty *vty, struct pce_opts *pce_opts; int num_pcep_sessions_conf = 0; int num_pcep_sessions_conn = 0; + json_object *json_array = NULL, *json_entry = NULL; + + if (json) + json_array = json_object_new_array(); for (int i = 0; i < MAX_PCC; i++) { pce_opts = pce_connections_g.connections[i]; if (pce_opts == NULL) { continue; } + if (json) { + json_entry = json_object_new_object(); + json_object_string_add(json_entry, "pceName", + pce_opts->pce_name); + } pcc_info = pcep_ctrl_get_pcc_info(pcep_g->fpt, pce_opts->pce_name); if (pcc_info == NULL) { - vty_out(vty, - "%% Cannot retrieve PCEP session info for PCE [%s]\n", - pce_opts->pce_name); + if (json_entry) { + json_object_string_addf(json_entry, "warning", + "Cannot retrieve PCEP session info for PCE [%s].", + pce_opts->pce_name); + json_object_array_add(json_array, json_entry); + } else + vty_out(vty, + "%% Cannot retrieve PCEP session info for PCE [%s]\n", + pce_opts->pce_name); continue; } num_pcep_sessions_conn += pcc_info->status == PCEP_PCC_OPERATING ? 1 : 0; num_pcep_sessions_conf++; - print_pcep_session(vty, pce_opts, pcc_info); - } - - vty_out(vty, "PCEP Sessions => Configured %d ; Connected %d\n", - num_pcep_sessions_conf, num_pcep_sessions_conn); + if (json_entry) { + print_pcep_session_json(vty, pce_opts, pcc_info, + json_entry); + json_object_array_add(json_array, json_entry); + } else + print_pcep_session(vty, pce_opts, pcc_info); + } + if (json) { + json_object_object_add(json, "pcepSessions", json_array); + json_object_int_add(json, "pcepSessionsConfigured", + num_pcep_sessions_conf); + json_object_int_add(json, "pcepSessionsConnected", + num_pcep_sessions_conn); + vty_json(vty, json); + } else + vty_out(vty, "PCEP Sessions => Configured %d ; Connected %d\n", + num_pcep_sessions_conf, num_pcep_sessions_conn); return CMD_SUCCESS; } @@ -1702,7 +1949,7 @@ int pcep_cli_pce_config_write(struct vty *vty) &pce_opts->addr.ipaddr_v4); } if (pce_opts->port != PCEP_DEFAULT_PORT) { - vty_out(vty, " %s %d", PCEP_VTYSH_ARG_PORT, + vty_out(vty, " %s %d", PCEP_VTYSH_ARG_PORT, pce_opts->port); } vty_out(vty, "%s\n", buf); @@ -1788,7 +2035,7 @@ DEFPY(show_debugging_pathd_pcep, DEFPY(pcep_cli_debug, pcep_cli_debug_cmd, - "[no] debug pathd pcep [basic]$basic_str [path]$path_str [message]$message_str [pceplib]$pceplib_str", + "[no] debug pathd pcep [<basic|path|message|pceplib>$debug_type]", NO_STR DEBUG_STR "pathd debugging\n" "pcep module debugging\n" @@ -1797,8 +2044,7 @@ DEFPY(pcep_cli_debug, "pcep message debugging\n" "pceplib debugging\n") { - return path_pcep_cli_debug(vty, no, basic_str, path_str, message_str, - pceplib_str); + return path_pcep_cli_debug(vty, debug_type, !no); } DEFPY(pcep_cli_show_srte_pcep_counters, @@ -2040,12 +2286,21 @@ DEFPY(pcep_cli_no_pcc, DEFPY(pcep_cli_pcc_pcc_msd, pcep_cli_pcc_pcc_msd_cmd, - "[no] msd (1-32)", + "msd (1-32)", + "PCC maximum SID depth \n" + "PCC maximum SID depth value\n") +{ + return path_pcep_cli_pcc_pcc_msd(vty, msd_str, msd, false); +} + +DEFPY(no_pcep_cli_pcc_pcc_msd, + no_pcep_cli_pcc_pcc_msd_cmd, + "no msd [(1-32)]", NO_STR "PCC maximum SID depth \n" "PCC maximum SID depth value\n") { - return path_pcep_cli_pcc_pcc_msd(vty, msd_str, msd, no); + return path_pcep_cli_pcc_pcc_msd(vty, msd_str, msd, true); } DEFPY(pcep_cli_pcc_pcc_peer, @@ -2079,14 +2334,27 @@ DEFPY(pcep_cli_show_srte_pcc, DEFPY(pcep_cli_show_srte_pcep_session, pcep_cli_show_srte_pcep_session_cmd, - "show sr-te pcep session [WORD]$pce", + "show sr-te pcep session WORD$pce [json$uj]", SHOW_STR "SR-TE info\n" "PCEP info\n" "Show PCEP Session information\n" - "PCE name\n") + "PCE name\n" + JSON_STR) +{ + return path_pcep_cli_show_srte_pcep_session(vty, pce, !!uj); +} + +DEFPY(pcep_cli_show_srte_pcep_sessions, + pcep_cli_show_srte_pcep_sessions_cmd, + "show sr-te pcep session [json$uj]", + SHOW_STR + "SR-TE info\n" + "PCEP info\n" + "Show PCEP Session information\n" + JSON_STR) { - return path_pcep_cli_show_srte_pcep_session(vty, pce); + return path_pcep_cli_show_srte_pcep_session(vty, NULL, !!uj); } DEFPY(pcep_cli_clear_srte_pcep_session, @@ -2150,6 +2418,7 @@ void pcep_cli_init(void) install_element(PCEP_NODE, &pcep_cli_no_pcc_cmd); install_element(PCEP_PCC_NODE, &pcep_cli_pcc_pcc_peer_cmd); install_element(PCEP_PCC_NODE, &pcep_cli_pcc_pcc_msd_cmd); + install_element(PCEP_PCC_NODE, &no_pcep_cli_pcc_pcc_msd_cmd); /* Top commands */ install_element(CONFIG_NODE, &pcep_cli_debug_cmd); @@ -2159,5 +2428,6 @@ void pcep_cli_init(void) install_element(ENABLE_NODE, &pcep_cli_show_srte_pcep_pce_config_cmd); install_element(ENABLE_NODE, &pcep_cli_show_srte_pcep_pce_cmd); install_element(ENABLE_NODE, &pcep_cli_show_srte_pcep_session_cmd); + install_element(ENABLE_NODE, &pcep_cli_show_srte_pcep_sessions_cmd); install_element(ENABLE_NODE, &pcep_cli_clear_srte_pcep_session_cmd); } diff --git a/pathd/path_zebra.c b/pathd/path_zebra.c index 826443f..645fa50 100644 --- a/pathd/path_zebra.c +++ b/pathd/path_zebra.c @@ -320,9 +320,6 @@ static zclient_handler *const path_handlers[] = { */ void path_zebra_init(struct event_loop *master) { - struct zclient_options options = zclient_options_default; - options.synchronous = true; - /* Initialize asynchronous zclient. */ zclient = zclient_new(master, &zclient_options_default, path_handlers, array_size(path_handlers)); @@ -330,7 +327,7 @@ void path_zebra_init(struct event_loop *master) zclient->zebra_connected = path_zebra_connected; /* Initialize special zclient for synchronous message exchanges. */ - zclient_sync = zclient_new(master, &options, NULL, 0); + zclient_sync = zclient_new(master, &zclient_options_sync, NULL, 0); zclient_sync->sock = -1; zclient_sync->redist_default = ZEBRA_ROUTE_SRTE; zclient_sync->instance = 1; |