Re: [PATCH AUTOSEL 6.18-5.10] ipv6: Honor oif when choosing nexthop for locally generated traffic
From: Flo Müller
Date: Thu Sep 17 2026 - 15:25:18 EST
On Mon, Aug 31, 2026 at 09:23:59AM -0400, Sasha Levin wrote:
> From: Ido Schimmel <idosch@xxxxxxxxxx>
>
> [ Upstream commit d25e7e9d8a6c1e2afb854613e417c6aa1a28ce6f ]
[...]
> **Step 3.5 — Dependencies**
> Record: Patch 2 is **standalone for classic multipath routes**
> (reproducer in commit message). For **nexthop object** multipath, patch
> 1/3 is also needed so `fib6_table_lookup()` picks the best-scoring
> nexthop before path selection is skipped. Patch 1 not in tree; patch 2
> alone does not worsen nexthop-object behavior.
[...]
> **Recommendation for v6.18.y:** Backport this commit. Ideally backport
> patch 1/3 from the same series together for complete nexthop-object
> multipath coverage; patch 2 alone is still valuable and safe for classic
> multipath routes.
Hi Sasha,
we are the nexthop-object case from your dependency note, hit in
production on 6.12.y, so here is a real-world data point and a request
to carry patch 1/3 along.
(Disclaimer: Analysis below done by AI, watched and confirmed by human)
Setup: Debian 13 host, kernel 6.12.101, dual-homed to two ToR switches
over unnumbered eBGP (FRR). FRR installs the default route through a
nexthop group, which is what every FRR or Cilium dual-homed host looks
like:
$ ip -6 route show default
default nhid 20 proto bgp metric 20 pref medium
nexthop via fe80::<tor-a> dev ens31f0np0 weight 1
nexthop via fe80::<tor-b> dev ens30f0np0 weight 1
nexthop via fe80::<tor-a> dev ens31f1np1 weight 1
nexthop via fe80::<tor-b> dev ens30f1np1 weight 1
The kernel's own lookup ignores the oif for this route, with and
without a source address:
$ ip -6 route get 2606:4700:4700::1111 oif ens31f1np1
2606:4700:4700::1111 from :: via fe80::<tor-b> dev ens30f1np1 \
proto bgp src fd00:2:1::11 metric 20 pref medium
$ ip -6 route get 2606:4700:4700::1111 oif ens31f1np1 from 2001:db8:a::1
2606:4700:4700::1111 from 2001:db8:a::1 via fe80::<tor-b> dev ens30f1np1 \
proto bgp src fd00:2:1::11 metric 20 pref medium
Same for a socket. A test tool sends UDP on an AF_INET6/SOCK_RAW/
IPPROTO_UDP socket with IPV6_HDRINCL and SO_BINDTODEVICE=ens31f1np1
(root; the source address is a service address of the host, not the
interface address). The option is accepted and readable back:
setsockopt(SO_BINDTODEVICE, "ens31f1np1") = 0
getsockopt(SO_BINDTODEVICE) -> "ens31f1np1"
but the frames leave the sibling interface. tcpdump on both NICs while
3 packets are sent:
ens31f1np1 (the bound device): 0 packets captured
ens30f1np1: 3 packets captured
IP6 2001:db8:a::1.41022 > 2606:4700:4700::1111.53: ...
Impact for us: anything that pins traffic to one uplink of a dual-homed
BGP host (per-link probes, validation of switch-side policy routing)
silently takes another link. We lost a day to it before suspecting the
kernel.
>From reading 6.12 route.c: with nexthop objects, fib6_table_lookup()
returns the first nexthop of the group unless the lookup is strict, so
the have_oif_match test that this patch adds to ip6_pol_route() only
becomes true for nexthop groups once 484bb9d164df ("ipv6: Select best
matching nexthop object in fib6_table_lookup()") makes the table lookup
prefer the oif-matching nexthop. Its commit message describes it as
preparation for this patch. For nexthop-object users this patch is
therefore incomplete on its own; please consider queueing both:
484bb9d164df ipv6: Select best matching nexthop object in fib6_table_lookup()
d25e7e9d8a6c ipv6: Honor oif when choosing nexthop for locally generated traffic
https://patch.msgid.link/20260611154605.992528-2-idosch@xxxxxxxxxx
https://patch.msgid.link/20260611154605.992528-3-idosch@xxxxxxxxxx
Happy to test a 6.12.y tree with one or both applied on these hosts and
report back.
Thanks,
Flo