// SPDX-License-Identifier: GPL-2.0-only/* * vsock_test - vsock.ko test suite * * Copyright (C) 2017 Red Hat, Inc. * * Author: Stefan Hajnoczi <stefanha@redhat.com> */ #include <getopt.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <linux/kernel.h>#include <sys/types.h>#include <sys/socket.h>#include <time.h>#include <sys/mman.h>#include <poll.h>#include <signal.h>#include <sys/ioctl.h>#include <linux/time64.h>#include <pthread.h>#include <fcntl.h>#include <linux/sockios.h> #include "vsock_test_zerocopy.h"#include "timeout.h"#include "control.h"#include "util.h" /* Basic messages for control_writeulong(), control_readulong() */#define CONTROL_CONTINUE 1#define CONTROL_DONE 0 static void test_stream_connection_reset(const struct test_opts *opts){ union { struct sockaddr sa; struct sockaddr_vm svm; } addr = { .svm = { .svm_family = AF_VSOCK, .svm_port = opts->peer_port, .svm_cid = opts->peer_cid, }, }; int ret; int fd; fd = socket(AF_VSOCK, SOCK_STREAM, 0); timeout_begin(TIMEOUT); do { ret = connect(fd, &addr.sa, sizeof(addr.svm)); timeout_check("connect"); } while (ret < 0 && errno == EINTR); timeout_end(); if (ret != -1) { fprintf(stderr, "expected connect(2) failure, got %d\n", ret); exit(EXIT_FAILURE); } if (errno != ECONNRESET) { fprintf(stderr, "unexpected connect(2) errno %d\n", errno); exit(EXIT_FAILURE); } close(fd);} static void test_stream_bind_only_client(const struct test_opts *opts){ union { struct sockaddr sa; struct sockaddr_vm svm; } addr = { .svm = { .svm_family = AF_VSOCK, .svm_port = opts->peer_port, .svm_cid = opts->peer_cid, }, }; int ret; int fd; /* Wait for the server to be ready */ control_expectln("BIND"); fd = socket(AF_VSOCK, SOCK_STREAM, 0); timeout_begin(TIMEOUT); do { ret = connect(fd, &addr.sa, sizeof(addr.svm)); timeout_check("connect"); } while (ret < 0 && errno == EINTR); timeout_end(); if (ret != -1) { fprintf(stderr, "expected connect(2) failure, got %d\n", ret); exit(EXIT_FAILURE); } if (errno != ECONNRESET) { fprintf(stderr, "unexpected connect(2) errno %d\n", errno); exit(EXIT_FAILURE); } /* Notify the server that the client has finished */ control_writeln("DONE"); close(fd);} static void test_stream_bind_only_server(const struct test_opts *opts){ int fd; fd = vsock_bind(VMADDR_CID_ANY, opts->peer_port, SOCK_STREAM); /* Notify the client that the server is ready */ control_writeln("BIND"); /* Wait for the client to finish */ control_expectln("DONE"); close(fd);} static void test_stream_client_close_client(const struct test_opts *opts){ int fd; fd = vsock_stream_connect(opts->peer_cid, opts->peer_port); if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } send_byte(fd, 1, 0); close(fd);} static void test_stream_client_close_server(const struct test_opts *opts){ int fd; fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } /* Wait for the remote to close the connection, before check * -EPIPE error on send. */ vsock_wait_remote_close(fd); send_byte(fd, -EPIPE, 0); recv_byte(fd, 1, 0); recv_byte(fd, 0, 0); close(fd);} static void test_stream_server_close_client(const struct test_opts *opts){ int fd; fd = vsock_stream_connect(opts->peer_cid, opts->peer_port); if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } /* Wait for the remote to close the connection, before check * -EPIPE error on send. */ vsock_wait_remote_close(fd); send_byte(fd, -EPIPE, 0); recv_byte(fd, 1, 0); recv_byte(fd, 0, 0); close(fd);} static void test_stream_server_close_server(const struct test_opts *opts){ int fd; fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } send_byte(fd, 1, 0); close(fd);} /* With the standard socket sizes, VMCI is able to support about 100 * concurrent stream connections. */#define MULTICONN_NFDS 100 static void test_stream_multiconn_client(const struct test_opts *opts){ int fds[MULTICONN_NFDS]; int i; for (i = 0; i < MULTICONN_NFDS; i++) { fds[i] = vsock_stream_connect(opts->peer_cid, opts->peer_port); if (fds[i] < 0) { perror("connect"); exit(EXIT_FAILURE); } } for (i = 0; i < MULTICONN_NFDS; i++) { if (i % 2) recv_byte(fds[i], 1, 0); else send_byte(fds[i], 1, 0); } for (i = 0; i < MULTICONN_NFDS; i++) close(fds[i]);} static void test_stream_multiconn_server(const struct test_opts *opts){ int fds[MULTICONN_NFDS]; int i; for (i = 0; i < MULTICONN_NFDS; i++) { fds[i] = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fds[i] < 0) { perror("accept"); exit(EXIT_FAILURE); } } for (i = 0; i < MULTICONN_NFDS; i++) { if (i % 2) send_byte(fds[i], 1, 0); else recv_byte(fds[i], 1, 0); } for (i = 0; i < MULTICONN_NFDS; i++) close(fds[i]);} #define MSG_PEEK_BUF_LEN 64 static void test_msg_peek_client(const struct test_opts *opts, bool seqpacket){ unsigned char buf[MSG_PEEK_BUF_LEN]; int fd; int i; if (seqpacket) fd = vsock_seqpacket_connect(opts->peer_cid, opts->peer_port); else fd = vsock_stream_connect(opts->peer_cid, opts->peer_port); if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } for (i = 0; i < sizeof(buf); i++) buf[i] = rand() & 0xFF; control_expectln("SRVREADY"); send_buf(fd, buf, sizeof(buf), 0, sizeof(buf)); close(fd);} static void test_msg_peek_server(const struct test_opts *opts, bool seqpacket){ unsigned char buf_half[MSG_PEEK_BUF_LEN / 2]; unsigned char buf_normal[MSG_PEEK_BUF_LEN]; unsigned char buf_peek[MSG_PEEK_BUF_LEN]; int fd; if (seqpacket) fd = vsock_seqpacket_accept(VMADDR_CID_ANY, opts->peer_port, NULL); else fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } /* Peek from empty socket. */ recv_buf(fd, buf_peek, sizeof(buf_peek), MSG_PEEK | MSG_DONTWAIT, -EAGAIN); control_writeln("SRVREADY"); /* Peek part of data. */ recv_buf(fd, buf_half, sizeof(buf_half), MSG_PEEK, sizeof(buf_half)); /* Peek whole data. */ recv_buf(fd, buf_peek, sizeof(buf_peek), MSG_PEEK, sizeof(buf_peek)); /* Compare partial and full peek. */ if (memcmp(buf_half, buf_peek, sizeof(buf_half))) { fprintf(stderr, "Partial peek data mismatch\n"); exit(EXIT_FAILURE); } if (seqpacket) { /* This type of socket supports MSG_TRUNC flag, * so check it with MSG_PEEK. We must get length * of the message. */ recv_buf(fd, buf_half, sizeof(buf_half), MSG_PEEK | MSG_TRUNC, sizeof(buf_peek)); } recv_buf(fd, buf_normal, sizeof(buf_normal), 0, sizeof(buf_normal)); /* Compare full peek and normal read. */ if (memcmp(buf_peek, buf_normal, sizeof(buf_peek))) { fprintf(stderr, "Full peek data mismatch\n"); exit(EXIT_FAILURE); } close(fd);} static void test_stream_msg_peek_client(const struct test_opts *opts){ return test_msg_peek_client(opts, false);} static void test_stream_msg_peek_server(const struct test_opts *opts){ return test_msg_peek_server(opts, false);} static void test_stream_peek_after_recv_server(const struct test_opts *opts){ unsigned char buf_normal[MSG_PEEK_BUF_LEN]; unsigned char buf_peek[MSG_PEEK_BUF_LEN]; int fd; fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } control_writeln("SRVREADY"); /* Partial recv to advance offset within the skb */ recv_buf(fd, buf_normal, 1, 0, 1); /* Peek with a buffer larger than the remaining data */ recv_buf(fd, buf_peek, sizeof(buf_peek), MSG_PEEK, sizeof(buf_peek) - 1); /* Consume the remaining data */ recv_buf(fd, buf_normal, sizeof(buf_normal) - 1, 0, sizeof(buf_normal) - 1); /* Compare full peek and normal read. */ if (memcmp(buf_peek, buf_normal, sizeof(buf_peek) - 1)) { fprintf(stderr, "Full peek data mismatch\n"); exit(EXIT_FAILURE); } close(fd);} #define SOCK_BUF_SIZE (2 * 1024 * 1024)#define SOCK_BUF_SIZE_SMALL (64 * 1024)#define MAX_MSG_PAGES 4 static void test_seqpacket_msg_bounds_client(const struct test_opts *opts){ unsigned long long sock_buf_size; unsigned long curr_hash; size_t max_msg_size; int page_size; int msg_count; int fd; fd = vsock_seqpacket_connect(opts->peer_cid, opts->peer_port); if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } sock_buf_size = SOCK_BUF_SIZE; setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE, sock_buf_size, "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)"); setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE, sock_buf_size, "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)"); /* Wait, until receiver sets buffer size. */ control_expectln("SRVREADY"); curr_hash = 0; page_size = getpagesize(); max_msg_size = MAX_MSG_PAGES * page_size; msg_count = SOCK_BUF_SIZE / max_msg_size; for (int i = 0; i < msg_count; i++) { size_t buf_size; int flags; void *buf; /* Use "small" buffers and "big" buffers. */ if (i & 1) buf_size = page_size + (rand() % (max_msg_size - page_size)); else buf_size = 1 + (rand() % page_size); buf = malloc(buf_size); if (!buf) { perror("malloc"); exit(EXIT_FAILURE); } memset(buf, rand() & 0xff, buf_size); /* Set at least one MSG_EOR + some random. */ if (i == (msg_count / 2) || (rand() & 1)) { flags = MSG_EOR; curr_hash++; } else { flags = 0; } send_buf(fd, buf, buf_size, flags, buf_size); /* * Hash sum is computed at both client and server in * the same way: * H += hash('message data') * Such hash "controls" both data integrity and message * bounds. After data exchange, both sums are compared * using control socket, and if message bounds wasn't * broken - two values must be equal. */ curr_hash += hash_djb2(buf, buf_size); free(buf); } control_writeln("SENDDONE"); control_writeulong(curr_hash); close(fd);} static void test_seqpacket_msg_bounds_server(const struct test_opts *opts){ unsigned long long sock_buf_size; unsigned long remote_hash; unsigned long curr_hash; int fd; struct msghdr msg = {0}; struct iovec iov = {0}; fd = vsock_seqpacket_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } sock_buf_size = SOCK_BUF_SIZE; setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE, sock_buf_size, "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)"); setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE, sock_buf_size, "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)"); /* Ready to receive data. */ control_writeln("SRVREADY"); /* Wait, until peer sends whole data. */ control_expectln("SENDDONE"); iov.iov_len = MAX_MSG_PAGES * getpagesize(); iov.iov_base = malloc(iov.iov_len); if (!iov.iov_base) { perror("malloc"); exit(EXIT_FAILURE); }Lines 1–500 of 2806. Load more
// SPDX-License-Identifier: GPL-2.0-only /* * vsock_test - vsock.ko test suite * * Copyright (C) 2017 Red Hat, Inc. * * Author: Stefan Hajnoczi <stefanha@redhat.com> */ #include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <linux/kernel.h> #include <sys/types.h> #include <sys/socket.h> #include <time.h> #include <sys/mman.h> #include <poll.h> #include <signal.h> #include <sys/ioctl.h> #include <linux/time64.h> #include <pthread.h> #include <fcntl.h> #include <linux/sockios.h> #include "vsock_test_zerocopy.h" #include "timeout.h" #include "control.h" #include "util.h" /* Basic messages for control_writeulong(), control_readulong() */ #define CONTROL_CONTINUE 1 #define CONTROL_DONE 0 static void test_stream_connection_reset(const struct test_opts *opts) { union { struct sockaddr sa; struct sockaddr_vm svm; } addr = { .svm = { .svm_family = AF_VSOCK, .svm_port = opts->peer_port, .svm_cid = opts->peer_cid, }, }; int ret; int fd; fd = socket(AF_VSOCK, SOCK_STREAM, 0); timeout_begin(TIMEOUT); do { ret = connect(fd, &addr.sa, sizeof(addr.svm)); timeout_check("connect"); } while (ret < 0 && errno == EINTR); timeout_end(); if (ret != -1) { fprintf(stderr, "expected connect(2) failure, got %d\n", ret); exit(EXIT_FAILURE); } if (errno != ECONNRESET) { fprintf(stderr, "unexpected connect(2) errno %d\n", errno); exit(EXIT_FAILURE); } close(fd); } static void test_stream_bind_only_client(const struct test_opts *opts) { union { struct sockaddr sa; struct sockaddr_vm svm; } addr = { .svm = { .svm_family = AF_VSOCK, .svm_port = opts->peer_port, .svm_cid = opts->peer_cid, }, }; int ret; int fd; /* Wait for the server to be ready */ control_expectln("BIND"); fd = socket(AF_VSOCK, SOCK_STREAM, 0); timeout_begin(TIMEOUT); do { ret = connect(fd, &addr.sa, sizeof(addr.svm)); timeout_check("connect"); } while (ret < 0 && errno == EINTR); timeout_end(); if (ret != -1) { fprintf(stderr, "expected connect(2) failure, got %d\n", ret); exit(EXIT_FAILURE); } if (errno != ECONNRESET) { fprintf(stderr, "unexpected connect(2) errno %d\n", errno); exit(EXIT_FAILURE); } /* Notify the server that the client has finished */ control_writeln("DONE"); close(fd); } static void test_stream_bind_only_server(const struct test_opts *opts) { int fd; fd = vsock_bind(VMADDR_CID_ANY, opts->peer_port, SOCK_STREAM); /* Notify the client that the server is ready */ control_writeln("BIND"); /* Wait for the client to finish */ control_expectln("DONE"); close(fd); } static void test_stream_client_close_client(const struct test_opts *opts) { int fd; fd = vsock_stream_connect(opts->peer_cid, opts->peer_port); if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } send_byte(fd, 1, 0); close(fd); } static void test_stream_client_close_server(const struct test_opts *opts) { int fd; fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } /* Wait for the remote to close the connection, before check * -EPIPE error on send. */ vsock_wait_remote_close(fd); send_byte(fd, -EPIPE, 0); recv_byte(fd, 1, 0); recv_byte(fd, 0, 0); close(fd); } static void test_stream_server_close_client(const struct test_opts *opts) { int fd; fd = vsock_stream_connect(opts->peer_cid, opts->peer_port); if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } /* Wait for the remote to close the connection, before check * -EPIPE error on send. */ vsock_wait_remote_close(fd); send_byte(fd, -EPIPE, 0); recv_byte(fd, 1, 0); recv_byte(fd, 0, 0); close(fd); } static void test_stream_server_close_server(const struct test_opts *opts) { int fd; fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } send_byte(fd, 1, 0); close(fd); } /* With the standard socket sizes, VMCI is able to support about 100 * concurrent stream connections. */ #define MULTICONN_NFDS 100 static void test_stream_multiconn_client(const struct test_opts *opts) { int fds[MULTICONN_NFDS]; int i; for (i = 0; i < MULTICONN_NFDS; i++) { fds[i] = vsock_stream_connect(opts->peer_cid, opts->peer_port); if (fds[i] < 0) { perror("connect"); exit(EXIT_FAILURE); } } for (i = 0; i < MULTICONN_NFDS; i++) { if (i % 2) recv_byte(fds[i], 1, 0); else send_byte(fds[i], 1, 0); } for (i = 0; i < MULTICONN_NFDS; i++) close(fds[i]); } static void test_stream_multiconn_server(const struct test_opts *opts) { int fds[MULTICONN_NFDS]; int i; for (i = 0; i < MULTICONN_NFDS; i++) { fds[i] = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fds[i] < 0) { perror("accept"); exit(EXIT_FAILURE); } } for (i = 0; i < MULTICONN_NFDS; i++) { if (i % 2) send_byte(fds[i], 1, 0); else recv_byte(fds[i], 1, 0); } for (i = 0; i < MULTICONN_NFDS; i++) close(fds[i]); } #define MSG_PEEK_BUF_LEN 64 static void test_msg_peek_client(const struct test_opts *opts, bool seqpacket) { unsigned char buf[MSG_PEEK_BUF_LEN]; int fd; int i; if (seqpacket) fd = vsock_seqpacket_connect(opts->peer_cid, opts->peer_port); else fd = vsock_stream_connect(opts->peer_cid, opts->peer_port); if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } for (i = 0; i < sizeof(buf); i++) buf[i] = rand() & 0xFF; control_expectln("SRVREADY"); send_buf(fd, buf, sizeof(buf), 0, sizeof(buf)); close(fd); } static void test_msg_peek_server(const struct test_opts *opts, bool seqpacket) { unsigned char buf_half[MSG_PEEK_BUF_LEN / 2]; unsigned char buf_normal[MSG_PEEK_BUF_LEN]; unsigned char buf_peek[MSG_PEEK_BUF_LEN]; int fd; if (seqpacket) fd = vsock_seqpacket_accept(VMADDR_CID_ANY, opts->peer_port, NULL); else fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } /* Peek from empty socket. */ recv_buf(fd, buf_peek, sizeof(buf_peek), MSG_PEEK | MSG_DONTWAIT, -EAGAIN); control_writeln("SRVREADY"); /* Peek part of data. */ recv_buf(fd, buf_half, sizeof(buf_half), MSG_PEEK, sizeof(buf_half)); /* Peek whole data. */ recv_buf(fd, buf_peek, sizeof(buf_peek), MSG_PEEK, sizeof(buf_peek)); /* Compare partial and full peek. */ if (memcmp(buf_half, buf_peek, sizeof(buf_half))) { fprintf(stderr, "Partial peek data mismatch\n"); exit(EXIT_FAILURE); } if (seqpacket) { /* This type of socket supports MSG_TRUNC flag, * so check it with MSG_PEEK. We must get length * of the message. */ recv_buf(fd, buf_half, sizeof(buf_half), MSG_PEEK | MSG_TRUNC, sizeof(buf_peek)); } recv_buf(fd, buf_normal, sizeof(buf_normal), 0, sizeof(buf_normal)); /* Compare full peek and normal read. */ if (memcmp(buf_peek, buf_normal, sizeof(buf_peek))) { fprintf(stderr, "Full peek data mismatch\n"); exit(EXIT_FAILURE); } close(fd); } static void test_stream_msg_peek_client(const struct test_opts *opts) { return test_msg_peek_client(opts, false); } static void test_stream_msg_peek_server(const struct test_opts *opts) { return test_msg_peek_server(opts, false); } static void test_stream_peek_after_recv_server(const struct test_opts *opts) { unsigned char buf_normal[MSG_PEEK_BUF_LEN]; unsigned char buf_peek[MSG_PEEK_BUF_LEN]; int fd; fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } control_writeln("SRVREADY"); /* Partial recv to advance offset within the skb */ recv_buf(fd, buf_normal, 1, 0, 1); /* Peek with a buffer larger than the remaining data */ recv_buf(fd, buf_peek, sizeof(buf_peek), MSG_PEEK, sizeof(buf_peek) - 1); /* Consume the remaining data */ recv_buf(fd, buf_normal, sizeof(buf_normal) - 1, 0, sizeof(buf_normal) - 1); /* Compare full peek and normal read. */ if (memcmp(buf_peek, buf_normal, sizeof(buf_peek) - 1)) { fprintf(stderr, "Full peek data mismatch\n"); exit(EXIT_FAILURE); } close(fd); } #define SOCK_BUF_SIZE (2 * 1024 * 1024) #define SOCK_BUF_SIZE_SMALL (64 * 1024) #define MAX_MSG_PAGES 4 static void test_seqpacket_msg_bounds_client(const struct test_opts *opts) { unsigned long long sock_buf_size; unsigned long curr_hash; size_t max_msg_size; int page_size; int msg_count; int fd; fd = vsock_seqpacket_connect(opts->peer_cid, opts->peer_port); if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } sock_buf_size = SOCK_BUF_SIZE; setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE, sock_buf_size, "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)"); setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE, sock_buf_size, "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)"); /* Wait, until receiver sets buffer size. */ control_expectln("SRVREADY"); curr_hash = 0; page_size = getpagesize(); max_msg_size = MAX_MSG_PAGES * page_size; msg_count = SOCK_BUF_SIZE / max_msg_size; for (int i = 0; i < msg_count; i++) { size_t buf_size; int flags; void *buf; /* Use "small" buffers and "big" buffers. */ if (i & 1) buf_size = page_size + (rand() % (max_msg_size - page_size)); else buf_size = 1 + (rand() % page_size); buf = malloc(buf_size); if (!buf) { perror("malloc"); exit(EXIT_FAILURE); } memset(buf, rand() & 0xff, buf_size); /* Set at least one MSG_EOR + some random. */ if (i == (msg_count / 2) || (rand() & 1)) { flags = MSG_EOR; curr_hash++; } else { flags = 0; } send_buf(fd, buf, buf_size, flags, buf_size); /* * Hash sum is computed at both client and server in * the same way: * H += hash('message data') * Such hash "controls" both data integrity and message * bounds. After data exchange, both sums are compared * using control socket, and if message bounds wasn't * broken - two values must be equal. */ curr_hash += hash_djb2(buf, buf_size); free(buf); } control_writeln("SENDDONE"); control_writeulong(curr_hash); close(fd); } static void test_seqpacket_msg_bounds_server(const struct test_opts *opts) { unsigned long long sock_buf_size; unsigned long remote_hash; unsigned long curr_hash; int fd; struct msghdr msg = {0}; struct iovec iov = {0}; fd = vsock_seqpacket_accept(VMADDR_CID_ANY, opts->peer_port, NULL); if (fd < 0) { perror("accept"); exit(EXIT_FAILURE); } sock_buf_size = SOCK_BUF_SIZE; setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE, sock_buf_size, "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)"); setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE, sock_buf_size, "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)"); /* Ready to receive data. */ control_writeln("SRVREADY"); /* Wait, until peer sends whole data. */ control_expectln("SENDDONE"); iov.iov_len = MAX_MSG_PAGES * getpagesize(); iov.iov_base = malloc(iov.iov_len); if (!iov.iov_base) { perror("malloc"); exit(EXIT_FAILURE); }