Recursive BGP next-hop resolution does not fall back to a lower-preference usable IGP route
水兵
jxshuibei at gmail.com
Tue May 12 08:23:43 CEST 2026
# 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://trubka.network.cz/pipermail/bird-users/attachments/20260512/65f47036/attachment.htm>
More information about the Bird-users
mailing list