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

Generated by: LCOV version 1.14