1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Some common code for MSG_ZEROCOPY logic 3 * 4 * Copyright (C) 2023 SberDevices. 5 * 6 * Author: Arseniy Krasnov <avkrasnov@salutedevices.com> 7 */ 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 #include <linux/errqueue.h> 14 15 #include "msg_zerocopy_common.h" 16 17 void vsock_recv_completion(int fd, const bool *zerocopied) 18 { 19 struct sock_extended_err *serr; 20 struct msghdr msg = { 0 }; 21 char cmsg_data[128]; 22 struct cmsghdr *cm; 23 ssize_t res; 24 25 msg.msg_control = cmsg_data; 26 msg.msg_controllen = sizeof(cmsg_data); 27 28 res = recvmsg(fd, &msg, MSG_ERRQUEUE); 29 if (res) { 30 fprintf(stderr, "failed to read error queue: %zi\n", res); 31 exit(EXIT_FAILURE); 32 } 33 34 cm = CMSG_FIRSTHDR(&msg); 35 if (!cm) { 36 fprintf(stderr, "cmsg: no cmsg\n"); 37 exit(EXIT_FAILURE); 38 } 39 40 if (cm->cmsg_level != SOL_VSOCK) { 41 fprintf(stderr, "cmsg: unexpected 'cmsg_level'\n"); 42 exit(EXIT_FAILURE); 43 } 44 45 if (cm->cmsg_type != VSOCK_RECVERR) { 46 fprintf(stderr, "cmsg: unexpected 'cmsg_type'\n"); 47 exit(EXIT_FAILURE); 48 } 49 50 serr = (void *)CMSG_DATA(cm); 51 if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY) { 52 fprintf(stderr, "serr: wrong origin: %u\n", serr->ee_origin); 53 exit(EXIT_FAILURE); 54 } 55 56 if (serr->ee_errno) { 57 fprintf(stderr, "serr: wrong error code: %u\n", serr->ee_errno); 58 exit(EXIT_FAILURE); 59 } 60 61 /* This flag is used for tests, to check that transmission was 62 * performed as expected: zerocopy or fallback to copy. If NULL 63 * - don't care. 64 */ 65 if (!zerocopied) 66 return; 67 68 if (*zerocopied && (serr->ee_code & SO_EE_CODE_ZEROCOPY_COPIED)) { 69 fprintf(stderr, "serr: was copy instead of zerocopy\n"); 70 exit(EXIT_FAILURE); 71 } 72 73 if (!*zerocopied && !(serr->ee_code & SO_EE_CODE_ZEROCOPY_COPIED)) { 74 fprintf(stderr, "serr: was zerocopy instead of copy\n"); 75 exit(EXIT_FAILURE); 76 } 77 } 78