Skip to content

Commit 99b9b13

Browse files
ameryhungKernel Patches Daemon
authored andcommitted
bpf: Support specifying linear xdp packet data size for BPF_PROG_TEST_RUN
To test bpf_xdp_pull_data(), an xdp packet containing fragments as well as free linear data area after xdp->data_end needs to be created. However, bpf_prog_test_run_xdp() always fills the linear area with data_in before creating fragments, leaving no space to pull data. This patch will allow users to specify the linear data size through ctx->data_end. Currently, ctx_in->data_end must match data_size_in and will not be the final ctx->data_end seen by xdp programs. This is because ctx->data_end is populated according to the xdp_buff passed to test_run. The linear data area available in an xdp_buff, max_data_sz, is alawys filled up before copying data_in into fragments. This patch will allow users to specify the size of data that goes into the linear area. When ctx_in->data_end is different from data_size_in, only ctx_in->data_end bytes of data will be put into the linear area when creating the xdp_buff. While ctx_in->data_end will be allowed to be different from data_size_in, it cannot be larger than the data_size_in as there will be no data to copy from user space. If it is larger than the maximum linear data area size, the layout suggested by the user will not be honored. Data beyond max_data_sz bytes will still be copied into fragments. Finally, since it is possible for a NIC to produce a xdp_buff with empty linear data area, allow it when calling bpf_test_init() from bpf_prog_test_run_xdp() so that we can test XDP kfuncs with such xdp_buff. Signed-off-by: Amery Hung <[email protected]>
1 parent d10adc4 commit 99b9b13

File tree

2 files changed

+17
-13
lines changed

2 files changed

+17
-13
lines changed

net/bpf/test_run.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -660,12 +660,15 @@ BTF_ID_FLAGS(func, bpf_kfunc_call_memb_release, KF_RELEASE)
660660
BTF_KFUNCS_END(test_sk_check_kfunc_ids)
661661

662662
static void *bpf_test_init(const union bpf_attr *kattr, u32 user_size,
663-
u32 size, u32 headroom, u32 tailroom)
663+
u32 size, u32 headroom, u32 tailroom, bool is_xdp)
664664
{
665665
void __user *data_in = u64_to_user_ptr(kattr->test.data_in);
666666
void *data;
667667

668-
if (user_size < ETH_HLEN || user_size > PAGE_SIZE - headroom - tailroom)
668+
if (!is_xdp && user_size < ETH_HLEN)
669+
return ERR_PTR(-EINVAL);
670+
671+
if (user_size > PAGE_SIZE - headroom - tailroom)
669672
return ERR_PTR(-EINVAL);
670673

671674
size = SKB_DATA_ALIGN(size);
@@ -1003,7 +1006,8 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
10031006

10041007
data = bpf_test_init(kattr, kattr->test.data_size_in,
10051008
size, NET_SKB_PAD + NET_IP_ALIGN,
1006-
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
1009+
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
1010+
false);
10071011
if (IS_ERR(data))
10081012
return PTR_ERR(data);
10091013

@@ -1207,8 +1211,8 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
12071211
{
12081212
bool do_live = (kattr->test.flags & BPF_F_TEST_XDP_LIVE_FRAMES);
12091213
u32 tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
1214+
u32 retval = 0, duration, max_data_sz, data_sz;
12101215
u32 batch_size = kattr->test.batch_size;
1211-
u32 retval = 0, duration, max_data_sz;
12121216
u32 size = kattr->test.data_size_in;
12131217
u32 headroom = XDP_PACKET_HEADROOM;
12141218
u32 repeat = kattr->test.repeat;
@@ -1246,7 +1250,7 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
12461250

12471251
if (ctx) {
12481252
/* There can't be user provided data before the meta data */
1249-
if (ctx->data_meta || ctx->data_end != size ||
1253+
if (ctx->data_meta || ctx->data_end > size ||
12501254
ctx->data > ctx->data_end ||
12511255
unlikely(xdp_metalen_invalid(ctx->data)) ||
12521256
(do_live && (kattr->test.data_out || kattr->test.ctx_out)))
@@ -1256,14 +1260,15 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
12561260
}
12571261

12581262
max_data_sz = PAGE_SIZE - headroom - tailroom;
1259-
if (size > max_data_sz) {
1263+
data_sz = (ctx && ctx->data_end < max_data_sz) ? ctx->data_end : max_data_sz;
1264+
if (size > data_sz) {
12601265
/* disallow live data mode for jumbo frames */
12611266
if (do_live)
12621267
goto free_ctx;
1263-
size = max_data_sz;
1268+
size = data_sz;
12641269
}
12651270

1266-
data = bpf_test_init(kattr, size, max_data_sz, headroom, tailroom);
1271+
data = bpf_test_init(kattr, size, max_data_sz, headroom, tailroom, true);
12671272
if (IS_ERR(data)) {
12681273
ret = PTR_ERR(data);
12691274
goto free_ctx;
@@ -1386,7 +1391,7 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
13861391
if (size < ETH_HLEN)
13871392
return -EINVAL;
13881393

1389-
data = bpf_test_init(kattr, kattr->test.data_size_in, size, 0, 0);
1394+
data = bpf_test_init(kattr, kattr->test.data_size_in, size, 0, 0, false);
13901395
if (IS_ERR(data))
13911396
return PTR_ERR(data);
13921397

@@ -1659,7 +1664,8 @@ int bpf_prog_test_run_nf(struct bpf_prog *prog,
16591664

16601665
data = bpf_test_init(kattr, kattr->test.data_size_in, size,
16611666
NET_SKB_PAD + NET_IP_ALIGN,
1662-
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
1667+
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
1668+
false);
16631669
if (IS_ERR(data))
16641670
return PTR_ERR(data);
16651671

tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,7 @@ void test_xdp_context_test_run(void)
9797
/* Meta data must be 255 bytes or smaller */
9898
test_xdp_context_error(prog_fd, opts, 0, 256, sizeof(data), 0, 0, 0);
9999

100-
/* Total size of data must match data_end - data_meta */
101-
test_xdp_context_error(prog_fd, opts, 0, sizeof(__u32),
102-
sizeof(data) - 1, 0, 0, 0);
100+
/* Total size of data must be data_end - data_meta or larger */
103101
test_xdp_context_error(prog_fd, opts, 0, sizeof(__u32),
104102
sizeof(data) + 1, 0, 0, 0);
105103

0 commit comments

Comments
 (0)