LCOV - code coverage report
Current view: top level - drivers/net/cnxk - cnxk_rep_msg.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 357 0.0 %
Date: 2025-01-02 22:41:34 Functions: 0 25 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 142 0.0 %

           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                 :            : }

Generated by: LCOV version 1.14