summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/zclient.c8
-rw-r--r--lib/zclient.h1
-rw-r--r--zebra/rt_netlink.c40
-rw-r--r--zebra/zebra_nhg.c19
-rw-r--r--zebra/zebra_nhg.h4
-rw-r--r--zebra/zebra_vty.c17
6 files changed, 88 insertions, 1 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index 17026d13a6..deb5f519bd 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -4083,3 +4083,11 @@ uint32_t zclient_get_nhg_start(uint32_t proto)
return ZEBRA_NHG_SPACING * proto;
}
+
+/*
+ * Where do routing protocols IDs start overall (first ID after zebra)
+ */
+uint32_t zclient_get_nhg_lower_bound()
+{
+ return ZEBRA_NHG_SPACING * (ZEBRA_ROUTE_CONNECT + 1);
+}
diff --git a/lib/zclient.h b/lib/zclient.h
index b7850cdec7..db5e1ce5b9 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -692,6 +692,7 @@ extern struct zclient_options zclient_options_default;
*/
#define ZEBRA_NHG_SPACING 50000000
extern uint32_t zclient_get_nhg_start(uint32_t proto);
+extern uint32_t zclient_get_nhg_lower_bound(void);
extern struct zclient *zclient_new(struct thread_master *m,
struct zclient_options *opt);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 146650f602..07135b7fc8 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -126,6 +126,31 @@ static bool kernel_nexthops_supported(void)
}
/*
+ * Some people may only want to use NHGs created by protos and not
+ * implicitly created by Zebra. This check accounts for that.
+ */
+static bool proto_nexthops_only(void)
+{
+ return zebra_nhg_proto_nexthops_only();
+}
+
+/* Is this a proto created NHG? */
+static bool is_proto_nhg(uint32_t id, int type)
+{
+ /* If type is available, use it as the source of truth */
+ if (type) {
+ if (type != ZEBRA_ROUTE_NHG)
+ return true;
+ return false;
+ }
+
+ if (id >= zclient_get_nhg_lower_bound())
+ return true;
+
+ return false;
+}
+
+/*
* The ipv4_ll data structure is used for all 5549
* additions to the kernel. Let's figure out the
* correct value one time instead for every
@@ -1748,7 +1773,10 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
nl_attr_nest_end(&req->n, nest);
}
- if ((!fpm && kernel_nexthops_supported()) || (fpm && force_nhg)) {
+ if ((!fpm && kernel_nexthops_supported()
+ && (!proto_nexthops_only()
+ || is_proto_nhg(dplane_ctx_get_nhe_id(ctx), 0)))
+ || (fpm && force_nhg)) {
/* Kernel supports nexthop objects */
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: %pFX nhg_id is %u", __func__, p,
@@ -2073,6 +2101,16 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
char label_buf[256];
int num_labels = 0;
+ /*
+ * Nothing to do if the kernel doesn't support nexthop objects or
+ * we dont want to install this type of NHG
+ */
+ if (!kernel_nexthops_supported()
+ || (proto_nexthops_only()
+ && !is_proto_nhg(dplane_ctx_get_nhe_id(ctx),
+ dplane_ctx_get_nhe_type(ctx))))
+ return 0;
+
label_buf[0] = '\0';
if (buflen < sizeof(*req))
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 59df45420b..dbf5adafe1 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -53,6 +53,7 @@ uint32_t id_counter;
/* */
static bool g_nexthops_enabled = true;
+static bool proto_nexthops_only = false;
static struct nhg_hash_entry *depends_find(const struct nexthop *nh, afi_t afi,
int type);
@@ -2661,6 +2662,24 @@ bool zebra_nhg_kernel_nexthops_enabled(void)
return g_nexthops_enabled;
}
+/*
+ * Global control to only use kernel nexthops for protocol created NHGs.
+ * There are some use cases where you may not want zebra to implicitly
+ * create kernel nexthops for all routes and only create them for NHGs
+ * passed down by upper level protos.
+ *
+ * Default is off.
+ */
+void zebra_nhg_set_proto_nexthops_only(bool set)
+{
+ proto_nexthops_only = set;
+}
+
+bool zebra_nhg_proto_nexthops_only(void)
+{
+ return proto_nexthops_only;
+}
+
/* Add NHE from upper level proto */
struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
struct nexthop_group *nhg, afi_t afi)
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 44d768648f..02858779b3 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -182,6 +182,10 @@ struct nhg_ctx {
void zebra_nhg_enable_kernel_nexthops(bool set);
bool zebra_nhg_kernel_nexthops_enabled(void);
+/* Global control for zebra to only use proto-owned nexthops */
+void zebra_nhg_set_proto_nexthops_only(bool set);
+bool zebra_nhg_proto_nexthops_only(void);
+
/**
* NHE abstracted tree functions.
* Use these where possible instead of direct access.
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index baf7d2c14d..7e73b3f724 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -1566,6 +1566,19 @@ DEFPY_HIDDEN(nexthop_group_use_enable,
return CMD_SUCCESS;
}
+DEFPY_HIDDEN (proto_nexthop_group_only,
+ proto_nexthop_group_only_cmd,
+ "[no] zebra nexthop proto only",
+ NO_STR
+ ZEBRA_STR
+ "Nexthop configuration\n"
+ "Configure exclusive use of proto nexthops\n"
+ "Only use proto nexthops\n")
+{
+ zebra_nhg_set_proto_nexthops_only(!no);
+ return CMD_SUCCESS;
+}
+
DEFUN (no_ip_nht_default_route,
no_ip_nht_default_route_cmd,
"no ip nht resolve-via-default",
@@ -3448,6 +3461,9 @@ static int config_write_protocol(struct vty *vty)
if (!zebra_nhg_kernel_nexthops_enabled())
vty_out(vty, "no zebra nexthop kernel enable\n");
+ if (zebra_nhg_proto_nexthops_only())
+ vty_out(vty, "zebra nexthop proto only\n");
+
#ifdef HAVE_NETLINK
/* Include netlink info */
netlink_config_write_helper(vty);
@@ -3882,6 +3898,7 @@ void zebra_vty_init(void)
install_element(CONFIG_NODE, &zebra_packet_process_cmd);
install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
install_element(CONFIG_NODE, &nexthop_group_use_enable_cmd);
+ install_element(CONFIG_NODE, &proto_nexthop_group_only_cmd);
install_element(VIEW_NODE, &show_nexthop_group_cmd);
install_element(VIEW_NODE, &show_interface_nexthop_group_cmd);