LCOV - code coverage report
Current view: top level - drivers/net/memif - memif_socket.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 605 0.0 %
Date: 2024-12-01 18:57:19 Functions: 0 28 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 329 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2018-2019 Cisco Systems, Inc.  All rights reserved.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdlib.h>
       6                 :            : #include <fcntl.h>
       7                 :            : #include <unistd.h>
       8                 :            : #include <sys/types.h>
       9                 :            : #include <sys/socket.h>
      10                 :            : #include <sys/ioctl.h>
      11                 :            : #include <errno.h>
      12                 :            : 
      13                 :            : #include <rte_version.h>
      14                 :            : #include <rte_mbuf.h>
      15                 :            : #include <rte_ether.h>
      16                 :            : #include <ethdev_driver.h>
      17                 :            : #include <ethdev_vdev.h>
      18                 :            : #include <rte_malloc.h>
      19                 :            : #include <rte_kvargs.h>
      20                 :            : #include <bus_vdev_driver.h>
      21                 :            : #include <rte_hash.h>
      22                 :            : #include <rte_jhash.h>
      23                 :            : #include <rte_string_fns.h>
      24                 :            : 
      25                 :            : #include "rte_eth_memif.h"
      26                 :            : #include "memif_socket.h"
      27                 :            : 
      28                 :            : static void memif_intr_handler(void *arg);
      29                 :            : 
      30                 :            : static ssize_t
      31                 :          0 : memif_msg_send(int fd, memif_msg_t *msg, int afd)
      32                 :            : {
      33                 :          0 :         struct msghdr mh = { 0 };
      34                 :            :         struct iovec iov[1];
      35                 :            :         struct cmsghdr *cmsg;
      36                 :            :         char ctl[CMSG_SPACE(sizeof(int))];
      37                 :            : 
      38                 :          0 :         iov[0].iov_base = msg;
      39                 :          0 :         iov[0].iov_len = sizeof(memif_msg_t);
      40                 :          0 :         mh.msg_iov = iov;
      41                 :          0 :         mh.msg_iovlen = 1;
      42                 :            : 
      43         [ #  # ]:          0 :         if (afd > 0) {
      44                 :            :                 memset(&ctl, 0, sizeof(ctl));
      45                 :          0 :                 mh.msg_control = ctl;
      46                 :          0 :                 mh.msg_controllen = sizeof(ctl);
      47                 :            :                 cmsg = CMSG_FIRSTHDR(&mh);
      48                 :          0 :                 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
      49                 :          0 :                 cmsg->cmsg_level = SOL_SOCKET;
      50         [ #  # ]:          0 :                 cmsg->cmsg_type = SCM_RIGHTS;
      51                 :            :                 rte_memcpy(CMSG_DATA(cmsg), &afd, sizeof(int));
      52                 :            :         }
      53                 :            : 
      54                 :          0 :         return sendmsg(fd, &mh, 0);
      55                 :            : }
      56                 :            : 
      57                 :            : static int
      58                 :          0 : memif_msg_send_from_queue(struct memif_control_channel *cc)
      59                 :            : {
      60                 :            :         ssize_t size;
      61                 :            :         int ret = 0;
      62                 :            :         struct memif_msg_queue_elt *e;
      63                 :            : 
      64                 :          0 :         e = TAILQ_FIRST(&cc->msg_queue);
      65         [ #  # ]:          0 :         if (e == NULL)
      66                 :            :                 return 0;
      67                 :            : 
      68         [ #  # ]:          0 :         if (rte_intr_fd_get(cc->intr_handle) < 0)
      69                 :            :                 return -1;
      70                 :            : 
      71                 :          0 :         size = memif_msg_send(rte_intr_fd_get(cc->intr_handle), &e->msg,
      72                 :            :                               e->fd);
      73         [ #  # ]:          0 :         if (size != sizeof(memif_msg_t)) {
      74                 :          0 :                 MIF_LOG(ERR, "sendmsg fail: %s.", strerror(errno));
      75                 :            :                 ret = -1;
      76                 :            :         } else {
      77                 :          0 :                 MIF_LOG(DEBUG, "Sent msg type %u.", e->msg.type);
      78                 :            :         }
      79         [ #  # ]:          0 :         TAILQ_REMOVE(&cc->msg_queue, e, next);
      80                 :          0 :         rte_free(e);
      81                 :            : 
      82                 :          0 :         return ret;
      83                 :            : }
      84                 :            : 
      85                 :            : static struct memif_msg_queue_elt *
      86                 :          0 : memif_msg_enq(struct memif_control_channel *cc)
      87                 :            : {
      88                 :            :         struct memif_msg_queue_elt *e;
      89                 :            : 
      90                 :          0 :         e = rte_zmalloc("memif_msg", sizeof(struct memif_msg_queue_elt), 0);
      91         [ #  # ]:          0 :         if (e == NULL) {
      92                 :          0 :                 MIF_LOG(ERR, "Failed to allocate control message.");
      93                 :          0 :                 return NULL;
      94                 :            :         }
      95                 :            : 
      96                 :          0 :         e->fd = -1;
      97                 :          0 :         TAILQ_INSERT_TAIL(&cc->msg_queue, e, next);
      98                 :            : 
      99                 :          0 :         return e;
     100                 :            : }
     101                 :            : 
     102                 :            : void
     103                 :          0 : memif_msg_enq_disconnect(struct memif_control_channel *cc, const char *reason,
     104                 :            :                          int err_code)
     105                 :            : {
     106                 :            :         struct memif_msg_queue_elt *e;
     107                 :            :         struct pmd_internals *pmd;
     108                 :            :         memif_msg_disconnect_t *d;
     109                 :            : 
     110         [ #  # ]:          0 :         if (cc == NULL) {
     111                 :          0 :                 MIF_LOG(DEBUG, "Missing control channel.");
     112                 :          0 :                 return;
     113                 :            :         }
     114                 :            : 
     115                 :          0 :         e = memif_msg_enq(cc);
     116         [ #  # ]:          0 :         if (e == NULL) {
     117                 :          0 :                 MIF_LOG(WARNING, "Failed to enqueue disconnect message.");
     118                 :          0 :                 return;
     119                 :            :         }
     120                 :            : 
     121                 :            :         d = &e->msg.disconnect;
     122                 :            : 
     123                 :          0 :         e->msg.type = MEMIF_MSG_TYPE_DISCONNECT;
     124                 :          0 :         d->code = err_code;
     125                 :            : 
     126         [ #  # ]:          0 :         if (reason != NULL) {
     127         [ #  # ]:          0 :                 strlcpy((char *)d->string, reason, sizeof(d->string));
     128         [ #  # ]:          0 :                 if (cc->dev != NULL) {
     129                 :          0 :                         pmd = cc->dev->data->dev_private;
     130                 :          0 :                         strlcpy(pmd->local_disc_string, reason,
     131                 :            :                                 sizeof(pmd->local_disc_string));
     132                 :            :                 }
     133                 :            :         }
     134                 :            : }
     135                 :            : 
     136                 :            : static int
     137                 :          0 : memif_msg_enq_hello(struct memif_control_channel *cc)
     138                 :            : {
     139                 :          0 :         struct memif_msg_queue_elt *e = memif_msg_enq(cc);
     140                 :            :         memif_msg_hello_t *h;
     141                 :            : 
     142         [ #  # ]:          0 :         if (e == NULL)
     143                 :            :                 return -1;
     144                 :            : 
     145                 :            :         h = &e->msg.hello;
     146                 :            : 
     147                 :          0 :         e->msg.type = MEMIF_MSG_TYPE_HELLO;
     148                 :          0 :         h->min_version = MEMIF_VERSION;
     149                 :          0 :         h->max_version = MEMIF_VERSION;
     150                 :          0 :         h->max_c2s_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS;
     151                 :          0 :         h->max_s2c_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS;
     152                 :          0 :         h->max_region = ETH_MEMIF_MAX_REGION_NUM - 1;
     153                 :          0 :         h->max_log2_ring_size = ETH_MEMIF_MAX_LOG2_RING_SIZE;
     154                 :            : 
     155                 :          0 :         strlcpy((char *)h->name, rte_version(), sizeof(h->name));
     156                 :            : 
     157                 :          0 :         return 0;
     158                 :            : }
     159                 :            : 
     160                 :            : static int
     161                 :          0 : memif_msg_receive_hello(struct rte_eth_dev *dev, memif_msg_t *msg)
     162                 :            : {
     163                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     164                 :            :         memif_msg_hello_t *h = &msg->hello;
     165                 :            : 
     166   [ #  #  #  # ]:          0 :         if (h->min_version > MEMIF_VERSION || h->max_version < MEMIF_VERSION) {
     167                 :          0 :                 memif_msg_enq_disconnect(pmd->cc, "Incompatible memif version", 0);
     168                 :          0 :                 return -1;
     169                 :            :         }
     170                 :            : 
     171                 :            :         /* Set parameters for active connection */
     172                 :          0 :         pmd->run.num_c2s_rings = RTE_MIN(h->max_c2s_ring + 1,
     173                 :            :                                            pmd->cfg.num_c2s_rings);
     174                 :          0 :         pmd->run.num_s2c_rings = RTE_MIN(h->max_s2c_ring + 1,
     175                 :            :                                            pmd->cfg.num_s2c_rings);
     176                 :          0 :         pmd->run.log2_ring_size = RTE_MIN(h->max_log2_ring_size,
     177                 :            :                                             pmd->cfg.log2_ring_size);
     178                 :          0 :         pmd->run.pkt_buffer_size = pmd->cfg.pkt_buffer_size;
     179                 :            : 
     180                 :          0 :         strlcpy(pmd->remote_name, (char *)h->name, sizeof(pmd->remote_name));
     181                 :            : 
     182                 :          0 :         MIF_LOG(DEBUG, "Connecting to %s.", pmd->remote_name);
     183                 :            : 
     184                 :          0 :         return 0;
     185                 :            : }
     186                 :            : 
     187                 :            : static int
     188                 :          0 : memif_msg_receive_init(struct memif_control_channel *cc, memif_msg_t *msg)
     189                 :            : {
     190                 :            :         memif_msg_init_t *i = &msg->init;
     191                 :            :         struct memif_socket_dev_list_elt *elt;
     192                 :            :         struct pmd_internals *pmd;
     193                 :            :         struct rte_eth_dev *dev;
     194                 :            : 
     195         [ #  # ]:          0 :         if (i->version != MEMIF_VERSION) {
     196                 :          0 :                 memif_msg_enq_disconnect(cc, "Incompatible memif version", 0);
     197                 :          0 :                 return -1;
     198                 :            :         }
     199                 :            : 
     200         [ #  # ]:          0 :         if (cc->socket == NULL) {
     201                 :          0 :                 memif_msg_enq_disconnect(cc, "Device error", 0);
     202                 :          0 :                 return -1;
     203                 :            :         }
     204                 :            : 
     205                 :            :         /* Find device with requested ID */
     206         [ #  # ]:          0 :         TAILQ_FOREACH(elt, &cc->socket->dev_queue, next) {
     207                 :          0 :                 dev = elt->dev;
     208                 :          0 :                 pmd = dev->data->dev_private;
     209         [ #  # ]:          0 :                 if (((pmd->flags & ETH_MEMIF_FLAG_DISABLED) == 0) &&
     210   [ #  #  #  # ]:          0 :                     (pmd->id == i->id) && (pmd->role == MEMIF_ROLE_SERVER)) {
     211         [ #  # ]:          0 :                         if (pmd->flags & (ETH_MEMIF_FLAG_CONNECTING |
     212                 :            :                                            ETH_MEMIF_FLAG_CONNECTED)) {
     213                 :          0 :                                 memif_msg_enq_disconnect(cc,
     214                 :            :                                                          "Already connected", 0);
     215                 :          0 :                                 return -1;
     216                 :            :                         }
     217                 :            : 
     218                 :            :                         /* assign control channel to device */
     219                 :          0 :                         cc->dev = dev;
     220                 :          0 :                         pmd->cc = cc;
     221                 :            : 
     222         [ #  # ]:          0 :                         if (i->mode != MEMIF_INTERFACE_MODE_ETHERNET) {
     223                 :          0 :                                 memif_msg_enq_disconnect(pmd->cc,
     224                 :            :                                                          "Only ethernet mode supported",
     225                 :            :                                                          0);
     226                 :          0 :                                 return -1;
     227                 :            :                         }
     228                 :            : 
     229         [ #  # ]:          0 :                         strlcpy(pmd->remote_name, (char *)i->name,
     230                 :            :                                 sizeof(pmd->remote_name));
     231                 :            : 
     232         [ #  # ]:          0 :                         if (*pmd->secret != '\0') {
     233         [ #  # ]:          0 :                                 if (*i->secret == '\0') {
     234                 :          0 :                                         memif_msg_enq_disconnect(pmd->cc,
     235                 :            :                                                                  "Secret required", 0);
     236                 :          0 :                                         return -1;
     237                 :            :                                 }
     238         [ #  # ]:          0 :                                 if (strncmp(pmd->secret, (char *)i->secret,
     239                 :            :                                                 ETH_MEMIF_SECRET_SIZE) != 0) {
     240                 :          0 :                                         memif_msg_enq_disconnect(pmd->cc,
     241                 :            :                                                                  "Incorrect secret", 0);
     242                 :          0 :                                         return -1;
     243                 :            :                                 }
     244                 :            :                         }
     245                 :            : 
     246                 :          0 :                         pmd->flags |= ETH_MEMIF_FLAG_CONNECTING;
     247                 :          0 :                         return 0;
     248                 :            :                 }
     249                 :            :         }
     250                 :            : 
     251                 :            :         /* ID not found on this socket */
     252                 :          0 :         MIF_LOG(DEBUG, "ID %u not found.", i->id);
     253                 :          0 :         memif_msg_enq_disconnect(cc, "ID not found", 0);
     254                 :          0 :         return -1;
     255                 :            : }
     256                 :            : 
     257                 :            : static int
     258                 :          0 : memif_msg_receive_add_region(struct rte_eth_dev *dev, memif_msg_t *msg,
     259                 :            :                              int fd)
     260                 :            : {
     261                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     262                 :          0 :         struct pmd_process_private *proc_private = dev->process_private;
     263                 :            :         memif_msg_add_region_t *ar = &msg->add_region;
     264                 :            :         struct memif_region *r;
     265                 :            : 
     266         [ #  # ]:          0 :         if (fd < 0) {
     267                 :          0 :                 memif_msg_enq_disconnect(pmd->cc, "Missing region fd", 0);
     268                 :          0 :                 return -1;
     269                 :            :         }
     270                 :            : 
     271         [ #  # ]:          0 :         if (ar->index >= ETH_MEMIF_MAX_REGION_NUM ||
     272         [ #  # ]:          0 :                         ar->index != proc_private->regions_num ||
     273         [ #  # ]:          0 :                         proc_private->regions[ar->index] != NULL) {
     274                 :          0 :                 memif_msg_enq_disconnect(pmd->cc, "Invalid region index", 0);
     275                 :          0 :                 return -1;
     276                 :            :         }
     277                 :            : 
     278                 :          0 :         r = rte_zmalloc("region", sizeof(struct memif_region), 0);
     279         [ #  # ]:          0 :         if (r == NULL) {
     280                 :          0 :                 memif_msg_enq_disconnect(pmd->cc, "Failed to alloc memif region.", 0);
     281                 :          0 :                 return -ENOMEM;
     282                 :            :         }
     283                 :            : 
     284                 :          0 :         r->fd = fd;
     285                 :          0 :         r->region_size = ar->size;
     286                 :          0 :         r->addr = NULL;
     287                 :            : 
     288                 :          0 :         proc_private->regions[ar->index] = r;
     289                 :          0 :         proc_private->regions_num++;
     290                 :            : 
     291                 :          0 :         return 0;
     292                 :            : }
     293                 :            : 
     294                 :            : static int
     295                 :          0 : memif_msg_receive_add_ring(struct rte_eth_dev *dev, memif_msg_t *msg, int fd)
     296                 :            : {
     297                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     298                 :            :         memif_msg_add_ring_t *ar = &msg->add_ring;
     299                 :            :         struct memif_queue *mq;
     300                 :            : 
     301         [ #  # ]:          0 :         if (fd < 0) {
     302                 :          0 :                 memif_msg_enq_disconnect(pmd->cc, "Missing interrupt fd", 0);
     303                 :          0 :                 return -1;
     304                 :            :         }
     305                 :            : 
     306                 :            :         /* check if we have enough queues */
     307         [ #  # ]:          0 :         if (ar->flags & MEMIF_MSG_ADD_RING_FLAG_C2S) {
     308         [ #  # ]:          0 :                 if (ar->index >= pmd->cfg.num_c2s_rings) {
     309                 :          0 :                         memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0);
     310                 :          0 :                         return -1;
     311                 :            :                 }
     312                 :          0 :                 pmd->run.num_c2s_rings++;
     313                 :            :         } else {
     314         [ #  # ]:          0 :                 if (ar->index >= pmd->cfg.num_s2c_rings) {
     315                 :          0 :                         memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0);
     316                 :          0 :                         return -1;
     317                 :            :                 }
     318                 :          0 :                 pmd->run.num_s2c_rings++;
     319                 :            :         }
     320                 :            : 
     321         [ #  # ]:          0 :         mq = (ar->flags & MEMIF_MSG_ADD_RING_FLAG_C2S) ?
     322                 :          0 :             dev->data->rx_queues[ar->index] : dev->data->tx_queues[ar->index];
     323                 :            : 
     324         [ #  # ]:          0 :         if (rte_intr_fd_set(mq->intr_handle, fd))
     325                 :            :                 return -1;
     326                 :            : 
     327                 :          0 :         mq->log2_ring_size = ar->log2_ring_size;
     328                 :          0 :         mq->region = ar->region;
     329                 :          0 :         mq->ring_offset = ar->offset;
     330                 :            : 
     331                 :          0 :         return 0;
     332                 :            : }
     333                 :            : 
     334                 :            : static int
     335                 :          0 : memif_msg_receive_connect(struct rte_eth_dev *dev, memif_msg_t *msg)
     336                 :            : {
     337                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     338                 :            :         memif_msg_connect_t *c = &msg->connect;
     339                 :            :         int ret;
     340                 :            : 
     341                 :          0 :         ret = memif_connect(dev);
     342         [ #  # ]:          0 :         if (ret < 0)
     343                 :            :                 return ret;
     344                 :            : 
     345                 :          0 :         strlcpy(pmd->remote_if_name, (char *)c->if_name,
     346                 :            :                 sizeof(pmd->remote_if_name));
     347                 :          0 :         MIF_LOG(INFO, "Remote interface %s connected.", pmd->remote_if_name);
     348                 :            : 
     349                 :          0 :         return 0;
     350                 :            : }
     351                 :            : 
     352                 :            : static int
     353                 :          0 : memif_msg_receive_connected(struct rte_eth_dev *dev, memif_msg_t *msg)
     354                 :            : {
     355                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     356                 :            :         memif_msg_connected_t *c = &msg->connected;
     357                 :            :         int ret;
     358                 :            : 
     359                 :          0 :         ret = memif_connect(dev);
     360         [ #  # ]:          0 :         if (ret < 0)
     361                 :            :                 return ret;
     362                 :            : 
     363                 :          0 :         strlcpy(pmd->remote_if_name, (char *)c->if_name,
     364                 :            :                 sizeof(pmd->remote_if_name));
     365                 :          0 :         MIF_LOG(INFO, "Remote interface %s connected.", pmd->remote_if_name);
     366                 :            : 
     367                 :          0 :         return 0;
     368                 :            : }
     369                 :            : 
     370                 :            : static int
     371                 :          0 : memif_msg_receive_disconnect(struct rte_eth_dev *dev, memif_msg_t *msg)
     372                 :            : {
     373                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     374                 :            :         memif_msg_disconnect_t *d = &msg->disconnect;
     375                 :            : 
     376                 :          0 :         memset(pmd->remote_disc_string, 0, sizeof(pmd->remote_disc_string));
     377                 :          0 :         strlcpy(pmd->remote_disc_string, (char *)d->string,
     378                 :            :                 sizeof(pmd->remote_disc_string));
     379                 :            : 
     380                 :          0 :         MIF_LOG(INFO, "Disconnect received: %s", pmd->remote_disc_string);
     381                 :            : 
     382                 :          0 :         memset(pmd->local_disc_string, 0, 96);
     383                 :          0 :         memif_disconnect(dev);
     384                 :          0 :         return 0;
     385                 :            : }
     386                 :            : 
     387                 :            : static int
     388                 :            : memif_msg_enq_ack(struct rte_eth_dev *dev)
     389                 :            : {
     390                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     391                 :          0 :         struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
     392   [ #  #  #  #  :          0 :         if (e == NULL)
                   #  # ]
     393                 :            :                 return -1;
     394                 :            : 
     395                 :          0 :         e->msg.type = MEMIF_MSG_TYPE_ACK;
     396                 :            : 
     397                 :            :         return 0;
     398                 :            : }
     399                 :            : 
     400                 :            : static int
     401                 :          0 : memif_msg_enq_init(struct rte_eth_dev *dev)
     402                 :            : {
     403                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     404                 :          0 :         struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
     405                 :            :         memif_msg_init_t *i;
     406                 :            : 
     407         [ #  # ]:          0 :         if (e == NULL)
     408                 :            :                 return -1;
     409                 :            :         i = &e->msg.init;
     410                 :          0 :         e->msg.type = MEMIF_MSG_TYPE_INIT;
     411                 :          0 :         i->version = MEMIF_VERSION;
     412                 :          0 :         i->id = pmd->id;
     413                 :          0 :         i->mode = MEMIF_INTERFACE_MODE_ETHERNET;
     414                 :            : 
     415         [ #  # ]:          0 :         strlcpy((char *)i->name, rte_version(), sizeof(i->name));
     416                 :            : 
     417         [ #  # ]:          0 :         if (*pmd->secret != '\0')
     418                 :          0 :                 strlcpy((char *)i->secret, pmd->secret, sizeof(i->secret));
     419                 :            : 
     420                 :            :         return 0;
     421                 :            : }
     422                 :            : 
     423                 :            : static int
     424                 :          0 : memif_msg_enq_add_region(struct rte_eth_dev *dev, uint8_t idx)
     425                 :            : {
     426                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     427                 :          0 :         struct pmd_process_private *proc_private = dev->process_private;
     428                 :          0 :         struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
     429                 :            :         memif_msg_add_region_t *ar;
     430                 :          0 :         struct memif_region *mr = proc_private->regions[idx];
     431                 :            : 
     432         [ #  # ]:          0 :         if (e == NULL)
     433                 :            :                 return -1;
     434                 :            : 
     435                 :            :         ar = &e->msg.add_region;
     436                 :          0 :         e->msg.type = MEMIF_MSG_TYPE_ADD_REGION;
     437                 :          0 :         e->fd = mr->fd;
     438                 :          0 :         ar->index = idx;
     439                 :          0 :         ar->size = mr->region_size;
     440                 :            : 
     441                 :          0 :         return 0;
     442                 :            : }
     443                 :            : 
     444                 :            : static int
     445                 :          0 : memif_msg_enq_add_ring(struct rte_eth_dev *dev, uint8_t idx,
     446                 :            :                        memif_ring_type_t type)
     447                 :            : {
     448                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     449                 :          0 :         struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
     450                 :            :         struct memif_queue *mq;
     451                 :            :         memif_msg_add_ring_t *ar;
     452                 :            : 
     453         [ #  # ]:          0 :         if (e == NULL)
     454                 :            :                 return -1;
     455                 :            : 
     456                 :            :         ar = &e->msg.add_ring;
     457         [ #  # ]:          0 :         mq = (type == MEMIF_RING_C2S) ? dev->data->tx_queues[idx] :
     458                 :          0 :             dev->data->rx_queues[idx];
     459                 :            : 
     460                 :          0 :         e->msg.type = MEMIF_MSG_TYPE_ADD_RING;
     461                 :          0 :         e->fd = rte_intr_fd_get(mq->intr_handle);
     462                 :          0 :         ar->index = idx;
     463                 :          0 :         ar->offset = mq->ring_offset;
     464                 :          0 :         ar->region = mq->region;
     465                 :          0 :         ar->log2_ring_size = mq->log2_ring_size;
     466                 :          0 :         ar->flags = (type == MEMIF_RING_C2S) ? MEMIF_MSG_ADD_RING_FLAG_C2S : 0;
     467                 :          0 :         ar->private_hdr_size = 0;
     468                 :            : 
     469                 :          0 :         return 0;
     470                 :            : }
     471                 :            : 
     472                 :            : static int
     473                 :          0 : memif_msg_enq_connect(struct rte_eth_dev *dev)
     474                 :            : {
     475                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     476                 :          0 :         struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
     477                 :            :         memif_msg_connect_t *c;
     478                 :            : 
     479         [ #  # ]:          0 :         if (e == NULL)
     480                 :            :                 return -1;
     481                 :            : 
     482                 :            :         c = &e->msg.connect;
     483                 :          0 :         e->msg.type = MEMIF_MSG_TYPE_CONNECT;
     484                 :          0 :         strlcpy((char *)c->if_name, dev->data->name, sizeof(c->if_name));
     485                 :            : 
     486                 :          0 :         return 0;
     487                 :            : }
     488                 :            : 
     489                 :            : static int
     490                 :          0 : memif_msg_enq_connected(struct rte_eth_dev *dev)
     491                 :            : {
     492                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     493                 :          0 :         struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
     494                 :            :         memif_msg_connected_t *c;
     495                 :            : 
     496         [ #  # ]:          0 :         if (e == NULL)
     497                 :            :                 return -1;
     498                 :            : 
     499                 :            :         c = &e->msg.connected;
     500                 :          0 :         e->msg.type = MEMIF_MSG_TYPE_CONNECTED;
     501                 :          0 :         strlcpy((char *)c->if_name, dev->data->name, sizeof(c->if_name));
     502                 :            : 
     503                 :          0 :         return 0;
     504                 :            : }
     505                 :            : 
     506                 :            : static void
     507                 :          0 : memif_intr_unregister_handler(struct rte_intr_handle *intr_handle, void *arg)
     508                 :            : {
     509                 :            :         struct memif_msg_queue_elt *elt;
     510                 :            :         struct memif_control_channel *cc = arg;
     511                 :            : 
     512                 :            :         /* close control channel fd */
     513         [ #  # ]:          0 :         if (rte_intr_fd_get(intr_handle) >= 0)
     514                 :          0 :                 close(rte_intr_fd_get(intr_handle));
     515                 :            :         /* clear message queue */
     516         [ #  # ]:          0 :         while ((elt = TAILQ_FIRST(&cc->msg_queue)) != NULL) {
     517         [ #  # ]:          0 :                 TAILQ_REMOVE(&cc->msg_queue, elt, next);
     518                 :          0 :                 rte_free(elt);
     519                 :            :         }
     520                 :          0 :         rte_intr_instance_free(cc->intr_handle);
     521                 :            :         /* free control channel */
     522                 :          0 :         rte_free(cc);
     523                 :          0 : }
     524                 :            : 
     525                 :            : void
     526                 :          0 : memif_disconnect(struct rte_eth_dev *dev)
     527                 :            : {
     528                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     529                 :            :         struct memif_msg_queue_elt *elt, *next;
     530                 :            :         struct memif_queue *mq;
     531                 :            :         struct rte_intr_handle *ih;
     532                 :            :         int i;
     533                 :            :         int ret;
     534                 :            : 
     535                 :          0 :         dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
     536                 :          0 :         pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTING;
     537                 :          0 :         pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTED;
     538                 :            : 
     539                 :          0 :         rte_spinlock_lock(&pmd->cc_lock);
     540         [ #  # ]:          0 :         if (pmd->cc != NULL) {
     541                 :            :                 /* Clear control message queue (except disconnect message if any). */
     542         [ #  # ]:          0 :                 for (elt = TAILQ_FIRST(&pmd->cc->msg_queue); elt != NULL; elt = next) {
     543                 :          0 :                         next = TAILQ_NEXT(elt, next);
     544         [ #  # ]:          0 :                         if (elt->msg.type != MEMIF_MSG_TYPE_DISCONNECT) {
     545         [ #  # ]:          0 :                                 TAILQ_REMOVE(&pmd->cc->msg_queue, elt, next);
     546                 :          0 :                                 rte_free(elt);
     547                 :            :                         }
     548                 :            :                 }
     549                 :            :                 /* send disconnect message (if there is any in queue) */
     550                 :          0 :                 memif_msg_send_from_queue(pmd->cc);
     551                 :            : 
     552                 :            :                 /* at this point, there should be no more messages in queue */
     553         [ #  # ]:          0 :                 if (TAILQ_FIRST(&pmd->cc->msg_queue) != NULL) {
     554                 :          0 :                         MIF_LOG(WARNING,
     555                 :            :                                 "Unexpected message(s) in message queue.");
     556                 :            :                 }
     557                 :            : 
     558                 :          0 :                 ih = pmd->cc->intr_handle;
     559         [ #  # ]:          0 :                 if (rte_intr_fd_get(ih) > 0) {
     560                 :          0 :                         ret = rte_intr_callback_unregister(ih,
     561                 :            :                                                         memif_intr_handler,
     562                 :          0 :                                                         pmd->cc);
     563                 :            :                         /*
     564                 :            :                          * If callback is active (disconnecting based on
     565                 :            :                          * received control message).
     566                 :            :                          */
     567         [ #  # ]:          0 :                         if (ret == -EAGAIN) {
     568                 :          0 :                                 ret = rte_intr_callback_unregister_pending(ih,
     569                 :            :                                                         memif_intr_handler,
     570                 :          0 :                                                         pmd->cc,
     571                 :            :                                                         memif_intr_unregister_handler);
     572         [ #  # ]:          0 :                         } else if (ret > 0) {
     573                 :          0 :                                 close(rte_intr_fd_get(ih));
     574                 :          0 :                                 rte_intr_instance_free(ih);
     575                 :          0 :                                 rte_free(pmd->cc);
     576                 :            :                         }
     577                 :          0 :                         pmd->cc = NULL;
     578         [ #  # ]:          0 :                         if (ret <= 0)
     579                 :          0 :                                 MIF_LOG(WARNING,
     580                 :            :                                         "Failed to unregister control channel callback.");
     581                 :            :                 }
     582                 :            :         }
     583                 :            :         rte_spinlock_unlock(&pmd->cc_lock);
     584                 :            : 
     585                 :            :         /* unconfig interrupts */
     586         [ #  # ]:          0 :         for (i = 0; i < pmd->cfg.num_c2s_rings; i++) {
     587         [ #  # ]:          0 :                 if (pmd->role == MEMIF_ROLE_CLIENT) {
     588         [ #  # ]:          0 :                         if (dev->data->tx_queues != NULL)
     589                 :          0 :                                 mq = dev->data->tx_queues[i];
     590                 :            :                         else
     591                 :          0 :                                 continue;
     592                 :            :                 } else {
     593         [ #  # ]:          0 :                         if (dev->data->rx_queues != NULL)
     594                 :          0 :                                 mq = dev->data->rx_queues[i];
     595                 :            :                         else
     596                 :          0 :                                 continue;
     597                 :            :                 }
     598                 :            : 
     599         [ #  # ]:          0 :                 if (rte_intr_fd_get(mq->intr_handle) > 0) {
     600                 :          0 :                         close(rte_intr_fd_get(mq->intr_handle));
     601                 :          0 :                         rte_intr_fd_set(mq->intr_handle, -1);
     602                 :            :                 }
     603                 :            :         }
     604         [ #  # ]:          0 :         for (i = 0; i < pmd->cfg.num_s2c_rings; i++) {
     605         [ #  # ]:          0 :                 if (pmd->role == MEMIF_ROLE_SERVER) {
     606         [ #  # ]:          0 :                         if (dev->data->tx_queues != NULL)
     607                 :          0 :                                 mq = dev->data->tx_queues[i];
     608                 :            :                         else
     609                 :          0 :                                 continue;
     610                 :            :                 } else {
     611         [ #  # ]:          0 :                         if (dev->data->rx_queues != NULL)
     612                 :          0 :                                 mq = dev->data->rx_queues[i];
     613                 :            :                         else
     614                 :          0 :                                 continue;
     615                 :            :                 }
     616                 :            : 
     617         [ #  # ]:          0 :                 if (rte_intr_fd_get(mq->intr_handle) > 0) {
     618                 :          0 :                         close(rte_intr_fd_get(mq->intr_handle));
     619                 :          0 :                         rte_intr_fd_set(mq->intr_handle, -1);
     620                 :            :                 }
     621                 :            :         }
     622                 :            : 
     623                 :          0 :         memif_free_regions(dev);
     624                 :            : 
     625                 :            :         /* reset connection configuration */
     626         [ #  # ]:          0 :         memset(&pmd->run, 0, sizeof(pmd->run));
     627                 :            : 
     628         [ #  # ]:          0 :         MIF_LOG(DEBUG, "Disconnected, id: %d, role: %s.", pmd->id,
     629                 :            :                 (pmd->role == MEMIF_ROLE_SERVER) ? "server" : "client");
     630                 :          0 : }
     631                 :            : 
     632                 :            : static int
     633                 :          0 : memif_msg_receive(struct memif_control_channel *cc)
     634                 :            : {
     635                 :          0 :         char ctl[CMSG_SPACE(sizeof(int)) +
     636                 :            :                  CMSG_SPACE(sizeof(struct ucred))] = { 0 };
     637                 :          0 :         struct msghdr mh = { 0 };
     638                 :            :         struct iovec iov[1];
     639                 :          0 :         memif_msg_t msg = { 0 };
     640                 :            :         ssize_t size;
     641                 :            :         int ret = 0;
     642                 :            :         struct ucred *cr __rte_unused;
     643                 :            :         cr = 0;
     644                 :            :         struct cmsghdr *cmsg;
     645                 :          0 :         int afd = -1;
     646                 :            :         int i;
     647                 :            :         struct pmd_internals *pmd;
     648                 :            :         struct pmd_process_private *proc_private;
     649                 :            : 
     650                 :          0 :         iov[0].iov_base = (void *)&msg;
     651                 :          0 :         iov[0].iov_len = sizeof(memif_msg_t);
     652                 :          0 :         mh.msg_iov = iov;
     653                 :          0 :         mh.msg_iovlen = 1;
     654                 :          0 :         mh.msg_control = ctl;
     655                 :          0 :         mh.msg_controllen = sizeof(ctl);
     656                 :            : 
     657         [ #  # ]:          0 :         if (rte_intr_fd_get(cc->intr_handle) < 0)
     658                 :            :                 return -1;
     659                 :            : 
     660                 :          0 :         size = recvmsg(rte_intr_fd_get(cc->intr_handle), &mh, 0);
     661         [ #  # ]:          0 :         if (size != sizeof(memif_msg_t)) {
     662                 :          0 :                 MIF_LOG(DEBUG, "Invalid message size = %zd", size);
     663         [ #  # ]:          0 :                 if (size > 0)
     664                 :            :                         /* 0 means end-of-file, negative size means error,
     665                 :            :                          * don't send further disconnect message in such cases.
     666                 :            :                          */
     667                 :          0 :                         memif_msg_enq_disconnect(cc, "Invalid message size", 0);
     668                 :          0 :                 return -1;
     669                 :            :         }
     670                 :          0 :         MIF_LOG(DEBUG, "Received msg type: %u.", msg.type);
     671                 :            : 
     672         [ #  # ]:          0 :         cmsg = CMSG_FIRSTHDR(&mh);
     673         [ #  # ]:          0 :         while (cmsg) {
     674         [ #  # ]:          0 :                 if (cmsg->cmsg_level == SOL_SOCKET) {
     675         [ #  # ]:          0 :                         if (cmsg->cmsg_type == SCM_CREDENTIALS)
     676                 :            :                                 cr = (struct ucred *)CMSG_DATA(cmsg);
     677         [ #  # ]:          0 :                         else if (cmsg->cmsg_type == SCM_RIGHTS)
     678         [ #  # ]:          0 :                                 rte_memcpy(&afd, CMSG_DATA(cmsg), sizeof(int));
     679                 :            :                 }
     680                 :            :                 cmsg = CMSG_NXTHDR(&mh, cmsg);
     681                 :            :         }
     682                 :            : 
     683   [ #  #  #  # ]:          0 :         if (cc->dev == NULL && msg.type != MEMIF_MSG_TYPE_INIT) {
     684                 :          0 :                 MIF_LOG(DEBUG, "Unexpected message.");
     685                 :          0 :                 memif_msg_enq_disconnect(cc, "Unexpected message", 0);
     686                 :          0 :                 return -1;
     687                 :            :         }
     688                 :            : 
     689                 :            :         /* get device from hash data */
     690   [ #  #  #  #  :          0 :         switch (msg.type) {
             #  #  #  #  
                      # ]
     691                 :            :         case MEMIF_MSG_TYPE_ACK:
     692                 :            :                 break;
     693                 :          0 :         case MEMIF_MSG_TYPE_HELLO:
     694                 :          0 :                 ret = memif_msg_receive_hello(cc->dev, &msg);
     695         [ #  # ]:          0 :                 if (ret < 0)
     696                 :          0 :                         goto exit;
     697                 :          0 :                 ret = memif_init_regions_and_queues(cc->dev);
     698         [ #  # ]:          0 :                 if (ret < 0)
     699                 :          0 :                         goto exit;
     700                 :          0 :                 ret = memif_msg_enq_init(cc->dev);
     701         [ #  # ]:          0 :                 if (ret < 0)
     702                 :          0 :                         goto exit;
     703                 :          0 :                 pmd = cc->dev->data->dev_private;
     704                 :          0 :                 proc_private = cc->dev->process_private;
     705         [ #  # ]:          0 :                 for (i = 0; i < proc_private->regions_num; i++) {
     706                 :          0 :                         ret = memif_msg_enq_add_region(cc->dev, i);
     707         [ #  # ]:          0 :                         if (ret < 0)
     708                 :          0 :                                 goto exit;
     709                 :            :                 }
     710         [ #  # ]:          0 :                 for (i = 0; i < pmd->run.num_c2s_rings; i++) {
     711                 :          0 :                         ret = memif_msg_enq_add_ring(cc->dev, i,
     712                 :            :                                                      MEMIF_RING_C2S);
     713         [ #  # ]:          0 :                         if (ret < 0)
     714                 :          0 :                                 goto exit;
     715                 :            :                 }
     716         [ #  # ]:          0 :                 for (i = 0; i < pmd->run.num_s2c_rings; i++) {
     717                 :          0 :                         ret = memif_msg_enq_add_ring(cc->dev, i,
     718                 :            :                                                      MEMIF_RING_S2C);
     719         [ #  # ]:          0 :                         if (ret < 0)
     720                 :          0 :                                 goto exit;
     721                 :            :                 }
     722                 :          0 :                 ret = memif_msg_enq_connect(cc->dev);
     723         [ #  # ]:          0 :                 if (ret < 0)
     724                 :          0 :                         goto exit;
     725                 :            :                 break;
     726                 :          0 :         case MEMIF_MSG_TYPE_INIT:
     727                 :            :                 /*
     728                 :            :                  * This cc does not have an interface associated with it.
     729                 :            :                  * If suitable interface is found it will be assigned here.
     730                 :            :                  */
     731                 :          0 :                 ret = memif_msg_receive_init(cc, &msg);
     732         [ #  # ]:          0 :                 if (ret < 0)
     733                 :          0 :                         goto exit;
     734                 :          0 :                 ret = memif_msg_enq_ack(cc->dev);
     735                 :            :                 if (ret < 0)
     736                 :          0 :                         goto exit;
     737                 :            :                 break;
     738                 :          0 :         case MEMIF_MSG_TYPE_ADD_REGION:
     739                 :          0 :                 ret = memif_msg_receive_add_region(cc->dev, &msg, afd);
     740         [ #  # ]:          0 :                 if (ret < 0)
     741                 :          0 :                         goto exit;
     742                 :          0 :                 ret = memif_msg_enq_ack(cc->dev);
     743                 :            :                 if (ret < 0)
     744                 :          0 :                         goto exit;
     745                 :            :                 break;
     746                 :          0 :         case MEMIF_MSG_TYPE_ADD_RING:
     747                 :          0 :                 ret = memif_msg_receive_add_ring(cc->dev, &msg, afd);
     748         [ #  # ]:          0 :                 if (ret < 0)
     749                 :          0 :                         goto exit;
     750                 :          0 :                 ret = memif_msg_enq_ack(cc->dev);
     751                 :            :                 if (ret < 0)
     752                 :          0 :                         goto exit;
     753                 :            :                 break;
     754                 :          0 :         case MEMIF_MSG_TYPE_CONNECT:
     755                 :          0 :                 ret = memif_msg_receive_connect(cc->dev, &msg);
     756         [ #  # ]:          0 :                 if (ret < 0)
     757                 :          0 :                         goto exit;
     758                 :          0 :                 ret = memif_msg_enq_connected(cc->dev);
     759         [ #  # ]:          0 :                 if (ret < 0)
     760                 :          0 :                         goto exit;
     761                 :            :                 break;
     762                 :          0 :         case MEMIF_MSG_TYPE_CONNECTED:
     763                 :          0 :                 ret = memif_msg_receive_connected(cc->dev, &msg);
     764                 :          0 :                 break;
     765                 :          0 :         case MEMIF_MSG_TYPE_DISCONNECT:
     766                 :          0 :                 ret = memif_msg_receive_disconnect(cc->dev, &msg);
     767         [ #  # ]:          0 :                 if (ret < 0)
     768                 :          0 :                         goto exit;
     769                 :            :                 break;
     770                 :          0 :         default:
     771                 :          0 :                 memif_msg_enq_disconnect(cc, "Unknown message type", 0);
     772                 :            :                 ret = -1;
     773                 :          0 :                 goto exit;
     774                 :            :         }
     775                 :            : 
     776                 :            :  exit:
     777                 :            :         return ret;
     778                 :            : }
     779                 :            : 
     780                 :            : static void
     781                 :          0 : memif_intr_handler(void *arg)
     782                 :            : {
     783                 :            :         struct memif_control_channel *cc = arg;
     784                 :            :         int ret;
     785                 :            : 
     786                 :          0 :         ret = memif_msg_receive(cc);
     787                 :            :         /* if driver failed to assign device */
     788         [ #  # ]:          0 :         if (cc->dev == NULL) {
     789                 :          0 :                 memif_msg_send_from_queue(cc);
     790                 :          0 :                 ret = rte_intr_callback_unregister_pending(cc->intr_handle,
     791                 :            :                                                            memif_intr_handler,
     792                 :            :                                                            cc,
     793                 :            :                                                            memif_intr_unregister_handler);
     794         [ #  # ]:          0 :                 if (ret < 0)
     795                 :          0 :                         MIF_LOG(WARNING,
     796                 :            :                                 "Failed to unregister control channel callback.");
     797                 :          0 :                 return;
     798                 :            :         }
     799                 :            :         /* if memif_msg_receive failed */
     800         [ #  # ]:          0 :         if (ret < 0)
     801                 :          0 :                 goto disconnect;
     802                 :            : 
     803                 :          0 :         ret = memif_msg_send_from_queue(cc);
     804         [ #  # ]:          0 :         if (ret < 0)
     805                 :          0 :                 goto disconnect;
     806                 :            : 
     807                 :            :         return;
     808                 :            : 
     809                 :          0 :  disconnect:
     810         [ #  # ]:          0 :         if (cc->dev == NULL) {
     811                 :          0 :                 MIF_LOG(WARNING, "eth dev not allocated");
     812                 :          0 :                 return;
     813                 :            :         }
     814                 :          0 :         memif_disconnect(cc->dev);
     815                 :            : }
     816                 :            : 
     817                 :            : static void
     818                 :          0 : memif_listener_handler(void *arg)
     819                 :            : {
     820                 :            :         struct memif_socket *socket = arg;
     821                 :            :         int sockfd;
     822                 :            :         int addr_len;
     823                 :            :         struct sockaddr_un client;
     824                 :            :         struct memif_control_channel *cc;
     825                 :            :         int ret;
     826                 :            : 
     827                 :          0 :         addr_len = sizeof(client);
     828                 :          0 :         sockfd = accept(rte_intr_fd_get(socket->intr_handle),
     829                 :            :                         (struct sockaddr *)&client, (socklen_t *)&addr_len);
     830         [ #  # ]:          0 :         if (sockfd < 0) {
     831                 :          0 :                 MIF_LOG(ERR,
     832                 :            :                         "Failed to accept connection request on socket fd %d",
     833                 :            :                         rte_intr_fd_get(socket->intr_handle));
     834                 :          0 :                 return;
     835                 :            :         }
     836                 :            : 
     837                 :          0 :         MIF_LOG(DEBUG, "%s: Connection request accepted.", socket->filename);
     838                 :            : 
     839                 :          0 :         cc = rte_zmalloc("memif-cc", sizeof(struct memif_control_channel), 0);
     840         [ #  # ]:          0 :         if (cc == NULL) {
     841                 :          0 :                 MIF_LOG(ERR, "Failed to allocate control channel.");
     842                 :          0 :                 goto error;
     843                 :            :         }
     844                 :            : 
     845                 :            :         /* Allocate interrupt instance */
     846                 :          0 :         cc->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
     847         [ #  # ]:          0 :         if (cc->intr_handle == NULL) {
     848                 :          0 :                 MIF_LOG(ERR, "Failed to allocate intr handle");
     849                 :          0 :                 goto error;
     850                 :            :         }
     851                 :            : 
     852         [ #  # ]:          0 :         if (rte_intr_fd_set(cc->intr_handle, sockfd))
     853                 :          0 :                 goto error;
     854                 :            : 
     855         [ #  # ]:          0 :         if (rte_intr_type_set(cc->intr_handle, RTE_INTR_HANDLE_EXT))
     856                 :          0 :                 goto error;
     857                 :            : 
     858                 :          0 :         cc->socket = socket;
     859                 :          0 :         cc->dev = NULL;
     860                 :          0 :         TAILQ_INIT(&cc->msg_queue);
     861                 :            : 
     862                 :          0 :         ret = rte_intr_callback_register(cc->intr_handle, memif_intr_handler,
     863                 :            :                                          cc);
     864         [ #  # ]:          0 :         if (ret < 0) {
     865                 :          0 :                 MIF_LOG(ERR, "Failed to register control channel callback.");
     866                 :          0 :                 goto error;
     867                 :            :         }
     868                 :            : 
     869                 :          0 :         ret = memif_msg_enq_hello(cc);
     870         [ #  # ]:          0 :         if (ret < 0) {
     871                 :          0 :                 MIF_LOG(ERR, "Failed to enqueue hello message.");
     872                 :          0 :                 goto error;
     873                 :            :         }
     874                 :          0 :         ret = memif_msg_send_from_queue(cc);
     875         [ #  # ]:          0 :         if (ret < 0)
     876                 :          0 :                 goto error;
     877                 :            : 
     878                 :            :         return;
     879                 :            : 
     880                 :          0 :  error:
     881                 :            :         if (sockfd >= 0) {
     882                 :          0 :                 close(sockfd);
     883                 :            :                 sockfd = -1;
     884                 :            :         }
     885         [ #  # ]:          0 :         if (cc != NULL) {
     886                 :          0 :                 rte_intr_instance_free(cc->intr_handle);
     887                 :          0 :                 rte_free(cc);
     888                 :            :         }
     889                 :            : }
     890                 :            : 
     891                 :            : static struct memif_socket *
     892                 :          0 : memif_socket_create(char *key, uint8_t listener, bool is_abstract, uid_t owner_uid, gid_t owner_gid)
     893                 :            : {
     894                 :            :         struct memif_socket *sock;
     895                 :          0 :         struct sockaddr_un un = { 0 };
     896                 :            :         uint32_t sunlen;
     897                 :            :         int sockfd;
     898                 :            :         int ret;
     899                 :          0 :         int on = 1;
     900                 :            : 
     901                 :          0 :         sock = rte_zmalloc("memif-socket", sizeof(struct memif_socket), 0);
     902         [ #  # ]:          0 :         if (sock == NULL) {
     903                 :          0 :                 MIF_LOG(ERR, "Failed to allocate memory for memif socket");
     904                 :          0 :                 return NULL;
     905                 :            :         }
     906                 :            : 
     907                 :          0 :         sock->listener = listener;
     908         [ #  # ]:          0 :         strlcpy(sock->filename, key, MEMIF_SOCKET_UN_SIZE);
     909                 :          0 :         TAILQ_INIT(&sock->dev_queue);
     910                 :            : 
     911         [ #  # ]:          0 :         if (listener != 0) {
     912                 :          0 :                 sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
     913         [ #  # ]:          0 :                 if (sockfd < 0)
     914                 :          0 :                         goto error;
     915                 :            : 
     916                 :          0 :                 un.sun_family = AF_UNIX;
     917         [ #  # ]:          0 :                 if (is_abstract) {
     918                 :            :                         /* abstract address */
     919                 :          0 :                         un.sun_path[0] = '\0';
     920                 :            :                         strlcpy(un.sun_path + 1, sock->filename, MEMIF_SOCKET_UN_SIZE - 1);
     921                 :          0 :                         sunlen = RTE_MIN(1 + strlen(sock->filename),
     922                 :            :                                          MEMIF_SOCKET_UN_SIZE) +
     923                 :          0 :                                  sizeof(un) - sizeof(un.sun_path);
     924                 :            :                 } else {
     925                 :            :                         sunlen = sizeof(un);
     926                 :            :                         strlcpy(un.sun_path, sock->filename, MEMIF_SOCKET_UN_SIZE);
     927                 :            :                 }
     928                 :            : 
     929                 :          0 :                 ret = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &on,
     930                 :            :                                  sizeof(on));
     931         [ #  # ]:          0 :                 if (ret < 0)
     932                 :          0 :                         goto error;
     933                 :            : 
     934                 :          0 :                 ret = bind(sockfd, (struct sockaddr *)&un, sunlen);
     935         [ #  # ]:          0 :                 if (ret < 0)
     936                 :          0 :                         goto error;
     937                 :            : 
     938                 :          0 :                 ret = listen(sockfd, 1);
     939         [ #  # ]:          0 :                 if (ret < 0)
     940                 :          0 :                         goto error;
     941                 :            : 
     942                 :          0 :                 MIF_LOG(DEBUG, "Memif listener socket %s created.", sock->filename);
     943                 :            : 
     944   [ #  #  #  # ]:          0 :                 if (!is_abstract && (owner_uid != (uid_t)-1 || owner_gid != (gid_t)-1)) {
     945                 :          0 :                         ret = chown(sock->filename, owner_uid, owner_gid);
     946         [ #  # ]:          0 :                         if (ret < 0) {
     947                 :          0 :                                 MIF_LOG(ERR, "Failed to change listener socket owner");
     948                 :          0 :                                 goto error;
     949                 :            :                         }
     950                 :            :                 }
     951                 :            : 
     952                 :            :                 /* Allocate interrupt instance */
     953                 :          0 :                 sock->intr_handle =
     954                 :          0 :                         rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
     955         [ #  # ]:          0 :                 if (sock->intr_handle == NULL) {
     956                 :          0 :                         MIF_LOG(ERR, "Failed to allocate intr handle");
     957                 :          0 :                         goto error;
     958                 :            :                 }
     959                 :            : 
     960         [ #  # ]:          0 :                 if (rte_intr_fd_set(sock->intr_handle, sockfd))
     961                 :          0 :                         goto error;
     962                 :            : 
     963         [ #  # ]:          0 :                 if (rte_intr_type_set(sock->intr_handle, RTE_INTR_HANDLE_EXT))
     964                 :          0 :                         goto error;
     965                 :            : 
     966                 :          0 :                 ret = rte_intr_callback_register(sock->intr_handle,
     967                 :            :                                                  memif_listener_handler, sock);
     968         [ #  # ]:          0 :                 if (ret < 0) {
     969                 :          0 :                         MIF_LOG(ERR, "Failed to register interrupt "
     970                 :            :                                 "callback for listener socket");
     971                 :          0 :                         return NULL;
     972                 :            :                 }
     973                 :            :         }
     974                 :            : 
     975                 :            :         return sock;
     976                 :            : 
     977                 :          0 :  error:
     978                 :          0 :         MIF_LOG(ERR, "Failed to setup socket %s: %s", key, strerror(errno));
     979                 :            :         if (sock != NULL) {
     980                 :          0 :                 rte_intr_instance_free(sock->intr_handle);
     981                 :          0 :                 rte_free(sock);
     982                 :            :         }
     983         [ #  # ]:          0 :         if (sockfd >= 0)
     984                 :          0 :                 close(sockfd);
     985                 :            :         return NULL;
     986                 :            : }
     987                 :            : 
     988                 :            : static struct rte_hash *
     989                 :          0 : memif_create_socket_hash(void)
     990                 :            : {
     991                 :          0 :         struct rte_hash_parameters params = { 0 };
     992                 :            : 
     993                 :          0 :         params.name = MEMIF_SOCKET_HASH_NAME;
     994                 :          0 :         params.entries = 256;
     995                 :          0 :         params.key_len = MEMIF_SOCKET_UN_SIZE;
     996                 :          0 :         params.hash_func = rte_jhash;
     997                 :            :         params.hash_func_init_val = 0;
     998                 :          0 :         params.socket_id = SOCKET_ID_ANY;
     999                 :          0 :         return rte_hash_create(&params);
    1000                 :            : }
    1001                 :            : 
    1002                 :            : int
    1003                 :          0 : memif_socket_init(struct rte_eth_dev *dev, const char *socket_filename)
    1004                 :            : {
    1005                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1006                 :          0 :         struct memif_socket *socket = NULL;
    1007                 :            :         struct memif_socket_dev_list_elt *elt;
    1008                 :            :         struct pmd_internals *tmp_pmd;
    1009                 :            :         struct rte_hash *hash;
    1010                 :            :         int ret;
    1011                 :            :         char key[MEMIF_SOCKET_UN_SIZE];
    1012                 :            : 
    1013                 :          0 :         hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME);
    1014         [ #  # ]:          0 :         if (hash == NULL) {
    1015                 :          0 :                 hash = memif_create_socket_hash();
    1016         [ #  # ]:          0 :                 if (hash == NULL) {
    1017                 :          0 :                         MIF_LOG(ERR, "Failed to create memif socket hash.");
    1018                 :          0 :                         return -1;
    1019                 :            :                 }
    1020                 :            :         }
    1021                 :            : 
    1022                 :            :         memset(key, 0, MEMIF_SOCKET_UN_SIZE);
    1023                 :            :         strlcpy(key, socket_filename, MEMIF_SOCKET_UN_SIZE);
    1024                 :          0 :         ret = rte_hash_lookup_data(hash, key, (void **)&socket);
    1025         [ #  # ]:          0 :         if (ret < 0) {
    1026                 :          0 :                 socket = memif_socket_create(key,
    1027                 :          0 :                         (pmd->role == MEMIF_ROLE_CLIENT) ? 0 : 1,
    1028                 :          0 :                         pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT,
    1029                 :            :                         pmd->owner_uid, pmd->owner_gid);
    1030         [ #  # ]:          0 :                 if (socket == NULL)
    1031                 :            :                         return -1;
    1032                 :          0 :                 ret = rte_hash_add_key_data(hash, key, socket);
    1033         [ #  # ]:          0 :                 if (ret < 0) {
    1034                 :          0 :                         MIF_LOG(ERR, "Failed to add socket to socket hash.");
    1035                 :          0 :                         return ret;
    1036                 :            :                 }
    1037                 :            :         }
    1038                 :          0 :         pmd->socket_filename = socket->filename;
    1039                 :            : 
    1040         [ #  # ]:          0 :         TAILQ_FOREACH(elt, &socket->dev_queue, next) {
    1041                 :          0 :                 tmp_pmd = elt->dev->data->dev_private;
    1042         [ #  # ]:          0 :                 if (tmp_pmd->id == pmd->id && tmp_pmd->role == pmd->role) {
    1043                 :          0 :                         MIF_LOG(ERR, "Two interfaces with the same id (%d) can "
    1044                 :            :                                 "not have the same role.", pmd->id);
    1045                 :          0 :                         return -1;
    1046                 :            :                 }
    1047                 :            :         }
    1048                 :            : 
    1049                 :          0 :         elt = rte_malloc("pmd-queue", sizeof(struct memif_socket_dev_list_elt), 0);
    1050         [ #  # ]:          0 :         if (elt == NULL) {
    1051                 :          0 :                 MIF_LOG(ERR, "Failed to add device to socket device list.");
    1052                 :          0 :                 return -1;
    1053                 :            :         }
    1054                 :          0 :         elt->dev = dev;
    1055                 :          0 :         TAILQ_INSERT_TAIL(&socket->dev_queue, elt, next);
    1056                 :            : 
    1057                 :          0 :         return 0;
    1058                 :            : }
    1059                 :            : 
    1060                 :            : void
    1061                 :          0 : memif_socket_remove_device(struct rte_eth_dev *dev)
    1062                 :            : {
    1063                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1064                 :          0 :         struct memif_socket *socket = NULL;
    1065                 :            :         struct memif_socket_dev_list_elt *elt, *next;
    1066                 :            :         struct rte_hash *hash;
    1067                 :            :         int ret;
    1068                 :            : 
    1069                 :          0 :         hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME);
    1070         [ #  # ]:          0 :         if (hash == NULL)
    1071                 :          0 :                 return;
    1072                 :            : 
    1073         [ #  # ]:          0 :         if (pmd->socket_filename == NULL)
    1074                 :            :                 return;
    1075                 :            : 
    1076         [ #  # ]:          0 :         if (rte_hash_lookup_data(hash, pmd->socket_filename, (void **)&socket) < 0)
    1077                 :            :                 return;
    1078                 :            : 
    1079         [ #  # ]:          0 :         for (elt = TAILQ_FIRST(&socket->dev_queue); elt != NULL; elt = next) {
    1080                 :          0 :                 next = TAILQ_NEXT(elt, next);
    1081         [ #  # ]:          0 :                 if (elt->dev == dev) {
    1082         [ #  # ]:          0 :                         TAILQ_REMOVE(&socket->dev_queue, elt, next);
    1083                 :          0 :                         rte_free(elt);
    1084                 :          0 :                         pmd->socket_filename = NULL;
    1085                 :            :                 }
    1086                 :            :         }
    1087                 :            : 
    1088                 :            :         /* remove socket, if this was the last device using it */
    1089         [ #  # ]:          0 :         if (TAILQ_EMPTY(&socket->dev_queue)) {
    1090                 :          0 :                 rte_hash_del_key(hash, socket->filename);
    1091   [ #  #  #  # ]:          0 :                 if (socket->listener && !(pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT)) {
    1092                 :            :                         /* remove listener socket file,
    1093                 :            :                          * so we can create new one later.
    1094                 :            :                          */
    1095                 :          0 :                         ret = remove(socket->filename);
    1096         [ #  # ]:          0 :                         if (ret < 0)
    1097                 :          0 :                                 MIF_LOG(ERR, "Failed to remove socket file: %s",
    1098                 :            :                                         socket->filename);
    1099                 :            :                 }
    1100         [ #  # ]:          0 :                 if (pmd->role != MEMIF_ROLE_CLIENT)
    1101                 :          0 :                         rte_intr_instance_free(socket->intr_handle);
    1102                 :          0 :                 rte_free(socket);
    1103                 :            :         }
    1104                 :            : }
    1105                 :            : 
    1106                 :            : int
    1107                 :          0 : memif_connect_server(struct rte_eth_dev *dev)
    1108                 :            : {
    1109                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1110                 :            : 
    1111                 :          0 :         memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE);
    1112                 :          0 :         memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE);
    1113                 :          0 :         pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED;
    1114                 :          0 :         return 0;
    1115                 :            : }
    1116                 :            : 
    1117                 :            : int
    1118                 :          0 : memif_connect_client(struct rte_eth_dev *dev)
    1119                 :            : {
    1120                 :            :         int sockfd;
    1121                 :            :         int ret;
    1122                 :            :         uint32_t sunlen;
    1123                 :          0 :         struct sockaddr_un sun = { 0 };
    1124                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1125                 :            : 
    1126                 :          0 :         memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE);
    1127                 :          0 :         memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE);
    1128                 :          0 :         pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED;
    1129                 :            : 
    1130                 :          0 :         sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
    1131         [ #  # ]:          0 :         if (sockfd < 0) {
    1132                 :          0 :                 MIF_LOG(ERR, "Failed to open socket.");
    1133                 :          0 :                 return -1;
    1134                 :            :         }
    1135                 :            : 
    1136                 :          0 :         sun.sun_family = AF_UNIX;
    1137                 :            :         sunlen = sizeof(struct sockaddr_un);
    1138         [ #  # ]:          0 :         if (pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT) {
    1139                 :            :                 /* abstract address */
    1140                 :          0 :                 sun.sun_path[0] = '\0';
    1141                 :          0 :                 strlcpy(sun.sun_path + 1,  pmd->socket_filename, MEMIF_SOCKET_UN_SIZE - 1);
    1142                 :          0 :                 sunlen = RTE_MIN(strlen(pmd->socket_filename) + 1,
    1143                 :            :                                  MEMIF_SOCKET_UN_SIZE) +
    1144                 :          0 :                          sizeof(sun) - sizeof(sun.sun_path);
    1145                 :            :         } else {
    1146                 :          0 :                 strlcpy(sun.sun_path,  pmd->socket_filename, MEMIF_SOCKET_UN_SIZE);
    1147                 :            :         }
    1148                 :            : 
    1149                 :          0 :         ret = connect(sockfd, (struct sockaddr *)&sun, sunlen);
    1150         [ #  # ]:          0 :         if (ret < 0) {
    1151                 :          0 :                 MIF_LOG(ERR, "Failed to connect socket: %s.", pmd->socket_filename);
    1152                 :          0 :                 goto error;
    1153                 :            :         }
    1154                 :            : 
    1155                 :          0 :         MIF_LOG(DEBUG, "Memif socket: %s connected.", pmd->socket_filename);
    1156                 :            : 
    1157                 :          0 :         pmd->cc = rte_zmalloc("memif-cc",
    1158                 :            :                               sizeof(struct memif_control_channel), 0);
    1159         [ #  # ]:          0 :         if (pmd->cc == NULL) {
    1160                 :          0 :                 MIF_LOG(ERR, "Failed to allocate control channel.");
    1161                 :          0 :                 goto error;
    1162                 :            :         }
    1163                 :            : 
    1164                 :            :         /* Allocate interrupt instance */
    1165                 :          0 :         pmd->cc->intr_handle =
    1166                 :          0 :                 rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
    1167         [ #  # ]:          0 :         if (pmd->cc->intr_handle == NULL) {
    1168                 :          0 :                 MIF_LOG(ERR, "Failed to allocate intr handle");
    1169                 :          0 :                 goto error;
    1170                 :            :         }
    1171                 :            : 
    1172         [ #  # ]:          0 :         if (rte_intr_fd_set(pmd->cc->intr_handle, sockfd))
    1173                 :          0 :                 goto error;
    1174                 :            : 
    1175         [ #  # ]:          0 :         if (rte_intr_type_set(pmd->cc->intr_handle, RTE_INTR_HANDLE_EXT))
    1176                 :          0 :                 goto error;
    1177                 :            : 
    1178                 :          0 :         pmd->cc->socket = NULL;
    1179                 :          0 :         pmd->cc->dev = dev;
    1180                 :          0 :         TAILQ_INIT(&pmd->cc->msg_queue);
    1181                 :            : 
    1182                 :          0 :         ret = rte_intr_callback_register(pmd->cc->intr_handle,
    1183                 :            :                                          memif_intr_handler, pmd->cc);
    1184         [ #  # ]:          0 :         if (ret < 0) {
    1185                 :          0 :                 MIF_LOG(ERR, "Failed to register interrupt callback for control fd");
    1186                 :          0 :                 goto error;
    1187                 :            :         }
    1188                 :            : 
    1189                 :            :         return 0;
    1190                 :            : 
    1191                 :          0 :  error:
    1192                 :            :         if (sockfd >= 0) {
    1193                 :          0 :                 close(sockfd);
    1194                 :            :                 sockfd = -1;
    1195                 :            :         }
    1196         [ #  # ]:          0 :         if (pmd->cc != NULL) {
    1197                 :          0 :                 rte_intr_instance_free(pmd->cc->intr_handle);
    1198                 :          0 :                 rte_free(pmd->cc);
    1199                 :          0 :                 pmd->cc = NULL;
    1200                 :            :         }
    1201                 :            :         return -1;
    1202                 :            : }

Generated by: LCOV version 1.14