]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
vsock/test: add test for small packets under pressure
authorStefano Garzarella <sgarzare@redhat.com>
Wed, 8 Jul 2026 10:29:04 +0000 (12:29 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 21 Jul 2026 10:11:06 +0000 (12:11 +0200)
Add a test that sends 2 MB of data using randomly sized small packets
(129-512 bytes) over a SOCK_STREAM connection. Packets above
GOOD_COPY_LEN (128) bypass the in-place coalescing in recv_enqueue(),
forcing each one into its own skb.

Without receive queue collapsing, the per-skb overhead eventually
exceeds buf_alloc and the connection is reset. The test verifies
that all data arrives and that content integrity is preserved.

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
Link: https://patch.msgid.link/20260708102904.50732-3-sgarzare@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
tools/testing/vsock/vsock_test.c

index 76be0e4a7f0ee6700e0b69c681f25a5b8970c5b4..b4ff9f946565b81167df93a69ea6950ae795ea73 100644 (file)
@@ -2347,6 +2347,88 @@ static void test_stream_tx_credit_bounds_server(const struct test_opts *opts)
        close(fd);
 }
 
+/* Test that many small packets don't cause a connection reset under pressure
+ * and that data integrity is preserved.  Packet sizes vary randomly between
+ * 129 and 512 bytes, above GOOD_COPY_LEN (128) to bypass in-place coalescing
+ * in recv_enqueue, forcing each one into its own skb.  Without receive queue
+ * collapsing, the per-skb overhead eventually exceeds buf_alloc and the
+ * connection is reset.
+ */
+#define COLLAPSE_PKT_MIN 129
+#define COLLAPSE_PKT_MAX 512
+#define COLLAPSE_TOTAL (2 * 1024 * 1024)
+
+static void test_stream_collapse_client(const struct test_opts *opts)
+{
+       unsigned char *data;
+       unsigned long hash;
+       size_t offset = 0;
+       int i, fd;
+
+       data = malloc(COLLAPSE_TOTAL);
+       if (!data) {
+               perror("malloc");
+               exit(EXIT_FAILURE);
+       }
+
+       for (i = 0; i < COLLAPSE_TOTAL; i++)
+               data[i] = rand() & 0xff;
+
+       fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
+       if (fd < 0) {
+               perror("connect");
+               exit(EXIT_FAILURE);
+       }
+
+       while (offset < COLLAPSE_TOTAL) {
+               size_t pkt_size = COLLAPSE_PKT_MIN +
+                       rand() % (COLLAPSE_PKT_MAX - COLLAPSE_PKT_MIN + 1);
+
+               pkt_size = min(pkt_size, COLLAPSE_TOTAL - offset);
+
+               send_buf(fd, data + offset, pkt_size, 0, pkt_size);
+               offset += pkt_size;
+       }
+
+       hash = hash_djb2(data, COLLAPSE_TOTAL);
+       control_writeulong(hash);
+
+       free(data);
+       close(fd);
+}
+
+static void test_stream_collapse_server(const struct test_opts *opts)
+{
+       unsigned long hash, remote_hash;
+       unsigned char *data;
+       int fd;
+
+       data = malloc(COLLAPSE_TOTAL);
+       if (!data) {
+               perror("malloc");
+               exit(EXIT_FAILURE);
+       }
+
+       fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
+       if (fd < 0) {
+               perror("accept");
+               exit(EXIT_FAILURE);
+       }
+
+       recv_buf(fd, data, COLLAPSE_TOTAL, 0, COLLAPSE_TOTAL);
+
+       hash = hash_djb2(data, COLLAPSE_TOTAL);
+       remote_hash = control_readulong();
+       if (hash != remote_hash) {
+               fprintf(stderr, "hash mismatch: local %lu remote %lu\n",
+                       hash, remote_hash);
+               exit(EXIT_FAILURE);
+       }
+
+       free(data);
+       close(fd);
+}
+
 static struct test_case test_cases[] = {
        {
                .name = "SOCK_STREAM connection reset",
@@ -2546,6 +2628,11 @@ static struct test_case test_cases[] = {
                .run_client = test_stream_msg_peek_client,
                .run_server = test_stream_peek_after_recv_server,
        },
+       {
+               .name = "SOCK_STREAM small packets backpressure",
+               .run_client = test_stream_collapse_client,
+               .run_server = test_stream_collapse_server,
+       },
        {},
 };