Skip to content

ip: preserve connected routes during protocol replay - #703

Draft
hcaldicott wants to merge 1 commit into
DPDK:mainfrom
hcaldicott:fix/connected-routes
Draft

ip: preserve connected routes during protocol replay#703
hcaldicott wants to merge 1 commit into
DPDK:mainfrom
hcaldicott:fix/connected-routes

Conversation

@hcaldicott

@hcaldicott hcaldicott commented Aug 17, 2026

Copy link
Copy Markdown

During control-plane replay, a routing daemon can briefly advertise a
connected prefix before it has learned the interface address, then
withdraw it again once it reconciles. route4_add() replaces the
address-owned connected route with the protocol route, so the later
withdrawal removes the only route to the prefix while the address stays
configured — the connected network is unreachable until the address is
removed and re-added.

This change treats address-owned connected routes as authoritative:
protocol adds for such prefixes are accepted as a silent no-op, and API
deletes of internal-origin routes are refused the same way. Deletions now
resolve their nexthop with an exact-prefix lookup first, so the nexthop
type of a covering route is never used to delete a more specific prefix;
the previous longest-prefix lookup remains as the fallback when no exact
entry exists. Same handling for both address families.

Found while integrating FRR restart handling for EVPN multihoming (#698),
but the race only needs a routing daemon replaying routes over a
configured address.

Testing

  • New smoke test connected_route_ownership_test.sh replays the
    add/withdraw cycle over configured IPv4 and IPv6 addresses and asserts
    the connected routes survive with their link origin.
  • Without the fix (test-only applied to main): the test fails at the
    first assertion — after add/withdraw, 172.16.0.0/24 is gone from the
    RIB entirely.
  • With the fix: the new test passes, the full unit suite passes, and
    ip_loadbalance_test.sh confirms ordinary route add/del and ECMP
    behaviour is unchanged (AlmaLinux 9 container, arm64).

Related: #698

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@rjarry rjarry left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Harrison,

Your check is a bit loose. See how to make it more robust below.

Also could you remove any mention that you were assisted by AI? It does not bring much value and we prefer to keep the git history leaner.

Thanks!

Comment thread modules/ip/control/route.c
Comment thread modules/ip/control/route.c
Comment thread modules/ip6/control/route.c
Comment thread modules/ip6/control/route.c
@hcaldicott
hcaldicott force-pushed the fix/connected-routes branch from 3b4929b to b973e2e Compare August 20, 2026 00:18
@hcaldicott

Copy link
Copy Markdown
Author

Hey Harrison,

Your check is a bit loose. See how to make it more robust below.

Also could you remove any mention that you were assisted by AI? It does not bring much value and we prefer to keep the git history leaner.

Thanks!

Good pickups - I will address these and re-run my lab tests!

During control-plane replay, a routing daemon can briefly advertise a
connected prefix before it has learned the interface address, then
withdraw it again once it reconciles. route4_add() replaced the
address-owned connected route with the protocol route, so the later
withdrawal removed the only route to the prefix while the address
stayed configured, cutting off the connected network until the
address was re-added.

Add is_addr_owned_route() which checks that the route's RIB origin is
internal and that its nexthop carries the local address flags. Accept
protocol adds for such prefixes as a silent no-op and refuse deleting
them with EBUSY. Deletions resolve their nexthop with an exact-prefix
lookup first so the nexthop type of a covering route is never used to
delete a more specific prefix; the previous longest-prefix lookup
remains as the fallback when no exact entry exists.

Add a smoke test replaying the add/withdraw cycle over configured IPv4
and IPv6 addresses, checking the withdrawal is refused and the
connected routes survive.

Signed-off-by: Harrison Caldicott <harrison@itsfubar.com.au>
@hcaldicott
hcaldicott force-pushed the fix/connected-routes branch from b973e2e to 25cac2c Compare August 20, 2026 00:52
@hcaldicott
hcaldicott marked this pull request as draft August 20, 2026 00:59
@hcaldicott

Copy link
Copy Markdown
Author

I have updated the PR. I am now rebuilding our physical lab on this to re-test the corrected behaviour. Converting back to a draft until my testing is completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants