LCOV - code coverage report
Current view: top level - drivers/net/memif - rte_eth_memif.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 2 1001 0.2 %
Date: 2025-03-01 20:23:48 Functions: 2 45 4.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 521 0.2 %

           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/un.h>
      11                 :            : #include <sys/ioctl.h>
      12                 :            : #include <sys/mman.h>
      13                 :            : #include <linux/if_ether.h>
      14                 :            : #include <errno.h>
      15                 :            : #include <sys/eventfd.h>
      16                 :            : 
      17                 :            : #include <rte_version.h>
      18                 :            : #include <rte_mbuf.h>
      19                 :            : #include <rte_ether.h>
      20                 :            : #include <ethdev_driver.h>
      21                 :            : #include <ethdev_vdev.h>
      22                 :            : #include <rte_malloc.h>
      23                 :            : #include <rte_kvargs.h>
      24                 :            : #include <bus_vdev_driver.h>
      25                 :            : #include <rte_string_fns.h>
      26                 :            : #include <rte_errno.h>
      27                 :            : #include <rte_memory.h>
      28                 :            : #include <rte_memzone.h>
      29                 :            : #include <rte_eal_memconfig.h>
      30                 :            : 
      31                 :            : #include "rte_eth_memif.h"
      32                 :            : #include "memif_socket.h"
      33                 :            : 
      34                 :            : #define ETH_MEMIF_ID_ARG                "id"
      35                 :            : #define ETH_MEMIF_ROLE_ARG              "role"
      36                 :            : #define ETH_MEMIF_PKT_BUFFER_SIZE_ARG   "bsize"
      37                 :            : #define ETH_MEMIF_RING_SIZE_ARG         "rsize"
      38                 :            : #define ETH_MEMIF_SOCKET_ARG            "socket"
      39                 :            : #define ETH_MEMIF_SOCKET_ABSTRACT_ARG   "socket-abstract"
      40                 :            : #define ETH_MEMIF_OWNER_UID_ARG         "owner-uid"
      41                 :            : #define ETH_MEMIF_OWNER_GID_ARG         "owner-gid"
      42                 :            : #define ETH_MEMIF_MAC_ARG               "mac"
      43                 :            : #define ETH_MEMIF_ZC_ARG                "zero-copy"
      44                 :            : #define ETH_MEMIF_SECRET_ARG            "secret"
      45                 :            : 
      46                 :            : static const char * const valid_arguments[] = {
      47                 :            :         ETH_MEMIF_ID_ARG,
      48                 :            :         ETH_MEMIF_ROLE_ARG,
      49                 :            :         ETH_MEMIF_PKT_BUFFER_SIZE_ARG,
      50                 :            :         ETH_MEMIF_RING_SIZE_ARG,
      51                 :            :         ETH_MEMIF_SOCKET_ARG,
      52                 :            :         ETH_MEMIF_SOCKET_ABSTRACT_ARG,
      53                 :            :         ETH_MEMIF_OWNER_UID_ARG,
      54                 :            :         ETH_MEMIF_OWNER_GID_ARG,
      55                 :            :         ETH_MEMIF_MAC_ARG,
      56                 :            :         ETH_MEMIF_ZC_ARG,
      57                 :            :         ETH_MEMIF_SECRET_ARG,
      58                 :            :         NULL
      59                 :            : };
      60                 :            : 
      61                 :            : static const struct rte_eth_link pmd_link = {
      62                 :            :         .link_speed = RTE_ETH_SPEED_NUM_100G,
      63                 :            :         .link_duplex = RTE_ETH_LINK_FULL_DUPLEX,
      64                 :            :         .link_status = RTE_ETH_LINK_DOWN,
      65                 :            :         .link_autoneg = RTE_ETH_LINK_AUTONEG
      66                 :            : };
      67                 :            : 
      68                 :            : #define MEMIF_MP_SEND_REGION            "memif_mp_send_region"
      69                 :            : 
      70                 :            : 
      71                 :            : static int memif_region_init_zc(const struct rte_memseg_list *msl,
      72                 :            :                                 const struct rte_memseg *ms, void *arg);
      73                 :            : 
      74                 :            : const char *
      75                 :          0 : memif_version(void)
      76                 :            : {
      77                 :          0 :         return ("memif-" RTE_STR(MEMIF_VERSION_MAJOR) "." RTE_STR(MEMIF_VERSION_MINOR));
      78                 :            : }
      79                 :            : 
      80                 :            : /* Message header to synchronize regions */
      81                 :            : struct mp_region_msg {
      82                 :            :         char port_name[RTE_DEV_NAME_MAX_LEN];
      83                 :            :         memif_region_index_t idx;
      84                 :            :         memif_region_size_t size;
      85                 :            : };
      86                 :            : 
      87                 :            : static int
      88                 :          0 : memif_mp_send_region(const struct rte_mp_msg *msg, const void *peer)
      89                 :            : {
      90                 :            :         struct rte_eth_dev *dev;
      91                 :            :         struct pmd_process_private *proc_private;
      92                 :            :         const struct mp_region_msg *msg_param = (const struct mp_region_msg *)msg->param;
      93                 :            :         struct rte_mp_msg reply;
      94                 :            :         struct mp_region_msg *reply_param = (struct mp_region_msg *)reply.param;
      95                 :            : 
      96                 :            :         /* Get requested port */
      97                 :          0 :         dev = rte_eth_dev_get_by_name(msg_param->port_name);
      98         [ #  # ]:          0 :         if (!dev) {
      99                 :          0 :                 MIF_LOG(ERR, "Failed to get port id for %s",
     100                 :            :                         msg_param->port_name);
     101                 :          0 :                 return -1;
     102                 :            :         }
     103         [ #  # ]:          0 :         proc_private = dev->process_private;
     104                 :            : 
     105                 :            :         memset(&reply, 0, sizeof(reply));
     106         [ #  # ]:          0 :         strlcpy(reply.name, msg->name, sizeof(reply.name));
     107                 :          0 :         reply_param->idx = msg_param->idx;
     108         [ #  # ]:          0 :         if (proc_private->regions[msg_param->idx] != NULL) {
     109                 :          0 :                 reply_param->size = proc_private->regions[msg_param->idx]->region_size;
     110                 :          0 :                 reply.fds[0] = proc_private->regions[msg_param->idx]->fd;
     111                 :          0 :                 reply.num_fds = 1;
     112                 :            :         }
     113                 :          0 :         reply.len_param = sizeof(*reply_param);
     114         [ #  # ]:          0 :         if (rte_mp_reply(&reply, peer) < 0) {
     115                 :          0 :                 MIF_LOG(ERR, "Failed to reply to an add region request");
     116                 :          0 :                 return -1;
     117                 :            :         }
     118                 :            : 
     119                 :            :         return 0;
     120                 :            : }
     121                 :            : 
     122                 :            : /*
     123                 :            :  * Request regions
     124                 :            :  * Called by secondary process, when ports link status goes up.
     125                 :            :  */
     126                 :            : static int
     127                 :          0 : memif_mp_request_regions(struct rte_eth_dev *dev)
     128                 :            : {
     129                 :            :         int ret, i;
     130                 :          0 :         struct timespec timeout = {.tv_sec = 5, .tv_nsec = 0};
     131                 :            :         struct rte_mp_msg msg, *reply;
     132                 :            :         struct rte_mp_reply replies;
     133                 :            :         struct mp_region_msg *msg_param = (struct mp_region_msg *)msg.param;
     134                 :            :         struct mp_region_msg *reply_param;
     135                 :            :         struct memif_region *r;
     136                 :          0 :         struct pmd_process_private *proc_private = dev->process_private;
     137                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     138                 :            :         /* in case of zero-copy client, only request region 0 */
     139         [ #  # ]:          0 :         uint16_t max_region_num = (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) ?
     140                 :            :                                    1 : ETH_MEMIF_MAX_REGION_NUM;
     141                 :            : 
     142                 :          0 :         MIF_LOG(DEBUG, "Requesting memory regions");
     143                 :            : 
     144         [ #  # ]:          0 :         for (i = 0; i < max_region_num; i++) {
     145                 :            :                 /* Prepare the message */
     146                 :            :                 memset(&msg, 0, sizeof(msg));
     147                 :            :                 strlcpy(msg.name, MEMIF_MP_SEND_REGION, sizeof(msg.name));
     148                 :          0 :                 strlcpy(msg_param->port_name, dev->data->name,
     149                 :            :                         sizeof(msg_param->port_name));
     150                 :          0 :                 msg_param->idx = i;
     151                 :          0 :                 msg.len_param = sizeof(*msg_param);
     152                 :            : 
     153                 :            :                 /* Send message */
     154                 :          0 :                 ret = rte_mp_request_sync(&msg, &replies, &timeout);
     155   [ #  #  #  # ]:          0 :                 if (ret < 0 || replies.nb_received != 1) {
     156                 :          0 :                         MIF_LOG(ERR, "Failed to send mp msg: %d",
     157                 :            :                                 rte_errno);
     158                 :          0 :                         return -1;
     159                 :            :                 }
     160                 :            : 
     161                 :          0 :                 reply = &replies.msgs[0];
     162                 :            :                 reply_param = (struct mp_region_msg *)reply->param;
     163                 :            : 
     164         [ #  # ]:          0 :                 if (reply_param->size > 0) {
     165                 :          0 :                         r = rte_zmalloc("region", sizeof(struct memif_region), 0);
     166         [ #  # ]:          0 :                         if (r == NULL) {
     167                 :          0 :                                 MIF_LOG(ERR, "Failed to alloc memif region.");
     168                 :          0 :                                 free(reply);
     169                 :          0 :                                 return -ENOMEM;
     170                 :            :                         }
     171                 :          0 :                         r->region_size = reply_param->size;
     172         [ #  # ]:          0 :                         if (reply->num_fds < 1) {
     173                 :          0 :                                 MIF_LOG(ERR, "Missing file descriptor.");
     174                 :          0 :                                 free(reply);
     175                 :          0 :                                 return -1;
     176                 :            :                         }
     177                 :          0 :                         r->fd = reply->fds[0];
     178                 :          0 :                         r->addr = NULL;
     179                 :            : 
     180                 :          0 :                         proc_private->regions[reply_param->idx] = r;
     181                 :          0 :                         proc_private->regions_num++;
     182                 :            :                 }
     183                 :          0 :                 free(reply);
     184                 :            :         }
     185                 :            : 
     186         [ #  # ]:          0 :         if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
     187                 :          0 :                 ret = rte_memseg_walk(memif_region_init_zc, (void *)proc_private);
     188         [ #  # ]:          0 :                 if (ret < 0)
     189                 :            :                         return ret;
     190                 :            :         }
     191                 :            : 
     192                 :          0 :         return memif_connect(dev);
     193                 :            : }
     194                 :            : 
     195                 :            : static int
     196                 :          0 : memif_dev_info(struct rte_eth_dev *dev __rte_unused, struct rte_eth_dev_info *dev_info)
     197                 :            : {
     198                 :          0 :         dev_info->max_mac_addrs = 1;
     199                 :          0 :         dev_info->max_rx_pktlen = RTE_ETHER_MAX_LEN;
     200                 :          0 :         dev_info->max_rx_queues = ETH_MEMIF_MAX_NUM_Q_PAIRS;
     201                 :          0 :         dev_info->max_tx_queues = ETH_MEMIF_MAX_NUM_Q_PAIRS;
     202                 :          0 :         dev_info->min_rx_bufsize = 0;
     203                 :          0 :         dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
     204                 :            : 
     205                 :          0 :         return 0;
     206                 :            : }
     207                 :            : 
     208                 :            : static memif_ring_t *
     209                 :            : memif_get_ring(struct pmd_internals *pmd, struct pmd_process_private *proc_private,
     210                 :            :                memif_ring_type_t type, uint16_t ring_num)
     211                 :            : {
     212                 :            :         /* rings only in region 0 */
     213                 :          0 :         void *p = proc_private->regions[0]->addr;
     214                 :          0 :         int ring_size = sizeof(memif_ring_t) + sizeof(memif_desc_t) *
     215                 :          0 :             (1 << pmd->run.log2_ring_size);
     216                 :            : 
     217                 :          0 :         p = (uint8_t *)p + (ring_num + type * pmd->run.num_c2s_rings) * ring_size;
     218                 :            : 
     219                 :            :         return (memif_ring_t *)p;
     220                 :            : }
     221                 :            : 
     222                 :            : static memif_region_offset_t
     223                 :            : memif_get_ring_offset(struct rte_eth_dev *dev, struct memif_queue *mq,
     224                 :            :                       memif_ring_type_t type, uint16_t num)
     225                 :            : {
     226                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     227                 :          0 :         struct pmd_process_private *proc_private = dev->process_private;
     228                 :            : 
     229                 :          0 :         return ((uint8_t *)memif_get_ring(pmd, proc_private, type, num) -
     230                 :            :                 (uint8_t *)proc_private->regions[mq->region]->addr);
     231                 :            : }
     232                 :            : 
     233                 :            : static memif_ring_t *
     234                 :            : memif_get_ring_from_queue(struct pmd_process_private *proc_private,
     235                 :            :                           struct memif_queue *mq)
     236                 :            : {
     237                 :            :         struct memif_region *r;
     238                 :            : 
     239                 :          0 :         r = proc_private->regions[mq->region];
     240   [ #  #  #  # ]:          0 :         if (r == NULL)
     241                 :            :                 return NULL;
     242                 :            : 
     243                 :          0 :         return (memif_ring_t *)((uint8_t *)r->addr + mq->ring_offset);
     244                 :            : }
     245                 :            : 
     246                 :            : static void *
     247                 :            : memif_get_buffer(struct pmd_process_private *proc_private, memif_desc_t *d)
     248                 :            : {
     249                 :          0 :         return ((uint8_t *)proc_private->regions[d->region]->addr + d->offset);
     250                 :            : }
     251                 :            : 
     252                 :            : /* Free mbufs received by server */
     253                 :            : static void
     254                 :          0 : memif_free_stored_mbufs(struct pmd_process_private *proc_private, struct memif_queue *mq)
     255                 :            : {
     256                 :            :         uint16_t cur_tail;
     257         [ #  # ]:          0 :         uint16_t mask = (1 << mq->log2_ring_size) - 1;
     258                 :            :         memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
     259                 :            : 
     260                 :            :         /* FIXME: improve performance */
     261                 :            :         /* The ring->tail acts as a guard variable between Tx and Rx
     262                 :            :          * threads, so using load-acquire pairs with store-release
     263                 :            :          * in function eth_memif_rx for C2S queues.
     264                 :            :          */
     265                 :          0 :         cur_tail = rte_atomic_load_explicit(&ring->tail, rte_memory_order_acquire);
     266         [ #  # ]:          0 :         while (mq->last_tail != cur_tail) {
     267         [ #  # ]:          0 :                 RTE_MBUF_PREFETCH_TO_FREE(mq->buffers[(mq->last_tail + 1) & mask]);
     268         [ #  # ]:          0 :                 rte_pktmbuf_free_seg(mq->buffers[mq->last_tail & mask]);
     269                 :          0 :                 mq->last_tail++;
     270                 :            :         }
     271                 :          0 : }
     272                 :            : 
     273                 :            : static int
     274                 :            : memif_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *cur_tail,
     275                 :            :                     struct rte_mbuf *tail)
     276                 :            : {
     277                 :            :         /* Check for number-of-segments-overflow */
     278         [ #  # ]:          0 :         if (unlikely(head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS))
     279                 :            :                 return -EOVERFLOW;
     280                 :            : 
     281                 :            :         /* Chain 'tail' onto the old tail */
     282                 :          0 :         cur_tail->next = tail;
     283                 :            : 
     284                 :            :         /* accumulate number of segments and total length. */
     285                 :          0 :         head->nb_segs = (uint16_t)(head->nb_segs + tail->nb_segs);
     286                 :            : 
     287                 :          0 :         tail->pkt_len = tail->data_len;
     288                 :          0 :         head->pkt_len += tail->pkt_len;
     289                 :            : 
     290                 :          0 :         return 0;
     291                 :            : }
     292                 :            : 
     293                 :            : static uint16_t
     294                 :          0 : eth_memif_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
     295                 :            : {
     296                 :            :         struct memif_queue *mq = queue;
     297                 :          0 :         struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private;
     298         [ #  # ]:          0 :         struct pmd_process_private *proc_private =
     299                 :            :                 rte_eth_devices[mq->in_port].process_private;
     300                 :            :         memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
     301                 :            :         uint16_t cur_slot, last_slot, n_slots, ring_size, mask, s0;
     302                 :            :         uint16_t pkts, rx_pkts, n_rx_pkts = 0;
     303         [ #  # ]:          0 :         uint16_t mbuf_size = rte_pktmbuf_data_room_size(mq->mempool) -
     304                 :            :                 RTE_PKTMBUF_HEADROOM;
     305                 :            :         uint16_t src_len, src_off, dst_len, dst_off, cp_len;
     306                 :          0 :         memif_ring_type_t type = mq->type;
     307                 :            :         memif_desc_t *d0;
     308                 :            :         struct rte_mbuf *mbuf, *mbuf_head, *mbuf_tail;
     309                 :            :         uint64_t b;
     310                 :            :         ssize_t size __rte_unused;
     311                 :            :         uint16_t head;
     312                 :            :         int ret;
     313                 :            :         struct rte_eth_link link;
     314                 :            : 
     315         [ #  # ]:          0 :         if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0))
     316                 :            :                 return 0;
     317         [ #  # ]:          0 :         if (unlikely(ring == NULL)) {
     318                 :            :                 /* Secondary process will attempt to request regions. */
     319                 :          0 :                 ret = rte_eth_link_get(mq->in_port, &link);
     320         [ #  # ]:          0 :                 if (ret < 0)
     321                 :          0 :                         MIF_LOG(ERR, "Failed to get port %u link info: %s",
     322                 :            :                                 mq->in_port, rte_strerror(-ret));
     323                 :          0 :                 return 0;
     324                 :            :         }
     325                 :            : 
     326                 :            :         /* consume interrupt */
     327   [ #  #  #  # ]:          0 :         if (((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) &&
     328                 :          0 :             (rte_intr_fd_get(mq->intr_handle) >= 0))
     329                 :          0 :                 size = read(rte_intr_fd_get(mq->intr_handle), &b,
     330                 :            :                             sizeof(b));
     331                 :            : 
     332                 :          0 :         ring_size = 1 << mq->log2_ring_size;
     333                 :          0 :         mask = ring_size - 1;
     334                 :            : 
     335         [ #  # ]:          0 :         if (type == MEMIF_RING_C2S) {
     336                 :          0 :                 cur_slot = mq->last_head;
     337                 :          0 :                 last_slot = rte_atomic_load_explicit(&ring->head, rte_memory_order_acquire);
     338                 :            :         } else {
     339                 :          0 :                 cur_slot = mq->last_tail;
     340                 :          0 :                 last_slot = rte_atomic_load_explicit(&ring->tail, rte_memory_order_acquire);
     341                 :            :         }
     342                 :            : 
     343         [ #  # ]:          0 :         if (cur_slot == last_slot)
     344                 :          0 :                 goto refill;
     345                 :          0 :         n_slots = last_slot - cur_slot;
     346                 :            : 
     347         [ #  # ]:          0 :         if (likely(mbuf_size >= pmd->cfg.pkt_buffer_size)) {
     348                 :            :                 struct rte_mbuf *mbufs[MAX_PKT_BURST];
     349                 :          0 : next_bulk:
     350                 :          0 :                 ret = rte_pktmbuf_alloc_bulk(mq->mempool, mbufs, MAX_PKT_BURST);
     351         [ #  # ]:          0 :                 if (unlikely(ret < 0))
     352                 :          0 :                         goto no_free_bufs;
     353                 :            : 
     354                 :            :                 rx_pkts = 0;
     355                 :          0 :                 pkts = nb_pkts < MAX_PKT_BURST ? nb_pkts : MAX_PKT_BURST;
     356         [ #  # ]:          0 :                 while (n_slots && rx_pkts < pkts) {
     357                 :          0 :                         mbuf_head = mbufs[rx_pkts];
     358                 :            :                         mbuf = mbuf_head;
     359                 :            : 
     360                 :          0 : next_slot1:
     361                 :          0 :                         mbuf->port = mq->in_port;
     362                 :          0 :                         s0 = cur_slot & mask;
     363                 :          0 :                         d0 = &ring->desc[s0];
     364                 :            : 
     365                 :          0 :                         cp_len = d0->length;
     366                 :            : 
     367                 :          0 :                         rte_pktmbuf_data_len(mbuf) = cp_len;
     368                 :          0 :                         rte_pktmbuf_pkt_len(mbuf) = cp_len;
     369         [ #  # ]:          0 :                         if (mbuf != mbuf_head)
     370                 :          0 :                                 rte_pktmbuf_pkt_len(mbuf_head) += cp_len;
     371                 :            : 
     372         [ #  # ]:          0 :                         rte_memcpy(rte_pktmbuf_mtod(mbuf, void *),
     373                 :            :                                 (uint8_t *)memif_get_buffer(proc_private, d0), cp_len);
     374                 :            : 
     375                 :          0 :                         cur_slot++;
     376                 :          0 :                         n_slots--;
     377                 :            : 
     378         [ #  # ]:          0 :                         if (d0->flags & MEMIF_DESC_FLAG_NEXT) {
     379                 :            :                                 mbuf_tail = mbuf;
     380                 :          0 :                                 mbuf = rte_pktmbuf_alloc(mq->mempool);
     381         [ #  # ]:          0 :                                 if (unlikely(mbuf == NULL)) {
     382                 :          0 :                                         rte_pktmbuf_free_bulk(mbufs + rx_pkts,
     383                 :          0 :                                                         MAX_PKT_BURST - rx_pkts);
     384                 :          0 :                                         goto no_free_bufs;
     385                 :            :                                 }
     386                 :            :                                 ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf);
     387         [ #  # ]:          0 :                                 if (unlikely(ret < 0)) {
     388                 :          0 :                                         MIF_LOG(ERR, "number-of-segments-overflow");
     389                 :          0 :                                         rte_pktmbuf_free(mbuf);
     390                 :          0 :                                         rte_pktmbuf_free_bulk(mbufs + rx_pkts,
     391                 :          0 :                                                         MAX_PKT_BURST - rx_pkts);
     392                 :          0 :                                         goto no_free_bufs;
     393                 :            :                                 }
     394                 :          0 :                                 goto next_slot1;
     395                 :            :                         }
     396                 :            : 
     397                 :          0 :                         mq->n_bytes += rte_pktmbuf_pkt_len(mbuf_head);
     398                 :          0 :                         *bufs++ = mbuf_head;
     399                 :          0 :                         rx_pkts++;
     400                 :          0 :                         n_rx_pkts++;
     401                 :            :                 }
     402                 :            : 
     403         [ #  # ]:          0 :                 if (rx_pkts < MAX_PKT_BURST) {
     404                 :          0 :                         rte_pktmbuf_free_bulk(mbufs + rx_pkts, MAX_PKT_BURST - rx_pkts);
     405                 :            :                 } else {
     406                 :          0 :                         nb_pkts -= rx_pkts;
     407         [ #  # ]:          0 :                         if (nb_pkts)
     408                 :          0 :                                 goto next_bulk;
     409                 :            :                 }
     410                 :            :         } else {
     411         [ #  # ]:          0 :                 while (n_slots && n_rx_pkts < nb_pkts) {
     412                 :          0 :                         mbuf_head = rte_pktmbuf_alloc(mq->mempool);
     413         [ #  # ]:          0 :                         if (unlikely(mbuf_head == NULL))
     414                 :          0 :                                 goto no_free_bufs;
     415                 :            :                         mbuf = mbuf_head;
     416                 :          0 :                         mbuf->port = mq->in_port;
     417                 :            : 
     418                 :          0 : next_slot2:
     419                 :          0 :                         s0 = cur_slot & mask;
     420                 :          0 :                         d0 = &ring->desc[s0];
     421                 :            : 
     422                 :          0 :                         src_len = d0->length;
     423                 :            :                         dst_off = 0;
     424                 :            :                         src_off = 0;
     425                 :            : 
     426                 :            :                         do {
     427                 :          0 :                                 dst_len = mbuf_size - dst_off;
     428         [ #  # ]:          0 :                                 if (dst_len == 0) {
     429                 :            :                                         dst_off = 0;
     430                 :            :                                         dst_len = mbuf_size;
     431                 :            : 
     432                 :            :                                         /* store pointer to tail */
     433                 :            :                                         mbuf_tail = mbuf;
     434                 :          0 :                                         mbuf = rte_pktmbuf_alloc(mq->mempool);
     435         [ #  # ]:          0 :                                         if (unlikely(mbuf == NULL))
     436                 :          0 :                                                 goto no_free_bufs;
     437         [ #  # ]:          0 :                                         mbuf->port = mq->in_port;
     438                 :            :                                         ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf);
     439         [ #  # ]:          0 :                                         if (unlikely(ret < 0)) {
     440                 :          0 :                                                 MIF_LOG(ERR, "number-of-segments-overflow");
     441                 :          0 :                                                 rte_pktmbuf_free(mbuf);
     442                 :          0 :                                                 goto no_free_bufs;
     443                 :            :                                         }
     444                 :            :                                 }
     445                 :          0 :                                 cp_len = RTE_MIN(dst_len, src_len);
     446                 :            : 
     447                 :          0 :                                 rte_pktmbuf_data_len(mbuf) += cp_len;
     448                 :          0 :                                 rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf);
     449         [ #  # ]:          0 :                                 if (mbuf != mbuf_head)
     450                 :          0 :                                         rte_pktmbuf_pkt_len(mbuf_head) += cp_len;
     451                 :            : 
     452         [ #  # ]:          0 :                                 rte_memcpy(rte_pktmbuf_mtod_offset(mbuf, void *,
     453                 :            :                                                                    dst_off),
     454                 :            :                                         (uint8_t *)memif_get_buffer(proc_private, d0) +
     455                 :            :                                         src_off, cp_len);
     456                 :            : 
     457                 :          0 :                                 src_off += cp_len;
     458                 :          0 :                                 dst_off += cp_len;
     459                 :          0 :                                 src_len -= cp_len;
     460         [ #  # ]:          0 :                         } while (src_len);
     461                 :            : 
     462                 :          0 :                         cur_slot++;
     463                 :          0 :                         n_slots--;
     464                 :            : 
     465         [ #  # ]:          0 :                         if (d0->flags & MEMIF_DESC_FLAG_NEXT)
     466                 :          0 :                                 goto next_slot2;
     467                 :            : 
     468                 :          0 :                         mq->n_bytes += rte_pktmbuf_pkt_len(mbuf_head);
     469                 :          0 :                         *bufs++ = mbuf_head;
     470                 :          0 :                         n_rx_pkts++;
     471                 :            :                 }
     472                 :            :         }
     473                 :            : 
     474                 :          0 : no_free_bufs:
     475         [ #  # ]:          0 :         if (type == MEMIF_RING_C2S) {
     476                 :          0 :                 rte_atomic_store_explicit(&ring->tail, cur_slot, rte_memory_order_release);
     477                 :          0 :                 mq->last_head = cur_slot;
     478                 :            :         } else {
     479                 :          0 :                 mq->last_tail = cur_slot;
     480                 :            :         }
     481                 :            : 
     482                 :          0 : refill:
     483         [ #  # ]:          0 :         if (type == MEMIF_RING_S2C) {
     484                 :            :                 /* ring->head is updated by the receiver and this function
     485                 :            :                  * is called in the context of receiver thread. The loads in
     486                 :            :                  * the receiver do not need to synchronize with its own stores.
     487                 :            :                  */
     488                 :          0 :                 head = rte_atomic_load_explicit(&ring->head, rte_memory_order_relaxed);
     489                 :          0 :                 n_slots = ring_size - head + mq->last_tail;
     490                 :            : 
     491         [ #  # ]:          0 :                 while (n_slots--) {
     492                 :          0 :                         s0 = head++ & mask;
     493                 :          0 :                         d0 = &ring->desc[s0];
     494                 :          0 :                         d0->length = pmd->run.pkt_buffer_size;
     495                 :            :                 }
     496                 :          0 :                 rte_atomic_store_explicit(&ring->head, head, rte_memory_order_release);
     497                 :            :         }
     498                 :            : 
     499                 :          0 :         mq->n_pkts += n_rx_pkts;
     500                 :          0 :         return n_rx_pkts;
     501                 :            : }
     502                 :            : 
     503                 :            : static uint16_t
     504                 :          0 : eth_memif_rx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
     505                 :            : {
     506                 :            :         struct memif_queue *mq = queue;
     507                 :          0 :         struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private;
     508         [ #  # ]:          0 :         struct pmd_process_private *proc_private =
     509                 :            :                 rte_eth_devices[mq->in_port].process_private;
     510                 :            :         memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
     511                 :            :         uint16_t cur_slot, last_slot, n_slots, ring_size, mask, s0, head;
     512                 :            :         uint16_t n_rx_pkts = 0;
     513                 :            :         memif_desc_t *d0;
     514                 :            :         struct rte_mbuf *mbuf, *mbuf_tail;
     515                 :            :         struct rte_mbuf *mbuf_head = NULL;
     516                 :            :         int ret;
     517                 :            :         struct rte_eth_link link;
     518                 :            : 
     519         [ #  # ]:          0 :         if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0))
     520                 :            :                 return 0;
     521         [ #  # ]:          0 :         if (unlikely(ring == NULL)) {
     522                 :            :                 /* Secondary process will attempt to request regions. */
     523                 :          0 :                 ret = rte_eth_link_get(mq->in_port, &link);
     524         [ #  # ]:          0 :                 if (ret < 0)
     525                 :          0 :                         MIF_LOG(ERR, "Failed to get port %u link info: %s",
     526                 :            :                                 mq->in_port, rte_strerror(-ret));
     527                 :          0 :                 return 0;
     528                 :            :         }
     529                 :            : 
     530                 :            :         /* consume interrupt */
     531         [ #  # ]:          0 :         if ((rte_intr_fd_get(mq->intr_handle) >= 0) &&
     532         [ #  # ]:          0 :             ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)) {
     533                 :            :                 uint64_t b;
     534                 :            :                 ssize_t size __rte_unused;
     535                 :          0 :                 size = read(rte_intr_fd_get(mq->intr_handle), &b,
     536                 :            :                             sizeof(b));
     537                 :            :         }
     538                 :            : 
     539                 :          0 :         ring_size = 1 << mq->log2_ring_size;
     540                 :          0 :         mask = ring_size - 1;
     541                 :            : 
     542                 :          0 :         cur_slot = mq->last_tail;
     543                 :            :         /* The ring->tail acts as a guard variable between Tx and Rx
     544                 :            :          * threads, so using load-acquire pairs with store-release
     545                 :            :          * to synchronize it between threads.
     546                 :            :          */
     547                 :          0 :         last_slot = rte_atomic_load_explicit(&ring->tail, rte_memory_order_acquire);
     548         [ #  # ]:          0 :         if (cur_slot == last_slot)
     549                 :          0 :                 goto refill;
     550                 :          0 :         n_slots = last_slot - cur_slot;
     551                 :            : 
     552         [ #  # ]:          0 :         while (n_slots && n_rx_pkts < nb_pkts) {
     553                 :          0 :                 s0 = cur_slot & mask;
     554                 :            : 
     555                 :          0 :                 d0 = &ring->desc[s0];
     556                 :          0 :                 mbuf_head = mq->buffers[s0];
     557                 :            :                 mbuf = mbuf_head;
     558                 :            : 
     559                 :          0 : next_slot:
     560                 :            :                 /* prefetch next descriptor */
     561         [ #  # ]:          0 :                 if (n_rx_pkts + 1 < nb_pkts)
     562                 :          0 :                         rte_prefetch0(&ring->desc[(cur_slot + 1) & mask]);
     563                 :            : 
     564                 :          0 :                 mbuf->port = mq->in_port;
     565                 :          0 :                 rte_pktmbuf_data_len(mbuf) = d0->length;
     566                 :          0 :                 rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf);
     567                 :            : 
     568                 :          0 :                 mq->n_bytes += rte_pktmbuf_data_len(mbuf);
     569                 :            : 
     570                 :          0 :                 cur_slot++;
     571                 :          0 :                 n_slots--;
     572         [ #  # ]:          0 :                 if (d0->flags & MEMIF_DESC_FLAG_NEXT) {
     573                 :          0 :                         s0 = cur_slot & mask;
     574                 :          0 :                         d0 = &ring->desc[s0];
     575                 :            :                         mbuf_tail = mbuf;
     576         [ #  # ]:          0 :                         mbuf = mq->buffers[s0];
     577                 :            :                         ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf);
     578         [ #  # ]:          0 :                         if (unlikely(ret < 0)) {
     579                 :          0 :                                 MIF_LOG(ERR, "number-of-segments-overflow");
     580                 :          0 :                                 goto refill;
     581                 :            :                         }
     582                 :          0 :                         goto next_slot;
     583                 :            :                 }
     584                 :            : 
     585                 :          0 :                 *bufs++ = mbuf_head;
     586                 :          0 :                 n_rx_pkts++;
     587                 :            :         }
     588                 :            : 
     589                 :          0 :         mq->last_tail = cur_slot;
     590                 :            : 
     591                 :            : /* Supply server with new buffers */
     592                 :          0 : refill:
     593                 :            :         /* ring->head is updated by the receiver and this function
     594                 :            :          * is called in the context of receiver thread. The loads in
     595                 :            :          * the receiver do not need to synchronize with its own stores.
     596                 :            :          */
     597                 :          0 :         head = rte_atomic_load_explicit(&ring->head, rte_memory_order_relaxed);
     598                 :          0 :         n_slots = ring_size - head + mq->last_tail;
     599                 :            : 
     600         [ #  # ]:          0 :         if (n_slots < 32)
     601                 :          0 :                 goto no_free_mbufs;
     602                 :            : 
     603                 :          0 :         ret = rte_pktmbuf_alloc_bulk(mq->mempool, &mq->buffers[head & mask], n_slots);
     604         [ #  # ]:          0 :         if (unlikely(ret < 0))
     605                 :          0 :                 goto no_free_mbufs;
     606         [ #  # ]:          0 :         if (unlikely(n_slots > ring_size - (head & mask))) {
     607                 :          0 :                 rte_memcpy(mq->buffers, &mq->buffers[ring_size],
     608         [ #  # ]:          0 :                         (n_slots + (head & mask) - ring_size) * sizeof(struct rte_mbuf *));
     609                 :            :         }
     610                 :            : 
     611         [ #  # ]:          0 :         while (n_slots--) {
     612                 :          0 :                 s0 = head++ & mask;
     613         [ #  # ]:          0 :                 if (n_slots > 0)
     614                 :          0 :                         rte_prefetch0(mq->buffers[head & mask]);
     615                 :          0 :                 d0 = &ring->desc[s0];
     616                 :            :                 /* store buffer header */
     617                 :          0 :                 mbuf = mq->buffers[s0];
     618                 :            :                 /* populate descriptor */
     619         [ #  # ]:          0 :                 d0->length = rte_pktmbuf_data_room_size(mq->mempool) -
     620                 :            :                                 RTE_PKTMBUF_HEADROOM;
     621                 :          0 :                 d0->region = 1;
     622                 :          0 :                 d0->offset = rte_pktmbuf_mtod(mbuf, uint8_t *) -
     623                 :          0 :                         (uint8_t *)proc_private->regions[d0->region]->addr;
     624                 :            :         }
     625                 :          0 : no_free_mbufs:
     626                 :            :         /* The ring->head acts as a guard variable between Tx and Rx
     627                 :            :          * threads, so using store-release pairs with load-acquire
     628                 :            :          * in function eth_memif_tx.
     629                 :            :          */
     630                 :          0 :         rte_atomic_store_explicit(&ring->head, head, rte_memory_order_release);
     631                 :            : 
     632                 :          0 :         mq->n_pkts += n_rx_pkts;
     633                 :            : 
     634                 :          0 :         return n_rx_pkts;
     635                 :            : }
     636                 :            : 
     637                 :            : static uint16_t
     638                 :          0 : eth_memif_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
     639                 :            : {
     640                 :            :         struct memif_queue *mq = queue;
     641                 :          0 :         struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private;
     642         [ #  # ]:          0 :         struct pmd_process_private *proc_private =
     643                 :            :                 rte_eth_devices[mq->in_port].process_private;
     644                 :            :         memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
     645                 :            :         uint16_t slot, saved_slot, n_free, ring_size, mask, n_tx_pkts = 0;
     646                 :            :         uint16_t src_len, src_off, dst_len, dst_off, cp_len, nb_segs;
     647                 :          0 :         memif_ring_type_t type = mq->type;
     648                 :            :         memif_desc_t *d0;
     649                 :            :         struct rte_mbuf *mbuf;
     650                 :            :         struct rte_mbuf *mbuf_head;
     651                 :            :         uint64_t a;
     652                 :            :         ssize_t size;
     653                 :            :         struct rte_eth_link link;
     654                 :            : 
     655         [ #  # ]:          0 :         if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0))
     656                 :            :                 return 0;
     657         [ #  # ]:          0 :         if (unlikely(ring == NULL)) {
     658                 :            :                 int ret;
     659                 :            : 
     660                 :            :                 /* Secondary process will attempt to request regions. */
     661                 :          0 :                 ret = rte_eth_link_get(mq->in_port, &link);
     662         [ #  # ]:          0 :                 if (ret < 0)
     663                 :          0 :                         MIF_LOG(ERR, "Failed to get port %u link info: %s",
     664                 :            :                                 mq->in_port, rte_strerror(-ret));
     665                 :          0 :                 return 0;
     666                 :            :         }
     667                 :            : 
     668                 :          0 :         ring_size = 1 << mq->log2_ring_size;
     669                 :          0 :         mask = ring_size - 1;
     670                 :            : 
     671         [ #  # ]:          0 :         if (type == MEMIF_RING_C2S) {
     672                 :            :                 /* For C2S queues ring->head is updated by the sender and
     673                 :            :                  * this function is called in the context of sending thread.
     674                 :            :                  * The loads in the sender do not need to synchronize with
     675                 :            :                  * its own stores. Hence, the following load can be a
     676                 :            :                  * relaxed load.
     677                 :            :                  */
     678                 :          0 :                 slot = rte_atomic_load_explicit(&ring->head, rte_memory_order_relaxed);
     679                 :          0 :                 n_free = ring_size - slot +
     680                 :          0 :                                 rte_atomic_load_explicit(&ring->tail, rte_memory_order_acquire);
     681                 :            :         } else {
     682                 :            :                 /* For S2C queues ring->tail is updated by the sender and
     683                 :            :                  * this function is called in the context of sending thread.
     684                 :            :                  * The loads in the sender do not need to synchronize with
     685                 :            :                  * its own stores. Hence, the following load can be a
     686                 :            :                  * relaxed load.
     687                 :            :                  */
     688                 :          0 :                 slot = rte_atomic_load_explicit(&ring->tail, rte_memory_order_relaxed);
     689                 :          0 :                 n_free = rte_atomic_load_explicit(&ring->head, rte_memory_order_acquire) - slot;
     690                 :            :         }
     691                 :            : 
     692                 :            :         uint16_t i;
     693                 :            :         struct rte_mbuf **buf_tmp = bufs;
     694                 :          0 :         mbuf_head = *buf_tmp++;
     695                 :          0 :         struct rte_mempool *mp = mbuf_head->pool;
     696                 :            : 
     697         [ #  # ]:          0 :         for (i = 1; i < nb_pkts; i++) {
     698                 :          0 :                 mbuf_head = *buf_tmp++;
     699         [ #  # ]:          0 :                 if (mbuf_head->pool != mp)
     700                 :            :                         break;
     701                 :            :         }
     702                 :            : 
     703                 :          0 :         uint16_t mbuf_size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM;
     704   [ #  #  #  # ]:          0 :         if (i == nb_pkts && pmd->cfg.pkt_buffer_size >= mbuf_size) {
     705                 :            :                 buf_tmp = bufs;
     706         [ #  # ]:          0 :                 while (n_tx_pkts < nb_pkts && n_free) {
     707                 :          0 :                         mbuf_head = *bufs++;
     708                 :          0 :                         nb_segs = mbuf_head->nb_segs;
     709                 :            :                         mbuf = mbuf_head;
     710                 :            : 
     711                 :            :                         saved_slot = slot;
     712                 :            : 
     713                 :          0 : next_in_chain1:
     714                 :          0 :                         d0 = &ring->desc[slot & mask];
     715                 :          0 :                         cp_len = rte_pktmbuf_data_len(mbuf);
     716                 :            : 
     717                 :          0 :                         rte_memcpy((uint8_t *)memif_get_buffer(proc_private, d0),
     718         [ #  # ]:          0 :                                 rte_pktmbuf_mtod(mbuf, void *), cp_len);
     719                 :            : 
     720                 :          0 :                         d0->length = cp_len;
     721                 :          0 :                         mq->n_bytes += cp_len;
     722                 :          0 :                         slot++;
     723                 :          0 :                         n_free--;
     724                 :            : 
     725         [ #  # ]:          0 :                         if (--nb_segs > 0) {
     726         [ #  # ]:          0 :                                 if (n_free) {
     727                 :          0 :                                         d0->flags |= MEMIF_DESC_FLAG_NEXT;
     728                 :          0 :                                         mbuf = mbuf->next;
     729                 :          0 :                                         goto next_in_chain1;
     730                 :            :                                 } else {
     731                 :            :                                         slot = saved_slot;
     732                 :          0 :                                         goto free_mbufs;
     733                 :            :                                 }
     734                 :            :                         }
     735                 :            : 
     736                 :          0 :                         n_tx_pkts++;
     737                 :            :                 }
     738                 :          0 : free_mbufs:
     739                 :          0 :                 rte_pktmbuf_free_bulk(buf_tmp, n_tx_pkts);
     740                 :            :         } else {
     741         [ #  # ]:          0 :                 while (n_tx_pkts < nb_pkts && n_free) {
     742                 :          0 :                         mbuf_head = *bufs++;
     743                 :          0 :                         nb_segs = mbuf_head->nb_segs;
     744                 :            :                         mbuf = mbuf_head;
     745                 :            : 
     746                 :            :                         saved_slot = slot;
     747                 :          0 :                         d0 = &ring->desc[slot & mask];
     748                 :            :                         dst_off = 0;
     749         [ #  # ]:          0 :                         dst_len = (type == MEMIF_RING_C2S) ?
     750                 :          0 :                                 pmd->run.pkt_buffer_size : d0->length;
     751                 :            : 
     752                 :          0 : next_in_chain2:
     753                 :            :                         src_off = 0;
     754                 :          0 :                         src_len = rte_pktmbuf_data_len(mbuf);
     755                 :            : 
     756         [ #  # ]:          0 :                         while (src_len) {
     757         [ #  # ]:          0 :                                 if (dst_len == 0) {
     758         [ #  # ]:          0 :                                         if (n_free) {
     759                 :          0 :                                                 slot++;
     760                 :          0 :                                                 n_free--;
     761                 :          0 :                                                 d0->flags |= MEMIF_DESC_FLAG_NEXT;
     762                 :          0 :                                                 d0 = &ring->desc[slot & mask];
     763                 :            :                                                 dst_off = 0;
     764         [ #  # ]:          0 :                                                 dst_len = (type == MEMIF_RING_C2S) ?
     765                 :          0 :                                                     pmd->run.pkt_buffer_size : d0->length;
     766                 :          0 :                                                 d0->flags = 0;
     767                 :            :                                         } else {
     768                 :            :                                                 slot = saved_slot;
     769                 :          0 :                                                 goto no_free_slots;
     770                 :            :                                         }
     771                 :            :                                 }
     772                 :          0 :                                 cp_len = RTE_MIN(dst_len, src_len);
     773                 :            : 
     774                 :          0 :                                 rte_memcpy((uint8_t *)memif_get_buffer(proc_private,
     775                 :            :                                                                        d0) + dst_off,
     776         [ #  # ]:          0 :                                         rte_pktmbuf_mtod_offset(mbuf, void *, src_off),
     777                 :            :                                         cp_len);
     778                 :            : 
     779                 :          0 :                                 mq->n_bytes += cp_len;
     780                 :          0 :                                 src_off += cp_len;
     781                 :          0 :                                 dst_off += cp_len;
     782                 :          0 :                                 src_len -= cp_len;
     783                 :          0 :                                 dst_len -= cp_len;
     784                 :            : 
     785                 :          0 :                                 d0->length = dst_off;
     786                 :            :                         }
     787                 :            : 
     788         [ #  # ]:          0 :                         if (--nb_segs > 0) {
     789                 :          0 :                                 mbuf = mbuf->next;
     790                 :          0 :                                 goto next_in_chain2;
     791                 :            :                         }
     792                 :            : 
     793                 :          0 :                         n_tx_pkts++;
     794                 :          0 :                         slot++;
     795                 :          0 :                         n_free--;
     796                 :          0 :                         rte_pktmbuf_free(mbuf_head);
     797                 :            :                 }
     798                 :            :         }
     799                 :            : 
     800                 :          0 : no_free_slots:
     801         [ #  # ]:          0 :         if (type == MEMIF_RING_C2S)
     802                 :          0 :                 rte_atomic_store_explicit(&ring->head, slot, rte_memory_order_release);
     803                 :            :         else
     804                 :          0 :                 rte_atomic_store_explicit(&ring->tail, slot, rte_memory_order_release);
     805                 :            : 
     806   [ #  #  #  # ]:          0 :         if (((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) &&
     807                 :          0 :             (rte_intr_fd_get(mq->intr_handle) >= 0)) {
     808                 :          0 :                 a = 1;
     809                 :          0 :                 size = write(rte_intr_fd_get(mq->intr_handle), &a,
     810                 :            :                              sizeof(a));
     811         [ #  # ]:          0 :                 if (unlikely(size < 0)) {
     812                 :          0 :                         MIF_LOG(WARNING,
     813                 :            :                                 "Failed to send interrupt. %s", strerror(errno));
     814                 :            :                 }
     815                 :            :         }
     816                 :            : 
     817                 :          0 :         mq->n_pkts += n_tx_pkts;
     818                 :          0 :         return n_tx_pkts;
     819                 :            : }
     820                 :            : 
     821                 :            : static int
     822                 :          0 : memif_tx_one_zc(struct pmd_process_private *proc_private, struct memif_queue *mq,
     823                 :            :                 memif_ring_t *ring, struct rte_mbuf *mbuf, const uint16_t mask,
     824                 :            :                 uint16_t slot, uint16_t n_free)
     825                 :            : {
     826                 :            :         memif_desc_t *d0;
     827                 :          0 :         uint16_t nb_segs = mbuf->nb_segs;
     828                 :            :         int used_slots = 1;
     829                 :            : 
     830                 :          0 : next_in_chain:
     831                 :            :         /* store pointer to mbuf to free it later */
     832                 :          0 :         mq->buffers[slot & mask] = mbuf;
     833                 :            :         /* populate descriptor */
     834                 :          0 :         d0 = &ring->desc[slot & mask];
     835                 :          0 :         d0->length = rte_pktmbuf_data_len(mbuf);
     836                 :          0 :         mq->n_bytes += rte_pktmbuf_data_len(mbuf);
     837                 :            :         /* FIXME: get region index */
     838                 :          0 :         d0->region = 1;
     839                 :          0 :         d0->offset = rte_pktmbuf_mtod(mbuf, uint8_t *) -
     840                 :          0 :                 (uint8_t *)proc_private->regions[d0->region]->addr;
     841                 :          0 :         d0->flags = 0;
     842                 :            : 
     843                 :            :         /* check if buffer is chained */
     844         [ #  # ]:          0 :         if (--nb_segs > 0) {
     845         [ #  # ]:          0 :                 if (n_free < 2)
     846                 :            :                         return 0;
     847                 :            :                 /* mark buffer as chained */
     848                 :          0 :                 d0->flags |= MEMIF_DESC_FLAG_NEXT;
     849                 :            :                 /* advance mbuf */
     850                 :          0 :                 mbuf = mbuf->next;
     851                 :            :                 /* update counters */
     852                 :          0 :                 used_slots++;
     853                 :          0 :                 slot++;
     854                 :          0 :                 n_free--;
     855                 :          0 :                 goto next_in_chain;
     856                 :            :         }
     857                 :            :         return used_slots;
     858                 :            : }
     859                 :            : 
     860                 :            : static uint16_t
     861                 :          0 : eth_memif_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
     862                 :            : {
     863                 :            :         struct memif_queue *mq = queue;
     864                 :          0 :         struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private;
     865         [ #  # ]:          0 :         struct pmd_process_private *proc_private =
     866                 :            :                 rte_eth_devices[mq->in_port].process_private;
     867                 :            :         memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
     868                 :            :         uint16_t slot, n_free, ring_size, mask, n_tx_pkts = 0;
     869                 :            :         struct rte_eth_link link;
     870                 :            : 
     871         [ #  # ]:          0 :         if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0))
     872                 :            :                 return 0;
     873         [ #  # ]:          0 :         if (unlikely(ring == NULL)) {
     874                 :            :                 int ret;
     875                 :            : 
     876                 :            :                 /* Secondary process will attempt to request regions. */
     877                 :          0 :                 ret = rte_eth_link_get(mq->in_port, &link);
     878         [ #  # ]:          0 :                 if (ret < 0)
     879                 :          0 :                         MIF_LOG(ERR, "Failed to get port %u link info: %s",
     880                 :            :                                 mq->in_port, rte_strerror(-ret));
     881                 :          0 :                 return 0;
     882                 :            :         }
     883                 :            : 
     884                 :          0 :         ring_size = 1 << mq->log2_ring_size;
     885                 :          0 :         mask = ring_size - 1;
     886                 :            : 
     887                 :            :         /* free mbufs received by server */
     888                 :          0 :         memif_free_stored_mbufs(proc_private, mq);
     889                 :            : 
     890                 :            :         /* ring type always MEMIF_RING_C2S */
     891                 :            :         /* For C2S queues ring->head is updated by the sender and
     892                 :            :          * this function is called in the context of sending thread.
     893                 :            :          * The loads in the sender do not need to synchronize with
     894                 :            :          * its own stores. Hence, the following load can be a
     895                 :            :          * relaxed load.
     896                 :            :          */
     897                 :          0 :         slot = rte_atomic_load_explicit(&ring->head, rte_memory_order_relaxed);
     898                 :          0 :         n_free = ring_size - slot + mq->last_tail;
     899                 :            : 
     900                 :            :         int used_slots;
     901                 :            : 
     902         [ #  # ]:          0 :         while (n_free && (n_tx_pkts < nb_pkts)) {
     903   [ #  #  #  # ]:          0 :                 while ((n_free > 4) && ((nb_pkts - n_tx_pkts) > 4)) {
     904         [ #  # ]:          0 :                         if ((nb_pkts - n_tx_pkts) > 8) {
     905                 :          0 :                                 rte_prefetch0(*bufs + 4);
     906                 :          0 :                                 rte_prefetch0(*bufs + 5);
     907                 :          0 :                                 rte_prefetch0(*bufs + 6);
     908                 :          0 :                                 rte_prefetch0(*bufs + 7);
     909                 :            :                         }
     910                 :          0 :                         used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
     911                 :            :                                 mask, slot, n_free);
     912         [ #  # ]:          0 :                         if (unlikely(used_slots < 1))
     913                 :          0 :                                 goto no_free_slots;
     914                 :          0 :                         n_tx_pkts++;
     915                 :          0 :                         slot += used_slots;
     916                 :          0 :                         n_free -= used_slots;
     917                 :            : 
     918                 :          0 :                         used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
     919                 :            :                                 mask, slot, n_free);
     920         [ #  # ]:          0 :                         if (unlikely(used_slots < 1))
     921                 :          0 :                                 goto no_free_slots;
     922                 :          0 :                         n_tx_pkts++;
     923                 :          0 :                         slot += used_slots;
     924                 :          0 :                         n_free -= used_slots;
     925                 :            : 
     926                 :          0 :                         used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
     927                 :            :                                 mask, slot, n_free);
     928         [ #  # ]:          0 :                         if (unlikely(used_slots < 1))
     929                 :          0 :                                 goto no_free_slots;
     930                 :          0 :                         n_tx_pkts++;
     931                 :          0 :                         slot += used_slots;
     932                 :          0 :                         n_free -= used_slots;
     933                 :            : 
     934                 :          0 :                         used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
     935                 :            :                                 mask, slot, n_free);
     936         [ #  # ]:          0 :                         if (unlikely(used_slots < 1))
     937                 :          0 :                                 goto no_free_slots;
     938                 :          0 :                         n_tx_pkts++;
     939                 :          0 :                         slot += used_slots;
     940                 :          0 :                         n_free -= used_slots;
     941                 :            :                 }
     942                 :          0 :                 used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
     943                 :            :                         mask, slot, n_free);
     944         [ #  # ]:          0 :                 if (unlikely(used_slots < 1))
     945                 :          0 :                         goto no_free_slots;
     946                 :          0 :                 n_tx_pkts++;
     947                 :          0 :                 slot += used_slots;
     948                 :          0 :                 n_free -= used_slots;
     949                 :            :         }
     950                 :            : 
     951                 :          0 : no_free_slots:
     952                 :            :         /* ring type always MEMIF_RING_C2S */
     953                 :            :         /* The ring->head acts as a guard variable between Tx and Rx
     954                 :            :          * threads, so using store-release pairs with load-acquire
     955                 :            :          * in function eth_memif_rx for C2S rings.
     956                 :            :          */
     957                 :          0 :         rte_atomic_store_explicit(&ring->head, slot, rte_memory_order_release);
     958                 :            : 
     959                 :            :         /* Send interrupt, if enabled. */
     960         [ #  # ]:          0 :         if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) {
     961                 :          0 :                 uint64_t a = 1;
     962         [ #  # ]:          0 :                 if (rte_intr_fd_get(mq->intr_handle) < 0)
     963                 :          0 :                         return -1;
     964                 :            : 
     965                 :          0 :                 ssize_t size = write(rte_intr_fd_get(mq->intr_handle),
     966                 :            :                                      &a, sizeof(a));
     967         [ #  # ]:          0 :                 if (unlikely(size < 0)) {
     968                 :          0 :                         MIF_LOG(WARNING,
     969                 :            :                                 "Failed to send interrupt. %s", strerror(errno));
     970                 :            :                 }
     971                 :            :         }
     972                 :            : 
     973                 :            :         /* increment queue counters */
     974                 :          0 :         mq->n_pkts += n_tx_pkts;
     975                 :            : 
     976                 :          0 :         return n_tx_pkts;
     977                 :            : }
     978                 :            : 
     979                 :            : void
     980                 :          0 : memif_free_regions(struct rte_eth_dev *dev)
     981                 :            : {
     982                 :          0 :         struct pmd_process_private *proc_private = dev->process_private;
     983                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
     984                 :            :         int i;
     985                 :            :         struct memif_region *r;
     986                 :            : 
     987                 :            :         /* regions are allocated contiguously, so it's
     988                 :            :          * enough to loop until 'proc_private->regions_num'
     989                 :            :          */
     990         [ #  # ]:          0 :         for (i = 0; i < proc_private->regions_num; i++) {
     991                 :          0 :                 r = proc_private->regions[i];
     992         [ #  # ]:          0 :                 if (r != NULL) {
     993                 :            :                         /* This is memzone */
     994   [ #  #  #  # ]:          0 :                         if (i > 0 && (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)) {
     995                 :          0 :                                 r->addr = NULL;
     996         [ #  # ]:          0 :                                 if (r->fd > 0)
     997                 :          0 :                                         close(r->fd);
     998                 :            :                         }
     999         [ #  # ]:          0 :                         if (r->addr != NULL) {
    1000                 :          0 :                                 munmap(r->addr, r->region_size);
    1001         [ #  # ]:          0 :                                 if (r->fd > 0) {
    1002                 :          0 :                                         close(r->fd);
    1003                 :          0 :                                         r->fd = -1;
    1004                 :            :                                 }
    1005                 :            :                         }
    1006                 :          0 :                         rte_free(r);
    1007                 :          0 :                         proc_private->regions[i] = NULL;
    1008                 :            :                 }
    1009                 :            :         }
    1010                 :          0 :         proc_private->regions_num = 0;
    1011                 :          0 : }
    1012                 :            : 
    1013                 :            : static int
    1014                 :          0 : memif_region_init_zc(const struct rte_memseg_list *msl, const struct rte_memseg *ms,
    1015                 :            :                      void *arg)
    1016                 :            : {
    1017                 :            :         struct pmd_process_private *proc_private = (struct pmd_process_private *)arg;
    1018                 :            :         struct memif_region *r;
    1019                 :            : 
    1020         [ #  # ]:          0 :         if (proc_private->regions_num < 1) {
    1021                 :          0 :                 MIF_LOG(ERR, "Missing descriptor region");
    1022                 :          0 :                 return -1;
    1023                 :            :         }
    1024                 :            : 
    1025                 :          0 :         r = proc_private->regions[proc_private->regions_num - 1];
    1026                 :            : 
    1027         [ #  # ]:          0 :         if (r->addr != msl->base_va)
    1028                 :          0 :                 r = proc_private->regions[++proc_private->regions_num - 1];
    1029                 :            : 
    1030         [ #  # ]:          0 :         if (r == NULL) {
    1031                 :          0 :                 r = rte_zmalloc("region", sizeof(struct memif_region), 0);
    1032         [ #  # ]:          0 :                 if (r == NULL) {
    1033                 :          0 :                         MIF_LOG(ERR, "Failed to alloc memif region.");
    1034                 :          0 :                         return -ENOMEM;
    1035                 :            :                 }
    1036                 :            : 
    1037                 :          0 :                 r->addr = msl->base_va;
    1038                 :          0 :                 r->region_size = ms->len;
    1039                 :          0 :                 r->fd = rte_memseg_get_fd(ms);
    1040         [ #  # ]:          0 :                 if (r->fd < 0)
    1041                 :            :                         return -1;
    1042                 :          0 :                 r->pkt_buffer_offset = 0;
    1043                 :            : 
    1044                 :          0 :                 proc_private->regions[proc_private->regions_num - 1] = r;
    1045                 :            :         } else {
    1046                 :          0 :                 r->region_size += ms->len;
    1047                 :            :         }
    1048                 :            : 
    1049                 :            :         return 0;
    1050                 :            : }
    1051                 :            : 
    1052                 :            : static int
    1053                 :          0 : memif_region_init_shm(struct rte_eth_dev *dev, uint8_t has_buffers)
    1054                 :            : {
    1055                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1056                 :          0 :         struct pmd_process_private *proc_private = dev->process_private;
    1057                 :            :         char shm_name[ETH_MEMIF_SHM_NAME_SIZE];
    1058                 :            :         int ret = 0;
    1059                 :            :         struct memif_region *r;
    1060                 :            : 
    1061         [ #  # ]:          0 :         if (proc_private->regions_num >= ETH_MEMIF_MAX_REGION_NUM) {
    1062                 :          0 :                 MIF_LOG(ERR, "Too many regions.");
    1063                 :          0 :                 return -1;
    1064                 :            :         }
    1065                 :            : 
    1066                 :          0 :         r = rte_zmalloc("region", sizeof(struct memif_region), 0);
    1067         [ #  # ]:          0 :         if (r == NULL) {
    1068                 :          0 :                 MIF_LOG(ERR, "Failed to alloc memif region.");
    1069                 :          0 :                 return -ENOMEM;
    1070                 :            :         }
    1071                 :            : 
    1072                 :            :         /* calculate buffer offset */
    1073                 :          0 :         r->pkt_buffer_offset = (pmd->run.num_c2s_rings + pmd->run.num_s2c_rings) *
    1074                 :          0 :             (sizeof(memif_ring_t) + sizeof(memif_desc_t) *
    1075                 :          0 :             (1 << pmd->run.log2_ring_size));
    1076                 :            : 
    1077                 :          0 :         r->region_size = r->pkt_buffer_offset;
    1078                 :            :         /* if region has buffers, add buffers size to region_size */
    1079         [ #  # ]:          0 :         if (has_buffers == 1)
    1080                 :          0 :                 r->region_size += (uint32_t)(pmd->run.pkt_buffer_size *
    1081                 :          0 :                         (1 << pmd->run.log2_ring_size) *
    1082                 :            :                         (pmd->run.num_c2s_rings +
    1083                 :            :                          pmd->run.num_s2c_rings));
    1084                 :            : 
    1085                 :            :         memset(shm_name, 0, sizeof(char) * ETH_MEMIF_SHM_NAME_SIZE);
    1086                 :          0 :         snprintf(shm_name, ETH_MEMIF_SHM_NAME_SIZE, "memif_region_%d",
    1087                 :          0 :                  proc_private->regions_num);
    1088                 :            : 
    1089                 :          0 :         r->fd = memfd_create(shm_name, MFD_ALLOW_SEALING);
    1090         [ #  # ]:          0 :         if (r->fd < 0) {
    1091                 :          0 :                 MIF_LOG(ERR, "Failed to create shm file: %s.", strerror(errno));
    1092                 :            :                 ret = -1;
    1093                 :          0 :                 goto error;
    1094                 :            :         }
    1095                 :            : 
    1096                 :          0 :         ret = fcntl(r->fd, F_ADD_SEALS, F_SEAL_SHRINK);
    1097         [ #  # ]:          0 :         if (ret < 0) {
    1098                 :          0 :                 MIF_LOG(ERR, "Failed to add seals to shm file: %s.", strerror(errno));
    1099                 :          0 :                 goto error;
    1100                 :            :         }
    1101                 :            : 
    1102                 :          0 :         ret = ftruncate(r->fd, r->region_size);
    1103         [ #  # ]:          0 :         if (ret < 0) {
    1104                 :          0 :                 MIF_LOG(ERR, "Failed to truncate shm file: %s.", strerror(errno));
    1105                 :          0 :                 goto error;
    1106                 :            :         }
    1107                 :            : 
    1108                 :          0 :         r->addr = mmap(NULL, r->region_size, PROT_READ |
    1109                 :            :                        PROT_WRITE, MAP_SHARED, r->fd, 0);
    1110         [ #  # ]:          0 :         if (r->addr == MAP_FAILED) {
    1111                 :          0 :                 MIF_LOG(ERR, "Failed to mmap shm region: %s.", strerror(ret));
    1112                 :            :                 ret = -1;
    1113                 :          0 :                 goto error;
    1114                 :            :         }
    1115                 :            : 
    1116                 :          0 :         proc_private->regions[proc_private->regions_num] = r;
    1117                 :          0 :         proc_private->regions_num++;
    1118                 :            : 
    1119                 :          0 :         return ret;
    1120                 :            : 
    1121                 :          0 : error:
    1122         [ #  # ]:          0 :         if (r->fd > 0)
    1123                 :          0 :                 close(r->fd);
    1124                 :          0 :         r->fd = -1;
    1125                 :            : 
    1126                 :          0 :         return ret;
    1127                 :            : }
    1128                 :            : 
    1129                 :            : static int
    1130                 :          0 : memif_regions_init(struct rte_eth_dev *dev)
    1131                 :            : {
    1132                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1133                 :            :         int ret;
    1134                 :            : 
    1135                 :            :         /*
    1136                 :            :          * Zero-copy exposes dpdk memory.
    1137                 :            :          * Each memseg list will be represented by memif region.
    1138                 :            :          * Zero-copy regions indexing: memseg list idx + 1,
    1139                 :            :          * as we already have region 0 reserved for descriptors.
    1140                 :            :          */
    1141         [ #  # ]:          0 :         if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
    1142                 :            :                 /* create region idx 0 containing descriptors */
    1143                 :          0 :                 ret = memif_region_init_shm(dev, 0);
    1144         [ #  # ]:          0 :                 if (ret < 0)
    1145                 :            :                         return ret;
    1146                 :          0 :                 ret = rte_memseg_walk(memif_region_init_zc, (void *)dev->process_private);
    1147                 :            :                 if (ret < 0)
    1148                 :            :                         return ret;
    1149                 :            :         } else {
    1150                 :            :                 /* create one memory region containing rings and buffers */
    1151                 :          0 :                 ret = memif_region_init_shm(dev, /* has buffers */ 1);
    1152                 :            :                 if (ret < 0)
    1153                 :            :                         return ret;
    1154                 :            :         }
    1155                 :            : 
    1156                 :            :         return 0;
    1157                 :            : }
    1158                 :            : 
    1159                 :            : static void
    1160                 :          0 : memif_init_rings(struct rte_eth_dev *dev)
    1161                 :            : {
    1162                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1163                 :          0 :         struct pmd_process_private *proc_private = dev->process_private;
    1164                 :            :         memif_ring_t *ring;
    1165                 :            :         int i, j;
    1166                 :            :         uint16_t slot;
    1167                 :            : 
    1168         [ #  # ]:          0 :         for (i = 0; i < pmd->run.num_c2s_rings; i++) {
    1169                 :            :                 ring = memif_get_ring(pmd, proc_private, MEMIF_RING_C2S, i);
    1170                 :          0 :                 rte_atomic_store_explicit(&ring->head, 0, rte_memory_order_relaxed);
    1171                 :          0 :                 rte_atomic_store_explicit(&ring->tail, 0, rte_memory_order_relaxed);
    1172                 :          0 :                 ring->cookie = MEMIF_COOKIE;
    1173                 :          0 :                 ring->flags = 0;
    1174                 :            : 
    1175         [ #  # ]:          0 :                 if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)
    1176                 :          0 :                         continue;
    1177                 :            : 
    1178         [ #  # ]:          0 :                 for (j = 0; j < (1 << pmd->run.log2_ring_size); j++) {
    1179                 :          0 :                         slot = i * (1 << pmd->run.log2_ring_size) + j;
    1180                 :          0 :                         ring->desc[j].region = 0;
    1181                 :          0 :                         ring->desc[j].offset =
    1182                 :          0 :                                 proc_private->regions[0]->pkt_buffer_offset +
    1183                 :          0 :                                 (uint32_t)(slot * pmd->run.pkt_buffer_size);
    1184                 :          0 :                         ring->desc[j].length = pmd->run.pkt_buffer_size;
    1185                 :            :                 }
    1186                 :            :         }
    1187                 :            : 
    1188         [ #  # ]:          0 :         for (i = 0; i < pmd->run.num_s2c_rings; i++) {
    1189                 :            :                 ring = memif_get_ring(pmd, proc_private, MEMIF_RING_S2C, i);
    1190                 :          0 :                 rte_atomic_store_explicit(&ring->head, 0, rte_memory_order_relaxed);
    1191                 :          0 :                 rte_atomic_store_explicit(&ring->tail, 0, rte_memory_order_relaxed);
    1192                 :          0 :                 ring->cookie = MEMIF_COOKIE;
    1193                 :          0 :                 ring->flags = 0;
    1194                 :            : 
    1195         [ #  # ]:          0 :                 if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)
    1196                 :          0 :                         continue;
    1197                 :            : 
    1198         [ #  # ]:          0 :                 for (j = 0; j < (1 << pmd->run.log2_ring_size); j++) {
    1199                 :          0 :                         slot = (i + pmd->run.num_c2s_rings) *
    1200                 :          0 :                             (1 << pmd->run.log2_ring_size) + j;
    1201                 :          0 :                         ring->desc[j].region = 0;
    1202                 :          0 :                         ring->desc[j].offset =
    1203                 :          0 :                                 proc_private->regions[0]->pkt_buffer_offset +
    1204                 :          0 :                                 (uint32_t)(slot * pmd->run.pkt_buffer_size);
    1205                 :          0 :                         ring->desc[j].length = pmd->run.pkt_buffer_size;
    1206                 :            :                 }
    1207                 :            :         }
    1208                 :          0 : }
    1209                 :            : 
    1210                 :            : /* called only by client */
    1211                 :            : static int
    1212                 :          0 : memif_init_queues(struct rte_eth_dev *dev)
    1213                 :            : {
    1214                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1215                 :            :         struct memif_queue *mq;
    1216                 :            :         int i;
    1217                 :            : 
    1218         [ #  # ]:          0 :         for (i = 0; i < pmd->run.num_c2s_rings; i++) {
    1219                 :          0 :                 mq = dev->data->tx_queues[i];
    1220                 :          0 :                 mq->log2_ring_size = pmd->run.log2_ring_size;
    1221                 :            :                 /* queues located only in region 0 */
    1222                 :          0 :                 mq->region = 0;
    1223                 :          0 :                 mq->ring_offset = memif_get_ring_offset(dev, mq, MEMIF_RING_C2S, i);
    1224                 :          0 :                 mq->last_head = 0;
    1225                 :          0 :                 mq->last_tail = 0;
    1226         [ #  # ]:          0 :                 if (rte_intr_fd_set(mq->intr_handle, eventfd(0, EFD_NONBLOCK)))
    1227                 :          0 :                         return -rte_errno;
    1228                 :            : 
    1229         [ #  # ]:          0 :                 if (rte_intr_fd_get(mq->intr_handle) < 0) {
    1230                 :          0 :                         MIF_LOG(WARNING,
    1231                 :            :                                 "Failed to create eventfd for tx queue %d: %s.", i,
    1232                 :            :                                 strerror(errno));
    1233                 :            :                 }
    1234                 :          0 :                 mq->buffers = NULL;
    1235         [ #  # ]:          0 :                 if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
    1236                 :          0 :                         mq->buffers = rte_zmalloc("bufs", sizeof(struct rte_mbuf *) *
    1237                 :          0 :                                                   (1 << mq->log2_ring_size), 0);
    1238         [ #  # ]:          0 :                         if (mq->buffers == NULL)
    1239                 :            :                                 return -ENOMEM;
    1240                 :            :                 }
    1241                 :            :         }
    1242                 :            : 
    1243         [ #  # ]:          0 :         for (i = 0; i < pmd->run.num_s2c_rings; i++) {
    1244                 :          0 :                 mq = dev->data->rx_queues[i];
    1245                 :          0 :                 mq->log2_ring_size = pmd->run.log2_ring_size;
    1246                 :            :                 /* queues located only in region 0 */
    1247                 :          0 :                 mq->region = 0;
    1248                 :          0 :                 mq->ring_offset = memif_get_ring_offset(dev, mq, MEMIF_RING_S2C, i);
    1249                 :          0 :                 mq->last_head = 0;
    1250                 :          0 :                 mq->last_tail = 0;
    1251         [ #  # ]:          0 :                 if (rte_intr_fd_set(mq->intr_handle, eventfd(0, EFD_NONBLOCK)))
    1252                 :          0 :                         return -rte_errno;
    1253         [ #  # ]:          0 :                 if (rte_intr_fd_get(mq->intr_handle) < 0) {
    1254                 :          0 :                         MIF_LOG(WARNING,
    1255                 :            :                                 "Failed to create eventfd for rx queue %d: %s.", i,
    1256                 :            :                                 strerror(errno));
    1257                 :            :                 }
    1258                 :          0 :                 mq->buffers = NULL;
    1259         [ #  # ]:          0 :                 if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
    1260                 :            :                         /*
    1261                 :            :                          * Allocate 2x ring_size to reserve a contiguous array for
    1262                 :            :                          * rte_pktmbuf_alloc_bulk (to store allocated mbufs).
    1263                 :            :                          */
    1264                 :          0 :                         mq->buffers = rte_zmalloc("bufs", sizeof(struct rte_mbuf *) *
    1265                 :          0 :                                                   (1 << (mq->log2_ring_size + 1)), 0);
    1266         [ #  # ]:          0 :                         if (mq->buffers == NULL)
    1267                 :            :                                 return -ENOMEM;
    1268                 :            :                 }
    1269                 :            :         }
    1270                 :            :         return 0;
    1271                 :            : }
    1272                 :            : 
    1273                 :            : int
    1274                 :          0 : memif_init_regions_and_queues(struct rte_eth_dev *dev)
    1275                 :            : {
    1276                 :            :         int ret;
    1277                 :            : 
    1278                 :          0 :         ret = memif_regions_init(dev);
    1279         [ #  # ]:          0 :         if (ret < 0)
    1280                 :            :                 return ret;
    1281                 :            : 
    1282                 :          0 :         memif_init_rings(dev);
    1283                 :            : 
    1284                 :          0 :         ret = memif_init_queues(dev);
    1285                 :            :         if (ret < 0)
    1286                 :            :                 return ret;
    1287                 :            : 
    1288                 :            :         return 0;
    1289                 :            : }
    1290                 :            : 
    1291                 :            : int
    1292                 :          0 : memif_connect(struct rte_eth_dev *dev)
    1293                 :            : {
    1294                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1295                 :          0 :         struct pmd_process_private *proc_private = dev->process_private;
    1296                 :            :         struct memif_region *mr;
    1297                 :            :         struct memif_queue *mq;
    1298                 :            :         memif_ring_t *ring;
    1299                 :            :         int i;
    1300                 :            : 
    1301         [ #  # ]:          0 :         for (i = 0; i < proc_private->regions_num; i++) {
    1302                 :          0 :                 mr = proc_private->regions[i];
    1303         [ #  # ]:          0 :                 if (mr != NULL) {
    1304         [ #  # ]:          0 :                         if (mr->addr == NULL) {
    1305         [ #  # ]:          0 :                                 if (mr->fd < 0)
    1306                 :            :                                         return -1;
    1307                 :          0 :                                 mr->addr = mmap(NULL, mr->region_size,
    1308                 :            :                                                 PROT_READ | PROT_WRITE,
    1309                 :            :                                                 MAP_SHARED, mr->fd, 0);
    1310         [ #  # ]:          0 :                                 if (mr->addr == MAP_FAILED) {
    1311                 :          0 :                                         MIF_LOG(ERR, "mmap failed: %s",
    1312                 :            :                                                 strerror(errno));
    1313                 :          0 :                                         return -1;
    1314                 :            :                                 }
    1315                 :            :                         }
    1316   [ #  #  #  # ]:          0 :                         if (i > 0 && (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)) {
    1317                 :            :                                 /* close memseg file */
    1318                 :          0 :                                 close(mr->fd);
    1319                 :          0 :                                 mr->fd = -1;
    1320                 :            :                         }
    1321                 :            :                 }
    1322                 :            :         }
    1323                 :            : 
    1324         [ #  # ]:          0 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
    1325         [ #  # ]:          0 :                 for (i = 0; i < pmd->run.num_c2s_rings; i++) {
    1326         [ #  # ]:          0 :                         mq = (pmd->role == MEMIF_ROLE_CLIENT) ?
    1327                 :          0 :                             dev->data->tx_queues[i] : dev->data->rx_queues[i];
    1328                 :            :                         ring = memif_get_ring_from_queue(proc_private, mq);
    1329   [ #  #  #  # ]:          0 :                         if (ring == NULL || ring->cookie != MEMIF_COOKIE) {
    1330                 :          0 :                                 MIF_LOG(ERR, "Wrong ring");
    1331                 :          0 :                                 return -1;
    1332                 :            :                         }
    1333                 :          0 :                         rte_atomic_store_explicit(&ring->head, 0, rte_memory_order_relaxed);
    1334                 :          0 :                         rte_atomic_store_explicit(&ring->tail, 0, rte_memory_order_relaxed);
    1335                 :          0 :                         mq->last_head = 0;
    1336                 :          0 :                         mq->last_tail = 0;
    1337                 :            :                         /* enable polling mode */
    1338         [ #  # ]:          0 :                         if (pmd->role == MEMIF_ROLE_SERVER)
    1339                 :          0 :                                 ring->flags = MEMIF_RING_FLAG_MASK_INT;
    1340                 :            :                 }
    1341         [ #  # ]:          0 :                 for (i = 0; i < pmd->run.num_s2c_rings; i++) {
    1342         [ #  # ]:          0 :                         mq = (pmd->role == MEMIF_ROLE_CLIENT) ?
    1343                 :          0 :                             dev->data->rx_queues[i] : dev->data->tx_queues[i];
    1344                 :            :                         ring = memif_get_ring_from_queue(proc_private, mq);
    1345   [ #  #  #  # ]:          0 :                         if (ring == NULL || ring->cookie != MEMIF_COOKIE) {
    1346                 :          0 :                                 MIF_LOG(ERR, "Wrong ring");
    1347                 :          0 :                                 return -1;
    1348                 :            :                         }
    1349                 :          0 :                         rte_atomic_store_explicit(&ring->head, 0, rte_memory_order_relaxed);
    1350                 :          0 :                         rte_atomic_store_explicit(&ring->tail, 0, rte_memory_order_relaxed);
    1351                 :          0 :                         mq->last_head = 0;
    1352                 :          0 :                         mq->last_tail = 0;
    1353                 :            :                         /* enable polling mode */
    1354         [ #  # ]:          0 :                         if (pmd->role == MEMIF_ROLE_CLIENT)
    1355                 :          0 :                                 ring->flags = MEMIF_RING_FLAG_MASK_INT;
    1356                 :            :                 }
    1357                 :            : 
    1358                 :          0 :                 pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTING;
    1359                 :          0 :                 pmd->flags |= ETH_MEMIF_FLAG_CONNECTED;
    1360                 :          0 :                 dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
    1361                 :            :         }
    1362                 :          0 :         MIF_LOG(INFO, "Connected.");
    1363                 :          0 :         return 0;
    1364                 :            : }
    1365                 :            : 
    1366                 :            : static int
    1367                 :          0 : memif_dev_start(struct rte_eth_dev *dev)
    1368                 :            : {
    1369                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1370                 :            :         int ret = 0;
    1371                 :            :         uint16_t i;
    1372                 :            : 
    1373      [ #  #  # ]:          0 :         switch (pmd->role) {
    1374                 :          0 :         case MEMIF_ROLE_CLIENT:
    1375                 :          0 :                 ret = memif_connect_client(dev);
    1376                 :          0 :                 break;
    1377                 :          0 :         case MEMIF_ROLE_SERVER:
    1378                 :          0 :                 ret = memif_connect_server(dev);
    1379                 :          0 :                 break;
    1380                 :          0 :         default:
    1381                 :          0 :                 MIF_LOG(ERR, "Unknown role: %d.", pmd->role);
    1382                 :            :                 ret = -1;
    1383                 :            :                 break;
    1384                 :            :         }
    1385                 :            : 
    1386         [ #  # ]:          0 :         if (ret == 0) {
    1387         [ #  # ]:          0 :                 for (i = 0; i < dev->data->nb_rx_queues; i++)
    1388                 :          0 :                         dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
    1389         [ #  # ]:          0 :                 for (i = 0; i < dev->data->nb_tx_queues; i++)
    1390                 :          0 :                         dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
    1391                 :            :         }
    1392                 :            : 
    1393                 :          0 :         return ret;
    1394                 :            : }
    1395                 :            : 
    1396                 :            : static int
    1397                 :          0 : memif_dev_stop(struct rte_eth_dev *dev)
    1398                 :            : {
    1399                 :            :         uint16_t i;
    1400                 :            : 
    1401                 :          0 :         memif_disconnect(dev);
    1402                 :            : 
    1403         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_rx_queues; i++)
    1404                 :          0 :                 dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
    1405         [ #  # ]:          0 :         for (i = 0; i < dev->data->nb_tx_queues; i++)
    1406                 :          0 :                 dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
    1407                 :            : 
    1408                 :          0 :         return 0;
    1409                 :            : }
    1410                 :            : 
    1411                 :            : static int
    1412                 :          0 : memif_dev_close(struct rte_eth_dev *dev)
    1413                 :            : {
    1414                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1415                 :            :         int i;
    1416                 :            : 
    1417         [ #  # ]:          0 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
    1418                 :          0 :                 memif_msg_enq_disconnect(pmd->cc, "Device closed", 0);
    1419                 :            : 
    1420         [ #  # ]:          0 :                 for (i = 0; i < dev->data->nb_rx_queues; i++)
    1421                 :          0 :                         (*dev->dev_ops->rx_queue_release)(dev, i);
    1422         [ #  # ]:          0 :                 for (i = 0; i < dev->data->nb_tx_queues; i++)
    1423                 :          0 :                         (*dev->dev_ops->tx_queue_release)(dev, i);
    1424                 :            : 
    1425                 :          0 :                 memif_socket_remove_device(dev);
    1426                 :            :         }
    1427                 :            : 
    1428                 :          0 :         rte_free(dev->process_private);
    1429                 :            : 
    1430                 :          0 :         return 0;
    1431                 :            : }
    1432                 :            : 
    1433                 :            : static int
    1434                 :          0 : memif_dev_configure(struct rte_eth_dev *dev)
    1435                 :            : {
    1436                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1437                 :            : 
    1438                 :            :         /*
    1439                 :            :          * CLIENT - TXQ
    1440                 :            :          * SERVER - RXQ
    1441                 :            :          */
    1442         [ #  # ]:          0 :         pmd->cfg.num_c2s_rings = (pmd->role == MEMIF_ROLE_CLIENT) ?
    1443                 :          0 :                                   dev->data->nb_tx_queues : dev->data->nb_rx_queues;
    1444                 :            : 
    1445                 :            :         /*
    1446                 :            :          * CLIENT - RXQ
    1447                 :            :          * SERVER - TXQ
    1448                 :            :          */
    1449         [ #  # ]:          0 :         pmd->cfg.num_s2c_rings = (pmd->role == MEMIF_ROLE_CLIENT) ?
    1450                 :          0 :                                   dev->data->nb_rx_queues : dev->data->nb_tx_queues;
    1451                 :            : 
    1452                 :          0 :         return 0;
    1453                 :            : }
    1454                 :            : 
    1455                 :            : static int
    1456                 :          0 : memif_tx_queue_setup(struct rte_eth_dev *dev,
    1457                 :            :                      uint16_t qid,
    1458                 :            :                      uint16_t nb_tx_desc __rte_unused,
    1459                 :            :                      unsigned int socket_id __rte_unused,
    1460                 :            :                      const struct rte_eth_txconf *tx_conf __rte_unused)
    1461                 :            : {
    1462                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1463                 :            :         struct memif_queue *mq;
    1464                 :            : 
    1465                 :          0 :         mq = rte_zmalloc("tx-queue", sizeof(struct memif_queue), 0);
    1466         [ #  # ]:          0 :         if (mq == NULL) {
    1467                 :          0 :                 MIF_LOG(ERR, "Failed to allocate tx queue id: %u", qid);
    1468                 :          0 :                 return -ENOMEM;
    1469                 :            :         }
    1470                 :            : 
    1471                 :            :         /* Allocate interrupt instance */
    1472                 :          0 :         mq->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
    1473         [ #  # ]:          0 :         if (mq->intr_handle == NULL) {
    1474                 :          0 :                 MIF_LOG(ERR, "Failed to allocate intr handle");
    1475                 :          0 :                 return -ENOMEM;
    1476                 :            :         }
    1477                 :            : 
    1478                 :          0 :         mq->type =
    1479                 :          0 :             (pmd->role == MEMIF_ROLE_CLIENT) ? MEMIF_RING_C2S : MEMIF_RING_S2C;
    1480                 :          0 :         mq->n_pkts = 0;
    1481                 :          0 :         mq->n_bytes = 0;
    1482                 :            : 
    1483         [ #  # ]:          0 :         if (rte_intr_fd_set(mq->intr_handle, -1))
    1484                 :          0 :                 return -rte_errno;
    1485                 :            : 
    1486         [ #  # ]:          0 :         if (rte_intr_type_set(mq->intr_handle, RTE_INTR_HANDLE_EXT))
    1487                 :          0 :                 return -rte_errno;
    1488                 :            : 
    1489                 :          0 :         mq->in_port = dev->data->port_id;
    1490                 :          0 :         dev->data->tx_queues[qid] = mq;
    1491                 :            : 
    1492                 :          0 :         return 0;
    1493                 :            : }
    1494                 :            : 
    1495                 :            : static int
    1496                 :          0 : memif_rx_queue_setup(struct rte_eth_dev *dev,
    1497                 :            :                      uint16_t qid,
    1498                 :            :                      uint16_t nb_rx_desc __rte_unused,
    1499                 :            :                      unsigned int socket_id __rte_unused,
    1500                 :            :                      const struct rte_eth_rxconf *rx_conf __rte_unused,
    1501                 :            :                      struct rte_mempool *mb_pool)
    1502                 :            : {
    1503                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1504                 :            :         struct memif_queue *mq;
    1505                 :            : 
    1506                 :          0 :         mq = rte_zmalloc("rx-queue", sizeof(struct memif_queue), 0);
    1507         [ #  # ]:          0 :         if (mq == NULL) {
    1508                 :          0 :                 MIF_LOG(ERR, "Failed to allocate rx queue id: %u", qid);
    1509                 :          0 :                 return -ENOMEM;
    1510                 :            :         }
    1511                 :            : 
    1512                 :            :         /* Allocate interrupt instance */
    1513                 :          0 :         mq->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
    1514         [ #  # ]:          0 :         if (mq->intr_handle == NULL) {
    1515                 :          0 :                 MIF_LOG(ERR, "Failed to allocate intr handle");
    1516                 :          0 :                 return -ENOMEM;
    1517                 :            :         }
    1518                 :            : 
    1519                 :          0 :         mq->type = (pmd->role == MEMIF_ROLE_CLIENT) ? MEMIF_RING_S2C : MEMIF_RING_C2S;
    1520                 :          0 :         mq->n_pkts = 0;
    1521                 :          0 :         mq->n_bytes = 0;
    1522                 :            : 
    1523         [ #  # ]:          0 :         if (rte_intr_fd_set(mq->intr_handle, -1))
    1524                 :          0 :                 return -rte_errno;
    1525                 :            : 
    1526         [ #  # ]:          0 :         if (rte_intr_type_set(mq->intr_handle, RTE_INTR_HANDLE_EXT))
    1527                 :          0 :                 return -rte_errno;
    1528                 :            : 
    1529                 :          0 :         mq->mempool = mb_pool;
    1530                 :          0 :         mq->in_port = dev->data->port_id;
    1531                 :          0 :         dev->data->rx_queues[qid] = mq;
    1532                 :            : 
    1533                 :          0 :         return 0;
    1534                 :            : }
    1535                 :            : 
    1536                 :            : static void
    1537                 :          0 : memif_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
    1538                 :            : {
    1539                 :          0 :         struct memif_queue *mq = dev->data->rx_queues[qid];
    1540                 :            : 
    1541         [ #  # ]:          0 :         if (!mq)
    1542                 :            :                 return;
    1543                 :            : 
    1544                 :          0 :         rte_intr_instance_free(mq->intr_handle);
    1545                 :          0 :         rte_free(mq);
    1546                 :            : }
    1547                 :            : 
    1548                 :            : static void
    1549                 :          0 : memif_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
    1550                 :            : {
    1551                 :          0 :         struct memif_queue *mq = dev->data->tx_queues[qid];
    1552                 :            : 
    1553         [ #  # ]:          0 :         if (!mq)
    1554                 :            :                 return;
    1555                 :            : 
    1556                 :          0 :         rte_free(mq);
    1557                 :            : }
    1558                 :            : 
    1559                 :            : static int
    1560                 :          0 : memif_link_update(struct rte_eth_dev *dev,
    1561                 :            :                   int wait_to_complete __rte_unused)
    1562                 :            : {
    1563                 :            :         struct pmd_process_private *proc_private;
    1564                 :            : 
    1565         [ #  # ]:          0 :         if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
    1566                 :          0 :                 proc_private = dev->process_private;
    1567         [ #  # ]:          0 :                 if (dev->data->dev_link.link_status == RTE_ETH_LINK_UP &&
    1568         [ #  # ]:          0 :                                 proc_private->regions_num == 0) {
    1569                 :          0 :                         memif_mp_request_regions(dev);
    1570         [ #  # ]:          0 :                 } else if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN &&
    1571         [ #  # ]:          0 :                                 proc_private->regions_num > 0) {
    1572                 :          0 :                         memif_free_regions(dev);
    1573                 :            :                 }
    1574                 :            :         }
    1575                 :          0 :         return 0;
    1576                 :            : }
    1577                 :            : 
    1578                 :            : static int
    1579                 :          0 : memif_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
    1580                 :            : {
    1581                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1582                 :            :         struct memif_queue *mq;
    1583                 :            :         int i;
    1584                 :            :         uint8_t tmp, nq;
    1585                 :            : 
    1586                 :          0 :         stats->ipackets = 0;
    1587                 :          0 :         stats->ibytes = 0;
    1588                 :          0 :         stats->opackets = 0;
    1589                 :          0 :         stats->obytes = 0;
    1590                 :            : 
    1591         [ #  # ]:          0 :         tmp = (pmd->role == MEMIF_ROLE_CLIENT) ? pmd->run.num_s2c_rings :
    1592                 :            :             pmd->run.num_c2s_rings;
    1593                 :          0 :         nq = (tmp < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? tmp :
    1594                 :            :             RTE_ETHDEV_QUEUE_STAT_CNTRS;
    1595                 :            : 
    1596                 :            :         /* RX stats */
    1597         [ #  # ]:          0 :         for (i = 0; i < nq; i++) {
    1598                 :          0 :                 mq = dev->data->rx_queues[i];
    1599                 :          0 :                 stats->q_ipackets[i] = mq->n_pkts;
    1600                 :          0 :                 stats->q_ibytes[i] = mq->n_bytes;
    1601                 :          0 :                 stats->ipackets += mq->n_pkts;
    1602                 :          0 :                 stats->ibytes += mq->n_bytes;
    1603                 :            :         }
    1604                 :            : 
    1605         [ #  # ]:          0 :         tmp = (pmd->role == MEMIF_ROLE_CLIENT) ? pmd->run.num_c2s_rings :
    1606                 :            :             pmd->run.num_s2c_rings;
    1607                 :          0 :         nq = (tmp < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? tmp :
    1608                 :            :             RTE_ETHDEV_QUEUE_STAT_CNTRS;
    1609                 :            : 
    1610                 :            :         /* TX stats */
    1611         [ #  # ]:          0 :         for (i = 0; i < nq; i++) {
    1612                 :          0 :                 mq = dev->data->tx_queues[i];
    1613                 :          0 :                 stats->q_opackets[i] = mq->n_pkts;
    1614                 :          0 :                 stats->q_obytes[i] = mq->n_bytes;
    1615                 :          0 :                 stats->opackets += mq->n_pkts;
    1616                 :          0 :                 stats->obytes += mq->n_bytes;
    1617                 :            :         }
    1618                 :          0 :         return 0;
    1619                 :            : }
    1620                 :            : 
    1621                 :            : static int
    1622                 :          0 : memif_stats_reset(struct rte_eth_dev *dev)
    1623                 :            : {
    1624                 :          0 :         struct pmd_internals *pmd = dev->data->dev_private;
    1625                 :            :         int i;
    1626                 :            :         struct memif_queue *mq;
    1627                 :            : 
    1628         [ #  # ]:          0 :         for (i = 0; i < pmd->run.num_c2s_rings; i++) {
    1629         [ #  # ]:          0 :                 mq = (pmd->role == MEMIF_ROLE_CLIENT) ? dev->data->tx_queues[i] :
    1630                 :          0 :                     dev->data->rx_queues[i];
    1631                 :          0 :                 mq->n_pkts = 0;
    1632                 :          0 :                 mq->n_bytes = 0;
    1633                 :            :         }
    1634         [ #  # ]:          0 :         for (i = 0; i < pmd->run.num_s2c_rings; i++) {
    1635         [ #  # ]:          0 :                 mq = (pmd->role == MEMIF_ROLE_CLIENT) ? dev->data->rx_queues[i] :
    1636                 :          0 :                     dev->data->tx_queues[i];
    1637                 :          0 :                 mq->n_pkts = 0;
    1638                 :          0 :                 mq->n_bytes = 0;
    1639                 :            :         }
    1640                 :            : 
    1641                 :          0 :         return 0;
    1642                 :            : }
    1643                 :            : 
    1644                 :            : static const struct eth_dev_ops ops = {
    1645                 :            :         .dev_start = memif_dev_start,
    1646                 :            :         .dev_stop = memif_dev_stop,
    1647                 :            :         .dev_close = memif_dev_close,
    1648                 :            :         .dev_infos_get = memif_dev_info,
    1649                 :            :         .dev_configure = memif_dev_configure,
    1650                 :            :         .tx_queue_setup = memif_tx_queue_setup,
    1651                 :            :         .rx_queue_setup = memif_rx_queue_setup,
    1652                 :            :         .rx_queue_release = memif_rx_queue_release,
    1653                 :            :         .tx_queue_release = memif_tx_queue_release,
    1654                 :            :         .link_update = memif_link_update,
    1655                 :            :         .stats_get = memif_stats_get,
    1656                 :            :         .stats_reset = memif_stats_reset,
    1657                 :            : };
    1658                 :            : 
    1659                 :            : static int
    1660                 :          0 : memif_create(struct rte_vdev_device *vdev, enum memif_role_t role,
    1661                 :            :              memif_interface_id_t id, uint32_t flags,
    1662                 :            :              const char *socket_filename, uid_t owner_uid, gid_t owner_gid,
    1663                 :            :              memif_log2_ring_size_t log2_ring_size,
    1664                 :            :              uint16_t pkt_buffer_size, const char *secret,
    1665                 :            :              struct rte_ether_addr *ether_addr)
    1666                 :            : {
    1667                 :            :         int ret = 0;
    1668                 :            :         struct rte_eth_dev *eth_dev;
    1669                 :            :         struct rte_eth_dev_data *data;
    1670                 :            :         struct pmd_internals *pmd;
    1671                 :            :         struct pmd_process_private *process_private;
    1672         [ #  # ]:          0 :         const unsigned int numa_node = vdev->device.numa_node;
    1673                 :            :         const char *name = rte_vdev_device_name(vdev);
    1674                 :            : 
    1675                 :          0 :         eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*pmd));
    1676         [ #  # ]:          0 :         if (eth_dev == NULL) {
    1677                 :          0 :                 MIF_LOG(ERR, "%s: Unable to allocate device struct.", name);
    1678                 :          0 :                 return -1;
    1679                 :            :         }
    1680                 :            : 
    1681                 :            :         process_private = (struct pmd_process_private *)
    1682                 :          0 :                 rte_zmalloc(name, sizeof(struct pmd_process_private),
    1683                 :            :                             RTE_CACHE_LINE_SIZE);
    1684                 :            : 
    1685         [ #  # ]:          0 :         if (process_private == NULL) {
    1686                 :          0 :                 MIF_LOG(ERR, "Failed to alloc memory for process private");
    1687                 :          0 :                 return -1;
    1688                 :            :         }
    1689                 :          0 :         eth_dev->process_private = process_private;
    1690                 :            : 
    1691         [ #  # ]:          0 :         pmd = eth_dev->data->dev_private;
    1692                 :            :         memset(pmd, 0, sizeof(*pmd));
    1693                 :            : 
    1694                 :          0 :         pmd->id = id;
    1695                 :            :         pmd->flags = flags;
    1696                 :          0 :         pmd->flags |= ETH_MEMIF_FLAG_DISABLED;
    1697                 :          0 :         pmd->role = role;
    1698                 :            :         /* Zero-copy flag irelevant to server. */
    1699         [ #  # ]:          0 :         if (pmd->role == MEMIF_ROLE_SERVER)
    1700                 :          0 :                 pmd->flags &= ~ETH_MEMIF_FLAG_ZERO_COPY;
    1701                 :          0 :         pmd->owner_uid = owner_uid;
    1702                 :          0 :         pmd->owner_gid = owner_gid;
    1703                 :            : 
    1704                 :          0 :         ret = memif_socket_init(eth_dev, socket_filename);
    1705         [ #  # ]:          0 :         if (ret < 0)
    1706                 :            :                 return ret;
    1707                 :            : 
    1708         [ #  # ]:          0 :         memset(pmd->secret, 0, sizeof(char) * ETH_MEMIF_SECRET_SIZE);
    1709         [ #  # ]:          0 :         if (secret != NULL)
    1710                 :            :                 strlcpy(pmd->secret, secret, sizeof(pmd->secret));
    1711                 :            : 
    1712                 :          0 :         pmd->cfg.log2_ring_size = log2_ring_size;
    1713                 :            :         /* set in .dev_configure() */
    1714                 :          0 :         pmd->cfg.num_c2s_rings = 0;
    1715                 :          0 :         pmd->cfg.num_s2c_rings = 0;
    1716                 :            : 
    1717         [ #  # ]:          0 :         pmd->cfg.pkt_buffer_size = pkt_buffer_size;
    1718                 :            :         rte_spinlock_init(&pmd->cc_lock);
    1719                 :            : 
    1720                 :          0 :         data = eth_dev->data;
    1721                 :          0 :         data->dev_private = pmd;
    1722                 :          0 :         data->numa_node = numa_node;
    1723                 :          0 :         data->dev_link = pmd_link;
    1724                 :          0 :         data->mac_addrs = ether_addr;
    1725                 :          0 :         data->promiscuous = 1;
    1726                 :          0 :         data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
    1727                 :            : 
    1728                 :          0 :         eth_dev->dev_ops = &ops;
    1729                 :          0 :         eth_dev->device = &vdev->device;
    1730         [ #  # ]:          0 :         if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
    1731                 :          0 :                 eth_dev->rx_pkt_burst = eth_memif_rx_zc;
    1732                 :          0 :                 eth_dev->tx_pkt_burst = eth_memif_tx_zc;
    1733                 :            :         } else {
    1734                 :          0 :                 eth_dev->rx_pkt_burst = eth_memif_rx;
    1735                 :          0 :                 eth_dev->tx_pkt_burst = eth_memif_tx;
    1736                 :            :         }
    1737                 :            : 
    1738                 :          0 :         rte_eth_dev_probing_finish(eth_dev);
    1739                 :            : 
    1740                 :          0 :         return 0;
    1741                 :            : }
    1742                 :            : 
    1743                 :            : static int
    1744                 :          0 : memif_set_role(const char *key __rte_unused, const char *value,
    1745                 :            :                void *extra_args)
    1746                 :            : {
    1747                 :            :         enum memif_role_t *role = (enum memif_role_t *)extra_args;
    1748                 :            : 
    1749         [ #  # ]:          0 :         if (strstr(value, "server") != NULL) {
    1750                 :          0 :                 *role = MEMIF_ROLE_SERVER;
    1751         [ #  # ]:          0 :         } else if (strstr(value, "client") != NULL) {
    1752                 :          0 :                 *role = MEMIF_ROLE_CLIENT;
    1753         [ #  # ]:          0 :         } else if (strstr(value, "master") != NULL) {
    1754                 :          0 :                 MIF_LOG(NOTICE, "Role argument \"master\" is deprecated, use \"server\"");
    1755                 :          0 :                 *role = MEMIF_ROLE_SERVER;
    1756         [ #  # ]:          0 :         } else if (strstr(value, "slave") != NULL) {
    1757                 :          0 :                 MIF_LOG(NOTICE, "Role argument \"slave\" is deprecated, use \"client\"");
    1758                 :          0 :                 *role = MEMIF_ROLE_CLIENT;
    1759                 :            :         } else {
    1760                 :          0 :                 MIF_LOG(ERR, "Unknown role: %s.", value);
    1761                 :          0 :                 return -EINVAL;
    1762                 :            :         }
    1763                 :            :         return 0;
    1764                 :            : }
    1765                 :            : 
    1766                 :            : static int
    1767                 :          0 : memif_set_zc(const char *key __rte_unused, const char *value, void *extra_args)
    1768                 :            : {
    1769                 :            :         uint32_t *flags = (uint32_t *)extra_args;
    1770                 :            : 
    1771         [ #  # ]:          0 :         if (strstr(value, "yes") != NULL) {
    1772         [ #  # ]:          0 :                 if (!rte_mcfg_get_single_file_segments()) {
    1773                 :          0 :                         MIF_LOG(ERR, "Zero-copy doesn't support multi-file segments.");
    1774                 :          0 :                         return -ENOTSUP;
    1775                 :            :                 }
    1776                 :          0 :                 *flags |= ETH_MEMIF_FLAG_ZERO_COPY;
    1777         [ #  # ]:          0 :         } else if (strstr(value, "no") != NULL) {
    1778                 :          0 :                 *flags &= ~ETH_MEMIF_FLAG_ZERO_COPY;
    1779                 :            :         } else {
    1780                 :          0 :                 MIF_LOG(ERR, "Failed to parse zero-copy param: %s.", value);
    1781                 :          0 :                 return -EINVAL;
    1782                 :            :         }
    1783                 :            :         return 0;
    1784                 :            : }
    1785                 :            : 
    1786                 :            : static int
    1787                 :          0 : memif_set_id(const char *key __rte_unused, const char *value, void *extra_args)
    1788                 :            : {
    1789                 :            :         memif_interface_id_t *id = (memif_interface_id_t *)extra_args;
    1790                 :            : 
    1791                 :            :         /* even if parsing fails, 0 is a valid id */
    1792                 :          0 :         *id = strtoul(value, NULL, 10);
    1793                 :          0 :         return 0;
    1794                 :            : }
    1795                 :            : 
    1796                 :            : static int
    1797                 :          0 : memif_set_bs(const char *key __rte_unused, const char *value, void *extra_args)
    1798                 :            : {
    1799                 :            :         unsigned long tmp;
    1800                 :            :         uint16_t *pkt_buffer_size = (uint16_t *)extra_args;
    1801                 :            : 
    1802                 :          0 :         tmp = strtoul(value, NULL, 10);
    1803         [ #  # ]:          0 :         if (tmp == 0 || tmp > 0xFFFF) {
    1804                 :          0 :                 MIF_LOG(ERR, "Invalid buffer size: %s.", value);
    1805                 :          0 :                 return -EINVAL;
    1806                 :            :         }
    1807                 :          0 :         *pkt_buffer_size = tmp;
    1808                 :          0 :         return 0;
    1809                 :            : }
    1810                 :            : 
    1811                 :            : static int
    1812                 :          0 : memif_set_rs(const char *key __rte_unused, const char *value, void *extra_args)
    1813                 :            : {
    1814                 :            :         unsigned long tmp;
    1815                 :            :         memif_log2_ring_size_t *log2_ring_size =
    1816                 :            :             (memif_log2_ring_size_t *)extra_args;
    1817                 :            : 
    1818                 :          0 :         tmp = strtoul(value, NULL, 10);
    1819         [ #  # ]:          0 :         if (tmp == 0 || tmp > ETH_MEMIF_MAX_LOG2_RING_SIZE) {
    1820                 :          0 :                 MIF_LOG(ERR, "Invalid ring size: %s (max %u).",
    1821                 :            :                         value, ETH_MEMIF_MAX_LOG2_RING_SIZE);
    1822                 :          0 :                 return -EINVAL;
    1823                 :            :         }
    1824                 :          0 :         *log2_ring_size = tmp;
    1825                 :          0 :         return 0;
    1826                 :            : }
    1827                 :            : 
    1828                 :            : /* check if directory exists and if we have permission to read/write */
    1829                 :            : static int
    1830                 :          0 : memif_check_socket_filename(const char *filename)
    1831                 :            : {
    1832                 :            :         char *dir = NULL, *tmp;
    1833                 :            :         uint32_t idx;
    1834                 :            :         int ret = 0;
    1835                 :            : 
    1836         [ #  # ]:          0 :         if (strlen(filename) >= MEMIF_SOCKET_UN_SIZE) {
    1837                 :          0 :                 MIF_LOG(ERR, "Unix socket address too long (max 108).");
    1838                 :          0 :                 return -1;
    1839                 :            :         }
    1840                 :            : 
    1841                 :          0 :         tmp = strrchr(filename, '/');
    1842         [ #  # ]:          0 :         if (tmp != NULL) {
    1843                 :          0 :                 idx = tmp - filename;
    1844                 :          0 :                 dir = rte_zmalloc("memif_tmp", sizeof(char) * (idx + 1), 0);
    1845         [ #  # ]:          0 :                 if (dir == NULL) {
    1846                 :          0 :                         MIF_LOG(ERR, "Failed to allocate memory.");
    1847                 :          0 :                         return -1;
    1848                 :            :                 }
    1849                 :            :                 strlcpy(dir, filename, sizeof(char) * (idx + 1));
    1850                 :            :         }
    1851                 :            : 
    1852         [ #  # ]:          0 :         if (dir == NULL || (faccessat(-1, dir, F_OK | R_OK |
    1853                 :            :                                         W_OK, AT_EACCESS) < 0)) {
    1854                 :          0 :                 MIF_LOG(ERR, "Invalid socket directory.");
    1855                 :            :                 ret = -EINVAL;
    1856                 :            :         }
    1857                 :            : 
    1858                 :          0 :         rte_free(dir);
    1859                 :            : 
    1860                 :          0 :         return ret;
    1861                 :            : }
    1862                 :            : 
    1863                 :            : static int
    1864                 :          0 : memif_set_socket_filename(const char *key __rte_unused, const char *value,
    1865                 :            :                           void *extra_args)
    1866                 :            : {
    1867                 :            :         const char **socket_filename = (const char **)extra_args;
    1868                 :            : 
    1869                 :          0 :         *socket_filename = value;
    1870                 :          0 :         return 0;
    1871                 :            : }
    1872                 :            : 
    1873                 :            : static int
    1874                 :          0 : memif_set_is_socket_abstract(const char *key __rte_unused, const char *value, void *extra_args)
    1875                 :            : {
    1876                 :            :         uint32_t *flags = (uint32_t *)extra_args;
    1877                 :            : 
    1878         [ #  # ]:          0 :         if (strstr(value, "yes") != NULL) {
    1879                 :          0 :                 *flags |= ETH_MEMIF_FLAG_SOCKET_ABSTRACT;
    1880         [ #  # ]:          0 :         } else if (strstr(value, "no") != NULL) {
    1881                 :          0 :                 *flags &= ~ETH_MEMIF_FLAG_SOCKET_ABSTRACT;
    1882                 :            :         } else {
    1883                 :          0 :                 MIF_LOG(ERR, "Failed to parse socket-abstract param: %s.", value);
    1884                 :          0 :                 return -EINVAL;
    1885                 :            :         }
    1886                 :            :         return 0;
    1887                 :            : }
    1888                 :            : 
    1889                 :            : static int
    1890                 :          0 : memif_set_owner(const char *key, const char *value, void *extra_args)
    1891                 :            : {
    1892                 :            :         RTE_ASSERT(sizeof(uid_t) == sizeof(uint32_t));
    1893                 :            :         RTE_ASSERT(sizeof(gid_t) == sizeof(uint32_t));
    1894                 :            : 
    1895                 :            :         unsigned long val;
    1896                 :          0 :         char *end = NULL;
    1897                 :            :         uint32_t *id = (uint32_t *)extra_args;
    1898                 :            : 
    1899                 :          0 :         val = strtoul(value, &end, 10);
    1900   [ #  #  #  # ]:          0 :         if (*value == '\0' || *end != '\0') {
    1901                 :          0 :                 MIF_LOG(ERR, "Failed to parse %s: %s.", key, value);
    1902                 :          0 :                 return -EINVAL;
    1903                 :            :         }
    1904         [ #  # ]:          0 :         if (val >= UINT32_MAX) {
    1905                 :          0 :                 MIF_LOG(ERR, "Invalid %s: %s.", key, value);
    1906                 :          0 :                 return -ERANGE;
    1907                 :            :         }
    1908                 :            : 
    1909                 :          0 :         *id = val;
    1910                 :          0 :         return 0;
    1911                 :            : }
    1912                 :            : 
    1913                 :            : static int
    1914                 :          0 : memif_set_mac(const char *key __rte_unused, const char *value, void *extra_args)
    1915                 :            : {
    1916                 :            :         struct rte_ether_addr *ether_addr = (struct rte_ether_addr *)extra_args;
    1917                 :            : 
    1918         [ #  # ]:          0 :         if (rte_ether_unformat_addr(value, ether_addr) < 0)
    1919                 :          0 :                 MIF_LOG(WARNING, "Failed to parse mac '%s'.", value);
    1920                 :          0 :         return 0;
    1921                 :            : }
    1922                 :            : 
    1923                 :            : static int
    1924                 :          0 : memif_set_secret(const char *key __rte_unused, const char *value, void *extra_args)
    1925                 :            : {
    1926                 :            :         const char **secret = (const char **)extra_args;
    1927                 :            : 
    1928                 :          0 :         *secret = value;
    1929                 :          0 :         return 0;
    1930                 :            : }
    1931                 :            : 
    1932                 :            : static int
    1933         [ #  # ]:          0 : rte_pmd_memif_probe(struct rte_vdev_device *vdev)
    1934                 :            : {
    1935                 :            :         RTE_BUILD_BUG_ON(sizeof(memif_msg_t) != 128);
    1936                 :            :         RTE_BUILD_BUG_ON(sizeof(memif_desc_t) != 16);
    1937                 :            :         int ret = 0;
    1938                 :            :         struct rte_kvargs *kvlist;
    1939                 :            :         const char *name = rte_vdev_device_name(vdev);
    1940                 :          0 :         enum memif_role_t role = MEMIF_ROLE_CLIENT;
    1941                 :          0 :         memif_interface_id_t id = 0;
    1942                 :          0 :         uint16_t pkt_buffer_size = ETH_MEMIF_DEFAULT_PKT_BUFFER_SIZE;
    1943                 :          0 :         memif_log2_ring_size_t log2_ring_size = ETH_MEMIF_DEFAULT_RING_SIZE;
    1944                 :          0 :         const char *socket_filename = ETH_MEMIF_DEFAULT_SOCKET_FILENAME;
    1945                 :          0 :         uid_t owner_uid = -1;
    1946                 :          0 :         gid_t owner_gid = -1;
    1947                 :          0 :         uint32_t flags = 0;
    1948                 :          0 :         const char *secret = NULL;
    1949                 :          0 :         struct rte_ether_addr *ether_addr = rte_zmalloc("",
    1950                 :            :                 sizeof(struct rte_ether_addr), 0);
    1951                 :            :         struct rte_eth_dev *eth_dev;
    1952                 :            : 
    1953                 :          0 :         rte_eth_random_addr(ether_addr->addr_bytes);
    1954                 :            : 
    1955                 :          0 :         MIF_LOG(INFO, "Initialize MEMIF: %s.", name);
    1956                 :            : 
    1957         [ #  # ]:          0 :         if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
    1958                 :          0 :                 eth_dev = rte_eth_dev_attach_secondary(name);
    1959         [ #  # ]:          0 :                 if (!eth_dev) {
    1960                 :          0 :                         MIF_LOG(ERR, "Failed to probe %s", name);
    1961                 :          0 :                         return -1;
    1962                 :            :                 }
    1963                 :            : 
    1964                 :          0 :                 eth_dev->dev_ops = &ops;
    1965                 :          0 :                 eth_dev->device = &vdev->device;
    1966                 :          0 :                 eth_dev->rx_pkt_burst = eth_memif_rx;
    1967                 :          0 :                 eth_dev->tx_pkt_burst = eth_memif_tx;
    1968                 :            : 
    1969         [ #  # ]:          0 :                 if (!rte_eal_primary_proc_alive(NULL)) {
    1970                 :          0 :                         MIF_LOG(ERR, "Primary process is missing");
    1971                 :          0 :                         return -1;
    1972                 :            :                 }
    1973                 :            : 
    1974                 :          0 :                 eth_dev->process_private = (struct pmd_process_private *)
    1975                 :          0 :                         rte_zmalloc(name,
    1976                 :            :                                 sizeof(struct pmd_process_private),
    1977                 :            :                                 RTE_CACHE_LINE_SIZE);
    1978         [ #  # ]:          0 :                 if (eth_dev->process_private == NULL) {
    1979                 :          0 :                         MIF_LOG(ERR,
    1980                 :            :                                 "Failed to alloc memory for process private");
    1981                 :          0 :                         return -1;
    1982                 :            :                 }
    1983                 :            : 
    1984                 :          0 :                 rte_eth_dev_probing_finish(eth_dev);
    1985                 :            : 
    1986                 :          0 :                 return 0;
    1987                 :            :         }
    1988                 :            : 
    1989                 :          0 :         ret = rte_mp_action_register(MEMIF_MP_SEND_REGION, memif_mp_send_region);
    1990                 :            :         /*
    1991                 :            :          * Primary process can continue probing, but secondary process won't
    1992                 :            :          * be able to get memory regions information
    1993                 :            :          */
    1994   [ #  #  #  # ]:          0 :         if (ret < 0 && rte_errno != EEXIST)
    1995                 :          0 :                 MIF_LOG(WARNING, "Failed to register mp action callback: %s",
    1996                 :            :                         strerror(rte_errno));
    1997                 :            : 
    1998                 :            :         /* use abstract address by default */
    1999         [ #  # ]:          0 :         flags |= ETH_MEMIF_FLAG_SOCKET_ABSTRACT;
    2000                 :            : 
    2001                 :          0 :         kvlist = rte_kvargs_parse(rte_vdev_device_args(vdev), valid_arguments);
    2002                 :            : 
    2003                 :            :         /* parse parameters */
    2004         [ #  # ]:          0 :         if (kvlist != NULL) {
    2005                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_ROLE_ARG,
    2006                 :            :                                          &memif_set_role, &role);
    2007         [ #  # ]:          0 :                 if (ret < 0)
    2008                 :          0 :                         goto exit;
    2009                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_ID_ARG,
    2010                 :            :                                          &memif_set_id, &id);
    2011         [ #  # ]:          0 :                 if (ret < 0)
    2012                 :          0 :                         goto exit;
    2013                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_PKT_BUFFER_SIZE_ARG,
    2014                 :            :                                          &memif_set_bs, &pkt_buffer_size);
    2015         [ #  # ]:          0 :                 if (ret < 0)
    2016                 :          0 :                         goto exit;
    2017                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_RING_SIZE_ARG,
    2018                 :            :                                          &memif_set_rs, &log2_ring_size);
    2019         [ #  # ]:          0 :                 if (ret < 0)
    2020                 :          0 :                         goto exit;
    2021                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_SOCKET_ARG,
    2022                 :            :                                          &memif_set_socket_filename,
    2023                 :            :                                          (void *)(&socket_filename));
    2024         [ #  # ]:          0 :                 if (ret < 0)
    2025                 :          0 :                         goto exit;
    2026                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_SOCKET_ABSTRACT_ARG,
    2027                 :            :                                          &memif_set_is_socket_abstract, &flags);
    2028         [ #  # ]:          0 :                 if (ret < 0)
    2029                 :          0 :                         goto exit;
    2030                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_OWNER_UID_ARG,
    2031                 :            :                                          &memif_set_owner, &owner_uid);
    2032         [ #  # ]:          0 :                 if (ret < 0)
    2033                 :          0 :                         goto exit;
    2034                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_OWNER_GID_ARG,
    2035                 :            :                                          &memif_set_owner, &owner_gid);
    2036         [ #  # ]:          0 :                 if (ret < 0)
    2037                 :          0 :                         goto exit;
    2038                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_MAC_ARG,
    2039                 :            :                                          &memif_set_mac, ether_addr);
    2040         [ #  # ]:          0 :                 if (ret < 0)
    2041                 :          0 :                         goto exit;
    2042                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_ZC_ARG,
    2043                 :            :                                          &memif_set_zc, &flags);
    2044         [ #  # ]:          0 :                 if (ret < 0)
    2045                 :          0 :                         goto exit;
    2046                 :          0 :                 ret = rte_kvargs_process(kvlist, ETH_MEMIF_SECRET_ARG,
    2047                 :            :                                          &memif_set_secret, (void *)(&secret));
    2048         [ #  # ]:          0 :                 if (ret < 0)
    2049                 :          0 :                         goto exit;
    2050                 :            :         }
    2051                 :            : 
    2052         [ #  # ]:          0 :         if (!(flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT)) {
    2053                 :          0 :                 ret = memif_check_socket_filename(socket_filename);
    2054         [ #  # ]:          0 :                 if (ret < 0)
    2055                 :          0 :                         goto exit;
    2056                 :            :         }
    2057                 :            : 
    2058                 :            :         /* create interface */
    2059                 :          0 :         ret = memif_create(vdev, role, id, flags, socket_filename, owner_uid, owner_gid,
    2060                 :            :                            log2_ring_size, pkt_buffer_size, secret, ether_addr);
    2061                 :            : 
    2062                 :          0 : exit:
    2063                 :          0 :         rte_kvargs_free(kvlist);
    2064                 :          0 :         return ret;
    2065                 :            : }
    2066                 :            : 
    2067                 :            : static int
    2068         [ #  # ]:          0 : rte_pmd_memif_remove(struct rte_vdev_device *vdev)
    2069                 :            : {
    2070                 :            :         struct rte_eth_dev *eth_dev;
    2071                 :            : 
    2072                 :          0 :         eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
    2073         [ #  # ]:          0 :         if (eth_dev == NULL)
    2074                 :            :                 return 0;
    2075                 :            : 
    2076                 :          0 :         return rte_eth_dev_close(eth_dev->data->port_id);
    2077                 :            : }
    2078                 :            : 
    2079                 :            : static struct rte_vdev_driver pmd_memif_drv = {
    2080                 :            :         .probe = rte_pmd_memif_probe,
    2081                 :            :         .remove = rte_pmd_memif_remove,
    2082                 :            : };
    2083                 :            : 
    2084                 :        252 : RTE_PMD_REGISTER_VDEV(net_memif, pmd_memif_drv);
    2085                 :            : 
    2086                 :            : RTE_PMD_REGISTER_PARAM_STRING(net_memif,
    2087                 :            :                               ETH_MEMIF_ID_ARG "=<int>"
    2088                 :            :                               ETH_MEMIF_ROLE_ARG "=server|client"
    2089                 :            :                               ETH_MEMIF_PKT_BUFFER_SIZE_ARG "=<int>"
    2090                 :            :                               ETH_MEMIF_RING_SIZE_ARG "=<int>"
    2091                 :            :                               ETH_MEMIF_SOCKET_ARG "=<string>"
    2092                 :            :                               ETH_MEMIF_SOCKET_ABSTRACT_ARG "=yes|no"
    2093                 :            :                               ETH_MEMIF_OWNER_UID_ARG "=<int>"
    2094                 :            :                               ETH_MEMIF_OWNER_GID_ARG "=<int>"
    2095                 :            :                               ETH_MEMIF_MAC_ARG "=xx:xx:xx:xx:xx:xx"
    2096                 :            :                               ETH_MEMIF_ZC_ARG "=yes|no"
    2097                 :            :                               ETH_MEMIF_SECRET_ARG "=<string>");
    2098                 :            : 
    2099         [ -  + ]:        252 : RTE_LOG_REGISTER_DEFAULT(memif_logtype, NOTICE);

Generated by: LCOV version 1.14