109c7e63aSJakub Grajciar /* SPDX-License-Identifier: BSD-3-Clause 209c7e63aSJakub Grajciar * Copyright 2018-2019 Cisco Systems, Inc. All rights reserved. 309c7e63aSJakub Grajciar */ 409c7e63aSJakub Grajciar 509c7e63aSJakub Grajciar #include <stdlib.h> 609c7e63aSJakub Grajciar #include <fcntl.h> 709c7e63aSJakub Grajciar #include <unistd.h> 809c7e63aSJakub Grajciar #include <sys/types.h> 909c7e63aSJakub Grajciar #include <sys/socket.h> 1009c7e63aSJakub Grajciar #include <sys/un.h> 1109c7e63aSJakub Grajciar #include <sys/ioctl.h> 1209c7e63aSJakub Grajciar #include <sys/mman.h> 1309c7e63aSJakub Grajciar #include <linux/if_ether.h> 1409c7e63aSJakub Grajciar #include <errno.h> 1509c7e63aSJakub Grajciar #include <sys/eventfd.h> 1609c7e63aSJakub Grajciar 1709c7e63aSJakub Grajciar #include <rte_version.h> 1809c7e63aSJakub Grajciar #include <rte_mbuf.h> 1909c7e63aSJakub Grajciar #include <rte_ether.h> 20df96fd0dSBruce Richardson #include <ethdev_driver.h> 21df96fd0dSBruce Richardson #include <ethdev_vdev.h> 2209c7e63aSJakub Grajciar #include <rte_malloc.h> 2309c7e63aSJakub Grajciar #include <rte_kvargs.h> 244851ef2bSDavid Marchand #include <bus_vdev_driver.h> 2509c7e63aSJakub Grajciar #include <rte_string_fns.h> 2643b815d8SJakub Grajciar #include <rte_errno.h> 2743b815d8SJakub Grajciar #include <rte_memory.h> 2843b815d8SJakub Grajciar #include <rte_memzone.h> 2943b815d8SJakub Grajciar #include <rte_eal_memconfig.h> 3009c7e63aSJakub Grajciar 3109c7e63aSJakub Grajciar #include "rte_eth_memif.h" 3209c7e63aSJakub Grajciar #include "memif_socket.h" 3309c7e63aSJakub Grajciar 3409c7e63aSJakub Grajciar #define ETH_MEMIF_ID_ARG "id" 3509c7e63aSJakub Grajciar #define ETH_MEMIF_ROLE_ARG "role" 3609c7e63aSJakub Grajciar #define ETH_MEMIF_PKT_BUFFER_SIZE_ARG "bsize" 3709c7e63aSJakub Grajciar #define ETH_MEMIF_RING_SIZE_ARG "rsize" 3809c7e63aSJakub Grajciar #define ETH_MEMIF_SOCKET_ARG "socket" 392f865ed0SJakub Grajciar #define ETH_MEMIF_SOCKET_ABSTRACT_ARG "socket-abstract" 40f62d5262SJunxiao Shi #define ETH_MEMIF_OWNER_UID_ARG "owner-uid" 41f62d5262SJunxiao Shi #define ETH_MEMIF_OWNER_GID_ARG "owner-gid" 4209c7e63aSJakub Grajciar #define ETH_MEMIF_MAC_ARG "mac" 4309c7e63aSJakub Grajciar #define ETH_MEMIF_ZC_ARG "zero-copy" 4409c7e63aSJakub Grajciar #define ETH_MEMIF_SECRET_ARG "secret" 4509c7e63aSJakub Grajciar 4609c7e63aSJakub Grajciar static const char * const valid_arguments[] = { 4709c7e63aSJakub Grajciar ETH_MEMIF_ID_ARG, 4809c7e63aSJakub Grajciar ETH_MEMIF_ROLE_ARG, 4909c7e63aSJakub Grajciar ETH_MEMIF_PKT_BUFFER_SIZE_ARG, 5009c7e63aSJakub Grajciar ETH_MEMIF_RING_SIZE_ARG, 5109c7e63aSJakub Grajciar ETH_MEMIF_SOCKET_ARG, 522f865ed0SJakub Grajciar ETH_MEMIF_SOCKET_ABSTRACT_ARG, 53f62d5262SJunxiao Shi ETH_MEMIF_OWNER_UID_ARG, 54f62d5262SJunxiao Shi ETH_MEMIF_OWNER_GID_ARG, 5509c7e63aSJakub Grajciar ETH_MEMIF_MAC_ARG, 5609c7e63aSJakub Grajciar ETH_MEMIF_ZC_ARG, 5709c7e63aSJakub Grajciar ETH_MEMIF_SECRET_ARG, 5809c7e63aSJakub Grajciar NULL 5909c7e63aSJakub Grajciar }; 6009c7e63aSJakub Grajciar 6119d4c1aeSJúlius Milan static const struct rte_eth_link pmd_link = { 62c1c8a32aSNathan Skrzypczak .link_speed = RTE_ETH_SPEED_NUM_100G, 63295968d1SFerruh Yigit .link_duplex = RTE_ETH_LINK_FULL_DUPLEX, 64295968d1SFerruh Yigit .link_status = RTE_ETH_LINK_DOWN, 65295968d1SFerruh Yigit .link_autoneg = RTE_ETH_LINK_AUTONEG 6619d4c1aeSJúlius Milan }; 6719d4c1aeSJúlius Milan 68c41a0495SJakub Grajciar #define MEMIF_MP_SEND_REGION "memif_mp_send_region" 69c41a0495SJakub Grajciar 7043b815d8SJakub Grajciar 7143b815d8SJakub Grajciar static int memif_region_init_zc(const struct rte_memseg_list *msl, 7243b815d8SJakub Grajciar const struct rte_memseg *ms, void *arg); 7343b815d8SJakub Grajciar 7409c7e63aSJakub Grajciar const char * 7509c7e63aSJakub Grajciar memif_version(void) 7609c7e63aSJakub Grajciar { 7709c7e63aSJakub Grajciar return ("memif-" RTE_STR(MEMIF_VERSION_MAJOR) "." RTE_STR(MEMIF_VERSION_MINOR)); 7809c7e63aSJakub Grajciar } 7909c7e63aSJakub Grajciar 80c41a0495SJakub Grajciar /* Message header to synchronize regions */ 81c41a0495SJakub Grajciar struct mp_region_msg { 82c41a0495SJakub Grajciar char port_name[RTE_DEV_NAME_MAX_LEN]; 83c41a0495SJakub Grajciar memif_region_index_t idx; 84c41a0495SJakub Grajciar memif_region_size_t size; 85c41a0495SJakub Grajciar }; 86c41a0495SJakub Grajciar 87c41a0495SJakub Grajciar static int 88c41a0495SJakub Grajciar memif_mp_send_region(const struct rte_mp_msg *msg, const void *peer) 89c41a0495SJakub Grajciar { 90c41a0495SJakub Grajciar struct rte_eth_dev *dev; 91c41a0495SJakub Grajciar struct pmd_process_private *proc_private; 92c41a0495SJakub Grajciar const struct mp_region_msg *msg_param = (const struct mp_region_msg *)msg->param; 93c41a0495SJakub Grajciar struct rte_mp_msg reply; 94c41a0495SJakub Grajciar struct mp_region_msg *reply_param = (struct mp_region_msg *)reply.param; 95c41a0495SJakub Grajciar 96c41a0495SJakub Grajciar /* Get requested port */ 97bcd9f098SKumara Parameshwaran dev = rte_eth_dev_get_by_name(msg_param->port_name); 98bcd9f098SKumara Parameshwaran if (!dev) { 99c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to get port id for %s", 100c41a0495SJakub Grajciar msg_param->port_name); 101c41a0495SJakub Grajciar return -1; 102c41a0495SJakub Grajciar } 103c41a0495SJakub Grajciar proc_private = dev->process_private; 104c41a0495SJakub Grajciar 105c41a0495SJakub Grajciar memset(&reply, 0, sizeof(reply)); 106c41a0495SJakub Grajciar strlcpy(reply.name, msg->name, sizeof(reply.name)); 107c41a0495SJakub Grajciar reply_param->idx = msg_param->idx; 108c41a0495SJakub Grajciar if (proc_private->regions[msg_param->idx] != NULL) { 109c41a0495SJakub Grajciar reply_param->size = proc_private->regions[msg_param->idx]->region_size; 110c41a0495SJakub Grajciar reply.fds[0] = proc_private->regions[msg_param->idx]->fd; 111c41a0495SJakub Grajciar reply.num_fds = 1; 112c41a0495SJakub Grajciar } 113c41a0495SJakub Grajciar reply.len_param = sizeof(*reply_param); 114c41a0495SJakub Grajciar if (rte_mp_reply(&reply, peer) < 0) { 115c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to reply to an add region request"); 116c41a0495SJakub Grajciar return -1; 117c41a0495SJakub Grajciar } 118c41a0495SJakub Grajciar 119c41a0495SJakub Grajciar return 0; 120c41a0495SJakub Grajciar } 121c41a0495SJakub Grajciar 122c41a0495SJakub Grajciar /* 123c41a0495SJakub Grajciar * Request regions 124c41a0495SJakub Grajciar * Called by secondary process, when ports link status goes up. 125c41a0495SJakub Grajciar */ 126c41a0495SJakub Grajciar static int 127c41a0495SJakub Grajciar memif_mp_request_regions(struct rte_eth_dev *dev) 128c41a0495SJakub Grajciar { 129c41a0495SJakub Grajciar int ret, i; 130c41a0495SJakub Grajciar struct timespec timeout = {.tv_sec = 5, .tv_nsec = 0}; 131c41a0495SJakub Grajciar struct rte_mp_msg msg, *reply; 132c41a0495SJakub Grajciar struct rte_mp_reply replies; 133c41a0495SJakub Grajciar struct mp_region_msg *msg_param = (struct mp_region_msg *)msg.param; 134c41a0495SJakub Grajciar struct mp_region_msg *reply_param; 135c41a0495SJakub Grajciar struct memif_region *r; 136c41a0495SJakub Grajciar struct pmd_process_private *proc_private = dev->process_private; 13743b815d8SJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 138d250589dSStephen Hemminger /* in case of zero-copy client, only request region 0 */ 13943b815d8SJakub Grajciar uint16_t max_region_num = (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) ? 14043b815d8SJakub Grajciar 1 : ETH_MEMIF_MAX_REGION_NUM; 141c41a0495SJakub Grajciar 142c41a0495SJakub Grajciar MIF_LOG(DEBUG, "Requesting memory regions"); 143c41a0495SJakub Grajciar 14443b815d8SJakub Grajciar for (i = 0; i < max_region_num; i++) { 145c41a0495SJakub Grajciar /* Prepare the message */ 146c41a0495SJakub Grajciar memset(&msg, 0, sizeof(msg)); 147c41a0495SJakub Grajciar strlcpy(msg.name, MEMIF_MP_SEND_REGION, sizeof(msg.name)); 148c41a0495SJakub Grajciar strlcpy(msg_param->port_name, dev->data->name, 149c41a0495SJakub Grajciar sizeof(msg_param->port_name)); 150c41a0495SJakub Grajciar msg_param->idx = i; 151c41a0495SJakub Grajciar msg.len_param = sizeof(*msg_param); 152c41a0495SJakub Grajciar 153c41a0495SJakub Grajciar /* Send message */ 154c41a0495SJakub Grajciar ret = rte_mp_request_sync(&msg, &replies, &timeout); 155c41a0495SJakub Grajciar if (ret < 0 || replies.nb_received != 1) { 156c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to send mp msg: %d", 157c41a0495SJakub Grajciar rte_errno); 158c41a0495SJakub Grajciar return -1; 159c41a0495SJakub Grajciar } 160c41a0495SJakub Grajciar 161c41a0495SJakub Grajciar reply = &replies.msgs[0]; 162c41a0495SJakub Grajciar reply_param = (struct mp_region_msg *)reply->param; 163c41a0495SJakub Grajciar 164c41a0495SJakub Grajciar if (reply_param->size > 0) { 165c41a0495SJakub Grajciar r = rte_zmalloc("region", sizeof(struct memif_region), 0); 166c41a0495SJakub Grajciar if (r == NULL) { 167c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to alloc memif region."); 168c41a0495SJakub Grajciar free(reply); 169c41a0495SJakub Grajciar return -ENOMEM; 170c41a0495SJakub Grajciar } 171c41a0495SJakub Grajciar r->region_size = reply_param->size; 172c41a0495SJakub Grajciar if (reply->num_fds < 1) { 173c41a0495SJakub Grajciar MIF_LOG(ERR, "Missing file descriptor."); 174c41a0495SJakub Grajciar free(reply); 175c41a0495SJakub Grajciar return -1; 176c41a0495SJakub Grajciar } 177c41a0495SJakub Grajciar r->fd = reply->fds[0]; 178c41a0495SJakub Grajciar r->addr = NULL; 179c41a0495SJakub Grajciar 180c41a0495SJakub Grajciar proc_private->regions[reply_param->idx] = r; 181c41a0495SJakub Grajciar proc_private->regions_num++; 182c41a0495SJakub Grajciar } 183c41a0495SJakub Grajciar free(reply); 184c41a0495SJakub Grajciar } 185c41a0495SJakub Grajciar 18643b815d8SJakub Grajciar if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) { 18743b815d8SJakub Grajciar ret = rte_memseg_walk(memif_region_init_zc, (void *)proc_private); 18843b815d8SJakub Grajciar if (ret < 0) 18943b815d8SJakub Grajciar return ret; 19043b815d8SJakub Grajciar } 19143b815d8SJakub Grajciar 192c41a0495SJakub Grajciar return memif_connect(dev); 193c41a0495SJakub Grajciar } 194c41a0495SJakub Grajciar 195bdad90d1SIvan Ilchenko static int 19609c7e63aSJakub Grajciar memif_dev_info(struct rte_eth_dev *dev __rte_unused, struct rte_eth_dev_info *dev_info) 19709c7e63aSJakub Grajciar { 19809c7e63aSJakub Grajciar dev_info->max_mac_addrs = 1; 199411878baSFerruh Yigit dev_info->max_rx_pktlen = RTE_ETHER_MAX_LEN; 20009c7e63aSJakub Grajciar dev_info->max_rx_queues = ETH_MEMIF_MAX_NUM_Q_PAIRS; 20109c7e63aSJakub Grajciar dev_info->max_tx_queues = ETH_MEMIF_MAX_NUM_Q_PAIRS; 20209c7e63aSJakub Grajciar dev_info->min_rx_bufsize = 0; 203295968d1SFerruh Yigit dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 204bdad90d1SIvan Ilchenko 205bdad90d1SIvan Ilchenko return 0; 20609c7e63aSJakub Grajciar } 20709c7e63aSJakub Grajciar 20809c7e63aSJakub Grajciar static memif_ring_t * 209c41a0495SJakub Grajciar memif_get_ring(struct pmd_internals *pmd, struct pmd_process_private *proc_private, 210c41a0495SJakub Grajciar memif_ring_type_t type, uint16_t ring_num) 21109c7e63aSJakub Grajciar { 21209c7e63aSJakub Grajciar /* rings only in region 0 */ 213c41a0495SJakub Grajciar void *p = proc_private->regions[0]->addr; 21409c7e63aSJakub Grajciar int ring_size = sizeof(memif_ring_t) + sizeof(memif_desc_t) * 21509c7e63aSJakub Grajciar (1 << pmd->run.log2_ring_size); 21609c7e63aSJakub Grajciar 217d250589dSStephen Hemminger p = (uint8_t *)p + (ring_num + type * pmd->run.num_c2s_rings) * ring_size; 21809c7e63aSJakub Grajciar 21909c7e63aSJakub Grajciar return (memif_ring_t *)p; 22009c7e63aSJakub Grajciar } 22109c7e63aSJakub Grajciar 222c41a0495SJakub Grajciar static memif_region_offset_t 223c41a0495SJakub Grajciar memif_get_ring_offset(struct rte_eth_dev *dev, struct memif_queue *mq, 224c41a0495SJakub Grajciar memif_ring_type_t type, uint16_t num) 22509c7e63aSJakub Grajciar { 226c41a0495SJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 227c41a0495SJakub Grajciar struct pmd_process_private *proc_private = dev->process_private; 228c41a0495SJakub Grajciar 229c41a0495SJakub Grajciar return ((uint8_t *)memif_get_ring(pmd, proc_private, type, num) - 230c41a0495SJakub Grajciar (uint8_t *)proc_private->regions[mq->region]->addr); 231c41a0495SJakub Grajciar } 232c41a0495SJakub Grajciar 233c41a0495SJakub Grajciar static memif_ring_t * 234c41a0495SJakub Grajciar memif_get_ring_from_queue(struct pmd_process_private *proc_private, 235c41a0495SJakub Grajciar struct memif_queue *mq) 236c41a0495SJakub Grajciar { 237c41a0495SJakub Grajciar struct memif_region *r; 238c41a0495SJakub Grajciar 239c41a0495SJakub Grajciar r = proc_private->regions[mq->region]; 240c41a0495SJakub Grajciar if (r == NULL) 241c41a0495SJakub Grajciar return NULL; 242c41a0495SJakub Grajciar 243c41a0495SJakub Grajciar return (memif_ring_t *)((uint8_t *)r->addr + mq->ring_offset); 244c41a0495SJakub Grajciar } 245c41a0495SJakub Grajciar 246c41a0495SJakub Grajciar static void * 247c41a0495SJakub Grajciar memif_get_buffer(struct pmd_process_private *proc_private, memif_desc_t *d) 248c41a0495SJakub Grajciar { 249c41a0495SJakub Grajciar return ((uint8_t *)proc_private->regions[d->region]->addr + d->offset); 25009c7e63aSJakub Grajciar } 25109c7e63aSJakub Grajciar 252d250589dSStephen Hemminger /* Free mbufs received by server */ 25343b815d8SJakub Grajciar static void 25443b815d8SJakub Grajciar memif_free_stored_mbufs(struct pmd_process_private *proc_private, struct memif_queue *mq) 25543b815d8SJakub Grajciar { 2569ef7dc22SHonnappa Nagarahalli uint16_t cur_tail; 25743b815d8SJakub Grajciar uint16_t mask = (1 << mq->log2_ring_size) - 1; 25843b815d8SJakub Grajciar memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq); 25943b815d8SJakub Grajciar 26043b815d8SJakub Grajciar /* FIXME: improve performance */ 2617ec9d6f4SPhil Yang /* The ring->tail acts as a guard variable between Tx and Rx 2627ec9d6f4SPhil Yang * threads, so using load-acquire pairs with store-release 263d250589dSStephen Hemminger * in function eth_memif_rx for C2S queues. 2647ec9d6f4SPhil Yang */ 265e12a0166STyler Retzlaff cur_tail = rte_atomic_load_explicit(&ring->tail, rte_memory_order_acquire); 2669ef7dc22SHonnappa Nagarahalli while (mq->last_tail != cur_tail) { 26743b815d8SJakub Grajciar RTE_MBUF_PREFETCH_TO_FREE(mq->buffers[(mq->last_tail + 1) & mask]); 26843b815d8SJakub Grajciar rte_pktmbuf_free_seg(mq->buffers[mq->last_tail & mask]); 26943b815d8SJakub Grajciar mq->last_tail++; 27043b815d8SJakub Grajciar } 27143b815d8SJakub Grajciar } 27243b815d8SJakub Grajciar 27309c7e63aSJakub Grajciar static int 27409c7e63aSJakub Grajciar memif_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *cur_tail, 27509c7e63aSJakub Grajciar struct rte_mbuf *tail) 27609c7e63aSJakub Grajciar { 27709c7e63aSJakub Grajciar /* Check for number-of-segments-overflow */ 27809c7e63aSJakub Grajciar if (unlikely(head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS)) 27909c7e63aSJakub Grajciar return -EOVERFLOW; 28009c7e63aSJakub Grajciar 28109c7e63aSJakub Grajciar /* Chain 'tail' onto the old tail */ 28209c7e63aSJakub Grajciar cur_tail->next = tail; 28309c7e63aSJakub Grajciar 28409c7e63aSJakub Grajciar /* accumulate number of segments and total length. */ 28509c7e63aSJakub Grajciar head->nb_segs = (uint16_t)(head->nb_segs + tail->nb_segs); 28609c7e63aSJakub Grajciar 28709c7e63aSJakub Grajciar tail->pkt_len = tail->data_len; 28809c7e63aSJakub Grajciar head->pkt_len += tail->pkt_len; 28909c7e63aSJakub Grajciar 29009c7e63aSJakub Grajciar return 0; 29109c7e63aSJakub Grajciar } 29209c7e63aSJakub Grajciar 29309c7e63aSJakub Grajciar static uint16_t 29409c7e63aSJakub Grajciar eth_memif_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) 29509c7e63aSJakub Grajciar { 29609c7e63aSJakub Grajciar struct memif_queue *mq = queue; 297c41a0495SJakub Grajciar struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private; 298c41a0495SJakub Grajciar struct pmd_process_private *proc_private = 299c41a0495SJakub Grajciar rte_eth_devices[mq->in_port].process_private; 300c41a0495SJakub Grajciar memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq); 30109c7e63aSJakub Grajciar uint16_t cur_slot, last_slot, n_slots, ring_size, mask, s0; 302aa17df86SJoyce Kong uint16_t pkts, rx_pkts, n_rx_pkts = 0; 30309c7e63aSJakub Grajciar uint16_t mbuf_size = rte_pktmbuf_data_room_size(mq->mempool) - 30409c7e63aSJakub Grajciar RTE_PKTMBUF_HEADROOM; 30509c7e63aSJakub Grajciar uint16_t src_len, src_off, dst_len, dst_off, cp_len; 30609c7e63aSJakub Grajciar memif_ring_type_t type = mq->type; 30709c7e63aSJakub Grajciar memif_desc_t *d0; 30809c7e63aSJakub Grajciar struct rte_mbuf *mbuf, *mbuf_head, *mbuf_tail; 30909c7e63aSJakub Grajciar uint64_t b; 31009c7e63aSJakub Grajciar ssize_t size __rte_unused; 31109c7e63aSJakub Grajciar uint16_t head; 31209c7e63aSJakub Grajciar int ret; 313c41a0495SJakub Grajciar struct rte_eth_link link; 31409c7e63aSJakub Grajciar 31509c7e63aSJakub Grajciar if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0)) 31609c7e63aSJakub Grajciar return 0; 317c41a0495SJakub Grajciar if (unlikely(ring == NULL)) { 318c41a0495SJakub Grajciar /* Secondary process will attempt to request regions. */ 319abfc0b9fSAndrew Rybchenko ret = rte_eth_link_get(mq->in_port, &link); 320abfc0b9fSAndrew Rybchenko if (ret < 0) 321abfc0b9fSAndrew Rybchenko MIF_LOG(ERR, "Failed to get port %u link info: %s", 322abfc0b9fSAndrew Rybchenko mq->in_port, rte_strerror(-ret)); 32309c7e63aSJakub Grajciar return 0; 324c41a0495SJakub Grajciar } 32509c7e63aSJakub Grajciar 32609c7e63aSJakub Grajciar /* consume interrupt */ 327aedd054cSHarman Kalra if (((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) && 328aedd054cSHarman Kalra (rte_intr_fd_get(mq->intr_handle) >= 0)) 329d61138d4SHarman Kalra size = read(rte_intr_fd_get(mq->intr_handle), &b, 330d61138d4SHarman Kalra sizeof(b)); 33109c7e63aSJakub Grajciar 33209c7e63aSJakub Grajciar ring_size = 1 << mq->log2_ring_size; 33309c7e63aSJakub Grajciar mask = ring_size - 1; 33409c7e63aSJakub Grajciar 335d250589dSStephen Hemminger if (type == MEMIF_RING_C2S) { 336a2aafb9aSPhil Yang cur_slot = mq->last_head; 337e12a0166STyler Retzlaff last_slot = rte_atomic_load_explicit(&ring->head, rte_memory_order_acquire); 338a2aafb9aSPhil Yang } else { 339a2aafb9aSPhil Yang cur_slot = mq->last_tail; 340e12a0166STyler Retzlaff last_slot = rte_atomic_load_explicit(&ring->tail, rte_memory_order_acquire); 341a2aafb9aSPhil Yang } 342a2aafb9aSPhil Yang 34309c7e63aSJakub Grajciar if (cur_slot == last_slot) 34409c7e63aSJakub Grajciar goto refill; 34509c7e63aSJakub Grajciar n_slots = last_slot - cur_slot; 34609c7e63aSJakub Grajciar 347aa17df86SJoyce Kong if (likely(mbuf_size >= pmd->cfg.pkt_buffer_size)) { 348aa17df86SJoyce Kong struct rte_mbuf *mbufs[MAX_PKT_BURST]; 349aa17df86SJoyce Kong next_bulk: 350aa17df86SJoyce Kong ret = rte_pktmbuf_alloc_bulk(mq->mempool, mbufs, MAX_PKT_BURST); 351aa17df86SJoyce Kong if (unlikely(ret < 0)) 352aa17df86SJoyce Kong goto no_free_bufs; 353aa17df86SJoyce Kong 354aa17df86SJoyce Kong rx_pkts = 0; 355aa17df86SJoyce Kong pkts = nb_pkts < MAX_PKT_BURST ? nb_pkts : MAX_PKT_BURST; 356aa17df86SJoyce Kong while (n_slots && rx_pkts < pkts) { 357cd7b0da6SJoyce Kong mbuf_head = mbufs[rx_pkts]; 358aa17df86SJoyce Kong mbuf = mbuf_head; 359aa17df86SJoyce Kong 360aa17df86SJoyce Kong next_slot1: 361aa17df86SJoyce Kong mbuf->port = mq->in_port; 362aa17df86SJoyce Kong s0 = cur_slot & mask; 363aa17df86SJoyce Kong d0 = &ring->desc[s0]; 364aa17df86SJoyce Kong 365aa17df86SJoyce Kong cp_len = d0->length; 366aa17df86SJoyce Kong 367aa17df86SJoyce Kong rte_pktmbuf_data_len(mbuf) = cp_len; 368aa17df86SJoyce Kong rte_pktmbuf_pkt_len(mbuf) = cp_len; 369aa17df86SJoyce Kong if (mbuf != mbuf_head) 370aa17df86SJoyce Kong rte_pktmbuf_pkt_len(mbuf_head) += cp_len; 371aa17df86SJoyce Kong 372aa17df86SJoyce Kong rte_memcpy(rte_pktmbuf_mtod(mbuf, void *), 373aa17df86SJoyce Kong (uint8_t *)memif_get_buffer(proc_private, d0), cp_len); 374aa17df86SJoyce Kong 375aa17df86SJoyce Kong cur_slot++; 376aa17df86SJoyce Kong n_slots--; 377aa17df86SJoyce Kong 378aa17df86SJoyce Kong if (d0->flags & MEMIF_DESC_FLAG_NEXT) { 379aa17df86SJoyce Kong mbuf_tail = mbuf; 380aa17df86SJoyce Kong mbuf = rte_pktmbuf_alloc(mq->mempool); 381aa17df86SJoyce Kong if (unlikely(mbuf == NULL)) { 382aa17df86SJoyce Kong rte_pktmbuf_free_bulk(mbufs + rx_pkts, 383aa17df86SJoyce Kong MAX_PKT_BURST - rx_pkts); 384aa17df86SJoyce Kong goto no_free_bufs; 385aa17df86SJoyce Kong } 386aa17df86SJoyce Kong ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf); 387aa17df86SJoyce Kong if (unlikely(ret < 0)) { 388aa17df86SJoyce Kong MIF_LOG(ERR, "number-of-segments-overflow"); 389aa17df86SJoyce Kong rte_pktmbuf_free(mbuf); 390aa17df86SJoyce Kong rte_pktmbuf_free_bulk(mbufs + rx_pkts, 391aa17df86SJoyce Kong MAX_PKT_BURST - rx_pkts); 392aa17df86SJoyce Kong goto no_free_bufs; 393aa17df86SJoyce Kong } 394aa17df86SJoyce Kong goto next_slot1; 395aa17df86SJoyce Kong } 396aa17df86SJoyce Kong 397aa17df86SJoyce Kong mq->n_bytes += rte_pktmbuf_pkt_len(mbuf_head); 398aa17df86SJoyce Kong *bufs++ = mbuf_head; 399aa17df86SJoyce Kong rx_pkts++; 400aa17df86SJoyce Kong n_rx_pkts++; 401aa17df86SJoyce Kong } 402aa17df86SJoyce Kong 403aa17df86SJoyce Kong if (rx_pkts < MAX_PKT_BURST) { 404aa17df86SJoyce Kong rte_pktmbuf_free_bulk(mbufs + rx_pkts, MAX_PKT_BURST - rx_pkts); 405aa17df86SJoyce Kong } else { 406aa17df86SJoyce Kong nb_pkts -= rx_pkts; 407aa17df86SJoyce Kong if (nb_pkts) 408aa17df86SJoyce Kong goto next_bulk; 409aa17df86SJoyce Kong } 410aa17df86SJoyce Kong } else { 41109c7e63aSJakub Grajciar while (n_slots && n_rx_pkts < nb_pkts) { 41209c7e63aSJakub Grajciar mbuf_head = rte_pktmbuf_alloc(mq->mempool); 41309c7e63aSJakub Grajciar if (unlikely(mbuf_head == NULL)) 41409c7e63aSJakub Grajciar goto no_free_bufs; 41509c7e63aSJakub Grajciar mbuf = mbuf_head; 41609c7e63aSJakub Grajciar mbuf->port = mq->in_port; 41709c7e63aSJakub Grajciar 418aa17df86SJoyce Kong next_slot2: 41909c7e63aSJakub Grajciar s0 = cur_slot & mask; 42009c7e63aSJakub Grajciar d0 = &ring->desc[s0]; 42109c7e63aSJakub Grajciar 42209c7e63aSJakub Grajciar src_len = d0->length; 423aa17df86SJoyce Kong dst_off = 0; 42409c7e63aSJakub Grajciar src_off = 0; 42509c7e63aSJakub Grajciar 42609c7e63aSJakub Grajciar do { 42709c7e63aSJakub Grajciar dst_len = mbuf_size - dst_off; 42809c7e63aSJakub Grajciar if (dst_len == 0) { 42909c7e63aSJakub Grajciar dst_off = 0; 43009c7e63aSJakub Grajciar dst_len = mbuf_size; 43109c7e63aSJakub Grajciar 43209c7e63aSJakub Grajciar /* store pointer to tail */ 43309c7e63aSJakub Grajciar mbuf_tail = mbuf; 43409c7e63aSJakub Grajciar mbuf = rte_pktmbuf_alloc(mq->mempool); 43509c7e63aSJakub Grajciar if (unlikely(mbuf == NULL)) 43609c7e63aSJakub Grajciar goto no_free_bufs; 43709c7e63aSJakub Grajciar mbuf->port = mq->in_port; 43809c7e63aSJakub Grajciar ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf); 43909c7e63aSJakub Grajciar if (unlikely(ret < 0)) { 440c41a0495SJakub Grajciar MIF_LOG(ERR, "number-of-segments-overflow"); 44109c7e63aSJakub Grajciar rte_pktmbuf_free(mbuf); 44209c7e63aSJakub Grajciar goto no_free_bufs; 44309c7e63aSJakub Grajciar } 44409c7e63aSJakub Grajciar } 44509c7e63aSJakub Grajciar cp_len = RTE_MIN(dst_len, src_len); 44609c7e63aSJakub Grajciar 44709c7e63aSJakub Grajciar rte_pktmbuf_data_len(mbuf) += cp_len; 44809c7e63aSJakub Grajciar rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf); 44909c7e63aSJakub Grajciar if (mbuf != mbuf_head) 45009c7e63aSJakub Grajciar rte_pktmbuf_pkt_len(mbuf_head) += cp_len; 45109c7e63aSJakub Grajciar 452663191e2SDavid Christensen rte_memcpy(rte_pktmbuf_mtod_offset(mbuf, void *, 453663191e2SDavid Christensen dst_off), 454663191e2SDavid Christensen (uint8_t *)memif_get_buffer(proc_private, d0) + 455663191e2SDavid Christensen src_off, cp_len); 45609c7e63aSJakub Grajciar 45709c7e63aSJakub Grajciar src_off += cp_len; 45809c7e63aSJakub Grajciar dst_off += cp_len; 45909c7e63aSJakub Grajciar src_len -= cp_len; 46009c7e63aSJakub Grajciar } while (src_len); 46109c7e63aSJakub Grajciar 46209c7e63aSJakub Grajciar cur_slot++; 46309c7e63aSJakub Grajciar n_slots--; 46409c7e63aSJakub Grajciar 46509c7e63aSJakub Grajciar if (d0->flags & MEMIF_DESC_FLAG_NEXT) 466aa17df86SJoyce Kong goto next_slot2; 46709c7e63aSJakub Grajciar 46809c7e63aSJakub Grajciar mq->n_bytes += rte_pktmbuf_pkt_len(mbuf_head); 46909c7e63aSJakub Grajciar *bufs++ = mbuf_head; 47009c7e63aSJakub Grajciar n_rx_pkts++; 47109c7e63aSJakub Grajciar } 472aa17df86SJoyce Kong } 47309c7e63aSJakub Grajciar 47409c7e63aSJakub Grajciar no_free_bufs: 475d250589dSStephen Hemminger if (type == MEMIF_RING_C2S) { 476e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->tail, cur_slot, rte_memory_order_release); 47709c7e63aSJakub Grajciar mq->last_head = cur_slot; 47809c7e63aSJakub Grajciar } else { 47909c7e63aSJakub Grajciar mq->last_tail = cur_slot; 48009c7e63aSJakub Grajciar } 48109c7e63aSJakub Grajciar 48209c7e63aSJakub Grajciar refill: 483d250589dSStephen Hemminger if (type == MEMIF_RING_S2C) { 484562fc6efSHonnappa Nagarahalli /* ring->head is updated by the receiver and this function 485562fc6efSHonnappa Nagarahalli * is called in the context of receiver thread. The loads in 486562fc6efSHonnappa Nagarahalli * the receiver do not need to synchronize with its own stores. 487562fc6efSHonnappa Nagarahalli */ 488e12a0166STyler Retzlaff head = rte_atomic_load_explicit(&ring->head, rte_memory_order_relaxed); 48909c7e63aSJakub Grajciar n_slots = ring_size - head + mq->last_tail; 49009c7e63aSJakub Grajciar 49109c7e63aSJakub Grajciar while (n_slots--) { 49209c7e63aSJakub Grajciar s0 = head++ & mask; 49309c7e63aSJakub Grajciar d0 = &ring->desc[s0]; 49409c7e63aSJakub Grajciar d0->length = pmd->run.pkt_buffer_size; 49509c7e63aSJakub Grajciar } 496e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->head, head, rte_memory_order_release); 49709c7e63aSJakub Grajciar } 49809c7e63aSJakub Grajciar 49909c7e63aSJakub Grajciar mq->n_pkts += n_rx_pkts; 50009c7e63aSJakub Grajciar return n_rx_pkts; 50109c7e63aSJakub Grajciar } 50209c7e63aSJakub Grajciar 50309c7e63aSJakub Grajciar static uint16_t 50443b815d8SJakub Grajciar eth_memif_rx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) 50543b815d8SJakub Grajciar { 50643b815d8SJakub Grajciar struct memif_queue *mq = queue; 50743b815d8SJakub Grajciar struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private; 50843b815d8SJakub Grajciar struct pmd_process_private *proc_private = 50943b815d8SJakub Grajciar rte_eth_devices[mq->in_port].process_private; 51043b815d8SJakub Grajciar memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq); 51143b815d8SJakub Grajciar uint16_t cur_slot, last_slot, n_slots, ring_size, mask, s0, head; 51243b815d8SJakub Grajciar uint16_t n_rx_pkts = 0; 51343b815d8SJakub Grajciar memif_desc_t *d0; 51443b815d8SJakub Grajciar struct rte_mbuf *mbuf, *mbuf_tail; 51543b815d8SJakub Grajciar struct rte_mbuf *mbuf_head = NULL; 51643b815d8SJakub Grajciar int ret; 51743b815d8SJakub Grajciar struct rte_eth_link link; 51843b815d8SJakub Grajciar 51943b815d8SJakub Grajciar if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0)) 52043b815d8SJakub Grajciar return 0; 52143b815d8SJakub Grajciar if (unlikely(ring == NULL)) { 52243b815d8SJakub Grajciar /* Secondary process will attempt to request regions. */ 523*a4fa02e0SStephen Hemminger ret = rte_eth_link_get(mq->in_port, &link); 524*a4fa02e0SStephen Hemminger if (ret < 0) 525*a4fa02e0SStephen Hemminger MIF_LOG(ERR, "Failed to get port %u link info: %s", 526*a4fa02e0SStephen Hemminger mq->in_port, rte_strerror(-ret)); 52743b815d8SJakub Grajciar return 0; 52843b815d8SJakub Grajciar } 52943b815d8SJakub Grajciar 53043b815d8SJakub Grajciar /* consume interrupt */ 531aedd054cSHarman Kalra if ((rte_intr_fd_get(mq->intr_handle) >= 0) && 532aedd054cSHarman Kalra ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)) { 53343b815d8SJakub Grajciar uint64_t b; 53443b815d8SJakub Grajciar ssize_t size __rte_unused; 535d61138d4SHarman Kalra size = read(rte_intr_fd_get(mq->intr_handle), &b, 536d61138d4SHarman Kalra sizeof(b)); 53743b815d8SJakub Grajciar } 53843b815d8SJakub Grajciar 53943b815d8SJakub Grajciar ring_size = 1 << mq->log2_ring_size; 54043b815d8SJakub Grajciar mask = ring_size - 1; 54143b815d8SJakub Grajciar 54243b815d8SJakub Grajciar cur_slot = mq->last_tail; 5437ec9d6f4SPhil Yang /* The ring->tail acts as a guard variable between Tx and Rx 5447ec9d6f4SPhil Yang * threads, so using load-acquire pairs with store-release 5457ec9d6f4SPhil Yang * to synchronize it between threads. 5467ec9d6f4SPhil Yang */ 547e12a0166STyler Retzlaff last_slot = rte_atomic_load_explicit(&ring->tail, rte_memory_order_acquire); 54843b815d8SJakub Grajciar if (cur_slot == last_slot) 54943b815d8SJakub Grajciar goto refill; 55043b815d8SJakub Grajciar n_slots = last_slot - cur_slot; 55143b815d8SJakub Grajciar 55243b815d8SJakub Grajciar while (n_slots && n_rx_pkts < nb_pkts) { 55343b815d8SJakub Grajciar s0 = cur_slot & mask; 55443b815d8SJakub Grajciar 55543b815d8SJakub Grajciar d0 = &ring->desc[s0]; 55643b815d8SJakub Grajciar mbuf_head = mq->buffers[s0]; 55743b815d8SJakub Grajciar mbuf = mbuf_head; 55843b815d8SJakub Grajciar 55943b815d8SJakub Grajciar next_slot: 56043b815d8SJakub Grajciar /* prefetch next descriptor */ 56143b815d8SJakub Grajciar if (n_rx_pkts + 1 < nb_pkts) 56243b815d8SJakub Grajciar rte_prefetch0(&ring->desc[(cur_slot + 1) & mask]); 56343b815d8SJakub Grajciar 56443b815d8SJakub Grajciar mbuf->port = mq->in_port; 56543b815d8SJakub Grajciar rte_pktmbuf_data_len(mbuf) = d0->length; 56643b815d8SJakub Grajciar rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf); 56743b815d8SJakub Grajciar 56843b815d8SJakub Grajciar mq->n_bytes += rte_pktmbuf_data_len(mbuf); 56943b815d8SJakub Grajciar 57043b815d8SJakub Grajciar cur_slot++; 57143b815d8SJakub Grajciar n_slots--; 57243b815d8SJakub Grajciar if (d0->flags & MEMIF_DESC_FLAG_NEXT) { 57343b815d8SJakub Grajciar s0 = cur_slot & mask; 57443b815d8SJakub Grajciar d0 = &ring->desc[s0]; 57543b815d8SJakub Grajciar mbuf_tail = mbuf; 57643b815d8SJakub Grajciar mbuf = mq->buffers[s0]; 57743b815d8SJakub Grajciar ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf); 57843b815d8SJakub Grajciar if (unlikely(ret < 0)) { 57943b815d8SJakub Grajciar MIF_LOG(ERR, "number-of-segments-overflow"); 58043b815d8SJakub Grajciar goto refill; 58143b815d8SJakub Grajciar } 58243b815d8SJakub Grajciar goto next_slot; 58343b815d8SJakub Grajciar } 58443b815d8SJakub Grajciar 58543b815d8SJakub Grajciar *bufs++ = mbuf_head; 58643b815d8SJakub Grajciar n_rx_pkts++; 58743b815d8SJakub Grajciar } 58843b815d8SJakub Grajciar 58943b815d8SJakub Grajciar mq->last_tail = cur_slot; 59043b815d8SJakub Grajciar 591d250589dSStephen Hemminger /* Supply server with new buffers */ 59243b815d8SJakub Grajciar refill: 5933a086c20SHonnappa Nagarahalli /* ring->head is updated by the receiver and this function 5943a086c20SHonnappa Nagarahalli * is called in the context of receiver thread. The loads in 5953a086c20SHonnappa Nagarahalli * the receiver do not need to synchronize with its own stores. 5967ec9d6f4SPhil Yang */ 597e12a0166STyler Retzlaff head = rte_atomic_load_explicit(&ring->head, rte_memory_order_relaxed); 59843b815d8SJakub Grajciar n_slots = ring_size - head + mq->last_tail; 59943b815d8SJakub Grajciar 60043b815d8SJakub Grajciar if (n_slots < 32) 60143b815d8SJakub Grajciar goto no_free_mbufs; 60243b815d8SJakub Grajciar 60343b815d8SJakub Grajciar ret = rte_pktmbuf_alloc_bulk(mq->mempool, &mq->buffers[head & mask], n_slots); 60443b815d8SJakub Grajciar if (unlikely(ret < 0)) 60543b815d8SJakub Grajciar goto no_free_mbufs; 606b92b18b7SMihai Brodschi if (unlikely(n_slots > ring_size - (head & mask))) { 607b92b18b7SMihai Brodschi rte_memcpy(mq->buffers, &mq->buffers[ring_size], 608b92b18b7SMihai Brodschi (n_slots + (head & mask) - ring_size) * sizeof(struct rte_mbuf *)); 609b92b18b7SMihai Brodschi } 61043b815d8SJakub Grajciar 61143b815d8SJakub Grajciar while (n_slots--) { 61243b815d8SJakub Grajciar s0 = head++ & mask; 61343b815d8SJakub Grajciar if (n_slots > 0) 61443b815d8SJakub Grajciar rte_prefetch0(mq->buffers[head & mask]); 61543b815d8SJakub Grajciar d0 = &ring->desc[s0]; 61643b815d8SJakub Grajciar /* store buffer header */ 61743b815d8SJakub Grajciar mbuf = mq->buffers[s0]; 61843b815d8SJakub Grajciar /* populate descriptor */ 61943b815d8SJakub Grajciar d0->length = rte_pktmbuf_data_room_size(mq->mempool) - 62043b815d8SJakub Grajciar RTE_PKTMBUF_HEADROOM; 62143b815d8SJakub Grajciar d0->region = 1; 62243b815d8SJakub Grajciar d0->offset = rte_pktmbuf_mtod(mbuf, uint8_t *) - 62343b815d8SJakub Grajciar (uint8_t *)proc_private->regions[d0->region]->addr; 62443b815d8SJakub Grajciar } 62543b815d8SJakub Grajciar no_free_mbufs: 6263a086c20SHonnappa Nagarahalli /* The ring->head acts as a guard variable between Tx and Rx 6273a086c20SHonnappa Nagarahalli * threads, so using store-release pairs with load-acquire 6283a086c20SHonnappa Nagarahalli * in function eth_memif_tx. 6293a086c20SHonnappa Nagarahalli */ 630e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->head, head, rte_memory_order_release); 63143b815d8SJakub Grajciar 63243b815d8SJakub Grajciar mq->n_pkts += n_rx_pkts; 63343b815d8SJakub Grajciar 63443b815d8SJakub Grajciar return n_rx_pkts; 63543b815d8SJakub Grajciar } 63643b815d8SJakub Grajciar 63743b815d8SJakub Grajciar static uint16_t 63809c7e63aSJakub Grajciar eth_memif_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) 63909c7e63aSJakub Grajciar { 64009c7e63aSJakub Grajciar struct memif_queue *mq = queue; 641c41a0495SJakub Grajciar struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private; 642c41a0495SJakub Grajciar struct pmd_process_private *proc_private = 643c41a0495SJakub Grajciar rte_eth_devices[mq->in_port].process_private; 644c41a0495SJakub Grajciar memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq); 64509c7e63aSJakub Grajciar uint16_t slot, saved_slot, n_free, ring_size, mask, n_tx_pkts = 0; 6463e3f736eSJunxiao Shi uint16_t src_len, src_off, dst_len, dst_off, cp_len, nb_segs; 64709c7e63aSJakub Grajciar memif_ring_type_t type = mq->type; 64809c7e63aSJakub Grajciar memif_desc_t *d0; 64909c7e63aSJakub Grajciar struct rte_mbuf *mbuf; 65009c7e63aSJakub Grajciar struct rte_mbuf *mbuf_head; 65109c7e63aSJakub Grajciar uint64_t a; 65209c7e63aSJakub Grajciar ssize_t size; 653c41a0495SJakub Grajciar struct rte_eth_link link; 65409c7e63aSJakub Grajciar 65509c7e63aSJakub Grajciar if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0)) 65609c7e63aSJakub Grajciar return 0; 657c41a0495SJakub Grajciar if (unlikely(ring == NULL)) { 658abfc0b9fSAndrew Rybchenko int ret; 659abfc0b9fSAndrew Rybchenko 660c41a0495SJakub Grajciar /* Secondary process will attempt to request regions. */ 661abfc0b9fSAndrew Rybchenko ret = rte_eth_link_get(mq->in_port, &link); 662abfc0b9fSAndrew Rybchenko if (ret < 0) 663abfc0b9fSAndrew Rybchenko MIF_LOG(ERR, "Failed to get port %u link info: %s", 664abfc0b9fSAndrew Rybchenko mq->in_port, rte_strerror(-ret)); 66509c7e63aSJakub Grajciar return 0; 666c41a0495SJakub Grajciar } 66709c7e63aSJakub Grajciar 66809c7e63aSJakub Grajciar ring_size = 1 << mq->log2_ring_size; 66909c7e63aSJakub Grajciar mask = ring_size - 1; 67009c7e63aSJakub Grajciar 671d250589dSStephen Hemminger if (type == MEMIF_RING_C2S) { 672d250589dSStephen Hemminger /* For C2S queues ring->head is updated by the sender and 6732416db20SHonnappa Nagarahalli * this function is called in the context of sending thread. 6742416db20SHonnappa Nagarahalli * The loads in the sender do not need to synchronize with 6752416db20SHonnappa Nagarahalli * its own stores. Hence, the following load can be a 6762416db20SHonnappa Nagarahalli * relaxed load. 6772416db20SHonnappa Nagarahalli */ 678e12a0166STyler Retzlaff slot = rte_atomic_load_explicit(&ring->head, rte_memory_order_relaxed); 6797fff1d31SHonnappa Nagarahalli n_free = ring_size - slot + 680e12a0166STyler Retzlaff rte_atomic_load_explicit(&ring->tail, rte_memory_order_acquire); 681a2aafb9aSPhil Yang } else { 682d250589dSStephen Hemminger /* For S2C queues ring->tail is updated by the sender and 68382766027SHonnappa Nagarahalli * this function is called in the context of sending thread. 68482766027SHonnappa Nagarahalli * The loads in the sender do not need to synchronize with 68582766027SHonnappa Nagarahalli * its own stores. Hence, the following load can be a 68682766027SHonnappa Nagarahalli * relaxed load. 68782766027SHonnappa Nagarahalli */ 688e12a0166STyler Retzlaff slot = rte_atomic_load_explicit(&ring->tail, rte_memory_order_relaxed); 689e12a0166STyler Retzlaff n_free = rte_atomic_load_explicit(&ring->head, rte_memory_order_acquire) - slot; 690a2aafb9aSPhil Yang } 69109c7e63aSJakub Grajciar 692d8d91d78SJoyce Kong uint16_t i; 693b5613c8fSJoyce Kong struct rte_mbuf **buf_tmp = bufs; 694b5613c8fSJoyce Kong mbuf_head = *buf_tmp++; 695b5613c8fSJoyce Kong struct rte_mempool *mp = mbuf_head->pool; 696b5613c8fSJoyce Kong 697b5613c8fSJoyce Kong for (i = 1; i < nb_pkts; i++) { 698b5613c8fSJoyce Kong mbuf_head = *buf_tmp++; 699b5613c8fSJoyce Kong if (mbuf_head->pool != mp) 700b5613c8fSJoyce Kong break; 701b5613c8fSJoyce Kong } 702b5613c8fSJoyce Kong 703b5613c8fSJoyce Kong uint16_t mbuf_size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM; 704b5613c8fSJoyce Kong if (i == nb_pkts && pmd->cfg.pkt_buffer_size >= mbuf_size) { 705b5613c8fSJoyce Kong buf_tmp = bufs; 706b5613c8fSJoyce Kong while (n_tx_pkts < nb_pkts && n_free) { 707b5613c8fSJoyce Kong mbuf_head = *bufs++; 708b5613c8fSJoyce Kong nb_segs = mbuf_head->nb_segs; 709b5613c8fSJoyce Kong mbuf = mbuf_head; 710b5613c8fSJoyce Kong 711b5613c8fSJoyce Kong saved_slot = slot; 712b5613c8fSJoyce Kong 713b5613c8fSJoyce Kong next_in_chain1: 714b5613c8fSJoyce Kong d0 = &ring->desc[slot & mask]; 715b5613c8fSJoyce Kong cp_len = rte_pktmbuf_data_len(mbuf); 716b5613c8fSJoyce Kong 717b5613c8fSJoyce Kong rte_memcpy((uint8_t *)memif_get_buffer(proc_private, d0), 718b5613c8fSJoyce Kong rte_pktmbuf_mtod(mbuf, void *), cp_len); 719b5613c8fSJoyce Kong 720b5613c8fSJoyce Kong d0->length = cp_len; 721b5613c8fSJoyce Kong mq->n_bytes += cp_len; 722b5613c8fSJoyce Kong slot++; 723b5613c8fSJoyce Kong n_free--; 724b5613c8fSJoyce Kong 725b5613c8fSJoyce Kong if (--nb_segs > 0) { 726b5613c8fSJoyce Kong if (n_free) { 727b5613c8fSJoyce Kong d0->flags |= MEMIF_DESC_FLAG_NEXT; 728b5613c8fSJoyce Kong mbuf = mbuf->next; 729b5613c8fSJoyce Kong goto next_in_chain1; 730b5613c8fSJoyce Kong } else { 731b5613c8fSJoyce Kong slot = saved_slot; 732b5613c8fSJoyce Kong goto free_mbufs; 733b5613c8fSJoyce Kong } 734b5613c8fSJoyce Kong } 735b5613c8fSJoyce Kong 736b5613c8fSJoyce Kong n_tx_pkts++; 737b5613c8fSJoyce Kong } 738b5613c8fSJoyce Kong free_mbufs: 739b5613c8fSJoyce Kong rte_pktmbuf_free_bulk(buf_tmp, n_tx_pkts); 740b5613c8fSJoyce Kong } else { 74109c7e63aSJakub Grajciar while (n_tx_pkts < nb_pkts && n_free) { 74209c7e63aSJakub Grajciar mbuf_head = *bufs++; 7433e3f736eSJunxiao Shi nb_segs = mbuf_head->nb_segs; 74409c7e63aSJakub Grajciar mbuf = mbuf_head; 74509c7e63aSJakub Grajciar 74609c7e63aSJakub Grajciar saved_slot = slot; 74709c7e63aSJakub Grajciar d0 = &ring->desc[slot & mask]; 74809c7e63aSJakub Grajciar dst_off = 0; 749d250589dSStephen Hemminger dst_len = (type == MEMIF_RING_C2S) ? 75009c7e63aSJakub Grajciar pmd->run.pkt_buffer_size : d0->length; 75109c7e63aSJakub Grajciar 752b5613c8fSJoyce Kong next_in_chain2: 75309c7e63aSJakub Grajciar src_off = 0; 75409c7e63aSJakub Grajciar src_len = rte_pktmbuf_data_len(mbuf); 75509c7e63aSJakub Grajciar 75609c7e63aSJakub Grajciar while (src_len) { 75709c7e63aSJakub Grajciar if (dst_len == 0) { 75809c7e63aSJakub Grajciar if (n_free) { 75909c7e63aSJakub Grajciar slot++; 76009c7e63aSJakub Grajciar n_free--; 76109c7e63aSJakub Grajciar d0->flags |= MEMIF_DESC_FLAG_NEXT; 76209c7e63aSJakub Grajciar d0 = &ring->desc[slot & mask]; 76309c7e63aSJakub Grajciar dst_off = 0; 764d250589dSStephen Hemminger dst_len = (type == MEMIF_RING_C2S) ? 76509c7e63aSJakub Grajciar pmd->run.pkt_buffer_size : d0->length; 76609c7e63aSJakub Grajciar d0->flags = 0; 76709c7e63aSJakub Grajciar } else { 76809c7e63aSJakub Grajciar slot = saved_slot; 76909c7e63aSJakub Grajciar goto no_free_slots; 77009c7e63aSJakub Grajciar } 77109c7e63aSJakub Grajciar } 77209c7e63aSJakub Grajciar cp_len = RTE_MIN(dst_len, src_len); 77309c7e63aSJakub Grajciar 774663191e2SDavid Christensen rte_memcpy((uint8_t *)memif_get_buffer(proc_private, 775663191e2SDavid Christensen d0) + dst_off, 77609c7e63aSJakub Grajciar rte_pktmbuf_mtod_offset(mbuf, void *, src_off), 77709c7e63aSJakub Grajciar cp_len); 77809c7e63aSJakub Grajciar 77909c7e63aSJakub Grajciar mq->n_bytes += cp_len; 78009c7e63aSJakub Grajciar src_off += cp_len; 78109c7e63aSJakub Grajciar dst_off += cp_len; 78209c7e63aSJakub Grajciar src_len -= cp_len; 78309c7e63aSJakub Grajciar dst_len -= cp_len; 78409c7e63aSJakub Grajciar 78509c7e63aSJakub Grajciar d0->length = dst_off; 78609c7e63aSJakub Grajciar } 78709c7e63aSJakub Grajciar 7883e3f736eSJunxiao Shi if (--nb_segs > 0) { 78909c7e63aSJakub Grajciar mbuf = mbuf->next; 790b5613c8fSJoyce Kong goto next_in_chain2; 79109c7e63aSJakub Grajciar } 79209c7e63aSJakub Grajciar 79309c7e63aSJakub Grajciar n_tx_pkts++; 79409c7e63aSJakub Grajciar slot++; 79509c7e63aSJakub Grajciar n_free--; 79609c7e63aSJakub Grajciar rte_pktmbuf_free(mbuf_head); 79709c7e63aSJakub Grajciar } 798b5613c8fSJoyce Kong } 79909c7e63aSJakub Grajciar 80009c7e63aSJakub Grajciar no_free_slots: 801d250589dSStephen Hemminger if (type == MEMIF_RING_C2S) 802e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->head, slot, rte_memory_order_release); 80309c7e63aSJakub Grajciar else 804e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->tail, slot, rte_memory_order_release); 80509c7e63aSJakub Grajciar 806aedd054cSHarman Kalra if (((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) && 807aedd054cSHarman Kalra (rte_intr_fd_get(mq->intr_handle) >= 0)) { 80809c7e63aSJakub Grajciar a = 1; 809d61138d4SHarman Kalra size = write(rte_intr_fd_get(mq->intr_handle), &a, 810d61138d4SHarman Kalra sizeof(a)); 81109c7e63aSJakub Grajciar if (unlikely(size < 0)) { 81209c7e63aSJakub Grajciar MIF_LOG(WARNING, 813c41a0495SJakub Grajciar "Failed to send interrupt. %s", strerror(errno)); 81409c7e63aSJakub Grajciar } 81509c7e63aSJakub Grajciar } 81609c7e63aSJakub Grajciar 81709c7e63aSJakub Grajciar mq->n_pkts += n_tx_pkts; 81809c7e63aSJakub Grajciar return n_tx_pkts; 81909c7e63aSJakub Grajciar } 82009c7e63aSJakub Grajciar 82143b815d8SJakub Grajciar static int 82243b815d8SJakub Grajciar memif_tx_one_zc(struct pmd_process_private *proc_private, struct memif_queue *mq, 82343b815d8SJakub Grajciar memif_ring_t *ring, struct rte_mbuf *mbuf, const uint16_t mask, 82443b815d8SJakub Grajciar uint16_t slot, uint16_t n_free) 82509c7e63aSJakub Grajciar { 82643b815d8SJakub Grajciar memif_desc_t *d0; 8273e3f736eSJunxiao Shi uint16_t nb_segs = mbuf->nb_segs; 82843b815d8SJakub Grajciar int used_slots = 1; 82943b815d8SJakub Grajciar 83043b815d8SJakub Grajciar next_in_chain: 83143b815d8SJakub Grajciar /* store pointer to mbuf to free it later */ 83243b815d8SJakub Grajciar mq->buffers[slot & mask] = mbuf; 83343b815d8SJakub Grajciar /* populate descriptor */ 83443b815d8SJakub Grajciar d0 = &ring->desc[slot & mask]; 83543b815d8SJakub Grajciar d0->length = rte_pktmbuf_data_len(mbuf); 83678dafb4bSTianyu Li mq->n_bytes += rte_pktmbuf_data_len(mbuf); 83743b815d8SJakub Grajciar /* FIXME: get region index */ 83843b815d8SJakub Grajciar d0->region = 1; 83943b815d8SJakub Grajciar d0->offset = rte_pktmbuf_mtod(mbuf, uint8_t *) - 84043b815d8SJakub Grajciar (uint8_t *)proc_private->regions[d0->region]->addr; 84143b815d8SJakub Grajciar d0->flags = 0; 84243b815d8SJakub Grajciar 84343b815d8SJakub Grajciar /* check if buffer is chained */ 8443e3f736eSJunxiao Shi if (--nb_segs > 0) { 84543b815d8SJakub Grajciar if (n_free < 2) 84643b815d8SJakub Grajciar return 0; 84743b815d8SJakub Grajciar /* mark buffer as chained */ 84843b815d8SJakub Grajciar d0->flags |= MEMIF_DESC_FLAG_NEXT; 84943b815d8SJakub Grajciar /* advance mbuf */ 85043b815d8SJakub Grajciar mbuf = mbuf->next; 85143b815d8SJakub Grajciar /* update counters */ 85243b815d8SJakub Grajciar used_slots++; 85343b815d8SJakub Grajciar slot++; 85443b815d8SJakub Grajciar n_free--; 85543b815d8SJakub Grajciar goto next_in_chain; 85643b815d8SJakub Grajciar } 85743b815d8SJakub Grajciar return used_slots; 85843b815d8SJakub Grajciar } 85943b815d8SJakub Grajciar 86043b815d8SJakub Grajciar static uint16_t 86143b815d8SJakub Grajciar eth_memif_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) 86243b815d8SJakub Grajciar { 86343b815d8SJakub Grajciar struct memif_queue *mq = queue; 86443b815d8SJakub Grajciar struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private; 86543b815d8SJakub Grajciar struct pmd_process_private *proc_private = 86643b815d8SJakub Grajciar rte_eth_devices[mq->in_port].process_private; 86743b815d8SJakub Grajciar memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq); 86843b815d8SJakub Grajciar uint16_t slot, n_free, ring_size, mask, n_tx_pkts = 0; 86943b815d8SJakub Grajciar struct rte_eth_link link; 87043b815d8SJakub Grajciar 87143b815d8SJakub Grajciar if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0)) 87243b815d8SJakub Grajciar return 0; 87343b815d8SJakub Grajciar if (unlikely(ring == NULL)) { 874*a4fa02e0SStephen Hemminger int ret; 875*a4fa02e0SStephen Hemminger 87643b815d8SJakub Grajciar /* Secondary process will attempt to request regions. */ 877*a4fa02e0SStephen Hemminger ret = rte_eth_link_get(mq->in_port, &link); 878*a4fa02e0SStephen Hemminger if (ret < 0) 879*a4fa02e0SStephen Hemminger MIF_LOG(ERR, "Failed to get port %u link info: %s", 880*a4fa02e0SStephen Hemminger mq->in_port, rte_strerror(-ret)); 88143b815d8SJakub Grajciar return 0; 88243b815d8SJakub Grajciar } 88343b815d8SJakub Grajciar 88443b815d8SJakub Grajciar ring_size = 1 << mq->log2_ring_size; 88543b815d8SJakub Grajciar mask = ring_size - 1; 88643b815d8SJakub Grajciar 887d250589dSStephen Hemminger /* free mbufs received by server */ 88843b815d8SJakub Grajciar memif_free_stored_mbufs(proc_private, mq); 88943b815d8SJakub Grajciar 890d250589dSStephen Hemminger /* ring type always MEMIF_RING_C2S */ 891d250589dSStephen Hemminger /* For C2S queues ring->head is updated by the sender and 8925198cb1cSHonnappa Nagarahalli * this function is called in the context of sending thread. 8935198cb1cSHonnappa Nagarahalli * The loads in the sender do not need to synchronize with 8945198cb1cSHonnappa Nagarahalli * its own stores. Hence, the following load can be a 8955198cb1cSHonnappa Nagarahalli * relaxed load. 8967ec9d6f4SPhil Yang */ 897e12a0166STyler Retzlaff slot = rte_atomic_load_explicit(&ring->head, rte_memory_order_relaxed); 8987ec9d6f4SPhil Yang n_free = ring_size - slot + mq->last_tail; 89943b815d8SJakub Grajciar 90043b815d8SJakub Grajciar int used_slots; 90143b815d8SJakub Grajciar 90243b815d8SJakub Grajciar while (n_free && (n_tx_pkts < nb_pkts)) { 90343b815d8SJakub Grajciar while ((n_free > 4) && ((nb_pkts - n_tx_pkts) > 4)) { 90443b815d8SJakub Grajciar if ((nb_pkts - n_tx_pkts) > 8) { 90543b815d8SJakub Grajciar rte_prefetch0(*bufs + 4); 90643b815d8SJakub Grajciar rte_prefetch0(*bufs + 5); 90743b815d8SJakub Grajciar rte_prefetch0(*bufs + 6); 90843b815d8SJakub Grajciar rte_prefetch0(*bufs + 7); 90943b815d8SJakub Grajciar } 91043b815d8SJakub Grajciar used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++, 91143b815d8SJakub Grajciar mask, slot, n_free); 91243b815d8SJakub Grajciar if (unlikely(used_slots < 1)) 91343b815d8SJakub Grajciar goto no_free_slots; 91443b815d8SJakub Grajciar n_tx_pkts++; 91543b815d8SJakub Grajciar slot += used_slots; 91643b815d8SJakub Grajciar n_free -= used_slots; 91743b815d8SJakub Grajciar 91843b815d8SJakub Grajciar used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++, 91943b815d8SJakub Grajciar mask, slot, n_free); 92043b815d8SJakub Grajciar if (unlikely(used_slots < 1)) 92143b815d8SJakub Grajciar goto no_free_slots; 92243b815d8SJakub Grajciar n_tx_pkts++; 92343b815d8SJakub Grajciar slot += used_slots; 92443b815d8SJakub Grajciar n_free -= used_slots; 92543b815d8SJakub Grajciar 92643b815d8SJakub Grajciar used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++, 92743b815d8SJakub Grajciar mask, slot, n_free); 92843b815d8SJakub Grajciar if (unlikely(used_slots < 1)) 92943b815d8SJakub Grajciar goto no_free_slots; 93043b815d8SJakub Grajciar n_tx_pkts++; 93143b815d8SJakub Grajciar slot += used_slots; 93243b815d8SJakub Grajciar n_free -= used_slots; 93343b815d8SJakub Grajciar 93443b815d8SJakub Grajciar used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++, 93543b815d8SJakub Grajciar mask, slot, n_free); 93643b815d8SJakub Grajciar if (unlikely(used_slots < 1)) 93743b815d8SJakub Grajciar goto no_free_slots; 93843b815d8SJakub Grajciar n_tx_pkts++; 93943b815d8SJakub Grajciar slot += used_slots; 94043b815d8SJakub Grajciar n_free -= used_slots; 94143b815d8SJakub Grajciar } 94243b815d8SJakub Grajciar used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++, 94343b815d8SJakub Grajciar mask, slot, n_free); 94443b815d8SJakub Grajciar if (unlikely(used_slots < 1)) 94543b815d8SJakub Grajciar goto no_free_slots; 94643b815d8SJakub Grajciar n_tx_pkts++; 94743b815d8SJakub Grajciar slot += used_slots; 94843b815d8SJakub Grajciar n_free -= used_slots; 94943b815d8SJakub Grajciar } 95043b815d8SJakub Grajciar 95143b815d8SJakub Grajciar no_free_slots: 952d250589dSStephen Hemminger /* ring type always MEMIF_RING_C2S */ 9535198cb1cSHonnappa Nagarahalli /* The ring->head acts as a guard variable between Tx and Rx 9545198cb1cSHonnappa Nagarahalli * threads, so using store-release pairs with load-acquire 955d250589dSStephen Hemminger * in function eth_memif_rx for C2S rings. 9565198cb1cSHonnappa Nagarahalli */ 957e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->head, slot, rte_memory_order_release); 95843b815d8SJakub Grajciar 95943b815d8SJakub Grajciar /* Send interrupt, if enabled. */ 96043b815d8SJakub Grajciar if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) { 96143b815d8SJakub Grajciar uint64_t a = 1; 962aedd054cSHarman Kalra if (rte_intr_fd_get(mq->intr_handle) < 0) 963aedd054cSHarman Kalra return -1; 964aedd054cSHarman Kalra 965d61138d4SHarman Kalra ssize_t size = write(rte_intr_fd_get(mq->intr_handle), 966d61138d4SHarman Kalra &a, sizeof(a)); 96743b815d8SJakub Grajciar if (unlikely(size < 0)) { 96843b815d8SJakub Grajciar MIF_LOG(WARNING, 96943b815d8SJakub Grajciar "Failed to send interrupt. %s", strerror(errno)); 97043b815d8SJakub Grajciar } 97143b815d8SJakub Grajciar } 97243b815d8SJakub Grajciar 97343b815d8SJakub Grajciar /* increment queue counters */ 97443b815d8SJakub Grajciar mq->n_pkts += n_tx_pkts; 97543b815d8SJakub Grajciar 97643b815d8SJakub Grajciar return n_tx_pkts; 97743b815d8SJakub Grajciar } 97843b815d8SJakub Grajciar 97943b815d8SJakub Grajciar void 98043b815d8SJakub Grajciar memif_free_regions(struct rte_eth_dev *dev) 98143b815d8SJakub Grajciar { 98243b815d8SJakub Grajciar struct pmd_process_private *proc_private = dev->process_private; 98343b815d8SJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 98409c7e63aSJakub Grajciar int i; 98509c7e63aSJakub Grajciar struct memif_region *r; 98609c7e63aSJakub Grajciar 98709c7e63aSJakub Grajciar /* regions are allocated contiguously, so it's 988c41a0495SJakub Grajciar * enough to loop until 'proc_private->regions_num' 98909c7e63aSJakub Grajciar */ 990c41a0495SJakub Grajciar for (i = 0; i < proc_private->regions_num; i++) { 991c41a0495SJakub Grajciar r = proc_private->regions[i]; 99209c7e63aSJakub Grajciar if (r != NULL) { 99343b815d8SJakub Grajciar /* This is memzone */ 99443b815d8SJakub Grajciar if (i > 0 && (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)) { 99543b815d8SJakub Grajciar r->addr = NULL; 99643b815d8SJakub Grajciar if (r->fd > 0) 99743b815d8SJakub Grajciar close(r->fd); 99843b815d8SJakub Grajciar } 99909c7e63aSJakub Grajciar if (r->addr != NULL) { 100009c7e63aSJakub Grajciar munmap(r->addr, r->region_size); 100109c7e63aSJakub Grajciar if (r->fd > 0) { 100209c7e63aSJakub Grajciar close(r->fd); 100309c7e63aSJakub Grajciar r->fd = -1; 100409c7e63aSJakub Grajciar } 100509c7e63aSJakub Grajciar } 100609c7e63aSJakub Grajciar rte_free(r); 1007c41a0495SJakub Grajciar proc_private->regions[i] = NULL; 100809c7e63aSJakub Grajciar } 100909c7e63aSJakub Grajciar } 1010c41a0495SJakub Grajciar proc_private->regions_num = 0; 101109c7e63aSJakub Grajciar } 101209c7e63aSJakub Grajciar 101309c7e63aSJakub Grajciar static int 101443b815d8SJakub Grajciar memif_region_init_zc(const struct rte_memseg_list *msl, const struct rte_memseg *ms, 101543b815d8SJakub Grajciar void *arg) 101643b815d8SJakub Grajciar { 101743b815d8SJakub Grajciar struct pmd_process_private *proc_private = (struct pmd_process_private *)arg; 101843b815d8SJakub Grajciar struct memif_region *r; 101943b815d8SJakub Grajciar 102043b815d8SJakub Grajciar if (proc_private->regions_num < 1) { 102143b815d8SJakub Grajciar MIF_LOG(ERR, "Missing descriptor region"); 102243b815d8SJakub Grajciar return -1; 102343b815d8SJakub Grajciar } 102443b815d8SJakub Grajciar 102543b815d8SJakub Grajciar r = proc_private->regions[proc_private->regions_num - 1]; 102643b815d8SJakub Grajciar 102743b815d8SJakub Grajciar if (r->addr != msl->base_va) 102843b815d8SJakub Grajciar r = proc_private->regions[++proc_private->regions_num - 1]; 102943b815d8SJakub Grajciar 103043b815d8SJakub Grajciar if (r == NULL) { 103143b815d8SJakub Grajciar r = rte_zmalloc("region", sizeof(struct memif_region), 0); 103243b815d8SJakub Grajciar if (r == NULL) { 103343b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to alloc memif region."); 103443b815d8SJakub Grajciar return -ENOMEM; 103543b815d8SJakub Grajciar } 103643b815d8SJakub Grajciar 103743b815d8SJakub Grajciar r->addr = msl->base_va; 103843b815d8SJakub Grajciar r->region_size = ms->len; 103943b815d8SJakub Grajciar r->fd = rte_memseg_get_fd(ms); 104043b815d8SJakub Grajciar if (r->fd < 0) 104143b815d8SJakub Grajciar return -1; 104243b815d8SJakub Grajciar r->pkt_buffer_offset = 0; 104343b815d8SJakub Grajciar 104443b815d8SJakub Grajciar proc_private->regions[proc_private->regions_num - 1] = r; 104543b815d8SJakub Grajciar } else { 104643b815d8SJakub Grajciar r->region_size += ms->len; 104743b815d8SJakub Grajciar } 104843b815d8SJakub Grajciar 104943b815d8SJakub Grajciar return 0; 105043b815d8SJakub Grajciar } 105143b815d8SJakub Grajciar 105243b815d8SJakub Grajciar static int 1053c41a0495SJakub Grajciar memif_region_init_shm(struct rte_eth_dev *dev, uint8_t has_buffers) 105409c7e63aSJakub Grajciar { 1055c41a0495SJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 1056c41a0495SJakub Grajciar struct pmd_process_private *proc_private = dev->process_private; 105709c7e63aSJakub Grajciar char shm_name[ETH_MEMIF_SHM_NAME_SIZE]; 105809c7e63aSJakub Grajciar int ret = 0; 105909c7e63aSJakub Grajciar struct memif_region *r; 106009c7e63aSJakub Grajciar 1061c41a0495SJakub Grajciar if (proc_private->regions_num >= ETH_MEMIF_MAX_REGION_NUM) { 1062c41a0495SJakub Grajciar MIF_LOG(ERR, "Too many regions."); 106309c7e63aSJakub Grajciar return -1; 106409c7e63aSJakub Grajciar } 106509c7e63aSJakub Grajciar 106609c7e63aSJakub Grajciar r = rte_zmalloc("region", sizeof(struct memif_region), 0); 106709c7e63aSJakub Grajciar if (r == NULL) { 1068c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to alloc memif region."); 106909c7e63aSJakub Grajciar return -ENOMEM; 107009c7e63aSJakub Grajciar } 107109c7e63aSJakub Grajciar 107209c7e63aSJakub Grajciar /* calculate buffer offset */ 1073d250589dSStephen Hemminger r->pkt_buffer_offset = (pmd->run.num_c2s_rings + pmd->run.num_s2c_rings) * 107409c7e63aSJakub Grajciar (sizeof(memif_ring_t) + sizeof(memif_desc_t) * 107509c7e63aSJakub Grajciar (1 << pmd->run.log2_ring_size)); 107609c7e63aSJakub Grajciar 107709c7e63aSJakub Grajciar r->region_size = r->pkt_buffer_offset; 107809c7e63aSJakub Grajciar /* if region has buffers, add buffers size to region_size */ 107909c7e63aSJakub Grajciar if (has_buffers == 1) 108009c7e63aSJakub Grajciar r->region_size += (uint32_t)(pmd->run.pkt_buffer_size * 108109c7e63aSJakub Grajciar (1 << pmd->run.log2_ring_size) * 1082d250589dSStephen Hemminger (pmd->run.num_c2s_rings + 1083d250589dSStephen Hemminger pmd->run.num_s2c_rings)); 108409c7e63aSJakub Grajciar 108509c7e63aSJakub Grajciar memset(shm_name, 0, sizeof(char) * ETH_MEMIF_SHM_NAME_SIZE); 108609c7e63aSJakub Grajciar snprintf(shm_name, ETH_MEMIF_SHM_NAME_SIZE, "memif_region_%d", 1087c41a0495SJakub Grajciar proc_private->regions_num); 108809c7e63aSJakub Grajciar 108909c7e63aSJakub Grajciar r->fd = memfd_create(shm_name, MFD_ALLOW_SEALING); 109009c7e63aSJakub Grajciar if (r->fd < 0) { 1091c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to create shm file: %s.", strerror(errno)); 109209c7e63aSJakub Grajciar ret = -1; 109309c7e63aSJakub Grajciar goto error; 109409c7e63aSJakub Grajciar } 109509c7e63aSJakub Grajciar 109609c7e63aSJakub Grajciar ret = fcntl(r->fd, F_ADD_SEALS, F_SEAL_SHRINK); 109709c7e63aSJakub Grajciar if (ret < 0) { 1098c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to add seals to shm file: %s.", strerror(errno)); 109909c7e63aSJakub Grajciar goto error; 110009c7e63aSJakub Grajciar } 110109c7e63aSJakub Grajciar 110209c7e63aSJakub Grajciar ret = ftruncate(r->fd, r->region_size); 110309c7e63aSJakub Grajciar if (ret < 0) { 1104c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to truncate shm file: %s.", strerror(errno)); 110509c7e63aSJakub Grajciar goto error; 110609c7e63aSJakub Grajciar } 110709c7e63aSJakub Grajciar 110809c7e63aSJakub Grajciar r->addr = mmap(NULL, r->region_size, PROT_READ | 110909c7e63aSJakub Grajciar PROT_WRITE, MAP_SHARED, r->fd, 0); 111009c7e63aSJakub Grajciar if (r->addr == MAP_FAILED) { 1111c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to mmap shm region: %s.", strerror(ret)); 111209c7e63aSJakub Grajciar ret = -1; 111309c7e63aSJakub Grajciar goto error; 111409c7e63aSJakub Grajciar } 111509c7e63aSJakub Grajciar 1116c41a0495SJakub Grajciar proc_private->regions[proc_private->regions_num] = r; 1117c41a0495SJakub Grajciar proc_private->regions_num++; 111809c7e63aSJakub Grajciar 111909c7e63aSJakub Grajciar return ret; 112009c7e63aSJakub Grajciar 112109c7e63aSJakub Grajciar error: 112209c7e63aSJakub Grajciar if (r->fd > 0) 112309c7e63aSJakub Grajciar close(r->fd); 112409c7e63aSJakub Grajciar r->fd = -1; 112509c7e63aSJakub Grajciar 112609c7e63aSJakub Grajciar return ret; 112709c7e63aSJakub Grajciar } 112809c7e63aSJakub Grajciar 112909c7e63aSJakub Grajciar static int 1130c41a0495SJakub Grajciar memif_regions_init(struct rte_eth_dev *dev) 113109c7e63aSJakub Grajciar { 113243b815d8SJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 113309c7e63aSJakub Grajciar int ret; 113409c7e63aSJakub Grajciar 113543b815d8SJakub Grajciar /* 113643b815d8SJakub Grajciar * Zero-copy exposes dpdk memory. 113743b815d8SJakub Grajciar * Each memseg list will be represented by memif region. 113843b815d8SJakub Grajciar * Zero-copy regions indexing: memseg list idx + 1, 113943b815d8SJakub Grajciar * as we already have region 0 reserved for descriptors. 114043b815d8SJakub Grajciar */ 114143b815d8SJakub Grajciar if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) { 114243b815d8SJakub Grajciar /* create region idx 0 containing descriptors */ 114343b815d8SJakub Grajciar ret = memif_region_init_shm(dev, 0); 114409c7e63aSJakub Grajciar if (ret < 0) 114509c7e63aSJakub Grajciar return ret; 114643b815d8SJakub Grajciar ret = rte_memseg_walk(memif_region_init_zc, (void *)dev->process_private); 114743b815d8SJakub Grajciar if (ret < 0) 114843b815d8SJakub Grajciar return ret; 114943b815d8SJakub Grajciar } else { 11507be78d02SJosh Soref /* create one memory region containing rings and buffers */ 115143b815d8SJakub Grajciar ret = memif_region_init_shm(dev, /* has buffers */ 1); 115243b815d8SJakub Grajciar if (ret < 0) 115343b815d8SJakub Grajciar return ret; 115443b815d8SJakub Grajciar } 115509c7e63aSJakub Grajciar 115609c7e63aSJakub Grajciar return 0; 115709c7e63aSJakub Grajciar } 115809c7e63aSJakub Grajciar 115909c7e63aSJakub Grajciar static void 116009c7e63aSJakub Grajciar memif_init_rings(struct rte_eth_dev *dev) 116109c7e63aSJakub Grajciar { 116209c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 1163c41a0495SJakub Grajciar struct pmd_process_private *proc_private = dev->process_private; 116409c7e63aSJakub Grajciar memif_ring_t *ring; 116509c7e63aSJakub Grajciar int i, j; 116609c7e63aSJakub Grajciar uint16_t slot; 116709c7e63aSJakub Grajciar 1168d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_c2s_rings; i++) { 1169d250589dSStephen Hemminger ring = memif_get_ring(pmd, proc_private, MEMIF_RING_C2S, i); 1170e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->head, 0, rte_memory_order_relaxed); 1171e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->tail, 0, rte_memory_order_relaxed); 117209c7e63aSJakub Grajciar ring->cookie = MEMIF_COOKIE; 117309c7e63aSJakub Grajciar ring->flags = 0; 117443b815d8SJakub Grajciar 117543b815d8SJakub Grajciar if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) 117643b815d8SJakub Grajciar continue; 117743b815d8SJakub Grajciar 117809c7e63aSJakub Grajciar for (j = 0; j < (1 << pmd->run.log2_ring_size); j++) { 117909c7e63aSJakub Grajciar slot = i * (1 << pmd->run.log2_ring_size) + j; 118009c7e63aSJakub Grajciar ring->desc[j].region = 0; 1181c41a0495SJakub Grajciar ring->desc[j].offset = 1182c41a0495SJakub Grajciar proc_private->regions[0]->pkt_buffer_offset + 118309c7e63aSJakub Grajciar (uint32_t)(slot * pmd->run.pkt_buffer_size); 118409c7e63aSJakub Grajciar ring->desc[j].length = pmd->run.pkt_buffer_size; 118509c7e63aSJakub Grajciar } 118609c7e63aSJakub Grajciar } 118709c7e63aSJakub Grajciar 1188d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_s2c_rings; i++) { 1189d250589dSStephen Hemminger ring = memif_get_ring(pmd, proc_private, MEMIF_RING_S2C, i); 1190e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->head, 0, rte_memory_order_relaxed); 1191e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->tail, 0, rte_memory_order_relaxed); 119209c7e63aSJakub Grajciar ring->cookie = MEMIF_COOKIE; 119309c7e63aSJakub Grajciar ring->flags = 0; 119443b815d8SJakub Grajciar 119543b815d8SJakub Grajciar if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) 119643b815d8SJakub Grajciar continue; 119743b815d8SJakub Grajciar 119809c7e63aSJakub Grajciar for (j = 0; j < (1 << pmd->run.log2_ring_size); j++) { 1199d250589dSStephen Hemminger slot = (i + pmd->run.num_c2s_rings) * 120009c7e63aSJakub Grajciar (1 << pmd->run.log2_ring_size) + j; 120109c7e63aSJakub Grajciar ring->desc[j].region = 0; 1202c41a0495SJakub Grajciar ring->desc[j].offset = 1203c41a0495SJakub Grajciar proc_private->regions[0]->pkt_buffer_offset + 120409c7e63aSJakub Grajciar (uint32_t)(slot * pmd->run.pkt_buffer_size); 120509c7e63aSJakub Grajciar ring->desc[j].length = pmd->run.pkt_buffer_size; 120609c7e63aSJakub Grajciar } 120709c7e63aSJakub Grajciar } 120809c7e63aSJakub Grajciar } 120909c7e63aSJakub Grajciar 1210d250589dSStephen Hemminger /* called only by client */ 121143b815d8SJakub Grajciar static int 121209c7e63aSJakub Grajciar memif_init_queues(struct rte_eth_dev *dev) 121309c7e63aSJakub Grajciar { 121409c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 121509c7e63aSJakub Grajciar struct memif_queue *mq; 121609c7e63aSJakub Grajciar int i; 121709c7e63aSJakub Grajciar 1218d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_c2s_rings; i++) { 121909c7e63aSJakub Grajciar mq = dev->data->tx_queues[i]; 122009c7e63aSJakub Grajciar mq->log2_ring_size = pmd->run.log2_ring_size; 122109c7e63aSJakub Grajciar /* queues located only in region 0 */ 122209c7e63aSJakub Grajciar mq->region = 0; 1223d250589dSStephen Hemminger mq->ring_offset = memif_get_ring_offset(dev, mq, MEMIF_RING_C2S, i); 122409c7e63aSJakub Grajciar mq->last_head = 0; 122509c7e63aSJakub Grajciar mq->last_tail = 0; 1226d61138d4SHarman Kalra if (rte_intr_fd_set(mq->intr_handle, eventfd(0, EFD_NONBLOCK))) 1227d61138d4SHarman Kalra return -rte_errno; 1228d61138d4SHarman Kalra 1229d61138d4SHarman Kalra if (rte_intr_fd_get(mq->intr_handle) < 0) { 123009c7e63aSJakub Grajciar MIF_LOG(WARNING, 1231c41a0495SJakub Grajciar "Failed to create eventfd for tx queue %d: %s.", i, 123209c7e63aSJakub Grajciar strerror(errno)); 123309c7e63aSJakub Grajciar } 123443b815d8SJakub Grajciar mq->buffers = NULL; 123543b815d8SJakub Grajciar if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) { 123643b815d8SJakub Grajciar mq->buffers = rte_zmalloc("bufs", sizeof(struct rte_mbuf *) * 123743b815d8SJakub Grajciar (1 << mq->log2_ring_size), 0); 123843b815d8SJakub Grajciar if (mq->buffers == NULL) 123943b815d8SJakub Grajciar return -ENOMEM; 124043b815d8SJakub Grajciar } 124109c7e63aSJakub Grajciar } 124209c7e63aSJakub Grajciar 1243d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_s2c_rings; i++) { 124409c7e63aSJakub Grajciar mq = dev->data->rx_queues[i]; 124509c7e63aSJakub Grajciar mq->log2_ring_size = pmd->run.log2_ring_size; 124609c7e63aSJakub Grajciar /* queues located only in region 0 */ 124709c7e63aSJakub Grajciar mq->region = 0; 1248d250589dSStephen Hemminger mq->ring_offset = memif_get_ring_offset(dev, mq, MEMIF_RING_S2C, i); 124909c7e63aSJakub Grajciar mq->last_head = 0; 125009c7e63aSJakub Grajciar mq->last_tail = 0; 1251d61138d4SHarman Kalra if (rte_intr_fd_set(mq->intr_handle, eventfd(0, EFD_NONBLOCK))) 1252d61138d4SHarman Kalra return -rte_errno; 1253d61138d4SHarman Kalra if (rte_intr_fd_get(mq->intr_handle) < 0) { 125409c7e63aSJakub Grajciar MIF_LOG(WARNING, 1255c41a0495SJakub Grajciar "Failed to create eventfd for rx queue %d: %s.", i, 125609c7e63aSJakub Grajciar strerror(errno)); 125709c7e63aSJakub Grajciar } 125843b815d8SJakub Grajciar mq->buffers = NULL; 125943b815d8SJakub Grajciar if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) { 1260b92b18b7SMihai Brodschi /* 1261b92b18b7SMihai Brodschi * Allocate 2x ring_size to reserve a contiguous array for 1262b92b18b7SMihai Brodschi * rte_pktmbuf_alloc_bulk (to store allocated mbufs). 1263b92b18b7SMihai Brodschi */ 126443b815d8SJakub Grajciar mq->buffers = rte_zmalloc("bufs", sizeof(struct rte_mbuf *) * 1265b92b18b7SMihai Brodschi (1 << (mq->log2_ring_size + 1)), 0); 126643b815d8SJakub Grajciar if (mq->buffers == NULL) 126743b815d8SJakub Grajciar return -ENOMEM; 126809c7e63aSJakub Grajciar } 126909c7e63aSJakub Grajciar } 127043b815d8SJakub Grajciar return 0; 127143b815d8SJakub Grajciar } 127209c7e63aSJakub Grajciar 127309c7e63aSJakub Grajciar int 127409c7e63aSJakub Grajciar memif_init_regions_and_queues(struct rte_eth_dev *dev) 127509c7e63aSJakub Grajciar { 127609c7e63aSJakub Grajciar int ret; 127709c7e63aSJakub Grajciar 1278c41a0495SJakub Grajciar ret = memif_regions_init(dev); 127909c7e63aSJakub Grajciar if (ret < 0) 128009c7e63aSJakub Grajciar return ret; 128109c7e63aSJakub Grajciar 128209c7e63aSJakub Grajciar memif_init_rings(dev); 128309c7e63aSJakub Grajciar 128443b815d8SJakub Grajciar ret = memif_init_queues(dev); 128543b815d8SJakub Grajciar if (ret < 0) 128643b815d8SJakub Grajciar return ret; 128709c7e63aSJakub Grajciar 128809c7e63aSJakub Grajciar return 0; 128909c7e63aSJakub Grajciar } 129009c7e63aSJakub Grajciar 129109c7e63aSJakub Grajciar int 129209c7e63aSJakub Grajciar memif_connect(struct rte_eth_dev *dev) 129309c7e63aSJakub Grajciar { 129409c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 1295c41a0495SJakub Grajciar struct pmd_process_private *proc_private = dev->process_private; 129609c7e63aSJakub Grajciar struct memif_region *mr; 129709c7e63aSJakub Grajciar struct memif_queue *mq; 1298c41a0495SJakub Grajciar memif_ring_t *ring; 129909c7e63aSJakub Grajciar int i; 130009c7e63aSJakub Grajciar 1301c41a0495SJakub Grajciar for (i = 0; i < proc_private->regions_num; i++) { 1302c41a0495SJakub Grajciar mr = proc_private->regions[i]; 130309c7e63aSJakub Grajciar if (mr != NULL) { 130409c7e63aSJakub Grajciar if (mr->addr == NULL) { 130509c7e63aSJakub Grajciar if (mr->fd < 0) 130609c7e63aSJakub Grajciar return -1; 130709c7e63aSJakub Grajciar mr->addr = mmap(NULL, mr->region_size, 130809c7e63aSJakub Grajciar PROT_READ | PROT_WRITE, 130909c7e63aSJakub Grajciar MAP_SHARED, mr->fd, 0); 131043b815d8SJakub Grajciar if (mr->addr == MAP_FAILED) { 1311f665790aSDavid Marchand MIF_LOG(ERR, "mmap failed: %s", 131243b815d8SJakub Grajciar strerror(errno)); 131309c7e63aSJakub Grajciar return -1; 131409c7e63aSJakub Grajciar } 131509c7e63aSJakub Grajciar } 131643b815d8SJakub Grajciar if (i > 0 && (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)) { 131743b815d8SJakub Grajciar /* close memseg file */ 131843b815d8SJakub Grajciar close(mr->fd); 131943b815d8SJakub Grajciar mr->fd = -1; 132043b815d8SJakub Grajciar } 132143b815d8SJakub Grajciar } 132209c7e63aSJakub Grajciar } 132309c7e63aSJakub Grajciar 1324c41a0495SJakub Grajciar if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 1325d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_c2s_rings; i++) { 1326d250589dSStephen Hemminger mq = (pmd->role == MEMIF_ROLE_CLIENT) ? 132709c7e63aSJakub Grajciar dev->data->tx_queues[i] : dev->data->rx_queues[i]; 1328c41a0495SJakub Grajciar ring = memif_get_ring_from_queue(proc_private, mq); 1329c41a0495SJakub Grajciar if (ring == NULL || ring->cookie != MEMIF_COOKIE) { 1330c41a0495SJakub Grajciar MIF_LOG(ERR, "Wrong ring"); 133109c7e63aSJakub Grajciar return -1; 133209c7e63aSJakub Grajciar } 1333e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->head, 0, rte_memory_order_relaxed); 1334e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->tail, 0, rte_memory_order_relaxed); 133509c7e63aSJakub Grajciar mq->last_head = 0; 133609c7e63aSJakub Grajciar mq->last_tail = 0; 133709c7e63aSJakub Grajciar /* enable polling mode */ 1338d250589dSStephen Hemminger if (pmd->role == MEMIF_ROLE_SERVER) 1339c41a0495SJakub Grajciar ring->flags = MEMIF_RING_FLAG_MASK_INT; 134009c7e63aSJakub Grajciar } 1341d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_s2c_rings; i++) { 1342d250589dSStephen Hemminger mq = (pmd->role == MEMIF_ROLE_CLIENT) ? 134309c7e63aSJakub Grajciar dev->data->rx_queues[i] : dev->data->tx_queues[i]; 1344c41a0495SJakub Grajciar ring = memif_get_ring_from_queue(proc_private, mq); 1345c41a0495SJakub Grajciar if (ring == NULL || ring->cookie != MEMIF_COOKIE) { 1346c41a0495SJakub Grajciar MIF_LOG(ERR, "Wrong ring"); 134709c7e63aSJakub Grajciar return -1; 134809c7e63aSJakub Grajciar } 1349e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->head, 0, rte_memory_order_relaxed); 1350e12a0166STyler Retzlaff rte_atomic_store_explicit(&ring->tail, 0, rte_memory_order_relaxed); 135109c7e63aSJakub Grajciar mq->last_head = 0; 135209c7e63aSJakub Grajciar mq->last_tail = 0; 135309c7e63aSJakub Grajciar /* enable polling mode */ 1354d250589dSStephen Hemminger if (pmd->role == MEMIF_ROLE_CLIENT) 1355c41a0495SJakub Grajciar ring->flags = MEMIF_RING_FLAG_MASK_INT; 135609c7e63aSJakub Grajciar } 135709c7e63aSJakub Grajciar 135809c7e63aSJakub Grajciar pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTING; 135909c7e63aSJakub Grajciar pmd->flags |= ETH_MEMIF_FLAG_CONNECTED; 1360295968d1SFerruh Yigit dev->data->dev_link.link_status = RTE_ETH_LINK_UP; 1361c41a0495SJakub Grajciar } 1362c41a0495SJakub Grajciar MIF_LOG(INFO, "Connected."); 136309c7e63aSJakub Grajciar return 0; 136409c7e63aSJakub Grajciar } 136509c7e63aSJakub Grajciar 136609c7e63aSJakub Grajciar static int 136709c7e63aSJakub Grajciar memif_dev_start(struct rte_eth_dev *dev) 136809c7e63aSJakub Grajciar { 136909c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 137009c7e63aSJakub Grajciar int ret = 0; 13711b5e3493SJie Hai uint16_t i; 137209c7e63aSJakub Grajciar 137309c7e63aSJakub Grajciar switch (pmd->role) { 1374d250589dSStephen Hemminger case MEMIF_ROLE_CLIENT: 1375d250589dSStephen Hemminger ret = memif_connect_client(dev); 137609c7e63aSJakub Grajciar break; 1377d250589dSStephen Hemminger case MEMIF_ROLE_SERVER: 1378d250589dSStephen Hemminger ret = memif_connect_server(dev); 137909c7e63aSJakub Grajciar break; 138009c7e63aSJakub Grajciar default: 138143b815d8SJakub Grajciar MIF_LOG(ERR, "Unknown role: %d.", pmd->role); 138209c7e63aSJakub Grajciar ret = -1; 138309c7e63aSJakub Grajciar break; 138409c7e63aSJakub Grajciar } 138509c7e63aSJakub Grajciar 13861b5e3493SJie Hai if (ret == 0) { 13871b5e3493SJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 13881b5e3493SJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 13891b5e3493SJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 13901b5e3493SJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 13911b5e3493SJie Hai } 13921b5e3493SJie Hai 139309c7e63aSJakub Grajciar return ret; 139409c7e63aSJakub Grajciar } 139509c7e63aSJakub Grajciar 1396b142387bSThomas Monjalon static int 1397858a152aSJunxiao Shi memif_dev_stop(struct rte_eth_dev *dev) 1398858a152aSJunxiao Shi { 13991b5e3493SJie Hai uint16_t i; 14001b5e3493SJie Hai 1401858a152aSJunxiao Shi memif_disconnect(dev); 14021b5e3493SJie Hai 14031b5e3493SJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 14041b5e3493SJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 14051b5e3493SJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 14061b5e3493SJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 14071b5e3493SJie Hai 1408858a152aSJunxiao Shi return 0; 1409858a152aSJunxiao Shi } 1410858a152aSJunxiao Shi 1411858a152aSJunxiao Shi static int 141209c7e63aSJakub Grajciar memif_dev_close(struct rte_eth_dev *dev) 141309c7e63aSJakub Grajciar { 141409c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 141509c7e63aSJakub Grajciar int i; 141609c7e63aSJakub Grajciar 1417c41a0495SJakub Grajciar if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 141809c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, "Device closed", 0); 141909c7e63aSJakub Grajciar 142009c7e63aSJakub Grajciar for (i = 0; i < dev->data->nb_rx_queues; i++) 14217483341aSXueming Li (*dev->dev_ops->rx_queue_release)(dev, i); 142209c7e63aSJakub Grajciar for (i = 0; i < dev->data->nb_tx_queues; i++) 14237483341aSXueming Li (*dev->dev_ops->tx_queue_release)(dev, i); 142409c7e63aSJakub Grajciar 142509c7e63aSJakub Grajciar memif_socket_remove_device(dev); 1426c41a0495SJakub Grajciar } 1427c41a0495SJakub Grajciar 1428c41a0495SJakub Grajciar rte_free(dev->process_private); 1429b142387bSThomas Monjalon 1430b142387bSThomas Monjalon return 0; 143109c7e63aSJakub Grajciar } 143209c7e63aSJakub Grajciar 143309c7e63aSJakub Grajciar static int 143409c7e63aSJakub Grajciar memif_dev_configure(struct rte_eth_dev *dev) 143509c7e63aSJakub Grajciar { 143609c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 143709c7e63aSJakub Grajciar 143809c7e63aSJakub Grajciar /* 1439d250589dSStephen Hemminger * CLIENT - TXQ 1440d250589dSStephen Hemminger * SERVER - RXQ 144109c7e63aSJakub Grajciar */ 1442d250589dSStephen Hemminger pmd->cfg.num_c2s_rings = (pmd->role == MEMIF_ROLE_CLIENT) ? 144309c7e63aSJakub Grajciar dev->data->nb_tx_queues : dev->data->nb_rx_queues; 144409c7e63aSJakub Grajciar 144509c7e63aSJakub Grajciar /* 1446d250589dSStephen Hemminger * CLIENT - RXQ 1447d250589dSStephen Hemminger * SERVER - TXQ 144809c7e63aSJakub Grajciar */ 1449d250589dSStephen Hemminger pmd->cfg.num_s2c_rings = (pmd->role == MEMIF_ROLE_CLIENT) ? 145009c7e63aSJakub Grajciar dev->data->nb_rx_queues : dev->data->nb_tx_queues; 145109c7e63aSJakub Grajciar 145209c7e63aSJakub Grajciar return 0; 145309c7e63aSJakub Grajciar } 145409c7e63aSJakub Grajciar 145509c7e63aSJakub Grajciar static int 145609c7e63aSJakub Grajciar memif_tx_queue_setup(struct rte_eth_dev *dev, 145709c7e63aSJakub Grajciar uint16_t qid, 145809c7e63aSJakub Grajciar uint16_t nb_tx_desc __rte_unused, 145909c7e63aSJakub Grajciar unsigned int socket_id __rte_unused, 146009c7e63aSJakub Grajciar const struct rte_eth_txconf *tx_conf __rte_unused) 146109c7e63aSJakub Grajciar { 146209c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 146309c7e63aSJakub Grajciar struct memif_queue *mq; 146409c7e63aSJakub Grajciar 146509c7e63aSJakub Grajciar mq = rte_zmalloc("tx-queue", sizeof(struct memif_queue), 0); 146609c7e63aSJakub Grajciar if (mq == NULL) { 146743b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to allocate tx queue id: %u", qid); 146809c7e63aSJakub Grajciar return -ENOMEM; 146909c7e63aSJakub Grajciar } 147009c7e63aSJakub Grajciar 1471d61138d4SHarman Kalra /* Allocate interrupt instance */ 1472d61138d4SHarman Kalra mq->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED); 1473d61138d4SHarman Kalra if (mq->intr_handle == NULL) { 1474d61138d4SHarman Kalra MIF_LOG(ERR, "Failed to allocate intr handle"); 1475d61138d4SHarman Kalra return -ENOMEM; 1476d61138d4SHarman Kalra } 1477d61138d4SHarman Kalra 147809c7e63aSJakub Grajciar mq->type = 1479d250589dSStephen Hemminger (pmd->role == MEMIF_ROLE_CLIENT) ? MEMIF_RING_C2S : MEMIF_RING_S2C; 148009c7e63aSJakub Grajciar mq->n_pkts = 0; 148109c7e63aSJakub Grajciar mq->n_bytes = 0; 1482d61138d4SHarman Kalra 1483d61138d4SHarman Kalra if (rte_intr_fd_set(mq->intr_handle, -1)) 1484d61138d4SHarman Kalra return -rte_errno; 1485d61138d4SHarman Kalra 1486d61138d4SHarman Kalra if (rte_intr_type_set(mq->intr_handle, RTE_INTR_HANDLE_EXT)) 1487d61138d4SHarman Kalra return -rte_errno; 1488d61138d4SHarman Kalra 1489ed650f3dSAnand Sunkad mq->in_port = dev->data->port_id; 149009c7e63aSJakub Grajciar dev->data->tx_queues[qid] = mq; 149109c7e63aSJakub Grajciar 149209c7e63aSJakub Grajciar return 0; 149309c7e63aSJakub Grajciar } 149409c7e63aSJakub Grajciar 149509c7e63aSJakub Grajciar static int 149609c7e63aSJakub Grajciar memif_rx_queue_setup(struct rte_eth_dev *dev, 149709c7e63aSJakub Grajciar uint16_t qid, 149809c7e63aSJakub Grajciar uint16_t nb_rx_desc __rte_unused, 149909c7e63aSJakub Grajciar unsigned int socket_id __rte_unused, 150009c7e63aSJakub Grajciar const struct rte_eth_rxconf *rx_conf __rte_unused, 150109c7e63aSJakub Grajciar struct rte_mempool *mb_pool) 150209c7e63aSJakub Grajciar { 150309c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 150409c7e63aSJakub Grajciar struct memif_queue *mq; 150509c7e63aSJakub Grajciar 150609c7e63aSJakub Grajciar mq = rte_zmalloc("rx-queue", sizeof(struct memif_queue), 0); 150709c7e63aSJakub Grajciar if (mq == NULL) { 150843b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to allocate rx queue id: %u", qid); 150909c7e63aSJakub Grajciar return -ENOMEM; 151009c7e63aSJakub Grajciar } 151109c7e63aSJakub Grajciar 1512d61138d4SHarman Kalra /* Allocate interrupt instance */ 1513d61138d4SHarman Kalra mq->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED); 1514d61138d4SHarman Kalra if (mq->intr_handle == NULL) { 1515d61138d4SHarman Kalra MIF_LOG(ERR, "Failed to allocate intr handle"); 1516d61138d4SHarman Kalra return -ENOMEM; 1517d61138d4SHarman Kalra } 1518d61138d4SHarman Kalra 1519d250589dSStephen Hemminger mq->type = (pmd->role == MEMIF_ROLE_CLIENT) ? MEMIF_RING_S2C : MEMIF_RING_C2S; 152009c7e63aSJakub Grajciar mq->n_pkts = 0; 152109c7e63aSJakub Grajciar mq->n_bytes = 0; 1522d61138d4SHarman Kalra 1523d61138d4SHarman Kalra if (rte_intr_fd_set(mq->intr_handle, -1)) 1524d61138d4SHarman Kalra return -rte_errno; 1525d61138d4SHarman Kalra 1526d61138d4SHarman Kalra if (rte_intr_type_set(mq->intr_handle, RTE_INTR_HANDLE_EXT)) 1527d61138d4SHarman Kalra return -rte_errno; 1528d61138d4SHarman Kalra 152909c7e63aSJakub Grajciar mq->mempool = mb_pool; 153009c7e63aSJakub Grajciar mq->in_port = dev->data->port_id; 153109c7e63aSJakub Grajciar dev->data->rx_queues[qid] = mq; 153209c7e63aSJakub Grajciar 153309c7e63aSJakub Grajciar return 0; 153409c7e63aSJakub Grajciar } 153509c7e63aSJakub Grajciar 153609c7e63aSJakub Grajciar static void 15377483341aSXueming Li memif_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 153809c7e63aSJakub Grajciar { 15397483341aSXueming Li struct memif_queue *mq = dev->data->rx_queues[qid]; 15407483341aSXueming Li 15417483341aSXueming Li if (!mq) 15427483341aSXueming Li return; 15437483341aSXueming Li 1544d61138d4SHarman Kalra rte_intr_instance_free(mq->intr_handle); 15457483341aSXueming Li rte_free(mq); 15467483341aSXueming Li } 15477483341aSXueming Li 15487483341aSXueming Li static void 15497483341aSXueming Li memif_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 15507483341aSXueming Li { 15517483341aSXueming Li struct memif_queue *mq = dev->data->tx_queues[qid]; 155209c7e63aSJakub Grajciar 155309c7e63aSJakub Grajciar if (!mq) 155409c7e63aSJakub Grajciar return; 155509c7e63aSJakub Grajciar 155609c7e63aSJakub Grajciar rte_free(mq); 155709c7e63aSJakub Grajciar } 155809c7e63aSJakub Grajciar 155909c7e63aSJakub Grajciar static int 1560c41a0495SJakub Grajciar memif_link_update(struct rte_eth_dev *dev, 156109c7e63aSJakub Grajciar int wait_to_complete __rte_unused) 156209c7e63aSJakub Grajciar { 1563c41a0495SJakub Grajciar struct pmd_process_private *proc_private; 1564c41a0495SJakub Grajciar 1565c41a0495SJakub Grajciar if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 1566c41a0495SJakub Grajciar proc_private = dev->process_private; 1567295968d1SFerruh Yigit if (dev->data->dev_link.link_status == RTE_ETH_LINK_UP && 1568c41a0495SJakub Grajciar proc_private->regions_num == 0) { 1569c41a0495SJakub Grajciar memif_mp_request_regions(dev); 1570295968d1SFerruh Yigit } else if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN && 1571c41a0495SJakub Grajciar proc_private->regions_num > 0) { 157243b815d8SJakub Grajciar memif_free_regions(dev); 1573c41a0495SJakub Grajciar } 1574c41a0495SJakub Grajciar } 157509c7e63aSJakub Grajciar return 0; 157609c7e63aSJakub Grajciar } 157709c7e63aSJakub Grajciar 157809c7e63aSJakub Grajciar static int 157909c7e63aSJakub Grajciar memif_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) 158009c7e63aSJakub Grajciar { 158109c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 158209c7e63aSJakub Grajciar struct memif_queue *mq; 158309c7e63aSJakub Grajciar int i; 158409c7e63aSJakub Grajciar uint8_t tmp, nq; 158509c7e63aSJakub Grajciar 158609c7e63aSJakub Grajciar stats->ipackets = 0; 158709c7e63aSJakub Grajciar stats->ibytes = 0; 158809c7e63aSJakub Grajciar stats->opackets = 0; 158909c7e63aSJakub Grajciar stats->obytes = 0; 159009c7e63aSJakub Grajciar 1591231435a5SHuzaifa Rahman tmp = (pmd->role == MEMIF_ROLE_CLIENT) ? pmd->run.num_s2c_rings : 1592231435a5SHuzaifa Rahman pmd->run.num_c2s_rings; 159309c7e63aSJakub Grajciar nq = (tmp < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? tmp : 159409c7e63aSJakub Grajciar RTE_ETHDEV_QUEUE_STAT_CNTRS; 159509c7e63aSJakub Grajciar 159609c7e63aSJakub Grajciar /* RX stats */ 159709c7e63aSJakub Grajciar for (i = 0; i < nq; i++) { 159809c7e63aSJakub Grajciar mq = dev->data->rx_queues[i]; 159909c7e63aSJakub Grajciar stats->q_ipackets[i] = mq->n_pkts; 160009c7e63aSJakub Grajciar stats->q_ibytes[i] = mq->n_bytes; 160109c7e63aSJakub Grajciar stats->ipackets += mq->n_pkts; 160209c7e63aSJakub Grajciar stats->ibytes += mq->n_bytes; 160309c7e63aSJakub Grajciar } 160409c7e63aSJakub Grajciar 1605231435a5SHuzaifa Rahman tmp = (pmd->role == MEMIF_ROLE_CLIENT) ? pmd->run.num_c2s_rings : 1606231435a5SHuzaifa Rahman pmd->run.num_s2c_rings; 160709c7e63aSJakub Grajciar nq = (tmp < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? tmp : 160809c7e63aSJakub Grajciar RTE_ETHDEV_QUEUE_STAT_CNTRS; 160909c7e63aSJakub Grajciar 161009c7e63aSJakub Grajciar /* TX stats */ 161109c7e63aSJakub Grajciar for (i = 0; i < nq; i++) { 161209c7e63aSJakub Grajciar mq = dev->data->tx_queues[i]; 161309c7e63aSJakub Grajciar stats->q_opackets[i] = mq->n_pkts; 161409c7e63aSJakub Grajciar stats->q_obytes[i] = mq->n_bytes; 161509c7e63aSJakub Grajciar stats->opackets += mq->n_pkts; 161609c7e63aSJakub Grajciar stats->obytes += mq->n_bytes; 161709c7e63aSJakub Grajciar } 161809c7e63aSJakub Grajciar return 0; 161909c7e63aSJakub Grajciar } 162009c7e63aSJakub Grajciar 16219970a9adSIgor Romanov static int 162209c7e63aSJakub Grajciar memif_stats_reset(struct rte_eth_dev *dev) 162309c7e63aSJakub Grajciar { 162409c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 162509c7e63aSJakub Grajciar int i; 162609c7e63aSJakub Grajciar struct memif_queue *mq; 162709c7e63aSJakub Grajciar 1628d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_c2s_rings; i++) { 1629d250589dSStephen Hemminger mq = (pmd->role == MEMIF_ROLE_CLIENT) ? dev->data->tx_queues[i] : 163009c7e63aSJakub Grajciar dev->data->rx_queues[i]; 163109c7e63aSJakub Grajciar mq->n_pkts = 0; 163209c7e63aSJakub Grajciar mq->n_bytes = 0; 163309c7e63aSJakub Grajciar } 1634d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_s2c_rings; i++) { 1635d250589dSStephen Hemminger mq = (pmd->role == MEMIF_ROLE_CLIENT) ? dev->data->rx_queues[i] : 163609c7e63aSJakub Grajciar dev->data->tx_queues[i]; 163709c7e63aSJakub Grajciar mq->n_pkts = 0; 163809c7e63aSJakub Grajciar mq->n_bytes = 0; 163909c7e63aSJakub Grajciar } 16409970a9adSIgor Romanov 16419970a9adSIgor Romanov return 0; 164209c7e63aSJakub Grajciar } 164309c7e63aSJakub Grajciar 164409c7e63aSJakub Grajciar static const struct eth_dev_ops ops = { 164509c7e63aSJakub Grajciar .dev_start = memif_dev_start, 1646858a152aSJunxiao Shi .dev_stop = memif_dev_stop, 164709c7e63aSJakub Grajciar .dev_close = memif_dev_close, 164809c7e63aSJakub Grajciar .dev_infos_get = memif_dev_info, 164909c7e63aSJakub Grajciar .dev_configure = memif_dev_configure, 165009c7e63aSJakub Grajciar .tx_queue_setup = memif_tx_queue_setup, 165109c7e63aSJakub Grajciar .rx_queue_setup = memif_rx_queue_setup, 16527483341aSXueming Li .rx_queue_release = memif_rx_queue_release, 16537483341aSXueming Li .tx_queue_release = memif_tx_queue_release, 165409c7e63aSJakub Grajciar .link_update = memif_link_update, 165509c7e63aSJakub Grajciar .stats_get = memif_stats_get, 165609c7e63aSJakub Grajciar .stats_reset = memif_stats_reset, 165709c7e63aSJakub Grajciar }; 165809c7e63aSJakub Grajciar 165909c7e63aSJakub Grajciar static int 166009c7e63aSJakub Grajciar memif_create(struct rte_vdev_device *vdev, enum memif_role_t role, 166109c7e63aSJakub Grajciar memif_interface_id_t id, uint32_t flags, 1662f62d5262SJunxiao Shi const char *socket_filename, uid_t owner_uid, gid_t owner_gid, 166309c7e63aSJakub Grajciar memif_log2_ring_size_t log2_ring_size, 166409c7e63aSJakub Grajciar uint16_t pkt_buffer_size, const char *secret, 166509c7e63aSJakub Grajciar struct rte_ether_addr *ether_addr) 166609c7e63aSJakub Grajciar { 166709c7e63aSJakub Grajciar int ret = 0; 166809c7e63aSJakub Grajciar struct rte_eth_dev *eth_dev; 166909c7e63aSJakub Grajciar struct rte_eth_dev_data *data; 167009c7e63aSJakub Grajciar struct pmd_internals *pmd; 1671c41a0495SJakub Grajciar struct pmd_process_private *process_private; 167209c7e63aSJakub Grajciar const unsigned int numa_node = vdev->device.numa_node; 167309c7e63aSJakub Grajciar const char *name = rte_vdev_device_name(vdev); 167409c7e63aSJakub Grajciar 167509c7e63aSJakub Grajciar eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*pmd)); 167609c7e63aSJakub Grajciar if (eth_dev == NULL) { 167709c7e63aSJakub Grajciar MIF_LOG(ERR, "%s: Unable to allocate device struct.", name); 167809c7e63aSJakub Grajciar return -1; 167909c7e63aSJakub Grajciar } 168009c7e63aSJakub Grajciar 1681c41a0495SJakub Grajciar process_private = (struct pmd_process_private *) 1682c41a0495SJakub Grajciar rte_zmalloc(name, sizeof(struct pmd_process_private), 1683c41a0495SJakub Grajciar RTE_CACHE_LINE_SIZE); 1684c41a0495SJakub Grajciar 1685c41a0495SJakub Grajciar if (process_private == NULL) { 1686c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to alloc memory for process private"); 1687c41a0495SJakub Grajciar return -1; 1688c41a0495SJakub Grajciar } 1689c41a0495SJakub Grajciar eth_dev->process_private = process_private; 1690c41a0495SJakub Grajciar 169109c7e63aSJakub Grajciar pmd = eth_dev->data->dev_private; 169209c7e63aSJakub Grajciar memset(pmd, 0, sizeof(*pmd)); 169309c7e63aSJakub Grajciar 169409c7e63aSJakub Grajciar pmd->id = id; 169509c7e63aSJakub Grajciar pmd->flags = flags; 169609c7e63aSJakub Grajciar pmd->flags |= ETH_MEMIF_FLAG_DISABLED; 169709c7e63aSJakub Grajciar pmd->role = role; 1698d250589dSStephen Hemminger /* Zero-copy flag irelevant to server. */ 1699d250589dSStephen Hemminger if (pmd->role == MEMIF_ROLE_SERVER) 170043b815d8SJakub Grajciar pmd->flags &= ~ETH_MEMIF_FLAG_ZERO_COPY; 1701f62d5262SJunxiao Shi pmd->owner_uid = owner_uid; 1702f62d5262SJunxiao Shi pmd->owner_gid = owner_gid; 170309c7e63aSJakub Grajciar 170409c7e63aSJakub Grajciar ret = memif_socket_init(eth_dev, socket_filename); 170509c7e63aSJakub Grajciar if (ret < 0) 170609c7e63aSJakub Grajciar return ret; 170709c7e63aSJakub Grajciar 170809c7e63aSJakub Grajciar memset(pmd->secret, 0, sizeof(char) * ETH_MEMIF_SECRET_SIZE); 170909c7e63aSJakub Grajciar if (secret != NULL) 171009c7e63aSJakub Grajciar strlcpy(pmd->secret, secret, sizeof(pmd->secret)); 171109c7e63aSJakub Grajciar 171209c7e63aSJakub Grajciar pmd->cfg.log2_ring_size = log2_ring_size; 171309c7e63aSJakub Grajciar /* set in .dev_configure() */ 1714d250589dSStephen Hemminger pmd->cfg.num_c2s_rings = 0; 1715d250589dSStephen Hemminger pmd->cfg.num_s2c_rings = 0; 171609c7e63aSJakub Grajciar 171709c7e63aSJakub Grajciar pmd->cfg.pkt_buffer_size = pkt_buffer_size; 1718cbbbbd33SJúlius Milan rte_spinlock_init(&pmd->cc_lock); 171909c7e63aSJakub Grajciar 172009c7e63aSJakub Grajciar data = eth_dev->data; 172109c7e63aSJakub Grajciar data->dev_private = pmd; 172209c7e63aSJakub Grajciar data->numa_node = numa_node; 172319d4c1aeSJúlius Milan data->dev_link = pmd_link; 172409c7e63aSJakub Grajciar data->mac_addrs = ether_addr; 17250a77baedSJakub Grajciar data->promiscuous = 1; 1726f30e69b4SFerruh Yigit data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 172709c7e63aSJakub Grajciar 172809c7e63aSJakub Grajciar eth_dev->dev_ops = &ops; 172909c7e63aSJakub Grajciar eth_dev->device = &vdev->device; 173043b815d8SJakub Grajciar if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) { 173143b815d8SJakub Grajciar eth_dev->rx_pkt_burst = eth_memif_rx_zc; 173243b815d8SJakub Grajciar eth_dev->tx_pkt_burst = eth_memif_tx_zc; 173343b815d8SJakub Grajciar } else { 173409c7e63aSJakub Grajciar eth_dev->rx_pkt_burst = eth_memif_rx; 173509c7e63aSJakub Grajciar eth_dev->tx_pkt_burst = eth_memif_tx; 173643b815d8SJakub Grajciar } 173743b815d8SJakub Grajciar 173809c7e63aSJakub Grajciar rte_eth_dev_probing_finish(eth_dev); 173909c7e63aSJakub Grajciar 174009c7e63aSJakub Grajciar return 0; 174109c7e63aSJakub Grajciar } 174209c7e63aSJakub Grajciar 174309c7e63aSJakub Grajciar static int 174409c7e63aSJakub Grajciar memif_set_role(const char *key __rte_unused, const char *value, 174509c7e63aSJakub Grajciar void *extra_args) 174609c7e63aSJakub Grajciar { 174709c7e63aSJakub Grajciar enum memif_role_t *role = (enum memif_role_t *)extra_args; 174809c7e63aSJakub Grajciar 1749d250589dSStephen Hemminger if (strstr(value, "server") != NULL) { 1750d250589dSStephen Hemminger *role = MEMIF_ROLE_SERVER; 1751d250589dSStephen Hemminger } else if (strstr(value, "client") != NULL) { 1752d250589dSStephen Hemminger *role = MEMIF_ROLE_CLIENT; 1753d250589dSStephen Hemminger } else if (strstr(value, "master") != NULL) { 1754d250589dSStephen Hemminger MIF_LOG(NOTICE, "Role argument \"master\" is deprecated, use \"server\""); 1755d250589dSStephen Hemminger *role = MEMIF_ROLE_SERVER; 175609c7e63aSJakub Grajciar } else if (strstr(value, "slave") != NULL) { 1757d250589dSStephen Hemminger MIF_LOG(NOTICE, "Role argument \"slave\" is deprecated, use \"client\""); 1758d250589dSStephen Hemminger *role = MEMIF_ROLE_CLIENT; 175909c7e63aSJakub Grajciar } else { 176009c7e63aSJakub Grajciar MIF_LOG(ERR, "Unknown role: %s.", value); 176109c7e63aSJakub Grajciar return -EINVAL; 176209c7e63aSJakub Grajciar } 176309c7e63aSJakub Grajciar return 0; 176409c7e63aSJakub Grajciar } 176509c7e63aSJakub Grajciar 176609c7e63aSJakub Grajciar static int 176709c7e63aSJakub Grajciar memif_set_zc(const char *key __rte_unused, const char *value, void *extra_args) 176809c7e63aSJakub Grajciar { 176909c7e63aSJakub Grajciar uint32_t *flags = (uint32_t *)extra_args; 177009c7e63aSJakub Grajciar 177109c7e63aSJakub Grajciar if (strstr(value, "yes") != NULL) { 177243b815d8SJakub Grajciar if (!rte_mcfg_get_single_file_segments()) { 177343b815d8SJakub Grajciar MIF_LOG(ERR, "Zero-copy doesn't support multi-file segments."); 177443b815d8SJakub Grajciar return -ENOTSUP; 177543b815d8SJakub Grajciar } 177609c7e63aSJakub Grajciar *flags |= ETH_MEMIF_FLAG_ZERO_COPY; 177709c7e63aSJakub Grajciar } else if (strstr(value, "no") != NULL) { 177809c7e63aSJakub Grajciar *flags &= ~ETH_MEMIF_FLAG_ZERO_COPY; 177909c7e63aSJakub Grajciar } else { 178009c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to parse zero-copy param: %s.", value); 178109c7e63aSJakub Grajciar return -EINVAL; 178209c7e63aSJakub Grajciar } 178309c7e63aSJakub Grajciar return 0; 178409c7e63aSJakub Grajciar } 178509c7e63aSJakub Grajciar 178609c7e63aSJakub Grajciar static int 178709c7e63aSJakub Grajciar memif_set_id(const char *key __rte_unused, const char *value, void *extra_args) 178809c7e63aSJakub Grajciar { 178909c7e63aSJakub Grajciar memif_interface_id_t *id = (memif_interface_id_t *)extra_args; 179009c7e63aSJakub Grajciar 179109c7e63aSJakub Grajciar /* even if parsing fails, 0 is a valid id */ 179209c7e63aSJakub Grajciar *id = strtoul(value, NULL, 10); 179309c7e63aSJakub Grajciar return 0; 179409c7e63aSJakub Grajciar } 179509c7e63aSJakub Grajciar 179609c7e63aSJakub Grajciar static int 179709c7e63aSJakub Grajciar memif_set_bs(const char *key __rte_unused, const char *value, void *extra_args) 179809c7e63aSJakub Grajciar { 179909c7e63aSJakub Grajciar unsigned long tmp; 180009c7e63aSJakub Grajciar uint16_t *pkt_buffer_size = (uint16_t *)extra_args; 180109c7e63aSJakub Grajciar 180209c7e63aSJakub Grajciar tmp = strtoul(value, NULL, 10); 180309c7e63aSJakub Grajciar if (tmp == 0 || tmp > 0xFFFF) { 180409c7e63aSJakub Grajciar MIF_LOG(ERR, "Invalid buffer size: %s.", value); 180509c7e63aSJakub Grajciar return -EINVAL; 180609c7e63aSJakub Grajciar } 180709c7e63aSJakub Grajciar *pkt_buffer_size = tmp; 180809c7e63aSJakub Grajciar return 0; 180909c7e63aSJakub Grajciar } 181009c7e63aSJakub Grajciar 181109c7e63aSJakub Grajciar static int 181209c7e63aSJakub Grajciar memif_set_rs(const char *key __rte_unused, const char *value, void *extra_args) 181309c7e63aSJakub Grajciar { 181409c7e63aSJakub Grajciar unsigned long tmp; 181509c7e63aSJakub Grajciar memif_log2_ring_size_t *log2_ring_size = 181609c7e63aSJakub Grajciar (memif_log2_ring_size_t *)extra_args; 181709c7e63aSJakub Grajciar 181809c7e63aSJakub Grajciar tmp = strtoul(value, NULL, 10); 181909c7e63aSJakub Grajciar if (tmp == 0 || tmp > ETH_MEMIF_MAX_LOG2_RING_SIZE) { 182009c7e63aSJakub Grajciar MIF_LOG(ERR, "Invalid ring size: %s (max %u).", 182109c7e63aSJakub Grajciar value, ETH_MEMIF_MAX_LOG2_RING_SIZE); 182209c7e63aSJakub Grajciar return -EINVAL; 182309c7e63aSJakub Grajciar } 182409c7e63aSJakub Grajciar *log2_ring_size = tmp; 182509c7e63aSJakub Grajciar return 0; 182609c7e63aSJakub Grajciar } 182709c7e63aSJakub Grajciar 182809c7e63aSJakub Grajciar /* check if directory exists and if we have permission to read/write */ 182909c7e63aSJakub Grajciar static int 183009c7e63aSJakub Grajciar memif_check_socket_filename(const char *filename) 183109c7e63aSJakub Grajciar { 183209c7e63aSJakub Grajciar char *dir = NULL, *tmp; 183309c7e63aSJakub Grajciar uint32_t idx; 183409c7e63aSJakub Grajciar int ret = 0; 183509c7e63aSJakub Grajciar 1836d803feecSJakub Grajciar if (strlen(filename) >= MEMIF_SOCKET_UN_SIZE) { 1837d803feecSJakub Grajciar MIF_LOG(ERR, "Unix socket address too long (max 108)."); 1838d803feecSJakub Grajciar return -1; 1839d803feecSJakub Grajciar } 1840d803feecSJakub Grajciar 184109c7e63aSJakub Grajciar tmp = strrchr(filename, '/'); 184209c7e63aSJakub Grajciar if (tmp != NULL) { 184309c7e63aSJakub Grajciar idx = tmp - filename; 184409c7e63aSJakub Grajciar dir = rte_zmalloc("memif_tmp", sizeof(char) * (idx + 1), 0); 184509c7e63aSJakub Grajciar if (dir == NULL) { 184609c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to allocate memory."); 184709c7e63aSJakub Grajciar return -1; 184809c7e63aSJakub Grajciar } 184909c7e63aSJakub Grajciar strlcpy(dir, filename, sizeof(char) * (idx + 1)); 185009c7e63aSJakub Grajciar } 185109c7e63aSJakub Grajciar 185209c7e63aSJakub Grajciar if (dir == NULL || (faccessat(-1, dir, F_OK | R_OK | 185309c7e63aSJakub Grajciar W_OK, AT_EACCESS) < 0)) { 185409c7e63aSJakub Grajciar MIF_LOG(ERR, "Invalid socket directory."); 185509c7e63aSJakub Grajciar ret = -EINVAL; 185609c7e63aSJakub Grajciar } 185709c7e63aSJakub Grajciar 185809c7e63aSJakub Grajciar rte_free(dir); 185909c7e63aSJakub Grajciar 186009c7e63aSJakub Grajciar return ret; 186109c7e63aSJakub Grajciar } 186209c7e63aSJakub Grajciar 186309c7e63aSJakub Grajciar static int 186409c7e63aSJakub Grajciar memif_set_socket_filename(const char *key __rte_unused, const char *value, 186509c7e63aSJakub Grajciar void *extra_args) 186609c7e63aSJakub Grajciar { 186709c7e63aSJakub Grajciar const char **socket_filename = (const char **)extra_args; 186809c7e63aSJakub Grajciar 186909c7e63aSJakub Grajciar *socket_filename = value; 18702f865ed0SJakub Grajciar return 0; 18712f865ed0SJakub Grajciar } 18722f865ed0SJakub Grajciar 18732f865ed0SJakub Grajciar static int 18742f865ed0SJakub Grajciar memif_set_is_socket_abstract(const char *key __rte_unused, const char *value, void *extra_args) 18752f865ed0SJakub Grajciar { 18762f865ed0SJakub Grajciar uint32_t *flags = (uint32_t *)extra_args; 18772f865ed0SJakub Grajciar 18782f865ed0SJakub Grajciar if (strstr(value, "yes") != NULL) { 18792f865ed0SJakub Grajciar *flags |= ETH_MEMIF_FLAG_SOCKET_ABSTRACT; 18802f865ed0SJakub Grajciar } else if (strstr(value, "no") != NULL) { 18812f865ed0SJakub Grajciar *flags &= ~ETH_MEMIF_FLAG_SOCKET_ABSTRACT; 18822f865ed0SJakub Grajciar } else { 18832f865ed0SJakub Grajciar MIF_LOG(ERR, "Failed to parse socket-abstract param: %s.", value); 18842f865ed0SJakub Grajciar return -EINVAL; 18852f865ed0SJakub Grajciar } 18862f865ed0SJakub Grajciar return 0; 188709c7e63aSJakub Grajciar } 188809c7e63aSJakub Grajciar 188909c7e63aSJakub Grajciar static int 1890f62d5262SJunxiao Shi memif_set_owner(const char *key, const char *value, void *extra_args) 1891f62d5262SJunxiao Shi { 1892f62d5262SJunxiao Shi RTE_ASSERT(sizeof(uid_t) == sizeof(uint32_t)); 1893f62d5262SJunxiao Shi RTE_ASSERT(sizeof(gid_t) == sizeof(uint32_t)); 1894f62d5262SJunxiao Shi 1895f62d5262SJunxiao Shi unsigned long val; 1896f62d5262SJunxiao Shi char *end = NULL; 1897f62d5262SJunxiao Shi uint32_t *id = (uint32_t *)extra_args; 1898f62d5262SJunxiao Shi 1899f62d5262SJunxiao Shi val = strtoul(value, &end, 10); 1900f62d5262SJunxiao Shi if (*value == '\0' || *end != '\0') { 1901f62d5262SJunxiao Shi MIF_LOG(ERR, "Failed to parse %s: %s.", key, value); 1902f62d5262SJunxiao Shi return -EINVAL; 1903f62d5262SJunxiao Shi } 1904f62d5262SJunxiao Shi if (val >= UINT32_MAX) { 1905f62d5262SJunxiao Shi MIF_LOG(ERR, "Invalid %s: %s.", key, value); 1906f62d5262SJunxiao Shi return -ERANGE; 1907f62d5262SJunxiao Shi } 1908f62d5262SJunxiao Shi 1909f62d5262SJunxiao Shi *id = val; 1910f62d5262SJunxiao Shi return 0; 1911f62d5262SJunxiao Shi } 1912f62d5262SJunxiao Shi 1913f62d5262SJunxiao Shi static int 191409c7e63aSJakub Grajciar memif_set_mac(const char *key __rte_unused, const char *value, void *extra_args) 191509c7e63aSJakub Grajciar { 191609c7e63aSJakub Grajciar struct rte_ether_addr *ether_addr = (struct rte_ether_addr *)extra_args; 191709c7e63aSJakub Grajciar 19184a49dbd1SStephen Hemminger if (rte_ether_unformat_addr(value, ether_addr) < 0) 191909c7e63aSJakub Grajciar MIF_LOG(WARNING, "Failed to parse mac '%s'.", value); 192009c7e63aSJakub Grajciar return 0; 192109c7e63aSJakub Grajciar } 192209c7e63aSJakub Grajciar 192309c7e63aSJakub Grajciar static int 192409c7e63aSJakub Grajciar memif_set_secret(const char *key __rte_unused, const char *value, void *extra_args) 192509c7e63aSJakub Grajciar { 192609c7e63aSJakub Grajciar const char **secret = (const char **)extra_args; 192709c7e63aSJakub Grajciar 192809c7e63aSJakub Grajciar *secret = value; 192909c7e63aSJakub Grajciar return 0; 193009c7e63aSJakub Grajciar } 193109c7e63aSJakub Grajciar 193209c7e63aSJakub Grajciar static int 193309c7e63aSJakub Grajciar rte_pmd_memif_probe(struct rte_vdev_device *vdev) 193409c7e63aSJakub Grajciar { 193509c7e63aSJakub Grajciar RTE_BUILD_BUG_ON(sizeof(memif_msg_t) != 128); 193609c7e63aSJakub Grajciar RTE_BUILD_BUG_ON(sizeof(memif_desc_t) != 16); 193709c7e63aSJakub Grajciar int ret = 0; 193809c7e63aSJakub Grajciar struct rte_kvargs *kvlist; 193909c7e63aSJakub Grajciar const char *name = rte_vdev_device_name(vdev); 1940d250589dSStephen Hemminger enum memif_role_t role = MEMIF_ROLE_CLIENT; 194109c7e63aSJakub Grajciar memif_interface_id_t id = 0; 194209c7e63aSJakub Grajciar uint16_t pkt_buffer_size = ETH_MEMIF_DEFAULT_PKT_BUFFER_SIZE; 194309c7e63aSJakub Grajciar memif_log2_ring_size_t log2_ring_size = ETH_MEMIF_DEFAULT_RING_SIZE; 194409c7e63aSJakub Grajciar const char *socket_filename = ETH_MEMIF_DEFAULT_SOCKET_FILENAME; 1945f62d5262SJunxiao Shi uid_t owner_uid = -1; 1946f62d5262SJunxiao Shi gid_t owner_gid = -1; 194709c7e63aSJakub Grajciar uint32_t flags = 0; 194809c7e63aSJakub Grajciar const char *secret = NULL; 194909c7e63aSJakub Grajciar struct rte_ether_addr *ether_addr = rte_zmalloc("", 195009c7e63aSJakub Grajciar sizeof(struct rte_ether_addr), 0); 1951c41a0495SJakub Grajciar struct rte_eth_dev *eth_dev; 195209c7e63aSJakub Grajciar 195309c7e63aSJakub Grajciar rte_eth_random_addr(ether_addr->addr_bytes); 195409c7e63aSJakub Grajciar 195509c7e63aSJakub Grajciar MIF_LOG(INFO, "Initialize MEMIF: %s.", name); 195609c7e63aSJakub Grajciar 195709c7e63aSJakub Grajciar if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 1958c41a0495SJakub Grajciar eth_dev = rte_eth_dev_attach_secondary(name); 1959c41a0495SJakub Grajciar if (!eth_dev) { 1960c41a0495SJakub Grajciar MIF_LOG(ERR, "Failed to probe %s", name); 196109c7e63aSJakub Grajciar return -1; 196209c7e63aSJakub Grajciar } 196309c7e63aSJakub Grajciar 1964c41a0495SJakub Grajciar eth_dev->dev_ops = &ops; 1965c41a0495SJakub Grajciar eth_dev->device = &vdev->device; 1966c41a0495SJakub Grajciar eth_dev->rx_pkt_burst = eth_memif_rx; 19679467deffSPhil Yang eth_dev->tx_pkt_burst = eth_memif_tx; 1968c41a0495SJakub Grajciar 1969c41a0495SJakub Grajciar if (!rte_eal_primary_proc_alive(NULL)) { 1970c41a0495SJakub Grajciar MIF_LOG(ERR, "Primary process is missing"); 1971c41a0495SJakub Grajciar return -1; 1972c41a0495SJakub Grajciar } 1973c41a0495SJakub Grajciar 1974c41a0495SJakub Grajciar eth_dev->process_private = (struct pmd_process_private *) 1975c41a0495SJakub Grajciar rte_zmalloc(name, 1976c41a0495SJakub Grajciar sizeof(struct pmd_process_private), 1977c41a0495SJakub Grajciar RTE_CACHE_LINE_SIZE); 1978c41a0495SJakub Grajciar if (eth_dev->process_private == NULL) { 1979c41a0495SJakub Grajciar MIF_LOG(ERR, 1980c41a0495SJakub Grajciar "Failed to alloc memory for process private"); 1981c41a0495SJakub Grajciar return -1; 1982c41a0495SJakub Grajciar } 1983c41a0495SJakub Grajciar 1984c41a0495SJakub Grajciar rte_eth_dev_probing_finish(eth_dev); 1985c41a0495SJakub Grajciar 1986c41a0495SJakub Grajciar return 0; 1987c41a0495SJakub Grajciar } 1988c41a0495SJakub Grajciar 1989c41a0495SJakub Grajciar ret = rte_mp_action_register(MEMIF_MP_SEND_REGION, memif_mp_send_region); 1990c41a0495SJakub Grajciar /* 1991c41a0495SJakub Grajciar * Primary process can continue probing, but secondary process won't 1992c41a0495SJakub Grajciar * be able to get memory regions information 1993c41a0495SJakub Grajciar */ 1994c41a0495SJakub Grajciar if (ret < 0 && rte_errno != EEXIST) 1995c41a0495SJakub Grajciar MIF_LOG(WARNING, "Failed to register mp action callback: %s", 1996c41a0495SJakub Grajciar strerror(rte_errno)); 1997c41a0495SJakub Grajciar 19982f865ed0SJakub Grajciar /* use abstract address by default */ 19992f865ed0SJakub Grajciar flags |= ETH_MEMIF_FLAG_SOCKET_ABSTRACT; 20002f865ed0SJakub Grajciar 200109c7e63aSJakub Grajciar kvlist = rte_kvargs_parse(rte_vdev_device_args(vdev), valid_arguments); 200209c7e63aSJakub Grajciar 200309c7e63aSJakub Grajciar /* parse parameters */ 200409c7e63aSJakub Grajciar if (kvlist != NULL) { 200509c7e63aSJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_ROLE_ARG, 200609c7e63aSJakub Grajciar &memif_set_role, &role); 200709c7e63aSJakub Grajciar if (ret < 0) 200809c7e63aSJakub Grajciar goto exit; 200909c7e63aSJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_ID_ARG, 201009c7e63aSJakub Grajciar &memif_set_id, &id); 201109c7e63aSJakub Grajciar if (ret < 0) 201209c7e63aSJakub Grajciar goto exit; 201309c7e63aSJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_PKT_BUFFER_SIZE_ARG, 201409c7e63aSJakub Grajciar &memif_set_bs, &pkt_buffer_size); 201509c7e63aSJakub Grajciar if (ret < 0) 201609c7e63aSJakub Grajciar goto exit; 201709c7e63aSJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_RING_SIZE_ARG, 201809c7e63aSJakub Grajciar &memif_set_rs, &log2_ring_size); 201909c7e63aSJakub Grajciar if (ret < 0) 202009c7e63aSJakub Grajciar goto exit; 202109c7e63aSJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_SOCKET_ARG, 202209c7e63aSJakub Grajciar &memif_set_socket_filename, 202309c7e63aSJakub Grajciar (void *)(&socket_filename)); 202409c7e63aSJakub Grajciar if (ret < 0) 202509c7e63aSJakub Grajciar goto exit; 20262f865ed0SJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_SOCKET_ABSTRACT_ARG, 20272f865ed0SJakub Grajciar &memif_set_is_socket_abstract, &flags); 20282f865ed0SJakub Grajciar if (ret < 0) 20292f865ed0SJakub Grajciar goto exit; 2030f62d5262SJunxiao Shi ret = rte_kvargs_process(kvlist, ETH_MEMIF_OWNER_UID_ARG, 2031f62d5262SJunxiao Shi &memif_set_owner, &owner_uid); 2032f62d5262SJunxiao Shi if (ret < 0) 2033f62d5262SJunxiao Shi goto exit; 2034f62d5262SJunxiao Shi ret = rte_kvargs_process(kvlist, ETH_MEMIF_OWNER_GID_ARG, 2035f62d5262SJunxiao Shi &memif_set_owner, &owner_gid); 2036f62d5262SJunxiao Shi if (ret < 0) 2037f62d5262SJunxiao Shi goto exit; 203809c7e63aSJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_MAC_ARG, 203909c7e63aSJakub Grajciar &memif_set_mac, ether_addr); 204009c7e63aSJakub Grajciar if (ret < 0) 204109c7e63aSJakub Grajciar goto exit; 204209c7e63aSJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_ZC_ARG, 204309c7e63aSJakub Grajciar &memif_set_zc, &flags); 204409c7e63aSJakub Grajciar if (ret < 0) 204509c7e63aSJakub Grajciar goto exit; 204609c7e63aSJakub Grajciar ret = rte_kvargs_process(kvlist, ETH_MEMIF_SECRET_ARG, 204709c7e63aSJakub Grajciar &memif_set_secret, (void *)(&secret)); 204809c7e63aSJakub Grajciar if (ret < 0) 204909c7e63aSJakub Grajciar goto exit; 205009c7e63aSJakub Grajciar } 205109c7e63aSJakub Grajciar 20522f865ed0SJakub Grajciar if (!(flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT)) { 20532f865ed0SJakub Grajciar ret = memif_check_socket_filename(socket_filename); 20542f865ed0SJakub Grajciar if (ret < 0) 20552f865ed0SJakub Grajciar goto exit; 20562f865ed0SJakub Grajciar } 20572f865ed0SJakub Grajciar 205809c7e63aSJakub Grajciar /* create interface */ 2059f62d5262SJunxiao Shi ret = memif_create(vdev, role, id, flags, socket_filename, owner_uid, owner_gid, 206009c7e63aSJakub Grajciar log2_ring_size, pkt_buffer_size, secret, ether_addr); 206109c7e63aSJakub Grajciar 206209c7e63aSJakub Grajciar exit: 206309c7e63aSJakub Grajciar rte_kvargs_free(kvlist); 206409c7e63aSJakub Grajciar return ret; 206509c7e63aSJakub Grajciar } 206609c7e63aSJakub Grajciar 206709c7e63aSJakub Grajciar static int 206809c7e63aSJakub Grajciar rte_pmd_memif_remove(struct rte_vdev_device *vdev) 206909c7e63aSJakub Grajciar { 207009c7e63aSJakub Grajciar struct rte_eth_dev *eth_dev; 207109c7e63aSJakub Grajciar 207209c7e63aSJakub Grajciar eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev)); 207309c7e63aSJakub Grajciar if (eth_dev == NULL) 207409c7e63aSJakub Grajciar return 0; 207509c7e63aSJakub Grajciar 20768a5a0aadSThomas Monjalon return rte_eth_dev_close(eth_dev->data->port_id); 207709c7e63aSJakub Grajciar } 207809c7e63aSJakub Grajciar 207909c7e63aSJakub Grajciar static struct rte_vdev_driver pmd_memif_drv = { 208009c7e63aSJakub Grajciar .probe = rte_pmd_memif_probe, 208109c7e63aSJakub Grajciar .remove = rte_pmd_memif_remove, 208209c7e63aSJakub Grajciar }; 208309c7e63aSJakub Grajciar 208409c7e63aSJakub Grajciar RTE_PMD_REGISTER_VDEV(net_memif, pmd_memif_drv); 208509c7e63aSJakub Grajciar 208609c7e63aSJakub Grajciar RTE_PMD_REGISTER_PARAM_STRING(net_memif, 208709c7e63aSJakub Grajciar ETH_MEMIF_ID_ARG "=<int>" 2088d250589dSStephen Hemminger ETH_MEMIF_ROLE_ARG "=server|client" 208909c7e63aSJakub Grajciar ETH_MEMIF_PKT_BUFFER_SIZE_ARG "=<int>" 209009c7e63aSJakub Grajciar ETH_MEMIF_RING_SIZE_ARG "=<int>" 209109c7e63aSJakub Grajciar ETH_MEMIF_SOCKET_ARG "=<string>" 20922f865ed0SJakub Grajciar ETH_MEMIF_SOCKET_ABSTRACT_ARG "=yes|no" 2093f62d5262SJunxiao Shi ETH_MEMIF_OWNER_UID_ARG "=<int>" 2094f62d5262SJunxiao Shi ETH_MEMIF_OWNER_GID_ARG "=<int>" 209509c7e63aSJakub Grajciar ETH_MEMIF_MAC_ARG "=xx:xx:xx:xx:xx:xx" 209609c7e63aSJakub Grajciar ETH_MEMIF_ZC_ARG "=yes|no" 209709c7e63aSJakub Grajciar ETH_MEMIF_SECRET_ARG "=<string>"); 209809c7e63aSJakub Grajciar 2099eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(memif_logtype, NOTICE); 2100