summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorDonatas Abraitis <donatas@opensourcerouting.org>2022-06-21 17:43:45 +0200
committerGitHub <noreply@github.com>2022-06-21 17:43:45 +0200
commit01ceb8b23cf2cc51649a719798f1a7a90a005de3 (patch)
treeb51a079a087e8da844d73bd45814458353217f9e /zebra
parentMerge pull request #11351 from kuldeepkash/uplink_mcast_tests (diff)
parentzebra: Add a configurable knob `zebra nexthop-group keep (1-3600)` (diff)
downloadfrr-01ceb8b23cf2cc51649a719798f1a7a90a005de3.tar.xz
frr-01ceb8b23cf2cc51649a719798f1a7a90a005de3.zip
Merge pull request #11417 from donaldsharp/nhg_timer
Nhg timer
Diffstat (limited to 'zebra')
-rw-r--r--zebra/interface.c7
-rw-r--r--zebra/zebra_nhg.c36
-rw-r--r--zebra/zebra_nhg.h29
-rw-r--r--zebra/zebra_router.c2
-rw-r--r--zebra/zebra_router.h3
-rw-r--r--zebra/zebra_vty.c31
6 files changed, 96 insertions, 12 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 96e378444..93ffeb437 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -184,13 +184,6 @@ static int if_zebra_new_hook(struct interface *ifp)
static void if_nhg_dependents_check_valid(struct nhg_hash_entry *nhe)
{
zebra_nhg_check_valid(nhe);
- if (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {
- /* If we're in shutdown, this interface event needs to clean
- * up installed NHGs, so don't clear that flag directly.
- */
- if (!zrouter.in_shutdown)
- UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
- }
}
static void if_down_nhg_dependents(const struct interface *ifp)
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 500f4b0f1..f025507f7 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1055,6 +1055,12 @@ static void zebra_nhg_set_invalid(struct nhg_hash_entry *nhe)
UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+ /* If we're in shutdown, this interface event needs to clean
+ * up installed NHGs, so don't clear that flag directly.
+ */
+ if (!zrouter.in_shutdown)
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+
/* Update validity of nexthops depending on it */
frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
zebra_nhg_check_valid(rb_node_dep->nhe);
@@ -1619,6 +1625,17 @@ void zebra_nhg_hash_free(void *p)
zebra_nhg_free((struct nhg_hash_entry *)p);
}
+static void zebra_nhg_timer(struct thread *thread)
+{
+ struct nhg_hash_entry *nhe = THREAD_ARG(thread);
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("Nexthop Timer for nhe: %pNG", nhe);
+
+ if (nhe->refcnt == 1)
+ zebra_nhg_decrement_ref(nhe);
+}
+
void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe)
{
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
@@ -1627,6 +1644,15 @@ void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe)
nhe->refcnt--;
+ if (!zrouter.in_shutdown && nhe->refcnt <= 0 &&
+ CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) &&
+ !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_KEEP_AROUND)) {
+ nhe->refcnt = 1;
+ SET_FLAG(nhe->flags, NEXTHOP_GROUP_KEEP_AROUND);
+ thread_add_timer(zrouter.master, zebra_nhg_timer, nhe,
+ zrouter.nhg_keep, &nhe->timer);
+ }
+
if (!zebra_nhg_depends_is_empty(nhe))
nhg_connected_tree_decrement_ref(&nhe->nhg_depends);
@@ -1642,6 +1668,12 @@ void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe)
nhe->refcnt++;
+ if (thread_is_scheduled(nhe->timer)) {
+ THREAD_OFF(nhe->timer);
+ nhe->refcnt--;
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_KEEP_AROUND);
+ }
+
if (!zebra_nhg_depends_is_empty(nhe))
nhg_connected_tree_increment_ref(&nhe->nhg_depends);
}
@@ -3290,9 +3322,6 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
rib_handle_nhg_replace(old, new);
- /* if this != 1 at this point, we have a bug */
- assert(old->refcnt == 1);
-
/* We have to decrement its singletons
* because some might not exist in NEW.
*/
@@ -3304,6 +3333,7 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
/* Dont call the dec API, we dont want to uninstall the ID */
old->refcnt = 0;
+ THREAD_OFF(old->timer);
zebra_nhg_free(old);
old = NULL;
}
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 0863d90a7..6d2ab248f 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -79,16 +79,34 @@ struct nhg_hash_entry {
uint32_t flags;
- /* Dependency tree for other entries.
+ /* Dependency trees for other entries.
* For instance a group with two
* nexthops will have two dependencies
* pointing to those nhg_hash_entries.
*
* Using a rb tree here to make lookups
* faster with ID's.
+ *
+ * nhg_depends the RB tree of entries that this
+ * group contains.
+ *
+ * nhg_dependents the RB tree of entries that
+ * this group is being used by
+ *
+ * NHG id 3 with nexthops id 1/2
+ * nhg(3)->nhg_depends has 1 and 2 in the tree
+ * nhg(3)->nhg_dependents is empty
+ *
+ * nhg(1)->nhg_depends is empty
+ * nhg(1)->nhg_dependents is 3 in the tree
+ *
+ * nhg(2)->nhg_depends is empty
+ * nhg(3)->nhg_dependents is 3 in the tree
*/
struct nhg_connected_tree_head nhg_depends, nhg_dependents;
+ struct thread *timer;
+
/*
* Is this nexthop group valid, ie all nexthops are fully resolved.
* What is fully resolved? It's a nexthop that is either self contained
@@ -130,6 +148,15 @@ struct nhg_hash_entry {
#define NEXTHOP_GROUP_PROTO_RELEASED (1 << 5)
/*
+ * When deleting a NHG notice that it is still installed
+ * and if it is, slightly delay the actual removal to
+ * the future. So that upper level protocols might
+ * be able to take advantage of some NHG's that
+ * are there
+ */
+#define NEXTHOP_GROUP_KEEP_AROUND (1 << 6)
+
+/*
* Track FPM installation status..
*/
#define NEXTHOP_GROUP_FPM (1 << 6)
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 6b4a7543c..92d519bad 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -278,6 +278,8 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
+ zrouter.nhg_keep = ZEBRA_DEFAULT_NHG_KEEP_TIMER;
+
zebra_vxlan_init();
zebra_mlag_init();
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index 7aca91959..c96c8e5f4 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -219,6 +219,9 @@ struct zebra_router {
bool notify_on_ack;
bool supports_nhgs;
+
+#define ZEBRA_DEFAULT_NHG_KEEP_TIMER 180
+ uint32_t nhg_keep;
};
#define GRACEFUL_RESTART_TIME 60
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index be19b07d9..9149da8b0 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -1433,14 +1433,22 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe)
struct nhg_connected *rb_node_dep = NULL;
struct nexthop_group *backup_nhg;
char up_str[MONOTIME_STRLEN];
+ char time_left[MONOTIME_STRLEN];
uptime2str(nhe->uptime, up_str, sizeof(up_str));
vty_out(vty, "ID: %u (%s)\n", nhe->id, zebra_route_string(nhe->type));
- vty_out(vty, " RefCnt: %u\n", nhe->refcnt);
+ vty_out(vty, " RefCnt: %u", nhe->refcnt);
+ if (thread_is_scheduled(nhe->timer))
+ vty_out(vty, " Time to Deletion: %s",
+ thread_timer_to_hhmmss(time_left, sizeof(time_left),
+ nhe->timer));
+ vty_out(vty, "\n");
+
vty_out(vty, " Uptime: %s\n", up_str);
vty_out(vty, " VRF: %s\n", vrf_id_to_name(nhe->vrf_id));
+
if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {
vty_out(vty, " Valid");
if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED))
@@ -3842,11 +3850,31 @@ DEFUN (no_ip_zebra_import_table,
return (zebra_import_table(AFI_IP, VRF_DEFAULT, table_id, 0, NULL, 0));
}
+DEFPY (zebra_nexthop_group_keep,
+ zebra_nexthop_group_keep_cmd,
+ "[no] zebra nexthop-group keep (1-3600)",
+ NO_STR
+ ZEBRA_STR
+ "Nexthop-Group\n"
+ "How long to keep\n"
+ "Time in seconds from 1-3600\n")
+{
+ if (no)
+ zrouter.nhg_keep = ZEBRA_DEFAULT_NHG_KEEP_TIMER;
+ else
+ zrouter.nhg_keep = keep;
+
+ return CMD_SUCCESS;
+}
+
static int config_write_protocol(struct vty *vty)
{
if (allow_delete)
vty_out(vty, "allow-external-route-update\n");
+ if (zrouter.nhg_keep != ZEBRA_DEFAULT_NHG_KEEP_TIMER)
+ vty_out(vty, "zebra nexthop-group keep %u\n", zrouter.nhg_keep);
+
if (zrouter.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
vty_out(vty, "zebra work-queue %u\n", zrouter.ribq->spec.hold);
@@ -4425,6 +4453,7 @@ void zebra_vty_init(void)
install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
+ install_element(CONFIG_NODE, &zebra_nexthop_group_keep_cmd);
install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);