test/vsock: MSG_ZEROCOPY support for vsock_perf
authorArseniy Krasnov <avkrasnov@salutedevices.com>
Tue, 10 Oct 2023 19:15:23 +0000 (22:15 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 15 Oct 2023 12:19:42 +0000 (13:19 +0100)
To use this option pass '--zerocopy' parameter:

./vsock_perf --zerocopy --sender <cid> ...

With this option MSG_ZEROCOPY flag will be passed to the 'send()' call.

Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
tools/testing/vsock/Makefile
tools/testing/vsock/vsock_perf.c

index bb938e4790b5e5572d94d7355481ddfcff8a6f34..228470ae33c296c3776a0abece5d0557ba6975a8 100644 (file)
@@ -3,7 +3,7 @@ all: test vsock_perf
 test: vsock_test vsock_diag_test
 vsock_test: vsock_test.o vsock_test_zerocopy.o timeout.o control.o util.o msg_zerocopy_common.o
 vsock_diag_test: vsock_diag_test.o timeout.o control.o util.o
-vsock_perf: vsock_perf.o
+vsock_perf: vsock_perf.o msg_zerocopy_common.o
 
 CFLAGS += -g -O2 -Werror -Wall -I. -I../../include -I../../../usr/include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE
 .PHONY: all test clean
index a72520338f84fe7fc8fa8a1b123364f6231614af..4e8578f815e08a55fc3d5e8691b23453e2c772fe 100644 (file)
@@ -18,6 +18,9 @@
 #include <poll.h>
 #include <sys/socket.h>
 #include <linux/vm_sockets.h>
+#include <sys/mman.h>
+
+#include "msg_zerocopy_common.h"
 
 #define DEFAULT_BUF_SIZE_BYTES (128 * 1024)
 #define DEFAULT_TO_SEND_BYTES  (64 * 1024)
@@ -31,6 +34,7 @@
 static unsigned int port = DEFAULT_PORT;
 static unsigned long buf_size_bytes = DEFAULT_BUF_SIZE_BYTES;
 static unsigned long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES;
+static bool zerocopy;
 
 static void error(const char *s)
 {
@@ -252,10 +256,15 @@ static void run_sender(int peer_cid, unsigned long to_send_bytes)
        time_t tx_begin_ns;
        time_t tx_total_ns;
        size_t total_send;
+       time_t time_in_send;
        void *data;
        int fd;
 
-       printf("Run as sender\n");
+       if (zerocopy)
+               printf("Run as sender MSG_ZEROCOPY\n");
+       else
+               printf("Run as sender\n");
+
        printf("Connect to %i:%u\n", peer_cid, port);
        printf("Send %lu bytes\n", to_send_bytes);
        printf("TX buffer %lu bytes\n", buf_size_bytes);
@@ -265,38 +274,82 @@ static void run_sender(int peer_cid, unsigned long to_send_bytes)
        if (fd < 0)
                exit(EXIT_FAILURE);
 
-       data = malloc(buf_size_bytes);
+       if (zerocopy) {
+               enable_so_zerocopy(fd);
 
-       if (!data) {
-               fprintf(stderr, "'malloc()' failed\n");
-               exit(EXIT_FAILURE);
+               data = mmap(NULL, buf_size_bytes, PROT_READ | PROT_WRITE,
+                           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+               if (data == MAP_FAILED) {
+                       perror("mmap");
+                       exit(EXIT_FAILURE);
+               }
+       } else {
+               data = malloc(buf_size_bytes);
+
+               if (!data) {
+                       fprintf(stderr, "'malloc()' failed\n");
+                       exit(EXIT_FAILURE);
+               }
        }
 
        memset(data, 0, buf_size_bytes);
        total_send = 0;
+       time_in_send = 0;
        tx_begin_ns = current_nsec();
 
        while (total_send < to_send_bytes) {
                ssize_t sent;
+               size_t rest_bytes;
+               time_t before;
 
-               sent = write(fd, data, buf_size_bytes);
+               rest_bytes = to_send_bytes - total_send;
+
+               before = current_nsec();
+               sent = send(fd, data, (rest_bytes > buf_size_bytes) ?
+                           buf_size_bytes : rest_bytes,
+                           zerocopy ? MSG_ZEROCOPY : 0);
+               time_in_send += (current_nsec() - before);
 
                if (sent <= 0)
                        error("write");
 
                total_send += sent;
+
+               if (zerocopy) {
+                       struct pollfd fds = { 0 };
+
+                       fds.fd = fd;
+
+                       if (poll(&fds, 1, -1) < 0) {
+                               perror("poll");
+                               exit(EXIT_FAILURE);
+                       }
+
+                       if (!(fds.revents & POLLERR)) {
+                               fprintf(stderr, "POLLERR expected\n");
+                               exit(EXIT_FAILURE);
+                       }
+
+                       vsock_recv_completion(fd, NULL);
+               }
        }
 
        tx_total_ns = current_nsec() - tx_begin_ns;
 
        printf("total bytes sent: %zu\n", total_send);
        printf("tx performance: %f Gbits/s\n",
-              get_gbps(total_send * 8, tx_total_ns));
-       printf("total time in 'write()': %f sec\n",
+              get_gbps(total_send * 8, time_in_send));
+       printf("total time in tx loop: %f sec\n",
               (float)tx_total_ns / NSEC_PER_SEC);
+       printf("time in 'send()': %f sec\n",
+              (float)time_in_send / NSEC_PER_SEC);
 
        close(fd);
-       free(data);
+
+       if (zerocopy)
+               munmap(data, buf_size_bytes);
+       else
+               free(data);
 }
 
 static const char optstring[] = "";
@@ -336,6 +389,11 @@ static const struct option longopts[] = {
                .has_arg = required_argument,
                .val = 'R',
        },
+       {
+               .name = "zerocopy",
+               .has_arg = no_argument,
+               .val = 'Z',
+       },
        {},
 };
 
@@ -351,6 +409,7 @@ static void usage(void)
               "  --help                        This message\n"
               "  --sender   <cid>              Sender mode (receiver default)\n"
               "                                <cid> of the receiver to connect to\n"
+              "  --zerocopy                    Enable zerocopy (for sender mode only)\n"
               "  --port     <port>             Port (default %d)\n"
               "  --bytes    <bytes>KMG         Bytes to send (default %d)\n"
               "  --buf-size <bytes>KMG         Data buffer size (default %d). In sender mode\n"
@@ -413,6 +472,9 @@ int main(int argc, char **argv)
                case 'H': /* Help. */
                        usage();
                        break;
+               case 'Z': /* Zerocopy. */
+                       zerocopy = true;
+                       break;
                default:
                        usage();
                }