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,
38 * Initialise the socket to communicate with the secondary
41 ret = socket(AF_UNIX, SOCK_STREAM, 0);
44 DRV_LOG(WARNING, "port %u secondary process not supported: %s",
45 dev->data->port_id, 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);
62 ret = bind(priv->primary_socket, (const struct sockaddr *)&sun,
67 "port %u cannot bind socket, secondary process not"
69 dev->data->port_id, strerror(errno));
72 ret = listen(priv->primary_socket, 0);
75 DRV_LOG(WARNING, "port %u secondary process not supported: %s",
76 dev->data->port_id, strerror(errno));
83 claim_zero(close(priv->primary_socket));
84 priv->primary_socket = 0;
89 * Un-Initialise the socket to communicate with the secondary process
94 mlx5_socket_uninit(struct rte_eth_dev *dev)
96 struct priv *priv = dev->data->dev_private;
98 MKSTR(path, "/var/tmp/%s_%d", MLX5_DRIVER_NAME, priv->primary_socket);
99 claim_zero(close(priv->primary_socket));
100 priv->primary_socket = 0;
101 claim_zero(remove(path));
105 * Handle socket interrupts.
108 * Pointer to Ethernet device.
111 mlx5_socket_handle(struct rte_eth_dev *dev)
113 struct priv *priv = dev->data->dev_private;
116 struct cmsghdr *cmsg = NULL;
117 struct ucred *cred = NULL;
118 char buf[CMSG_SPACE(sizeof(struct ucred))] = { 0 };
119 char vbuf[1024] = { 0 };
122 .iov_len = sizeof(*vbuf),
124 struct msghdr msg = {
128 .msg_controllen = sizeof(buf),
132 /* Accept the connection from the client. */
133 conn_sock = accept(priv->primary_socket, NULL, NULL);
135 DRV_LOG(WARNING, "port %u connection failed: %s",
136 dev->data->port_id, strerror(errno));
139 ret = setsockopt(conn_sock, SOL_SOCKET, SO_PASSCRED, &(int){1},
143 DRV_LOG(WARNING, "port %u cannot change socket options: %s",
144 dev->data->port_id, strerror(rte_errno));
147 ret = recvmsg(conn_sock, &msg, MSG_WAITALL);
150 DRV_LOG(WARNING, "port %u received an empty message: %s",
151 dev->data->port_id, strerror(rte_errno));
154 /* Expect to receive credentials only. */
155 cmsg = CMSG_FIRSTHDR(&msg);
157 DRV_LOG(WARNING, "port %u no message", dev->data->port_id);
160 if ((cmsg->cmsg_type == SCM_CREDENTIALS) &&
161 (cmsg->cmsg_len >= sizeof(*cred))) {
162 cred = (struct ucred *)CMSG_DATA(cmsg);
163 assert(cred != NULL);
165 cmsg = CMSG_NXTHDR(&msg, cmsg);
167 DRV_LOG(WARNING, "port %u message wrongly formatted",
171 /* Make sure all the ancillary data was received and valid. */
172 if ((cred == NULL) || (cred->uid != getuid()) ||
173 (cred->gid != getgid())) {
174 DRV_LOG(WARNING, "port %u wrong credentials",
178 /* Set-up the ancillary data. */
179 cmsg = CMSG_FIRSTHDR(&msg);
180 assert(cmsg != NULL);
181 cmsg->cmsg_level = SOL_SOCKET;
182 cmsg->cmsg_type = SCM_RIGHTS;
183 cmsg->cmsg_len = CMSG_LEN(sizeof(priv->ctx->cmd_fd));
184 fd = (int *)CMSG_DATA(cmsg);
185 *fd = priv->ctx->cmd_fd;
186 ret = sendmsg(conn_sock, &msg, 0);
188 DRV_LOG(WARNING, "port %u cannot send response",
195 * Connect to the primary process.
198 * Pointer to Ethernet structure.
201 * fd on success, negative errno value otherwise and rte_errno is set.
204 mlx5_socket_connect(struct rte_eth_dev *dev)
206 struct priv *priv = dev->data->dev_private;
207 struct sockaddr_un sun = {
208 .sun_family = AF_UNIX,
214 char buf[CMSG_SPACE(sizeof(*cred))] = { 0 };
215 char vbuf[1024] = { 0 };
218 .iov_len = sizeof(*vbuf),
220 struct msghdr msg = {
222 .msg_controllen = sizeof(buf),
226 struct cmsghdr *cmsg;
228 ret = socket(AF_UNIX, SOCK_STREAM, 0);
231 DRV_LOG(WARNING, "port %u cannot connect to primary",
236 snprintf(sun.sun_path, sizeof(sun.sun_path), "/var/tmp/%s_%d",
237 MLX5_DRIVER_NAME, priv->primary_socket);
238 ret = connect(socket_fd, (const struct sockaddr *)&sun, sizeof(sun));
241 DRV_LOG(WARNING, "port %u cannot connect to primary",
245 cmsg = CMSG_FIRSTHDR(&msg);
248 DRV_LOG(DEBUG, "port %u cannot get first message",
252 cmsg->cmsg_level = SOL_SOCKET;
253 cmsg->cmsg_type = SCM_CREDENTIALS;
254 cmsg->cmsg_len = CMSG_LEN(sizeof(*cred));
255 cred = (struct ucred *)CMSG_DATA(cmsg);
258 DRV_LOG(DEBUG, "port %u no credentials received",
262 cred->pid = getpid();
263 cred->uid = getuid();
264 cred->gid = getgid();
265 ret = sendmsg(socket_fd, &msg, MSG_DONTWAIT);
269 "port %u cannot send credentials to primary: %s",
270 dev->data->port_id, strerror(errno));
273 ret = recvmsg(socket_fd, &msg, MSG_WAITALL);
276 DRV_LOG(WARNING, "port %u no message from primary: %s",
277 dev->data->port_id, strerror(errno));
280 cmsg = CMSG_FIRSTHDR(&msg);
283 DRV_LOG(WARNING, "port %u no file descriptor received",
287 fd = (int *)CMSG_DATA(cmsg);
289 DRV_LOG(WARNING, "port %u no file descriptor received: %s",
290 dev->data->port_id, strerror(errno));