xref: /dpdk/drivers/net/cnxk/cnxk_rep_msg.c (revision 30d38a718b9f63f0bda9e24dae90486303f1b206)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2024 Marvell.
3  */
4 
5 #include <cnxk_rep.h>
6 #include <cnxk_rep_msg.h>
7 
8 #define CTRL_MSG_RCV_TIMEOUT_MS 2000
9 #define CTRL_MSG_READY_WAIT_US	2000
10 #define CTRL_MSG_THRD_NAME_LEN	35
11 #define CTRL_MSG_BUFFER_SZ	1500
12 #define CTRL_MSG_SIGNATURE	0xcdacdeadbeefcadc
13 
14 static void
close_socket(int fd)15 close_socket(int fd)
16 {
17 	close(fd);
18 	unlink(CNXK_ESWITCH_CTRL_MSG_SOCK_PATH);
19 }
20 
21 static int
receive_control_message(int socketfd,void * data,uint32_t len)22 receive_control_message(int socketfd, void *data, uint32_t len)
23 {
24 	char ctl[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred))] = {0};
25 	struct ucred *cr __rte_unused;
26 	struct msghdr mh = {0};
27 	struct cmsghdr *cmsg;
28 	static uint64_t rec;
29 	struct iovec iov[1];
30 	ssize_t size;
31 	int afd = -1;
32 
33 	iov[0].iov_base = data;
34 	iov[0].iov_len = len;
35 	mh.msg_iov = iov;
36 	mh.msg_iovlen = 1;
37 	mh.msg_control = ctl;
38 	mh.msg_controllen = sizeof(ctl);
39 
40 	size = recvmsg(socketfd, &mh, MSG_DONTWAIT);
41 	if (size < 0) {
42 		if (errno == EAGAIN)
43 			return 0;
44 		plt_err("recvmsg err %d size %zu", errno, size);
45 		return -errno;
46 	} else if (size == 0) {
47 		return 0;
48 	}
49 
50 	rec++;
51 	plt_rep_dbg("Packet %" PRId64 " Received %" PRId64 " bytes over socketfd %d",
52 		    rec, size, socketfd);
53 
54 	cr = 0;
55 	cmsg = CMSG_FIRSTHDR(&mh);
56 	while (cmsg) {
57 		if (cmsg->cmsg_level == SOL_SOCKET) {
58 			if (cmsg->cmsg_type == SCM_CREDENTIALS) {
59 				cr = (struct ucred *)CMSG_DATA(cmsg);
60 			} else if (cmsg->cmsg_type == SCM_RIGHTS) {
61 				rte_memcpy(&afd, CMSG_DATA(cmsg), sizeof(int));
62 				plt_rep_dbg("afd %d", afd);
63 			}
64 		}
65 		cmsg = CMSG_NXTHDR(&mh, cmsg);
66 	}
67 	return size;
68 }
69 
70 static int
send_message_on_socket(int socketfd,void * data,uint32_t len,int afd)71 send_message_on_socket(int socketfd, void *data, uint32_t len, int afd)
72 {
73 	char ctl[CMSG_SPACE(sizeof(int))];
74 	struct msghdr mh = {0};
75 	struct cmsghdr *cmsg;
76 	static uint64_t sent;
77 	struct iovec iov[1];
78 	int size;
79 
80 	iov[0].iov_base = data;
81 	iov[0].iov_len = len;
82 	mh.msg_iov = iov;
83 	mh.msg_iovlen = 1;
84 
85 	if (afd > 0) {
86 		memset(&ctl, 0, sizeof(ctl));
87 		mh.msg_control = ctl;
88 		mh.msg_controllen = sizeof(ctl);
89 		cmsg = CMSG_FIRSTHDR(&mh);
90 		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
91 		cmsg->cmsg_level = SOL_SOCKET;
92 		cmsg->cmsg_type = SCM_RIGHTS;
93 		rte_memcpy(CMSG_DATA(cmsg), &afd, sizeof(int));
94 	}
95 
96 	size = sendmsg(socketfd, &mh, MSG_DONTWAIT);
97 	if (size < 0) {
98 		if (errno == EAGAIN)
99 			return 0;
100 		plt_err("Failed to send message, err %d", -errno);
101 		return -errno;
102 	} else if (size == 0) {
103 		return 0;
104 	}
105 	sent++;
106 	plt_rep_dbg("Sent %" PRId64 " packets of size %d on socketfd %d", sent, size, socketfd);
107 
108 	return size;
109 }
110 
111 static int
open_socket_ctrl_channel(void)112 open_socket_ctrl_channel(void)
113 {
114 	struct sockaddr_un un;
115 	int sock_fd;
116 
117 	sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
118 	if (sock_fd < 0) {
119 		plt_err("Failed to create unix socket");
120 		return -1;
121 	}
122 
123 	/* Set unix socket path and bind */
124 	memset(&un, 0, sizeof(un));
125 	un.sun_family = AF_UNIX;
126 
127 	if (strlen(CNXK_ESWITCH_CTRL_MSG_SOCK_PATH) > sizeof(un.sun_path) - 1) {
128 		plt_err("Server socket path too long: %s", CNXK_ESWITCH_CTRL_MSG_SOCK_PATH);
129 		close(sock_fd);
130 		return -E2BIG;
131 	}
132 
133 	if (remove(CNXK_ESWITCH_CTRL_MSG_SOCK_PATH) == -1 && errno != ENOENT) {
134 		plt_err("remove-%s", CNXK_ESWITCH_CTRL_MSG_SOCK_PATH);
135 		close(sock_fd);
136 		return -errno;
137 	}
138 
139 	memset(&un, 0, sizeof(struct sockaddr_un));
140 	un.sun_family = AF_UNIX;
141 	strncpy(un.sun_path, CNXK_ESWITCH_CTRL_MSG_SOCK_PATH, sizeof(un.sun_path) - 1);
142 
143 	if (bind(sock_fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
144 		plt_err("Failed to bind %s: %s", un.sun_path, strerror(errno));
145 		close(sock_fd);
146 		return -errno;
147 	}
148 
149 	if (listen(sock_fd, 1) < 0) {
150 		plt_err("Failed to listen, err %s", strerror(errno));
151 		close(sock_fd);
152 		return -errno;
153 	}
154 
155 	plt_rep_dbg("Unix socket path %s", un.sun_path);
156 	return sock_fd;
157 }
158 
159 static int
send_control_message(struct cnxk_eswitch_dev * eswitch_dev,void * buffer,uint32_t len)160 send_control_message(struct cnxk_eswitch_dev *eswitch_dev, void *buffer, uint32_t len)
161 {
162 	int sz;
163 	int rc = 0;
164 
165 	sz = send_message_on_socket(eswitch_dev->sock_fd, buffer, len, 0);
166 	if (sz < 0) {
167 		plt_err("Error sending message, err %d", sz);
168 		rc = sz;
169 		goto done;
170 	}
171 
172 	/* Ensuring entire message has been processed */
173 	if (sz != (int)len) {
174 		plt_err("Out of %d bytes only %d bytes sent", sz, len);
175 		rc = -EFAULT;
176 		goto done;
177 	}
178 	plt_rep_dbg("Sent %d bytes of buffer", sz);
179 done:
180 	return rc;
181 }
182 
183 void
cnxk_rep_msg_populate_msg_end(void * buffer,uint32_t * length)184 cnxk_rep_msg_populate_msg_end(void *buffer, uint32_t *length)
185 {
186 	cnxk_rep_msg_populate_command(buffer, length, CNXK_REP_MSG_END, 0);
187 }
188 
189 void
cnxk_rep_msg_populate_type(void * buffer,uint32_t * length,cnxk_type_t type,uint32_t sz)190 cnxk_rep_msg_populate_type(void *buffer, uint32_t *length, cnxk_type_t type, uint32_t sz)
191 {
192 	uint32_t len = *length;
193 	cnxk_type_data_t data;
194 
195 	memset(&data, 0, sizeof(cnxk_type_data_t));
196 	/* Prepare type data */
197 	data.type = type;
198 	data.length = sz;
199 
200 	/* Populate the type data */
201 	rte_memcpy(RTE_PTR_ADD(buffer, len), &data, sizeof(cnxk_type_data_t));
202 	len += sizeof(cnxk_type_data_t);
203 
204 	*length = len;
205 }
206 
207 void
cnxk_rep_msg_populate_header(void * buffer,uint32_t * length)208 cnxk_rep_msg_populate_header(void *buffer, uint32_t *length)
209 {
210 	cnxk_header_t hdr;
211 	int len;
212 
213 	cnxk_rep_msg_populate_type(buffer, length, CNXK_TYPE_HEADER, sizeof(cnxk_header_t));
214 
215 	memset(&hdr, 0, sizeof(cnxk_header_t));
216 	len = *length;
217 	/* Prepare header data */
218 	hdr.signature = CTRL_MSG_SIGNATURE;
219 
220 	/* Populate header data */
221 	rte_memcpy(RTE_PTR_ADD(buffer, len), &hdr, sizeof(cnxk_header_t));
222 	len += sizeof(cnxk_header_t);
223 
224 	*length = len;
225 }
226 
227 void
cnxk_rep_msg_populate_command(void * buffer,uint32_t * length,cnxk_rep_msg_t type,uint32_t size)228 cnxk_rep_msg_populate_command(void *buffer, uint32_t *length, cnxk_rep_msg_t type, uint32_t size)
229 {
230 	cnxk_rep_msg_data_t msg_data;
231 	uint32_t len;
232 	uint16_t sz = sizeof(cnxk_rep_msg_data_t);
233 
234 	memset(&msg_data, 0, sz);
235 	cnxk_rep_msg_populate_type(buffer, length, CNXK_TYPE_MSG, sz);
236 
237 	len = *length;
238 	/* Prepare command data */
239 	msg_data.type = type;
240 	msg_data.length = size;
241 
242 	/* Populate the command */
243 	rte_memcpy(RTE_PTR_ADD(buffer, len), &msg_data, sz);
244 	len += sz;
245 
246 	*length = len;
247 }
248 
249 void
cnxk_rep_msg_populate_command_meta(void * buffer,uint32_t * length,void * msg_meta,uint32_t sz,cnxk_rep_msg_t msg)250 cnxk_rep_msg_populate_command_meta(void *buffer, uint32_t *length, void *msg_meta, uint32_t sz,
251 				   cnxk_rep_msg_t msg)
252 {
253 	uint32_t len;
254 
255 	cnxk_rep_msg_populate_command(buffer, length, msg, sz);
256 
257 	len = *length;
258 	/* Populate command data */
259 	rte_memcpy(RTE_PTR_ADD(buffer, len), msg_meta, sz);
260 	len += sz;
261 
262 	*length = len;
263 }
264 
265 static int
parse_validate_header(void * msg_buf,uint32_t * buf_trav_len)266 parse_validate_header(void *msg_buf, uint32_t *buf_trav_len)
267 {
268 	cnxk_type_data_t *tdata = NULL;
269 	cnxk_header_t *hdr = NULL;
270 	void *data = NULL;
271 	uint16_t len = 0;
272 
273 	/* Read first bytes of type data */
274 	data = msg_buf;
275 	tdata = (cnxk_type_data_t *)data;
276 	if (tdata->type != CNXK_TYPE_HEADER) {
277 		plt_err("Invalid type %d, type header expected", tdata->type);
278 		goto fail;
279 	}
280 
281 	/* Get the header value */
282 	data = RTE_PTR_ADD(msg_buf, sizeof(cnxk_type_data_t));
283 	len += sizeof(cnxk_type_data_t);
284 
285 	/* Validate the header */
286 	hdr = (cnxk_header_t *)data;
287 	if (hdr->signature != CTRL_MSG_SIGNATURE) {
288 		plt_err("Invalid signature %" PRIu64 " detected", hdr->signature);
289 		goto fail;
290 	}
291 
292 	/* Update length read till point */
293 	len += tdata->length;
294 
295 	*buf_trav_len = len;
296 	return 0;
297 fail:
298 	return errno;
299 }
300 
301 static cnxk_rep_msg_data_t *
message_data_extract(void * msg_buf,uint32_t * buf_trav_len)302 message_data_extract(void *msg_buf, uint32_t *buf_trav_len)
303 {
304 	cnxk_type_data_t *tdata = NULL;
305 	cnxk_rep_msg_data_t *msg = NULL;
306 	uint16_t len = *buf_trav_len;
307 	void *data;
308 
309 	tdata = (cnxk_type_data_t *)RTE_PTR_ADD(msg_buf, len);
310 	if (tdata->type != CNXK_TYPE_MSG) {
311 		plt_err("Invalid type %d, type MSG expected", tdata->type);
312 		goto fail;
313 	}
314 
315 	/* Get the message type */
316 	len += sizeof(cnxk_type_data_t);
317 	data = RTE_PTR_ADD(msg_buf, len);
318 	msg = (cnxk_rep_msg_data_t *)data;
319 
320 	/* Advance to actual message data */
321 	len += tdata->length;
322 	*buf_trav_len = len;
323 
324 	return msg;
325 fail:
326 	return NULL;
327 }
328 
329 static void
process_ack_message(void * msg_buf,uint32_t * buf_trav_len,uint32_t msg_len,void * data)330 process_ack_message(void *msg_buf, uint32_t *buf_trav_len, uint32_t msg_len, void *data)
331 {
332 	cnxk_rep_msg_ack_data_t *adata = (cnxk_rep_msg_ack_data_t *)data;
333 	uint16_t len = *buf_trav_len;
334 	void *buf;
335 
336 	/* Get the message type data viz ack data */
337 	buf = RTE_PTR_ADD(msg_buf, len);
338 	adata->u.data = rte_zmalloc("Ack data", msg_len, 0);
339 	adata->size = msg_len;
340 	if (adata->size == sizeof(uint64_t))
341 		rte_memcpy(&adata->u.data, buf, msg_len);
342 	else
343 		rte_memcpy(adata->u.data, buf, msg_len);
344 	plt_rep_dbg("Address %p val 0x%" PRIu64 " sval %" PRId64 " msg_len %d",
345 		    adata->u.data, adata->u.val, adata->u.sval, msg_len);
346 
347 	/* Advance length to nex message */
348 	len += msg_len;
349 	*buf_trav_len = len;
350 }
351 
352 static int
notify_rep_dev_ready(cnxk_rep_msg_ready_data_t * rdata,void * data,cnxk_rep_msg_ack_data1_t ** padata)353 notify_rep_dev_ready(cnxk_rep_msg_ready_data_t *rdata, void *data,
354 		     cnxk_rep_msg_ack_data1_t **padata)
355 {
356 	struct cnxk_eswitch_dev *eswitch_dev;
357 	uint64_t rep_id_arr[RTE_MAX_ETHPORTS];
358 	cnxk_rep_msg_ack_data1_t *adata;
359 	uint16_t rep_id, sz, total_sz;
360 	int rc, i, j = 0;
361 
362 	PLT_SET_USED(data);
363 	eswitch_dev = cnxk_eswitch_pmd_priv();
364 	if (!eswitch_dev) {
365 		plt_err("Failed to get PF ethdev handle");
366 		rc = -EINVAL;
367 		goto fail;
368 	}
369 
370 	memset(rep_id_arr, 0, RTE_MAX_ETHPORTS * sizeof(uint64_t));
371 	/* For ready state */
372 	if (rdata->nb_ports > eswitch_dev->repr_cnt.nb_repr_probed) {
373 		rc = CNXK_REP_CTRL_MSG_NACK_INV_REP_CNT;
374 		goto fail;
375 	}
376 
377 	for (i = 0; i < rdata->nb_ports; i++) {
378 		rep_id = UINT16_MAX;
379 		rc = cnxk_rep_state_update(eswitch_dev, rdata->data[i], &rep_id);
380 		if (rc) {
381 			rc = CNXK_REP_CTRL_MSG_NACK_REP_STAT_UP_FAIL;
382 			goto fail;
383 		}
384 		if (rep_id != UINT16_MAX)
385 			rep_id_arr[j++] = rep_id;
386 	}
387 
388 	/* Send Rep Id array to companian app */
389 	sz = j * sizeof(uint64_t);
390 	total_sz = sizeof(cnxk_rep_msg_ack_data1_t) + sz;
391 	adata = plt_zmalloc(total_sz, 0);
392 	rte_memcpy(adata->data, rep_id_arr, sz);
393 	adata->size = sz;
394 	*padata = adata;
395 
396 	plt_rep_dbg("Installing NPC rules for Eswitch VF");
397 	/* Install RX VLAN rule for eswitch VF */
398 	if (!eswitch_dev->eswitch_vf_rules_setup) {
399 		rc = cnxk_eswitch_pfvf_flow_rules_install(eswitch_dev, true);
400 		if (rc) {
401 			plt_err("Failed to install rxtx rules, rc %d", rc);
402 			goto fail;
403 		}
404 
405 		/* Configure TPID for Eswitch PF LFs */
406 		rc = roc_eswitch_nix_vlan_tpid_set(&eswitch_dev->nix, ROC_NIX_VLAN_TYPE_OUTER,
407 						   CNXK_ESWITCH_VLAN_TPID, true);
408 		if (rc) {
409 			plt_err("Failed to configure tpid, rc %d", rc);
410 			goto fail;
411 		}
412 		eswitch_dev->eswitch_vf_rules_setup = true;
413 	}
414 
415 	return 0;
416 fail:
417 	sz = sizeof(cnxk_rep_msg_ack_data1_t) + sizeof(uint64_t);
418 	adata = plt_zmalloc(sz, 0);
419 	adata->data[0] = rc;
420 	adata->size = sizeof(uint64_t);
421 	*padata = adata;
422 
423 	return rc;
424 }
425 
426 static int
process_ready_message(void * msg_buf,uint32_t * buf_trav_len,uint32_t msg_len,void * data,cnxk_rep_msg_ack_data1_t ** padata)427 process_ready_message(void *msg_buf, uint32_t *buf_trav_len, uint32_t msg_len, void *data,
428 		      cnxk_rep_msg_ack_data1_t **padata)
429 {
430 	cnxk_rep_msg_ready_data_t *rdata = NULL;
431 	cnxk_rep_msg_ack_data1_t *adata;
432 	uint16_t len = *buf_trav_len;
433 	void *buf;
434 	int rc = 0, sz;
435 
436 	/* Get the message type data viz ready data */
437 	buf = RTE_PTR_ADD(msg_buf, len);
438 	rdata = (cnxk_rep_msg_ready_data_t *)buf;
439 
440 	plt_rep_dbg("Ready data received %d, nb_ports %d", rdata->val, rdata->nb_ports);
441 
442 	/* Wait required to ensure other side ready for receiving the ack */
443 	usleep(CTRL_MSG_READY_WAIT_US);
444 
445 	/* Update all representor about ready message */
446 	if (rdata->val) {
447 		rc = notify_rep_dev_ready(rdata, data, padata);
448 	} else {
449 		sz = sizeof(cnxk_rep_msg_ack_data1_t) + sizeof(uint64_t);
450 		adata = plt_zmalloc(sz, 0);
451 		adata->data[0] = CNXK_REP_CTRL_MSG_NACK_INV_RDY_DATA;
452 		adata->size = sizeof(uint64_t);
453 		*padata = adata;
454 	}
455 
456 	/* Advance length to nex message */
457 	len += msg_len;
458 	*buf_trav_len = len;
459 
460 	return rc;
461 }
462 
463 static int
notify_rep_dev_exit(cnxk_rep_msg_exit_data_t * edata,void * data)464 notify_rep_dev_exit(cnxk_rep_msg_exit_data_t *edata, void *data)
465 {
466 	struct cnxk_eswitch_dev *eswitch_dev;
467 	struct cnxk_rep_dev *rep_dev = NULL;
468 	struct rte_eth_dev *rep_eth_dev;
469 	int i, rc = 0;
470 
471 	PLT_SET_USED(data);
472 	eswitch_dev = cnxk_eswitch_pmd_priv();
473 	if (!eswitch_dev) {
474 		plt_err("Failed to get PF ethdev handle");
475 		rc = -EINVAL;
476 		goto fail;
477 	}
478 	if (edata->nb_ports > eswitch_dev->repr_cnt.nb_repr_probed) {
479 		rc = CNXK_REP_CTRL_MSG_NACK_INV_REP_CNT;
480 		goto fail;
481 	}
482 
483 	for (i = 0; i < eswitch_dev->repr_cnt.nb_repr_probed; i++) {
484 		rep_eth_dev = eswitch_dev->rep_info[i].rep_eth_dev;
485 		if (!rep_eth_dev) {
486 			plt_err("Failed to get rep ethdev handle");
487 			rc = -EINVAL;
488 			goto fail;
489 		}
490 
491 		rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
492 		if (!rep_dev->native_repte)
493 			rep_dev->is_vf_active = false;
494 	}
495 	/* For Exit message */
496 	eswitch_dev->client_connected = false;
497 	return 0;
498 fail:
499 	return rc;
500 }
501 
502 static void
process_exit_message(void * msg_buf,uint32_t * buf_trav_len,uint32_t msg_len,void * data)503 process_exit_message(void *msg_buf, uint32_t *buf_trav_len, uint32_t msg_len, void *data)
504 {
505 	cnxk_rep_msg_exit_data_t *edata = NULL;
506 	uint16_t len = *buf_trav_len;
507 	void *buf;
508 
509 	/* Get the message type data viz exit data */
510 	buf = RTE_PTR_ADD(msg_buf, len);
511 	edata = (cnxk_rep_msg_exit_data_t *)buf;
512 
513 	plt_rep_dbg("Exit data received %d", edata->val);
514 
515 	/* Update all representor about ready/exit message */
516 	if (edata->val)
517 		notify_rep_dev_exit(edata, data);
518 
519 	/* Advance length to nex message */
520 	len += msg_len;
521 	*buf_trav_len = len;
522 }
523 
524 static void
populate_ack_msg(void * buffer,uint32_t * length,cnxk_rep_msg_ack_data1_t * adata)525 populate_ack_msg(void *buffer, uint32_t *length, cnxk_rep_msg_ack_data1_t *adata)
526 {
527 	uint32_t sz = sizeof(cnxk_rep_msg_ack_data1_t) + adata->size;
528 	uint32_t len;
529 
530 	cnxk_rep_msg_populate_command(buffer, length, CNXK_REP_MSG_ACK, sz);
531 
532 	len = *length;
533 
534 	/* Populate ACK message data */
535 	rte_memcpy(RTE_PTR_ADD(buffer, len), adata, sz);
536 
537 	len += sz;
538 
539 	*length = len;
540 }
541 
542 static int
send_ack_message(void * data,cnxk_rep_msg_ack_data1_t * adata)543 send_ack_message(void *data, cnxk_rep_msg_ack_data1_t *adata)
544 {
545 	struct cnxk_eswitch_dev *eswitch_dev = (struct cnxk_eswitch_dev *)data;
546 	uint32_t len = 0, size;
547 	void *buffer;
548 	int rc = 0;
549 
550 	/* Allocate memory for preparing a message */
551 	size = CTRL_MSG_BUFFER_SZ;
552 	buffer = rte_zmalloc("ACK msg", size, 0);
553 	if (!buffer) {
554 		plt_err("Failed to allocate mem");
555 		return -ENOMEM;
556 	}
557 
558 	/* Prepare the ACK message */
559 	cnxk_rep_msg_populate_header(buffer, &len);
560 	populate_ack_msg(buffer, &len, adata);
561 	cnxk_rep_msg_populate_msg_end(buffer, &len);
562 
563 	/* Length check to avoid buffer overflow */
564 	if (len > CTRL_MSG_BUFFER_SZ) {
565 		plt_err("Invalid length %d for max sized buffer %d", len, CTRL_MSG_BUFFER_SZ);
566 		rc = -EFAULT;
567 		goto done;
568 	}
569 
570 	/* Send it to the peer */
571 	rc = send_control_message(eswitch_dev, buffer, len);
572 	if (rc)
573 		plt_err("Failed send ack");
574 
575 done:
576 	return rc;
577 }
578 
579 static int
process_message(void * msg_buf,uint32_t * buf_trav_len,void * data)580 process_message(void *msg_buf, uint32_t *buf_trav_len, void *data)
581 {
582 	cnxk_rep_msg_data_t *msg = NULL;
583 	cnxk_rep_msg_ack_data1_t *adata = NULL;
584 	bool send_ack;
585 	int rc = 0, sz;
586 
587 	/* Get the message data */
588 	msg = message_data_extract(msg_buf, buf_trav_len);
589 	if (!msg) {
590 		plt_err("Failed to get message data");
591 		rc = -EINVAL;
592 		goto fail;
593 	}
594 
595 	/* Different message type processing */
596 	while (msg->type != CNXK_REP_MSG_END) {
597 		send_ack = true;
598 		switch (msg->type) {
599 		case CNXK_REP_MSG_ACK:
600 			plt_rep_dbg("Received ack response");
601 			process_ack_message(msg_buf, buf_trav_len, msg->length, data);
602 			send_ack = false;
603 			break;
604 		case CNXK_REP_MSG_READY:
605 			plt_rep_dbg("Received ready message");
606 			process_ready_message(msg_buf, buf_trav_len, msg->length, data, &adata);
607 			adata->type = CNXK_REP_MSG_READY;
608 			break;
609 		case CNXK_REP_MSG_EXIT:
610 			plt_rep_dbg("Received exit message");
611 			process_exit_message(msg_buf, buf_trav_len, msg->length, data);
612 			sz = sizeof(cnxk_rep_msg_ack_data1_t) + sizeof(uint64_t);
613 			adata = plt_zmalloc(sz, 0);
614 			adata->type = CNXK_REP_MSG_EXIT;
615 			adata->data[0] = 0;
616 			adata->size = sizeof(uint64_t);
617 			break;
618 		default:
619 			send_ack = false;
620 			plt_err("Invalid message type: %d", msg->type);
621 			rc = -EINVAL;
622 		};
623 
624 		/* Send ACK */
625 		if (send_ack)
626 			send_ack_message(data, adata);
627 
628 		/* Advance to next message */
629 		msg = message_data_extract(msg_buf, buf_trav_len);
630 		if (!msg) {
631 			plt_err("Failed to get message data");
632 			rc = -EINVAL;
633 			goto fail;
634 		}
635 	}
636 
637 	return 0;
638 fail:
639 	return rc;
640 }
641 
642 static int
process_control_message(void * msg_buf,void * data,size_t sz)643 process_control_message(void *msg_buf, void *data, size_t sz)
644 {
645 	uint32_t buf_trav_len = 0;
646 	int rc;
647 
648 	/* Validate the validity of the received message */
649 	parse_validate_header(msg_buf, &buf_trav_len);
650 
651 	/* Detect message and process */
652 	rc = process_message(msg_buf, &buf_trav_len, data);
653 	if (rc) {
654 		plt_err("Failed to process message");
655 		goto fail;
656 	}
657 
658 	/* Ensuring entire message has been processed */
659 	if (sz != buf_trav_len) {
660 		plt_err("Out of %" PRId64 " bytes %d bytes of msg_buf processed", sz, buf_trav_len);
661 		rc = -EFAULT;
662 		goto fail;
663 	}
664 
665 	return 0;
666 fail:
667 	return rc;
668 }
669 
670 static int
receive_control_msg_resp(struct cnxk_eswitch_dev * eswitch_dev,void * data)671 receive_control_msg_resp(struct cnxk_eswitch_dev *eswitch_dev, void *data)
672 {
673 	uint32_t wait_us = CTRL_MSG_RCV_TIMEOUT_MS * 1000;
674 	uint32_t timeout = 0, sleep = 1;
675 	int sz = 0;
676 	int rc = -1;
677 	uint32_t len = BUFSIZ;
678 	void *msg_buf;
679 
680 	msg_buf = plt_zmalloc(len, 0);
681 
682 	do {
683 		sz = receive_control_message(eswitch_dev->sock_fd, msg_buf, len);
684 		if (sz != 0)
685 			break;
686 
687 		/* Timeout after CTRL_MSG_RCV_TIMEOUT_MS */
688 		if (timeout >= wait_us) {
689 			plt_err("Control message wait timedout");
690 			return -ETIMEDOUT;
691 		}
692 
693 		plt_delay_us(sleep);
694 		timeout += sleep;
695 	} while ((sz == 0) || (timeout < wait_us));
696 
697 	if (sz > 0) {
698 		plt_rep_dbg("Received %d sized response packet", sz);
699 		rc = process_control_message(msg_buf, data, sz);
700 		plt_free(msg_buf);
701 	}
702 
703 	return rc;
704 }
705 
706 int
cnxk_rep_msg_send_process(struct cnxk_rep_dev * rep_dev,void * buffer,uint32_t len,cnxk_rep_msg_ack_data_t * adata)707 cnxk_rep_msg_send_process(struct cnxk_rep_dev *rep_dev, void *buffer, uint32_t len,
708 			  cnxk_rep_msg_ack_data_t *adata)
709 {
710 	struct cnxk_eswitch_dev *eswitch_dev;
711 	int rc = 0;
712 
713 	eswitch_dev = rep_dev->parent_dev;
714 	if (!eswitch_dev) {
715 		plt_err("Failed to get parent eswitch handle");
716 		rc = -1;
717 		goto fail;
718 	}
719 
720 	plt_spinlock_lock(&eswitch_dev->rep_lock);
721 	rc = send_control_message(eswitch_dev, buffer, len);
722 	if (rc) {
723 		plt_err("Failed to send the message, err %d", rc);
724 		goto free;
725 	}
726 
727 	/* Get response of the command sent */
728 	rc = receive_control_msg_resp(eswitch_dev, adata);
729 	if (rc) {
730 		plt_err("Failed to receive the response, err %d", rc);
731 		goto free;
732 	}
733 	plt_spinlock_unlock(&eswitch_dev->rep_lock);
734 
735 	return 0;
736 free:
737 	plt_spinlock_unlock(&eswitch_dev->rep_lock);
738 fail:
739 	return rc;
740 }
741 
742 static void
poll_for_control_msg(void * data)743 poll_for_control_msg(void *data)
744 {
745 	struct cnxk_eswitch_dev *eswitch_dev = (struct cnxk_eswitch_dev *)data;
746 	uint32_t len = BUFSIZ;
747 	int sz = 0;
748 	void *msg_buf;
749 
750 	while (eswitch_dev->client_connected) {
751 		msg_buf = plt_zmalloc(len, 0);
752 		do {
753 			plt_spinlock_lock(&eswitch_dev->rep_lock);
754 			sz = receive_control_message(eswitch_dev->sock_fd, msg_buf, len);
755 			plt_spinlock_unlock(&eswitch_dev->rep_lock);
756 			if (sz != 0)
757 				break;
758 			plt_delay_us(2000);
759 		} while (sz == 0);
760 
761 		if (sz > 0) {
762 			plt_rep_dbg("Received new %d bytes control message", sz);
763 			plt_spinlock_lock(&eswitch_dev->rep_lock);
764 			process_control_message(msg_buf, data, sz);
765 			plt_spinlock_unlock(&eswitch_dev->rep_lock);
766 			plt_free(msg_buf);
767 		}
768 	}
769 	plt_rep_dbg("Exiting poll for control message loop");
770 }
771 
772 static uint32_t
rep_ctrl_msg_thread_main(void * arg)773 rep_ctrl_msg_thread_main(void *arg)
774 {
775 	struct cnxk_eswitch_dev *eswitch_dev = (struct cnxk_eswitch_dev *)arg;
776 	struct sockaddr_un client;
777 	int addr_len;
778 	int ssock_fd;
779 	int sock_fd;
780 
781 	ssock_fd = open_socket_ctrl_channel();
782 	if (ssock_fd < 0) {
783 		plt_err("Failed to open socket for ctrl channel, err %d", ssock_fd);
784 		return UINT32_MAX;
785 	}
786 
787 	addr_len = sizeof(client);
788 	while (eswitch_dev->start_ctrl_msg_thrd) {
789 		/* Accept client connection until the thread is running */
790 		sock_fd = accept(ssock_fd, (struct sockaddr *)&client, (socklen_t *)&addr_len);
791 		if (sock_fd < 0) {
792 			plt_err("Failed to accept connection request on socket fd %d", ssock_fd);
793 			break;
794 		}
795 
796 		plt_rep_dbg("Client %s: Connection request accepted.", client.sun_path);
797 		eswitch_dev->sock_fd = sock_fd;
798 		if (eswitch_dev->start_ctrl_msg_thrd) {
799 			eswitch_dev->client_connected = true;
800 			poll_for_control_msg(eswitch_dev);
801 		}
802 		eswitch_dev->sock_fd = -1;
803 		close(sock_fd);
804 	}
805 
806 	/* Closing the opened socket */
807 	close_socket(ssock_fd);
808 	plt_rep_dbg("Exiting representor ctrl thread");
809 
810 	return 0;
811 }
812 
813 int
cnxk_rep_msg_control_thread_launch(struct cnxk_eswitch_dev * eswitch_dev)814 cnxk_rep_msg_control_thread_launch(struct cnxk_eswitch_dev *eswitch_dev)
815 {
816 	char name[CTRL_MSG_THRD_NAME_LEN];
817 	int rc = 0;
818 
819 	rte_strscpy(name, "rep_ctrl_msg_hndlr", CTRL_MSG_THRD_NAME_LEN);
820 	eswitch_dev->start_ctrl_msg_thrd = true;
821 	rc = rte_thread_create_internal_control(&eswitch_dev->rep_ctrl_msg_thread, name,
822 						rep_ctrl_msg_thread_main, eswitch_dev);
823 	if (rc)
824 		plt_err("Failed to create rep control message handling");
825 
826 	return rc;
827 }
828