summaryrefslogtreecommitdiffstats
path: root/staticd
diff options
context:
space:
mode:
authorvdhingra <vdhingra@vmware.com>2020-04-24 14:38:43 +0200
committervdhingra <vdhingra@vmware.com>2020-07-16 17:33:00 +0200
commit88fa5104a04af60b7d1107f02ee84fb9c0a15abe (patch)
treec2bbeecd9a5c384b7a615032c5fe13a1ff495c36 /staticd
parentlib : basic-routing backend configuration northbound code (diff)
downloadfrr-88fa5104a04af60b7d1107f02ee84fb9c0a15abe.tar.xz
frr-88fa5104a04af60b7d1107f02ee84fb9c0a15abe.zip
staticd : Configuration northbound implementation
1. Modifies the data structs to make the distance, tag and table-id property of a route, i.e created a hireachical data struct to save route and nexthop information. 2. Backend northbound implementation Signed-off-by: VishalDhingra <vdhingra@vmware.com>
Diffstat (limited to 'staticd')
-rw-r--r--staticd/static_main.c10
-rw-r--r--staticd/static_memory.c2
-rw-r--r--staticd/static_memory.h3
-rw-r--r--staticd/static_nb.c188
-rw-r--r--staticd/static_nb.h166
-rw-r--r--staticd/static_nb_config.c1234
-rw-r--r--staticd/static_nht.c122
-rw-r--r--staticd/static_routes.c626
-rw-r--r--staticd/static_routes.h112
-rw-r--r--staticd/static_vrf.c68
-rw-r--r--staticd/static_vrf.h10
-rw-r--r--staticd/static_vty.c1163
-rw-r--r--staticd/static_vty.h2
-rw-r--r--staticd/static_zebra.c142
-rw-r--r--staticd/static_zebra.h8
-rw-r--r--staticd/subdir.am7
16 files changed, 2718 insertions, 1145 deletions
diff --git a/staticd/static_main.c b/staticd/static_main.c
index 3c5922b85..0b5063a08 100644
--- a/staticd/static_main.c
+++ b/staticd/static_main.c
@@ -31,12 +31,14 @@
#include "vrf.h"
#include "nexthop.h"
#include "filter.h"
+#include "routing_nb.h"
#include "static_vrf.h"
#include "static_vty.h"
#include "static_routes.h"
#include "static_zebra.h"
#include "static_debug.h"
+#include "static_nb.h"
char backup_config_file[256];
@@ -63,10 +65,12 @@ struct option longopts[] = { { 0 } };
/* Master of threads. */
struct thread_master *master;
+static struct frr_daemon_info staticd_di;
/* SIGHUP handler. */
static void sighup(void)
{
zlog_info("SIGHUP received");
+ vty_read_config(NULL, staticd_di.config_file, config_default);
}
/* SIGINT / SIGTERM handler. */
@@ -108,7 +112,10 @@ struct quagga_signal_t static_signals[] = {
static const struct frr_yang_module_info *const staticd_yang_modules[] = {
&frr_filter_info,
+ &frr_interface_info,
&frr_vrf_info,
+ &frr_routing_info,
+ &frr_staticd_info,
};
#define STATIC_VTY_PORT 2616
@@ -155,6 +162,9 @@ int main(int argc, char **argv, char **envp)
static_zebra_init();
static_vty_init();
+ hook_register(routing_conf_event,
+ routing_control_plane_protocols_name_validate);
+
snprintf(backup_config_file, sizeof(backup_config_file),
"%s/zebra.conf", frr_sysconfdir);
staticd_di.backup_config_file = backup_config_file;
diff --git a/staticd/static_memory.c b/staticd/static_memory.c
index 77ca4a343..122cc9fce 100644
--- a/staticd/static_memory.c
+++ b/staticd/static_memory.c
@@ -25,4 +25,4 @@
DEFINE_MGROUP(STATIC, "staticd")
-DEFINE_MTYPE(STATIC, STATIC_ROUTE, "Static Route");
+DEFINE_MTYPE(STATIC, STATIC_NEXTHOP, "Static Nexthop");
diff --git a/staticd/static_memory.h b/staticd/static_memory.h
index 77a0db3b1..e9cc7ba46 100644
--- a/staticd/static_memory.h
+++ b/staticd/static_memory.h
@@ -23,6 +23,7 @@
DECLARE_MGROUP(STATIC)
-DECLARE_MTYPE(STATIC_ROUTE);
+DECLARE_MTYPE(STATIC_NEXTHOP);
+DECLARE_MTYPE(STATIC_PATH);
#endif
diff --git a/staticd/static_nb.c b/staticd/static_nb.c
new file mode 100644
index 000000000..419a6a536
--- /dev/null
+++ b/staticd/static_nb.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2018 Vmware
+ * Vishal Dhingra
+ *
+ * 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 "northbound.h"
+#include "libfrr.h"
+#include "static_nb.h"
+
+
+/* clang-format off */
+
+const struct frr_yang_module_info frr_staticd_info = {
+ .name = "frr-staticd",
+ .nodes = {
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/tag",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/table-id",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_table_id_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop",
+ .cbs = {
+ .apply_finish = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish,
+ .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy,
+ .pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bh-type",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/onlink",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy,
+
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/tag",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_tag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/table-id",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_table_id_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop",
+ .cbs = {
+ .apply_finish = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_apply_finish,
+ .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy,
+ .pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/bh-type",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/onlink",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy,
+ }
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/staticd/static_nb.h b/staticd/static_nb.h
new file mode 100644
index 000000000..9116ac8e5
--- /dev/null
+++ b/staticd/static_nb.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2018 Vmware
+ * Vishal Dhingra
+ *
+ * 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_STATIC_NB_H_
+#define _FRR_STATIC_NB_H_
+
+extern const struct frr_yang_module_info frr_staticd_info;
+
+/* Mandatory callbacks. */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_table_id_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_tag_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_table_id_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy(
+ struct nb_cb_destroy_args *args);
+
+/* Optional 'apply_finish' callbacks. */
+
+void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish(
+ struct nb_cb_apply_finish_args *args);
+void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_apply_finish(
+ struct nb_cb_apply_finish_args *args);
+
+/* Optional 'pre_validate' callbacks. */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate(
+ struct nb_cb_pre_validate_args *args);
+
+/*
+ * Callback registered with routing_nb lib to validate only
+ * one instance of staticd is allowed
+ */
+int routing_control_plane_protocols_name_validate(
+ struct nb_cb_create_args *args);
+
+/* xpath macros */
+/* route-list */
+#define FRR_STATIC_ROUTE_INFO_KEY_XPATH \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \
+ "frr-staticd:staticd/route-list[prefix='%s']" \
+ "path-list[distance='%u']"
+
+
+#define FRR_STATIC_ROUTE_PATH_TAG_XPATH "/tag"
+
+#define FRR_STATIC_ROUTE_PATH_TABLEID_XPATH "/table-id"
+
+/* route-list/frr-nexthops */
+#define FRR_STATIC_ROUTE_NH_KEY_XPATH \
+ "/frr-nexthops/" \
+ "nexthop[nh-type='%s'][vrf='%s'][gateway='%s'][interface='%s']"
+
+#define FRR_STATIC_ROUTE_NH_ONLINK_XPATH "/onlink"
+
+#define FRR_STATIC_ROUTE_NH_BH_XPATH "/bh-type"
+
+#define FRR_STATIC_ROUTE_NH_LABEL_XPATH "/mpls-label-stack"
+
+#define FRR_STATIC_ROUTE_NHLB_KEY_XPATH "/entry[id='%u']/label"
+
+/* route-list/srclist */
+#define FRR_S_ROUTE_SRC_INFO_KEY_XPATH \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \
+ "frr-staticd:staticd/route-list[prefix='%s']" \
+ "src-list[src-prefix='%s']/path-list[distance='%u']"
+
+/* route-list/frr-nexthops */
+#define FRR_DEL_S_ROUTE_NH_KEY_XPATH \
+ FRR_STATIC_ROUTE_INFO_KEY_XPATH \
+ FRR_STATIC_ROUTE_NH_KEY_XPATH
+
+/* route-list/src/src-list/frr-nexthops*/
+#define FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH \
+ FRR_S_ROUTE_SRC_INFO_KEY_XPATH \
+ FRR_STATIC_ROUTE_NH_KEY_XPATH
+
+#endif
diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c
new file mode 100644
index 000000000..282299eef
--- /dev/null
+++ b/staticd/static_nb_config.c
@@ -0,0 +1,1234 @@
+/*
+ * Copyright (C) 2018 Vmware
+ * Vishal Dhingra
+ *
+ * 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 "northbound.h"
+#include "libfrr.h"
+#include "log.h"
+#include "lib_errors.h"
+#include "prefix.h"
+#include "table.h"
+#include "vrf.h"
+#include "nexthop.h"
+#include "srcdest_table.h"
+
+#include "static_vrf.h"
+#include "static_routes.h"
+#include "static_nb.h"
+
+
+static int static_path_list_create(struct nb_cb_create_args *args)
+{
+ struct route_node *rn;
+ struct static_path *pn;
+ uint8_t distance;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_ABORT:
+ case NB_EV_PREPARE:
+ break;
+ case NB_EV_APPLY:
+ rn = nb_running_get_entry(args->dnode, NULL, true);
+ distance = yang_dnode_get_uint8(args->dnode, "./distance");
+ pn = static_add_path(rn, distance);
+ nb_running_set_entry(args->dnode, pn);
+ }
+
+ return NB_OK;
+}
+
+static void static_path_list_destroy(struct nb_cb_destroy_args *args,
+ const struct lyd_node *rn_dnode,
+ struct stable_info *info)
+{
+ struct route_node *rn;
+ struct static_path *pn;
+
+ pn = nb_running_unset_entry(args->dnode);
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ static_del_path(rn, pn, info->safi, info->svrf);
+}
+
+static void static_path_list_tag_modify(struct nb_cb_modify_args *args,
+ const struct lyd_node *rn_dnode,
+ struct stable_info *info)
+{
+ struct static_path *pn;
+ struct route_node *rn;
+ route_tag_t tag;
+
+ tag = yang_dnode_get_uint32(args->dnode, NULL);
+ pn = nb_running_get_entry(args->dnode, NULL, true);
+ pn->tag = tag;
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+
+ static_install_path(rn, pn, info->safi, info->svrf);
+}
+
+static int static_path_list_tableid_modify(struct nb_cb_modify_args *args,
+ const struct lyd_node *rn_dnode,
+ struct stable_info *info)
+{
+ struct static_path *pn;
+ struct route_node *rn;
+ uint32_t table_id;
+ const struct lyd_node *vrf_dnode;
+ const char *vrf;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ vrf_dnode = yang_dnode_get_parent(args->dnode,
+ "control-plane-protocol");
+ vrf = yang_dnode_get_string(vrf_dnode, "./vrf");
+ table_id = yang_dnode_get_uint32(args->dnode, NULL);
+ if (table_id && (strcmp(vrf, vrf_get_default_name()) != 0)
+ && !vrf_is_backend_netns()) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "%% table param only available when running on netns-based vrfs");
+ return NB_ERR_VALIDATION;
+ }
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ table_id = yang_dnode_get_uint32(args->dnode, NULL);
+ pn = nb_running_get_entry(args->dnode, NULL, true);
+ pn->table_id = table_id;
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ static_install_path(rn, pn, info->safi, info->svrf);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static bool static_nexthop_create(struct nb_cb_create_args *args,
+ const struct lyd_node *rn_dnode,
+ struct stable_info *info)
+{
+ struct route_node *rn;
+ struct static_path *pn;
+ struct ipaddr ipaddr;
+ struct static_nexthop *nh;
+ int nh_type;
+ const char *ifname;
+ const char *nh_vrf;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ ifname = yang_dnode_get_string(args->dnode, "./interface");
+ if (ifname != NULL) {
+ if (strcasecmp(ifname, "Null0") == 0
+ || strcasecmp(ifname, "reject") == 0
+ || strcasecmp(ifname, "blackhole") == 0) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "%s: Nexthop interface name can not be from reserved keywords(Null0, reject, blackhole)",
+ ifname);
+ return NB_ERR_VALIDATION;
+ }
+ }
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ yang_dnode_get_ip(&ipaddr, args->dnode, "./gateway");
+ nh_type = yang_dnode_get_enum(args->dnode, "./nh-type");
+ ifname = yang_dnode_get_string(args->dnode, "./interface");
+ nh_vrf = yang_dnode_get_string(args->dnode, "./vrf");
+ pn = nb_running_get_entry(args->dnode, NULL, true);
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+
+ if (!static_add_nexthop_validate(info->svrf, nh_type, &ipaddr))
+ flog_warn(
+ EC_LIB_NB_CB_CONFIG_VALIDATE,
+ "Warning!! Local connected address is configured as Gateway IP((%s))",
+ yang_dnode_get_string(args->dnode,
+ "./gateway"));
+ nh = static_add_nexthop(rn, pn, info->safi, info->svrf, nh_type,
+ &ipaddr, ifname, nh_vrf);
+ if (!nh) {
+ char buf[SRCDEST2STR_BUFFER];
+
+ flog_warn(
+ EC_LIB_NB_CB_CONFIG_APPLY,
+ "%s : nh [%d:%s:%s:%s] nexthop creation failed",
+ srcdest_rnode2str(rn, buf, sizeof(buf)),
+ nh_type, ifname,
+ yang_dnode_get_string(args->dnode, "./gateway"),
+ nh_vrf);
+ return NB_ERR;
+ }
+ nb_running_set_entry(args->dnode, nh);
+ break;
+ }
+
+ return NB_OK;
+}
+
+static bool static_nexthop_destroy(struct nb_cb_destroy_args *args,
+ const struct lyd_node *rn_dnode,
+ struct stable_info *info)
+{
+ struct route_node *rn;
+ struct static_path *pn;
+ const struct lyd_node *pn_dnode;
+ struct static_nexthop *nh;
+ int ret;
+
+ nh = nb_running_unset_entry(args->dnode);
+ pn_dnode = yang_dnode_get_parent(args->dnode, "path-list");
+ pn = nb_running_get_entry(pn_dnode, NULL, true);
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+
+ ret = static_delete_nexthop(rn, pn, info->safi, info->svrf, nh);
+ if (!ret) {
+ char buf[SRCDEST2STR_BUFFER];
+
+ flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
+ "%s : nh [%d:%s:%s:%s] nexthop destroy failed",
+ srcdest_rnode2str(rn, buf, sizeof(buf)),
+ yang_dnode_get_enum(args->dnode, "./nh-type"),
+ yang_dnode_get_string(args->dnode, "./interface"),
+ yang_dnode_get_string(args->dnode, "./gateway"),
+ yang_dnode_get_string(args->dnode, "./vrf"));
+ return NB_ERR;
+ }
+
+ return NB_OK;
+}
+
+static int nexthop_mpls_label_stack_entry_create(struct nb_cb_create_args *args)
+{
+ struct static_nexthop *nh;
+ uint32_t pos;
+ uint8_t index;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ nh = nb_running_get_entry(args->dnode, NULL, true);
+ pos = yang_get_list_pos(args->dnode);
+ if (!pos) {
+ flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
+ "libyang returns invalid label position");
+ return NB_ERR;
+ }
+ /* Mapping to array = list-index -1 */
+ index = pos - 1;
+ nh->snh_label.label[index] = 0;
+ nh->snh_label.num_labels++;
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int
+nexthop_mpls_label_stack_entry_destroy(struct nb_cb_destroy_args *args)
+{
+ struct static_nexthop *nh;
+ uint32_t pos;
+ uint8_t index;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ nh = nb_running_get_entry(args->dnode, NULL, true);
+ pos = yang_get_list_pos(args->dnode);
+ if (!pos) {
+ flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
+ "libyang returns invalid label position");
+ return NB_ERR;
+ }
+ index = pos - 1;
+ nh->snh_label.label[index] = 0;
+ nh->snh_label.num_labels--;
+ break;
+ }
+
+ return NB_OK;
+}
+
+static int static_nexthop_mpls_label_modify(struct nb_cb_modify_args *args)
+{
+ struct static_nexthop *nh;
+ uint32_t pos;
+ uint8_t index;
+
+ nh = nb_running_get_entry(args->dnode, NULL, true);
+ pos = yang_get_list_pos(args->dnode->parent);
+ if (!pos) {
+ flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
+ "libyang returns invalid label position");
+ return NB_ERR;
+ }
+ /* Mapping to array = list-index -1 */
+ index = pos - 1;
+ nh->snh_label.label[index] = yang_dnode_get_uint32(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+static int static_nexthop_onlink_modify(struct nb_cb_modify_args *args)
+{
+ struct static_nexthop *nh;
+
+ nh = nb_running_get_entry(args->dnode, NULL, true);
+ nh->onlink = yang_dnode_get_bool(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+static int static_nexthop_bh_type_modify(struct nb_cb_modify_args *args)
+{
+ struct static_nexthop *nh;
+
+ nh = nb_running_get_entry(args->dnode, NULL, true);
+ nh->bh_type = yang_dnode_get_enum(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+
+void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish(
+ struct nb_cb_apply_finish_args *args)
+{
+ struct static_nexthop *nh;
+ struct static_path *pn;
+ struct route_node *rn;
+ const struct lyd_node *pn_dnode;
+ const struct lyd_node *rn_dnode;
+ const char *ifname;
+ const char *nh_vrf;
+ struct stable_info *info;
+ int nh_type;
+
+ nh_type = yang_dnode_get_enum(args->dnode, "./nh-type");
+ ifname = yang_dnode_get_string(args->dnode, "./interface");
+ nh_vrf = yang_dnode_get_string(args->dnode, "./vrf");
+
+ nh = nb_running_get_entry(args->dnode, NULL, true);
+
+ pn_dnode = yang_dnode_get_parent(args->dnode, "path-list");
+ pn = nb_running_get_entry(pn_dnode, NULL, true);
+
+ rn_dnode = yang_dnode_get_parent(pn_dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+
+ static_install_nexthop(rn, pn, nh, info->safi, info->svrf, ifname,
+ nh_type, nh_vrf);
+}
+
+
+void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_apply_finish(
+ struct nb_cb_apply_finish_args *args)
+{
+ struct static_nexthop *nh;
+ struct static_path *pn;
+ struct route_node *rn;
+ struct route_node *src_rn;
+ const struct lyd_node *pn_dnode;
+ const struct lyd_node *rn_dnode;
+ const struct lyd_node *src_dnode;
+ const char *ifname;
+ const char *nh_vrf;
+ struct stable_info *info;
+ int nh_type;
+
+ nh_type = yang_dnode_get_enum(args->dnode, "./nh-type");
+ ifname = yang_dnode_get_string(args->dnode, "./interface");
+ nh_vrf = yang_dnode_get_string(args->dnode, "./vrf");
+
+ nh = nb_running_get_entry(args->dnode, NULL, true);
+
+ pn_dnode = yang_dnode_get_parent(args->dnode, "path-list");
+ pn = nb_running_get_entry(pn_dnode, NULL, true);
+
+ src_dnode = yang_dnode_get_parent(pn_dnode, "src-list");
+ src_rn = nb_running_get_entry(src_dnode, NULL, true);
+
+ rn_dnode = yang_dnode_get_parent(src_dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+
+ static_install_nexthop(src_rn, pn, nh, info->safi, info->svrf, ifname,
+ nh_type, nh_vrf);
+}
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate(
+ struct nb_cb_pre_validate_args *args)
+{
+ const struct lyd_node *mls_dnode;
+ uint32_t count;
+
+ mls_dnode = yang_dnode_get(args->dnode, "./mpls-label-stack");
+ count = yang_get_list_elements_count(yang_dnode_get_child(mls_dnode));
+
+ if (count > MPLS_MAX_LABELS) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Too many labels, Enter %d or fewer",
+ MPLS_MAX_LABELS);
+ return NB_ERR_VALIDATION;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_name_validate(
+ struct nb_cb_create_args *args)
+{
+ const char *name;
+
+ name = yang_dnode_get_string(args->dnode, "./name");
+ if (!strmatch(name, "staticd")) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "static routing supports only one instance with name staticd");
+ return NB_ERR_VALIDATION;
+ }
+ return NB_OK;
+}
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
+ struct nb_cb_create_args *args)
+{
+ struct vrf *vrf;
+ struct static_vrf *s_vrf;
+ struct route_node *rn;
+ const struct lyd_node *vrf_dnode;
+ struct prefix prefix;
+ afi_t afi;
+ safi_t safi = SAFI_UNICAST;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ vrf_dnode = yang_dnode_get_parent(args->dnode,
+ "control-plane-protocol");
+ vrf = nb_running_get_entry(vrf_dnode, NULL, true);
+ s_vrf = vrf->info;
+
+ yang_dnode_get_prefix(&prefix, args->dnode, "./prefix");
+ afi = family2afi(prefix.family);
+
+ if (afi == AFI_IP) {
+ if (IN_MULTICAST(ntohl(prefix.u.prefix4.s_addr)))
+ safi = SAFI_MULTICAST;
+ } else {
+ if (IN6_IS_ADDR_MULTICAST(&prefix.u.prefix6))
+ safi = SAFI_MULTICAST;
+ }
+
+ rn = static_add_route(afi, safi, &prefix, NULL, s_vrf);
+ if (!rn) {
+ flog_warn(
+ EC_LIB_NB_CB_CONFIG_APPLY,
+ "route node %s creation failed",
+ yang_dnode_get_string(args->dnode, "./prefix"));
+ return NB_ERR;
+ }
+ nb_running_set_entry(args->dnode, rn);
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct route_node *rn;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ rn = nb_running_unset_entry(args->dnode);
+ info = route_table_get_info(rn->table);
+ static_del_route(rn, info->safi, info->svrf);
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create(
+ struct nb_cb_create_args *args)
+{
+ return static_path_list_create(args);
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ const struct lyd_node *rn_dnode;
+ struct route_node *rn;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ rn_dnode = yang_dnode_get_parent(args->dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+ static_path_list_destroy(args, rn_dnode, info);
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/tag
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct stable_info *info;
+ struct route_node *rn;
+ const struct lyd_node *rn_dnode;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_ABORT:
+ case NB_EV_PREPARE:
+ break;
+ case NB_EV_APPLY:
+ rn_dnode = yang_dnode_get_parent(args->dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+ static_path_list_tag_modify(args, rn_dnode, info);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/table-id
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_table_id_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct route_node *rn;
+ const struct lyd_node *rn_dnode;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (static_path_list_tableid_modify(args, NULL, NULL) != NB_OK)
+ return NB_ERR_VALIDATION;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ rn_dnode = yang_dnode_get_parent(args->dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+
+ if (static_path_list_tableid_modify(args, rn_dnode, info)
+ != NB_OK)
+ return NB_ERR_VALIDATION;
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create(
+ struct nb_cb_create_args *args)
+{
+ struct route_node *rn;
+ const struct lyd_node *rn_dnode;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ rn_dnode = yang_dnode_get_parent(args->dnode, "route-list");
+ if (static_nexthop_create(args, rn_dnode, NULL) != NB_OK)
+ return NB_ERR_VALIDATION;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ rn_dnode = yang_dnode_get_parent(args->dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+
+ if (static_nexthop_create(args, rn_dnode, info) != NB_OK)
+ return NB_ERR_VALIDATION;
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct route_node *rn;
+ const struct lyd_node *rn_dnode;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ rn_dnode = yang_dnode_get_parent(args->dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+
+ if (static_nexthop_destroy(args, rn_dnode, info) != NB_OK)
+ return NB_ERR;
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bh-type
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ if (static_nexthop_bh_type_modify(args) != NB_OK)
+ return NB_ERR;
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ /* blackhole type has a boolean type with default value,
+ * so no need to do any operations in destroy callback
+ */
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/onlink
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ if (static_nexthop_onlink_modify(args) != NB_OK)
+ return NB_ERR;
+
+ break;
+ }
+ return NB_OK;
+}
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ /* onlink has a boolean type with default value,
+ * so no need to do any operations in destroy callback
+ */
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+ return NB_OK;
+}
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(
+ struct nb_cb_create_args *args)
+{
+ return nexthop_mpls_label_stack_entry_create(args);
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ return nexthop_mpls_label_stack_entry_destroy(args);
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ if (static_nexthop_mpls_label_modify(args) != NB_OK)
+ return NB_ERR;
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ /*
+ * No operation is required in this call back.
+ * nexthop_mpls_label_stack_entry_destroy() will take care
+ * to reset the label vaue.
+ */
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create(
+ struct nb_cb_create_args *args)
+{
+ struct static_vrf *s_vrf;
+ struct route_node *rn;
+ struct route_node *src_rn;
+ struct prefix_ipv6 src_prefix = {};
+ struct stable_info *info;
+ afi_t afi;
+ safi_t safi = SAFI_UNICAST;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ rn = nb_running_get_entry(args->dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+ s_vrf = info->svrf;
+ yang_dnode_get_ipv6p(&src_prefix, args->dnode, "./src-prefix");
+ afi = family2afi(src_prefix.family);
+ src_rn =
+ static_add_route(afi, safi, &rn->p, &src_prefix, s_vrf);
+ if (!src_rn) {
+ flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
+ "src rn %s creation failed",
+ yang_dnode_get_string(args->dnode,
+ "./src-prefix"));
+ return NB_ERR;
+ }
+ nb_running_set_entry(args->dnode, src_rn);
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct route_node *src_rn;
+ struct route_node *rn;
+ struct stable_info *info;
+ const struct lyd_node *rn_dnode;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ src_rn = nb_running_unset_entry(args->dnode);
+ rn_dnode = yang_dnode_get_parent(args->dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+ static_del_route(src_rn, info->safi, info->svrf);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create(
+ struct nb_cb_create_args *args)
+{
+ return static_path_list_create(args);
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct route_node *rn;
+ const struct lyd_node *rn_dnode;
+ const struct lyd_node *srn_dnode;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ srn_dnode = yang_dnode_get_parent(args->dnode, "src-list");
+ rn_dnode = yang_dnode_get_parent(srn_dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+ static_path_list_destroy(args, srn_dnode, info);
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/tag
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_tag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct stable_info *info;
+ struct route_node *rn;
+ const struct lyd_node *srn_dnode;
+ const struct lyd_node *rn_dnode;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_ABORT:
+ case NB_EV_PREPARE:
+ break;
+ case NB_EV_APPLY:
+ srn_dnode = yang_dnode_get_parent(args->dnode, "src-list");
+ rn_dnode = yang_dnode_get_parent(srn_dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+ static_path_list_tag_modify(args, srn_dnode, info);
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/table-id
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_table_id_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct route_node *rn;
+ const struct lyd_node *rn_dnode;
+ const struct lyd_node *src_dnode;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (static_path_list_tableid_modify(args, NULL, NULL) != NB_OK)
+ return NB_ERR_VALIDATION;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ src_dnode = yang_dnode_get_parent(args->dnode, "src-list");
+ rn_dnode = yang_dnode_get_parent(src_dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+
+ if (static_path_list_tableid_modify(args, src_dnode, info)
+ != NB_OK)
+ return NB_ERR_VALIDATION;
+
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create(
+ struct nb_cb_create_args *args)
+{
+ struct route_node *rn;
+ const struct lyd_node *rn_dnode;
+ const struct lyd_node *src_dnode;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ rn_dnode = yang_dnode_get_parent(args->dnode, "route-list");
+ if (static_nexthop_create(args, rn_dnode, NULL) != NB_OK)
+ return NB_ERR_VALIDATION;
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ src_dnode = yang_dnode_get_parent(args->dnode, "src-list");
+ rn_dnode = yang_dnode_get_parent(src_dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+
+ if (static_nexthop_create(args, src_dnode, info) != NB_OK)
+ return NB_ERR_VALIDATION;
+
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct route_node *rn;
+ const struct lyd_node *rn_dnode;
+ const struct lyd_node *src_dnode;
+ struct stable_info *info;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ src_dnode = yang_dnode_get_parent(args->dnode, "src-list");
+ rn_dnode = yang_dnode_get_parent(src_dnode, "route-list");
+ rn = nb_running_get_entry(rn_dnode, NULL, true);
+ info = route_table_get_info(rn->table);
+
+ if (static_nexthop_destroy(args, rn_dnode, info) != NB_OK)
+ return NB_ERR;
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/bh-type
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ if (static_nexthop_bh_type_modify(args) != NB_OK)
+ return NB_ERR;
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_bh_type_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ /* blackhole type has a boolean type with default value,
+ * so no need to do any operations in destroy callback
+ */
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/onlink
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ if (static_nexthop_onlink_modify(args) != NB_OK)
+ return NB_ERR;
+
+ break;
+ }
+ return NB_OK;
+}
+
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_onlink_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ /* onlink has a boolean type with default value,
+ * so no need to do any operations in destroy callback
+ */
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(
+ struct nb_cb_create_args *args)
+{
+ return nexthop_mpls_label_stack_entry_create(args);
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ return nexthop_mpls_label_stack_entry_destroy(args);
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ if (static_nexthop_mpls_label_modify(args) != NB_OK)
+ return NB_ERR;
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ /*
+ * No operation is required in this call back.
+ * nexthop_mpls_label_stack_entry_destroy() will take care
+ * to reset the label vaue.
+ */
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class
+ */
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_modify(
+ struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
diff --git a/staticd/static_nht.c b/staticd/static_nht.c
index 1a2ddd7f0..feb6e0f99 100644
--- a/staticd/static_nht.c
+++ b/staticd/static_nht.c
@@ -30,33 +30,33 @@
#include "static_zebra.h"
#include "static_nht.h"
-static void static_nht_update_rn(struct route_node *rn,
- struct prefix *nhp, uint32_t nh_num,
- vrf_id_t nh_vrf_id, struct vrf *vrf,
- safi_t safi)
+static void static_nht_update_path(struct route_node *rn,
+ struct static_path *pn, struct prefix *nhp,
+ uint32_t nh_num, vrf_id_t nh_vrf_id,
+ struct vrf *vrf, safi_t safi)
{
- struct static_route *si;
+ struct static_nexthop *nh;
- for (si = rn->info; si; si = si->next) {
- if (si->nh_vrf_id != nh_vrf_id)
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ if (nh->nh_vrf_id != nh_vrf_id)
continue;
- if (si->type != STATIC_IPV4_GATEWAY
- && si->type != STATIC_IPV4_GATEWAY_IFNAME
- && si->type != STATIC_IPV6_GATEWAY
- && si->type != STATIC_IPV6_GATEWAY_IFNAME)
+ if (nh->type != STATIC_IPV4_GATEWAY
+ && nh->type != STATIC_IPV4_GATEWAY_IFNAME
+ && nh->type != STATIC_IPV6_GATEWAY
+ && nh->type != STATIC_IPV6_GATEWAY_IFNAME)
continue;
if (nhp->family == AF_INET
- && nhp->u.prefix4.s_addr == si->addr.ipv4.s_addr)
- si->nh_valid = !!nh_num;
+ && nhp->u.prefix4.s_addr == nh->addr.ipv4.s_addr)
+ nh->nh_valid = !!nh_num;
if (nhp->family == AF_INET6
- && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) == 0)
- si->nh_valid = !!nh_num;
+ && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, 16) == 0)
+ nh->nh_valid = !!nh_num;
- if (si->state == STATIC_START)
- static_zebra_route_add(rn, si, vrf->vrf_id, safi, true);
+ if (nh->state == STATIC_START)
+ static_zebra_route_add(rn, pn, safi, true);
}
}
@@ -67,6 +67,8 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
struct route_table *stable;
struct static_vrf *svrf;
struct route_node *rn;
+ struct static_path *pn;
+ struct static_route_info *si;
svrf = vrf->info;
if (!svrf)
@@ -78,17 +80,26 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
if (sp) {
rn = srcdest_rnode_lookup(stable, sp, NULL);
- if (rn) {
- static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id,
- vrf, safi);
+ if (rn && rn->info) {
+ si = static_route_info_from_rnode(rn);
+ frr_each(static_path_list, &si->path_list, pn) {
+ static_nht_update_path(rn, pn, nhp, nh_num,
+ nh_vrf_id, vrf, safi);
+ }
route_unlock_node(rn);
}
return;
}
- for (rn = route_top(stable); rn; rn = route_next(rn))
- static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id, vrf, safi);
-
+ for (rn = route_top(stable); rn; rn = route_next(rn)) {
+ si = static_route_info_from_rnode(rn);
+ if (!si)
+ continue;
+ frr_each(static_path_list, &si->path_list, pn) {
+ static_nht_update_path(rn, pn, nhp, nh_num, nh_vrf_id,
+ vrf, safi);
+ }
+ }
}
void static_nht_update(struct prefix *sp, struct prefix *nhp,
@@ -111,8 +122,10 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
{
struct static_vrf *svrf;
struct route_table *stable;
- struct static_route *si;
+ struct static_nexthop *nh;
+ struct static_path *pn;
struct route_node *rn;
+ struct static_route_info *si;
svrf = vrf->info;
if (!svrf)
@@ -123,25 +136,33 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
return;
for (rn = route_top(stable); rn; rn = route_next(rn)) {
- for (si = rn->info; si; si = si->next) {
- if (si->nh_vrf_id != nh_vrf_id)
- continue;
-
- if (nhp->family == AF_INET
- && nhp->u.prefix4.s_addr != si->addr.ipv4.s_addr)
- continue;
-
- if (nhp->family == AF_INET6
- && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) != 0)
- continue;
-
- /*
- * We've been told that a nexthop we depend
- * on has changed in some manner, so reset
- * the state machine to allow us to start
- * over.
- */
- si->state = STATIC_START;
+ si = static_route_info_from_rnode(rn);
+ if (!si)
+ continue;
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ if (nh->nh_vrf_id != nh_vrf_id)
+ continue;
+
+ if (nhp->family == AF_INET
+ && nhp->u.prefix4.s_addr
+ != nh->addr.ipv4.s_addr)
+ continue;
+
+ if (nhp->family == AF_INET6
+ && memcmp(&nhp->u.prefix6, &nh->addr.ipv6,
+ 16)
+ != 0)
+ continue;
+
+ /*
+ * We've been told that a nexthop we
+ * depend on has changed in some manner,
+ * so reset the state machine to allow
+ * us to start over.
+ */
+ nh->state = STATIC_START;
+ }
}
}
}
@@ -164,8 +185,10 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
{
struct static_vrf *svrf;
struct route_table *stable;
- struct static_route *si;
struct route_node *rn;
+ struct static_nexthop *nh;
+ struct static_path *pn;
+ struct static_route_info *si;
svrf = vrf->info;
if (!svrf)
@@ -178,9 +201,14 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
rn = srcdest_rnode_lookup(stable, sp, NULL);
if (!rn)
return;
-
- for (si = rn->info; si; si = si->next)
- si->state = state;
+ si = rn->info;
+ if (si) {
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ nh->state = state;
+ }
+ }
+ }
route_unlock_node(rn);
}
diff --git a/staticd/static_routes.c b/staticd/static_routes.c
index e8d6a4289..829fe6cd6 100644
--- a/staticd/static_routes.c
+++ b/staticd/static_routes.c
@@ -32,256 +32,328 @@
#include "static_memory.h"
#include "static_zebra.h"
-/* Install static route into rib. */
-static void static_install_route(struct route_node *rn,
- struct static_route *si_changed, safi_t safi)
-{
- struct static_route *si;
+DEFINE_MTYPE_STATIC(STATIC, STATIC_ROUTE, "Static Route Info");
+DEFINE_MTYPE(STATIC, STATIC_PATH, "Static Path");
- for (si = rn->info; si; si = si->next)
- static_zebra_nht_register(rn, si, true);
+/* Install static path into rib. */
+void static_install_path(struct route_node *rn, struct static_path *pn,
+ safi_t safi, struct static_vrf *svrf)
+{
+ struct static_nexthop *nh;
- si = rn->info;
- if (si)
- static_zebra_route_add(rn, si_changed, si->vrf_id, safi, true);
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh)
+ static_zebra_nht_register(rn, nh, true);
+ if (static_nexthop_list_count(&pn->nexthop_list) && svrf && svrf->vrf)
+ static_zebra_route_add(rn, pn, safi, true);
}
-/* Uninstall static route from RIB. */
-static void static_uninstall_route(vrf_id_t vrf_id, safi_t safi,
- struct route_node *rn,
- struct static_route *si_changed)
+/* Uninstall static path from RIB. */
+static void static_uninstall_path(struct route_node *rn, struct static_path *pn,
+ safi_t safi, struct static_vrf *svrf)
{
-
- if (rn->info)
- static_zebra_route_add(rn, si_changed, vrf_id, safi, true);
+ if (static_nexthop_list_count(&pn->nexthop_list))
+ static_zebra_route_add(rn, pn, safi, true);
else
- static_zebra_route_add(rn, si_changed, vrf_id, safi, false);
+ static_zebra_route_add(rn, pn, safi, false);
}
-int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
- struct prefix_ipv6 *src_p, union g_addr *gate,
- const char *ifname, enum static_blackhole_type bh_type,
- route_tag_t tag, uint8_t distance, struct static_vrf *svrf,
- struct static_vrf *nh_svrf,
- struct static_nh_label *snh_label, uint32_t table_id,
- bool onlink)
+struct route_node *static_add_route(afi_t afi, safi_t safi, struct prefix *p,
+ struct prefix_ipv6 *src_p,
+ struct static_vrf *svrf)
{
struct route_node *rn;
- struct static_route *si;
- struct static_route *pp;
- struct static_route *cp;
- struct static_route *update = NULL;
+ struct static_route_info *si;
struct route_table *stable = svrf->stable[afi][safi];
- struct interface *ifp;
if (!stable)
- return -1;
-
- if (!gate && (type == STATIC_IPV4_GATEWAY
- || type == STATIC_IPV4_GATEWAY_IFNAME
- || type == STATIC_IPV6_GATEWAY
- || type == STATIC_IPV6_GATEWAY_IFNAME))
- return -1;
-
- if (!ifname
- && (type == STATIC_IFNAME || type == STATIC_IPV4_GATEWAY_IFNAME
- || type == STATIC_IPV6_GATEWAY_IFNAME))
- return -1;
+ return NULL;
/* Lookup static route prefix. */
rn = srcdest_rnode_get(stable, p, src_p);
- /* Do nothing if there is a same static route. */
- for (si = rn->info; si; si = si->next) {
- if (type == si->type
- && (!gate
- || ((afi == AFI_IP
- && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
- || (afi == AFI_IP6
- && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
- && (!strcmp(ifname ? ifname : "", si->ifname))
- && nh_svrf->vrf->vrf_id == si->nh_vrf_id) {
- if ((distance == si->distance) && (tag == si->tag)
- && (table_id == si->table_id)
- && !memcmp(&si->snh_label, snh_label,
- sizeof(struct static_nh_label))
- && si->bh_type == bh_type && si->onlink == onlink) {
- route_unlock_node(rn);
- return 0;
- }
- update = si;
+ si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route_info));
+ static_route_info_init(si);
+
+ rn->info = si;
+
+ /* Mark as having FRR configuration */
+ vrf_set_user_cfged(svrf->vrf);
+
+ return rn;
+}
+
+/* To delete the srcnodes */
+static void static_del_src_route(struct route_node *rn, safi_t safi,
+ struct static_vrf *svrf)
+{
+ struct static_path *pn;
+ struct static_route_info *si;
+
+ si = rn->info;
+
+ frr_each_safe(static_path_list, &si->path_list, pn) {
+ static_del_path(rn, pn, safi, svrf);
+ }
+
+ XFREE(MTYPE_STATIC_ROUTE, rn->info);
+ route_unlock_node(rn);
+ /* If no other FRR config for this VRF, mark accordingly. */
+ if (!static_vrf_has_config(svrf))
+ vrf_reset_user_cfged(svrf->vrf);
+}
+
+void static_del_route(struct route_node *rn, safi_t safi,
+ struct static_vrf *svrf)
+{
+ struct static_path *pn;
+ struct static_route_info *si;
+ struct route_table *src_table;
+ struct route_node *src_node;
+
+ si = rn->info;
+
+ frr_each_safe(static_path_list, &si->path_list, pn) {
+ static_del_path(rn, pn, safi, svrf);
+ }
+
+ /* clean up for dst table */
+ src_table = srcdest_srcnode_table(rn);
+ if (src_table) {
+ /* This means the route_node is part of the top hierarchy
+ * and refers to a destination prefix.
+ */
+ for (src_node = route_top(src_table); src_node;
+ src_node = route_next(src_node)) {
+ static_del_src_route(src_node, safi, svrf);
}
}
+ XFREE(MTYPE_STATIC_ROUTE, rn->info);
+ route_unlock_node(rn);
+ /* If no other FRR config for this VRF, mark accordingly. */
+ if (!static_vrf_has_config(svrf))
+ vrf_reset_user_cfged(svrf->vrf);
+}
+
+bool static_add_nexthop_validate(struct static_vrf *svrf, static_types type,
+ struct ipaddr *ipaddr)
+{
+ switch (type) {
+ case STATIC_IPV4_GATEWAY:
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ if (if_lookup_exact_address(&ipaddr->ipaddr_v4, AF_INET,
+ svrf->vrf->vrf_id))
+ return false;
+ break;
+ case STATIC_IPV6_GATEWAY:
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ if (if_lookup_exact_address(&ipaddr->ipaddr_v6, AF_INET6,
+ svrf->vrf->vrf_id))
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+struct static_path *static_add_path(struct route_node *rn, uint8_t distance)
+{
+ struct static_path *pn;
+ struct static_route_info *si;
+
+ route_lock_node(rn);
+
+ /* Make new static route structure. */
+ pn = XCALLOC(MTYPE_STATIC_PATH, sizeof(struct static_path));
+
+ pn->distance = distance;
+ static_nexthop_list_init(&(pn->nexthop_list));
+
+ si = rn->info;
+ static_path_list_add_head(&(si->path_list), pn);
+
+ return pn;
+}
+
+void static_del_path(struct route_node *rn, struct static_path *pn, safi_t safi,
+ struct static_vrf *svrf)
+{
+ struct static_route_info *si;
+ struct static_nexthop *nh;
+
+ si = rn->info;
+
+ static_path_list_del(&si->path_list, pn);
+
+ frr_each_safe(static_nexthop_list, &pn->nexthop_list, nh) {
+ static_delete_nexthop(rn, pn, safi, svrf, nh);
+ }
+
+ route_unlock_node(rn);
+
+ XFREE(MTYPE_STATIC_PATH, pn);
+}
+
+struct static_nexthop *
+static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi,
+ struct static_vrf *svrf, static_types type,
+ struct ipaddr *ipaddr, const char *ifname,
+ const char *nh_vrf)
+{
+ struct static_nexthop *nh;
+ struct static_vrf *nh_svrf;
+ struct interface *ifp;
+ struct static_nexthop *cp;
+
+ route_lock_node(rn);
+
+ nh_svrf = static_vty_get_unknown_vrf(nh_vrf);
- /* Distance or tag or label changed, delete existing first. */
- if (update)
- static_delete_route(afi, safi, type, p, src_p, gate, ifname,
- update->tag, update->distance, svrf,
- &update->snh_label, table_id);
+ if (!nh_svrf)
+ return NULL;
/* Make new static route structure. */
- si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
-
- si->type = type;
- si->distance = distance;
- si->bh_type = bh_type;
- si->tag = tag;
- si->vrf_id = svrf->vrf->vrf_id;
- si->nh_vrf_id = nh_svrf->vrf->vrf_id;
- strlcpy(si->nh_vrfname, nh_svrf->vrf->name, sizeof(si->nh_vrfname));
- si->table_id = table_id;
- si->onlink = onlink;
+ nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
+
+ nh->type = type;
+
+ nh->nh_vrf_id = nh_svrf->vrf->vrf_id;
+ strlcpy(nh->nh_vrfname, nh_svrf->vrf->name, sizeof(nh->nh_vrfname));
if (ifname)
- strlcpy(si->ifname, ifname, sizeof(si->ifname));
- si->ifindex = IFINDEX_INTERNAL;
+ strlcpy(nh->ifname, ifname, sizeof(nh->ifname));
+ nh->ifindex = IFINDEX_INTERNAL;
switch (type) {
case STATIC_IPV4_GATEWAY:
case STATIC_IPV4_GATEWAY_IFNAME:
- si->addr.ipv4 = gate->ipv4;
+ nh->addr.ipv4 = ipaddr->ipaddr_v4;
break;
case STATIC_IPV6_GATEWAY:
case STATIC_IPV6_GATEWAY_IFNAME:
- si->addr.ipv6 = gate->ipv6;
+ nh->addr.ipv6 = ipaddr->ipaddr_v6;
break;
- case STATIC_IFNAME:
+ default:
break;
}
-
- /* Save labels, if any. */
- memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label));
-
/*
* Add new static route information to the tree with sort by
- * distance value and gateway address.
+ * gateway address.
*/
- for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) {
- if (si->distance < cp->distance)
- break;
- if (si->distance > cp->distance)
- continue;
- if (si->type == STATIC_IPV4_GATEWAY
+ frr_each(static_nexthop_list, &pn->nexthop_list, cp) {
+ if (nh->type == STATIC_IPV4_GATEWAY
&& cp->type == STATIC_IPV4_GATEWAY) {
- if (ntohl(si->addr.ipv4.s_addr)
+ if (ntohl(nh->addr.ipv4.s_addr)
< ntohl(cp->addr.ipv4.s_addr))
break;
- if (ntohl(si->addr.ipv4.s_addr)
+ if (ntohl(nh->addr.ipv4.s_addr)
> ntohl(cp->addr.ipv4.s_addr))
continue;
}
}
+ static_nexthop_list_add_after(&(pn->nexthop_list), cp, nh);
- /* Make linked list. */
- if (pp)
- pp->next = si;
- else
- rn->info = si;
- if (cp)
- cp->prev = si;
- si->prev = pp;
- si->next = cp;
+ if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN)
+ return nh;
/* check whether interface exists in system & install if it does */
- switch (si->type) {
+ switch (nh->type) {
case STATIC_IPV4_GATEWAY:
case STATIC_IPV6_GATEWAY:
- static_zebra_nht_register(rn, si, true);
break;
case STATIC_IPV4_GATEWAY_IFNAME:
case STATIC_IPV6_GATEWAY_IFNAME:
- ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
+ ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
- si->ifindex = ifp->ifindex;
+ nh->ifindex = ifp->ifindex;
else
- zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
- ifname);
+ zlog_warn(
+ "Static Route using %s interface not installed because the interface does not exist in specified vrf",
+ ifname);
- static_zebra_nht_register(rn, si, true);
break;
case STATIC_BLACKHOLE:
- static_install_route(rn, si, safi);
break;
case STATIC_IFNAME:
ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
- si->ifindex = ifp->ifindex;
- static_install_route(rn, si, safi);
+ nh->ifindex = ifp->ifindex;
} else
- zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
- ifname);
-
+ zlog_warn(
+ "Static Route using %s interface not installed because the interface does not exist in specified vrf",
+ ifname);
break;
}
- return 1;
+ return nh;
}
-int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
- struct prefix_ipv6 *src_p, union g_addr *gate,
- const char *ifname, route_tag_t tag, uint8_t distance,
- struct static_vrf *svrf,
- struct static_nh_label *snh_label,
- uint32_t table_id)
+void static_install_nexthop(struct route_node *rn, struct static_path *pn,
+ struct static_nexthop *nh, safi_t safi,
+ struct static_vrf *svrf, const char *ifname,
+ static_types type, const char *nh_vrf)
{
- struct route_node *rn;
- struct static_route *si;
- struct route_table *stable;
+ struct static_vrf *nh_svrf;
+ struct interface *ifp;
- /* Lookup table. */
- stable = static_vrf_static_table(afi, safi, svrf);
- if (!stable)
- return -1;
+ nh_svrf = static_vty_get_unknown_vrf(nh_vrf);
- /* Lookup static route prefix. */
- rn = srcdest_rnode_lookup(stable, p, src_p);
- if (!rn)
- return 0;
-
- /* Find same static route is the tree */
- for (si = rn->info; si; si = si->next)
- if (type == si->type
- && (!gate
- || ((afi == AFI_IP
- && IPV4_ADDR_SAME(&gate->ipv4, &si->addr.ipv4))
- || (afi == AFI_IP6
- && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
- && (!strcmp(ifname ? ifname : "", si->ifname))
- && (!tag || (tag == si->tag))
- && (table_id == si->table_id)
- && (!snh_label->num_labels
- || !memcmp(&si->snh_label, snh_label,
- sizeof(struct static_nh_label))))
- break;
-
- /* Can't find static route. */
- if (!si) {
- route_unlock_node(rn);
- return 0;
+ if (!nh_svrf)
+ return;
+
+ if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN)
+ return;
+
+ /* check whether interface exists in system & install if it does */
+ switch (nh->type) {
+ case STATIC_IPV4_GATEWAY:
+ case STATIC_IPV6_GATEWAY:
+ if (!static_zebra_nh_update(rn, nh))
+ static_zebra_nht_register(rn, nh, true);
+ break;
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ if (!static_zebra_nh_update(rn, nh))
+ static_zebra_nht_register(rn, nh, true);
+ break;
+ case STATIC_BLACKHOLE:
+ static_install_path(rn, pn, safi, svrf);
+ break;
+ case STATIC_IFNAME:
+ ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
+ if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
+ static_install_path(rn, pn, safi, svrf);
+
+ break;
}
+}
- static_zebra_nht_register(rn, si, false);
+int static_delete_nexthop(struct route_node *rn, struct static_path *pn,
+ safi_t safi, struct static_vrf *svrf,
+ struct static_nexthop *nh)
+{
+ struct static_vrf *nh_svrf;
- /* Unlink static route from linked list. */
- if (si->prev)
- si->prev->next = si->next;
- else
- rn->info = si->next;
- if (si->next)
- si->next->prev = si->prev;
+ nh_svrf = static_vrf_lookup_by_name(nh->nh_vrfname);
+
+ static_nexthop_list_del(&(pn->nexthop_list), nh);
+
+ if (nh_svrf->vrf->vrf_id == VRF_UNKNOWN)
+ goto EXIT;
+ static_zebra_nht_register(rn, nh, false);
/*
* If we have other si nodes then route replace
* else delete the route
*/
- static_uninstall_route(si->vrf_id, safi, rn, si);
- route_unlock_node(rn);
-
- /* Free static route configuration. */
- XFREE(MTYPE_STATIC_ROUTE, si);
+ static_uninstall_path(rn, pn, safi, svrf);
+EXIT:
route_unlock_node(rn);
+ /* Free static route configuration. */
+ XFREE(MTYPE_STATIC_NEXTHOP, nh);
return 1;
}
@@ -291,8 +363,10 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
{
struct route_table *stable;
struct route_node *rn;
- struct static_route *si;
+ struct static_nexthop *nh;
+ struct static_path *pn;
struct vrf *vrf;
+ struct static_route_info *si;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
struct static_vrf *svrf;
@@ -302,26 +376,34 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
stable = static_vrf_static_table(afi, safi, svrf);
if (!stable)
continue;
-
for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
- for (si = rn->info; si; si = si->next) {
- if (!si->ifname[0])
- continue;
- if (up) {
- if (strcmp(si->ifname, ifp->name))
- continue;
- if (si->nh_vrf_id != ifp->vrf_id)
- continue;
- si->ifindex = ifp->ifindex;
- } else {
- if (si->ifindex != ifp->ifindex)
- continue;
- if (si->nh_vrf_id != ifp->vrf_id)
+ si = static_route_info_from_rnode(rn);
+ if (!si)
+ continue;
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list,
+ &pn->nexthop_list, nh) {
+ if (!nh->ifname[0])
continue;
- si->ifindex = IFINDEX_INTERNAL;
+ if (up) {
+ if (strcmp(nh->ifname,
+ ifp->name))
+ continue;
+ if (nh->nh_vrf_id
+ != ifp->vrf_id)
+ continue;
+ nh->ifindex = ifp->ifindex;
+ } else {
+ if (nh->ifindex != ifp->ifindex)
+ continue;
+ if (nh->nh_vrf_id
+ != ifp->vrf_id)
+ continue;
+ nh->ifindex = IFINDEX_INTERNAL;
+ }
+
+ static_install_path(rn, pn, safi, svrf);
}
-
- static_install_route(rn, si, safi);
}
}
}
@@ -343,26 +425,34 @@ static void static_fixup_vrf(struct static_vrf *svrf,
struct route_table *stable, afi_t afi, safi_t safi)
{
struct route_node *rn;
- struct static_route *si;
+ struct static_nexthop *nh;
struct interface *ifp;
+ struct static_path *pn;
+ struct static_route_info *si;
for (rn = route_top(stable); rn; rn = route_next(rn)) {
- for (si = rn->info; si; si = si->next) {
- if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
- continue;
-
- si->nh_vrf_id = svrf->vrf->vrf_id;
- si->nh_registered = false;
- if (si->ifindex) {
- ifp = if_lookup_by_name(si->ifname,
- si->nh_vrf_id);
- if (ifp)
- si->ifindex = ifp->ifindex;
- else
+ si = static_route_info_from_rnode(rn);
+ if (!si)
+ continue;
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ if (strcmp(svrf->vrf->name, nh->nh_vrfname)
+ != 0)
continue;
- }
- static_install_route(rn, si, safi);
+ nh->nh_vrf_id = svrf->vrf->vrf_id;
+ nh->nh_registered = false;
+ if (nh->ifindex) {
+ ifp = if_lookup_by_name(nh->ifname,
+ nh->nh_vrf_id);
+ if (ifp)
+ nh->ifindex = ifp->ifindex;
+ else
+ continue;
+ }
+
+ static_install_path(rn, pn, safi, svrf);
+ }
}
}
}
@@ -377,26 +467,31 @@ static void static_fixup_vrf(struct static_vrf *svrf,
* safi -> the safi in question
*/
static void static_enable_vrf(struct static_vrf *svrf,
- struct route_table *stable,
- afi_t afi, safi_t safi)
+ struct route_table *stable, afi_t afi,
+ safi_t safi)
{
struct route_node *rn;
- struct static_route *si;
+ struct static_nexthop *nh;
struct interface *ifp;
- struct vrf *vrf = svrf->vrf;
+ struct static_path *pn;
+ struct static_route_info *si;
for (rn = route_top(stable); rn; rn = route_next(rn)) {
- for (si = rn->info; si; si = si->next) {
- si->vrf_id = vrf->vrf_id;
- if (si->ifindex) {
- ifp = if_lookup_by_name(si->ifname,
- si->nh_vrf_id);
- if (ifp)
- si->ifindex = ifp->ifindex;
- else
- continue;
+ si = static_route_info_from_rnode(rn);
+ if (!si)
+ continue;
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ if (nh->ifindex) {
+ ifp = if_lookup_by_name(nh->ifname,
+ nh->nh_vrf_id);
+ if (ifp)
+ nh->ifindex = ifp->ifindex;
+ else
+ continue;
+ }
+ static_install_path(rn, pn, safi, svrf);
}
- static_install_route(rn, si, safi);
}
}
}
@@ -452,14 +547,22 @@ static void static_cleanup_vrf(struct static_vrf *svrf,
afi_t afi, safi_t safi)
{
struct route_node *rn;
- struct static_route *si;
+ struct static_nexthop *nh;
+ struct static_path *pn;
+ struct static_route_info *si;
for (rn = route_top(stable); rn; rn = route_next(rn)) {
- for (si = rn->info; si; si = si->next) {
- if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
- continue;
+ si = static_route_info_from_rnode(rn);
+ if (!si)
+ continue;
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ if (strcmp(svrf->vrf->name, nh->nh_vrfname)
+ != 0)
+ continue;
- static_uninstall_route(si->vrf_id, safi, rn, si);
+ static_uninstall_path(rn, pn, safi, svrf);
+ }
}
}
}
@@ -476,11 +579,23 @@ static void static_disable_vrf(struct route_table *stable,
afi_t afi, safi_t safi)
{
struct route_node *rn;
- struct static_route *si;
+ struct static_nexthop *nh;
+ struct static_path *pn;
+ struct stable_info *info;
+ struct static_route_info *si;
- for (rn = route_top(stable); rn; rn = route_next(rn))
- for (si = rn->info; si; si = si->next)
- static_uninstall_route(si->vrf_id, safi, rn, si);
+ info = route_table_get_info(stable);
+
+ for (rn = route_top(stable); rn; rn = route_next(rn)) {
+ si = static_route_info_from_rnode(rn);
+ if (!si)
+ continue;
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ static_uninstall_path(rn, pn, safi, info->svrf);
+ }
+ }
+ }
}
/*
@@ -535,17 +650,27 @@ static void static_fixup_intf_nh(struct route_table *stable,
afi_t afi, safi_t safi)
{
struct route_node *rn;
- struct static_route *si;
+ struct stable_info *info;
+ struct static_nexthop *nh;
+ struct static_path *pn;
+ struct static_route_info *si;
+
+ info = route_table_get_info(stable);
for (rn = route_top(stable); rn; rn = route_next(rn)) {
- for (si = rn->info; si; si = si->next) {
- if (si->nh_vrf_id != ifp->vrf_id)
- continue;
+ si = static_route_info_from_rnode(rn);
+ if (!si)
+ continue;
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ if (nh->nh_vrf_id != ifp->vrf_id)
+ continue;
- if (si->ifindex != ifp->ifindex)
- continue;
+ if (nh->ifindex != ifp->ifindex)
+ continue;
- static_install_route(rn, si, safi);
+ static_install_path(rn, pn, safi, info->svrf);
+ }
}
}
}
@@ -589,3 +714,40 @@ void static_ifindex_update(struct interface *ifp, bool up)
static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
}
+
+void static_get_nh_type(static_types stype, char *type, size_t size)
+{
+ switch (stype) {
+ case STATIC_IFNAME:
+ strlcpy(type, "ifindex", size);
+ break;
+ case STATIC_IPV4_GATEWAY:
+ strlcpy(type, "ip4", size);
+ break;
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ strlcpy(type, "ip4-ifindex", size);
+ break;
+ case STATIC_BLACKHOLE:
+ strlcpy(type, "blackhole", size);
+ break;
+ case STATIC_IPV6_GATEWAY:
+ strlcpy(type, "ip6", size);
+ break;
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ strlcpy(type, "ip6-ifindex", size);
+ break;
+ };
+}
+
+struct stable_info *static_get_stable_info(struct route_node *rn)
+{
+ struct route_table *table;
+
+ table = srcdest_rnode_table(rn);
+ return table->info;
+}
+
+void static_route_info_init(struct static_route_info *si)
+{
+ static_path_list_init(&(si->path_list));
+}
diff --git a/staticd/static_routes.h b/staticd/static_routes.h
index 6414947b1..89ef54402 100644
--- a/staticd/static_routes.h
+++ b/staticd/static_routes.h
@@ -21,6 +21,7 @@
#define __STATIC_ROUTES_H__
#include "lib/mpls.h"
+#include "table.h"
/* Static route label information */
struct static_nh_label {
@@ -35,13 +36,17 @@ enum static_blackhole_type {
STATIC_BLACKHOLE_REJECT
};
+/*
+ * The order for below macros should be in sync with
+ * yang model typedef nexthop-type
+ */
typedef enum {
- STATIC_IFNAME,
+ STATIC_IFNAME = 1,
STATIC_IPV4_GATEWAY,
STATIC_IPV4_GATEWAY_IFNAME,
- STATIC_BLACKHOLE,
STATIC_IPV6_GATEWAY,
STATIC_IPV6_GATEWAY_IFNAME,
+ STATIC_BLACKHOLE,
} static_types;
/*
@@ -64,14 +69,37 @@ enum static_install_states {
STATIC_NOT_INSTALLED,
};
+PREDECL_DLIST(static_path_list);
+PREDECL_DLIST(static_nexthop_list);
+
+/* Static route information */
+struct static_route_info {
+ /* path list */
+ struct static_path_list_head path_list;
+};
+
+/* Static path information */
+struct static_path {
+ /* Linkage for static path lists */
+ struct static_path_list_item list;
+ /* Administrative distance. */
+ uint8_t distance;
+ /* Tag */
+ route_tag_t tag;
+ /* Table-id */
+ uint32_t table_id;
+ /* Nexthop list */
+ struct static_nexthop_list_head nexthop_list;
+};
+
+DECLARE_DLIST(static_path_list, struct static_path, list);
+
/* Static route information. */
-struct static_route {
+struct static_nexthop {
/* For linked list. */
- struct static_route *prev;
- struct static_route *next;
+ struct static_nexthop_list_item list;
/* VRF identifier. */
- vrf_id_t vrf_id;
vrf_id_t nh_vrf_id;
char nh_vrfname[VRF_NAMSIZ + 1];
@@ -81,12 +109,6 @@ struct static_route {
*/
enum static_install_states state;
- /* Administrative distance. */
- uint8_t distance;
-
- /* Tag */
- route_tag_t tag;
-
/* Flag for this static route's type. */
static_types type;
@@ -104,8 +126,6 @@ struct static_route {
/* Label information */
struct static_nh_label snh_label;
- uint32_t table_id;
-
/*
* Whether to pretend the nexthop is directly attached to the specified
* link. Only meaningful when both a gateway address and interface name
@@ -114,32 +134,64 @@ struct static_route {
bool onlink;
};
+DECLARE_DLIST(static_nexthop_list, struct static_nexthop, list);
+
+
+/*
+ * rib_dest_from_rnode
+ */
+static inline struct static_route_info *
+static_route_info_from_rnode(struct route_node *rn)
+{
+ return (struct static_route_info *)(rn->info);
+}
+
extern bool mpls_enabled;
extern struct zebra_privs_t static_privs;
void static_fixup_vrf_ids(struct static_vrf *svrf);
-extern int static_add_route(afi_t afi, safi_t safi, uint8_t type,
- struct prefix *p, struct prefix_ipv6 *src_p,
- union g_addr *gate, const char *ifname,
- enum static_blackhole_type bh_type, route_tag_t tag,
- uint8_t distance, struct static_vrf *svrf,
- struct static_vrf *nh_svrf,
- struct static_nh_label *snh_label,
- uint32_t table_id, bool onlink);
-
-extern int static_delete_route(afi_t afi, safi_t safi, uint8_t type,
- struct prefix *p, struct prefix_ipv6 *src_p,
- union g_addr *gate, const char *ifname,
- route_tag_t tag, uint8_t distance,
- struct static_vrf *svrf,
- struct static_nh_label *snh_label,
- uint32_t table_id);
+extern struct static_nexthop *
+static_add_nexthop(struct route_node *rn, struct static_path *pn, safi_t safi,
+ struct static_vrf *svrf, static_types type,
+ struct ipaddr *ipaddr, const char *ifname,
+ const char *nh_vrf);
+extern void static_install_nexthop(struct route_node *rn,
+ struct static_path *pn,
+ struct static_nexthop *nh, safi_t safi,
+ struct static_vrf *svrf, const char *ifname,
+ static_types type, const char *nh_vrf);
+
+extern int static_delete_nexthop(struct route_node *rn, struct static_path *pn,
+ safi_t safi, struct static_vrf *svrf,
+ struct static_nexthop *nh);
extern void static_cleanup_vrf_ids(struct static_vrf *disable_svrf);
extern void static_install_intf_nh(struct interface *ifp);
extern void static_ifindex_update(struct interface *ifp, bool up);
+
+extern void static_install_path(struct route_node *rn, struct static_path *pn,
+ safi_t safi, struct static_vrf *svrf);
+
+extern struct route_node *static_add_route(afi_t afi, safi_t safi,
+ struct prefix *p,
+ struct prefix_ipv6 *src_p,
+ struct static_vrf *svrf);
+extern void static_del_route(struct route_node *rn, safi_t safi,
+ struct static_vrf *svrf);
+
+extern struct static_path *static_add_path(struct route_node *rn,
+ uint8_t distance);
+extern void static_del_path(struct route_node *rn, struct static_path *pn,
+ safi_t safi, struct static_vrf *svrf);
+
+extern void static_get_nh_type(static_types stype, char *type, size_t size);
+extern bool static_add_nexthop_validate(struct static_vrf *svrf,
+ static_types type,
+ struct ipaddr *ipaddr);
+extern struct stable_info *static_get_stable_info(struct route_node *rn);
+extern void static_route_info_init(struct static_route_info *si);
#endif
diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c
index 6c065932a..39b86787f 100644
--- a/staticd/static_vrf.c
+++ b/staticd/static_vrf.c
@@ -30,26 +30,39 @@
#include "static_zebra.h"
#include "static_vty.h"
+DEFINE_MTYPE_STATIC(STATIC, STATIC_RTABLE_INFO, "Static Route Table Info");
+
static void zebra_stable_node_cleanup(struct route_table *table,
struct route_node *node)
{
- struct static_route *si, *next;
-
- if (node->info)
- for (si = node->info; si; si = next) {
- next = si->next;
- XFREE(MTYPE_STATIC_ROUTE, si);
+ struct static_nexthop *nh;
+ struct static_path *pn;
+ struct static_route_info *si;
+
+ si = node->info;
+
+ if (si) {
+ frr_each_safe(static_path_list, &si->path_list, pn) {
+ frr_each_safe(static_nexthop_list, &pn->nexthop_list,
+ nh) {
+ static_nexthop_list_del(&pn->nexthop_list, nh);
+ XFREE(MTYPE_STATIC_NEXTHOP, nh);
+ }
+ static_path_list_del(&si->path_list, pn);
+ XFREE(MTYPE_STATIC_PATH, pn);
}
+ }
}
static struct static_vrf *static_vrf_alloc(void)
{
struct route_table *table;
struct static_vrf *svrf;
+ struct stable_info *info;
safi_t safi;
afi_t afi;
- svrf = XCALLOC(MTYPE_TMP, sizeof(struct static_vrf));
+ svrf = XCALLOC(MTYPE_STATIC_RTABLE_INFO, sizeof(struct static_vrf));
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
@@ -57,6 +70,14 @@ static struct static_vrf *static_vrf_alloc(void)
table = srcdest_table_init();
else
table = route_table_init();
+
+ info = XCALLOC(MTYPE_STATIC_RTABLE_INFO,
+ sizeof(struct stable_info));
+ info->svrf = svrf;
+ info->afi = afi;
+ info->safi = safi;
+ route_table_set_info(table, info);
+
table->cleanup = zebra_stable_node_cleanup;
svrf->stable[afi][safi] = table;
}
@@ -81,12 +102,6 @@ static int static_vrf_enable(struct vrf *vrf)
static_fixup_vrf_ids(vrf->info);
- /*
- * We may have static routes that are now possible to
- * insert into the appropriate tables
- */
- static_config_install_delayed_routes(vrf->info);
-
return 0;
}
@@ -102,16 +117,19 @@ static int static_vrf_delete(struct vrf *vrf)
struct static_vrf *svrf;
safi_t safi;
afi_t afi;
+ void *info;
svrf = vrf->info;
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
table = svrf->stable[afi][safi];
+ info = route_table_get_info(table);
route_table_finish(table);
+ XFREE(MTYPE_STATIC_RTABLE_INFO, info);
svrf->stable[afi][safi] = NULL;
}
}
- XFREE(MTYPE_TMP, svrf);
+ XFREE(MTYPE_STATIC_RTABLE_INFO, svrf);
return 0;
}
@@ -210,3 +228,25 @@ void static_vrf_terminate(void)
{
vrf_terminate();
}
+
+struct static_vrf *static_vty_get_unknown_vrf(const char *vrf_name)
+{
+ struct static_vrf *svrf;
+ struct vrf *vrf;
+
+ svrf = static_vrf_lookup_by_name(vrf_name);
+
+ if (svrf)
+ return svrf;
+
+ vrf = vrf_get(VRF_UNKNOWN, vrf_name);
+ if (!vrf)
+ return NULL;
+ svrf = vrf->info;
+ if (!svrf)
+ return NULL;
+ /* Mark as having FRR configuration */
+ vrf_set_user_cfged(vrf);
+
+ return svrf;
+}
diff --git a/staticd/static_vrf.h b/staticd/static_vrf.h
index 6951e5671..12ad1b255 100644
--- a/staticd/static_vrf.h
+++ b/staticd/static_vrf.h
@@ -26,6 +26,14 @@ struct static_vrf {
struct route_table *stable[AFI_MAX][SAFI_MAX];
};
+struct stable_info {
+ struct static_vrf *svrf;
+ afi_t afi;
+ safi_t safi;
+};
+
+#define GET_STABLE_VRF_ID(info) info->svrf->vrf->vrf_id
+
struct static_vrf *static_vrf_lookup_by_name(const char *vrf_name);
struct static_vrf *static_vrf_lookup_by_id(vrf_id_t vrf_id);
@@ -36,4 +44,6 @@ void static_vrf_init(void);
struct route_table *static_vrf_static_table(afi_t afi, safi_t safi,
struct static_vrf *svrf);
extern void static_vrf_terminate(void);
+
+struct static_vrf *static_vty_get_unknown_vrf(const char *vrf_name);
#endif
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index 75bce82ee..311462db7 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -27,6 +27,10 @@
#include "table.h"
#include "srcdest_table.h"
#include "mpls.h"
+#include "northbound.h"
+#include "libfrr.h"
+#include "routing_nb.h"
+#include "northbound_cli.h"
#include "static_vrf.h"
#include "static_memory.h"
@@ -36,251 +40,43 @@
#ifndef VTYSH_EXTRACT_PL
#include "staticd/static_vty_clippy.c"
#endif
+#include "static_nb.h"
#define STATICD_STR "Static route daemon\n"
-static struct static_vrf *static_vty_get_unknown_vrf(struct vty *vty,
- const char *vrf_name)
+static int static_route_leak(struct vty *vty, const char *svrf,
+ const char *nh_svrf, afi_t afi, safi_t safi,
+ const char *negate, const char *dest_str,
+ const char *mask_str, const char *src_str,
+ const char *gate_str, const char *ifname,
+ const char *flag_str, const char *tag_str,
+ const char *distance_str, const char *label_str,
+ const char *table_str, bool onlink)
{
- struct static_vrf *svrf;
- struct vrf *vrf;
-
- svrf = static_vrf_lookup_by_name(vrf_name);
-
- if (svrf)
- return svrf;
-
- vrf = vrf_get(VRF_UNKNOWN, vrf_name);
- if (!vrf) {
- vty_out(vty, "%% Could not create vrf %s\n", vrf_name);
- return NULL;
- }
- svrf = vrf->info;
- if (!svrf) {
- vty_out(vty, "%% Could not create vrf-info %s\n",
- vrf_name);
- return NULL;
- }
- /* Mark as having FRR configuration */
- vrf_set_user_cfged(vrf);
-
- return svrf;
-}
-
-struct static_hold_route {
- char *vrf_name;
- char *nhvrf_name;
- afi_t afi;
- safi_t safi;
- char *dest_str;
- char *mask_str;
- char *src_str;
- char *gate_str;
- char *ifname;
- char *flag_str;
- char *tag_str;
- char *distance_str;
- char *label_str;
- char *table_str;
- bool onlink;
-
- /* processed & masked destination, used for config display */
- struct prefix dest;
-};
-
-static struct list *static_list;
-
-static int static_list_compare_helper(const char *s1, const char *s2)
-{
- /* extra (!s1 && !s2) to keep SA happy */
- if (s1 == s2 || (!s1 && !s2))
- return 0;
-
- if (!s1 && s2)
- return -1;
-
- if (s1 && !s2)
- return 1;
-
- return strcmp(s1, s2);
-}
-
-static void static_list_delete(struct static_hold_route *shr)
-{
- XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
- XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
- XFREE(MTYPE_STATIC_ROUTE, shr->dest_str);
- XFREE(MTYPE_STATIC_ROUTE, shr->mask_str);
- XFREE(MTYPE_STATIC_ROUTE, shr->src_str);
- XFREE(MTYPE_STATIC_ROUTE, shr->gate_str);
- XFREE(MTYPE_STATIC_ROUTE, shr->ifname);
- XFREE(MTYPE_STATIC_ROUTE, shr->flag_str);
- XFREE(MTYPE_STATIC_ROUTE, shr->tag_str);
- XFREE(MTYPE_STATIC_ROUTE, shr->distance_str);
- XFREE(MTYPE_STATIC_ROUTE, shr->label_str);
- XFREE(MTYPE_STATIC_ROUTE, shr->table_str);
-
- XFREE(MTYPE_STATIC_ROUTE, shr);
-}
-
-static int static_list_compare(void *arg1, void *arg2)
-{
- struct static_hold_route *shr1 = arg1;
- struct static_hold_route *shr2 = arg2;
int ret;
-
- ret = strcmp(shr1->vrf_name, shr2->vrf_name);
- if (ret)
- return ret;
-
- ret = strcmp(shr1->nhvrf_name, shr2->nhvrf_name);
- if (ret)
- return ret;
-
- ret = shr1->afi - shr2->afi;
- if (ret)
- return ret;
-
- ret = shr1->safi - shr2->safi;
- if (ret)
- return ret;
-
- ret = prefix_cmp(&shr1->dest, &shr2->dest);
- if (ret)
- return ret;
-
- ret = static_list_compare_helper(shr1->src_str, shr2->src_str);
- if (ret)
- return ret;
-
- ret = static_list_compare_helper(shr1->gate_str, shr2->gate_str);
- if (ret)
- return ret;
-
- ret = static_list_compare_helper(shr1->ifname, shr2->ifname);
- if (ret)
- return ret;
-
- ret = static_list_compare_helper(shr1->flag_str, shr2->flag_str);
- if (ret)
- return ret;
-
- ret = static_list_compare_helper(shr1->tag_str, shr2->tag_str);
- if (ret)
- return ret;
-
- ret = static_list_compare_helper(shr1->distance_str,
- shr2->distance_str);
- if (ret)
- return ret;
-
- ret = static_list_compare_helper(shr1->table_str,
- shr2->table_str);
- if (ret)
- return ret;
-
- return static_list_compare_helper(shr1->label_str, shr2->label_str);
-}
-
-
-/* General function for static route. */
-static int zebra_static_route_holdem(
- struct static_vrf *svrf, struct static_vrf *nh_svrf, afi_t afi,
- safi_t safi, const char *negate, struct prefix *dest,
- const char *dest_str, const char *mask_str, const char *src_str,
- const char *gate_str, const char *ifname, const char *flag_str,
- const char *tag_str, const char *distance_str, const char *label_str,
- const char *table_str, bool onlink)
-{
- struct static_hold_route *shr, *lookup;
- struct listnode *node;
-
- zlog_warn("Static Route to %s not installed currently because dependent config not fully available",
- dest_str);
-
- shr = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(*shr));
- shr->vrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, svrf->vrf->name);
- shr->nhvrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, nh_svrf->vrf->name);
- shr->afi = afi;
- shr->safi = safi;
- shr->onlink = onlink;
- if (dest)
- prefix_copy(&shr->dest, dest);
- if (dest_str)
- shr->dest_str = XSTRDUP(MTYPE_STATIC_ROUTE, dest_str);
- if (mask_str)
- shr->mask_str = XSTRDUP(MTYPE_STATIC_ROUTE, mask_str);
- if (src_str)
- shr->src_str = XSTRDUP(MTYPE_STATIC_ROUTE, src_str);
- if (gate_str)
- shr->gate_str = XSTRDUP(MTYPE_STATIC_ROUTE, gate_str);
- if (ifname)
- shr->ifname = XSTRDUP(MTYPE_STATIC_ROUTE, ifname);
- if (flag_str)
- shr->flag_str = XSTRDUP(MTYPE_STATIC_ROUTE, flag_str);
- if (tag_str)
- shr->tag_str = XSTRDUP(MTYPE_STATIC_ROUTE, tag_str);
- if (distance_str)
- shr->distance_str = XSTRDUP(MTYPE_STATIC_ROUTE, distance_str);
- if (label_str)
- shr->label_str = XSTRDUP(MTYPE_STATIC_ROUTE, label_str);
- if (table_str)
- shr->table_str = XSTRDUP(MTYPE_STATIC_ROUTE, table_str);
-
- for (ALL_LIST_ELEMENTS_RO(static_list, node, lookup)) {
- if (static_list_compare(shr, lookup) == 0)
- break;
- }
-
- if (lookup) {
- if (negate) {
- listnode_delete(static_list, lookup);
- static_list_delete(shr);
- static_list_delete(lookup);
-
- return CMD_SUCCESS;
- }
-
- /*
- * If a person enters the same line again
- * we need to silently accept it
- */
- goto shr_cleanup;
- }
-
- if (!negate) {
- listnode_add_sort(static_list, shr);
- return CMD_SUCCESS;
- }
-
- shr_cleanup:
- XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
- XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
- XFREE(MTYPE_STATIC_ROUTE, shr);
-
- return CMD_SUCCESS;
-}
-
-static int static_route_leak(
- struct vty *vty, struct static_vrf *svrf, struct static_vrf *nh_svrf,
- afi_t afi, safi_t safi, const char *negate, const char *dest_str,
- const char *mask_str, const char *src_str, const char *gate_str,
- const char *ifname, const char *flag_str, const char *tag_str,
- const char *distance_str, const char *label_str, const char *table_str,
- bool onlink)
-{
- int ret;
- uint8_t distance;
struct prefix p, src;
- struct prefix_ipv6 *src_p = NULL;
- union g_addr gate;
- union g_addr *gatep = NULL;
struct in_addr mask;
- enum static_blackhole_type bh_type = 0;
- route_tag_t tag = 0;
uint8_t type;
- struct static_nh_label snh_label;
+ const char *bh_type;
+ char xpath_prefix[XPATH_MAXLEN];
+ char xpath_nexthop[XPATH_MAXLEN];
+ char xpath_mpls[XPATH_MAXLEN];
+ char xpath_label[XPATH_MAXLEN];
+ char ab_xpath[XPATH_MAXLEN];
+ char buf_prefix[PREFIX_STRLEN];
+ char buf_src_prefix[PREFIX_STRLEN];
+ char buf_nh_type[PREFIX_STRLEN];
+ char buf_tag[PREFIX_STRLEN];
+ char buf_tableid[PREFIX_STRLEN];
+ uint8_t label_stack_id = 0;
+ const char *buf_gate_str;
+ uint8_t distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
+ route_tag_t tag = 0;
uint32_t table_id = 0;
+ const struct lyd_node *dnode;
+
+ memset(buf_src_prefix, 0, PREFIX_STRLEN);
+ memset(buf_nh_type, 0, PREFIX_STRLEN);
ret = str2prefix(dest_str, &p);
if (ret <= 0) {
@@ -322,7 +118,6 @@ static int static_route_leak(
__func__, src_str);
return CMD_WARNING_CONFIG_FAILED;
}
- src_p = (struct prefix_ipv6 *)&src;
}
break;
default:
@@ -332,29 +127,29 @@ static int static_route_leak(
/* Apply mask for given prefix. */
apply_mask(&p);
- if (svrf->vrf->vrf_id == VRF_UNKNOWN
- || nh_svrf->vrf->vrf_id == VRF_UNKNOWN) {
- vrf_set_user_cfged(svrf->vrf);
- return zebra_static_route_holdem(
- svrf, nh_svrf, afi, safi, negate, &p, dest_str,
- mask_str, src_str, gate_str, ifname, flag_str, tag_str,
- distance_str, label_str, table_str, onlink);
- }
+ prefix2str(&p, buf_prefix, sizeof(buf_prefix));
- if (table_str) {
- /* table configured. check consistent with vrf config
- */
- if (svrf->vrf->data.l.table_id != RT_TABLE_MAIN) {
- if (vty)
- vty_out(vty,
- "%% Table %s overlaps vrf table %u\n",
- table_str, svrf->vrf->data.l.table_id);
- else
- zlog_warn("%s: Table %s overlaps vrf table %u",
- __func__, table_str,
- svrf->vrf->data.l.table_id);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (src_str)
+ prefix2str(&src, buf_src_prefix, sizeof(buf_src_prefix));
+ if (gate_str)
+ buf_gate_str = gate_str;
+ else
+ buf_gate_str = "";
+
+ if (gate_str == NULL && ifname == NULL)
+ type = STATIC_BLACKHOLE;
+ else if (gate_str && ifname) {
+ if (afi == AFI_IP)
+ type = STATIC_IPV4_GATEWAY_IFNAME;
+ else
+ type = STATIC_IPV6_GATEWAY_IFNAME;
+ } else if (ifname)
+ type = STATIC_IFNAME;
+ else {
+ if (afi == AFI_IP)
+ type = STATIC_IPV4_GATEWAY;
+ else
+ type = STATIC_IPV6_GATEWAY;
}
/* Administrative distance. */
@@ -367,169 +162,156 @@ static int static_route_leak(
if (tag_str)
tag = strtoul(tag_str, NULL, 10);
- /* Labels */
- memset(&snh_label, 0, sizeof(struct static_nh_label));
- if (label_str) {
- if (!mpls_enabled) {
- if (vty)
- vty_out(vty,
- "%% MPLS not turned on in kernel, ignoring command\n");
- else
- zlog_warn(
- "%s: MPLS not turned on in kernel ignoring static route to %s",
- __func__, dest_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
- int rc = mpls_str2label(label_str, &snh_label.num_labels,
- snh_label.label);
- if (rc < 0) {
- switch (rc) {
- case -1:
- if (vty)
- vty_out(vty, "%% Malformed label(s)\n");
- else
- zlog_warn(
- "%s: Malformed labels specified for route %s",
- __func__, dest_str);
- break;
- case -2:
- if (vty)
- vty_out(vty,
- "%% Cannot use reserved label(s) (%d-%d)\n",
- MPLS_LABEL_RESERVED_MIN,
- MPLS_LABEL_RESERVED_MAX);
- else
- zlog_warn(
- "%s: Cannot use reserved labels (%d-%d) for %s",
- __func__,
- MPLS_LABEL_RESERVED_MIN,
- MPLS_LABEL_RESERVED_MAX,
- dest_str);
- break;
- case -3:
- if (vty)
- vty_out(vty,
- "%% Too many labels. Enter %d or fewer\n",
- MPLS_MAX_LABELS);
- else
- zlog_warn(
- "%s: Too many labels, Enter %d or fewer for %s",
- __func__, MPLS_MAX_LABELS,
- dest_str);
- break;
- }
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
-
/* TableID */
if (table_str)
table_id = atol(table_str);
- /* Null0 static route. */
- if (ifname != NULL) {
- if (strcasecmp(ifname, "Null0") == 0
- || strcasecmp(ifname, "reject") == 0
- || strcasecmp(ifname, "blackhole") == 0) {
- if (vty)
- vty_out(vty,
- "%% Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)\n");
- else
- zlog_warn(
- "%s: %s: Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)",
- __func__, dest_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
-
- /* Route flags */
- if (flag_str) {
- switch (flag_str[0]) {
- case 'r':
- bh_type = STATIC_BLACKHOLE_REJECT;
- break;
- case 'b':
- bh_type = STATIC_BLACKHOLE_DROP;
- break;
- case 'N':
- bh_type = STATIC_BLACKHOLE_NULL;
- break;
- default:
- if (vty)
- vty_out(vty, "%% Malformed flag %s \n",
- flag_str);
- else
- zlog_warn("%s: Malformed flag %s for %s",
- __func__, flag_str, dest_str);
- return CMD_WARNING_CONFIG_FAILED;
+ static_get_nh_type(type, buf_nh_type, PREFIX_STRLEN);
+ if (!negate) {
+ /* route + path procesing */
+ if (src_str)
+ snprintf(xpath_prefix, sizeof(xpath_prefix),
+ FRR_S_ROUTE_SRC_INFO_KEY_XPATH,
+ "frr-staticd:staticd", "staticd", svrf,
+ buf_prefix,
+ buf_src_prefix, distance);
+ else
+ snprintf(xpath_prefix, sizeof(xpath_prefix),
+ FRR_STATIC_ROUTE_INFO_KEY_XPATH,
+ "frr-staticd:staticd", "staticd", svrf,
+ buf_prefix,
+ distance);
+
+ nb_cli_enqueue_change(vty, xpath_prefix, NB_OP_CREATE, NULL);
+
+ /* Tag processing */
+ snprintf(buf_tag, sizeof(buf_tag), "%u", tag);
+ strlcpy(ab_xpath, xpath_prefix, sizeof(ab_xpath));
+ strlcat(ab_xpath, FRR_STATIC_ROUTE_PATH_TAG_XPATH,
+ sizeof(ab_xpath));
+ nb_cli_enqueue_change(vty, ab_xpath, NB_OP_MODIFY, buf_tag);
+
+ /* Table-Id processing */
+ snprintf(buf_tableid, sizeof(buf_tableid), "%u", table_id);
+ strlcpy(ab_xpath, xpath_prefix, sizeof(ab_xpath));
+ strlcat(ab_xpath, FRR_STATIC_ROUTE_PATH_TABLEID_XPATH,
+ sizeof(ab_xpath));
+ nb_cli_enqueue_change(vty, ab_xpath, NB_OP_MODIFY, buf_tableid);
+ /* nexthop processing */
+
+ snprintf(ab_xpath, sizeof(ab_xpath),
+ FRR_STATIC_ROUTE_NH_KEY_XPATH, buf_nh_type, nh_svrf,
+ buf_gate_str, ifname);
+ strlcpy(xpath_nexthop, xpath_prefix, sizeof(xpath_nexthop));
+ strlcat(xpath_nexthop, ab_xpath, sizeof(xpath_nexthop));
+ nb_cli_enqueue_change(vty, xpath_nexthop, NB_OP_CREATE, NULL);
+
+ if (type == STATIC_BLACKHOLE) {
+ strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
+ strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_BH_XPATH,
+ sizeof(ab_xpath));
+
+ /* Route flags */
+ if (flag_str) {
+ switch (flag_str[0]) {
+ case 'r':
+ bh_type = "reject";
+ break;
+ case 'b':
+ bh_type = "unspec";
+ break;
+ case 'N':
+ bh_type = "null";
+ break;
+ default:
+ bh_type = NULL;
+ break;
+ }
+ nb_cli_enqueue_change(vty, ab_xpath,
+ NB_OP_MODIFY, bh_type);
+ } else {
+ nb_cli_enqueue_change(vty, ab_xpath,
+ NB_OP_MODIFY, "null");
+ }
}
- }
-
- if (gate_str) {
- if (inet_pton(afi2family(afi), gate_str, &gate) != 1) {
- if (vty)
- vty_out(vty,
- "%% Malformed nexthop address %s\n",
- gate_str);
+ if (type == STATIC_IPV4_GATEWAY_IFNAME
+ || type == STATIC_IPV6_GATEWAY_IFNAME) {
+ strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
+ strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_ONLINK_XPATH,
+ sizeof(ab_xpath));
+
+ if (onlink)
+ nb_cli_enqueue_change(vty, ab_xpath,
+ NB_OP_MODIFY, "true");
else
- zlog_warn(
- "%s: Malformed nexthop address %s for %s",
- __func__, gate_str, dest_str);
- return CMD_WARNING_CONFIG_FAILED;
+ nb_cli_enqueue_change(vty, ab_xpath,
+ NB_OP_MODIFY, "false");
}
- gatep = &gate;
-
- if (afi == AFI_IP && !negate) {
- if (if_lookup_exact_address(&gatep->ipv4, AF_INET,
- svrf->vrf->vrf_id))
- if (vty)
- vty_out(vty,
- "%% Warning!! Local connected address is configured as Gateway IP(%s)\n",
- gate_str);
- } else if (afi == AFI_IP6 && !negate) {
- if (if_lookup_exact_address(&gatep->ipv6, AF_INET6,
- svrf->vrf->vrf_id))
- if (vty)
- vty_out(vty,
- "%% Warning!! Local connected address is configured as Gateway IPv6(%s)\n",
- gate_str);
+ if (label_str) {
+ /* copy of label string (start) */
+ char *ostr;
+ /* pointer to next segment */
+ char *nump;
+
+ strlcpy(xpath_mpls, xpath_nexthop, sizeof(xpath_mpls));
+ strlcat(xpath_mpls, FRR_STATIC_ROUTE_NH_LABEL_XPATH,
+ sizeof(xpath_mpls));
+
+ nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
+ NULL);
+
+ ostr = XSTRDUP(MTYPE_TMP, label_str);
+ while ((nump = strsep(&ostr, "/")) != NULL) {
+ snprintf(ab_xpath, sizeof(ab_xpath),
+ FRR_STATIC_ROUTE_NHLB_KEY_XPATH,
+ label_stack_id);
+ strlcpy(xpath_label, xpath_mpls,
+ sizeof(xpath_label));
+ strlcat(xpath_label, ab_xpath,
+ sizeof(xpath_label));
+ nb_cli_enqueue_change(vty, xpath_label,
+ NB_OP_MODIFY, nump);
+ label_stack_id++;
+ }
+ XFREE(MTYPE_TMP, ostr);
+ } else {
+ strlcpy(xpath_mpls, xpath_nexthop, sizeof(xpath_mpls));
+ strlcat(xpath_mpls, FRR_STATIC_ROUTE_NH_LABEL_XPATH,
+ sizeof(xpath_mpls));
+ nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
+ NULL);
}
-
- }
-
- if (gate_str == NULL && ifname == NULL)
- type = STATIC_BLACKHOLE;
- else if (gate_str && ifname) {
- if (afi == AFI_IP)
- type = STATIC_IPV4_GATEWAY_IFNAME;
- else
- type = STATIC_IPV6_GATEWAY_IFNAME;
- } else if (ifname)
- type = STATIC_IFNAME;
- else {
- if (afi == AFI_IP)
- type = STATIC_IPV4_GATEWAY;
- else
- type = STATIC_IPV6_GATEWAY;
- }
-
- if (!negate) {
- static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
- bh_type, tag, distance, svrf, nh_svrf,
- &snh_label, table_id, onlink);
- /* Mark as having FRR configuration */
- vrf_set_user_cfged(svrf->vrf);
+ ret = nb_cli_apply_changes(vty, xpath_prefix);
} else {
- static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
- tag, distance, svrf, &snh_label, table_id);
- /* If no other FRR config for this VRF, mark accordingly. */
- if (!static_vrf_has_config(svrf))
- vrf_reset_user_cfged(svrf->vrf);
+ if (src_str)
+ snprintf(ab_xpath, sizeof(ab_xpath),
+ FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH,
+ "frr-staticd:staticd", "staticd", svrf,
+ buf_prefix,
+ buf_src_prefix, distance, buf_nh_type, nh_svrf,
+ buf_gate_str, ifname);
+ else
+ snprintf(ab_xpath, sizeof(ab_xpath),
+ FRR_DEL_S_ROUTE_NH_KEY_XPATH,
+ "frr-staticd:staticd", "staticd", svrf,
+ buf_prefix,
+ distance, buf_nh_type, nh_svrf, buf_gate_str,
+ ifname);
+
+ dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath);
+ if (!dnode)
+ return ret;
+
+ dnode = yang_get_subtree_with_no_sibling(dnode);
+ assert(dnode);
+ yang_dnode_get_path(dnode, ab_xpath, XPATH_MAXLEN);
+
+ nb_cli_enqueue_change(vty, ab_xpath, NB_OP_DESTROY, NULL);
+ ret = nb_cli_apply_changes(vty, ab_xpath);
}
- return CMD_SUCCESS;
+ return ret;
}
-
static int static_route(struct vty *vty, afi_t afi, safi_t safi,
const char *negate, const char *dest_str,
const char *mask_str, const char *src_str,
@@ -538,77 +320,28 @@ static int static_route(struct vty *vty, afi_t afi, safi_t safi,
const char *distance_str, const char *vrf_name,
const char *label_str, const char *table_str)
{
- struct static_vrf *svrf;
-
- /* VRF id */
- svrf = static_vrf_lookup_by_name(vrf_name);
-
- /* When trying to delete, the VRF must exist. */
- if (negate && !svrf) {
- vty_out(vty, "%% vrf %s is not defined\n", vrf_name);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (!vrf_name)
+ vrf_name = VRF_DEFAULT_NAME;
- /* When trying to create, create the VRF if it doesn't exist.
- * Note: The VRF isn't active until we hear about it from the kernel.
- */
- if (!svrf) {
- svrf = static_vty_get_unknown_vrf(vty, vrf_name);
- if (!svrf)
- return CMD_WARNING_CONFIG_FAILED;
- }
- return static_route_leak(vty, svrf, svrf, afi, safi, negate, dest_str,
- mask_str, src_str, gate_str, ifname, flag_str,
- tag_str, distance_str, label_str, table_str,
- false);
-}
-
-void static_config_install_delayed_routes(struct static_vrf *svrf)
-{
- struct listnode *node, *nnode;
- struct static_hold_route *shr;
- struct static_vrf *osvrf, *nh_svrf;
- int installed;
-
- for (ALL_LIST_ELEMENTS(static_list, node, nnode, shr)) {
- osvrf = static_vrf_lookup_by_name(shr->vrf_name);
- nh_svrf = static_vrf_lookup_by_name(shr->nhvrf_name);
-
- if (osvrf != svrf && nh_svrf != svrf)
- continue;
-
- if (osvrf->vrf->vrf_id == VRF_UNKNOWN
- || nh_svrf->vrf->vrf_id == VRF_UNKNOWN)
- continue;
-
- installed = static_route_leak(
- NULL, osvrf, nh_svrf, shr->afi, shr->safi, NULL,
- shr->dest_str, shr->mask_str, shr->src_str,
- shr->gate_str, shr->ifname, shr->flag_str, shr->tag_str,
- shr->distance_str, shr->label_str, shr->table_str,
- shr->onlink);
-
- if (installed != CMD_SUCCESS)
- zlog_debug(
- "%s: Attempt to install %s as a route and it was rejected",
- __func__, shr->dest_str);
- listnode_delete(static_list, shr);
- static_list_delete(shr);
- }
+ return static_route_leak(vty, vrf_name, vrf_name, afi, safi, negate,
+ dest_str, mask_str, src_str, gate_str, ifname,
+ flag_str, tag_str, distance_str, label_str,
+ table_str, false);
}
/* Write static route configuration. */
int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi,
safi_t safi, const char *cmd)
{
- struct static_hold_route *shr;
- struct listnode *node;
char spacing[100];
struct route_node *rn;
- struct static_route *si;
+ struct static_nexthop *nh;
+ struct static_path *pn;
struct route_table *stable;
+ struct static_route_info *si;
char buf[SRCDEST2STR_BUFFER];
int write = 0;
+ struct stable_info *info;
stable = svrf->stable[afi][safi];
if (stable == NULL)
@@ -617,120 +350,99 @@ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi,
snprintf(spacing, sizeof(spacing), "%s%s",
(svrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ", cmd);
- /*
- * Static routes for vrfs not fully inited
- */
- for (ALL_LIST_ELEMENTS_RO(static_list, node, shr)) {
- if (shr->afi != afi || shr->safi != safi)
+ for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
+ si = static_route_info_from_rnode(rn);
+ if (!si)
continue;
-
- if (strcmp(svrf->vrf->name, shr->vrf_name) != 0)
- continue;
-
- char dest_str[PREFIX_STRLEN];
-
- prefix2str(&shr->dest, dest_str, sizeof(dest_str));
-
- vty_out(vty, "%s ", spacing);
- if (shr->dest_str)
- vty_out(vty, "%s ", dest_str);
- if (shr->src_str)
- vty_out(vty, "from %s ", shr->src_str);
- if (shr->gate_str)
- vty_out(vty, "%s ", shr->gate_str);
- if (shr->ifname)
- vty_out(vty, "%s ", shr->ifname);
- if (shr->flag_str)
- vty_out(vty, "%s ", shr->flag_str);
- if (shr->tag_str)
- vty_out(vty, "tag %s ", shr->tag_str);
- if (shr->distance_str)
- vty_out(vty, "%s ", shr->distance_str);
- if (shr->label_str)
- vty_out(vty, "label %s ", shr->label_str);
- if (shr->table_str)
- vty_out(vty, "table %s", shr->table_str);
- if (strcmp(shr->vrf_name, shr->nhvrf_name) != 0)
- vty_out(vty, "nexthop-vrf %s ", shr->nhvrf_name);
- if (shr->onlink)
- vty_out(vty, "onlink");
- vty_out(vty, "\n");
- }
-
- for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
- for (si = rn->info; si; si = si->next) {
- vty_out(vty, "%s %s", spacing,
- srcdest_rnode2str(rn, buf, sizeof(buf)));
-
- switch (si->type) {
- case STATIC_IPV4_GATEWAY:
- vty_out(vty, " %s", inet_ntoa(si->addr.ipv4));
- break;
- case STATIC_IPV6_GATEWAY:
- vty_out(vty, " %s",
- inet_ntop(AF_INET6, &si->addr.ipv6, buf,
- sizeof(buf)));
- break;
- case STATIC_IFNAME:
- vty_out(vty, " %s", si->ifname);
- break;
- case STATIC_BLACKHOLE:
- switch (si->bh_type) {
- case STATIC_BLACKHOLE_DROP:
- vty_out(vty, " blackhole");
+ info = static_get_stable_info(rn);
+ frr_each(static_path_list, &si->path_list, pn) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
+ vty_out(vty, "%s %s", spacing,
+ srcdest_rnode2str(rn, buf,
+ sizeof(buf)));
+
+ switch (nh->type) {
+ case STATIC_IPV4_GATEWAY:
+ vty_out(vty, " %s",
+ inet_ntoa(nh->addr.ipv4));
break;
- case STATIC_BLACKHOLE_NULL:
- vty_out(vty, " Null0");
+ case STATIC_IPV6_GATEWAY:
+ vty_out(vty, " %s",
+ inet_ntop(AF_INET6,
+ &nh->addr.ipv6, buf,
+ sizeof(buf)));
break;
- case STATIC_BLACKHOLE_REJECT:
- vty_out(vty, " reject");
+ case STATIC_IFNAME:
+ vty_out(vty, " %s", nh->ifname);
+ break;
+ case STATIC_BLACKHOLE:
+ switch (nh->bh_type) {
+ case STATIC_BLACKHOLE_DROP:
+ vty_out(vty, " blackhole");
+ break;
+ case STATIC_BLACKHOLE_NULL:
+ vty_out(vty, " Null0");
+ break;
+ case STATIC_BLACKHOLE_REJECT:
+ vty_out(vty, " reject");
+ break;
+ }
+ break;
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ vty_out(vty, " %s %s",
+ inet_ntop(AF_INET,
+ &nh->addr.ipv4, buf,
+ sizeof(buf)),
+ nh->ifname);
+ break;
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ vty_out(vty, " %s %s",
+ inet_ntop(AF_INET6,
+ &nh->addr.ipv6, buf,
+ sizeof(buf)),
+ nh->ifname);
break;
}
- break;
- case STATIC_IPV4_GATEWAY_IFNAME:
- vty_out(vty, " %s %s",
- inet_ntop(AF_INET, &si->addr.ipv4, buf,
- sizeof(buf)),
- si->ifname);
- break;
- case STATIC_IPV6_GATEWAY_IFNAME:
- vty_out(vty, " %s %s",
- inet_ntop(AF_INET6, &si->addr.ipv6, buf,
- sizeof(buf)),
- si->ifname);
- break;
- }
- if (si->tag)
- vty_out(vty, " tag %" ROUTE_TAG_PRI, si->tag);
-
- if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
- vty_out(vty, " %d", si->distance);
-
- /* Label information */
- if (si->snh_label.num_labels)
- vty_out(vty, " label %s",
- mpls_label2str(si->snh_label.num_labels,
- si->snh_label.label, buf,
- sizeof(buf), 0));
-
- if (si->nh_vrf_id != si->vrf_id)
- vty_out(vty, " nexthop-vrf %s", si->nh_vrfname);
-
- /*
- * table ID from VRF overrides configured
- */
- if (si->table_id &&
- svrf->vrf->data.l.table_id == RT_TABLE_MAIN)
- vty_out(vty, " table %u", si->table_id);
-
- if (si->onlink)
- vty_out(vty, " onlink");
-
- vty_out(vty, "\n");
-
- write = 1;
+ if (pn->tag)
+ vty_out(vty, " tag %" ROUTE_TAG_PRI,
+ pn->tag);
+
+ if (pn->distance
+ != ZEBRA_STATIC_DISTANCE_DEFAULT)
+ vty_out(vty, " %u", pn->distance);
+
+ /* Label information */
+ if (nh->snh_label.num_labels)
+ vty_out(vty, " label %s",
+ mpls_label2str(
+ nh->snh_label
+ .num_labels,
+ nh->snh_label.label,
+ buf, sizeof(buf), 0));
+
+ if (nh->nh_vrf_id != GET_STABLE_VRF_ID(info))
+ vty_out(vty, " nexthop-vrf %s",
+ nh->nh_vrfname);
+
+ /*
+ * table ID from VRF overrides
+ * configured
+ */
+ if (pn->table_id
+ && svrf->vrf->data.l.table_id
+ == RT_TABLE_MAIN)
+ vty_out(vty, " table %u", pn->table_id);
+
+ if (nh->onlink)
+ vty_out(vty, " onlink");
+
+ vty_out(vty, "\n");
+
+ write = 1;
+ }
}
+ }
return write;
}
@@ -815,23 +527,24 @@ DEFPY(ip_route_blackhole_vrf,
"Table to configure\n"
"The table number to configure\n")
{
- VTY_DECLVAR_CONTEXT(vrf, vrf);
- struct static_vrf *svrf = vrf->info;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
- if (table_str && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
+ vrf_dnode =
+ yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+ if (!vrf_dnode) {
+ vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
-
+ vrfname = yang_dnode_get_string(vrf_dnode, "./name");
/*
* Coverity is complaining that prefix could
* be dereferenced, but we know that prefix will
* valid. Add an assert to make it happy
*/
assert(prefix);
- return static_route_leak(vty, svrf, svrf, AFI_IP, SAFI_UNICAST, no,
- prefix, mask_str, NULL, NULL, NULL, flag,
+ return static_route_leak(vty, vrfname, vrfname, AFI_IP, SAFI_UNICAST,
+ no, prefix, mask_str, NULL, NULL, NULL, flag,
tag_str, distance_str, label, table_str,
false);
}
@@ -869,38 +582,22 @@ DEFPY(ip_route_address_interface,
VRF_CMD_HELP_STR
"Treat the nexthop as directly attached to the interface\n")
{
- struct static_vrf *svrf;
- struct static_vrf *nh_svrf;
+ const char *nh_vrf;
const char *flag = NULL;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
-
- svrf = static_vty_get_unknown_vrf(vty, vrf);
- if (!svrf) {
- vty_out(vty, "%% vrf %s is not defined\n", vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (table_str && vrf && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
if (nexthop_vrf)
- nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
+ nh_vrf = nexthop_vrf;
else
- nh_svrf = svrf;
+ nh_vrf = vrf;
- if (!nh_svrf) {
- vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no,
+ return static_route_leak(vty, vrf, nh_vrf, AFI_IP, SAFI_UNICAST, no,
prefix, mask_str, NULL, gate_str, ifname, flag,
tag_str, distance_str, label, table_str,
!!onlink);
@@ -937,33 +634,29 @@ DEFPY(ip_route_address_interface_vrf,
VRF_CMD_HELP_STR
"Treat the nexthop as directly attached to the interface\n")
{
- VTY_DECLVAR_CONTEXT(vrf, vrf);
+ const char *nh_vrf;
const char *flag = NULL;
- struct static_vrf *svrf = vrf->info;
- struct static_vrf *nh_svrf;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
- if (table_str && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
+ vrf_dnode =
+ yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+ if (!vrf_dnode) {
+ vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
+ vrfname = yang_dnode_get_string(vrf_dnode, "./name");
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
-
if (nexthop_vrf)
- nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
+ nh_vrf = nexthop_vrf;
else
- nh_svrf = svrf;
-
- if (!nh_svrf) {
- vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ nh_vrf = vrfname;
- return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no,
+ return static_route_leak(vty, vrfname, nh_vrf, AFI_IP, SAFI_UNICAST, no,
prefix, mask_str, NULL, gate_str, ifname, flag,
tag_str, distance_str, label, table_str,
!!onlink);
@@ -999,41 +692,26 @@ DEFPY(ip_route,
"The table number to configure\n"
VRF_CMD_HELP_STR)
{
- struct static_vrf *svrf;
- struct static_vrf *nh_svrf;
+ const char *nh_vrf;
const char *flag = NULL;
- if (table_str && vrf && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
- svrf = static_vty_get_unknown_vrf(vty, vrf);
- if (!svrf) {
- vty_out(vty, "%% vrf %s is not defined\n", vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
if (nexthop_vrf)
- nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
+ nh_vrf = nexthop_vrf;
else
- nh_svrf = svrf;
+ nh_vrf = vrf;
- if (!nh_svrf) {
- vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return static_route_leak(
- vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
- NULL, gate_str, ifname, flag, tag_str, distance_str, label,
- table_str, false);
+ return static_route_leak(vty, vrf, nh_vrf, AFI_IP, SAFI_UNICAST, no,
+ prefix, mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label, table_str,
+ false);
}
DEFPY(ip_route_vrf,
@@ -1064,36 +742,33 @@ DEFPY(ip_route_vrf,
"The table number to configure\n"
VRF_CMD_HELP_STR)
{
- VTY_DECLVAR_CONTEXT(vrf, vrf);
- struct static_vrf *svrf = vrf->info;
- struct static_vrf *nh_svrf;
+ const char *nh_vrf;
const char *flag = NULL;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
- if (table_str && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
+ vrf_dnode =
+ yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+ if (!vrf_dnode) {
+ vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
+ vrfname = yang_dnode_get_string(vrf_dnode, "./name");
+
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
-
if (nexthop_vrf)
- nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
+ nh_vrf = nexthop_vrf;
else
- nh_svrf = svrf;
-
- if (!nh_svrf) {
- vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ nh_vrf = vrfname;
- return static_route_leak(
- vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
- NULL, gate_str, ifname, flag, tag_str, distance_str, label,
- table_str, false);
+ return static_route_leak(vty, vrfname, nh_vrf, AFI_IP, SAFI_UNICAST, no,
+ prefix, mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label, table_str,
+ false);
}
DEFPY(ipv6_route_blackhole,
@@ -1159,14 +834,16 @@ DEFPY(ipv6_route_blackhole_vrf,
"Table to configure\n"
"The table number to configure\n")
{
- VTY_DECLVAR_CONTEXT(vrf, vrf);
- struct static_vrf *svrf = vrf->info;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
- if (table_str && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
+ vrf_dnode =
+ yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+ if (!vrf_dnode) {
+ vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
+ vrfname = yang_dnode_get_string(vrf_dnode, "./name");
/*
* Coverity is complaining that prefix could
@@ -1174,10 +851,11 @@ DEFPY(ipv6_route_blackhole_vrf,
* valid. Add an assert to make it happy
*/
assert(prefix);
- return static_route_leak(
- vty, svrf, svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
- from_str, NULL, NULL, flag, tag_str, distance_str, label,
- table_str, false);
+
+ return static_route_leak(vty, vrfname, vrfname, AFI_IP6, SAFI_UNICAST,
+ no, prefix_str, NULL, from_str, NULL, NULL,
+ flag, tag_str, distance_str, label, table_str,
+ false);
}
DEFPY(ipv6_route_address_interface,
@@ -1213,41 +891,26 @@ DEFPY(ipv6_route_address_interface,
VRF_CMD_HELP_STR
"Treat the nexthop as directly attached to the interface\n")
{
- struct static_vrf *svrf;
- struct static_vrf *nh_svrf;
+ const char *nh_vrf;
const char *flag = NULL;
- if (table_str && vrf && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
- return CMD_WARNING_CONFIG_FAILED;
+ if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+ flag = "Null0";
+ ifname = NULL;
}
- svrf = static_vty_get_unknown_vrf(vty, vrf);
- if (!svrf) {
- vty_out(vty, "%% vrf %s is not defined\n", vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
if (nexthop_vrf)
- nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
+ nh_vrf = nexthop_vrf;
else
- nh_svrf = svrf;
-
- if (!nh_svrf) {
- vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ nh_vrf = vrf;
- if (ifname && !strncasecmp(ifname, "Null0", 5)) {
- flag = "Null0";
- ifname = NULL;
- }
-
- return static_route_leak(
- vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
- from_str, gate_str, ifname, flag, tag_str, distance_str, label,
- table_str, !!onlink);
+ return static_route_leak(vty, vrf, nh_vrf, AFI_IP6, SAFI_UNICAST, no,
+ prefix_str, NULL, from_str, gate_str, ifname,
+ flag, tag_str, distance_str, label, table_str,
+ !!onlink);
}
DEFPY(ipv6_route_address_interface_vrf,
@@ -1281,36 +944,32 @@ DEFPY(ipv6_route_address_interface_vrf,
VRF_CMD_HELP_STR
"Treat the nexthop as directly attached to the interface\n")
{
- VTY_DECLVAR_CONTEXT(vrf, vrf);
- struct static_vrf *svrf = vrf->info;
- struct static_vrf *nh_svrf;
+ const char *nh_vrf;
const char *flag = NULL;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
- if (table_str && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
+ vrf_dnode =
+ yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+ if (!vrf_dnode) {
+ vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
+ vrfname = yang_dnode_get_string(vrf_dnode, "./name");
if (nexthop_vrf)
- nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
+ nh_vrf = nexthop_vrf;
else
- nh_svrf = svrf;
-
- if (!nh_svrf) {
- vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ nh_vrf = vrfname;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
-
- return static_route_leak(
- vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
- from_str, gate_str, ifname, flag, tag_str, distance_str, label,
- table_str, !!onlink);
+ return static_route_leak(vty, vrfname, nh_vrf, AFI_IP6, SAFI_UNICAST,
+ no, prefix_str, NULL, from_str, gate_str,
+ ifname, flag, tag_str, distance_str, label,
+ table_str, !!onlink);
}
DEFPY(ipv6_route,
@@ -1343,41 +1002,25 @@ DEFPY(ipv6_route,
"The table number to configure\n"
VRF_CMD_HELP_STR)
{
- struct static_vrf *svrf;
- struct static_vrf *nh_svrf;
+ const char *nh_vrf;
const char *flag = NULL;
- if (table_str && vrf && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- svrf = static_vty_get_unknown_vrf(vty, vrf);
- if (!svrf) {
- vty_out(vty, "%% vrf %s is not defined\n", vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (!vrf)
+ vrf = VRF_DEFAULT_NAME;
if (nexthop_vrf)
- nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
+ nh_vrf = nexthop_vrf;
else
- nh_svrf = svrf;
-
- if (!nh_svrf) {
- vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ nh_vrf = vrf;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
-
- return static_route_leak(
- vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
- from_str, gate_str, ifname, flag, tag_str, distance_str, label,
- table_str, false);
+ return static_route_leak(vty, vrf, nh_vrf, AFI_IP6, SAFI_UNICAST, no,
+ prefix_str, NULL, from_str, gate_str, ifname,
+ flag, tag_str, distance_str, label, table_str,
+ false);
}
DEFPY(ipv6_route_vrf,
@@ -1408,36 +1051,32 @@ DEFPY(ipv6_route_vrf,
"The table number to configure\n"
VRF_CMD_HELP_STR)
{
- VTY_DECLVAR_CONTEXT(vrf, vrf);
- struct static_vrf *svrf = vrf->info;
- struct static_vrf *nh_svrf;
+ const char *nh_vrf;
const char *flag = NULL;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
- if (table_str && !vrf_is_backend_netns()) {
- vty_out(vty,
- "%% table param only available when running on netns-based vrfs\n");
+ vrf_dnode =
+ yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+ if (!vrf_dnode) {
+ vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
+ vrfname = yang_dnode_get_string(vrf_dnode, "./name");
if (nexthop_vrf)
- nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
+ nh_vrf = nexthop_vrf;
else
- nh_svrf = svrf;
-
- if (!nh_svrf) {
- vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ nh_vrf = vrfname;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
-
- return static_route_leak(
- vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
- from_str, gate_str, ifname, flag, tag_str, distance_str, label,
- table_str, false);
+ return static_route_leak(vty, vrfname, nh_vrf, AFI_IP6, SAFI_UNICAST,
+ no, prefix_str, NULL, from_str, gate_str,
+ ifname, flag, tag_str, distance_str, label,
+ table_str, false);
}
DEFPY(debug_staticd,
debug_staticd_cmd,
@@ -1500,8 +1139,4 @@ void static_vty_init(void)
install_element(VIEW_NODE, &show_debugging_static_cmd);
install_element(VIEW_NODE, &debug_staticd_cmd);
install_element(CONFIG_NODE, &debug_staticd_cmd);
-
- static_list = list_new();
- static_list->cmp = (int (*)(void *, void *))static_list_compare;
- static_list->del = (void (*)(void *))static_list_delete;
}
diff --git a/staticd/static_vty.h b/staticd/static_vty.h
index 2f65c08b8..7ffc8d9c9 100644
--- a/staticd/static_vty.h
+++ b/staticd/static_vty.h
@@ -19,8 +19,6 @@
#ifndef __STATIC_VTY_H__
#define __STATIC_VTY_H__
-void static_config_install_delayed_routes(struct static_vrf *svrf);
-
int static_config(struct vty *vty, struct static_vrf *svrf,
afi_t afi, safi_t safi, const char *cmd);
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index c42f632ff..d8a4b7f0c 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -89,7 +89,6 @@ static int static_ifp_up(struct interface *ifp)
struct static_vrf *svrf = static_vrf_lookup_by_id(ifp->vrf_id);
static_fixup_vrf_ids(svrf);
- static_config_install_delayed_routes(svrf);
}
/* Install any static reliant on this interface coming up */
@@ -265,8 +264,8 @@ static void static_nht_hash_free(void *data)
XFREE(MTYPE_TMP, nhtd);
}
-void static_zebra_nht_register(struct route_node *rn,
- struct static_route *si, bool reg)
+void static_zebra_nht_register(struct route_node *rn, struct static_nexthop *nh,
+ bool reg)
{
struct static_nht_data *nhtd, lookup;
uint32_t cmd;
@@ -276,14 +275,14 @@ void static_zebra_nht_register(struct route_node *rn,
cmd = (reg) ?
ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
- if (si->nh_registered && reg)
+ if (nh->nh_registered && reg)
return;
- if (!si->nh_registered && !reg)
+ if (!nh->nh_registered && !reg)
return;
memset(&p, 0, sizeof(p));
- switch (si->type) {
+ switch (nh->type) {
case STATIC_IFNAME:
case STATIC_BLACKHOLE:
return;
@@ -291,23 +290,23 @@ void static_zebra_nht_register(struct route_node *rn,
case STATIC_IPV4_GATEWAY_IFNAME:
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
- p.u.prefix4 = si->addr.ipv4;
+ p.u.prefix4 = nh->addr.ipv4;
afi = AFI_IP;
break;
case STATIC_IPV6_GATEWAY:
case STATIC_IPV6_GATEWAY_IFNAME:
p.family = AF_INET6;
p.prefixlen = IPV6_MAX_BITLEN;
- p.u.prefix6 = si->addr.ipv6;
+ p.u.prefix6 = nh->addr.ipv6;
afi = AFI_IP6;
break;
}
memset(&lookup, 0, sizeof(lookup));
lookup.nh = &p;
- lookup.nh_vrf_id = si->nh_vrf_id;
+ lookup.nh_vrf_id = nh->nh_vrf_id;
- si->nh_registered = reg;
+ nh->nh_registered = reg;
if (reg) {
nhtd = hash_get(static_nht_hash, &lookup,
@@ -318,8 +317,8 @@ void static_zebra_nht_register(struct route_node *rn,
zlog_debug("Registered nexthop(%pFX) for %pRN %d", &p,
rn, nhtd->nh_num);
if (nhtd->refcount > 1 && nhtd->nh_num) {
- static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num,
- afi, si->nh_vrf_id);
+ static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi,
+ nh->nh_vrf_id);
return;
}
} else {
@@ -335,25 +334,72 @@ void static_zebra_nht_register(struct route_node *rn,
static_nht_hash_free(nhtd);
}
- if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
+ if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id) < 0)
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
}
+/*
+ * When nexthop gets updated via configuration then use the
+ * already registered NH and resend the route to zebra
+ */
+int static_zebra_nh_update(struct route_node *rn, struct static_nexthop *nh)
+{
+ struct static_nht_data *nhtd, lookup = {};
+ struct prefix p = {};
+ afi_t afi = AFI_IP;
+
+ if (!nh->nh_registered)
+ return 0;
+
+ switch (nh->type) {
+ case STATIC_IFNAME:
+ case STATIC_BLACKHOLE:
+ return 0;
+ case STATIC_IPV4_GATEWAY:
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ p.family = AF_INET;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ p.u.prefix4 = nh->addr.ipv4;
+ afi = AFI_IP;
+ break;
+ case STATIC_IPV6_GATEWAY:
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ p.family = AF_INET6;
+ p.prefixlen = IPV6_MAX_BITLEN;
+ p.u.prefix6 = nh->addr.ipv6;
+ afi = AFI_IP6;
+ break;
+ }
+
+ lookup.nh = &p;
+ lookup.nh_vrf_id = nh->nh_vrf_id;
+
+ nhtd = hash_lookup(static_nht_hash, &lookup);
+ if (nhtd && nhtd->nh_num) {
+ nh->state = STATIC_START;
+ static_nht_update(&rn->p, nhtd->nh, nhtd->nh_num, afi,
+ nh->nh_vrf_id);
+ return 1;
+ }
+ return 0;
+}
extern void static_zebra_route_add(struct route_node *rn,
- struct static_route *si_changed,
- vrf_id_t vrf_id, safi_t safi, bool install)
+ struct static_path *pn, safi_t safi,
+ bool install)
{
- struct static_route *si = rn->info;
+ struct static_nexthop *nh;
const struct prefix *p, *src_pp;
struct zapi_nexthop *api_nh;
struct zapi_route api;
uint32_t nh_num = 0;
+ struct stable_info *info;
p = src_pp = NULL;
srcdest_rnode_prefixes(rn, &p, &src_pp);
memset(&api, 0, sizeof(api));
- api.vrf_id = vrf_id;
+ info = static_get_stable_info(rn);
+ api.vrf_id = GET_STABLE_VRF_ID(info);
api.type = ZEBRA_ROUTE_STATIC;
api.safi = safi;
memcpy(&api.prefix, p, sizeof(api.prefix));
@@ -365,71 +411,65 @@ extern void static_zebra_route_add(struct route_node *rn,
SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE);
SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
- if (si_changed->distance) {
+ if (pn->distance) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
- api.distance = si_changed->distance;
+ api.distance = pn->distance;
}
- if (si_changed->tag) {
+ if (pn->tag) {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
- api.tag = si_changed->tag;
+ api.tag = pn->tag;
}
- if (si_changed->table_id != 0) {
+ if (pn->table_id != 0) {
SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
- api.tableid = si_changed->table_id;
+ api.tableid = pn->table_id;
}
- for (/*loaded above*/; si; si = si->next) {
+ frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
api_nh = &api.nexthops[nh_num];
- if (si->nh_vrf_id == VRF_UNKNOWN)
- continue;
-
- if (si->distance != si_changed->distance)
- continue;
-
- if (si->table_id != si_changed->table_id)
+ if (nh->nh_vrf_id == VRF_UNKNOWN)
continue;
- api_nh->vrf_id = si->nh_vrf_id;
- if (si->onlink)
+ api_nh->vrf_id = nh->nh_vrf_id;
+ if (nh->onlink)
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
- si->state = STATIC_SENT_TO_ZEBRA;
+ nh->state = STATIC_SENT_TO_ZEBRA;
- switch (si->type) {
+ switch (nh->type) {
case STATIC_IFNAME:
- if (si->ifindex == IFINDEX_INTERNAL)
+ if (nh->ifindex == IFINDEX_INTERNAL)
continue;
- api_nh->ifindex = si->ifindex;
+ api_nh->ifindex = nh->ifindex;
api_nh->type = NEXTHOP_TYPE_IFINDEX;
break;
case STATIC_IPV4_GATEWAY:
- if (!si->nh_valid)
+ if (!nh->nh_valid)
continue;
api_nh->type = NEXTHOP_TYPE_IPV4;
- api_nh->gate = si->addr;
+ api_nh->gate = nh->addr;
break;
case STATIC_IPV4_GATEWAY_IFNAME:
- if (si->ifindex == IFINDEX_INTERNAL)
+ if (nh->ifindex == IFINDEX_INTERNAL)
continue;
- api_nh->ifindex = si->ifindex;
+ api_nh->ifindex = nh->ifindex;
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
- api_nh->gate = si->addr;
+ api_nh->gate = nh->addr;
break;
case STATIC_IPV6_GATEWAY:
- if (!si->nh_valid)
+ if (!nh->nh_valid)
continue;
api_nh->type = NEXTHOP_TYPE_IPV6;
- api_nh->gate = si->addr;
+ api_nh->gate = nh->addr;
break;
case STATIC_IPV6_GATEWAY_IFNAME:
- if (si->ifindex == IFINDEX_INTERNAL)
+ if (nh->ifindex == IFINDEX_INTERNAL)
continue;
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
- api_nh->ifindex = si->ifindex;
- api_nh->gate = si->addr;
+ api_nh->ifindex = nh->ifindex;
+ api_nh->gate = nh->addr;
break;
case STATIC_BLACKHOLE:
api_nh->type = NEXTHOP_TYPE_BLACKHOLE;
- switch (si->bh_type) {
+ switch (nh->bh_type) {
case STATIC_BLACKHOLE_DROP:
case STATIC_BLACKHOLE_NULL:
api_nh->bh_type = BLACKHOLE_NULL;
@@ -440,13 +480,13 @@ extern void static_zebra_route_add(struct route_node *rn,
break;
}
- if (si->snh_label.num_labels) {
+ if (nh->snh_label.num_labels) {
int i;
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
- api_nh->label_num = si->snh_label.num_labels;
+ api_nh->label_num = nh->snh_label.num_labels;
for (i = 0; i < api_nh->label_num; i++)
- api_nh->labels[i] = si->snh_label.label[i];
+ api_nh->labels[i] = nh->snh_label.label[i];
}
nh_num++;
}
diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h
index 962dc3908..9f93f3ee6 100644
--- a/staticd/static_zebra.h
+++ b/staticd/static_zebra.h
@@ -22,13 +22,15 @@
extern struct thread_master *master;
extern void static_zebra_nht_register(struct route_node *rn,
- struct static_route *si, bool reg);
+ struct static_nexthop *nh, bool reg);
extern void static_zebra_route_add(struct route_node *rn,
- struct static_route *si_changed,
- vrf_id_t vrf_id, safi_t safi, bool install);
+ struct static_path *pn, safi_t safi,
+ bool install);
extern void static_zebra_init(void);
extern void static_zebra_vrf_register(struct vrf *vrf);
extern void static_zebra_vrf_unregister(struct vrf *vrf);
+extern int static_zebra_nh_update(struct route_node *rn,
+ struct static_nexthop *nh);
#endif
diff --git a/staticd/subdir.am b/staticd/subdir.am
index f2b3d11f2..eba7f270b 100644
--- a/staticd/subdir.am
+++ b/staticd/subdir.am
@@ -18,6 +18,8 @@ staticd_libstatic_a_SOURCES = \
staticd/static_zebra.c \
staticd/static_vrf.c \
staticd/static_vty.c \
+ staticd/static_nb.c \
+ staticd/static_nb_config.c \
# end
noinst_HEADERS += \
@@ -28,6 +30,7 @@ noinst_HEADERS += \
staticd/static_routes.h \
staticd/static_vty.h \
staticd/static_vrf.h \
+ staticd/static_nb.h \
# end
clippy_scan += \
@@ -36,3 +39,7 @@ clippy_scan += \
staticd_staticd_SOURCES = staticd/static_main.c
staticd_staticd_LDADD = staticd/libstatic.a lib/libfrr.la $(LIBCAP)
+
+nodist_staticd_staticd_SOURCES = \
+ yang/frr-staticd.yang.c \
+ # end