Inter-revision diff: patch 14

Comparing v11 (message) to v9 (message)

--- v11
+++ v9
@@ -1,118 +1,215 @@
-Introduce the capability to allocate a xdp multi-buff in
-bpf_prog_test_run_xdp routine. This is a preliminary patch to introduce
-the selftests for new xdp multi-buff ebpf helpers
-
+From: Eelco Chaudron <echaudro@redhat.com>
+
+This change adds test cases for the multi-buffer scenarios when shrinking
+and growing.
+
+Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
 Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
 ---
- net/bpf/test_run.c | 54 ++++++++++++++++++++++++++++++++++++----------
- 1 file changed, 43 insertions(+), 11 deletions(-)
-
-diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
-index 362e020631b3..1833b863c185 100644
---- a/net/bpf/test_run.c
-+++ b/net/bpf/test_run.c
-@@ -749,16 +749,16 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
- 			  union bpf_attr __user *uattr)
+ .../bpf/prog_tests/xdp_adjust_tail.c          | 105 ++++++++++++++++++
+ .../bpf/progs/test_xdp_adjust_tail_grow.c     |  10 +-
+ .../bpf/progs/test_xdp_adjust_tail_shrink.c   |  32 +++++-
+ 3 files changed, 140 insertions(+), 7 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
+index d5c98f2cb12f..b936beaba797 100644
+--- a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
++++ b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
+@@ -130,6 +130,107 @@ void test_xdp_adjust_tail_grow2(void)
+ 	bpf_object__close(obj);
+ }
+ 
++void test_xdp_adjust_mb_tail_shrink(void)
++{
++	const char *file = "./test_xdp_adjust_tail_shrink.o";
++	__u32 duration, retval, size, exp_size;
++	struct bpf_object *obj;
++	static char buf[9000];
++	int err, prog_fd;
++
++	/* For the individual test cases, the first byte in the packet
++	 * indicates which test will be run.
++	 */
++
++	err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
++	if (CHECK_FAIL(err))
++		return;
++
++	/* Test case removing 10 bytes from last frag, NOT freeing it */
++	buf[0] = 0;
++	exp_size = sizeof(buf) - 10;
++	err = bpf_prog_test_run(prog_fd, 1, buf, sizeof(buf),
++				buf, &size, &retval, &duration);
++
++	CHECK(err || retval != XDP_TX || size != exp_size,
++	      "9k-10b", "err %d errno %d retval %d[%d] size %d[%u]\n",
++	      err, errno, retval, XDP_TX, size, exp_size);
++
++	/* Test case removing one of two pages, assuming 4K pages */
++	buf[0] = 1;
++	exp_size = sizeof(buf) - 4100;
++	err = bpf_prog_test_run(prog_fd, 1, buf, sizeof(buf),
++				buf, &size, &retval, &duration);
++
++	CHECK(err || retval != XDP_TX || size != exp_size,
++	      "9k-1p", "err %d errno %d retval %d[%d] size %d[%u]\n",
++	      err, errno, retval, XDP_TX, size, exp_size);
++
++	/* Test case removing two pages resulting in a non mb xdp_buff */
++	buf[0] = 2;
++	exp_size = sizeof(buf) - 8200;
++	err = bpf_prog_test_run(prog_fd, 1, buf, sizeof(buf),
++				buf, &size, &retval, &duration);
++
++	CHECK(err || retval != XDP_TX || size != exp_size,
++	      "9k-2p", "err %d errno %d retval %d[%d] size %d[%u]\n",
++	      err, errno, retval, XDP_TX, size, exp_size);
++
++	bpf_object__close(obj);
++}
++
++void test_xdp_adjust_mb_tail_grow(void)
++{
++	const char *file = "./test_xdp_adjust_tail_grow.o";
++	__u32 duration, retval, size, exp_size;
++	static char buf[16384];
++	struct bpf_object *obj;
++	int err, i, prog_fd;
++
++	err = bpf_prog_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
++	if (CHECK_FAIL(err))
++		return;
++
++	/* Test case add 10 bytes to last frag */
++	memset(buf, 1, sizeof(buf));
++	size = 9000;
++	exp_size = size + 10;
++	err = bpf_prog_test_run(prog_fd, 1, buf, size,
++				buf, &size, &retval, &duration);
++
++	CHECK(err || retval != XDP_TX || size != exp_size,
++	      "9k+10b", "err %d retval %d[%d] size %d[%u]\n",
++	      err, retval, XDP_TX, size, exp_size);
++
++	for (i = 0; i < 9000; i++)
++		CHECK(buf[i] != 1, "9k+10b-old",
++		      "Old data not all ok, offset %i is failing [%u]!\n",
++		      i, buf[i]);
++
++	for (i = 9000; i < 9010; i++)
++		CHECK(buf[i] != 0, "9k+10b-new",
++		      "New data not all ok, offset %i is failing [%u]!\n",
++		      i, buf[i]);
++
++	for (i = 9010; i < sizeof(buf); i++)
++		CHECK(buf[i] != 1, "9k+10b-untouched",
++		      "Unused data not all ok, offset %i is failing [%u]!\n",
++		      i, buf[i]);
++
++	/* Test a too large grow */
++	memset(buf, 1, sizeof(buf));
++	size = 9001;
++	exp_size = size;
++	err = bpf_prog_test_run(prog_fd, 1, buf, size,
++				buf, &size, &retval, &duration);
++
++	CHECK(err || retval != XDP_DROP || size != exp_size,
++	      "9k+10b", "err %d retval %d[%d] size %d[%u]\n",
++	      err, retval, XDP_TX, size, exp_size);
++
++	bpf_object__close(obj);
++}
++
+ void test_xdp_adjust_tail(void)
  {
- 	u32 tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
--	u32 headroom = XDP_PACKET_HEADROOM;
- 	u32 size = kattr->test.data_size_in;
-+	u32 headroom = XDP_PACKET_HEADROOM;
-+	u32 retval, duration, max_data_sz;
- 	u32 repeat = kattr->test.repeat;
- 	struct netdev_rx_queue *rxqueue;
-+	struct skb_shared_info *sinfo;
- 	struct xdp_buff xdp = {};
--	u32 retval, duration;
-+	int i, ret = -EINVAL;
- 	struct xdp_md *ctx;
--	u32 max_data_sz;
- 	void *data;
--	int ret = -EINVAL;
- 
- 	if (prog->expected_attach_type == BPF_XDP_DEVMAP ||
- 	    prog->expected_attach_type == BPF_XDP_CPUMAP)
-@@ -778,11 +778,10 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
- 		headroom -= ctx->data;
+ 	if (test__start_subtest("xdp_adjust_tail_shrink"))
+@@ -138,4 +239,8 @@ void test_xdp_adjust_tail(void)
+ 		test_xdp_adjust_tail_grow();
+ 	if (test__start_subtest("xdp_adjust_tail_grow2"))
+ 		test_xdp_adjust_tail_grow2();
++	if (test__start_subtest("xdp_adjust_mb_tail_shrink"))
++		test_xdp_adjust_mb_tail_shrink();
++	if (test__start_subtest("xdp_adjust_mb_tail_grow"))
++		test_xdp_adjust_mb_tail_grow();
+ }
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
+index 3d66599eee2e..3d43defb0e00 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
+@@ -7,11 +7,10 @@ int _xdp_adjust_tail_grow(struct xdp_md *xdp)
+ {
+ 	void *data_end = (void *)(long)xdp->data_end;
+ 	void *data = (void *)(long)xdp->data;
+-	unsigned int data_len;
++	int data_len = bpf_xdp_get_buff_len(xdp);
+ 	int offset = 0;
+ 
+ 	/* Data length determine test case */
+-	data_len = data_end - data;
+ 
+ 	if (data_len == 54) { /* sizeof(pkt_v4) */
+ 		offset = 4096; /* test too large offset */
+@@ -20,7 +19,12 @@ int _xdp_adjust_tail_grow(struct xdp_md *xdp)
+ 	} else if (data_len == 64) {
+ 		offset = 128;
+ 	} else if (data_len == 128) {
+-		offset = 4096 - 256 - 320 - data_len; /* Max tail grow 3520 */
++		/* Max tail grow 3520 */
++		offset = 4096 - 256 - 320 - data_len;
++	} else if (data_len == 9000) {
++		offset = 10;
++	} else if (data_len == 9001) {
++		offset = 4096;
+ 	} else {
+ 		return XDP_ABORTED; /* No matching test */
  	}
- 
--	/* XDP have extra tailroom as (most) drivers use full page */
- 	max_data_sz = 4096 - headroom - tailroom;
-+	size = min_t(u32, size, max_data_sz);
- 
--	data = bpf_test_init(kattr, kattr->test.data_size_in,
--			     max_data_sz, headroom, tailroom);
-+	data = bpf_test_init(kattr, size, max_data_sz, headroom, tailroom);
- 	if (IS_ERR(data)) {
- 		ret = PTR_ERR(data);
- 		goto free_ctx;
-@@ -792,11 +791,45 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
- 	xdp_init_buff(&xdp, headroom + max_data_sz + tailroom,
- 		      &rxqueue->xdp_rxq);
- 	xdp_prepare_buff(&xdp, data, headroom, size, true);
-+	sinfo = xdp_get_shared_info_from_buff(&xdp);
- 
- 	ret = xdp_convert_md_to_buff(ctx, &xdp);
- 	if (ret)
- 		goto free_data;
- 
-+	if (unlikely(kattr->test.data_size_in > size)) {
-+		void __user *data_in = u64_to_user_ptr(kattr->test.data_in);
-+
-+		while (size < kattr->test.data_size_in) {
-+			struct page *page;
-+			skb_frag_t *frag;
-+			int data_len;
-+
-+			page = alloc_page(GFP_KERNEL);
-+			if (!page) {
-+				ret = -ENOMEM;
-+				goto out;
-+			}
-+
-+			frag = &sinfo->frags[sinfo->nr_frags++];
-+			__skb_frag_set_page(frag, page);
-+
-+			data_len = min_t(int, kattr->test.data_size_in - size,
-+					 PAGE_SIZE);
-+			skb_frag_size_set(frag, data_len);
-+
-+			if (copy_from_user(page_address(page), data_in + size,
-+					   data_len)) {
-+				ret = -EFAULT;
-+				goto out;
-+			}
-+			sinfo->xdp_frags_tsize += PAGE_SIZE;
-+			sinfo->xdp_frags_size += data_len;
-+			size += data_len;
+diff --git a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_shrink.c b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_shrink.c
+index 22065a9cfb25..64177597ac29 100644
+--- a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_shrink.c
++++ b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_shrink.c
+@@ -14,14 +14,38 @@ int _version SEC("version") = 1;
+ SEC("xdp_adjust_tail_shrink")
+ int _xdp_adjust_tail_shrink(struct xdp_md *xdp)
+ {
+-	void *data_end = (void *)(long)xdp->data_end;
+-	void *data = (void *)(long)xdp->data;
++	__u8 *data_end = (void *)(long)xdp->data_end;
++	__u8 *data = (void *)(long)xdp->data;
+ 	int offset = 0;
+ 
+-	if (data_end - data == 54) /* sizeof(pkt_v4) */
++	switch (bpf_xdp_get_buff_len(xdp)) {
++	case 54:
++		/* sizeof(pkt_v4) */
+ 		offset = 256; /* shrink too much */
+-	else
++		break;
++	case 9000:
++		/* Multi-buffer test cases */
++		if (data + 1 > data_end)
++			return XDP_DROP;
++
++		switch (data[0]) {
++		case 0:
++			offset = 10;
++			break;
++		case 1:
++			offset = 4100;
++			break;
++		case 2:
++			offset = 8200;
++			break;
++		default:
++			return XDP_DROP;
 +		}
-+		xdp_buff_set_mb(&xdp);
++		break;
++	default:
+ 		offset = 20;
++		break;
 +	}
-+
- 	bpf_prog_change_xdp(NULL, prog);
- 	ret = bpf_test_run(prog, &xdp, repeat, &retval, &duration, true);
- 	/* We convert the xdp_buff back to an xdp_md before checking the return
-@@ -807,10 +840,7 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
- 	if (ret)
- 		goto out;
- 
--	if (xdp.data_meta != data + headroom ||
--	    xdp.data_end != xdp.data_meta + size)
--		size = xdp.data_end - xdp.data_meta;
--
-+	size = xdp.data_end - xdp.data_meta + sinfo->xdp_frags_size;
- 	ret = bpf_test_finish(kattr, uattr, xdp.data_meta, size, retval,
- 			      duration);
- 	if (!ret)
-@@ -820,6 +850,8 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
- out:
- 	bpf_prog_change_xdp(prog, NULL);
- free_data:
-+	for (i = 0; i < sinfo->nr_frags; i++)
-+		__free_page(skb_frag_page(&sinfo->frags[i]));
- 	kfree(data);
- free_ctx:
- 	kfree(ctx);
+ 	if (bpf_xdp_adjust_tail(xdp, 0 - offset))
+ 		return XDP_DROP;
+ 	return XDP_TX;
 -- 
 2.31.1
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help