Subject: [PATCH bpf-next v2 4/4] bpf: sockmap test cork and pop combined

From: John Fastabend <[email-masked]>
Date: Wed, 24 Jan 2024 10:54:03 -0800

Its possible to cork data for some N bytes and then pop
a some bytes off that scatterlist. Test combining cork
and pop here.

Signed-off-by: John Fastabend <[email-masked]>
---
 .../bpf/prog_tests/sockmap_msg_helpers.c      | 19 ++++++++++++++-----
 .../bpf/progs/test_sockmap_msg_helpers.c      | 14 +++++++++++++-
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_msg_helpers.c b/tools/testing/selftests/bpf/prog_tests/sockmap_msg_helpers.c
index 8ced54fe1a0b..cfb965f6832f 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_msg_helpers.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_msg_helpers.c
@@ -21,7 +21,7 @@ struct msg_test_opts {
 
 #define POP_END -1
 
-static void cork_send(struct msg_test_opts *opts, int cork)
+static void cork_send(struct msg_test_opts *opts, int cork, int start, int len)
 {
 	struct test_sockmap_msg_helpers *skel = opts->skel;
 	char buf[] = "abcdefghijklmnopqrstuvwxyz";
@@ -29,9 +29,12 @@ static void cork_send(struct msg_test_opts *opts, int cork)
 	char *recvbuf;
 	int i;
 
-	skel->bss->pop = false;
+	skel->bss->pop = !!len;
 	skel->bss->cork = cork;
 
+	skel->bss->pop_start = start;
+	skel->bss->pop_len = len;
+
 	/* Send N bytes in 27B chunks */
 	for (i = 0; i < cork / sizeof(buf); i++) {
 		sent = xsend(opts->client, buf, sizeof(buf), 0);
@@ -48,7 +51,7 @@ static void cork_send(struct msg_test_opts *opts, int cork)
 	ASSERT_EQ(skel->bss->size, cork, "cork did not receive all bytes");
 
 	recv = xrecv_nonblock(opts->server, recvbuf, total, 0);
-	if (recv != total)
+	if (recv != total - len)
 		FAIL("Received incorrect number of bytes");
 
 	free(recvbuf);
@@ -88,9 +91,15 @@ static void test_sockmap_cork()
 	opts.skel = skel;
 
 	/* Small cork */
-	cork_send(&opts, 54);
+	cork_send(&opts, 54, 0, 0);
 	/* Full cork */
-	cork_send(&opts, 270);
+	cork_send(&opts, 270, 0, 0);
+
+	/* Combine cork and pop small */
+	cork_send(&opts, 54, 0, 10);
+	/* Full cork and pop */
+	cork_send(&opts, 270, 200, 50);
+
 close_sockets:
 	close(client);
 	close(server);
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_msg_helpers.c b/tools/testing/selftests/bpf/progs/test_sockmap_msg_helpers.c
index 9622f154d016..4c7e70367e35 100644
--- a/tools/testing/selftests/bpf/progs/test_sockmap_msg_helpers.c
+++ b/tools/testing/selftests/bpf/progs/test_sockmap_msg_helpers.c
@@ -37,8 +37,19 @@ int msg_helpers(struct sk_msg_md *msg)
 {
 	size = msg->size;
 
-	if (cork)
+	/* If message is not yet fully cork'ed skip push, pull, pop */
+	if (cork && cork > msg->size) {
 		err = bpf_msg_cork_bytes(msg, cork);
+		goto out;
+	} else if (cork) {
+	/* If we previously corked the msg we need to clear the cork
+	 * otherwise next pop would cause datapath to wait for the
+	 * popped bytes to actually do the send.
+	 */
+		err = bpf_msg_cork_bytes(msg, 0);
+		if (err)
+			goto out;
+	}
 
 	if (pull)
 		err = bpf_msg_pull_data(msg, pull_start, pull_end, 0);
@@ -49,6 +60,7 @@ int msg_helpers(struct sk_msg_md *msg)
 	if (pop)
 		err = bpf_msg_pop_data(msg, pop_start, pop_len, 0);
 
+out:
 	return SK_PASS;
 }
 
-- 
2.33.0