static route bfd admin down state handling improvements - #21400
Conversation
Greptile SummaryThis PR fixes unnecessary route churn in Key changes:
Concern:
Confidence Score: 4/5Needs review of the ADMIN_DOWNβDOWN guard before merging; a real-failure scenario following admin-down removal can leave routes permanently installed. The BSS_UP early-exit guard and all test infrastructure look correct. The BSS_DOWN guard introduces a P1 correctness regression: when admin-down is removed and the peer is genuinely unreachable, the BFD callback fires once (ADMIN_DOWNβDOWN), the fix skips route removal, and because lib/bfd.c only notifies on state changes (line 994β996), no further callbacks fire. The route stays installed indefinitely despite the path being down. staticd/static_bfd.c β the BSS_DOWN early-exit guard at line 46 needs to handle the permanent-DOWN case. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[BFD state-change callback fires] --> B{bss->state?}
B -->|BSS_UNKNOWN| C[No action]
B -->|BSS_ADMIN_DOWN| C
B -->|BSS_DOWN| D{previous_state == BSS_ADMIN_DOWN\nAND !sn->path_down?}
D -->|YES β NEW guard| E[Break: keep route installed\nβ οΈ Also skips removal if peer is\ngenuinely unreachable]
D -->|NO| F[path_down = true\nstatic_zebra_route_add\nremove route from RIB]
B -->|BSS_UP| G{!sn->path_down?\nroute already installed}
G -->|YES β NEW guard| H[Break: no redundant add]
G -->|NO| I[path_down = false\nstatic_zebra_route_add\nadd route to RIB]
Prompt To Fix All With AIThis is a comment left during a code review.
Path: staticd/static_bfd.c
Line: 46-51
Comment:
**Route stays installed permanently when peer is unreachable after admin-down is lifted**
The fix correctly prevents unnecessary route churn during the `ADMIN_DOWN β DOWN β UP` sequence, but it introduces a correctness regression when the peer is genuinely unreachable after admin-down is removed.
**Problematic scenario:**
1. BFD is UP, route installed (`path_down = false`)
2. Operator shuts down BFD session β `BSS_ADMIN_DOWN` event fires, route stays installed (correct)
3. Meanwhile, the remote peer becomes unreachable (link failure, daemon crash, etc.)
4. Operator removes admin-down β BFD transitions `ADMIN_DOWN β DOWN` immediately
5. The callback fires with `bss->previous_state == BSS_ADMIN_DOWN` and `!sn->path_down` β **route removal is skipped**
6. BFD stays in `DOWN` state indefinitely because the remote is unreachable
7. **No further callbacks fire**, confirmed by `lib/bfd.c` line 994β996:
```c
if ((int)bsp->bss.state == state)
continue;
```
The `updatecb` is only triggered on state *changes*. Since BFD stays in `DOWN`, the route **remains installed forever** even though the peer is genuinely down β defeating the entire purpose of BFD route tracking.
The condition `previous_state == BSS_ADMIN_DOWN` cannot distinguish between a transient DOWN (on the way to UP) and a permanent DOWN (peer unreachable). At the time the `BSS_DOWN` event fires, the reachability of the peer is not yet known.
One approach: use a short hold-down timer β delay route removal briefly when `previous_state == BSS_ADMIN_DOWN`, and cancel the timer if `BSS_UP` arrives. Another option: always remove the route on `BSS_DOWN` (restoring the original behaviour) but rely solely on the `BSS_UP` guard to avoid the double-add, which the second half of this fix already handles correctly.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: tests/topotests/static_bfd_admin_down/test_static_bfd_admin_down.py
Line: 326-340
Comment:
**Missing test coverage for real-failure-after-admin-down scenario**
The test suite includes `test_bfd_real_failure_removes_routes`, which verifies that a real link failure starting from `BSS_UP` still removes the route. However, there is no test for the scenario identified in the core logic issue: admin-down is removed while the peer is genuinely unreachable (i.e., `ADMIN_DOWN β DOWN` where DOWN is permanent, not transient).
A test along these lines would be valuable:
1. Bring the link down to simulate a real failure.
2. While the session is in DOWN state, admin-down the BFD profile on r1.
3. Remove admin-down on r1 (link still down).
4. Verify that the route is eventually removed (since the peer is still unreachable).
This case maps directly to the regression introduced by the `previous_state == BSS_ADMIN_DOWN` guard in `BSS_DOWN`.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "tests: add topotest for static route BFD..." | Re-trigger Greptile |
|
please correct the PR headline to match our conventions |
riw777
left a comment
There was a problem hiding this comment.
headline needs to be fixed ...
rzalamena
left a comment
There was a problem hiding this comment.
Please merge the third commit into the first so we have less commits (and less logic change)
| switch (bss->state) { | ||
| case BSS_UNKNOWN: | ||
| /* FALLTHROUGH: no known state yet. */ | ||
| case BSS_ADMIN_DOWN: |
There was a problem hiding this comment.
Let's assume a situation where static route started installed and BFD session administratively down.
What happens when we transition to BFD session down and then back to administratively down? It seems to me that the BSS_DOWN timer would remain and after 5 seconds in BSS_ADMIN_DOWN the route would be uninstalled. Is this the desired behavior? I think that when in BSS_ADMIN_DOWN state the route should be kept installed (BFD session is "working" its just administratively shutdown).
There was a problem hiding this comment.
What happens when we transition to BFD session down and then back to administratively down?
Sougata>>
holddown timer starts only when bss->previous_state == BSS_ADMIN_DOWN && !sn->path_down. So in this case no change, route already removed when BFD session went down. admin down will only cancle the holddown timer.
@rzalamena
riw777
left a comment
There was a problem hiding this comment.
looks good, waiting on @rzalamena 's comments
85859e0 to
1830390
Compare
Avoid unnecessary static route removal/reinstall when BFD transitions Admin Down -> Down -> Up after clearing local administrative shutdown. When admin-down is lifted while the peer may be unreachable, use a short hold-down after Admin Down -> Down: cancel the timer if BFD reaches Up; otherwise remove the stale route when the timer expires. Cancel pending hold-down when re-entering admin-down, when BFD reaches Up, or when BFD monitoring is disabled. Signed-off-by: Sougata Barik <sougatab@nvidia.com>
Add topotests under static_bfd_admin_down/ that exercise BFD profile and per-peer administrative shutdown, admin-down hold-down and cancellation, recovery after link failure, and directed BFD state transitions. Enable "debug static bfd" on staticd and assert expected staticd log lines where appropriate. Signed-off-by: Sougata Barik <sougatab@nvidia.com>
Add provider frr_static with tracepoints aligned to staticd static BFD DEBUG output: session state changes, admin hold-down arm/cancel/expire, generic down removal from RIB, and up (already installed vs install). Signed-off-by: Sougata Barik <sougatab@nvidia.com>
1830390 to
207b2e6
Compare
rzalamena
left a comment
There was a problem hiding this comment.
Looks good, please just apply frrbot formating patch before we can merge it.
Prevent static route deletion/re-addition during BFD admin down/up transitions
Skip route removal when BFD transitions from Admin Down to Down state
Add check to avoid re-installing already installed routes on BFD Up
Enhanced debug logging for BFD state transitions and path status