Asymmetric ADD/DEL sequences in FIB6 trie (a covering parent
removed between the ADD and DEL of a longer prefix) eventually
make ADD fail with -ENOSPC even when the tbl8 pool is empty.

Patch 2/3 is a small reproducer.

Root cause: rsvd_tbl8s is updated by depth_diff recomputed from
the current RIB, so increments at ADD and decrements at DEL do
not cancel when the RIB state changes in between. The counter
drifts and wraps to UINT32_MAX.

The simplest fix I could find (1/3, 3/3) is to drop rsvd_tbl8s
and use the pool counters already maintained by alloc/free:
tbl8_pool_pos in trie, cur_tbl8s in dir24_8. The DQ reclaim
inside tbl8_alloc() is moved into the pre-check.

I am not sure I understood the original intent of keeping
rsvd_tbl8s separate from the pool counters. In dir24_8 the two
mirror each other 1:1 and rsvd_tbl8s looks redundant; in trie,
depth_diff gives it a worst-case-reservation flavor but the
recomputation from the RIB is exactly what makes it drift. If
there was a deliberate reason, please point it out.

Patch 3/3 is a no-op cleanup that aligns dir24_8 with the trie
pattern.

Maxime Leroy (3):
  fib6: fix tbl8 reservation drift in trie
  test/fib6: add reproducer for tbl8 reservation drift
  fib: drop redundant tbl8 reservation counter

 app/test/test_fib6.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
 lib/fib/dir24_8.c    | 31 ++++++-----------
 lib/fib/dir24_8.h    |  1 -
 lib/fib/trie.c       | 23 ++++++------
 lib/fib/trie.h       |  3 +-
 5 files changed, 104 insertions(+), 37 deletions(-)

-- 
2.43.0

Reply via email to