From 059410d0c3f2ca3455d2672ef678f9b1fdeb2011 Mon Sep 17 00:00:00 2001 From: vdhingra Date: Thu, 5 Mar 2020 04:43:01 -0800 Subject: [PATCH] staticd : northbound backend code basic routing northbound callbacks vrf northbound callbacks staticd northbound callbacks tag, distance, tableid is the property of route Signed-off-by: VishalDhingra --- lib/routing_nb.c | 65 +++++ lib/routing_nb.h | 17 ++ lib/subdir.am | 3 + lib/vrf.c | 202 +++++++++++-- lib/vrf.h | 8 + lib/yang.c | 21 ++ lib/yang.h | 5 +- staticd/static_main.c | 6 + staticd/static_memory.c | 2 + staticd/static_memory.h | 1 + staticd/static_nb.c | 561 +++++++++++++++++++++++++++++++++++ staticd/static_nb.h | 54 ++++ staticd/static_nht.c | 45 +-- staticd/static_routes.c | 586 +++++++++++++++++++++++++------------ staticd/static_routes.h | 97 ++++-- staticd/static_vrf.c | 20 +- staticd/static_vrf.h | 8 + staticd/static_vty.c | 632 +++++++++------------------------------- staticd/static_vty.h | 2 - staticd/static_zebra.c | 28 +- staticd/static_zebra.h | 3 +- staticd/subdir.am | 3 + yang/frr-nexthop.yang | 2 +- yang/frr-staticd.yang | 28 +- yang/frr-vrf.yang | 1 - 25 files changed, 1636 insertions(+), 764 deletions(-) create mode 100644 lib/routing_nb.c create mode 100644 lib/routing_nb.h create mode 100644 staticd/static_nb.c create mode 100644 staticd/static_nb.h diff --git a/lib/routing_nb.c b/lib/routing_nb.c new file mode 100644 index 000000000000..b48cfdf629e8 --- /dev/null +++ b/lib/routing_nb.c @@ -0,0 +1,65 @@ +#include "northbound.h" +#include "libfrr.h" +#include "vrf.h" +#include "routing_nb.h" + + +static int lib_routing_cp_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct vrf *vrf; + const char *vrfname; + + switch (event) { + case NB_EV_VALIDATE: + vrfname = yang_dnode_get_string(dnode, "./vrf"); + vrf = vrf_lookup_by_name(vrfname); + if (!vrf) { + zlog_warn( + "vrf is not configured\n"); + return NB_ERR_VALIDATION; + } + + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrfname = yang_dnode_get_string(dnode, "./vrf"); + vrf = vrf_lookup_by_name(vrfname); + nb_running_set_entry(dnode, vrf); + break; + }; + + return NB_OK; +} + +static int lib_routing_cp_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct vrf *vrf; + + if (event != NB_EV_APPLY) + return NB_OK; + + vrf = nb_running_unset_entry(dnode); + (void)vrf; + return NB_OK; +} + +const struct frr_yang_module_info frr_routing_info = { + .name = "frr-routing", + .nodes = { + { + .xpath = FRR_ROUTING_XPATH, + .cbs = { + .create = lib_routing_cp_create, + .destroy = lib_routing_cp_destroy, + }, + }, + { + .xpath = NULL, + }, + } +}; diff --git a/lib/routing_nb.h b/lib/routing_nb.h new file mode 100644 index 000000000000..d9f704ee092d --- /dev/null +++ b/lib/routing_nb.h @@ -0,0 +1,17 @@ +#ifndef _FRR_ROUTING_NB_H_ +#define _FRR_ROUTING_NB_H_ + + +#define FRR_ROUTING_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol" + +#define FRR_ROUTING_KEY_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol[type='%s'][name='%s'][vrf='%s']" + +extern const struct frr_yang_module_info frr_routing_info; + +/* Mandatory callbacks. */ + + + +#endif /* _FRR_ROUTING_NB_H_ */ diff --git a/lib/subdir.am b/lib/subdir.am index 56d11c5852d1..7dd43edb7dc3 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -103,6 +103,7 @@ lib_libfrr_la_SOURCES = \ lib/printf/printf-pos.c \ lib/printf/vfprintf.c \ lib/printf/glue.c \ + lib/routing_nb.c \ # end nodist_lib_libfrr_la_SOURCES = \ @@ -112,6 +113,7 @@ nodist_lib_libfrr_la_SOURCES = \ yang/frr-route-types.yang.c \ yang/frr-vrf.yang.c \ yang/frr-routing.yang.c \ + yang/frr-nexthop.yang.c \ yang/ietf/ietf-routing-types.yang.c \ yang/frr-module-translator.yang.c \ # end @@ -257,6 +259,7 @@ pkginclude_HEADERS += \ lib/zclient.h \ lib/zebra.h \ lib/pbr.h \ + lib/routing_nb.h \ # end diff --git a/lib/vrf.c b/lib/vrf.c index c3a94224eef8..1634442e07fc 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -36,6 +36,7 @@ #include "privs.h" #include "nexthop_group.h" #include "lib_errors.h" +#include "northbound_cli.h" /* default VRF ID value used when VRF backend is not NETNS */ #define VRF_DEFAULT_INTERNAL 0 @@ -714,10 +715,32 @@ DEFUN_NOSH (vrf, "Select a VRF to configure\n" "VRF's name\n") { + char xpath_list[XPATH_MAXLEN]; int idx_name = 1; + int ret; const char *vrfname = argv[idx_name]->arg; + struct vrf *vrfp; + + snprintf(xpath_list, sizeof(xpath_list), + "/frr-vrf:lib/vrf[name='%s']", + vrfname); + + nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL); + ret = nb_cli_apply_changes(vty, xpath_list); + + if (ret == CMD_SUCCESS) { + /* + * For backward compatibility with old commands we still need + * to use the qobj infrastructure. This can be removed once + * all vrf-level commands are converted to the new + * northbound model. + */ + vrfp = vrf_lookup_by_name(vrfname); + if (vrfp) + VTY_PUSH_CONTEXT(VRF_NODE, vrfp); + } - return vrf_handler_create(vty, vrfname, NULL); + return ret; } DEFUN (no_vrf, @@ -727,27 +750,18 @@ DEFUN (no_vrf, "Delete a pseudo VRF's configuration\n" "VRF's name\n") { + char xpath_list[XPATH_MAXLEN]; const char *vrfname = argv[2]->arg; + int ret; - struct vrf *vrfp; - - vrfp = vrf_lookup_by_name(vrfname); + snprintf(xpath_list, sizeof(xpath_list), + "/frr-vrf:lib/vrf[name='%s']", + vrfname); - if (vrfp == NULL) { - vty_out(vty, "%% VRF %s does not exist\n", vrfname); - return CMD_WARNING_CONFIG_FAILED; - } + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + ret = nb_cli_apply_changes(vty, xpath_list); - if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) { - vty_out(vty, "%% Only inactive VRFs can be deleted\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Clear configured flag and invoke delete. */ - UNSET_FLAG(vrfp->status, VRF_CONFIGURED); - vrf_delete(vrfp); - - return CMD_SUCCESS; + return ret; } @@ -1012,3 +1026,155 @@ vrf_id_t vrf_generate_id(void) return ++vrf_id_local; } + + +/* ------- Northbound callbacks ------- */ + +/* + * XPath: /frr-vrf:lib/vrf + */ +static int lib_vrf_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + const char *vrfname; + struct vrf *vrfp; + + if (event != NB_EV_APPLY) + return NB_OK; + + vrfname = yang_dnode_get_string(dnode, "./name"); + + vrfp = vrf_get(VRF_UNKNOWN, vrfname); + + nb_running_set_entry(dnode, vrfp); + + return NB_OK; +} + +static int lib_vrf_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct vrf *vrfp; + + + switch (event) { + case NB_EV_VALIDATE: + vrfp = nb_running_get_entry(dnode, NULL, true); + if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) { + zlog_warn( + "Only inactive VRFs can be deleted\n"); + return NB_ERR_VALIDATION; + } + + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrfp = nb_running_unset_entry(dnode); + + /* Clear configured flag and invoke delete. */ + UNSET_FLAG(vrfp->status, VRF_CONFIGURED); + vrf_delete(vrfp); + + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-vrf:lib/vrf + */ +static const void *lib_vrf_get_next(const void *parent_list_entry, + const void *list_entry) +{ + return NULL; +} + +static int lib_vrf_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + return NB_OK; +} + +static const void *lib_vrf_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys) +{ + + return NULL; +} + + +/* + * XPath: /frr-vrf:lib/vrf/id + */ +struct yang_data * lib_vrf_id_get_elem(const char *xpath, + const void *list_entry) +{ + return NULL; +} + +/* + * XPath: /frr-vrf:lib/vrf/active + */ +struct yang_data * lib_vrf_active_get_elem(const char *xpath, + const void *list_entry) +{ + return NULL; +} + +/* + * XPath: /frr-vrf:lib/vrf/netns/name + */ +static int lib_vrf_netns_name_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return NB_OK; +} + +static int lib_vrf_netns_name_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return NB_OK; +} + +const struct frr_yang_module_info frr_vrf_info = { + .name = "frr-vrf", + .nodes = { + { + .xpath = "/frr-vrf:lib/vrf", + .cbs = { + .create = lib_vrf_create, + .destroy = lib_vrf_destroy, + .get_next = lib_vrf_get_next, + .get_keys = lib_vrf_get_keys, + .lookup_entry = lib_vrf_lookup_entry, + }, + }, + { + .xpath = "/frr-vrf:lib/vrf/id", + .cbs = { + .get_elem = lib_vrf_id_get_elem, + }, + }, + { + .xpath = "/frr-vrf:lib/vrf/active", + .cbs = { + .get_elem = lib_vrf_active_get_elem, + }, + }, + { + .xpath = "/frr-vrf:lib/vrf/netns/name", + .cbs = { + .modify = lib_vrf_netns_name_modify, + .destroy = lib_vrf_netns_name_destroy, + }, + }, + { + .xpath = NULL, + }, + } +}; diff --git a/lib/vrf.h b/lib/vrf.h index f231d2433fbc..15703b854a51 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -321,6 +321,14 @@ extern void vrf_disable(struct vrf *vrf); extern int vrf_enable(struct vrf *vrf); extern void vrf_delete(struct vrf *vrf); extern vrf_id_t vrf_generate_id(void); +extern const struct frr_yang_module_info frr_vrf_info; + +/* ------- Northbound callbacks ------- */ + +struct yang_data * lib_vrf_id_get_elem(const char *xpath, + const void *list_entry); +struct yang_data * lib_vrf_active_get_elem(const char *xpath, + const void *list_entry); #ifdef __cplusplus } diff --git a/lib/yang.c b/lib/yang.c index 93e6db305530..e2f7d45b626f 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -688,3 +688,24 @@ void yang_terminate(void) ly_ctx_destroy(ly_native_ctx, NULL); } + +const struct lyd_node *yang_dnode_get_pleaf(const struct lyd_node *dnode, + const char *lname) +{ + const struct lyd_node *orig_dnode = dnode; + + while (orig_dnode) { + switch (orig_dnode->schema->nodetype) { + case LYS_LIST: + if(!strcmp(orig_dnode->schema->name, lname)) + return orig_dnode; + break; + default: + break; + } + + orig_dnode = orig_dnode->parent; + } + + return NULL; +} diff --git a/lib/yang.h b/lib/yang.h index 6892e3601973..430e6229c07e 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -34,7 +34,7 @@ extern "C" { #endif /* Maximum XPath length. */ -#define XPATH_MAXLEN 256 +#define XPATH_MAXLEN 1024 /* Maximum list key length. */ #define LIST_MAXKEYS 8 @@ -505,6 +505,9 @@ extern void yang_init(void); */ extern void yang_terminate(void); +extern const struct lyd_node *yang_dnode_get_pleaf(const struct lyd_node *dnode, + const char *lname); + #ifdef __cplusplus } #endif diff --git a/staticd/static_main.c b/staticd/static_main.c index 43cb7db51dfd..f2d34d1ce41e 100644 --- a/staticd/static_main.c +++ b/staticd/static_main.c @@ -31,12 +31,14 @@ #include "vrf.h" #include "nexthop.h" #include "filter.h" +#include "routing_nb.h" #include "static_vrf.h" #include "static_vty.h" #include "static_routes.h" #include "static_zebra.h" #include "static_debug.h" +#include "static_nb.h" char backup_config_file[256]; @@ -102,6 +104,10 @@ struct quagga_signal_t static_signals[] = { }; static const struct frr_yang_module_info *const staticd_yang_modules[] = { + &frr_interface_info, + &frr_vrf_info, + &frr_routing_info, + &frr_staticd_info, }; #define STATIC_VTY_PORT 2616 diff --git a/staticd/static_memory.c b/staticd/static_memory.c index 77ca4a34396d..e17b5bca1891 100644 --- a/staticd/static_memory.c +++ b/staticd/static_memory.c @@ -26,3 +26,5 @@ DEFINE_MGROUP(STATIC, "staticd") DEFINE_MTYPE(STATIC, STATIC_ROUTE, "Static Route"); + +DEFINE_MTYPE(STATIC, STATIC_ROUTE_INFO, "Static Route Info"); diff --git a/staticd/static_memory.h b/staticd/static_memory.h index 77a0db3b123a..d11745ffb070 100644 --- a/staticd/static_memory.h +++ b/staticd/static_memory.h @@ -24,5 +24,6 @@ DECLARE_MGROUP(STATIC) DECLARE_MTYPE(STATIC_ROUTE); +DECLARE_MTYPE(STATIC_ROUTE_INFO); #endif diff --git a/staticd/static_nb.c b/staticd/static_nb.c new file mode 100644 index 000000000000..64f2be26097e --- /dev/null +++ b/staticd/static_nb.c @@ -0,0 +1,561 @@ +#include "northbound.h" +#include "libfrr.h" +#include "log.h" +#include "lib_errors.h" +#include "prefix.h" +#include "table.h" +#include "vrf.h" +#include "nexthop.h" + +#include "static_vrf.h" +#include "static_routes.h" +#include "static_nb.h" + +static int static_route_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct vrf *vrf; + struct static_vrf *s_vrf; + struct route_node *rn; + struct prefix prefix; + struct prefix_ipv6 src_prefix; + afi_t afi; + safi_t safi = SAFI_UNICAST; + int ret; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(dnode, NULL, true); + s_vrf = vrf->info; + yang_dnode_get_prefix(&prefix, dnode, "./destination-prefix"); + yang_dnode_get_ipv6p(&src_prefix, dnode, "./src-prefix"); + afi = family2afi(prefix.family); + rn = static_add_route(afi, safi, &prefix, + &src_prefix, s_vrf); + if(!rn) { + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "rn creation failed"); + return NB_ERR; + } + nb_running_set_entry(dnode, rn); + break; + }; + return NB_OK; +} + +static int static_route_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct route_node *rn; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn = nb_running_get_entry(dnode, NULL, true); + static_del_route(rn); + nb_running_unset_entry(dnode); + break; + }; + return NB_OK; +} + +static int static_route_distance_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct route_node *rn; + struct static_route_info *ri; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn = nb_running_get_entry(dnode, NULL, true); + ri = rn->info; + ri->distance = yang_dnode_get_uint8(dnode, NULL); + static_install_route(rn); + break; + } + + return NB_OK; +} + + +static int static_route_distance_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct route_node *rn; + struct static_route_info *ri; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn = nb_running_get_entry(dnode, NULL, true); + ri = rn->info; + ri->distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + static_install_route(rn); + break; + } + return NB_OK; +} + + +static int static_route_tag_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct route_node *rn; + struct static_route_info *ri; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn = nb_running_get_entry(dnode, NULL, true); + ri = rn->info; + ri->tag = yang_dnode_get_uint32(dnode, NULL); + static_install_route(rn); + break; + } + return NB_OK; +} + +static int static_route_tag_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct route_node *rn; + struct static_route_info *ri; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn = nb_running_get_entry(dnode, NULL, true); + ri = rn->info; + ri->tag = 0; + static_install_route(rn); + break; + } + return NB_OK; +} + +static int static_route_table_id_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct route_node *rn; + struct static_route_info *ri; + stable_info_t *info; + struct static_vrf *svrf; + + switch (event) { + case NB_EV_VALIDATE: + if (!vrf_is_backend_netns()) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "table param only available when running on netns-based vrfs"); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + rn = nb_running_get_entry(dnode, NULL, true); + info = route_table_get_info(rn->table); + svrf = info->svrf; + if (svrf->vrf->data.l.table_id != RT_TABLE_MAIN) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Table %d overlaps vrf table %u\n", + yang_dnode_get_uint32(dnode, NULL), + svrf->vrf->data.l.table_id); + return NB_ERR_VALIDATION; + } + + rn = nb_running_get_entry(dnode, NULL, true); + ri = rn->info; + ri->table_id = yang_dnode_get_uint32(dnode, NULL); + static_install_route(rn); + break; + } + return NB_OK; +} + +static int static_route_table_id_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return NB_OK; +} + + + +static int static_route_nh_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct route_node *rn; + struct ipaddr ipaddr; + struct static_nexthop *nh; + int nh_type; + const char *ifname; + const char *nh_vrf; + + switch (event) { + case NB_EV_VALIDATE: + ifname = yang_dnode_get_string(dnode, "./interface"); + if (ifname != NULL) { + if (strcasecmp(ifname, "Null0") == 0 + || strcasecmp(ifname, "reject") == 0 + || strcasecmp(ifname, "blackhole") == 0) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)"); + return NB_ERR_VALIDATION; + } + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + yang_dnode_get_ip(&ipaddr, dnode, "./gateway"); + nh_type = yang_dnode_get_enum(dnode, "./nh-type"); + ifname = yang_dnode_get_string(dnode, "./interface"); + nh_vrf = yang_dnode_get_string(dnode, "./vrf"); + rn = nb_running_get_entry(dnode, NULL, true); + if (!static_add_nexthop_validate(rn, nh_type, &ipaddr)) + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Warning!! Local connected address is configured as Gateway IP"); + nh = static_add_nexthop(rn, nh_type, &ipaddr, + ifname, nh_vrf); + if(!nh) { + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "nh creation failed"); + return NB_ERR; + } + nb_running_set_entry(dnode, nh); + break; + }; + return NB_OK; +} + + +static int static_route_nh_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + struct static_nexthop *nh; + int ret; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + nh = nb_running_get_entry(dnode, NULL, true); + rn_dnode = yang_dnode_get_pleaf(dnode,"prefix-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + ret = static_delete_nexthop(rn, nh); + if (!ret) { + flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, + "nh destroy failed"); + return NB_ERR; + } + nb_running_unset_entry(dnode); + break; + }; + return NB_OK; +} + + +static int static_route_bh_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct route_node *rn; + const struct lyd_node *rn_dnode; + struct static_nexthop *nh; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + nh = nb_running_get_entry(dnode, NULL, true); + rn_dnode = yang_dnode_get_pleaf(dnode,"prefix-list"); + rn = nb_running_get_entry(rn_dnode, NULL, true); + nh->bh_type = yang_dnode_get_enum(dnode, NULL); + static_install_route(rn); + break; + }; + return NB_OK; +} + + +static int static_route_bh_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return NB_OK; +} + +static int static_route_onlink_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return NB_OK; +} + +static int static_route_onlink_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return NB_OK; +} + + +static int static_route_label_id_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct route_node *rn; + struct static_nexthop *nh; + uint8_t id; + + switch (event) { + case NB_EV_VALIDATE: + id = yang_dnode_get_uint8(dnode, "id"); + if (id > MPLS_MAX_LABELS) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Too many labels, Enter %d or fewer", + MPLS_MAX_LABELS); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + id = yang_dnode_get_uint8(dnode, "id"); + nh = nb_running_get_entry(dnode, NULL, true); + break; + } + + return NB_OK; +} + +static int static_route_label_id_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct route_node *rn; + struct static_nexthop *nh; + uint8_t id; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + id = yang_dnode_get_uint8(dnode, "id"); + nh = nb_running_get_entry(dnode, NULL, true); + break; + } + return NB_OK; +} + + +static int static_route_label_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct route_node *rn; + struct static_nexthop *nh; + const struct lyd_node *id_dnode; + uint8_t id; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + nh = nb_running_get_entry(dnode, NULL, true); + id_dnode = yang_dnode_get_pleaf(dnode,"entry"); + id = yang_dnode_get_uint8(id_dnode, "id"); + nh->snh_label.label[id] = + yang_dnode_get_uint32(dnode, NULL); + nh->snh_label.num_labels++; + break; + default: + break; + } + return NB_OK; +} + +static int static_route_label_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct route_node *rn; + struct static_nexthop *nh; + const struct lyd_node *id_dnode; + uint8_t id; + + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + nh = nb_running_get_entry(dnode, NULL, true); + id_dnode = yang_dnode_get_pleaf(dnode,"entry"); + id = yang_dnode_get_uint8(id_dnode, "id"); + nh->snh_label.num_labels--; + nh->snh_label.label[id] = 0; + break; + default: + break; + } + return NB_OK; +} + +/* These below APIs are not supported by staticd at present */ +static int static_route_label_id_ttl_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return NB_OK; +} + +static int static_route_label_id_ttl_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return NB_OK; +} + + +static int static_route_label_id_tc_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return NB_OK; +} + +static int static_route_label_id_tc_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return NB_OK; +} +const struct frr_yang_module_info frr_staticd_info = { + .name = "frr-staticd", + .nodes = { + { + .xpath = FRR_STATIC_ROUTE_XPATH, + .cbs = { + .create = static_route_create, + .destroy = static_route_destroy, + }, + }, + { + .xpath = FRR_STATIC_ROUTE_DIS_XPATH, + .cbs = { + .modify = static_route_distance_modify, + .destroy = static_route_distance_destroy, + }, + }, + { + .xpath = FRR_STATIC_ROUTE_TAG_XPATH, + .cbs = { + .modify = static_route_tag_modify, + .destroy = static_route_tag_destroy, + }, + }, + { + .xpath = FRR_STATIC_ROUTE_TB_ID_XPATH, + .cbs = { + .modify = static_route_table_id_modify, + .destroy = static_route_table_id_destroy, + }, + }, + { + .xpath = FRR_STATIC_NH_XPATH, + .cbs = { + .create = static_route_nh_create, + .destroy = static_route_nh_destroy, + + }, + }, + { + .xpath = FRR_STATIC_NH_ONLINK_XPATH, + .cbs = { + .modify = static_route_onlink_modify, + .destroy = static_route_onlink_destroy, + }, + }, + { + .xpath = FRR_STATIC_NH_BH_TYPE_XPATH, + .cbs = { + .modify = static_route_bh_modify, + .destroy = static_route_bh_destroy, + }, + }, + { + .xpath = FRR_STATIC_NH_LABEL_ID_XPATH, + .cbs = { + .create = static_route_label_id_create, + .destroy = static_route_label_id_destroy, + }, + }, + { + .xpath = FRR_STATIC_NH_LABEL_ID_LABEL_XPATH, + .cbs = { + .modify = static_route_label_modify, + .destroy = static_route_label_destroy, + }, + }, + { + .xpath = FRR_STATIC_NH_LABEL_ID_TTL_XPATH, + .cbs = { + .modify = static_route_label_id_ttl_modify, + .destroy = static_route_label_id_ttl_destroy, + }, + }, + { + .xpath = FRR_STATIC_NH_LABEL_ID_TC_XPATH, + .cbs = { + .modify = static_route_label_id_tc_modify, + .destroy = static_route_label_id_tc_destroy, + }, + }, + { + .xpath = NULL, + }, + } +}; diff --git a/staticd/static_nb.h b/staticd/static_nb.h new file mode 100644 index 000000000000..1d3cdb255d64 --- /dev/null +++ b/staticd/static_nb.h @@ -0,0 +1,54 @@ +#ifndef _FRR_STATIC_NB_H_ +#define _FRR_STATIC_NB_H_ + + +#define FRR_STATIC_ROUTE_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list" + +#define FRR_STATIC_ROUTE_DIS_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/distance" + +#define FRR_STATIC_ROUTE_TAG_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/tag" + +#define FRR_STATIC_ROUTE_TB_ID_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/table-id" + +#define FRR_STATIC_NH_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/frr-staticd-next-hop/frr-nexthops/nexthop" + +#define FRR_STATIC_NH_ONLINK_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/frr-staticd-next-hop/frr-nexthops/nexthop/onlink" + +#define FRR_STATIC_NH_BH_TYPE_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/frr-staticd-next-hop/frr-nexthops/nexthop/bh-type" + +#define FRR_STATIC_NH_LABEL_ID_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/frr-staticd-next-hop/frr-nexthops/nexthop/mpls-label-stack/entry" + +#define FRR_STATIC_NH_LABEL_ID_LABEL_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/frr-staticd-next-hop/frr-nexthops/nexthop/mpls-label-stack/entry/label" + +#define FRR_STATIC_NH_LABEL_ID_TTL_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/frr-staticd-next-hop/frr-nexthops/nexthop/mpls-label-stack/entry/ttl" + +#define FRR_STATIC_NH_LABEL_ID_TC_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/prefix-list/frr-staticd-next-hop/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class" + +#define FRR_STATIC_ROUTE_KEY_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol[type='%s'][name='%s'][vrf='%s']/frr-staticd:staticd/prefix-list[destination-prefix='%s'][src-prefix='%s']" + +#define FRR_STATIC_ROUTE_NH_KEY_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol[type='%s'][name='%s'][vrf='%s']/frr-staticd:staticd/prefix-list[destination-prefix='%s'][src-prefix='%s']/frr-staticd-next-hop/frr-nexthops/nexthop[nh-type='%s'][gateway='%s'][interface='%s'][vrf='%s']" + + +#define FRR_STATIC_ROUTE_NH_LABEL_ID_KEY_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol[type='%s'][name='%s'][vrf='%s']/frr-staticd:staticd/prefix-list[destination-prefix='%s'][src-prefix='%s']/frr-staticd-next-hop/frr-nexthops/nexthop[nh-type='%s'][gateway='%s'][interface='%s'][vrf='%s']/mpls-label-stack/entry[id='%d']/label" + + +#define FRR_STATIC_ROUTE_NH_LABEL_XPATH \ + "/frr-routing:routing/control-plane-protocols/control-plane-protocol[type='%s'][name='%s'][vrf='%s']/frr-staticd:staticd/prefix-list[destination-prefix='%s'][src-prefix='%s']/frr-staticd-next-hop/frr-nexthops/nexthop[nh-type='%s'][gateway='%s'][interface='%s'][vrf='%s']/mpls-label-stack" + +extern const struct frr_yang_module_info frr_staticd_info; + +#endif diff --git a/staticd/static_nht.c b/staticd/static_nht.c index 1a2ddd7f051b..9fdd93a4920b 100644 --- a/staticd/static_nht.c +++ b/staticd/static_nht.c @@ -35,28 +35,28 @@ static void static_nht_update_rn(struct route_node *rn, vrf_id_t nh_vrf_id, struct vrf *vrf, safi_t safi) { - struct static_route *si; + struct static_nexthop *nh; - for (si = rn->info; si; si = si->next) { - if (si->nh_vrf_id != nh_vrf_id) + RNODE_FOREACH_NH(rn, nh) { + if (nh->nh_vrf_id != nh_vrf_id) continue; - if (si->type != STATIC_IPV4_GATEWAY - && si->type != STATIC_IPV4_GATEWAY_IFNAME - && si->type != STATIC_IPV6_GATEWAY - && si->type != STATIC_IPV6_GATEWAY_IFNAME) + if (nh->type != STATIC_IPV4_GATEWAY + && nh->type != STATIC_IPV4_GATEWAY_IFNAME + && nh->type != STATIC_IPV6_GATEWAY + && nh->type != STATIC_IPV6_GATEWAY_IFNAME) continue; if (nhp->family == AF_INET - && nhp->u.prefix4.s_addr == si->addr.ipv4.s_addr) - si->nh_valid = !!nh_num; + && nhp->u.prefix4.s_addr == nh->addr.ipv4.s_addr) + nh->nh_valid = !!nh_num; if (nhp->family == AF_INET6 - && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) == 0) - si->nh_valid = !!nh_num; + && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, 16) == 0) + nh->nh_valid = !!nh_num; - if (si->state == STATIC_START) - static_zebra_route_add(rn, si, vrf->vrf_id, safi, true); + if (nh->state == STATIC_START) + static_zebra_route_add(rn, vrf->vrf_id, safi, true); } } @@ -111,7 +111,7 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi, { struct static_vrf *svrf; struct route_table *stable; - struct static_route *si; + struct static_nexthop *nh; struct route_node *rn; svrf = vrf->info; @@ -123,16 +123,16 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi, return; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (si->nh_vrf_id != nh_vrf_id) + RNODE_FOREACH_NH(rn, nh) { + if (nh->nh_vrf_id != nh_vrf_id) continue; if (nhp->family == AF_INET - && nhp->u.prefix4.s_addr != si->addr.ipv4.s_addr) + && nhp->u.prefix4.s_addr != nh->addr.ipv4.s_addr) continue; if (nhp->family == AF_INET6 - && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) != 0) + && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, 16) != 0) continue; /* @@ -141,7 +141,7 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi, * the state machine to allow us to start * over. */ - si->state = STATIC_START; + nh->state = STATIC_START; } } } @@ -164,8 +164,9 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi, { struct static_vrf *svrf; struct route_table *stable; - struct static_route *si; struct route_node *rn; + struct static_route_info *ri; + struct static_nexthop *nh; svrf = vrf->info; if (!svrf) @@ -179,8 +180,8 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi, if (!rn) return; - for (si = rn->info; si; si = si->next) - si->state = state; + RNODE_FOREACH_NH(rn, nh) + nh->state = state; route_unlock_node(rn); } diff --git a/staticd/static_routes.c b/staticd/static_routes.c index e8d6a4289b97..393559388b76 100644 --- a/staticd/static_routes.c +++ b/staticd/static_routes.c @@ -33,135 +33,196 @@ #include "static_zebra.h" /* Install static route into rib. */ -static void static_install_route(struct route_node *rn, - struct static_route *si_changed, safi_t safi) +void static_install_route(struct route_node *rn) { - struct static_route *si; + struct static_nexthop *si; + struct static_route_info *ri; + stable_info_t *info; - for (si = rn->info; si; si = si->next) - static_zebra_nht_register(rn, si, true); + ri = rn->info; + info = route_table_get_info(rn->table); + si = ri->nh; - si = rn->info; if (si) - static_zebra_route_add(rn, si_changed, si->vrf_id, safi, true); - + static_zebra_route_add(rn, GET_STABLE_VRF_ID(info), + info->safi, true); } /* Uninstall static route from RIB. */ -static void static_uninstall_route(vrf_id_t vrf_id, safi_t safi, - struct route_node *rn, - struct static_route *si_changed) +static void static_uninstall_route(struct route_node *rn) { + struct static_route_info *ri; + struct static_nexthop *si; + stable_info_t *info; - if (rn->info) - static_zebra_route_add(rn, si_changed, vrf_id, safi, true); + ri = rn->info; + info = route_table_get_info(rn->table); + si = ri->nh; + + if (si) + static_zebra_route_add(rn, GET_STABLE_VRF_ID(info), + info->safi, true); else - static_zebra_route_add(rn, si_changed, vrf_id, safi, false); + static_zebra_route_add(rn, GET_STABLE_VRF_ID(info), + info->safi, false); } -int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, - const char *ifname, enum static_blackhole_type bh_type, - route_tag_t tag, uint8_t distance, struct static_vrf *svrf, - struct static_vrf *nh_svrf, - struct static_nh_label *snh_label, uint32_t table_id, - bool onlink) + +struct route_node* static_add_route(afi_t afi, safi_t safi, + struct prefix *p, + struct prefix_ipv6 *src_p, + struct static_vrf *svrf) { struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; + struct static_route_info *ri; struct route_table *stable = svrf->stable[afi][safi]; - struct interface *ifp; + int ret; + bool negate = false; if (!stable) - return -1; + return NULL; - if (!gate && (type == STATIC_IPV4_GATEWAY - || type == STATIC_IPV4_GATEWAY_IFNAME - || type == STATIC_IPV6_GATEWAY - || type == STATIC_IPV6_GATEWAY_IFNAME)) - return -1; + if (afi == AFI_IP6) { + /* Lookup static route prefix. */ + rn = srcdest_rnode_get(stable, p, src_p); + } else { + rn = srcdest_rnode_get(stable, p , NULL); + } - if (!ifname - && (type == STATIC_IFNAME || type == STATIC_IPV4_GATEWAY_IFNAME - || type == STATIC_IPV6_GATEWAY_IFNAME)) - return -1; + /* Make new static route structure. */ + ri = XCALLOC(MTYPE_STATIC_ROUTE_INFO, + sizeof(struct static_route_info)); - /* Lookup static route prefix. */ - rn = srcdest_rnode_get(stable, p, src_p); - - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) { - if (type == si->type - && (!gate - || ((afi == AFI_IP - && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4)) - || (afi == AFI_IP6 - && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) - && (!strcmp(ifname ? ifname : "", si->ifname)) - && nh_svrf->vrf->vrf_id == si->nh_vrf_id) { - if ((distance == si->distance) && (tag == si->tag) - && (table_id == si->table_id) - && !memcmp(&si->snh_label, snh_label, - sizeof(struct static_nh_label)) - && si->bh_type == bh_type && si->onlink == onlink) { - route_unlock_node(rn); - return 0; - } - update = si; + ri->distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + + rn->info = ri; + + /* Mark as having FRR configuration */ + vrf_set_user_cfged(svrf->vrf); + + if (svrf->vrf->vrf_id == VRF_UNKNOWN) { + ret = zebra_static_route_holdem(rn, NULL, + negate); + if(!ret) { + zlog_warn("rn creation failed"); + return NULL; } } + return rn; +} + +void static_del_route(struct route_node *rn) +{ + stable_info_t *info; + struct static_vrf *svrf; + struct static_route_info *ri; + struct static_nexthop *nh; + struct static_nexthop *next_nh; + bool negate = true; + int ret; + + info = route_table_get_info(rn->table); + svrf = info->svrf; + ri = rn->info; + + + if (svrf->vrf->vrf_id == VRF_UNKNOWN) { + ret = zebra_static_route_holdem(rn, NULL, + negate); + if(!ret) { + zlog_warn("rn deletion failed"); + } + } + + for (nh = ri->nh; nh; nh = next_nh) { + next_nh = nh->next; + static_delete_nexthop(rn, nh); + } + + XFREE(MTYPE_STATIC_ROUTE_INFO, rn->info); + route_unlock_node(rn); + /* If no other FRR config for this VRF, mark accordingly. */ + if (!static_vrf_has_config(svrf)) + vrf_reset_user_cfged(svrf->vrf); +} + + +int static_add_nexthop_validate(struct route_node *rn, static_types type, + struct ipaddr *ipaddr) +{ + stable_info_t *info; + info = route_table_get_info(rn->table); + + switch (type) { + case STATIC_IPV4_GATEWAY: + case STATIC_IPV4_GATEWAY_IFNAME: + if (if_lookup_exact_address(&ipaddr->ipaddr_v4, + AF_INET, + GET_STABLE_VRF_ID(info))) + return -1; + break; + case STATIC_IPV6_GATEWAY: + case STATIC_IPV6_GATEWAY_IFNAME: + if (if_lookup_exact_address(&ipaddr->ipaddr_v6, + AF_INET6, + GET_STABLE_VRF_ID(info))) + return -1; + break; + default: + break; + } + + return 1; +} + +struct static_nexthop* static_add_nexthop(struct route_node *rn, + static_types type, + struct ipaddr *ipaddr, + const char *ifname, + const char *nh_vrf) +{ + struct static_nexthop *si; + struct static_nexthop *pp; + struct static_nexthop *cp; + struct static_route_info *ri; + struct static_vrf *nh_svrf; + struct interface *ifp; + int ret; + bool negate = false; - /* Distance or tag or label changed, delete existing first. */ - if (update) - static_delete_route(afi, safi, type, p, src_p, gate, ifname, - update->tag, update->distance, svrf, - &update->snh_label, table_id); + ri = rn->info; + nh_svrf = static_vrf_lookup_by_name(nh_vrf); /* Make new static route structure. */ - si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route)); + si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_nexthop)); si->type = type; - si->distance = distance; - si->bh_type = bh_type; - si->tag = tag; - si->vrf_id = svrf->vrf->vrf_id; + si->nh_vrf_id = nh_svrf->vrf->vrf_id; strlcpy(si->nh_vrfname, nh_svrf->vrf->name, sizeof(si->nh_vrfname)); - si->table_id = table_id; - si->onlink = onlink; if (ifname) strlcpy(si->ifname, ifname, sizeof(si->ifname)); si->ifindex = IFINDEX_INTERNAL; switch (type) { - case STATIC_IPV4_GATEWAY: - case STATIC_IPV4_GATEWAY_IFNAME: - si->addr.ipv4 = gate->ipv4; - break; - case STATIC_IPV6_GATEWAY: - case STATIC_IPV6_GATEWAY_IFNAME: - si->addr.ipv6 = gate->ipv6; - break; - case STATIC_IFNAME: - break; + case STATIC_IPV4_GATEWAY: + case STATIC_IPV4_GATEWAY_IFNAME: + si->addr.ipv4 = ipaddr->ipaddr_v4; + break; + case STATIC_IPV6_GATEWAY: + case STATIC_IPV6_GATEWAY_IFNAME: + si->addr.ipv6 = ipaddr->ipaddr_v6; + break; + default: + break; } - /* Save labels, if any. */ - memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label)); - /* * Add new static route information to the tree with sort by - * distance value and gateway address. + * gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; + for (pp = NULL, cp = ri->nh; cp; pp = cp, cp = cp->next) { if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) { if (ntohl(si->addr.ipv4.s_addr) @@ -177,12 +238,22 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, if (pp) pp->next = si; else - rn->info = si; + ri->nh = si; if (cp) cp->prev = si; si->prev = pp; si->next = cp; + if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN) { + ret = zebra_static_route_holdem(rn, si, + negate); + if(!ret) { + zlog_warn("nh creation failed"); + return NULL; + } + return si; + } + /* check whether interface exists in system & install if it does */ switch (si->type) { case STATIC_IPV4_GATEWAY: @@ -201,13 +272,13 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, static_zebra_nht_register(rn, si, true); break; case STATIC_BLACKHOLE: - static_install_route(rn, si, safi); + static_install_route(rn); break; case STATIC_IFNAME: ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id); if (ifp && ifp->ifindex != IFINDEX_INTERNAL) { si->ifindex = ifp->ifindex; - static_install_route(rn, si, safi); + static_install_route(rn); } else zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf", ifname); @@ -215,74 +286,49 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, break; } - return 1; + return si; } -int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, - const char *ifname, route_tag_t tag, uint8_t distance, - struct static_vrf *svrf, - struct static_nh_label *snh_label, - uint32_t table_id) +int static_delete_nexthop(struct route_node *rn, struct static_nexthop *si) { - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - - /* Lookup table. */ - stable = static_vrf_static_table(afi, safi, svrf); - if (!stable) - return -1; - - /* Lookup static route prefix. */ - rn = srcdest_rnode_lookup(stable, p, src_p); - if (!rn) - return 0; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (type == si->type - && (!gate - || ((afi == AFI_IP - && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4)) - || (afi == AFI_IP6 - && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) - && (!strcmp(ifname ? ifname : "", si->ifname)) - && (!tag || (tag == si->tag)) - && (table_id == si->table_id) - && (!snh_label->num_labels - || !memcmp(&si->snh_label, snh_label, - sizeof(struct static_nh_label)))) - break; + struct static_route_info *ri; + struct static_vrf *nh_svrf; + int ret; + bool negate = true; - /* Can't find static route. */ - if (!si) { - route_unlock_node(rn); - return 0; - } + ri = rn->info; - static_zebra_nht_register(rn, si, false); + nh_svrf = static_vrf_lookup_by_name(si->nh_vrfname); /* Unlink static route from linked list. */ if (si->prev) si->prev->next = si->next; else - rn->info = si->next; + ri->nh = si->next; if (si->next) si->next->prev = si->prev; + if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN) { + ret = zebra_static_route_holdem(rn, si, + negate); + if(!ret) { + zlog_warn("nh deletion failed"); + } + + goto EXIT; + } + + static_zebra_nht_register(rn, si, false); /* * If we have other si nodes then route replace * else delete the route */ - static_uninstall_route(si->vrf_id, safi, rn, si); - route_unlock_node(rn); + static_uninstall_route(rn); +EXIT: /* Free static route configuration. */ XFREE(MTYPE_STATIC_ROUTE, si); - route_unlock_node(rn); - return 1; } @@ -291,7 +337,7 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi, { struct route_table *stable; struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; struct vrf *vrf; RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { @@ -304,24 +350,24 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi, continue; for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (!si->ifname[0]) + RNODE_FOREACH_NH(rn, nh) { + if (!nh->ifname[0]) continue; if (up) { - if (strcmp(si->ifname, ifp->name)) + if (strcmp(nh->ifname, ifp->name)) continue; - if (si->nh_vrf_id != ifp->vrf_id) + if (nh->nh_vrf_id != ifp->vrf_id) continue; - si->ifindex = ifp->ifindex; + nh->ifindex = ifp->ifindex; } else { - if (si->ifindex != ifp->ifindex) + if (nh->ifindex != ifp->ifindex) continue; - if (si->nh_vrf_id != ifp->vrf_id) + if (nh->nh_vrf_id != ifp->vrf_id) continue; - si->ifindex = IFINDEX_INTERNAL; + nh->ifindex = IFINDEX_INTERNAL; } - static_install_route(rn, si, safi); + static_install_route(rn); } } } @@ -343,26 +389,26 @@ static void static_fixup_vrf(struct static_vrf *svrf, struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; struct interface *ifp; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0) + RNODE_FOREACH_NH(rn, nh) { + if (strcmp(svrf->vrf->name, nh->nh_vrfname) != 0) continue; - si->nh_vrf_id = svrf->vrf->vrf_id; - si->nh_registered = false; - if (si->ifindex) { - ifp = if_lookup_by_name(si->ifname, - si->nh_vrf_id); + nh->nh_vrf_id = svrf->vrf->vrf_id; + nh->nh_registered = false; + if (nh->ifindex) { + ifp = if_lookup_by_name(nh->ifname, + nh->nh_vrf_id); if (ifp) - si->ifindex = ifp->ifindex; + nh->ifindex = ifp->ifindex; else continue; } - static_install_route(rn, si, safi); + static_install_route(rn); } } } @@ -381,22 +427,22 @@ static void static_enable_vrf(struct static_vrf *svrf, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; struct interface *ifp; struct vrf *vrf = svrf->vrf; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - si->vrf_id = vrf->vrf_id; - if (si->ifindex) { - ifp = if_lookup_by_name(si->ifname, - si->nh_vrf_id); + RNODE_FOREACH_NH(rn, nh){ + nh->vrf_id = vrf->vrf_id; + if (nh->ifindex) { + ifp = if_lookup_by_name(nh->ifname, + nh->nh_vrf_id); if (ifp) - si->ifindex = ifp->ifindex; + nh->ifindex = ifp->ifindex; else continue; } - static_install_route(rn, si, safi); + static_install_route(rn); } } } @@ -452,14 +498,14 @@ static void static_cleanup_vrf(struct static_vrf *svrf, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0) + RNODE_FOREACH_NH(rn, nh) { + if (strcmp(svrf->vrf->name, nh->nh_vrfname) != 0) continue; - static_uninstall_route(si->vrf_id, safi, rn, si); + static_uninstall_route(rn); } } } @@ -476,11 +522,12 @@ static void static_disable_vrf(struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; - for (rn = route_top(stable); rn; rn = route_next(rn)) - for (si = rn->info; si; si = si->next) - static_uninstall_route(si->vrf_id, safi, rn, si); + for (rn = route_top(stable); rn; rn = route_next(rn)) { + RNODE_FOREACH_NH(rn, nh) + static_uninstall_route(rn); + } } /* @@ -535,17 +582,17 @@ static void static_fixup_intf_nh(struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_route *si; + struct static_nexthop *nh; for (rn = route_top(stable); rn; rn = route_next(rn)) { - for (si = rn->info; si; si = si->next) { - if (si->nh_vrf_id != ifp->vrf_id) + RNODE_FOREACH_NH(rn, nh) { + if (nh->nh_vrf_id != ifp->vrf_id) continue; - if (si->ifindex != ifp->ifindex) + if (nh->ifindex != ifp->ifindex) continue; - static_install_route(rn, si, safi); + static_install_route(rn); } } } @@ -589,3 +636,182 @@ void static_ifindex_update(struct interface *ifp, bool up) static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST); static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST); } + +void static_get_nh_type(static_types stype, char *type) +{ + switch(stype) { + case STATIC_IFNAME: + strcpy(type, "ifindex"); + break; + case STATIC_IPV4_GATEWAY: + strcpy(type, "ip4"); + break; + case STATIC_IPV4_GATEWAY_IFNAME: + strcpy(type, "ip4-ifindex"); + break; + case STATIC_BLACKHOLE: + strcpy(type, "blackhole"); + break; + case STATIC_IPV6_GATEWAY: + strcpy(type, "ipv6"); + break; + case STATIC_IPV6_GATEWAY_IFNAME: + strcpy(type, "ipv6-ifindex"); + break; + }; +} + + +/* This API is necessary as libyang does not support the auto deletion + * of node; if it's all child nodes gets deleted. like prefix is not + * deleted automatically if all it's nexthops gets deleted. + */ +int static_get_route_delete(afi_t afi, safi_t safi, uint8_t type, + struct prefix *p, struct prefix_ipv6 *src_p, + const char *gate_str, const char *ifname, + struct static_vrf *svrf) +{ + struct route_node *rn; + struct static_route_info *si; + struct static_nexthop *nh; + struct route_table *stable; + union g_addr gate; + union g_addr *gatep = NULL; + + + if (gate_str) { + if (inet_pton(afi2family(afi), gate_str, &gate) != 1) + return 0; + gatep = &gate; + } + + /* Lookup table. */ + stable = static_vrf_static_table(afi, safi, svrf); + if (!stable) + return -1; + + /* Lookup static route prefix. */ + rn = srcdest_rnode_lookup(stable, p, src_p); + if (!rn) + return 0; + si = rn->info; + nh = si->nh; + + if(nh && !nh->next + && (type == nh->type + && (!gatep + || ((afi == AFI_IP + && IPV4_ADDR_SAME(&gatep->ipv4, &nh->addr.ipv4)) + || (afi == AFI_IP6 + && IPV6_ADDR_SAME(gatep, &nh->addr.ipv6)))) + && (!strcmp(ifname ? ifname : "(null)", nh->ifname)))) { + route_unlock_node(rn); + return 1; + } + route_unlock_node(rn); + return 0; +} + +struct static_hold_route { + struct route_node *rn; + struct static_nexthop *nh; +}; + +static struct list *static_list; + + +static void static_list_delete(struct static_hold_route *shr) +{ + 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; + + if (shr1->rn != shr2->rn) + return 1; + if (shr1->nh != shr2->nh) + return 1; + + return 0; +} + +void static_list_init(void) +{ + static_list = list_new(); + static_list->cmp = (int (*)(void *, void *))static_list_compare; + static_list->del = (void (*)(void *))static_list_delete; +} + +int zebra_static_route_holdem(struct route_node *rn, + struct static_nexthop *nh, bool negate) +{ + + struct static_hold_route *shr, *lookup; + struct listnode *node; + + zlog_warn("Static Route to not installed currently because dependent config not fully available"); + + shr = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(*shr)); + shr->rn = rn; + shr->nh = nh; + + + 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 1; + } + + /* + * 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 1; + } + +shr_cleanup: + XFREE(MTYPE_STATIC_ROUTE, shr); + + return 1; +} + +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 = NULL; + stable_info_t *info; + + for (ALL_LIST_ELEMENTS(static_list, node, nnode, shr)) { + info = route_table_get_info(shr->rn->table); + osvrf = info->svrf; + if(shr->nh) + nh_svrf = static_vrf_lookup_by_name( + shr->nh->nh_vrfname); + + if (osvrf != svrf && nh_svrf != svrf) + continue; + + if (osvrf->vrf->vrf_id == VRF_UNKNOWN + || (nh_svrf && nh_svrf->vrf->vrf_id == VRF_UNKNOWN)) + continue; + static_install_route(shr->rn); + listnode_delete(static_list, shr); + static_list_delete(shr); + } +} diff --git a/staticd/static_routes.h b/staticd/static_routes.h index 6414947b1601..d61e9ad86970 100644 --- a/staticd/static_routes.h +++ b/staticd/static_routes.h @@ -21,6 +21,7 @@ #define __STATIC_ROUTES_H__ #include "lib/mpls.h" +#include "table.h" /* Static route label information */ struct static_nh_label { @@ -36,12 +37,12 @@ enum static_blackhole_type { }; typedef enum { - STATIC_IFNAME, + STATIC_IFNAME = 1, STATIC_IPV4_GATEWAY, STATIC_IPV4_GATEWAY_IFNAME, - STATIC_BLACKHOLE, STATIC_IPV6_GATEWAY, STATIC_IPV6_GATEWAY_IFNAME, + STATIC_BLACKHOLE, } static_types; /* @@ -64,11 +65,24 @@ enum static_install_states { STATIC_NOT_INSTALLED, }; + +struct static_route_info { + + /* Administrative distance. */ + uint8_t distance; + /* Tag */ + route_tag_t tag; + /* Table-id */ + uint32_t table_id; + /* Nexthop list */ + struct static_nexthop *nh; +}; + /* Static route information. */ -struct static_route { +struct static_nexthop { /* For linked list. */ - struct static_route *prev; - struct static_route *next; + struct static_nexthop *prev; + struct static_nexthop *next; /* VRF identifier. */ vrf_id_t vrf_id; @@ -81,12 +95,6 @@ struct static_route { */ enum static_install_states state; - /* Administrative distance. */ - uint8_t distance; - - /* Tag */ - route_tag_t tag; - /* Flag for this static route's type. */ static_types type; @@ -104,8 +112,6 @@ struct static_route { /* Label information */ struct static_nh_label snh_label; - uint32_t table_id; - /* * Whether to pretend the nexthop is directly attached to the specified * link. Only meaningful when both a gateway address and interface name @@ -114,32 +120,65 @@ struct static_route { bool onlink; }; +/* + * rib_dest_from_rnode + */ +static inline struct static_route_info *static_route_info_from_rnode( + struct route_node *rn) +{ + return (struct static_route_info *)(rn->info); +} + +#define NH_FOREACH_ROUTE(ri, nh) \ + for ((nh) = ri ? ri->nh : NULL; (nh); (nh) = nh->next) + +#define RNODE_FOREACH_NH(rn, nh) \ + NH_FOREACH_ROUTE (static_route_info_from_rnode(rn), nh) + extern bool mpls_enabled; extern struct zebra_privs_t static_privs; void static_fixup_vrf_ids(struct static_vrf *svrf); -extern int static_add_route(afi_t afi, safi_t safi, uint8_t type, - struct prefix *p, struct prefix_ipv6 *src_p, - union g_addr *gate, const char *ifname, - enum static_blackhole_type bh_type, route_tag_t tag, - uint8_t distance, struct static_vrf *svrf, - struct static_vrf *nh_svrf, - struct static_nh_label *snh_label, - uint32_t table_id, bool onlink); - -extern int static_delete_route(afi_t afi, safi_t safi, uint8_t type, - struct prefix *p, struct prefix_ipv6 *src_p, - union g_addr *gate, const char *ifname, - route_tag_t tag, uint8_t distance, - struct static_vrf *svrf, - struct static_nh_label *snh_label, - uint32_t table_id); +extern struct static_nexthop* static_add_nexthop (struct route_node *rn, + static_types type, + struct ipaddr *ipaddr, + const char *ifname, + const char *nh_vrf); + +extern int static_delete_nexthop(struct route_node *rn, + struct static_nexthop *si); extern void static_cleanup_vrf_ids(struct static_vrf *disable_svrf); extern void static_install_intf_nh(struct interface *ifp); extern void static_ifindex_update(struct interface *ifp, bool up); + +extern void static_install_route(struct route_node *rn); + + +/*** New API's remove this comment later ***/ +extern struct route_node* static_add_route(afi_t afi, safi_t safi, + struct prefix *p, + struct prefix_ipv6 *src_p, + struct static_vrf *svrf); +extern void static_del_route(struct route_node *rn); + +void static_get_nh_type(static_types stype, char *type); +int static_add_nexthop_validate(struct route_node *rn, static_types type, + struct ipaddr *ipaddr); +int static_get_route_delete(afi_t afi, safi_t safi, uint8_t type, + struct prefix *p, struct prefix_ipv6 *src_p, + const char *gate_str, const char *ifname, + struct static_vrf *svrf); + +void static_list_init(void); + +int zebra_static_route_holdem(struct route_node *rn, + struct static_nexthop *nh, bool negate); + +void static_config_install_delayed_routes(struct static_vrf *svrf); + #endif diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index abb64aad3f34..a7893602eb99 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -33,19 +33,23 @@ static void zebra_stable_node_cleanup(struct route_table *table, struct route_node *node) { - struct static_route *si, *next; + struct static_nexthop *si, *next; + struct static_route_info *ri; - if (node->info) - for (si = node->info; si; si = next) { + if (node->info) { + ri = node->info; + for (si = ri->nh; si; si = next) { next = si->next; XFREE(MTYPE_STATIC_ROUTE, si); } + } } static struct static_vrf *static_vrf_alloc(void) { struct route_table *table; struct static_vrf *svrf; + stable_info_t *info; safi_t safi; afi_t afi; @@ -57,6 +61,13 @@ static struct static_vrf *static_vrf_alloc(void) table = srcdest_table_init(); else table = route_table_init(); + + info = XCALLOC(MTYPE_TMP, sizeof(stable_info_t)); + info->svrf = svrf; + info->afi = afi; + info->safi = safi; + route_table_set_info(table, info); + table->cleanup = zebra_stable_node_cleanup; svrf->stable[afi][safi] = table; } @@ -102,12 +113,15 @@ static int static_vrf_delete(struct vrf *vrf) struct static_vrf *svrf; safi_t safi; afi_t afi; + void *info; svrf = vrf->info; for (afi = AFI_IP; afi <= AFI_IP6; afi++) { for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { table = svrf->stable[afi][safi]; + info = route_table_get_info(table); route_table_finish(table); + XFREE(MTYPE_TMP, info); svrf->stable[afi][safi] = NULL; } } diff --git a/staticd/static_vrf.h b/staticd/static_vrf.h index 28fcdd0d36ac..f9965c5f189b 100644 --- a/staticd/static_vrf.h +++ b/staticd/static_vrf.h @@ -26,6 +26,14 @@ struct static_vrf { struct route_table *stable[AFI_MAX][SAFI_MAX]; }; +typedef struct stable_info_t_ { + struct static_vrf *svrf; + afi_t afi; + safi_t safi; +}stable_info_t; + +#define GET_STABLE_VRF_ID(info) info->svrf->vrf->vrf_id + struct static_vrf *static_vrf_lookup_by_name(const char *vrf_name); struct static_vrf *static_vrf_lookup_by_id(vrf_id_t vrf_id); diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 6390fd811f64..d1f231de967d 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,6 +40,7 @@ #ifndef VTYSH_EXTRACT_PL #include "staticd/static_vty_clippy.c" #endif +#include "static_nb.h" #define STATICD_STR "Static route daemon\n" @@ -67,200 +72,6 @@ static struct static_vrf *static_vty_get_unknown_vrf(struct vty *vty, 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, @@ -270,17 +81,19 @@ static int static_route_leak( 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; - uint32_t table_id = 0; + const char *bh_type; + char xpath_list[XPATH_MAXLEN]; + char buf_prefix[PREFIX_STRLEN]; + char buf_src_prefix[PREFIX_STRLEN]; + char buf_nh_type[PREFIX_STRLEN]; + uint8_t label_stack_id = 0; + + memset(buf_src_prefix, 0, PREFIX_STRLEN); + memset(buf_nh_type, 0, PREFIX_STRLEN); ret = str2prefix(dest_str, &p); if (ret <= 0) { @@ -320,7 +133,7 @@ static int static_route_leak( else zlog_warn( "%s: Malformed source address: %s", - __PRETTY_FUNCTION__, src_str); + __func__, src_str); return CMD_WARNING_CONFIG_FAILED; } src_p = (struct prefix_ipv6 *)&src; @@ -333,173 +146,10 @@ 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); - } - - 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", - __PRETTY_FUNCTION__, - table_str, svrf->vrf->data.l.table_id); - return CMD_WARNING_CONFIG_FAILED; - } - } + prefix2str(&p, buf_prefix, sizeof(buf_prefix)); - /* Administrative distance. */ - if (distance_str) - distance = atoi(distance_str); - else - distance = ZEBRA_STATIC_DISTANCE_DEFAULT; - - /* tag */ - 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", - __PRETTY_FUNCTION__, 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", - __PRETTY_FUNCTION__, 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", - __PRETTY_FUNCTION__, - 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", - __PRETTY_FUNCTION__, - 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)", - __PRETTY_FUNCTION__, 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", - __PRETTY_FUNCTION__, flag_str, - dest_str); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (gate_str) { - if (inet_pton(afi2family(afi), gate_str, &gate) != 1) { - if (vty) - vty_out(vty, - "%% Malformed nexthop address %s\n", - gate_str); - else - zlog_warn( - "%s: Malformed nexthop address %s for %s", - __PRETTY_FUNCTION__, gate_str, - dest_str); - return CMD_WARNING_CONFIG_FAILED; - } - 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 (src_str) + prefix2str(&src, buf_src_prefix, sizeof(buf_prefix)); if (gate_str == NULL && ifname == NULL) type = STATIC_BLACKHOLE; @@ -517,21 +167,108 @@ static int static_route_leak( 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); + static_get_nh_type(type, buf_nh_type); + + if(!negate) { + /* route processing */ + snprintf(xpath_list, sizeof(xpath_list), + FRR_STATIC_ROUTE_KEY_XPATH, + "frr-staticd:static","static",svrf->vrf->name, + buf_prefix, buf_src_prefix); + + + nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL); + + /* Administrative distance. */ + if (distance_str) + nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY, + distance_str); + /* tag */ + if (tag_str) + nb_cli_enqueue_change(vty, "./tag", NB_OP_MODIFY, + tag_str); + /* table-id */ + if (table_str) + nb_cli_enqueue_change(vty, "./table-id", NB_OP_MODIFY, + table_str); + + /* nexthop processing */ + + snprintf(xpath_list, sizeof(xpath_list), + FRR_STATIC_ROUTE_NH_KEY_XPATH, + "frr-staticd:static","static",svrf->vrf->name, + buf_prefix, buf_src_prefix, buf_nh_type, + gate_str, ifname, nh_svrf->vrf->name); + + nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL); + + /* 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, "./bh-type", NB_OP_MODIFY, + bh_type); + } + + if (label_str) { + char *ostr; // copy of label string (start) + char *nump; // pointer to next segment + ostr = XSTRDUP(MTYPE_TMP, label_str); + while( (nump = strsep(&ostr,"/")) != NULL ) { + label_stack_id++; + snprintf(xpath_list, sizeof(xpath_list), + FRR_STATIC_ROUTE_NH_LABEL_ID_KEY_XPATH, + "frr-staticd:static","static",svrf->vrf->name, + buf_prefix, buf_src_prefix, buf_nh_type, gate_str, + ifname, nh_svrf->vrf->name, label_stack_id); + nb_cli_enqueue_change(vty, xpath_list, NB_OP_MODIFY, + nump); + } + XFREE(MTYPE_TMP, ostr); + } else { + snprintf(xpath_list, sizeof(xpath_list), + FRR_STATIC_ROUTE_NH_LABEL_XPATH, + "frr-staticd:static","static",svrf->vrf->name, + buf_prefix, buf_src_prefix, buf_nh_type, gate_str, + ifname, nh_svrf->vrf->name); + nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL); + } + + ret = nb_cli_apply_changes(vty, xpath_list); } 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 (static_get_route_delete(afi, safi, type, &p, src_p, + gate_str, ifname, svrf)) + snprintf(xpath_list, sizeof(xpath_list), + FRR_STATIC_ROUTE_KEY_XPATH, + "frr-staticd:static","static",svrf->vrf->name, + buf_prefix, buf_src_prefix); + else + snprintf(xpath_list, sizeof(xpath_list), + FRR_STATIC_ROUTE_NH_KEY_XPATH, + "frr-staticd:static","static",svrf->vrf->name, + buf_prefix, buf_src_prefix, buf_nh_type, + gate_str, ifname, nh_svrf->vrf->name); + + nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL); + + ret = nb_cli_apply_changes(vty, xpath_list); } return CMD_SUCCESS; + } static int static_route(struct vty *vty, afi_t afi, safi_t safi, @@ -567,49 +304,14 @@ static int static_route(struct vty *vty, afi_t afi, safi_t safi, 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", - __PRETTY_FUNCTION__, shr->dest_str); - listnode_delete(static_list, shr); - static_list_delete(shr); - } -} - /* 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_route_info *ri; struct route_table *stable; char buf[SRCDEST2STR_BUFFER]; int write = 0; @@ -621,65 +323,28 @@ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, sprintf(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) - continue; - - if (strcmp(svrf->vrf->name, shr->vrf_name) != 0) + for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) { + ri = rn->info; + if(!ri) 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) { + RNODE_FOREACH_NH(rn, nh) { vty_out(vty, "%s %s", spacing, srcdest_rnode2str(rn, buf, sizeof(buf))); - switch (si->type) { + switch (nh->type) { case STATIC_IPV4_GATEWAY: - vty_out(vty, " %s", inet_ntoa(si->addr.ipv4)); + vty_out(vty, " %s", inet_ntoa(nh->addr.ipv4)); break; case STATIC_IPV6_GATEWAY: vty_out(vty, " %s", - inet_ntop(AF_INET6, &si->addr.ipv6, buf, + inet_ntop(AF_INET6, &nh->addr.ipv6, buf, sizeof(buf))); break; case STATIC_IFNAME: - vty_out(vty, " %s", si->ifname); + vty_out(vty, " %s", nh->ifname); break; case STATIC_BLACKHOLE: - switch (si->bh_type) { + switch (nh->bh_type) { case STATIC_BLACKHOLE_DROP: vty_out(vty, " blackhole"); break; @@ -693,48 +358,49 @@ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, break; case STATIC_IPV4_GATEWAY_IFNAME: vty_out(vty, " %s %s", - inet_ntop(AF_INET, &si->addr.ipv4, buf, + inet_ntop(AF_INET, &nh->addr.ipv4, buf, sizeof(buf)), - si->ifname); + nh->ifname); break; case STATIC_IPV6_GATEWAY_IFNAME: vty_out(vty, " %s %s", - inet_ntop(AF_INET6, &si->addr.ipv6, buf, + inet_ntop(AF_INET6, &nh->addr.ipv6, buf, sizeof(buf)), - si->ifname); + nh->ifname); break; } - if (si->tag) - vty_out(vty, " tag %" ROUTE_TAG_PRI, si->tag); + if (ri->tag) + vty_out(vty, " tag %" ROUTE_TAG_PRI, ri->tag); - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out(vty, " %d", si->distance); + if (ri->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out(vty, " %d", ri->distance); /* Label information */ - if (si->snh_label.num_labels) + if (nh->snh_label.num_labels) vty_out(vty, " label %s", - mpls_label2str(si->snh_label.num_labels, - si->snh_label.label, buf, + mpls_label2str(nh->snh_label.num_labels, + nh->snh_label.label, buf, sizeof(buf), 0)); - if (si->nh_vrf_id != si->vrf_id) - vty_out(vty, " nexthop-vrf %s", si->nh_vrfname); + if (nh->nh_vrf_id != nh->vrf_id) + vty_out(vty, " nexthop-vrf %s", nh->nh_vrfname); /* * table ID from VRF overrides configured */ - if (si->table_id && + if (ri->table_id && svrf->vrf->data.l.table_id == RT_TABLE_MAIN) - vty_out(vty, " table %u", si->table_id); + vty_out(vty, " table %u", ri->table_id); - if (si->onlink) + if (nh->onlink) vty_out(vty, " onlink"); vty_out(vty, "\n"); write = 1; } + } return write; } @@ -946,12 +612,6 @@ DEFPY(ip_route_address_interface_vrf, struct static_vrf *svrf = vrf->info; struct static_vrf *nh_svrf; - if (table_str && !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; @@ -1499,8 +1159,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; } diff --git a/staticd/static_vty.h b/staticd/static_vty.h index 2f65c08b8b61..7ffc8d9c98b3 100644 --- a/staticd/static_vty.h +++ b/staticd/static_vty.h @@ -19,8 +19,6 @@ #ifndef __STATIC_VTY_H__ #define __STATIC_VTY_H__ -void static_config_install_delayed_routes(struct static_vrf *svrf); - int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, safi_t safi, const char *cmd); diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 42646d15bca7..b70521908286 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -265,7 +265,7 @@ static void static_nht_hash_free(void *data) } void static_zebra_nht_register(struct route_node *rn, - struct static_route *si, bool reg) + struct static_nexthop *si, bool reg) { struct static_nht_data *nhtd, lookup; uint32_t cmd; @@ -340,10 +340,10 @@ void static_zebra_nht_register(struct route_node *rn, } extern void static_zebra_route_add(struct route_node *rn, - struct static_route *si_changed, vrf_id_t vrf_id, safi_t safi, bool install) { - struct static_route *si = rn->info; + struct static_nexthop *si; + struct static_route_info *ri; const struct prefix *p, *src_pp; struct zapi_nexthop *api_nh; struct zapi_route api; @@ -358,35 +358,32 @@ extern void static_zebra_route_add(struct route_node *rn, api.safi = safi; memcpy(&api.prefix, p, sizeof(api.prefix)); + ri = rn->info; + si = ri->nh; + if (src_pp) { SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); memcpy(&api.src_prefix, src_pp, sizeof(api.src_prefix)); } SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - if (si_changed->distance) { + if (ri->distance) { SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = si_changed->distance; + api.distance = ri->distance; } - if (si_changed->tag) { + if (ri->tag) { SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = si_changed->tag; + api.tag = ri->tag; } - if (si_changed->table_id != 0) { + if (ri->table_id != 0) { SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID); - api.tableid = si_changed->table_id; + api.tableid = ri->table_id; } for (/*loaded above*/; si; si = si->next) { api_nh = &api.nexthops[nh_num]; if (si->nh_vrf_id == VRF_UNKNOWN) continue; - if (si->distance != si_changed->distance) - continue; - - if (si->table_id != si_changed->table_id) - continue; - api_nh->vrf_id = si->nh_vrf_id; if (si->onlink) SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); @@ -484,6 +481,7 @@ void static_zebra_init(void) static_nht_hash = hash_create(static_nht_hash_key, static_nht_hash_cmp, "Static Nexthop Tracking hash"); + static_list_init(); } void static_zebra_vrf_register(struct vrf *vrf) diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h index 962dc3908fa9..89ecf29b1265 100644 --- a/staticd/static_zebra.h +++ b/staticd/static_zebra.h @@ -22,10 +22,9 @@ extern struct thread_master *master; extern void static_zebra_nht_register(struct route_node *rn, - struct static_route *si, bool reg); + struct static_nexthop *si, bool reg); extern void static_zebra_route_add(struct route_node *rn, - struct static_route *si_changed, vrf_id_t vrf_id, safi_t safi, bool install); extern void static_zebra_init(void); extern void static_zebra_vrf_register(struct vrf *vrf); diff --git a/staticd/subdir.am b/staticd/subdir.am index 30c69231c915..287ed01e8482 100644 --- a/staticd/subdir.am +++ b/staticd/subdir.am @@ -18,6 +18,8 @@ staticd_libstatic_a_SOURCES = \ staticd/static_zebra.c \ staticd/static_vrf.c \ staticd/static_vty.c \ + staticd/static_nb.c \ + yang/frr-staticd.yang.c \ # end noinst_HEADERS += \ @@ -28,6 +30,7 @@ noinst_HEADERS += \ staticd/static_routes.h \ staticd/static_vty.h \ staticd/static_vrf.h \ + staticd/static_nb.h \ # end staticd/static_vty_clippy.c: $(CLIPPY_DEPS) diff --git a/yang/frr-nexthop.yang b/yang/frr-nexthop.yang index 248dd56d937e..f43b3dbd45f4 100644 --- a/yang/frr-nexthop.yang +++ b/yang/frr-nexthop.yang @@ -196,7 +196,7 @@ module frr-nexthop { description "FRR nexthop object."; list nexthop { - key "nh-type gateway interface"; + key "nh-type gateway interface vrf"; description "A list of nexthop objects."; diff --git a/yang/frr-staticd.yang b/yang/frr-staticd.yang index 58933c904083..43695b286896 100644 --- a/yang/frr-staticd.yang +++ b/yang/frr-staticd.yang @@ -39,6 +39,16 @@ module frr-staticd { "'Static' routing pseudo-protocol."; } + typedef optional-src-prefix { + type union { + type inet:ipv6-prefix; + type string { + pattern + ''; + } + } + } + augment "/frr-rt:routing/frr-rt:control-plane-protocols/" + "frr-rt:control-plane-protocol" { container staticd { @@ -52,16 +62,22 @@ module frr-staticd { consists of a list of routes."; list prefix-list { - key "destination-prefix"; + key "destination-prefix src-prefix"; description "List of static IP routes."; leaf destination-prefix { - type inet:ip-address; + type inet:ip-prefix; description "IP destination prefix."; } + leaf src-prefix { + type optional-src-prefix; + description + "IPv6 source prefix"; + } + leaf distance { type frr-rt:administrative-distance; description @@ -75,6 +91,14 @@ module frr-staticd { description "Route tag"; } + + leaf table-id { + type uint32 { + range "1..4294967295"; + } + description + "Table-id"; + } container frr-staticd-next-hop { description "Augment static route configuration 'nexthop-list'."; diff --git a/yang/frr-vrf.yang b/yang/frr-vrf.yang index 40ead7e79c61..bc474eb5ba47 100644 --- a/yang/frr-vrf.yang +++ b/yang/frr-vrf.yang @@ -54,7 +54,6 @@ module frr-vrf { } container netns { - if-feature "netns"; leaf name { type string; description