summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md9
-rw-r--r--bgpd/bgp_rpki.c3
-rw-r--r--bgpd/bgp_snmp.c4
-rw-r--r--fpm/subdir.am4
-rw-r--r--lib/northbound.c2
-rw-r--r--lib/yang.c1
-rw-r--r--lib/zebra.h49
-rw-r--r--ripd/rip_cli.c3
-rw-r--r--ripd/rip_debug.c7
-rw-r--r--ripd/rip_debug.h1
-rw-r--r--ripd/rip_interface.c9
-rw-r--r--ripd/rip_northbound.c12
-rw-r--r--ripd/rip_routemap.c5
-rw-r--r--ripd/rip_zebra.c5
-rw-r--r--ripd/ripd.h3
-rw-r--r--ripd/subdir.am3
-rw-r--r--ripngd/ripng_cli.c489
-rw-r--r--ripngd/ripng_cli.h58
-rw-r--r--ripngd/ripng_debug.c7
-rw-r--r--ripngd/ripng_debug.h1
-rw-r--r--ripngd/ripng_interface.c267
-rw-r--r--ripngd/ripng_main.c6
-rw-r--r--ripngd/ripng_northbound.c1001
-rw-r--r--ripngd/ripng_offset.c292
-rw-r--r--ripngd/ripng_routemap.c6
-rw-r--r--ripngd/ripng_zebra.c252
-rw-r--r--ripngd/ripngd.c530
-rw-r--r--ripngd/ripngd.h81
-rw-r--r--ripngd/subdir.am13
-rw-r--r--yang/confd/confd.frr-ripngd.yang22
-rw-r--r--yang/frr-ripngd.yang321
-rw-r--r--yang/subdir.am4
-rw-r--r--zebra/kernel_socket.c188
-rw-r--r--zebra/rib.h2
-rw-r--r--zebra/rt_netlink.c16
-rw-r--r--zebra/zebra_rib.c111
-rw-r--r--zebra/zebra_rnh.c8
37 files changed, 2179 insertions, 1616 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index cedca17729..62d3c2350c 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,3 +1,12 @@
+# HOW TO GET YOUR ISSUE ADDRESSED FASTER
+
+* When reporting a crash provide a backtrace
+* When pasting configs, logs, shell output, backtraces, and other large chunks
+ of text [use Markdown code blocks](https://github.github.com/gfm/#fenced-code-blocks)
+* Include the FRR version; if you built from Git, please provide the commit
+ hash
+* Write your issue in English
+
### How to submit an issue
Please use this text as a template and replace text in the sections or remove
the entire section if it does not apply to your issue. For example in case of
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index c69997a41d..b614e87d23 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -418,7 +418,8 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
for (ain = bgp_node->adj_in; ain; ain = ain->next) {
int ret;
- struct bgp_path_info *path = bgp_info_from_node(bgp_node);
+ struct bgp_path_info *path =
+ bgp_node_get_bgp_path_info(bgp_node);
mpls_label_t *label = NULL;
uint32_t num_labels = 0;
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
index e9ba93bbd4..c1321dd7dc 100644
--- a/bgpd/bgp_snmp.c
+++ b/bgpd/bgp_snmp.c
@@ -715,7 +715,7 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[],
if (rn) {
bgp_unlock_node(rn);
- for (path = bgp_info_from_node(rn); path;
+ for (path = bgp_node_get_bgp_path_info(rn); path;
path = path->next)
if (sockunion_same(&path->peer->su, &su))
return path;
@@ -763,7 +763,7 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[],
do {
min = NULL;
- for (path = bgp_info_from_node(rn); path;
+ for (path = bgp_node_get_bgp_path_info(rn); path;
path = path->next) {
if (path->peer->su.sin.sin_family == AF_INET
&& ntohl(paddr.s_addr)
diff --git a/fpm/subdir.am b/fpm/subdir.am
index 05cec5a528..a0fa3d274f 100644
--- a/fpm/subdir.am
+++ b/fpm/subdir.am
@@ -1,6 +1,8 @@
if FPM
+if HAVE_PROTOBUF
lib_LTLIBRARIES += fpm/libfrrfpm_pb.la
endif
+endif
fpm_libfrrfpm_pb_la_LDFLAGS = -version-info 0:0:0
fpm_libfrrfpm_pb_la_CPPFLAGS = $(AM_CPPFLAGS) $(PROTOBUF_C_CFLAGS)
@@ -10,11 +12,9 @@ fpm_libfrrfpm_pb_la_SOURCES = \
fpm/fpm_pb.c \
# end
-if HAVE_PROTOBUF
nodist_fpm_libfrrfpm_pb_la_SOURCES = \
fpm/fpm.pb-c.c \
# end
-endif
CLEANFILES += \
fpm/fpm.pb-c.c \
diff --git a/lib/northbound.c b/lib/northbound.c
index 8b96dc4a6c..09aa60b1d2 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -1071,7 +1071,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node,
/* Iterate over all list entries. */
do {
struct yang_list_keys list_keys;
- char xpath[XPATH_MAXLEN];
+ char xpath[XPATH_MAXLEN * 2];
int ret;
/* Obtain list entry. */
diff --git a/lib/yang.c b/lib/yang.c
index 462e693549..780b986103 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -74,6 +74,7 @@ static const char *yang_module_imp_clb(const char *mod_name,
static const char * const frr_native_modules[] = {
"frr-interface",
"frr-ripd",
+ "frr-ripngd",
};
/* Generate the yang_modules tree. */
diff --git a/lib/zebra.h b/lib/zebra.h
index 46721cc1ab..0f3f45f7ba 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -410,18 +410,47 @@ extern const char *zserv_command_string(unsigned int command);
#define strmatch(a,b) (!strcmp((a), (b)))
/* Zebra message flags */
+
+/*
+ * Cause Zebra to consider this routes nexthops recursively
+ */
#define ZEBRA_FLAG_ALLOW_RECURSION 0x01
+/*
+ * This is a route that is read in on startup that was left around
+ * from a previous run of FRR
+ */
#define ZEBRA_FLAG_SELFROUTE 0x02
-#define ZEBRA_FLAG_IBGP 0x08
-#define ZEBRA_FLAG_SELECTED 0x10
-#define ZEBRA_FLAG_STATIC 0x40
-#define ZEBRA_FLAG_SCOPE_LINK 0x100
-#define ZEBRA_FLAG_FIB_OVERRIDE 0x200
-#define ZEBRA_FLAG_EVPN_ROUTE 0x400
-#define ZEBRA_FLAG_RR_USE_DISTANCE 0x800
-#define ZEBRA_FLAG_ONLINK 0x1000
-/* ZEBRA_FLAG_BLACKHOLE was 0x04 */
-/* ZEBRA_FLAG_REJECT was 0x80 */
+/*
+ * This flag is used to tell Zebra that the BGP route being passed
+ * down is a IBGP route
+ */
+#define ZEBRA_FLAG_IBGP 0x04
+/*
+ * This is a route that has been selected for FIB installation.
+ * This flag is set in zebra and can be passed up to routing daemons
+ */
+#define ZEBRA_FLAG_SELECTED 0x08
+/*
+ * This is a route that we are telling Zebra that this route *must*
+ * win and will be installed even over ZEBRA_FLAG_SELECTED
+ */
+#define ZEBRA_FLAG_FIB_OVERRIDE 0x10
+/*
+ * This flag tells Zebra that the route is a EVPN route and should
+ * be treated specially
+ */
+#define ZEBRA_FLAG_EVPN_ROUTE 0x20
+/*
+ * This flag tells Zebra that it should treat the distance passed
+ * down as an additional discriminator for route selection of the
+ * route entry. This mainly is used for backup static routes.
+ */
+#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
+/*
+ * This flag tells Zebra that the passed down route is ONLINK and the
+ * kernel install flag for it should be turned on
+ */
+#define ZEBRA_FLAG_ONLINK 0x80
/* Zebra FEC flags. */
#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c
index e0e5d95895..5bb81ef157 100644
--- a/ripd/rip_cli.c
+++ b/ripd/rip_cli.c
@@ -210,7 +210,8 @@ DEFPY (rip_distance_source,
{
if (!no) {
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
- nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY, NULL);
+ nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
+ distance_str);
nb_cli_enqueue_change(vty, "./access-list",
acl ? NB_OP_MODIFY : NB_OP_DELETE, acl);
} else
diff --git a/ripd/rip_debug.c b/ripd/rip_debug.c
index 2ce289e38f..3356d99c2a 100644
--- a/ripd/rip_debug.c
+++ b/ripd/rip_debug.c
@@ -204,13 +204,6 @@ static int config_write_debug(struct vty *vty)
return write;
}
-void rip_debug_reset(void)
-{
- rip_debug_event = 0;
- rip_debug_packet = 0;
- rip_debug_zebra = 0;
-}
-
void rip_debug_init(void)
{
rip_debug_event = 0;
diff --git a/ripd/rip_debug.h b/ripd/rip_debug.h
index c3b15d2e15..3d819ccd0b 100644
--- a/ripd/rip_debug.h
+++ b/ripd/rip_debug.h
@@ -47,6 +47,5 @@ extern unsigned long rip_debug_packet;
extern unsigned long rip_debug_zebra;
extern void rip_debug_init(void);
-extern void rip_debug_reset(void);
#endif /* _ZEBRA_RIP_DEBUG_H */
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 3d11ba1464..96b1cd8938 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -531,15 +531,6 @@ static void rip_interface_reset(struct rip_interface *ri)
rip_interface_clean(ri);
}
-void rip_interfaces_reset(void)
-{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
- struct interface *ifp;
-
- FOR_ALL_INTERFACES (vrf, ifp)
- rip_interface_reset(ifp->info);
-}
-
int rip_if_down(struct interface *ifp)
{
struct route_node *rp;
diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c
index 421b0afe38..4e445bd46d 100644
--- a/ripd/rip_northbound.c
+++ b/ripd/rip_northbound.c
@@ -170,6 +170,7 @@ static int ripd_instance_distance_source_create(enum nb_event event,
return NB_OK;
yang_dnode_get_ipv4p(&prefix, dnode, "./prefix");
+ apply_mask_ipv4(&prefix);
/* Get RIP distance node. */
rn = route_node_get(rip_distance_table, (struct prefix *)&prefix);
@@ -317,6 +318,7 @@ static int ripd_instance_network_create(enum nb_event event,
return NB_OK;
yang_dnode_get_ipv4p(&p, dnode, NULL);
+ apply_mask_ipv4((struct prefix_ipv4 *)&p);
return rip_enable_network_add(&p);
}
@@ -330,6 +332,7 @@ static int ripd_instance_network_delete(enum nb_event event,
return NB_OK;
yang_dnode_get_ipv4p(&p, dnode, NULL);
+ apply_mask_ipv4((struct prefix_ipv4 *)&p);
return rip_enable_network_delete(&p);
}
@@ -605,10 +608,9 @@ ripd_instance_redistribute_route_map_delete(enum nb_event event,
type = yang_dnode_get_enum(dnode, "../protocol");
- if (rip->route_map[type].name) {
- free(rip->route_map[type].name);
- rip->route_map[type].name = NULL;
- }
+ free(rip->route_map[type].name);
+ rip->route_map[type].name = NULL;
+ rip->route_map[type].map = NULL;
return NB_OK;
}
@@ -667,6 +669,7 @@ static int ripd_instance_static_route_create(enum nb_event event,
return NB_OK;
yang_dnode_get_ipv4p(&p, dnode, NULL);
+ apply_mask_ipv4(&p);
memset(&nh, 0, sizeof(nh));
nh.type = NEXTHOP_TYPE_IPV4;
@@ -685,6 +688,7 @@ static int ripd_instance_static_route_delete(enum nb_event event,
return NB_OK;
yang_dnode_get_ipv4p(&p, dnode, NULL);
+ apply_mask_ipv4(&p);
rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c
index b69b2466d5..b34f944c9e 100644
--- a/ripd/rip_routemap.c
+++ b/ripd/rip_routemap.c
@@ -517,11 +517,6 @@ static struct route_map_rule_cmd route_set_tag_cmd = {
#define MATCH_STR "Match values from routing table\n"
#define SET_STR "Set values in destination routing protocol\n"
-void rip_route_map_reset()
-{
- ;
-}
-
/* Route-map init */
void rip_route_map_init()
{
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index 20f543a258..fff8681775 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -147,11 +147,6 @@ static int rip_zebra_read_route(int command, struct zclient *zclient,
return 0;
}
-void rip_zclient_reset(void)
-{
- zclient_reset(zclient);
-}
-
void rip_redistribute_conf_update(int type)
{
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
diff --git a/ripd/ripd.h b/ripd/ripd.h
index d4fb230a20..91fab2a7a2 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -376,17 +376,14 @@ extern void rip_init(void);
extern void rip_clean(void);
extern void rip_clean_network(void);
extern void rip_interfaces_clean(void);
-extern void rip_interfaces_reset(void);
extern int rip_passive_nondefault_set(const char *ifname);
extern int rip_passive_nondefault_unset(const char *ifname);
extern void rip_passive_nondefault_clean(void);
extern void rip_if_init(void);
extern void rip_if_down_all(void);
extern void rip_route_map_init(void);
-extern void rip_route_map_reset(void);
extern void rip_zclient_init(struct thread_master *);
extern void rip_zclient_stop(void);
-extern void rip_zclient_reset(void);
extern int if_check_address(struct in_addr addr);
extern int rip_create(int socket);
diff --git a/ripd/subdir.am b/ripd/subdir.am
index ed74047cce..90cf79178e 100644
--- a/ripd/subdir.am
+++ b/ripd/subdir.am
@@ -9,9 +9,6 @@ dist_examples_DATA += ripd/ripd.conf.sample
vtysh_scan += \
$(top_srcdir)/ripd/rip_cli.c \
$(top_srcdir)/ripd/rip_debug.c \
- $(top_srcdir)/ripd/rip_interface.c \
- $(top_srcdir)/ripd/rip_offset.c \
- $(top_srcdir)/ripd/rip_zebra.c \
$(top_srcdir)/ripd/ripd.c \
# end
diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c
new file mode 100644
index 0000000000..a187e80fd7
--- /dev/null
+++ b/ripngd/ripng_cli.c
@@ -0,0 +1,489 @@
+/*
+ * 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 "command.h"
+#include "northbound_cli.h"
+#include "libfrr.h"
+
+#include "ripngd/ripngd.h"
+#include "ripngd/ripng_cli.h"
+#ifndef VTYSH_EXTRACT_PL
+#include "ripngd/ripng_cli_clippy.c"
+#endif
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance
+ */
+DEFPY_NOSH (router_ripng,
+ router_ripng_cmd,
+ "router ripng",
+ "Enable a routing process\n"
+ "Make RIPng instance command\n")
+{
+ int ret;
+
+ nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_CREATE,
+ NULL);
+
+ ret = nb_cli_apply_changes(vty, NULL);
+ if (ret == CMD_SUCCESS)
+ VTY_PUSH_XPATH(RIPNG_NODE, "/frr-ripngd:ripngd/instance");
+
+ return ret;
+}
+
+DEFPY (no_router_ripng,
+ no_router_ripng_cmd,
+ "no router ripng",
+ NO_STR
+ "Enable a routing process\n"
+ "Make RIPng instance command\n")
+{
+ nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_DELETE,
+ NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, "!\n");
+ vty_out(vty, "router ripng\n");
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
+ */
+DEFPY (ripng_allow_ecmp,
+ ripng_allow_ecmp_cmd,
+ "[no] allow-ecmp",
+ NO_STR
+ "Allow Equal Cost MultiPath\n")
+{
+ nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY,
+ no ? "false" : "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ripng_allow_ecmp(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ if (!yang_dnode_get_bool(dnode, NULL))
+ vty_out(vty, " no");
+
+ vty_out(vty, " allow-ecmp\n");
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/default-information-originate
+ */
+DEFPY (ripng_default_information_originate,
+ ripng_default_information_originate_cmd,
+ "[no] default-information originate",
+ NO_STR
+ "Default route information\n"
+ "Distribute default route\n")
+{
+ nb_cli_enqueue_change(vty, "./default-information-originate",
+ NB_OP_MODIFY, no ? "false" : "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ripng_default_information_originate(struct vty *vty,
+ struct lyd_node *dnode,
+ bool show_defaults)
+{
+ if (!yang_dnode_get_bool(dnode, NULL))
+ vty_out(vty, " no");
+
+ vty_out(vty, " default-information originate\n");
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/default-metric
+ */
+DEFPY (ripng_default_metric,
+ ripng_default_metric_cmd,
+ "default-metric (1-16)",
+ "Set a metric of redistribute routes\n"
+ "Default metric\n")
+{
+ nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY,
+ default_metric_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY (no_ripng_default_metric,
+ no_ripng_default_metric_cmd,
+ "no default-metric [(1-16)]",
+ NO_STR
+ "Set a metric of redistribute routes\n"
+ "Default metric\n")
+{
+ nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ripng_default_metric(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " default-metric %s\n",
+ yang_dnode_get_string(dnode, NULL));
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/network
+ */
+DEFPY (ripng_network_prefix,
+ ripng_network_prefix_cmd,
+ "[no] network X:X::X:X/M",
+ NO_STR
+ "RIPng enable on specified interface or network.\n"
+ "IPv6 network\n")
+{
+ nb_cli_enqueue_change(vty, "./network",
+ no ? NB_OP_DELETE : NB_OP_CREATE, network_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ripng_network_prefix(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/interface
+ */
+DEFPY (ripng_network_if,
+ ripng_network_if_cmd,
+ "[no] network WORD",
+ NO_STR
+ "RIPng enable on specified interface or network.\n"
+ "Interface name\n")
+{
+ nb_cli_enqueue_change(vty, "./interface",
+ no ? NB_OP_DELETE : NB_OP_CREATE, network);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/offset-list
+ */
+DEFPY (ripng_offset_list,
+ ripng_offset_list_cmd,
+ "[no] offset-list WORD$acl <in|out>$direction (0-16)$metric [IFNAME]",
+ NO_STR
+ "Modify RIPng metric\n"
+ "Access-list name\n"
+ "For incoming updates\n"
+ "For outgoing updates\n"
+ "Metric value\n"
+ "Interface to match\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, "./access-list", NB_OP_MODIFY, acl);
+ nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY,
+ metric_str);
+ } else
+ nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL);
+
+ return nb_cli_apply_changes(
+ vty, "./offset-list[interface='%s'][direction='%s']",
+ ifname ? ifname : "*", direction);
+}
+
+void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *interface;
+
+ interface = yang_dnode_get_string(dnode, "./interface");
+
+ vty_out(vty, " offset-list %s %s %s",
+ yang_dnode_get_string(dnode, "./access-list"),
+ yang_dnode_get_string(dnode, "./direction"),
+ yang_dnode_get_string(dnode, "./metric"));
+ if (!strmatch(interface, "*"))
+ vty_out(vty, " %s", interface);
+ vty_out(vty, "\n");
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/passive-interface
+ */
+DEFPY (ripng_passive_interface,
+ ripng_passive_interface_cmd,
+ "[no] passive-interface IFNAME",
+ NO_STR
+ "Suppress routing updates on an interface\n"
+ "Interface name\n")
+{
+ nb_cli_enqueue_change(vty, "./passive-interface",
+ no ? NB_OP_DELETE : NB_OP_CREATE, ifname);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ripng_passive_interface(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " passive-interface %s\n",
+ yang_dnode_get_string(dnode, NULL));
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/redistribute
+ */
+DEFPY (ripng_redistribute,
+ ripng_redistribute_cmd,
+ "[no] redistribute " FRR_REDIST_STR_RIPNGD "$protocol [{metric (0-16)|route-map WORD}]",
+ NO_STR
+ REDIST_STR
+ FRR_REDIST_HELP_STR_RIPNGD
+ "Metric\n"
+ "Metric value\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, "./route-map",
+ route_map ? NB_OP_MODIFY : NB_OP_DELETE,
+ route_map);
+ nb_cli_enqueue_change(vty, "./metric",
+ metric_str ? NB_OP_MODIFY : NB_OP_DELETE,
+ metric_str);
+ } else
+ nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL);
+
+ return nb_cli_apply_changes(vty, "./redistribute[protocol='%s']",
+ protocol);
+}
+
+void cli_show_ripng_redistribute(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " redistribute %s",
+ yang_dnode_get_string(dnode, "./protocol"));
+ if (yang_dnode_exists(dnode, "./metric"))
+ vty_out(vty, " metric %s",
+ yang_dnode_get_string(dnode, "./metric"));
+ if (yang_dnode_exists(dnode, "./route-map"))
+ vty_out(vty, " route-map %s",
+ yang_dnode_get_string(dnode, "./route-map"));
+ vty_out(vty, "\n");
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/static-route
+ */
+DEFPY (ripng_route,
+ ripng_route_cmd,
+ "[no] route X:X::X:X/M",
+ NO_STR
+ "Static route setup\n"
+ "Set static RIPng route announcement\n")
+{
+ nb_cli_enqueue_change(vty, "./static-route",
+ no ? NB_OP_DELETE : NB_OP_CREATE, route_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ripng_route(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " route %s\n", yang_dnode_get_string(dnode, NULL));
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/aggregate-addres
+ */
+DEFPY (ripng_aggregate_address,
+ ripng_aggregate_address_cmd,
+ "[no] aggregate-address X:X::X:X/M",
+ NO_STR
+ "Set aggregate RIPng route announcement\n"
+ "Aggregate network\n")
+{
+ nb_cli_enqueue_change(vty, "./aggregate-address",
+ no ? NB_OP_DELETE : NB_OP_CREATE,
+ aggregate_address_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ripng_aggregate_address(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " aggregate-address %s\n",
+ yang_dnode_get_string(dnode, NULL));
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/timers
+ */
+DEFPY (ripng_timers,
+ ripng_timers_cmd,
+ "timers basic (1-65535)$update (1-65535)$timeout (1-65535)$garbage",
+ "RIPng timers setup\n"
+ "Basic timer\n"
+ "Routing table update timer value in second. Default is 30.\n"
+ "Routing information timeout timer. Default is 180.\n"
+ "Garbage collection timer. Default is 120.\n")
+{
+ nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY,
+ update_str);
+ nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY,
+ timeout_str);
+ nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY,
+ garbage_str);
+
+ return nb_cli_apply_changes(vty, "./timers");
+}
+
+DEFPY (no_ripng_timers,
+ no_ripng_timers_cmd,
+ "no timers basic [(1-65535) (1-65535) (1-65535)]",
+ NO_STR
+ "RIPng timers setup\n"
+ "Basic timer\n"
+ "Routing table update timer value in second. Default is 30.\n"
+ "Routing information timeout timer. Default is 180.\n"
+ "Garbage collection timer. Default is 120.\n")
+{
+ nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, NULL);
+ nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, NULL);
+ nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, NULL);
+
+ return nb_cli_apply_changes(vty, "./timers");
+}
+
+void cli_show_ripng_timers(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " timers basic %s %s %s\n",
+ yang_dnode_get_string(dnode, "./update-interval"),
+ yang_dnode_get_string(dnode, "./holddown-interval"),
+ yang_dnode_get_string(dnode, "./flush-interval"));
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
+ */
+DEFPY (ipv6_ripng_split_horizon,
+ ipv6_ripng_split_horizon_cmd,
+ "[no] ipv6 ripng split-horizon [poisoned-reverse$poisoned_reverse]",
+ NO_STR
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+{
+ const char *value;
+
+ if (no)
+ value = "disabled";
+ else if (poisoned_reverse)
+ value = "poison-reverse";
+ else
+ value = "simple";
+
+ nb_cli_enqueue_change(vty, "./split-horizon", NB_OP_MODIFY, value);
+
+ return nb_cli_apply_changes(vty, "./frr-ripngd:ripng");
+}
+
+void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ int value;
+
+ value = yang_dnode_get_enum(dnode, NULL);
+ switch (value) {
+ case RIPNG_NO_SPLIT_HORIZON:
+ vty_out(vty, " no ipv6 ripng split-horizon\n");
+ break;
+ case RIPNG_SPLIT_HORIZON:
+ vty_out(vty, " ipv6 ripng split-horizon\n");
+ break;
+ case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
+ vty_out(vty, " ipv6 ripng split-horizon poisoned-reverse\n");
+ break;
+ }
+}
+
+/*
+ * XPath: /frr-ripngd:clear-ripng-route
+ */
+DEFPY (clear_ipv6_rip,
+ clear_ipv6_rip_cmd,
+ "clear ipv6 ripng",
+ CLEAR_STR
+ IPV6_STR
+ "Clear IPv6 RIP database\n")
+{
+ return nb_cli_rpc("/frr-ripngd:clear-ripng-route", NULL, NULL);
+}
+
+void ripng_cli_init(void)
+{
+ install_element(CONFIG_NODE, &router_ripng_cmd);
+ install_element(CONFIG_NODE, &no_router_ripng_cmd);
+
+ install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd);
+ install_element(RIPNG_NODE, &ripng_default_information_originate_cmd);
+ install_element(RIPNG_NODE, &ripng_default_metric_cmd);
+ install_element(RIPNG_NODE, &no_ripng_default_metric_cmd);
+ install_element(RIPNG_NODE, &ripng_network_prefix_cmd);
+ install_element(RIPNG_NODE, &ripng_network_if_cmd);
+ install_element(RIPNG_NODE, &ripng_offset_list_cmd);
+ install_element(RIPNG_NODE, &ripng_passive_interface_cmd);
+ install_element(RIPNG_NODE, &ripng_redistribute_cmd);
+ install_element(RIPNG_NODE, &ripng_route_cmd);
+ install_element(RIPNG_NODE, &ripng_aggregate_address_cmd);
+ install_element(RIPNG_NODE, &ripng_timers_cmd);
+ install_element(RIPNG_NODE, &no_ripng_timers_cmd);
+
+ install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
+
+ install_element(ENABLE_NODE, &clear_ipv6_rip_cmd);
+}
diff --git a/ripngd/ripng_cli.h b/ripngd/ripng_cli.h
new file mode 100644
index 0000000000..d95747e0f8
--- /dev/null
+++ b/ripngd/ripng_cli.h
@@ -0,0 +1,58 @@
+/*
+ * 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_debug.c b/ripngd/ripng_debug.c
index c8cad23add..c56ff12627 100644
--- a/ripngd/ripng_debug.c
+++ b/ripngd/ripng_debug.c
@@ -207,13 +207,6 @@ static int config_write_debug(struct vty *vty)
return write;
}
-void ripng_debug_reset()
-{
- ripng_debug_event = 0;
- ripng_debug_packet = 0;
- ripng_debug_zebra = 0;
-}
-
void ripng_debug_init()
{
ripng_debug_event = 0;
diff --git a/ripngd/ripng_debug.h b/ripngd/ripng_debug.h
index 8124a1a0c9..81cb0f9c7e 100644
--- a/ripngd/ripng_debug.h
+++ b/ripngd/ripng_debug.h
@@ -45,6 +45,5 @@ extern unsigned long ripng_debug_packet;
extern unsigned long ripng_debug_zebra;
extern void ripng_debug_init(void);
-extern void ripng_debug_reset(void);
#endif /* _ZEBRA_RIPNG_DEBUG_H */
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index a1d25f2961..4d14fbab64 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -36,6 +36,7 @@
#include "privs.h"
#include "vrf.h"
#include "lib_errors.h"
+#include "northbound_cli.h"
#include "ripngd/ripngd.h"
#include "ripngd/ripng_debug.h"
@@ -323,37 +324,6 @@ void ripng_interface_clean(void)
}
}
-void ripng_interface_reset(void)
-{
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
- struct interface *ifp;
- struct ripng_interface *ri;
-
- FOR_ALL_INTERFACES (vrf, ifp) {
- ri = ifp->info;
-
- ri->enable_network = 0;
- ri->enable_interface = 0;
- ri->running = 0;
-
- ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
- ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON;
-
- ri->list[RIPNG_FILTER_IN] = NULL;
- ri->list[RIPNG_FILTER_OUT] = NULL;
-
- ri->prefix[RIPNG_FILTER_IN] = NULL;
- ri->prefix[RIPNG_FILTER_OUT] = NULL;
-
- if (ri->t_wakeup) {
- thread_cancel(ri->t_wakeup);
- ri->t_wakeup = NULL;
- }
-
- ri->passive = 0;
- }
-}
-
static void ripng_apply_address_add(struct connected *ifc)
{
struct prefix_ipv6 address;
@@ -543,7 +513,7 @@ static int ripng_enable_network_lookup2(struct connected *connected)
}
/* Add RIPng enable network. */
-static int ripng_enable_network_add(struct prefix *p)
+int ripng_enable_network_add(struct prefix *p)
{
struct agg_node *node;
@@ -551,18 +521,18 @@ static int ripng_enable_network_add(struct prefix *p)
if (node->info) {
agg_unlock_node(node);
- return -1;
+ return NB_ERR_INCONSISTENCY;
} else
node->info = (void *)1;
/* XXX: One should find a better solution than a generic one */
ripng_enable_apply_all();
- return 1;
+ return NB_OK;
}
/* Delete RIPng enable network. */
-static int ripng_enable_network_delete(struct prefix *p)
+int ripng_enable_network_delete(struct prefix *p)
{
struct agg_node *node;
@@ -576,9 +546,10 @@ static int ripng_enable_network_delete(struct prefix *p)
/* Unlock lookup lock. */
agg_unlock_node(node);
- return 1;
+ return NB_OK;
}
- return -1;
+
+ return NB_ERR_INCONSISTENCY;
}
/* Lookup function. */
@@ -595,30 +566,30 @@ static int ripng_enable_if_lookup(const char *ifname)
}
/* Add interface to ripng_enable_if. */
-static int ripng_enable_if_add(const char *ifname)
+int ripng_enable_if_add(const char *ifname)
{
int ret;
ret = ripng_enable_if_lookup(ifname);
if (ret >= 0)
- return -1;
+ return NB_ERR_INCONSISTENCY;
vector_set(ripng_enable_if, strdup(ifname));
ripng_enable_apply_all();
- return 1;
+ return NB_OK;
}
/* Delete interface from ripng_enable_if. */
-static int ripng_enable_if_delete(const char *ifname)
+int ripng_enable_if_delete(const char *ifname)
{
int index;
char *str;
index = ripng_enable_if_lookup(ifname);
if (index < 0)
- return -1;
+ return NB_ERR_INCONSISTENCY;
str = vector_slot(ripng_enable_if, index);
free(str);
@@ -626,7 +597,7 @@ static int ripng_enable_if_delete(const char *ifname)
ripng_enable_apply_all();
- return 1;
+ return NB_OK;
}
/* Wake up interface. */
@@ -830,26 +801,26 @@ static void ripng_passive_interface_apply_all(void)
}
/* Passive interface. */
-static int ripng_passive_interface_set(struct vty *vty, const char *ifname)
+int ripng_passive_interface_set(const char *ifname)
{
if (ripng_passive_interface_lookup(ifname) >= 0)
- return CMD_WARNING_CONFIG_FAILED;
+ return NB_ERR_INCONSISTENCY;
vector_set(Vripng_passive_interface, strdup(ifname));
ripng_passive_interface_apply_all();
- return CMD_SUCCESS;
+ return NB_OK;
}
-static int ripng_passive_interface_unset(struct vty *vty, const char *ifname)
+int ripng_passive_interface_unset(const char *ifname)
{
int i;
char *str;
i = ripng_passive_interface_lookup(ifname);
if (i < 0)
- return CMD_WARNING_CONFIG_FAILED;
+ return NB_ERR_INCONSISTENCY;
str = vector_slot(Vripng_passive_interface, i);
free(str);
@@ -857,7 +828,7 @@ static int ripng_passive_interface_unset(struct vty *vty, const char *ifname)
ripng_passive_interface_apply_all();
- return CMD_SUCCESS;
+ return NB_OK;
}
/* Free all configured RIP passive-interface settings. */
@@ -875,7 +846,7 @@ void ripng_passive_interface_clean(void)
}
/* Write RIPng enable network and interface to the vty. */
-int ripng_network_write(struct vty *vty, int config_mode)
+int ripng_network_write(struct vty *vty)
{
unsigned int i;
const char *ifname;
@@ -887,8 +858,7 @@ int ripng_network_write(struct vty *vty, int config_mode)
node = agg_route_next(node))
if (node->info) {
struct prefix *p = &node->p;
- vty_out(vty, "%s%s/%d\n",
- config_mode ? " network " : " ",
+ vty_out(vty, " %s/%d\n",
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
p->prefixlen);
}
@@ -896,148 +866,11 @@ int ripng_network_write(struct vty *vty, int config_mode)
/* Write enable interface. */
for (i = 0; i < vector_active(ripng_enable_if); i++)
if ((ifname = vector_slot(ripng_enable_if, i)) != NULL)
- vty_out(vty, "%s%s\n",
- config_mode ? " network " : " ", ifname);
-
- /* Write passive interface. */
- if (config_mode)
- for (i = 0; i < vector_active(Vripng_passive_interface); i++)
- if ((ifname = vector_slot(Vripng_passive_interface, i))
- != NULL)
- vty_out(vty, " passive-interface %s\n", ifname);
+ vty_out(vty, " %s\n", ifname);
return 0;
}
-/* RIPng enable on specified interface or matched network. */
-DEFUN (ripng_network,
- ripng_network_cmd,
- "network IF_OR_ADDR",
- "RIPng enable on specified interface or network.\n"
- "Interface or address\n")
-{
- int idx_if_or_addr = 1;
- int ret;
- struct prefix p;
-
- ret = str2prefix(argv[idx_if_or_addr]->arg, &p);
-
- /* Given string is IPv6 network or interface name. */
- if (ret)
- ret = ripng_enable_network_add(&p);
- else
- ret = ripng_enable_if_add(argv[idx_if_or_addr]->arg);
-
- if (ret < 0) {
- vty_out(vty, "There is same network configuration %s\n",
- argv[idx_if_or_addr]->arg);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-/* RIPng enable on specified interface or matched network. */
-DEFUN (no_ripng_network,
- no_ripng_network_cmd,
- "no network IF_OR_ADDR",
- NO_STR
- "RIPng enable on specified interface or network.\n"
- "Interface or address\n")
-{
- int idx_if_or_addr = 2;
- int ret;
- struct prefix p;
-
- ret = str2prefix(argv[idx_if_or_addr]->arg, &p);
-
- /* Given string is interface name. */
- if (ret)
- ret = ripng_enable_network_delete(&p);
- else
- ret = ripng_enable_if_delete(argv[idx_if_or_addr]->arg);
-
- if (ret < 0) {
- vty_out(vty, "can't find network %s\n",
- argv[idx_if_or_addr]->arg);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_ripng_split_horizon,
- ipv6_ripng_split_horizon_cmd,
- "ipv6 ripng split-horizon",
- IPV6_STR
- "Routing Information Protocol\n"
- "Perform split horizon\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct ripng_interface *ri;
-
- ri = ifp->info;
-
- ri->split_horizon = RIPNG_SPLIT_HORIZON;
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_ripng_split_horizon_poisoned_reverse,
- ipv6_ripng_split_horizon_poisoned_reverse_cmd,
- "ipv6 ripng split-horizon poisoned-reverse",
- IPV6_STR
- "Routing Information Protocol\n"
- "Perform split horizon\n"
- "With poisoned-reverse\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct ripng_interface *ri;
-
- ri = ifp->info;
-
- ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE;
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_ripng_split_horizon,
- no_ipv6_ripng_split_horizon_cmd,
- "no ipv6 ripng split-horizon [poisoned-reverse]",
- NO_STR
- IPV6_STR
- "Routing Information Protocol\n"
- "Perform split horizon\n"
- "With poisoned-reverse\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct ripng_interface *ri;
-
- ri = ifp->info;
-
- ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
- return CMD_SUCCESS;
-}
-
-DEFUN (ripng_passive_interface,
- ripng_passive_interface_cmd,
- "passive-interface IFNAME",
- "Suppress routing updates on an interface\n"
- "Interface name\n")
-{
- int idx_ifname = 1;
- return ripng_passive_interface_set(vty, argv[idx_ifname]->arg);
-}
-
-DEFUN (no_ripng_passive_interface,
- no_ripng_passive_interface_cmd,
- "no passive-interface IFNAME",
- NO_STR
- "Suppress routing updates on an interface\n"
- "Interface name\n")
-{
- int idx_ifname = 2;
- return ripng_passive_interface_unset(vty, argv[idx_ifname]->arg);
-}
-
static struct ripng_interface *ri_new(void)
{
struct ripng_interface *ri;
@@ -1047,8 +880,8 @@ static struct ripng_interface *ri_new(void)
Relay or SMDS is enabled, the default value for split-horizon is
off. But currently Zebra does detect Frame Relay or SMDS
interface. So all interface is set to split horizon. */
- ri->split_horizon_default = RIPNG_SPLIT_HORIZON;
- ri->split_horizon = ri->split_horizon_default;
+ ri->split_horizon =
+ yang_get_default_enum("%s/split-horizon", RIPNG_IFACE);
return ri;
}
@@ -1072,44 +905,22 @@ static int interface_config_write(struct vty *vty)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
- struct ripng_interface *ri;
int write = 0;
FOR_ALL_INTERFACES (vrf, ifp) {
- ri = ifp->info;
+ struct lyd_node *dnode;
- /* Do not display the interface if there is no
- * configuration about it.
- **/
- if ((!ifp->desc)
- && (ri->split_horizon == ri->split_horizon_default))
+ dnode = yang_dnode_get(
+ running_config->dnode,
+ "/frr-interface:lib/interface[name='%s'][vrf='%s']",
+ ifp->name, vrf->name);
+ if (dnode == NULL)
continue;
- vty_frame(vty, "interface %s\n", ifp->name);
- if (ifp->desc)
- vty_out(vty, " description %s\n", ifp->desc);
-
- /* Split horizon. */
- if (ri->split_horizon != ri->split_horizon_default) {
- switch (ri->split_horizon) {
- case RIPNG_SPLIT_HORIZON:
- vty_out(vty, " ipv6 ripng split-horizon\n");
- break;
- case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
- vty_out(vty,
- " ipv6 ripng split-horizon poisoned-reverse\n");
- break;
- case RIPNG_NO_SPLIT_HORIZON:
- default:
- vty_out(vty, " no ipv6 ripng split-horizon\n");
- break;
- }
- }
-
- vty_endframe(vty, "!\n");
-
- write++;
+ write = 1;
+ nb_cli_show_dnode_cmds(vty, dnode, false);
}
+
return write;
}
@@ -1137,14 +948,4 @@ void ripng_if_init()
/* Install interface node. */
install_node(&interface_node, interface_config_write);
if_cmd_init();
-
- install_element(RIPNG_NODE, &ripng_network_cmd);
- install_element(RIPNG_NODE, &no_ripng_network_cmd);
- install_element(RIPNG_NODE, &ripng_passive_interface_cmd);
- install_element(RIPNG_NODE, &no_ripng_passive_interface_cmd);
-
- install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
- install_element(INTERFACE_NODE,
- &ipv6_ripng_split_horizon_poisoned_reverse_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd);
}
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index 98df7ef12d..10e19efe77 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -72,13 +72,9 @@ static struct frr_daemon_info ripngd_di;
static void sighup(void)
{
zlog_info("SIGHUP received");
- ripng_clean();
- ripng_reset();
/* Reload config file. */
vty_read_config(NULL, ripngd_di.config_file, config_default);
-
- /* Try to return to normal operation. */
}
/* SIGINT handler. */
@@ -120,6 +116,7 @@ struct quagga_signal_t ripng_signals[] = {
static const struct frr_yang_module_info *ripngd_yang_modules[] = {
&frr_interface_info,
+ &frr_ripngd_info,
};
FRR_DAEMON_INFO(ripngd, RIPNG, .vty_port = RIPNG_VTY_PORT,
@@ -177,6 +174,7 @@ int main(int argc, char **argv)
/* RIPngd inits. */
ripng_init();
+ ripng_cli_init();
zebra_init(master);
ripng_peer_init();
diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c
new file mode 100644
index 0000000000..7993714e8d
--- /dev/null
+++ b/ripngd/ripng_northbound.c
@@ -0,0 +1,1001 @@
+/*
+ * 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_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)
+{
+ int socket;
+
+ switch (event) {
+ case NB_EV_VALIDATE:
+ break;
+ case NB_EV_PREPARE:
+ socket = ripng_make_socket();
+ if (socket < 0)
+ return NB_ERR_RESOURCE;
+ resource->fd = socket;
+ break;
+ case NB_EV_ABORT:
+ socket = resource->fd;
+ close(socket);
+ break;
+ case NB_EV_APPLY:
+ socket = resource->fd;
+ ripng_create(socket);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int ripngd_instance_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng_clean();
+
+ return NB_OK;
+}
+
+/*
+ * 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)
+{
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng->ecmp = yang_dnode_get_bool(dnode, NULL);
+ if (!ripng->ecmp)
+ ripng_ecmp_disable();
+
+ 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)
+{
+ bool default_information;
+ struct prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ default_information = yang_dnode_get_bool(dnode, NULL);
+ str2prefix_ipv6("::/0", &p);
+ if (default_information) {
+ ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT,
+ &p, 0, NULL, 0);
+ } else {
+ ripng_redistribute_delete(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)
+{
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ 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 prefix p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6((struct prefix_ipv6 *)&p);
+
+ return ripng_enable_network_add(&p);
+}
+
+static int ripngd_instance_network_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct prefix p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6((struct prefix_ipv6 *)&p);
+
+ return ripng_enable_network_delete(&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)
+{
+ const char *ifname;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifname = yang_dnode_get_string(dnode, NULL);
+
+ return ripng_enable_if_add(ifname);
+}
+
+static int ripngd_instance_interface_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ const char *ifname;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifname = yang_dnode_get_string(dnode, NULL);
+
+ return ripng_enable_if_delete(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)
+{
+ const char *ifname;
+ struct ripng_offset_list *offset;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifname = yang_dnode_get_string(dnode, "./interface");
+
+ offset = ripng_offset_list_new(ifname);
+ yang_dnode_set_entry(dnode, offset);
+
+ return NB_OK;
+}
+
+static int ripngd_instance_offset_list_delete(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 = yang_dnode_get_entry(dnode, true);
+ 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 = yang_dnode_get_entry(dnode, 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 = yang_dnode_get_entry(dnode, 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)
+{
+ const char *ifname;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifname = yang_dnode_get_string(dnode, NULL);
+
+ return ripng_passive_interface_set(ifname);
+}
+
+static int
+ripngd_instance_passive_interface_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ const char *ifname;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifname = yang_dnode_get_string(dnode, NULL);
+
+ return ripng_passive_interface_unset(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)
+{
+ return NB_OK;
+}
+
+static int ripngd_instance_redistribute_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ int type;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ type = yang_dnode_get_enum(dnode, "./protocol");
+
+ ripng_redistribute_conf_delete(type);
+
+ return NB_OK;
+}
+
+static void
+ripngd_instance_redistribute_apply_finish(const struct lyd_node *dnode)
+{
+ int type;
+
+ type = yang_dnode_get_enum(dnode, "./protocol");
+ ripng_redistribute_conf_update(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)
+{
+ int type;
+ const char *rmap_name;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ type = yang_dnode_get_enum(dnode, "../protocol");
+ rmap_name = yang_dnode_get_string(dnode, NULL);
+
+ if (ripng->route_map[type].name)
+ free(ripng->route_map[type].name);
+ ripng->route_map[type].name = strdup(rmap_name);
+ ripng->route_map[type].map = route_map_lookup_by_name(rmap_name);
+
+ return NB_OK;
+}
+
+static int
+ripngd_instance_redistribute_route_map_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ int type;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ type = yang_dnode_get_enum(dnode, "../protocol");
+
+ free(ripng->route_map[type].name);
+ ripng->route_map[type].name = NULL;
+ ripng->route_map[type].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)
+{
+ int type;
+ uint8_t metric;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ type = yang_dnode_get_enum(dnode, "../protocol");
+ metric = yang_dnode_get_uint8(dnode, NULL);
+
+ ripng->route_map[type].metric_config = true;
+ ripng->route_map[type].metric = metric;
+
+ return NB_OK;
+}
+
+static int
+ripngd_instance_redistribute_metric_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ int type;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ type = yang_dnode_get_enum(dnode, "../protocol");
+
+ ripng->route_map[type].metric_config = false;
+ ripng->route_map[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 prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6(&p);
+
+ ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0,
+ NULL, 0);
+
+ return NB_OK;
+}
+
+static int ripngd_instance_static_route_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6(&p);
+
+ ripng_redistribute_delete(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 prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6(&p);
+
+ ripng_aggregate_add((struct prefix *)&p);
+
+ return NB_OK;
+}
+
+static int
+ripngd_instance_aggregate_address_delete(enum nb_event event,
+ const struct lyd_node *dnode)
+{
+ struct prefix_ipv6 p;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ yang_dnode_get_ipv6p(&p, dnode, NULL);
+ apply_mask_ipv6(&p);
+
+ ripng_aggregate_delete((struct prefix *)&p);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/instance/timers
+ */
+static void ripngd_instance_timers_apply_finish(const struct lyd_node *dnode)
+{
+ /* Reset update timer thread. */
+ ripng_event(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)
+{
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ 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)
+{
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ 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)
+{
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ ripng->update_time = yang_dnode_get_uint16(dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor
+ */
+static const void *
+ripngd_state_neighbors_neighbor_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ struct listnode *node;
+
+ if (list_entry == NULL)
+ node = listhead(peer_list);
+ else
+ node = listnextnode((struct listnode *)list_entry);
+
+ return node;
+}
+
+static int ripngd_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_state_neighbors_neighbor_lookup_entry(const void *parent_list_entry,
+ const struct yang_list_keys *keys)
+{
+ struct in6_addr address;
+ struct ripng_peer *peer;
+ struct listnode *node;
+
+ yang_str2ipv6(keys->key[0], &address);
+
+ for (ALL_LIST_ELEMENTS_RO(peer_list, node, peer)) {
+ if (IPV6_ADDR_SAME(&peer->addr, &address))
+ return node;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/state/neighbors/neighbor/address
+ */
+static struct yang_data *
+ripngd_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/state/neighbors/neighbor/last-update
+ */
+static struct yang_data *
+ripngd_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/state/neighbors/neighbor/bad-packets-rcvd
+ */
+static struct yang_data *
+ripngd_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/state/neighbors/neighbor/bad-routes-rcvd
+ */
+static struct yang_data *
+ripngd_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/state/routes/route
+ */
+static const void *
+ripngd_state_routes_route_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ struct agg_node *rn;
+
+ if (ripng == NULL)
+ return NULL;
+
+ 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_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_state_routes_route_lookup_entry(const void *parent_list_entry,
+ const struct yang_list_keys *keys)
+{
+ 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/state/routes/route/prefix
+ */
+static struct yang_data *
+ripngd_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/state/routes/route/next-hop
+ */
+static struct yang_data *
+ripngd_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/state/routes/route/interface
+ */
+static struct yang_data *
+ripngd_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);
+
+ return yang_data_new_string(
+ xpath, ifindex2ifname(rinfo->ifindex, VRF_DEFAULT));
+}
+
+/*
+ * XPath: /frr-ripngd:ripngd/state/routes/route/metric
+ */
+static struct yang_data *
+ripngd_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 int clear_ripng_route_rpc(const char *xpath, const struct list *input,
+ struct list *output)
+{
+ struct agg_node *rp;
+ struct ripng_info *rinfo;
+ struct list *list;
+ struct listnode *listnode;
+
+ /* Clear received RIPng routes */
+ for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
+ 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(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);
+ }
+ }
+
+ 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 = yang_dnode_get_entry(dnode, 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.create = ripngd_instance_create,
+ .cbs.delete = ripngd_instance_delete,
+ .cbs.cli_show = cli_show_router_ripng,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/allow-ecmp",
+ .cbs.modify = ripngd_instance_allow_ecmp_modify,
+ .cbs.cli_show = cli_show_ripng_allow_ecmp,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/default-information-originate",
+ .cbs.modify = ripngd_instance_default_information_originate_modify,
+ .cbs.cli_show = cli_show_ripng_default_information_originate,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/default-metric",
+ .cbs.modify = ripngd_instance_default_metric_modify,
+ .cbs.cli_show = cli_show_ripng_default_metric,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/network",
+ .cbs.create = ripngd_instance_network_create,
+ .cbs.delete = ripngd_instance_network_delete,
+ .cbs.cli_show = cli_show_ripng_network_prefix,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/interface",
+ .cbs.create = ripngd_instance_interface_create,
+ .cbs.delete = ripngd_instance_interface_delete,
+ .cbs.cli_show = cli_show_ripng_network_interface,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/offset-list",
+ .cbs.create = ripngd_instance_offset_list_create,
+ .cbs.delete = ripngd_instance_offset_list_delete,
+ .cbs.cli_show = cli_show_ripng_offset_list,
+ },
+ {
+ .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.create = ripngd_instance_passive_interface_create,
+ .cbs.delete = ripngd_instance_passive_interface_delete,
+ .cbs.cli_show = cli_show_ripng_passive_interface,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/redistribute",
+ .cbs.create = ripngd_instance_redistribute_create,
+ .cbs.delete = ripngd_instance_redistribute_delete,
+ .cbs.apply_finish = ripngd_instance_redistribute_apply_finish,
+ .cbs.cli_show = cli_show_ripng_redistribute,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/redistribute/route-map",
+ .cbs.modify = ripngd_instance_redistribute_route_map_modify,
+ .cbs.delete = ripngd_instance_redistribute_route_map_delete,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/redistribute/metric",
+ .cbs.modify = ripngd_instance_redistribute_metric_modify,
+ .cbs.delete = ripngd_instance_redistribute_metric_delete,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/static-route",
+ .cbs.create = ripngd_instance_static_route_create,
+ .cbs.delete = ripngd_instance_static_route_delete,
+ .cbs.cli_show = cli_show_ripng_route,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/aggregate-address",
+ .cbs.create = ripngd_instance_aggregate_address_create,
+ .cbs.delete = ripngd_instance_aggregate_address_delete,
+ .cbs.cli_show = cli_show_ripng_aggregate_address,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/instance/timers",
+ .cbs.apply_finish = ripngd_instance_timers_apply_finish,
+ .cbs.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/state/neighbors/neighbor",
+ .cbs.get_next = ripngd_state_neighbors_neighbor_get_next,
+ .cbs.get_keys = ripngd_state_neighbors_neighbor_get_keys,
+ .cbs.lookup_entry = ripngd_state_neighbors_neighbor_lookup_entry,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/address",
+ .cbs.get_elem = ripngd_state_neighbors_neighbor_address_get_elem,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/last-update",
+ .cbs.get_elem = ripngd_state_neighbors_neighbor_last_update_get_elem,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-packets-rcvd",
+ .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_packets_rcvd_get_elem,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/neighbors/neighbor/bad-routes-rcvd",
+ .cbs.get_elem = ripngd_state_neighbors_neighbor_bad_routes_rcvd_get_elem,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/routes/route",
+ .cbs.get_next = ripngd_state_routes_route_get_next,
+ .cbs.get_keys = ripngd_state_routes_route_get_keys,
+ .cbs.lookup_entry = ripngd_state_routes_route_lookup_entry,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/routes/route/prefix",
+ .cbs.get_elem = ripngd_state_routes_route_prefix_get_elem,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/routes/route/next-hop",
+ .cbs.get_elem = ripngd_state_routes_route_next_hop_get_elem,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/routes/route/interface",
+ .cbs.get_elem = ripngd_state_routes_route_interface_get_elem,
+ },
+ {
+ .xpath = "/frr-ripngd:ripngd/state/routes/route/metric",
+ .cbs.get_elem = ripngd_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.modify = lib_interface_ripng_split_horizon_modify,
+ .cbs.cli_show = cli_show_ipv6_ripng_split_horizon,
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/ripngd/ripng_offset.c b/ripngd/ripng_offset.c
index 32b81b5480..278df75892 100644
--- a/ripngd/ripng_offset.c
+++ b/ripngd/ripng_offset.c
@@ -33,165 +33,49 @@
#include "ripngd/ripngd.h"
-#define RIPNG_OFFSET_LIST_IN 0
-#define RIPNG_OFFSET_LIST_OUT 1
-#define RIPNG_OFFSET_LIST_MAX 2
-
-struct ripng_offset_list {
- char *ifname;
-
- struct {
- char *alist_name;
- /* struct access_list *alist; */
- int metric;
- } direct[RIPNG_OFFSET_LIST_MAX];
-};
-
static struct list *ripng_offset_list_master;
-static int strcmp_safe(const char *s1, const char *s2)
-{
- if (s1 == NULL && s2 == NULL)
- return 0;
- if (s1 == NULL)
- return -1;
- if (s2 == NULL)
- return 1;
- return strcmp(s1, s2);
-}
+#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
+#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
+
+#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
+#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
-static struct ripng_offset_list *ripng_offset_list_new(void)
+struct ripng_offset_list *ripng_offset_list_new(const char *ifname)
{
struct ripng_offset_list *new;
new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST,
sizeof(struct ripng_offset_list));
+ new->ifname = strdup(ifname);
+ listnode_add_sort(ripng_offset_list_master, new);
+
return new;
}
-static void ripng_offset_list_free(struct ripng_offset_list *offset)
+void ripng_offset_list_del(struct ripng_offset_list *offset)
{
+ listnode_delete(ripng_offset_list_master, offset);
+ if (OFFSET_LIST_IN_NAME(offset))
+ free(OFFSET_LIST_IN_NAME(offset));
+ if (OFFSET_LIST_OUT_NAME(offset))
+ free(OFFSET_LIST_OUT_NAME(offset));
+ free(offset->ifname);
XFREE(MTYPE_RIPNG_OFFSET_LIST, offset);
}
-static struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
+struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
{
struct ripng_offset_list *offset;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
- if (strcmp_safe(offset->ifname, ifname) == 0)
+ if (strcmp(offset->ifname, ifname) == 0)
return offset;
}
return NULL;
}
-static struct ripng_offset_list *ripng_offset_list_get(const char *ifname)
-{
- struct ripng_offset_list *offset;
-
- offset = ripng_offset_list_lookup(ifname);
- if (offset)
- return offset;
-
- offset = ripng_offset_list_new();
- if (ifname)
- offset->ifname = strdup(ifname);
- listnode_add_sort(ripng_offset_list_master, offset);
-
- return offset;
-}
-
-static int ripng_offset_list_set(struct vty *vty, const char *alist,
- const char *direct_str, const char *metric_str,
- const char *ifname)
-{
- int direct;
- int metric;
- struct ripng_offset_list *offset;
-
- /* Check direction. */
- if (strncmp(direct_str, "i", 1) == 0)
- direct = RIPNG_OFFSET_LIST_IN;
- else if (strncmp(direct_str, "o", 1) == 0)
- direct = RIPNG_OFFSET_LIST_OUT;
- else {
- vty_out(vty, "Invalid direction: %s\n", direct_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check metric. */
- metric = atoi(metric_str);
- if (metric < 0 || metric > 16) {
- vty_out(vty, "Invalid metric: %s\n", metric_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Get offset-list structure with interface name. */
- offset = ripng_offset_list_get(ifname);
-
- if (offset->direct[direct].alist_name)
- free(offset->direct[direct].alist_name);
- offset->direct[direct].alist_name = strdup(alist);
- offset->direct[direct].metric = metric;
-
- return CMD_SUCCESS;
-}
-
-static int ripng_offset_list_unset(struct vty *vty, const char *alist,
- const char *direct_str,
- const char *metric_str, const char *ifname)
-{
- int direct;
- int metric;
- struct ripng_offset_list *offset;
-
- /* Check direction. */
- if (strncmp(direct_str, "i", 1) == 0)
- direct = RIPNG_OFFSET_LIST_IN;
- else if (strncmp(direct_str, "o", 1) == 0)
- direct = RIPNG_OFFSET_LIST_OUT;
- else {
- vty_out(vty, "Invalid direction: %s\n", direct_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check metric. */
- metric = atoi(metric_str);
- if (metric < 0 || metric > 16) {
- vty_out(vty, "Invalid metric: %s\n", metric_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Get offset-list structure with interface name. */
- offset = ripng_offset_list_lookup(ifname);
-
- if (offset) {
- 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) {
- listnode_delete(ripng_offset_list_master, offset);
- if (offset->ifname)
- free(offset->ifname);
- ripng_offset_list_free(offset);
- }
- } else {
- vty_out(vty, "Can't find offset-list\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- return CMD_SUCCESS;
-}
-
-#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
-#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
-
-#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
-#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
-
/* If metric is modifed return 1. */
int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
uint8_t *metric)
@@ -214,7 +98,7 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
return 0;
}
/* Look up offset-list without interface name. */
- offset = ripng_offset_list_lookup(NULL);
+ offset = ripng_offset_list_lookup("*");
if (offset && OFFSET_LIST_IN_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_IN_NAME(offset));
@@ -253,7 +137,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
}
/* Look up offset-list without interface name. */
- offset = ripng_offset_list_lookup(NULL);
+ offset = ripng_offset_list_lookup("*");
if (offset && OFFSET_LIST_OUT_NAME(offset)) {
alist = access_list_lookup(AFI_IP6,
OFFSET_LIST_OUT_NAME(offset));
@@ -269,95 +153,10 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
return 0;
}
-DEFUN (ripng_offset_list,
- ripng_offset_list_cmd,
- "offset-list WORD <in|out> (0-16)",
- "Modify RIPng metric\n"
- "Access-list name\n"
- "For incoming updates\n"
- "For outgoing updates\n"
- "Metric value\n")
-{
- int idx_word = 1;
- int idx_in_out = 2;
- int idx_number = 3;
- return ripng_offset_list_set(vty, argv[idx_word]->arg,
- argv[idx_in_out]->arg,
- argv[idx_number]->arg, NULL);
-}
-
-DEFUN (ripng_offset_list_ifname,
- ripng_offset_list_ifname_cmd,
- "offset-list WORD <in|out> (0-16) IFNAME",
- "Modify RIPng metric\n"
- "Access-list name\n"
- "For incoming updates\n"
- "For outgoing updates\n"
- "Metric value\n"
- "Interface to match\n")
-{
- int idx_word = 1;
- int idx_in_out = 2;
- int idx_number = 3;
- int idx_ifname = 4;
- return ripng_offset_list_set(
- vty, argv[idx_word]->arg, argv[idx_in_out]->arg,
- argv[idx_number]->arg, argv[idx_ifname]->arg);
-}
-
-DEFUN (no_ripng_offset_list,
- no_ripng_offset_list_cmd,
- "no offset-list WORD <in|out> (0-16)",
- NO_STR
- "Modify RIPng metric\n"
- "Access-list name\n"
- "For incoming updates\n"
- "For outgoing updates\n"
- "Metric value\n")
-{
- int idx_word = 2;
- int idx_in_out = 3;
- int idx_number = 4;
- return ripng_offset_list_unset(vty, argv[idx_word]->arg,
- argv[idx_in_out]->arg,
- argv[idx_number]->arg, NULL);
-}
-
-DEFUN (no_ripng_offset_list_ifname,
- no_ripng_offset_list_ifname_cmd,
- "no offset-list WORD <in|out> (0-16) IFNAME",
- NO_STR
- "Modify RIPng metric\n"
- "Access-list name\n"
- "For incoming updates\n"
- "For outgoing updates\n"
- "Metric value\n"
- "Interface to match\n")
-{
- int idx_word = 2;
- int idx_in_out = 3;
- int idx_number = 4;
- int idx_ifname = 5;
- return ripng_offset_list_unset(
- vty, argv[idx_word]->arg, argv[idx_in_out]->arg,
- argv[idx_number]->arg, argv[idx_ifname]->arg);
-}
-
static int offset_list_cmp(struct ripng_offset_list *o1,
struct ripng_offset_list *o2)
{
- return strcmp_safe(o1->ifname, o2->ifname);
-}
-
-static void offset_list_del(struct ripng_offset_list *offset)
-{
- if (OFFSET_LIST_IN_NAME(offset))
- free(OFFSET_LIST_IN_NAME(offset));
- if (OFFSET_LIST_OUT_NAME(offset))
- free(OFFSET_LIST_OUT_NAME(offset));
- if (offset->ifname)
- free(offset->ifname);
- ripng_offset_list_free(offset);
+ return strcmp(o1->ifname, o2->ifname);
}
void ripng_offset_init(void)
@@ -365,12 +164,7 @@ void ripng_offset_init(void)
ripng_offset_list_master = list_new();
ripng_offset_list_master->cmp =
(int (*)(void *, void *))offset_list_cmp;
- ripng_offset_list_master->del = (void (*)(void *))offset_list_del;
-
- install_element(RIPNG_NODE, &ripng_offset_list_cmd);
- install_element(RIPNG_NODE, &ripng_offset_list_ifname_cmd);
- install_element(RIPNG_NODE, &no_ripng_offset_list_cmd);
- install_element(RIPNG_NODE, &no_ripng_offset_list_ifname_cmd);
+ ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
}
void ripng_offset_clean(void)
@@ -380,45 +174,5 @@ void ripng_offset_clean(void)
ripng_offset_list_master = list_new();
ripng_offset_list_master->cmp =
(int (*)(void *, void *))offset_list_cmp;
- ripng_offset_list_master->del = (void (*)(void *))offset_list_del;
-}
-
-int config_write_ripng_offset_list(struct vty *vty)
-{
- struct listnode *node, *nnode;
- struct ripng_offset_list *offset;
-
- for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
- if (!offset->ifname) {
- if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
- vty_out(vty, " offset-list %s in %d\n",
- offset->direct[RIPNG_OFFSET_LIST_IN]
- .alist_name,
- offset->direct[RIPNG_OFFSET_LIST_IN]
- .metric);
- if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
- vty_out(vty, " offset-list %s out %d\n",
- offset->direct[RIPNG_OFFSET_LIST_OUT]
- .alist_name,
- offset->direct[RIPNG_OFFSET_LIST_OUT]
- .metric);
- } else {
- if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
- vty_out(vty, " offset-list %s in %d %s\n",
- offset->direct[RIPNG_OFFSET_LIST_IN]
- .alist_name,
- offset->direct[RIPNG_OFFSET_LIST_IN]
- .metric,
- offset->ifname);
- if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
- vty_out(vty, " offset-list %s out %d %s\n",
- offset->direct[RIPNG_OFFSET_LIST_OUT]
- .alist_name,
- offset->direct[RIPNG_OFFSET_LIST_OUT]
- .metric,
- offset->ifname);
- }
- }
-
- return 0;
+ ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
}
diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c
index a18332516e..9a9e346a59 100644
--- a/ripngd/ripng_routemap.c
+++ b/ripngd/ripng_routemap.c
@@ -337,12 +337,6 @@ static struct route_map_rule_cmd route_set_tag_cmd = {
#define MATCH_STR "Match values from routing table\n"
#define SET_STR "Set values in destination routing protocol\n"
-void ripng_route_map_reset()
-{
- /* XXX ??? */
- ;
-}
-
void ripng_route_map_init()
{
route_map_init();
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index f2b69c85a7..e3f42edf51 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -141,26 +141,19 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient,
return 0;
}
-void ripng_zclient_reset(void)
+void ripng_redistribute_conf_update(int type)
{
- zclient_reset(zclient);
+ zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
+ VRF_DEFAULT);
}
-static int ripng_redistribute_unset(int type)
+void ripng_redistribute_conf_delete(int type)
{
-
- if (!vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT))
- return CMD_SUCCESS;
-
- vrf_bitmap_set(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
-
if (zclient->sock > 0)
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
AFI_IP6, type, 0, VRF_DEFAULT);
ripng_redistribute_withdraw(type);
-
- return CMD_SUCCESS;
}
int ripng_redistribute_check(int type)
@@ -168,206 +161,25 @@ int ripng_redistribute_check(int type)
return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
}
-static void ripng_redistribute_metric_set(int type, int metric)
-{
- ripng->route_map[type].metric_config = 1;
- ripng->route_map[type].metric = metric;
-}
-
-static int ripng_redistribute_metric_unset(int type)
-{
- ripng->route_map[type].metric_config = 0;
- ripng->route_map[type].metric = 0;
- return 0;
-}
-
-static void ripng_redistribute_routemap_set(int type, const char *name)
-{
- if (ripng->route_map[type].name)
- free(ripng->route_map[type].name);
-
- ripng->route_map[type].name = strdup(name);
- ripng->route_map[type].map = route_map_lookup_by_name(name);
-}
-
-static void ripng_redistribute_routemap_unset(int type)
-{
- if (ripng->route_map[type].name)
- free(ripng->route_map[type].name);
-
- ripng->route_map[type].name = NULL;
- ripng->route_map[type].map = NULL;
-}
-
-/* Redistribution types */
-static struct {
- int type;
- int str_min_len;
- const char *str;
-} redist_type[] = {{ZEBRA_ROUTE_KERNEL, 1, "kernel"},
- {ZEBRA_ROUTE_CONNECT, 1, "connected"},
- {ZEBRA_ROUTE_STATIC, 1, "static"},
- {ZEBRA_ROUTE_OSPF6, 1, "ospf6"},
- {ZEBRA_ROUTE_BGP, 2, "bgp"},
- {ZEBRA_ROUTE_VNC, 1, "vnc"},
- {0, 0, NULL}};
-
void ripng_redistribute_clean()
{
- int i;
-
- for (i = 0; redist_type[i].str; i++) {
- if (vrf_bitmap_check(
- zclient->redist[AFI_IP6][redist_type[i].type],
- VRF_DEFAULT)) {
- if (zclient->sock > 0)
- zebra_redistribute_send(
- ZEBRA_REDISTRIBUTE_DELETE, zclient,
- AFI_IP6, redist_type[i].type, 0,
- VRF_DEFAULT);
-
- vrf_bitmap_unset(
- zclient->redist[AFI_IP6][redist_type[i].type],
- VRF_DEFAULT);
-
- /* Remove the routes from RIPng table. */
- ripng_redistribute_withdraw(redist_type[i].type);
- }
- }
-}
-
-DEFUN (ripng_redistribute_type,
- ripng_redistribute_type_cmd,
- "redistribute " FRR_REDIST_STR_RIPNGD,
- "Redistribute\n"
- FRR_REDIST_HELP_STR_RIPNGD)
-{
- int type;
-
- char *proto = argv[argc - 1]->text;
- type = proto_redistnum(AFI_IP6, proto);
-
- if (type < 0) {
- vty_out(vty, "Invalid type %s\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
- VRF_DEFAULT);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_redistribute_type,
- no_ripng_redistribute_type_cmd,
- "no redistribute " FRR_REDIST_STR_RIPNGD " [metric (0-16)] [route-map WORD]",
- NO_STR
- "Redistribute\n"
- FRR_REDIST_HELP_STR_RIPNGD
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- int type;
-
- char *proto = argv[2]->text;
- type = proto_redistnum(AFI_IP6, proto);
-
- if (type < 0) {
- vty_out(vty, "Invalid type %s\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ripng_redistribute_metric_unset(type);
- ripng_redistribute_routemap_unset(type);
- return ripng_redistribute_unset(type);
-}
-
-
-DEFUN (ripng_redistribute_type_metric,
- ripng_redistribute_type_metric_cmd,
- "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16)",
- "Redistribute\n"
- FRR_REDIST_HELP_STR_RIPNGD
- "Metric\n"
- "Metric value\n")
-{
- int idx_protocol = 1;
- int idx_number = 3;
- int type;
- int metric;
-
- metric = atoi(argv[idx_number]->arg);
- type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
-
- if (type < 0) {
- vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ripng_redistribute_metric_set(type, metric);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
- VRF_DEFAULT);
- return CMD_SUCCESS;
-}
-
-DEFUN (ripng_redistribute_type_routemap,
- ripng_redistribute_type_routemap_cmd,
- "redistribute " FRR_REDIST_STR_RIPNGD " route-map WORD",
- "Redistribute\n"
- FRR_REDIST_HELP_STR_RIPNGD
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- int idx_protocol = 1;
- int idx_word = 3;
- int type;
-
- type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
+ for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+ if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT))
+ continue;
- if (type < 0) {
- vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (zclient->sock > 0)
+ zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE,
+ zclient, AFI_IP6, i, 0,
+ VRF_DEFAULT);
- ripng_redistribute_routemap_set(type, argv[idx_word]->text);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
- VRF_DEFAULT);
- return CMD_SUCCESS;
-}
+ vrf_bitmap_unset(zclient->redist[AFI_IP6][i], VRF_DEFAULT);
-DEFUN (ripng_redistribute_type_metric_routemap,
- ripng_redistribute_type_metric_routemap_cmd,
- "redistribute " FRR_REDIST_STR_RIPNGD " metric (0-16) route-map WORD",
- "Redistribute\n"
- FRR_REDIST_HELP_STR_RIPNGD
- "Metric\n"
- "Metric value\n"
- "Route map reference\n"
- "Pointer to route-map entries\n")
-{
- int idx_protocol = 1;
- int idx_number = 3;
- int idx_word = 5;
- int type;
- int metric;
-
- type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
- metric = atoi(argv[idx_number]->arg);
-
- if (type < 0) {
- vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text);
- return CMD_WARNING_CONFIG_FAILED;
+ /* Remove the routes from RIP table. */
+ ripng_redistribute_withdraw(i);
}
-
- ripng_redistribute_metric_set(type, metric);
- ripng_redistribute_routemap_set(type, argv[idx_word]->text);
- zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0,
- VRF_DEFAULT);
- return CMD_SUCCESS;
}
-void ripng_redistribute_write(struct vty *vty, int config_mode)
+void ripng_redistribute_write(struct vty *vty)
{
int i;
@@ -377,31 +189,7 @@ void ripng_redistribute_write(struct vty *vty, int config_mode)
VRF_DEFAULT))
continue;
- if (!config_mode) {
- vty_out(vty, " %s", zebra_route_string(i));
- continue;
- }
-
- if (ripng->route_map[i].metric_config) {
- if (ripng->route_map[i].name)
- vty_out(vty,
- " redistribute %s metric %d route-map %s\n",
- zebra_route_string(i),
- ripng->route_map[i].metric,
- ripng->route_map[i].name);
- else
- vty_out(vty, " redistribute %s metric %d\n",
- zebra_route_string(i),
- ripng->route_map[i].metric);
- } else {
- if (ripng->route_map[i].name)
- vty_out(vty, " redistribute %s route-map %s\n",
- zebra_route_string(i),
- ripng->route_map[i].name);
- else
- vty_out(vty, " redistribute %s\n",
- zebra_route_string(i));
- }
+ vty_out(vty, " %s", zebra_route_string(i));
}
}
@@ -426,14 +214,6 @@ void zebra_init(struct thread_master *master)
zclient->interface_address_delete = ripng_interface_address_delete;
zclient->redistribute_route_add = ripng_zebra_read_route;
zclient->redistribute_route_del = ripng_zebra_read_route;
-
- /* Install command elements to ripng node */
- install_element(RIPNG_NODE, &ripng_redistribute_type_cmd);
- install_element(RIPNG_NODE, &ripng_redistribute_type_routemap_cmd);
- install_element(RIPNG_NODE, &ripng_redistribute_type_metric_cmd);
- install_element(RIPNG_NODE,
- &ripng_redistribute_type_metric_routemap_cmd);
- install_element(RIPNG_NODE, &no_ripng_redistribute_type_cmd);
}
void ripng_zebra_stop(void)
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 2cbbbae7f5..58d83febfb 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -36,6 +36,7 @@
#include "if_rmap.h"
#include "privs.h"
#include "lib_errors.h"
+#include "northbound_cli.h"
#include "ripngd/ripngd.h"
#include "ripngd/ripng_route.h"
@@ -65,7 +66,7 @@ struct ripng_nexthop {
struct in6_addr address;
};
-static int ripng_route_rte(struct ripng_info *rinfo)
+int ripng_route_rte(struct ripng_info *rinfo)
{
return (rinfo->type == ZEBRA_ROUTE_RIPNG
&& rinfo->sub_type == RIPNG_ROUTE_RTE);
@@ -87,7 +88,7 @@ void ripng_info_free(struct ripng_info *rinfo)
}
/* Create ripng socket. */
-static int ripng_make_socket(void)
+int ripng_make_socket(void)
{
int ret;
int sock;
@@ -1778,7 +1779,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
}
/* Create new RIPng instance and set it to global variable. */
-static int ripng_create(void)
+int ripng_create(int socket)
{
/* ripng should be NULL. */
assert(ripng == NULL);
@@ -1788,10 +1789,15 @@ static int ripng_create(void)
/* Default version and timer values. */
ripng->version = RIPNG_V1;
- ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
- ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
- ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
- ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
+ ripng->update_time = yang_get_default_uint32(
+ "%s/timers/update-interval", RIPNG_INSTANCE);
+ ripng->timeout_time = yang_get_default_uint32(
+ "%s/timers/holddown-interval", RIPNG_INSTANCE);
+ ripng->garbage_time = yang_get_default_uint32(
+ "%s/timers/flush-interval", RIPNG_INSTANCE);
+ ripng->default_metric =
+ yang_get_default_uint8("%s/default-metric", RIPNG_INSTANCE);
+ ripng->ecmp = yang_get_default_bool("%s/allow-ecmp", RIPNG_INSTANCE);
/* Make buffer. */
ripng->ibuf = stream_new(RIPNG_MAX_PACKET_SIZE * 5);
@@ -1799,13 +1805,9 @@ static int ripng_create(void)
/* Initialize RIPng routig table. */
ripng->table = agg_table_init();
- ripng->route = agg_table_init();
- ripng->aggregate = agg_table_init();
/* Make socket. */
- ripng->sock = ripng_make_socket();
- if (ripng->sock < 0)
- return ripng->sock;
+ ripng->sock = socket;
/* Threads. */
ripng_event(RIPNG_READ, ripng->sock);
@@ -2060,12 +2062,12 @@ DEFUN (show_ipv6_ripng_status,
return CMD_SUCCESS;
vty_out(vty, "Routing Protocol is \"RIPng\"\n");
- vty_out(vty, " Sending updates every %ld seconds with +/-50%%,",
+ vty_out(vty, " Sending updates every %u seconds with +/-50%%,",
ripng->update_time);
vty_out(vty, " next due in %lu seconds\n",
thread_timer_remain_second(ripng->t_update));
- vty_out(vty, " Timeout after %ld seconds,", ripng->timeout_time);
- vty_out(vty, " garbage collect after %ld seconds\n",
+ vty_out(vty, " Timeout after %u seconds,", ripng->timeout_time);
+ vty_out(vty, " garbage collect after %u seconds\n",
ripng->garbage_time);
/* Filtering status show. */
@@ -2077,7 +2079,7 @@ DEFUN (show_ipv6_ripng_status,
/* Redistribute information. */
vty_out(vty, " Redistributing:");
- ripng_redistribute_write(vty, 0);
+ ripng_redistribute_write(vty);
vty_out(vty, "\n");
vty_out(vty, " Default version control: send version %d,",
@@ -2099,7 +2101,7 @@ DEFUN (show_ipv6_ripng_status,
}
vty_out(vty, " Routing for Networks:\n");
- ripng_network_write(vty, 0);
+ ripng_network_write(vty);
vty_out(vty, " Routing Information Sources:\n");
vty_out(vty,
@@ -2109,245 +2111,6 @@ DEFUN (show_ipv6_ripng_status,
return CMD_SUCCESS;
}
-DEFUN (clear_ipv6_rip,
- clear_ipv6_rip_cmd,
- "clear ipv6 ripng",
- CLEAR_STR
- IPV6_STR
- "Clear IPv6 RIP database\n")
-{
- struct agg_node *rp;
- struct ripng_info *rinfo;
- struct list *list;
- struct listnode *listnode;
-
- /* Clear received RIPng routes */
- for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
- 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(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);
- }
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN_NOSH (router_ripng,
- router_ripng_cmd,
- "router ripng",
- "Enable a routing process\n"
- "Make RIPng instance command\n")
-{
- int ret;
-
- vty->node = RIPNG_NODE;
-
- if (!ripng) {
- ret = ripng_create();
-
- /* Notice to user we couldn't create RIPng. */
- if (ret < 0) {
- zlog_warn("can't create RIPng");
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_router_ripng,
- no_router_ripng_cmd,
- "no router ripng",
- NO_STR
- "Enable a routing process\n"
- "Make RIPng instance command\n")
-{
- if (ripng)
- ripng_clean();
- return CMD_SUCCESS;
-}
-
-DEFUN (ripng_route,
- ripng_route_cmd,
- "route IPV6ADDR",
- "Static route setup\n"
- "Set static RIPng route announcement\n")
-{
- int idx_ipv6addr = 1;
- int ret;
- struct prefix_ipv6 p;
- struct agg_node *rp;
-
- ret = str2prefix_ipv6(argv[idx_ipv6addr]->arg,
- (struct prefix_ipv6 *)&p);
- if (ret <= 0) {
- vty_out(vty, "Malformed address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- apply_mask_ipv6(&p);
-
- rp = agg_node_get(ripng->route, (struct prefix *)&p);
- if (rp->info) {
- vty_out(vty, "There is already same static route.\n");
- agg_unlock_node(rp);
- return CMD_WARNING;
- }
- rp->info = (void *)1;
-
- ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0,
- NULL, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_route,
- no_ripng_route_cmd,
- "no route IPV6ADDR",
- NO_STR
- "Static route setup\n"
- "Delete static RIPng route announcement\n")
-{
- int idx_ipv6addr = 2;
- int ret;
- struct prefix_ipv6 p;
- struct agg_node *rp;
-
- ret = str2prefix_ipv6(argv[idx_ipv6addr]->arg,
- (struct prefix_ipv6 *)&p);
- if (ret <= 0) {
- vty_out(vty, "Malformed address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- apply_mask_ipv6(&p);
-
- rp = agg_node_lookup(ripng->route, (struct prefix *)&p);
- if (!rp) {
- vty_out(vty, "Can't find static route.\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
- agg_unlock_node(rp);
-
- rp->info = NULL;
- agg_unlock_node(rp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ripng_aggregate_address,
- ripng_aggregate_address_cmd,
- "aggregate-address X:X::X:X/M",
- "Set aggregate RIPng route announcement\n"
- "Aggregate network\n")
-{
- int idx_ipv6_prefixlen = 1;
- int ret;
- struct prefix p;
- struct agg_node *node;
-
- ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg,
- (struct prefix_ipv6 *)&p);
- if (ret <= 0) {
- vty_out(vty, "Malformed address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check aggregate alredy exist or not. */
- node = agg_node_get(ripng->aggregate, &p);
- if (node->info) {
- vty_out(vty, "There is already same aggregate route.\n");
- agg_unlock_node(node);
- return CMD_WARNING;
- }
- node->info = (void *)1;
-
- ripng_aggregate_add(&p);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_aggregate_address,
- no_ripng_aggregate_address_cmd,
- "no aggregate-address X:X::X:X/M",
- NO_STR
- "Delete aggregate RIPng route announcement\n"
- "Aggregate network\n")
-{
- int idx_ipv6_prefixlen = 2;
- int ret;
- struct prefix p;
- struct agg_node *rn;
-
- ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg,
- (struct prefix_ipv6 *)&p);
- if (ret <= 0) {
- vty_out(vty, "Malformed address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- rn = agg_node_lookup(ripng->aggregate, &p);
- if (!rn) {
- vty_out(vty, "Can't find aggregate route.\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- agg_unlock_node(rn);
- rn->info = NULL;
- agg_unlock_node(rn);
-
- ripng_aggregate_delete(&p);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ripng_default_metric,
- ripng_default_metric_cmd,
- "default-metric (1-16)",
- "Set a metric of redistribute routes\n"
- "Default metric\n")
-{
- int idx_number = 1;
- if (ripng) {
- ripng->default_metric = atoi(argv[idx_number]->arg);
- }
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_default_metric,
- no_ripng_default_metric_cmd,
- "no default-metric [(1-16)]",
- NO_STR
- "Set a metric of redistribute routes\n"
- "Default metric\n")
-{
- if (ripng) {
- ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
- }
- return CMD_SUCCESS;
-}
-
-
#if 0
/* RIPng update timer setup. */
DEFUN (ripng_update_timer,
@@ -2451,58 +2214,6 @@ DEFUN (no_ripng_garbage_timer,
}
#endif /* 0 */
-DEFUN (ripng_timers,
- ripng_timers_cmd,
- "timers basic (0-65535) (0-65535) (0-65535)",
- "RIPng timers setup\n"
- "Basic timer\n"
- "Routing table update timer value in second. Default is 30.\n"
- "Routing information timeout timer. Default is 180.\n"
- "Garbage collection timer. Default is 120.\n")
-{
- int idx_number = 2;
- int idx_number_2 = 3;
- int idx_number_3 = 4;
- unsigned long update;
- unsigned long timeout;
- unsigned long garbage;
-
- update = strtoul(argv[idx_number]->arg, NULL, 10);
- timeout = strtoul(argv[idx_number_2]->arg, NULL, 10);
- garbage = strtoul(argv[idx_number_3]->arg, NULL, 10);
-
- /* Set each timer value. */
- ripng->update_time = update;
- ripng->timeout_time = timeout;
- ripng->garbage_time = garbage;
-
- /* Reset update timer thread. */
- ripng_event(RIPNG_UPDATE_EVENT, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_timers,
- no_ripng_timers_cmd,
- "no timers basic [(0-65535) (0-65535) (0-65535)]",
- NO_STR
- "RIPng timers setup\n"
- "Basic timer\n"
- "Routing table update timer value in second. Default is 30.\n"
- "Routing information timeout timer. Default is 180.\n"
- "Garbage collection timer. Default is 120.\n")
-{
- /* Set each timer value to the default. */
- ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
- ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
- ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
-
- /* Reset update timer thread. */
- ripng_event(RIPNG_UPDATE_EVENT, 0);
-
- return CMD_SUCCESS;
-}
-
#if 0
DEFUN (show_ipv6_protocols,
show_ipv6_protocols_cmd,
@@ -2530,48 +2241,8 @@ DEFUN (show_ipv6_protocols,
}
#endif
-/* Please be carefull to use this command. */
-DEFUN (ripng_default_information_originate,
- ripng_default_information_originate_cmd,
- "default-information originate",
- "Default route information\n"
- "Distribute default route\n")
-{
- struct prefix_ipv6 p;
-
- if (!ripng->default_information) {
- ripng->default_information = 1;
-
- str2prefix_ipv6("::/0", &p);
- ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT,
- &p, 0, NULL, 0);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_default_information_originate,
- no_ripng_default_information_originate_cmd,
- "no default-information originate",
- NO_STR
- "Default route information\n"
- "Distribute default route\n")
-{
- struct prefix_ipv6 p;
-
- if (ripng->default_information) {
- ripng->default_information = 0;
-
- str2prefix_ipv6("::/0", &p);
- ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG,
- RIPNG_ROUTE_DEFAULT, &p, 0);
- }
-
- return CMD_SUCCESS;
-}
-
/* Update ECMP routes to zebra when ECMP is disabled. */
-static void ripng_ecmp_disable(void)
+void ripng_ecmp_disable(void)
{
struct agg_node *rp;
struct ripng_info *rinfo, *tmp_rinfo;
@@ -2608,109 +2279,24 @@ static void ripng_ecmp_disable(void)
}
}
-DEFUN (ripng_allow_ecmp,
- ripng_allow_ecmp_cmd,
- "allow-ecmp",
- "Allow Equal Cost MultiPath\n")
-{
- if (ripng->ecmp) {
- vty_out(vty, "ECMP is already enabled.\n");
- return CMD_WARNING;
- }
-
- ripng->ecmp = 1;
- zlog_info("ECMP is enabled.");
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ripng_allow_ecmp,
- no_ripng_allow_ecmp_cmd,
- "no allow-ecmp",
- NO_STR
- "Allow Equal Cost MultiPath\n")
-{
- if (!ripng->ecmp) {
- vty_out(vty, "ECMP is already disabled.\n");
- return CMD_WARNING;
- }
-
- ripng->ecmp = 0;
- zlog_info("ECMP is disabled.");
- ripng_ecmp_disable();
- return CMD_SUCCESS;
-}
-
/* RIPng configuration write function. */
static int ripng_config_write(struct vty *vty)
{
- int ripng_network_write(struct vty *, int);
- void ripng_redistribute_write(struct vty *, int);
+ struct lyd_node *dnode;
int write = 0;
- struct agg_node *rp;
-
- if (ripng) {
- /* RIPng router. */
- vty_out(vty, "router ripng\n");
-
- if (ripng->default_information)
- vty_out(vty, " default-information originate\n");
-
- ripng_network_write(vty, 1);
-
- /* RIPng default metric configuration */
- if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT)
- vty_out(vty, " default-metric %d\n",
- ripng->default_metric);
-
- ripng_redistribute_write(vty, 1);
-
- /* RIP offset-list configuration. */
- config_write_ripng_offset_list(vty);
-
- /* RIPng aggregate routes. */
- for (rp = agg_route_top(ripng->aggregate); rp;
- rp = agg_route_next(rp))
- if (rp->info != NULL)
- vty_out(vty, " aggregate-address %s/%d\n",
- inet6_ntoa(rp->p.u.prefix6),
- rp->p.prefixlen);
-
- /* ECMP configuration. */
- if (ripng->ecmp)
- vty_out(vty, " allow-ecmp\n");
-
- /* RIPng static routes. */
- for (rp = agg_route_top(ripng->route); rp;
- rp = agg_route_next(rp))
- if (rp->info != NULL)
- vty_out(vty, " route %s/%d\n",
- inet6_ntoa(rp->p.u.prefix6),
- rp->p.prefixlen);
-
- /* RIPng timers configuration. */
- if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT
- || ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT
- || ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT) {
- vty_out(vty, " timers basic %ld %ld %ld\n",
- ripng->update_time, ripng->timeout_time,
- ripng->garbage_time);
- }
-#if 0
- if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT)
- vty_out (vty, " update-timer %d\n", ripng->update_time);
- if (ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT)
- vty_out (vty, " timeout-timer %d\n", ripng->timeout_time);
- if (ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
- vty_out (vty, " garbage-timer %d\n", ripng->garbage_time);
-#endif /* 0 */
+ dnode = yang_dnode_get(running_config->dnode,
+ "/frr-ripngd:ripngd/instance");
+ if (dnode) {
+ nb_cli_show_dnode_cmds(vty, dnode, false);
- write += config_write_distribute(vty);
+ config_write_distribute(vty);
- write += config_write_if_rmap(vty);
+ config_write_if_rmap(vty);
- write++;
+ write = 1;
}
+
return write;
}
@@ -2855,29 +2441,11 @@ void ripng_clean()
ripng->sock = -1;
}
- /* Static RIPng route configuration. */
- for (rp = agg_route_top(ripng->route); rp;
- rp = agg_route_next(rp))
- if (rp->info) {
- rp->info = NULL;
- agg_unlock_node(rp);
- }
-
- /* RIPng aggregated prefixes */
- for (rp = agg_route_top(ripng->aggregate); rp;
- rp = agg_route_next(rp))
- if (rp->info) {
- rp->info = NULL;
- agg_unlock_node(rp);
- }
-
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
if (ripng->route_map[i].name)
free(ripng->route_map[i].name);
XFREE(MTYPE_ROUTE_TABLE, ripng->table);
- XFREE(MTYPE_ROUTE_TABLE, ripng->route);
- XFREE(MTYPE_ROUTE_TABLE, ripng->aggregate);
stream_free(ripng->ibuf);
stream_free(ripng->obuf);
@@ -2893,25 +2461,6 @@ void ripng_clean()
ripng_redistribute_clean();
}
-/* Reset all values to the default settings. */
-void ripng_reset()
-{
- /* Call ripd related reset functions. */
- ripng_debug_reset();
- ripng_route_map_reset();
-
- /* Call library reset functions. */
- vty_reset();
- access_list_reset();
- prefix_list_reset();
-
- distribute_list_reset();
-
- ripng_interface_reset();
-
- ripng_zclient_reset();
-}
-
static void ripng_if_rmap_update(struct if_rmap *if_rmap)
{
struct interface *ifp;
@@ -2987,22 +2536,8 @@ void ripng_init()
install_element(VIEW_NODE, &show_ipv6_ripng_cmd);
install_element(VIEW_NODE, &show_ipv6_ripng_status_cmd);
- install_element(ENABLE_NODE, &clear_ipv6_rip_cmd);
-
- install_element(CONFIG_NODE, &router_ripng_cmd);
- install_element(CONFIG_NODE, &no_router_ripng_cmd);
-
install_default(RIPNG_NODE);
- install_element(RIPNG_NODE, &ripng_route_cmd);
- install_element(RIPNG_NODE, &no_ripng_route_cmd);
- install_element(RIPNG_NODE, &ripng_aggregate_address_cmd);
- install_element(RIPNG_NODE, &no_ripng_aggregate_address_cmd);
-
- install_element(RIPNG_NODE, &ripng_default_metric_cmd);
- install_element(RIPNG_NODE, &no_ripng_default_metric_cmd);
- install_element(RIPNG_NODE, &ripng_timers_cmd);
- install_element(RIPNG_NODE, &no_ripng_timers_cmd);
#if 0
install_element (VIEW_NODE, &show_ipv6_protocols_cmd);
install_element (RIPNG_NODE, &ripng_update_timer_cmd);
@@ -3013,13 +2548,6 @@ void ripng_init()
install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd);
#endif /* 0 */
- install_element(RIPNG_NODE, &ripng_default_information_originate_cmd);
- install_element(RIPNG_NODE,
- &no_ripng_default_information_originate_cmd);
-
- install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd);
- install_element(RIPNG_NODE, &no_ripng_allow_ecmp_cmd);
-
ripng_if_init();
ripng_debug_init();
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 1095a33494..5b32374ace 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -43,11 +43,6 @@
#define RIPNG_METRIC_NEXTHOP 0xff
#define RIPNG_GROUP "ff02::9"
-/* RIPng timers. */
-#define RIPNG_UPDATE_TIMER_DEFAULT 30
-#define RIPNG_TIMEOUT_TIMER_DEFAULT 180
-#define RIPNG_GARBAGE_TIMER_DEFAULT 120
-
/* RIPng peer timeout value. */
#define RIPNG_PEER_TIMER_DEFAULT 180
@@ -77,9 +72,6 @@
#define RIPNG_DEFAULT_ACCEPT_NONE 1
#define RIPNG_DEFAULT_ACCEPT 2
-/* Default value for "default-metric" command. */
-#define RIPNG_DEFAULT_METRIC_DEFAULT 1
-
/* For max RTE calculation. */
#ifndef IPV6_HDRLEN
#define IPV6_HDRLEN 40
@@ -89,6 +81,10 @@
#define IFMINMTU 576
#endif /* IFMINMTU */
+/* YANG paths */
+#define RIPNG_INSTANCE "/frr-ripngd:ripngd/instance"
+#define RIPNG_IFACE "/frr-interface:lib/interface/frr-ripngd:ripng"
+
/* RIPng structure. */
struct ripng {
/* RIPng socket. */
@@ -97,12 +93,11 @@ struct ripng {
/* RIPng Parameters.*/
uint8_t command;
uint8_t version;
- unsigned long update_time;
- unsigned long timeout_time;
- unsigned long garbage_time;
+ uint16_t update_time;
+ uint16_t timeout_time;
+ uint16_t garbage_time;
int max_mtu;
- int default_metric;
- int default_information;
+ uint8_t default_metric;
/* Input/output buffer of RIPng. */
struct stream *ibuf;
@@ -111,12 +106,6 @@ struct ripng {
/* RIPng routing information base. */
struct agg_table *table;
- /* RIPng only static route information. */
- struct agg_table *route;
-
- /* RIPng aggregate route information. */
- struct agg_table *aggregate;
-
/* RIPng threads. */
struct thread *t_read;
struct thread *t_write;
@@ -130,14 +119,14 @@ struct ripng {
struct thread *t_triggered_interval;
/* RIPng ECMP flag */
- unsigned int ecmp;
+ bool ecmp;
/* For redistribute route map. */
struct {
char *name;
struct route_map *map;
- int metric_config;
- uint32_t metric;
+ bool metric_config;
+ uint8_t metric;
} route_map[ZEBRA_ROUTE_MAX];
};
@@ -247,7 +236,6 @@ struct ripng_interface {
/* Split horizon flag. */
split_horizon_policy_t split_horizon;
- split_horizon_policy_t split_horizon_default;
/* For filter type slot. */
#define RIPNG_FILTER_IN 0
@@ -325,30 +313,46 @@ enum ripng_event {
} \
} while (0)
+#define RIPNG_OFFSET_LIST_IN 0
+#define RIPNG_OFFSET_LIST_OUT 1
+#define RIPNG_OFFSET_LIST_MAX 2
+
+struct ripng_offset_list {
+ char *ifname;
+
+ struct {
+ char *alist_name;
+ /* struct access_list *alist; */
+ uint8_t metric;
+ } direct[RIPNG_OFFSET_LIST_MAX];
+};
+
/* Extern variables. */
extern struct ripng *ripng;
+extern struct list *peer_list;
extern struct zebra_privs_t ripngd_privs;
extern struct thread_master *master;
/* Prototypes. */
extern void ripng_init(void);
-extern void ripng_reset(void);
extern void ripng_clean(void);
extern void ripng_clean_network(void);
extern void ripng_interface_clean(void);
-extern void ripng_interface_reset(void);
+extern int ripng_enable_network_add(struct prefix *p);
+extern int ripng_enable_network_delete(struct prefix *p);
+extern int ripng_enable_if_add(const char *ifname);
+extern int ripng_enable_if_delete(const char *ifname);
+extern int ripng_passive_interface_set(const char *ifname);
+extern int ripng_passive_interface_unset(const char *ifname);
extern void ripng_passive_interface_clean(void);
extern void ripng_if_init(void);
extern void ripng_route_map_init(void);
-extern void ripng_route_map_reset(void);
extern void ripng_terminate(void);
/* zclient_init() is done by ripng_zebra.c:zebra_init() */
extern void zebra_init(struct thread_master *);
extern void ripng_zebra_stop(void);
-extern void ripng_zclient_reset(void);
-extern void ripng_offset_init(void);
-
-extern int config_write_ripng_offset_list(struct vty *);
+extern void ripng_redistribute_conf_update(int type);
+extern void ripng_redistribute_conf_delete(int type);
extern void ripng_peer_init(void);
extern void ripng_peer_update(struct sockaddr_in6 *, uint8_t);
@@ -358,12 +362,18 @@ extern void ripng_peer_display(struct vty *);
extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *);
extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *);
+extern struct ripng_offset_list *ripng_offset_list_new(const char *ifname);
+extern void ripng_offset_list_del(struct ripng_offset_list *offset);
+extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
+extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *,
uint8_t *);
extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *,
uint8_t *);
+extern void ripng_offset_init(void);
extern void ripng_offset_clean(void);
+extern int ripng_route_rte(struct ripng_info *rinfo);
extern struct ripng_info *ripng_info_new(void);
extern void ripng_info_free(struct ripng_info *rinfo);
extern void ripng_event(enum ripng_event, int);
@@ -374,6 +384,7 @@ extern void ripng_redistribute_delete(int, int, struct prefix_ipv6 *,
ifindex_t);
extern void ripng_redistribute_withdraw(int type);
+extern void ripng_ecmp_disable(void);
extern void ripng_distribute_update_interface(struct interface *);
extern void ripng_if_rmap_update_interface(struct interface *);
@@ -382,7 +393,7 @@ extern void ripng_zebra_ipv6_delete(struct agg_node *node);
extern void ripng_redistribute_clean(void);
extern int ripng_redistribute_check(int);
-extern void ripng_redistribute_write(struct vty *, int);
+extern void ripng_redistribute_write(struct vty *);
extern int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p,
struct in6_addr *nexthop, uint16_t tag,
@@ -406,10 +417,16 @@ extern int ripng_interface_address_add(int command, struct zclient *,
extern int ripng_interface_address_delete(int command, struct zclient *,
zebra_size_t, vrf_id_t);
-extern int ripng_network_write(struct vty *, int);
+extern int ripng_create(int socket);
+extern int ripng_make_socket(void);
+extern int ripng_network_write(struct vty *);
extern struct ripng_info *ripng_ecmp_add(struct ripng_info *);
extern struct ripng_info *ripng_ecmp_replace(struct ripng_info *);
extern struct ripng_info *ripng_ecmp_delete(struct ripng_info *);
+/* 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 8f834a1d29..d401e9bbf6 100644
--- a/ripngd/subdir.am
+++ b/ripngd/subdir.am
@@ -6,21 +6,21 @@ if RIPNGD
noinst_LIBRARIES += ripngd/libripng.a
sbin_PROGRAMS += ripngd/ripngd
vtysh_scan += \
+ $(top_srcdir)/ripngd/ripng_cli.c \
$(top_srcdir)/ripngd/ripng_debug.c \
- $(top_srcdir)/ripngd/ripng_interface.c \
- $(top_srcdir)/ripngd/ripng_offset.c \
- $(top_srcdir)/ripngd/ripng_zebra.c \
$(top_srcdir)/ripngd/ripngd.c \
# end
man8 += $(MANBUILD)/ripngd.8
endif
ripngd_libripng_a_SOURCES = \
+ ripngd/ripng_cli.c \
ripngd/ripng_debug.c \
ripngd/ripng_interface.c \
ripngd/ripng_memory.c \
ripngd/ripng_nexthop.c \
ripngd/ripng_offset.c \
+ ripngd/ripng_northbound.c \
ripngd/ripng_peer.c \
ripngd/ripng_route.c \
ripngd/ripng_routemap.c \
@@ -28,7 +28,11 @@ ripngd_libripng_a_SOURCES = \
ripngd/ripngd.c \
# end
+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_memory.h \
ripngd/ripng_nexthop.h \
@@ -40,5 +44,8 @@ ripngd_ripngd_LDADD = ripngd/libripng.a lib/libfrr.la @LIBCAP@
ripngd_ripngd_SOURCES = \
ripngd/ripng_main.c \
# end
+nodist_ripngd_ripngd_SOURCES = \
+ yang/frr-ripngd.yang.c \
+ # end
dist_examples_DATA += ripngd/ripngd.conf.sample
diff --git a/yang/confd/confd.frr-ripngd.yang b/yang/confd/confd.frr-ripngd.yang
new file mode 100644
index 0000000000..5d876ff4d3
--- /dev/null
+++ b/yang/confd/confd.frr-ripngd.yang
@@ -0,0 +1,22 @@
+module confd.frr-ripngd {
+ namespace "urn:dummy";
+ prefix "dummy";
+
+ import tailf-common {
+ prefix tailf;
+ }
+ import frr-ripngd {
+ prefix frr-ripngd;
+ }
+
+ tailf:annotate-module "frr-ripngd" {
+ tailf:annotate-statement "container[name='ripngd']" {
+ tailf:annotate-statement "container[name='state']" {
+ tailf:callpoint "state";
+ }
+ }
+ tailf:annotate-statement "rpc[name='clear-ripng-route']" {
+ tailf:actionpoint "actionpoint";
+ }
+ }
+}
diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang
new file mode 100644
index 0000000000..0cc5f18a5f
--- /dev/null
+++ b/yang/frr-ripngd.yang
@@ -0,0 +1,321 @@
+module frr-ripngd {
+ yang-version 1.1;
+ namespace "http://frrouting.org/yang/ripngd";
+ prefix frr-ripngd;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+ import frr-interface {
+ prefix frr-interface;
+ }
+ import frr-route-types {
+ prefix frr-route-types;
+ }
+
+ organization
+ "Free Range Routing";
+ contact
+ "FRR Users List: <mailto:frog@lists.frrouting.org>
+ FRR Development List: <mailto:dev@lists.frrouting.org>";
+ description
+ "This module defines a model for managing FRR ripngd daemon.";
+
+ revision 2018-11-27 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 2080: RIPng for IPv6.";
+ }
+
+ container ripngd {
+ /*
+ * Global configuration data
+ */
+ container instance {
+ presence "Present if the RIPng protocol is enabled.";
+ description
+ "RIPng routing instance.";
+
+ leaf allow-ecmp {
+ type boolean;
+ default "false";
+ description
+ "Allow equal-cost multi-path.";
+ }
+ leaf default-information-originate {
+ type boolean;
+ default "false";
+ description
+ "Control distribution of default route.";
+ }
+ leaf default-metric {
+ type uint8 {
+ range "1..16";
+ }
+ default "1";
+ description
+ "Default metric of redistributed routes.";
+ }
+ leaf-list network {
+ type inet:ipv6-prefix;
+ description
+ "Enable RIPng on the specified IPv6 network.";
+ }
+ leaf-list interface {
+ type string {
+ length "1..16";
+ }
+ description
+ "Enable RIPng on the specified interface.";
+ }
+ list offset-list {
+ key "interface direction";
+ description
+ "Offset-list to modify route metric.";
+ leaf interface {
+ type string;
+ description
+ "Interface to match. Use '*' to match all interfaces.";
+ }
+ leaf direction {
+ type enumeration {
+ enum in {
+ value 0;
+ description
+ "Incoming updates.";
+ }
+ enum out {
+ value 1;
+ description
+ "Outgoing updates.";
+ }
+ }
+ description
+ "Incoming or outgoing updates.";
+ }
+ leaf access-list {
+ type string;
+ mandatory true;
+ description
+ "Access-list name.";
+ }
+ leaf metric {
+ type uint8 {
+ range "0..16";
+ }
+ mandatory true;
+ description
+ "Route metric.";
+ }
+ }
+ leaf-list passive-interface {
+ type string {
+ length "1..16";
+ }
+ description
+ "A list of interfaces where the sending of RIPng packets
+ is disabled.";
+ }
+ list redistribute {
+ key "protocol";
+ description
+ "Redistributes routes learned from other routing protocols.";
+ leaf protocol {
+ type frr-route-types:frr-route-types-v6;
+ description
+ "Routing protocol.";
+ must '. != "ripng"';
+ }
+ leaf route-map {
+ type string {
+ length "1..max";
+ }
+ description
+ "Applies the conditions of the specified route-map to
+ routes that are redistributed into the RIPng routing
+ instance.";
+ }
+ leaf metric {
+ type uint8 {
+ range "0..16";
+ }
+ description
+ "Metric used for the redistributed route. If a metric is
+ not specified, the metric configured with the
+ default-metric attribute in RIPng router configuration is
+ used. If the default-metric attribute has not been
+ configured, the default metric for redistributed routes
+ is 0.";
+ }
+ }
+ leaf-list static-route {
+ type inet:ipv6-prefix;
+ description
+ "RIPng static routes.";
+ }
+ leaf-list aggregate-address {
+ type inet:ipv6-prefix;
+ description
+ "RIPng aggregate route announcement.";
+ }
+ container timers {
+ description
+ "Settings of basic timers";
+ leaf flush-interval {
+ type uint16 {
+ range "1..65535";
+ }
+ units "seconds";
+ default "120";
+ description
+ "Interval before a route is flushed from the routing
+ table.";
+ }
+ leaf holddown-interval {
+ type uint16 {
+ range "1..65535";
+ }
+ units "seconds";
+ default "180";
+ description
+ "Interval before better routes are released.";
+ }
+ leaf update-interval {
+ type uint16 {
+ range "1..65535";
+ }
+ units "seconds";
+ default "30";
+ description
+ "Interval at which RIPng updates are sent.";
+ }
+ }
+ }
+
+ /*
+ * Operational data.
+ */
+ container state {
+ config false;
+ description
+ "Operational data.";
+
+ container neighbors {
+ description
+ "Neighbor information.";
+ list neighbor {
+ key "address";
+ description
+ "A RIPng neighbor.";
+ leaf address {
+ type inet:ipv6-address;
+ description
+ "IPv6 address that a RIPng neighbor is using as its
+ source address.";
+ }
+ leaf last-update {
+ type yang:date-and-time;
+ description
+ "The time when the most recent RIPng update was
+ received from this neighbor.";
+ }
+ leaf bad-packets-rcvd {
+ type yang:counter32;
+ description
+ "The number of RIPng invalid packets received from
+ this neighbor which were subsequently discarded
+ for any reason (e.g. a version 0 packet, or an
+ unknown command type).";
+ }
+ leaf bad-routes-rcvd {
+ type yang:counter32;
+ description
+ "The number of routes received from this neighbor,
+ in valid RIPng packets, which were ignored for any
+ reason (e.g. unknown address family, or invalid
+ metric).";
+ }
+ }
+ }
+ container routes {
+ description
+ "Route information.";
+ list route {
+ key "prefix";
+ description
+ "A RIPng IPv6 route.";
+ leaf prefix {
+ type inet:ipv6-prefix;
+ description
+ "IPv6 address and prefix length, in the format
+ specified in RFC6991.";
+ }
+ leaf next-hop {
+ type inet:ipv6-address;
+ description
+ "Next hop IPv6 address.";
+ }
+ leaf interface {
+ type string;
+ description
+ "The interface that the route uses.";
+ }
+ leaf metric {
+ type uint8 {
+ range "0..16";
+ }
+ description
+ "Route metric.";
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Per-interface configuration data
+ */
+ augment "/frr-interface:lib/frr-interface:interface" {
+ container ripng {
+ description
+ "RIPng interface parameters.";
+ leaf split-horizon {
+ type enumeration {
+ enum "disabled" {
+ value 0;
+ description
+ "Disables split-horizon processing.";
+ }
+ enum "simple" {
+ value 1;
+ description
+ "Enables simple split-horizon processing.";
+ }
+ enum "poison-reverse" {
+ value 2;
+ description
+ "Enables split-horizon processing with poison
+ reverse.";
+ }
+ }
+ default "simple";
+ description
+ "Controls RIPng split-horizon processing on the specified
+ interface.";
+ }
+ }
+ }
+
+ /*
+ * RPCs
+ */
+ rpc clear-ripng-route {
+ description
+ "Clears RIPng routes from the IPv6 routing table and routes
+ redistributed into the RIPng protocol.";
+ }
+}
diff --git a/yang/subdir.am b/yang/subdir.am
index 07bd225780..6484e1181f 100644
--- a/yang/subdir.am
+++ b/yang/subdir.am
@@ -27,3 +27,7 @@ dist_yangmodels_DATA += yang/frr-route-types.yang
if RIPD
dist_yangmodels_DATA += yang/frr-ripd.yang
endif
+
+if RIPNGD
+dist_yangmodels_DATA += yang/frr-ripngd.yang
+endif
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 8a7cb0e528..4f89d53e39 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -918,6 +918,9 @@ void rtm_read(struct rt_msghdr *rtm)
char ifname[INTERFACE_NAMSIZ + 1];
short ifnlen = 0;
struct nexthop nh;
+ struct prefix p;
+ ifindex_t ifindex = 0;
+ afi_t afi;
zebra_flags = 0;
@@ -951,10 +954,6 @@ void rtm_read(struct rt_msghdr *rtm)
if (flags & RTF_PROTO1)
SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
- /* This is persistent route. */
- if (flags & RTF_STATIC)
- SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
-
memset(&nh, 0, sizeof(nh));
nh.vrf_id = VRF_DEFAULT;
@@ -967,9 +966,14 @@ void rtm_read(struct rt_msghdr *rtm)
nh.bh_type = BLACKHOLE_NULL;
}
- if (dest.sa.sa_family == AF_INET) {
- struct prefix p;
+ /*
+ * Ignore our own messages.
+ */
+ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
+ return;
+ if (dest.sa.sa_family == AF_INET) {
+ afi = AFI_IP;
p.family = AF_INET;
p.u.prefix4 = dest.sin.sin_addr;
if (flags & RTF_HOST)
@@ -977,146 +981,12 @@ void rtm_read(struct rt_msghdr *rtm)
else
p.prefixlen = ip_masklen(mask.sin.sin_addr);
- /* Catch self originated messages and match them against our
- * current RIB.
- * At the same time, ignore unconfirmed messages, they should be
- * tracked
- * by rtm_write() and kernel_rtm_ipv4().
- */
- if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) {
- char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN];
- int ret;
- if (!IS_ZEBRA_DEBUG_RIB)
- return;
- ret = rib_lookup_ipv4_route((struct prefix_ipv4 *)&p,
- &gate, VRF_DEFAULT);
- prefix2str(&p, buf, sizeof(buf));
- switch (rtm->rtm_type) {
- case RTM_ADD:
- case RTM_GET:
- case RTM_CHANGE:
- /* The kernel notifies us about a new route in
- FIB created by us.
- Do we have a correspondent entry in our RIB?
- */
- switch (ret) {
- case ZEBRA_RIB_NOTFOUND:
- zlog_debug(
- "%s: %s %s: desync: RR isn't yet in RIB, while already in FIB",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- break;
- case ZEBRA_RIB_FOUND_CONNECTED:
- case ZEBRA_RIB_FOUND_NOGATE:
- inet_ntop(AF_INET, &gate.sin.sin_addr,
- gate_buf, INET_ADDRSTRLEN);
- zlog_debug(
- "%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf, gate_buf);
- break;
- case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR
- */
- zlog_debug(
- "%s: %s %s: done Ok", __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- return;
- break;
- }
- break;
- case RTM_DELETE:
- /* The kernel notifies us about a route deleted
- by us. Do we still
- have it in the RIB? Do we have anything
- instead? */
- switch (ret) {
- case ZEBRA_RIB_FOUND_EXACT:
- zlog_debug(
- "%s: %s %s: desync: RR is still in RIB, while already not in FIB",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- break;
- case ZEBRA_RIB_FOUND_CONNECTED:
- case ZEBRA_RIB_FOUND_NOGATE:
- zlog_debug(
- "%s: %s %s: desync: RR is still in RIB, plus gate differs",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- break;
- case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
- zlog_debug(
- "%s: %s %s: done Ok", __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- return;
- break;
- }
- break;
- default:
- zlog_debug(
- "%s: %s: warning: loopback RTM of type %s received",
- __func__, buf,
- lookup_msg(rtm_type_str, rtm->rtm_type,
- NULL));
- }
- return;
- }
-
- /* Change, delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- NULL, 0, 0, 0, true);
-
if (!nh.type) {
nh.type = NEXTHOP_TYPE_IPV4;
nh.gate.ipv4 = gate.sin.sin_addr;
}
-
- if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
- || rtm->rtm_type == RTM_CHANGE)
- rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, 0, 0);
- else
- rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, true);
- }
- if (dest.sa.sa_family == AF_INET6) {
- /* One day we might have a debug section here like one in the
- * IPv4 case above. Just ignore own messages at the moment.
- */
- if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
- return;
- struct prefix p;
- ifindex_t ifindex = 0;
-
+ } else if (dest.sa.sa_family == AF_INET6) {
+ afi = AFI_IP6;
p.family = AF_INET6;
p.u.prefix6 = dest.sin6.sin6_addr;
if (flags & RTF_HOST)
@@ -1131,31 +1001,29 @@ void rtm_read(struct rt_msghdr *rtm)
}
#endif /* KAME */
- /* CHANGE: delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- NULL, 0, 0, 0, true);
-
if (!nh.type) {
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
: NEXTHOP_TYPE_IPV6;
nh.gate.ipv6 = gate.sin6.sin6_addr;
nh.ifindex = ifindex;
}
+ } else
+ return;
- if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
- || rtm->rtm_type == RTM_CHANGE)
- rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, 0, 0);
- else
- rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, true);
- }
+ /*
+ * CHANGE: delete the old prefix, we have no further information
+ * to specify the route really
+ */
+ if (rtm->rtm_type == RTM_CHANGE)
+ rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
+ 0, zebra_flags, &p, NULL, NULL, 0, 0, 0, true);
+ if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
+ || rtm->rtm_type == RTM_CHANGE)
+ rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
+ zebra_flags, &p, NULL, &nh, 0, 0, 0, 0, 0);
+ else
+ rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
+ 0, zebra_flags, &p, NULL, &nh, 0, 0, 0, true);
}
/* Interface function for the kernel routing table updates. Support
diff --git a/zebra/rib.h b/zebra/rib.h
index 97eae79f03..ae25a0e679 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -282,8 +282,6 @@ extern enum multicast_mode multicast_mode_ipv4_get(void);
extern void rib_lookup_and_dump(struct prefix_ipv4 *p, vrf_id_t vrf_id);
extern void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id);
-extern int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
- vrf_id_t vrf_id);
#define ZEBRA_RIB_LOOKUP_ERROR -1
#define ZEBRA_RIB_FOUND_EXACT 0
#define ZEBRA_RIB_FOUND_NOGATE 1
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index cb9ef8e36f..8ce963b37b 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1584,7 +1584,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
}
/* Singlepath case. */
- if (nexthop_num == 1 || multipath_num == 1) {
+ if (nexthop_num == 1) {
nexthop_num = 0;
for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
/*
@@ -1676,9 +1676,6 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
nexthop_num = 0;
for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
- if (nexthop_num >= multipath_num)
- break;
-
if (CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_RECURSIVE)) {
/* This only works for IPv4 now */
@@ -1876,12 +1873,6 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
-
- /* If we're only allowed a single nh, don't
- * continue.
- */
- if (multipath_num == 1)
- break;
}
}
}
@@ -2698,7 +2689,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
/* Fill nexthops (paths) based on single-path or multipath. The paths
* chosen depend on the operation.
*/
- if (nexthop_num == 1 || multipath_num == 1) {
+ if (nexthop_num == 1) {
routedesc = "single-path";
_netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
@@ -2745,9 +2736,6 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
if (!nexthop)
continue;
- if (nexthop_num >= multipath_num)
- break;
-
if ((cmd == RTM_NEWROUTE
&& (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
&& CHECK_FLAG(nexthop->flags,
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 9f1374af57..5d6eac7533 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -412,7 +412,7 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop,
/* If force flag is not set, do not modify falgs at all for uninstall
the route from FIB. */
static int nexthop_active(afi_t afi, struct route_entry *re,
- struct nexthop *nexthop, int set,
+ struct nexthop *nexthop, bool set,
struct route_node *top)
{
struct prefix p;
@@ -808,84 +808,6 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
return NULL;
}
-/*
- * This clone function, unlike its original rib_lookup_ipv4(), checks
- * if specified IPv4 route record (prefix/mask -> gate) exists in
- * the whole RIB and has ROUTE_ENTRY_SELECTED_FIB set.
- *
- * Return values:
- * -1: error
- * 0: exact match found
- * 1: a match was found with a different gate
- * 2: connected route found
- * 3: no matches found
- */
-int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
- vrf_id_t vrf_id)
-{
- struct route_table *table;
- struct route_node *rn;
- struct route_entry *match = NULL;
- struct nexthop *nexthop;
- int nexthops_active;
- rib_dest_t *dest;
-
- /* Lookup table. */
- table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
- if (!table)
- return ZEBRA_RIB_LOOKUP_ERROR;
-
- /* Scan the RIB table for exactly matching RIB entry. */
- rn = route_node_lookup(table, (struct prefix *)p);
-
- /* No route for this prefix. */
- if (!rn)
- return ZEBRA_RIB_NOTFOUND;
-
- /* Unlock node. */
- route_unlock_node(rn);
- dest = rib_dest_from_rnode(rn);
-
- /* Find out if a "selected" RR for the discovered RIB entry exists ever.
- */
- if (dest && dest->selected_fib
- && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
- match = dest->selected_fib;
-
- /* None such found :( */
- if (!match)
- return ZEBRA_RIB_NOTFOUND;
-
- if (match->type == ZEBRA_ROUTE_CONNECT)
- return ZEBRA_RIB_FOUND_CONNECTED;
-
- /* Ok, we have a cood candidate, let's check it's nexthop list... */
- nexthops_active = 0;
- for (ALL_NEXTHOPS(match->ng, nexthop))
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
- nexthops_active = 1;
- if (nexthop->gate.ipv4.s_addr == sockunion2ip(qgate))
- return ZEBRA_RIB_FOUND_EXACT;
- if (IS_ZEBRA_DEBUG_RIB) {
- char gate_buf[INET_ADDRSTRLEN],
- qgate_buf[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &nexthop->gate.ipv4.s_addr,
- gate_buf, INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &sockunion2ip(qgate),
- qgate_buf, INET_ADDRSTRLEN);
- zlog_debug("%s: qgate == %s, %s == %s",
- __func__, qgate_buf,
- nexthop->rparent ? "rgate" : "gate",
- gate_buf);
- }
- }
-
- if (nexthops_active)
- return ZEBRA_RIB_FOUND_NOGATE;
-
- return ZEBRA_RIB_NOTFOUND;
-}
-
#define RIB_SYSTEM_ROUTE(R) \
((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
@@ -904,7 +826,7 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
static unsigned nexthop_active_check(struct route_node *rn,
struct route_entry *re,
- struct nexthop *nexthop, int set)
+ struct nexthop *nexthop, bool set)
{
struct interface *ifp;
route_map_result_t ret = RMAP_MATCH;
@@ -1031,7 +953,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
*/
static int nexthop_active_update(struct route_node *rn, struct route_entry *re,
- int set)
+ bool set)
{
struct nexthop *nexthop;
union g_addr prev_src;
@@ -1049,7 +971,18 @@ static int nexthop_active_update(struct route_node *rn, struct route_entry *re,
prev_src = nexthop->rmap_src;
prev_active = CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
prev_index = nexthop->ifindex;
- if ((new_active = nexthop_active_check(rn, re, nexthop, set)))
+ /*
+ * We need to respect the multipath_num here
+ * as that what we should be able to install from
+ * a multipath perpsective should not be a data plane
+ * decision point.
+ */
+ new_active = nexthop_active_check(rn, re, nexthop, set);
+ if (new_active && re->nexthop_active_num >= multipath_num) {
+ UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ new_active = 0;
+ }
+ if (new_active)
re->nexthop_active_num++;
/* Don't allow src setting on IPv6 addr for now */
if (prev_active != new_active || prev_index != nexthop->ifindex
@@ -1322,7 +1255,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
/* Update real nexthop. This may actually determine if nexthop is active
* or not. */
- if (!nexthop_active_update(rn, new, 1)) {
+ if (!nexthop_active_update(rn, new, true)) {
UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
return;
}
@@ -1383,7 +1316,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
* down, causing the kernel to delete routes without sending DELROUTE
* notifications
*/
- if (!nexthop_active_update(rn, old, 1) &&
+ if (!nexthop_active_update(rn, old, true) &&
(RIB_KERNEL_ROUTE(old)))
SET_FLAG(old->status, ROUTE_ENTRY_REMOVED);
else
@@ -1408,7 +1341,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
/* Update the nexthop; we could determine here that nexthop is
* inactive. */
- if (nexthop_active_update(rn, new, 1))
+ if (nexthop_active_update(rn, new, true))
nh_active = 1;
/* If nexthop is active, install the selected route, if
@@ -1533,7 +1466,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
/* Update prior route. */
if (new != old) {
/* Set real nexthop. */
- nexthop_active_update(rn, old, 1);
+ nexthop_active_update(rn, old, true);
UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED);
}
@@ -1682,7 +1615,7 @@ static void rib_process(struct route_node *rn)
* recursive NHs.
*/
if (!CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)
- && !nexthop_active_update(rn, re, 0)) {
+ && !nexthop_active_update(rn, re, false)) {
if (re->type == ZEBRA_ROUTE_TABLE) {
/* XXX: HERE BE DRAGONS!!!!!
* In all honesty, I have not yet figured out
@@ -1774,7 +1707,7 @@ static void rib_process(struct route_node *rn)
if (old_selected != new_selected || selected_changed) {
if (new_selected && new_selected != new_fib) {
- nexthop_active_update(rn, new_selected, 1);
+ nexthop_active_update(rn, new_selected, true);
UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED);
}
@@ -1950,7 +1883,7 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx)
zvrf->removals++;
} else {
zsend_route_notify_owner_ctx(ctx,
- ZAPI_ROUTE_FAIL_INSTALL);
+ ZAPI_ROUTE_REMOVE_FAIL);
zlog_warn("%u:%s: Route Deletion failure",
dplane_ctx_get_vrf(ctx),
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index e92cd8bb8a..b1fbe8a653 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -528,8 +528,7 @@ static void zebra_rnh_process_pbr_tables(int family,
*/
static bool rnh_nexthop_valid(const struct nexthop *nh)
{
- return ((CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB)
- || CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE))
+ return (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB)
&& CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE));
}
@@ -581,8 +580,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, int family,
/* Just being SELECTED isn't quite enough - must
* have an installed nexthop to be useful.
*/
- for (nexthop = re->ng.nexthop; nexthop;
- nexthop = nexthop->next) {
+ for (ALL_NEXTHOPS(re->ng, nexthop)) {
if (rnh_nexthop_valid(nexthop))
break;
}
@@ -915,7 +913,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
num = 0;
nump = stream_get_endp(s);
stream_putc(s, 0);
- for (nh = re->ng.nexthop; nh; nh = nh->next)
+ for (ALL_NEXTHOPS(re->ng, nh))
if (rnh_nexthop_valid(nh)) {
stream_putl(s, nh->vrf_id);
stream_putc(s, nh->type);