Skip to content

Commit 5c33811

Browse files
Arseniy KrasnovPaolo Abeni
authored andcommitted
test/vsock: rework message bounds test
This updates message bound test making it more complex. Instead of sending 1 bytes messages with one MSG_EOR bit, it sends messages of random length(one half of messages are smaller than page size, second half are bigger) with random number of MSG_EOR bits set. Receiver also don't know total number of messages. Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent c43170b commit 5c33811

File tree

5 files changed

+157
-15
lines changed

5 files changed

+157
-15
lines changed

tools/testing/vsock/control.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,34 @@ void control_writeln(const char *str)
141141
timeout_end();
142142
}
143143

144+
void control_writeulong(unsigned long value)
145+
{
146+
char str[32];
147+
148+
if (snprintf(str, sizeof(str), "%lu", value) >= sizeof(str)) {
149+
perror("snprintf");
150+
exit(EXIT_FAILURE);
151+
}
152+
153+
control_writeln(str);
154+
}
155+
156+
unsigned long control_readulong(void)
157+
{
158+
unsigned long value;
159+
char *str;
160+
161+
str = control_readln();
162+
163+
if (!str)
164+
exit(EXIT_FAILURE);
165+
166+
value = strtoul(str, NULL, 10);
167+
free(str);
168+
169+
return value;
170+
}
171+
144172
/* Return the next line from the control socket (without the trailing newline).
145173
*
146174
* The program terminates if a timeout occurs.

tools/testing/vsock/control.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ void control_init(const char *control_host, const char *control_port,
99
void control_cleanup(void);
1010
void control_writeln(const char *str);
1111
char *control_readln(void);
12+
unsigned long control_readulong(void);
1213
void control_expectln(const char *str);
1314
bool control_cmpln(char *line, const char *str, bool fail);
15+
void control_writeulong(unsigned long value);
1416

1517
#endif /* CONTROL_H */

tools/testing/vsock/util.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,3 +395,16 @@ void skip_test(struct test_case *test_cases, size_t test_cases_len,
395395

396396
test_cases[test_id].skip = true;
397397
}
398+
399+
unsigned long hash_djb2(const void *data, size_t len)
400+
{
401+
unsigned long hash = 5381;
402+
int i = 0;
403+
404+
while (i < len) {
405+
hash = ((hash << 5) + hash) + ((unsigned char *)data)[i];
406+
i++;
407+
}
408+
409+
return hash;
410+
}

tools/testing/vsock/util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,5 @@ void run_tests(const struct test_case *test_cases,
4949
void list_tests(const struct test_case *test_cases);
5050
void skip_test(struct test_case *test_cases, size_t test_cases_len,
5151
const char *test_id_str);
52+
unsigned long hash_djb2(const void *data, size_t len);
5253
#endif /* UTIL_H */

tools/testing/vsock/vsock_test.c

Lines changed: 113 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,14 @@ static void test_stream_msg_peek_server(const struct test_opts *opts)
284284
close(fd);
285285
}
286286

287-
#define MESSAGES_CNT 7
288-
#define MSG_EOR_IDX (MESSAGES_CNT / 2)
287+
#define SOCK_BUF_SIZE (2 * 1024 * 1024)
288+
#define MAX_MSG_SIZE (32 * 1024)
289+
289290
static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
290291
{
292+
unsigned long curr_hash;
293+
int page_size;
294+
int msg_count;
291295
int fd;
292296

293297
fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
@@ -296,18 +300,79 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
296300
exit(EXIT_FAILURE);
297301
}
298302

299-
/* Send several messages, one with MSG_EOR flag */
300-
for (int i = 0; i < MESSAGES_CNT; i++)
301-
send_byte(fd, 1, (i == MSG_EOR_IDX) ? MSG_EOR : 0);
303+
/* Wait, until receiver sets buffer size. */
304+
control_expectln("SRVREADY");
305+
306+
curr_hash = 0;
307+
page_size = getpagesize();
308+
msg_count = SOCK_BUF_SIZE / MAX_MSG_SIZE;
309+
310+
for (int i = 0; i < msg_count; i++) {
311+
ssize_t send_size;
312+
size_t buf_size;
313+
int flags;
314+
void *buf;
315+
316+
/* Use "small" buffers and "big" buffers. */
317+
if (i & 1)
318+
buf_size = page_size +
319+
(rand() % (MAX_MSG_SIZE - page_size));
320+
else
321+
buf_size = 1 + (rand() % page_size);
322+
323+
buf = malloc(buf_size);
324+
325+
if (!buf) {
326+
perror("malloc");
327+
exit(EXIT_FAILURE);
328+
}
329+
330+
memset(buf, rand() & 0xff, buf_size);
331+
/* Set at least one MSG_EOR + some random. */
332+
if (i == (msg_count / 2) || (rand() & 1)) {
333+
flags = MSG_EOR;
334+
curr_hash++;
335+
} else {
336+
flags = 0;
337+
}
338+
339+
send_size = send(fd, buf, buf_size, flags);
340+
341+
if (send_size < 0) {
342+
perror("send");
343+
exit(EXIT_FAILURE);
344+
}
345+
346+
if (send_size != buf_size) {
347+
fprintf(stderr, "Invalid send size\n");
348+
exit(EXIT_FAILURE);
349+
}
350+
351+
/*
352+
* Hash sum is computed at both client and server in
353+
* the same way:
354+
* H += hash('message data')
355+
* Such hash "controls" both data integrity and message
356+
* bounds. After data exchange, both sums are compared
357+
* using control socket, and if message bounds wasn't
358+
* broken - two values must be equal.
359+
*/
360+
curr_hash += hash_djb2(buf, buf_size);
361+
free(buf);
362+
}
302363

