]> git.proxmox.com Git - mirror_frr.git/commitdiff
ripd: split northbound callbacks into multiple files
authorRenato Westphal <renato@opensourcerouting.org>
Thu, 17 Oct 2019 18:46:54 +0000 (15:46 -0300)
committerRenato Westphal <renato@opensourcerouting.org>
Wed, 30 Oct 2019 00:49:14 +0000 (21:49 -0300)
Rearrange the ripd northbound callbacks as following:
* rip_nb.h: prototypes of all northbound callbacks.
* rip_nb.c: definition of all northbound callbacks and their
  associated YANG data paths.
* rip_nb_config.c: implementation of YANG configuration nodes.
* rip_nb_state.c: implementation of YANG state nodes.
* rip_nb_rpcs.c: implementation of YANG RPCs.
* rip_nb_notifications.c: implementation of YANG notifications.

This should help to keep to code more organized and easier to
maintain.

No behavior changes intended.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
13 files changed:
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

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