forked from Mirror/frr

We may actually need to send CLI commands to mgmtd and another daemon at the same time, for example, if this daemon is not mgmtd-converted. The only daemon this exception protects is staticd. But we don't actually need any configuration commands in staticd, so just remove the exception and don't install unnecessary commands to staticd. Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
1721 lines
49 KiB
C
1721 lines
49 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* STATICd - vty code
|
|
* Copyright (C) 2018 Cumulus Networks, Inc.
|
|
* Donald Sharp
|
|
*/
|
|
#include <zebra.h>
|
|
|
|
#include "command.h"
|
|
#include "vty.h"
|
|
#include "vrf.h"
|
|
#include "prefix.h"
|
|
#include "nexthop.h"
|
|
#include "table.h"
|
|
#include "srcdest_table.h"
|
|
#include "mgmt_be_client.h"
|
|
#include "mpls.h"
|
|
#include "northbound.h"
|
|
#include "libfrr.h"
|
|
#include "routing_nb.h"
|
|
#include "northbound_cli.h"
|
|
#include "frrdistance.h"
|
|
|
|
#include "static_vrf.h"
|
|
#include "static_vty.h"
|
|
#include "static_routes.h"
|
|
#include "static_debug.h"
|
|
#include "staticd/static_vty_clippy.c"
|
|
#include "static_nb.h"
|
|
|
|
#define STATICD_STR "Static route daemon\n"
|
|
|
|
/** All possible route parameters available in CLI. */
|
|
struct static_route_args {
|
|
/** "no" command? */
|
|
bool delete;
|
|
/** Is VRF obtained from XPath? */
|
|
bool xpath_vrf;
|
|
|
|
bool onlink;
|
|
afi_t afi;
|
|
safi_t safi;
|
|
|
|
const char *vrf;
|
|
const char *nexthop_vrf;
|
|
const char *prefix;
|
|
const char *prefix_mask;
|
|
const char *source;
|
|
const char *gateway;
|
|
const char *interface_name;
|
|
const char *segs;
|
|
const char *flag;
|
|
const char *tag;
|
|
const char *distance;
|
|
const char *label;
|
|
const char *table;
|
|
const char *color;
|
|
|
|
bool bfd;
|
|
bool bfd_multi_hop;
|
|
const char *bfd_source;
|
|
const char *bfd_profile;
|
|
|
|
const char *input;
|
|
};
|
|
|
|
static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
|
|
{
|
|
int ret;
|
|
struct prefix p, src;
|
|
struct in_addr mask;
|
|
enum static_nh_type type;
|
|
const char *bh_type;
|
|
char xpath_prefix[XPATH_MAXLEN];
|
|
char xpath_nexthop[XPATH_MAXLEN];
|
|
char xpath_mpls[XPATH_MAXLEN];
|
|
char xpath_label[XPATH_MAXLEN];
|
|
char xpath_segs[XPATH_MAXLEN];
|
|
char xpath_seg[XPATH_MAXLEN];
|
|
char ab_xpath[XPATH_MAXLEN];
|
|
char buf_prefix[PREFIX_STRLEN];
|
|
char buf_src_prefix[PREFIX_STRLEN] = {};
|
|
char buf_nh_type[PREFIX_STRLEN] = {};
|
|
char buf_tag[PREFIX_STRLEN];
|
|
uint8_t label_stack_id = 0;
|
|
uint8_t segs_stack_id = 0;
|
|
char *orig_label = NULL, *orig_seg = NULL;
|
|
const char *buf_gate_str;
|
|
uint8_t distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
|
|
route_tag_t tag = 0;
|
|
uint32_t table_id = 0;
|
|
const struct lyd_node *dnode;
|
|
const struct lyd_node *vrf_dnode;
|
|
|
|
if (args->xpath_vrf) {
|
|
vrf_dnode = yang_dnode_get(vty->candidate_config->dnode,
|
|
VTY_CURR_XPATH);
|
|
if (vrf_dnode == NULL) {
|
|
vty_out(vty,
|
|
"%% Failed to get vrf dnode in candidate db\n");
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
}
|
|
|
|
args->vrf = yang_dnode_get_string(vrf_dnode, "name");
|
|
} else {
|
|
if (args->vrf == NULL)
|
|
args->vrf = VRF_DEFAULT_NAME;
|
|
}
|
|
if (args->nexthop_vrf == NULL)
|
|
args->nexthop_vrf = args->vrf;
|
|
|
|
if (args->interface_name &&
|
|
!strcasecmp(args->interface_name, "Null0")) {
|
|
args->flag = "Null0";
|
|
args->interface_name = NULL;
|
|
}
|
|
|
|
assert(!!str2prefix(args->prefix, &p));
|
|
|
|
switch (args->afi) {
|
|
case AFI_IP:
|
|
/* Cisco like mask notation. */
|
|
if (args->prefix_mask) {
|
|
assert(inet_pton(AF_INET, args->prefix_mask, &mask) ==
|
|
1);
|
|
p.prefixlen = ip_masklen(mask);
|
|
}
|
|
break;
|
|
case AFI_IP6:
|
|
/* srcdest routing */
|
|
if (args->source)
|
|
assert(!!str2prefix(args->source, &src));
|
|
break;
|
|
case AFI_L2VPN:
|
|
case AFI_UNSPEC:
|
|
case AFI_MAX:
|
|
break;
|
|
}
|
|
|
|
/* Apply mask for given prefix. */
|
|
apply_mask(&p);
|
|
prefix2str(&p, buf_prefix, sizeof(buf_prefix));
|
|
|
|
if (args->bfd && args->gateway == NULL) {
|
|
vty_out(vty, "%% Route monitoring requires a gateway\n");
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
}
|
|
|
|
if (args->source)
|
|
prefix2str(&src, buf_src_prefix, sizeof(buf_src_prefix));
|
|
if (args->gateway)
|
|
buf_gate_str = args->gateway;
|
|
else
|
|
buf_gate_str = "";
|
|
|
|
if (args->gateway == NULL && args->interface_name == NULL) {
|
|
type = STATIC_BLACKHOLE;
|
|
/* If this is blackhole/reject flagged route, then
|
|
* specify interface_name with the value of what was really
|
|
* entered.
|
|
* interface_name will be validated later in NB functions
|
|
* to check if we don't create blackhole/reject routes that
|
|
* match the real interface names.
|
|
* E.g.: `ip route 10.0.0.1/32 bla` will create a blackhole
|
|
* route despite the real interface named `bla` exists.
|
|
*/
|
|
if (args->input)
|
|
args->interface_name = args->input;
|
|
} else if (args->gateway && args->interface_name) {
|
|
if (args->afi == AFI_IP)
|
|
type = STATIC_IPV4_GATEWAY_IFNAME;
|
|
else
|
|
type = STATIC_IPV6_GATEWAY_IFNAME;
|
|
} else if (args->interface_name)
|
|
type = STATIC_IFNAME;
|
|
else {
|
|
if (args->afi == AFI_IP)
|
|
type = STATIC_IPV4_GATEWAY;
|
|
else
|
|
type = STATIC_IPV6_GATEWAY;
|
|
}
|
|
|
|
/* Administrative distance. */
|
|
if (args->distance)
|
|
distance = strtol(args->distance, NULL, 10);
|
|
|
|
/* tag */
|
|
if (args->tag)
|
|
tag = strtoul(args->tag, NULL, 10);
|
|
|
|
/* TableID */
|
|
if (args->table)
|
|
table_id = strtol(args->table, NULL, 10);
|
|
|
|
static_get_nh_type(type, buf_nh_type, sizeof(buf_nh_type));
|
|
if (!args->delete) {
|
|
if (args->source)
|
|
snprintf(ab_xpath, sizeof(ab_xpath),
|
|
FRR_DEL_S_ROUTE_SRC_NH_KEY_NO_DISTANCE_XPATH,
|
|
"frr-staticd:staticd", "staticd", args->vrf,
|
|
buf_prefix,
|
|
yang_afi_safi_value2identity(args->afi,
|
|
args->safi),
|
|
buf_src_prefix, table_id, buf_nh_type,
|
|
args->nexthop_vrf, buf_gate_str,
|
|
args->interface_name);
|
|
else
|
|
snprintf(ab_xpath, sizeof(ab_xpath),
|
|
FRR_DEL_S_ROUTE_NH_KEY_NO_DISTANCE_XPATH,
|
|
"frr-staticd:staticd", "staticd", args->vrf,
|
|
buf_prefix,
|
|
yang_afi_safi_value2identity(args->afi,
|
|
args->safi),
|
|
table_id, buf_nh_type, args->nexthop_vrf,
|
|
buf_gate_str, args->interface_name);
|
|
|
|
/*
|
|
* If there's already the same nexthop but with a different
|
|
* distance, then remove it for the replacement.
|
|
*/
|
|
dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath);
|
|
if (dnode) {
|
|
dnode = yang_get_subtree_with_no_sibling(dnode);
|
|
assert(dnode);
|
|
yang_dnode_get_path(dnode, ab_xpath, XPATH_MAXLEN);
|
|
|
|
nb_cli_enqueue_change(vty, ab_xpath, NB_OP_DESTROY,
|
|
NULL);
|
|
}
|
|
|
|
/* route + path procesing */
|
|
if (args->source)
|
|
snprintf(xpath_prefix, sizeof(xpath_prefix),
|
|
FRR_S_ROUTE_SRC_INFO_KEY_XPATH,
|
|
"frr-staticd:staticd", "staticd", args->vrf,
|
|
buf_prefix,
|
|
yang_afi_safi_value2identity(args->afi,
|
|
args->safi),
|
|
buf_src_prefix, table_id, distance);
|
|
else
|
|
snprintf(xpath_prefix, sizeof(xpath_prefix),
|
|
FRR_STATIC_ROUTE_INFO_KEY_XPATH,
|
|
"frr-staticd:staticd", "staticd", args->vrf,
|
|
buf_prefix,
|
|
yang_afi_safi_value2identity(args->afi,
|
|
args->safi),
|
|
table_id, distance);
|
|
|
|
nb_cli_enqueue_change(vty, xpath_prefix, NB_OP_CREATE, NULL);
|
|
|
|
/* Tag processing */
|
|
snprintf(buf_tag, sizeof(buf_tag), "%u", tag);
|
|
strlcpy(ab_xpath, xpath_prefix, sizeof(ab_xpath));
|
|
strlcat(ab_xpath, FRR_STATIC_ROUTE_PATH_TAG_XPATH,
|
|
sizeof(ab_xpath));
|
|
nb_cli_enqueue_change(vty, ab_xpath, NB_OP_MODIFY, buf_tag);
|
|
|
|
/* nexthop processing */
|
|
|
|
snprintf(ab_xpath, sizeof(ab_xpath),
|
|
FRR_STATIC_ROUTE_NH_KEY_XPATH, buf_nh_type,
|
|
args->nexthop_vrf, buf_gate_str, args->interface_name);
|
|
strlcpy(xpath_nexthop, xpath_prefix, sizeof(xpath_nexthop));
|
|
strlcat(xpath_nexthop, ab_xpath, sizeof(xpath_nexthop));
|
|
nb_cli_enqueue_change(vty, xpath_nexthop, NB_OP_CREATE, NULL);
|
|
|
|
if (type == STATIC_BLACKHOLE) {
|
|
strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
|
|
strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_BH_XPATH,
|
|
sizeof(ab_xpath));
|
|
|
|
/* Route flags */
|
|
if (args->flag) {
|
|
switch (args->flag[0]) {
|
|
case 'r':
|
|
bh_type = "reject";
|
|
break;
|
|
case 'b':
|
|
bh_type = "unspec";
|
|
break;
|
|
case 'N':
|
|
bh_type = "null";
|
|
break;
|
|
default:
|
|
bh_type = NULL;
|
|
break;
|
|
}
|
|
nb_cli_enqueue_change(vty, ab_xpath,
|
|
NB_OP_MODIFY, bh_type);
|
|
} else {
|
|
nb_cli_enqueue_change(vty, ab_xpath,
|
|
NB_OP_MODIFY, "null");
|
|
}
|
|
}
|
|
if (type == STATIC_IPV4_GATEWAY_IFNAME
|
|
|| type == STATIC_IPV6_GATEWAY_IFNAME) {
|
|
strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
|
|
strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_ONLINK_XPATH,
|
|
sizeof(ab_xpath));
|
|
|
|
if (args->onlink)
|
|
nb_cli_enqueue_change(vty, ab_xpath,
|
|
NB_OP_MODIFY, "true");
|
|
else
|
|
nb_cli_enqueue_change(vty, ab_xpath,
|
|
NB_OP_MODIFY, "false");
|
|
}
|
|
if (type == STATIC_IPV4_GATEWAY ||
|
|
type == STATIC_IPV6_GATEWAY ||
|
|
type == STATIC_IPV4_GATEWAY_IFNAME ||
|
|
type == STATIC_IPV6_GATEWAY_IFNAME) {
|
|
strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
|
|
strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_COLOR_XPATH,
|
|
sizeof(ab_xpath));
|
|
if (args->color)
|
|
nb_cli_enqueue_change(vty, ab_xpath,
|
|
NB_OP_MODIFY,
|
|
args->color);
|
|
}
|
|
if (args->label) {
|
|
/* copy of label string (start) */
|
|
char *ostr;
|
|
/* pointer to next segment */
|
|
char *nump;
|
|
|
|
strlcpy(xpath_mpls, xpath_nexthop, sizeof(xpath_mpls));
|
|
strlcat(xpath_mpls, FRR_STATIC_ROUTE_NH_LABEL_XPATH,
|
|
sizeof(xpath_mpls));
|
|
|
|
nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
|
|
NULL);
|
|
|
|
orig_label = ostr = XSTRDUP(MTYPE_TMP, args->label);
|
|
while ((nump = strsep(&ostr, "/")) != NULL) {
|
|
snprintf(ab_xpath, sizeof(ab_xpath),
|
|
FRR_STATIC_ROUTE_NHLB_KEY_XPATH,
|
|
label_stack_id);
|
|
strlcpy(xpath_label, xpath_mpls,
|
|
sizeof(xpath_label));
|
|
strlcat(xpath_label, ab_xpath,
|
|
sizeof(xpath_label));
|
|
nb_cli_enqueue_change(vty, xpath_label,
|
|
NB_OP_MODIFY, nump);
|
|
label_stack_id++;
|
|
}
|
|
} else {
|
|
strlcpy(xpath_mpls, xpath_nexthop, sizeof(xpath_mpls));
|
|
strlcat(xpath_mpls, FRR_STATIC_ROUTE_NH_LABEL_XPATH,
|
|
sizeof(xpath_mpls));
|
|
nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
|
|
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);
|
|
|
|
orig_seg = 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++;
|
|
}
|
|
} 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) {
|
|
char xpath_bfd[XPATH_MAXLEN];
|
|
|
|
if (args->bfd_source) {
|
|
strlcpy(xpath_bfd, xpath_nexthop,
|
|
sizeof(xpath_bfd));
|
|
strlcat(xpath_bfd,
|
|
"/frr-staticd:bfd-monitoring/source",
|
|
sizeof(xpath_bfd));
|
|
nb_cli_enqueue_change(vty, xpath_bfd,
|
|
NB_OP_MODIFY,
|
|
args->bfd_source);
|
|
}
|
|
|
|
strlcpy(xpath_bfd, xpath_nexthop, sizeof(xpath_bfd));
|
|
strlcat(xpath_bfd,
|
|
"/frr-staticd:bfd-monitoring/multi-hop",
|
|
sizeof(xpath_bfd));
|
|
nb_cli_enqueue_change(vty, xpath_bfd, NB_OP_MODIFY,
|
|
args->bfd_multi_hop ? "true"
|
|
: "false");
|
|
|
|
if (args->bfd_profile) {
|
|
strlcpy(xpath_bfd, xpath_nexthop,
|
|
sizeof(xpath_bfd));
|
|
strlcat(xpath_bfd,
|
|
"/frr-staticd:bfd-monitoring/profile",
|
|
sizeof(xpath_bfd));
|
|
nb_cli_enqueue_change(vty, xpath_bfd,
|
|
NB_OP_MODIFY,
|
|
args->bfd_profile);
|
|
}
|
|
}
|
|
|
|
ret = nb_cli_apply_changes(vty, "%s", xpath_prefix);
|
|
|
|
if (orig_label)
|
|
XFREE(MTYPE_TMP, orig_label);
|
|
if (orig_seg)
|
|
XFREE(MTYPE_TMP, orig_seg);
|
|
} else {
|
|
if (args->source) {
|
|
if (args->distance)
|
|
snprintf(ab_xpath, sizeof(ab_xpath),
|
|
FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH,
|
|
"frr-staticd:staticd", "staticd",
|
|
args->vrf, buf_prefix,
|
|
yang_afi_safi_value2identity(
|
|
args->afi, args->safi),
|
|
buf_src_prefix, table_id, distance,
|
|
buf_nh_type, args->nexthop_vrf,
|
|
buf_gate_str, args->interface_name);
|
|
else
|
|
snprintf(
|
|
ab_xpath, sizeof(ab_xpath),
|
|
FRR_DEL_S_ROUTE_SRC_NH_KEY_NO_DISTANCE_XPATH,
|
|
"frr-staticd:staticd", "staticd",
|
|
args->vrf, buf_prefix,
|
|
yang_afi_safi_value2identity(
|
|
args->afi, args->safi),
|
|
buf_src_prefix, table_id, buf_nh_type,
|
|
args->nexthop_vrf, buf_gate_str,
|
|
args->interface_name);
|
|
} else {
|
|
if (args->distance)
|
|
snprintf(ab_xpath, sizeof(ab_xpath),
|
|
FRR_DEL_S_ROUTE_NH_KEY_XPATH,
|
|
"frr-staticd:staticd", "staticd",
|
|
args->vrf, buf_prefix,
|
|
yang_afi_safi_value2identity(
|
|
args->afi, args->safi),
|
|
table_id, distance, buf_nh_type,
|
|
args->nexthop_vrf, buf_gate_str,
|
|
args->interface_name);
|
|
else
|
|
snprintf(
|
|
ab_xpath, sizeof(ab_xpath),
|
|
FRR_DEL_S_ROUTE_NH_KEY_NO_DISTANCE_XPATH,
|
|
"frr-staticd:staticd", "staticd",
|
|
args->vrf, buf_prefix,
|
|
yang_afi_safi_value2identity(
|
|
args->afi, args->safi),
|
|
table_id, buf_nh_type,
|
|
args->nexthop_vrf, buf_gate_str,
|
|
args->interface_name);
|
|
}
|
|
|
|
dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath);
|
|
if (!dnode) {
|
|
vty_out(vty,
|
|
"%% Refusing to remove a non-existent route\n");
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
dnode = yang_get_subtree_with_no_sibling(dnode);
|
|
assert(dnode);
|
|
yang_dnode_get_path(dnode, ab_xpath, XPATH_MAXLEN);
|
|
|
|
nb_cli_enqueue_change(vty, ab_xpath, NB_OP_DESTROY, NULL);
|
|
ret = nb_cli_apply_changes(vty, "%s", ab_xpath);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Static unicast routes for multicast RPF lookup. */
|
|
DEFPY_YANG (ip_mroute_dist,
|
|
ip_mroute_dist_cmd,
|
|
"[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [{"
|
|
"(1-255)$distance"
|
|
"|bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}]"
|
|
"}]",
|
|
NO_STR
|
|
IP_STR
|
|
"Configure static unicast route into MRIB for multicast RPF lookup\n"
|
|
"IP destination prefix (e.g. 10.0.0.0/8)\n"
|
|
"Nexthop address\n"
|
|
"Nexthop interface name\n"
|
|
"Distance\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 = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP,
|
|
.safi = SAFI_MULTICAST,
|
|
.prefix = prefix_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.distance = distance_str,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
/* Static route configuration. */
|
|
DEFPY_YANG(ip_route_blackhole,
|
|
ip_route_blackhole_cmd,
|
|
"[no] ip route\
|
|
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
|
|
<reject|blackhole>$flag \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|vrf NAME \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
}]",
|
|
NO_STR IP_STR
|
|
"Establish static routes\n"
|
|
"IP destination prefix (e.g. 10.0.0.0/8)\n"
|
|
"IP destination prefix\n"
|
|
"IP destination prefix mask\n"
|
|
"Emit an ICMP unreachable when matched\n"
|
|
"Silently discard pkts when matched\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this route\n"
|
|
VRF_CMD_HELP_STR
|
|
MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n")
|
|
{
|
|
int idx_flag = 0;
|
|
|
|
struct static_route_args args = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix,
|
|
.prefix_mask = mask_str,
|
|
.flag = flag,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.vrf = vrf,
|
|
};
|
|
|
|
if (flag && argv_find(argv, argc, flag, &idx_flag))
|
|
args.input = argv[idx_flag]->arg;
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ip_route_blackhole_vrf,
|
|
ip_route_blackhole_vrf_cmd,
|
|
"[no] ip route\
|
|
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
|
|
<reject|blackhole>$flag \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
}]",
|
|
NO_STR IP_STR
|
|
"Establish static routes\n"
|
|
"IP destination prefix (e.g. 10.0.0.0/8)\n"
|
|
"IP destination prefix\n"
|
|
"IP destination prefix mask\n"
|
|
"Emit an ICMP unreachable when matched\n"
|
|
"Silently discard pkts when matched\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this route\n"
|
|
MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n")
|
|
{
|
|
int idx_flag = 0;
|
|
|
|
struct static_route_args args = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix,
|
|
.prefix_mask = mask_str,
|
|
.flag = flag,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.xpath_vrf = true,
|
|
};
|
|
|
|
/*
|
|
* Coverity is complaining that prefix could
|
|
* be dereferenced, but we know that prefix will
|
|
* valid. Add an assert to make it happy
|
|
*/
|
|
assert(args.prefix);
|
|
|
|
if (flag && argv_find(argv, argc, flag, &idx_flag))
|
|
args.input = argv[idx_flag]->arg;
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ip_route_address_interface,
|
|
ip_route_address_interface_cmd,
|
|
"[no] ip route\
|
|
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
|
|
A.B.C.D$gate \
|
|
<INTERFACE|Null0>$ifname \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|vrf NAME \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
|nexthop-vrf NAME \
|
|
|onlink$onlink \
|
|
|color (1-4294967295) \
|
|
|bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
|
|
}]",
|
|
NO_STR IP_STR
|
|
"Establish static routes\n"
|
|
"IP destination prefix (e.g. 10.0.0.0/8)\n"
|
|
"IP destination prefix\n"
|
|
"IP destination prefix mask\n"
|
|
"IP gateway address\n"
|
|
"IP gateway interface name\n"
|
|
"Null interface\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this route\n"
|
|
VRF_CMD_HELP_STR
|
|
MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n"
|
|
VRF_CMD_HELP_STR
|
|
"Treat the nexthop as directly attached to the interface\n"
|
|
"SR-TE color\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 = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix,
|
|
.prefix_mask = mask_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.color = color_str,
|
|
.onlink = !!onlink,
|
|
.vrf = vrf,
|
|
.nexthop_vrf = nexthop_vrf,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ip_route_address_interface_vrf,
|
|
ip_route_address_interface_vrf_cmd,
|
|
"[no] ip route\
|
|
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
|
|
A.B.C.D$gate \
|
|
<INTERFACE|Null0>$ifname \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
|nexthop-vrf NAME \
|
|
|onlink$onlink \
|
|
|color (1-4294967295) \
|
|
|bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
|
|
}]",
|
|
NO_STR IP_STR
|
|
"Establish static routes\n"
|
|
"IP destination prefix (e.g. 10.0.0.0/8)\n"
|
|
"IP destination prefix\n"
|
|
"IP destination prefix mask\n"
|
|
"IP gateway address\n"
|
|
"IP gateway interface name\n"
|
|
"Null interface\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this route\n"
|
|
MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n"
|
|
VRF_CMD_HELP_STR
|
|
"Treat the nexthop as directly attached to the interface\n"
|
|
"SR-TE color\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 = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix,
|
|
.prefix_mask = mask_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.color = color_str,
|
|
.onlink = !!onlink,
|
|
.xpath_vrf = true,
|
|
.nexthop_vrf = nexthop_vrf,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ip_route,
|
|
ip_route_cmd,
|
|
"[no] ip route\
|
|
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
|
|
<A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|vrf NAME \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
|nexthop-vrf NAME \
|
|
|color (1-4294967295) \
|
|
|bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
|
|
}]",
|
|
NO_STR IP_STR
|
|
"Establish static routes\n"
|
|
"IP destination prefix (e.g. 10.0.0.0/8)\n"
|
|
"IP destination prefix\n"
|
|
"IP destination prefix mask\n"
|
|
"IP gateway address\n"
|
|
"IP gateway interface name\n"
|
|
"Null interface\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this route\n"
|
|
VRF_CMD_HELP_STR
|
|
MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n"
|
|
VRF_CMD_HELP_STR
|
|
"SR-TE color\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 = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix,
|
|
.prefix_mask = mask_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.color = color_str,
|
|
.vrf = vrf,
|
|
.nexthop_vrf = nexthop_vrf,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ip_route_vrf,
|
|
ip_route_vrf_cmd,
|
|
"[no] ip route\
|
|
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
|
|
<A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
|nexthop-vrf NAME \
|
|
|color (1-4294967295) \
|
|
|bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
|
|
}]",
|
|
NO_STR IP_STR
|
|
"Establish static routes\n"
|
|
"IP destination prefix (e.g. 10.0.0.0/8)\n"
|
|
"IP destination prefix\n"
|
|
"IP destination prefix mask\n"
|
|
"IP gateway address\n"
|
|
"IP gateway interface name\n"
|
|
"Null interface\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this route\n"
|
|
MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n"
|
|
VRF_CMD_HELP_STR
|
|
"SR-TE color\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 = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix,
|
|
.prefix_mask = mask_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.color = color_str,
|
|
.xpath_vrf = true,
|
|
.nexthop_vrf = nexthop_vrf,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ipv6_route_blackhole,
|
|
ipv6_route_blackhole_cmd,
|
|
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
|
|
<reject|blackhole>$flag \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|vrf NAME \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
}]",
|
|
NO_STR
|
|
IPV6_STR
|
|
"Establish static routes\n"
|
|
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
|
|
"IPv6 source-dest route\n"
|
|
"IPv6 source prefix\n"
|
|
"Emit an ICMP unreachable when matched\n"
|
|
"Silently discard pkts when matched\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this prefix\n"
|
|
VRF_CMD_HELP_STR
|
|
MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n")
|
|
{
|
|
int idx_flag = 0;
|
|
|
|
struct static_route_args args = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP6,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix_str,
|
|
.source = from_str,
|
|
.flag = flag,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.vrf = vrf,
|
|
};
|
|
|
|
if (flag && argv_find(argv, argc, flag, &idx_flag))
|
|
args.input = argv[idx_flag]->arg;
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ipv6_route_blackhole_vrf,
|
|
ipv6_route_blackhole_vrf_cmd,
|
|
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
|
|
<reject|blackhole>$flag \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
}]",
|
|
NO_STR
|
|
IPV6_STR
|
|
"Establish static routes\n"
|
|
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
|
|
"IPv6 source-dest route\n"
|
|
"IPv6 source prefix\n"
|
|
"Emit an ICMP unreachable when matched\n"
|
|
"Silently discard pkts when matched\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this prefix\n"
|
|
MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n")
|
|
{
|
|
int idx_flag = 0;
|
|
|
|
struct static_route_args args = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP6,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix_str,
|
|
.source = from_str,
|
|
.flag = flag,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.xpath_vrf = true,
|
|
};
|
|
|
|
/*
|
|
* Coverity is complaining that prefix could
|
|
* be dereferenced, but we know that prefix will
|
|
* valid. Add an assert to make it happy
|
|
*/
|
|
assert(args.prefix);
|
|
|
|
if (flag && argv_find(argv, argc, flag, &idx_flag))
|
|
args.input = argv[idx_flag]->arg;
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ipv6_route_address_interface, ipv6_route_address_interface_cmd,
|
|
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
|
|
X:X::X:X$gate \
|
|
<INTERFACE|Null0>$ifname \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|vrf NAME \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
|nexthop-vrf NAME \
|
|
|onlink$onlink \
|
|
|color (1-4294967295) \
|
|
|bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
|
|
|segments WORD \
|
|
}]",
|
|
NO_STR IPV6_STR
|
|
"Establish static routes\n"
|
|
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
|
|
"IPv6 source-dest route\n"
|
|
"IPv6 source prefix\n"
|
|
"IPv6 gateway address\n"
|
|
"IPv6 gateway interface name\n"
|
|
"Null interface\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this prefix\n" VRF_CMD_HELP_STR MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n" VRF_CMD_HELP_STR
|
|
"Treat the nexthop as directly attached to the interface\n"
|
|
"SR-TE color\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 "Value of segs\n"
|
|
"Segs (SIDs)\n")
|
|
{
|
|
struct static_route_args args = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP6,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix_str,
|
|
.source = from_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.color = color_str,
|
|
.onlink = !!onlink,
|
|
.vrf = vrf,
|
|
.nexthop_vrf = nexthop_vrf,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
.segs = segments,
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ipv6_route_address_interface_vrf,
|
|
ipv6_route_address_interface_vrf_cmd,
|
|
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
|
|
X:X::X:X$gate \
|
|
<INTERFACE|Null0>$ifname \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
|nexthop-vrf NAME \
|
|
|onlink$onlink \
|
|
|color (1-4294967295) \
|
|
|bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
|
|
|segments WORD \
|
|
}]",
|
|
NO_STR IPV6_STR
|
|
"Establish static routes\n"
|
|
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
|
|
"IPv6 source-dest route\n"
|
|
"IPv6 source prefix\n"
|
|
"IPv6 gateway address\n"
|
|
"IPv6 gateway interface name\n"
|
|
"Null interface\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this prefix\n" MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n" VRF_CMD_HELP_STR
|
|
"Treat the nexthop as directly attached to the interface\n"
|
|
"SR-TE color\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 "Value of segs\n"
|
|
"Segs (SIDs)\n")
|
|
{
|
|
struct static_route_args args = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP6,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix_str,
|
|
.source = from_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.color = color_str,
|
|
.onlink = !!onlink,
|
|
.xpath_vrf = true,
|
|
.nexthop_vrf = nexthop_vrf,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
.segs = segments,
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ipv6_route, ipv6_route_cmd,
|
|
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
|
|
<X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|vrf NAME \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
|nexthop-vrf NAME \
|
|
|color (1-4294967295) \
|
|
|bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
|
|
|segments WORD \
|
|
}]",
|
|
NO_STR IPV6_STR
|
|
"Establish static routes\n"
|
|
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
|
|
"IPv6 source-dest route\n"
|
|
"IPv6 source prefix\n"
|
|
"IPv6 gateway address\n"
|
|
"IPv6 gateway interface name\n"
|
|
"Null interface\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this prefix\n" VRF_CMD_HELP_STR MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n" VRF_CMD_HELP_STR "SR-TE color\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 "Value of segs\n"
|
|
"Segs (SIDs)\n")
|
|
{
|
|
struct static_route_args args = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP6,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix_str,
|
|
.source = from_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.color = color_str,
|
|
.vrf = vrf,
|
|
.nexthop_vrf = nexthop_vrf,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
.segs = segments,
|
|
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
DEFPY_YANG(ipv6_route_vrf, ipv6_route_vrf_cmd,
|
|
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
|
|
<X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
|
|
[{ \
|
|
tag (1-4294967295) \
|
|
|(1-255)$distance \
|
|
|label WORD \
|
|
|table (1-4294967295) \
|
|
|nexthop-vrf NAME \
|
|
|color (1-4294967295) \
|
|
|bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
|
|
|segments WORD \
|
|
}]",
|
|
NO_STR IPV6_STR
|
|
"Establish static routes\n"
|
|
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
|
|
"IPv6 source-dest route\n"
|
|
"IPv6 source prefix\n"
|
|
"IPv6 gateway address\n"
|
|
"IPv6 gateway interface name\n"
|
|
"Null interface\n"
|
|
"Set tag for this route\n"
|
|
"Tag value\n"
|
|
"Distance value for this prefix\n" MPLS_LABEL_HELPSTR
|
|
"Table to configure\n"
|
|
"The table number to configure\n" VRF_CMD_HELP_STR "SR-TE color\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 "Value of segs\n"
|
|
"Segs (SIDs)\n")
|
|
{
|
|
struct static_route_args args = {
|
|
.delete = !!no,
|
|
.afi = AFI_IP6,
|
|
.safi = SAFI_UNICAST,
|
|
.prefix = prefix_str,
|
|
.source = from_str,
|
|
.gateway = gate_str,
|
|
.interface_name = ifname,
|
|
.tag = tag_str,
|
|
.distance = distance_str,
|
|
.label = label,
|
|
.table = table_str,
|
|
.color = color_str,
|
|
.xpath_vrf = true,
|
|
.nexthop_vrf = nexthop_vrf,
|
|
.bfd = !!bfd,
|
|
.bfd_multi_hop = !!bfd_multi_hop,
|
|
.bfd_source = bfd_source_str,
|
|
.bfd_profile = bfd_profile,
|
|
.segs = segments,
|
|
};
|
|
|
|
return static_route_nb_run(vty, &args);
|
|
}
|
|
|
|
#ifdef INCLUDE_MGMTD_CMDDEFS_ONLY
|
|
|
|
static void static_cli_show(struct vty *vty, const struct lyd_node *dnode,
|
|
bool show_defaults)
|
|
{
|
|
const char *vrf;
|
|
|
|
vrf = yang_dnode_get_string(dnode, "../vrf");
|
|
if (strcmp(vrf, VRF_DEFAULT_NAME))
|
|
vty_out(vty, "vrf %s\n", vrf);
|
|
}
|
|
|
|
static void static_cli_show_end(struct vty *vty, const struct lyd_node *dnode)
|
|
{
|
|
const char *vrf;
|
|
|
|
vrf = yang_dnode_get_string(dnode, "../vrf");
|
|
if (strcmp(vrf, VRF_DEFAULT_NAME))
|
|
vty_out(vty, "exit-vrf\n");
|
|
}
|
|
|
|
struct mpls_label_iter {
|
|
struct vty *vty;
|
|
bool first;
|
|
};
|
|
|
|
static int mpls_label_iter_cb(const struct lyd_node *dnode, void *arg)
|
|
{
|
|
struct mpls_label_iter *iter = arg;
|
|
|
|
if (yang_dnode_exists(dnode, "label")) {
|
|
if (iter->first)
|
|
vty_out(iter->vty, " label %s",
|
|
yang_dnode_get_string(dnode, "label"));
|
|
else
|
|
vty_out(iter->vty, "/%s",
|
|
yang_dnode_get_string(dnode, "label"));
|
|
iter->first = false;
|
|
}
|
|
|
|
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,
|
|
const struct lyd_node *src,
|
|
const struct lyd_node *path,
|
|
const struct lyd_node *nexthop, bool show_defaults)
|
|
{
|
|
const char *vrf;
|
|
const char *afi_safi;
|
|
afi_t afi;
|
|
safi_t safi;
|
|
enum static_nh_type nh_type;
|
|
enum static_blackhole_type bh_type;
|
|
uint32_t tag;
|
|
uint8_t distance;
|
|
struct mpls_label_iter iter;
|
|
struct srv6_seg_iter seg_iter;
|
|
const char *nexthop_vrf;
|
|
uint32_t table_id;
|
|
bool onlink;
|
|
|
|
vrf = yang_dnode_get_string(route, "../../vrf");
|
|
|
|
afi_safi = yang_dnode_get_string(route, "afi-safi");
|
|
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
|
|
|
|
if (afi == AFI_IP)
|
|
vty_out(vty, "%sip",
|
|
strmatch(vrf, VRF_DEFAULT_NAME) ? "" : " ");
|
|
else
|
|
vty_out(vty, "%sipv6",
|
|
strmatch(vrf, VRF_DEFAULT_NAME) ? "" : " ");
|
|
|
|
if (safi == SAFI_UNICAST)
|
|
vty_out(vty, " route");
|
|
else
|
|
vty_out(vty, " mroute");
|
|
|
|
vty_out(vty, " %s", yang_dnode_get_string(route, "prefix"));
|
|
|
|
if (src)
|
|
vty_out(vty, " from %s",
|
|
yang_dnode_get_string(src, "src-prefix"));
|
|
|
|
nh_type = yang_dnode_get_enum(nexthop, "nh-type");
|
|
switch (nh_type) {
|
|
case STATIC_IFNAME:
|
|
vty_out(vty, " %s",
|
|
yang_dnode_get_string(nexthop, "interface"));
|
|
break;
|
|
case STATIC_IPV4_GATEWAY:
|
|
case STATIC_IPV6_GATEWAY:
|
|
vty_out(vty, " %s",
|
|
yang_dnode_get_string(nexthop, "gateway"));
|
|
break;
|
|
case STATIC_IPV4_GATEWAY_IFNAME:
|
|
case STATIC_IPV6_GATEWAY_IFNAME:
|
|
vty_out(vty, " %s",
|
|
yang_dnode_get_string(nexthop, "gateway"));
|
|
vty_out(vty, " %s",
|
|
yang_dnode_get_string(nexthop, "interface"));
|
|
break;
|
|
case STATIC_BLACKHOLE:
|
|
bh_type = yang_dnode_get_enum(nexthop, "bh-type");
|
|
switch (bh_type) {
|
|
case STATIC_BLACKHOLE_DROP:
|
|
vty_out(vty, " blackhole");
|
|
break;
|
|
case STATIC_BLACKHOLE_NULL:
|
|
vty_out(vty, " Null0");
|
|
break;
|
|
case STATIC_BLACKHOLE_REJECT:
|
|
vty_out(vty, " reject");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (yang_dnode_exists(path, "tag")) {
|
|
tag = yang_dnode_get_uint32(path, "tag");
|
|
if (tag != 0 || show_defaults)
|
|
vty_out(vty, " tag %" PRIu32, tag);
|
|
}
|
|
|
|
distance = yang_dnode_get_uint8(path, "distance");
|
|
if (distance != ZEBRA_STATIC_DISTANCE_DEFAULT || show_defaults)
|
|
vty_out(vty, " %" PRIu8, distance);
|
|
|
|
iter.vty = vty;
|
|
iter.first = true;
|
|
yang_dnode_iterate(mpls_label_iter_cb, &iter, nexthop,
|
|
"./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");
|
|
if (strcmp(vrf, nexthop_vrf))
|
|
vty_out(vty, " nexthop-vrf %s", nexthop_vrf);
|
|
|
|
table_id = yang_dnode_get_uint32(path, "table-id");
|
|
if (table_id || show_defaults)
|
|
vty_out(vty, " table %" PRIu32, table_id);
|
|
|
|
if (yang_dnode_exists(nexthop, "onlink")) {
|
|
onlink = yang_dnode_get_bool(nexthop, "onlink");
|
|
if (onlink)
|
|
vty_out(vty, " onlink");
|
|
}
|
|
|
|
if (yang_dnode_exists(nexthop, "srte-color"))
|
|
vty_out(vty, " color %s",
|
|
yang_dnode_get_string(nexthop, "srte-color"));
|
|
|
|
if (yang_dnode_exists(nexthop, "bfd-monitoring")) {
|
|
const struct lyd_node *bfd_dnode =
|
|
yang_dnode_get(nexthop, "bfd-monitoring");
|
|
|
|
if (yang_dnode_get_bool(bfd_dnode, "multi-hop")) {
|
|
vty_out(vty, " bfd multi-hop");
|
|
|
|
if (yang_dnode_exists(bfd_dnode, "source"))
|
|
vty_out(vty, " source %s",
|
|
yang_dnode_get_string(bfd_dnode,
|
|
"./source"));
|
|
} else
|
|
vty_out(vty, " bfd");
|
|
|
|
if (yang_dnode_exists(bfd_dnode, "profile"))
|
|
vty_out(vty, " profile %s",
|
|
yang_dnode_get_string(bfd_dnode, "profile"));
|
|
}
|
|
|
|
vty_out(vty, "\n");
|
|
}
|
|
|
|
static void static_nexthop_cli_show(struct vty *vty,
|
|
const struct lyd_node *dnode,
|
|
bool show_defaults)
|
|
{
|
|
const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list");
|
|
const struct lyd_node *route =
|
|
yang_dnode_get_parent(path, "route-list");
|
|
|
|
nexthop_cli_show(vty, route, NULL, path, dnode, show_defaults);
|
|
}
|
|
|
|
static void static_src_nexthop_cli_show(struct vty *vty,
|
|
const struct lyd_node *dnode,
|
|
bool show_defaults)
|
|
{
|
|
const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list");
|
|
const struct lyd_node *src = yang_dnode_get_parent(path, "src-list");
|
|
const struct lyd_node *route = yang_dnode_get_parent(src, "route-list");
|
|
|
|
nexthop_cli_show(vty, route, src, path, dnode, show_defaults);
|
|
}
|
|
|
|
static int static_nexthop_cli_cmp(const struct lyd_node *dnode1,
|
|
const struct lyd_node *dnode2)
|
|
{
|
|
enum static_nh_type nh_type1, nh_type2;
|
|
struct prefix prefix1, prefix2;
|
|
const char *vrf1, *vrf2;
|
|
int ret = 0;
|
|
|
|
nh_type1 = yang_dnode_get_enum(dnode1, "nh-type");
|
|
nh_type2 = yang_dnode_get_enum(dnode2, "nh-type");
|
|
|
|
if (nh_type1 != nh_type2)
|
|
return (int)nh_type1 - (int)nh_type2;
|
|
|
|
switch (nh_type1) {
|
|
case STATIC_IFNAME:
|
|
ret = if_cmp_name_func(
|
|
yang_dnode_get_string(dnode1, "interface"),
|
|
yang_dnode_get_string(dnode2, "interface"));
|
|
break;
|
|
case STATIC_IPV4_GATEWAY:
|
|
case STATIC_IPV6_GATEWAY:
|
|
yang_dnode_get_prefix(&prefix1, dnode1, "gateway");
|
|
yang_dnode_get_prefix(&prefix2, dnode2, "gateway");
|
|
ret = prefix_cmp(&prefix1, &prefix2);
|
|
break;
|
|
case STATIC_IPV4_GATEWAY_IFNAME:
|
|
case STATIC_IPV6_GATEWAY_IFNAME:
|
|
yang_dnode_get_prefix(&prefix1, dnode1, "gateway");
|
|
yang_dnode_get_prefix(&prefix2, dnode2, "gateway");
|
|
ret = prefix_cmp(&prefix1, &prefix2);
|
|
if (!ret)
|
|
ret = if_cmp_name_func(
|
|
yang_dnode_get_string(dnode1, "interface"),
|
|
yang_dnode_get_string(dnode2, "interface"));
|
|
break;
|
|
case STATIC_BLACKHOLE:
|
|
/* There's only one blackhole nexthop per route */
|
|
ret = 0;
|
|
break;
|
|
}
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
vrf1 = yang_dnode_get_string(dnode1, "vrf");
|
|
if (strmatch(vrf1, "default"))
|
|
vrf1 = "";
|
|
vrf2 = yang_dnode_get_string(dnode2, "vrf");
|
|
if (strmatch(vrf2, "default"))
|
|
vrf2 = "";
|
|
|
|
return if_cmp_name_func(vrf1, vrf2);
|
|
}
|
|
|
|
static int static_route_list_cli_cmp(const struct lyd_node *dnode1,
|
|
const struct lyd_node *dnode2)
|
|
{
|
|
const char *afi_safi1, *afi_safi2;
|
|
afi_t afi1, afi2;
|
|
safi_t safi1, safi2;
|
|
struct prefix prefix1, prefix2;
|
|
|
|
afi_safi1 = yang_dnode_get_string(dnode1, "afi-safi");
|
|
yang_afi_safi_identity2value(afi_safi1, &afi1, &safi1);
|
|
|
|
afi_safi2 = yang_dnode_get_string(dnode2, "afi-safi");
|
|
yang_afi_safi_identity2value(afi_safi2, &afi2, &safi2);
|
|
|
|
if (afi1 != afi2)
|
|
return (int)afi1 - (int)afi2;
|
|
|
|
if (safi1 != safi2)
|
|
return (int)safi1 - (int)safi2;
|
|
|
|
yang_dnode_get_prefix(&prefix1, dnode1, "prefix");
|
|
yang_dnode_get_prefix(&prefix2, dnode2, "prefix");
|
|
|
|
return prefix_cmp(&prefix1, &prefix2);
|
|
}
|
|
|
|
static int static_src_list_cli_cmp(const struct lyd_node *dnode1,
|
|
const struct lyd_node *dnode2)
|
|
{
|
|
struct prefix prefix1, prefix2;
|
|
|
|
yang_dnode_get_prefix(&prefix1, dnode1, "src-prefix");
|
|
yang_dnode_get_prefix(&prefix2, dnode2, "src-prefix");
|
|
|
|
return prefix_cmp(&prefix1, &prefix2);
|
|
}
|
|
|
|
static int static_path_list_cli_cmp(const struct lyd_node *dnode1,
|
|
const struct lyd_node *dnode2)
|
|
{
|
|
uint32_t table_id1, table_id2;
|
|
uint8_t distance1, distance2;
|
|
|
|
table_id1 = yang_dnode_get_uint32(dnode1, "table-id");
|
|
table_id2 = yang_dnode_get_uint32(dnode2, "table-id");
|
|
|
|
if (table_id1 != table_id2)
|
|
return (int)table_id1 - (int)table_id2;
|
|
|
|
distance1 = yang_dnode_get_uint8(dnode1, "distance");
|
|
distance2 = yang_dnode_get_uint8(dnode2, "distance");
|
|
|
|
return (int)distance1 - (int)distance2;
|
|
}
|
|
|
|
const struct frr_yang_module_info frr_staticd_cli_info = {
|
|
.name = "frr-staticd",
|
|
.ignore_cfg_cbs = true,
|
|
.nodes = {
|
|
{
|
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd",
|
|
.cbs = {
|
|
.cli_show = static_cli_show,
|
|
.cli_show_end = static_cli_show_end,
|
|
}
|
|
},
|
|
{
|
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list",
|
|
.cbs = {
|
|
.cli_cmp = static_route_list_cli_cmp,
|
|
}
|
|
},
|
|
{
|
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list",
|
|
.cbs = {
|
|
.cli_cmp = static_path_list_cli_cmp,
|
|
}
|
|
},
|
|
{
|
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop",
|
|
.cbs = {
|
|
.cli_show = static_nexthop_cli_show,
|
|
.cli_cmp = static_nexthop_cli_cmp,
|
|
}
|
|
},
|
|
{
|
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list",
|
|
.cbs = {
|
|
.cli_cmp = static_src_list_cli_cmp,
|
|
}
|
|
},
|
|
{
|
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list",
|
|
.cbs = {
|
|
.cli_cmp = static_path_list_cli_cmp,
|
|
}
|
|
},
|
|
{
|
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop",
|
|
.cbs = {
|
|
.cli_show = static_src_nexthop_cli_show,
|
|
.cli_cmp = static_nexthop_cli_cmp,
|
|
}
|
|
},
|
|
{
|
|
.xpath = NULL,
|
|
},
|
|
}
|
|
};
|
|
|
|
#else /* ifdef INCLUDE_MGMTD_CMDDEFS_ONLY */
|
|
|
|
DEFPY_YANG(debug_staticd, debug_staticd_cmd,
|
|
"[no] debug static [{events$events|route$route|bfd$bfd}]",
|
|
NO_STR DEBUG_STR STATICD_STR
|
|
"Debug events\n"
|
|
"Debug route\n"
|
|
"Debug bfd\n")
|
|
{
|
|
/* If no specific category, change all */
|
|
if (strmatch(argv[argc - 1]->text, "static"))
|
|
static_debug_set(vty->node, !no, true, true, true);
|
|
else
|
|
static_debug_set(vty->node, !no, !!events, !!route, !!bfd);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFPY(staticd_show_bfd_routes, staticd_show_bfd_routes_cmd,
|
|
"show bfd static route [json]$isjson",
|
|
SHOW_STR
|
|
BFD_INTEGRATION_STR
|
|
STATICD_STR
|
|
ROUTE_STR
|
|
JSON_STR)
|
|
{
|
|
static_bfd_show(vty, !!isjson);
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
DEFUN_NOSH (show_debugging_static,
|
|
show_debugging_static_cmd,
|
|
"show debugging [static]",
|
|
SHOW_STR
|
|
DEBUG_STR
|
|
"Static Information\n")
|
|
{
|
|
vty_out(vty, "Staticd debugging status\n");
|
|
|
|
static_debug_status_write(vty);
|
|
|
|
cmd_show_lib_debugs(vty);
|
|
|
|
return CMD_SUCCESS;
|
|
}
|
|
|
|
static struct cmd_node debug_node = {
|
|
.name = "debug",
|
|
.node = DEBUG_NODE,
|
|
.prompt = "",
|
|
.config_write = static_config_write_debug,
|
|
};
|
|
|
|
#endif /* ifndef INCLUDE_MGMTD_CMDDEFS_ONLY */
|
|
|
|
void static_vty_init(void)
|
|
{
|
|
#ifndef INCLUDE_MGMTD_CMDDEFS_ONLY
|
|
install_node(&debug_node);
|
|
install_element(ENABLE_NODE, &debug_staticd_cmd);
|
|
install_element(CONFIG_NODE, &debug_staticd_cmd);
|
|
install_element(ENABLE_NODE, &show_debugging_static_cmd);
|
|
install_element(ENABLE_NODE, &staticd_show_bfd_routes_cmd);
|
|
#else /* else INCLUDE_MGMTD_CMDDEFS_ONLY */
|
|
install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
|
|
|
|
install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
|
|
install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
|
|
install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
|
|
install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
|
|
install_element(CONFIG_NODE, &ip_route_cmd);
|
|
install_element(VRF_NODE, &ip_route_vrf_cmd);
|
|
|
|
install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
|
|
install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
|
|
install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
|
|
install_element(CONFIG_NODE, &ipv6_route_cmd);
|
|
install_element(VRF_NODE, &ipv6_route_vrf_cmd);
|
|
#endif /* ifndef INCLUDE_MGMTD_CMDDEFS_ONLY */
|
|
|
|
#ifndef INCLUDE_MGMTD_CMDDEFS_ONLY
|
|
mgmt_be_client_lib_vty_init();
|
|
#endif
|
|
}
|