303364
control_writeln("SENDDONE");
365+
control_writeulong(curr_hash);
304366
close(fd);
305367
}
306368

307369
static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
308370
{
371+
unsigned long sock_buf_size;
372+
unsigned long remote_hash;
373+
unsigned long curr_hash;
309374
int fd;
310-
char buf[16];
375+
char buf[MAX_MSG_SIZE];
311376
struct msghdr msg = {0};
312377
struct iovec iov = {0};
313378

@@ -317,25 +382,57 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
317382
exit(EXIT_FAILURE);
318383
}
319384

385+
sock_buf_size = SOCK_BUF_SIZE;
386+
387+
if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
388+
&sock_buf_size, sizeof(sock_buf_size))) {
389+
perror("setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");
390+
exit(EXIT_FAILURE);
391+
}
392+
393+
if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
394+
&sock_buf_size, sizeof(sock_buf_size))) {
395+
perror("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
396+
exit(EXIT_FAILURE);
397+
}
398+
399+
/* Ready to receive data. */
400+
control_writeln("SRVREADY");
401+
/* Wait, until peer sends whole data. */
320402
control_expectln("SENDDONE");
321403
iov.iov_base = buf;
322404
iov.iov_len = sizeof(buf);
323405
msg.msg_iov = &iov;
324406
msg.msg_iovlen = 1;
325407

326-
for (int i = 0; i < MESSAGES_CNT; i++) {
327-
if (recvmsg(fd, &msg, 0) != 1) {
328-
perror("message bound violated");
329-
exit(EXIT_FAILURE);
330-
}
408+
curr_hash = 0;
331409

332-
if ((i == MSG_EOR_IDX) ^ !!(msg.msg_flags & MSG_EOR)) {
333-
perror("MSG_EOR");
410+
while (1) {
411+
ssize_t recv_size;
412+
413+
recv_size = recvmsg(fd, &msg, 0);
414+
415+
if (!recv_size)
416+
break;
417+
418+
if (recv_size < 0) {
419+
perror("recvmsg");
334420
exit(EXIT_FAILURE);
335421
}
422+
423+
if (msg.msg_flags & MSG_EOR)
424+
curr_hash++;
425+
426+
curr_hash += hash_djb2(msg.msg_iov[0].iov_base, recv_size);
336427
}
337428

338429
close(fd);
430+
remote_hash = control_readulong();
431+
432+
if (curr_hash != remote_hash) {
433+
fprintf(stderr, "Message bounds broken\n");
434+
exit(EXIT_FAILURE);
435+
}
339436
}
340437

341438
#define MESSAGE_TRUNC_SZ 32
@@ -427,7 +524,7 @@ static void test_seqpacket_timeout_client(const struct test_opts *opts)
427524
tv.tv_usec = 0;
428525

429526
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) == -1) {
430-
perror("setsockopt 'SO_RCVTIMEO'");
527+
perror("setsockopt(SO_RCVTIMEO)");
431528
exit(EXIT_FAILURE);
432529
}
433530

@@ -644,7 +741,7 @@ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
644741

645742
if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT,
646743
&lowat_val, sizeof(lowat_val))) {
647-
perror("setsockopt");
744+
perror("setsockopt(SO_RCVLOWAT)");
648745
exit(EXIT_FAILURE);
649746
}
650747

@@ -837,6 +934,7 @@ int main(int argc, char **argv)
837934
.peer_cid = VMADDR_CID_ANY,
838935
};
839936

937+
srand(time(NULL));
840938
init_signals();
841939

842940
for (;;) {

0 commit comments

Comments
 (0)