forked from Minki/linux
xdp: split code for map vs non-map redirect
The compiler does an efficient job of inlining static C functions. Perf top clearly shows that almost everything gets inlined into the function call xdp_do_redirect. The function xdp_do_redirect end-up containing and interleaving the map and non-map redirect code. This is sub-optimal, as it would be strange for an XDP program to use both types of redirect in the same program. The two use-cases are separate, and interleaving the code just cause more instruction-cache pressure. I would like to stress (again) that the non-map variant bpf_redirect is very slow compared to the bpf_redirect_map variant, approx half the speed. Measured with driver i40e the difference is: - map redirect: 13,250,350 pps - non-map redirect: 7,491,425 pps For this reason, the function name of the non-map variant of redirect have been called xdp_do_redirect_slow. This hopefully gives a hint when using perf, that this is not the optimal XDP redirect operating mode. Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
2a68d85fe1
commit
47b123ed9e
@ -3175,6 +3175,32 @@ static int __bpf_tx_xdp(struct net_device *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static noinline int
|
||||||
|
xdp_do_redirect_slow(struct net_device *dev, struct xdp_buff *xdp,
|
||||||
|
struct bpf_prog *xdp_prog, struct bpf_redirect_info *ri)
|
||||||
|
{
|
||||||
|
struct net_device *fwd;
|
||||||
|
u32 index = ri->ifindex;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
fwd = dev_get_by_index_rcu(dev_net(dev), index);
|
||||||
|
ri->ifindex = 0;
|
||||||
|
if (unlikely(!fwd)) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = __bpf_tx_xdp(fwd, NULL, xdp, 0);
|
||||||
|
if (unlikely(err))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
_trace_xdp_redirect(dev, xdp_prog, index);
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
_trace_xdp_redirect_err(dev, xdp_prog, index, err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd,
|
static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd,
|
||||||
struct bpf_map *map,
|
struct bpf_map *map,
|
||||||
struct xdp_buff *xdp,
|
struct xdp_buff *xdp,
|
||||||
@ -3269,9 +3295,9 @@ void bpf_clear_redirect_map(struct bpf_map *map)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
|
static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
|
||||||
struct bpf_prog *xdp_prog, struct bpf_map *map)
|
struct bpf_prog *xdp_prog, struct bpf_map *map,
|
||||||
|
struct bpf_redirect_info *ri)
|
||||||
{
|
{
|
||||||
struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
|
|
||||||
u32 index = ri->ifindex;
|
u32 index = ri->ifindex;
|
||||||
void *fwd = NULL;
|
void *fwd = NULL;
|
||||||
int err;
|
int err;
|
||||||
@ -3304,29 +3330,11 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
|
|||||||
{
|
{
|
||||||
struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
|
struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
|
||||||
struct bpf_map *map = READ_ONCE(ri->map);
|
struct bpf_map *map = READ_ONCE(ri->map);
|
||||||
struct net_device *fwd;
|
|
||||||
u32 index = ri->ifindex;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (likely(map))
|
if (likely(map))
|
||||||
return xdp_do_redirect_map(dev, xdp, xdp_prog, map);
|
return xdp_do_redirect_map(dev, xdp, xdp_prog, map, ri);
|
||||||
|
|
||||||
fwd = dev_get_by_index_rcu(dev_net(dev), index);
|
return xdp_do_redirect_slow(dev, xdp, xdp_prog, ri);
|
||||||
ri->ifindex = 0;
|
|
||||||
if (unlikely(!fwd)) {
|
|
||||||
err = -EINVAL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = __bpf_tx_xdp(fwd, NULL, xdp, 0);
|
|
||||||
if (unlikely(err))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
_trace_xdp_redirect(dev, xdp_prog, index);
|
|
||||||
return 0;
|
|
||||||
err:
|
|
||||||
_trace_xdp_redirect_err(dev, xdp_prog, index, err);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(xdp_do_redirect);
|
EXPORT_SYMBOL_GPL(xdp_do_redirect);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user