# Title Recursive BGP next-hop resolution does not fall back to a lower-preference usable IGP route # Description BIRD resolves a recursive BGP next hop using the current best IGP route for the next-hop address. If that best route is itself recursive, BIRD marks the BGP route as unreachable even when a lower-preference route to the same next-hop address is directly usable. In the reproduced topology, the final IGP route set contains both a higher-preference recursive static route and a lower-preference OSPF route for the BGP next-hop `/32`. The OSPF route is usable and resolves to a direct next hop, but the BGP route is still installed as unreachable. # Version Reproduced with: ```text BIRD 2.18+branch.master.f0f859c26cf9 ``` # How to reproduce 1. Build a three-router topology: ```text iBGP advertises 203.0.113.0/24 NEXT_HOP=10.0.0.2 +---------------------------+ | | +------+ +------+ | r2 | | r1 | +------+ +------+ | | OSPF, 198.51.100.0/24 | +------+ | r3 | +------+ r3 advertises OSPF stub routes: 10.0.0.2/32 172.16.0.1/32 ``` 2. On `r1`, configure the BGP channel to use recursive next-hop resolution through the IGP table: ```bird protocol bgp bgp_from_r2 { ipv4 { import all; export none; gateway recursive; igp table master4; }; local as 65000; neighbor <r2-address> as 65000; } ``` 3. On `r2`, advertise `203.0.113.0/24` to `r1` and set `bgp_next_hop = 10.0.0.2` in the export policy. 4. On `r1` and `r3`, run OSPF so that `r1` learns `10.0.0.2/32` via `r3`, reachable through `198.51.100.2` on `r1`'s OSPF-facing interface. 5. Add a higher-preference recursive static route on `r1`: ```bird route 10.0.0.2/32 recursive 172.16.0.1; ``` 6. Confirm that `r1` has both routes for `10.0.0.2/32`: - Higher-preference `static_recursive`. - Lower-preference but usable `ospf_igp`, via `198.51.100.2` on the OSPF-facing interface. 7. Inspect `r1`'s route for `203.0.113.0/24` and the Linux FIB: ```bash birdc show route for 203.0.113.0/24 all ip route show 203.0.113.0/24 ``` # Expected behavior BIRD should resolve the BGP route through the lower-preference usable OSPF route when the higher-preference route cannot provide a valid recursive next-hop result. The BGP route should remain reachable via: ```text via 198.51.100.2 on r1-eth1 ``` # Actual behavior With only the OSPF route, BIRD resolves and installs the BGP route correctly: ```text 203.0.113.0/24 unicast [bgp_from_r2 ...] * (100/20) [i] via 198.51.100.2 on r1-eth1 ``` After the higher-preference recursive static route is present, BIRD marks the same BGP route unreachable: ```text 203.0.113.0/24 unreachable [bgp_from_r2 ...] * (100) [i] ``` The Linux FIB also contains an unreachable route: ```text unreachable 203.0.113.0/24 proto bird metric 32 ``` # Additional context The suspected source path is the recursive hostentry update logic used by BGP next-hop resolution. The implementation appears to start from the current best IGP route and stop when it encounters a route with hostentry/recursive state at the best preference level, instead of continuing to search lower-preference routes that are directly usable. This makes a valid BGP route unreachable solely because a higher-preference recursive route exists for the same next-hop address.