diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 04:24:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 04:24:32 +0000 |
commit | 35cadacd2bb9383686753731e31bd7e145fb2506 (patch) | |
tree | 4489adbde75a837989533837185b2b8369a0bf68 /staticd | |
parent | Adding debian version 9.1-0.1. (diff) | |
download | frr-35cadacd2bb9383686753731e31bd7e145fb2506.tar.xz frr-35cadacd2bb9383686753731e31bd7e145fb2506.zip |
Merging upstream version 10.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'staticd')
-rw-r--r-- | staticd/static_bfd.c | 24 | ||||
-rw-r--r-- | staticd/static_main.c | 29 | ||||
-rw-r--r-- | staticd/static_nb.c | 15 | ||||
-rw-r--r-- | staticd/static_nb.h | 6 | ||||
-rw-r--r-- | staticd/static_nb_config.c | 131 | ||||
-rw-r--r-- | staticd/static_nht.c | 34 | ||||
-rw-r--r-- | staticd/static_routes.c | 201 | ||||
-rw-r--r-- | staticd/static_routes.h | 12 | ||||
-rw-r--r-- | staticd/static_vrf.c | 126 | ||||
-rw-r--r-- | staticd/static_vrf.h | 14 | ||||
-rw-r--r-- | staticd/static_vty.c | 241 | ||||
-rw-r--r-- | staticd/static_vty.h | 16 | ||||
-rw-r--r-- | staticd/static_zebra.c | 64 |
13 files changed, 437 insertions, 476 deletions
diff --git a/staticd/static_bfd.c b/staticd/static_bfd.c index 507c64e..c35751f 100644 --- a/staticd/static_bfd.c +++ b/staticd/static_bfd.c @@ -91,11 +91,11 @@ void static_next_hop_bfd_monitor_enable(struct static_nexthop *sn, struct vrf *vrf = NULL; use_interface = false; - use_source = yang_dnode_exists(dnode, "./source"); - use_profile = yang_dnode_exists(dnode, "./profile"); + use_source = yang_dnode_exists(dnode, "source"); + use_profile = yang_dnode_exists(dnode, "profile"); onlink = yang_dnode_exists(dnode, "../onlink") && yang_dnode_get_bool(dnode, "../onlink"); - mhop = yang_dnode_get_bool(dnode, "./multi-hop"); + mhop = yang_dnode_get_bool(dnode, "multi-hop"); vrf = vrf_lookup_by_name(yang_dnode_get_string(dnode, "../vrf")); family = static_next_hop_type_to_family(sn); @@ -112,7 +112,7 @@ void static_next_hop_bfd_monitor_enable(struct static_nexthop *sn, /* Configure the session. */ if (use_source) - yang_dnode_get_ip(&source, dnode, "./source"); + yang_dnode_get_ip(&source, dnode, "source"); if (onlink || mhop == false) bfd_sess_set_auto_source(sn->bsp, false); @@ -263,14 +263,13 @@ static void static_bfd_show_path_json(struct vty *vty, struct json_object *jo, static void static_bfd_show_json(struct vty *vty) { struct json_object *jo, *jo_path, *jo_afi_safi; - struct vrf *vrf; + struct static_vrf *svrf; jo = json_object_new_object(); jo_path = json_object_new_object(); json_object_object_add(jo, "path-list", jo_path); - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - const struct static_vrf *svrf = vrf->info; + RB_FOREACH (svrf, svrf_name_head, &svrfs) { struct route_table *rt; jo_afi_safi = json_object_new_array(); @@ -346,7 +345,7 @@ static void static_bfd_show_path(struct vty *vty, struct route_table *rt) void static_bfd_show(struct vty *vty, bool json) { - struct vrf *vrf; + struct static_vrf *svrf; if (json) { static_bfd_show_json(vty); @@ -355,21 +354,20 @@ void static_bfd_show(struct vty *vty, bool json) vty_out(vty, "Showing BFD monitored static routes:\n"); vty_out(vty, "\n Next hops:\n"); - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - const struct static_vrf *svrf = vrf->info; + RB_FOREACH (svrf, svrf_name_head, &svrfs) { struct route_table *rt; - vty_out(vty, " VRF %s IPv4 Unicast:\n", vrf->name); + vty_out(vty, " VRF %s IPv4 Unicast:\n", svrf->name); rt = svrf->stable[AFI_IP][SAFI_UNICAST]; if (rt) static_bfd_show_path(vty, rt); - vty_out(vty, "\n VRF %s IPv4 Multicast:\n", vrf->name); + vty_out(vty, "\n VRF %s IPv4 Multicast:\n", svrf->name); rt = svrf->stable[AFI_IP][SAFI_MULTICAST]; if (rt) static_bfd_show_path(vty, rt); - vty_out(vty, "\n VRF %s IPv6 Unicast:\n", vrf->name); + vty_out(vty, "\n VRF %s IPv6 Unicast:\n", svrf->name); rt = svrf->stable[AFI_IP6][SAFI_UNICAST]; if (rt) static_bfd_show_path(vty, rt); diff --git a/staticd/static_main.c b/staticd/static_main.c index 165fb4d..9468a98 100644 --- a/staticd/static_main.c +++ b/staticd/static_main.c @@ -53,7 +53,7 @@ struct option longopts[] = { { 0 } }; /* Master of threads. */ struct event_loop *master; -struct mgmt_be_client *mgmt_be_client; +static struct mgmt_be_client *mgmt_be_client; static struct frr_daemon_info staticd_di; @@ -113,23 +113,26 @@ static const struct frr_yang_module_info *const staticd_yang_modules[] = { &frr_staticd_info, }; -#define STATIC_VTY_PORT 2616 - /* * NOTE: .flags == FRR_NO_SPLIT_CONFIG to avoid reading split config, mgmtd will * do this for us now */ -FRR_DAEMON_INFO(staticd, STATIC, .vty_port = STATIC_VTY_PORT, +/* clang-format off */ +FRR_DAEMON_INFO(staticd, STATIC, + .vty_port = STATIC_VTY_PORT, + .proghelp = "Implementation of STATIC.", - .proghelp = "Implementation of STATIC.", + .signals = static_signals, + .n_signals = array_size(static_signals), - .signals = static_signals, - .n_signals = array_size(static_signals), + .privs = &static_privs, - .privs = &static_privs, .yang_modules = staticd_yang_modules, - .n_yang_modules = array_size(staticd_yang_modules), + .yang_modules = staticd_yang_modules, + .n_yang_modules = array_size(staticd_yang_modules), - .flags = FRR_NO_SPLIT_CONFIG); + .flags = FRR_NO_SPLIT_CONFIG, +); +/* clang-format on */ int main(int argc, char **argv, char **envp) { @@ -165,8 +168,10 @@ int main(int argc, char **argv, char **envp) hook_register(routing_conf_event, routing_control_plane_protocols_name_validate); - - routing_control_plane_protocols_register_vrf_dependency(); + hook_register(routing_create, + routing_control_plane_protocols_staticd_create); + hook_register(routing_destroy, + routing_control_plane_protocols_staticd_destroy); /* * We set FRR_NO_SPLIT_CONFIG flag to avoid reading our config, but we diff --git a/staticd/static_nb.c b/staticd/static_nb.c index 1c69a58..e6aa71a 100644 --- a/staticd/static_nb.c +++ b/staticd/static_nb.c @@ -16,18 +16,10 @@ const struct frr_yang_module_info frr_staticd_info = { .name = "frr-staticd", .nodes = { { - .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd", - .cbs = { - .cli_show = static_cli_show, - .cli_show_end = static_cli_show_end, - } - }, - { .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list", .cbs = { .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create, .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy, - .cli_cmp = static_route_list_cli_cmp, } }, { @@ -35,7 +27,6 @@ const struct frr_yang_module_info frr_staticd_info = { .cbs = { .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create, .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy, - .cli_cmp = static_path_list_cli_cmp, } }, { @@ -51,8 +42,6 @@ const struct frr_yang_module_info frr_staticd_info = { .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create, .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy, .pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate, - .cli_show = static_nexthop_cli_show, - .cli_cmp = static_nexthop_cli_cmp, } }, { @@ -150,7 +139,6 @@ const struct frr_yang_module_info frr_staticd_info = { .cbs = { .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create, .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy, - .cli_cmp = static_src_list_cli_cmp, } }, { @@ -158,7 +146,6 @@ const struct frr_yang_module_info frr_staticd_info = { .cbs = { .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create, .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy, - .cli_cmp = static_path_list_cli_cmp, } }, { @@ -174,8 +161,6 @@ const struct frr_yang_module_info frr_staticd_info = { .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create, .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy, .pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate, - .cli_show = static_src_nexthop_cli_show, - .cli_cmp = static_nexthop_cli_cmp, } }, { diff --git a/staticd/static_nb.h b/staticd/static_nb.h index 9f80653..be75d9d 100644 --- a/staticd/static_nb.h +++ b/staticd/static_nb.h @@ -11,6 +11,12 @@ extern "C" { #endif extern const struct frr_yang_module_info frr_staticd_info; +extern const struct frr_yang_module_info frr_staticd_cli_info; + +int routing_control_plane_protocols_staticd_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_staticd_destroy( + struct nb_cb_destroy_args *args); /* Mandatory callbacks. */ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create( diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c index ede2e38..7de5f04 100644 --- a/staticd/static_nb_config.c +++ b/staticd/static_nb_config.c @@ -18,6 +18,7 @@ #include "static_vrf.h" #include "static_routes.h" #include "static_nb.h" +#include "static_zebra.h" static int static_path_list_create(struct nb_cb_create_args *args) @@ -33,8 +34,8 @@ static int static_path_list_create(struct nb_cb_create_args *args) case NB_EV_VALIDATE: vrf_dnode = yang_dnode_get_parent(args->dnode, "control-plane-protocol"); - vrf = yang_dnode_get_string(vrf_dnode, "./vrf"); - table_id = yang_dnode_get_uint32(args->dnode, "./table-id"); + vrf = yang_dnode_get_string(vrf_dnode, "vrf"); + table_id = yang_dnode_get_uint32(args->dnode, "table-id"); /* * TableId is not applicable for VRF. Consider the case of @@ -55,8 +56,8 @@ static int static_path_list_create(struct nb_cb_create_args *args) break; case NB_EV_APPLY: rn = nb_running_get_entry(args->dnode, NULL, true); - distance = yang_dnode_get_uint8(args->dnode, "./distance"); - table_id = yang_dnode_get_uint32(args->dnode, "./table-id"); + distance = yang_dnode_get_uint8(args->dnode, "distance"); + table_id = yang_dnode_get_uint32(args->dnode, "table-id"); pn = static_add_path(rn, table_id, distance); nb_running_set_entry(args->dnode, pn); } @@ -111,7 +112,7 @@ static int nexthop_iter_cb(const struct lyd_node *dnode, void *arg) struct nexthop_iter *iter = arg; enum static_nh_type nh_type; - nh_type = yang_dnode_get_enum(dnode, "./nh-type"); + nh_type = yang_dnode_get_enum(dnode, "nh-type"); if (nh_type == STATIC_BLACKHOLE) iter->blackhole = true; @@ -134,9 +135,8 @@ static bool static_nexthop_create(struct nb_cb_create_args *args) switch (args->event) { case NB_EV_VALIDATE: - ifname = yang_dnode_get_string(args->dnode, "./interface"); - nh_type = yang_dnode_get_enum(args->dnode, "./nh-type"); - if (ifname != NULL && nh_type != STATIC_BLACKHOLE) { + ifname = yang_dnode_get_string(args->dnode, "interface"); + if (ifname != NULL) { if (strcasecmp(ifname, "Null0") == 0 || strcasecmp(ifname, "reject") == 0 || strcasecmp(ifname, "blackhole") == 0) { @@ -170,12 +170,15 @@ static bool static_nexthop_create(struct nb_cb_create_args *args) case NB_EV_ABORT: break; case NB_EV_APPLY: - yang_dnode_get_ip(&ipaddr, args->dnode, "./gateway"); - nh_type = yang_dnode_get_enum(args->dnode, "./nh-type"); - ifname = yang_dnode_get_string(args->dnode, "./interface"); - nh_vrf = yang_dnode_get_string(args->dnode, "./vrf"); + yang_dnode_get_ip(&ipaddr, args->dnode, "gateway"); + nh_type = yang_dnode_get_enum(args->dnode, "nh-type"); + ifname = yang_dnode_get_string(args->dnode, "interface"); + nh_vrf = yang_dnode_get_string(args->dnode, "vrf"); pn = nb_running_get_entry(args->dnode, NULL, true); + if (strmatch(ifname, "(null)")) + ifname = ""; + if (!static_add_nexthop_validate(nh_vrf, nh_type, &ipaddr)) flog_warn( EC_LIB_NB_CB_CONFIG_VALIDATE, @@ -464,33 +467,10 @@ static int static_nexthop_bh_type_modify(struct nb_cb_modify_args *args) { struct static_nexthop *nh; enum static_nh_type nh_type; - const char *nh_ifname; - const char *nh_vrf; switch (args->event) { case NB_EV_VALIDATE: nh_type = yang_dnode_get_enum(args->dnode, "../nh-type"); - nh_ifname = yang_dnode_get_string(args->dnode, "../interface"); - nh_vrf = yang_dnode_get_string(args->dnode, "../vrf"); - if (nh_ifname && nh_vrf) { - struct vrf *vrf = vrf_lookup_by_name(nh_vrf); - - if (!vrf) { - snprintf(args->errmsg, args->errmsg_len, - "nexthop vrf %s not found", nh_vrf); - return NB_ERR_VALIDATION; - } - - struct interface *ifp = if_lookup_by_name(nh_ifname, - vrf->vrf_id); - - if (ifp && (!strmatch(nh_ifname, "blackhole") || - !strmatch(nh_ifname, "reject"))) { - snprintf(args->errmsg, args->errmsg_len, - "nexthop interface name must be (reject, blackhole)"); - return NB_ERR_VALIDATION; - } - } if (nh_type != STATIC_BLACKHOLE) { snprintf(args->errmsg, args->errmsg_len, "nexthop type is not the blackhole type"); @@ -535,7 +515,7 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa const struct lyd_node *mls_dnode; uint32_t count; - mls_dnode = yang_dnode_get(args->dnode, "./mpls-label-stack"); + mls_dnode = yang_dnode_get(args->dnode, "mpls-label-stack"); count = yang_get_list_elements_count(lyd_child(mls_dnode)); if (count > MPLS_MAX_LABELS) { @@ -552,7 +532,7 @@ int routing_control_plane_protocols_name_validate( { const char *name; - name = yang_dnode_get_string(args->dnode, "./name"); + name = yang_dnode_get_string(args->dnode, "name"); if (!strmatch(name, "staticd")) { snprintf(args->errmsg, args->errmsg_len, "static routing supports only one instance with name staticd"); @@ -560,6 +540,48 @@ int routing_control_plane_protocols_name_validate( } return NB_OK; } + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol + */ +int routing_control_plane_protocols_staticd_create(struct nb_cb_create_args *args) +{ + struct static_vrf *svrf; + const char *vrf; + + vrf = yang_dnode_get_string(args->dnode, "vrf"); + svrf = static_vrf_alloc(vrf); + nb_running_set_entry(args->dnode, svrf); + + return NB_OK; +} + +int routing_control_plane_protocols_staticd_destroy( + struct nb_cb_destroy_args *args) +{ + struct static_vrf *svrf; + struct route_table *stable; + struct route_node *rn; + afi_t afi; + safi_t safi; + + svrf = nb_running_unset_entry(args->dnode); + + FOREACH_AFI_SAFI (afi, safi) { + stable = svrf->stable[afi][safi]; + if (!stable) + continue; + + for (rn = route_top(stable); rn; rn = route_next(rn)) + static_del_route(rn); + } + + static_vrf_free(svrf); + + return NB_OK; +} + /* * XPath: * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list @@ -567,8 +589,7 @@ int routing_control_plane_protocols_name_validate( int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create( struct nb_cb_create_args *args) { - struct vrf *vrf; - struct static_vrf *s_vrf; + struct static_vrf *svrf; struct route_node *rn; const struct lyd_node *vrf_dnode; struct prefix prefix; @@ -579,15 +600,15 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_cr switch (args->event) { case NB_EV_VALIDATE: - yang_dnode_get_prefix(&prefix, args->dnode, "./prefix"); - afi_safi = yang_dnode_get_string(args->dnode, "./afi-safi"); + yang_dnode_get_prefix(&prefix, args->dnode, "prefix"); + afi_safi = yang_dnode_get_string(args->dnode, "afi-safi"); yang_afi_safi_identity2value(afi_safi, &afi, &safi); prefix_afi = family2afi(prefix.family); if (afi != prefix_afi) { flog_warn( EC_LIB_NB_CB_CONFIG_VALIDATE, "route node %s creation failed", - yang_dnode_get_string(args->dnode, "./prefix")); + yang_dnode_get_string(args->dnode, "prefix")); return NB_ERR_VALIDATION; } break; @@ -597,19 +618,18 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_cr case NB_EV_APPLY: vrf_dnode = yang_dnode_get_parent(args->dnode, "control-plane-protocol"); - vrf = nb_running_get_entry(vrf_dnode, NULL, true); - s_vrf = vrf->info; + svrf = nb_running_get_entry(vrf_dnode, NULL, true); - yang_dnode_get_prefix(&prefix, args->dnode, "./prefix"); - afi_safi = yang_dnode_get_string(args->dnode, "./afi-safi"); + yang_dnode_get_prefix(&prefix, args->dnode, "prefix"); + afi_safi = yang_dnode_get_string(args->dnode, "afi-safi"); yang_afi_safi_identity2value(afi_safi, &afi, &safi); - rn = static_add_route(afi, safi, &prefix, NULL, s_vrf); - if (vrf->vrf_id == VRF_UNKNOWN) + rn = static_add_route(afi, safi, &prefix, NULL, svrf); + if (!svrf->vrf || svrf->vrf->vrf_id == VRF_UNKNOWN) snprintf( args->errmsg, args->errmsg_len, "Static Route to %s not installed currently because dependent config not fully available", - yang_dnode_get_string(args->dnode, "./prefix")); + yang_dnode_get_string(args->dnode, "prefix")); nb_running_set_entry(args->dnode, rn); break; } @@ -960,6 +980,17 @@ int route_next_hop_bfd_source_destroy(struct nb_cb_destroy_args *args) sn = nb_running_get_entry(args->dnode, NULL, true); static_next_hop_bfd_auto_source(sn); + + /* NHT information are needed by BFD to automatically find the source + * + * Force zebra to resend the information to BFD by unregistering and + * registering again NHT. The (...)/frr-nexthops/nexthop northbound + * apply_finish function will trigger a call to static_install_nexthop() + * that does a call to static_zebra_nht_register(nh, true); + * static_zebra_nht_register(sn, false); + */ + static_zebra_nht_register(sn, false); + return NB_OK; } @@ -1036,7 +1067,7 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_sr rn = nb_running_get_entry(args->dnode, NULL, true); info = route_table_get_info(rn->table); s_vrf = info->svrf; - yang_dnode_get_ipv6p(&src_prefix, args->dnode, "./src-prefix"); + yang_dnode_get_ipv6p(&src_prefix, args->dnode, "src-prefix"); afi = family2afi(src_prefix.family); src_rn = static_add_route(afi, safi, &rn->p, &src_prefix, s_vrf); diff --git a/staticd/static_nht.c b/staticd/static_nht.c index ebc5ea1..6be5984 100644 --- a/staticd/static_nht.c +++ b/staticd/static_nht.c @@ -18,8 +18,7 @@ #include "static_nht.h" static void static_nht_update_path(struct static_path *pn, struct prefix *nhp, - uint32_t nh_num, vrf_id_t nh_vrf_id, - struct vrf *vrf) + uint32_t nh_num, vrf_id_t nh_vrf_id) { struct static_nexthop *nh; @@ -49,18 +48,13 @@ static void static_nht_update_path(struct static_path *pn, struct prefix *nhp, static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp, uint32_t nh_num, afi_t afi, safi_t safi, - struct vrf *vrf, vrf_id_t nh_vrf_id) + struct static_vrf *svrf, vrf_id_t nh_vrf_id) { struct route_table *stable; - struct static_vrf *svrf; struct route_node *rn; struct static_path *pn; struct static_route_info *si; - svrf = vrf->info; - if (!svrf) - return; - stable = static_vrf_static_table(afi, safi, svrf); if (!stable) return; @@ -71,7 +65,7 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp, si = static_route_info_from_rnode(rn); frr_each(static_path_list, &si->path_list, pn) { static_nht_update_path(pn, nhp, nh_num, - nh_vrf_id, vrf); + nh_vrf_id); } route_unlock_node(rn); } @@ -83,7 +77,7 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp, if (!si) continue; frr_each(static_path_list, &si->path_list, pn) { - static_nht_update_path(pn, nhp, nh_num, nh_vrf_id, vrf); + static_nht_update_path(pn, nhp, nh_num, nh_vrf_id); } } } @@ -91,29 +85,23 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp, void static_nht_update(struct prefix *sp, struct prefix *nhp, uint32_t nh_num, afi_t afi, safi_t safi, vrf_id_t nh_vrf_id) { + struct static_vrf *svrf; - struct vrf *vrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - static_nht_update_safi(sp, nhp, nh_num, afi, safi, vrf, + RB_FOREACH (svrf, svrf_name_head, &svrfs) + static_nht_update_safi(sp, nhp, nh_num, afi, safi, svrf, nh_vrf_id); } static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi, - safi_t safi, struct vrf *vrf, + safi_t safi, struct static_vrf *svrf, vrf_id_t nh_vrf_id) { - struct static_vrf *svrf; struct route_table *stable; struct static_nexthop *nh; struct static_path *pn; struct route_node *rn; struct static_route_info *si; - svrf = vrf->info; - if (!svrf) - return; - stable = static_vrf_static_table(afi, safi, svrf); if (!stable) return; @@ -153,10 +141,10 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi, void static_nht_reset_start(struct prefix *nhp, afi_t afi, safi_t safi, vrf_id_t nh_vrf_id) { - struct vrf *vrf; + struct static_vrf *svrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - static_nht_reset_start_safi(nhp, afi, safi, vrf, nh_vrf_id); + RB_FOREACH (svrf, svrf_name_head, &svrfs) + static_nht_reset_start_safi(nhp, afi, safi, svrf, nh_vrf_id); } static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi, diff --git a/staticd/static_routes.c b/staticd/static_routes.c index 1fbbf7e..cba3818 100644 --- a/staticd/static_routes.c +++ b/staticd/static_routes.c @@ -87,11 +87,6 @@ void zebra_stable_node_cleanup(struct route_table *table, /* Install static path into rib. */ void static_install_path(struct static_path *pn) { - struct static_nexthop *nh; - - frr_each(static_nexthop_list, &pn->nexthop_list, nh) - static_zebra_nht_register(nh, true); - if (static_nexthop_list_count(&pn->nexthop_list)) static_zebra_route_add(pn, true); } @@ -245,21 +240,20 @@ void static_del_path(struct static_path *pn) XFREE(MTYPE_STATIC_PATH, pn); } -struct static_nexthop *static_add_nexthop(struct static_path *pn, - enum static_nh_type type, - struct ipaddr *ipaddr, - const char *ifname, - const char *nh_vrf, uint32_t color) +struct static_nexthop * +static_add_nexthop(struct static_path *pn, enum static_nh_type type, + struct ipaddr *ipaddr, const char *ifname, + const char *nh_vrfname, uint32_t color) { struct route_node *rn = pn->rn; struct static_nexthop *nh; - struct static_vrf *nh_svrf; + struct vrf *nh_vrf; struct interface *ifp; struct static_nexthop *cp; route_lock_node(rn); - nh_svrf = static_vrf_lookup_by_name(nh_vrf); + nh_vrf = vrf_lookup_by_name(nh_vrfname); /* Make new static route structure. */ nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop)); @@ -274,8 +268,8 @@ struct static_nexthop *static_add_nexthop(struct static_path *pn, if (nh->type == STATIC_BLACKHOLE) nh->bh_type = STATIC_BLACKHOLE_NULL; - nh->nh_vrf_id = nh_svrf ? nh_svrf->vrf->vrf_id : VRF_UNKNOWN; - strlcpy(nh->nh_vrfname, nh_vrf, sizeof(nh->nh_vrfname)); + nh->nh_vrf_id = nh_vrf ? nh_vrf->vrf_id : VRF_UNKNOWN; + strlcpy(nh->nh_vrfname, nh_vrfname, sizeof(nh->nh_vrfname)); if (ifname) strlcpy(nh->ifname, ifname, sizeof(nh->ifname)); @@ -378,6 +372,17 @@ void static_install_nexthop(struct static_nexthop *nh) } } +void static_uninstall_nexthop(struct static_nexthop *nh) +{ + struct static_path *pn = nh->pn; + + if (nh->nh_vrf_id == VRF_UNKNOWN) + return; + + static_zebra_nht_register(nh, false); + static_uninstall_path(pn); +} + void static_delete_nexthop(struct static_nexthop *nh) { struct static_path *pn = nh->pn; @@ -387,17 +392,8 @@ void static_delete_nexthop(struct static_nexthop *nh) /* Remove BFD session/configuration if any. */ bfd_sess_free(&nh->bsp); - if (nh->nh_vrf_id == VRF_UNKNOWN) - goto EXIT; - - static_zebra_nht_register(nh, false); - /* - * If we have other si nodes then route replace - * else delete the route - */ - static_uninstall_path(pn); + static_uninstall_nexthop(nh); -EXIT: route_unlock_node(rn); /* Free static route configuration. */ XFREE(MTYPE_STATIC_NEXTHOP, nh); @@ -437,14 +433,10 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi, struct route_node *rn; struct static_nexthop *nh; struct static_path *pn; - struct vrf *vrf; + struct static_vrf *svrf; struct static_route_info *si; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - struct static_vrf *svrf; - - svrf = vrf->info; - + RB_FOREACH (svrf, svrf_name_head, &svrfs) { stable = static_vrf_static_table(afi, safi, svrf); if (!stable) continue; @@ -476,8 +468,8 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi, * afi -> The afi to look at * safi -> the safi to look at */ -static void static_fixup_vrf(struct static_vrf *svrf, - struct route_table *stable, afi_t afi, safi_t safi) +static void static_fixup_vrf(struct vrf *vrf, struct route_table *stable, + afi_t afi, safi_t safi) { struct route_node *rn; struct static_nexthop *nh; @@ -491,13 +483,11 @@ static void static_fixup_vrf(struct static_vrf *svrf, continue; frr_each(static_path_list, &si->path_list, pn) { frr_each(static_nexthop_list, &pn->nexthop_list, nh) { - if (strcmp(svrf->vrf->name, nh->nh_vrfname) - != 0) + if (strcmp(vrf->name, nh->nh_vrfname) != 0) continue; - nh->nh_vrf_id = svrf->vrf->vrf_id; - nh->nh_registered = false; - if (nh->ifindex) { + nh->nh_vrf_id = vrf->vrf_id; + if (nh->ifname[0]) { ifp = if_lookup_by_name(nh->ifname, nh->nh_vrf_id); if (ifp) @@ -506,7 +496,7 @@ static void static_fixup_vrf(struct static_vrf *svrf, continue; } - static_install_path(pn); + static_install_nexthop(nh); } } } @@ -521,13 +511,9 @@ static void static_fixup_vrf(struct static_vrf *svrf, * afi -> the afi in question * safi -> the safi in question */ -static void static_enable_vrf(struct static_vrf *svrf, - struct route_table *stable, afi_t afi, - safi_t safi) +static void static_enable_vrf(struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_nexthop *nh; - struct interface *ifp; struct static_path *pn; struct static_route_info *si; @@ -535,21 +521,8 @@ static void static_enable_vrf(struct static_vrf *svrf, si = static_route_info_from_rnode(rn); if (!si) continue; - frr_each(static_path_list, &si->path_list, pn) { - frr_each(static_nexthop_list, &pn->nexthop_list, nh) { - if (nh->ifindex) { - ifp = if_lookup_by_name(nh->ifname, - nh->nh_vrf_id); - if (ifp) - nh->ifindex = ifp->ifindex; - else - continue; - } - if (nh->nh_vrf_id == VRF_UNKNOWN) - continue; - static_install_path(pn); - } - } + frr_each(static_path_list, &si->path_list, pn) + static_install_path(pn); } } @@ -560,27 +533,26 @@ static void static_enable_vrf(struct static_vrf *svrf, * * enable_svrf -> the vrf being enabled */ -void static_fixup_vrf_ids(struct static_vrf *enable_svrf) +void static_fixup_vrf_ids(struct vrf *vrf) { struct route_table *stable; - struct vrf *vrf; + struct static_vrf *svrf, *enable_svrf; afi_t afi; safi_t safi; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - struct static_vrf *svrf; + enable_svrf = vrf->info; - svrf = vrf->info; + RB_FOREACH (svrf, svrf_name_head, &svrfs) { /* Install any static routes configured for this VRF. */ FOREACH_AFI_SAFI (afi, safi) { stable = svrf->stable[afi][safi]; if (!stable) continue; - static_fixup_vrf(enable_svrf, stable, afi, safi); + static_fixup_vrf(vrf, stable, afi, safi); if (enable_svrf == svrf) - static_enable_vrf(svrf, stable, afi, safi); + static_enable_vrf(stable, afi, safi); } } } @@ -595,8 +567,7 @@ void static_fixup_vrf_ids(struct static_vrf *enable_svrf) * afi -> the afi in question * safi -> the safi in question */ -static void static_cleanup_vrf(struct static_vrf *svrf, - struct route_table *stable, +static void static_cleanup_vrf(struct vrf *vrf, struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; @@ -610,11 +581,13 @@ static void static_cleanup_vrf(struct static_vrf *svrf, continue; frr_each(static_path_list, &si->path_list, pn) { frr_each(static_nexthop_list, &pn->nexthop_list, nh) { - if (strcmp(svrf->vrf->name, nh->nh_vrfname) - != 0) + if (strcmp(vrf->name, nh->nh_vrfname) != 0) continue; - static_uninstall_path(pn); + static_uninstall_nexthop(nh); + + nh->nh_vrf_id = VRF_UNKNOWN; + nh->ifindex = IFINDEX_INTERNAL; } } } @@ -632,7 +605,6 @@ static void static_disable_vrf(struct route_table *stable, afi_t afi, safi_t safi) { struct route_node *rn; - struct static_nexthop *nh; struct static_path *pn; struct static_route_info *si; @@ -640,11 +612,8 @@ static void static_disable_vrf(struct route_table *stable, si = static_route_info_from_rnode(rn); if (!si) continue; - frr_each(static_path_list, &si->path_list, pn) { - frr_each(static_nexthop_list, &pn->nexthop_list, nh) { - static_uninstall_path(pn); - } - } + frr_each(static_path_list, &si->path_list, pn) + static_uninstall_path(pn); } } @@ -656,26 +625,23 @@ static void static_disable_vrf(struct route_table *stable, * * disable_svrf - The vrf being disabled */ -void static_cleanup_vrf_ids(struct static_vrf *disable_svrf) +void static_cleanup_vrf_ids(struct vrf *vrf) { - struct vrf *vrf; + struct route_table *stable; + struct static_vrf *svrf, *disable_svrf; afi_t afi; safi_t safi; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - struct static_vrf *svrf; - - svrf = vrf->info; + disable_svrf = vrf->info; + RB_FOREACH (svrf, svrf_name_head, &svrfs) { /* Uninstall any static routes configured for this VRF. */ FOREACH_AFI_SAFI (afi, safi) { - struct route_table *stable; - stable = svrf->stable[afi][safi]; if (!stable) continue; - static_cleanup_vrf(disable_svrf, stable, afi, safi); + static_cleanup_vrf(vrf, stable, afi, safi); if (disable_svrf == svrf) static_disable_vrf(stable, afi, safi); @@ -683,71 +649,6 @@ void static_cleanup_vrf_ids(struct static_vrf *disable_svrf) } } -/* - * This function enables static routes when an interface it relies - * on in a different vrf is coming up. - * - * stable -> The stable we are looking at. - * ifp -> interface coming up - * afi -> the afi in question - * safi -> the safi in question - */ -static void static_fixup_intf_nh(struct route_table *stable, - struct interface *ifp, - afi_t afi, safi_t safi) -{ - struct route_node *rn; - struct static_nexthop *nh; - struct static_path *pn; - struct static_route_info *si; - - for (rn = route_top(stable); rn; rn = route_next(rn)) { - si = static_route_info_from_rnode(rn); - if (!si) - continue; - frr_each(static_path_list, &si->path_list, pn) { - frr_each(static_nexthop_list, &pn->nexthop_list, nh) { - if (nh->nh_vrf_id != ifp->vrf->vrf_id) - continue; - - if (nh->ifindex != ifp->ifindex) - continue; - - static_install_path(pn); - } - } - } -} - -/* - * This function enables static routes that rely on an interface in - * a different vrf when that interface comes up. - */ -void static_install_intf_nh(struct interface *ifp) -{ - struct route_table *stable; - struct vrf *vrf; - afi_t afi; - safi_t safi; - - RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) { - struct static_vrf *svrf = vrf->info; - - /* Not needed if same vrf since happens naturally */ - if (vrf->vrf_id == ifp->vrf->vrf_id) - continue; - - /* Install any static routes configured for this interface. */ - FOREACH_AFI_SAFI (afi, safi) { - stable = svrf->stable[afi][safi]; - if (!stable) - continue; - - static_fixup_intf_nh(stable, ifp, afi, safi); - } - } -} - /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */ void static_ifindex_update(struct interface *ifp, bool up) { diff --git a/staticd/static_routes.h b/staticd/static_routes.h index 548148b..2e2e498 100644 --- a/staticd/static_routes.h +++ b/staticd/static_routes.h @@ -131,7 +131,7 @@ struct static_nexthop { bool nh_registered; bool nh_valid; - char ifname[INTERFACE_NAMSIZ + 1]; + char ifname[IFNAMSIZ + 1]; /* Label information */ struct static_nh_label snh_label; @@ -199,20 +199,18 @@ extern uint32_t zebra_ecmp_count; extern struct zebra_privs_t static_privs; -void static_fixup_vrf_ids(struct static_vrf *svrf); +extern void static_fixup_vrf_ids(struct vrf *vrf); +extern void static_cleanup_vrf_ids(struct vrf *vrf); extern struct static_nexthop * static_add_nexthop(struct static_path *pn, enum static_nh_type type, struct ipaddr *ipaddr, const char *ifname, const char *nh_vrf, uint32_t color); extern void static_install_nexthop(struct static_nexthop *nh); +extern void static_uninstall_nexthop(struct static_nexthop *nh); extern void static_delete_nexthop(struct static_nexthop *nh); -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_path(struct static_path *pn); @@ -239,7 +237,7 @@ extern void zebra_stable_node_cleanup(struct route_table *table, * Max string return via API static_get_nh_str in size_t */ -#define NEXTHOP_STR (INET6_ADDRSTRLEN + INTERFACE_NAMSIZ + 25) +#define NEXTHOP_STR (INET6_ADDRSTRLEN + IFNAMSIZ + 25) /* * For the given nexthop, returns the string * nexthop : returns the formatted string in nexthop diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index a67dce2..710827a 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -18,16 +18,37 @@ DEFINE_MTYPE_STATIC(STATIC, STATIC_RTABLE_INFO, "Static Route Table Info"); -static struct static_vrf *static_vrf_alloc(void) +static int svrf_name_compare(const struct static_vrf *a, + const struct static_vrf *b) +{ + return strcmp(a->name, b->name); +} + +RB_GENERATE(svrf_name_head, static_vrf, entry, svrf_name_compare); + +struct svrf_name_head svrfs = RB_INITIALIZER(&svrfs); + +static struct static_vrf *static_vrf_lookup_by_name(const char *name) +{ + struct static_vrf svrf; + + strlcpy(svrf.name, name, sizeof(svrf.name)); + return RB_FIND(svrf_name_head, &svrfs, &svrf); +} + +struct static_vrf *static_vrf_alloc(const char *name) { struct route_table *table; struct static_vrf *svrf; struct stable_info *info; + struct vrf *vrf; safi_t safi; afi_t afi; svrf = XCALLOC(MTYPE_STATIC_RTABLE_INFO, sizeof(struct static_vrf)); + strlcpy(svrf->name, name, sizeof(svrf->name)); + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { if (afi == AFI_IP6) @@ -46,16 +67,56 @@ static struct static_vrf *static_vrf_alloc(void) svrf->stable[afi][safi] = table; } } + + RB_INSERT(svrf_name_head, &svrfs, svrf); + + vrf = vrf_lookup_by_name(name); + if (vrf) { + svrf->vrf = vrf; + vrf->info = svrf; + } + return svrf; } +void static_vrf_free(struct static_vrf *svrf) +{ + struct route_table *table; + struct vrf *vrf; + safi_t safi; + afi_t afi; + void *info; + + vrf = svrf->vrf; + if (vrf) { + vrf->info = NULL; + svrf->vrf = NULL; + } + + RB_REMOVE(svrf_name_head, &svrfs, svrf); + + 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_STATIC_RTABLE_INFO, info); + svrf->stable[afi][safi] = NULL; + } + } + + XFREE(MTYPE_STATIC_RTABLE_INFO, svrf); +} + static int static_vrf_new(struct vrf *vrf) { struct static_vrf *svrf; - svrf = static_vrf_alloc(); - vrf->info = svrf; - svrf->vrf = vrf; + svrf = static_vrf_lookup_by_name(vrf->name); + if (svrf) { + vrf->info = svrf; + svrf->vrf = vrf; + } return 0; } @@ -63,37 +124,27 @@ static int static_vrf_new(struct vrf *vrf) static int static_vrf_enable(struct vrf *vrf) { static_zebra_vrf_register(vrf); - - static_fixup_vrf_ids(vrf->info); - + static_fixup_vrf_ids(vrf); return 0; } static int static_vrf_disable(struct vrf *vrf) { + static_cleanup_vrf_ids(vrf); static_zebra_vrf_unregister(vrf); return 0; } static int static_vrf_delete(struct vrf *vrf) { - struct route_table *table; 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_STATIC_RTABLE_INFO, info); - svrf->stable[afi][safi] = NULL; - } + if (svrf) { + svrf->vrf = NULL; + vrf->info = NULL; } - XFREE(MTYPE_STATIC_RTABLE_INFO, svrf); + return 0; } @@ -110,43 +161,20 @@ struct route_table *static_vrf_static_table(afi_t afi, safi_t safi, return svrf->stable[afi][safi]; } -struct static_vrf *static_vrf_lookup_by_name(const char *name) -{ - struct vrf *vrf; - - if (!name) - name = VRF_DEFAULT_NAME; - - vrf = vrf_lookup_by_name(name); - if (vrf) - return ((struct static_vrf *)vrf->info); - - return NULL; -} - -static int static_vrf_config_write(struct vty *vty) -{ - struct lyd_node *dnode; - int written = 0; - - dnode = yang_dnode_get(running_config->dnode, "/frr-routing:routing"); - if (dnode) { - nb_cli_show_dnode_cmds(vty, dnode, false); - written = 1; - } - - return written; -} - void static_vrf_init(void) { vrf_init(static_vrf_new, static_vrf_enable, static_vrf_disable, static_vrf_delete); - vrf_cmd_init(static_vrf_config_write); + vrf_cmd_init(NULL); } void static_vrf_terminate(void) { + struct static_vrf *svrf, *svrf_next; + + RB_FOREACH_SAFE (svrf, svrf_name_head, &svrfs, svrf_next) + static_vrf_free(svrf); + vrf_terminate(); } diff --git a/staticd/static_vrf.h b/staticd/static_vrf.h index 8f55775..26ee28f 100644 --- a/staticd/static_vrf.h +++ b/staticd/static_vrf.h @@ -7,15 +7,27 @@ #ifndef __STATIC_VRF_H__ #define __STATIC_VRF_H__ +#include "openbsd-tree.h" + #ifdef __cplusplus extern "C" { #endif struct static_vrf { + RB_ENTRY(static_vrf) entry; + + char name[VRF_NAMSIZ + 1]; struct vrf *vrf; struct route_table *stable[AFI_MAX][SAFI_MAX]; }; +RB_HEAD(svrf_name_head, static_vrf); +RB_PROTOTYPE(svrf_name_head, static_vrf, entry, svrf_name_compare) + +extern struct svrf_name_head svrfs; + +struct static_vrf *static_vrf_alloc(const char *name); +void static_vrf_free(struct static_vrf *svrf); struct stable_info { struct static_vrf *svrf; @@ -25,8 +37,6 @@ struct stable_info { #define GET_STABLE_VRF_ID(info) info->svrf->vrf->vrf_id -struct static_vrf *static_vrf_lookup_by_name(const char *vrf_name); - void static_vrf_init(void); struct route_table *static_vrf_static_table(afi_t afi, safi_t safi, diff --git a/staticd/static_vty.c b/staticd/static_vty.c index e94acba..a18028e 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -19,6 +19,7 @@ #include "libfrr.h" #include "routing_nb.h" #include "northbound_cli.h" +#include "frrdistance.h" #include "static_vrf.h" #include "static_vty.h" @@ -59,8 +60,6 @@ struct static_route_args { bool bfd_multi_hop; const char *bfd_source; const char *bfd_profile; - - const char *input; }; static int static_route_nb_run(struct vty *vty, struct static_route_args *args) @@ -100,7 +99,7 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args) return CMD_WARNING_CONFIG_FAILED; } - args->vrf = yang_dnode_get_string(vrf_dnode, "./name"); + args->vrf = yang_dnode_get_string(vrf_dnode, "name"); } else { if (args->vrf == NULL) args->vrf = VRF_DEFAULT_NAME; @@ -152,20 +151,9 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args) else buf_gate_str = ""; - if (args->gateway == NULL && args->interface_name == NULL) { + if (args->gateway == NULL && args->interface_name == NULL) type = STATIC_BLACKHOLE; - /* If this is blackhole/reject flagged route, then - * specify interface_name with the value of what was really - * entered. - * interface_name will be validated later in NB functions - * to check if we don't create blackhole/reject routes that - * match the real interface names. - * E.g.: `ip route 10.0.0.1/32 bla` will create a blackhole - * route despite the real interface named `bla` exists. - */ - if (args->input) - args->interface_name = args->input; - } else if (args->gateway && args->interface_name) { + else if (args->gateway && args->interface_name) { if (args->afi == AFI_IP) type = STATIC_IPV4_GATEWAY_IFNAME; else @@ -552,8 +540,6 @@ DEFPY_YANG(ip_route_blackhole, "Table to configure\n" "The table number to configure\n") { - int idx_flag = 0; - struct static_route_args args = { .delete = !!no, .afi = AFI_IP, @@ -568,9 +554,6 @@ DEFPY_YANG(ip_route_blackhole, .vrf = vrf, }; - if (flag && argv_find(argv, argc, flag, &idx_flag)) - args.input = argv[idx_flag]->arg; - return static_route_nb_run(vty, &args); } @@ -599,8 +582,6 @@ DEFPY_YANG(ip_route_blackhole_vrf, "Table to configure\n" "The table number to configure\n") { - int idx_flag = 0; - struct static_route_args args = { .delete = !!no, .afi = AFI_IP, @@ -622,9 +603,6 @@ DEFPY_YANG(ip_route_blackhole_vrf, */ assert(args.prefix); - if (flag && argv_find(argv, argc, flag, &idx_flag)) - args.input = argv[idx_flag]->arg; - return static_route_nb_run(vty, &args); } @@ -915,8 +893,6 @@ DEFPY_YANG(ipv6_route_blackhole, "Table to configure\n" "The table number to configure\n") { - int idx_flag = 0; - struct static_route_args args = { .delete = !!no, .afi = AFI_IP6, @@ -931,9 +907,6 @@ DEFPY_YANG(ipv6_route_blackhole, .vrf = vrf, }; - if (flag && argv_find(argv, argc, flag, &idx_flag)) - args.input = argv[idx_flag]->arg; - return static_route_nb_run(vty, &args); } @@ -962,8 +935,6 @@ DEFPY_YANG(ipv6_route_blackhole_vrf, "Table to configure\n" "The table number to configure\n") { - int idx_flag = 0; - struct static_route_args args = { .delete = !!no, .afi = AFI_IP6, @@ -985,9 +956,6 @@ DEFPY_YANG(ipv6_route_blackhole_vrf, */ assert(args.prefix); - if (flag && argv_find(argv, argc, flag, &idx_flag)) - args.input = argv[idx_flag]->arg; - return static_route_nb_run(vty, &args); } @@ -1233,8 +1201,10 @@ DEFPY_YANG(ipv6_route_vrf, ipv6_route_vrf_cmd, return static_route_nb_run(vty, &args); } -void static_cli_show(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults) +#ifdef INCLUDE_MGMTD_CMDDEFS_ONLY + +static void static_cli_show(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) { const char *vrf; @@ -1243,7 +1213,7 @@ void static_cli_show(struct vty *vty, const struct lyd_node *dnode, vty_out(vty, "vrf %s\n", vrf); } -void static_cli_show_end(struct vty *vty, const struct lyd_node *dnode) +static void static_cli_show_end(struct vty *vty, const struct lyd_node *dnode) { const char *vrf; @@ -1261,13 +1231,13 @@ static int mpls_label_iter_cb(const struct lyd_node *dnode, void *arg) { struct mpls_label_iter *iter = arg; - if (yang_dnode_exists(dnode, "./label")) { + if (yang_dnode_exists(dnode, "label")) { if (iter->first) vty_out(iter->vty, " label %s", - yang_dnode_get_string(dnode, "./label")); + yang_dnode_get_string(dnode, "label")); else vty_out(iter->vty, "/%s", - yang_dnode_get_string(dnode, "./label")); + yang_dnode_get_string(dnode, "label")); iter->first = false; } @@ -1285,16 +1255,16 @@ static int srv6_seg_iter_cb(const struct lyd_node *dnode, void *arg) char buffer[INET6_ADDRSTRLEN]; struct in6_addr cli_seg; - if (yang_dnode_exists(dnode, "./seg")) { + if (yang_dnode_exists(dnode, "seg")) { if (iter->first) { - yang_dnode_get_ipv6(&cli_seg, dnode, "./seg"); + yang_dnode_get_ipv6(&cli_seg, dnode, "seg"); if (inet_ntop(AF_INET6, &cli_seg, buffer, INET6_ADDRSTRLEN) == NULL) { return 1; } vty_out(iter->vty, " segments %s", buffer); } else { - yang_dnode_get_ipv6(&cli_seg, dnode, "./seg"); + yang_dnode_get_ipv6(&cli_seg, dnode, "seg"); if (inet_ntop(AF_INET6, &cli_seg, buffer, INET6_ADDRSTRLEN) == NULL) { return 1; @@ -1328,7 +1298,7 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route, vrf = yang_dnode_get_string(route, "../../vrf"); - afi_safi = yang_dnode_get_string(route, "./afi-safi"); + afi_safi = yang_dnode_get_string(route, "afi-safi"); yang_afi_safi_identity2value(afi_safi, &afi, &safi); if (afi == AFI_IP) @@ -1343,32 +1313,32 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route, else vty_out(vty, " mroute"); - vty_out(vty, " %s", yang_dnode_get_string(route, "./prefix")); + vty_out(vty, " %s", yang_dnode_get_string(route, "prefix")); if (src) vty_out(vty, " from %s", - yang_dnode_get_string(src, "./src-prefix")); + yang_dnode_get_string(src, "src-prefix")); - nh_type = yang_dnode_get_enum(nexthop, "./nh-type"); + nh_type = yang_dnode_get_enum(nexthop, "nh-type"); switch (nh_type) { case STATIC_IFNAME: vty_out(vty, " %s", - yang_dnode_get_string(nexthop, "./interface")); + yang_dnode_get_string(nexthop, "interface")); break; case STATIC_IPV4_GATEWAY: case STATIC_IPV6_GATEWAY: vty_out(vty, " %s", - yang_dnode_get_string(nexthop, "./gateway")); + yang_dnode_get_string(nexthop, "gateway")); break; case STATIC_IPV4_GATEWAY_IFNAME: case STATIC_IPV6_GATEWAY_IFNAME: vty_out(vty, " %s", - yang_dnode_get_string(nexthop, "./gateway")); + yang_dnode_get_string(nexthop, "gateway")); vty_out(vty, " %s", - yang_dnode_get_string(nexthop, "./interface")); + yang_dnode_get_string(nexthop, "interface")); break; case STATIC_BLACKHOLE: - bh_type = yang_dnode_get_enum(nexthop, "./bh-type"); + bh_type = yang_dnode_get_enum(nexthop, "bh-type"); switch (bh_type) { case STATIC_BLACKHOLE_DROP: vty_out(vty, " blackhole"); @@ -1383,13 +1353,13 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route, break; } - if (yang_dnode_exists(path, "./tag")) { - tag = yang_dnode_get_uint32(path, "./tag"); + if (yang_dnode_exists(path, "tag")) { + tag = yang_dnode_get_uint32(path, "tag"); if (tag != 0 || show_defaults) vty_out(vty, " tag %" PRIu32, tag); } - distance = yang_dnode_get_uint8(path, "./distance"); + distance = yang_dnode_get_uint8(path, "distance"); if (distance != ZEBRA_STATIC_DISTANCE_DEFAULT || show_defaults) vty_out(vty, " %" PRIu8, distance); @@ -1403,48 +1373,49 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route, yang_dnode_iterate(srv6_seg_iter_cb, &seg_iter, nexthop, "./srv6-segs-stack/entry"); - nexthop_vrf = yang_dnode_get_string(nexthop, "./vrf"); + nexthop_vrf = yang_dnode_get_string(nexthop, "vrf"); if (strcmp(vrf, nexthop_vrf)) vty_out(vty, " nexthop-vrf %s", nexthop_vrf); - table_id = yang_dnode_get_uint32(path, "./table-id"); + table_id = yang_dnode_get_uint32(path, "table-id"); if (table_id || show_defaults) vty_out(vty, " table %" PRIu32, table_id); - if (yang_dnode_exists(nexthop, "./onlink")) { - onlink = yang_dnode_get_bool(nexthop, "./onlink"); + if (yang_dnode_exists(nexthop, "onlink")) { + onlink = yang_dnode_get_bool(nexthop, "onlink"); if (onlink) vty_out(vty, " onlink"); } - if (yang_dnode_exists(nexthop, "./srte-color")) + if (yang_dnode_exists(nexthop, "srte-color")) vty_out(vty, " color %s", - yang_dnode_get_string(nexthop, "./srte-color")); + yang_dnode_get_string(nexthop, "srte-color")); - if (yang_dnode_exists(nexthop, "./bfd-monitoring")) { + if (yang_dnode_exists(nexthop, "bfd-monitoring")) { const struct lyd_node *bfd_dnode = - yang_dnode_get(nexthop, "./bfd-monitoring"); + yang_dnode_get(nexthop, "bfd-monitoring"); - if (yang_dnode_get_bool(bfd_dnode, "./multi-hop")) { + if (yang_dnode_get_bool(bfd_dnode, "multi-hop")) { vty_out(vty, " bfd multi-hop"); - if (yang_dnode_exists(bfd_dnode, "./source")) + if (yang_dnode_exists(bfd_dnode, "source")) vty_out(vty, " source %s", yang_dnode_get_string(bfd_dnode, "./source")); } else vty_out(vty, " bfd"); - if (yang_dnode_exists(bfd_dnode, "./profile")) + if (yang_dnode_exists(bfd_dnode, "profile")) vty_out(vty, " profile %s", - yang_dnode_get_string(bfd_dnode, "./profile")); + yang_dnode_get_string(bfd_dnode, "profile")); } vty_out(vty, "\n"); } -void static_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults) +static void static_nexthop_cli_show(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) { const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list"); const struct lyd_node *route = @@ -1453,8 +1424,9 @@ void static_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode, nexthop_cli_show(vty, route, NULL, path, dnode, show_defaults); } -void static_src_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults) +static void static_src_nexthop_cli_show(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) { const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list"); const struct lyd_node *src = yang_dnode_get_parent(path, "src-list"); @@ -1463,16 +1435,16 @@ void static_src_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode, nexthop_cli_show(vty, route, src, path, dnode, show_defaults); } -int static_nexthop_cli_cmp(const struct lyd_node *dnode1, - const struct lyd_node *dnode2) +static int static_nexthop_cli_cmp(const struct lyd_node *dnode1, + const struct lyd_node *dnode2) { enum static_nh_type nh_type1, nh_type2; struct prefix prefix1, prefix2; const char *vrf1, *vrf2; int ret = 0; - nh_type1 = yang_dnode_get_enum(dnode1, "./nh-type"); - nh_type2 = yang_dnode_get_enum(dnode2, "./nh-type"); + nh_type1 = yang_dnode_get_enum(dnode1, "nh-type"); + nh_type2 = yang_dnode_get_enum(dnode2, "nh-type"); if (nh_type1 != nh_type2) return (int)nh_type1 - (int)nh_type2; @@ -1480,24 +1452,24 @@ int static_nexthop_cli_cmp(const struct lyd_node *dnode1, switch (nh_type1) { case STATIC_IFNAME: ret = if_cmp_name_func( - yang_dnode_get_string(dnode1, "./interface"), - yang_dnode_get_string(dnode2, "./interface")); + yang_dnode_get_string(dnode1, "interface"), + yang_dnode_get_string(dnode2, "interface")); break; case STATIC_IPV4_GATEWAY: case STATIC_IPV6_GATEWAY: - yang_dnode_get_prefix(&prefix1, dnode1, "./gateway"); - yang_dnode_get_prefix(&prefix2, dnode2, "./gateway"); + yang_dnode_get_prefix(&prefix1, dnode1, "gateway"); + yang_dnode_get_prefix(&prefix2, dnode2, "gateway"); ret = prefix_cmp(&prefix1, &prefix2); break; case STATIC_IPV4_GATEWAY_IFNAME: case STATIC_IPV6_GATEWAY_IFNAME: - yang_dnode_get_prefix(&prefix1, dnode1, "./gateway"); - yang_dnode_get_prefix(&prefix2, dnode2, "./gateway"); + yang_dnode_get_prefix(&prefix1, dnode1, "gateway"); + yang_dnode_get_prefix(&prefix2, dnode2, "gateway"); ret = prefix_cmp(&prefix1, &prefix2); if (!ret) ret = if_cmp_name_func( - yang_dnode_get_string(dnode1, "./interface"), - yang_dnode_get_string(dnode2, "./interface")); + yang_dnode_get_string(dnode1, "interface"), + yang_dnode_get_string(dnode2, "interface")); break; case STATIC_BLACKHOLE: /* There's only one blackhole nexthop per route */ @@ -1508,28 +1480,28 @@ int static_nexthop_cli_cmp(const struct lyd_node *dnode1, if (ret) return ret; - vrf1 = yang_dnode_get_string(dnode1, "./vrf"); + vrf1 = yang_dnode_get_string(dnode1, "vrf"); if (strmatch(vrf1, "default")) vrf1 = ""; - vrf2 = yang_dnode_get_string(dnode2, "./vrf"); + vrf2 = yang_dnode_get_string(dnode2, "vrf"); if (strmatch(vrf2, "default")) vrf2 = ""; return if_cmp_name_func(vrf1, vrf2); } -int static_route_list_cli_cmp(const struct lyd_node *dnode1, - const struct lyd_node *dnode2) +static int static_route_list_cli_cmp(const struct lyd_node *dnode1, + const struct lyd_node *dnode2) { const char *afi_safi1, *afi_safi2; afi_t afi1, afi2; safi_t safi1, safi2; struct prefix prefix1, prefix2; - afi_safi1 = yang_dnode_get_string(dnode1, "./afi-safi"); + afi_safi1 = yang_dnode_get_string(dnode1, "afi-safi"); yang_afi_safi_identity2value(afi_safi1, &afi1, &safi1); - afi_safi2 = yang_dnode_get_string(dnode2, "./afi-safi"); + afi_safi2 = yang_dnode_get_string(dnode2, "afi-safi"); yang_afi_safi_identity2value(afi_safi2, &afi2, &safi2); if (afi1 != afi2) @@ -1538,42 +1510,97 @@ int static_route_list_cli_cmp(const struct lyd_node *dnode1, if (safi1 != safi2) return (int)safi1 - (int)safi2; - yang_dnode_get_prefix(&prefix1, dnode1, "./prefix"); - yang_dnode_get_prefix(&prefix2, dnode2, "./prefix"); + yang_dnode_get_prefix(&prefix1, dnode1, "prefix"); + yang_dnode_get_prefix(&prefix2, dnode2, "prefix"); return prefix_cmp(&prefix1, &prefix2); } -int static_src_list_cli_cmp(const struct lyd_node *dnode1, - const struct lyd_node *dnode2) +static int static_src_list_cli_cmp(const struct lyd_node *dnode1, + const struct lyd_node *dnode2) { struct prefix prefix1, prefix2; - yang_dnode_get_prefix(&prefix1, dnode1, "./src-prefix"); - yang_dnode_get_prefix(&prefix2, dnode2, "./src-prefix"); + yang_dnode_get_prefix(&prefix1, dnode1, "src-prefix"); + yang_dnode_get_prefix(&prefix2, dnode2, "src-prefix"); return prefix_cmp(&prefix1, &prefix2); } -int static_path_list_cli_cmp(const struct lyd_node *dnode1, - const struct lyd_node *dnode2) +static int static_path_list_cli_cmp(const struct lyd_node *dnode1, + const struct lyd_node *dnode2) { uint32_t table_id1, table_id2; uint8_t distance1, distance2; - table_id1 = yang_dnode_get_uint32(dnode1, "./table-id"); - table_id2 = yang_dnode_get_uint32(dnode2, "./table-id"); + table_id1 = yang_dnode_get_uint32(dnode1, "table-id"); + table_id2 = yang_dnode_get_uint32(dnode2, "table-id"); if (table_id1 != table_id2) return (int)table_id1 - (int)table_id2; - distance1 = yang_dnode_get_uint8(dnode1, "./distance"); - distance2 = yang_dnode_get_uint8(dnode2, "./distance"); + distance1 = yang_dnode_get_uint8(dnode1, "distance"); + distance2 = yang_dnode_get_uint8(dnode2, "distance"); return (int)distance1 - (int)distance2; } -#ifndef INCLUDE_MGMTD_CMDDEFS_ONLY +const struct frr_yang_module_info frr_staticd_cli_info = { + .name = "frr-staticd", + .ignore_cfg_cbs = true, + .nodes = { + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd", + .cbs = { + .cli_show = static_cli_show, + .cli_show_end = static_cli_show_end, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list", + .cbs = { + .cli_cmp = static_route_list_cli_cmp, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list", + .cbs = { + .cli_cmp = static_path_list_cli_cmp, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop", + .cbs = { + .cli_show = static_nexthop_cli_show, + .cli_cmp = static_nexthop_cli_cmp, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list", + .cbs = { + .cli_cmp = static_src_list_cli_cmp, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list", + .cbs = { + .cli_cmp = static_path_list_cli_cmp, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop", + .cbs = { + .cli_show = static_src_nexthop_cli_show, + .cli_cmp = static_nexthop_cli_cmp, + } + }, + { + .xpath = NULL, + }, + } +}; + +#else /* ifdef INCLUDE_MGMTD_CMDDEFS_ONLY */ DEFPY_YANG(debug_staticd, debug_staticd_cmd, "[no] debug static [{events$events|route$route|bfd$bfd}]", @@ -1636,8 +1663,7 @@ void static_vty_init(void) install_element(CONFIG_NODE, &debug_staticd_cmd); install_element(ENABLE_NODE, &show_debugging_static_cmd); install_element(ENABLE_NODE, &staticd_show_bfd_routes_cmd); -#endif /* ifndef INCLUDE_MGMTD_CMDDEFS_ONLY */ - +#else /* else INCLUDE_MGMTD_CMDDEFS_ONLY */ install_element(CONFIG_NODE, &ip_mroute_dist_cmd); install_element(CONFIG_NODE, &ip_route_blackhole_cmd); @@ -1653,6 +1679,9 @@ void static_vty_init(void) install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd); install_element(CONFIG_NODE, &ipv6_route_cmd); install_element(VRF_NODE, &ipv6_route_vrf_cmd); +#endif /* ifndef INCLUDE_MGMTD_CMDDEFS_ONLY */ +#ifndef INCLUDE_MGMTD_CMDDEFS_ONLY mgmt_be_client_lib_vty_init(); +#endif } diff --git a/staticd/static_vty.h b/staticd/static_vty.h index 77e52b5..4b4cc1c 100644 --- a/staticd/static_vty.h +++ b/staticd/static_vty.h @@ -11,22 +11,6 @@ extern "C" { #endif -void static_cli_show(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults); -void static_cli_show_end(struct vty *vty, const struct lyd_node *dnode); -void static_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults); -void static_src_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults); -int static_nexthop_cli_cmp(const struct lyd_node *dnode1, - const struct lyd_node *dnode2); -int static_route_list_cli_cmp(const struct lyd_node *dnode1, - const struct lyd_node *dnode2); -int static_src_list_cli_cmp(const struct lyd_node *dnode1, - const struct lyd_node *dnode2); -int static_path_list_cli_cmp(const struct lyd_node *dnode1, - const struct lyd_node *dnode2); - void static_vty_init(void); #ifdef __cplusplus diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 6abbdad..c4efc14 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -111,8 +111,6 @@ static int interface_address_delete(ZAPI_CALLBACK_ARGS) static int static_ifp_up(struct interface *ifp) { - /* Install any static reliant on this interface coming up */ - static_install_intf_nh(ifp); static_ifindex_update(ifp, true); return 0; @@ -166,9 +164,14 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS) static void zebra_connected(struct zclient *zclient) { + struct vrf *vrf; + + zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST, zclient, true); zclient_send_reg_requests(zclient, VRF_DEFAULT); - static_fixup_vrf_ids(vrf_info_lookup(VRF_DEFAULT)); + vrf = vrf_lookup_by_id(VRF_DEFAULT); + assert(vrf); + static_fixup_vrf_ids(vrf); } /* API to check whether the configured nexthop address is @@ -186,48 +189,40 @@ static_nexthop_is_local(vrf_id_t vrfid, struct prefix *addr, int family) } return false; } -static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS) + +static void static_zebra_nexthop_update(struct vrf *vrf, struct prefix *matched, + struct zapi_route *nhr) { struct static_nht_data *nhtd, lookup; - struct zapi_route nhr; - struct prefix matched; afi_t afi = AFI_IP; - if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) { - zlog_err("Failure to decode nexthop update message"); - return 1; - } - if (zclient->bfd_integration) - bfd_nht_update(&matched, &nhr); + bfd_nht_update(matched, nhr); - if (matched.family == AF_INET6) + if (matched->family == AF_INET6) afi = AFI_IP6; - if (nhr.type == ZEBRA_ROUTE_CONNECT) { - if (static_nexthop_is_local(vrf_id, &matched, - nhr.prefix.family)) - nhr.nexthop_num = 0; + if (nhr->type == ZEBRA_ROUTE_CONNECT) { + if (static_nexthop_is_local(vrf->vrf_id, matched, + nhr->prefix.family)) + nhr->nexthop_num = 0; } memset(&lookup, 0, sizeof(lookup)); - lookup.nh = matched; - lookup.nh_vrf_id = vrf_id; - lookup.safi = nhr.safi; + lookup.nh = *matched; + lookup.nh_vrf_id = vrf->vrf_id; + lookup.safi = nhr->safi; nhtd = static_nht_hash_find(static_nht_hash, &lookup); if (nhtd) { - nhtd->nh_num = nhr.nexthop_num; + nhtd->nh_num = nhr->nexthop_num; - static_nht_reset_start(&matched, afi, nhr.safi, - nhtd->nh_vrf_id); - static_nht_update(NULL, &matched, nhr.nexthop_num, afi, - nhr.safi, nhtd->nh_vrf_id); + static_nht_reset_start(matched, afi, nhr->safi, nhtd->nh_vrf_id); + static_nht_update(NULL, matched, nhr->nexthop_num, afi, + nhr->safi, nhtd->nh_vrf_id); } else zlog_err("No nhtd?"); - - return 1; } static void static_zebra_capabilities(struct zclient_capabilities *cap) @@ -395,6 +390,9 @@ extern void static_zebra_route_add(struct static_path *pn, bool install) struct zapi_route api; uint32_t nh_num = 0; + if (!si->svrf->vrf || si->svrf->vrf->vrf_id == VRF_UNKNOWN) + return; + p = src_pp = NULL; srcdest_rnode_prefixes(rn, &p, &src_pp); @@ -535,22 +533,22 @@ static zclient_handler *const static_handlers[] = { [ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add, [ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete, [ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner, - [ZEBRA_NEXTHOP_UPDATE] = static_zebra_nexthop_update, }; void static_zebra_init(void) { - struct zclient_options opt = { .receive_notify = true }; - - if_zapi_callbacks(static_ifp_create, static_ifp_up, - static_ifp_down, static_ifp_destroy); + hook_register_prio(if_real, 0, static_ifp_create); + hook_register_prio(if_up, 0, static_ifp_up); + hook_register_prio(if_down, 0, static_ifp_down); + hook_register_prio(if_unreal, 0, static_ifp_destroy); - zclient = zclient_new(master, &opt, static_handlers, + zclient = zclient_new(master, &zclient_options_default, static_handlers, array_size(static_handlers)); zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs); zclient->zebra_capabilities = static_zebra_capabilities; zclient->zebra_connected = zebra_connected; + zclient->nexthop_update = static_zebra_nexthop_update; static_nht_hash_init(static_nht_hash); static_bfd_initialize(zclient, master); |