summaryrefslogtreecommitdiff
path: root/pathd/path_cli.c
diff options
context:
space:
mode:
authorJavier Garcia <javier.garcia@voltanet.io>2021-04-22 16:04:42 +0200
committerJavier Garcia <javier.garcia@voltanet.io>2021-05-10 15:24:59 +0200
commitf2b9485d6f5aa1508334a7e92d26d95faf0e1733 (patch)
tree18d754185d84e48675820d0c4fb658b53e78d1e6 /pathd/path_cli.c
parent75c69d151c8e72e42dfb4b1966428e9cf79cb7f4 (diff)
pathd. TED support . Validation of candidate path - [part 2/4]
- Explicit segment list nai will be resolved to corresponded sid. - Dynamic segment list (from pce) will be validated. - If segment list could not be resolved or validated won't be used. - Now this new config is supported segment-list sl-1 index 10 nai prefix 10.1.2.1/32 iface 1 index 30 nai adjacency 10.2.5.2 10.2.5.5 index 40 nai prefix 10.10.10.5/32 algorithm 0 Signed-off-by: Javier Garcia <javier.garcia@voltanet.io>
Diffstat (limited to 'pathd/path_cli.c')
-rw-r--r--pathd/path_cli.c297
1 files changed, 260 insertions, 37 deletions
diff --git a/pathd/path_cli.c b/pathd/path_cli.c
index ecb667f985..7a28449e4e 100644
--- a/pathd/path_cli.c
+++ b/pathd/path_cli.c
@@ -34,6 +34,7 @@
#ifndef VTYSH_EXTRACT_PL
#include "pathd/path_cli_clippy.c"
#endif
+#include "pathd/path_ted.h"
#define XPATH_MAXATTRSIZE 64
#define XPATH_MAXKEYSIZE 42
@@ -47,6 +48,18 @@ static int config_write_segment_routing(struct vty *vty);
static int config_write_traffic_eng(struct vty *vty);
static int config_write_segment_lists(struct vty *vty);
static int config_write_sr_policies(struct vty *vty);
+static int segment_list_has_src_dst(
+ struct vty *vty, char *xpath, long index, const char *index_str,
+ struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4,
+ struct in6_addr adj_src_ipv6, struct in6_addr adj_dst_ipv6,
+ const char *adj_src_ipv4_str, const char *adj_dst_ipv4_str,
+ const char *adj_src_ipv6_str, const char *adj_dst_ipv6_str);
+static int segment_list_has_prefix(
+ struct vty *vty, char *xpath, long index, const char *index_str,
+ const struct prefix_ipv4 *prefix_ipv4, const char *prefix_ipv4_str,
+ const struct prefix_ipv6 *prefix_ipv6, const char *prefix_ipv6_str,
+ const char *has_algo, long algo, const char *algo_str,
+ const char *has_iface_id, long iface_id, const char *iface_id_str);
DEFINE_MTYPE_STATIC(PATHD, PATH_CLI, "Client");
@@ -144,6 +157,7 @@ DEFPY(show_srte_policy,
return CMD_SUCCESS;
}
+
/*
* Show detailed SR-TE info
*/
@@ -295,56 +309,227 @@ void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode,
yang_dnode_get_string(dnode, "./name"));
}
+static int segment_list_has_src_dst(
+ struct vty *vty, char *xpath, long index, const char *index_str,
+ struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4,
+ struct in6_addr adj_src_ipv6, struct in6_addr adj_dst_ipv6,
+ const char *adj_src_ipv4_str, const char *adj_dst_ipv4_str,
+ const char *adj_src_ipv6_str, const char *adj_dst_ipv6_str)
+{
+ const char *node_src_id;
+ uint32_t ted_sid = MPLS_LABEL_NONE;
+
+ struct ipaddr ip_src = {};
+ struct ipaddr ip_dst = {};
+ if (adj_src_ipv4_str != NULL) {
+ ip_src.ipa_type = IPADDR_V4;
+ ip_src.ip._v4_addr = adj_src_ipv4;
+ ip_dst.ipa_type = IPADDR_V4;
+ ip_dst.ip._v4_addr = adj_dst_ipv4;
+ } else if (adj_src_ipv6_str != NULL) {
+ ip_src.ipa_type = IPADDR_V6;
+ ip_src.ip._v6_addr = adj_src_ipv6;
+ ip_dst.ipa_type = IPADDR_V6;
+ ip_dst.ip._v6_addr = adj_dst_ipv6;
+ } else {
+ return CMD_ERR_NO_MATCH;
+ }
+ ted_sid = path_ted_query_type_f(&ip_src, &ip_dst);
+ if (ted_sid == MPLS_LABEL_NONE) {
+ zlog_warn(
+ "%s: [rcv ted] CLI NOT FOUND Continue query_type_f SRC (%pIA) DST (%pIA)!",
+ __func__, &ip_src, &ip_dst);
+ }
+ /* type */
+ snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/type",
+ index_str);
+ if (adj_src_ipv4_str != NULL) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ "ipv4_adjacency");
+ node_src_id = adj_src_ipv4_str;
+ } else if (adj_src_ipv6_str != NULL) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ "ipv6_adjacency");
+ node_src_id = adj_src_ipv6_str;
+ } else {
+ return CMD_ERR_NO_MATCH;
+ }
+ /* addresses */
+ snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
+ index_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, node_src_id);
+ snprintf(xpath, XPATH_MAXLEN,
+ "./segment[index='%s']/nai/remote-address", index_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ adj_dst_ipv4_str ? adj_dst_ipv4_str
+ : adj_dst_ipv6_str);
+ return CMD_SUCCESS;
+}
+int segment_list_has_prefix(
+ struct vty *vty, char *xpath, long index, const char *index_str,
+ const struct prefix_ipv4 *prefix_ipv4, const char *prefix_ipv4_str,
+ const struct prefix_ipv6 *prefix_ipv6, const char *prefix_ipv6_str,
+ const char *has_algo, long algo, const char *algo_str,
+ const char *has_iface_id, long iface_id, const char *iface_id_str)
+{
+ char buf_prefix[INET6_ADDRSTRLEN];
+
+ uint32_t ted_sid = MPLS_LABEL_NONE;
+ struct prefix prefix_cli = {};
+ struct ipaddr pre_ipaddr = {};
+ /* prefix with algorithm or local interface id */
+ /* Type */
+ snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/type",
+ index_str);
+ if (has_iface_id != NULL) {
+ if (prefix_ipv4_str != NULL) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ "ipv4_local_iface");
+ } else if (prefix_ipv6_str != NULL) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ "ipv6_local_iface");
+ } else {
+ return CMD_ERR_NO_MATCH;
+ }
+ } else {
+ if (prefix_ipv4_str != NULL) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ "ipv4_algo");
+ } else if (prefix_ipv6_str != NULL) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ "ipv6_algo");
+ } else {
+ return CMD_ERR_NO_MATCH;
+ }
+ }
+ /* Prefix */
+ if (prefix_ipv4_str != NULL) {
+ if (!str2prefix(prefix_ipv4_str, &prefix_cli)) {
+ vty_out(vty, "%% Malformed prefix\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ inet_ntop(AF_INET, &prefix_cli.u.prefix4, buf_prefix,
+ sizeof(buf_prefix));
+ pre_ipaddr.ipa_type = IPADDR_V4;
+ pre_ipaddr.ip._v4_addr = prefix_cli.u.prefix4;
+ } else if (prefix_ipv6_str != NULL) {
+ if (!str2prefix(prefix_ipv6_str, &prefix_cli)) {
+ vty_out(vty, "%% Malformed prefix\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ inet_ntop(AF_INET6, &prefix_cli.u.prefix6, buf_prefix,
+ sizeof(buf_prefix));
+ pre_ipaddr.ipa_type = IPADDR_V6;
+ pre_ipaddr.ip._v6_addr = prefix_cli.u.prefix6;
+ } else {
+ return CMD_ERR_NO_MATCH;
+ }
+ snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
+ index_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, buf_prefix);
+ snprintf(xpath, XPATH_MAXLEN,
+ "./segment[index='%s']/nai/local-prefix-len", index_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ prefix_ipv4_str
+ ? strchr(prefix_ipv4_str, '/') + 1
+ : strchr(prefix_ipv6_str, '/') + 1);
+ /* Alg / Iface */
+ if (has_algo != NULL) {
+ snprintf(xpath, XPATH_MAXLEN,
+ "./segment[index='%s']/nai/algorithm", index_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, algo_str);
+ } else {
+ if (has_iface_id != NULL) {
+ snprintf(xpath, XPATH_MAXLEN,
+ "./segment[index='%s']/nai/local-interface",
+ index_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
+ iface_id_str);
+ }
+ }
+ if (has_algo != NULL) {
+ ted_sid = path_ted_query_type_c(&prefix_cli, algo);
+ if (ted_sid == MPLS_LABEL_NONE) {
+ zlog_err(
+ "%s: [rcv ted] CLI NOT FOUND Continue query_type_c PREFIX (%pIA/%d) ALGO (%ld) sid:(%d)!",
+ __func__, &pre_ipaddr, prefix_cli.prefixlen,
+ algo, ted_sid);
+ }
+ }
+ if (has_iface_id != NULL) {
+ ted_sid = path_ted_query_type_e(&prefix_cli, iface_id);
+ if (ted_sid == MPLS_LABEL_NONE) {
+ zlog_err(
+ "%s: [rcv ted] CLI NOT FOUND Continue query_type_e PREFIX (%pIA/%d) IFACE (%ld) sid:(%d)!",
+ __func__, &pre_ipaddr, prefix_cli.prefixlen,
+ iface_id, ted_sid);
+ }
+ }
+ return CMD_SUCCESS;
+}
/*
* XPath: /frr-pathd:pathd/srte/segment-list/segment
*/
-DEFPY(srte_segment_list_segment,
- srte_segment_list_segment_cmd,
- "index (0-4294967295)$index mpls label (16-1048575)$label "
+/* clang-format off */
+DEFPY(srte_segment_list_segment, srte_segment_list_segment_cmd,
+ "index (0-4294967295)$index <[mpls$has_mpls_label label (16-1048575)$label] "
+ "|"
"[nai$has_nai <"
- "node <A.B.C.D$node_ipv4|X:X::X:X$node_ipv6>"
- ">]",
+ "prefix <A.B.C.D/M$prefix_ipv4|X:X::X:X/M$prefix_ipv6>"
+ "<algorithm$has_algo (0-1)$algo| iface$has_iface_id (0-4294967295)$iface_id>"
+ "| adjacency$has_adj "
+ "<A.B.C.D$adj_src_ipv4 A.B.C.D$adj_dst_ipv4|X:X::X:X$adj_src_ipv6 X:X::X:X$adj_dst_ipv6>"
+ ">]"
+ ">",
"Index\n"
"Index Value\n"
"MPLS or IP Label\n"
"Label\n"
"Label Value\n"
"Segment NAI\n"
- "NAI node identifier\n"
- "NAI IPv4 node identifier\n"
- "NAI IPv6 node identifier\n")
+ "NAI prefix identifier\n"
+ "NAI IPv4 prefix identifier\n"
+ "NAI IPv6 prefix identifier\n"
+ "IGP Algorithm\n"
+ "Algorithm Value SPF or Strict-SPF\n"
+ "Interface Id\n"
+ "Interface Value\n"
+ "ADJ identifier\n"
+ "ADJ IPv4 src identifier\n"
+ "ADJ IPv4 dst identifier\n"
+ "ADJ IPv6 src identifier\n"
+ "ADJ IPv6 dst identifier\n")
+/* clang-format on */
{
char xpath[XPATH_MAXLEN];
- const char *node_id;
+ int status = CMD_SUCCESS;
+
snprintf(xpath, sizeof(xpath), "./segment[index='%s']", index_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- snprintf(xpath, sizeof(xpath), "./segment[index='%s']/sid-value",
- index_str);
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, label_str);
-
- if (has_nai != NULL) {
- snprintf(xpath, sizeof(xpath), "./segment[index='%s']/nai/type",
- index_str);
- if (node_ipv4_str != NULL) {
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
- "ipv4_node");
- node_id = node_ipv4_str;
- } else if (node_ipv6_str != NULL) {
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
- "ipv6_node");
- node_id = node_ipv6_str;
- } else {
- return CMD_ERR_NO_MATCH;
- }
+ if (has_mpls_label != NULL) {
snprintf(xpath, sizeof(xpath),
- "./segment[index='%s']/nai/local-address", index_str);
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, node_id);
+ "./segment[index='%s']/sid-value", index_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, label_str);
+ return nb_cli_apply_changes(vty, NULL);
+ }
+
+ if (has_adj != NULL) {
+ status = segment_list_has_src_dst(vty, xpath, index, index_str,
+ adj_src_ipv4, adj_dst_ipv4,
+ adj_src_ipv6, adj_dst_ipv6,
+ adj_src_ipv4_str, adj_dst_ipv4_str,
+ adj_dst_ipv6_str, adj_src_ipv6_str);
+ if (status != CMD_SUCCESS)
+ return status;
} else {
- snprintf(xpath, sizeof(xpath), "./segment[index='%s']/nai",
- index_str);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ segment_list_has_prefix(
+ vty, xpath, index, index_str, prefix_ipv4,
+ prefix_ipv4_str, prefix_ipv6, prefix_ipv6_str, has_algo,
+ algo, algo_str, has_iface_id, iface_id, iface_id_str);
+ if (status != CMD_SUCCESS)
+ return status;
}
return nb_cli_apply_changes(vty, NULL);
@@ -369,23 +554,60 @@ void cli_show_srte_segment_list_segment(struct vty *vty,
struct lyd_node *dnode,
bool show_defaults)
{
- vty_out(vty, " index %s mpls label %s",
- yang_dnode_get_string(dnode, "./index"),
- yang_dnode_get_string(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"));
+ }
if (yang_dnode_exists(dnode, "./nai")) {
struct ipaddr addr;
+ struct ipaddr addr_rmt;
+
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");
- vty_out(vty, " nai node %pI4", &addr.ipaddr_v4);
+ 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");
- vty_out(vty, " nai node %pI6", &addr.ipaddr_v6);
+ 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_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_rmt, dnode,
+ "./nai/remote-address");
+ vty_out(vty, " nai adjacency %pI6", &addr.ipaddr_v6);
+ vty_out(vty, " %pI6", &addr_rmt.ipaddr_v6);
break;
default:
break;
}
+ 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")) {
+ vty_out(vty, " iface %s",
+ yang_dnode_get_string(dnode,
+ "./nai/local-interface"));
+ }
+ if (yang_dnode_exists(dnode, "./nai/algorithm")) {
+ vty_out(vty, " algorithm %s",
+ yang_dnode_get_string(dnode,
+ "./nai/algorithm"));
+ }
}
vty_out(vty, "\n");
}
@@ -1038,6 +1260,7 @@ int config_write_segment_routing(struct vty *vty)
int config_write_traffic_eng(struct vty *vty)
{
vty_out(vty, " traffic-eng\n");
+ path_ted_config_write(vty);
return 1;
}