1688 lines
48 KiB
C
1688 lines
48 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;
|
||
|
};
|
||
|
|
||
|
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;
|
||
|
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")
|
||
|
{
|
||
|
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,
|
||
|
};
|
||
|
|
||
|
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")
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
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")
|
||
|
{
|
||
|
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,
|
||
|
};
|
||
|
|
||
|
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")
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
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
|
||
|
}
|