Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

test/vsock: MSG_ZEROCOPY support for vsock_perf

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>

authored by

Arseniy Krasnov and committed by
David S. Miller
e846d679 bc36442e

+72 -10
+1 -1
tools/testing/vsock/Makefile
··· 3 3 test: vsock_test vsock_diag_test 4 4 vsock_test: vsock_test.o vsock_test_zerocopy.o timeout.o control.o util.o msg_zerocopy_common.o 5 5 vsock_diag_test: vsock_diag_test.o timeout.o control.o util.o 6 - vsock_perf: vsock_perf.o 6 + vsock_perf: vsock_perf.o msg_zerocopy_common.o 7 7 8 8 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 9 9 .PHONY: all test clean
+71 -9
tools/testing/vsock/vsock_perf.c
··· 18 18 #include <poll.h> 19 19 #include <sys/socket.h> 20 20 #include <linux/vm_sockets.h> 21 + #include <sys/mman.h> 22 + 23 + #include "msg_zerocopy_common.h" 21 24 22 25 #define DEFAULT_BUF_SIZE_BYTES (128 * 1024) 23 26 #define DEFAULT_TO_SEND_BYTES (64 * 1024) ··· 34 31 static unsigned int port = DEFAULT_PORT; 35 32 static unsigned long buf_size_bytes = DEFAULT_BUF_SIZE_BYTES; 36 33 static unsigned long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES; 34 + static bool zerocopy; 37 35 38 36 static void error(const char *s) 39 37 { ··· 256 252 time_t tx_begin_ns; 257 253 time_t tx_total_ns; 258 254 size_t total_send; 255 + time_t time_in_send; 259 256 void *data; 260 257 int fd; 261 258 262 - printf("Run as sender\n"); 259 + if (zerocopy) 260 + printf("Run as sender MSG_ZEROCOPY\n"); 261 + else 262 + printf("Run as sender\n"); 263 + 263 264 printf("Connect to %i:%u\n", peer_cid, port); 264 265 printf("Send %lu bytes\n", to_send_bytes); 265 266 printf("TX buffer %lu bytes\n", buf_size_bytes); ··· 274 265 if (fd < 0) 275 266 exit(EXIT_FAILURE); 276 267 277 - data = malloc(buf_size_bytes); 268 + if (zerocopy) { 269 + enable_so_zerocopy(fd); 278 270 279 - if (!data) { 280 - fprintf(stderr, "'malloc()' failed\n"); 281 - exit(EXIT_FAILURE); 271 + data = mmap(NULL, buf_size_bytes, PROT_READ | PROT_WRITE, 272 + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 273 + if (data == MAP_FAILED) { 274 + perror("mmap"); 275 + exit(EXIT_FAILURE); 276 + } 277 + } else { 278 + data = malloc(buf_size_bytes); 279 + 280 + if (!data) { 281 + fprintf(stderr, "'malloc()' failed\n"); 282 + exit(EXIT_FAILURE); 283 + } 282 284 } 283 285 284 286 memset(data, 0, buf_size_bytes); 285 287 total_send = 0; 288 + time_in_send = 0; 286 289 tx_begin_ns = current_nsec(); 287 290 288 291 while (total_send < to_send_bytes) { 289 292 ssize_t sent; 293 + size_t rest_bytes; 294 + time_t before; 290 295 291 - sent = write(fd, data, buf_size_bytes); 296 + rest_bytes = to_send_bytes - total_send; 297 + 298 + before = current_nsec(); 299 + sent = send(fd, data, (rest_bytes > buf_size_bytes) ? 300 + buf_size_bytes : rest_bytes, 301 + zerocopy ? MSG_ZEROCOPY : 0); 302 + time_in_send += (current_nsec() - before); 292 303 293 304 if (sent <= 0) 294 305 error("write"); 295 306 296 307 total_send += sent; 308 + 309 + if (zerocopy) { 310 + struct pollfd fds = { 0 }; 311 + 312 + fds.fd = fd; 313 + 314 + if (poll(&fds, 1, -1) < 0) { 315 + perror("poll"); 316 + exit(EXIT_FAILURE); 317 + } 318 + 319 + if (!(fds.revents & POLLERR)) { 320 + fprintf(stderr, "POLLERR expected\n"); 321 + exit(EXIT_FAILURE); 322 + } 323 + 324 + vsock_recv_completion(fd, NULL); 325 + } 297 326 } 298 327 299 328 tx_total_ns = current_nsec() - tx_begin_ns; 300 329 301 330 printf("total bytes sent: %zu\n", total_send); 302 331 printf("tx performance: %f Gbits/s\n", 303 - get_gbps(total_send * 8, tx_total_ns)); 304 - printf("total time in 'write()': %f sec\n", 332 + get_gbps(total_send * 8, time_in_send)); 333 + printf("total time in tx loop: %f sec\n", 305 334 (float)tx_total_ns / NSEC_PER_SEC); 335 + printf("time in 'send()': %f sec\n", 336 + (float)time_in_send / NSEC_PER_SEC); 306 337 307 338 close(fd); 308 - free(data); 339 + 340 + if (zerocopy) 341 + munmap(data, buf_size_bytes); 342 + else 343 + free(data); 309 344 } 310 345 311 346 static const char optstring[] = ""; ··· 389 336 .has_arg = required_argument, 390 337 .val = 'R', 391 338 }, 339 + { 340 + .name = "zerocopy", 341 + .has_arg = no_argument, 342 + .val = 'Z', 343 + }, 392 344 {}, 393 345 }; 394 346 ··· 409 351 " --help This message\n" 410 352 " --sender <cid> Sender mode (receiver default)\n" 411 353 " <cid> of the receiver to connect to\n" 354 + " --zerocopy Enable zerocopy (for sender mode only)\n" 412 355 " --port <port> Port (default %d)\n" 413 356 " --bytes <bytes>KMG Bytes to send (default %d)\n" 414 357 " --buf-size <bytes>KMG Data buffer size (default %d). In sender mode\n" ··· 471 412 break; 472 413 case 'H': /* Help. */ 473 414 usage(); 415 + break; 416 + case 'Z': /* Zerocopy. */ 417 + zerocopy = true; 474 418 break; 475 419 default: 476 420 usage();