summaryrefslogtreecommitdiffstats
path: root/ripngd
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2019-10-17 21:03:09 +0200
committerRenato Westphal <renato@opensourcerouting.org>2019-10-30 01:49:14 +0100
commitca4739362988cc1591bf977dd9db0b911ed4f158 (patch)
treea747e08b6a656501591bc6d64c75aee7a248829b /ripngd
parentripd: split northbound callbacks into multiple files (diff)
downloadfrr-ca4739362988cc1591bf977dd9db0b911ed4f158.tar.xz
frr-ca4739362988cc1591bf977dd9db0b911ed4f158.zip
ripngd: split northbound callbacks into multiple files
Rearrange the ripngd northbound callbacks as following: * ripng_nb.h: prototypes of all northbound callbacks. * ripng_nb.c: definition of all northbound callbacks and their associated YANG data paths. * ripng_nb_config.c: implementation of YANG configuration nodes. * ripng_nb_state.c: implementation of YANG state nodes. * ripng_nb_rpcs.c: implementation of YANG RPCs. This should help to keep to code more organized and easier to maintain. No behavior changes intended. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'ripngd')
-rw-r--r--ripngd/ripng_cli.c2
-rw-r--r--ripngd/ripng_cli.h58
-rw-r--r--ripngd/ripng_main.c1
-rw-r--r--ripngd/ripng_nb.c252
-rw-r--r--ripngd/ripng_nb.h179
-rw-r--r--ripngd/ripng_nb_config.c714
-rw-r--r--ripngd/ripng_nb_rpcs.c107
-rw-r--r--ripngd/ripng_nb_state.c236
-rw-r--r--ripngd/ripng_northbound.c1234
-rw-r--r--ripngd/ripngd.h3
-rw-r--r--ripngd/subdir.am7
11 files changed, 1495 insertions, 1298 deletions
diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c
index e95c0e95d..2d9930e35 100644
--- a/ripngd/ripng_cli.c
+++ b/ripngd/ripng_cli.c
@@ -29,7 +29,7 @@
#include "libfrr.h"
#include "ripngd/ripngd.h"
-#include "ripngd/ripng_cli.h"
+#include "ripngd/ripng_nb.h"
#ifndef VTYSH_EXTRACT_PL
#include "ripngd/ripng_cli_clippy.c"
#endif
diff --git a/ripngd/ripng_cli.h b/ripngd/ripng_cli.h
deleted file mode 100644
index d95747e0f..000000000
--- a/ripngd/ripng_cli.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 1998 Kunihiro Ishiguro
- * Copyright (C) 2018 NetDEF, Inc.
- * Renato Westphal
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _FRR_RIPNG_CLI_H_
-#define _FRR_RIPNG_CLI_H_
-
-extern void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_allow_ecmp(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_default_information_originate(struct vty *vty,
- struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_default_metric(struct vty *vty,
- struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_network_prefix(struct vty *vty,
- struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_network_interface(struct vty *vty,
- struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_passive_interface(struct vty *vty,
- struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_redistribute(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_route(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_aggregate_address(struct vty *vty,
- struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ripng_timers(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults);
-extern void cli_show_ipv6_ripng_split_horizon(struct vty *vty,
- struct lyd_node *dnode,
- bool show_defaults);
-
-#endif /* _FRR_RIPNG_CLI_H_ */
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index 4b027019c..3f2c0e9da 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -39,6 +39,7 @@
#include "libfrr.h"
#include "ripngd/ripngd.h"
+#include "ripngd/ripng_nb.h"
/* RIPngd options. */
struct option longopts[] = {{0}};
diff --git a/ripngd/ripng_nb.c b/ripngd/ripng_nb.c
new file mode 100644
index 000000000..a02a72112
--- /dev/null
+++ b/ripngd/ripng_nb.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2018 NetDEF, Inc.
+ * Renato Westphal
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "northbound.h"
+#include "libfrr.h"
+
+#include "ripngd/ripng_nb.h"
+
+/* clang-format off */
+const struct frr_yang_module_info frr_ripngd_info = {
+ .name = "frr-ripngd",
+ .nodes = {
+ {
+ .xpath = "/frr-ripngd:ripngd/instance",
+ .cbs = {
+ .cli_show = cli_show_router_ripng,
+ .create = ripngd_instance_create,
+ .destroy = ripngd_instance_destroy,
+ .get_keys = ripngd_instance_get_keys,
+ .get_next = ripngd_instance_get_next,
+ .lookup_entry = ripngd_instance_lookup_entry,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
+ .cbs = {
+ .cli_show = cli_show_ripng_allow_ecmp,
+ .modify = ripngd_instance_allow_ecmp_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
+ .cbs = {
+ .cli_show = cli_show_ripng_default_information_originate,
+ .modify = ripngd_instance_default_information_originate_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/default-metric",
+ .cbs = {
+ .cli_show = cli_show_ripng_default_metric,
+ .modify = ripngd_instance_default_metric_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/network",
+ .cbs = {
+ .cli_show = cli_show_ripng_network_prefix,
+ .create = ripngd_instance_network_create,
+ .destroy = ripngd_instance_network_destroy,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/interface",
+ .cbs = {
+ .cli_show = cli_show_ripng_network_interface,
+ .create = ripngd_instance_interface_create,
+ .destroy = ripngd_instance_interface_destroy,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/offset-list",
+ .cbs = {
+ .cli_show = cli_show_ripng_offset_list,
+ .create = ripngd_instance_offset_list_create,
+ .destroy = ripngd_instance_offset_list_destroy,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list",
+ .cbs = {
+ .modify = ripngd_instance_offset_list_access_list_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric",
+ .cbs = {
+ .modify = ripngd_instance_offset_list_metric_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
+ .cbs = {
+ .cli_show = cli_show_ripng_passive_interface,
+ .create = ripngd_instance_passive_interface_create,
+ .destroy = ripngd_instance_passive_interface_destroy,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/redistribute",
+ .cbs = {
+ .apply_finish = ripngd_instance_redistribute_apply_finish,
+ .cli_show = cli_show_ripng_redistribute,
+ .create = ripngd_instance_redistribute_create,
+ .destroy = ripngd_instance_redistribute_destroy,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
+ .cbs = {
+ .destroy = ripngd_instance_redistribute_route_map_destroy,
+ .modify = ripngd_instance_redistribute_route_map_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
+ .cbs = {
+ .destroy = ripngd_instance_redistribute_metric_destroy,
+ .modify = ripngd_instance_redistribute_metric_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/static-route",
+ .cbs = {
+ .cli_show = cli_show_ripng_route,
+ .create = ripngd_instance_static_route_create,
+ .destroy = ripngd_instance_static_route_destroy,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
+ .cbs = {
+ .cli_show = cli_show_ripng_aggregate_address,
+ .create = ripngd_instance_aggregate_address_create,
+ .destroy = ripngd_instance_aggregate_address_destroy,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/timers",
+ .cbs = {
+ .apply_finish = ripngd_instance_timers_apply_finish,
+ .cli_show = cli_show_ripng_timers,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval",
+ .cbs = {
+ .modify = ripngd_instance_timers_flush_interval_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval",
+ .cbs = {
+ .modify = ripngd_instance_timers_holddown_interval_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval",
+ .cbs = {
+ .modify = ripngd_instance_timers_update_interval_modify,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor",
+ .cbs = {
+ .get_keys = ripngd_instance_state_neighbors_neighbor_get_keys,
+ .get_next = ripngd_instance_state_neighbors_neighbor_get_next,
+ .lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address",
+ .cbs = {
+ .get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update",
+ .cbs = {
+ .get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd",
+ .cbs = {
+ .get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd",
+ .cbs = {
+ .get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route",
+ .cbs = {
+ .get_keys = ripngd_instance_state_routes_route_get_keys,
+ .get_next = ripngd_instance_state_routes_route_get_next,
+ .lookup_entry = ripngd_instance_state_routes_route_lookup_entry,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix",
+ .cbs = {
+ .get_elem = ripngd_instance_state_routes_route_prefix_get_elem,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop",
+ .cbs = {
+ .get_elem = ripngd_instance_state_routes_route_next_hop_get_elem,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface",
+ .cbs = {
+ .get_elem = ripngd_instance_state_routes_route_interface_get_elem,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric",
+ .cbs = {
+ .get_elem = ripngd_instance_state_routes_route_metric_get_elem,
+ },
+ },
+ {
+ .xpath = "/frr-ripngd:clear-ripng-route",
+ .cbs = {
+ .rpc = clear_ripng_route_rpc,
+ },
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
+ .cbs = {
+ .cli_show = cli_show_ipv6_ripng_split_horizon,
+ .modify = lib_interface_ripng_split_horizon_modify,
+ },
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/ripngd/ripng_nb.h b/ripngd/ripng_nb.h
new file mode 100644
index 000000000..45e92e0a1
--- /dev/null
+++ b/ripngd/ripng_nb.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2018 NetDEF, Inc.
+ * Renato Westphal
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _FRR_RIPNG_NB_H_
+#define _FRR_RIPNG_NB_H_
+
+extern const struct frr_yang_module_info frr_ripngd_info;
+
+/* Mandatory callbacks. */
+int ripngd_instance_create(enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_destroy(enum nb_event event, const struct lyd_node *dnode);
+const void *ripngd_instance_get_next(const void *parent_list_entry,
+ const void *list_entry);
+int ripngd_instance_get_keys(const void *list_entry,
+ struct yang_list_keys *keys);
+const void *ripngd_instance_lookup_entry(const void *parent_list_entry,
+ const struct yang_list_keys *keys);
+int ripngd_instance_allow_ecmp_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_default_information_originate_modify(
+ enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_default_metric_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_network_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_network_destroy(enum nb_event event,
+ const struct lyd_node *dnode);
+int ripngd_instance_interface_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode);
+int ripngd_instance_offset_list_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_offset_list_destroy(enum nb_event event,
+ const struct lyd_node *dnode);
+int ripngd_instance_offset_list_access_list_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_offset_list_metric_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_passive_interface_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_passive_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode);
+int ripngd_instance_redistribute_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_redistribute_destroy(enum nb_event event,
+ const struct lyd_node *dnode);
+int ripngd_instance_redistribute_route_map_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_redistribute_route_map_destroy(
+ enum nb_event event, const struct lyd_node *dnode);
+int ripngd_instance_redistribute_metric_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_redistribute_metric_destroy(enum nb_event event,
+ const struct lyd_node *dnode);
+int ripngd_instance_static_route_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_static_route_destroy(enum nb_event event,
+ const struct lyd_node *dnode);
+int ripngd_instance_aggregate_address_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_aggregate_address_destroy(enum nb_event event,
+ const struct lyd_node *dnode);
+int ripngd_instance_timers_flush_interval_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_timers_holddown_interval_modify(
+ enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource);
+int ripngd_instance_timers_update_interval_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+const void *
+ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
+ const void *list_entry);
+int ripngd_instance_state_neighbors_neighbor_get_keys(
+ const void *list_entry, struct yang_list_keys *keys);
+const void *ripngd_instance_state_neighbors_neighbor_lookup_entry(
+ const void *parent_list_entry, const struct yang_list_keys *keys);
+struct yang_data *ripngd_instance_state_neighbors_neighbor_address_get_elem(
+ const char *xpath, const void *list_entry);
+struct yang_data *ripngd_instance_state_neighbors_neighbor_last_update_get_elem(
+ const char *xpath, const void *list_entry);
+struct yang_data *
+ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
+ const char *xpath, const void *list_entry);
+struct yang_data *
+ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
+ const char *xpath, const void *list_entry);
+const void *
+ripngd_instance_state_routes_route_get_next(const void *parent_list_entry,
+ const void *list_entry);
+int ripngd_instance_state_routes_route_get_keys(const void *list_entry,
+ struct yang_list_keys *keys);
+const void *ripngd_instance_state_routes_route_lookup_entry(
+ const void *parent_list_entry, const struct yang_list_keys *keys);
+struct yang_data *
+ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath,
+ const void *list_entry);
+struct yang_data *
+ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
+ const void *list_entry);
+struct yang_data *
+ripngd_instance_state_routes_route_interface_get_elem(const char *xpath,
+ const void *list_entry);
+struct yang_data *
+ripngd_instance_state_routes_route_metric_get_elem(const char *xpath,
+ const void *list_entry);
+int clear_ripng_route_rpc(const char *xpath, const struct list *input,
+ struct list *output);
+int lib_interface_ripng_split_horizon_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource);
+
+/* Optional 'apply_finish' callbacks. */
+void ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode);
+void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode);
+
+/* Optional 'cli_show' callbacks. */
+void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_allow_ecmp(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_default_information_originate(struct vty *vty,
+ struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_default_metric(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_network_prefix(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_passive_interface(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_redistribute(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_route(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_aggregate_address(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ripng_timers(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+
+#endif /* _FRR_RIPNG_NB_H_ */
diff --git a/ripngd/ripng_nb_config.c b/ripngd/ripng_nb_config.c
new file mode 100644
index 000000000..b39c1d443
--- /dev/null
+++ b/ripngd/ripng_nb_config.c
@@ -0,0 +1,714 @@
+/*
+ * Copyright (C) 1998 Kunihiro Ishiguro
+ * Copyright (C) 2018 NetDEF, Inc.
+ * Renato Westphal
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "if.h"
+#include "vrf.h"
+#include "log.h"
+#include "prefix.h"
+#include "table.h"
+#include "command.h"
+#include "routemap.h"
+#include "agg_table.h"
+#include "northbound.h"
+#include "libfrr.h"
+
+#include "ripngd/ripngd.h"
+#include "ripngd/ripng_nb.h"
+#include "ripngd/ripng_debug.h"
+#include "ripngd/ripng_route.h"
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance
+ */
+int ripngd_instance_create(enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ struct vrf *vrf;
+ const char *vrf_name;
+ int socket;
+
+ vrf_name = yang_dnode_get_string(dnode, "./vrf");
+ vrf = vrf_lookup_by_name(vrf_name);
+
+ /*
+ * Try to create a RIPng socket only if the VRF is enabled, otherwise
+ * create a disabled RIPng instance and wait for the VRF to be enabled.
+ */
+ switch (event) {
+ case NB_EV_VALIDATE:
+ break;
+ case NB_EV_PREPARE:
+ if (!vrf || !vrf_is_enabled(vrf))
+ break;
+
+ socket = ripng_make_socket(vrf);
+ if (socket < 0)
+ return NB_ERR_RESOURCE;
+ resource->fd = socket;
+ break;
+ case NB_EV_ABORT:
+ if (!vrf || !vrf_is_enabled(vrf))
+ break;
+
+ socket = resource->fd;
+ close(socket);
+ break;
+ case NB_EV_APPLY:
+ if (vrf && vrf_is_enabled(vrf))
+ socket = resource->fd;
+ else
+ socket = -1;
+
+ ripng = ripng_create(vrf_name, vrf, socket);
+ nb_running_set_entry(dnode, ripng);
+ break;
+ }
+
+ return NB_OK;
+}
+
+int ripngd_instance_destroy(enum nb_event event, const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_unset_entry(dnode);
+ ripng_clean(ripng);
+
+ return NB_OK;
+}
+
+const void *ripngd_instance_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ struct ripng *ripng = (struct ripng *)list_entry;
+
+ if (list_entry == NULL)
+ ripng = RB_MIN(ripng_instance_head, &ripng_instances);
+ else
+ ripng = RB_NEXT(ripng_instance_head, ripng);
+
+ return ripng;
+}
+
+int ripngd_instance_get_keys(const void *list_entry,
+ struct yang_list_keys *keys)
+{
+ const struct ripng *ripng = list_entry;
+
+ keys->num = 1;
+ strlcpy(keys->key[0], ripng->vrf_name, sizeof(keys->key[0]));
+
+ return NB_OK;
+}
+
+const void *ripngd_instance_lookup_entry(const void *parent_list_entry,
+ const struct yang_list_keys *keys)
+{
+ const char *vrf_name = keys->key[0];
+
+ return ripng_lookup_by_vrf_name(vrf_name);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
+ */
+int ripngd_instance_allow_ecmp_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
+ if (!ripng->ecmp)
+ ripng_ecmp_disable(ripng);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/default-information-originate
+ */
+int ripngd_instance_default_information_originate_modify(
+ enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ bool default_information;
+ struct prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ default_information = yang_dnode_get_bool(dnode, NULL);
+
+ str2prefix_ipv6("::/0", &p);
+ if (default_information) {
+ ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
+ RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
+ } else {
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
+ RIPNG_ROUTE_DEFAULT, &p, 0);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/default-metric
+ */
+int ripngd_instance_default_metric_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/network
+ */
+int ripngd_instance_network_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ struct prefix p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6((struct prefix_ipv6 *)&p);
+
+ return ripng_enable_network_add(ripng, &p);
+}
+
+int ripngd_instance_network_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ struct prefix p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6((struct prefix_ipv6 *)&p);
+
+ return ripng_enable_network_delete(ripng, &p);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/interface
+ */
+int ripngd_instance_interface_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ const char *ifname;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ifname = yang_dnode_get_string(dnode, NULL);
+
+ return ripng_enable_if_add(ripng, ifname);
+}
+
+int ripngd_instance_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ const char *ifname;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ifname = yang_dnode_get_string(dnode, NULL);
+
+ return ripng_enable_if_delete(ripng, ifname);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/offset-list
+ */
+int ripngd_instance_offset_list_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ const char *ifname;
+ struct ripng_offset_list *offset;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ifname = yang_dnode_get_string(dnode, "./interface");
+
+ offset = ripng_offset_list_new(ripng, ifname);
+ nb_running_set_entry(dnode, offset);
+
+ return NB_OK;
+}
+
+int ripngd_instance_offset_list_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ int direct;
+ struct ripng_offset_list *offset;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ direct = yang_dnode_get_enum(dnode, "./direction");
+
+ offset = nb_running_unset_entry(dnode);
+ if (offset->direct[direct].alist_name) {
+ free(offset->direct[direct].alist_name);
+ offset->direct[direct].alist_name = NULL;
+ }
+ if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
+ && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
+ ripng_offset_list_del(offset);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
+ */
+int ripngd_instance_offset_list_access_list_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ int direct;
+ struct ripng_offset_list *offset;
+ const char *alist_name;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ direct = yang_dnode_get_enum(dnode, "../direction");
+ alist_name = yang_dnode_get_string(dnode, NULL);
+
+ offset = nb_running_get_entry(dnode, NULL, true);
+ if (offset->direct[direct].alist_name)
+ free(offset->direct[direct].alist_name);
+ offset->direct[direct].alist_name = strdup(alist_name);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
+ */
+int ripngd_instance_offset_list_metric_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ int direct;
+ uint8_t metric;
+ struct ripng_offset_list *offset;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ direct = yang_dnode_get_enum(dnode, "../direction");
+ metric = yang_dnode_get_uint8(dnode, NULL);
+
+ offset = nb_running_get_entry(dnode, NULL, true);
+ offset->direct[direct].metric = metric;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/passive-interface
+ */
+int ripngd_instance_passive_interface_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ const char *ifname;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ifname = yang_dnode_get_string(dnode, NULL);
+
+ return ripng_passive_interface_set(ripng, ifname);
+}
+
+int ripngd_instance_passive_interface_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ const char *ifname;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ifname = yang_dnode_get_string(dnode, NULL);
+
+ return ripng_passive_interface_unset(ripng, ifname);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/redistribute
+ */
+int ripngd_instance_redistribute_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ int type;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ type = yang_dnode_get_enum(dnode, "./protocol");
+
+ ripng->redist[type].enabled = true;
+
+ return NB_OK;
+}
+
+int ripngd_instance_redistribute_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ int type;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ type = yang_dnode_get_enum(dnode, "./protocol");
+
+ ripng->redist[type].enabled = false;
+ if (ripng->redist[type].route_map.name) {
+ free(ripng->redist[type].route_map.name);
+ ripng->redist[type].route_map.name = NULL;
+ ripng->redist[type].route_map.map = NULL;
+ }
+ ripng->redist[type].metric_config = false;
+ ripng->redist[type].metric = 0;
+
+ if (ripng->enabled)
+ ripng_redistribute_conf_delete(ripng, type);
+
+ return NB_OK;
+}
+
+void ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ int type;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ type = yang_dnode_get_enum(dnode, "./protocol");
+
+ if (ripng->enabled)
+ ripng_redistribute_conf_update(ripng, type);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
+ */
+int ripngd_instance_redistribute_route_map_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ int type;
+ const char *rmap_name;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ type = yang_dnode_get_enum(dnode, "../protocol");
+ rmap_name = yang_dnode_get_string(dnode, NULL);
+
+ if (ripng->redist[type].route_map.name)
+ free(ripng->redist[type].route_map.name);
+ ripng->redist[type].route_map.name = strdup(rmap_name);
+ ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
+
+ return NB_OK;
+}
+
+int ripngd_instance_redistribute_route_map_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ int type;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ type = yang_dnode_get_enum(dnode, "../protocol");
+
+ free(ripng->redist[type].route_map.name);
+ ripng->redist[type].route_map.name = NULL;
+ ripng->redist[type].route_map.map = NULL;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
+ */
+int ripngd_instance_redistribute_metric_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ int type;
+ uint8_t metric;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ type = yang_dnode_get_enum(dnode, "../protocol");
+ metric = yang_dnode_get_uint8(dnode, NULL);
+
+ ripng->redist[type].metric_config = true;
+ ripng->redist[type].metric = metric;
+
+ return NB_OK;
+}
+
+int ripngd_instance_redistribute_metric_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ int type;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ type = yang_dnode_get_enum(dnode, "../protocol");
+
+ ripng->redist[type].metric_config = false;
+ ripng->redist[type].metric = 0;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/static-route
+ */
+int ripngd_instance_static_route_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ struct prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6(&p);
+
+ ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
+ 0, NULL, 0);
+
+ return NB_OK;
+}
+
+int ripngd_instance_static_route_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ struct prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6(&p);
+
+ ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
+ &p, 0);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/aggregate-address
+ */
+int ripngd_instance_aggregate_address_create(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+ struct prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6(&p);
+
+ ripng_aggregate_add(ripng, (struct prefix *)&p);
+
+ return NB_OK;
+}
+
+int ripngd_instance_aggregate_address_destroy(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+ struct prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6(&p);
+
+ ripng_aggregate_delete(ripng, (struct prefix *)&p);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/timers
+ */
+void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
+{
+ struct ripng *ripng;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+
+ /* Reset update timer thread. */
+ ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
+ */
+int ripngd_instance_timers_flush_interval_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
+ */
+int ripngd_instance_timers_holddown_interval_modify(
+ enum nb_event event, const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
+ */
+int ripngd_instance_timers_update_interval_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct ripng *ripng;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng = nb_running_get_entry(dnode, NULL, true);
+ ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
+ */
+int lib_interface_ripng_split_horizon_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(dnode, NULL, true);
+ ri = ifp->info;
+ ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
+
+ return NB_OK;
+}
diff --git a/ripngd/ripng_nb_rpcs.c b/ripngd/ripng_nb_rpcs.c
new file mode 100644
index 000000000..0396daf89
--- /dev/null
+++ b/ripngd/ripng_nb_rpcs.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 NetDEF, Inc.
+ * Renato Westphal
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "if.h"
+#include "vrf.h"
+#include "log.h"
+#include "prefix.h"
+#include "table.h"
+#include "command.h"
+#include "routemap.h"
+#include "agg_table.h"
+#include "northbound.h"
+#include "libfrr.h"
+
+#include "ripngd/ripngd.h"
+#include "ripngd/ripng_nb.h"
+#include "ripngd/ripng_debug.h"
+#include "ripngd/ripng_route.h"
+
+/*
+ * XPath: /frr-ripngd:clear-ripng-route
+ */
+static void clear_ripng_route(struct ripng *ripng)
+{
+ struct agg_node *rp;
+
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_debug("Clearing all RIPng routes (VRF %s)",
+ ripng->vrf_name);
+
+ /* Clear received RIPng routes */
+ for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
+ struct list *list;
+ struct listnode *listnode;
+ struct ripng_info *rinfo;
+
+ list = rp->info;
+ if (list == NULL)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
+ if (!ripng_route_rte(rinfo))
+ continue;
+
+ if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
+ ripng_zebra_ipv6_delete(ripng, rp);
+ break;
+ }
+
+ if (rinfo) {
+ RIPNG_TIMER_OFF(rinfo->t_timeout);
+ RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
+ listnode_delete(list, rinfo);
+ ripng_info_free(rinfo);
+ }
+
+ if (list_isempty(list)) {
+ list_delete(&list);
+ rp->info = NULL;
+ agg_unlock_node(rp);
+ }
+ }
+}
+
+int clear_ripng_route_rpc(const char *xpath, const struct list *input,
+ struct list *output)
+{
+ struct ripng *ripng;
+ struct yang_data *yang_vrf;
+
+ yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf");
+ if (yang_vrf) {
+ ripng = ripng_lookup_by_vrf_name(yang_vrf->value);
+ if (ripng)
+ clear_ripng_route(ripng);
+ } else {
+ struct vrf *vrf;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ ripng = vrf->info;
+ if (!ripng)
+ continue;
+
+ clear_ripng_route(ripng);
+ }
+ }
+
+ return NB_OK;
+}
diff --git a/ripngd/ripng_nb_state.c b/ripngd/ripng_nb_state.c
new file mode 100644
index 000000000..167077ea2
--- /dev/null
+++ b/ripngd/ripng_nb_state.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2018 NetDEF, Inc.
+ * Renato Westphal
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "if.h"
+#include "vrf.h"
+#include "log.h"
+#include "prefix.h"
+#include "table.h"
+#include "command.h"
+#include "routemap.h"
+#include "agg_table.h"
+#include "northbound.h"
+#include "libfrr.h"
+
+#include "ripngd/ripngd.h"
+#include "ripngd/ripng_nb.h"
+#include "ripngd/ripng_debug.h"
+#include "ripngd/ripng_route.h"
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor
+ */
+const void *
+ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ const struct ripng *ripng = parent_list_entry;
+ struct listnode *node;
+
+ if (list_entry == NULL)
+ node = listhead(ripng->peer_list);
+ else
+ node = listnextnode((struct listnode *)list_entry);
+
+ return node;
+}
+
+int ripngd_instance_state_neighbors_neighbor_get_keys(
+ const void *list_entry, struct yang_list_keys *keys)
+{
+ const struct listnode *node = list_entry;
+ const struct ripng_peer *peer = listgetdata(node);
+
+ keys->num = 1;
+ (void)inet_ntop(AF_INET6, &peer->addr, keys->key[0],
+ sizeof(keys->key[0]));
+
+ return NB_OK;
+}
+
+const void *ripngd_instance_state_neighbors_neighbor_lookup_entry(
+ const void *parent_list_entry, const struct yang_list_keys *keys)
+{
+ const struct ripng *ripng = parent_list_entry;
+ struct in6_addr address;
+ struct ripng_peer *peer;
+ struct listnode *node;
+
+ yang_str2ipv6(keys->key[0], &address);
+
+ for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) {
+ if (IPV6_ADDR_SAME(&peer->addr, &address))
+ return node;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address
+ */
+struct yang_data *ripngd_instance_state_neighbors_neighbor_address_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct listnode *node = list_entry;
+ const struct ripng_peer *peer = listgetdata(node);
+
+ return yang_data_new_ipv6(xpath, &peer->addr);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update
+ */
+struct yang_data *ripngd_instance_state_neighbors_neighbor_last_update_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ /* TODO: yang:date-and-time is tricky */
+ return NULL;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd
+ */
+struct yang_data *
+ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct listnode *node = list_entry;
+ const struct ripng_peer *peer = listgetdata(node);
+
+ return yang_data_new_uint32(xpath, peer->recv_badpackets);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd
+ */
+struct yang_data *
+ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct listnode *node = list_entry;
+ const struct ripng_peer *peer = listgetdata(node);
+
+ return yang_data_new_uint32(xpath, peer->recv_badroutes);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/routes/route
+ */
+const void *
+ripngd_instance_state_routes_route_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ const struct ripng *ripng = parent_list_entry;
+ struct agg_node *rn;
+
+ if (list_entry == NULL)
+ rn = agg_route_top(ripng->table);
+ else
+ rn = agg_route_next((struct agg_node *)list_entry);
+ while (rn && rn->info == NULL)
+ rn = agg_route_next(rn);
+
+ return rn;
+}
+
+int ripngd_instance_state_routes_route_get_keys(const void *list_entry,
+ struct yang_list_keys *keys)
+{
+ const struct agg_node *rn = list_entry;
+
+ keys->num = 1;
+ (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0]));
+
+ return NB_OK;
+}
+
+const void *ripngd_instance_state_routes_route_lookup_entry(
+ const void *parent_list_entry, const struct yang_list_keys *keys)
+{
+ const struct ripng *ripng = parent_list_entry;
+ struct prefix prefix;
+ struct agg_node *rn;
+
+ yang_str2ipv6p(keys->key[0], &prefix);
+
+ rn = agg_node_lookup(ripng->table, &prefix);
+ if (!rn || !rn->info)
+ return NULL;
+
+ agg_unlock_node(rn);
+
+ return rn;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix
+ */
+struct yang_data *
+ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath,
+ const void *list_entry)
+{
+ const struct agg_node *rn = list_entry;
+ const struct ripng_info *rinfo = listnode_head(rn->info);
+
+ return yang_data_new_ipv6p(xpath, &rinfo->rp->p);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop
+ */
+struct yang_data *
+ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
+ const void *list_entry)
+{
+ const struct agg_node *rn = list_entry;
+ const struct ripng_info *rinfo = listnode_head(rn->info);
+
+ return yang_data_new_ipv6(xpath, &rinfo->nexthop);
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface
+ */
+struct yang_data *
+ripngd_instance_state_routes_route_interface_get_elem(const char *xpath,
+ const void *list_entry)
+{
+ const struct agg_node *rn = list_entry;
+ const struct ripng_info *rinfo = listnode_head(rn->info);
+ const struct ripng *ripng = ripng_info_get_instance(rinfo);
+
+ return yang_data_new_string(
+ xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id));
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric
+ */
+struct yang_data *
+ripngd_instance_state_routes_route_metric_get_elem(const char *xpath,
+ const void *list_entry)
+{
+ const struct agg_node *rn = list_entry;
+ const struct ripng_info *rinfo = listnode_head(rn->info);
+
+ return yang_data_new_uint8(xpath, rinfo->metric);
+}
diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c
deleted file mode 100644
index 588f6db03..000000000
--- a/ripngd/ripng_northbound.c
+++ /dev/null
@@ -1,1234 +0,0 @@
-/*
- * Copyright (C) 1998 Kunihiro Ishiguro
- * Copyright (C) 2018 NetDEF, Inc.
- * Renato Westphal
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-
-#include "if.h"
-#include "vrf.h"
-#include "log.h"
-#include "prefix.h"
-#include "table.h"
-#include "command.h"
-#include "routemap.h"
-#include "agg_table.h"
-#include "northbound.h"
-#include "libfrr.h"
-
-#include "ripngd/ripngd.h"
-#include "ripngd/ripng_debug.h"
-#include "ripngd/ripng_route.h"
-#include "ripngd/ripng_cli.h"
-
-/*
- * XPath: /frr-ripngd:ripngd/instance
- */
-static int ripngd_instance_create(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- struct vrf *vrf;
- const char *vrf_name;
- int socket;
-
- vrf_name = yang_dnode_get_string(dnode, "./vrf");
- vrf = vrf_lookup_by_name(vrf_name);
-
- /*
- * Try to create a RIPng socket only if the VRF is enabled, otherwise
- * create a disabled RIPng instance and wait for the VRF to be enabled.
- */
- switch (event) {
- case NB_EV_VALIDATE:
- break;
- case NB_EV_PREPARE:
- if (!vrf || !vrf_is_enabled(vrf))
- break;
-
- socket = ripng_make_socket(vrf);
- if (socket < 0)
- return NB_ERR_RESOURCE;
- resource->fd = socket;
- break;
- case NB_EV_ABORT:
- if (!vrf || !vrf_is_enabled(vrf))
- break;
-
- socket = resource->fd;
- close(socket);
- break;
- case NB_EV_APPLY:
- if (vrf && vrf_is_enabled(vrf))
- socket = resource->fd;
- else
- socket = -1;
-
- ripng = ripng_create(vrf_name, vrf, socket);
- nb_running_set_entry(dnode, ripng);
- break;
- }
-
- return NB_OK;
-}
-
-static int ripngd_instance_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_unset_entry(dnode);
- ripng_clean(ripng);
-
- return NB_OK;
-}
-
-static const void *ripngd_instance_get_next(const void *parent_list_entry,
- const void *list_entry)
-{
- struct ripng *ripng = (struct ripng *)list_entry;
-
- if (list_entry == NULL)
- ripng = RB_MIN(ripng_instance_head, &ripng_instances);
- else
- ripng = RB_NEXT(ripng_instance_head, ripng);
-
- return ripng;
-}
-
-static int ripngd_instance_get_keys(const void *list_entry,
- struct yang_list_keys *keys)
-{
- const struct ripng *ripng = list_entry;
-
- keys->num = 1;
- strlcpy(keys->key[0], ripng->vrf_name, sizeof(keys->key[0]));
-
- return NB_OK;
-}
-
-static const void *
-ripngd_instance_lookup_entry(const void *parent_list_entry,
- const struct yang_list_keys *keys)
-{
- const char *vrf_name = keys->key[0];
-
- return ripng_lookup_by_vrf_name(vrf_name);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
- */
-static int ripngd_instance_allow_ecmp_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
- if (!ripng->ecmp)
- ripng_ecmp_disable(ripng);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/default-information-originate
- */
-static int ripngd_instance_default_information_originate_modify(
- enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- bool default_information;
- struct prefix_ipv6 p;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- default_information = yang_dnode_get_bool(dnode, NULL);
-
- str2prefix_ipv6("::/0", &p);
- if (default_information) {
- ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
- RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
- } else {
- ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
- RIPNG_ROUTE_DEFAULT, &p, 0);
- }
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/default-metric
- */
-static int ripngd_instance_default_metric_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ripng->default_metric = yang_dnode_get_uint8(dnode, NULL);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/network
- */
-static int ripngd_instance_network_create(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- struct prefix p;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- yang_dnode_get_ipv6p(&p, dnode, NULL);
- apply_mask_ipv6((struct prefix_ipv6 *)&p);
-
- return ripng_enable_network_add(ripng, &p);
-}
-
-static int ripngd_instance_network_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- struct prefix p;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- yang_dnode_get_ipv6p(&p, dnode, NULL);
- apply_mask_ipv6((struct prefix_ipv6 *)&p);
-
- return ripng_enable_network_delete(ripng, &p);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/interface
- */
-static int ripngd_instance_interface_create(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- const char *ifname;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ifname = yang_dnode_get_string(dnode, NULL);
-
- return ripng_enable_if_add(ripng, ifname);
-}
-
-static int ripngd_instance_interface_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- const char *ifname;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ifname = yang_dnode_get_string(dnode, NULL);
-
- return ripng_enable_if_delete(ripng, ifname);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/offset-list
- */
-static int ripngd_instance_offset_list_create(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- const char *ifname;
- struct ripng_offset_list *offset;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ifname = yang_dnode_get_string(dnode, "./interface");
-
- offset = ripng_offset_list_new(ripng, ifname);
- nb_running_set_entry(dnode, offset);
-
- return NB_OK;
-}
-
-static int ripngd_instance_offset_list_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- int direct;
- struct ripng_offset_list *offset;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- direct = yang_dnode_get_enum(dnode, "./direction");
-
- offset = nb_running_unset_entry(dnode);
- if (offset->direct[direct].alist_name) {
- free(offset->direct[direct].alist_name);
- offset->direct[direct].alist_name = NULL;
- }
- if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
- && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
- ripng_offset_list_del(offset);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
- */
-static int
-ripngd_instance_offset_list_access_list_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- int direct;
- struct ripng_offset_list *offset;
- const char *alist_name;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- direct = yang_dnode_get_enum(dnode, "../direction");
- alist_name = yang_dnode_get_string(dnode, NULL);
-
- offset = nb_running_get_entry(dnode, NULL, true);
- if (offset->direct[direct].alist_name)
- free(offset->direct[direct].alist_name);
- offset->direct[direct].alist_name = strdup(alist_name);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
- */
-static int
-ripngd_instance_offset_list_metric_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- int direct;
- uint8_t metric;
- struct ripng_offset_list *offset;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- direct = yang_dnode_get_enum(dnode, "../direction");
- metric = yang_dnode_get_uint8(dnode, NULL);
-
- offset = nb_running_get_entry(dnode, NULL, true);
- offset->direct[direct].metric = metric;
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/passive-interface
- */
-static int
-ripngd_instance_passive_interface_create(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- const char *ifname;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ifname = yang_dnode_get_string(dnode, NULL);
-
- return ripng_passive_interface_set(ripng, ifname);
-}
-
-static int
-ripngd_instance_passive_interface_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- const char *ifname;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ifname = yang_dnode_get_string(dnode, NULL);
-
- return ripng_passive_interface_unset(ripng, ifname);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/redistribute
- */
-static int ripngd_instance_redistribute_create(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- int type;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- type = yang_dnode_get_enum(dnode, "./protocol");
-
- ripng->redist[type].enabled = true;
-
- return NB_OK;
-}
-
-static int ripngd_instance_redistribute_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- int type;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- type = yang_dnode_get_enum(dnode, "./protocol");
-
- ripng->redist[type].enabled = false;
- if (ripng->redist[type].route_map.name) {
- free(ripng->redist[type].route_map.name);
- ripng->redist[type].route_map.name = NULL;
- ripng->redist[type].route_map.map = NULL;
- }
- ripng->redist[type].metric_config = false;
- ripng->redist[type].metric = 0;
-
- if (ripng->enabled)
- ripng_redistribute_conf_delete(ripng, type);
-
- return NB_OK;
-}
-
-static void
-ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- int type;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- type = yang_dnode_get_enum(dnode, "./protocol");
-
- if (ripng->enabled)
- ripng_redistribute_conf_update(ripng, type);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
- */
-static int
-ripngd_instance_redistribute_route_map_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- int type;
- const char *rmap_name;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- type = yang_dnode_get_enum(dnode, "../protocol");
- rmap_name = yang_dnode_get_string(dnode, NULL);
-
- if (ripng->redist[type].route_map.name)
- free(ripng->redist[type].route_map.name);
- ripng->redist[type].route_map.name = strdup(rmap_name);
- ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
-
- return NB_OK;
-}
-
-static int
-ripngd_instance_redistribute_route_map_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- int type;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- type = yang_dnode_get_enum(dnode, "../protocol");
-
- free(ripng->redist[type].route_map.name);
- ripng->redist[type].route_map.name = NULL;
- ripng->redist[type].route_map.map = NULL;
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
- */
-static int
-ripngd_instance_redistribute_metric_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- int type;
- uint8_t metric;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- type = yang_dnode_get_enum(dnode, "../protocol");
- metric = yang_dnode_get_uint8(dnode, NULL);
-
- ripng->redist[type].metric_config = true;
- ripng->redist[type].metric = metric;
-
- return NB_OK;
-}
-
-static int
-ripngd_instance_redistribute_metric_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- int type;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- type = yang_dnode_get_enum(dnode, "../protocol");
-
- ripng->redist[type].metric_config = false;
- ripng->redist[type].metric = 0;
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/static-route
- */
-static int ripngd_instance_static_route_create(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- struct prefix_ipv6 p;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- yang_dnode_get_ipv6p(&p, dnode, NULL);
- apply_mask_ipv6(&p);
-
- ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
- 0, NULL, 0);
-
- return NB_OK;
-}
-
-static int ripngd_instance_static_route_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- struct prefix_ipv6 p;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- yang_dnode_get_ipv6p(&p, dnode, NULL);
- apply_mask_ipv6(&p);
-
- ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
- &p, 0);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/aggregate-address
- */
-static int
-ripngd_instance_aggregate_address_create(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
- struct prefix_ipv6 p;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- yang_dnode_get_ipv6p(&p, dnode, NULL);
- apply_mask_ipv6(&p);
-
- ripng_aggregate_add(ripng, (struct prefix *)&p);
-
- return NB_OK;
-}
-
-static int
-ripngd_instance_aggregate_address_destroy(enum nb_event event,
- const struct lyd_node *dnode)
-{
- struct ripng *ripng;
- struct prefix_ipv6 p;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- yang_dnode_get_ipv6p(&p, dnode, NULL);
- apply_mask_ipv6(&p);
-
- ripng_aggregate_delete(ripng, (struct prefix *)&p);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/timers
- */
-static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
-{
- struct ripng *ripng;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
-
- /* Reset update timer thread. */
- ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
- */
-static int
-ripngd_instance_timers_flush_interval_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ripng->garbage_time = yang_dnode_get_uint16(dnode, NULL);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
- */
-static int
-ripngd_instance_timers_holddown_interval_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ripng->timeout_time = yang_dnode_get_uint16(dnode, NULL);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
- */
-static int
-ripngd_instance_timers_update_interval_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct ripng *ripng;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ripng = nb_running_get_entry(dnode, NULL, true);
- ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor
- */
-static const void *
-ripngd_instance_state_neighbors_neighbor_get_next(const void *parent_list_entry,
- const void *list_entry)
-{
- const struct ripng *ripng = parent_list_entry;
- struct listnode *node;
-
- if (list_entry == NULL)
- node = listhead(ripng->peer_list);
- else
- node = listnextnode((struct listnode *)list_entry);
-
- return node;
-}
-
-static int
-ripngd_instance_state_neighbors_neighbor_get_keys(const void *list_entry,
- struct yang_list_keys *keys)
-{
- const struct listnode *node = list_entry;
- const struct ripng_peer *peer = listgetdata(node);
-
- keys->num = 1;
- (void)inet_ntop(AF_INET6, &peer->addr, keys->key[0],
- sizeof(keys->key[0]));
-
- return NB_OK;
-}
-
-static const void *ripngd_instance_state_neighbors_neighbor_lookup_entry(
- const void *parent_list_entry, const struct yang_list_keys *keys)
-{
- const struct ripng *ripng = parent_list_entry;
- struct in6_addr address;
- struct ripng_peer *peer;
- struct listnode *node;
-
- yang_str2ipv6(keys->key[0], &address);
-
- for (ALL_LIST_ELEMENTS_RO(ripng->peer_list, node, peer)) {
- if (IPV6_ADDR_SAME(&peer->addr, &address))
- return node;
- }
-
- return NULL;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/address
- */
-static struct yang_data *
-ripngd_instance_state_neighbors_neighbor_address_get_elem(
- const char *xpath, const void *list_entry)
-{
- const struct listnode *node = list_entry;
- const struct ripng_peer *peer = listgetdata(node);
-
- return yang_data_new_ipv6(xpath, &peer->addr);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update
- */
-static struct yang_data *
-ripngd_instance_state_neighbors_neighbor_last_update_get_elem(
- const char *xpath, const void *list_entry)
-{
- /* TODO: yang:date-and-time is tricky */
- return NULL;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd
- */
-static struct yang_data *
-ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem(
- const char *xpath, const void *list_entry)
-{
- const struct listnode *node = list_entry;
- const struct ripng_peer *peer = listgetdata(node);
-
- return yang_data_new_uint32(xpath, peer->recv_badpackets);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd
- */
-static struct yang_data *
-ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem(
- const char *xpath, const void *list_entry)
-{
- const struct listnode *node = list_entry;
- const struct ripng_peer *peer = listgetdata(node);
-
- return yang_data_new_uint32(xpath, peer->recv_badroutes);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/routes/route
- */
-static const void *
-ripngd_instance_state_routes_route_get_next(const void *parent_list_entry,
- const void *list_entry)
-{
- const struct ripng *ripng = parent_list_entry;
- struct agg_node *rn;
-
- if (list_entry == NULL)
- rn = agg_route_top(ripng->table);
- else
- rn = agg_route_next((struct agg_node *)list_entry);
- while (rn && rn->info == NULL)
- rn = agg_route_next(rn);
-
- return rn;
-}
-
-static int
-ripngd_instance_state_routes_route_get_keys(const void *list_entry,
- struct yang_list_keys *keys)
-{
- const struct agg_node *rn = list_entry;
-
- keys->num = 1;
- (void)prefix2str(&rn->p, keys->key[0], sizeof(keys->key[0]));
-
- return NB_OK;
-}
-
-static const void *ripngd_instance_state_routes_route_lookup_entry(
- const void *parent_list_entry, const struct yang_list_keys *keys)
-{
- const struct ripng *ripng = parent_list_entry;
- struct prefix prefix;
- struct agg_node *rn;
-
- yang_str2ipv6p(keys->key[0], &prefix);
-
- rn = agg_node_lookup(ripng->table, &prefix);
- if (!rn || !rn->info)
- return NULL;
-
- agg_unlock_node(rn);
-
- return rn;
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/routes/route/prefix
- */
-static struct yang_data *
-ripngd_instance_state_routes_route_prefix_get_elem(const char *xpath,
- const void *list_entry)
-{
- const struct agg_node *rn = list_entry;
- const struct ripng_info *rinfo = listnode_head(rn->info);
-
- return yang_data_new_ipv6p(xpath, &rinfo->rp->p);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/routes/route/next-hop
- */
-static struct yang_data *
-ripngd_instance_state_routes_route_next_hop_get_elem(const char *xpath,
- const void *list_entry)
-{
- const struct agg_node *rn = list_entry;
- const struct ripng_info *rinfo = listnode_head(rn->info);
-
- return yang_data_new_ipv6(xpath, &rinfo->nexthop);
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/routes/route/interface
- */
-static struct yang_data *
-ripngd_instance_state_routes_route_interface_get_elem(const char *xpath,
- const void *list_entry)
-{
- const struct agg_node *rn = list_entry;
- const struct ripng_info *rinfo = listnode_head(rn->info);
- const struct ripng *ripng = ripng_info_get_instance(rinfo);
-
- return yang_data_new_string(
- xpath, ifindex2ifname(rinfo->ifindex, ripng->vrf->vrf_id));
-}
-
-/*
- * XPath: /frr-ripngd:ripngd/instance/state/routes/route/metric
- */
-static struct yang_data *
-ripngd_instance_state_routes_route_metric_get_elem(const char *xpath,
- const void *list_entry)
-{
- const struct agg_node *rn = list_entry;
- const struct ripng_info *rinfo = listnode_head(rn->info);
-
- return yang_data_new_uint8(xpath, rinfo->metric);
-}
-
-/*
- * XPath: /frr-ripngd:clear-ripng-route
- */
-static void clear_ripng_route(struct ripng *ripng)
-{
- struct agg_node *rp;
-
- if (IS_RIPNG_DEBUG_EVENT)
- zlog_debug("Clearing all RIPng routes (VRF %s)",
- ripng->vrf_name);
-
- /* Clear received RIPng routes */
- for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
- struct list *list;
- struct listnode *listnode;
- struct ripng_info *rinfo;
-
- list = rp->info;
- if (list == NULL)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
- if (!ripng_route_rte(rinfo))
- continue;
-
- if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
- ripng_zebra_ipv6_delete(ripng, rp);
- break;
- }
-
- if (rinfo) {
- RIPNG_TIMER_OFF(rinfo->t_timeout);
- RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
- listnode_delete(list, rinfo);
- ripng_info_free(rinfo);
- }
-
- if (list_isempty(list)) {
- list_delete(&list);
- rp->info = NULL;
- agg_unlock_node(rp);
- }
- }
-}
-
-static int clear_ripng_route_rpc(const char *xpath, const struct list *input,
- struct list *output)
-{
- struct ripng *ripng;
- struct yang_data *yang_vrf;
-
- yang_vrf = yang_data_list_find(input, "%s/%s", xpath, "input/vrf");
- if (yang_vrf) {
- ripng = ripng_lookup_by_vrf_name(yang_vrf->value);
- if (ripng)
- clear_ripng_route(ripng);
- } else {
- struct vrf *vrf;
-
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- ripng = vrf->info;
- if (!ripng)
- continue;
-
- clear_ripng_route(ripng);
- }
- }
-
- return NB_OK;
-}
-
-/*
- * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
- */
-static int
-lib_interface_ripng_split_horizon_modify(enum nb_event event,
- const struct lyd_node *dnode,
- union nb_resource *resource)
-{
- struct interface *ifp;
- struct ripng_interface *ri;
-
- if (event != NB_EV_APPLY)
- return NB_OK;
-
- ifp = nb_running_get_entry(dnode, NULL, true);
- ri = ifp->info;
- ri->split_horizon = yang_dnode_get_enum(dnode, NULL);
-
- return NB_OK;
-}
-
-/* clang-format off */
-const struct frr_yang_module_info frr_ripngd_info = {
- .name = "frr-ripngd",
- .nodes = {
- {
- .xpath = "/frr-ripngd:ripngd/instance",
- .cbs = {
- .cli_show = cli_show_router_ripng,
- .create = ripngd_instance_create,
- .destroy = ripngd_instance_destroy,
- .get_keys = ripngd_instance_get_keys,
- .get_next = ripngd_instance_get_next,
- .lookup_entry = ripngd_instance_lookup_entry,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
- .cbs = {
- .cli_show = cli_show_ripng_allow_ecmp,
- .modify = ripngd_instance_allow_ecmp_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
- .cbs = {
- .cli_show = cli_show_ripng_default_information_originate,
- .modify = ripngd_instance_default_information_originate_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/default-metric",
- .cbs = {
- .cli_show = cli_show_ripng_default_metric,
- .modify = ripngd_instance_default_metric_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/network",
- .cbs = {
- .cli_show = cli_show_ripng_network_prefix,
- .create = ripngd_instance_network_create,
- .destroy = ripngd_instance_network_destroy,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/interface",
- .cbs = {
- .cli_show = cli_show_ripng_network_interface,
- .create = ripngd_instance_interface_create,
- .destroy = ripngd_instance_interface_destroy,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/offset-list",
- .cbs = {
- .cli_show = cli_show_ripng_offset_list,
- .create = ripngd_instance_offset_list_create,
- .destroy = ripngd_instance_offset_list_destroy,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list",
- .cbs = {
- .modify = ripngd_instance_offset_list_access_list_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/offset-list/metric",
- .cbs = {
- .modify = ripngd_instance_offset_list_metric_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/passive-interface",
- .cbs = {
- .cli_show = cli_show_ripng_passive_interface,
- .create = ripngd_instance_passive_interface_create,
- .destroy = ripngd_instance_passive_interface_destroy,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/redistribute",
- .cbs = {
- .apply_finish = ripngd_instance_redistribute_apply_finish,
- .cli_show = cli_show_ripng_redistribute,
- .create = ripngd_instance_redistribute_create,
- .destroy = ripngd_instance_redistribute_destroy,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
- .cbs = {
- .destroy = ripngd_instance_redistribute_route_map_destroy,
- .modify = ripngd_instance_redistribute_route_map_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
- .cbs = {
- .destroy = ripngd_instance_redistribute_metric_destroy,
- .modify = ripngd_instance_redistribute_metric_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/static-route",
- .cbs = {
- .cli_show = cli_show_ripng_route,
- .create = ripngd_instance_static_route_create,
- .destroy = ripngd_instance_static_route_destroy,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
- .cbs = {
- .cli_show = cli_show_ripng_aggregate_address,
- .create = ripngd_instance_aggregate_address_create,
- .destroy = ripngd_instance_aggregate_address_destroy,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/timers",
- .cbs = {
- .apply_finish = ripngd_instance_timers_apply_finish,
- .cli_show = cli_show_ripng_timers,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/timers/flush-interval",
- .cbs = {
- .modify = ripngd_instance_timers_flush_interval_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/timers/holddown-interval",
- .cbs = {
- .modify = ripngd_instance_timers_holddown_interval_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/timers/update-interval",
- .cbs = {
- .modify = ripngd_instance_timers_update_interval_modify,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor",
- .cbs = {
- .get_keys = ripngd_instance_state_neighbors_neighbor_get_keys,
- .get_next = ripngd_instance_state_neighbors_neighbor_get_next,
- .lookup_entry = ripngd_instance_state_neighbors_neighbor_lookup_entry,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/address",
- .cbs = {
- .get_elem = ripngd_instance_state_neighbors_neighbor_address_get_elem,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/last-update",
- .cbs = {
- .get_elem = ripngd_instance_state_neighbors_neighbor_last_update_get_elem,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-packets-rcvd",
- .cbs = {
- .get_elem = ripngd_instance_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/neighbors/neighbor/bad-routes-rcvd",
- .cbs = {
- .get_elem = ripngd_instance_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/routes/route",
- .cbs = {
- .get_keys = ripngd_instance_state_routes_route_get_keys,
- .get_next = ripngd_instance_state_routes_route_get_next,
- .lookup_entry = ripngd_instance_state_routes_route_lookup_entry,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/prefix",
- .cbs = {
- .get_elem = ripngd_instance_state_routes_route_prefix_get_elem,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/next-hop",
- .cbs = {
- .get_elem = ripngd_instance_state_routes_route_next_hop_get_elem,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/interface",
- .cbs = {
- .get_elem = ripngd_instance_state_routes_route_interface_get_elem,
- },
- },
- {
- .xpath = "/frr-ripngd:ripngd/instance/state/routes/route/metric",
- .cbs = {
- .get_elem = ripngd_instance_state_routes_route_metric_get_elem,
- },
- },
- {
- .xpath = "/frr-ripngd:clear-ripng-route",
- .cbs = {
- .rpc = clear_ripng_route_rpc,
- },
- },
- {
- .xpath = "/frr-interface:lib/interface/frr-ripngd:ripng/split-horizon",
- .cbs = {
- .cli_show = cli_show_ipv6_ripng_split_horizon,
- .modify = lib_interface_ripng_split_horizon_modify,
- },
- },
- {
- .xpath = NULL,
- },
- }
-};
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 5a0d350a8..70508d5cb 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -494,9 +494,6 @@ extern struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
extern void ripng_vrf_init(void);
extern void ripng_vrf_terminate(void);
-
-/* Northbound. */
extern void ripng_cli_init(void);
-extern const struct frr_yang_module_info frr_ripngd_info;
#endif /* _ZEBRA_RIPNG_RIPNGD_H */
diff --git a/ripngd/subdir.am b/ripngd/subdir.am
index eac0d6731..07d0cb892 100644
--- a/ripngd/subdir.am
+++ b/ripngd/subdir.am
@@ -19,7 +19,10 @@ ripngd_libripng_a_SOURCES = \
ripngd/ripng_interface.c \
ripngd/ripng_nexthop.c \
ripngd/ripng_offset.c \
- ripngd/ripng_northbound.c \
+ ripngd/ripng_nb.c \
+ ripngd/ripng_nb_config.c \
+ ripngd/ripng_nb_rpcs.c \
+ ripngd/ripng_nb_state.c \
ripngd/ripng_peer.c \
ripngd/ripng_route.c \
ripngd/ripng_routemap.c \
@@ -31,8 +34,8 @@ ripngd/ripng_cli_clippy.c: $(CLIPPY_DEPS)
ripngd/ripng_cli.$(OBJEXT): ripngd/ripng_cli_clippy.c
noinst_HEADERS += \
- ripngd/ripng_cli.h \
ripngd/ripng_debug.h \
+ ripngd/ripng_nb.h \
ripngd/ripng_nexthop.h \
ripngd/ripng_route.h \
ripngd/ripngd.h \