]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #5186 from opensourcerouting/nb-cbs-reorg
authorQuentin Young <qlyoung@users.noreply.github.com>
Wed, 30 Oct 2019 17:59:13 +0000 (13:59 -0400)
committerGitHub <noreply@github.com>
Wed, 30 Oct 2019 17:59:13 +0000 (13:59 -0400)
northbound callbacks reorganization

51 files changed:
bfdd/bfd.h
bfdd/bfdd.c
bfdd/bfdd_cli.c
bfdd/bfdd_nb.c [new file with mode: 0644]
bfdd/bfdd_nb.h [new file with mode: 0644]
bfdd/bfdd_nb_config.c [new file with mode: 0644]
bfdd/bfdd_nb_state.c [new file with mode: 0644]
bfdd/bfdd_northbound.c [deleted file]
bfdd/subdir.am
isisd/isis_adjacency.c
isisd/isis_adjacency.h
isisd/isis_circuit.c
isisd/isis_cli.c
isisd/isis_cli.h [deleted file]
isisd/isis_lsp.c
isisd/isis_main.c
isisd/isis_nb.c [new file with mode: 0644]
isisd/isis_nb.h [new file with mode: 0644]
isisd/isis_nb_config.c [new file with mode: 0644]
isisd/isis_nb_notifications.c [new file with mode: 0644]
isisd/isis_nb_state.c [new file with mode: 0644]
isisd/isis_northbound.c [deleted file]
isisd/isis_pdu.c
isisd/isisd.c
isisd/isisd.h
isisd/subdir.am
ripd/rip_cli.c
ripd/rip_cli.h [deleted file]
ripd/rip_main.c
ripd/rip_nb.c [new file with mode: 0644]
ripd/rip_nb.h [new file with mode: 0644]
ripd/rip_nb_config.c [new file with mode: 0644]
ripd/rip_nb_notifications.c [new file with mode: 0644]
ripd/rip_nb_rpcs.c [new file with mode: 0644]
ripd/rip_nb_state.c [new file with mode: 0644]
ripd/rip_northbound.c [deleted file]
ripd/ripd.c
ripd/ripd.h
ripd/subdir.am
ripngd/ripng_cli.c
ripngd/ripng_cli.h [deleted file]
ripngd/ripng_main.c
ripngd/ripng_nb.c [new file with mode: 0644]
ripngd/ripng_nb.h [new file with mode: 0644]
ripngd/ripng_nb_config.c [new file with mode: 0644]
ripngd/ripng_nb_rpcs.c [new file with mode: 0644]
ripngd/ripng_nb_state.c [new file with mode: 0644]
ripngd/ripng_northbound.c [deleted file]
ripngd/ripngd.h
ripngd/subdir.am
tools/gen_northbound_callbacks.c

index 815b0aec2e2b3c132291646446394b192116dcdb..220dd6e0a81aee79556760771ef2e6dd1dc3a30e 100644 (file)
@@ -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_ */
index 5657744f756ce7813707044f8bb1fd9bf3d86bee..a91fa3d04776ba038f398efd8caeb257f5cda561 100644 (file)
@@ -23,6 +23,7 @@
 #include "filter.h"
 
 #include "bfd.h"
+#include "bfdd_nb.h"
 #include "lib/version.h"
 
 
index acb1801cc431f471808de29285b2185967000569..3e44fcb22ad9ecfc20dc2e35b5bd0b2b109b70cf 100644 (file)
@@ -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 (file)
index 0000000..8d46742
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..8377c87
--- /dev/null
@@ -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 (file)
index 0000000..50f9531
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..dfca3d1
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index edbd406..0000000
+++ /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 <zebra.h>
-
-#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,
-               },
-       }
-};
index 5e3c3d4765007f49240d66c99dbf41ec43bf1bd5..ed1d3962bf76d45c1581ef67d5033b2d699a0b04 100644 (file)
@@ -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
 
index d2ec6ff5665f8cbe2e598dc9e9b6376bf69e052f..1d70521e6812da2bb91157c5d59a51179a9fb542 100644 (file)
@@ -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;
index 2a4cb6e6142849c409ace39815a89f6cac2808d3..93583fc1224372a31518af7c42911a1fc3f121ec 100644 (file)
@@ -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);
index 29fb725b047a8885a9788db346e1fa45646383ff..1d0e6549df878b47968adade1c5cd35c20ae7532 100644 (file)
@@ -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)
 
