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