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