From 2a1c520e9f105b1a1bbdb89d59ad3c3953f46f49 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 17 Oct 2019 15:33:53 -0300 Subject: [PATCH 1/5] isisd: split northbound callbacks into multiple files Rearrange the isisd northbound callbacks as following: * isis_nb.h: prototypes of all northbound callbacks. * isis_nb.c: definition of all northbound callbacks and their associated YANG data paths. * isis_nb_config.c: implementation of YANG configuration nodes. * isis_nb_state.c: implementation of YANG state nodes. * isis_nb_notifications.c: implementation of YANG notifications. This should help to keep to code more organized and easier to maintain. No behavior changes intended. Signed-off-by: Renato Westphal --- isisd/isis_adjacency.c | 15 + isisd/isis_adjacency.h | 1 + isisd/isis_circuit.c | 1 + isisd/isis_cli.c | 2 +- isisd/isis_cli.h | 127 -- isisd/isis_lsp.c | 1 + isisd/isis_main.c | 1 + isisd/isis_nb.c | 815 +++++++ isisd/isis_nb.h | 548 +++++ isisd/isis_nb_config.c | 2236 +++++++++++++++++++ isisd/isis_nb_notifications.c | 491 ++++ isisd/isis_nb_state.c | 386 ++++ isisd/isis_northbound.c | 3932 --------------------------------- isisd/isis_pdu.c | 1 + isisd/isisd.c | 1 + isisd/isisd.h | 46 - isisd/subdir.am | 7 +- 17 files changed, 4503 insertions(+), 4108 deletions(-) delete mode 100644 isisd/isis_cli.h create mode 100644 isisd/isis_nb.c create mode 100644 isisd/isis_nb.h create mode 100644 isisd/isis_nb_config.c create mode 100644 isisd/isis_nb_notifications.c create mode 100644 isisd/isis_nb_state.c delete mode 100644 isisd/isis_northbound.c diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index d2ec6ff566..1d70521e68 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -48,6 +48,7 @@ #include "isisd/isis_mt.h" #include "isisd/isis_tlvs.h" #include "isisd/fabricd.h" +#include "isisd/isis_nb.h" extern struct isis *isis; @@ -375,6 +376,20 @@ void isis_adj_print(struct isis_adjacency *adj) return; } +const char *isis_adj_yang_state(enum isis_adj_state state) +{ + switch (state) { + case ISIS_ADJ_DOWN: + return "down"; + case ISIS_ADJ_UP: + return "up"; + case ISIS_ADJ_INITIALIZING: + return "init"; + default: + return "failed"; + } +} + int isis_adj_expire(struct thread *thread) { struct isis_adjacency *adj; diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h index 2a4cb6e614..93583fc122 100644 --- a/isisd/isis_adjacency.h +++ b/isisd/isis_adjacency.h @@ -121,6 +121,7 @@ DECLARE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj)) void isis_adj_state_change(struct isis_adjacency *adj, enum isis_adj_state state, const char *reason); void isis_adj_print(struct isis_adjacency *adj); +const char *isis_adj_yang_state(enum isis_adj_state state); int isis_adj_expire(struct thread *thread); void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, char detail); diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 29fb725b04..1d0e6549df 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -58,6 +58,7 @@ #include "isisd/isis_mt.h" #include "isisd/isis_errors.h" #include "isisd/isis_tx_queue.h" +#include "isisd/isis_nb.h" DEFINE_QOBJ_TYPE(isis_circuit) diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 37f4dcfabd..3144b3c28e 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -32,7 +32,7 @@ #include "yang.h" #include "lib/linklist.h" #include "isisd/isisd.h" -#include "isisd/isis_cli.h" +#include "isisd/isis_nb.h" #include "isisd/isis_misc.h" #include "isisd/isis_circuit.h" #include "isisd/isis_csm.h" diff --git a/isisd/isis_cli.h b/isisd/isis_cli.h deleted file mode 100644 index 6621dc0fc0..0000000000 --- a/isisd/isis_cli.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2018 Volta Networks - * Emanuele Di Pascale - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef ISISD_ISIS_CLI_H_ -#define ISISD_ISIS_CLI_H_ - -/* add cli_show declarations here as externs */ -void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_is_type(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_dynamic_hostname(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_attached(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_overload(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_metric_style(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_area_pwd(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_domain_pwd(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_lsp_gen_interval(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_lsp_ref_interval(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_lsp_max_lifetime(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_lsp_mtu(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_spf_min_interval(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_spf_ietf_backoff(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_purge_origin(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_mpls_te(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_mpls_te_router_addr(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_def_origin_ipv4(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_def_origin_ipv6(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_redistribute_ipv4(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_redistribute_ipv6(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_passive(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_password(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_metric(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_hello_interval(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_hello_multi(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_threeway_shake(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_hello_padding(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_csnp_interval(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_psnp_interval(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_mt_ipv4_unicast(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_circ_type(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_network_type(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_ip_isis_priority(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void cli_show_isis_log_adjacency(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); - -#endif /* ISISD_ISIS_CLI_H_ */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 061e758831..c0b90e8439 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -57,6 +57,7 @@ #include "isisd/isis_te.h" #include "isisd/fabricd.h" #include "isisd/isis_tx_queue.h" +#include "isisd/isis_nb.h" static int lsp_refresh(struct thread *thread); static int lsp_l1_refresh_pseudo(struct thread *thread); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 718924daf2..2ef0065180 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -57,6 +57,7 @@ #include "isisd/isis_lsp.h" #include "isisd/isis_mt.h" #include "isisd/fabricd.h" +#include "isisd/isis_nb.h" /* Default configuration file name */ #define ISISD_DEFAULT_CONFIG "isisd.conf" diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c new file mode 100644 index 0000000000..d84e533240 --- /dev/null +++ b/isisd/isis_nb.c @@ -0,0 +1,815 @@ +/* + * Copyright (C) 2018 Volta Networks + * Emanuele Di Pascale + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "northbound.h" +#include "libfrr.h" + +#include "isisd/isis_nb.h" + +/* clang-format off */ +const struct frr_yang_module_info frr_isisd_info = { + .name = "frr-isisd", + .nodes = { + { + .xpath = "/frr-isisd:isis/instance", + .cbs = { + .cli_show = cli_show_router_isis, + .create = isis_instance_create, + .destroy = isis_instance_destroy, + }, + .priority = NB_DFLT_PRIORITY - 1, + }, + { + .xpath = "/frr-isisd:isis/instance/is-type", + .cbs = { + .cli_show = cli_show_isis_is_type, + .modify = isis_instance_is_type_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/area-address", + .cbs = { + .cli_show = cli_show_isis_area_address, + .create = isis_instance_area_address_create, + .destroy = isis_instance_area_address_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/dynamic-hostname", + .cbs = { + .cli_show = cli_show_isis_dynamic_hostname, + .modify = isis_instance_dynamic_hostname_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/attached", + .cbs = { + .cli_show = cli_show_isis_attached, + .modify = isis_instance_attached_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/overload", + .cbs = { + .cli_show = cli_show_isis_overload, + .modify = isis_instance_overload_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/metric-style", + .cbs = { + .cli_show = cli_show_isis_metric_style, + .modify = isis_instance_metric_style_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/purge-originator", + .cbs = { + .cli_show = cli_show_isis_purge_origin, + .modify = isis_instance_purge_originator_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/mtu", + .cbs = { + .cli_show = cli_show_isis_lsp_mtu, + .modify = isis_instance_lsp_mtu_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/refresh-interval", + .cbs = { + .cli_show = cli_show_isis_lsp_ref_interval, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/refresh-interval/level-1", + .cbs = { + .modify = isis_instance_lsp_refresh_interval_level_1_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/refresh-interval/level-2", + .cbs = { + .modify = isis_instance_lsp_refresh_interval_level_2_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/maximum-lifetime", + .cbs = { + .cli_show = cli_show_isis_lsp_max_lifetime, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/maximum-lifetime/level-1", + .cbs = { + .modify = isis_instance_lsp_maximum_lifetime_level_1_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/maximum-lifetime/level-2", + .cbs = { + .modify = isis_instance_lsp_maximum_lifetime_level_2_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/generation-interval", + .cbs = { + .cli_show = cli_show_isis_lsp_gen_interval, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/generation-interval/level-1", + .cbs = { + .modify = isis_instance_lsp_generation_interval_level_1_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/lsp/generation-interval/level-2", + .cbs = { + .modify = isis_instance_lsp_generation_interval_level_2_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay", + .cbs = { + .apply_finish = ietf_backoff_delay_apply_finish, + .cli_show = cli_show_isis_spf_ietf_backoff, + .create = isis_instance_spf_ietf_backoff_delay_create, + .destroy = isis_instance_spf_ietf_backoff_delay_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/init-delay", + .cbs = { + .modify = isis_instance_spf_ietf_backoff_delay_init_delay_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/short-delay", + .cbs = { + .modify = isis_instance_spf_ietf_backoff_delay_short_delay_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/long-delay", + .cbs = { + .modify = isis_instance_spf_ietf_backoff_delay_long_delay_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/hold-down", + .cbs = { + .modify = isis_instance_spf_ietf_backoff_delay_hold_down_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/time-to-learn", + .cbs = { + .modify = isis_instance_spf_ietf_backoff_delay_time_to_learn_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/minimum-interval", + .cbs = { + .cli_show = cli_show_isis_spf_min_interval, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/minimum-interval/level-1", + .cbs = { + .modify = isis_instance_spf_minimum_interval_level_1_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/spf/minimum-interval/level-2", + .cbs = { + .modify = isis_instance_spf_minimum_interval_level_2_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/area-password", + .cbs = { + .apply_finish = area_password_apply_finish, + .cli_show = cli_show_isis_area_pwd, + .create = isis_instance_area_password_create, + .destroy = isis_instance_area_password_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/area-password/password", + .cbs = { + .modify = isis_instance_area_password_password_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/area-password/password-type", + .cbs = { + .modify = isis_instance_area_password_password_type_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/area-password/authenticate-snp", + .cbs = { + .modify = isis_instance_area_password_authenticate_snp_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/domain-password", + .cbs = { + .apply_finish = domain_password_apply_finish, + .cli_show = cli_show_isis_domain_pwd, + .create = isis_instance_domain_password_create, + .destroy = isis_instance_domain_password_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/domain-password/password", + .cbs = { + .modify = isis_instance_domain_password_password_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/domain-password/password-type", + .cbs = { + .modify = isis_instance_domain_password_password_type_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/domain-password/authenticate-snp", + .cbs = { + .modify = isis_instance_domain_password_authenticate_snp_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv4", + .cbs = { + .apply_finish = default_info_origin_ipv4_apply_finish, + .cli_show = cli_show_isis_def_origin_ipv4, + .create = isis_instance_default_information_originate_ipv4_create, + .destroy = isis_instance_default_information_originate_ipv4_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv4/always", + .cbs = { + .modify = isis_instance_default_information_originate_ipv4_always_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv4/route-map", + .cbs = { + .destroy = isis_instance_default_information_originate_ipv4_route_map_destroy, + .modify = isis_instance_default_information_originate_ipv4_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv4/metric", + .cbs = { + .modify = isis_instance_default_information_originate_ipv4_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv6", + .cbs = { + .apply_finish = default_info_origin_ipv6_apply_finish, + .cli_show = cli_show_isis_def_origin_ipv6, + .create = isis_instance_default_information_originate_ipv6_create, + .destroy = isis_instance_default_information_originate_ipv6_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv6/always", + .cbs = { + .modify = isis_instance_default_information_originate_ipv6_always_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv6/route-map", + .cbs = { + .destroy = isis_instance_default_information_originate_ipv6_route_map_destroy, + .modify = isis_instance_default_information_originate_ipv6_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv6/metric", + .cbs = { + .modify = isis_instance_default_information_originate_ipv6_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv4", + .cbs = { + .apply_finish = redistribute_ipv4_apply_finish, + .cli_show = cli_show_isis_redistribute_ipv4, + .create = isis_instance_redistribute_ipv4_create, + .destroy = isis_instance_redistribute_ipv4_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv4/route-map", + .cbs = { + .destroy = isis_instance_redistribute_ipv4_route_map_destroy, + .modify = isis_instance_redistribute_ipv4_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv4/metric", + .cbs = { + .modify = isis_instance_redistribute_ipv4_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6", + .cbs = { + .apply_finish = redistribute_ipv6_apply_finish, + .cli_show = cli_show_isis_redistribute_ipv6, + .create = isis_instance_redistribute_ipv6_create, + .destroy = isis_instance_redistribute_ipv6_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/route-map", + .cbs = { + .destroy = isis_instance_redistribute_ipv6_route_map_destroy, + .modify = isis_instance_redistribute_ipv6_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/metric", + .cbs = { + .modify = isis_instance_redistribute_ipv6_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv4-multicast", + .cbs = { + .cli_show = cli_show_isis_mt_ipv4_multicast, + .create = isis_instance_multi_topology_ipv4_multicast_create, + .destroy = isis_instance_multi_topology_ipv4_multicast_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv4-multicast/overload", + .cbs = { + .modify = isis_instance_multi_topology_ipv4_multicast_overload_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv4-management", + .cbs = { + .cli_show = cli_show_isis_mt_ipv4_mgmt, + .create = isis_instance_multi_topology_ipv4_management_create, + .destroy = isis_instance_multi_topology_ipv4_management_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv4-management/overload", + .cbs = { + .modify = isis_instance_multi_topology_ipv4_management_overload_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-unicast", + .cbs = { + .cli_show = cli_show_isis_mt_ipv6_unicast, + .create = isis_instance_multi_topology_ipv6_unicast_create, + .destroy = isis_instance_multi_topology_ipv6_unicast_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-unicast/overload", + .cbs = { + .modify = isis_instance_multi_topology_ipv6_unicast_overload_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-multicast", + .cbs = { + .cli_show = cli_show_isis_mt_ipv6_multicast, + .create = isis_instance_multi_topology_ipv6_multicast_create, + .destroy = isis_instance_multi_topology_ipv6_multicast_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-multicast/overload", + .cbs = { + .modify = isis_instance_multi_topology_ipv6_multicast_overload_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-management", + .cbs = { + .cli_show = cli_show_isis_mt_ipv6_mgmt, + .create = isis_instance_multi_topology_ipv6_management_create, + .destroy = isis_instance_multi_topology_ipv6_management_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-management/overload", + .cbs = { + .modify = isis_instance_multi_topology_ipv6_management_overload_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-dstsrc", + .cbs = { + .cli_show = cli_show_isis_mt_ipv6_dstsrc, + .create = isis_instance_multi_topology_ipv6_dstsrc_create, + .destroy = isis_instance_multi_topology_ipv6_dstsrc_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-dstsrc/overload", + .cbs = { + .modify = isis_instance_multi_topology_ipv6_dstsrc_overload_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/log-adjacency-changes", + .cbs = { + .cli_show = cli_show_isis_log_adjacency, + .modify = isis_instance_log_adjacency_changes_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/mpls-te", + .cbs = { + .cli_show = cli_show_isis_mpls_te, + .create = isis_instance_mpls_te_create, + .destroy = isis_instance_mpls_te_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/mpls-te/router-address", + .cbs = { + .cli_show = cli_show_isis_mpls_te_router_addr, + .destroy = isis_instance_mpls_te_router_address_destroy, + .modify = isis_instance_mpls_te_router_address_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis", + .cbs = { + .create = lib_interface_isis_create, + .destroy = lib_interface_isis_destroy, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/area-tag", + .cbs = { + .modify = lib_interface_isis_area_tag_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/circuit-type", + .cbs = { + .cli_show = cli_show_ip_isis_circ_type, + .modify = lib_interface_isis_circuit_type_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/ipv4-routing", + .cbs = { + .cli_show = cli_show_ip_isis_ipv4, + .modify = lib_interface_isis_ipv4_routing_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/ipv6-routing", + .cbs = { + .cli_show = cli_show_ip_isis_ipv6, + .modify = lib_interface_isis_ipv6_routing_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring", + .cbs = { + .modify = lib_interface_isis_bfd_monitoring_modify, + .cli_show = cli_show_ip_isis_bfd_monitoring, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval", + .cbs = { + .cli_show = cli_show_ip_isis_csnp_interval, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-1", + .cbs = { + .modify = lib_interface_isis_csnp_interval_level_1_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-2", + .cbs = { + .modify = lib_interface_isis_csnp_interval_level_2_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/psnp-interval", + .cbs = { + .cli_show = cli_show_ip_isis_psnp_interval, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-1", + .cbs = { + .modify = lib_interface_isis_psnp_interval_level_1_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-2", + .cbs = { + .modify = lib_interface_isis_psnp_interval_level_2_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/padding", + .cbs = { + .cli_show = cli_show_ip_isis_hello_padding, + .modify = lib_interface_isis_hello_padding_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/interval", + .cbs = { + .cli_show = cli_show_ip_isis_hello_interval, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-1", + .cbs = { + .modify = lib_interface_isis_hello_interval_level_1_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-2", + .cbs = { + .modify = lib_interface_isis_hello_interval_level_2_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/multiplier", + .cbs = { + .cli_show = cli_show_ip_isis_hello_multi, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-1", + .cbs = { + .modify = lib_interface_isis_hello_multiplier_level_1_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-2", + .cbs = { + .modify = lib_interface_isis_hello_multiplier_level_2_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/metric", + .cbs = { + .cli_show = cli_show_ip_isis_metric, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/metric/level-1", + .cbs = { + .modify = lib_interface_isis_metric_level_1_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/metric/level-2", + .cbs = { + .modify = lib_interface_isis_metric_level_2_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/priority", + .cbs = { + .cli_show = cli_show_ip_isis_priority, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/priority/level-1", + .cbs = { + .modify = lib_interface_isis_priority_level_1_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/priority/level-2", + .cbs = { + .modify = lib_interface_isis_priority_level_2_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/network-type", + .cbs = { + .cli_show = cli_show_ip_isis_network_type, + .modify = lib_interface_isis_network_type_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/passive", + .cbs = { + .cli_show = cli_show_ip_isis_passive, + .modify = lib_interface_isis_passive_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/password", + .cbs = { + .cli_show = cli_show_ip_isis_password, + .create = lib_interface_isis_password_create, + .destroy = lib_interface_isis_password_destroy, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/password/password", + .cbs = { + .modify = lib_interface_isis_password_password_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/password/password-type", + .cbs = { + .modify = lib_interface_isis_password_password_type_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/disable-three-way-handshake", + .cbs = { + .cli_show = cli_show_ip_isis_threeway_shake, + .modify = lib_interface_isis_disable_three_way_handshake_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-unicast", + .cbs = { + .cli_show = cli_show_ip_isis_mt_ipv4_unicast, + .modify = lib_interface_isis_multi_topology_ipv4_unicast_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-multicast", + .cbs = { + .cli_show = cli_show_ip_isis_mt_ipv4_multicast, + .modify = lib_interface_isis_multi_topology_ipv4_multicast_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-management", + .cbs = { + .cli_show = cli_show_ip_isis_mt_ipv4_mgmt, + .modify = lib_interface_isis_multi_topology_ipv4_management_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-unicast", + .cbs = { + .cli_show = cli_show_ip_isis_mt_ipv6_unicast, + .modify = lib_interface_isis_multi_topology_ipv6_unicast_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-multicast", + .cbs = { + .cli_show = cli_show_ip_isis_mt_ipv6_multicast, + .modify = lib_interface_isis_multi_topology_ipv6_multicast_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-management", + .cbs = { + .cli_show = cli_show_ip_isis_mt_ipv6_mgmt, + .modify = lib_interface_isis_multi_topology_ipv6_management_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-dstsrc", + .cbs = { + .cli_show = cli_show_ip_isis_mt_ipv6_dstsrc, + .modify = lib_interface_isis_multi_topology_ipv6_dstsrc_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency", + .cbs = { + .get_next = lib_interface_isis_adjacencies_adjacency_get_next, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_state_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_changes_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_number_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_init_fails_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_rejects_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch", + .cbs = { + .get_elem = lib_interface_isis_event_counters_id_len_mismatch_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch", + .cbs = { + .get_elem = lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_authentication_type_fails_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_authentication_fails_get_elem, + } + }, + { + .xpath = NULL, + }, + } +}; diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h new file mode 100644 index 0000000000..29a2ded0de --- /dev/null +++ b/isisd/isis_nb.h @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2018 Volta Networks + * Emanuele Di Pascale + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ISISD_ISIS_NB_H_ +#define ISISD_ISIS_NB_H_ + +extern const struct frr_yang_module_info frr_isisd_info; + +/* Forward declaration(s). */ +struct isis_area; +struct isis_circuit; +struct isis_adjacency; + +/* Mandatory callbacks. */ +int isis_instance_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_destroy(enum nb_event event, const struct lyd_node *dnode); +int isis_instance_is_type_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_area_address_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_area_address_destroy(enum nb_event event, + const struct lyd_node *dnode); +int isis_instance_dynamic_hostname_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_attached_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_overload_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_metric_style_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_purge_originator_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_lsp_mtu_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_lsp_refresh_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_lsp_refresh_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_lsp_maximum_lifetime_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_lsp_maximum_lifetime_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_lsp_generation_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_lsp_generation_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_spf_ietf_backoff_delay_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_spf_ietf_backoff_delay_destroy(enum nb_event event, + const struct lyd_node *dnode); +int isis_instance_spf_ietf_backoff_delay_init_delay_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_spf_ietf_backoff_delay_short_delay_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_spf_ietf_backoff_delay_long_delay_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_spf_ietf_backoff_delay_hold_down_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_spf_ietf_backoff_delay_time_to_learn_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_spf_minimum_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_spf_minimum_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_area_password_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_area_password_destroy(enum nb_event event, + const struct lyd_node *dnode); +int isis_instance_area_password_password_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_area_password_password_type_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_area_password_authenticate_snp_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_domain_password_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_domain_password_destroy(enum nb_event event, + const struct lyd_node *dnode); +int isis_instance_domain_password_password_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_domain_password_password_type_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_domain_password_authenticate_snp_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_default_information_originate_ipv4_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_default_information_originate_ipv4_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_default_information_originate_ipv4_always_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_default_information_originate_ipv4_route_map_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_default_information_originate_ipv4_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_default_information_originate_ipv4_metric_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_default_information_originate_ipv6_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_default_information_originate_ipv6_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_default_information_originate_ipv6_always_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_default_information_originate_ipv6_route_map_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_default_information_originate_ipv6_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_default_information_originate_ipv6_metric_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_redistribute_ipv4_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_redistribute_ipv4_destroy(enum nb_event event, + const struct lyd_node *dnode); +int isis_instance_redistribute_ipv4_route_map_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_redistribute_ipv4_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_redistribute_ipv4_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_redistribute_ipv6_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_redistribute_ipv6_destroy(enum nb_event event, + const struct lyd_node *dnode); +int isis_instance_redistribute_ipv6_route_map_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_redistribute_ipv6_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_redistribute_ipv6_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv4_multicast_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv4_multicast_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_multi_topology_ipv4_multicast_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv4_management_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv4_management_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_multi_topology_ipv4_management_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv6_unicast_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv6_unicast_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_multi_topology_ipv6_unicast_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv6_multicast_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv6_multicast_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_multi_topology_ipv6_multicast_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv6_management_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv6_management_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_multi_topology_ipv6_management_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv6_dstsrc_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_multi_topology_ipv6_dstsrc_destroy( + enum nb_event event, const struct lyd_node *dnode); +int isis_instance_multi_topology_ipv6_dstsrc_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_log_adjacency_changes_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_mpls_te_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_mpls_te_destroy(enum nb_event event, + const struct lyd_node *dnode); +int isis_instance_mpls_te_router_address_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int isis_instance_mpls_te_router_address_destroy(enum nb_event event, + const struct lyd_node *dnode); +int lib_interface_isis_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_destroy(enum nb_event event, + const struct lyd_node *dnode); +int lib_interface_isis_area_tag_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_ipv4_routing_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_ipv6_routing_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_circuit_type_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_bfd_monitoring_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_csnp_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_csnp_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_psnp_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_psnp_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_hello_padding_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_hello_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_hello_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_hello_multiplier_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_hello_multiplier_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_metric_level_1_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_metric_level_2_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_priority_level_1_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_priority_level_2_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_network_type_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_passive_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_password_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_password_destroy(enum nb_event event, + const struct lyd_node *dnode); +int lib_interface_isis_password_password_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_password_password_type_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_disable_three_way_handshake_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_multi_topology_ipv4_unicast_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_multi_topology_ipv4_multicast_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_multi_topology_ipv4_management_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_multi_topology_ipv6_unicast_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_multi_topology_ipv6_multicast_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_multi_topology_ipv6_management_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_isis_multi_topology_ipv6_dstsrc_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +const void * +lib_interface_isis_adjacencies_adjacency_get_next(const void *parent_list_entry, + const void *list_entry); +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_adjacencies_adjacency_state_get_elem(const char *xpath, + const void *list_entry); +struct yang_data *lib_interface_isis_event_counters_adjacency_changes_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *lib_interface_isis_event_counters_adjacency_number_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_event_counters_init_fails_get_elem(const char *xpath, + const void *list_entry); +struct yang_data *lib_interface_isis_event_counters_adjacency_rejects_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *lib_interface_isis_event_counters_id_len_mismatch_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_event_counters_authentication_type_fails_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +lib_interface_isis_event_counters_authentication_fails_get_elem( + const char *xpath, const void *list_entry); + +/* Optional 'apply_finish' callbacks. */ +void ietf_backoff_delay_apply_finish(const struct lyd_node *dnode); +void area_password_apply_finish(const struct lyd_node *dnode); +void domain_password_apply_finish(const struct lyd_node *dnode); +void default_info_origin_apply_finish(const struct lyd_node *dnode, int family); +void default_info_origin_ipv4_apply_finish(const struct lyd_node *dnode); +void default_info_origin_ipv6_apply_finish(const struct lyd_node *dnode); +void redistribute_apply_finish(const struct lyd_node *dnode, int family); +void redistribute_ipv4_apply_finish(const struct lyd_node *dnode); +void redistribute_ipv6_apply_finish(const struct lyd_node *dnode); + +/* Optional 'cli_show' callbacks. */ +void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_is_type(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_dynamic_hostname(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_attached(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_overload(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_metric_style(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_area_pwd(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_domain_pwd(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_lsp_gen_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_lsp_ref_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_lsp_max_lifetime(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_lsp_mtu(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_spf_min_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_spf_ietf_backoff(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_purge_origin(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_mpls_te(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_mpls_te_router_addr(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_def_origin_ipv4(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_def_origin_ipv6(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_redistribute_ipv4(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_redistribute_ipv6(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_passive(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_password(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_metric(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_hello_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_hello_multi(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_threeway_shake(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_hello_padding(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_csnp_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_psnp_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_mt_ipv4_unicast(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_circ_type(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_network_type(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_isis_priority(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_log_adjacency(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); + +/* Notifications. */ +void isis_notif_db_overload(const struct isis_area *area, bool overload); +void isis_notif_lsp_too_large(const struct isis_circuit *circuit, + uint32_t pdu_size, const char *lsp_id); +void isis_notif_if_state_change(const struct isis_circuit *circuit, bool down); +void isis_notif_corrupted_lsp(const struct isis_area *area, + const char *lsp_id); /* currently unused */ +void isis_notif_lsp_exceed_max(const struct isis_area *area, + const char *lsp_id); +void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit, + uint8_t max_area_addrs, + const char *raw_pdu); +void isis_notif_authentication_type_failure(const struct isis_circuit *circuit, + const char *raw_pdu); +void isis_notif_authentication_failure(const struct isis_circuit *circuit, + const char *raw_pdu); +void isis_notif_adj_state_change(const struct isis_adjacency *adj, + int new_state, const char *reason); +void isis_notif_reject_adjacency(const struct isis_circuit *circuit, + const char *reason, const char *raw_pdu); +void isis_notif_area_mismatch(const struct isis_circuit *circuit, + const char *raw_pdu); +void isis_notif_lsp_received(const struct isis_circuit *circuit, + const char *lsp_id, uint32_t seqno, + uint32_t timestamp, const char *sys_id); +void isis_notif_lsp_gen(const struct isis_area *area, const char *lsp_id, + uint32_t seqno, uint32_t timestamp); +void isis_notif_id_len_mismatch(const struct isis_circuit *circuit, + uint8_t rcv_id_len, const char *raw_pdu); +void isis_notif_version_skew(const struct isis_circuit *circuit, + uint8_t version, const char *raw_pdu); +void isis_notif_lsp_error(const struct isis_circuit *circuit, + const char *lsp_id, const char *raw_pdu, + uint32_t offset, uint8_t tlv_type); +void isis_notif_seqno_skipped(const struct isis_circuit *circuit, + const char *lsp_id); +void isis_notif_own_lsp_purge(const struct isis_circuit *circuit, + const char *lsp_id); + +#endif /* ISISD_ISIS_NB_H_ */ diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c new file mode 100644 index 0000000000..820cfaa426 --- /dev/null +++ b/isisd/isis_nb_config.c @@ -0,0 +1,2236 @@ +/* + * Copyright (C) 2001,2002 Sampo Saaristo + * Tampere University of Technology + * Institute of Communications Engineering + * Copyright (C) 2018 Volta Networks + * Emanuele Di Pascale + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "northbound.h" +#include "linklist.h" +#include "log.h" +#include "bfd.h" +#include "spf_backoff.h" +#include "lib_errors.h" +#include "vrf.h" + +#include "isisd/isisd.h" +#include "isisd/isis_nb.h" +#include "isisd/isis_common.h" +#include "isisd/isis_bfd.h" +#include "isisd/isis_circuit.h" +#include "isisd/isis_lsp.h" +#include "isisd/isis_dynhn.h" +#include "isisd/isis_misc.h" +#include "isisd/isis_csm.h" +#include "isisd/isis_adjacency.h" +#include "isisd/isis_spf.h" +#include "isisd/isis_te.h" +#include "isisd/isis_memory.h" +#include "isisd/isis_mt.h" +#include "isisd/isis_redist.h" + +/* + * XPath: /frr-isisd:isis/instance + */ +int isis_instance_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + const char *area_tag; + + if (event != NB_EV_APPLY) + return NB_OK; + + area_tag = yang_dnode_get_string(dnode, "./area-tag"); + area = isis_area_lookup(area_tag); + if (area) + return NB_ERR_INCONSISTENCY; + + area = isis_area_create(area_tag); + /* save area in dnode to avoid looking it up all the time */ + nb_running_set_entry(dnode, area); + + return NB_OK; +} + +int isis_instance_destroy(enum nb_event event, const struct lyd_node *dnode) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_unset_entry(dnode); + isis_area_destroy(area->area_tag); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/is-type + */ +int isis_instance_is_type_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, NULL); + isis_area_is_type_set(area, type); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/area-address + */ +int isis_instance_area_address_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + struct area_addr addr, *addrr = NULL, *addrp = NULL; + struct listnode *node; + uint8_t buff[255]; + const char *net_title = yang_dnode_get_string(dnode, NULL); + + switch (event) { + case NB_EV_VALIDATE: + addr.addr_len = dotformat2buff(buff, net_title); + memcpy(addr.area_addr, buff, addr.addr_len); + if (addr.area_addr[addr.addr_len - 1] != 0) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "nsel byte (last byte) in area address must be 0"); + return NB_ERR_VALIDATION; + } + if (isis->sysid_set) { + /* Check that the SystemID portions match */ + if (memcmp(isis->sysid, GETSYSID((&addr)), + ISIS_SYS_ID_LEN)) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "System ID must not change when defining additional area addresses"); + return NB_ERR_VALIDATION; + } + } + break; + case NB_EV_PREPARE: + addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr)); + addrr->addr_len = dotformat2buff(buff, net_title); + memcpy(addrr->area_addr, buff, addrr->addr_len); + resource->ptr = addrr; + break; + case NB_EV_ABORT: + XFREE(MTYPE_ISIS_AREA_ADDR, resource->ptr); + break; + case NB_EV_APPLY: + area = nb_running_get_entry(dnode, NULL, true); + addrr = resource->ptr; + + if (isis->sysid_set == 0) { + /* + * First area address - get the SystemID for this router + */ + memcpy(isis->sysid, GETSYSID(addrr), ISIS_SYS_ID_LEN); + isis->sysid_set = 1; + } else { + /* check that we don't already have this address */ + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, + addrp)) { + if ((addrp->addr_len + ISIS_SYS_ID_LEN + + ISIS_NSEL_LEN) + != (addrr->addr_len)) + continue; + if (!memcmp(addrp->area_addr, addrr->area_addr, + addrr->addr_len)) { + XFREE(MTYPE_ISIS_AREA_ADDR, addrr); + return NB_OK; /* silent fail */ + } + } + } + + /*Forget the systemID part of the address */ + addrr->addr_len -= (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN); + assert(area->area_addrs); /* to silence scan-build sillyness */ + listnode_add(area->area_addrs, addrr); + + /* only now we can safely generate our LSPs for this area */ + if (listcount(area->area_addrs) > 0) { + if (area->is_type & IS_LEVEL_1) + lsp_generate(area, IS_LEVEL_1); + if (area->is_type & IS_LEVEL_2) + lsp_generate(area, IS_LEVEL_2); + } + break; + } + + return NB_OK; +} + +int isis_instance_area_address_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct area_addr addr, *addrp = NULL; + struct listnode *node; + uint8_t buff[255]; + struct isis_area *area; + const char *net_title; + + if (event != NB_EV_APPLY) + return NB_OK; + + net_title = yang_dnode_get_string(dnode, NULL); + addr.addr_len = dotformat2buff(buff, net_title); + memcpy(addr.area_addr, buff, (int)addr.addr_len); + area = nb_running_get_entry(dnode, NULL, true); + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) { + if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len + && !memcmp(addrp->area_addr, addr.area_addr, addr.addr_len)) + break; + } + if (!addrp) + return NB_ERR_INCONSISTENCY; + + listnode_delete(area->area_addrs, addrp); + XFREE(MTYPE_ISIS_AREA_ADDR, addrp); + /* + * Last area address - reset the SystemID for this router + */ + if (listcount(area->area_addrs) == 0) { + memset(isis->sysid, 0, ISIS_SYS_ID_LEN); + isis->sysid_set = 0; + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("Router has no SystemID"); + } + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/dynamic-hostname + */ +int isis_instance_dynamic_hostname_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + isis_area_dynhostname_set(area, yang_dnode_get_bool(dnode, NULL)); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/attached + */ +int isis_instance_attached_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + bool attached; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + attached = yang_dnode_get_bool(dnode, NULL); + isis_area_attached_bit_set(area, attached); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/overload + */ +int isis_instance_overload_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + bool overload; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + overload = yang_dnode_get_bool(dnode, NULL); + isis_area_overload_bit_set(area, overload); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/metric-style + */ +int isis_instance_metric_style_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + bool old_metric, new_metric; + enum isis_metric_style metric_style = yang_dnode_get_enum(dnode, NULL); + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + old_metric = (metric_style == ISIS_WIDE_METRIC) ? false : true; + new_metric = (metric_style == ISIS_NARROW_METRIC) ? false : true; + isis_area_metricstyle_set(area, old_metric, new_metric); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/purge-originator + */ +int isis_instance_purge_originator_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + area->purge_originator = yang_dnode_get_bool(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/mtu + */ +int isis_instance_lsp_mtu_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct listnode *node; + struct isis_circuit *circuit; + uint16_t lsp_mtu = yang_dnode_get_uint16(dnode, NULL); + struct isis_area *area; + + switch (event) { + case NB_EV_VALIDATE: + area = nb_running_get_entry(dnode, NULL, false); + if (!area) + break; + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { + if (circuit->state != C_STATE_INIT + && circuit->state != C_STATE_UP) + continue; + if (lsp_mtu > isis_circuit_pdu_size(circuit)) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "ISIS area contains circuit %s, which has a maximum PDU size of %zu", + circuit->interface->name, + isis_circuit_pdu_size(circuit)); + return NB_ERR_VALIDATION; + } + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + area = nb_running_get_entry(dnode, NULL, true); + isis_area_lsp_mtu_set(area, lsp_mtu); + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/refresh-interval/level-1 + */ +int isis_instance_lsp_refresh_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + uint16_t refr_int; + + if (event != NB_EV_APPLY) + return NB_OK; + + refr_int = yang_dnode_get_uint16(dnode, NULL); + area = nb_running_get_entry(dnode, NULL, true); + isis_area_lsp_refresh_set(area, IS_LEVEL_1, refr_int); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/refresh-interval/level-2 + */ +int isis_instance_lsp_refresh_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + uint16_t refr_int; + + if (event != NB_EV_APPLY) + return NB_OK; + + refr_int = yang_dnode_get_uint16(dnode, NULL); + area = nb_running_get_entry(dnode, NULL, true); + isis_area_lsp_refresh_set(area, IS_LEVEL_2, refr_int); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/maximum-lifetime/level-1 + */ +int isis_instance_lsp_maximum_lifetime_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + uint16_t max_lt; + + if (event != NB_EV_APPLY) + return NB_OK; + + max_lt = yang_dnode_get_uint16(dnode, NULL); + area = nb_running_get_entry(dnode, NULL, true); + isis_area_max_lsp_lifetime_set(area, IS_LEVEL_1, max_lt); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/maximum-lifetime/level-2 + */ +int isis_instance_lsp_maximum_lifetime_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + uint16_t max_lt; + + if (event != NB_EV_APPLY) + return NB_OK; + + max_lt = yang_dnode_get_uint16(dnode, NULL); + area = nb_running_get_entry(dnode, NULL, true); + isis_area_max_lsp_lifetime_set(area, IS_LEVEL_2, max_lt); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/generation-interval/level-1 + */ +int isis_instance_lsp_generation_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + uint16_t gen_int; + + if (event != NB_EV_APPLY) + return NB_OK; + + gen_int = yang_dnode_get_uint16(dnode, NULL); + area = nb_running_get_entry(dnode, NULL, true); + area->lsp_gen_interval[0] = gen_int; + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/generation-interval/level-2 + */ +int isis_instance_lsp_generation_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + uint16_t gen_int; + + if (event != NB_EV_APPLY) + return NB_OK; + + gen_int = yang_dnode_get_uint16(dnode, NULL); + area = nb_running_get_entry(dnode, NULL, true); + area->lsp_gen_interval[1] = gen_int; + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay + */ +void ietf_backoff_delay_apply_finish(const struct lyd_node *dnode) +{ + long init_delay = yang_dnode_get_uint16(dnode, "./init-delay"); + long short_delay = yang_dnode_get_uint16(dnode, "./short-delay"); + long long_delay = yang_dnode_get_uint16(dnode, "./long-delay"); + long holddown = yang_dnode_get_uint16(dnode, "./hold-down"); + long timetolearn = yang_dnode_get_uint16(dnode, "./time-to-learn"); + struct isis_area *area = nb_running_get_entry(dnode, NULL, true); + size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx"); + char *buf = XCALLOC(MTYPE_TMP, bufsiz); + + snprintf(buf, bufsiz, "IS-IS %s L1", area->area_tag); + spf_backoff_free(area->spf_delay_ietf[0]); + area->spf_delay_ietf[0] = + spf_backoff_new(master, buf, init_delay, short_delay, + long_delay, holddown, timetolearn); + + snprintf(buf, bufsiz, "IS-IS %s L2", area->area_tag); + spf_backoff_free(area->spf_delay_ietf[1]); + area->spf_delay_ietf[1] = + spf_backoff_new(master, buf, init_delay, short_delay, + long_delay, holddown, timetolearn); + + XFREE(MTYPE_TMP, buf); +} + +int isis_instance_spf_ietf_backoff_delay_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* All the work is done in the apply_finish */ + return NB_OK; +} + +int isis_instance_spf_ietf_backoff_delay_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + spf_backoff_free(area->spf_delay_ietf[0]); + spf_backoff_free(area->spf_delay_ietf[1]); + area->spf_delay_ietf[0] = NULL; + area->spf_delay_ietf[1] = NULL; + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/init-delay + */ +int isis_instance_spf_ietf_backoff_delay_init_delay_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* All the work is done in the apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/short-delay + */ +int isis_instance_spf_ietf_backoff_delay_short_delay_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* All the work is done in the apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/long-delay + */ +int isis_instance_spf_ietf_backoff_delay_long_delay_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* All the work is done in the apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/hold-down + */ +int isis_instance_spf_ietf_backoff_delay_hold_down_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* All the work is done in the apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/time-to-learn + */ +int isis_instance_spf_ietf_backoff_delay_time_to_learn_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* All the work is done in the apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/spf/minimum-interval/level-1 + */ +int isis_instance_spf_minimum_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + area->min_spf_interval[0] = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/spf/minimum-interval/level-2 + */ +int isis_instance_spf_minimum_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + area->min_spf_interval[1] = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/area-password + */ +void area_password_apply_finish(const struct lyd_node *dnode) +{ + const char *password = yang_dnode_get_string(dnode, "./password"); + struct isis_area *area = nb_running_get_entry(dnode, NULL, true); + int pass_type = yang_dnode_get_enum(dnode, "./password-type"); + uint8_t snp_auth = yang_dnode_get_enum(dnode, "./authenticate-snp"); + + switch (pass_type) { + case ISIS_PASSWD_TYPE_CLEARTXT: + isis_area_passwd_cleartext_set(area, IS_LEVEL_1, password, + snp_auth); + break; + case ISIS_PASSWD_TYPE_HMAC_MD5: + isis_area_passwd_hmac_md5_set(area, IS_LEVEL_1, password, + snp_auth); + break; + } +} + +int isis_instance_area_password_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* actual setting is done in apply_finish */ + return NB_OK; +} + +int isis_instance_area_password_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + isis_area_passwd_unset(area, IS_LEVEL_1); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/area-password/password + */ +int isis_instance_area_password_password_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* actual setting is done in apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/area-password/password-type + */ +int isis_instance_area_password_password_type_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* actual setting is done in apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/area-password/authenticate-snp + */ +int isis_instance_area_password_authenticate_snp_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* actual setting is done in apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/domain-password + */ +void domain_password_apply_finish(const struct lyd_node *dnode) +{ + const char *password = yang_dnode_get_string(dnode, "./password"); + struct isis_area *area = nb_running_get_entry(dnode, NULL, true); + int pass_type = yang_dnode_get_enum(dnode, "./password-type"); + uint8_t snp_auth = yang_dnode_get_enum(dnode, "./authenticate-snp"); + + switch (pass_type) { + case ISIS_PASSWD_TYPE_CLEARTXT: + isis_area_passwd_cleartext_set(area, IS_LEVEL_2, password, + snp_auth); + break; + case ISIS_PASSWD_TYPE_HMAC_MD5: + isis_area_passwd_hmac_md5_set(area, IS_LEVEL_2, password, + snp_auth); + break; + } +} + +int isis_instance_domain_password_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* actual setting is done in apply_finish */ + return NB_OK; +} + +int isis_instance_domain_password_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + isis_area_passwd_unset(area, IS_LEVEL_2); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/domain-password/password + */ +int isis_instance_domain_password_password_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* actual setting is done in apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/domain-password/password-type + */ +int isis_instance_domain_password_password_type_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* actual setting is done in apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/domain-password/authenticate-snp + */ +int isis_instance_domain_password_authenticate_snp_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* actual setting is done in apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4 + */ +void default_info_origin_apply_finish(const struct lyd_node *dnode, int family) +{ + int originate_type = DEFAULT_ORIGINATE; + unsigned long metric = 0; + const char *routemap = NULL; + struct isis_area *area = nb_running_get_entry(dnode, NULL, true); + int level = yang_dnode_get_enum(dnode, "./level"); + + if (yang_dnode_get_bool(dnode, "./always")) { + originate_type = DEFAULT_ORIGINATE_ALWAYS; + } else if (family == AF_INET6) { + zlog_warn( + "%s: Zebra doesn't implement default-originate for IPv6 yet, so use with care or use default-originate always.", + __func__); + } + + if (yang_dnode_exists(dnode, "./metric")) + metric = yang_dnode_get_uint32(dnode, "./metric"); + if (yang_dnode_exists(dnode, "./route-map")) + routemap = yang_dnode_get_string(dnode, "./route-map"); + + isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, + originate_type); +} + +void default_info_origin_ipv4_apply_finish(const struct lyd_node *dnode) +{ + default_info_origin_apply_finish(dnode, AF_INET); +} + +void default_info_origin_ipv6_apply_finish(const struct lyd_node *dnode) +{ + default_info_origin_apply_finish(dnode, AF_INET6); +} + +int isis_instance_default_information_originate_ipv4_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +int isis_instance_default_information_originate_ipv4_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct isis_area *area; + int level; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + level = yang_dnode_get_enum(dnode, "./level"); + isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/always + */ +int isis_instance_default_information_originate_ipv4_always_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/route-map + */ +int isis_instance_default_information_originate_ipv4_route_map_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +int isis_instance_default_information_originate_ipv4_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/metric + */ +int isis_instance_default_information_originate_ipv4_metric_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6 + */ +int isis_instance_default_information_originate_ipv6_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +int isis_instance_default_information_originate_ipv6_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct isis_area *area; + int level; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + level = yang_dnode_get_enum(dnode, "./level"); + isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/always + */ +int isis_instance_default_information_originate_ipv6_always_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/route-map + */ +int isis_instance_default_information_originate_ipv6_route_map_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +int isis_instance_default_information_originate_ipv6_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/metric + */ +int isis_instance_default_information_originate_ipv6_metric_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by default_info_origin_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv4 + */ +void redistribute_apply_finish(const struct lyd_node *dnode, int family) +{ + assert(family == AF_INET || family == AF_INET6); + int type, level; + unsigned long metric = 0; + const char *routemap = NULL; + struct isis_area *area; + + type = yang_dnode_get_enum(dnode, "./protocol"); + level = yang_dnode_get_enum(dnode, "./level"); + area = nb_running_get_entry(dnode, NULL, true); + + if (yang_dnode_exists(dnode, "./metric")) + metric = yang_dnode_get_uint32(dnode, "./metric"); + if (yang_dnode_exists(dnode, "./route-map")) + routemap = yang_dnode_get_string(dnode, "./route-map"); + + isis_redist_set(area, level, family, type, metric, routemap, 0); +} + +void redistribute_ipv4_apply_finish(const struct lyd_node *dnode) +{ + redistribute_apply_finish(dnode, AF_INET); +} + +void redistribute_ipv6_apply_finish(const struct lyd_node *dnode) +{ + redistribute_apply_finish(dnode, AF_INET6); +} + +int isis_instance_redistribute_ipv4_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +int isis_instance_redistribute_ipv4_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct isis_area *area; + int level, type; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + level = yang_dnode_get_enum(dnode, "./level"); + type = yang_dnode_get_enum(dnode, "./protocol"); + isis_redist_unset(area, level, AF_INET, type); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv4/route-map + */ +int isis_instance_redistribute_ipv4_route_map_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +int isis_instance_redistribute_ipv4_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv4/metric + */ +int isis_instance_redistribute_ipv4_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv6 + */ +int isis_instance_redistribute_ipv6_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +int isis_instance_redistribute_ipv6_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct isis_area *area; + int level, type; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + level = yang_dnode_get_enum(dnode, "./level"); + type = yang_dnode_get_enum(dnode, "./protocol"); + isis_redist_unset(area, level, AF_INET6, type); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv6/route-map + */ +int isis_instance_redistribute_ipv6_route_map_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +int isis_instance_redistribute_ipv6_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv6/metric + */ +int isis_instance_redistribute_ipv6_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast + */ +static int isis_multi_topology_common(enum nb_event event, + const struct lyd_node *dnode, + const char *topology, bool create) +{ + struct isis_area *area; + struct isis_area_mt_setting *setting; + uint16_t mtid = isis_str2mtid(topology); + + switch (event) { + case NB_EV_VALIDATE: + if (mtid == (uint16_t)-1) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Unknown topology %s", topology); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + area = nb_running_get_entry(dnode, NULL, true); + setting = area_get_mt_setting(area, mtid); + setting->enabled = create; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); + break; + } + + return NB_OK; +} + +static int isis_multi_topology_overload_common(enum nb_event event, + const struct lyd_node *dnode, + const char *topology) +{ + struct isis_area *area; + struct isis_area_mt_setting *setting; + uint16_t mtid = isis_str2mtid(topology); + + /* validation is done in isis_multi_topology_common */ + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + setting = area_get_mt_setting(area, mtid); + setting->overload = yang_dnode_get_bool(dnode, NULL); + if (setting->enabled) + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); + + return NB_OK; +} + +int isis_instance_multi_topology_ipv4_multicast_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_common(event, dnode, "ipv4-multicast", true); +} + +int isis_instance_multi_topology_ipv4_multicast_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + return isis_multi_topology_common(event, dnode, "ipv4-multicast", + false); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast/overload + */ +int isis_instance_multi_topology_ipv4_multicast_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_overload_common(event, dnode, + "ipv4-multicast"); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-management + */ +int isis_instance_multi_topology_ipv4_management_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_common(event, dnode, "ipv4-mgmt", true); +} + +int isis_instance_multi_topology_ipv4_management_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + return isis_multi_topology_common(event, dnode, "ipv4-mgmt", false); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-management/overload + */ +int isis_instance_multi_topology_ipv4_management_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_overload_common(event, dnode, "ipv4-mgmt"); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-unicast + */ +int isis_instance_multi_topology_ipv6_unicast_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_common(event, dnode, "ipv6-unicast", true); +} + +int isis_instance_multi_topology_ipv6_unicast_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + return isis_multi_topology_common(event, dnode, "ipv6-unicast", false); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-unicast/overload + */ +int isis_instance_multi_topology_ipv6_unicast_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_overload_common(event, dnode, + "ipv6-unicast"); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-multicast + */ +int isis_instance_multi_topology_ipv6_multicast_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_common(event, dnode, "ipv6-multicast", true); +} + +int isis_instance_multi_topology_ipv6_multicast_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + return isis_multi_topology_common(event, dnode, "ipv6-multicast", + false); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-multicast/overload + */ +int isis_instance_multi_topology_ipv6_multicast_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_overload_common(event, dnode, + "ipv6-multicast"); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-management + */ +int isis_instance_multi_topology_ipv6_management_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_common(event, dnode, "ipv6-mgmt", true); +} + +int isis_instance_multi_topology_ipv6_management_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + return isis_multi_topology_common(event, dnode, "ipv6-mgmt", false); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-management/overload + */ +int isis_instance_multi_topology_ipv6_management_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_overload_common(event, dnode, "ipv6-mgmt"); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-dstsrc + */ +int isis_instance_multi_topology_ipv6_dstsrc_create( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_common(event, dnode, "ipv6-dstsrc", true); +} + +int isis_instance_multi_topology_ipv6_dstsrc_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + return isis_multi_topology_common(event, dnode, "ipv6-dstsrc", false); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-dstsrc/overload + */ +int isis_instance_multi_topology_ipv6_dstsrc_overload_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return isis_multi_topology_overload_common(event, dnode, "ipv6-dstsrc"); +} + +/* + * XPath: /frr-isisd:isis/instance/log-adjacency-changes + */ +int isis_instance_log_adjacency_changes_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + bool log = yang_dnode_get_bool(dnode, NULL); + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + area->log_adj_changes = log ? 1 : 0; + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/mpls-te + */ +int isis_instance_mpls_te_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct listnode *node; + struct isis_area *area; + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + if (area->mta == NULL) { + + struct mpls_te_area *new; + + zlog_debug("ISIS-TE(%s): Initialize MPLS Traffic Engineering", + area->area_tag); + + new = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_area)); + + /* Initialize MPLS_TE structure */ + new->status = enable; + new->level = 0; + new->inter_as = off; + new->interas_areaid.s_addr = 0; + new->router_id.s_addr = 0; + + area->mta = new; + } else { + area->mta->status = enable; + } + + /* Update Extended TLVs according to Interface link parameters */ + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + isis_link_params_update(circuit, circuit->interface); + + /* Reoriginate STD_TE & GMPLS circuits */ + lsp_regenerate_schedule(area, area->is_type, 0); + + return NB_OK; +} + +int isis_instance_mpls_te_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct listnode *node; + struct isis_area *area; + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + if (IS_MPLS_TE(area->mta)) + area->mta->status = disable; + else + return NB_OK; + + /* Flush LSP if circuit engage */ + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { + if (!IS_EXT_TE(circuit->ext)) + continue; + + /* disable MPLS_TE Circuit keeping SR one's */ + if (IS_SUBTLV(circuit->ext, EXT_ADJ_SID)) + circuit->ext->status = EXT_ADJ_SID; + else if (IS_SUBTLV(circuit->ext, EXT_LAN_ADJ_SID)) + circuit->ext->status = EXT_LAN_ADJ_SID; + else + circuit->ext->status = 0; + } + + /* Reoriginate STD_TE & GMPLS circuits */ + lsp_regenerate_schedule(area, area->is_type, 0); + + zlog_debug("ISIS-TE(%s): Disabled MPLS Traffic Engineering", + area->area_tag); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/mpls-te/router-address + */ +int isis_instance_mpls_te_router_address_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct in_addr value; + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + /* only proceed if MPLS-TE is enabled */ + if (!IS_MPLS_TE(area->mta)) + return NB_OK; + + /* Update Area Router ID */ + yang_dnode_get_ipv4(&value, dnode, NULL); + area->mta->router_id.s_addr = value.s_addr; + + /* And re-schedule LSP update */ + lsp_regenerate_schedule(area, area->is_type, 0); + + return NB_OK; +} + +int isis_instance_mpls_te_router_address_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct isis_area *area; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(dnode, NULL, true); + /* only proceed if MPLS-TE is enabled */ + if (!IS_MPLS_TE(area->mta)) + return NB_OK; + + /* Reset Area Router ID */ + area->mta->router_id.s_addr = INADDR_ANY; + + /* And re-schedule LSP update */ + lsp_regenerate_schedule(area, area->is_type, 0); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis + */ +int lib_interface_isis_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_area *area; + struct interface *ifp; + struct isis_circuit *circuit; + const char *area_tag = yang_dnode_get_string(dnode, "./area-tag"); + uint32_t min_mtu, actual_mtu; + + switch (event) { + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_VALIDATE: + /* check if interface mtu is sufficient. If the area has not + * been created yet, assume default MTU for the area + */ + ifp = nb_running_get_entry(dnode, NULL, false); + /* zebra might not know yet about the MTU - nothing we can do */ + if (!ifp || ifp->mtu == 0) + break; + actual_mtu = + if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu; + area = isis_area_lookup(area_tag); + if (area) + min_mtu = area->lsp_mtu; + else +#ifndef FABRICD + min_mtu = yang_get_default_uint16( + "/frr-isisd:isis/instance/lsp/mtu"); +#else + min_mtu = DEFAULT_LSP_MTU; +#endif /* ifndef FABRICD */ + if (actual_mtu < min_mtu) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Interface %s has MTU %" PRIu32 + ", minimum MTU for the area is %" PRIu32 "", + ifp->name, actual_mtu, min_mtu); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_APPLY: + area = isis_area_lookup(area_tag); + /* The area should have already be created. We are + * setting the priority of the global isis area creation + * slightly lower, so it should be executed first, but I + * cannot rely on that so here I have to check. + */ + if (!area) { + flog_err( + EC_LIB_NB_CB_CONFIG_APPLY, + "%s: attempt to create circuit for area %s before the area has been created", + __func__, area_tag); + abort(); + } + + ifp = nb_running_get_entry(dnode, NULL, true); + circuit = isis_circuit_create(area, ifp); + assert(circuit + && (circuit->state == C_STATE_CONF + || circuit->state == C_STATE_UP)); + nb_running_set_entry(dnode, circuit); + break; + } + + return NB_OK; +} + +int lib_interface_isis_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_unset_entry(dnode); + if (!circuit) + return NB_ERR_INCONSISTENCY; + if (circuit->state == C_STATE_UP || circuit->state == C_STATE_CONF) + isis_csm_state_change(ISIS_DISABLE, circuit, circuit->area); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/area-tag + */ +int lib_interface_isis_area_tag_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + struct interface *ifp; + struct vrf *vrf; + const char *area_tag, *ifname, *vrfname; + + if (event == NB_EV_VALIDATE) { + /* libyang doesn't like relative paths across module boundaries + */ + ifname = yang_dnode_get_string(dnode->parent->parent, "./name"); + vrfname = yang_dnode_get_string(dnode->parent->parent, "./vrf"); + vrf = vrf_lookup_by_name(vrfname); + assert(vrf); + ifp = if_lookup_by_name(ifname, vrf->vrf_id); + if (!ifp) + return NB_OK; + circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); + area_tag = yang_dnode_get_string(dnode, NULL); + if (circuit && circuit->area && circuit->area->area_tag + && strcmp(circuit->area->area_tag, area_tag)) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "ISIS circuit is already defined on %s", + circuit->area->area_tag); + return NB_ERR_VALIDATION; + } + } + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type + */ +int lib_interface_isis_circuit_type_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + int circ_type = yang_dnode_get_enum(dnode, NULL); + struct isis_circuit *circuit; + struct interface *ifp; + struct vrf *vrf; + const char *ifname, *vrfname; + + switch (event) { + case NB_EV_VALIDATE: + /* libyang doesn't like relative paths across module boundaries + */ + ifname = yang_dnode_get_string(dnode->parent->parent, "./name"); + vrfname = yang_dnode_get_string(dnode->parent->parent, "./vrf"); + vrf = vrf_lookup_by_name(vrfname); + assert(vrf); + ifp = if_lookup_by_name(ifname, vrf->vrf_id); + if (!ifp) + break; + circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); + if (circuit && circuit->state == C_STATE_UP + && circuit->area->is_type != IS_LEVEL_1_AND_2 + && circuit->area->is_type != circ_type) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Invalid circuit level for area %s", + circuit->area->area_tag); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + circuit = nb_running_get_entry(dnode, NULL, true); + isis_circuit_is_type_set(circuit, circ_type); + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing + */ +int lib_interface_isis_ipv4_routing_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + bool ipv4, ipv6; + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + ipv4 = yang_dnode_get_bool(dnode, NULL); + ipv6 = yang_dnode_get_bool(dnode, "../ipv6-routing"); + isis_circuit_af_set(circuit, ipv4, ipv6); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing + */ +int lib_interface_isis_ipv6_routing_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + bool ipv4, ipv6; + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + ipv4 = yang_dnode_exists(dnode, "../ipv4-routing"); + ipv6 = yang_dnode_get_bool(dnode, NULL); + isis_circuit_af_set(circuit, ipv4, ipv6); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring + */ +int lib_interface_isis_bfd_monitoring_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + bool bfd_monitoring; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + bfd_monitoring = yang_dnode_get_bool(dnode, NULL); + + if (bfd_monitoring) { + isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX, + BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, + true); + } else { + isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER); + bfd_info_free(&circuit->bfd_info); + } + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-1 + */ +int lib_interface_isis_csnp_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->csnp_interval[0] = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-2 + */ +int lib_interface_isis_csnp_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->csnp_interval[1] = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-1 + */ +int lib_interface_isis_psnp_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->psnp_interval[0] = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-2 + */ +int lib_interface_isis_psnp_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->psnp_interval[1] = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/padding + */ +int lib_interface_isis_hello_padding_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->pad_hellos = yang_dnode_get_bool(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-1 + */ +int lib_interface_isis_hello_interval_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + uint32_t interval; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + interval = yang_dnode_get_uint32(dnode, NULL); + circuit->hello_interval[0] = interval; + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-2 + */ +int lib_interface_isis_hello_interval_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + uint32_t interval; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + interval = yang_dnode_get_uint32(dnode, NULL); + circuit->hello_interval[1] = interval; + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-1 + */ +int lib_interface_isis_hello_multiplier_level_1_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + uint16_t multi; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + multi = yang_dnode_get_uint16(dnode, NULL); + circuit->hello_multiplier[0] = multi; + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-2 + */ +int lib_interface_isis_hello_multiplier_level_2_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + uint16_t multi; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + multi = yang_dnode_get_uint16(dnode, NULL); + circuit->hello_multiplier[1] = multi; + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric/level-1 + */ +int lib_interface_isis_metric_level_1_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + unsigned int met; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + met = yang_dnode_get_uint32(dnode, NULL); + isis_circuit_metric_set(circuit, IS_LEVEL_1, met); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric/level-2 + */ +int lib_interface_isis_metric_level_2_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + unsigned int met; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + met = yang_dnode_get_uint32(dnode, NULL); + isis_circuit_metric_set(circuit, IS_LEVEL_2, met); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority/level-1 + */ +int lib_interface_isis_priority_level_1_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->priority[0] = yang_dnode_get_uint8(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority/level-2 + */ +int lib_interface_isis_priority_level_2_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->priority[1] = yang_dnode_get_uint8(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/network-type + */ +int lib_interface_isis_network_type_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + int net_type = yang_dnode_get_enum(dnode, NULL); + + switch (event) { + case NB_EV_VALIDATE: + circuit = nb_running_get_entry(dnode, NULL, false); + if (!circuit) + break; + if (circuit->circ_type == CIRCUIT_T_LOOPBACK) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "Cannot change network type on loopback interface"); + return NB_ERR_VALIDATION; + } + if (net_type == CIRCUIT_T_BROADCAST + && circuit->state == C_STATE_UP + && !if_is_broadcast(circuit->interface)) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "Cannot configure non-broadcast interface for broadcast operation"); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + circuit = nb_running_get_entry(dnode, NULL, true); + isis_circuit_circ_type_set(circuit, net_type); + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/passive + */ +int lib_interface_isis_passive_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + struct isis_area *area; + struct interface *ifp; + bool passive = yang_dnode_get_bool(dnode, NULL); + + /* validation only applies if we are setting passive to false */ + if (!passive && event == NB_EV_VALIDATE) { + circuit = nb_running_get_entry(dnode, NULL, false); + if (!circuit) + return NB_OK; + ifp = circuit->interface; + if (!ifp) + return NB_OK; + if (if_is_loopback(ifp)) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Loopback is always passive"); + return NB_ERR_VALIDATION; + } + } + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + if (circuit->state != C_STATE_UP) { + circuit->is_passive = passive; + } else { + area = circuit->area; + isis_csm_state_change(ISIS_DISABLE, circuit, area); + circuit->is_passive = passive; + isis_csm_state_change(ISIS_ENABLE, circuit, area); + } + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/password + */ +int lib_interface_isis_password_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return NB_OK; +} + +int lib_interface_isis_password_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + isis_circuit_passwd_unset(circuit); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/password/password + */ +int lib_interface_isis_password_password_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + const char *password; + + if (event != NB_EV_APPLY) + return NB_OK; + + password = yang_dnode_get_string(dnode, NULL); + circuit = nb_running_get_entry(dnode, NULL, true); + + isis_circuit_passwd_set(circuit, circuit->passwd.type, password); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/password/password-type + */ +int lib_interface_isis_password_password_type_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + uint8_t pass_type; + + if (event != NB_EV_APPLY) + return NB_OK; + + pass_type = yang_dnode_get_enum(dnode, NULL); + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->passwd.type = pass_type; + + return NB_OK; +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/disable-three-way-handshake + */ +int lib_interface_isis_disable_three_way_handshake_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = nb_running_get_entry(dnode, NULL, true); + circuit->disable_threeway_adj = yang_dnode_get_bool(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-unicast + */ +static int lib_interface_isis_multi_topology_common( + enum nb_event event, const struct lyd_node *dnode, uint16_t mtid) +{ + struct isis_circuit *circuit; + bool value; + + switch (event) { + case NB_EV_VALIDATE: + circuit = nb_running_get_entry(dnode, NULL, false); + if (circuit && circuit->area && circuit->area->oldmetric) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "Multi topology IS-IS can only be used with wide metrics"); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + circuit = nb_running_get_entry(dnode, NULL, true); + value = yang_dnode_get_bool(dnode, NULL); + isis_circuit_mt_enabled_set(circuit, mtid, value); + break; + } + + return NB_OK; +} + +int lib_interface_isis_multi_topology_ipv4_unicast_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_interface_isis_multi_topology_common(event, dnode, + ISIS_MT_IPV4_UNICAST); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-multicast + */ +int lib_interface_isis_multi_topology_ipv4_multicast_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_interface_isis_multi_topology_common(event, dnode, + ISIS_MT_IPV4_MULTICAST); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-management + */ +int lib_interface_isis_multi_topology_ipv4_management_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_interface_isis_multi_topology_common(event, dnode, + ISIS_MT_IPV4_MGMT); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-unicast + */ +int lib_interface_isis_multi_topology_ipv6_unicast_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_interface_isis_multi_topology_common(event, dnode, + ISIS_MT_IPV6_UNICAST); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-multicast + */ +int lib_interface_isis_multi_topology_ipv6_multicast_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_interface_isis_multi_topology_common(event, dnode, + ISIS_MT_IPV6_MULTICAST); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-management + */ +int lib_interface_isis_multi_topology_ipv6_management_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_interface_isis_multi_topology_common(event, dnode, + ISIS_MT_IPV6_MGMT); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-dstsrc + */ +int lib_interface_isis_multi_topology_ipv6_dstsrc_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + return lib_interface_isis_multi_topology_common(event, dnode, + ISIS_MT_IPV6_DSTSRC); +} diff --git a/isisd/isis_nb_notifications.c b/isisd/isis_nb_notifications.c new file mode 100644 index 0000000000..ea33ec10ec --- /dev/null +++ b/isisd/isis_nb_notifications.c @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2018 Volta Networks + * Emanuele Di Pascale + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "northbound.h" +#include "log.h" + +#include "isisd/isisd.h" +#include "isisd/isis_nb.h" +#include "isisd/isis_adjacency.h" +#include "isisd/isis_dynhn.h" +#include "isisd/isis_misc.h" + +/* + * Helper functions. + */ +static void notif_prep_instance_hdr(const char *xpath, + const struct isis_area *area, + const char *routing_instance, + struct list *args) +{ + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + + snprintf(xpath_arg, sizeof(xpath_arg), "%s/routing-instance", xpath); + data = yang_data_new_string(xpath_arg, routing_instance); + listnode_add(args, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/routing-protocol-name", + xpath); + data = yang_data_new_string(xpath_arg, area->area_tag); + listnode_add(args, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/isis-level", xpath); + data = yang_data_new_enum(xpath_arg, area->is_type); + listnode_add(args, data); +} + +static void notif_prepr_iface_hdr(const char *xpath, + const struct isis_circuit *circuit, + struct list *args) +{ + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + + snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath); + data = yang_data_new_string(xpath_arg, circuit->interface->name); + listnode_add(args, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-level", xpath); + data = yang_data_new_enum(xpath_arg, circuit->is_type); + listnode_add(args, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/extended-circuit-id", xpath); + /* we do not seem to have the extended version of the circuit_id */ + data = yang_data_new_uint32(xpath_arg, (uint32_t)circuit->circuit_id); + listnode_add(args, data); +} + +/* + * XPath: /frr-isisd:database-overload + */ +void isis_notif_db_overload(const struct isis_area *area, bool overload) +{ + const char *xpath = "/frr-isisd:database-overload"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/overload", xpath); + data = yang_data_new_enum(xpath_arg, !!overload); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:lsp-too-large + */ +void isis_notif_lsp_too_large(const struct isis_circuit *circuit, + uint32_t pdu_size, const char *lsp_id) +{ + const char *xpath = "/frr-isisd:lsp-too-large"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/pdu-size", xpath); + data = yang_data_new_uint32(xpath_arg, pdu_size); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); + data = yang_data_new_string(xpath_arg, lsp_id); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:if-state-change + */ +void isis_notif_if_state_change(const struct isis_circuit *circuit, bool down) +{ + const char *xpath = "/frr-isisd:if-state-change"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath); + data = yang_data_new_enum(xpath_arg, !!down); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:corrupted-lsp-detected + */ +void isis_notif_corrupted_lsp(const struct isis_area *area, const char *lsp_id) +{ + const char *xpath = "/frr-isisd:corrupted-lsp-detected"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); + data = yang_data_new_string(xpath_arg, lsp_id); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:attempt-to-exceed-max-sequence + */ +void isis_notif_lsp_exceed_max(const struct isis_area *area, const char *lsp_id) +{ + const char *xpath = "/frr-isisd:attempt-to-exceed-max-sequence"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); + data = yang_data_new_string(xpath_arg, lsp_id); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:max-area-addresses-mismatch + */ +void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit, + uint8_t max_area_addrs, + const char *raw_pdu) +{ + const char *xpath = "/frr-isisd:max-area-addresses-mismatch"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/max-area-addresses", xpath); + data = yang_data_new_uint8(xpath_arg, max_area_addrs); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:authentication-type-failure + */ +void isis_notif_authentication_type_failure(const struct isis_circuit *circuit, + const char *raw_pdu) +{ + const char *xpath = "/frr-isisd:authentication-type-failure"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:authentication-failure + */ +void isis_notif_authentication_failure(const struct isis_circuit *circuit, + const char *raw_pdu) +{ + const char *xpath = "/frr-isisd:authentication-failure"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:adjacency-state-change + */ +void isis_notif_adj_state_change(const struct isis_adjacency *adj, + int new_state, const char *reason) +{ + const char *xpath = "/frr-isisd:adjacency-state-change"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_circuit *circuit = adj->circuit; + struct isis_area *area = circuit->area; + struct isis_dynhn *dyn = dynhn_find_by_id(adj->sysid); + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + if (dyn) { + snprintf(xpath_arg, sizeof(xpath_arg), "%s/neighbor", xpath); + data = yang_data_new_string(xpath_arg, dyn->hostname); + listnode_add(arguments, data); + } + snprintf(xpath_arg, sizeof(xpath_arg), "%s/neighbor-system-id", xpath); + data = yang_data_new_string(xpath_arg, sysid_print(adj->sysid)); + listnode_add(arguments, data); + + snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath); + data = yang_data_new_string(xpath_arg, isis_adj_yang_state(new_state)); + listnode_add(arguments, data); + if (new_state == ISIS_ADJ_DOWN) { + snprintf(xpath_arg, sizeof(xpath_arg), "%s/reason", xpath); + data = yang_data_new_string(xpath_arg, reason); + listnode_add(arguments, data); + } + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:rejected-adjacency + */ +void isis_notif_reject_adjacency(const struct isis_circuit *circuit, + const char *reason, const char *raw_pdu) +{ + const char *xpath = "/frr-isisd:rejected-adjacency"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/reason", xpath); + data = yang_data_new_string(xpath_arg, reason); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:area-mismatch + */ +void isis_notif_area_mismatch(const struct isis_circuit *circuit, + const char *raw_pdu) +{ + const char *xpath = "/frr-isisd:area-mismatch"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:lsp-received + */ +void isis_notif_lsp_received(const struct isis_circuit *circuit, + const char *lsp_id, uint32_t seqno, + uint32_t timestamp, const char *sys_id) +{ + const char *xpath = "/frr-isisd:lsp-received"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); + data = yang_data_new_string(xpath_arg, lsp_id); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath); + data = yang_data_new_uint32(xpath_arg, seqno); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/received-timestamp", xpath); + data = yang_data_new_uint32(xpath_arg, timestamp); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/neighbor-system-id", xpath); + data = yang_data_new_string(xpath_arg, sys_id); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:lsp-generation + */ +void isis_notif_lsp_gen(const struct isis_area *area, const char *lsp_id, + uint32_t seqno, uint32_t timestamp) +{ + const char *xpath = "/frr-isisd:lsp-generation"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); + data = yang_data_new_string(xpath_arg, lsp_id); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath); + data = yang_data_new_uint32(xpath_arg, seqno); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/send-timestamp", xpath); + data = yang_data_new_uint32(xpath_arg, timestamp); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:id-len-mismatch + */ +void isis_notif_id_len_mismatch(const struct isis_circuit *circuit, + uint8_t rcv_id_len, const char *raw_pdu) +{ + const char *xpath = "/frr-isisd:id-len-mismatch"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/pdu-field-len", xpath); + data = yang_data_new_uint8(xpath_arg, rcv_id_len); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:version-skew + */ +void isis_notif_version_skew(const struct isis_circuit *circuit, + uint8_t version, const char *raw_pdu) +{ + const char *xpath = "/frr-isisd:version-skew"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/protocol-version", xpath); + data = yang_data_new_uint8(xpath_arg, version); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:lsp-error-detected + */ +void isis_notif_lsp_error(const struct isis_circuit *circuit, + const char *lsp_id, const char *raw_pdu, + __attribute__((unused)) uint32_t offset, + __attribute__((unused)) uint8_t tlv_type) +{ + const char *xpath = "/frr-isisd:lsp-error-detected"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); + data = yang_data_new_string(xpath_arg, lsp_id); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + /* ignore offset and tlv_type which cannot be set properly */ + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:sequence-number-skipped + */ +void isis_notif_seqno_skipped(const struct isis_circuit *circuit, + const char *lsp_id) +{ + const char *xpath = "/frr-isisd:sequence-number-skipped"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); + data = yang_data_new_string(xpath_arg, lsp_id); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-isisd:own-lsp-purge + */ +void isis_notif_own_lsp_purge(const struct isis_circuit *circuit, + const char *lsp_id) +{ + const char *xpath = "/frr-isisd:own-lsp-purge"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); + data = yang_data_new_string(xpath_arg, lsp_id); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} diff --git a/isisd/isis_nb_state.c b/isisd/isis_nb_state.c new file mode 100644 index 0000000000..e52d0201d5 --- /dev/null +++ b/isisd/isis_nb_state.c @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2018 Volta Networks + * Emanuele Di Pascale + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "northbound.h" +#include "linklist.h" + +#include "isisd/isisd.h" +#include "isisd/isis_nb.h" +#include "isisd/isis_circuit.h" +#include "isisd/isis_adjacency.h" +#include "isisd/isis_misc.h" + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency + */ +const void * +lib_interface_isis_adjacencies_adjacency_get_next(const void *parent_list_entry, + const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + struct isis_adjacency *adj, *adj_next = NULL; + struct list *list; + struct listnode *node, *node_next; + + /* Get first adjacency. */ + if (list_entry == NULL) { + ifp = (struct interface *)parent_list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; + level++) { + adj = listnode_head( + circuit->u.bc.adjdb[level - 1]); + if (adj) + break; + } + break; + case CIRCUIT_T_P2P: + adj = circuit->u.p2p.neighbor; + break; + default: + adj = NULL; + break; + } + + return adj; + } + + /* Get next adjacency. */ + adj = (struct isis_adjacency *)list_entry; + circuit = adj->circuit; + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + list = circuit->u.bc.adjdb[adj->level - 1]; + node = listnode_lookup(list, adj); + node_next = listnextnode(node); + if (node_next) + adj_next = listgetdata(node_next); + else if (adj->level == ISIS_LEVEL1) { + /* + * Once we finish the L1 adjacencies, move to the L2 + * adjacencies list. + */ + list = circuit->u.bc.adjdb[ISIS_LEVEL2 - 1]; + adj_next = listnode_head(list); + } + break; + case CIRCUIT_T_P2P: + /* P2P circuits have at most one adjacency. */ + default: + break; + } + + return adj_next; +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type + */ +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_enum(xpath, adj->level); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid + */ +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, sysid_print(adj->sysid)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id + */ +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint32(xpath, adj->circuit->circuit_id); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa + */ +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, snpa_print(adj->snpa)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer + */ +struct yang_data *lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint16(xpath, adj->hold_time); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority + */ +struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint8(xpath, adj->prio[adj->level - 1]); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state + */ +struct yang_data * +lib_interface_isis_adjacencies_adjacency_state_get_elem(const char *xpath, + const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, isis_adj_yang_state(adj->adj_state)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes + */ +struct yang_data *lib_interface_isis_event_counters_adjacency_changes_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->adj_state_changes); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number + */ +struct yang_data *lib_interface_isis_event_counters_adjacency_number_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + struct isis_adjacency *adj; + struct listnode *node; + uint32_t total = 0; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + /* + * TODO: keep track of the number of adjacencies instead of calculating + * it on demand. + */ + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { + for (ALL_LIST_ELEMENTS_RO( + circuit->u.bc.adjdb[level - 1], node, adj)) + total++; + } + break; + case CIRCUIT_T_P2P: + adj = circuit->u.p2p.neighbor; + if (adj) + total = 1; + break; + default: + break; + } + + return yang_data_new_uint32(xpath, total); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails + */ +struct yang_data * +lib_interface_isis_event_counters_init_fails_get_elem(const char *xpath, + const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->init_failures); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects + */ +struct yang_data *lib_interface_isis_event_counters_adjacency_rejects_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->rej_adjacencies); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch + */ +struct yang_data *lib_interface_isis_event_counters_id_len_mismatch_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->id_len_mismatches); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch + */ +struct yang_data * +lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->max_area_addr_mismatches); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails + */ +struct yang_data * +lib_interface_isis_event_counters_authentication_type_fails_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->auth_type_failures); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails + */ +struct yang_data * +lib_interface_isis_event_counters_authentication_fails_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->auth_failures); +} diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c deleted file mode 100644 index 97b7ae4f7e..0000000000 --- a/isisd/isis_northbound.c +++ /dev/null @@ -1,3932 +0,0 @@ -/* - * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology - * Institute of Communications Engineering - * Copyright (C) 2018 Volta Networks - * Emanuele Di Pascale - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include "northbound.h" -#include "libfrr.h" -#include "linklist.h" -#include "log.h" -#include "lib/bfd.h" -#include "isisd/isis_bfd.h" -#include "isisd/isis_constants.h" -#include "isisd/isis_common.h" -#include "isisd/isis_flags.h" -#include "isisd/isis_circuit.h" -#include "isisd/isisd.h" -#include "isisd/isis_lsp.h" -#include "isisd/isis_pdu.h" -#include "isisd/isis_dynhn.h" -#include "isisd/isis_misc.h" -#include "isisd/isis_csm.h" -#include "isisd/isis_adjacency.h" -#include "isisd/isis_spf.h" -#include "isisd/isis_te.h" -#include "isisd/isis_memory.h" -#include "isisd/isis_mt.h" -#include "isisd/isis_cli.h" -#include "isisd/isis_redist.h" -#include "lib/spf_backoff.h" -#include "lib/lib_errors.h" -#include "lib/vrf.h" - -/* - * Helper functions. - */ -static const char *isis_yang_adj_state(enum isis_adj_state state) -{ - switch (state) { - case ISIS_ADJ_DOWN: - return "down"; - case ISIS_ADJ_UP: - return "up"; - case ISIS_ADJ_INITIALIZING: - return "init"; - default: - return "failed"; - } -} - -/* - * XPath: /frr-isisd:isis/instance - */ -static int isis_instance_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - const char *area_tag; - - if (event != NB_EV_APPLY) - return NB_OK; - - area_tag = yang_dnode_get_string(dnode, "./area-tag"); - area = isis_area_lookup(area_tag); - if (area) - return NB_ERR_INCONSISTENCY; - - area = isis_area_create(area_tag); - /* save area in dnode to avoid looking it up all the time */ - nb_running_set_entry(dnode, area); - - return NB_OK; -} - -static int isis_instance_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_unset_entry(dnode); - isis_area_destroy(area->area_tag); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/is-type - */ -static int isis_instance_is_type_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, NULL); - isis_area_is_type_set(area, type); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/area-address - */ -static int isis_instance_area_address_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - struct area_addr addr, *addrr = NULL, *addrp = NULL; - struct listnode *node; - uint8_t buff[255]; - const char *net_title = yang_dnode_get_string(dnode, NULL); - - switch (event) { - case NB_EV_VALIDATE: - addr.addr_len = dotformat2buff(buff, net_title); - memcpy(addr.area_addr, buff, addr.addr_len); - if (addr.area_addr[addr.addr_len - 1] != 0) { - flog_warn( - EC_LIB_NB_CB_CONFIG_VALIDATE, - "nsel byte (last byte) in area address must be 0"); - return NB_ERR_VALIDATION; - } - if (isis->sysid_set) { - /* Check that the SystemID portions match */ - if (memcmp(isis->sysid, GETSYSID((&addr)), - ISIS_SYS_ID_LEN)) { - flog_warn( - EC_LIB_NB_CB_CONFIG_VALIDATE, - "System ID must not change when defining additional area addresses"); - return NB_ERR_VALIDATION; - } - } - break; - case NB_EV_PREPARE: - addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr)); - addrr->addr_len = dotformat2buff(buff, net_title); - memcpy(addrr->area_addr, buff, addrr->addr_len); - resource->ptr = addrr; - break; - case NB_EV_ABORT: - XFREE(MTYPE_ISIS_AREA_ADDR, resource->ptr); - break; - case NB_EV_APPLY: - area = nb_running_get_entry(dnode, NULL, true); - addrr = resource->ptr; - - if (isis->sysid_set == 0) { - /* - * First area address - get the SystemID for this router - */ - memcpy(isis->sysid, GETSYSID(addrr), ISIS_SYS_ID_LEN); - isis->sysid_set = 1; - } else { - /* check that we don't already have this address */ - for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, - addrp)) { - if ((addrp->addr_len + ISIS_SYS_ID_LEN - + ISIS_NSEL_LEN) - != (addrr->addr_len)) - continue; - if (!memcmp(addrp->area_addr, addrr->area_addr, - addrr->addr_len)) { - XFREE(MTYPE_ISIS_AREA_ADDR, addrr); - return NB_OK; /* silent fail */ - } - } - } - - /*Forget the systemID part of the address */ - addrr->addr_len -= (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN); - assert(area->area_addrs); /* to silence scan-build sillyness */ - listnode_add(area->area_addrs, addrr); - - /* only now we can safely generate our LSPs for this area */ - if (listcount(area->area_addrs) > 0) { - if (area->is_type & IS_LEVEL_1) - lsp_generate(area, IS_LEVEL_1); - if (area->is_type & IS_LEVEL_2) - lsp_generate(area, IS_LEVEL_2); - } - break; - } - - return NB_OK; -} - -static int isis_instance_area_address_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct area_addr addr, *addrp = NULL; - struct listnode *node; - uint8_t buff[255]; - struct isis_area *area; - const char *net_title; - - if (event != NB_EV_APPLY) - return NB_OK; - - net_title = yang_dnode_get_string(dnode, NULL); - addr.addr_len = dotformat2buff(buff, net_title); - memcpy(addr.area_addr, buff, (int)addr.addr_len); - area = nb_running_get_entry(dnode, NULL, true); - for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) { - if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len - && !memcmp(addrp->area_addr, addr.area_addr, addr.addr_len)) - break; - } - if (!addrp) - return NB_ERR_INCONSISTENCY; - - listnode_delete(area->area_addrs, addrp); - XFREE(MTYPE_ISIS_AREA_ADDR, addrp); - /* - * Last area address - reset the SystemID for this router - */ - if (listcount(area->area_addrs) == 0) { - memset(isis->sysid, 0, ISIS_SYS_ID_LEN); - isis->sysid_set = 0; - if (isis->debugs & DEBUG_EVENTS) - zlog_debug("Router has no SystemID"); - } - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/dynamic-hostname - */ -static int isis_instance_dynamic_hostname_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - isis_area_dynhostname_set(area, yang_dnode_get_bool(dnode, NULL)); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/attached - */ -static int isis_instance_attached_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - bool attached; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - attached = yang_dnode_get_bool(dnode, NULL); - isis_area_attached_bit_set(area, attached); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/overload - */ -static int isis_instance_overload_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - bool overload; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - overload = yang_dnode_get_bool(dnode, NULL); - isis_area_overload_bit_set(area, overload); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/metric-style - */ -static int isis_instance_metric_style_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - bool old_metric, new_metric; - enum isis_metric_style metric_style = yang_dnode_get_enum(dnode, NULL); - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - old_metric = (metric_style == ISIS_WIDE_METRIC) ? false : true; - new_metric = (metric_style == ISIS_NARROW_METRIC) ? false : true; - isis_area_metricstyle_set(area, old_metric, new_metric); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/purge-originator - */ -static int isis_instance_purge_originator_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - area->purge_originator = yang_dnode_get_bool(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/lsp/mtu - */ -static int isis_instance_lsp_mtu_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct listnode *node; - struct isis_circuit *circuit; - uint16_t lsp_mtu = yang_dnode_get_uint16(dnode, NULL); - struct isis_area *area; - - switch (event) { - case NB_EV_VALIDATE: - area = nb_running_get_entry(dnode, NULL, false); - if (!area) - break; - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { - if (circuit->state != C_STATE_INIT - && circuit->state != C_STATE_UP) - continue; - if (lsp_mtu > isis_circuit_pdu_size(circuit)) { - flog_warn( - EC_LIB_NB_CB_CONFIG_VALIDATE, - "ISIS area contains circuit %s, which has a maximum PDU size of %zu", - circuit->interface->name, - isis_circuit_pdu_size(circuit)); - return NB_ERR_VALIDATION; - } - } - break; - case NB_EV_PREPARE: - case NB_EV_ABORT: - break; - case NB_EV_APPLY: - area = nb_running_get_entry(dnode, NULL, true); - isis_area_lsp_mtu_set(area, lsp_mtu); - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/lsp/refresh-interval/level-1 - */ -static int -isis_instance_lsp_refresh_interval_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - uint16_t refr_int; - - if (event != NB_EV_APPLY) - return NB_OK; - - refr_int = yang_dnode_get_uint16(dnode, NULL); - area = nb_running_get_entry(dnode, NULL, true); - isis_area_lsp_refresh_set(area, IS_LEVEL_1, refr_int); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/lsp/refresh-interval/level-2 - */ -static int -isis_instance_lsp_refresh_interval_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - uint16_t refr_int; - - if (event != NB_EV_APPLY) - return NB_OK; - - refr_int = yang_dnode_get_uint16(dnode, NULL); - area = nb_running_get_entry(dnode, NULL, true); - isis_area_lsp_refresh_set(area, IS_LEVEL_2, refr_int); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/lsp/maximum-lifetime/level-1 - */ -static int -isis_instance_lsp_maximum_lifetime_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - uint16_t max_lt; - - if (event != NB_EV_APPLY) - return NB_OK; - - max_lt = yang_dnode_get_uint16(dnode, NULL); - area = nb_running_get_entry(dnode, NULL, true); - isis_area_max_lsp_lifetime_set(area, IS_LEVEL_1, max_lt); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/lsp/maximum-lifetime/level-2 - */ -static int -isis_instance_lsp_maximum_lifetime_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - uint16_t max_lt; - - if (event != NB_EV_APPLY) - return NB_OK; - - max_lt = yang_dnode_get_uint16(dnode, NULL); - area = nb_running_get_entry(dnode, NULL, true); - isis_area_max_lsp_lifetime_set(area, IS_LEVEL_2, max_lt); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/lsp/generation-interval/level-1 - */ -static int isis_instance_lsp_generation_interval_level_1_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - uint16_t gen_int; - - if (event != NB_EV_APPLY) - return NB_OK; - - gen_int = yang_dnode_get_uint16(dnode, NULL); - area = nb_running_get_entry(dnode, NULL, true); - area->lsp_gen_interval[0] = gen_int; - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/lsp/generation-interval/level-2 - */ -static int isis_instance_lsp_generation_interval_level_2_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - uint16_t gen_int; - - if (event != NB_EV_APPLY) - return NB_OK; - - gen_int = yang_dnode_get_uint16(dnode, NULL); - area = nb_running_get_entry(dnode, NULL, true); - area->lsp_gen_interval[1] = gen_int; - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay - */ -static void ietf_backoff_delay_apply_finish(const struct lyd_node *dnode) -{ - long init_delay = yang_dnode_get_uint16(dnode, "./init-delay"); - long short_delay = yang_dnode_get_uint16(dnode, "./short-delay"); - long long_delay = yang_dnode_get_uint16(dnode, "./long-delay"); - long holddown = yang_dnode_get_uint16(dnode, "./hold-down"); - long timetolearn = yang_dnode_get_uint16(dnode, "./time-to-learn"); - struct isis_area *area = nb_running_get_entry(dnode, NULL, true); - size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx"); - char *buf = XCALLOC(MTYPE_TMP, bufsiz); - - snprintf(buf, bufsiz, "IS-IS %s L1", area->area_tag); - spf_backoff_free(area->spf_delay_ietf[0]); - area->spf_delay_ietf[0] = - spf_backoff_new(master, buf, init_delay, short_delay, - long_delay, holddown, timetolearn); - - snprintf(buf, bufsiz, "IS-IS %s L2", area->area_tag); - spf_backoff_free(area->spf_delay_ietf[1]); - area->spf_delay_ietf[1] = - spf_backoff_new(master, buf, init_delay, short_delay, - long_delay, holddown, timetolearn); - - XFREE(MTYPE_TMP, buf); -} - -static int -isis_instance_spf_ietf_backoff_delay_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* All the work is done in the apply_finish */ - return NB_OK; -} - -static int -isis_instance_spf_ietf_backoff_delay_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - spf_backoff_free(area->spf_delay_ietf[0]); - spf_backoff_free(area->spf_delay_ietf[1]); - area->spf_delay_ietf[0] = NULL; - area->spf_delay_ietf[1] = NULL; - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/init-delay - */ -static int isis_instance_spf_ietf_backoff_delay_init_delay_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* All the work is done in the apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/short-delay - */ -static int isis_instance_spf_ietf_backoff_delay_short_delay_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* All the work is done in the apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/long-delay - */ -static int isis_instance_spf_ietf_backoff_delay_long_delay_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* All the work is done in the apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/hold-down - */ -static int isis_instance_spf_ietf_backoff_delay_hold_down_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* All the work is done in the apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/time-to-learn - */ -static int isis_instance_spf_ietf_backoff_delay_time_to_learn_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* All the work is done in the apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/spf/minimum-interval/level-1 - */ -static int -isis_instance_spf_minimum_interval_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - area->min_spf_interval[0] = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/spf/minimum-interval/level-2 - */ -static int -isis_instance_spf_minimum_interval_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - area->min_spf_interval[1] = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/area-password - */ -static void area_password_apply_finish(const struct lyd_node *dnode) -{ - const char *password = yang_dnode_get_string(dnode, "./password"); - struct isis_area *area = nb_running_get_entry(dnode, NULL, true); - int pass_type = yang_dnode_get_enum(dnode, "./password-type"); - uint8_t snp_auth = yang_dnode_get_enum(dnode, "./authenticate-snp"); - - switch (pass_type) { - case ISIS_PASSWD_TYPE_CLEARTXT: - isis_area_passwd_cleartext_set(area, IS_LEVEL_1, password, - snp_auth); - break; - case ISIS_PASSWD_TYPE_HMAC_MD5: - isis_area_passwd_hmac_md5_set(area, IS_LEVEL_1, password, - snp_auth); - break; - } -} - -static int isis_instance_area_password_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* actual setting is done in apply_finish */ - return NB_OK; -} - -static int isis_instance_area_password_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - isis_area_passwd_unset(area, IS_LEVEL_1); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/area-password/password - */ -static int -isis_instance_area_password_password_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* actual setting is done in apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/area-password/password-type - */ -static int -isis_instance_area_password_password_type_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* actual setting is done in apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/area-password/authenticate-snp - */ -static int isis_instance_area_password_authenticate_snp_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* actual setting is done in apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/domain-password - */ -static void domain_password_apply_finish(const struct lyd_node *dnode) -{ - const char *password = yang_dnode_get_string(dnode, "./password"); - struct isis_area *area = nb_running_get_entry(dnode, NULL, true); - int pass_type = yang_dnode_get_enum(dnode, "./password-type"); - uint8_t snp_auth = yang_dnode_get_enum(dnode, "./authenticate-snp"); - - switch (pass_type) { - case ISIS_PASSWD_TYPE_CLEARTXT: - isis_area_passwd_cleartext_set(area, IS_LEVEL_2, password, - snp_auth); - break; - case ISIS_PASSWD_TYPE_HMAC_MD5: - isis_area_passwd_hmac_md5_set(area, IS_LEVEL_2, password, - snp_auth); - break; - } -} - -static int isis_instance_domain_password_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* actual setting is done in apply_finish */ - return NB_OK; -} - -static int isis_instance_domain_password_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - isis_area_passwd_unset(area, IS_LEVEL_2); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/domain-password/password - */ -static int -isis_instance_domain_password_password_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* actual setting is done in apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/domain-password/password-type - */ -static int -isis_instance_domain_password_password_type_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* actual setting is done in apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/domain-password/authenticate-snp - */ -static int isis_instance_domain_password_authenticate_snp_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* actual setting is done in apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4 - */ -static void default_info_origin_apply_finish(const struct lyd_node *dnode, - int family) -{ - int originate_type = DEFAULT_ORIGINATE; - unsigned long metric = 0; - const char *routemap = NULL; - struct isis_area *area = nb_running_get_entry(dnode, NULL, true); - int level = yang_dnode_get_enum(dnode, "./level"); - - if (yang_dnode_get_bool(dnode, "./always")) { - originate_type = DEFAULT_ORIGINATE_ALWAYS; - } else if (family == AF_INET6) { - zlog_warn( - "%s: Zebra doesn't implement default-originate for IPv6 yet, so use with care or use default-originate always.", - __func__); - } - - if (yang_dnode_exists(dnode, "./metric")) - metric = yang_dnode_get_uint32(dnode, "./metric"); - if (yang_dnode_exists(dnode, "./route-map")) - routemap = yang_dnode_get_string(dnode, "./route-map"); - - isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, - originate_type); -} - -static void default_info_origin_ipv4_apply_finish(const struct lyd_node *dnode) -{ - default_info_origin_apply_finish(dnode, AF_INET); -} - -static void default_info_origin_ipv6_apply_finish(const struct lyd_node *dnode) -{ - default_info_origin_apply_finish(dnode, AF_INET6); -} - -static int isis_instance_default_information_originate_ipv4_create( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -static int isis_instance_default_information_originate_ipv4_destroy( - enum nb_event event, const struct lyd_node *dnode) -{ - struct isis_area *area; - int level; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - level = yang_dnode_get_enum(dnode, "./level"); - isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/always - */ -static int isis_instance_default_information_originate_ipv4_always_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/route-map - */ -static int isis_instance_default_information_originate_ipv4_route_map_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -static int isis_instance_default_information_originate_ipv4_route_map_destroy( - enum nb_event event, const struct lyd_node *dnode) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/metric - */ -static int isis_instance_default_information_originate_ipv4_metric_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6 - */ -static int isis_instance_default_information_originate_ipv6_create( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -static int isis_instance_default_information_originate_ipv6_destroy( - enum nb_event event, const struct lyd_node *dnode) -{ - struct isis_area *area; - int level; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - level = yang_dnode_get_enum(dnode, "./level"); - isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/always - */ -static int isis_instance_default_information_originate_ipv6_always_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/route-map - */ -static int isis_instance_default_information_originate_ipv6_route_map_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -static int isis_instance_default_information_originate_ipv6_route_map_destroy( - enum nb_event event, const struct lyd_node *dnode) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/metric - */ -static int isis_instance_default_information_originate_ipv6_metric_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by default_info_origin_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/redistribute/ipv4 - */ -static void redistribute_apply_finish(const struct lyd_node *dnode, int family) -{ - assert(family == AF_INET || family == AF_INET6); - int type, level; - unsigned long metric = 0; - const char *routemap = NULL; - struct isis_area *area; - - type = yang_dnode_get_enum(dnode, "./protocol"); - level = yang_dnode_get_enum(dnode, "./level"); - area = nb_running_get_entry(dnode, NULL, true); - - if (yang_dnode_exists(dnode, "./metric")) - metric = yang_dnode_get_uint32(dnode, "./metric"); - if (yang_dnode_exists(dnode, "./route-map")) - routemap = yang_dnode_get_string(dnode, "./route-map"); - - isis_redist_set(area, level, family, type, metric, routemap, 0); -} - -static void redistribute_ipv4_apply_finish(const struct lyd_node *dnode) -{ - redistribute_apply_finish(dnode, AF_INET); -} - -static void redistribute_ipv6_apply_finish(const struct lyd_node *dnode) -{ - redistribute_apply_finish(dnode, AF_INET6); -} - -static int isis_instance_redistribute_ipv4_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by redistribute_apply_finish */ - return NB_OK; -} - -static int isis_instance_redistribute_ipv4_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_area *area; - int level, type; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - level = yang_dnode_get_enum(dnode, "./level"); - type = yang_dnode_get_enum(dnode, "./protocol"); - isis_redist_unset(area, level, AF_INET, type); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/redistribute/ipv4/route-map - */ -static int -isis_instance_redistribute_ipv4_route_map_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by redistribute_apply_finish */ - return NB_OK; -} - -static int -isis_instance_redistribute_ipv4_route_map_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - /* It's all done by redistribute_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/redistribute/ipv4/metric - */ -static int -isis_instance_redistribute_ipv4_metric_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by redistribute_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/redistribute/ipv6 - */ -static int isis_instance_redistribute_ipv6_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by redistribute_apply_finish */ - return NB_OK; -} - -static int isis_instance_redistribute_ipv6_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_area *area; - int level, type; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - level = yang_dnode_get_enum(dnode, "./level"); - type = yang_dnode_get_enum(dnode, "./protocol"); - isis_redist_unset(area, level, AF_INET6, type); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/redistribute/ipv6/route-map - */ -static int -isis_instance_redistribute_ipv6_route_map_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by redistribute_apply_finish */ - return NB_OK; -} - -static int -isis_instance_redistribute_ipv6_route_map_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - /* It's all done by redistribute_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/redistribute/ipv6/metric - */ -static int -isis_instance_redistribute_ipv6_metric_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - /* It's all done by redistribute_apply_finish */ - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast - */ -static int isis_multi_topology_common(enum nb_event event, - const struct lyd_node *dnode, - const char *topology, bool create) -{ - struct isis_area *area; - struct isis_area_mt_setting *setting; - uint16_t mtid = isis_str2mtid(topology); - - switch (event) { - case NB_EV_VALIDATE: - if (mtid == (uint16_t)-1) { - flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, - "Unknown topology %s", topology); - return NB_ERR_VALIDATION; - } - break; - case NB_EV_PREPARE: - case NB_EV_ABORT: - break; - case NB_EV_APPLY: - area = nb_running_get_entry(dnode, NULL, true); - setting = area_get_mt_setting(area, mtid); - setting->enabled = create; - lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); - break; - } - - return NB_OK; -} - -static int isis_multi_topology_overload_common(enum nb_event event, - const struct lyd_node *dnode, - const char *topology) -{ - struct isis_area *area; - struct isis_area_mt_setting *setting; - uint16_t mtid = isis_str2mtid(topology); - - /* validation is done in isis_multi_topology_common */ - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - setting = area_get_mt_setting(area, mtid); - setting->overload = yang_dnode_get_bool(dnode, NULL); - if (setting->enabled) - lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); - - return NB_OK; -} - -static int -isis_instance_multi_topology_ipv4_multicast_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_common(event, dnode, "ipv4-multicast", true); -} - -static int -isis_instance_multi_topology_ipv4_multicast_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - return isis_multi_topology_common(event, dnode, "ipv4-multicast", - false); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast/overload - */ -static int isis_instance_multi_topology_ipv4_multicast_overload_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_overload_common(event, dnode, - "ipv4-multicast"); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-management - */ -static int isis_instance_multi_topology_ipv4_management_create( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_common(event, dnode, "ipv4-mgmt", true); -} - -static int isis_instance_multi_topology_ipv4_management_destroy( - enum nb_event event, const struct lyd_node *dnode) -{ - return isis_multi_topology_common(event, dnode, "ipv4-mgmt", false); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-management/overload - */ -static int isis_instance_multi_topology_ipv4_management_overload_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_overload_common(event, dnode, "ipv4-mgmt"); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-unicast - */ -static int -isis_instance_multi_topology_ipv6_unicast_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_common(event, dnode, "ipv6-unicast", true); -} - -static int -isis_instance_multi_topology_ipv6_unicast_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - return isis_multi_topology_common(event, dnode, "ipv6-unicast", false); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-unicast/overload - */ -static int isis_instance_multi_topology_ipv6_unicast_overload_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_overload_common(event, dnode, - "ipv6-unicast"); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-multicast - */ -static int -isis_instance_multi_topology_ipv6_multicast_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_common(event, dnode, "ipv6-multicast", true); -} - -static int -isis_instance_multi_topology_ipv6_multicast_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - return isis_multi_topology_common(event, dnode, "ipv6-multicast", - false); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-multicast/overload - */ -static int isis_instance_multi_topology_ipv6_multicast_overload_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_overload_common(event, dnode, - "ipv6-multicast"); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-management - */ -static int isis_instance_multi_topology_ipv6_management_create( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_common(event, dnode, "ipv6-mgmt", true); -} - -static int isis_instance_multi_topology_ipv6_management_destroy( - enum nb_event event, const struct lyd_node *dnode) -{ - return isis_multi_topology_common(event, dnode, "ipv6-mgmt", false); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-management/overload - */ -static int isis_instance_multi_topology_ipv6_management_overload_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_overload_common(event, dnode, "ipv6-mgmt"); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-dstsrc - */ -static int -isis_instance_multi_topology_ipv6_dstsrc_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_common(event, dnode, "ipv6-dstsrc", true); -} - -static int -isis_instance_multi_topology_ipv6_dstsrc_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - return isis_multi_topology_common(event, dnode, "ipv6-dstsrc", false); -} - -/* - * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-dstsrc/overload - */ -static int isis_instance_multi_topology_ipv6_dstsrc_overload_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return isis_multi_topology_overload_common(event, dnode, "ipv6-dstsrc"); -} - -/* - * XPath: /frr-isisd:isis/instance/log-adjacency-changes - */ -static int -isis_instance_log_adjacency_changes_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - bool log = yang_dnode_get_bool(dnode, NULL); - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - area->log_adj_changes = log ? 1 : 0; - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/mpls-te - */ -static int isis_instance_mpls_te_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct listnode *node; - struct isis_area *area; - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - if (area->mta == NULL) { - - struct mpls_te_area *new; - - zlog_debug("ISIS-TE(%s): Initialize MPLS Traffic Engineering", - area->area_tag); - - new = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_area)); - - /* Initialize MPLS_TE structure */ - new->status = enable; - new->level = 0; - new->inter_as = off; - new->interas_areaid.s_addr = 0; - new->router_id.s_addr = 0; - - area->mta = new; - } else { - area->mta->status = enable; - } - - /* Update Extended TLVs according to Interface link parameters */ - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) - isis_link_params_update(circuit, circuit->interface); - - /* Reoriginate STD_TE & GMPLS circuits */ - lsp_regenerate_schedule(area, area->is_type, 0); - - return NB_OK; -} - -static int isis_instance_mpls_te_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct listnode *node; - struct isis_area *area; - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - if (IS_MPLS_TE(area->mta)) - area->mta->status = disable; - else - return NB_OK; - - /* Flush LSP if circuit engage */ - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { - if (!IS_EXT_TE(circuit->ext)) - continue; - - /* disable MPLS_TE Circuit keeping SR one's */ - if (IS_SUBTLV(circuit->ext, EXT_ADJ_SID)) - circuit->ext->status = EXT_ADJ_SID; - else if (IS_SUBTLV(circuit->ext, EXT_LAN_ADJ_SID)) - circuit->ext->status = EXT_LAN_ADJ_SID; - else - circuit->ext->status = 0; - } - - /* Reoriginate STD_TE & GMPLS circuits */ - lsp_regenerate_schedule(area, area->is_type, 0); - - zlog_debug("ISIS-TE(%s): Disabled MPLS Traffic Engineering", - area->area_tag); - - return NB_OK; -} - -/* - * XPath: /frr-isisd:isis/instance/mpls-te/router-address - */ -static int isis_instance_mpls_te_router_address_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct in_addr value; - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - /* only proceed if MPLS-TE is enabled */ - if (!IS_MPLS_TE(area->mta)) - return NB_OK; - - /* Update Area Router ID */ - yang_dnode_get_ipv4(&value, dnode, NULL); - area->mta->router_id.s_addr = value.s_addr; - - /* And re-schedule LSP update */ - lsp_regenerate_schedule(area, area->is_type, 0); - - return NB_OK; -} - -static int isis_instance_mpls_te_router_address_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_area *area; - - if (event != NB_EV_APPLY) - return NB_OK; - - area = nb_running_get_entry(dnode, NULL, true); - /* only proceed if MPLS-TE is enabled */ - if (!IS_MPLS_TE(area->mta)) - return NB_OK; - - /* Reset Area Router ID */ - area->mta->router_id.s_addr = INADDR_ANY; - - /* And re-schedule LSP update */ - lsp_regenerate_schedule(area, area->is_type, 0); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis - */ -static int lib_interface_isis_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_area *area; - struct interface *ifp; - struct isis_circuit *circuit; - const char *area_tag = yang_dnode_get_string(dnode, "./area-tag"); - uint32_t min_mtu, actual_mtu; - - switch (event) { - case NB_EV_PREPARE: - case NB_EV_ABORT: - break; - case NB_EV_VALIDATE: - /* check if interface mtu is sufficient. If the area has not - * been created yet, assume default MTU for the area - */ - ifp = nb_running_get_entry(dnode, NULL, false); - /* zebra might not know yet about the MTU - nothing we can do */ - if (!ifp || ifp->mtu == 0) - break; - actual_mtu = - if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu; - area = isis_area_lookup(area_tag); - if (area) - min_mtu = area->lsp_mtu; - else -#ifndef FABRICD - min_mtu = yang_get_default_uint16( - "/frr-isisd:isis/instance/lsp/mtu"); -#else - min_mtu = DEFAULT_LSP_MTU; -#endif /* ifndef FABRICD */ - if (actual_mtu < min_mtu) { - flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, - "Interface %s has MTU %" PRIu32 - ", minimum MTU for the area is %" PRIu32 "", - ifp->name, actual_mtu, min_mtu); - return NB_ERR_VALIDATION; - } - break; - case NB_EV_APPLY: - area = isis_area_lookup(area_tag); - /* The area should have already be created. We are - * setting the priority of the global isis area creation - * slightly lower, so it should be executed first, but I - * cannot rely on that so here I have to check. - */ - if (!area) { - flog_err( - EC_LIB_NB_CB_CONFIG_APPLY, - "%s: attempt to create circuit for area %s before the area has been created", - __func__, area_tag); - abort(); - } - - ifp = nb_running_get_entry(dnode, NULL, true); - circuit = isis_circuit_create(area, ifp); - assert(circuit - && (circuit->state == C_STATE_CONF - || circuit->state == C_STATE_UP)); - nb_running_set_entry(dnode, circuit); - break; - } - - return NB_OK; -} - -static int lib_interface_isis_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_unset_entry(dnode); - if (!circuit) - return NB_ERR_INCONSISTENCY; - if (circuit->state == C_STATE_UP || circuit->state == C_STATE_CONF) - isis_csm_state_change(ISIS_DISABLE, circuit, circuit->area); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/area-tag - */ -static int lib_interface_isis_area_tag_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - struct interface *ifp; - struct vrf *vrf; - const char *area_tag, *ifname, *vrfname; - - if (event == NB_EV_VALIDATE) { - /* libyang doesn't like relative paths across module boundaries - */ - ifname = yang_dnode_get_string(dnode->parent->parent, "./name"); - vrfname = yang_dnode_get_string(dnode->parent->parent, "./vrf"); - vrf = vrf_lookup_by_name(vrfname); - assert(vrf); - ifp = if_lookup_by_name(ifname, vrf->vrf_id); - if (!ifp) - return NB_OK; - circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); - area_tag = yang_dnode_get_string(dnode, NULL); - if (circuit && circuit->area && circuit->area->area_tag - && strcmp(circuit->area->area_tag, area_tag)) { - flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, - "ISIS circuit is already defined on %s", - circuit->area->area_tag); - return NB_ERR_VALIDATION; - } - } - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type - */ -static int lib_interface_isis_circuit_type_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - int circ_type = yang_dnode_get_enum(dnode, NULL); - struct isis_circuit *circuit; - struct interface *ifp; - struct vrf *vrf; - const char *ifname, *vrfname; - - switch (event) { - case NB_EV_VALIDATE: - /* libyang doesn't like relative paths across module boundaries - */ - ifname = yang_dnode_get_string(dnode->parent->parent, "./name"); - vrfname = yang_dnode_get_string(dnode->parent->parent, "./vrf"); - vrf = vrf_lookup_by_name(vrfname); - assert(vrf); - ifp = if_lookup_by_name(ifname, vrf->vrf_id); - if (!ifp) - break; - circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); - if (circuit && circuit->state == C_STATE_UP - && circuit->area->is_type != IS_LEVEL_1_AND_2 - && circuit->area->is_type != circ_type) { - flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, - "Invalid circuit level for area %s", - circuit->area->area_tag); - return NB_ERR_VALIDATION; - } - break; - case NB_EV_PREPARE: - case NB_EV_ABORT: - break; - case NB_EV_APPLY: - circuit = nb_running_get_entry(dnode, NULL, true); - isis_circuit_is_type_set(circuit, circ_type); - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing - */ -static int lib_interface_isis_ipv4_routing_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - bool ipv4, ipv6; - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - ipv4 = yang_dnode_get_bool(dnode, NULL); - ipv6 = yang_dnode_get_bool(dnode, "../ipv6-routing"); - isis_circuit_af_set(circuit, ipv4, ipv6); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing - */ -static int lib_interface_isis_ipv6_routing_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - bool ipv4, ipv6; - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - ipv4 = yang_dnode_exists(dnode, "../ipv4-routing"); - ipv6 = yang_dnode_get_bool(dnode, NULL); - isis_circuit_af_set(circuit, ipv4, ipv6); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring - */ -static int lib_interface_isis_bfd_monitoring_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - bool bfd_monitoring; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - bfd_monitoring = yang_dnode_get_bool(dnode, NULL); - - if (bfd_monitoring) { - isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX, - BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, - true); - } else { - isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER); - bfd_info_free(&circuit->bfd_info); - } - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-1 - */ -static int -lib_interface_isis_csnp_interval_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->csnp_interval[0] = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-2 - */ -static int -lib_interface_isis_csnp_interval_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->csnp_interval[1] = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-1 - */ -static int -lib_interface_isis_psnp_interval_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->psnp_interval[0] = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-2 - */ -static int -lib_interface_isis_psnp_interval_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->psnp_interval[1] = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/padding - */ -static int lib_interface_isis_hello_padding_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->pad_hellos = yang_dnode_get_bool(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-1 - */ -static int -lib_interface_isis_hello_interval_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - uint32_t interval; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - interval = yang_dnode_get_uint32(dnode, NULL); - circuit->hello_interval[0] = interval; - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-2 - */ -static int -lib_interface_isis_hello_interval_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - uint32_t interval; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - interval = yang_dnode_get_uint32(dnode, NULL); - circuit->hello_interval[1] = interval; - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-1 - */ -static int -lib_interface_isis_hello_multiplier_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - uint16_t multi; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - multi = yang_dnode_get_uint16(dnode, NULL); - circuit->hello_multiplier[0] = multi; - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-2 - */ -static int -lib_interface_isis_hello_multiplier_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - uint16_t multi; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - multi = yang_dnode_get_uint16(dnode, NULL); - circuit->hello_multiplier[1] = multi; - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric/level-1 - */ -static int -lib_interface_isis_metric_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - unsigned int met; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - met = yang_dnode_get_uint32(dnode, NULL); - isis_circuit_metric_set(circuit, IS_LEVEL_1, met); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric/level-2 - */ -static int -lib_interface_isis_metric_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - unsigned int met; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - met = yang_dnode_get_uint32(dnode, NULL); - isis_circuit_metric_set(circuit, IS_LEVEL_2, met); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority/level-1 - */ -static int -lib_interface_isis_priority_level_1_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->priority[0] = yang_dnode_get_uint8(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority/level-2 - */ -static int -lib_interface_isis_priority_level_2_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->priority[1] = yang_dnode_get_uint8(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/network-type - */ -static int lib_interface_isis_network_type_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - int net_type = yang_dnode_get_enum(dnode, NULL); - - switch (event) { - case NB_EV_VALIDATE: - circuit = nb_running_get_entry(dnode, NULL, false); - if (!circuit) - break; - if (circuit->circ_type == CIRCUIT_T_LOOPBACK) { - flog_warn( - EC_LIB_NB_CB_CONFIG_VALIDATE, - "Cannot change network type on loopback interface"); - return NB_ERR_VALIDATION; - } - if (net_type == CIRCUIT_T_BROADCAST - && circuit->state == C_STATE_UP - && !if_is_broadcast(circuit->interface)) { - flog_warn( - EC_LIB_NB_CB_CONFIG_VALIDATE, - "Cannot configure non-broadcast interface for broadcast operation"); - return NB_ERR_VALIDATION; - } - break; - case NB_EV_PREPARE: - case NB_EV_ABORT: - break; - case NB_EV_APPLY: - circuit = nb_running_get_entry(dnode, NULL, true); - isis_circuit_circ_type_set(circuit, net_type); - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/passive - */ -static int lib_interface_isis_passive_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - struct isis_area *area; - struct interface *ifp; - bool passive = yang_dnode_get_bool(dnode, NULL); - - /* validation only applies if we are setting passive to false */ - if (!passive && event == NB_EV_VALIDATE) { - circuit = nb_running_get_entry(dnode, NULL, false); - if (!circuit) - return NB_OK; - ifp = circuit->interface; - if (!ifp) - return NB_OK; - if (if_is_loopback(ifp)) { - flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, - "Loopback is always passive"); - return NB_ERR_VALIDATION; - } - } - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - if (circuit->state != C_STATE_UP) { - circuit->is_passive = passive; - } else { - area = circuit->area; - isis_csm_state_change(ISIS_DISABLE, circuit, area); - circuit->is_passive = passive; - isis_csm_state_change(ISIS_ENABLE, circuit, area); - } - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/password - */ -static int lib_interface_isis_password_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - return NB_OK; -} - -static int lib_interface_isis_password_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - isis_circuit_passwd_unset(circuit); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/password/password - */ -static int -lib_interface_isis_password_password_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - const char *password; - - if (event != NB_EV_APPLY) - return NB_OK; - - password = yang_dnode_get_string(dnode, NULL); - circuit = nb_running_get_entry(dnode, NULL, true); - - isis_circuit_passwd_set(circuit, circuit->passwd.type, password); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/password/password-type - */ -static int -lib_interface_isis_password_password_type_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - uint8_t pass_type; - - if (event != NB_EV_APPLY) - return NB_OK; - - pass_type = yang_dnode_get_enum(dnode, NULL); - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->passwd.type = pass_type; - - return NB_OK; -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/disable-three-way-handshake - */ -static int lib_interface_isis_disable_three_way_handshake_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct isis_circuit *circuit; - - if (event != NB_EV_APPLY) - return NB_OK; - - circuit = nb_running_get_entry(dnode, NULL, true); - circuit->disable_threeway_adj = yang_dnode_get_bool(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-unicast - */ -static int lib_interface_isis_multi_topology_common( - enum nb_event event, const struct lyd_node *dnode, uint16_t mtid) -{ - struct isis_circuit *circuit; - bool value; - - switch (event) { - case NB_EV_VALIDATE: - circuit = nb_running_get_entry(dnode, NULL, false); - if (circuit && circuit->area && circuit->area->oldmetric) { - flog_warn( - EC_LIB_NB_CB_CONFIG_VALIDATE, - "Multi topology IS-IS can only be used with wide metrics"); - return NB_ERR_VALIDATION; - } - break; - case NB_EV_PREPARE: - case NB_EV_ABORT: - break; - case NB_EV_APPLY: - circuit = nb_running_get_entry(dnode, NULL, true); - value = yang_dnode_get_bool(dnode, NULL); - isis_circuit_mt_enabled_set(circuit, mtid, value); - break; - } - - return NB_OK; -} - -static int lib_interface_isis_multi_topology_ipv4_unicast_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return lib_interface_isis_multi_topology_common(event, dnode, - ISIS_MT_IPV4_UNICAST); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-multicast - */ -static int lib_interface_isis_multi_topology_ipv4_multicast_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return lib_interface_isis_multi_topology_common(event, dnode, - ISIS_MT_IPV4_MULTICAST); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-management - */ -static int lib_interface_isis_multi_topology_ipv4_management_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return lib_interface_isis_multi_topology_common(event, dnode, - ISIS_MT_IPV4_MGMT); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-unicast - */ -static int lib_interface_isis_multi_topology_ipv6_unicast_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return lib_interface_isis_multi_topology_common(event, dnode, - ISIS_MT_IPV6_UNICAST); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-multicast - */ -static int lib_interface_isis_multi_topology_ipv6_multicast_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return lib_interface_isis_multi_topology_common(event, dnode, - ISIS_MT_IPV6_MULTICAST); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-management - */ -static int lib_interface_isis_multi_topology_ipv6_management_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return lib_interface_isis_multi_topology_common(event, dnode, - ISIS_MT_IPV6_MGMT); -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-dstsrc - */ -static int lib_interface_isis_multi_topology_ipv6_dstsrc_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - return lib_interface_isis_multi_topology_common(event, dnode, - ISIS_MT_IPV6_DSTSRC); -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency - */ -static const void * -lib_interface_isis_adjacencies_adjacency_get_next(const void *parent_list_entry, - const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - struct isis_adjacency *adj, *adj_next = NULL; - struct list *list; - struct listnode *node, *node_next; - - /* Get first adjacency. */ - if (list_entry == NULL) { - ifp = (struct interface *)parent_list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - switch (circuit->circ_type) { - case CIRCUIT_T_BROADCAST: - for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; - level++) { - adj = listnode_head( - circuit->u.bc.adjdb[level - 1]); - if (adj) - break; - } - break; - case CIRCUIT_T_P2P: - adj = circuit->u.p2p.neighbor; - break; - default: - adj = NULL; - break; - } - - return adj; - } - - /* Get next adjacency. */ - adj = (struct isis_adjacency *)list_entry; - circuit = adj->circuit; - switch (circuit->circ_type) { - case CIRCUIT_T_BROADCAST: - list = circuit->u.bc.adjdb[adj->level - 1]; - node = listnode_lookup(list, adj); - node_next = listnextnode(node); - if (node_next) - adj_next = listgetdata(node_next); - else if (adj->level == ISIS_LEVEL1) { - /* - * Once we finish the L1 adjacencies, move to the L2 - * adjacencies list. - */ - list = circuit->u.bc.adjdb[ISIS_LEVEL2 - 1]; - adj_next = listnode_head(list); - } - break; - case CIRCUIT_T_P2P: - /* P2P circuits have at most one adjacency. */ - default: - break; - } - - return adj_next; -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type - */ -static struct yang_data * -lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem( - const char *xpath, const void *list_entry) -{ - const struct isis_adjacency *adj = list_entry; - - return yang_data_new_enum(xpath, adj->level); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid - */ -static struct yang_data * -lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem( - const char *xpath, const void *list_entry) -{ - const struct isis_adjacency *adj = list_entry; - - return yang_data_new_string(xpath, sysid_print(adj->sysid)); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id - */ -static struct yang_data * -lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem( - const char *xpath, const void *list_entry) -{ - const struct isis_adjacency *adj = list_entry; - - return yang_data_new_uint32(xpath, adj->circuit->circuit_id); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa - */ -static struct yang_data * -lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem( - const char *xpath, const void *list_entry) -{ - const struct isis_adjacency *adj = list_entry; - - return yang_data_new_string(xpath, snpa_print(adj->snpa)); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer - */ -static struct yang_data * -lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem( - const char *xpath, const void *list_entry) -{ - const struct isis_adjacency *adj = list_entry; - - return yang_data_new_uint16(xpath, adj->hold_time); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority - */ -static struct yang_data * -lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem( - const char *xpath, const void *list_entry) -{ - const struct isis_adjacency *adj = list_entry; - - return yang_data_new_uint8(xpath, adj->prio[adj->level - 1]); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state - */ -static struct yang_data * -lib_interface_isis_adjacencies_adjacency_state_get_elem(const char *xpath, - const void *list_entry) -{ - const struct isis_adjacency *adj = list_entry; - - return yang_data_new_string(xpath, isis_yang_adj_state(adj->adj_state)); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes - */ -static struct yang_data * -lib_interface_isis_event_counters_adjacency_changes_get_elem( - const char *xpath, const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *)list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - return yang_data_new_uint32(xpath, circuit->adj_state_changes); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number - */ -static struct yang_data * -lib_interface_isis_event_counters_adjacency_number_get_elem( - const char *xpath, const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - struct isis_adjacency *adj; - struct listnode *node; - uint32_t total = 0; - - ifp = (struct interface *)list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - /* - * TODO: keep track of the number of adjacencies instead of calculating - * it on demand. - */ - switch (circuit->circ_type) { - case CIRCUIT_T_BROADCAST: - for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { - for (ALL_LIST_ELEMENTS_RO( - circuit->u.bc.adjdb[level - 1], node, adj)) - total++; - } - break; - case CIRCUIT_T_P2P: - adj = circuit->u.p2p.neighbor; - if (adj) - total = 1; - break; - default: - break; - } - - return yang_data_new_uint32(xpath, total); -} - -/* - * XPath: /frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails - */ -static struct yang_data * -lib_interface_isis_event_counters_init_fails_get_elem(const char *xpath, - const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *)list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - return yang_data_new_uint32(xpath, circuit->init_failures); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects - */ -static struct yang_data * -lib_interface_isis_event_counters_adjacency_rejects_get_elem( - const char *xpath, const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *)list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - return yang_data_new_uint32(xpath, circuit->rej_adjacencies); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch - */ -static struct yang_data * -lib_interface_isis_event_counters_id_len_mismatch_get_elem( - const char *xpath, const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *)list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - return yang_data_new_uint32(xpath, circuit->id_len_mismatches); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch - */ -static struct yang_data * -lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem( - const char *xpath, const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *)list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - return yang_data_new_uint32(xpath, circuit->max_area_addr_mismatches); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails - */ -static struct yang_data * -lib_interface_isis_event_counters_authentication_type_fails_get_elem( - const char *xpath, const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *)list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - return yang_data_new_uint32(xpath, circuit->auth_type_failures); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails - */ -static struct yang_data * -lib_interface_isis_event_counters_authentication_fails_get_elem( - const char *xpath, const void *list_entry) -{ - struct interface *ifp; - struct isis_circuit *circuit; - - ifp = (struct interface *)list_entry; - if (!ifp) - return NULL; - - circuit = circuit_scan_by_ifp(ifp); - if (!circuit) - return NULL; - - return yang_data_new_uint32(xpath, circuit->auth_failures); -} - -/* - * NOTIFICATIONS - */ -static void notif_prep_instance_hdr(const char *xpath, - const struct isis_area *area, - const char *routing_instance, - struct list *args) -{ - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - - snprintf(xpath_arg, sizeof(xpath_arg), "%s/routing-instance", xpath); - data = yang_data_new_string(xpath_arg, routing_instance); - listnode_add(args, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/routing-protocol-name", - xpath); - data = yang_data_new_string(xpath_arg, area->area_tag); - listnode_add(args, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/isis-level", xpath); - data = yang_data_new_enum(xpath_arg, area->is_type); - listnode_add(args, data); -} - -static void notif_prepr_iface_hdr(const char *xpath, - const struct isis_circuit *circuit, - struct list *args) -{ - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - - snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath); - data = yang_data_new_string(xpath_arg, circuit->interface->name); - listnode_add(args, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-level", xpath); - data = yang_data_new_enum(xpath_arg, circuit->is_type); - listnode_add(args, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/extended-circuit-id", xpath); - /* we do not seem to have the extended version of the circuit_id */ - data = yang_data_new_uint32(xpath_arg, (uint32_t)circuit->circuit_id); - listnode_add(args, data); -} - -/* - * XPath: - * /frr-isisd:database-overload - */ -void isis_notif_db_overload(const struct isis_area *area, bool overload) -{ - const char *xpath = "/frr-isisd:database-overload"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/overload", xpath); - data = yang_data_new_enum(xpath_arg, !!overload); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:lsp-too-large - */ -void isis_notif_lsp_too_large(const struct isis_circuit *circuit, - uint32_t pdu_size, const char *lsp_id) -{ - const char *xpath = "/frr-isisd:lsp-too-large"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/pdu-size", xpath); - data = yang_data_new_uint32(xpath_arg, pdu_size); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, lsp_id); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:if-state-change - */ -void isis_notif_if_state_change(const struct isis_circuit *circuit, bool down) -{ - const char *xpath = "/frr-isisd:if-state-change"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath); - data = yang_data_new_enum(xpath_arg, !!down); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:corrupted-lsp-detected - */ -void isis_notif_corrupted_lsp(const struct isis_area *area, const char *lsp_id) -{ - const char *xpath = "/frr-isisd:corrupted-lsp-detected"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, lsp_id); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:attempt-to-exceed-max-sequence - */ -void isis_notif_lsp_exceed_max(const struct isis_area *area, const char *lsp_id) -{ - const char *xpath = "/frr-isisd:attempt-to-exceed-max-sequence"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, lsp_id); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:max-area-addresses-mismatch - */ -void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit, - uint8_t max_area_addrs, - const char *raw_pdu) -{ - const char *xpath = "/frr-isisd:max-area-addresses-mismatch"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/max-area-addresses", xpath); - data = yang_data_new_uint8(xpath_arg, max_area_addrs); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); - data = yang_data_new(xpath_arg, raw_pdu); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:authentication-type-failure - */ -void isis_notif_authentication_type_failure(const struct isis_circuit *circuit, - const char *raw_pdu) -{ - const char *xpath = "/frr-isisd:authentication-type-failure"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); - data = yang_data_new(xpath_arg, raw_pdu); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:authentication-failure - */ -void isis_notif_authentication_failure(const struct isis_circuit *circuit, - const char *raw_pdu) -{ - const char *xpath = "/frr-isisd:authentication-failure"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); - data = yang_data_new(xpath_arg, raw_pdu); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:adjacency-state-change - */ -void isis_notif_adj_state_change(const struct isis_adjacency *adj, - int new_state, const char *reason) -{ - const char *xpath = "/frr-isisd:adjacency-state-change"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_circuit *circuit = adj->circuit; - struct isis_area *area = circuit->area; - struct isis_dynhn *dyn = dynhn_find_by_id(adj->sysid); - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - if (dyn) { - snprintf(xpath_arg, sizeof(xpath_arg), "%s/neighbor", xpath); - data = yang_data_new_string(xpath_arg, dyn->hostname); - listnode_add(arguments, data); - } - snprintf(xpath_arg, sizeof(xpath_arg), "%s/neighbor-system-id", xpath); - data = yang_data_new_string(xpath_arg, sysid_print(adj->sysid)); - listnode_add(arguments, data); - - snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath); - data = yang_data_new_string(xpath_arg, isis_yang_adj_state(new_state)); - listnode_add(arguments, data); - if (new_state == ISIS_ADJ_DOWN) { - snprintf(xpath_arg, sizeof(xpath_arg), "%s/reason", xpath); - data = yang_data_new_string(xpath_arg, reason); - listnode_add(arguments, data); - } - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:rejected-adjacency - */ -void isis_notif_reject_adjacency(const struct isis_circuit *circuit, - const char *reason, const char *raw_pdu) -{ - const char *xpath = "/frr-isisd:rejected-adjacency"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/reason", xpath); - data = yang_data_new_string(xpath_arg, reason); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); - data = yang_data_new(xpath_arg, raw_pdu); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:area-mismatch - */ -void isis_notif_area_mismatch(const struct isis_circuit *circuit, - const char *raw_pdu) -{ - const char *xpath = "/frr-isisd:area-mismatch"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); - data = yang_data_new(xpath_arg, raw_pdu); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:lsp-received - */ -void isis_notif_lsp_received(const struct isis_circuit *circuit, - const char *lsp_id, uint32_t seqno, - uint32_t timestamp, const char *sys_id) -{ - const char *xpath = "/frr-isisd:lsp-received"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, lsp_id); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath); - data = yang_data_new_uint32(xpath_arg, seqno); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/received-timestamp", xpath); - data = yang_data_new_uint32(xpath_arg, timestamp); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/neighbor-system-id", xpath); - data = yang_data_new_string(xpath_arg, sys_id); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:lsp-generation - */ -void isis_notif_lsp_gen(const struct isis_area *area, const char *lsp_id, - uint32_t seqno, uint32_t timestamp) -{ - const char *xpath = "/frr-isisd:lsp-generation"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, lsp_id); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath); - data = yang_data_new_uint32(xpath_arg, seqno); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/send-timestamp", xpath); - data = yang_data_new_uint32(xpath_arg, timestamp); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:id-len-mismatch - */ -void isis_notif_id_len_mismatch(const struct isis_circuit *circuit, - uint8_t rcv_id_len, const char *raw_pdu) -{ - const char *xpath = "/frr-isisd:id-len-mismatch"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/pdu-field-len", xpath); - data = yang_data_new_uint8(xpath_arg, rcv_id_len); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); - data = yang_data_new(xpath_arg, raw_pdu); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:version-skew - */ -void isis_notif_version_skew(const struct isis_circuit *circuit, - uint8_t version, const char *raw_pdu) -{ - const char *xpath = "/frr-isisd:version-skew"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/protocol-version", xpath); - data = yang_data_new_uint8(xpath_arg, version); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); - data = yang_data_new(xpath_arg, raw_pdu); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:lsp-error-detected - */ -void isis_notif_lsp_error(const struct isis_circuit *circuit, - const char *lsp_id, const char *raw_pdu, - __attribute__((unused)) uint32_t offset, - __attribute__((unused)) uint8_t tlv_type) -{ - const char *xpath = "/frr-isisd:lsp-error-detected"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, lsp_id); - listnode_add(arguments, data); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); - data = yang_data_new(xpath_arg, raw_pdu); - listnode_add(arguments, data); - /* ignore offset and tlv_type which cannot be set properly */ - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:sequence-number-skipped - */ -void isis_notif_seqno_skipped(const struct isis_circuit *circuit, - const char *lsp_id) -{ - const char *xpath = "/frr-isisd:sequence-number-skipped"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, lsp_id); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: - * /frr-isisd:own-lsp-purge - */ -void isis_notif_own_lsp_purge(const struct isis_circuit *circuit, - const char *lsp_id) -{ - const char *xpath = "/frr-isisd:own-lsp-purge"; - struct list *arguments = yang_data_list_new(); - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - struct isis_area *area = circuit->area; - - notif_prep_instance_hdr(xpath, area, "default", arguments); - notif_prepr_iface_hdr(xpath, circuit, arguments); - snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath); - data = yang_data_new_string(xpath_arg, lsp_id); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* clang-format off */ -const struct frr_yang_module_info frr_isisd_info = { - .name = "frr-isisd", - .nodes = { - { - .xpath = "/frr-isisd:isis/instance", - .cbs = { - .cli_show = cli_show_router_isis, - .create = isis_instance_create, - .destroy = isis_instance_destroy, - }, - .priority = NB_DFLT_PRIORITY - 1, - }, - { - .xpath = "/frr-isisd:isis/instance/is-type", - .cbs = { - .cli_show = cli_show_isis_is_type, - .modify = isis_instance_is_type_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/area-address", - .cbs = { - .cli_show = cli_show_isis_area_address, - .create = isis_instance_area_address_create, - .destroy = isis_instance_area_address_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/dynamic-hostname", - .cbs = { - .cli_show = cli_show_isis_dynamic_hostname, - .modify = isis_instance_dynamic_hostname_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/attached", - .cbs = { - .cli_show = cli_show_isis_attached, - .modify = isis_instance_attached_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/overload", - .cbs = { - .cli_show = cli_show_isis_overload, - .modify = isis_instance_overload_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/metric-style", - .cbs = { - .cli_show = cli_show_isis_metric_style, - .modify = isis_instance_metric_style_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/purge-originator", - .cbs = { - .cli_show = cli_show_isis_purge_origin, - .modify = isis_instance_purge_originator_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/mtu", - .cbs = { - .cli_show = cli_show_isis_lsp_mtu, - .modify = isis_instance_lsp_mtu_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/refresh-interval", - .cbs = { - .cli_show = cli_show_isis_lsp_ref_interval, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/refresh-interval/level-1", - .cbs = { - .modify = isis_instance_lsp_refresh_interval_level_1_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/refresh-interval/level-2", - .cbs = { - .modify = isis_instance_lsp_refresh_interval_level_2_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/maximum-lifetime", - .cbs = { - .cli_show = cli_show_isis_lsp_max_lifetime, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/maximum-lifetime/level-1", - .cbs = { - .modify = isis_instance_lsp_maximum_lifetime_level_1_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/maximum-lifetime/level-2", - .cbs = { - .modify = isis_instance_lsp_maximum_lifetime_level_2_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/generation-interval", - .cbs = { - .cli_show = cli_show_isis_lsp_gen_interval, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/generation-interval/level-1", - .cbs = { - .modify = isis_instance_lsp_generation_interval_level_1_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/lsp/generation-interval/level-2", - .cbs = { - .modify = isis_instance_lsp_generation_interval_level_2_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay", - .cbs = { - .apply_finish = ietf_backoff_delay_apply_finish, - .cli_show = cli_show_isis_spf_ietf_backoff, - .create = isis_instance_spf_ietf_backoff_delay_create, - .destroy = isis_instance_spf_ietf_backoff_delay_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/init-delay", - .cbs = { - .modify = isis_instance_spf_ietf_backoff_delay_init_delay_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/short-delay", - .cbs = { - .modify = isis_instance_spf_ietf_backoff_delay_short_delay_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/long-delay", - .cbs = { - .modify = isis_instance_spf_ietf_backoff_delay_long_delay_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/hold-down", - .cbs = { - .modify = isis_instance_spf_ietf_backoff_delay_hold_down_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/ietf-backoff-delay/time-to-learn", - .cbs = { - .modify = isis_instance_spf_ietf_backoff_delay_time_to_learn_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/minimum-interval", - .cbs = { - .cli_show = cli_show_isis_spf_min_interval, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/minimum-interval/level-1", - .cbs = { - .modify = isis_instance_spf_minimum_interval_level_1_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/spf/minimum-interval/level-2", - .cbs = { - .modify = isis_instance_spf_minimum_interval_level_2_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/area-password", - .cbs = { - .apply_finish = area_password_apply_finish, - .cli_show = cli_show_isis_area_pwd, - .create = isis_instance_area_password_create, - .destroy = isis_instance_area_password_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/area-password/password", - .cbs = { - .modify = isis_instance_area_password_password_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/area-password/password-type", - .cbs = { - .modify = isis_instance_area_password_password_type_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/area-password/authenticate-snp", - .cbs = { - .modify = isis_instance_area_password_authenticate_snp_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/domain-password", - .cbs = { - .apply_finish = domain_password_apply_finish, - .cli_show = cli_show_isis_domain_pwd, - .create = isis_instance_domain_password_create, - .destroy = isis_instance_domain_password_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/domain-password/password", - .cbs = { - .modify = isis_instance_domain_password_password_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/domain-password/password-type", - .cbs = { - .modify = isis_instance_domain_password_password_type_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/domain-password/authenticate-snp", - .cbs = { - .modify = isis_instance_domain_password_authenticate_snp_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv4", - .cbs = { - .apply_finish = default_info_origin_ipv4_apply_finish, - .cli_show = cli_show_isis_def_origin_ipv4, - .create = isis_instance_default_information_originate_ipv4_create, - .destroy = isis_instance_default_information_originate_ipv4_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv4/always", - .cbs = { - .modify = isis_instance_default_information_originate_ipv4_always_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv4/route-map", - .cbs = { - .destroy = isis_instance_default_information_originate_ipv4_route_map_destroy, - .modify = isis_instance_default_information_originate_ipv4_route_map_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv4/metric", - .cbs = { - .modify = isis_instance_default_information_originate_ipv4_metric_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv6", - .cbs = { - .apply_finish = default_info_origin_ipv6_apply_finish, - .cli_show = cli_show_isis_def_origin_ipv6, - .create = isis_instance_default_information_originate_ipv6_create, - .destroy = isis_instance_default_information_originate_ipv6_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv6/always", - .cbs = { - .modify = isis_instance_default_information_originate_ipv6_always_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv6/route-map", - .cbs = { - .destroy = isis_instance_default_information_originate_ipv6_route_map_destroy, - .modify = isis_instance_default_information_originate_ipv6_route_map_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/default-information-originate/ipv6/metric", - .cbs = { - .modify = isis_instance_default_information_originate_ipv6_metric_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/redistribute/ipv4", - .cbs = { - .apply_finish = redistribute_ipv4_apply_finish, - .cli_show = cli_show_isis_redistribute_ipv4, - .create = isis_instance_redistribute_ipv4_create, - .destroy = isis_instance_redistribute_ipv4_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/redistribute/ipv4/route-map", - .cbs = { - .destroy = isis_instance_redistribute_ipv4_route_map_destroy, - .modify = isis_instance_redistribute_ipv4_route_map_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/redistribute/ipv4/metric", - .cbs = { - .modify = isis_instance_redistribute_ipv4_metric_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/redistribute/ipv6", - .cbs = { - .apply_finish = redistribute_ipv6_apply_finish, - .cli_show = cli_show_isis_redistribute_ipv6, - .create = isis_instance_redistribute_ipv6_create, - .destroy = isis_instance_redistribute_ipv6_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/route-map", - .cbs = { - .destroy = isis_instance_redistribute_ipv6_route_map_destroy, - .modify = isis_instance_redistribute_ipv6_route_map_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/metric", - .cbs = { - .modify = isis_instance_redistribute_ipv6_metric_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv4-multicast", - .cbs = { - .cli_show = cli_show_isis_mt_ipv4_multicast, - .create = isis_instance_multi_topology_ipv4_multicast_create, - .destroy = isis_instance_multi_topology_ipv4_multicast_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv4-multicast/overload", - .cbs = { - .modify = isis_instance_multi_topology_ipv4_multicast_overload_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv4-management", - .cbs = { - .cli_show = cli_show_isis_mt_ipv4_mgmt, - .create = isis_instance_multi_topology_ipv4_management_create, - .destroy = isis_instance_multi_topology_ipv4_management_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv4-management/overload", - .cbs = { - .modify = isis_instance_multi_topology_ipv4_management_overload_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-unicast", - .cbs = { - .cli_show = cli_show_isis_mt_ipv6_unicast, - .create = isis_instance_multi_topology_ipv6_unicast_create, - .destroy = isis_instance_multi_topology_ipv6_unicast_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-unicast/overload", - .cbs = { - .modify = isis_instance_multi_topology_ipv6_unicast_overload_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-multicast", - .cbs = { - .cli_show = cli_show_isis_mt_ipv6_multicast, - .create = isis_instance_multi_topology_ipv6_multicast_create, - .destroy = isis_instance_multi_topology_ipv6_multicast_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-multicast/overload", - .cbs = { - .modify = isis_instance_multi_topology_ipv6_multicast_overload_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-management", - .cbs = { - .cli_show = cli_show_isis_mt_ipv6_mgmt, - .create = isis_instance_multi_topology_ipv6_management_create, - .destroy = isis_instance_multi_topology_ipv6_management_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-management/overload", - .cbs = { - .modify = isis_instance_multi_topology_ipv6_management_overload_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-dstsrc", - .cbs = { - .cli_show = cli_show_isis_mt_ipv6_dstsrc, - .create = isis_instance_multi_topology_ipv6_dstsrc_create, - .destroy = isis_instance_multi_topology_ipv6_dstsrc_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/multi-topology/ipv6-dstsrc/overload", - .cbs = { - .modify = isis_instance_multi_topology_ipv6_dstsrc_overload_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/log-adjacency-changes", - .cbs = { - .cli_show = cli_show_isis_log_adjacency, - .modify = isis_instance_log_adjacency_changes_modify, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/mpls-te", - .cbs = { - .cli_show = cli_show_isis_mpls_te, - .create = isis_instance_mpls_te_create, - .destroy = isis_instance_mpls_te_destroy, - }, - }, - { - .xpath = "/frr-isisd:isis/instance/mpls-te/router-address", - .cbs = { - .cli_show = cli_show_isis_mpls_te_router_addr, - .destroy = isis_instance_mpls_te_router_address_destroy, - .modify = isis_instance_mpls_te_router_address_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis", - .cbs = { - .create = lib_interface_isis_create, - .destroy = lib_interface_isis_destroy, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/area-tag", - .cbs = { - .modify = lib_interface_isis_area_tag_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/circuit-type", - .cbs = { - .cli_show = cli_show_ip_isis_circ_type, - .modify = lib_interface_isis_circuit_type_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/ipv4-routing", - .cbs = { - .cli_show = cli_show_ip_isis_ipv4, - .modify = lib_interface_isis_ipv4_routing_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/ipv6-routing", - .cbs = { - .cli_show = cli_show_ip_isis_ipv6, - .modify = lib_interface_isis_ipv6_routing_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring", - .cbs = { - .modify = lib_interface_isis_bfd_monitoring_modify, - .cli_show = cli_show_ip_isis_bfd_monitoring, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval", - .cbs = { - .cli_show = cli_show_ip_isis_csnp_interval, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-1", - .cbs = { - .modify = lib_interface_isis_csnp_interval_level_1_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-2", - .cbs = { - .modify = lib_interface_isis_csnp_interval_level_2_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/psnp-interval", - .cbs = { - .cli_show = cli_show_ip_isis_psnp_interval, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-1", - .cbs = { - .modify = lib_interface_isis_psnp_interval_level_1_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-2", - .cbs = { - .modify = lib_interface_isis_psnp_interval_level_2_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/padding", - .cbs = { - .cli_show = cli_show_ip_isis_hello_padding, - .modify = lib_interface_isis_hello_padding_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/interval", - .cbs = { - .cli_show = cli_show_ip_isis_hello_interval, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-1", - .cbs = { - .modify = lib_interface_isis_hello_interval_level_1_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-2", - .cbs = { - .modify = lib_interface_isis_hello_interval_level_2_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/multiplier", - .cbs = { - .cli_show = cli_show_ip_isis_hello_multi, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-1", - .cbs = { - .modify = lib_interface_isis_hello_multiplier_level_1_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-2", - .cbs = { - .modify = lib_interface_isis_hello_multiplier_level_2_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/metric", - .cbs = { - .cli_show = cli_show_ip_isis_metric, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/metric/level-1", - .cbs = { - .modify = lib_interface_isis_metric_level_1_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/metric/level-2", - .cbs = { - .modify = lib_interface_isis_metric_level_2_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/priority", - .cbs = { - .cli_show = cli_show_ip_isis_priority, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/priority/level-1", - .cbs = { - .modify = lib_interface_isis_priority_level_1_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/priority/level-2", - .cbs = { - .modify = lib_interface_isis_priority_level_2_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/network-type", - .cbs = { - .cli_show = cli_show_ip_isis_network_type, - .modify = lib_interface_isis_network_type_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/passive", - .cbs = { - .cli_show = cli_show_ip_isis_passive, - .modify = lib_interface_isis_passive_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/password", - .cbs = { - .cli_show = cli_show_ip_isis_password, - .create = lib_interface_isis_password_create, - .destroy = lib_interface_isis_password_destroy, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/password/password", - .cbs = { - .modify = lib_interface_isis_password_password_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/password/password-type", - .cbs = { - .modify = lib_interface_isis_password_password_type_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/disable-three-way-handshake", - .cbs = { - .cli_show = cli_show_ip_isis_threeway_shake, - .modify = lib_interface_isis_disable_three_way_handshake_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-unicast", - .cbs = { - .cli_show = cli_show_ip_isis_mt_ipv4_unicast, - .modify = lib_interface_isis_multi_topology_ipv4_unicast_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-multicast", - .cbs = { - .cli_show = cli_show_ip_isis_mt_ipv4_multicast, - .modify = lib_interface_isis_multi_topology_ipv4_multicast_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-management", - .cbs = { - .cli_show = cli_show_ip_isis_mt_ipv4_mgmt, - .modify = lib_interface_isis_multi_topology_ipv4_management_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-unicast", - .cbs = { - .cli_show = cli_show_ip_isis_mt_ipv6_unicast, - .modify = lib_interface_isis_multi_topology_ipv6_unicast_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-multicast", - .cbs = { - .cli_show = cli_show_ip_isis_mt_ipv6_multicast, - .modify = lib_interface_isis_multi_topology_ipv6_multicast_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-management", - .cbs = { - .cli_show = cli_show_ip_isis_mt_ipv6_mgmt, - .modify = lib_interface_isis_multi_topology_ipv6_management_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-dstsrc", - .cbs = { - .cli_show = cli_show_ip_isis_mt_ipv6_dstsrc, - .modify = lib_interface_isis_multi_topology_ipv6_dstsrc_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency", - .cbs = { - .get_next = lib_interface_isis_adjacencies_adjacency_get_next, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type", - .cbs = { - .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid", - .cbs = { - .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id", - .cbs = { - .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa", - .cbs = { - .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer", - .cbs = { - .get_elem = lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority", - .cbs = { - .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state", - .cbs = { - .get_elem = lib_interface_isis_adjacencies_adjacency_state_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes", - .cbs = { - .get_elem = lib_interface_isis_event_counters_adjacency_changes_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number", - .cbs = { - .get_elem = lib_interface_isis_event_counters_adjacency_number_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails", - .cbs = { - .get_elem = lib_interface_isis_event_counters_init_fails_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects", - .cbs = { - .get_elem = lib_interface_isis_event_counters_adjacency_rejects_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch", - .cbs = { - .get_elem = lib_interface_isis_event_counters_id_len_mismatch_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch", - .cbs = { - .get_elem = lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails", - .cbs = { - .get_elem = lib_interface_isis_event_counters_authentication_type_fails_get_elem, - } - }, - { - .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails", - .cbs = { - .get_elem = lib_interface_isis_event_counters_authentication_fails_get_elem, - } - }, - { - .xpath = NULL, - }, - } -}; diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index a637ff003f..71249cf658 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -58,6 +58,7 @@ #include "isisd/fabricd.h" #include "isisd/isis_tx_queue.h" #include "isisd/isis_pdu_counter.h" +#include "isisd/isis_nb.h" static int ack_lsp(struct isis_lsp_hdr *hdr, struct isis_circuit *circuit, int level) diff --git a/isisd/isisd.c b/isisd/isisd.c index 029a9e0688..f15d7a9c7e 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -57,6 +57,7 @@ #include "isisd/isis_te.h" #include "isisd/isis_mt.h" #include "isisd/fabricd.h" +#include "isisd/isis_nb.h" struct isis *isis = NULL; diff --git a/isisd/isisd.h b/isisd/isisd.h index f825b6ecb4..052cc10928 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -219,52 +219,6 @@ int isis_area_passwd_cleartext_set(struct isis_area *area, int level, int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level, const char *passwd, uint8_t snp_auth); -extern const struct frr_yang_module_info frr_isisd_info; -extern void isis_northbound_init(void); - -/* YANG northbound notifications */ -extern void isis_notif_db_overload(const struct isis_area *area, bool overload); -extern void isis_notif_lsp_too_large(const struct isis_circuit *circuit, - uint32_t pdu_size, const char *lsp_id); -extern void isis_notif_if_state_change(const struct isis_circuit *circuit, - bool down); -extern void isis_notif_corrupted_lsp(const struct isis_area *area, - const char *lsp_id); /* currently unused */ -extern void isis_notif_lsp_exceed_max(const struct isis_area *area, - const char *lsp_id); -extern void -isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit, - uint8_t max_area_addrs, const char *raw_pdu); -extern void -isis_notif_authentication_type_failure(const struct isis_circuit *circuit, - const char *raw_pdu); -extern void -isis_notif_authentication_failure(const struct isis_circuit *circuit, - const char *raw_pdu); -extern void isis_notif_adj_state_change(const struct isis_adjacency *adj, - int new_state, const char *reason); -extern void isis_notif_reject_adjacency(const struct isis_circuit *circuit, - const char *reason, - const char *raw_pdu); -extern void isis_notif_area_mismatch(const struct isis_circuit *circuit, - const char *raw_pdu); -extern void isis_notif_lsp_received(const struct isis_circuit *circuit, - const char *lsp_id, uint32_t seqno, - uint32_t timestamp, const char *sys_id); -extern void isis_notif_lsp_gen(const struct isis_area *area, const char *lsp_id, - uint32_t seqno, uint32_t timestamp); -extern void isis_notif_id_len_mismatch(const struct isis_circuit *circuit, - uint8_t rcv_id_len, const char *raw_pdu); -extern void isis_notif_version_skew(const struct isis_circuit *circuit, - uint8_t version, const char *raw_pdu); -extern void isis_notif_lsp_error(const struct isis_circuit *circuit, - const char *lsp_id, const char *raw_pdu, - uint32_t offset, uint8_t tlv_type); -extern void isis_notif_seqno_skipped(const struct isis_circuit *circuit, - const char *lsp_id); -extern void isis_notif_own_lsp_purge(const struct isis_circuit *circuit, - const char *lsp_id); - /* Master of threads. */ extern struct thread_master *master; diff --git a/isisd/subdir.am b/isisd/subdir.am index 24f24022a5..e77fef41dd 100644 --- a/isisd/subdir.am +++ b/isisd/subdir.am @@ -39,6 +39,7 @@ noinst_HEADERS += \ isisd/isis_memory.h \ isisd/isis_misc.h \ isisd/isis_mt.h \ + isisd/isis_nb.h \ isisd/isis_network.h \ isisd/isis_pdu.h \ isisd/isis_pdu_counter.h \ @@ -54,7 +55,6 @@ noinst_HEADERS += \ isisd/isisd.h \ isisd/iso_checksum.h \ isisd/fabricd.h \ - isisd/isis_cli.h \ # end LIBISIS_SOURCES = \ @@ -99,7 +99,10 @@ ISIS_LDADD_COMMON = lib/libfrr.la $(LIBCAP) isisd_libisis_a_SOURCES = \ $(LIBISIS_SOURCES) \ - isisd/isis_northbound.c \ + isisd/isis_nb.c \ + isisd/isis_nb_config.c \ + isisd/isis_nb_notifications.c \ + isisd/isis_nb_state.c \ isisd/isis_cli.c \ #end From f80ec39e52e3932aa75e836cc741677f5e5cd0fb Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 17 Oct 2019 15:46:54 -0300 Subject: [PATCH 2/5] ripd: split northbound callbacks into multiple files Rearrange the ripd northbound callbacks as following: * rip_nb.h: prototypes of all northbound callbacks. * rip_nb.c: definition of all northbound callbacks and their associated YANG data paths. * rip_nb_config.c: implementation of YANG configuration nodes. * rip_nb_state.c: implementation of YANG state nodes. * rip_nb_rpcs.c: implementation of YANG RPCs. * rip_nb_notifications.c: implementation of YANG notifications. This should help to keep to code more organized and easier to maintain. No behavior changes intended. Signed-off-by: Renato Westphal --- ripd/rip_cli.c | 2 +- ripd/rip_cli.h | 86 -- ripd/rip_main.c | 1 + ripd/rip_nb.c | 369 +++++++ ripd/rip_nb.h | 265 +++++ ripd/rip_nb_config.c | 1099 +++++++++++++++++++++ ripd/rip_nb_notifications.c | 73 ++ ripd/rip_nb_rpcs.c | 105 ++ ripd/rip_nb_state.c | 284 ++++++ ripd/rip_northbound.c | 1823 ----------------------------------- ripd/ripd.c | 1 + ripd/ripd.h | 9 +- ripd/subdir.am | 8 +- 13 files changed, 2205 insertions(+), 1920 deletions(-) delete mode 100644 ripd/rip_cli.h create mode 100644 ripd/rip_nb.c create mode 100644 ripd/rip_nb.h create mode 100644 ripd/rip_nb_config.c create mode 100644 ripd/rip_nb_notifications.c create mode 100644 ripd/rip_nb_rpcs.c create mode 100644 ripd/rip_nb_state.c delete mode 100644 ripd/rip_northbound.c diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index 627d3d1993..5c26c0cef7 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -29,7 +29,7 @@ #include "libfrr.h" #include "ripd/ripd.h" -#include "ripd/rip_cli.h" +#include "ripd/rip_nb.h" #ifndef VTYSH_EXTRACT_PL #include "ripd/rip_cli_clippy.c" #endif diff --git a/ripd/rip_cli.h b/ripd/rip_cli.h deleted file mode 100644 index ef1e1504e8..0000000000 --- a/ripd/rip_cli.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro - * Copyright (C) 2018 NetDEF, Inc. - * Renato Westphal - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _FRR_RIP_CLI_H_ -#define _FRR_RIP_CLI_H_ - -extern void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_allow_ecmp(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_default_information_originate(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_default_metric(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_distance_source(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_neighbor(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_network_prefix(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_network_interface(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_offset_list(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_passive_default(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_passive_interface(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_non_passive_interface(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_redistribute(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_route(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_timers(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_rip_version(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ip_rip_split_horizon(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ip_rip_v2_broadcast(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ip_rip_receive_version(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ip_rip_send_version(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ip_rip_authentication_scheme(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ip_rip_authentication_string(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ip_rip_authentication_key_chain(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); - -#endif /* _FRR_RIP_CLI_H_ */ diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 773cb1d0fe..08cc515856 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -38,6 +38,7 @@ #include "libfrr.h" #include "ripd/ripd.h" +#include "ripd/rip_nb.h" #include "ripd/rip_errors.h" /* ripd options. */ diff --git a/ripd/rip_nb.c b/ripd/rip_nb.c new file mode 100644 index 0000000000..4716041ad6 --- /dev/null +++ b/ripd/rip_nb.c @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "northbound.h" +#include "libfrr.h" + +#include "ripd/rip_nb.h" + +/* clang-format off */ +const struct frr_yang_module_info frr_ripd_info = { + .name = "frr-ripd", + .nodes = { + { + .xpath = "/frr-ripd:ripd/instance", + .cbs = { + .cli_show = cli_show_router_rip, + .create = ripd_instance_create, + .destroy = ripd_instance_destroy, + .get_keys = ripd_instance_get_keys, + .get_next = ripd_instance_get_next, + .lookup_entry = ripd_instance_lookup_entry, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/allow-ecmp", + .cbs = { + .cli_show = cli_show_rip_allow_ecmp, + .modify = ripd_instance_allow_ecmp_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/default-information-originate", + .cbs = { + .cli_show = cli_show_rip_default_information_originate, + .modify = ripd_instance_default_information_originate_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/default-metric", + .cbs = { + .cli_show = cli_show_rip_default_metric, + .modify = ripd_instance_default_metric_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/distance/default", + .cbs = { + .cli_show = cli_show_rip_distance, + .modify = ripd_instance_distance_default_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/distance/source", + .cbs = { + .cli_show = cli_show_rip_distance_source, + .create = ripd_instance_distance_source_create, + .destroy = ripd_instance_distance_source_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/distance/source/distance", + .cbs = { + .modify = ripd_instance_distance_source_distance_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/distance/source/access-list", + .cbs = { + .destroy = ripd_instance_distance_source_access_list_destroy, + .modify = ripd_instance_distance_source_access_list_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/explicit-neighbor", + .cbs = { + .cli_show = cli_show_rip_neighbor, + .create = ripd_instance_explicit_neighbor_create, + .destroy = ripd_instance_explicit_neighbor_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/network", + .cbs = { + .cli_show = cli_show_rip_network_prefix, + .create = ripd_instance_network_create, + .destroy = ripd_instance_network_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/interface", + .cbs = { + .cli_show = cli_show_rip_network_interface, + .create = ripd_instance_interface_create, + .destroy = ripd_instance_interface_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/offset-list", + .cbs = { + .cli_show = cli_show_rip_offset_list, + .create = ripd_instance_offset_list_create, + .destroy = ripd_instance_offset_list_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/offset-list/access-list", + .cbs = { + .modify = ripd_instance_offset_list_access_list_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/offset-list/metric", + .cbs = { + .modify = ripd_instance_offset_list_metric_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/passive-default", + .cbs = { + .cli_show = cli_show_rip_passive_default, + .modify = ripd_instance_passive_default_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/passive-interface", + .cbs = { + .cli_show = cli_show_rip_passive_interface, + .create = ripd_instance_passive_interface_create, + .destroy = ripd_instance_passive_interface_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/non-passive-interface", + .cbs = { + .cli_show = cli_show_rip_non_passive_interface, + .create = ripd_instance_non_passive_interface_create, + .destroy = ripd_instance_non_passive_interface_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/redistribute", + .cbs = { + .apply_finish = ripd_instance_redistribute_apply_finish, + .cli_show = cli_show_rip_redistribute, + .create = ripd_instance_redistribute_create, + .destroy = ripd_instance_redistribute_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/redistribute/route-map", + .cbs = { + .destroy = ripd_instance_redistribute_route_map_destroy, + .modify = ripd_instance_redistribute_route_map_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/redistribute/metric", + .cbs = { + .destroy = ripd_instance_redistribute_metric_destroy, + .modify = ripd_instance_redistribute_metric_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/static-route", + .cbs = { + .cli_show = cli_show_rip_route, + .create = ripd_instance_static_route_create, + .destroy = ripd_instance_static_route_destroy, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/timers", + .cbs = { + .apply_finish = ripd_instance_timers_apply_finish, + .cli_show = cli_show_rip_timers, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/timers/flush-interval", + .cbs = { + .modify = ripd_instance_timers_flush_interval_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/timers/holddown-interval", + .cbs = { + .modify = ripd_instance_timers_holddown_interval_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/timers/update-interval", + .cbs = { + .modify = ripd_instance_timers_update_interval_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/version", + .cbs = { + .cli_show = cli_show_rip_version, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/version/receive", + .cbs = { + .modify = ripd_instance_version_receive_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/version/send", + .cbs = { + .modify = ripd_instance_version_send_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/split-horizon", + .cbs = { + .cli_show = cli_show_ip_rip_split_horizon, + .modify = lib_interface_rip_split_horizon_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/v2-broadcast", + .cbs = { + .cli_show = cli_show_ip_rip_v2_broadcast, + .modify = lib_interface_rip_v2_broadcast_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-receive", + .cbs = { + .cli_show = cli_show_ip_rip_receive_version, + .modify = lib_interface_rip_version_receive_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-send", + .cbs = { + .cli_show = cli_show_ip_rip_send_version, + .modify = lib_interface_rip_version_send_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme", + .cbs = { + .cli_show = cli_show_ip_rip_authentication_scheme, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode", + .cbs = { + .modify = lib_interface_rip_authentication_scheme_mode_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length", + .cbs = { + .destroy = lib_interface_rip_authentication_scheme_md5_auth_length_destroy, + .modify = lib_interface_rip_authentication_scheme_md5_auth_length_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password", + .cbs = { + .cli_show = cli_show_ip_rip_authentication_string, + .destroy = lib_interface_rip_authentication_password_destroy, + .modify = lib_interface_rip_authentication_password_modify, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain", + .cbs = { + .cli_show = cli_show_ip_rip_authentication_key_chain, + .destroy = lib_interface_rip_authentication_key_chain_destroy, + .modify = lib_interface_rip_authentication_key_chain_modify, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor", + .cbs = { + .get_keys = ripd_instance_state_neighbors_neighbor_get_keys, + .get_next = ripd_instance_state_neighbors_neighbor_get_next, + .lookup_entry = ripd_instance_state_neighbors_neighbor_lookup_entry, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/address", + .cbs = { + .get_elem = ripd_instance_state_neighbors_neighbor_address_get_elem, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/last-update", + .cbs = { + .get_elem = ripd_instance_state_neighbors_neighbor_last_update_get_elem, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd", + .cbs = { + .get_elem = ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd", + .cbs = { + .get_elem = ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route", + .cbs = { + .get_keys = ripd_instance_state_routes_route_get_keys, + .get_next = ripd_instance_state_routes_route_get_next, + .lookup_entry = ripd_instance_state_routes_route_lookup_entry, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/prefix", + .cbs = { + .get_elem = ripd_instance_state_routes_route_prefix_get_elem, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/next-hop", + .cbs = { + .get_elem = ripd_instance_state_routes_route_next_hop_get_elem, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/interface", + .cbs = { + .get_elem = ripd_instance_state_routes_route_interface_get_elem, + }, + }, + { + .xpath = "/frr-ripd:ripd/instance/state/routes/route/metric", + .cbs = { + .get_elem = ripd_instance_state_routes_route_metric_get_elem, + }, + }, + { + .xpath = "/frr-ripd:clear-rip-route", + .cbs = { + .rpc = clear_rip_route_rpc, + }, + }, + { + .xpath = NULL, + }, + } +}; diff --git a/ripd/rip_nb.h b/ripd/rip_nb.h new file mode 100644 index 0000000000..441b253fea --- /dev/null +++ b/ripd/rip_nb.h @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_RIP_NB_H_ +#define _FRR_RIP_NB_H_ + +extern const struct frr_yang_module_info frr_ripd_info; + +/* Mandatory callbacks. */ +int ripd_instance_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_destroy(enum nb_event event, const struct lyd_node *dnode); +const void *ripd_instance_get_next(const void *parent_list_entry, + const void *list_entry); +int ripd_instance_get_keys(const void *list_entry, struct yang_list_keys *keys); +const void *ripd_instance_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys); +int ripd_instance_allow_ecmp_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_default_information_originate_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_default_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_distance_default_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_distance_source_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_distance_source_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_distance_source_distance_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_distance_source_access_list_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_distance_source_access_list_destroy( + enum nb_event event, const struct lyd_node *dnode); +int ripd_instance_explicit_neighbor_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_explicit_neighbor_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_network_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_network_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_interface_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_offset_list_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_offset_list_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_offset_list_access_list_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_offset_list_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_passive_default_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_passive_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_non_passive_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_non_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_redistribute_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_redistribute_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_redistribute_route_map_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_redistribute_route_map_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_redistribute_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_redistribute_metric_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_static_route_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_static_route_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripd_instance_timers_flush_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_timers_holddown_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_timers_update_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_version_receive_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripd_instance_version_send_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +const void * +ripd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry, + const void *list_entry); +int ripd_instance_state_neighbors_neighbor_get_keys( + const void *list_entry, struct yang_list_keys *keys); +const void *ripd_instance_state_neighbors_neighbor_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys); +struct yang_data * +ripd_instance_state_neighbors_neighbor_address_get_elem(const char *xpath, + const void *list_entry); +struct yang_data *ripd_instance_state_neighbors_neighbor_last_update_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem( + const char *xpath, const void *list_entry); +const void * +ripd_instance_state_routes_route_get_next(const void *parent_list_entry, + const void *list_entry); +int ripd_instance_state_routes_route_get_keys(const void *list_entry, + struct yang_list_keys *keys); +const void *ripd_instance_state_routes_route_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys); +struct yang_data * +ripd_instance_state_routes_route_prefix_get_elem(const char *xpath, + const void *list_entry); +struct yang_data * +ripd_instance_state_routes_route_next_hop_get_elem(const char *xpath, + const void *list_entry); +struct yang_data * +ripd_instance_state_routes_route_interface_get_elem(const char *xpath, + const void *list_entry); +struct yang_data * +ripd_instance_state_routes_route_metric_get_elem(const char *xpath, + const void *list_entry); +int clear_rip_route_rpc(const char *xpath, const struct list *input, + struct list *output); +int lib_interface_rip_split_horizon_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_rip_v2_broadcast_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_rip_version_receive_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_rip_version_send_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_rip_authentication_scheme_mode_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_rip_authentication_scheme_md5_auth_length_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_rip_authentication_scheme_md5_auth_length_destroy( + enum nb_event event, const struct lyd_node *dnode); +int lib_interface_rip_authentication_password_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_rip_authentication_password_destroy( + enum nb_event event, const struct lyd_node *dnode); +int lib_interface_rip_authentication_key_chain_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int lib_interface_rip_authentication_key_chain_destroy( + enum nb_event event, const struct lyd_node *dnode); + +/* Optional 'apply_finish' callbacks. */ +void ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode); +void ripd_instance_timers_apply_finish(const struct lyd_node *dnode); + +/* Optional 'cli_show' callbacks. */ +void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_allow_ecmp(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_default_information_originate(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_default_metric(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_distance_source(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_neighbor(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_network_prefix(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_network_interface(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_offset_list(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_passive_default(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_passive_interface(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_non_passive_interface(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_redistribute(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_route(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_timers(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_rip_version(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_rip_split_horizon(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_rip_v2_broadcast(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_rip_receive_version(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_rip_send_version(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_rip_authentication_scheme(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_rip_authentication_string(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); +void cli_show_ip_rip_authentication_key_chain(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); + +/* Notifications. */ +extern void ripd_notif_send_auth_type_failure(const char *ifname); +extern void ripd_notif_send_auth_failure(const char *ifname); + +#endif /* _FRR_RIP_NB_H_ */ diff --git a/ripd/rip_nb_config.c b/ripd/rip_nb_config.c new file mode 100644 index 0000000000..e75db342af --- /dev/null +++ b/ripd/rip_nb_config.c @@ -0,0 +1,1099 @@ +/* + * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "table.h" +#include "command.h" +#include "routemap.h" +#include "northbound.h" +#include "libfrr.h" + +#include "ripd/ripd.h" +#include "ripd/rip_nb.h" +#include "ripd/rip_debug.h" +#include "ripd/rip_interface.h" + +/* + * XPath: /frr-ripd:ripd/instance + */ +int ripd_instance_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + struct vrf *vrf; + const char *vrf_name; + int socket; + + vrf_name = yang_dnode_get_string(dnode, "./vrf"); + vrf = vrf_lookup_by_name(vrf_name); + + /* + * Try to create a RIP socket only if the VRF is enabled, otherwise + * create a disabled RIP instance and wait for the VRF to be enabled. + */ + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + if (!vrf || !vrf_is_enabled(vrf)) + break; + + socket = rip_create_socket(vrf); + if (socket < 0) + return NB_ERR_RESOURCE; + resource->fd = socket; + break; + case NB_EV_ABORT: + if (!vrf || !vrf_is_enabled(vrf)) + break; + + socket = resource->fd; + close(socket); + break; + case NB_EV_APPLY: + if (vrf && vrf_is_enabled(vrf)) + socket = resource->fd; + else + socket = -1; + + rip = rip_create(vrf_name, vrf, socket); + nb_running_set_entry(dnode, rip); + break; + } + + return NB_OK; +} + +int ripd_instance_destroy(enum nb_event event, const struct lyd_node *dnode) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_unset_entry(dnode); + rip_clean(rip); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/allow-ecmp + */ +int ripd_instance_allow_ecmp_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->ecmp = yang_dnode_get_bool(dnode, NULL); + if (!rip->ecmp) + rip_ecmp_disable(rip); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/default-information-originate + */ +int ripd_instance_default_information_originate_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + bool default_information; + struct prefix_ipv4 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + default_information = yang_dnode_get_bool(dnode, NULL); + + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + if (default_information) { + struct nexthop nh; + + memset(&nh, 0, sizeof(nh)); + nh.type = NEXTHOP_TYPE_IPV4; + rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, + &p, &nh, 0, 0, 0); + } else { + rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, + &p, 0); + } + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/default-metric + */ +int ripd_instance_default_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->default_metric = yang_dnode_get_uint8(dnode, NULL); + /* rip_update_default_metric (); */ + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/distance/default + */ +int ripd_instance_distance_default_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->distance = yang_dnode_get_uint8(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/distance/source + */ +int ripd_instance_distance_source_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + struct prefix_ipv4 prefix; + struct route_node *rn; + + if (event != NB_EV_APPLY) + return NB_OK; + + yang_dnode_get_ipv4p(&prefix, dnode, "./prefix"); + apply_mask_ipv4(&prefix); + + /* Get RIP distance node. */ + rip = nb_running_get_entry(dnode, NULL, true); + rn = route_node_get(rip->distance_table, (struct prefix *)&prefix); + rn->info = rip_distance_new(); + nb_running_set_entry(dnode, rn); + + return NB_OK; +} + +int ripd_instance_distance_source_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct route_node *rn; + struct rip_distance *rdistance; + + if (event != NB_EV_APPLY) + return NB_OK; + + rn = nb_running_unset_entry(dnode); + rdistance = rn->info; + rip_distance_free(rdistance); + rn->info = NULL; + route_unlock_node(rn); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/distance/source/distance + */ +int ripd_instance_distance_source_distance_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct route_node *rn; + uint8_t distance; + struct rip_distance *rdistance; + + if (event != NB_EV_APPLY) + return NB_OK; + + /* Set distance value. */ + rn = nb_running_get_entry(dnode, NULL, true); + distance = yang_dnode_get_uint8(dnode, NULL); + rdistance = rn->info; + rdistance->distance = distance; + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/distance/source/access-list + */ +int ripd_instance_distance_source_access_list_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + const char *acl_name; + struct route_node *rn; + struct rip_distance *rdistance; + + if (event != NB_EV_APPLY) + return NB_OK; + + acl_name = yang_dnode_get_string(dnode, NULL); + + /* Set access-list */ + rn = nb_running_get_entry(dnode, NULL, true); + rdistance = rn->info; + if (rdistance->access_list) + free(rdistance->access_list); + rdistance->access_list = strdup(acl_name); + + return NB_OK; +} + +int ripd_instance_distance_source_access_list_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct route_node *rn; + struct rip_distance *rdistance; + + if (event != NB_EV_APPLY) + return NB_OK; + + /* Reset access-list configuration. */ + rn = nb_running_get_entry(dnode, NULL, true); + rdistance = rn->info; + free(rdistance->access_list); + rdistance->access_list = NULL; + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/explicit-neighbor + */ +int ripd_instance_explicit_neighbor_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + struct prefix_ipv4 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + yang_dnode_get_ipv4(&p.prefix, dnode, NULL); + + return rip_neighbor_add(rip, &p); +} + +int ripd_instance_explicit_neighbor_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + struct prefix_ipv4 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + yang_dnode_get_ipv4(&p.prefix, dnode, NULL); + + return rip_neighbor_delete(rip, &p); +} + +/* + * XPath: /frr-ripd:ripd/instance/network + */ +int ripd_instance_network_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + struct prefix p; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv4p(&p, dnode, NULL); + apply_mask_ipv4((struct prefix_ipv4 *)&p); + + return rip_enable_network_add(rip, &p); +} + +int ripd_instance_network_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + struct prefix p; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv4p(&p, dnode, NULL); + apply_mask_ipv4((struct prefix_ipv4 *)&p); + + return rip_enable_network_delete(rip, &p); +} + +/* + * XPath: /frr-ripd:ripd/instance/interface + */ +int ripd_instance_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return rip_enable_if_add(rip, ifname); +} + +int ripd_instance_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return rip_enable_if_delete(rip, ifname); +} + +/* + * XPath: /frr-ripd:ripd/instance/offset-list + */ +int ripd_instance_offset_list_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + const char *ifname; + struct rip_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, "./interface"); + + offset = rip_offset_list_new(rip, ifname); + nb_running_set_entry(dnode, offset); + + return NB_OK; +} + +int ripd_instance_offset_list_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + int direct; + struct rip_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "./direction"); + + offset = nb_running_unset_entry(dnode); + if (offset->direct[direct].alist_name) { + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = NULL; + } + if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL + && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL) + offset_list_del(offset); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/offset-list/access-list + */ +int ripd_instance_offset_list_access_list_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + int direct; + struct rip_offset_list *offset; + const char *alist_name; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "../direction"); + alist_name = yang_dnode_get_string(dnode, NULL); + + offset = nb_running_get_entry(dnode, NULL, true); + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = strdup(alist_name); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/offset-list/metric + */ +int ripd_instance_offset_list_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + int direct; + uint8_t metric; + struct rip_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "../direction"); + metric = yang_dnode_get_uint8(dnode, NULL); + + offset = nb_running_get_entry(dnode, NULL, true); + offset->direct[direct].metric = metric; + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/passive-default + */ +int ripd_instance_passive_default_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->passive_default = yang_dnode_get_bool(dnode, NULL); + rip_passive_nondefault_clean(rip); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/passive-interface + */ +int ripd_instance_passive_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return rip_passive_nondefault_set(rip, ifname); +} + +int ripd_instance_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return rip_passive_nondefault_unset(rip, ifname); +} + +/* + * XPath: /frr-ripd:ripd/instance/non-passive-interface + */ +int ripd_instance_non_passive_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return rip_passive_nondefault_unset(rip, ifname); +} + +int ripd_instance_non_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return rip_passive_nondefault_set(rip, ifname); +} + +/* + * XPath: /frr-ripd:ripd/instance/redistribute + */ +int ripd_instance_redistribute_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "./protocol"); + + rip->redist[type].enabled = true; + + return NB_OK; +} + +int ripd_instance_redistribute_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "./protocol"); + + rip->redist[type].enabled = false; + if (rip->redist[type].route_map.name) { + free(rip->redist[type].route_map.name); + rip->redist[type].route_map.name = NULL; + rip->redist[type].route_map.map = NULL; + } + rip->redist[type].metric_config = false; + rip->redist[type].metric = 0; + + if (rip->enabled) + rip_redistribute_conf_delete(rip, type); + + return NB_OK; +} + +void ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode) +{ + struct rip *rip; + int type; + + rip = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "./protocol"); + + if (rip->enabled) + rip_redistribute_conf_update(rip, type); +} + +/* + * XPath: /frr-ripd:ripd/instance/redistribute/route-map + */ +int ripd_instance_redistribute_route_map_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + int type; + const char *rmap_name; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "../protocol"); + rmap_name = yang_dnode_get_string(dnode, NULL); + + if (rip->redist[type].route_map.name) + free(rip->redist[type].route_map.name); + rip->redist[type].route_map.name = strdup(rmap_name); + rip->redist[type].route_map.map = route_map_lookup_by_name(rmap_name); + + return NB_OK; +} + +int ripd_instance_redistribute_route_map_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "../protocol"); + + free(rip->redist[type].route_map.name); + rip->redist[type].route_map.name = NULL; + rip->redist[type].route_map.map = NULL; + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/redistribute/metric + */ +int ripd_instance_redistribute_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + int type; + uint8_t metric; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "../protocol"); + metric = yang_dnode_get_uint8(dnode, NULL); + + rip->redist[type].metric_config = true; + rip->redist[type].metric = metric; + + return NB_OK; +} + +int ripd_instance_redistribute_metric_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "../protocol"); + + rip->redist[type].metric_config = false; + rip->redist[type].metric = 0; + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/static-route + */ +int ripd_instance_static_route_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + struct nexthop nh; + struct prefix_ipv4 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv4p(&p, dnode, NULL); + apply_mask_ipv4(&p); + + memset(&nh, 0, sizeof(nh)); + nh.type = NEXTHOP_TYPE_IPV4; + rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, + 0, 0); + + return NB_OK; +} + +int ripd_instance_static_route_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct rip *rip; + struct prefix_ipv4 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv4p(&p, dnode, NULL); + apply_mask_ipv4(&p); + + rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/timers/ + */ +void ripd_instance_timers_apply_finish(const struct lyd_node *dnode) +{ + struct rip *rip; + + rip = nb_running_get_entry(dnode, NULL, true); + + /* Reset update timer thread. */ + rip_event(rip, RIP_UPDATE_EVENT, 0); +} + +/* + * XPath: /frr-ripd:ripd/instance/timers/flush-interval + */ +int ripd_instance_timers_flush_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->garbage_time = yang_dnode_get_uint32(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/timers/holddown-interval + */ +int ripd_instance_timers_holddown_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->timeout_time = yang_dnode_get_uint32(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/timers/update-interval + */ +int ripd_instance_timers_update_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->update_time = yang_dnode_get_uint32(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/version/receive + */ +int ripd_instance_version_receive_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->version_recv = yang_dnode_get_enum(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/version/send + */ +int ripd_instance_version_send_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct rip *rip; + + if (event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(dnode, NULL, true); + rip->version_send = yang_dnode_get_enum(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/split-horizon + */ +int lib_interface_rip_split_horizon_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + ri->split_horizon = yang_dnode_get_enum(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/v2-broadcast + */ +int lib_interface_rip_v2_broadcast_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + ri->v2_broadcast = yang_dnode_get_bool(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-receive + */ +int lib_interface_rip_version_receive_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + ri->ri_receive = yang_dnode_get_enum(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-send + */ +int lib_interface_rip_version_send_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + ri->ri_send = yang_dnode_get_enum(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode + */ +int lib_interface_rip_authentication_scheme_mode_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + ri->auth_type = yang_dnode_get_enum(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length + */ +int lib_interface_rip_authentication_scheme_md5_auth_length_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + ri->md5_auth_len = yang_dnode_get_enum(dnode, NULL); + + return NB_OK; +} + +int lib_interface_rip_authentication_scheme_md5_auth_length_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + ri->md5_auth_len = yang_get_default_enum( + "%s/authentication-scheme/md5-auth-length", RIP_IFACE); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-password + */ +int lib_interface_rip_authentication_password_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str); + ri->auth_str = XSTRDUP(MTYPE_RIP_INTERFACE_STRING, + yang_dnode_get_string(dnode, NULL)); + + return NB_OK; +} + +int lib_interface_rip_authentication_password_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain + */ +int lib_interface_rip_authentication_key_chain_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain); + ri->key_chain = XSTRDUP(MTYPE_RIP_INTERFACE_STRING, + yang_dnode_get_string(dnode, NULL)); + + return NB_OK; +} + +int lib_interface_rip_authentication_key_chain_destroy( + enum nb_event event, const struct lyd_node *dnode) +{ + struct interface *ifp; + struct rip_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain); + + return NB_OK; +} diff --git a/ripd/rip_nb_notifications.c b/ripd/rip_nb_notifications.c new file mode 100644 index 0000000000..28d3517dfd --- /dev/null +++ b/ripd/rip_nb_notifications.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "table.h" +#include "command.h" +#include "routemap.h" +#include "northbound.h" +#include "libfrr.h" + +#include "ripd/ripd.h" +#include "ripd/rip_nb.h" +#include "ripd/rip_debug.h" +#include "ripd/rip_interface.h" + +/* + * XPath: /frr-ripd:authentication-type-failure + */ +void ripd_notif_send_auth_type_failure(const char *ifname) +{ + const char *xpath = "/frr-ripd:authentication-type-failure"; + struct list *arguments; + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + + arguments = yang_data_list_new(); + + snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath); + data = yang_data_new_string(xpath_arg, ifname); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + +/* + * XPath: /frr-ripd:authentication-failure + */ +void ripd_notif_send_auth_failure(const char *ifname) +{ + const char *xpath = "/frr-ripd:authentication-failure"; + struct list *arguments; + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + + arguments = yang_data_list_new(); + + snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath); + data = yang_data_new_string(xpath_arg, ifname); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} diff --git a/ripd/rip_nb_rpcs.c b/ripd/rip_nb_rpcs.c new file mode 100644 index 0000000000..0ca85296fd --- /dev/null +++ b/ripd/rip_nb_rpcs.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "table.h" +#include "command.h" +#include "routemap.h" +#include "northbound.h" +#include "libfrr.h" + +#include "ripd/ripd.h" +#include "ripd/rip_nb.h" +#include "ripd/rip_debug.h" +#include "ripd/rip_interface.h" + +/* + * XPath: /frr-ripd:clear-rip-route + */ +static void clear_rip_route(struct rip *rip) +{ + struct route_node *rp; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("Clearing all RIP routes (VRF %s)", rip->vrf_name); + + /* Clear received RIP routes */ + for (rp = route_top(rip->table); rp; rp = route_next(rp)) { + struct list *list; + struct listnode *listnode; + struct rip_info *rinfo; + + list = rp->info; + if (!list) + continue; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + if (!rip_route_rte(rinfo)) + continue; + + if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) + rip_zebra_ipv4_delete(rip, rp); + break; + } + + if (rinfo) { + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_OFF(rinfo->t_garbage_collect); + listnode_delete(list, rinfo); + rip_info_free(rinfo); + } + + if (list_isempty(list)) { + list_delete(&list); + rp->info = NULL; + route_unlock_node(rp); + } + } +} + +int clear_rip_route_rpc(const char *xpath, const struct list *input, + struct list *output) +{ + struct rip *rip; + struct yang_data *yang_vrf; + + yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf"); + if (yang_vrf) { + rip = rip_lookup_by_vrf_name(yang_vrf->value); + if (rip) + clear_rip_route(rip); + } else { + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + rip = vrf->info; + if (!rip) + continue; + + clear_rip_route(rip); + } + } + + return NB_OK; +} diff --git a/ripd/rip_nb_state.c b/ripd/rip_nb_state.c new file mode 100644 index 0000000000..2f7eb3cb5e --- /dev/null +++ b/ripd/rip_nb_state.c @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "table.h" +#include "command.h" +#include "routemap.h" +#include "northbound.h" +#include "libfrr.h" + +#include "ripd/ripd.h" +#include "ripd/rip_nb.h" +#include "ripd/rip_debug.h" +#include "ripd/rip_interface.h" + +/* + * XPath: /frr-ripd:ripd/instance + */ +const void *ripd_instance_get_next(const void *parent_list_entry, + const void *list_entry) +{ + struct rip *rip = (struct rip *)list_entry; + + if (list_entry == NULL) + rip = RB_MIN(rip_instance_head, &rip_instances); + else + rip = RB_NEXT(rip_instance_head, rip); + + return rip; +} + +int ripd_instance_get_keys(const void *list_entry, struct yang_list_keys *keys) +{ + const struct rip *rip = list_entry; + + keys->num = 1; + strlcpy(keys->key[0], rip->vrf_name, sizeof(keys->key[0])); + + return NB_OK; +} + +const void *ripd_instance_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys) +{ + const char *vrf_name = keys->key[0]; + + return rip_lookup_by_vrf_name(vrf_name); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor + */ +const void * +ripd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry, + const void *list_entry) +{ + const struct rip *rip = parent_list_entry; + struct listnode *node; + + if (list_entry == NULL) + node = listhead(rip->peer_list); + else + node = listnextnode((struct listnode *)list_entry); + + return node; +} + +int ripd_instance_state_neighbors_neighbor_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct listnode *node = list_entry; + const struct rip_peer *peer = listgetdata(node); + + keys->num = 1; + (void)inet_ntop(AF_INET, &peer->addr, keys->key[0], + sizeof(keys->key[0])); + + return NB_OK; +} + +const void *ripd_instance_state_neighbors_neighbor_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys) +{ + const struct rip *rip = parent_list_entry; + struct in_addr address; + struct rip_peer *peer; + struct listnode *node; + + yang_str2ipv4(keys->key[0], &address); + + for (ALL_LIST_ELEMENTS_RO(rip->peer_list, node, peer)) { + if (IPV4_ADDR_SAME(&peer->addr, &address)) + return node; + } + + return NULL; +} + +/* + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/address + */ +struct yang_data * +ripd_instance_state_neighbors_neighbor_address_get_elem(const char *xpath, + const void *list_entry) +{ + const struct listnode *node = list_entry; + const struct rip_peer *peer = listgetdata(node); + + return yang_data_new_ipv4(xpath, &peer->addr); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/last-update + */ +struct yang_data *ripd_instance_state_neighbors_neighbor_last_update_get_elem( + const char *xpath, const void *list_entry) +{ + /* TODO: yang:date-and-time is tricky */ + return NULL; +} + +/* + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd + */ +struct yang_data * +ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem( + const char *xpath, const void *list_entry) +{ + const struct listnode *node = list_entry; + const struct rip_peer *peer = listgetdata(node); + + return yang_data_new_uint32(xpath, peer->recv_badpackets); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd + */ +struct yang_data * +ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem( + const char *xpath, const void *list_entry) +{ + const struct listnode *node = list_entry; + const struct rip_peer *peer = listgetdata(node); + + return yang_data_new_uint32(xpath, peer->recv_badroutes); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route + */ +const void * +ripd_instance_state_routes_route_get_next(const void *parent_list_entry, + const void *list_entry) +{ + const struct rip *rip = parent_list_entry; + struct route_node *rn; + + if (list_entry == NULL) + rn = route_top(rip->table); + else + rn = route_next((struct route_node *)list_entry); + while (rn && rn->info == NULL) + rn = route_next(rn); + + return rn; +} + +int ripd_instance_state_routes_route_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct route_node *rn = list_entry; + + keys->num = 1; + (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0])); + + return NB_OK; +} + +const void * +ripd_instance_state_routes_route_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys) +{ + const struct rip *rip = parent_list_entry; + struct prefix prefix; + struct route_node *rn; + + yang_str2ipv4p(keys->key[0], &prefix); + + rn = route_node_lookup(rip->table, &prefix); + if (!rn || !rn->info) + return NULL; + + route_unlock_node(rn); + + return rn; +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/prefix + */ +struct yang_data * +ripd_instance_state_routes_route_prefix_get_elem(const char *xpath, + const void *list_entry) +{ + const struct route_node *rn = list_entry; + const struct rip_info *rinfo = listnode_head(rn->info); + + return yang_data_new_ipv4p(xpath, &rinfo->rp->p); +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/next-hop + */ +struct yang_data * +ripd_instance_state_routes_route_next_hop_get_elem(const char *xpath, + const void *list_entry) +{ + const struct route_node *rn = list_entry; + const struct rip_info *rinfo = listnode_head(rn->info); + + switch (rinfo->nh.type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + return yang_data_new_ipv4(xpath, &rinfo->nh.gate.ipv4); + default: + return NULL; + } +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/interface + */ +struct yang_data * +ripd_instance_state_routes_route_interface_get_elem(const char *xpath, + const void *list_entry) +{ + const struct route_node *rn = list_entry; + const struct rip_info *rinfo = listnode_head(rn->info); + const struct rip *rip = rip_info_get_instance(rinfo); + + switch (rinfo->nh.type) { + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: + return yang_data_new_string( + xpath, + ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id)); + default: + return NULL; + } +} + +/* + * XPath: /frr-ripd:ripd/instance/state/routes/route/metric + */ +struct yang_data * +ripd_instance_state_routes_route_metric_get_elem(const char *xpath, + const void *list_entry) +{ + const struct route_node *rn = list_entry; + const struct rip_info *rinfo = listnode_head(rn->info); + + return yang_data_new_uint8(xpath, rinfo->metric); +} diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c deleted file mode 100644 index 1238d0f0fc..0000000000 --- a/ripd/rip_northbound.c +++ /dev/null @@ -1,1823 +0,0 @@ -/* - * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro - * Copyright (C) 2018 NetDEF, Inc. - * Renato Westphal - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "if.h" -#include "vrf.h" -#include "log.h" -#include "prefix.h" -#include "table.h" -#include "command.h" -#include "routemap.h" -#include "northbound.h" -#include "libfrr.h" - -#include "ripd/ripd.h" -#include "ripd/rip_debug.h" -#include "ripd/rip_cli.h" -#include "ripd/rip_interface.h" - -/* - * XPath: /frr-ripd:ripd/instance - */ -static int ripd_instance_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - struct vrf *vrf; - const char *vrf_name; - int socket; - - vrf_name = yang_dnode_get_string(dnode, "./vrf"); - vrf = vrf_lookup_by_name(vrf_name); - - /* - * Try to create a RIP socket only if the VRF is enabled, otherwise - * create a disabled RIP instance and wait for the VRF to be enabled. - */ - switch (event) { - case NB_EV_VALIDATE: - break; - case NB_EV_PREPARE: - if (!vrf || !vrf_is_enabled(vrf)) - break; - - socket = rip_create_socket(vrf); - if (socket < 0) - return NB_ERR_RESOURCE; - resource->fd = socket; - break; - case NB_EV_ABORT: - if (!vrf || !vrf_is_enabled(vrf)) - break; - - socket = resource->fd; - close(socket); - break; - case NB_EV_APPLY: - if (vrf && vrf_is_enabled(vrf)) - socket = resource->fd; - else - socket = -1; - - rip = rip_create(vrf_name, vrf, socket); - nb_running_set_entry(dnode, rip); - break; - } - - return NB_OK; -} - -static int ripd_instance_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_unset_entry(dnode); - rip_clean(rip); - - return NB_OK; -} - -static const void *ripd_instance_get_next(const void *parent_list_entry, - const void *list_entry) -{ - struct rip *rip = (struct rip *)list_entry; - - if (list_entry == NULL) - rip = RB_MIN(rip_instance_head, &rip_instances); - else - rip = RB_NEXT(rip_instance_head, rip); - - return rip; -} - -static int ripd_instance_get_keys(const void *list_entry, - struct yang_list_keys *keys) -{ - const struct rip *rip = list_entry; - - keys->num = 1; - strlcpy(keys->key[0], rip->vrf_name, sizeof(keys->key[0])); - - return NB_OK; -} - -static const void *ripd_instance_lookup_entry(const void *parent_list_entry, - const struct yang_list_keys *keys) -{ - const char *vrf_name = keys->key[0]; - - return rip_lookup_by_vrf_name(vrf_name); -} - -/* - * XPath: /frr-ripd:ripd/instance/allow-ecmp - */ -static int ripd_instance_allow_ecmp_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->ecmp = yang_dnode_get_bool(dnode, NULL); - if (!rip->ecmp) - rip_ecmp_disable(rip); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/default-information-originate - */ -static int -ripd_instance_default_information_originate_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - bool default_information; - struct prefix_ipv4 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - default_information = yang_dnode_get_bool(dnode, NULL); - - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - if (default_information) { - struct nexthop nh; - - memset(&nh, 0, sizeof(nh)); - nh.type = NEXTHOP_TYPE_IPV4; - rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, - &p, &nh, 0, 0, 0); - } else { - rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, - &p, 0); - } - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/default-metric - */ -static int ripd_instance_default_metric_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->default_metric = yang_dnode_get_uint8(dnode, NULL); - /* rip_update_default_metric (); */ - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/distance/default - */ -static int ripd_instance_distance_default_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->distance = yang_dnode_get_uint8(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/distance/source - */ -static int ripd_instance_distance_source_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - struct prefix_ipv4 prefix; - struct route_node *rn; - - if (event != NB_EV_APPLY) - return NB_OK; - - yang_dnode_get_ipv4p(&prefix, dnode, "./prefix"); - apply_mask_ipv4(&prefix); - - /* Get RIP distance node. */ - rip = nb_running_get_entry(dnode, NULL, true); - rn = route_node_get(rip->distance_table, (struct prefix *)&prefix); - rn->info = rip_distance_new(); - nb_running_set_entry(dnode, rn); - - return NB_OK; -} - -static int ripd_instance_distance_source_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct route_node *rn; - struct rip_distance *rdistance; - - if (event != NB_EV_APPLY) - return NB_OK; - - rn = nb_running_unset_entry(dnode); - rdistance = rn->info; - rip_distance_free(rdistance); - rn->info = NULL; - route_unlock_node(rn); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/distance/source/distance - */ -static int -ripd_instance_distance_source_distance_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct route_node *rn; - uint8_t distance; - struct rip_distance *rdistance; - - if (event != NB_EV_APPLY) - return NB_OK; - - /* Set distance value. */ - rn = nb_running_get_entry(dnode, NULL, true); - distance = yang_dnode_get_uint8(dnode, NULL); - rdistance = rn->info; - rdistance->distance = distance; - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/distance/source/access-list - */ -static int -ripd_instance_distance_source_access_list_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - const char *acl_name; - struct route_node *rn; - struct rip_distance *rdistance; - - if (event != NB_EV_APPLY) - return NB_OK; - - acl_name = yang_dnode_get_string(dnode, NULL); - - /* Set access-list */ - rn = nb_running_get_entry(dnode, NULL, true); - rdistance = rn->info; - if (rdistance->access_list) - free(rdistance->access_list); - rdistance->access_list = strdup(acl_name); - - return NB_OK; -} - -static int -ripd_instance_distance_source_access_list_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct route_node *rn; - struct rip_distance *rdistance; - - if (event != NB_EV_APPLY) - return NB_OK; - - /* Reset access-list configuration. */ - rn = nb_running_get_entry(dnode, NULL, true); - rdistance = rn->info; - free(rdistance->access_list); - rdistance->access_list = NULL; - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/explicit-neighbor - */ -static int ripd_instance_explicit_neighbor_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - struct prefix_ipv4 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - yang_dnode_get_ipv4(&p.prefix, dnode, NULL); - - return rip_neighbor_add(rip, &p); -} - -static int ripd_instance_explicit_neighbor_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - struct prefix_ipv4 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - yang_dnode_get_ipv4(&p.prefix, dnode, NULL); - - return rip_neighbor_delete(rip, &p); -} - -/* - * XPath: /frr-ripd:ripd/instance/network - */ -static int ripd_instance_network_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - struct prefix p; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv4p(&p, dnode, NULL); - apply_mask_ipv4((struct prefix_ipv4 *)&p); - - return rip_enable_network_add(rip, &p); -} - -static int ripd_instance_network_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - struct prefix p; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv4p(&p, dnode, NULL); - apply_mask_ipv4((struct prefix_ipv4 *)&p); - - return rip_enable_network_delete(rip, &p); -} - -/* - * XPath: /frr-ripd:ripd/instance/interface - */ -static int ripd_instance_interface_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return rip_enable_if_add(rip, ifname); -} - -static int ripd_instance_interface_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return rip_enable_if_delete(rip, ifname); -} - -/* - * XPath: /frr-ripd:ripd/instance/offset-list - */ -static int ripd_instance_offset_list_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - const char *ifname; - struct rip_offset_list *offset; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, "./interface"); - - offset = rip_offset_list_new(rip, ifname); - nb_running_set_entry(dnode, offset); - - return NB_OK; -} - -static int ripd_instance_offset_list_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - int direct; - struct rip_offset_list *offset; - - if (event != NB_EV_APPLY) - return NB_OK; - - direct = yang_dnode_get_enum(dnode, "./direction"); - - offset = nb_running_unset_entry(dnode); - if (offset->direct[direct].alist_name) { - free(offset->direct[direct].alist_name); - offset->direct[direct].alist_name = NULL; - } - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL - && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL) - offset_list_del(offset); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/offset-list/access-list - */ -static int -ripd_instance_offset_list_access_list_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - int direct; - struct rip_offset_list *offset; - const char *alist_name; - - if (event != NB_EV_APPLY) - return NB_OK; - - direct = yang_dnode_get_enum(dnode, "../direction"); - alist_name = yang_dnode_get_string(dnode, NULL); - - offset = nb_running_get_entry(dnode, NULL, true); - if (offset->direct[direct].alist_name) - free(offset->direct[direct].alist_name); - offset->direct[direct].alist_name = strdup(alist_name); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/offset-list/metric - */ -static int ripd_instance_offset_list_metric_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - int direct; - uint8_t metric; - struct rip_offset_list *offset; - - if (event != NB_EV_APPLY) - return NB_OK; - - direct = yang_dnode_get_enum(dnode, "../direction"); - metric = yang_dnode_get_uint8(dnode, NULL); - - offset = nb_running_get_entry(dnode, NULL, true); - offset->direct[direct].metric = metric; - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/passive-default - */ -static int ripd_instance_passive_default_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->passive_default = yang_dnode_get_bool(dnode, NULL); - rip_passive_nondefault_clean(rip); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/passive-interface - */ -static int ripd_instance_passive_interface_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return rip_passive_nondefault_set(rip, ifname); -} - -static int ripd_instance_passive_interface_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return rip_passive_nondefault_unset(rip, ifname); -} - -/* - * XPath: /frr-ripd:ripd/instance/non-passive-interface - */ -static int -ripd_instance_non_passive_interface_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return rip_passive_nondefault_unset(rip, ifname); -} - -static int -ripd_instance_non_passive_interface_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return rip_passive_nondefault_set(rip, ifname); -} - -/* - * XPath: /frr-ripd:ripd/instance/redistribute - */ -static int ripd_instance_redistribute_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "./protocol"); - - rip->redist[type].enabled = true; - - return NB_OK; -} - -static int ripd_instance_redistribute_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "./protocol"); - - rip->redist[type].enabled = false; - if (rip->redist[type].route_map.name) { - free(rip->redist[type].route_map.name); - rip->redist[type].route_map.name = NULL; - rip->redist[type].route_map.map = NULL; - } - rip->redist[type].metric_config = false; - rip->redist[type].metric = 0; - - if (rip->enabled) - rip_redistribute_conf_delete(rip, type); - - return NB_OK; -} - -static void -ripd_instance_redistribute_apply_finish(const struct lyd_node *dnode) -{ - struct rip *rip; - int type; - - rip = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "./protocol"); - - if (rip->enabled) - rip_redistribute_conf_update(rip, type); -} - -/* - * XPath: /frr-ripd:ripd/instance/redistribute/route-map - */ -static int -ripd_instance_redistribute_route_map_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - int type; - const char *rmap_name; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "../protocol"); - rmap_name = yang_dnode_get_string(dnode, NULL); - - if (rip->redist[type].route_map.name) - free(rip->redist[type].route_map.name); - rip->redist[type].route_map.name = strdup(rmap_name); - rip->redist[type].route_map.map = route_map_lookup_by_name(rmap_name); - - return NB_OK; -} - -static int -ripd_instance_redistribute_route_map_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "../protocol"); - - free(rip->redist[type].route_map.name); - rip->redist[type].route_map.name = NULL; - rip->redist[type].route_map.map = NULL; - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/redistribute/metric - */ -static int -ripd_instance_redistribute_metric_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - int type; - uint8_t metric; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "../protocol"); - metric = yang_dnode_get_uint8(dnode, NULL); - - rip->redist[type].metric_config = true; - rip->redist[type].metric = metric; - - return NB_OK; -} - -static int -ripd_instance_redistribute_metric_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "../protocol"); - - rip->redist[type].metric_config = false; - rip->redist[type].metric = 0; - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/static-route - */ -static int ripd_instance_static_route_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - struct nexthop nh; - struct prefix_ipv4 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv4p(&p, dnode, NULL); - apply_mask_ipv4(&p); - - memset(&nh, 0, sizeof(nh)); - nh.type = NEXTHOP_TYPE_IPV4; - rip_redistribute_add(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0, - 0, 0); - - return NB_OK; -} - -static int ripd_instance_static_route_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct rip *rip; - struct prefix_ipv4 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv4p(&p, dnode, NULL); - apply_mask_ipv4(&p); - - rip_redistribute_delete(rip, ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/timers/ - */ -static void ripd_instance_timers_apply_finish(const struct lyd_node *dnode) -{ - struct rip *rip; - - rip = nb_running_get_entry(dnode, NULL, true); - - /* Reset update timer thread. */ - rip_event(rip, RIP_UPDATE_EVENT, 0); -} - -/* - * XPath: /frr-ripd:ripd/instance/timers/flush-interval - */ -static int -ripd_instance_timers_flush_interval_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->garbage_time = yang_dnode_get_uint32(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/timers/holddown-interval - */ -static int -ripd_instance_timers_holddown_interval_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->timeout_time = yang_dnode_get_uint32(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/timers/update-interval - */ -static int -ripd_instance_timers_update_interval_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->update_time = yang_dnode_get_uint32(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/version/receive - */ -static int ripd_instance_version_receive_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->version_recv = yang_dnode_get_enum(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/version/send - */ -static int ripd_instance_version_send_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct rip *rip; - - if (event != NB_EV_APPLY) - return NB_OK; - - rip = nb_running_get_entry(dnode, NULL, true); - rip->version_send = yang_dnode_get_enum(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-ripd:rip/split-horizon - */ -static int lib_interface_rip_split_horizon_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - ri->split_horizon = yang_dnode_get_enum(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-ripd:rip/v2-broadcast - */ -static int lib_interface_rip_v2_broadcast_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - ri->v2_broadcast = yang_dnode_get_bool(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-receive - */ -static int -lib_interface_rip_version_receive_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - ri->ri_receive = yang_dnode_get_enum(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-send - */ -static int lib_interface_rip_version_send_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - ri->ri_send = yang_dnode_get_enum(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode - */ -static int lib_interface_rip_authentication_scheme_mode_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - ri->auth_type = yang_dnode_get_enum(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length - */ -static int lib_interface_rip_authentication_scheme_md5_auth_length_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - ri->md5_auth_len = yang_dnode_get_enum(dnode, NULL); - - return NB_OK; -} - -static int lib_interface_rip_authentication_scheme_md5_auth_length_destroy( - enum nb_event event, const struct lyd_node *dnode) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - ri->md5_auth_len = yang_get_default_enum( - "%s/authentication-scheme/md5-auth-length", RIP_IFACE); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-password - */ -static int -lib_interface_rip_authentication_password_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str); - ri->auth_str = XSTRDUP(MTYPE_RIP_INTERFACE_STRING, - yang_dnode_get_string(dnode, NULL)); - - return NB_OK; -} - -static int -lib_interface_rip_authentication_password_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str); - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain - */ -static int -lib_interface_rip_authentication_key_chain_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain); - ri->key_chain = XSTRDUP(MTYPE_RIP_INTERFACE_STRING, - yang_dnode_get_string(dnode, NULL)); - - return NB_OK; -} - -static int -lib_interface_rip_authentication_key_chain_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct interface *ifp; - struct rip_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain); - - return NB_OK; -} - -/* - * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor - */ -static const void * -ripd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry, - const void *list_entry) -{ - const struct rip *rip = parent_list_entry; - struct listnode *node; - - if (list_entry == NULL) - node = listhead(rip->peer_list); - else - node = listnextnode((struct listnode *)list_entry); - - return node; -} - -static int -ripd_instance_state_neighbors_neighbor_get_keys(const void *list_entry, - struct yang_list_keys *keys) -{ - const struct listnode *node = list_entry; - const struct rip_peer *peer = listgetdata(node); - - keys->num = 1; - (void)inet_ntop(AF_INET, &peer->addr, keys->key[0], - sizeof(keys->key[0])); - - return NB_OK; -} - -static const void *ripd_instance_state_neighbors_neighbor_lookup_entry( - const void *parent_list_entry, const struct yang_list_keys *keys) -{ - const struct rip *rip = parent_list_entry; - struct in_addr address; - struct rip_peer *peer; - struct listnode *node; - - yang_str2ipv4(keys->key[0], &address); - - for (ALL_LIST_ELEMENTS_RO(rip->peer_list, node, peer)) { - if (IPV4_ADDR_SAME(&peer->addr, &address)) - return node; - } - - return NULL; -} - -/* - * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/address - */ -static struct yang_data * -ripd_instance_state_neighbors_neighbor_address_get_elem(const char *xpath, - const void *list_entry) -{ - const struct listnode *node = list_entry; - const struct rip_peer *peer = listgetdata(node); - - return yang_data_new_ipv4(xpath, &peer->addr); -} - -/* - * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/last-update - */ -static struct yang_data * -ripd_instance_state_neighbors_neighbor_last_update_get_elem( - const char *xpath, const void *list_entry) -{ - /* TODO: yang:date-and-time is tricky */ - return NULL; -} - -/* - * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd - */ -static struct yang_data * -ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem( - const char *xpath, const void *list_entry) -{ - const struct listnode *node = list_entry; - const struct rip_peer *peer = listgetdata(node); - - return yang_data_new_uint32(xpath, peer->recv_badpackets); -} - -/* - * XPath: /frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd - */ -static struct yang_data * -ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem( - const char *xpath, const void *list_entry) -{ - const struct listnode *node = list_entry; - const struct rip_peer *peer = listgetdata(node); - - return yang_data_new_uint32(xpath, peer->recv_badroutes); -} - -/* - * XPath: /frr-ripd:ripd/instance/state/routes/route - */ -static const void * -ripd_instance_state_routes_route_get_next(const void *parent_list_entry, - const void *list_entry) -{ - const struct rip *rip = parent_list_entry; - struct route_node *rn; - - if (list_entry == NULL) - rn = route_top(rip->table); - else - rn = route_next((struct route_node *)list_entry); - while (rn && rn->info == NULL) - rn = route_next(rn); - - return rn; -} - -static int -ripd_instance_state_routes_route_get_keys(const void *list_entry, - struct yang_list_keys *keys) -{ - const struct route_node *rn = list_entry; - - keys->num = 1; - (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0])); - - return NB_OK; -} - -static const void * -ripd_instance_state_routes_route_lookup_entry(const void *parent_list_entry, - const struct yang_list_keys *keys) -{ - const struct rip *rip = parent_list_entry; - struct prefix prefix; - struct route_node *rn; - - yang_str2ipv4p(keys->key[0], &prefix); - - rn = route_node_lookup(rip->table, &prefix); - if (!rn || !rn->info) - return NULL; - - route_unlock_node(rn); - - return rn; -} - -/* - * XPath: /frr-ripd:ripd/instance/state/routes/route/prefix - */ -static struct yang_data * -ripd_instance_state_routes_route_prefix_get_elem(const char *xpath, - const void *list_entry) -{ - const struct route_node *rn = list_entry; - const struct rip_info *rinfo = listnode_head(rn->info); - - return yang_data_new_ipv4p(xpath, &rinfo->rp->p); -} - -/* - * XPath: /frr-ripd:ripd/instance/state/routes/route/next-hop - */ -static struct yang_data * -ripd_instance_state_routes_route_next_hop_get_elem(const char *xpath, - const void *list_entry) -{ - const struct route_node *rn = list_entry; - const struct rip_info *rinfo = listnode_head(rn->info); - - switch (rinfo->nh.type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - return yang_data_new_ipv4(xpath, &rinfo->nh.gate.ipv4); - default: - return NULL; - } -} - -/* - * XPath: /frr-ripd:ripd/instance/state/routes/route/interface - */ -static struct yang_data * -ripd_instance_state_routes_route_interface_get_elem(const char *xpath, - const void *list_entry) -{ - const struct route_node *rn = list_entry; - const struct rip_info *rinfo = listnode_head(rn->info); - const struct rip *rip = rip_info_get_instance(rinfo); - - switch (rinfo->nh.type) { - case NEXTHOP_TYPE_IFINDEX: - case NEXTHOP_TYPE_IPV4_IFINDEX: - return yang_data_new_string( - xpath, - ifindex2ifname(rinfo->nh.ifindex, rip->vrf->vrf_id)); - default: - return NULL; - } -} - -/* - * XPath: /frr-ripd:ripd/instance/state/routes/route/metric - */ -static struct yang_data * -ripd_instance_state_routes_route_metric_get_elem(const char *xpath, - const void *list_entry) -{ - const struct route_node *rn = list_entry; - const struct rip_info *rinfo = listnode_head(rn->info); - - return yang_data_new_uint8(xpath, rinfo->metric); -} - -/* - * XPath: /frr-ripd:clear-rip-route - */ -static void clear_rip_route(struct rip *rip) -{ - struct route_node *rp; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug("Clearing all RIP routes (VRF %s)", rip->vrf_name); - - /* Clear received RIP routes */ - for (rp = route_top(rip->table); rp; rp = route_next(rp)) { - struct list *list; - struct listnode *listnode; - struct rip_info *rinfo; - - list = rp->info; - if (!list) - continue; - - for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - if (!rip_route_rte(rinfo)) - continue; - - if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete(rip, rp); - break; - } - - if (rinfo) { - RIP_TIMER_OFF(rinfo->t_timeout); - RIP_TIMER_OFF(rinfo->t_garbage_collect); - listnode_delete(list, rinfo); - rip_info_free(rinfo); - } - - if (list_isempty(list)) { - list_delete(&list); - rp->info = NULL; - route_unlock_node(rp); - } - } -} - -static int clear_rip_route_rpc(const char *xpath, const struct list *input, - struct list *output) -{ - struct rip *rip; - struct yang_data *yang_vrf; - - yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf"); - if (yang_vrf) { - rip = rip_lookup_by_vrf_name(yang_vrf->value); - if (rip) - clear_rip_route(rip); - } else { - struct vrf *vrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - rip = vrf->info; - if (!rip) - continue; - - clear_rip_route(rip); - } - } - - return NB_OK; -} - -/* - * XPath: /frr-ripd:authentication-type-failure - */ -void ripd_notif_send_auth_type_failure(const char *ifname) -{ - const char *xpath = "/frr-ripd:authentication-type-failure"; - struct list *arguments; - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - - arguments = yang_data_list_new(); - - snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath); - data = yang_data_new_string(xpath_arg, ifname); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* - * XPath: /frr-ripd:authentication-failure - */ -void ripd_notif_send_auth_failure(const char *ifname) -{ - const char *xpath = "/frr-ripd:authentication-failure"; - struct list *arguments; - char xpath_arg[XPATH_MAXLEN]; - struct yang_data *data; - - arguments = yang_data_list_new(); - - snprintf(xpath_arg, sizeof(xpath_arg), "%s/interface-name", xpath); - data = yang_data_new_string(xpath_arg, ifname); - listnode_add(arguments, data); - - nb_notification_send(xpath, arguments); -} - -/* clang-format off */ -const struct frr_yang_module_info frr_ripd_info = { - .name = "frr-ripd", - .nodes = { - { - .xpath = "/frr-ripd:ripd/instance", - .cbs = { - .cli_show = cli_show_router_rip, - .create = ripd_instance_create, - .destroy = ripd_instance_destroy, - .get_keys = ripd_instance_get_keys, - .get_next = ripd_instance_get_next, - .lookup_entry = ripd_instance_lookup_entry, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/allow-ecmp", - .cbs = { - .cli_show = cli_show_rip_allow_ecmp, - .modify = ripd_instance_allow_ecmp_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/default-information-originate", - .cbs = { - .cli_show = cli_show_rip_default_information_originate, - .modify = ripd_instance_default_information_originate_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/default-metric", - .cbs = { - .cli_show = cli_show_rip_default_metric, - .modify = ripd_instance_default_metric_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/distance/default", - .cbs = { - .cli_show = cli_show_rip_distance, - .modify = ripd_instance_distance_default_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/distance/source", - .cbs = { - .cli_show = cli_show_rip_distance_source, - .create = ripd_instance_distance_source_create, - .destroy = ripd_instance_distance_source_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/distance/source/distance", - .cbs = { - .modify = ripd_instance_distance_source_distance_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/distance/source/access-list", - .cbs = { - .destroy = ripd_instance_distance_source_access_list_destroy, - .modify = ripd_instance_distance_source_access_list_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/explicit-neighbor", - .cbs = { - .cli_show = cli_show_rip_neighbor, - .create = ripd_instance_explicit_neighbor_create, - .destroy = ripd_instance_explicit_neighbor_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/network", - .cbs = { - .cli_show = cli_show_rip_network_prefix, - .create = ripd_instance_network_create, - .destroy = ripd_instance_network_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/interface", - .cbs = { - .cli_show = cli_show_rip_network_interface, - .create = ripd_instance_interface_create, - .destroy = ripd_instance_interface_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/offset-list", - .cbs = { - .cli_show = cli_show_rip_offset_list, - .create = ripd_instance_offset_list_create, - .destroy = ripd_instance_offset_list_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/offset-list/access-list", - .cbs = { - .modify = ripd_instance_offset_list_access_list_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/offset-list/metric", - .cbs = { - .modify = ripd_instance_offset_list_metric_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/passive-default", - .cbs = { - .cli_show = cli_show_rip_passive_default, - .modify = ripd_instance_passive_default_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/passive-interface", - .cbs = { - .cli_show = cli_show_rip_passive_interface, - .create = ripd_instance_passive_interface_create, - .destroy = ripd_instance_passive_interface_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/non-passive-interface", - .cbs = { - .cli_show = cli_show_rip_non_passive_interface, - .create = ripd_instance_non_passive_interface_create, - .destroy = ripd_instance_non_passive_interface_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/redistribute", - .cbs = { - .apply_finish = ripd_instance_redistribute_apply_finish, - .cli_show = cli_show_rip_redistribute, - .create = ripd_instance_redistribute_create, - .destroy = ripd_instance_redistribute_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/redistribute/route-map", - .cbs = { - .destroy = ripd_instance_redistribute_route_map_destroy, - .modify = ripd_instance_redistribute_route_map_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/redistribute/metric", - .cbs = { - .destroy = ripd_instance_redistribute_metric_destroy, - .modify = ripd_instance_redistribute_metric_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/static-route", - .cbs = { - .cli_show = cli_show_rip_route, - .create = ripd_instance_static_route_create, - .destroy = ripd_instance_static_route_destroy, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/timers", - .cbs = { - .apply_finish = ripd_instance_timers_apply_finish, - .cli_show = cli_show_rip_timers, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/timers/flush-interval", - .cbs = { - .modify = ripd_instance_timers_flush_interval_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/timers/holddown-interval", - .cbs = { - .modify = ripd_instance_timers_holddown_interval_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/timers/update-interval", - .cbs = { - .modify = ripd_instance_timers_update_interval_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/version", - .cbs = { - .cli_show = cli_show_rip_version, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/version/receive", - .cbs = { - .modify = ripd_instance_version_receive_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/version/send", - .cbs = { - .modify = ripd_instance_version_send_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/split-horizon", - .cbs = { - .cli_show = cli_show_ip_rip_split_horizon, - .modify = lib_interface_rip_split_horizon_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/v2-broadcast", - .cbs = { - .cli_show = cli_show_ip_rip_v2_broadcast, - .modify = lib_interface_rip_v2_broadcast_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-receive", - .cbs = { - .cli_show = cli_show_ip_rip_receive_version, - .modify = lib_interface_rip_version_receive_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-send", - .cbs = { - .cli_show = cli_show_ip_rip_send_version, - .modify = lib_interface_rip_version_send_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme", - .cbs = { - .cli_show = cli_show_ip_rip_authentication_scheme, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/mode", - .cbs = { - .modify = lib_interface_rip_authentication_scheme_mode_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme/md5-auth-length", - .cbs = { - .destroy = lib_interface_rip_authentication_scheme_md5_auth_length_destroy, - .modify = lib_interface_rip_authentication_scheme_md5_auth_length_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password", - .cbs = { - .cli_show = cli_show_ip_rip_authentication_string, - .destroy = lib_interface_rip_authentication_password_destroy, - .modify = lib_interface_rip_authentication_password_modify, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain", - .cbs = { - .cli_show = cli_show_ip_rip_authentication_key_chain, - .destroy = lib_interface_rip_authentication_key_chain_destroy, - .modify = lib_interface_rip_authentication_key_chain_modify, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor", - .cbs = { - .get_keys = ripd_instance_state_neighbors_neighbor_get_keys, - .get_next = ripd_instance_state_neighbors_neighbor_get_next, - .lookup_entry = ripd_instance_state_neighbors_neighbor_lookup_entry, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/address", - .cbs = { - .get_elem = ripd_instance_state_neighbors_neighbor_address_get_elem, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/last-update", - .cbs = { - .get_elem = ripd_instance_state_neighbors_neighbor_last_update_get_elem, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-packets-rcvd", - .cbs = { - .get_elem = ripd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/neighbors/neighbor/bad-routes-rcvd", - .cbs = { - .get_elem = ripd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/routes/route", - .cbs = { - .get_keys = ripd_instance_state_routes_route_get_keys, - .get_next = ripd_instance_state_routes_route_get_next, - .lookup_entry = ripd_instance_state_routes_route_lookup_entry, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/routes/route/prefix", - .cbs = { - .get_elem = ripd_instance_state_routes_route_prefix_get_elem, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/routes/route/next-hop", - .cbs = { - .get_elem = ripd_instance_state_routes_route_next_hop_get_elem, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/routes/route/interface", - .cbs = { - .get_elem = ripd_instance_state_routes_route_interface_get_elem, - }, - }, - { - .xpath = "/frr-ripd:ripd/instance/state/routes/route/metric", - .cbs = { - .get_elem = ripd_instance_state_routes_route_metric_get_elem, - }, - }, - { - .xpath = "/frr-ripd:clear-rip-route", - .cbs = { - .rpc = clear_rip_route_rpc, - }, - }, - { - .xpath = NULL, - }, - } -}; diff --git a/ripd/ripd.c b/ripd/ripd.c index 1b5a582cb1..ec0770ef3d 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -46,6 +46,7 @@ #include "northbound_cli.h" #include "ripd/ripd.h" +#include "ripd/rip_nb.h" #include "ripd/rip_debug.h" #include "ripd/rip_errors.h" #include "ripd/rip_interface.h" diff --git a/ripd/ripd.h b/ripd/ripd.h index 7f2c3fd068..417bd5b3b1 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -521,10 +521,7 @@ extern int offset_list_cmp(struct rip_offset_list *o1, extern void rip_vrf_init(void); extern void rip_vrf_terminate(void); - -/* YANG notifications */ -extern void ripd_notif_send_auth_type_failure(const char *ifname); -extern void ripd_notif_send_auth_failure(const char *ifname); +extern void rip_cli_init(void); extern struct zebra_privs_t ripd_privs; extern struct rip_instance_head rip_instances; @@ -535,8 +532,4 @@ extern struct thread_master *master; DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) -/* Northbound. */ -extern void rip_cli_init(void); -extern const struct frr_yang_module_info frr_ripd_info; - #endif /* _ZEBRA_RIP_H */ diff --git a/ripd/subdir.am b/ripd/subdir.am index 312c1db6af..dfdfc88a56 100644 --- a/ripd/subdir.am +++ b/ripd/subdir.am @@ -24,7 +24,11 @@ ripd_librip_a_SOURCES = \ ripd/rip_errors.c \ ripd/rip_interface.c \ ripd/rip_offset.c \ - ripd/rip_northbound.c \ + ripd/rip_nb.c \ + ripd/rip_nb_config.c \ + ripd/rip_nb_rpcs.c \ + ripd/rip_nb_notifications.c \ + ripd/rip_nb_state.c \ ripd/rip_peer.c \ ripd/rip_routemap.c \ ripd/rip_zebra.c \ @@ -35,10 +39,10 @@ ripd/rip_cli_clippy.c: $(CLIPPY_DEPS) ripd/rip_cli.$(OBJEXT): ripd/rip_cli_clippy.c noinst_HEADERS += \ - ripd/rip_cli.h \ ripd/rip_debug.h \ ripd/rip_errors.h \ ripd/rip_interface.h \ + ripd/rip_nb.h \ ripd/ripd.h \ # end From ca4739362988cc1591bf977dd9db0b911ed4f158 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 17 Oct 2019 16:03:09 -0300 Subject: [PATCH 3/5] ripngd: split northbound callbacks into multiple files Rearrange the ripngd northbound callbacks as following: * ripng_nb.h: prototypes of all northbound callbacks. * ripng_nb.c: definition of all northbound callbacks and their associated YANG data paths. * ripng_nb_config.c: implementation of YANG configuration nodes. * ripng_nb_state.c: implementation of YANG state nodes. * ripng_nb_rpcs.c: implementation of YANG RPCs. This should help to keep to code more organized and easier to maintain. No behavior changes intended. Signed-off-by: Renato Westphal --- ripngd/ripng_cli.c | 2 +- ripngd/ripng_cli.h | 58 -- ripngd/ripng_main.c | 1 + ripngd/ripng_nb.c | 252 ++++++++ ripngd/ripng_nb.h | 179 ++++++ ripngd/ripng_nb_config.c | 714 +++++++++++++++++++++ ripngd/ripng_nb_rpcs.c | 107 ++++ ripngd/ripng_nb_state.c | 236 +++++++ ripngd/ripng_northbound.c | 1234 ------------------------------------- ripngd/ripngd.h | 3 - ripngd/subdir.am | 7 +- 11 files changed, 1495 insertions(+), 1298 deletions(-) delete mode 100644 ripngd/ripng_cli.h create mode 100644 ripngd/ripng_nb.c create mode 100644 ripngd/ripng_nb.h create mode 100644 ripngd/ripng_nb_config.c create mode 100644 ripngd/ripng_nb_rpcs.c create mode 100644 ripngd/ripng_nb_state.c delete mode 100644 ripngd/ripng_northbound.c diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index e95c0e95d6..2d9930e357 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -29,7 +29,7 @@ #include "libfrr.h" #include "ripngd/ripngd.h" -#include "ripngd/ripng_cli.h" +#include "ripngd/ripng_nb.h" #ifndef VTYSH_EXTRACT_PL #include "ripngd/ripng_cli_clippy.c" #endif diff --git a/ripngd/ripng_cli.h b/ripngd/ripng_cli.h deleted file mode 100644 index d95747e0f8..0000000000 --- a/ripngd/ripng_cli.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 1998 Kunihiro Ishiguro - * Copyright (C) 2018 NetDEF, Inc. - * Renato Westphal - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _FRR_RIPNG_CLI_H_ -#define _FRR_RIPNG_CLI_H_ - -extern void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_allow_ecmp(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_default_information_originate(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_default_metric(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_network_prefix(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_network_interface(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_passive_interface(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_redistribute(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_route(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_aggregate_address(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ripng_timers(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -extern void cli_show_ipv6_ripng_split_horizon(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); - -#endif /* _FRR_RIPNG_CLI_H_ */ diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index 4b027019c0..3f2c0e9da0 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -39,6 +39,7 @@ #include "libfrr.h" #include "ripngd/ripngd.h" +#include "ripngd/ripng_nb.h" /* RIPngd options. */ struct option longopts[] = {{0}}; diff --git a/ripngd/ripng_nb.c b/ripngd/ripng_nb.c new file mode 100644 index 0000000000..a02a72112f --- /dev/null +++ b/ripngd/ripng_nb.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "northbound.h" +#include "libfrr.h" + +#include "ripngd/ripng_nb.h" + +/* clang-format off */ +const struct frr_yang_module_info frr_ripngd_info = { + .name = "frr-ripngd", + .nodes = { + { + .xpath = "/frr-ripngd:ripngd/instance", + .cbs = { + .cli_show = cli_show_router_ripng, + .create = ripngd_instance_create, + .destroy = ripngd_instance_destroy, + .get_keys = ripngd_instance_get_keys, + .get_next = ripngd_instance_get_next, + .lookup_entry = ripngd_instance_lookup_entry, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp", + .cbs = { + .cli_show = cli_show_ripng_allow_ecmp, + .modify = ripngd_instance_allow_ecmp_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/default-information-originate", + .cbs = { + .cli_show = cli_show_ripng_default_information_originate, + .modify = ripngd_instance_default_information_originate_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/default-metric", + .cbs = { + .cli_show = cli_show_ripng_default_metric, + .modify = ripngd_instance_default_metric_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/network", + .cbs = { + .cli_show = cli_show_ripng_network_prefix, + .create = ripngd_instance_network_create, + .destroy = ripngd_instance_network_destroy, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/interface", + .cbs = { + .cli_show = cli_show_ripng_network_interface, + .create = ripngd_instance_interface_create, + .destroy = ripngd_instance_interface_destroy, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/offset-list", + .cbs = { + .cli_show = cli_show_ripng_offset_list, + .create = ripngd_instance_offset_list_create, + .destroy = ripngd_instance_offset_list_destroy, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list", + .cbs = { + .modify = ripngd_instance_offset_list_access_list_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric", + .cbs = { + .modify = ripngd_instance_offset_list_metric_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/passive-interface", + .cbs = { + .cli_show = cli_show_ripng_passive_interface, + .create = ripngd_instance_passive_interface_create, + .destroy = ripngd_instance_passive_interface_destroy, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/redistribute", + .cbs = { + .apply_finish = ripngd_instance_redistribute_apply_finish, + .cli_show = cli_show_ripng_redistribute, + .create = ripngd_instance_redistribute_create, + .destroy = ripngd_instance_redistribute_destroy, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map", + .cbs = { + .destroy = ripngd_instance_redistribute_route_map_destroy, + .modify = ripngd_instance_redistribute_route_map_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric", + .cbs = { + .destroy = ripngd_instance_redistribute_metric_destroy, + .modify = ripngd_instance_redistribute_metric_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/static-route", + .cbs = { + .cli_show = cli_show_ripng_route, + .create = ripngd_instance_static_route_create, + .destroy = ripngd_instance_static_route_destroy, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/aggregate-address", + .cbs = { + .cli_show = cli_show_ripng_aggregate_address, + .create = ripngd_instance_aggregate_address_create, + .destroy = ripngd_instance_aggregate_address_destroy, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/timers", + .cbs = { + .apply_finish = ripngd_instance_timers_apply_finish, + .cli_show = cli_show_ripng_timers, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval", + .cbs = { + .modify = ripngd_instance_timers_flush_interval_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval", + .cbs = { + .modify = ripngd_instance_timers_holddown_interval_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval", + .cbs = { + .modify = ripngd_instance_timers_update_interval_modify, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor", + .cbs = { + .get_keys = ripngd_instance_state_neighbors_neighbor_get_keys, + .get_next = ripngd_instance_state_neighbors_neighbor_get_next, + .lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address", + .cbs = { + .get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update", + .cbs = { + .get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd", + .cbs = { + .get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd", + .cbs = { + .get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route", + .cbs = { + .get_keys = ripngd_instance_state_routes_route_get_keys, + .get_next = ripngd_instance_state_routes_route_get_next, + .lookup_entry = ripngd_instance_state_routes_route_lookup_entry, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix", + .cbs = { + .get_elem = ripngd_instance_state_routes_route_prefix_get_elem, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop", + .cbs = { + .get_elem = ripngd_instance_state_routes_route_next_hop_get_elem, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface", + .cbs = { + .get_elem = ripngd_instance_state_routes_route_interface_get_elem, + }, + }, + { + .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric", + .cbs = { + .get_elem = ripngd_instance_state_routes_route_metric_get_elem, + }, + }, + { + .xpath = "/frr-ripngd:clear-ripng-route", + .cbs = { + .rpc = clear_ripng_route_rpc, + }, + }, + { + .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon", + .cbs = { + .cli_show = cli_show_ipv6_ripng_split_horizon, + .modify = lib_interface_ripng_split_horizon_modify, + }, + }, + { + .xpath = NULL, + }, + } +}; diff --git a/ripngd/ripng_nb.h b/ripngd/ripng_nb.h new file mode 100644 index 0000000000..45e92e0a10 --- /dev/null +++ b/ripngd/ripng_nb.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_RIPNG_NB_H_ +#define _FRR_RIPNG_NB_H_ + +extern const struct frr_yang_module_info frr_ripngd_info; + +/* Mandatory callbacks. */ +int ripngd_instance_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_destroy(enum nb_event event, const struct lyd_node *dnode); +const void *ripngd_instance_get_next(const void *parent_list_entry, + const void *list_entry); +int ripngd_instance_get_keys(const void *list_entry, + struct yang_list_keys *keys); +const void *ripngd_instance_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys); +int ripngd_instance_allow_ecmp_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_default_information_originate_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_default_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_network_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_network_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripngd_instance_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_interface_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripngd_instance_offset_list_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_offset_list_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripngd_instance_offset_list_access_list_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_offset_list_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_passive_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripngd_instance_redistribute_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_redistribute_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripngd_instance_redistribute_route_map_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_redistribute_route_map_destroy( + enum nb_event event, const struct lyd_node *dnode); +int ripngd_instance_redistribute_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_redistribute_metric_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripngd_instance_static_route_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_static_route_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripngd_instance_aggregate_address_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_aggregate_address_destroy(enum nb_event event, + const struct lyd_node *dnode); +int ripngd_instance_timers_flush_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_timers_holddown_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int ripngd_instance_timers_update_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +const void * +ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry, + const void *list_entry); +int ripngd_instance_state_neighbors_neighbor_get_keys( + const void *list_entry, struct yang_list_keys *keys); +const void *ripngd_instance_state_neighbors_neighbor_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys); +struct yang_data *ripngd_instance_state_neighbors_neighbor_address_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *ripngd_instance_state_neighbors_neighbor_last_update_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem( + const char *xpath, const void *list_entry); +const void * +ripngd_instance_state_routes_route_get_next(const void *parent_list_entry, + const void *list_entry); +int ripngd_instance_state_routes_route_get_keys(const void *list_entry, + struct yang_list_keys *keys); +const void *ripngd_instance_state_routes_route_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys); +struct yang_data * +ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath, + const void *list_entry); +struct yang_data * +ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath, + const void *list_entry); +struct yang_data * +ripngd_instance_state_routes_route_interface_get_elem(const char *xpath, + const void *list_entry); +struct yang_data * +ripngd_instance_state_routes_route_metric_get_elem(const char *xpath, + const void *list_entry); +int clear_ripng_route_rpc(const char *xpath, const struct list *input, + struct list *output); +int lib_interface_ripng_split_horizon_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); + +/* Optional 'apply_finish' callbacks. */ +void ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode); +void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode); + +/* Optional 'cli_show' callbacks. */ +void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_allow_ecmp(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_default_information_originate(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_default_metric(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_network_prefix(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_passive_interface(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_redistribute(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_route(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_aggregate_address(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ripng_timers(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); + +#endif /* _FRR_RIPNG_NB_H_ */ diff --git a/ripngd/ripng_nb_config.c b/ripngd/ripng_nb_config.c new file mode 100644 index 0000000000..b39c1d443a --- /dev/null +++ b/ripngd/ripng_nb_config.c @@ -0,0 +1,714 @@ +/* + * Copyright (C) 1998 Kunihiro Ishiguro + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "table.h" +#include "command.h" +#include "routemap.h" +#include "agg_table.h" +#include "northbound.h" +#include "libfrr.h" + +#include "ripngd/ripngd.h" +#include "ripngd/ripng_nb.h" +#include "ripngd/ripng_debug.h" +#include "ripngd/ripng_route.h" + +/* + * XPath: /frr-ripngd:ripngd/instance + */ +int ripngd_instance_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + struct vrf *vrf; + const char *vrf_name; + int socket; + + vrf_name = yang_dnode_get_string(dnode, "./vrf"); + vrf = vrf_lookup_by_name(vrf_name); + + /* + * Try to create a RIPng socket only if the VRF is enabled, otherwise + * create a disabled RIPng instance and wait for the VRF to be enabled. + */ + switch (event) { + case NB_EV_VALIDATE: + break; + case NB_EV_PREPARE: + if (!vrf || !vrf_is_enabled(vrf)) + break; + + socket = ripng_make_socket(vrf); + if (socket < 0) + return NB_ERR_RESOURCE; + resource->fd = socket; + break; + case NB_EV_ABORT: + if (!vrf || !vrf_is_enabled(vrf)) + break; + + socket = resource->fd; + close(socket); + break; + case NB_EV_APPLY: + if (vrf && vrf_is_enabled(vrf)) + socket = resource->fd; + else + socket = -1; + + ripng = ripng_create(vrf_name, vrf, socket); + nb_running_set_entry(dnode, ripng); + break; + } + + return NB_OK; +} + +int ripngd_instance_destroy(enum nb_event event, const struct lyd_node *dnode) +{ + struct ripng *ripng; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_unset_entry(dnode); + ripng_clean(ripng); + + return NB_OK; +} + +const void *ripngd_instance_get_next(const void *parent_list_entry, + const void *list_entry) +{ + struct ripng *ripng = (struct ripng *)list_entry; + + if (list_entry == NULL) + ripng = RB_MIN(ripng_instance_head, &ripng_instances); + else + ripng = RB_NEXT(ripng_instance_head, ripng); + + return ripng; +} + +int ripngd_instance_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct ripng *ripng = list_entry; + + keys->num = 1; + strlcpy(keys->key[0], ripng->vrf_name, sizeof(keys->key[0])); + + return NB_OK; +} + +const void *ripngd_instance_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys) +{ + const char *vrf_name = keys->key[0]; + + return ripng_lookup_by_vrf_name(vrf_name); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/allow-ecmp + */ +int ripngd_instance_allow_ecmp_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ripng->ecmp = yang_dnode_get_bool(dnode, NULL); + if (!ripng->ecmp) + ripng_ecmp_disable(ripng); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/default-information-originate + */ +int ripngd_instance_default_information_originate_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + bool default_information; + struct prefix_ipv6 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + default_information = yang_dnode_get_bool(dnode, NULL); + + str2prefix_ipv6("::/0", &p); + if (default_information) { + ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, + RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0); + } else { + ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, + RIPNG_ROUTE_DEFAULT, &p, 0); + } + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/default-metric + */ +int ripngd_instance_default_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ripng->default_metric = yang_dnode_get_uint8(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/network + */ +int ripngd_instance_network_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + struct prefix p; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv6p(&p, dnode, NULL); + apply_mask_ipv6((struct prefix_ipv6 *)&p); + + return ripng_enable_network_add(ripng, &p); +} + +int ripngd_instance_network_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct ripng *ripng; + struct prefix p; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv6p(&p, dnode, NULL); + apply_mask_ipv6((struct prefix_ipv6 *)&p); + + return ripng_enable_network_delete(ripng, &p); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/interface + */ +int ripngd_instance_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return ripng_enable_if_add(ripng, ifname); +} + +int ripngd_instance_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct ripng *ripng; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return ripng_enable_if_delete(ripng, ifname); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/offset-list + */ +int ripngd_instance_offset_list_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + const char *ifname; + struct ripng_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, "./interface"); + + offset = ripng_offset_list_new(ripng, ifname); + nb_running_set_entry(dnode, offset); + + return NB_OK; +} + +int ripngd_instance_offset_list_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + int direct; + struct ripng_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "./direction"); + + offset = nb_running_unset_entry(dnode); + if (offset->direct[direct].alist_name) { + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = NULL; + } + if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL + && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL) + ripng_offset_list_del(offset); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list + */ +int ripngd_instance_offset_list_access_list_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + int direct; + struct ripng_offset_list *offset; + const char *alist_name; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "../direction"); + alist_name = yang_dnode_get_string(dnode, NULL); + + offset = nb_running_get_entry(dnode, NULL, true); + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = strdup(alist_name); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/offset-list/metric + */ +int ripngd_instance_offset_list_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + int direct; + uint8_t metric; + struct ripng_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "../direction"); + metric = yang_dnode_get_uint8(dnode, NULL); + + offset = nb_running_get_entry(dnode, NULL, true); + offset->direct[direct].metric = metric; + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/passive-interface + */ +int ripngd_instance_passive_interface_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return ripng_passive_interface_set(ripng, ifname); +} + +int ripngd_instance_passive_interface_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct ripng *ripng; + const char *ifname; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ifname = yang_dnode_get_string(dnode, NULL); + + return ripng_passive_interface_unset(ripng, ifname); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/redistribute + */ +int ripngd_instance_redistribute_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "./protocol"); + + ripng->redist[type].enabled = true; + + return NB_OK; +} + +int ripngd_instance_redistribute_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct ripng *ripng; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "./protocol"); + + ripng->redist[type].enabled = false; + if (ripng->redist[type].route_map.name) { + free(ripng->redist[type].route_map.name); + ripng->redist[type].route_map.name = NULL; + ripng->redist[type].route_map.map = NULL; + } + ripng->redist[type].metric_config = false; + ripng->redist[type].metric = 0; + + if (ripng->enabled) + ripng_redistribute_conf_delete(ripng, type); + + return NB_OK; +} + +void ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode) +{ + struct ripng *ripng; + int type; + + ripng = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "./protocol"); + + if (ripng->enabled) + ripng_redistribute_conf_update(ripng, type); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map + */ +int ripngd_instance_redistribute_route_map_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + int type; + const char *rmap_name; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "../protocol"); + rmap_name = yang_dnode_get_string(dnode, NULL); + + if (ripng->redist[type].route_map.name) + free(ripng->redist[type].route_map.name); + ripng->redist[type].route_map.name = strdup(rmap_name); + ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name); + + return NB_OK; +} + +int ripngd_instance_redistribute_route_map_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct ripng *ripng; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "../protocol"); + + free(ripng->redist[type].route_map.name); + ripng->redist[type].route_map.name = NULL; + ripng->redist[type].route_map.map = NULL; + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/redistribute/metric + */ +int ripngd_instance_redistribute_metric_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + int type; + uint8_t metric; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "../protocol"); + metric = yang_dnode_get_uint8(dnode, NULL); + + ripng->redist[type].metric_config = true; + ripng->redist[type].metric = metric; + + return NB_OK; +} + +int ripngd_instance_redistribute_metric_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct ripng *ripng; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + type = yang_dnode_get_enum(dnode, "../protocol"); + + ripng->redist[type].metric_config = false; + ripng->redist[type].metric = 0; + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/static-route + */ +int ripngd_instance_static_route_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + struct prefix_ipv6 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv6p(&p, dnode, NULL); + apply_mask_ipv6(&p); + + ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, + 0, NULL, 0); + + return NB_OK; +} + +int ripngd_instance_static_route_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct ripng *ripng; + struct prefix_ipv6 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv6p(&p, dnode, NULL); + apply_mask_ipv6(&p); + + ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, + &p, 0); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/aggregate-address + */ +int ripngd_instance_aggregate_address_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + struct prefix_ipv6 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv6p(&p, dnode, NULL); + apply_mask_ipv6(&p); + + ripng_aggregate_add(ripng, (struct prefix *)&p); + + return NB_OK; +} + +int ripngd_instance_aggregate_address_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + struct ripng *ripng; + struct prefix_ipv6 p; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + yang_dnode_get_ipv6p(&p, dnode, NULL); + apply_mask_ipv6(&p); + + ripng_aggregate_delete(ripng, (struct prefix *)&p); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/timers + */ +void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode) +{ + struct ripng *ripng; + + ripng = nb_running_get_entry(dnode, NULL, true); + + /* Reset update timer thread. */ + ripng_event(ripng, RIPNG_UPDATE_EVENT, 0); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval + */ +int ripngd_instance_timers_flush_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval + */ +int ripngd_instance_timers_holddown_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/timers/update-interval + */ +int ripngd_instance_timers_update_interval_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct ripng *ripng; + + if (event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(dnode, NULL, true); + ripng->update_time = yang_dnode_get_uint16(dnode, NULL); + + return NB_OK; +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon + */ +int lib_interface_ripng_split_horizon_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + struct interface *ifp; + struct ripng_interface *ri; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifp = nb_running_get_entry(dnode, NULL, true); + ri = ifp->info; + ri->split_horizon = yang_dnode_get_enum(dnode, NULL); + + return NB_OK; +} diff --git a/ripngd/ripng_nb_rpcs.c b/ripngd/ripng_nb_rpcs.c new file mode 100644 index 0000000000..0396daf890 --- /dev/null +++ b/ripngd/ripng_nb_rpcs.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "table.h" +#include "command.h" +#include "routemap.h" +#include "agg_table.h" +#include "northbound.h" +#include "libfrr.h" + +#include "ripngd/ripngd.h" +#include "ripngd/ripng_nb.h" +#include "ripngd/ripng_debug.h" +#include "ripngd/ripng_route.h" + +/* + * XPath: /frr-ripngd:clear-ripng-route + */ +static void clear_ripng_route(struct ripng *ripng) +{ + struct agg_node *rp; + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("Clearing all RIPng routes (VRF %s)", + ripng->vrf_name); + + /* Clear received RIPng routes */ + for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { + struct list *list; + struct listnode *listnode; + struct ripng_info *rinfo; + + list = rp->info; + if (list == NULL) + continue; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + if (!ripng_route_rte(rinfo)) + continue; + + if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete(ripng, rp); + break; + } + + if (rinfo) { + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_OFF(rinfo->t_garbage_collect); + listnode_delete(list, rinfo); + ripng_info_free(rinfo); + } + + if (list_isempty(list)) { + list_delete(&list); + rp->info = NULL; + agg_unlock_node(rp); + } + } +} + +int clear_ripng_route_rpc(const char *xpath, const struct list *input, + struct list *output) +{ + struct ripng *ripng; + struct yang_data *yang_vrf; + + yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf"); + if (yang_vrf) { + ripng = ripng_lookup_by_vrf_name(yang_vrf->value); + if (ripng) + clear_ripng_route(ripng); + } else { + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + ripng = vrf->info; + if (!ripng) + continue; + + clear_ripng_route(ripng); + } + } + + return NB_OK; +} diff --git a/ripngd/ripng_nb_state.c b/ripngd/ripng_nb_state.c new file mode 100644 index 0000000000..167077ea29 --- /dev/null +++ b/ripngd/ripng_nb_state.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "table.h" +#include "command.h" +#include "routemap.h" +#include "agg_table.h" +#include "northbound.h" +#include "libfrr.h" + +#include "ripngd/ripngd.h" +#include "ripngd/ripng_nb.h" +#include "ripngd/ripng_debug.h" +#include "ripngd/ripng_route.h" + +/* + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor + */ +const void * +ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry, + const void *list_entry) +{ + const struct ripng *ripng = parent_list_entry; + struct listnode *node; + + if (list_entry == NULL) + node = listhead(ripng->peer_list); + else + node = listnextnode((struct listnode *)list_entry); + + return node; +} + +int ripngd_instance_state_neighbors_neighbor_get_keys( + const void *list_entry, struct yang_list_keys *keys) +{ + const struct listnode *node = list_entry; + const struct ripng_peer *peer = listgetdata(node); + + keys->num = 1; + (void)inet_ntop(AF_INET6, &peer->addr, keys->key[0], + sizeof(keys->key[0])); + + return NB_OK; +} + +const void *ripngd_instance_state_neighbors_neighbor_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys) +{ + const struct ripng *ripng = parent_list_entry; + struct in6_addr address; + struct ripng_peer *peer; + struct listnode *node; + + yang_str2ipv6(keys->key[0], &address); + + for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) { + if (IPV6_ADDR_SAME(&peer->addr, &address)) + return node; + } + + return NULL; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address + */ +struct yang_data *ripngd_instance_state_neighbors_neighbor_address_get_elem( + const char *xpath, const void *list_entry) +{ + const struct listnode *node = list_entry; + const struct ripng_peer *peer = listgetdata(node); + + return yang_data_new_ipv6(xpath, &peer->addr); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update + */ +struct yang_data *ripngd_instance_state_neighbors_neighbor_last_update_get_elem( + const char *xpath, const void *list_entry) +{ + /* TODO: yang:date-and-time is tricky */ + return NULL; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd + */ +struct yang_data * +ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem( + const char *xpath, const void *list_entry) +{ + const struct listnode *node = list_entry; + const struct ripng_peer *peer = listgetdata(node); + + return yang_data_new_uint32(xpath, peer->recv_badpackets); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd + */ +struct yang_data * +ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem( + const char *xpath, const void *list_entry) +{ + const struct listnode *node = list_entry; + const struct ripng_peer *peer = listgetdata(node); + + return yang_data_new_uint32(xpath, peer->recv_badroutes); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/routes/route + */ +const void * +ripngd_instance_state_routes_route_get_next(const void *parent_list_entry, + const void *list_entry) +{ + const struct ripng *ripng = parent_list_entry; + struct agg_node *rn; + + if (list_entry == NULL) + rn = agg_route_top(ripng->table); + else + rn = agg_route_next((struct agg_node *)list_entry); + while (rn && rn->info == NULL) + rn = agg_route_next(rn); + + return rn; +} + +int ripngd_instance_state_routes_route_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct agg_node *rn = list_entry; + + keys->num = 1; + (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0])); + + return NB_OK; +} + +const void *ripngd_instance_state_routes_route_lookup_entry( + const void *parent_list_entry, const struct yang_list_keys *keys) +{ + const struct ripng *ripng = parent_list_entry; + struct prefix prefix; + struct agg_node *rn; + + yang_str2ipv6p(keys->key[0], &prefix); + + rn = agg_node_lookup(ripng->table, &prefix); + if (!rn || !rn->info) + return NULL; + + agg_unlock_node(rn); + + return rn; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix + */ +struct yang_data * +ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath, + const void *list_entry) +{ + const struct agg_node *rn = list_entry; + const struct ripng_info *rinfo = listnode_head(rn->info); + + return yang_data_new_ipv6p(xpath, &rinfo->rp->p); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop + */ +struct yang_data * +ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath, + const void *list_entry) +{ + const struct agg_node *rn = list_entry; + const struct ripng_info *rinfo = listnode_head(rn->info); + + return yang_data_new_ipv6(xpath, &rinfo->nexthop); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface + */ +struct yang_data * +ripngd_instance_state_routes_route_interface_get_elem(const char *xpath, + const void *list_entry) +{ + const struct agg_node *rn = list_entry; + const struct ripng_info *rinfo = listnode_head(rn->info); + const struct ripng *ripng = ripng_info_get_instance(rinfo); + + return yang_data_new_string( + xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id)); +} + +/* + * XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric + */ +struct yang_data * +ripngd_instance_state_routes_route_metric_get_elem(const char *xpath, + const void *list_entry) +{ + const struct agg_node *rn = list_entry; + const struct ripng_info *rinfo = listnode_head(rn->info); + + return yang_data_new_uint8(xpath, rinfo->metric); +} diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c deleted file mode 100644 index 588f6db037..0000000000 --- a/ripngd/ripng_northbound.c +++ /dev/null @@ -1,1234 +0,0 @@ -/* - * Copyright (C) 1998 Kunihiro Ishiguro - * Copyright (C) 2018 NetDEF, Inc. - * Renato Westphal - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "if.h" -#include "vrf.h" -#include "log.h" -#include "prefix.h" -#include "table.h" -#include "command.h" -#include "routemap.h" -#include "agg_table.h" -#include "northbound.h" -#include "libfrr.h" - -#include "ripngd/ripngd.h" -#include "ripngd/ripng_debug.h" -#include "ripngd/ripng_route.h" -#include "ripngd/ripng_cli.h" - -/* - * XPath: /frr-ripngd:ripngd/instance - */ -static int ripngd_instance_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - struct vrf *vrf; - const char *vrf_name; - int socket; - - vrf_name = yang_dnode_get_string(dnode, "./vrf"); - vrf = vrf_lookup_by_name(vrf_name); - - /* - * Try to create a RIPng socket only if the VRF is enabled, otherwise - * create a disabled RIPng instance and wait for the VRF to be enabled. - */ - switch (event) { - case NB_EV_VALIDATE: - break; - case NB_EV_PREPARE: - if (!vrf || !vrf_is_enabled(vrf)) - break; - - socket = ripng_make_socket(vrf); - if (socket < 0) - return NB_ERR_RESOURCE; - resource->fd = socket; - break; - case NB_EV_ABORT: - if (!vrf || !vrf_is_enabled(vrf)) - break; - - socket = resource->fd; - close(socket); - break; - case NB_EV_APPLY: - if (vrf && vrf_is_enabled(vrf)) - socket = resource->fd; - else - socket = -1; - - ripng = ripng_create(vrf_name, vrf, socket); - nb_running_set_entry(dnode, ripng); - break; - } - - return NB_OK; -} - -static int ripngd_instance_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_unset_entry(dnode); - ripng_clean(ripng); - - return NB_OK; -} - -static const void *ripngd_instance_get_next(const void *parent_list_entry, - const void *list_entry) -{ - struct ripng *ripng = (struct ripng *)list_entry; - - if (list_entry == NULL) - ripng = RB_MIN(ripng_instance_head, &ripng_instances); - else - ripng = RB_NEXT(ripng_instance_head, ripng); - - return ripng; -} - -static int ripngd_instance_get_keys(const void *list_entry, - struct yang_list_keys *keys) -{ - const struct ripng *ripng = list_entry; - - keys->num = 1; - strlcpy(keys->key[0], ripng->vrf_name, sizeof(keys->key[0])); - - return NB_OK; -} - -static const void * -ripngd_instance_lookup_entry(const void *parent_list_entry, - const struct yang_list_keys *keys) -{ - const char *vrf_name = keys->key[0]; - - return ripng_lookup_by_vrf_name(vrf_name); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/allow-ecmp - */ -static int ripngd_instance_allow_ecmp_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ripng->ecmp = yang_dnode_get_bool(dnode, NULL); - if (!ripng->ecmp) - ripng_ecmp_disable(ripng); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/default-information-originate - */ -static int ripngd_instance_default_information_originate_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - bool default_information; - struct prefix_ipv6 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - default_information = yang_dnode_get_bool(dnode, NULL); - - str2prefix_ipv6("::/0", &p); - if (default_information) { - ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, - RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0); - } else { - ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, - RIPNG_ROUTE_DEFAULT, &p, 0); - } - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/default-metric - */ -static int ripngd_instance_default_metric_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ripng->default_metric = yang_dnode_get_uint8(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/network - */ -static int ripngd_instance_network_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - struct prefix p; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv6p(&p, dnode, NULL); - apply_mask_ipv6((struct prefix_ipv6 *)&p); - - return ripng_enable_network_add(ripng, &p); -} - -static int ripngd_instance_network_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - struct prefix p; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv6p(&p, dnode, NULL); - apply_mask_ipv6((struct prefix_ipv6 *)&p); - - return ripng_enable_network_delete(ripng, &p); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/interface - */ -static int ripngd_instance_interface_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return ripng_enable_if_add(ripng, ifname); -} - -static int ripngd_instance_interface_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return ripng_enable_if_delete(ripng, ifname); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/offset-list - */ -static int ripngd_instance_offset_list_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - const char *ifname; - struct ripng_offset_list *offset; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, "./interface"); - - offset = ripng_offset_list_new(ripng, ifname); - nb_running_set_entry(dnode, offset); - - return NB_OK; -} - -static int ripngd_instance_offset_list_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - int direct; - struct ripng_offset_list *offset; - - if (event != NB_EV_APPLY) - return NB_OK; - - direct = yang_dnode_get_enum(dnode, "./direction"); - - offset = nb_running_unset_entry(dnode); - if (offset->direct[direct].alist_name) { - free(offset->direct[direct].alist_name); - offset->direct[direct].alist_name = NULL; - } - if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL - && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL) - ripng_offset_list_del(offset); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list - */ -static int -ripngd_instance_offset_list_access_list_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - int direct; - struct ripng_offset_list *offset; - const char *alist_name; - - if (event != NB_EV_APPLY) - return NB_OK; - - direct = yang_dnode_get_enum(dnode, "../direction"); - alist_name = yang_dnode_get_string(dnode, NULL); - - offset = nb_running_get_entry(dnode, NULL, true); - if (offset->direct[direct].alist_name) - free(offset->direct[direct].alist_name); - offset->direct[direct].alist_name = strdup(alist_name); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/offset-list/metric - */ -static int -ripngd_instance_offset_list_metric_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - int direct; - uint8_t metric; - struct ripng_offset_list *offset; - - if (event != NB_EV_APPLY) - return NB_OK; - - direct = yang_dnode_get_enum(dnode, "../direction"); - metric = yang_dnode_get_uint8(dnode, NULL); - - offset = nb_running_get_entry(dnode, NULL, true); - offset->direct[direct].metric = metric; - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/passive-interface - */ -static int -ripngd_instance_passive_interface_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return ripng_passive_interface_set(ripng, ifname); -} - -static int -ripngd_instance_passive_interface_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - const char *ifname; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ifname = yang_dnode_get_string(dnode, NULL); - - return ripng_passive_interface_unset(ripng, ifname); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/redistribute - */ -static int ripngd_instance_redistribute_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "./protocol"); - - ripng->redist[type].enabled = true; - - return NB_OK; -} - -static int ripngd_instance_redistribute_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "./protocol"); - - ripng->redist[type].enabled = false; - if (ripng->redist[type].route_map.name) { - free(ripng->redist[type].route_map.name); - ripng->redist[type].route_map.name = NULL; - ripng->redist[type].route_map.map = NULL; - } - ripng->redist[type].metric_config = false; - ripng->redist[type].metric = 0; - - if (ripng->enabled) - ripng_redistribute_conf_delete(ripng, type); - - return NB_OK; -} - -static void -ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode) -{ - struct ripng *ripng; - int type; - - ripng = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "./protocol"); - - if (ripng->enabled) - ripng_redistribute_conf_update(ripng, type); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map - */ -static int -ripngd_instance_redistribute_route_map_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - int type; - const char *rmap_name; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "../protocol"); - rmap_name = yang_dnode_get_string(dnode, NULL); - - if (ripng->redist[type].route_map.name) - free(ripng->redist[type].route_map.name); - ripng->redist[type].route_map.name = strdup(rmap_name); - ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name); - - return NB_OK; -} - -static int -ripngd_instance_redistribute_route_map_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "../protocol"); - - free(ripng->redist[type].route_map.name); - ripng->redist[type].route_map.name = NULL; - ripng->redist[type].route_map.map = NULL; - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/redistribute/metric - */ -static int -ripngd_instance_redistribute_metric_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - int type; - uint8_t metric; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "../protocol"); - metric = yang_dnode_get_uint8(dnode, NULL); - - ripng->redist[type].metric_config = true; - ripng->redist[type].metric = metric; - - return NB_OK; -} - -static int -ripngd_instance_redistribute_metric_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - int type; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - type = yang_dnode_get_enum(dnode, "../protocol"); - - ripng->redist[type].metric_config = false; - ripng->redist[type].metric = 0; - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/static-route - */ -static int ripngd_instance_static_route_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - struct prefix_ipv6 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv6p(&p, dnode, NULL); - apply_mask_ipv6(&p); - - ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, - 0, NULL, 0); - - return NB_OK; -} - -static int ripngd_instance_static_route_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - struct prefix_ipv6 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv6p(&p, dnode, NULL); - apply_mask_ipv6(&p); - - ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, - &p, 0); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/aggregate-address - */ -static int -ripngd_instance_aggregate_address_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - struct prefix_ipv6 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv6p(&p, dnode, NULL); - apply_mask_ipv6(&p); - - ripng_aggregate_add(ripng, (struct prefix *)&p); - - return NB_OK; -} - -static int -ripngd_instance_aggregate_address_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - struct ripng *ripng; - struct prefix_ipv6 p; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - yang_dnode_get_ipv6p(&p, dnode, NULL); - apply_mask_ipv6(&p); - - ripng_aggregate_delete(ripng, (struct prefix *)&p); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/timers - */ -static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode) -{ - struct ripng *ripng; - - ripng = nb_running_get_entry(dnode, NULL, true); - - /* Reset update timer thread. */ - ripng_event(ripng, RIPNG_UPDATE_EVENT, 0); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval - */ -static int -ripngd_instance_timers_flush_interval_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval - */ -static int -ripngd_instance_timers_holddown_interval_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/timers/update-interval - */ -static int -ripngd_instance_timers_update_interval_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct ripng *ripng; - - if (event != NB_EV_APPLY) - return NB_OK; - - ripng = nb_running_get_entry(dnode, NULL, true); - ripng->update_time = yang_dnode_get_uint16(dnode, NULL); - - return NB_OK; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor - */ -static const void * -ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry, - const void *list_entry) -{ - const struct ripng *ripng = parent_list_entry; - struct listnode *node; - - if (list_entry == NULL) - node = listhead(ripng->peer_list); - else - node = listnextnode((struct listnode *)list_entry); - - return node; -} - -static int -ripngd_instance_state_neighbors_neighbor_get_keys(const void *list_entry, - struct yang_list_keys *keys) -{ - const struct listnode *node = list_entry; - const struct ripng_peer *peer = listgetdata(node); - - keys->num = 1; - (void)inet_ntop(AF_INET6, &peer->addr, keys->key[0], - sizeof(keys->key[0])); - - return NB_OK; -} - -static const void *ripngd_instance_state_neighbors_neighbor_lookup_entry( - const void *parent_list_entry, const struct yang_list_keys *keys) -{ - const struct ripng *ripng = parent_list_entry; - struct in6_addr address; - struct ripng_peer *peer; - struct listnode *node; - - yang_str2ipv6(keys->key[0], &address); - - for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) { - if (IPV6_ADDR_SAME(&peer->addr, &address)) - return node; - } - - return NULL; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address - */ -static struct yang_data * -ripngd_instance_state_neighbors_neighbor_address_get_elem( - const char *xpath, const void *list_entry) -{ - const struct listnode *node = list_entry; - const struct ripng_peer *peer = listgetdata(node); - - return yang_data_new_ipv6(xpath, &peer->addr); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update - */ -static struct yang_data * -ripngd_instance_state_neighbors_neighbor_last_update_get_elem( - const char *xpath, const void *list_entry) -{ - /* TODO: yang:date-and-time is tricky */ - return NULL; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd - */ -static struct yang_data * -ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem( - const char *xpath, const void *list_entry) -{ - const struct listnode *node = list_entry; - const struct ripng_peer *peer = listgetdata(node); - - return yang_data_new_uint32(xpath, peer->recv_badpackets); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd - */ -static struct yang_data * -ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem( - const char *xpath, const void *list_entry) -{ - const struct listnode *node = list_entry; - const struct ripng_peer *peer = listgetdata(node); - - return yang_data_new_uint32(xpath, peer->recv_badroutes); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/routes/route - */ -static const void * -ripngd_instance_state_routes_route_get_next(const void *parent_list_entry, - const void *list_entry) -{ - const struct ripng *ripng = parent_list_entry; - struct agg_node *rn; - - if (list_entry == NULL) - rn = agg_route_top(ripng->table); - else - rn = agg_route_next((struct agg_node *)list_entry); - while (rn && rn->info == NULL) - rn = agg_route_next(rn); - - return rn; -} - -static int -ripngd_instance_state_routes_route_get_keys(const void *list_entry, - struct yang_list_keys *keys) -{ - const struct agg_node *rn = list_entry; - - keys->num = 1; - (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0])); - - return NB_OK; -} - -static const void *ripngd_instance_state_routes_route_lookup_entry( - const void *parent_list_entry, const struct yang_list_keys *keys) -{ - const struct ripng *ripng = parent_list_entry; - struct prefix prefix; - struct agg_node *rn; - - yang_str2ipv6p(keys->key[0], &prefix); - - rn = agg_node_lookup(ripng->table, &prefix); - if (!rn || !rn->info) - return NULL; - - agg_unlock_node(rn); - - return rn; -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix - */ -static struct yang_data * -ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath, - const void *list_entry) -{ - const struct agg_node *rn = list_entry; - const struct ripng_info *rinfo = listnode_head(rn->info); - - return yang_data_new_ipv6p(xpath, &rinfo->rp->p); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop - */ -static struct yang_data * -ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath, - const void *list_entry) -{ - const struct agg_node *rn = list_entry; - const struct ripng_info *rinfo = listnode_head(rn->info); - - return yang_data_new_ipv6(xpath, &rinfo->nexthop); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface - */ -static struct yang_data * -ripngd_instance_state_routes_route_interface_get_elem(const char *xpath, - const void *list_entry) -{ - const struct agg_node *rn = list_entry; - const struct ripng_info *rinfo = listnode_head(rn->info); - const struct ripng *ripng = ripng_info_get_instance(rinfo); - - return yang_data_new_string( - xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id)); -} - -/* - * XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric - */ -static struct yang_data * -ripngd_instance_state_routes_route_metric_get_elem(const char *xpath, - const void *list_entry) -{ - const struct agg_node *rn = list_entry; - const struct ripng_info *rinfo = listnode_head(rn->info); - - return yang_data_new_uint8(xpath, rinfo->metric); -} - -/* - * XPath: /frr-ripngd:clear-ripng-route - */ -static void clear_ripng_route(struct ripng *ripng) -{ - struct agg_node *rp; - - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug("Clearing all RIPng routes (VRF %s)", - ripng->vrf_name); - - /* Clear received RIPng routes */ - for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) { - struct list *list; - struct listnode *listnode; - struct ripng_info *rinfo; - - list = rp->info; - if (list == NULL) - continue; - - for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - if (!ripng_route_rte(rinfo)) - continue; - - if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete(ripng, rp); - break; - } - - if (rinfo) { - RIPNG_TIMER_OFF(rinfo->t_timeout); - RIPNG_TIMER_OFF(rinfo->t_garbage_collect); - listnode_delete(list, rinfo); - ripng_info_free(rinfo); - } - - if (list_isempty(list)) { - list_delete(&list); - rp->info = NULL; - agg_unlock_node(rp); - } - } -} - -static int clear_ripng_route_rpc(const char *xpath, const struct list *input, - struct list *output) -{ - struct ripng *ripng; - struct yang_data *yang_vrf; - - yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf"); - if (yang_vrf) { - ripng = ripng_lookup_by_vrf_name(yang_vrf->value); - if (ripng) - clear_ripng_route(ripng); - } else { - struct vrf *vrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - ripng = vrf->info; - if (!ripng) - continue; - - clear_ripng_route(ripng); - } - } - - return NB_OK; -} - -/* - * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon - */ -static int -lib_interface_ripng_split_horizon_modify(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - struct interface *ifp; - struct ripng_interface *ri; - - if (event != NB_EV_APPLY) - return NB_OK; - - ifp = nb_running_get_entry(dnode, NULL, true); - ri = ifp->info; - ri->split_horizon = yang_dnode_get_enum(dnode, NULL); - - return NB_OK; -} - -/* clang-format off */ -const struct frr_yang_module_info frr_ripngd_info = { - .name = "frr-ripngd", - .nodes = { - { - .xpath = "/frr-ripngd:ripngd/instance", - .cbs = { - .cli_show = cli_show_router_ripng, - .create = ripngd_instance_create, - .destroy = ripngd_instance_destroy, - .get_keys = ripngd_instance_get_keys, - .get_next = ripngd_instance_get_next, - .lookup_entry = ripngd_instance_lookup_entry, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp", - .cbs = { - .cli_show = cli_show_ripng_allow_ecmp, - .modify = ripngd_instance_allow_ecmp_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/default-information-originate", - .cbs = { - .cli_show = cli_show_ripng_default_information_originate, - .modify = ripngd_instance_default_information_originate_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/default-metric", - .cbs = { - .cli_show = cli_show_ripng_default_metric, - .modify = ripngd_instance_default_metric_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/network", - .cbs = { - .cli_show = cli_show_ripng_network_prefix, - .create = ripngd_instance_network_create, - .destroy = ripngd_instance_network_destroy, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/interface", - .cbs = { - .cli_show = cli_show_ripng_network_interface, - .create = ripngd_instance_interface_create, - .destroy = ripngd_instance_interface_destroy, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/offset-list", - .cbs = { - .cli_show = cli_show_ripng_offset_list, - .create = ripngd_instance_offset_list_create, - .destroy = ripngd_instance_offset_list_destroy, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list", - .cbs = { - .modify = ripngd_instance_offset_list_access_list_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric", - .cbs = { - .modify = ripngd_instance_offset_list_metric_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/passive-interface", - .cbs = { - .cli_show = cli_show_ripng_passive_interface, - .create = ripngd_instance_passive_interface_create, - .destroy = ripngd_instance_passive_interface_destroy, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/redistribute", - .cbs = { - .apply_finish = ripngd_instance_redistribute_apply_finish, - .cli_show = cli_show_ripng_redistribute, - .create = ripngd_instance_redistribute_create, - .destroy = ripngd_instance_redistribute_destroy, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map", - .cbs = { - .destroy = ripngd_instance_redistribute_route_map_destroy, - .modify = ripngd_instance_redistribute_route_map_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric", - .cbs = { - .destroy = ripngd_instance_redistribute_metric_destroy, - .modify = ripngd_instance_redistribute_metric_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/static-route", - .cbs = { - .cli_show = cli_show_ripng_route, - .create = ripngd_instance_static_route_create, - .destroy = ripngd_instance_static_route_destroy, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/aggregate-address", - .cbs = { - .cli_show = cli_show_ripng_aggregate_address, - .create = ripngd_instance_aggregate_address_create, - .destroy = ripngd_instance_aggregate_address_destroy, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/timers", - .cbs = { - .apply_finish = ripngd_instance_timers_apply_finish, - .cli_show = cli_show_ripng_timers, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval", - .cbs = { - .modify = ripngd_instance_timers_flush_interval_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval", - .cbs = { - .modify = ripngd_instance_timers_holddown_interval_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval", - .cbs = { - .modify = ripngd_instance_timers_update_interval_modify, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor", - .cbs = { - .get_keys = ripngd_instance_state_neighbors_neighbor_get_keys, - .get_next = ripngd_instance_state_neighbors_neighbor_get_next, - .lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address", - .cbs = { - .get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update", - .cbs = { - .get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd", - .cbs = { - .get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd", - .cbs = { - .get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/routes/route", - .cbs = { - .get_keys = ripngd_instance_state_routes_route_get_keys, - .get_next = ripngd_instance_state_routes_route_get_next, - .lookup_entry = ripngd_instance_state_routes_route_lookup_entry, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix", - .cbs = { - .get_elem = ripngd_instance_state_routes_route_prefix_get_elem, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop", - .cbs = { - .get_elem = ripngd_instance_state_routes_route_next_hop_get_elem, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface", - .cbs = { - .get_elem = ripngd_instance_state_routes_route_interface_get_elem, - }, - }, - { - .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric", - .cbs = { - .get_elem = ripngd_instance_state_routes_route_metric_get_elem, - }, - }, - { - .xpath = "/frr-ripngd:clear-ripng-route", - .cbs = { - .rpc = clear_ripng_route_rpc, - }, - }, - { - .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon", - .cbs = { - .cli_show = cli_show_ipv6_ripng_split_horizon, - .modify = lib_interface_ripng_split_horizon_modify, - }, - }, - { - .xpath = NULL, - }, - } -}; diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 5a0d350a84..70508d5cb0 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -494,9 +494,6 @@ extern struct ripng_info *ripng_ecmp_delete(struct ripng *ripng, extern void ripng_vrf_init(void); extern void ripng_vrf_terminate(void); - -/* Northbound. */ extern void ripng_cli_init(void); -extern const struct frr_yang_module_info frr_ripngd_info; #endif /* _ZEBRA_RIPNG_RIPNGD_H */ diff --git a/ripngd/subdir.am b/ripngd/subdir.am index eac0d67313..07d0cb892c 100644 --- a/ripngd/subdir.am +++ b/ripngd/subdir.am @@ -19,7 +19,10 @@ ripngd_libripng_a_SOURCES = \ ripngd/ripng_interface.c \ ripngd/ripng_nexthop.c \ ripngd/ripng_offset.c \ - ripngd/ripng_northbound.c \ + ripngd/ripng_nb.c \ + ripngd/ripng_nb_config.c \ + ripngd/ripng_nb_rpcs.c \ + ripngd/ripng_nb_state.c \ ripngd/ripng_peer.c \ ripngd/ripng_route.c \ ripngd/ripng_routemap.c \ @@ -31,8 +34,8 @@ ripngd/ripng_cli_clippy.c: $(CLIPPY_DEPS) ripngd/ripng_cli.$(OBJEXT): ripngd/ripng_cli_clippy.c noinst_HEADERS += \ - ripngd/ripng_cli.h \ ripngd/ripng_debug.h \ + ripngd/ripng_nb.h \ ripngd/ripng_nexthop.h \ ripngd/ripng_route.h \ ripngd/ripngd.h \ From 6c57402944e642b9dab888f8f8ab15675c234bf0 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 17 Oct 2019 17:11:17 -0300 Subject: [PATCH 4/5] bfdd: split northbound callbacks into multiple files Rearrange the bfdd northbound callbacks as following: * bfd_nb.h: prototypes of all northbound callbacks. * bfd_nb.c: definition of all northbound callbacks and their associated YANG data paths. * bfd_nb_config.c: implementation of YANG configuration nodes. * bfd_nb_state.c: implementation of YANG state nodes. This should help to keep to code more organized and easier to maintain. No behavior changes intended. Signed-off-by: Renato Westphal --- bfdd/bfd.h | 31 - bfdd/bfdd.c | 1 + bfdd/bfdd_cli.c | 1 + bfdd/bfdd_nb.c | 388 +++++++++++++ bfdd/bfdd_nb.h | 217 +++++++ bfdd/bfdd_nb_config.c | 520 +++++++++++++++++ bfdd/bfdd_nb_state.c | 383 +++++++++++++ bfdd/bfdd_northbound.c | 1236 ---------------------------------------- bfdd/subdir.am | 5 +- 9 files changed, 1514 insertions(+), 1268 deletions(-) create mode 100644 bfdd/bfdd_nb.c create mode 100644 bfdd/bfdd_nb.h create mode 100644 bfdd/bfdd_nb_config.c create mode 100644 bfdd/bfdd_nb_state.c delete mode 100644 bfdd/bfdd_northbound.c diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 815b0aec2e..220dd6e0a8 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -593,29 +593,6 @@ void bfdd_vty_init(void); */ void bfdd_cli_init(void); -void bfd_cli_show_header(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void bfd_cli_show_header_end(struct vty *vty, struct lyd_node *dnode); -void bfd_cli_show_single_hop_peer(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -void bfd_cli_show_multi_hop_peer(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults); -void bfd_cli_show_peer_end(struct vty *vty, struct lyd_node *dnode); -void bfd_cli_show_mult(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void bfd_cli_show_echo(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); -void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode, - bool show_defaults); - /* * ptm_adapter.c @@ -630,12 +607,4 @@ void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf); int ptm_bfd_notify(struct bfd_session *bs, uint8_t notify_state); - -/* - * bfdd_northbound.c - * - * BFD northbound callbacks. - */ -extern const struct frr_yang_module_info frr_bfdd_info; - #endif /* _BFD_H_ */ diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index 5657744f75..a91fa3d047 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -23,6 +23,7 @@ #include "filter.h" #include "bfd.h" +#include "bfdd_nb.h" #include "lib/version.h" diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index acb1801cc4..3e44fcb22a 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -31,6 +31,7 @@ #endif /* VTYSH_EXTRACT_PL */ #include "bfd.h" +#include "bfdd_nb.h" /* * Definitions. diff --git a/bfdd/bfdd_nb.c b/bfdd/bfdd_nb.c new file mode 100644 index 0000000000..8d46742337 --- /dev/null +++ b/bfdd/bfdd_nb.c @@ -0,0 +1,388 @@ +/* + * BFD daemon northbound implementation. + * + * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") + * Rafael Zalamena + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ + +#include + +#include "lib/log.h" +#include "lib/northbound.h" + +#include "bfdd_nb.h" + +/* clang-format off */ +const struct frr_yang_module_info frr_bfdd_info = { + .name = "frr-bfdd", + .nodes = { + { + .xpath = "/frr-bfdd:bfdd/bfd", + .cbs = { + .create = bfdd_bfd_create, + .destroy = bfdd_bfd_destroy, + .cli_show = bfd_cli_show_header, + .cli_show_end = bfd_cli_show_header_end, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop", + .cbs = { + .create = bfdd_bfd_sessions_single_hop_create, + .destroy = bfdd_bfd_sessions_single_hop_destroy, + .get_next = bfdd_bfd_sessions_single_hop_get_next, + .get_keys = bfdd_bfd_sessions_single_hop_get_keys, + .lookup_entry = bfdd_bfd_sessions_single_hop_lookup_entry, + .cli_show = bfd_cli_show_single_hop_peer, + .cli_show_end = bfd_cli_show_peer_end, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_source_addr_modify, + .destroy = bfdd_bfd_sessions_single_hop_source_addr_destroy, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, + .cli_show = bfd_cli_show_mult, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, + .cli_show = bfd_cli_show_tx, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, + .cli_show = bfd_cli_show_rx, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, + .cli_show = bfd_cli_show_shutdown, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_echo_mode_modify, + .cli_show = bfd_cli_show_echo, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify, + .cli_show = bfd_cli_show_echo_interval, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop", + .cbs = { + .create = bfdd_bfd_sessions_multi_hop_create, + .destroy = bfdd_bfd_sessions_multi_hop_destroy, + .get_next = bfdd_bfd_sessions_multi_hop_get_next, + .get_keys = bfdd_bfd_sessions_multi_hop_get_keys, + .lookup_entry = bfdd_bfd_sessions_multi_hop_lookup_entry, + .cli_show = bfd_cli_show_multi_hop_peer, + .cli_show_end = bfd_cli_show_peer_end, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/detection-multiplier", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, + .cli_show = bfd_cli_show_mult, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/desired-transmission-interval", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, + .cli_show = bfd_cli_show_tx, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/required-receive-interval", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, + .cli_show = bfd_cli_show_rx, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/administrative-down", + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, + .cli_show = bfd_cli_show_shutdown, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-discriminator", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-state", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-diagnostic", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-multiplier", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-discriminator", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-state", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-diagnostic", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-multiplier", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-transmission-interval", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-receive-interval", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/detection-mode", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-down-time", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-up-time", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-down-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-up-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-input-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-output-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-echo-transmission-interval", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-input-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, + } + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-output-count", + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, + } + }, + { + .xpath = NULL, + }, + } +}; diff --git a/bfdd/bfdd_nb.h b/bfdd/bfdd_nb.h new file mode 100644 index 0000000000..8377c87bb7 --- /dev/null +++ b/bfdd/bfdd_nb.h @@ -0,0 +1,217 @@ +/* + * BFD daemon northbound implementation. + * + * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") + * Rafael Zalamena + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ + +#ifndef _FRR_BFDD_NB_H_ +#define _FRR_BFDD_NB_H_ + +extern const struct frr_yang_module_info frr_bfdd_info; + +/* Mandatory callbacks. */ +int bfdd_bfd_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_destroy(enum nb_event event, const struct lyd_node *dnode); +int bfdd_bfd_sessions_single_hop_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_single_hop_destroy(enum nb_event event, + const struct lyd_node *dnode); +const void *bfdd_bfd_sessions_single_hop_get_next(const void *parent_list_entry, + const void *list_entry); +int bfdd_bfd_sessions_single_hop_get_keys(const void *list_entry, + struct yang_list_keys *keys); +const void * +bfdd_bfd_sessions_single_hop_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys); +int bfdd_bfd_sessions_single_hop_source_addr_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_single_hop_source_addr_destroy( + enum nb_event event, const struct lyd_node *dnode); +int bfdd_bfd_sessions_single_hop_detection_multiplier_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_single_hop_required_receive_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_single_hop_administrative_down_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_single_hop_echo_mode_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_local_state_get_elem(const char *xpath, + const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem( + const char *xpath, const void *list_entry); +int bfdd_bfd_sessions_multi_hop_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_multi_hop_destroy(enum nb_event event, + const struct lyd_node *dnode); +const void *bfdd_bfd_sessions_multi_hop_get_next(const void *parent_list_entry, + const void *list_entry); +int bfdd_bfd_sessions_multi_hop_get_keys(const void *list_entry, + struct yang_list_keys *keys); +const void * +bfdd_bfd_sessions_multi_hop_lookup_entry(const void *parent_list_entry, + const struct yang_list_keys *keys); +int bfdd_bfd_sessions_multi_hop_detection_multiplier_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_multi_hop_desired_transmission_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_multi_hop_required_receive_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +int bfdd_bfd_sessions_multi_hop_administrative_down_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_local_discriminator_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_local_state_get_elem(const char *xpath, + const void *list_entry); +struct yang_data *bfdd_bfd_sessions_multi_hop_stats_local_diagnostic_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_multi_hop_stats_local_multiplier_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_remote_discriminator_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_remote_state_get_elem(const char *xpath, + const void *list_entry); +struct yang_data *bfdd_bfd_sessions_multi_hop_stats_remote_diagnostic_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_multi_hop_stats_remote_multiplier_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_negotiated_transmission_interval_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_negotiated_receive_interval_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_multi_hop_stats_detection_mode_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_multi_hop_stats_last_down_time_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_last_up_time_get_elem(const char *xpath, + const void *list_entry); +struct yang_data *bfdd_bfd_sessions_multi_hop_stats_session_down_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data *bfdd_bfd_sessions_multi_hop_stats_session_up_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_control_packet_input_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_control_packet_output_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_negotiated_echo_transmission_interval_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_echo_packet_input_count_get_elem( + const char *xpath, const void *list_entry); +struct yang_data * +bfdd_bfd_sessions_multi_hop_stats_echo_packet_output_count_get_elem( + const char *xpath, const void *list_entry); + +/* Optional 'cli_show' callbacks. */ +void bfd_cli_show_header(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_header_end(struct vty *vty, struct lyd_node *dnode); +void bfd_cli_show_single_hop_peer(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_multi_hop_peer(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_peer_end(struct vty *vty, struct lyd_node *dnode); +void bfd_cli_show_mult(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_echo(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); + +#endif /* _FRR_BFDD_NB_H_ */ diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c new file mode 100644 index 0000000000..50f953115c --- /dev/null +++ b/bfdd/bfdd_nb_config.c @@ -0,0 +1,520 @@ +/* + * BFD daemon northbound implementation. + * + * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") + * Rafael Zalamena + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ + +#include + +#include "lib/log.h" +#include "lib/northbound.h" + +#include "bfd.h" +#include "bfdd_nb.h" + +/* + * Helpers. + */ +static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, + struct bfd_key *bk) +{ + const char *ifname = NULL, *vrfname = NULL; + struct sockaddr_any psa, lsa; + + /* Required destination parameter. */ + strtosa(yang_dnode_get_string(dnode, "./dest-addr"), &psa); + + /* Get optional source address. */ + memset(&lsa, 0, sizeof(lsa)); + if (yang_dnode_exists(dnode, "./source-addr")) + strtosa(yang_dnode_get_string(dnode, "./source-addr"), &lsa); + + /* Get optional interface and vrf names. */ + if (yang_dnode_exists(dnode, "./interface")) + ifname = yang_dnode_get_string(dnode, "./interface"); + if (yang_dnode_exists(dnode, "./vrf")) + vrfname = yang_dnode_get_string(dnode, "./vrf"); + + /* Generate the corresponding key. */ + gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname); +} + +static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource, bool mhop) +{ + struct bfd_session *bs; + const char *ifname; + struct bfd_key bk; + struct prefix p; + + switch (event) { + case NB_EV_VALIDATE: + /* + * When `dest-addr` is IPv6 and link-local we must + * require interface name, otherwise we can't figure + * which interface to use to send the packets. + */ + yang_dnode_get_prefix(&p, dnode, "./dest-addr"); + + /* + * To support old FRR versions we must allow empty + * interface to be specified, however that should + * change in the future. + */ + if (yang_dnode_exists(dnode, "./interface")) + ifname = yang_dnode_get_string(dnode, "./interface"); + else + ifname = ""; + + if (p.family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6) + && strlen(ifname) == 0) { + zlog_warn( + "%s: when using link-local you must specify " + "an interface.", + __func__); + return NB_ERR_VALIDATION; + } + break; + + case NB_EV_PREPARE: + bfd_session_get_key(mhop, dnode, &bk); + bs = bfd_key_lookup(bk); + + /* This session was already configured by another daemon. */ + if (bs != NULL) { + /* Now it is configured also by CLI. */ + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); + bs->refcount++; + + resource->ptr = bs; + break; + } + + bs = bfd_session_new(); + if (bs == NULL) + return NB_ERR_RESOURCE; + + /* Fill the session key. */ + bfd_session_get_key(mhop, dnode, &bs->key); + + /* Set configuration flags. */ + bs->refcount = 1; + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); + if (mhop) + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_MH); + if (bs->key.family == AF_INET6) + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6); + + resource->ptr = bs; + break; + + case NB_EV_APPLY: + bs = resource->ptr; + + /* Only attempt to registrate if freshly allocated. */ + if (bs->discrs.my_discr == 0 && bs_registrate(bs) == NULL) + return NB_ERR_RESOURCE; + + nb_running_set_entry(dnode, bs); + break; + + case NB_EV_ABORT: + bs = resource->ptr; + if (bs->refcount <= 1) + bfd_session_free(resource->ptr); + break; + } + + return NB_OK; +} + +static int bfd_session_destroy(enum nb_event event, + const struct lyd_node *dnode, bool mhop) +{ + struct bfd_session *bs; + struct bfd_key bk; + + switch (event) { + case NB_EV_VALIDATE: + bfd_session_get_key(mhop, dnode, &bk); + if (bfd_key_lookup(bk) == NULL) + return NB_ERR_INCONSISTENCY; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_unset_entry(dnode); + /* CLI is not using this session anymore. */ + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) == 0) + break; + + BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); + bs->refcount--; + /* There are still daemons using it. */ + if (bs->refcount > 0) + break; + + bfd_session_free(bs); + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd + */ +int bfdd_bfd_create(enum nb_event event, + const struct lyd_node *dnode __attribute__((__unused__)), + union nb_resource *resource __attribute__((__unused__))) +{ + /* NOTHING */ + return NB_OK; +} + +int bfdd_bfd_destroy(enum nb_event event, const struct lyd_node *dnode) +{ + switch (event) { + case NB_EV_VALIDATE: + /* NOTHING */ + return NB_OK; + + case NB_EV_PREPARE: + /* NOTHING */ + return NB_OK; + + case NB_EV_APPLY: + bfd_sessions_remove_manual(); + break; + + case NB_EV_ABORT: + /* NOTHING */ + return NB_OK; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop + */ +int bfdd_bfd_sessions_single_hop_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return bfd_session_create(event, dnode, resource, false); +} + +int bfdd_bfd_sessions_single_hop_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return bfd_session_destroy(event, dnode, false); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr + */ +int bfdd_bfd_sessions_single_hop_source_addr_modify(enum nb_event event + __attribute__((__unused__)), + const struct lyd_node *dnode + __attribute__((__unused__)), + union nb_resource *resource + __attribute__((__unused__))) +{ + return NB_OK; +} + +int bfdd_bfd_sessions_single_hop_source_addr_destroy( + enum nb_event event __attribute__((__unused__)), + const struct lyd_node *dnode __attribute__((__unused__))) +{ + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier + */ +int bfdd_bfd_sessions_single_hop_detection_multiplier_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + uint8_t detection_multiplier = yang_dnode_get_uint8(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_get_entry(dnode, NULL, true); + bs->detect_mult = detection_multiplier; + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval + */ +int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + uint32_t tx_interval = yang_dnode_get_uint32(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + if (tx_interval < 10000 || tx_interval > 60000000) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_get_entry(dnode, NULL, true); + if (tx_interval == bs->timers.desired_min_tx) + return NB_OK; + + bs->timers.desired_min_tx = tx_interval; + bfd_set_polling(bs); + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval + */ +int bfdd_bfd_sessions_single_hop_required_receive_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + uint32_t rx_interval = yang_dnode_get_uint32(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + if (rx_interval < 10000 || rx_interval > 60000000) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_get_entry(dnode, NULL, true); + if (rx_interval == bs->timers.required_min_rx) + return NB_OK; + + bs->timers.required_min_rx = rx_interval; + bfd_set_polling(bs); + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down + */ +int bfdd_bfd_sessions_single_hop_administrative_down_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + bool shutdown = yang_dnode_get_bool(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + return NB_OK; + + case NB_EV_APPLY: + break; + + case NB_EV_ABORT: + return NB_OK; + } + + bs = nb_running_get_entry(dnode, NULL, true); + + if (shutdown == false) { + if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) + return NB_OK; + + BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN); + + /* Change and notify state change. */ + bs->ses_state = PTM_BFD_DOWN; + control_notify(bs, bs->ses_state); + + /* Enable all timers. */ + bfd_recvtimer_update(bs); + bfd_xmttimer_update(bs, bs->xmt_TO); + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) { + bfd_echo_recvtimer_update(bs); + bfd_echo_xmttimer_update(bs, bs->echo_xmt_TO); + } + } else { + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) + return NB_OK; + + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN); + + /* Disable all events. */ + bfd_recvtimer_delete(bs); + bfd_echo_recvtimer_delete(bs); + bfd_xmttimer_delete(bs); + bfd_echo_xmttimer_delete(bs); + + /* Change and notify state change. */ + bs->ses_state = PTM_BFD_ADM_DOWN; + control_notify(bs, bs->ses_state); + + ptm_bfd_snd(bs, 0); + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode + */ +int bfdd_bfd_sessions_single_hop_echo_mode_modify(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource + __attribute__((__unused__))) +{ + bool echo = yang_dnode_get_bool(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + return NB_OK; + + case NB_EV_APPLY: + break; + + case NB_EV_ABORT: + return NB_OK; + } + + bs = nb_running_get_entry(dnode, NULL, true); + + if (echo == false) { + if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) + return NB_OK; + + BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO); + ptm_bfd_echo_stop(bs); + } else { + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) + return NB_OK; + + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO); + /* Apply setting immediately. */ + if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) + bs_echo_timer_handler(bs); + } + + return NB_OK; +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval + */ +int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + uint32_t echo_interval = yang_dnode_get_uint32(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + if (echo_interval < 10000 || echo_interval > 60000000) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_get_entry(dnode, NULL, true); + if (echo_interval == bs->timers.required_min_echo) + return NB_OK; + + bs->timers.required_min_echo = echo_interval; + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop + */ +int bfdd_bfd_sessions_multi_hop_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return bfd_session_create(event, dnode, resource, true); +} + +int bfdd_bfd_sessions_multi_hop_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return bfd_session_destroy(event, dnode, true); +} diff --git a/bfdd/bfdd_nb_state.c b/bfdd/bfdd_nb_state.c new file mode 100644 index 0000000000..dfca3d1417 --- /dev/null +++ b/bfdd/bfdd_nb_state.c @@ -0,0 +1,383 @@ +/* + * BFD daemon northbound implementation. + * + * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") + * Rafael Zalamena + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ + +#include + +#include "lib/log.h" +#include "lib/northbound.h" + +#include "bfd.h" +#include "bfdd_nb.h" + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop + */ +const void *bfdd_bfd_sessions_single_hop_get_next(const void *parent_list_entry + __attribute__((__unused__)), + const void *list_entry) +{ + return bfd_session_next(list_entry, false); +} + +int bfdd_bfd_sessions_single_hop_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct bfd_session *bs = list_entry; + char dstbuf[INET6_ADDRSTRLEN]; + + inet_ntop(bs->key.family, &bs->key.peer, dstbuf, sizeof(dstbuf)); + + keys->num = 3; + strlcpy(keys->key[0], dstbuf, sizeof(keys->key[0])); + strlcpy(keys->key[1], bs->key.ifname, sizeof(keys->key[1])); + strlcpy(keys->key[2], bs->key.vrfname, sizeof(keys->key[2])); + + return NB_OK; +} + +const void * +bfdd_bfd_sessions_single_hop_lookup_entry(const void *parent_list_entry + __attribute__((__unused__)), + const struct yang_list_keys *keys) +{ + const char *dest_addr = keys->key[0]; + const char *ifname = keys->key[1]; + const char *vrf = keys->key[2]; + struct sockaddr_any psa, lsa; + struct bfd_key bk; + + strtosa(dest_addr, &psa); + memset(&lsa, 0, sizeof(lsa)); + gen_bfd_key(&bk, &psa, &lsa, false, ifname, vrf); + + return bfd_key_lookup(bk); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, bs->discrs.my_discr); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_local_state_get_elem(const char *xpath, + const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_enum(xpath, bs->ses_state); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic + */ +struct yang_data *bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_enum(xpath, bs->local_diag); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier + */ +struct yang_data *bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_int8(xpath, bs->detect_mult); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + if (bs->discrs.remote_discr == 0) + return NULL; + + return yang_data_new_uint32(xpath, bs->discrs.remote_discr); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem(const char *xpath, + const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_enum(xpath, bs->ses_state); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic + */ +struct yang_data *bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_enum(xpath, bs->remote_diag); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier + */ +struct yang_data *bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_int8(xpath, bs->remote_detect_mult); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, bs->remote_timers.desired_min_tx); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, bs->remote_timers.required_min_rx); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode + */ +struct yang_data *bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + int detection_mode; + + /* + * Detection mode: + * 1. Async with echo + * 2. Async without echo + * 3. Demand with echo + * 4. Demand without echo + * + * TODO: support demand mode. + */ + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) + detection_mode = 1; + else + detection_mode = 2; + + return yang_data_new_enum(xpath, detection_mode); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time + */ +struct yang_data *bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem( + const char *xpath __attribute__((__unused__)), + const void *list_entry __attribute__((__unused__))) +{ + /* + * TODO: implement me. + * + * No yang support for time elements yet. + */ + return NULL; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time + */ +struct yang_data *bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem( + const char *xpath __attribute__((__unused__)), + const void *list_entry __attribute__((__unused__))) +{ + /* + * TODO: implement me. + * + * No yang support for time elements yet. + */ + return NULL; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.session_down); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count + */ +struct yang_data *bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.session_up); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.rx_ctrl_pkt); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.tx_ctrl_pkt); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, bs->remote_timers.required_min_echo); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.rx_echo_pkt); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count + */ +struct yang_data * +bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.tx_echo_pkt); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop + */ +const void *bfdd_bfd_sessions_multi_hop_get_next(const void *parent_list_entry + __attribute__((__unused__)), + const void *list_entry) +{ + return bfd_session_next(list_entry, true); +} + +int bfdd_bfd_sessions_multi_hop_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct bfd_session *bs = list_entry; + char dstbuf[INET6_ADDRSTRLEN], srcbuf[INET6_ADDRSTRLEN]; + + inet_ntop(bs->key.family, &bs->key.peer, dstbuf, sizeof(dstbuf)); + inet_ntop(bs->key.family, &bs->key.local, srcbuf, sizeof(srcbuf)); + + keys->num = 4; + strlcpy(keys->key[0], srcbuf, sizeof(keys->key[0])); + strlcpy(keys->key[1], dstbuf, sizeof(keys->key[1])); + strlcpy(keys->key[2], bs->key.ifname, sizeof(keys->key[2])); + strlcpy(keys->key[3], bs->key.vrfname, sizeof(keys->key[3])); + + return NB_OK; +} + +const void * +bfdd_bfd_sessions_multi_hop_lookup_entry(const void *parent_list_entry + __attribute__((__unused__)), + const struct yang_list_keys *keys) +{ + const char *source_addr = keys->key[0]; + const char *dest_addr = keys->key[1]; + const char *ifname = keys->key[2]; + const char *vrf = keys->key[3]; + struct sockaddr_any psa, lsa; + struct bfd_key bk; + + strtosa(dest_addr, &psa); + strtosa(source_addr, &lsa); + gen_bfd_key(&bk, &psa, &lsa, true, ifname, vrf); + + return bfd_key_lookup(bk); +} diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c deleted file mode 100644 index edbd406918..0000000000 --- a/bfdd/bfdd_northbound.c +++ /dev/null @@ -1,1236 +0,0 @@ -/* - * BFD daemon northbound implementation. - * - * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") - * Rafael Zalamena - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -#include - -#include "lib/log.h" -#include "lib/northbound.h" - -#include "bfd.h" - -/* - * Helpers. - */ -static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, - struct bfd_key *bk) -{ - const char *ifname = NULL, *vrfname = NULL; - struct sockaddr_any psa, lsa; - - /* Required destination parameter. */ - strtosa(yang_dnode_get_string(dnode, "./dest-addr"), &psa); - - /* Get optional source address. */ - memset(&lsa, 0, sizeof(lsa)); - if (yang_dnode_exists(dnode, "./source-addr")) - strtosa(yang_dnode_get_string(dnode, "./source-addr"), &lsa); - - /* Get optional interface and vrf names. */ - if (yang_dnode_exists(dnode, "./interface")) - ifname = yang_dnode_get_string(dnode, "./interface"); - if (yang_dnode_exists(dnode, "./vrf")) - vrfname = yang_dnode_get_string(dnode, "./vrf"); - - /* Generate the corresponding key. */ - gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname); -} - -static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource, bool mhop) -{ - struct bfd_session *bs; - const char *ifname; - struct bfd_key bk; - struct prefix p; - - switch (event) { - case NB_EV_VALIDATE: - /* - * When `dest-addr` is IPv6 and link-local we must - * require interface name, otherwise we can't figure - * which interface to use to send the packets. - */ - yang_dnode_get_prefix(&p, dnode, "./dest-addr"); - - /* - * To support old FRR versions we must allow empty - * interface to be specified, however that should - * change in the future. - */ - if (yang_dnode_exists(dnode, "./interface")) - ifname = yang_dnode_get_string(dnode, "./interface"); - else - ifname = ""; - - if (p.family == AF_INET6 - && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6) - && strlen(ifname) == 0) { - zlog_warn("%s: when using link-local you must specify " - "an interface.", __func__); - return NB_ERR_VALIDATION; - } - break; - - case NB_EV_PREPARE: - bfd_session_get_key(mhop, dnode, &bk); - bs = bfd_key_lookup(bk); - - /* This session was already configured by another daemon. */ - if (bs != NULL) { - /* Now it is configured also by CLI. */ - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); - bs->refcount++; - - resource->ptr = bs; - break; - } - - bs = bfd_session_new(); - if (bs == NULL) - return NB_ERR_RESOURCE; - - /* Fill the session key. */ - bfd_session_get_key(mhop, dnode, &bs->key); - - /* Set configuration flags. */ - bs->refcount = 1; - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); - if (mhop) - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_MH); - if (bs->key.family == AF_INET6) - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6); - - resource->ptr = bs; - break; - - case NB_EV_APPLY: - bs = resource->ptr; - - /* Only attempt to registrate if freshly allocated. */ - if (bs->discrs.my_discr == 0 && bs_registrate(bs) == NULL) - return NB_ERR_RESOURCE; - - nb_running_set_entry(dnode, bs); - break; - - case NB_EV_ABORT: - bs = resource->ptr; - if (bs->refcount <= 1) - bfd_session_free(resource->ptr); - break; - } - - return NB_OK; -} - -static int bfd_session_destroy(enum nb_event event, - const struct lyd_node *dnode, bool mhop) -{ - struct bfd_session *bs; - struct bfd_key bk; - - switch (event) { - case NB_EV_VALIDATE: - bfd_session_get_key(mhop, dnode, &bk); - if (bfd_key_lookup(bk) == NULL) - return NB_ERR_INCONSISTENCY; - break; - - case NB_EV_PREPARE: - /* NOTHING */ - break; - - case NB_EV_APPLY: - bs = nb_running_unset_entry(dnode); - /* CLI is not using this session anymore. */ - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) == 0) - break; - - BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); - bs->refcount--; - /* There are still daemons using it. */ - if (bs->refcount > 0) - break; - - bfd_session_free(bs); - break; - - case NB_EV_ABORT: - /* NOTHING */ - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd - */ -static int bfdd_bfd_create(enum nb_event event, - const struct lyd_node *dnode - __attribute__((__unused__)), - union nb_resource *resource - __attribute__((__unused__))) -{ - /* NOTHING */ - return NB_OK; -} - -static int bfdd_bfd_destroy(enum nb_event event, const struct lyd_node *dnode) -{ - switch (event) { - case NB_EV_VALIDATE: - /* NOTHING */ - return NB_OK; - - case NB_EV_PREPARE: - /* NOTHING */ - return NB_OK; - - case NB_EV_APPLY: - bfd_sessions_remove_manual(); - break; - - case NB_EV_ABORT: - /* NOTHING */ - return NB_OK; - } - - return NB_OK; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop - */ -static int bfdd_bfd_sessions_single_hop_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - return bfd_session_create(event, dnode, resource, false); -} - -static int bfdd_bfd_sessions_single_hop_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - return bfd_session_destroy(event, dnode, false); -} - -static const void * -bfdd_bfd_sessions_single_hop_get_next(const void *parent_list_entry - __attribute__((__unused__)), - const void *list_entry) -{ - return bfd_session_next(list_entry, false); -} - -static int bfdd_bfd_sessions_single_hop_get_keys(const void *list_entry, - struct yang_list_keys *keys) -{ - const struct bfd_session *bs = list_entry; - char dstbuf[INET6_ADDRSTRLEN]; - - inet_ntop(bs->key.family, &bs->key.peer, dstbuf, sizeof(dstbuf)); - - keys->num = 3; - strlcpy(keys->key[0], dstbuf, sizeof(keys->key[0])); - strlcpy(keys->key[1], bs->key.ifname, sizeof(keys->key[1])); - strlcpy(keys->key[2], bs->key.vrfname, sizeof(keys->key[2])); - - return NB_OK; -} - -static const void * -bfdd_bfd_sessions_single_hop_lookup_entry(const void *parent_list_entry - __attribute__((__unused__)), - const struct yang_list_keys *keys) -{ - const char *dest_addr = keys->key[0]; - const char *ifname = keys->key[1]; - const char *vrf = keys->key[2]; - struct sockaddr_any psa, lsa; - struct bfd_key bk; - - strtosa(dest_addr, &psa); - memset(&lsa, 0, sizeof(lsa)); - gen_bfd_key(&bk, &psa, &lsa, false, ifname, vrf); - - return bfd_key_lookup(bk); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr - */ -static int bfdd_bfd_sessions_single_hop_source_addr_modify( - enum nb_event event __attribute__((__unused__)), - const struct lyd_node *dnode __attribute__((__unused__)), - union nb_resource *resource __attribute__((__unused__))) -{ - return NB_OK; -} - -static int bfdd_bfd_sessions_single_hop_source_addr_destroy( - enum nb_event event __attribute__((__unused__)), - const struct lyd_node *dnode __attribute__((__unused__))) -{ - return NB_OK; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier - */ -static int bfdd_bfd_sessions_single_hop_detection_multiplier_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource __attribute__((__unused__))) -{ - uint8_t detection_multiplier = yang_dnode_get_uint8(dnode, NULL); - struct bfd_session *bs; - - switch (event) { - case NB_EV_VALIDATE: - break; - - case NB_EV_PREPARE: - /* NOTHING */ - break; - - case NB_EV_APPLY: - bs = nb_running_get_entry(dnode, NULL, true); - bs->detect_mult = detection_multiplier; - break; - - case NB_EV_ABORT: - /* NOTHING */ - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval - */ -static int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource __attribute__((__unused__))) -{ - uint32_t tx_interval = yang_dnode_get_uint32(dnode, NULL); - struct bfd_session *bs; - - switch (event) { - case NB_EV_VALIDATE: - if (tx_interval < 10000 || tx_interval > 60000000) - return NB_ERR_VALIDATION; - break; - - case NB_EV_PREPARE: - /* NOTHING */ - break; - - case NB_EV_APPLY: - bs = nb_running_get_entry(dnode, NULL, true); - if (tx_interval == bs->timers.desired_min_tx) - return NB_OK; - - bs->timers.desired_min_tx = tx_interval; - bfd_set_polling(bs); - break; - - case NB_EV_ABORT: - /* NOTHING */ - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval - */ -static int bfdd_bfd_sessions_single_hop_required_receive_interval_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource __attribute__((__unused__))) -{ - uint32_t rx_interval = yang_dnode_get_uint32(dnode, NULL); - struct bfd_session *bs; - - switch (event) { - case NB_EV_VALIDATE: - if (rx_interval < 10000 || rx_interval > 60000000) - return NB_ERR_VALIDATION; - break; - - case NB_EV_PREPARE: - /* NOTHING */ - break; - - case NB_EV_APPLY: - bs = nb_running_get_entry(dnode, NULL, true); - if (rx_interval == bs->timers.required_min_rx) - return NB_OK; - - bs->timers.required_min_rx = rx_interval; - bfd_set_polling(bs); - break; - - case NB_EV_ABORT: - /* NOTHING */ - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down - */ -static int bfdd_bfd_sessions_single_hop_administrative_down_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource __attribute__((__unused__))) -{ - bool shutdown = yang_dnode_get_bool(dnode, NULL); - struct bfd_session *bs; - - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - return NB_OK; - - case NB_EV_APPLY: - break; - - case NB_EV_ABORT: - return NB_OK; - } - - bs = nb_running_get_entry(dnode, NULL, true); - - if (shutdown == false) { - if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) - return NB_OK; - - BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN); - - /* Change and notify state change. */ - bs->ses_state = PTM_BFD_DOWN; - control_notify(bs, bs->ses_state); - - /* Enable all timers. */ - bfd_recvtimer_update(bs); - bfd_xmttimer_update(bs, bs->xmt_TO); - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) { - bfd_echo_recvtimer_update(bs); - bfd_echo_xmttimer_update(bs, bs->echo_xmt_TO); - } - } else { - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) - return NB_OK; - - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN); - - /* Disable all events. */ - bfd_recvtimer_delete(bs); - bfd_echo_recvtimer_delete(bs); - bfd_xmttimer_delete(bs); - bfd_echo_xmttimer_delete(bs); - - /* Change and notify state change. */ - bs->ses_state = PTM_BFD_ADM_DOWN; - control_notify(bs, bs->ses_state); - - ptm_bfd_snd(bs, 0); - } - - return NB_OK; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode - */ -static int bfdd_bfd_sessions_single_hop_echo_mode_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource __attribute__((__unused__))) -{ - bool echo = yang_dnode_get_bool(dnode, NULL); - struct bfd_session *bs; - - switch (event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - return NB_OK; - - case NB_EV_APPLY: - break; - - case NB_EV_ABORT: - return NB_OK; - } - - bs = nb_running_get_entry(dnode, NULL, true); - - if (echo == false) { - if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) - return NB_OK; - - BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO); - ptm_bfd_echo_stop(bs); - } else { - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) - return NB_OK; - - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO); - /* Apply setting immediately. */ - if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) - bs_echo_timer_handler(bs); - } - - return NB_OK; -} - -/* - * XPath: - * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval - */ -static int -bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify( - enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource __attribute__((__unused__))) -{ - uint32_t echo_interval = yang_dnode_get_uint32(dnode, NULL); - struct bfd_session *bs; - - switch (event) { - case NB_EV_VALIDATE: - if (echo_interval < 10000 || echo_interval > 60000000) - return NB_ERR_VALIDATION; - break; - - case NB_EV_PREPARE: - /* NOTHING */ - break; - - case NB_EV_APPLY: - bs = nb_running_get_entry(dnode, NULL, true); - if (echo_interval == bs->timers.required_min_echo) - return NB_OK; - - bs->timers.required_min_echo = echo_interval; - break; - - case NB_EV_ABORT: - /* NOTHING */ - break; - } - - return NB_OK; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint32(xpath, bs->discrs.my_discr); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_local_state_get_elem(const char *xpath, - const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_enum(xpath, bs->ses_state); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_enum(xpath, bs->local_diag); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_int8(xpath, bs->detect_mult); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - if (bs->discrs.remote_discr == 0) - return NULL; - - return yang_data_new_uint32(xpath, bs->discrs.remote_discr); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem(const char *xpath, - const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_enum(xpath, bs->ses_state); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_enum(xpath, bs->remote_diag); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_int8(xpath, bs->remote_detect_mult); -} - -/* - * XPath: - * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint32(xpath, bs->remote_timers.desired_min_tx); -} - -/* - * XPath: - * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint32(xpath, bs->remote_timers.required_min_rx); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - int detection_mode; - - /* - * Detection mode: - * 1. Async with echo - * 2. Async without echo - * 3. Demand with echo - * 4. Demand without echo - * - * TODO: support demand mode. - */ - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) - detection_mode = 1; - else - detection_mode = 2; - - return yang_data_new_enum(xpath, detection_mode); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem( - const char *xpath __attribute__((__unused__)), - const void *list_entry __attribute__((__unused__))) -{ - /* - * TODO: implement me. - * - * No yang support for time elements yet. - */ - return NULL; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem( - const char *xpath __attribute__((__unused__)), - const void *list_entry __attribute__((__unused__))) -{ - /* - * TODO: implement me. - * - * No yang support for time elements yet. - */ - return NULL; -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint64(xpath, bs->stats.session_down); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint64(xpath, bs->stats.session_up); -} - -/* - * XPath: - * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint64(xpath, bs->stats.rx_ctrl_pkt); -} - -/* - * XPath: - * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint64(xpath, bs->stats.tx_ctrl_pkt); -} - -/* - * XPath: - * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint32(xpath, bs->remote_timers.required_min_echo); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint64(xpath, bs->stats.rx_echo_pkt); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count - */ -static struct yang_data * -bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem( - const char *xpath, const void *list_entry) -{ - const struct bfd_session *bs = list_entry; - - return yang_data_new_uint64(xpath, bs->stats.tx_echo_pkt); -} - -/* - * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop - */ -static int bfdd_bfd_sessions_multi_hop_create(enum nb_event event, - const struct lyd_node *dnode, - union nb_resource *resource) -{ - return bfd_session_create(event, dnode, resource, true); -} - -static int bfdd_bfd_sessions_multi_hop_destroy(enum nb_event event, - const struct lyd_node *dnode) -{ - return bfd_session_destroy(event, dnode, true); -} - -static const void * -bfdd_bfd_sessions_multi_hop_get_next(const void *parent_list_entry - __attribute__((__unused__)), - const void *list_entry) -{ - return bfd_session_next(list_entry, true); -} - -static int bfdd_bfd_sessions_multi_hop_get_keys(const void *list_entry, - struct yang_list_keys *keys) -{ - const struct bfd_session *bs = list_entry; - char dstbuf[INET6_ADDRSTRLEN], srcbuf[INET6_ADDRSTRLEN]; - - inet_ntop(bs->key.family, &bs->key.peer, dstbuf, sizeof(dstbuf)); - inet_ntop(bs->key.family, &bs->key.local, srcbuf, sizeof(srcbuf)); - - keys->num = 4; - strlcpy(keys->key[0], srcbuf, sizeof(keys->key[0])); - strlcpy(keys->key[1], dstbuf, sizeof(keys->key[1])); - strlcpy(keys->key[2], bs->key.ifname, sizeof(keys->key[2])); - strlcpy(keys->key[3], bs->key.vrfname, sizeof(keys->key[3])); - - return NB_OK; -} - -static const void * -bfdd_bfd_sessions_multi_hop_lookup_entry(const void *parent_list_entry - __attribute__((__unused__)), - const struct yang_list_keys *keys) -{ - const char *source_addr = keys->key[0]; - const char *dest_addr = keys->key[1]; - const char *ifname = keys->key[2]; - const char *vrf = keys->key[3]; - struct sockaddr_any psa, lsa; - struct bfd_key bk; - - strtosa(dest_addr, &psa); - strtosa(source_addr, &lsa); - gen_bfd_key(&bk, &psa, &lsa, true, ifname, vrf); - - return bfd_key_lookup(bk); -} - -/* clang-format off */ -const struct frr_yang_module_info frr_bfdd_info = { - .name = "frr-bfdd", - .nodes = { - { - .xpath = "/frr-bfdd:bfdd/bfd", - .cbs = { - .create = bfdd_bfd_create, - .destroy = bfdd_bfd_destroy, - .cli_show = bfd_cli_show_header, - .cli_show_end = bfd_cli_show_header_end, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop", - .cbs = { - .create = bfdd_bfd_sessions_single_hop_create, - .destroy = bfdd_bfd_sessions_single_hop_destroy, - .get_next = bfdd_bfd_sessions_single_hop_get_next, - .get_keys = bfdd_bfd_sessions_single_hop_get_keys, - .lookup_entry = bfdd_bfd_sessions_single_hop_lookup_entry, - .cli_show = bfd_cli_show_single_hop_peer, - .cli_show_end = bfd_cli_show_peer_end, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_source_addr_modify, - .destroy = bfdd_bfd_sessions_single_hop_source_addr_destroy, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, - .cli_show = bfd_cli_show_mult, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, - .cli_show = bfd_cli_show_tx, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, - .cli_show = bfd_cli_show_rx, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, - .cli_show = bfd_cli_show_shutdown, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_echo_mode_modify, - .cli_show = bfd_cli_show_echo, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify, - .cli_show = bfd_cli_show_echo_interval, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop", - .cbs = { - .create = bfdd_bfd_sessions_multi_hop_create, - .destroy = bfdd_bfd_sessions_multi_hop_destroy, - .get_next = bfdd_bfd_sessions_multi_hop_get_next, - .get_keys = bfdd_bfd_sessions_multi_hop_get_keys, - .lookup_entry = bfdd_bfd_sessions_multi_hop_lookup_entry, - .cli_show = bfd_cli_show_multi_hop_peer, - .cli_show_end = bfd_cli_show_peer_end, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/detection-multiplier", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, - .cli_show = bfd_cli_show_mult, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/desired-transmission-interval", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, - .cli_show = bfd_cli_show_tx, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/required-receive-interval", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, - .cli_show = bfd_cli_show_rx, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/administrative-down", - .cbs = { - .modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, - .cli_show = bfd_cli_show_shutdown, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-discriminator", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-state", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-diagnostic", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-multiplier", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-discriminator", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-state", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-diagnostic", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-multiplier", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-transmission-interval", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-receive-interval", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/detection-mode", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-down-time", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-up-time", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-down-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-up-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-input-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-output-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-echo-transmission-interval", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-input-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, - } - }, - { - .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-output-count", - .cbs = { - .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, - } - }, - { - .xpath = NULL, - }, - } -}; diff --git a/bfdd/subdir.am b/bfdd/subdir.am index 5e3c3d4765..ed1d3962bf 100644 --- a/bfdd/subdir.am +++ b/bfdd/subdir.am @@ -13,7 +13,9 @@ endif bfdd_libbfd_a_SOURCES = \ bfdd/bfd.c \ - bfdd/bfdd_northbound.c \ + bfdd/bfdd_nb.c \ + bfdd/bfdd_nb_config.c \ + bfdd/bfdd_nb_state.c \ bfdd/bfdd_vty.c \ bfdd/bfdd_cli.c \ bfdd/bfd_packet.c \ @@ -32,6 +34,7 @@ bfdd/bfdd_cli.$(OBJEXT): bfdd/bfdd_cli_clippy.c noinst_HEADERS += \ bfdd/bfdctl.h \ + bfdd/bfdd_nb.h \ bfdd/bfd.h \ # end From f5f0a0e302da2e84d32c5accff28f0a2237483d4 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 17 Oct 2019 17:26:02 -0300 Subject: [PATCH 5/5] tools: update the northbound callbacks generator Add a new '-s' option which controls whether the generated northbound callbacks are declared with the 'static' specifier or not. If not (the default), a prototype is generated for each callback before their declarations. It's suggested that daemons shouldn't use the '-s' option so that their northbound callbacks can be implemented in different files according to their class (config, state, rpc or notification). libfrr commands, on the other hand, can use the '-s' option when their associated YANG module is too small and putting all callbacks in the same file is desirable. Signed-off-by: Renato Westphal --- tools/gen_northbound_callbacks.c | 55 ++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/tools/gen_northbound_callbacks.c b/tools/gen_northbound_callbacks.c index 14f648e8da..cbdf01e7b8 100644 --- a/tools/gen_northbound_callbacks.c +++ b/tools/gen_northbound_callbacks.c @@ -26,10 +26,12 @@ #include "yang.h" #include "northbound.h" +static bool static_cbs; + static void __attribute__((noreturn)) usage(int status) { extern const char *__progname; - fprintf(stderr, "usage: %s [-h] [-p path] MODULE\n", __progname); + fprintf(stderr, "usage: %s [-h] [-s] [-p path] MODULE\n", __progname); exit(status); } @@ -153,10 +155,46 @@ static void generate_callback_name(struct lys_node *snode, replace_hyphens_by_underscores(buffer); } +static void generate_prototype(const struct nb_callback_info *ncinfo, + const char *cb_name) +{ + printf("%s%s(%s);\n", ncinfo->return_type, cb_name, ncinfo->arguments); +} + +static int generate_prototypes(const struct lys_node *snode, void *arg) +{ + switch (snode->nodetype) { + case LYS_CONTAINER: + case LYS_LEAF: + case LYS_LEAFLIST: + case LYS_LIST: + case LYS_NOTIF: + case LYS_RPC: + break; + default: + return YANG_ITER_CONTINUE; + } + + for (struct nb_callback_info *cb = &nb_callbacks[0]; + cb->operation != -1; cb++) { + char cb_name[BUFSIZ]; + + if (cb->optional + || !nb_operation_is_valid(cb->operation, snode)) + continue; + + generate_callback_name((struct lys_node *)snode, cb->operation, + cb_name, sizeof(cb_name)); + generate_prototype(cb, cb_name); + } + + return YANG_ITER_CONTINUE; +} + static void generate_callback(const struct nb_callback_info *ncinfo, const char *cb_name) { - printf("static %s%s(%s)\n{\n", + printf("%s%s%s(%s)\n{\n", static_cbs ? "static " : "", ncinfo->return_type, cb_name, ncinfo->arguments); switch (ncinfo->operation) { @@ -287,7 +325,7 @@ int main(int argc, char *argv[]) struct stat st; int opt; - while ((opt = getopt(argc, argv, "hp:")) != -1) { + while ((opt = getopt(argc, argv, "hp:s")) != -1) { switch (opt) { case 'h': usage(EXIT_SUCCESS); @@ -307,6 +345,9 @@ int main(int argc, char *argv[]) search_path = optarg; break; + case 's': + static_cbs = true; + break; default: usage(EXIT_FAILURE); /* NOTREACHED */ @@ -332,6 +373,14 @@ int main(int argc, char *argv[]) /* Create a nb_node for all YANG schema nodes. */ nb_nodes_create(); + /* Generate callback prototypes. */ + if (!static_cbs) { + printf("/* prototypes */\n"); + yang_snodes_iterate_module(module->info, generate_prototypes, 0, + NULL); + printf("\n"); + } + /* Generate callback functions. */ yang_snodes_iterate_module(module->info, generate_callbacks, 0, NULL);