The bpf_fib_lookup() helper performs a neighbour lookup for the destination
IP and returns BPF_FIB_LKUP_NO_NEIGH if this fails, with the expectation
that the BPF program will pass the packet up the stack in this case.
However, with the addition of bpf_redirect_neigh() that can be used instead
to perform the neighbour lookup.

However, for that we still need the target ifindex, and since
bpf_fib_lookup() already has that at the time it performs the neighbour
lookup, there is really no reason why it can't just return it in any case.
With this fix, a BPF program can do the following to perform a redirect
based on the routing table that will succeed even if there is no neighbour
entry:

        ret = bpf_fib_lookup(skb, &fib_params, sizeof(fib_params), 0);
        if (ret == BPF_FIB_LKUP_RET_SUCCESS) {
                __builtin_memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN);
                __builtin_memcpy(eth->h_source, fib_params.smac, ETH_ALEN);

                return bpf_redirect(fib_params.ifindex, 0);
        } else if (ret == BPF_FIB_LKUP_RET_NO_NEIGH) {
                return bpf_redirect_neigh(fib_params.ifindex, 0);
        }

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Toke Høiland-Jørgensen <t...@redhat.com>
---
 net/core/filter.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index 05df73780dd3..00fce34a2204 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -5192,7 +5192,6 @@ static int bpf_fib_set_fwd_params(struct bpf_fib_lookup 
*params,
        memcpy(params->smac, dev->dev_addr, ETH_ALEN);
        params->h_vlan_TCI = 0;
        params->h_vlan_proto = 0;
-       params->ifindex = dev->ifindex;
 
        return 0;
 }
@@ -5289,6 +5288,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct 
bpf_fib_lookup *params,
        dev = nhc->nhc_dev;
 
        params->rt_metric = res.fi->fib_priority;
+       params->ifindex = dev->ifindex;
 
        /* xdp and cls_bpf programs are run in RCU-bh so
         * rcu_read_lock_bh is not needed here
@@ -5414,6 +5414,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct 
bpf_fib_lookup *params,
 
        dev = res.nh->fib_nh_dev;
        params->rt_metric = res.f6i->fib6_metric;
+       params->ifindex = dev->ifindex;
 
        /* xdp and cls_bpf programs are run in RCU-bh so rcu_read_lock_bh is
         * not needed here.
-- 
2.28.0

Reply via email to