Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+50 -12
+16 -11
kernel/bpf/core.c
··· 2358 2358 return 0; 2359 2359 } 2360 2360 2361 - bool bpf_prog_map_compatible(struct bpf_map *map, 2362 - const struct bpf_prog *fp) 2361 + static bool __bpf_prog_map_compatible(struct bpf_map *map, 2362 + const struct bpf_prog *fp) 2363 2363 { 2364 2364 enum bpf_prog_type prog_type = resolve_prog_type(fp); 2365 2365 bool ret; 2366 2366 struct bpf_prog_aux *aux = fp->aux; 2367 2367 2368 2368 if (fp->kprobe_override) 2369 - return false; 2370 - 2371 - /* XDP programs inserted into maps are not guaranteed to run on 2372 - * a particular netdev (and can run outside driver context entirely 2373 - * in the case of devmap and cpumap). Until device checks 2374 - * are implemented, prohibit adding dev-bound programs to program maps. 2375 - */ 2376 - if (bpf_prog_is_dev_bound(aux)) 2377 2369 return false; 2378 2370 2379 2371 spin_lock(&map->owner.lock); ··· 2401 2409 return ret; 2402 2410 } 2403 2411 2412 + bool bpf_prog_map_compatible(struct bpf_map *map, const struct bpf_prog *fp) 2413 + { 2414 + /* XDP programs inserted into maps are not guaranteed to run on 2415 + * a particular netdev (and can run outside driver context entirely 2416 + * in the case of devmap and cpumap). Until device checks 2417 + * are implemented, prohibit adding dev-bound programs to program maps. 2418 + */ 2419 + if (bpf_prog_is_dev_bound(fp->aux)) 2420 + return false; 2421 + 2422 + return __bpf_prog_map_compatible(map, fp); 2423 + } 2424 + 2404 2425 static int bpf_check_tail_call(const struct bpf_prog *fp) 2405 2426 { 2406 2427 struct bpf_prog_aux *aux = fp->aux; ··· 2426 2421 if (!map_type_contains_progs(map)) 2427 2422 continue; 2428 2423 2429 - if (!bpf_prog_map_compatible(map, fp)) { 2424 + if (!__bpf_prog_map_compatible(map, fp)) { 2430 2425 ret = -EINVAL; 2431 2426 goto out; 2432 2427 }
+21 -1
tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
··· 351 351 struct xdp_metadata2 *bpf_obj2 = NULL; 352 352 struct xdp_metadata *bpf_obj = NULL; 353 353 struct bpf_program *new_prog, *prog; 354 + struct bpf_devmap_val devmap_e = {}; 355 + struct bpf_map *prog_arr, *devmap; 354 356 struct nstoken *tok = NULL; 355 357 __u32 queue_id = QUEUE_ID; 356 - struct bpf_map *prog_arr; 357 358 struct xsk tx_xsk = {}; 358 359 struct xsk rx_xsk = {}; 359 360 __u32 val, key = 0; ··· 410 409 bpf_program__set_ifindex(prog, rx_ifindex); 411 410 bpf_program__set_flags(prog, BPF_F_XDP_DEV_BOUND_ONLY); 412 411 412 + /* Make sure we can load a dev-bound program that performs 413 + * XDP_REDIRECT into a devmap. 414 + */ 415 + new_prog = bpf_object__find_program_by_name(bpf_obj->obj, "redirect"); 416 + bpf_program__set_ifindex(new_prog, rx_ifindex); 417 + bpf_program__set_flags(new_prog, BPF_F_XDP_DEV_BOUND_ONLY); 418 + 413 419 if (!ASSERT_OK(xdp_metadata__load(bpf_obj), "load skeleton")) 414 420 goto out; 415 421 ··· 429 421 if (!ASSERT_ERR(bpf_map__update_elem(prog_arr, &key, sizeof(key), 430 422 &val, sizeof(val), BPF_ANY), 431 423 "update prog_arr")) 424 + goto out; 425 + 426 + /* Make sure we can't add dev-bound programs to devmaps. */ 427 + devmap = bpf_object__find_map_by_name(bpf_obj->obj, "dev_map"); 428 + if (!ASSERT_OK_PTR(devmap, "no dev_map found")) 429 + goto out; 430 + 431 + devmap_e.bpf_prog.fd = val; 432 + if (!ASSERT_ERR(bpf_map__update_elem(devmap, &key, sizeof(key), 433 + &devmap_e, sizeof(devmap_e), 434 + BPF_ANY), 435 + "update dev_map")) 432 436 goto out; 433 437 434 438 /* Attach BPF program to RX interface. */
+13
tools/testing/selftests/bpf/progs/xdp_metadata.c
··· 19 19 __type(value, __u32); 20 20 } prog_arr SEC(".maps"); 21 21 22 + struct { 23 + __uint(type, BPF_MAP_TYPE_DEVMAP); 24 + __uint(key_size, sizeof(__u32)); 25 + __uint(value_size, sizeof(struct bpf_devmap_val)); 26 + __uint(max_entries, 1); 27 + } dev_map SEC(".maps"); 28 + 22 29 extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, 23 30 __u64 *timestamp) __ksym; 24 31 extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash, ··· 100 93 &meta->rx_vlan_tci); 101 94 102 95 return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS); 96 + } 97 + 98 + SEC("xdp") 99 + int redirect(struct xdp_md *ctx) 100 + { 101 + return bpf_redirect_map(&dev_map, ctx->rx_queue_index, XDP_PASS); 103 102 } 104 103 105 104 char _license[] SEC("license") = "GPL";