Potential bug: Inconsistent next-hop resolution in multi-homed same-subnet setup

Pysio mcyouyousever at gmail.com
Sun Jan 11 22:40:42 CET 2026


Hi Alexander,

Thanks for the tips!

I just tried the multihop (recursive) approach, but unfortunately, it
didn't change anything. Even with multihop on, BIRD still picks ens23 for
the next hop resolution. It seems like it's still looking at the global
interface list instead of sticking to the route in the specific table I've
assigned.

I'll give VRFs a shot later tonight to see if that fixes

While VRFs should work as a workaround, I still feel like BIRD should
ideally handle this better out of the box. In a multi-table setup, you'd
expect it to prioritize the lookup within the attached table first.

Anyway, I’ll let you know how the VRF test goes!

Best,

Liu HaoRan

On Mon, Jan 12, 2026 at 3:03 AM Alexander Zubkov <green at qrator.net> wrote:

> I probably saw something like that bug for IPv6, so not sure if it is the
> same. And I did not have separate tables for the interfaces. But worth a
> check anyway. It seemed to me that direct sessions created routes with the
> interface and ip through that the bgi session was installed. And recursive
> (multihop) sessions set the routes to the first found interface (I remind,
> I had all them in one table).
> So you can try to change protocol to recursive to check (but it could have
> other drawbacks) if it would use the appropriate route from the attached
> table.
> Also, if you wander of the possible solutions, I think you could play with
> vrfs to divide the interfaces routing, bird is aware of vrfs.
>
> On Sun, Jan 11, 2026 at 7:09 PM Pysio <mcyouyousever at gmail.com> wrote:
>
>> Additionally, I should mention that the issue persists even when I
>> explicitly declare the IGP table using the following configuration file.
>>
>> protocol bgp cloudflare_tpix_210440_v4 {
>>     local as 210440;
>>     source address 203.163.223.48;
>>     neighbor 203.163.222.39 as 13335;
>>     ipv4 {
>>         table table_tpix_210440_v4;
>>         import keep filtered on;
>>         import where import_filter_v4();
>>         export where export_filter_tpix_210440();
>>         graceful restart on;
>>         export limit 99 action block;
>>         igp table table_tpix_210440_v4;
>>     };
>> }
>>
>> BIRD 2.17.1 ready.
>> Table table_tpix_210440_v4:
>> 1.1.1.0/24           unicast [cloudflare_tpix_210440_v4 2026-01-12
>> 02:07:03] * (100) [AS13335i]
>>         via 203.163.222.39 on ens23
>>         Type: BGP univ
>>         BGP.origin: IGP
>>         BGP.as_path: 13335
>>         BGP.next_hop: 203.163.222.39
>>         BGP.local_pref: 100
>>         BGP.aggregator: 162.158.240.1 AS13335
>>         BGP.community: (13335,10080)
>>         BGP.large_community: (213605, 10, 1) (213605, 10, 4)
>>
>>
>> BIRD 2.17.1 ready.
>> Table table_tpix_210440_v4:
>> 203.163.222.0/23     unicast [direct_tpix_210440 2026-01-12 02:04:33] *
>> (240)
>>         dev ens4
>>         Type: device univ
>>
>>
>> On Mon, Jan 12, 2026 at 1:57 AM Pysio <mcyouyousever at gmail.com> wrote:
>>
>>> Hi Alexander,
>>>
>>> Thank you for your response. To answer your question: yes, I am using
>>> specific tables (e.g., table_tpix_210440_v4) for each BGP session, and
>>> I have corresponding protocol direct instances to populate those tables
>>> with the respective interface routes.
>>>
>>> However, despite having a valid direct route in the specific table, BIRD
>>> still resolves the BGP next hop via ens23 (the first interface in the
>>> kernel's subnet list) instead of honoring the device route defined in the
>>> local table.
>>>
>>> Below is the relevant part of my configuration for your review.
>>>
>>> ```config
>>> table table_tpix_210440_v4;
>>> table table_tpix_210440_v6;
>>>
>>> protocol direct direct_tpix_210440 {
>>>     ipv4 { table table_tpix_210440_v4; };
>>>     ipv6 { table table_tpix_210440_v6; };
>>>     interface "ens4";
>>> }
>>>
>>>
>>> protocol bgp cloudflare_tpix_210440_v4 {
>>>     local as 210440;
>>>     source address 203.163.223.48;
>>>     neighbor 203.163.222.39 as 13335;
>>>     ipv4 {
>>>         table table_tpix_210440_v4;
>>>         import keep filtered on;
>>>         import where import_filter_v4();
>>>         export where export_filter_tpix_210440();
>>>         graceful restart on;
>>>         export limit 99 action block;
>>>     };
>>> }
>>>
>>> ```
>>>
>>> Even though table_tpix_210440_v4 contains a direct route for
>>> 203.163.222.0/23 via ens4, BIRD's show route output for the BGP session
>>> on ens4 indicates the next hop is resolved via ens23.
>>>
>>> On Mon, Jan 12, 2026 at 1:06 AM Alexander Zubkov <green at qrator.net>
>>> wrote:
>>>
>>>> Hi Lui,
>>>>
>>>> Does cloudflare_tpix_210440_v4 bgp protocol use table_tpix_210440_v4 as
>>>> IGP table also? It might be better to have an overview of your config file.
>>>>
>>>> Regards,
>>>> Alexander
>>>>
>>>> On Sun, Jan 11, 2026 at 3:14 PM HaoRanLiu <mcyouyousever at gmail.com>
>>>> wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> I am writing to report a potential issue (or seek clarification on
>>>>> resolution logic) in BIRD 2.17.1 regarding how next hops are resolved
>>>>> when multiple interfaces exist in the same subnet.
>>>>>
>>>>> [ Environment ]
>>>>> - BIRD version: 2.17.1
>>>>> - OS: Linux
>>>>> - Setup: Multiple physical interfaces (ens4, ens23, ens2) are
>>>>> configured
>>>>> with IP addresses in the same prefix: 203.163.222.0/23.
>>>>>
>>>>> [ Observation ]
>>>>> Within a specific routing table (table_tpix_210440_v4), BIRD's
>>>>> recursive
>>>>> resolution for a BGP route does not seem to honor the "Direct/Device"
>>>>> route present in that same table.
>>>>>
>>>>> [ Evidence ]
>>>>>
>>>>> 1. The Direct Route in table "table_tpix_210440_v4" points to ens4:
>>>>>
>>>>> bird> show route for 203.163.222.39/32 table table_tpix_210440_v4 all
>>>>> Table table_tpix_210440_v4:
>>>>> 203.163.222.0/23     unicast [direct_tpix_210440 2026-01-11 21:10:29]
>>>>> *
>>>>> (240)
>>>>>          dev ens4
>>>>>          Type: device univ
>>>>>
>>>>> 2. However, a BGP route in the SAME table resolves via ens23:
>>>>>
>>>>> bird> show route for 1.1.1.1 table table_tpix_210440_v4 all
>>>>> Table table_tpix_210440_v4:
>>>>> 1.1.1.0/24           unicast [cloudflare_tpix_210440_v4 2026-01-11
>>>>> 21:33:43] * (100) [AS13335i]
>>>>>          via 203.163.222.39 on ens23
>>>>>          Type: BGP univ
>>>>>          BGP.origin: IGP
>>>>>          BGP.as_path: 13335
>>>>>          BGP.next_hop: 203.163.222.39
>>>>>          ...
>>>>>
>>>>> [ System Network State ]
>>>>> The OS kernel shows three interfaces in this subnet:
>>>>>
>>>>> # ip route show 203.163.222.0/23
>>>>> 203.163.222.0/23 dev ens23 proto kernel scope link src 203.163.223.49
>>>>> 203.163.222.0/23 dev ens2 proto kernel scope link src 203.163.223.50
>>>>> 203.163.222.0/23 dev ens4 proto kernel scope link src 203.163.223.48
>>>>>
>>>>> [ Questions ]
>>>>> 1. Is this a bug in the recursive resolution logic? It appears BIRD
>>>>> might be picking an interface from the global interface list (perhaps
>>>>> the first one UP) rather than following the best route available in
>>>>> the
>>>>> specific table being queried.
>>>>> 2. Why does the BGP route's "via" field not honor the interface (ens4)
>>>>> defined by the device route in the same table?
>>>>> 3. Is there any configuration to force BIRD to resolve next hops
>>>>> strictly based on the current table's best path in such multi-homed
>>>>> scenarios?
>>>>>
>>>>> Any insights would be appreciated.
>>>>>
>>>>> Best regards,
>>>>> Liu HaoRan
>>>>>
>>>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://trubka.network.cz/pipermail/bird-users/attachments/20260112/050711bd/attachment.htm>


More information about the Bird-users mailing list