xref: /dpdk/drivers/net/mlx5/linux/mlx5_socket.c (revision f484ffa1b15a71568a61a0ff8b722622ceac76a6)
1*f484ffa1SOphir Munk /* SPDX-License-Identifier: BSD-3-Clause
2*f484ffa1SOphir Munk  * Copyright 2019 Mellanox Technologies, Ltd
3*f484ffa1SOphir Munk  */
4*f484ffa1SOphir Munk 
5*f484ffa1SOphir Munk #ifndef _GNU_SOURCE
6*f484ffa1SOphir Munk #define _GNU_SOURCE
7*f484ffa1SOphir Munk #endif
8*f484ffa1SOphir Munk 
9*f484ffa1SOphir Munk #include <sys/types.h>
10*f484ffa1SOphir Munk #include <sys/socket.h>
11*f484ffa1SOphir Munk #include <sys/un.h>
12*f484ffa1SOphir Munk #include <fcntl.h>
13*f484ffa1SOphir Munk #include <stdio.h>
14*f484ffa1SOphir Munk #include <unistd.h>
15*f484ffa1SOphir Munk #include <sys/stat.h>
16*f484ffa1SOphir Munk 
17*f484ffa1SOphir Munk #include "rte_eal.h"
18*f484ffa1SOphir Munk #include "mlx5_utils.h"
19*f484ffa1SOphir Munk #include "mlx5.h"
20*f484ffa1SOphir Munk 
21*f484ffa1SOphir Munk /* PMD socket service for tools. */
22*f484ffa1SOphir Munk 
23*f484ffa1SOphir Munk int server_socket; /* Unix socket for primary process. */
24*f484ffa1SOphir Munk struct rte_intr_handle server_intr_handle; /* Interrupt handler. */
25*f484ffa1SOphir Munk 
26*f484ffa1SOphir Munk static void
27*f484ffa1SOphir Munk mlx5_pmd_make_path(struct sockaddr_un *addr, int pid)
28*f484ffa1SOphir Munk {
29*f484ffa1SOphir Munk 	snprintf(addr->sun_path, sizeof(addr->sun_path), "/var/tmp/dpdk_%s_%d",
30*f484ffa1SOphir Munk 		 MLX5_DRIVER_NAME, pid);
31*f484ffa1SOphir Munk }
32*f484ffa1SOphir Munk 
33*f484ffa1SOphir Munk /**
34*f484ffa1SOphir Munk  * Handle server pmd socket interrupts.
35*f484ffa1SOphir Munk  */
36*f484ffa1SOphir Munk static void
37*f484ffa1SOphir Munk mlx5_pmd_socket_handle(void *cb __rte_unused)
38*f484ffa1SOphir Munk {
39*f484ffa1SOphir Munk 	int conn_sock;
40*f484ffa1SOphir Munk 	int ret;
41*f484ffa1SOphir Munk 	struct cmsghdr *cmsg = NULL;
42*f484ffa1SOphir Munk 	int data;
43*f484ffa1SOphir Munk 	char buf[CMSG_SPACE(sizeof(int))] = { 0 };
44*f484ffa1SOphir Munk 	struct iovec io = {
45*f484ffa1SOphir Munk 		.iov_base = &data,
46*f484ffa1SOphir Munk 		.iov_len = sizeof(data),
47*f484ffa1SOphir Munk 	};
48*f484ffa1SOphir Munk 	struct msghdr msg = {
49*f484ffa1SOphir Munk 		.msg_iov = &io,
50*f484ffa1SOphir Munk 		.msg_iovlen = 1,
51*f484ffa1SOphir Munk 		.msg_control = buf,
52*f484ffa1SOphir Munk 		.msg_controllen = sizeof(buf),
53*f484ffa1SOphir Munk 	};
54*f484ffa1SOphir Munk 	uint16_t port_id;
55*f484ffa1SOphir Munk 	int fd;
56*f484ffa1SOphir Munk 	FILE *file = NULL;
57*f484ffa1SOphir Munk 	struct rte_eth_dev *dev;
58*f484ffa1SOphir Munk 
59*f484ffa1SOphir Munk 	/* Accept the connection from the client. */
60*f484ffa1SOphir Munk 	conn_sock = accept(server_socket, NULL, NULL);
61*f484ffa1SOphir Munk 	if (conn_sock < 0) {
62*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "connection failed: %s", strerror(errno));
63*f484ffa1SOphir Munk 		return;
64*f484ffa1SOphir Munk 	}
65*f484ffa1SOphir Munk 	ret = recvmsg(conn_sock, &msg, MSG_WAITALL);
66*f484ffa1SOphir Munk 	if (ret < 0) {
67*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "wrong message received: %s",
68*f484ffa1SOphir Munk 			strerror(errno));
69*f484ffa1SOphir Munk 		goto error;
70*f484ffa1SOphir Munk 	}
71*f484ffa1SOphir Munk 	/* Receive file descriptor. */
72*f484ffa1SOphir Munk 	cmsg = CMSG_FIRSTHDR(&msg);
73*f484ffa1SOphir Munk 	if (cmsg == NULL || cmsg->cmsg_type != SCM_RIGHTS ||
74*f484ffa1SOphir Munk 	    cmsg->cmsg_len < sizeof(int)) {
75*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "invalid file descriptor message");
76*f484ffa1SOphir Munk 		goto error;
77*f484ffa1SOphir Munk 	}
78*f484ffa1SOphir Munk 	memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
79*f484ffa1SOphir Munk 	file = fdopen(fd, "w");
80*f484ffa1SOphir Munk 	if (!file) {
81*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "Failed to open file");
82*f484ffa1SOphir Munk 		goto error;
83*f484ffa1SOphir Munk 	}
84*f484ffa1SOphir Munk 	/* Receive port number. */
85*f484ffa1SOphir Munk 	if (msg.msg_iovlen != 1 || msg.msg_iov->iov_len < sizeof(uint16_t)) {
86*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "wrong port number message");
87*f484ffa1SOphir Munk 		goto error;
88*f484ffa1SOphir Munk 	}
89*f484ffa1SOphir Munk 	memcpy(&port_id, msg.msg_iov->iov_base, sizeof(port_id));
90*f484ffa1SOphir Munk 	if (!rte_eth_dev_is_valid_port(port_id)) {
91*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "Invalid port %u", port_id);
92*f484ffa1SOphir Munk 		goto error;
93*f484ffa1SOphir Munk 	}
94*f484ffa1SOphir Munk 	/* Dump flow. */
95*f484ffa1SOphir Munk 	dev = &rte_eth_devices[port_id];
96*f484ffa1SOphir Munk 	ret = mlx5_flow_dev_dump(dev, file, NULL);
97*f484ffa1SOphir Munk 	/* Set-up the ancillary data and reply. */
98*f484ffa1SOphir Munk 	msg.msg_controllen = 0;
99*f484ffa1SOphir Munk 	msg.msg_control = NULL;
100*f484ffa1SOphir Munk 	msg.msg_iovlen = 1;
101*f484ffa1SOphir Munk 	msg.msg_iov = &io;
102*f484ffa1SOphir Munk 	data = -ret;
103*f484ffa1SOphir Munk 	io.iov_len = sizeof(data);
104*f484ffa1SOphir Munk 	io.iov_base = &data;
105*f484ffa1SOphir Munk 	do {
106*f484ffa1SOphir Munk 		ret = sendmsg(conn_sock, &msg, 0);
107*f484ffa1SOphir Munk 	} while (ret < 0 && errno == EINTR);
108*f484ffa1SOphir Munk 	if (ret < 0)
109*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "failed to send response %s",
110*f484ffa1SOphir Munk 			strerror(errno));
111*f484ffa1SOphir Munk error:
112*f484ffa1SOphir Munk 	if (conn_sock >= 0)
113*f484ffa1SOphir Munk 		close(conn_sock);
114*f484ffa1SOphir Munk 	if (file)
115*f484ffa1SOphir Munk 		fclose(file);
116*f484ffa1SOphir Munk }
117*f484ffa1SOphir Munk 
118*f484ffa1SOphir Munk /**
119*f484ffa1SOphir Munk  * Install interrupt handler.
120*f484ffa1SOphir Munk  *
121*f484ffa1SOphir Munk  * @param dev
122*f484ffa1SOphir Munk  *   Pointer to Ethernet device.
123*f484ffa1SOphir Munk  * @return
124*f484ffa1SOphir Munk  *   0 on success, a negative errno value otherwise.
125*f484ffa1SOphir Munk  */
126*f484ffa1SOphir Munk static int
127*f484ffa1SOphir Munk mlx5_pmd_interrupt_handler_install(void)
128*f484ffa1SOphir Munk {
129*f484ffa1SOphir Munk 	MLX5_ASSERT(server_socket);
130*f484ffa1SOphir Munk 	server_intr_handle.fd = server_socket;
131*f484ffa1SOphir Munk 	server_intr_handle.type = RTE_INTR_HANDLE_EXT;
132*f484ffa1SOphir Munk 	return rte_intr_callback_register(&server_intr_handle,
133*f484ffa1SOphir Munk 					  mlx5_pmd_socket_handle, NULL);
134*f484ffa1SOphir Munk }
135*f484ffa1SOphir Munk 
136*f484ffa1SOphir Munk /**
137*f484ffa1SOphir Munk  * Uninstall interrupt handler.
138*f484ffa1SOphir Munk  */
139*f484ffa1SOphir Munk static void
140*f484ffa1SOphir Munk mlx5_pmd_interrupt_handler_uninstall(void)
141*f484ffa1SOphir Munk {
142*f484ffa1SOphir Munk 	if (server_socket) {
143*f484ffa1SOphir Munk 		mlx5_intr_callback_unregister(&server_intr_handle,
144*f484ffa1SOphir Munk 					      mlx5_pmd_socket_handle,
145*f484ffa1SOphir Munk 					      NULL);
146*f484ffa1SOphir Munk 	}
147*f484ffa1SOphir Munk 	server_intr_handle.fd = 0;
148*f484ffa1SOphir Munk 	server_intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
149*f484ffa1SOphir Munk }
150*f484ffa1SOphir Munk 
151*f484ffa1SOphir Munk /**
152*f484ffa1SOphir Munk  * Initialise the socket to communicate with the secondary process
153*f484ffa1SOphir Munk  *
154*f484ffa1SOphir Munk  * @param[in] dev
155*f484ffa1SOphir Munk  *   Pointer to Ethernet device.
156*f484ffa1SOphir Munk  *
157*f484ffa1SOphir Munk  * @return
158*f484ffa1SOphir Munk  *   0 on success, a negative value otherwise.
159*f484ffa1SOphir Munk  */
160*f484ffa1SOphir Munk int
161*f484ffa1SOphir Munk mlx5_pmd_socket_init(void)
162*f484ffa1SOphir Munk {
163*f484ffa1SOphir Munk 	struct sockaddr_un sun = {
164*f484ffa1SOphir Munk 		.sun_family = AF_UNIX,
165*f484ffa1SOphir Munk 	};
166*f484ffa1SOphir Munk 	int ret;
167*f484ffa1SOphir Munk 	int flags;
168*f484ffa1SOphir Munk 
169*f484ffa1SOphir Munk 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
170*f484ffa1SOphir Munk 	if (server_socket)
171*f484ffa1SOphir Munk 		return 0;
172*f484ffa1SOphir Munk 	/*
173*f484ffa1SOphir Munk 	 * Initialize the socket to communicate with the secondary
174*f484ffa1SOphir Munk 	 * process.
175*f484ffa1SOphir Munk 	 */
176*f484ffa1SOphir Munk 	ret = socket(AF_UNIX, SOCK_STREAM, 0);
177*f484ffa1SOphir Munk 	if (ret < 0) {
178*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "Failed to open mlx5 socket: %s",
179*f484ffa1SOphir Munk 			strerror(errno));
180*f484ffa1SOphir Munk 		goto error;
181*f484ffa1SOphir Munk 	}
182*f484ffa1SOphir Munk 	server_socket = ret;
183*f484ffa1SOphir Munk 	flags = fcntl(server_socket, F_GETFL, 0);
184*f484ffa1SOphir Munk 	if (flags == -1)
185*f484ffa1SOphir Munk 		goto error;
186*f484ffa1SOphir Munk 	ret = fcntl(server_socket, F_SETFL, flags | O_NONBLOCK);
187*f484ffa1SOphir Munk 	if (ret < 0)
188*f484ffa1SOphir Munk 		goto error;
189*f484ffa1SOphir Munk 	mlx5_pmd_make_path(&sun, getpid());
190*f484ffa1SOphir Munk 	remove(sun.sun_path);
191*f484ffa1SOphir Munk 	ret = bind(server_socket, (const struct sockaddr *)&sun, sizeof(sun));
192*f484ffa1SOphir Munk 	if (ret < 0) {
193*f484ffa1SOphir Munk 		DRV_LOG(WARNING,
194*f484ffa1SOphir Munk 			"cannot bind mlx5 socket: %s", strerror(errno));
195*f484ffa1SOphir Munk 		goto close;
196*f484ffa1SOphir Munk 	}
197*f484ffa1SOphir Munk 	ret = listen(server_socket, 0);
198*f484ffa1SOphir Munk 	if (ret < 0) {
199*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "cannot listen on mlx5 socket: %s",
200*f484ffa1SOphir Munk 			strerror(errno));
201*f484ffa1SOphir Munk 		goto close;
202*f484ffa1SOphir Munk 	}
203*f484ffa1SOphir Munk 	if (mlx5_pmd_interrupt_handler_install()) {
204*f484ffa1SOphir Munk 		DRV_LOG(WARNING, "cannot register interrupt handler for mlx5 socket: %s",
205*f484ffa1SOphir Munk 			strerror(errno));
206*f484ffa1SOphir Munk 		goto close;
207*f484ffa1SOphir Munk 	}
208*f484ffa1SOphir Munk 	return 0;
209*f484ffa1SOphir Munk close:
210*f484ffa1SOphir Munk 	remove(sun.sun_path);
211*f484ffa1SOphir Munk error:
212*f484ffa1SOphir Munk 	claim_zero(close(server_socket));
213*f484ffa1SOphir Munk 	server_socket = 0;
214*f484ffa1SOphir Munk 	DRV_LOG(ERR, "Cannot initialize socket: %s", strerror(errno));
215*f484ffa1SOphir Munk 	return -errno;
216*f484ffa1SOphir Munk }
217*f484ffa1SOphir Munk 
218*f484ffa1SOphir Munk /**
219*f484ffa1SOphir Munk  * Un-Initialize the pmd socket
220*f484ffa1SOphir Munk  */
221*f484ffa1SOphir Munk RTE_FINI(mlx5_pmd_socket_uninit)
222*f484ffa1SOphir Munk {
223*f484ffa1SOphir Munk 	if (!server_socket)
224*f484ffa1SOphir Munk 		return;
225*f484ffa1SOphir Munk 	mlx5_pmd_interrupt_handler_uninstall();
226*f484ffa1SOphir Munk 	claim_zero(close(server_socket));
227*f484ffa1SOphir Munk 	server_socket = 0;
228*f484ffa1SOphir Munk 	MKSTR(path, "/var/tmp/dpdk_%s_%d", MLX5_DRIVER_NAME, getpid());
229*f484ffa1SOphir Munk 	claim_zero(remove(path));
230*f484ffa1SOphir Munk }
231