index 37f4dcfabdec496d5b4b57d3307d0e037f21da02..3144b3c28ebafbe6720f16c2f917ee33ac46ace5 100644 (file)
@@ -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 (file)
index 6621dc0..0000000
+++ /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_ */
index 061e7588314356098ce013214d924bf01895fcab..c0b90e8439cea1436fb88b221a78c53359a11272 100644 (file)
@@ -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);
index 718924daf24ab199262a0d8efebc67a18c5e7649..2ef0065180b895aaccf67b72d1fff43514f5744b 100644 (file)
@@ -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 (file)
index 0000000..d84e533
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..29a2ded
--- /dev/null
@@ -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 (file)
index 0000000..820cfaa
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..ea33ec1
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..e52d020
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 97b7ae4..0000000
+++ /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 <zebra.h>
-#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,
-               },
-       }
-};
index a637ff003f4ac77d80645e95f6af1a74a2f1dea4..71249cf658aa027f9590bcfb9a4daf57dc7df531 100644 (file)
@@ -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)
index 029a9e068898b34ad6b97d88baa296c4973c256e..f15d7a9c7eccca6e42c4d9ac567ae36ba391b2ef 100644 (file)
@@ -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;
 
index f825b6ecb4a2fe0f263f7d7ea1e9ed2a092d6c9f..052cc109286975481b6c5aeb4884a85848c0c34f 100644 (file)
@@ -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;
 
index 24f24022a506ca88bf8e27113dda0f715aeadd3e..e77fef41dd6c74d7999cd521dfc2a96e05b59b99 100644 (file)
@@ -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
 
index 627d3d1993655dadeef931a47eaafca6f83a0f3c..5c26c0cef73ceec970471523e27f0762a62d0dba 100644 (file)
@@ -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 (file)
index ef1e150..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
- * 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_ */
index 773cb1d0fe6efabc88c8faa6d1c037bc21132fcb..08cc5158569918069022d93c2f0312ede8cc98f7 100644 (file)
@@ -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 (file)
index 0000000..4716041
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..441b253
--- /dev/null
@@ -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 (file)
index 0000000..e75db34
--- /dev/null
@@ -0,0 +1,1099 @@
+/*
+ * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
+ * 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 <zebra.h>
+
+#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 (file)
index 0000000..28d3517
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..0ca8529
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..2f7eb3c
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 1238d0f..0000000
+++ /dev/null
@@ -1,1823 +0,0 @@
-/*
- * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
- * 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 <zebra.h>
-
-#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,
-               },
-       }
-};
index 1b5a582cb1006014c47f03d3caa7b435d624f732..ec0770ef3d7d835441ff5da0b81c4edc621b0f9c 100644 (file)
@@ -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"
index 7f2c3fd068e9e3c4f771bd46db2c87cfb67791f0..417bd5b3b16732ed91a2509e940eb1ea8113c13c 100644 (file)
@@ -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 */
index 312c1db6afd56c565f512922ab66605799fe0b36..dfdfc88a56e288cd414ce879797f764b83e983d5 100644 (file)
@@ -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
 
index e95c0e95d672395000498b75d535717e99260fe6..2d9930e3576d76a93f2d81f489e30a90e8b0c2fc 100644 (file)
@@ -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 (file)
index d95747e..0000000
+++ /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_ */
index 4b027019c0977018920a133f28ef10e24a6f1671..3f2c0e9da07cd787d82bbd1babda04fed3ef03a9 100644 (file)
@@ -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 (file)
index 0000000..a02a721
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..45e92e0
--- /dev/null
@@ -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 (file)
index 0000000..b39c1d4
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..0396daf
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 0000000..167077e
--- /dev/null
@@ -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 <zebra.h>
+
+#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 (file)
index 588f6db..0000000
+++ /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 <zebra.h>
-
-#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,
-               },
-       }
-};
index 5a0d350a84b1108c686d8b1f1e5c0d12c2ac6f0e..70508d5cb04ada785caf02cec9c241a42e1ff0eb 100644 (file)
@@ -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 */
index eac0d673139a16b2149e810e2b0c153e00425b38..07d0cb892c63910aff6e9bb1731edf468f4e6f2d 100644 (file)
@@ -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 \
index 14f648e8dae222feec2b76ec0fe5ee9178e8bdc2..cbdf01e7b80804f663f5c0b0f201c3de792c524a 100644 (file)
 #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);