staticd: add vtysh srv6 multiple segs SIDs

Append staticd vty with multiple segs SIDs.

Signed-off-by: Dmytro Shytyi <dmytro.shytyi@6wind.com>
This commit is contained in:
Dmytro Shytyi 2023-07-26 18:44:23 +02:00
parent b13b5f85f9
commit d91a38a4db

View file

@ -47,6 +47,7 @@ struct static_route_args {
const char *source; const char *source;
const char *gateway; const char *gateway;
const char *interface_name; const char *interface_name;
const char *segs;
const char *flag; const char *flag;
const char *tag; const char *tag;
const char *distance; const char *distance;
@ -73,12 +74,16 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
char xpath_nexthop[XPATH_MAXLEN]; char xpath_nexthop[XPATH_MAXLEN];
char xpath_mpls[XPATH_MAXLEN]; char xpath_mpls[XPATH_MAXLEN];
char xpath_label[XPATH_MAXLEN]; char xpath_label[XPATH_MAXLEN];
char xpath_segs[XPATH_MAXLEN];
char xpath_seg[XPATH_MAXLEN];
char ab_xpath[XPATH_MAXLEN]; char ab_xpath[XPATH_MAXLEN];
char buf_prefix[PREFIX_STRLEN]; char buf_prefix[PREFIX_STRLEN];
char buf_src_prefix[PREFIX_STRLEN] = {}; char buf_src_prefix[PREFIX_STRLEN] = {};
char buf_nh_type[PREFIX_STRLEN] = {}; char buf_nh_type[PREFIX_STRLEN] = {};
char buf_tag[PREFIX_STRLEN]; char buf_tag[PREFIX_STRLEN];
uint8_t label_stack_id = 0; uint8_t label_stack_id = 0;
uint8_t segs_stack_id = 0;
const char *buf_gate_str; const char *buf_gate_str;
uint8_t distance = ZEBRA_STATIC_DISTANCE_DEFAULT; uint8_t distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
route_tag_t tag = 0; route_tag_t tag = 0;
@ -345,7 +350,39 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY, nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
NULL); NULL);
} }
if (args->segs) {
/* copy of seg string (start) */
char *ostr;
/* pointer to next segment */
char *nump;
strlcpy(xpath_segs, xpath_nexthop, sizeof(xpath_segs));
strlcat(xpath_segs, FRR_STATIC_ROUTE_NH_SRV6_SEGS_XPATH,
sizeof(xpath_segs));
nb_cli_enqueue_change(vty, xpath_segs, NB_OP_DESTROY,
NULL);
ostr = XSTRDUP(MTYPE_TMP, args->segs);
while ((nump = strsep(&ostr, "/")) != NULL) {
snprintf(ab_xpath, sizeof(ab_xpath),
FRR_STATIC_ROUTE_NH_SRV6_KEY_SEG_XPATH,
segs_stack_id);
strlcpy(xpath_seg, xpath_segs,
sizeof(xpath_seg));
strlcat(xpath_seg, ab_xpath, sizeof(xpath_seg));
nb_cli_enqueue_change(vty, xpath_seg,
NB_OP_MODIFY, nump);
segs_stack_id++;
}
XFREE(MTYPE_TMP, ostr);
} else {
strlcpy(xpath_segs, xpath_nexthop, sizeof(xpath_segs));
strlcat(xpath_segs, FRR_STATIC_ROUTE_NH_SRV6_SEGS_XPATH,
sizeof(xpath_segs));
nb_cli_enqueue_change(vty, xpath_segs, NB_OP_DESTROY,
NULL);
}
if (args->bfd) { if (args->bfd) {
char xpath_bfd[XPATH_MAXLEN]; char xpath_bfd[XPATH_MAXLEN];
@ -951,9 +988,8 @@ DEFPY_YANG(ipv6_route_blackhole_vrf,
return static_route_nb_run(vty, &args); return static_route_nb_run(vty, &args);
} }
DEFPY_YANG(ipv6_route_address_interface, DEFPY_YANG(ipv6_route_address_interface, ipv6_route_address_interface_cmd,
ipv6_route_address_interface_cmd, "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
X:X::X:X$gate \ X:X::X:X$gate \
<INTERFACE|Null0>$ifname \ <INTERFACE|Null0>$ifname \
[{ \ [{ \
@ -966,33 +1002,28 @@ DEFPY_YANG(ipv6_route_address_interface,
|onlink$onlink \ |onlink$onlink \
|color (1-4294967295) \ |color (1-4294967295) \
|bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \ |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
|segments WORD \
}]", }]",
NO_STR NO_STR IPV6_STR
IPV6_STR "Establish static routes\n"
"Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 source-dest route\n"
"IPv6 source-dest route\n" "IPv6 source prefix\n"
"IPv6 source prefix\n" "IPv6 gateway address\n"
"IPv6 gateway address\n" "IPv6 gateway interface name\n"
"IPv6 gateway interface name\n" "Null interface\n"
"Null interface\n" "Set tag for this route\n"
"Set tag for this route\n" "Tag value\n"
"Tag value\n" "Distance value for this prefix\n" VRF_CMD_HELP_STR MPLS_LABEL_HELPSTR
"Distance value for this prefix\n" "Table to configure\n"
VRF_CMD_HELP_STR "The table number to configure\n" VRF_CMD_HELP_STR
MPLS_LABEL_HELPSTR "Treat the nexthop as directly attached to the interface\n"
"Table to configure\n" "SR-TE color\n"
"The table number to configure\n" "The SR-TE color to configure\n" BFD_INTEGRATION_STR
VRF_CMD_HELP_STR BFD_INTEGRATION_MULTI_HOP_STR BFD_INTEGRATION_SOURCE_STR
"Treat the nexthop as directly attached to the interface\n" BFD_INTEGRATION_SOURCEV4_STR BFD_PROFILE_STR
"SR-TE color\n" BFD_PROFILE_NAME_STR "Value of segs\n"
"The SR-TE color to configure\n" "Segs (SIDs)\n")
BFD_INTEGRATION_STR
BFD_INTEGRATION_MULTI_HOP_STR
BFD_INTEGRATION_SOURCE_STR
BFD_INTEGRATION_SOURCEV4_STR
BFD_PROFILE_STR
BFD_PROFILE_NAME_STR)
{ {
struct static_route_args args = { struct static_route_args args = {
.delete = !!no, .delete = !!no,
@ -1014,14 +1045,15 @@ DEFPY_YANG(ipv6_route_address_interface,
.bfd_multi_hop = !!bfd_multi_hop, .bfd_multi_hop = !!bfd_multi_hop,
.bfd_source = bfd_source_str, .bfd_source = bfd_source_str,
.bfd_profile = bfd_profile, .bfd_profile = bfd_profile,
.segs = segments,
}; };
return static_route_nb_run(vty, &args); return static_route_nb_run(vty, &args);
} }
DEFPY_YANG(ipv6_route_address_interface_vrf, DEFPY_YANG(ipv6_route_address_interface_vrf,
ipv6_route_address_interface_vrf_cmd, ipv6_route_address_interface_vrf_cmd,
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
X:X::X:X$gate \ X:X::X:X$gate \
<INTERFACE|Null0>$ifname \ <INTERFACE|Null0>$ifname \
[{ \ [{ \
@ -1033,32 +1065,28 @@ DEFPY_YANG(ipv6_route_address_interface_vrf,
|onlink$onlink \ |onlink$onlink \
|color (1-4294967295) \ |color (1-4294967295) \
|bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \ |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
|segments WORD \
}]", }]",
NO_STR NO_STR IPV6_STR
IPV6_STR "Establish static routes\n"
"Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 source-dest route\n"
"IPv6 source-dest route\n" "IPv6 source prefix\n"
"IPv6 source prefix\n" "IPv6 gateway address\n"
"IPv6 gateway address\n" "IPv6 gateway interface name\n"
"IPv6 gateway interface name\n" "Null interface\n"
"Null interface\n" "Set tag for this route\n"
"Set tag for this route\n" "Tag value\n"
"Tag value\n" "Distance value for this prefix\n" MPLS_LABEL_HELPSTR
"Distance value for this prefix\n" "Table to configure\n"
MPLS_LABEL_HELPSTR "The table number to configure\n" VRF_CMD_HELP_STR
"Table to configure\n" "Treat the nexthop as directly attached to the interface\n"
"The table number to configure\n" "SR-TE color\n"
VRF_CMD_HELP_STR "The SR-TE color to configure\n" BFD_INTEGRATION_STR
"Treat the nexthop as directly attached to the interface\n" BFD_INTEGRATION_MULTI_HOP_STR BFD_INTEGRATION_SOURCE_STR
"SR-TE color\n" BFD_INTEGRATION_SOURCEV4_STR BFD_PROFILE_STR
"The SR-TE color to configure\n" BFD_PROFILE_NAME_STR "Value of segs\n"
BFD_INTEGRATION_STR "Segs (SIDs)\n")
BFD_INTEGRATION_MULTI_HOP_STR
BFD_INTEGRATION_SOURCE_STR
BFD_INTEGRATION_SOURCEV4_STR
BFD_PROFILE_STR
BFD_PROFILE_NAME_STR)
{ {
struct static_route_args args = { struct static_route_args args = {
.delete = !!no, .delete = !!no,
@ -1080,14 +1108,14 @@ DEFPY_YANG(ipv6_route_address_interface_vrf,
.bfd_multi_hop = !!bfd_multi_hop, .bfd_multi_hop = !!bfd_multi_hop,
.bfd_source = bfd_source_str, .bfd_source = bfd_source_str,
.bfd_profile = bfd_profile, .bfd_profile = bfd_profile,
.segs = segments,
}; };
return static_route_nb_run(vty, &args); return static_route_nb_run(vty, &args);
} }
DEFPY_YANG(ipv6_route, DEFPY_YANG(ipv6_route, ipv6_route_cmd,
ipv6_route_cmd, "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
<X:X::X:X$gate|<INTERFACE|Null0>$ifname> \ <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
[{ \ [{ \
tag (1-4294967295) \ tag (1-4294967295) \
@ -1098,32 +1126,26 @@ DEFPY_YANG(ipv6_route,
|nexthop-vrf NAME \ |nexthop-vrf NAME \
|color (1-4294967295) \ |color (1-4294967295) \
|bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \ |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
|segments WORD \
}]", }]",
NO_STR NO_STR IPV6_STR
IPV6_STR "Establish static routes\n"
"Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 source-dest route\n"
"IPv6 source-dest route\n" "IPv6 source prefix\n"
"IPv6 source prefix\n" "IPv6 gateway address\n"
"IPv6 gateway address\n" "IPv6 gateway interface name\n"
"IPv6 gateway interface name\n" "Null interface\n"
"Null interface\n" "Set tag for this route\n"
"Set tag for this route\n" "Tag value\n"
"Tag value\n" "Distance value for this prefix\n" VRF_CMD_HELP_STR MPLS_LABEL_HELPSTR
"Distance value for this prefix\n" "Table to configure\n"
VRF_CMD_HELP_STR "The table number to configure\n" VRF_CMD_HELP_STR "SR-TE color\n"
MPLS_LABEL_HELPSTR "The SR-TE color to configure\n" BFD_INTEGRATION_STR
"Table to configure\n" BFD_INTEGRATION_MULTI_HOP_STR BFD_INTEGRATION_SOURCE_STR
"The table number to configure\n" BFD_INTEGRATION_SOURCEV4_STR BFD_PROFILE_STR
VRF_CMD_HELP_STR BFD_PROFILE_NAME_STR "Value of segs\n"
"SR-TE color\n" "Segs (SIDs)\n")
"The SR-TE color to configure\n"
BFD_INTEGRATION_STR
BFD_INTEGRATION_MULTI_HOP_STR
BFD_INTEGRATION_SOURCE_STR
BFD_INTEGRATION_SOURCEV4_STR
BFD_PROFILE_STR
BFD_PROFILE_NAME_STR)
{ {
struct static_route_args args = { struct static_route_args args = {
.delete = !!no, .delete = !!no,
@ -1144,14 +1166,15 @@ DEFPY_YANG(ipv6_route,
.bfd_multi_hop = !!bfd_multi_hop, .bfd_multi_hop = !!bfd_multi_hop,
.bfd_source = bfd_source_str, .bfd_source = bfd_source_str,
.bfd_profile = bfd_profile, .bfd_profile = bfd_profile,
.segs = segments,
}; };
return static_route_nb_run(vty, &args); return static_route_nb_run(vty, &args);
} }
DEFPY_YANG(ipv6_route_vrf, DEFPY_YANG(ipv6_route_vrf, ipv6_route_vrf_cmd,
ipv6_route_vrf_cmd, "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
<X:X::X:X$gate|<INTERFACE|Null0>$ifname> \ <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
[{ \ [{ \
tag (1-4294967295) \ tag (1-4294967295) \
@ -1161,31 +1184,26 @@ DEFPY_YANG(ipv6_route_vrf,
|nexthop-vrf NAME \ |nexthop-vrf NAME \
|color (1-4294967295) \ |color (1-4294967295) \
|bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \ |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
|segments WORD \
}]", }]",
NO_STR NO_STR IPV6_STR
IPV6_STR "Establish static routes\n"
"Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 source-dest route\n"
"IPv6 source-dest route\n" "IPv6 source prefix\n"
"IPv6 source prefix\n" "IPv6 gateway address\n"
"IPv6 gateway address\n" "IPv6 gateway interface name\n"
"IPv6 gateway interface name\n" "Null interface\n"
"Null interface\n" "Set tag for this route\n"
"Set tag for this route\n" "Tag value\n"
"Tag value\n" "Distance value for this prefix\n" MPLS_LABEL_HELPSTR
"Distance value for this prefix\n" "Table to configure\n"
MPLS_LABEL_HELPSTR "The table number to configure\n" VRF_CMD_HELP_STR "SR-TE color\n"
"Table to configure\n" "The SR-TE color to configure\n" BFD_INTEGRATION_STR
"The table number to configure\n" BFD_INTEGRATION_MULTI_HOP_STR BFD_INTEGRATION_SOURCE_STR
VRF_CMD_HELP_STR BFD_INTEGRATION_SOURCEV4_STR BFD_PROFILE_STR
"SR-TE color\n" BFD_PROFILE_NAME_STR "Value of segs\n"
"The SR-TE color to configure\n" "Segs (SIDs)\n")
BFD_INTEGRATION_STR
BFD_INTEGRATION_MULTI_HOP_STR
BFD_INTEGRATION_SOURCE_STR
BFD_INTEGRATION_SOURCEV4_STR
BFD_PROFILE_STR
BFD_PROFILE_NAME_STR)
{ {
struct static_route_args args = { struct static_route_args args = {
.delete = !!no, .delete = !!no,
@ -1206,6 +1224,7 @@ DEFPY_YANG(ipv6_route_vrf,
.bfd_multi_hop = !!bfd_multi_hop, .bfd_multi_hop = !!bfd_multi_hop,
.bfd_source = bfd_source_str, .bfd_source = bfd_source_str,
.bfd_profile = bfd_profile, .bfd_profile = bfd_profile,
.segs = segments,
}; };
return static_route_nb_run(vty, &args); return static_route_nb_run(vty, &args);
@ -1252,6 +1271,39 @@ static int mpls_label_iter_cb(const struct lyd_node *dnode, void *arg)
return YANG_ITER_CONTINUE; return YANG_ITER_CONTINUE;
} }
struct srv6_seg_iter {
struct vty *vty;
bool first;
};
static int srv6_seg_iter_cb(const struct lyd_node *dnode, void *arg)
{
struct srv6_seg_iter *iter = arg;
char buffer[INET6_ADDRSTRLEN];
struct in6_addr cli_seg;
if (yang_dnode_exists(dnode, "./seg")) {
if (iter->first) {
yang_dnode_get_ipv6(&cli_seg, dnode, "./seg");
if (inet_ntop(AF_INET6, &cli_seg, buffer,
INET6_ADDRSTRLEN) == NULL) {
return 1;
}
vty_out(iter->vty, " segments %s", buffer);
} else {
yang_dnode_get_ipv6(&cli_seg, dnode, "./seg");
if (inet_ntop(AF_INET6, &cli_seg, buffer,
INET6_ADDRSTRLEN) == NULL) {
return 1;
}
vty_out(iter->vty, "/%s", buffer);
}
iter->first = false;
}
return YANG_ITER_CONTINUE;
}
static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route, static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,
const struct lyd_node *src, const struct lyd_node *src,
const struct lyd_node *path, const struct lyd_node *path,
@ -1266,6 +1318,7 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,
uint32_t tag; uint32_t tag;
uint8_t distance; uint8_t distance;
struct mpls_label_iter iter; struct mpls_label_iter iter;
struct srv6_seg_iter seg_iter;
const char *nexthop_vrf; const char *nexthop_vrf;
uint32_t table_id; uint32_t table_id;
bool onlink; bool onlink;
@ -1342,6 +1395,11 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,
yang_dnode_iterate(mpls_label_iter_cb, &iter, nexthop, yang_dnode_iterate(mpls_label_iter_cb, &iter, nexthop,
"./mpls-label-stack/entry"); "./mpls-label-stack/entry");
seg_iter.vty = vty;
seg_iter.first = true;
yang_dnode_iterate(srv6_seg_iter_cb, &seg_iter, nexthop,
"./srv6-segs-stack/entry");
nexthop_vrf = yang_dnode_get_string(nexthop, "./vrf"); nexthop_vrf = yang_dnode_get_string(nexthop, "./vrf");
if (strcmp(vrf, nexthop_vrf)) if (strcmp(vrf, nexthop_vrf))
vty_out(vty, " nexthop-vrf %s", nexthop_vrf); vty_out(vty, " nexthop-vrf %s", nexthop_vrf);