diff options
Diffstat (limited to 'staticd/static_vty.c')
| -rw-r--r-- | staticd/static_vty.c | 1195 |
1 files changed, 417 insertions, 778 deletions
diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 75bce82eef..ac18f6adf4 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -27,6 +27,10 @@ #include "table.h" #include "srcdest_table.h" #include "mpls.h" +#include "northbound.h" +#include "libfrr.h" +#include "routing_nb.h" +#include "northbound_cli.h" #include "static_vrf.h" #include "static_memory.h" @@ -36,251 +40,43 @@ #ifndef VTYSH_EXTRACT_PL #include "staticd/static_vty_clippy.c" #endif +#include "static_nb.h" #define STATICD_STR "Static route daemon\n" -static struct static_vrf *static_vty_get_unknown_vrf(struct vty *vty, - const char *vrf_name) +static int static_route_leak(struct vty *vty, const char *svrf, + const char *nh_svrf, afi_t afi, safi_t safi, + const char *negate, const char *dest_str, + const char *mask_str, const char *src_str, + const char *gate_str, const char *ifname, + const char *flag_str, const char *tag_str, + const char *distance_str, const char *label_str, + const char *table_str, bool onlink) { - struct static_vrf *svrf; - struct vrf *vrf; - - svrf = static_vrf_lookup_by_name(vrf_name); - - if (svrf) - return svrf; - - vrf = vrf_get(VRF_UNKNOWN, vrf_name); - if (!vrf) { - vty_out(vty, "%% Could not create vrf %s\n", vrf_name); - return NULL; - } - svrf = vrf->info; - if (!svrf) { - vty_out(vty, "%% Could not create vrf-info %s\n", - vrf_name); - return NULL; - } - /* Mark as having FRR configuration */ - vrf_set_user_cfged(vrf); - - return svrf; -} - -struct static_hold_route { - char *vrf_name; - char *nhvrf_name; - afi_t afi; - safi_t safi; - char *dest_str; - char *mask_str; - char *src_str; - char *gate_str; - char *ifname; - char *flag_str; - char *tag_str; - char *distance_str; - char *label_str; - char *table_str; - bool onlink; - - /* processed & masked destination, used for config display */ - struct prefix dest; -}; - -static struct list *static_list; - -static int static_list_compare_helper(const char *s1, const char *s2) -{ - /* extra (!s1 && !s2) to keep SA happy */ - if (s1 == s2 || (!s1 && !s2)) - return 0; - - if (!s1 && s2) - return -1; - - if (s1 && !s2) - return 1; - - return strcmp(s1, s2); -} - -static void static_list_delete(struct static_hold_route *shr) -{ - XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name); - XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name); - XFREE(MTYPE_STATIC_ROUTE, shr->dest_str); - XFREE(MTYPE_STATIC_ROUTE, shr->mask_str); - XFREE(MTYPE_STATIC_ROUTE, shr->src_str); - XFREE(MTYPE_STATIC_ROUTE, shr->gate_str); - XFREE(MTYPE_STATIC_ROUTE, shr->ifname); - XFREE(MTYPE_STATIC_ROUTE, shr->flag_str); - XFREE(MTYPE_STATIC_ROUTE, shr->tag_str); - XFREE(MTYPE_STATIC_ROUTE, shr->distance_str); - XFREE(MTYPE_STATIC_ROUTE, shr->label_str); - XFREE(MTYPE_STATIC_ROUTE, shr->table_str); - - XFREE(MTYPE_STATIC_ROUTE, shr); -} - -static int static_list_compare(void *arg1, void *arg2) -{ - struct static_hold_route *shr1 = arg1; - struct static_hold_route *shr2 = arg2; int ret; - - ret = strcmp(shr1->vrf_name, shr2->vrf_name); - if (ret) - return ret; - - ret = strcmp(shr1->nhvrf_name, shr2->nhvrf_name); - if (ret) - return ret; - - ret = shr1->afi - shr2->afi; - if (ret) - return ret; - - ret = shr1->safi - shr2->safi; - if (ret) - return ret; - - ret = prefix_cmp(&shr1->dest, &shr2->dest); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->src_str, shr2->src_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->gate_str, shr2->gate_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->ifname, shr2->ifname); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->flag_str, shr2->flag_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->tag_str, shr2->tag_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->distance_str, - shr2->distance_str); - if (ret) - return ret; - - ret = static_list_compare_helper(shr1->table_str, - shr2->table_str); - if (ret) - return ret; - - return static_list_compare_helper(shr1->label_str, shr2->label_str); -} - - -/* General function for static route. */ -static int zebra_static_route_holdem( - struct static_vrf *svrf, struct static_vrf *nh_svrf, afi_t afi, - safi_t safi, const char *negate, struct prefix *dest, - const char *dest_str, const char *mask_str, const char *src_str, - const char *gate_str, const char *ifname, const char *flag_str, - const char *tag_str, const char *distance_str, const char *label_str, - const char *table_str, bool onlink) -{ - struct static_hold_route *shr, *lookup; - struct listnode *node; - - zlog_warn("Static Route to %s not installed currently because dependent config not fully available", - dest_str); - - shr = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(*shr)); - shr->vrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, svrf->vrf->name); - shr->nhvrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, nh_svrf->vrf->name); - shr->afi = afi; - shr->safi = safi; - shr->onlink = onlink; - if (dest) - prefix_copy(&shr->dest, dest); - if (dest_str) - shr->dest_str = XSTRDUP(MTYPE_STATIC_ROUTE, dest_str); - if (mask_str) - shr->mask_str = XSTRDUP(MTYPE_STATIC_ROUTE, mask_str); - if (src_str) - shr->src_str = XSTRDUP(MTYPE_STATIC_ROUTE, src_str); - if (gate_str) - shr->gate_str = XSTRDUP(MTYPE_STATIC_ROUTE, gate_str); - if (ifname) - shr->ifname = XSTRDUP(MTYPE_STATIC_ROUTE, ifname); - if (flag_str) - shr->flag_str = XSTRDUP(MTYPE_STATIC_ROUTE, flag_str); - if (tag_str) - shr->tag_str = XSTRDUP(MTYPE_STATIC_ROUTE, tag_str); - if (distance_str) - shr->distance_str = XSTRDUP(MTYPE_STATIC_ROUTE, distance_str); - if (label_str) - shr->label_str = XSTRDUP(MTYPE_STATIC_ROUTE, label_str); - if (table_str) - shr->table_str = XSTRDUP(MTYPE_STATIC_ROUTE, table_str); - - for (ALL_LIST_ELEMENTS_RO(static_list, node, lookup)) { - if (static_list_compare(shr, lookup) == 0) - break; - } - - if (lookup) { - if (negate) { - listnode_delete(static_list, lookup); - static_list_delete(shr); - static_list_delete(lookup); - - return CMD_SUCCESS; - } - - /* - * If a person enters the same line again - * we need to silently accept it - */ - goto shr_cleanup; - } - - if (!negate) { - listnode_add_sort(static_list, shr); - return CMD_SUCCESS; - } - - shr_cleanup: - XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name); - XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name); - XFREE(MTYPE_STATIC_ROUTE, shr); - - return CMD_SUCCESS; -} - -static int static_route_leak( - struct vty *vty, struct static_vrf *svrf, struct static_vrf *nh_svrf, - afi_t afi, safi_t safi, const char *negate, const char *dest_str, - const char *mask_str, const char *src_str, const char *gate_str, - const char *ifname, const char *flag_str, const char *tag_str, - const char *distance_str, const char *label_str, const char *table_str, - bool onlink) -{ - int ret; - uint8_t distance; struct prefix p, src; - struct prefix_ipv6 *src_p = NULL; - union g_addr gate; - union g_addr *gatep = NULL; struct in_addr mask; - enum static_blackhole_type bh_type = 0; - route_tag_t tag = 0; uint8_t type; - struct static_nh_label snh_label; + 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 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]; + char buf_tableid[PREFIX_STRLEN]; + uint8_t label_stack_id = 0; + 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; + + memset(buf_src_prefix, 0, PREFIX_STRLEN); + memset(buf_nh_type, 0, PREFIX_STRLEN); ret = str2prefix(dest_str, &p); if (ret <= 0) { @@ -322,7 +118,6 @@ static int static_route_leak( __func__, src_str); return CMD_WARNING_CONFIG_FAILED; } - src_p = (struct prefix_ipv6 *)&src; } break; default: @@ -332,29 +127,29 @@ static int static_route_leak( /* Apply mask for given prefix. */ apply_mask(&p); - if (svrf->vrf->vrf_id == VRF_UNKNOWN - || nh_svrf->vrf->vrf_id == VRF_UNKNOWN) { - vrf_set_user_cfged(svrf->vrf); - return zebra_static_route_holdem( - svrf, nh_svrf, afi, safi, negate, &p, dest_str, - mask_str, src_str, gate_str, ifname, flag_str, tag_str, - distance_str, label_str, table_str, onlink); - } + prefix2str(&p, buf_prefix, sizeof(buf_prefix)); - if (table_str) { - /* table configured. check consistent with vrf config - */ - if (svrf->vrf->data.l.table_id != RT_TABLE_MAIN) { - if (vty) - vty_out(vty, - "%% Table %s overlaps vrf table %u\n", - table_str, svrf->vrf->data.l.table_id); - else - zlog_warn("%s: Table %s overlaps vrf table %u", - __func__, table_str, - svrf->vrf->data.l.table_id); - return CMD_WARNING_CONFIG_FAILED; - } + if (src_str) + prefix2str(&src, buf_src_prefix, sizeof(buf_src_prefix)); + if (gate_str) + buf_gate_str = gate_str; + else + buf_gate_str = ""; + + if (gate_str == NULL && ifname == NULL) + type = STATIC_BLACKHOLE; + else if (gate_str && ifname) { + if (afi == AFI_IP) + type = STATIC_IPV4_GATEWAY_IFNAME; + else + type = STATIC_IPV6_GATEWAY_IFNAME; + } else if (ifname) + type = STATIC_IFNAME; + else { + if (afi == AFI_IP) + type = STATIC_IPV4_GATEWAY; + else + type = STATIC_IPV6_GATEWAY; } /* Administrative distance. */ @@ -367,169 +162,160 @@ static int static_route_leak( if (tag_str) tag = strtoul(tag_str, NULL, 10); - /* Labels */ - memset(&snh_label, 0, sizeof(struct static_nh_label)); - if (label_str) { - if (!mpls_enabled) { - if (vty) - vty_out(vty, - "%% MPLS not turned on in kernel, ignoring command\n"); - else - zlog_warn( - "%s: MPLS not turned on in kernel ignoring static route to %s", - __func__, dest_str); - return CMD_WARNING_CONFIG_FAILED; - } - int rc = mpls_str2label(label_str, &snh_label.num_labels, - snh_label.label); - if (rc < 0) { - switch (rc) { - case -1: - if (vty) - vty_out(vty, "%% Malformed label(s)\n"); - else - zlog_warn( - "%s: Malformed labels specified for route %s", - __func__, dest_str); - break; - case -2: - if (vty) - vty_out(vty, - "%% Cannot use reserved label(s) (%d-%d)\n", - MPLS_LABEL_RESERVED_MIN, - MPLS_LABEL_RESERVED_MAX); - else - zlog_warn( - "%s: Cannot use reserved labels (%d-%d) for %s", - __func__, - MPLS_LABEL_RESERVED_MIN, - MPLS_LABEL_RESERVED_MAX, - dest_str); - break; - case -3: - if (vty) - vty_out(vty, - "%% Too many labels. Enter %d or fewer\n", - MPLS_MAX_LABELS); - else - zlog_warn( - "%s: Too many labels, Enter %d or fewer for %s", - __func__, MPLS_MAX_LABELS, - dest_str); - break; - } - return CMD_WARNING_CONFIG_FAILED; - } - } - /* TableID */ if (table_str) table_id = atol(table_str); - /* Null0 static route. */ - if (ifname != NULL) { - if (strcasecmp(ifname, "Null0") == 0 - || strcasecmp(ifname, "reject") == 0 - || strcasecmp(ifname, "blackhole") == 0) { - if (vty) - vty_out(vty, - "%% Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)\n"); - else - zlog_warn( - "%s: %s: Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)", - __func__, dest_str); - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Route flags */ - if (flag_str) { - switch (flag_str[0]) { - case 'r': - bh_type = STATIC_BLACKHOLE_REJECT; - break; - case 'b': - bh_type = STATIC_BLACKHOLE_DROP; - break; - case 'N': - bh_type = STATIC_BLACKHOLE_NULL; - break; - default: - if (vty) - vty_out(vty, "%% Malformed flag %s \n", - flag_str); - else - zlog_warn("%s: Malformed flag %s for %s", - __func__, flag_str, dest_str); - return CMD_WARNING_CONFIG_FAILED; + static_get_nh_type(type, buf_nh_type, PREFIX_STRLEN); + if (!negate) { + /* route + path procesing */ + if (src_str) + snprintf(xpath_prefix, sizeof(xpath_prefix), + FRR_S_ROUTE_SRC_INFO_KEY_XPATH, + "frr-staticd:staticd", "staticd", svrf, + buf_prefix, + yang_afi_safi_value2identity(afi, safi), + buf_src_prefix, distance); + else + snprintf(xpath_prefix, sizeof(xpath_prefix), + FRR_STATIC_ROUTE_INFO_KEY_XPATH, + "frr-staticd:staticd", "staticd", svrf, + buf_prefix, + yang_afi_safi_value2identity(afi, safi), + 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); + + /* Table-Id processing */ + snprintf(buf_tableid, sizeof(buf_tableid), "%u", table_id); + strlcpy(ab_xpath, xpath_prefix, sizeof(ab_xpath)); + strlcat(ab_xpath, FRR_STATIC_ROUTE_PATH_TABLEID_XPATH, + sizeof(ab_xpath)); + nb_cli_enqueue_change(vty, ab_xpath, NB_OP_MODIFY, buf_tableid); + /* nexthop processing */ + + snprintf(ab_xpath, sizeof(ab_xpath), + FRR_STATIC_ROUTE_NH_KEY_XPATH, buf_nh_type, nh_svrf, + buf_gate_str, ifname); + 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 (flag_str) { + switch (flag_str[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 (gate_str) { - if (inet_pton(afi2family(afi), gate_str, &gate) != 1) { - if (vty) - vty_out(vty, - "%% Malformed nexthop address %s\n", - gate_str); + 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 (onlink) + nb_cli_enqueue_change(vty, ab_xpath, + NB_OP_MODIFY, "true"); else - zlog_warn( - "%s: Malformed nexthop address %s for %s", - __func__, gate_str, dest_str); - return CMD_WARNING_CONFIG_FAILED; + nb_cli_enqueue_change(vty, ab_xpath, + NB_OP_MODIFY, "false"); } - gatep = &gate; - - if (afi == AFI_IP && !negate) { - if (if_lookup_exact_address(&gatep->ipv4, AF_INET, - svrf->vrf->vrf_id)) - if (vty) - vty_out(vty, - "%% Warning!! Local connected address is configured as Gateway IP(%s)\n", - gate_str); - } else if (afi == AFI_IP6 && !negate) { - if (if_lookup_exact_address(&gatep->ipv6, AF_INET6, - svrf->vrf->vrf_id)) - if (vty) - vty_out(vty, - "%% Warning!! Local connected address is configured as Gateway IPv6(%s)\n", - gate_str); + if (label_str) { + /* 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); + + ostr = XSTRDUP(MTYPE_TMP, label_str); + 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++; + } + XFREE(MTYPE_TMP, ostr); + } 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 (gate_str == NULL && ifname == NULL) - type = STATIC_BLACKHOLE; - else if (gate_str && ifname) { - if (afi == AFI_IP) - type = STATIC_IPV4_GATEWAY_IFNAME; - else - type = STATIC_IPV6_GATEWAY_IFNAME; - } else if (ifname) - type = STATIC_IFNAME; - else { - if (afi == AFI_IP) - type = STATIC_IPV4_GATEWAY; - else - type = STATIC_IPV6_GATEWAY; - } - - if (!negate) { - static_add_route(afi, safi, type, &p, src_p, gatep, ifname, - bh_type, tag, distance, svrf, nh_svrf, - &snh_label, table_id, onlink); - /* Mark as having FRR configuration */ - vrf_set_user_cfged(svrf->vrf); + ret = nb_cli_apply_changes(vty, xpath_prefix); } else { - static_delete_route(afi, safi, type, &p, src_p, gatep, ifname, - tag, distance, svrf, &snh_label, table_id); - /* If no other FRR config for this VRF, mark accordingly. */ - if (!static_vrf_has_config(svrf)) - vrf_reset_user_cfged(svrf->vrf); + if (src_str) + snprintf(ab_xpath, sizeof(ab_xpath), + FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH, + "frr-staticd:staticd", "staticd", svrf, + buf_prefix, + yang_afi_safi_value2identity(afi, safi), + buf_src_prefix, distance, buf_nh_type, nh_svrf, + buf_gate_str, ifname); + else + snprintf(ab_xpath, sizeof(ab_xpath), + FRR_DEL_S_ROUTE_NH_KEY_XPATH, + "frr-staticd:staticd", "staticd", svrf, + buf_prefix, + yang_afi_safi_value2identity(afi, safi), + distance, buf_nh_type, nh_svrf, buf_gate_str, + ifname); + + dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath); + if (!dnode) + return ret; + + 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, ab_xpath); } - return CMD_SUCCESS; + return ret; } - static int static_route(struct vty *vty, afi_t afi, safi_t safi, const char *negate, const char *dest_str, const char *mask_str, const char *src_str, @@ -538,77 +324,28 @@ static int static_route(struct vty *vty, afi_t afi, safi_t safi, const char *distance_str, const char *vrf_name, const char *label_str, const char *table_str) { - struct static_vrf *svrf; - - /* VRF id */ - svrf = static_vrf_lookup_by_name(vrf_name); - - /* When trying to delete, the VRF must exist. */ - if (negate && !svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf_name); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; - /* When trying to create, create the VRF if it doesn't exist. - * Note: The VRF isn't active until we hear about it from the kernel. - */ - if (!svrf) { - svrf = static_vty_get_unknown_vrf(vty, vrf_name); - if (!svrf) - return CMD_WARNING_CONFIG_FAILED; - } - return static_route_leak(vty, svrf, svrf, afi, safi, negate, dest_str, - mask_str, src_str, gate_str, ifname, flag_str, - tag_str, distance_str, label_str, table_str, - false); -} - -void static_config_install_delayed_routes(struct static_vrf *svrf) -{ - struct listnode *node, *nnode; - struct static_hold_route *shr; - struct static_vrf *osvrf, *nh_svrf; - int installed; - - for (ALL_LIST_ELEMENTS(static_list, node, nnode, shr)) { - osvrf = static_vrf_lookup_by_name(shr->vrf_name); - nh_svrf = static_vrf_lookup_by_name(shr->nhvrf_name); - - if (osvrf != svrf && nh_svrf != svrf) - continue; - - if (osvrf->vrf->vrf_id == VRF_UNKNOWN - || nh_svrf->vrf->vrf_id == VRF_UNKNOWN) - continue; - - installed = static_route_leak( - NULL, osvrf, nh_svrf, shr->afi, shr->safi, NULL, - shr->dest_str, shr->mask_str, shr->src_str, - shr->gate_str, shr->ifname, shr->flag_str, shr->tag_str, - shr->distance_str, shr->label_str, shr->table_str, - shr->onlink); - - if (installed != CMD_SUCCESS) - zlog_debug( - "%s: Attempt to install %s as a route and it was rejected", - __func__, shr->dest_str); - listnode_delete(static_list, shr); - static_list_delete(shr); - } + return static_route_leak(vty, vrf_name, vrf_name, afi, safi, negate, + dest_str, mask_str, src_str, gate_str, ifname, + flag_str, tag_str, distance_str, label_str, + table_str, false); } /* Write static route configuration. */ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, safi_t safi, const char *cmd) { - struct static_hold_route *shr; - struct listnode *node; char spacing[100]; struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; + struct static_path *pn; struct route_table *stable; + struct static_route_info *si; char buf[SRCDEST2STR_BUFFER]; int write = 0; + struct stable_info *info; stable = svrf->stable[afi][safi]; if (stable == NULL) @@ -617,125 +354,104 @@ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, snprintf(spacing, sizeof(spacing), "%s%s", (svrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ", cmd); - /* - * Static routes for vrfs not fully inited - */ - for (ALL_LIST_ELEMENTS_RO(static_list, node, shr)) { - if (shr->afi != afi || shr->safi != safi) + for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) { + si = static_route_info_from_rnode(rn); + if (!si) continue; - - if (strcmp(svrf->vrf->name, shr->vrf_name) != 0) - continue; - - char dest_str[PREFIX_STRLEN]; - - prefix2str(&shr->dest, dest_str, sizeof(dest_str)); - - vty_out(vty, "%s ", spacing); - if (shr->dest_str) - vty_out(vty, "%s ", dest_str); - if (shr->src_str) - vty_out(vty, "from %s ", shr->src_str); - if (shr->gate_str) - vty_out(vty, "%s ", shr->gate_str); - if (shr->ifname) - vty_out(vty, "%s ", shr->ifname); - if (shr->flag_str) - vty_out(vty, "%s ", shr->flag_str); - if (shr->tag_str) - vty_out(vty, "tag %s ", shr->tag_str); - if (shr->distance_str) - vty_out(vty, "%s ", shr->distance_str); - if (shr->label_str) - vty_out(vty, "label %s ", shr->label_str); - if (shr->table_str) - vty_out(vty, "table %s", shr->table_str); - if (strcmp(shr->vrf_name, shr->nhvrf_name) != 0) - vty_out(vty, "nexthop-vrf %s ", shr->nhvrf_name); - if (shr->onlink) - vty_out(vty, "onlink"); - vty_out(vty, "\n"); - } - - for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) - for (si = rn->info; si; si = si->next) { - vty_out(vty, "%s %s", spacing, - srcdest_rnode2str(rn, buf, sizeof(buf))); - - switch (si->type) { - case STATIC_IPV4_GATEWAY: - vty_out(vty, " %s", inet_ntoa(si->addr.ipv4)); - break; - case STATIC_IPV6_GATEWAY: - vty_out(vty, " %s", - inet_ntop(AF_INET6, &si->addr.ipv6, buf, - sizeof(buf))); - break; - case STATIC_IFNAME: - vty_out(vty, " %s", si->ifname); - break; - case STATIC_BLACKHOLE: - switch (si->bh_type) { - case STATIC_BLACKHOLE_DROP: - vty_out(vty, " blackhole"); + info = static_get_stable_info(rn); + frr_each(static_path_list, &si->path_list, pn) { + frr_each(static_nexthop_list, &pn->nexthop_list, nh) { + vty_out(vty, "%s %s", spacing, + srcdest_rnode2str(rn, buf, + sizeof(buf))); + + switch (nh->type) { + case STATIC_IPV4_GATEWAY: + vty_out(vty, " %s", + inet_ntoa(nh->addr.ipv4)); break; - case STATIC_BLACKHOLE_NULL: - vty_out(vty, " Null0"); + case STATIC_IPV6_GATEWAY: + vty_out(vty, " %s", + inet_ntop(AF_INET6, + &nh->addr.ipv6, buf, + sizeof(buf))); break; - case STATIC_BLACKHOLE_REJECT: - vty_out(vty, " reject"); + case STATIC_IFNAME: + vty_out(vty, " %s", nh->ifname); + break; + case STATIC_BLACKHOLE: + switch (nh->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; + case STATIC_IPV4_GATEWAY_IFNAME: + vty_out(vty, " %s %s", + inet_ntop(AF_INET, + &nh->addr.ipv4, buf, + sizeof(buf)), + nh->ifname); + break; + case STATIC_IPV6_GATEWAY_IFNAME: + vty_out(vty, " %s %s", + inet_ntop(AF_INET6, + &nh->addr.ipv6, buf, + sizeof(buf)), + nh->ifname); break; } - break; - case STATIC_IPV4_GATEWAY_IFNAME: - vty_out(vty, " %s %s", - inet_ntop(AF_INET, &si->addr.ipv4, buf, - sizeof(buf)), - si->ifname); - break; - case STATIC_IPV6_GATEWAY_IFNAME: - vty_out(vty, " %s %s", - inet_ntop(AF_INET6, &si->addr.ipv6, buf, - sizeof(buf)), - si->ifname); - break; - } - if (si->tag) - vty_out(vty, " tag %" ROUTE_TAG_PRI, si->tag); - - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out(vty, " %d", si->distance); - - /* Label information */ - if (si->snh_label.num_labels) - vty_out(vty, " label %s", - mpls_label2str(si->snh_label.num_labels, - si->snh_label.label, buf, - sizeof(buf), 0)); - - if (si->nh_vrf_id != si->vrf_id) - vty_out(vty, " nexthop-vrf %s", si->nh_vrfname); - - /* - * table ID from VRF overrides configured - */ - if (si->table_id && - svrf->vrf->data.l.table_id == RT_TABLE_MAIN) - vty_out(vty, " table %u", si->table_id); - - if (si->onlink) - vty_out(vty, " onlink"); - - vty_out(vty, "\n"); - - write = 1; + if (pn->tag) + vty_out(vty, " tag %" ROUTE_TAG_PRI, + pn->tag); + + if (pn->distance + != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out(vty, " %u", pn->distance); + + /* Label information */ + if (nh->snh_label.num_labels) + vty_out(vty, " label %s", + mpls_label2str( + nh->snh_label + .num_labels, + nh->snh_label.label, + buf, sizeof(buf), 0)); + + if (nh->nh_vrf_id != GET_STABLE_VRF_ID(info)) + vty_out(vty, " nexthop-vrf %s", + nh->nh_vrfname); + + /* + * table ID from VRF overrides + * configured + */ + if (pn->table_id + && svrf->vrf->data.l.table_id + == RT_TABLE_MAIN) + vty_out(vty, " table %u", pn->table_id); + + if (nh->onlink) + vty_out(vty, " onlink"); + + vty_out(vty, "\n"); + + write = 1; + } } + } return write; } /* Static unicast routes for multicast RPF lookup. */ -DEFPY (ip_mroute_dist, +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]", NO_STR @@ -752,7 +468,7 @@ DEFPY (ip_mroute_dist, } /* Static route configuration. */ -DEFPY(ip_route_blackhole, +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> \ @@ -790,7 +506,7 @@ DEFPY(ip_route_blackhole, distance_str, vrf, label, table_str); } -DEFPY(ip_route_blackhole_vrf, +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> \ @@ -815,28 +531,29 @@ DEFPY(ip_route_blackhole_vrf, "Table to configure\n" "The table number to configure\n") { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } - + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); /* * Coverity is complaining that prefix could * be dereferenced, but we know that prefix will * valid. Add an assert to make it happy */ assert(prefix); - return static_route_leak(vty, svrf, svrf, AFI_IP, SAFI_UNICAST, no, - prefix, mask_str, NULL, NULL, NULL, flag, + return static_route_leak(vty, vrfname, vrfname, AFI_IP, SAFI_UNICAST, + no, prefix, mask_str, NULL, NULL, NULL, flag, tag_str, distance_str, label, table_str, false); } -DEFPY(ip_route_address_interface, +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> \ @@ -869,44 +586,28 @@ DEFPY(ip_route_address_interface, VRF_CMD_HELP_STR "Treat the nexthop as directly attached to the interface\n") { - struct static_vrf *svrf; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - - svrf = static_vty_get_unknown_vrf(vty, vrf); - if (!svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf); - return CMD_WARNING_CONFIG_FAILED; - } - - if (table_str && vrf && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf) + vrf = VRF_DEFAULT_NAME; if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; + nh_vrf = vrf; - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } - - return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, + return static_route_leak(vty, vrf, nh_vrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, NULL, gate_str, ifname, flag, tag_str, distance_str, label, table_str, !!onlink); } -DEFPY(ip_route_address_interface_vrf, +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> \ @@ -937,39 +638,35 @@ DEFPY(ip_route_address_interface_vrf, VRF_CMD_HELP_STR "Treat the nexthop as directly attached to the interface\n") { - VTY_DECLVAR_CONTEXT(vrf, vrf); + const char *nh_vrf; const char *flag = NULL; - struct static_vrf *svrf = vrf->info; - struct static_vrf *nh_svrf; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrfname; - return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, + return static_route_leak(vty, vrfname, nh_vrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, NULL, gate_str, ifname, flag, tag_str, distance_str, label, table_str, !!onlink); } -DEFPY(ip_route, +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> \ @@ -999,44 +696,29 @@ DEFPY(ip_route, "The table number to configure\n" VRF_CMD_HELP_STR) { - struct static_vrf *svrf; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - svrf = static_vty_get_unknown_vrf(vty, vrf); - if (!svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf) + vrf = VRF_DEFAULT_NAME; if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; + nh_vrf = vrf; - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, - NULL, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, false); + return static_route_leak(vty, vrf, nh_vrf, AFI_IP, SAFI_UNICAST, no, + prefix, mask_str, NULL, gate_str, ifname, flag, + tag_str, distance_str, label, table_str, + false); } -DEFPY(ip_route_vrf, +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> \ @@ -1064,39 +746,36 @@ DEFPY(ip_route_vrf, "The table number to configure\n" VRF_CMD_HELP_STR) { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrfname; - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, - NULL, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, false); + return static_route_leak(vty, vrfname, nh_vrf, AFI_IP, SAFI_UNICAST, no, + prefix, mask_str, NULL, gate_str, ifname, flag, + tag_str, distance_str, label, table_str, + false); } -DEFPY(ipv6_route_blackhole, +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 \ @@ -1134,7 +813,7 @@ DEFPY(ipv6_route_blackhole, distance_str, vrf, label, table_str); } -DEFPY(ipv6_route_blackhole_vrf, +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 \ @@ -1159,14 +838,16 @@ DEFPY(ipv6_route_blackhole_vrf, "Table to configure\n" "The table number to configure\n") { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); /* * Coverity is complaining that prefix could @@ -1174,13 +855,14 @@ DEFPY(ipv6_route_blackhole_vrf, * valid. Add an assert to make it happy */ assert(prefix); - return static_route_leak( - vty, svrf, svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, NULL, NULL, flag, tag_str, distance_str, label, - table_str, false); + + return static_route_leak(vty, vrfname, vrfname, AFI_IP6, SAFI_UNICAST, + no, prefix_str, NULL, from_str, NULL, NULL, + flag, tag_str, distance_str, label, table_str, + false); } -DEFPY(ipv6_route_address_interface, +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 \ @@ -1213,44 +895,29 @@ DEFPY(ipv6_route_address_interface, VRF_CMD_HELP_STR "Treat the nexthop as directly attached to the interface\n") { - struct static_vrf *svrf; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); - return CMD_WARNING_CONFIG_FAILED; + if (ifname && !strncasecmp(ifname, "Null0", 5)) { + flag = "Null0"; + ifname = NULL; } - svrf = static_vty_get_unknown_vrf(vty, vrf); - if (!svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf) + vrf = VRF_DEFAULT_NAME; if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrf; - if (ifname && !strncasecmp(ifname, "Null0", 5)) { - flag = "Null0"; - ifname = NULL; - } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, !!onlink); + return static_route_leak(vty, vrf, nh_vrf, AFI_IP6, SAFI_UNICAST, no, + prefix_str, NULL, from_str, gate_str, ifname, + flag, tag_str, distance_str, label, table_str, + !!onlink); } -DEFPY(ipv6_route_address_interface_vrf, +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 \ @@ -1281,39 +948,35 @@ DEFPY(ipv6_route_address_interface_vrf, VRF_CMD_HELP_STR "Treat the nexthop as directly attached to the interface\n") { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrfname; if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, !!onlink); + return static_route_leak(vty, vrfname, nh_vrf, AFI_IP6, SAFI_UNICAST, + no, prefix_str, NULL, from_str, gate_str, + ifname, flag, tag_str, distance_str, label, + table_str, !!onlink); } -DEFPY(ipv6_route, +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> \ @@ -1343,44 +1006,28 @@ DEFPY(ipv6_route, "The table number to configure\n" VRF_CMD_HELP_STR) { - struct static_vrf *svrf; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - svrf = static_vty_get_unknown_vrf(vty, vrf); - if (!svrf) { - vty_out(vty, "%% vrf %s is not defined\n", vrf); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vrf) + vrf = VRF_DEFAULT_NAME; if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrf; if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, false); + return static_route_leak(vty, vrf, nh_vrf, AFI_IP6, SAFI_UNICAST, no, + prefix_str, NULL, from_str, gate_str, ifname, + flag, tag_str, distance_str, label, table_str, + false); } -DEFPY(ipv6_route_vrf, +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> \ @@ -1408,38 +1055,34 @@ DEFPY(ipv6_route_vrf, "The table number to configure\n" VRF_CMD_HELP_STR) { - VTY_DECLVAR_CONTEXT(vrf, vrf); - struct static_vrf *svrf = vrf->info; - struct static_vrf *nh_svrf; + const char *nh_vrf; const char *flag = NULL; + const struct lyd_node *vrf_dnode; + const char *vrfname; - if (table_str && !vrf_is_backend_netns()) { - vty_out(vty, - "%% table param only available when running on netns-based vrfs\n"); + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, "%% Failed to get vrf dnode in candidate db\n"); return CMD_WARNING_CONFIG_FAILED; } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); if (nexthop_vrf) - nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf); + nh_vrf = nexthop_vrf; else - nh_svrf = svrf; - - if (!nh_svrf) { - vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf); - return CMD_WARNING_CONFIG_FAILED; - } + nh_vrf = vrfname; if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; } - - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, - from_str, gate_str, ifname, flag, tag_str, distance_str, label, - table_str, false); + return static_route_leak(vty, vrfname, nh_vrf, AFI_IP6, SAFI_UNICAST, + no, prefix_str, NULL, from_str, gate_str, + ifname, flag, tag_str, distance_str, label, + table_str, false); } -DEFPY(debug_staticd, +DEFPY_YANG(debug_staticd, debug_staticd_cmd, "[no] debug static [{events$events}]", NO_STR @@ -1500,8 +1143,4 @@ void static_vty_init(void) install_element(VIEW_NODE, &show_debugging_static_cmd); install_element(VIEW_NODE, &debug_staticd_cmd); install_element(CONFIG_NODE, &debug_staticd_cmd); - - static_list = list_new(); - static_list->cmp = (int (*)(void *, void *))static_list_compare; - static_list->del = (void (*)(void *))static_list_delete; } |
