<div dir="ltr"><div style="color:rgb(51,51,51);background-color:rgb(245,245,245);font-family:Menlo,Monaco,"Courier New",monospace;font-size:14px;line-height:21px;white-space:pre"><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Title</span></div><br><div>Recursive BGP next-hop resolution does not fall back to a lower-preference usable IGP route</div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Description</span></div><br><div>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.</div><br><div>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 <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">/32</span><span style="color:rgb(119,119,119)">`</span>. The OSPF route is usable and resolves to a direct next hop, but the BGP route is still installed as unreachable.</div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Version</span></div><br><div>Reproduced with:</div><br><div><span style="color:rgb(119,119,119)">```</span>text</div><div>BIRD 2.18+branch.master.f0f859c26cf9</div><div><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">How to reproduce</span></div><br><div><span style="color:rgb(119,119,119)">1.</span><span style="color:rgb(75,105,198)"> Build a three-router topology:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">text</span></div><div><span style="color:rgb(75,105,198)">                         iBGP</span></div><div><span style="color:rgb(75,105,198)">          advertises <a href="http://203.0.113.0/24">203.0.113.0/24</a></span></div><div><span style="color:rgb(75,105,198)">          NEXT_HOP=10.0.0.2</span></div><div><span style="color:rgb(75,105,198)">        +---------------------------+</span></div><div><span style="color:rgb(75,105,198)">        |                           |</span></div><div><span style="color:rgb(75,105,198)">     +------+                   +------+</span></div><div><span style="color:rgb(75,105,198)">     |  r2  |                   |  r1  |</span></div><div><span style="color:rgb(75,105,198)">     +------+                   +------+</span></div><div><span style="color:rgb(75,105,198)">                                    |</span></div><div><span style="color:rgb(75,105,198)">                                    | OSPF, <a href="http://198.51.100.0/24">198.51.100.0/24</a></span></div><div><span style="color:rgb(75,105,198)">                                    |</span></div><div><span style="color:rgb(75,105,198)">                                 +------+</span></div><div><span style="color:rgb(75,105,198)">                                 |  r3  |</span></div><div><span style="color:rgb(75,105,198)">                                 +------+</span></div><br><div><span style="color:rgb(75,105,198)">     r3 advertises OSPF stub routes:</span></div><div><span style="color:rgb(75,105,198)">       <a href="http://10.0.0.2/32">10.0.0.2/32</a></span></div><div><span style="color:rgb(75,105,198)">       <a href="http://172.16.0.1/32">172.16.0.1/32</a></span></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">2.</span><span style="color:rgb(75,105,198)"> On </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">, configure the BGP channel to use recursive next-hop resolution through the IGP table:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">bird</span></div><div><span style="color:rgb(75,105,198)">   protocol bgp bgp_from_r2 {</span></div><div><span style="color:rgb(75,105,198)">       ipv4 {</span></div><div><span style="color:rgb(75,105,198)">           import all;</span></div><div><span style="color:rgb(75,105,198)">           export none;</span></div><div><span style="color:rgb(75,105,198)">           gateway recursive;</span></div><div><span style="color:rgb(75,105,198)">           igp table master4;</span></div><div><span style="color:rgb(75,105,198)">       };</span></div><div><span style="color:rgb(75,105,198)">       local as 65000;</span></div><div><span style="color:rgb(75,105,198)">       neighbor <r2-address> as 65000;</span></div><div><span style="color:rgb(75,105,198)">   }</span></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">3.</span><span style="color:rgb(75,105,198)"> On </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r2</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">, advertise </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)"><a href="http://203.0.113.0/24">203.0.113.0/24</a></span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> to </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> and set </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">bgp_next_hop = 10.0.0.2</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> in the export policy.</span></div><br><div><span style="color:rgb(119,119,119)">4.</span><span style="color:rgb(75,105,198)"> On </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> and </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r3</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">, run OSPF so that </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> learns </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)"><a href="http://10.0.0.2/32">10.0.0.2/32</a></span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> via </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r3</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">, reachable through </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">198.51.100.2</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> on </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">'s OSPF-facing interface.</span></div><br><div><span style="color:rgb(119,119,119)">5.</span><span style="color:rgb(75,105,198)"> Add a higher-preference recursive static route on </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">bird</span></div><div><span style="color:rgb(75,105,198)">   route <a href="http://10.0.0.2/32">10.0.0.2/32</a> recursive 172.16.0.1;</span></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">6.</span><span style="color:rgb(75,105,198)"> Confirm that </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> has both routes for </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)"><a href="http://10.0.0.2/32">10.0.0.2/32</a></span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">-</span><span style="color:rgb(75,105,198)"> Higher-preference </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">static_recursive</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">.</span></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">-</span><span style="color:rgb(75,105,198)"> Lower-preference but usable </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">ospf_igp</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">, via </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">198.51.100.2</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> on the OSPF-facing interface.</span></div><br><div><span style="color:rgb(119,119,119)">7.</span><span style="color:rgb(75,105,198)"> Inspect </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)">'s route for </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)"><a href="http://203.0.113.0/24">203.0.113.0/24</a></span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> and the Linux FIB:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">bash</span></div><div><span style="color:rgb(75,105,198)">   </span>birdc show route <span style="color:rgb(75,105,198)">for</span> <a href="http://203.0.113.0/24">203.0.113.0/24</a> all</div><div><span style="color:rgb(75,105,198)">   </span>ip route show <a href="http://203.0.113.0/24">203.0.113.0/24</a></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Expected behavior</span></div><br><div>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:</div><br><div><span style="color:rgb(119,119,119)">```</span>text</div><div>via 198.51.100.2 on r1-eth1</div><div><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Actual behavior</span></div><br><div>With only the OSPF route, BIRD resolves and installs the BGP route correctly:</div><br><div><span style="color:rgb(119,119,119)">```</span>text</div><div><a href="http://203.0.113.0/24">203.0.113.0/24</a> unicast [bgp_from_r2 ...] * (100/20) [i]</div><div>        via 198.51.100.2 on r1-eth1</div><div><span style="color:rgb(119,119,119)">```</span></div><br><div>After the higher-preference recursive static route is present, BIRD marks the same BGP route unreachable:</div><br><div><span style="color:rgb(119,119,119)">```</span>text</div><div><a href="http://203.0.113.0/24">203.0.113.0/24</a> unreachable [bgp_from_r2 ...] * (100) [i]</div><div><span style="color:rgb(119,119,119)">```</span></div><br><div>The Linux FIB also contains an unreachable route:</div><br><div><span style="color:rgb(119,119,119)">```</span>text</div><div>unreachable <a href="http://203.0.113.0/24">203.0.113.0/24</a> proto bird metric 32</div><div><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Additional context</span></div><br><div>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.</div><br></div></div>