| // SPDX-License-Identifier: GPL-2.0-only | |
| /* Some common code for MSG_ZEROCOPY logic | |
| * | |
| * Copyright (C) 2023 SberDevices. | |
| * | |
| * Author: Arseniy Krasnov <avkrasnov@salutedevices.com> | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <sys/types.h> | |
| #include <sys/socket.h> | |
| #include <linux/errqueue.h> | |
| #include "msg_zerocopy_common.h" | |
| 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); | |
| } | |
| } |