Merge pull request #11417 from donaldsharp/nhg_timer

Nhg timer
This commit is contained in:
Donatas Abraitis 2022-06-21 18:43:45 +03:00 committed by GitHub
commit 01ceb8b23c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 102 additions and 12 deletions

View File

@ -273,6 +273,12 @@ Nexthop tracking doesn't resolve nexthops via the default route by default.
Allowing this might be useful when e.g. you want to allow BGP to peer across
the default route.
.. clicmd:: zebra nexthop-group keep (1-3600)
Set the time that zebra will keep a created and installed nexthop group
before removing it from the system if the nexthop group is no longer
being used. The default time is 180 seconds.
.. clicmd:: ip nht resolve-via-default
Allow IPv4 nexthop tracking to resolve via the default route. This parameter

View File

@ -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)

View File

@ -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;
}

View File

@ -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
@ -129,6 +147,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..
*/

View File

@ -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();

View File

@ -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

View File

@ -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);