mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 22:37:49 +00:00
commit
01ceb8b23c
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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..
|
||||
*/
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user