Commit 148a9ab0 authored by Tom Nabarro's avatar Tom Nabarro Committed by Jim Harris
Browse files

env/dpdk: retry SO_RCVBUF if SO_RCVBUFFORCE fails



PCI event module currently requires use of SO_RCVBUFFORCE socket option
which is restricted to CAP_NET_ADMIN. Retry with SO_RCVBUF for non-root
(unprivileged) processes where this capability is not available.

Return -ENOSPC if receive buffer is not of sufficient size.

Fixes issue #2224

Signed-off-by: default avatarTom Nabarro <tom.nabarro@intel.com>
Change-Id: I0bed1b1eac0c7e8601d3d172d8027380ec8be391
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10126


Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarDong Yi <dongx.yi@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent fded6f0d
Loading
Loading
Loading
Loading
+26 −10
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ spdk_pci_event_listen(void)
	struct sockaddr_nl addr;
	int netlink_fd;
	int size = SPDK_UEVENT_RECVBUF_SIZE;
	int buf_size;
	socklen_t opt_size;
	int flag, rc;

	memset(&addr, 0, sizeof(addr));
@@ -64,35 +66,49 @@ spdk_pci_event_listen(void)
	}

	if (setsockopt(netlink_fd, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size)) < 0) {
		if (setsockopt(netlink_fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) {
			rc = errno;
		SPDK_ERRLOG("Failed to set socket option\n");
		close(netlink_fd);
		return -rc;
			SPDK_ERRLOG("Failed to set socket option SO_RCVBUF\n");
			goto error;
		}
		opt_size = sizeof(buf_size);
		if (getsockopt(netlink_fd, SOL_SOCKET, SO_RCVBUF, &buf_size, &opt_size) < 0) {
			rc = errno;
			SPDK_ERRLOG("Failed to get socket option SO_RCVBUF\n");
			goto error;
		}
		if (buf_size < SPDK_UEVENT_RECVBUF_SIZE) {
			SPDK_ERRLOG("Socket recv buffer is too small (< %d), see SO_RCVBUF "
				    "section in socket(7) man page for specifics on how to "
				    "adjust the system setting.", SPDK_UEVENT_RECVBUF_SIZE);
			rc = ENOSPC;
			goto error;
		}
	}

	flag = fcntl(netlink_fd, F_GETFL);
	if (flag < 0) {
		rc = errno;
		SPDK_ERRLOG("Failed to get socket flag, fd: %d\n", netlink_fd);
		close(netlink_fd);
		return -rc;
		goto error;
	}

	if (fcntl(netlink_fd, F_SETFL, flag | O_NONBLOCK) < 0) {
		rc = errno;
		SPDK_ERRLOG("Fcntl can't set nonblocking mode for socket, fd: %d\n", netlink_fd);
		close(netlink_fd);
		return -rc;
		goto error;
	}

	if (bind(netlink_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
		rc = errno;
		SPDK_ERRLOG("Failed to bind the netlink\n");
		close(netlink_fd);
		return -rc;
		goto error;
	}

	return netlink_fd;
error:
	close(netlink_fd);
	return -rc;
}

/* Note: We parse the event from uio and vfio subsystem and will ignore