diff options
author | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-06-21 17:43:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-21 17:43:45 +0200 |
commit | 01ceb8b23cf2cc51649a719798f1a7a90a005de3 (patch) | |
tree | b51a079a087e8da844d73bd45814458353217f9e /zebra | |
parent | Merge pull request #11351 from kuldeepkash/uplink_mcast_tests (diff) | |
parent | zebra: Add a configurable knob `zebra nexthop-group keep (1-3600)` (diff) | |
download | frr-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.c | 7 | ||||
-rw-r--r-- | zebra/zebra_nhg.c | 36 | ||||
-rw-r--r-- | zebra/zebra_nhg.h | 29 | ||||
-rw-r--r-- | zebra/zebra_router.c | 2 | ||||
-rw-r--r-- | zebra/zebra_router.h | 3 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 31 |
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); |