mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 07:51:16 -04:00
Merge branch 'bpf-allow-xdp_redirect-for-xdp-dev-bound-programs'
Lorenzo Bianconi says: ==================== bpf: Allow XDP_REDIRECT for XDP dev-bound programs In the current implementation if the program is dev-bound to a specific device, it will not be possible to perform XDP_REDIRECT into a DEVMAP or CPUMAP even if the program is running in the driver NAPI context. Fix the issue introducing __bpf_prog_map_compatible utility routine in order to avoid bpf_prog_is_dev_bound() during the XDP program load. Continue forbidding to attach a dev-bound program to XDP maps. ==================== Link: https://patch.msgid.link/20250428-xdp-prog-bound-fix-v3-0-c9e9ba3300c7@kernel.org Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
This commit is contained in:
@@ -2358,8 +2358,8 @@ static unsigned int __bpf_prog_ret0_warn(const void *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bpf_prog_map_compatible(struct bpf_map *map,
|
||||
const struct bpf_prog *fp)
|
||||
static bool __bpf_prog_map_compatible(struct bpf_map *map,
|
||||
const struct bpf_prog *fp)
|
||||
{
|
||||
enum bpf_prog_type prog_type = resolve_prog_type(fp);
|
||||
bool ret;
|
||||
@@ -2368,14 +2368,6 @@ bool bpf_prog_map_compatible(struct bpf_map *map,
|
||||
if (fp->kprobe_override)
|
||||
return false;
|
||||
|
||||
/* XDP programs inserted into maps are not guaranteed to run on
|
||||
* a particular netdev (and can run outside driver context entirely
|
||||
* in the case of devmap and cpumap). Until device checks
|
||||
* are implemented, prohibit adding dev-bound programs to program maps.
|
||||
*/
|
||||
if (bpf_prog_is_dev_bound(aux))
|
||||
return false;
|
||||
|
||||
spin_lock(&map->owner.lock);
|
||||
if (!map->owner.type) {
|
||||
/* There's no owner yet where we could check for
|
||||
@@ -2409,6 +2401,19 @@ bool bpf_prog_map_compatible(struct bpf_map *map,
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool bpf_prog_map_compatible(struct bpf_map *map, const struct bpf_prog *fp)
|
||||
{
|
||||
/* XDP programs inserted into maps are not guaranteed to run on
|
||||
* a particular netdev (and can run outside driver context entirely
|
||||
* in the case of devmap and cpumap). Until device checks
|
||||
* are implemented, prohibit adding dev-bound programs to program maps.
|
||||
*/
|
||||
if (bpf_prog_is_dev_bound(fp->aux))
|
||||
return false;
|
||||
|
||||
return __bpf_prog_map_compatible(map, fp);
|
||||
}
|
||||
|
||||
static int bpf_check_tail_call(const struct bpf_prog *fp)
|
||||
{
|
||||
struct bpf_prog_aux *aux = fp->aux;
|
||||
@@ -2421,7 +2426,7 @@ static int bpf_check_tail_call(const struct bpf_prog *fp)
|
||||
if (!map_type_contains_progs(map))
|
||||
continue;
|
||||
|
||||
if (!bpf_prog_map_compatible(map, fp)) {
|
||||
if (!__bpf_prog_map_compatible(map, fp)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -351,9 +351,10 @@ void test_xdp_metadata(void)
|
||||
struct xdp_metadata2 *bpf_obj2 = NULL;
|
||||
struct xdp_metadata *bpf_obj = NULL;
|
||||
struct bpf_program *new_prog, *prog;
|
||||
struct bpf_devmap_val devmap_e = {};
|
||||
struct bpf_map *prog_arr, *devmap;
|
||||
struct nstoken *tok = NULL;
|
||||
__u32 queue_id = QUEUE_ID;
|
||||
struct bpf_map *prog_arr;
|
||||
struct xsk tx_xsk = {};
|
||||
struct xsk rx_xsk = {};
|
||||
__u32 val, key = 0;
|
||||
@@ -409,6 +410,13 @@ void test_xdp_metadata(void)
|
||||
bpf_program__set_ifindex(prog, rx_ifindex);
|
||||
bpf_program__set_flags(prog, BPF_F_XDP_DEV_BOUND_ONLY);
|
||||
|
||||
/* Make sure we can load a dev-bound program that performs
|
||||
* XDP_REDIRECT into a devmap.
|
||||
*/
|
||||
new_prog = bpf_object__find_program_by_name(bpf_obj->obj, "redirect");
|
||||
bpf_program__set_ifindex(new_prog, rx_ifindex);
|
||||
bpf_program__set_flags(new_prog, BPF_F_XDP_DEV_BOUND_ONLY);
|
||||
|
||||
if (!ASSERT_OK(xdp_metadata__load(bpf_obj), "load skeleton"))
|
||||
goto out;
|
||||
|
||||
@@ -423,6 +431,18 @@ void test_xdp_metadata(void)
|
||||
"update prog_arr"))
|
||||
goto out;
|
||||
|
||||
/* Make sure we can't add dev-bound programs to devmaps. */
|
||||
devmap = bpf_object__find_map_by_name(bpf_obj->obj, "dev_map");
|
||||
if (!ASSERT_OK_PTR(devmap, "no dev_map found"))
|
||||
goto out;
|
||||
|
||||
devmap_e.bpf_prog.fd = val;
|
||||
if (!ASSERT_ERR(bpf_map__update_elem(devmap, &key, sizeof(key),
|
||||
&devmap_e, sizeof(devmap_e),
|
||||
BPF_ANY),
|
||||
"update dev_map"))
|
||||
goto out;
|
||||
|
||||
/* Attach BPF program to RX interface. */
|
||||
|
||||
ret = bpf_xdp_attach(rx_ifindex,
|
||||
|
||||
@@ -19,6 +19,13 @@ struct {
|
||||
__type(value, __u32);
|
||||
} prog_arr SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_DEVMAP);
|
||||
__uint(key_size, sizeof(__u32));
|
||||
__uint(value_size, sizeof(struct bpf_devmap_val));
|
||||
__uint(max_entries, 1);
|
||||
} dev_map SEC(".maps");
|
||||
|
||||
extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx,
|
||||
__u64 *timestamp) __ksym;
|
||||
extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,
|
||||
@@ -95,4 +102,10 @@ int rx(struct xdp_md *ctx)
|
||||
return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
|
||||
}
|
||||
|
||||
SEC("xdp")
|
||||
int redirect(struct xdp_md *ctx)
|
||||
{
|
||||
return bpf_redirect_map(&dev_map, ctx->rx_queue_index, XDP_PASS);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
Reference in New Issue
Block a user