mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
vsock/test: add test for small packets under pressure
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>
This commit is contained in:
parent
2a12c05aef
commit
30c82aa0a8
|
|
@ -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,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user