// SPDX-License-Identifier: GPL-2.0-only /* Some common code for MSG_ZEROCOPY logic * * Copyright (C) 2023 SberDevices. * * Author: Arseniy Krasnov */ #include #include #include #include #include #include "msg_zerocopy_common.h" void enable_so_zerocopy(int fd) { int val = 1; if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &val, sizeof(val))) { perror("setsockopt"); exit(EXIT_FAILURE); } } void vsock_recv_completion(int fd, const bool *zerocopied) { struct sock_extended_err *serr; struct msghdr msg = { 0 }; char cmsg_data[128]; struct cmsghdr *cm; ssize_t res; msg.msg_control = cmsg_data; msg.msg_controllen = sizeof(cmsg_data); res = recvmsg(fd, &msg, MSG_ERRQUEUE); if (res) { fprintf(stderr, "failed to read error queue: %zi\n", res); exit(EXIT_FAILURE); } cm = CMSG_FIRSTHDR(&msg); if (!cm) { fprintf(stderr, "cmsg: no cmsg\n"); exit(EXIT_FAILURE); } if (cm->cmsg_level != SOL_VSOCK) { fprintf(stderr, "cmsg: unexpected 'cmsg_level'\n"); exit(EXIT_FAILURE); } if (cm->cmsg_type != VSOCK_RECVERR) { fprintf(stderr, "cmsg: unexpected 'cmsg_type'\n"); exit(EXIT_FAILURE); } serr = (void *)CMSG_DATA(cm); if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY) { fprintf(stderr, "serr: wrong origin: %u\n", serr->ee_origin); exit(EXIT_FAILURE); } if (serr->ee_errno) { fprintf(stderr, "serr: wrong error code: %u\n", serr->ee_errno); exit(EXIT_FAILURE); } /* This flag is used for tests, to check that transmission was * performed as expected: zerocopy or fallback to copy. If NULL * - don't care. */ if (!zerocopied) return; if (*zerocopied && (serr->ee_code & SO_EE_CODE_ZEROCOPY_COPIED)) { fprintf(stderr, "serr: was copy instead of zerocopy\n"); exit(EXIT_FAILURE); } if (!*zerocopied && !(serr->ee_code & SO_EE_CODE_ZEROCOPY_COPIED)) { fprintf(stderr, "serr: was zerocopy instead of copy\n"); exit(EXIT_FAILURE); } }