1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
8 #include <sys/socket.h>
16 #include "mlx5_utils.h"
19 * Initialise the socket to communicate with the secondary process
22 * Pointer to Ethernet device.
25 * 0 on success, a negative errno value otherwise and rte_errno is set.
28 mlx5_socket_init(struct rte_eth_dev *dev)
30 struct priv *priv = dev->data->dev_private;
31 struct sockaddr_un sun = {
32 .sun_family = AF_UNIX,
36 struct stat file_stat;
39 * Initialise the socket to communicate with the secondary
42 ret = socket(AF_UNIX, SOCK_STREAM, 0);
45 WARN("secondary process not supported: %s", strerror(errno));
48 priv->primary_socket = ret;
49 flags = fcntl(priv->primary_socket, F_GETFL, 0);
54 ret = fcntl(priv->primary_socket, F_SETFL, flags | O_NONBLOCK);
59 snprintf(sun.sun_path, sizeof(sun.sun_path), "/var/tmp/%s_%d",
60 MLX5_DRIVER_NAME, priv->primary_socket);
61 ret = stat(sun.sun_path, &file_stat);
63 claim_zero(remove(sun.sun_path));
64 ret = bind(priv->primary_socket, (const struct sockaddr *)&sun,
68 WARN("cannot bind socket, secondary process not supported: %s",
72 ret = listen(priv->primary_socket, 0);
75 WARN("Secondary process not supported: %s", strerror(errno));
82 claim_zero(close(priv->primary_socket));
83 priv->primary_socket = 0;
88 * Un-Initialise the socket to communicate with the secondary process
93 mlx5_socket_uninit(struct rte_eth_dev *dev)
95 struct priv *priv = dev->data->dev_private;
97 MKSTR(path, "/var/tmp/%s_%d", MLX5_DRIVER_NAME, priv->primary_socket);
98 claim_zero(close(priv->primary_socket));
99 priv->primary_socket = 0;
100 claim_zero(remove(path));
104 * Handle socket interrupts.
107 * Pointer to Ethernet device.
110 mlx5_socket_handle(struct rte_eth_dev *dev)
112 struct priv *priv = dev->data->dev_private;
115 struct cmsghdr *cmsg = NULL;
116 struct ucred *cred = NULL;
117 char buf[CMSG_SPACE(sizeof(struct ucred))] = { 0 };
118 char vbuf[1024] = { 0 };
121 .iov_len = sizeof(*vbuf),
123 struct msghdr msg = {
127 .msg_controllen = sizeof(buf),
131 /* Accept the connection from the client. */
132 conn_sock = accept(priv->primary_socket, NULL, NULL);
134 WARN("connection failed: %s", strerror(errno));
137 ret = setsockopt(conn_sock, SOL_SOCKET, SO_PASSCRED, &(int){1},
141 WARN("cannot change socket options: %s", strerror(rte_errno));
144 ret = recvmsg(conn_sock, &msg, MSG_WAITALL);
147 WARN("received an empty message: %s", strerror(rte_errno));
150 /* Expect to receive credentials only. */
151 cmsg = CMSG_FIRSTHDR(&msg);
156 if ((cmsg->cmsg_type == SCM_CREDENTIALS) &&
157 (cmsg->cmsg_len >= sizeof(*cred))) {
158 cred = (struct ucred *)CMSG_DATA(cmsg);
159 assert(cred != NULL);
161 cmsg = CMSG_NXTHDR(&msg, cmsg);
163 WARN("Message wrongly formatted");
166 /* Make sure all the ancillary data was received and valid. */
167 if ((cred == NULL) || (cred->uid != getuid()) ||
168 (cred->gid != getgid())) {
169 WARN("wrong credentials");
172 /* Set-up the ancillary data. */
173 cmsg = CMSG_FIRSTHDR(&msg);
174 assert(cmsg != NULL);
175 cmsg->cmsg_level = SOL_SOCKET;
176 cmsg->cmsg_type = SCM_RIGHTS;
177 cmsg->cmsg_len = CMSG_LEN(sizeof(priv->ctx->cmd_fd));
178 fd = (int *)CMSG_DATA(cmsg);
179 *fd = priv->ctx->cmd_fd;
180 ret = sendmsg(conn_sock, &msg, 0);
182 WARN("cannot send response");
188 * Connect to the primary process.
191 * Pointer to Ethernet structure.
194 * fd on success, negative errno value otherwise and rte_errno is set.
197 mlx5_socket_connect(struct rte_eth_dev *dev)
199 struct priv *priv = dev->data->dev_private;
200 struct sockaddr_un sun = {
201 .sun_family = AF_UNIX,
207 char buf[CMSG_SPACE(sizeof(*cred))] = { 0 };
208 char vbuf[1024] = { 0 };
211 .iov_len = sizeof(*vbuf),
213 struct msghdr msg = {
215 .msg_controllen = sizeof(buf),
219 struct cmsghdr *cmsg;
221 ret = socket(AF_UNIX, SOCK_STREAM, 0);
224 WARN("cannot connect to primary");
228 snprintf(sun.sun_path, sizeof(sun.sun_path), "/var/tmp/%s_%d",
229 MLX5_DRIVER_NAME, priv->primary_socket);
230 ret = connect(socket_fd, (const struct sockaddr *)&sun, sizeof(sun));
233 WARN("cannot connect to primary");
236 cmsg = CMSG_FIRSTHDR(&msg);
239 DEBUG("cannot get first message");
242 cmsg->cmsg_level = SOL_SOCKET;
243 cmsg->cmsg_type = SCM_CREDENTIALS;
244 cmsg->cmsg_len = CMSG_LEN(sizeof(*cred));
245 cred = (struct ucred *)CMSG_DATA(cmsg);
248 DEBUG("no credentials received");
251 cred->pid = getpid();
252 cred->uid = getuid();
253 cred->gid = getgid();
254 ret = sendmsg(socket_fd, &msg, MSG_DONTWAIT);
257 WARN("cannot send credentials to primary: %s",
261 ret = recvmsg(socket_fd, &msg, MSG_WAITALL);
264 WARN("no message from primary: %s", strerror(errno));
267 cmsg = CMSG_FIRSTHDR(&msg);
270 WARN("No file descriptor received");
273 fd = (int *)CMSG_DATA(cmsg);
275 WARN("no file descriptor received: %s", strerror(errno));