xref: /dpdk/drivers/net/memif/rte_eth_memif.c (revision a4fa02e06046d36c6a7340201571397d2f59a682)
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