Commit 14597ebb3f for frr
commit 14597ebb3fefe2d1b9738f02d03840d086015362
Author: Minghan Chan <mhchann082@gmail.com>
Date: Fri Nov 6 08:22:23 2026 +0800
bfdd: walk the reflectors when no sbfd reflector deletes a range
"no sbfd reflector START END" looked up every value from START to END
with an int32_t counter, which cannot reach an END above 2147483647.
Incrementing it past that is undefined behavior. Built with -O0 the
loop never ends; gcc 11 at -O2 widens the counter and stops after 2^32
lookups, which kept bfdd busy for 30 seconds in testing. Either way
bfdd serves neither vty nor BFD packets meanwhile, and even a range
that ends lower costs one hash lookup per value.
Walk the configured reflectors and free those in the range instead.
hash_iterate() saves the next bucket before calling back, so freeing
the current one is safe, as sbfd_reflector_flush() already relies on.
Fixes #24202
Signed-off-by: Minghan Chan <mhchann082@gmail.com>
diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c
index d2b50f5c55..e0d5283877 100644
--- a/bfdd/bfdd_cli.c
+++ b/bfdd/bfdd_cli.c
@@ -1386,6 +1386,24 @@ DEFPY(
return CMD_SUCCESS;
}
+struct sbfd_reflector_range {
+ uint32_t from;
+ uint32_t to;
+};
+
+static void _sbfd_reflector_free_range(struct hash_bucket *hb, void *arg)
+{
+ struct sbfd_reflector *sr = hb->data;
+ struct sbfd_reflector_range *range = arg;
+
+ if (sr->discr < range->from || sr->discr > range->to)
+ return;
+
+ // notify bfdsyncd
+ //bfd_fpm_sbfd_reflector_sendmsg(sr, false);
+ sbfd_reflector_free(sr->discr);
+}
+
DEFPY(
no_sbfd_reflector, no_sbfd_reflector_cmd,
"no sbfd reflector (0-4294967295)$start_discr [(0-4294967295)$end_discr]",
@@ -1396,7 +1414,7 @@ DEFPY(
"end discriminator\n")
{
struct sbfd_reflector *sr;
- int32_t i;
+ struct sbfd_reflector_range range;
if (end_discr == 0) {
if (start_discr == 0) {
@@ -1420,14 +1438,10 @@ DEFPY(
return CMD_WARNING_CONFIG_FAILED;
}
- for (i = start_discr; i <= end_discr; i++) {
- sr = sbfd_discr_lookup(i);
- if (sr) {
- // notify bfdsyncd
- //bfd_fpm_sbfd_reflector_sendmsg(sr, false);
- sbfd_reflector_free(i);
- }
- }
+ /* Walk the reflectors, not the range, which can span 2^32 values. */
+ range.from = start_discr;
+ range.to = end_discr;
+ sbfd_discr_iterate(_sbfd_reflector_free_range, &range);
}
return CMD_SUCCESS;