This series adds VLAN awareness to bpf_fib_lookup() in both directions. BPF_FIB_LOOKUP_VLAN resolves a VLAN egress to its underlying real device plus the VLAN tag (XDP programs need this because VLAN devices have no XDP xmit), and BPF_FIB_LOOKUP_VLAN_INPUT runs the lookup as if a tagged frame had arrived on the matching VLAN subinterface, for iif policy routing and VRF table selection.
The independent l3mdev/VRF flow-init fix, patch 1 in v1 and v2, was split out and merged to bpf separately. v4 changes what bpf_fib_lookup() returns in one case. v3 left a VLAN egress that cannot be reduced to a physical device plus one tag (a QinQ egress, or a parent in another namespace) as best-effort SUCCESS with the VLAN device's ifindex. In his v3 review Toke asked for a distinct error code there instead, so an XDP program cannot mistake an unresolved VLAN egress for a physical one, and suggested the name BPF_FIB_LKUP_RET_VLAN_FAILURE; v4 implements that. The code is appended after BPF_FIB_LKUP_RET_NO_SRC_ADDR (nothing renumbered, tools/ mirror updated) and is returned only when BPF_FIB_LOOKUP_VLAN is set, so no existing caller can observe it. On that failure params->ifindex is left at the input, like the input-side failures; a tc or XDP program that wants the VLAN device's own ifindex re-issues the lookup without the flag, the recovery path he described. The reason for a distinct code rather than best-effort SUCCESS: SUCCESS on an unreducible egress silently blackholed XDP. A redirect to the VLAN device drops at xdp_do_flush() with no in-band signal to the program; VLAN_FAILURE makes the unreducible case explicit, and a live-frames selftest exercises both the redirected and the passed paths. Only the immediate parent is resolved, so QinQ and foreign-netns are the unreducible cases; bond, team, TBID and VRF egress resolve, as the selftest table pins. Changes v3 -> v4: - Patch 1: return BPF_FIB_LKUP_RET_VLAN_FAILURE for an unreducible VLAN egress, leaving params->ifindex at the input. - Patch 3: the QinQ-egress and cross-namespace-egress arms expect VLAN_FAILURE; an escape-hatch arm re-issues without the flag for the inner VLAN device's ifindex; and test_fib_lookup_vlan_redirect drives live frames (BPF_F_TEST_XDP_LIVE_FRAMES) through the native redirect path, asserting a reducible egress is delivered and a QinQ egress is passed to the stack. The selftest's VLAN_FAILURE arms are IPv4 only, since bpf_ipv6_fib_lookup() restores params->ifindex with the same code as the IPv4 path that the arms exercise. The three other v3 questions Toke marked fine as-is, and v4 keeps them: an unmatched, down, or cross-namespace tag on input returns NOT_FWDED; OUTPUT | VLAN_INPUT is rejected with -EINVAL; the BPF_FIB_LOOKUP_VLAN_INPUT name is kept. Taking the tag as lookup input follows the approach David Ahern suggested in the 2021 fwmark discussion: https://lore.kernel.org/bpf/[email protected]/ v3: https://lore.kernel.org/all/[email protected]/ v2: https://lore.kernel.org/all/[email protected]/ v1: https://lore.kernel.org/all/[email protected]/ Avinash Duduskar (3): bpf: Add BPF_FIB_LOOKUP_VLAN flag to bpf_fib_lookup() helper bpf: Add BPF_FIB_LOOKUP_VLAN_INPUT flag to bpf_fib_lookup() helper selftests/bpf: Add bpf_fib_lookup() VLAN flag tests include/uapi/linux/bpf.h | 47 +- net/core/filter.c | 133 +++- tools/include/uapi/linux/bpf.h | 47 +- .../selftests/bpf/prog_tests/fib_lookup.c | 696 +++++++++++++++++- .../testing/selftests/bpf/progs/fib_lookup.c | 36 + 5 files changed, 930 insertions(+), 29 deletions(-) base-commit: a975094bf98ca97be9146f9d3b5681a6f9cf5ce3 -- 2.54.0

