xref: /f-stack/dpdk/drivers/net/memif/memif_socket.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright 2018-2019 Cisco Systems, Inc.  All rights reserved.
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang #include <stdlib.h>
64418919fSjohnjiang #include <fcntl.h>
74418919fSjohnjiang #include <unistd.h>
84418919fSjohnjiang #include <sys/types.h>
94418919fSjohnjiang #include <sys/socket.h>
104418919fSjohnjiang #include <sys/ioctl.h>
114418919fSjohnjiang #include <errno.h>
124418919fSjohnjiang 
134418919fSjohnjiang #include <rte_version.h>
144418919fSjohnjiang #include <rte_mbuf.h>
154418919fSjohnjiang #include <rte_ether.h>
164418919fSjohnjiang #include <rte_ethdev_driver.h>
174418919fSjohnjiang #include <rte_ethdev_vdev.h>
184418919fSjohnjiang #include <rte_malloc.h>
194418919fSjohnjiang #include <rte_kvargs.h>
204418919fSjohnjiang #include <rte_bus_vdev.h>
214418919fSjohnjiang #include <rte_hash.h>
224418919fSjohnjiang #include <rte_jhash.h>
234418919fSjohnjiang #include <rte_string_fns.h>
244418919fSjohnjiang 
254418919fSjohnjiang #include "rte_eth_memif.h"
264418919fSjohnjiang #include "memif_socket.h"
274418919fSjohnjiang 
284418919fSjohnjiang static void memif_intr_handler(void *arg);
294418919fSjohnjiang 
304418919fSjohnjiang static ssize_t
memif_msg_send(int fd,memif_msg_t * msg,int afd)314418919fSjohnjiang memif_msg_send(int fd, memif_msg_t *msg, int afd)
324418919fSjohnjiang {
334418919fSjohnjiang 	struct msghdr mh = { 0 };
344418919fSjohnjiang 	struct iovec iov[1];
354418919fSjohnjiang 	struct cmsghdr *cmsg;
364418919fSjohnjiang 	char ctl[CMSG_SPACE(sizeof(int))];
374418919fSjohnjiang 
384418919fSjohnjiang 	iov[0].iov_base = msg;
394418919fSjohnjiang 	iov[0].iov_len = sizeof(memif_msg_t);
404418919fSjohnjiang 	mh.msg_iov = iov;
414418919fSjohnjiang 	mh.msg_iovlen = 1;
424418919fSjohnjiang 
434418919fSjohnjiang 	if (afd > 0) {
444418919fSjohnjiang 		memset(&ctl, 0, sizeof(ctl));
454418919fSjohnjiang 		mh.msg_control = ctl;
464418919fSjohnjiang 		mh.msg_controllen = sizeof(ctl);
474418919fSjohnjiang 		cmsg = CMSG_FIRSTHDR(&mh);
484418919fSjohnjiang 		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
494418919fSjohnjiang 		cmsg->cmsg_level = SOL_SOCKET;
504418919fSjohnjiang 		cmsg->cmsg_type = SCM_RIGHTS;
514418919fSjohnjiang 		rte_memcpy(CMSG_DATA(cmsg), &afd, sizeof(int));
524418919fSjohnjiang 	}
534418919fSjohnjiang 
544418919fSjohnjiang 	return sendmsg(fd, &mh, 0);
554418919fSjohnjiang }
564418919fSjohnjiang 
574418919fSjohnjiang static int
memif_msg_send_from_queue(struct memif_control_channel * cc)584418919fSjohnjiang memif_msg_send_from_queue(struct memif_control_channel *cc)
594418919fSjohnjiang {
604418919fSjohnjiang 	ssize_t size;
614418919fSjohnjiang 	int ret = 0;
624418919fSjohnjiang 	struct memif_msg_queue_elt *e;
634418919fSjohnjiang 
644418919fSjohnjiang 	e = TAILQ_FIRST(&cc->msg_queue);
654418919fSjohnjiang 	if (e == NULL)
664418919fSjohnjiang 		return 0;
674418919fSjohnjiang 
684418919fSjohnjiang 	size = memif_msg_send(cc->intr_handle.fd, &e->msg, e->fd);
694418919fSjohnjiang 	if (size != sizeof(memif_msg_t)) {
704418919fSjohnjiang 		MIF_LOG(ERR, "sendmsg fail: %s.", strerror(errno));
714418919fSjohnjiang 		ret = -1;
724418919fSjohnjiang 	} else {
734418919fSjohnjiang 		MIF_LOG(DEBUG, "Sent msg type %u.", e->msg.type);
744418919fSjohnjiang 	}
754418919fSjohnjiang 	TAILQ_REMOVE(&cc->msg_queue, e, next);
764418919fSjohnjiang 	rte_free(e);
774418919fSjohnjiang 
784418919fSjohnjiang 	return ret;
794418919fSjohnjiang }
804418919fSjohnjiang 
814418919fSjohnjiang static struct memif_msg_queue_elt *
memif_msg_enq(struct memif_control_channel * cc)824418919fSjohnjiang memif_msg_enq(struct memif_control_channel *cc)
834418919fSjohnjiang {
844418919fSjohnjiang 	struct memif_msg_queue_elt *e;
854418919fSjohnjiang 
864418919fSjohnjiang 	e = rte_zmalloc("memif_msg", sizeof(struct memif_msg_queue_elt), 0);
874418919fSjohnjiang 	if (e == NULL) {
884418919fSjohnjiang 		MIF_LOG(ERR, "Failed to allocate control message.");
894418919fSjohnjiang 		return NULL;
904418919fSjohnjiang 	}
914418919fSjohnjiang 
924418919fSjohnjiang 	e->fd = -1;
934418919fSjohnjiang 	TAILQ_INSERT_TAIL(&cc->msg_queue, e, next);
944418919fSjohnjiang 
954418919fSjohnjiang 	return e;
964418919fSjohnjiang }
974418919fSjohnjiang 
984418919fSjohnjiang void
memif_msg_enq_disconnect(struct memif_control_channel * cc,const char * reason,int err_code)994418919fSjohnjiang memif_msg_enq_disconnect(struct memif_control_channel *cc, const char *reason,
1004418919fSjohnjiang 			 int err_code)
1014418919fSjohnjiang {
1024418919fSjohnjiang 	struct memif_msg_queue_elt *e;
1034418919fSjohnjiang 	struct pmd_internals *pmd;
1044418919fSjohnjiang 	memif_msg_disconnect_t *d;
1054418919fSjohnjiang 
1064418919fSjohnjiang 	if (cc == NULL) {
1074418919fSjohnjiang 		MIF_LOG(DEBUG, "Missing control channel.");
1084418919fSjohnjiang 		return;
1094418919fSjohnjiang 	}
1104418919fSjohnjiang 
1114418919fSjohnjiang 	e = memif_msg_enq(cc);
1124418919fSjohnjiang 	if (e == NULL) {
1134418919fSjohnjiang 		MIF_LOG(WARNING, "Failed to enqueue disconnect message.");
1144418919fSjohnjiang 		return;
1154418919fSjohnjiang 	}
1164418919fSjohnjiang 
1174418919fSjohnjiang 	d = &e->msg.disconnect;
1184418919fSjohnjiang 
1194418919fSjohnjiang 	e->msg.type = MEMIF_MSG_TYPE_DISCONNECT;
1204418919fSjohnjiang 	d->code = err_code;
1214418919fSjohnjiang 
1224418919fSjohnjiang 	if (reason != NULL) {
1234418919fSjohnjiang 		strlcpy((char *)d->string, reason, sizeof(d->string));
1244418919fSjohnjiang 		if (cc->dev != NULL) {
1254418919fSjohnjiang 			pmd = cc->dev->data->dev_private;
1264418919fSjohnjiang 			strlcpy(pmd->local_disc_string, reason,
1274418919fSjohnjiang 				sizeof(pmd->local_disc_string));
1284418919fSjohnjiang 		}
1294418919fSjohnjiang 	}
1304418919fSjohnjiang }
1314418919fSjohnjiang 
1324418919fSjohnjiang static int
memif_msg_enq_hello(struct memif_control_channel * cc)1334418919fSjohnjiang memif_msg_enq_hello(struct memif_control_channel *cc)
1344418919fSjohnjiang {
1354418919fSjohnjiang 	struct memif_msg_queue_elt *e = memif_msg_enq(cc);
1364418919fSjohnjiang 	memif_msg_hello_t *h;
1374418919fSjohnjiang 
1384418919fSjohnjiang 	if (e == NULL)
1394418919fSjohnjiang 		return -1;
1404418919fSjohnjiang 
1414418919fSjohnjiang 	h = &e->msg.hello;
1424418919fSjohnjiang 
1434418919fSjohnjiang 	e->msg.type = MEMIF_MSG_TYPE_HELLO;
1444418919fSjohnjiang 	h->min_version = MEMIF_VERSION;
1454418919fSjohnjiang 	h->max_version = MEMIF_VERSION;
146*2d9fd380Sjfb8856606 	h->max_c2s_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS;
147*2d9fd380Sjfb8856606 	h->max_s2c_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS;
1484418919fSjohnjiang 	h->max_region = ETH_MEMIF_MAX_REGION_NUM - 1;
1494418919fSjohnjiang 	h->max_log2_ring_size = ETH_MEMIF_MAX_LOG2_RING_SIZE;
1504418919fSjohnjiang 
1514418919fSjohnjiang 	strlcpy((char *)h->name, rte_version(), sizeof(h->name));
1524418919fSjohnjiang 
1534418919fSjohnjiang 	return 0;
1544418919fSjohnjiang }
1554418919fSjohnjiang 
1564418919fSjohnjiang static int
memif_msg_receive_hello(struct rte_eth_dev * dev,memif_msg_t * msg)1574418919fSjohnjiang memif_msg_receive_hello(struct rte_eth_dev *dev, memif_msg_t *msg)
1584418919fSjohnjiang {
1594418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
1604418919fSjohnjiang 	memif_msg_hello_t *h = &msg->hello;
1614418919fSjohnjiang 
1624418919fSjohnjiang 	if (h->min_version > MEMIF_VERSION || h->max_version < MEMIF_VERSION) {
1634418919fSjohnjiang 		memif_msg_enq_disconnect(pmd->cc, "Incompatible memif version", 0);
1644418919fSjohnjiang 		return -1;
1654418919fSjohnjiang 	}
1664418919fSjohnjiang 
1674418919fSjohnjiang 	/* Set parameters for active connection */
168*2d9fd380Sjfb8856606 	pmd->run.num_c2s_rings = RTE_MIN(h->max_c2s_ring + 1,
169*2d9fd380Sjfb8856606 					   pmd->cfg.num_c2s_rings);
170*2d9fd380Sjfb8856606 	pmd->run.num_s2c_rings = RTE_MIN(h->max_s2c_ring + 1,
171*2d9fd380Sjfb8856606 					   pmd->cfg.num_s2c_rings);
1724418919fSjohnjiang 	pmd->run.log2_ring_size = RTE_MIN(h->max_log2_ring_size,
1734418919fSjohnjiang 					    pmd->cfg.log2_ring_size);
1744418919fSjohnjiang 	pmd->run.pkt_buffer_size = pmd->cfg.pkt_buffer_size;
1754418919fSjohnjiang 
1764418919fSjohnjiang 	strlcpy(pmd->remote_name, (char *)h->name, sizeof(pmd->remote_name));
1774418919fSjohnjiang 
1784418919fSjohnjiang 	MIF_LOG(DEBUG, "Connecting to %s.", pmd->remote_name);
1794418919fSjohnjiang 
1804418919fSjohnjiang 	return 0;
1814418919fSjohnjiang }
1824418919fSjohnjiang 
1834418919fSjohnjiang static int
memif_msg_receive_init(struct memif_control_channel * cc,memif_msg_t * msg)1844418919fSjohnjiang memif_msg_receive_init(struct memif_control_channel *cc, memif_msg_t *msg)
1854418919fSjohnjiang {
1864418919fSjohnjiang 	memif_msg_init_t *i = &msg->init;
1874418919fSjohnjiang 	struct memif_socket_dev_list_elt *elt;
1884418919fSjohnjiang 	struct pmd_internals *pmd;
1894418919fSjohnjiang 	struct rte_eth_dev *dev;
1904418919fSjohnjiang 
1914418919fSjohnjiang 	if (i->version != MEMIF_VERSION) {
1924418919fSjohnjiang 		memif_msg_enq_disconnect(cc, "Incompatible memif version", 0);
1934418919fSjohnjiang 		return -1;
1944418919fSjohnjiang 	}
1954418919fSjohnjiang 
1964418919fSjohnjiang 	if (cc->socket == NULL) {
1974418919fSjohnjiang 		memif_msg_enq_disconnect(cc, "Device error", 0);
1984418919fSjohnjiang 		return -1;
1994418919fSjohnjiang 	}
2004418919fSjohnjiang 
2014418919fSjohnjiang 	/* Find device with requested ID */
2024418919fSjohnjiang 	TAILQ_FOREACH(elt, &cc->socket->dev_queue, next) {
2034418919fSjohnjiang 		dev = elt->dev;
2044418919fSjohnjiang 		pmd = dev->data->dev_private;
2054418919fSjohnjiang 		if (((pmd->flags & ETH_MEMIF_FLAG_DISABLED) == 0) &&
206*2d9fd380Sjfb8856606 		    (pmd->id == i->id) && (pmd->role == MEMIF_ROLE_SERVER)) {
2070c6bd470Sfengbojiang 			if (pmd->flags & (ETH_MEMIF_FLAG_CONNECTING |
2080c6bd470Sfengbojiang 					   ETH_MEMIF_FLAG_CONNECTED)) {
2090c6bd470Sfengbojiang 				memif_msg_enq_disconnect(cc,
2100c6bd470Sfengbojiang 							 "Already connected", 0);
2110c6bd470Sfengbojiang 				return -1;
2120c6bd470Sfengbojiang 			}
2130c6bd470Sfengbojiang 
2144418919fSjohnjiang 			/* assign control channel to device */
2154418919fSjohnjiang 			cc->dev = dev;
2164418919fSjohnjiang 			pmd->cc = cc;
2174418919fSjohnjiang 
2184418919fSjohnjiang 			if (i->mode != MEMIF_INTERFACE_MODE_ETHERNET) {
2194418919fSjohnjiang 				memif_msg_enq_disconnect(pmd->cc,
2204418919fSjohnjiang 							 "Only ethernet mode supported",
2214418919fSjohnjiang 							 0);
2224418919fSjohnjiang 				return -1;
2234418919fSjohnjiang 			}
2244418919fSjohnjiang 
2254418919fSjohnjiang 			strlcpy(pmd->remote_name, (char *)i->name,
2264418919fSjohnjiang 				sizeof(pmd->remote_name));
2274418919fSjohnjiang 
2284418919fSjohnjiang 			if (*pmd->secret != '\0') {
2294418919fSjohnjiang 				if (*i->secret == '\0') {
2304418919fSjohnjiang 					memif_msg_enq_disconnect(pmd->cc,
2314418919fSjohnjiang 								 "Secret required", 0);
2324418919fSjohnjiang 					return -1;
2334418919fSjohnjiang 				}
2344418919fSjohnjiang 				if (strncmp(pmd->secret, (char *)i->secret,
2354418919fSjohnjiang 						ETH_MEMIF_SECRET_SIZE) != 0) {
2364418919fSjohnjiang 					memif_msg_enq_disconnect(pmd->cc,
2374418919fSjohnjiang 								 "Incorrect secret", 0);
2384418919fSjohnjiang 					return -1;
2394418919fSjohnjiang 				}
2404418919fSjohnjiang 			}
2414418919fSjohnjiang 
2424418919fSjohnjiang 			pmd->flags |= ETH_MEMIF_FLAG_CONNECTING;
2434418919fSjohnjiang 			return 0;
2444418919fSjohnjiang 		}
2454418919fSjohnjiang 	}
2464418919fSjohnjiang 
2474418919fSjohnjiang 	/* ID not found on this socket */
2484418919fSjohnjiang 	MIF_LOG(DEBUG, "ID %u not found.", i->id);
2494418919fSjohnjiang 	memif_msg_enq_disconnect(cc, "ID not found", 0);
2504418919fSjohnjiang 	return -1;
2514418919fSjohnjiang }
2524418919fSjohnjiang 
2534418919fSjohnjiang static int
memif_msg_receive_add_region(struct rte_eth_dev * dev,memif_msg_t * msg,int fd)2544418919fSjohnjiang memif_msg_receive_add_region(struct rte_eth_dev *dev, memif_msg_t *msg,
2554418919fSjohnjiang 			     int fd)
2564418919fSjohnjiang {
2574418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
2584418919fSjohnjiang 	struct pmd_process_private *proc_private = dev->process_private;
2594418919fSjohnjiang 	memif_msg_add_region_t *ar = &msg->add_region;
2604418919fSjohnjiang 	struct memif_region *r;
2614418919fSjohnjiang 
2624418919fSjohnjiang 	if (fd < 0) {
2634418919fSjohnjiang 		memif_msg_enq_disconnect(pmd->cc, "Missing region fd", 0);
2644418919fSjohnjiang 		return -1;
2654418919fSjohnjiang 	}
2664418919fSjohnjiang 
2674418919fSjohnjiang 	if (ar->index >= ETH_MEMIF_MAX_REGION_NUM ||
2684418919fSjohnjiang 			ar->index != proc_private->regions_num ||
2694418919fSjohnjiang 			proc_private->regions[ar->index] != NULL) {
2704418919fSjohnjiang 		memif_msg_enq_disconnect(pmd->cc, "Invalid region index", 0);
2714418919fSjohnjiang 		return -1;
2724418919fSjohnjiang 	}
2734418919fSjohnjiang 
2744418919fSjohnjiang 	r = rte_zmalloc("region", sizeof(struct memif_region), 0);
2754418919fSjohnjiang 	if (r == NULL) {
2764418919fSjohnjiang 		memif_msg_enq_disconnect(pmd->cc, "Failed to alloc memif region.", 0);
2774418919fSjohnjiang 		return -ENOMEM;
2784418919fSjohnjiang 	}
2794418919fSjohnjiang 
2804418919fSjohnjiang 	r->fd = fd;
2814418919fSjohnjiang 	r->region_size = ar->size;
2824418919fSjohnjiang 	r->addr = NULL;
2834418919fSjohnjiang 
2844418919fSjohnjiang 	proc_private->regions[ar->index] = r;
2854418919fSjohnjiang 	proc_private->regions_num++;
2864418919fSjohnjiang 
2874418919fSjohnjiang 	return 0;
2884418919fSjohnjiang }
2894418919fSjohnjiang 
2904418919fSjohnjiang static int
memif_msg_receive_add_ring(struct rte_eth_dev * dev,memif_msg_t * msg,int fd)2914418919fSjohnjiang memif_msg_receive_add_ring(struct rte_eth_dev *dev, memif_msg_t *msg, int fd)
2924418919fSjohnjiang {
2934418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
2944418919fSjohnjiang 	memif_msg_add_ring_t *ar = &msg->add_ring;
2954418919fSjohnjiang 	struct memif_queue *mq;
2964418919fSjohnjiang 
2974418919fSjohnjiang 	if (fd < 0) {
2984418919fSjohnjiang 		memif_msg_enq_disconnect(pmd->cc, "Missing interrupt fd", 0);
2994418919fSjohnjiang 		return -1;
3004418919fSjohnjiang 	}
3014418919fSjohnjiang 
3024418919fSjohnjiang 	/* check if we have enough queues */
303*2d9fd380Sjfb8856606 	if (ar->flags & MEMIF_MSG_ADD_RING_FLAG_C2S) {
304*2d9fd380Sjfb8856606 		if (ar->index >= pmd->cfg.num_c2s_rings) {
3054418919fSjohnjiang 			memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0);
3064418919fSjohnjiang 			return -1;
3074418919fSjohnjiang 		}
308*2d9fd380Sjfb8856606 		pmd->run.num_c2s_rings++;
3094418919fSjohnjiang 	} else {
310*2d9fd380Sjfb8856606 		if (ar->index >= pmd->cfg.num_s2c_rings) {
3114418919fSjohnjiang 			memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0);
3124418919fSjohnjiang 			return -1;
3134418919fSjohnjiang 		}
314*2d9fd380Sjfb8856606 		pmd->run.num_s2c_rings++;
3154418919fSjohnjiang 	}
3164418919fSjohnjiang 
317*2d9fd380Sjfb8856606 	mq = (ar->flags & MEMIF_MSG_ADD_RING_FLAG_C2S) ?
3184418919fSjohnjiang 	    dev->data->rx_queues[ar->index] : dev->data->tx_queues[ar->index];
3194418919fSjohnjiang 
3204418919fSjohnjiang 	mq->intr_handle.fd = fd;
3214418919fSjohnjiang 	mq->log2_ring_size = ar->log2_ring_size;
3224418919fSjohnjiang 	mq->region = ar->region;
3234418919fSjohnjiang 	mq->ring_offset = ar->offset;
3244418919fSjohnjiang 
3254418919fSjohnjiang 	return 0;
3264418919fSjohnjiang }
3274418919fSjohnjiang 
3284418919fSjohnjiang static int
memif_msg_receive_connect(struct rte_eth_dev * dev,memif_msg_t * msg)3294418919fSjohnjiang memif_msg_receive_connect(struct rte_eth_dev *dev, memif_msg_t *msg)
3304418919fSjohnjiang {
3314418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
3324418919fSjohnjiang 	memif_msg_connect_t *c = &msg->connect;
3334418919fSjohnjiang 	int ret;
3344418919fSjohnjiang 
3354418919fSjohnjiang 	ret = memif_connect(dev);
3364418919fSjohnjiang 	if (ret < 0)
3374418919fSjohnjiang 		return ret;
3384418919fSjohnjiang 
3394418919fSjohnjiang 	strlcpy(pmd->remote_if_name, (char *)c->if_name,
3404418919fSjohnjiang 		sizeof(pmd->remote_if_name));
3414418919fSjohnjiang 	MIF_LOG(INFO, "Remote interface %s connected.", pmd->remote_if_name);
3424418919fSjohnjiang 
3434418919fSjohnjiang 	return 0;
3444418919fSjohnjiang }
3454418919fSjohnjiang 
3464418919fSjohnjiang static int
memif_msg_receive_connected(struct rte_eth_dev * dev,memif_msg_t * msg)3474418919fSjohnjiang memif_msg_receive_connected(struct rte_eth_dev *dev, memif_msg_t *msg)
3484418919fSjohnjiang {
3494418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
3504418919fSjohnjiang 	memif_msg_connected_t *c = &msg->connected;
3514418919fSjohnjiang 	int ret;
3524418919fSjohnjiang 
3534418919fSjohnjiang 	ret = memif_connect(dev);
3544418919fSjohnjiang 	if (ret < 0)
3554418919fSjohnjiang 		return ret;
3564418919fSjohnjiang 
3574418919fSjohnjiang 	strlcpy(pmd->remote_if_name, (char *)c->if_name,
3584418919fSjohnjiang 		sizeof(pmd->remote_if_name));
3594418919fSjohnjiang 	MIF_LOG(INFO, "Remote interface %s connected.", pmd->remote_if_name);
3604418919fSjohnjiang 
3614418919fSjohnjiang 	return 0;
3624418919fSjohnjiang }
3634418919fSjohnjiang 
3644418919fSjohnjiang static int
memif_msg_receive_disconnect(struct rte_eth_dev * dev,memif_msg_t * msg)3654418919fSjohnjiang memif_msg_receive_disconnect(struct rte_eth_dev *dev, memif_msg_t *msg)
3664418919fSjohnjiang {
3674418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
3684418919fSjohnjiang 	memif_msg_disconnect_t *d = &msg->disconnect;
3694418919fSjohnjiang 
3704418919fSjohnjiang 	memset(pmd->remote_disc_string, 0, sizeof(pmd->remote_disc_string));
3714418919fSjohnjiang 	strlcpy(pmd->remote_disc_string, (char *)d->string,
3724418919fSjohnjiang 		sizeof(pmd->remote_disc_string));
3734418919fSjohnjiang 
3744418919fSjohnjiang 	MIF_LOG(INFO, "Disconnect received: %s", pmd->remote_disc_string);
3754418919fSjohnjiang 
3764418919fSjohnjiang 	memset(pmd->local_disc_string, 0, 96);
3774418919fSjohnjiang 	memif_disconnect(dev);
3784418919fSjohnjiang 	return 0;
3794418919fSjohnjiang }
3804418919fSjohnjiang 
3814418919fSjohnjiang static int
memif_msg_enq_ack(struct rte_eth_dev * dev)3824418919fSjohnjiang memif_msg_enq_ack(struct rte_eth_dev *dev)
3834418919fSjohnjiang {
3844418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
3854418919fSjohnjiang 	struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
3864418919fSjohnjiang 	if (e == NULL)
3874418919fSjohnjiang 		return -1;
3884418919fSjohnjiang 
3894418919fSjohnjiang 	e->msg.type = MEMIF_MSG_TYPE_ACK;
3904418919fSjohnjiang 
3914418919fSjohnjiang 	return 0;
3924418919fSjohnjiang }
3934418919fSjohnjiang 
3944418919fSjohnjiang static int
memif_msg_enq_init(struct rte_eth_dev * dev)3954418919fSjohnjiang memif_msg_enq_init(struct rte_eth_dev *dev)
3964418919fSjohnjiang {
3974418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
3984418919fSjohnjiang 	struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
3994418919fSjohnjiang 	memif_msg_init_t *i = &e->msg.init;
4004418919fSjohnjiang 
4014418919fSjohnjiang 	if (e == NULL)
4024418919fSjohnjiang 		return -1;
4034418919fSjohnjiang 
4044418919fSjohnjiang 	i = &e->msg.init;
4054418919fSjohnjiang 	e->msg.type = MEMIF_MSG_TYPE_INIT;
4064418919fSjohnjiang 	i->version = MEMIF_VERSION;
4074418919fSjohnjiang 	i->id = pmd->id;
4084418919fSjohnjiang 	i->mode = MEMIF_INTERFACE_MODE_ETHERNET;
4094418919fSjohnjiang 
4104418919fSjohnjiang 	strlcpy((char *)i->name, rte_version(), sizeof(i->name));
4114418919fSjohnjiang 
4124418919fSjohnjiang 	if (*pmd->secret != '\0')
4134418919fSjohnjiang 		strlcpy((char *)i->secret, pmd->secret, sizeof(i->secret));
4144418919fSjohnjiang 
4154418919fSjohnjiang 	return 0;
4164418919fSjohnjiang }
4174418919fSjohnjiang 
4184418919fSjohnjiang static int
memif_msg_enq_add_region(struct rte_eth_dev * dev,uint8_t idx)4194418919fSjohnjiang memif_msg_enq_add_region(struct rte_eth_dev *dev, uint8_t idx)
4204418919fSjohnjiang {
4214418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
4224418919fSjohnjiang 	struct pmd_process_private *proc_private = dev->process_private;
4234418919fSjohnjiang 	struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
4244418919fSjohnjiang 	memif_msg_add_region_t *ar;
4254418919fSjohnjiang 	struct memif_region *mr = proc_private->regions[idx];
4264418919fSjohnjiang 
4274418919fSjohnjiang 	if (e == NULL)
4284418919fSjohnjiang 		return -1;
4294418919fSjohnjiang 
4304418919fSjohnjiang 	ar = &e->msg.add_region;
4314418919fSjohnjiang 	e->msg.type = MEMIF_MSG_TYPE_ADD_REGION;
4324418919fSjohnjiang 	e->fd = mr->fd;
4334418919fSjohnjiang 	ar->index = idx;
4344418919fSjohnjiang 	ar->size = mr->region_size;
4354418919fSjohnjiang 
4364418919fSjohnjiang 	return 0;
4374418919fSjohnjiang }
4384418919fSjohnjiang 
4394418919fSjohnjiang static int
memif_msg_enq_add_ring(struct rte_eth_dev * dev,uint8_t idx,memif_ring_type_t type)4404418919fSjohnjiang memif_msg_enq_add_ring(struct rte_eth_dev *dev, uint8_t idx,
4414418919fSjohnjiang 		       memif_ring_type_t type)
4424418919fSjohnjiang {
4434418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
4444418919fSjohnjiang 	struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
4454418919fSjohnjiang 	struct memif_queue *mq;
4464418919fSjohnjiang 	memif_msg_add_ring_t *ar;
4474418919fSjohnjiang 
4484418919fSjohnjiang 	if (e == NULL)
4494418919fSjohnjiang 		return -1;
4504418919fSjohnjiang 
4514418919fSjohnjiang 	ar = &e->msg.add_ring;
452*2d9fd380Sjfb8856606 	mq = (type == MEMIF_RING_C2S) ? dev->data->tx_queues[idx] :
4534418919fSjohnjiang 	    dev->data->rx_queues[idx];
4544418919fSjohnjiang 
4554418919fSjohnjiang 	e->msg.type = MEMIF_MSG_TYPE_ADD_RING;
4564418919fSjohnjiang 	e->fd = mq->intr_handle.fd;
4574418919fSjohnjiang 	ar->index = idx;
4584418919fSjohnjiang 	ar->offset = mq->ring_offset;
4594418919fSjohnjiang 	ar->region = mq->region;
4604418919fSjohnjiang 	ar->log2_ring_size = mq->log2_ring_size;
461*2d9fd380Sjfb8856606 	ar->flags = (type == MEMIF_RING_C2S) ? MEMIF_MSG_ADD_RING_FLAG_C2S : 0;
4624418919fSjohnjiang 	ar->private_hdr_size = 0;
4634418919fSjohnjiang 
4644418919fSjohnjiang 	return 0;
4654418919fSjohnjiang }
4664418919fSjohnjiang 
4674418919fSjohnjiang static int
memif_msg_enq_connect(struct rte_eth_dev * dev)4684418919fSjohnjiang memif_msg_enq_connect(struct rte_eth_dev *dev)
4694418919fSjohnjiang {
4704418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
4714418919fSjohnjiang 	struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
4724418919fSjohnjiang 	memif_msg_connect_t *c;
4734418919fSjohnjiang 
4744418919fSjohnjiang 	if (e == NULL)
4754418919fSjohnjiang 		return -1;
4764418919fSjohnjiang 
4774418919fSjohnjiang 	c = &e->msg.connect;
4784418919fSjohnjiang 	e->msg.type = MEMIF_MSG_TYPE_CONNECT;
4794418919fSjohnjiang 	strlcpy((char *)c->if_name, dev->data->name, sizeof(c->if_name));
4804418919fSjohnjiang 
4814418919fSjohnjiang 	return 0;
4824418919fSjohnjiang }
4834418919fSjohnjiang 
4844418919fSjohnjiang static int
memif_msg_enq_connected(struct rte_eth_dev * dev)4854418919fSjohnjiang memif_msg_enq_connected(struct rte_eth_dev *dev)
4864418919fSjohnjiang {
4874418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
4884418919fSjohnjiang 	struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc);
4894418919fSjohnjiang 	memif_msg_connected_t *c;
4904418919fSjohnjiang 
4914418919fSjohnjiang 	if (e == NULL)
4924418919fSjohnjiang 		return -1;
4934418919fSjohnjiang 
4944418919fSjohnjiang 	c = &e->msg.connected;
4954418919fSjohnjiang 	e->msg.type = MEMIF_MSG_TYPE_CONNECTED;
4964418919fSjohnjiang 	strlcpy((char *)c->if_name, dev->data->name, sizeof(c->if_name));
4974418919fSjohnjiang 
4984418919fSjohnjiang 	return 0;
4994418919fSjohnjiang }
5004418919fSjohnjiang 
5014418919fSjohnjiang static void
memif_intr_unregister_handler(struct rte_intr_handle * intr_handle,void * arg)5024418919fSjohnjiang memif_intr_unregister_handler(struct rte_intr_handle *intr_handle, void *arg)
5034418919fSjohnjiang {
5044418919fSjohnjiang 	struct memif_msg_queue_elt *elt;
5054418919fSjohnjiang 	struct memif_control_channel *cc = arg;
5064418919fSjohnjiang 
5074418919fSjohnjiang 	/* close control channel fd */
5084418919fSjohnjiang 	close(intr_handle->fd);
5094418919fSjohnjiang 	/* clear message queue */
5104418919fSjohnjiang 	while ((elt = TAILQ_FIRST(&cc->msg_queue)) != NULL) {
5114418919fSjohnjiang 		TAILQ_REMOVE(&cc->msg_queue, elt, next);
5124418919fSjohnjiang 		rte_free(elt);
5134418919fSjohnjiang 	}
5144418919fSjohnjiang 	/* free control channel */
5154418919fSjohnjiang 	rte_free(cc);
5164418919fSjohnjiang }
5174418919fSjohnjiang 
5184418919fSjohnjiang void
memif_disconnect(struct rte_eth_dev * dev)5194418919fSjohnjiang memif_disconnect(struct rte_eth_dev *dev)
5204418919fSjohnjiang {
5214418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
5224418919fSjohnjiang 	struct memif_msg_queue_elt *elt, *next;
5234418919fSjohnjiang 	struct memif_queue *mq;
5244418919fSjohnjiang 	struct rte_intr_handle *ih;
5254418919fSjohnjiang 	int i;
5264418919fSjohnjiang 	int ret;
5274418919fSjohnjiang 
5284418919fSjohnjiang 	dev->data->dev_link.link_status = ETH_LINK_DOWN;
5294418919fSjohnjiang 	pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTING;
5304418919fSjohnjiang 	pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTED;
5314418919fSjohnjiang 
532*2d9fd380Sjfb8856606 	rte_spinlock_lock(&pmd->cc_lock);
5334418919fSjohnjiang 	if (pmd->cc != NULL) {
5344418919fSjohnjiang 		/* Clear control message queue (except disconnect message if any). */
5354418919fSjohnjiang 		for (elt = TAILQ_FIRST(&pmd->cc->msg_queue); elt != NULL; elt = next) {
5364418919fSjohnjiang 			next = TAILQ_NEXT(elt, next);
5374418919fSjohnjiang 			if (elt->msg.type != MEMIF_MSG_TYPE_DISCONNECT) {
5384418919fSjohnjiang 				TAILQ_REMOVE(&pmd->cc->msg_queue, elt, next);
5394418919fSjohnjiang 				rte_free(elt);
5404418919fSjohnjiang 			}
5414418919fSjohnjiang 		}
5424418919fSjohnjiang 		/* send disconnect message (if there is any in queue) */
5434418919fSjohnjiang 		memif_msg_send_from_queue(pmd->cc);
5444418919fSjohnjiang 
5454418919fSjohnjiang 		/* at this point, there should be no more messages in queue */
5464418919fSjohnjiang 		if (TAILQ_FIRST(&pmd->cc->msg_queue) != NULL) {
5474418919fSjohnjiang 			MIF_LOG(WARNING,
5484418919fSjohnjiang 				"Unexpected message(s) in message queue.");
5494418919fSjohnjiang 		}
5504418919fSjohnjiang 
5514418919fSjohnjiang 		ih = &pmd->cc->intr_handle;
5524418919fSjohnjiang 		if (ih->fd > 0) {
5534418919fSjohnjiang 			ret = rte_intr_callback_unregister(ih,
5544418919fSjohnjiang 							memif_intr_handler,
5554418919fSjohnjiang 							pmd->cc);
5564418919fSjohnjiang 			/*
5574418919fSjohnjiang 			 * If callback is active (disconnecting based on
5584418919fSjohnjiang 			 * received control message).
5594418919fSjohnjiang 			 */
5604418919fSjohnjiang 			if (ret == -EAGAIN) {
5614418919fSjohnjiang 				ret = rte_intr_callback_unregister_pending(ih,
5624418919fSjohnjiang 							memif_intr_handler,
5634418919fSjohnjiang 							pmd->cc,
5644418919fSjohnjiang 							memif_intr_unregister_handler);
5654418919fSjohnjiang 			} else if (ret > 0) {
5664418919fSjohnjiang 				close(ih->fd);
5674418919fSjohnjiang 				rte_free(pmd->cc);
5684418919fSjohnjiang 			}
5694418919fSjohnjiang 			pmd->cc = NULL;
5704418919fSjohnjiang 			if (ret <= 0)
5714418919fSjohnjiang 				MIF_LOG(WARNING,
5724418919fSjohnjiang 					"Failed to unregister control channel callback.");
5734418919fSjohnjiang 		}
5744418919fSjohnjiang 	}
575*2d9fd380Sjfb8856606 	rte_spinlock_unlock(&pmd->cc_lock);
5764418919fSjohnjiang 
5774418919fSjohnjiang 	/* unconfig interrupts */
578*2d9fd380Sjfb8856606 	for (i = 0; i < pmd->cfg.num_c2s_rings; i++) {
579*2d9fd380Sjfb8856606 		if (pmd->role == MEMIF_ROLE_CLIENT) {
5804418919fSjohnjiang 			if (dev->data->tx_queues != NULL)
5814418919fSjohnjiang 				mq = dev->data->tx_queues[i];
5824418919fSjohnjiang 			else
5834418919fSjohnjiang 				continue;
5844418919fSjohnjiang 		} else {
5854418919fSjohnjiang 			if (dev->data->rx_queues != NULL)
5864418919fSjohnjiang 				mq = dev->data->rx_queues[i];
5874418919fSjohnjiang 			else
5884418919fSjohnjiang 				continue;
5894418919fSjohnjiang 		}
5904418919fSjohnjiang 		if (mq->intr_handle.fd > 0) {
5914418919fSjohnjiang 			close(mq->intr_handle.fd);
5924418919fSjohnjiang 			mq->intr_handle.fd = -1;
5934418919fSjohnjiang 		}
5944418919fSjohnjiang 	}
595*2d9fd380Sjfb8856606 	for (i = 0; i < pmd->cfg.num_s2c_rings; i++) {
596*2d9fd380Sjfb8856606 		if (pmd->role == MEMIF_ROLE_SERVER) {
5974418919fSjohnjiang 			if (dev->data->tx_queues != NULL)
5984418919fSjohnjiang 				mq = dev->data->tx_queues[i];
5994418919fSjohnjiang 			else
6004418919fSjohnjiang 				continue;
6014418919fSjohnjiang 		} else {
6024418919fSjohnjiang 			if (dev->data->rx_queues != NULL)
6034418919fSjohnjiang 				mq = dev->data->rx_queues[i];
6044418919fSjohnjiang 			else
6054418919fSjohnjiang 				continue;
6064418919fSjohnjiang 		}
6074418919fSjohnjiang 		if (mq->intr_handle.fd > 0) {
6084418919fSjohnjiang 			close(mq->intr_handle.fd);
6094418919fSjohnjiang 			mq->intr_handle.fd = -1;
6104418919fSjohnjiang 		}
6114418919fSjohnjiang 	}
6124418919fSjohnjiang 
6134418919fSjohnjiang 	memif_free_regions(dev);
6144418919fSjohnjiang 
6154418919fSjohnjiang 	/* reset connection configuration */
6164418919fSjohnjiang 	memset(&pmd->run, 0, sizeof(pmd->run));
6174418919fSjohnjiang 
618*2d9fd380Sjfb8856606 	MIF_LOG(DEBUG, "Disconnected, id: %d, role: %s.", pmd->id,
619*2d9fd380Sjfb8856606 		(pmd->role == MEMIF_ROLE_SERVER) ? "server" : "client");
6204418919fSjohnjiang }
6214418919fSjohnjiang 
6224418919fSjohnjiang static int
memif_msg_receive(struct memif_control_channel * cc)6234418919fSjohnjiang memif_msg_receive(struct memif_control_channel *cc)
6244418919fSjohnjiang {
6254418919fSjohnjiang 	char ctl[CMSG_SPACE(sizeof(int)) +
6264418919fSjohnjiang 		 CMSG_SPACE(sizeof(struct ucred))] = { 0 };
6274418919fSjohnjiang 	struct msghdr mh = { 0 };
6284418919fSjohnjiang 	struct iovec iov[1];
6294418919fSjohnjiang 	memif_msg_t msg = { 0 };
6304418919fSjohnjiang 	ssize_t size;
6314418919fSjohnjiang 	int ret = 0;
6324418919fSjohnjiang 	struct ucred *cr __rte_unused;
6334418919fSjohnjiang 	cr = 0;
6344418919fSjohnjiang 	struct cmsghdr *cmsg;
6354418919fSjohnjiang 	int afd = -1;
6364418919fSjohnjiang 	int i;
6374418919fSjohnjiang 	struct pmd_internals *pmd;
6384418919fSjohnjiang 	struct pmd_process_private *proc_private;
6394418919fSjohnjiang 
6404418919fSjohnjiang 	iov[0].iov_base = (void *)&msg;
6414418919fSjohnjiang 	iov[0].iov_len = sizeof(memif_msg_t);
6424418919fSjohnjiang 	mh.msg_iov = iov;
6434418919fSjohnjiang 	mh.msg_iovlen = 1;
6444418919fSjohnjiang 	mh.msg_control = ctl;
6454418919fSjohnjiang 	mh.msg_controllen = sizeof(ctl);
6464418919fSjohnjiang 
6474418919fSjohnjiang 	size = recvmsg(cc->intr_handle.fd, &mh, 0);
6484418919fSjohnjiang 	if (size != sizeof(memif_msg_t)) {
649*2d9fd380Sjfb8856606 		MIF_LOG(DEBUG, "Invalid message size = %zd", size);
650*2d9fd380Sjfb8856606 		if (size > 0)
651*2d9fd380Sjfb8856606 			/* 0 means end-of-file, negative size means error,
652*2d9fd380Sjfb8856606 			 * don't send further disconnect message in such cases.
653*2d9fd380Sjfb8856606 			 */
6544418919fSjohnjiang 			memif_msg_enq_disconnect(cc, "Invalid message size", 0);
6554418919fSjohnjiang 		return -1;
6564418919fSjohnjiang 	}
6574418919fSjohnjiang 	MIF_LOG(DEBUG, "Received msg type: %u.", msg.type);
6584418919fSjohnjiang 
6594418919fSjohnjiang 	cmsg = CMSG_FIRSTHDR(&mh);
6604418919fSjohnjiang 	while (cmsg) {
6614418919fSjohnjiang 		if (cmsg->cmsg_level == SOL_SOCKET) {
6624418919fSjohnjiang 			if (cmsg->cmsg_type == SCM_CREDENTIALS)
6634418919fSjohnjiang 				cr = (struct ucred *)CMSG_DATA(cmsg);
6644418919fSjohnjiang 			else if (cmsg->cmsg_type == SCM_RIGHTS)
6654418919fSjohnjiang 				rte_memcpy(&afd, CMSG_DATA(cmsg), sizeof(int));
6664418919fSjohnjiang 		}
6674418919fSjohnjiang 		cmsg = CMSG_NXTHDR(&mh, cmsg);
6684418919fSjohnjiang 	}
6694418919fSjohnjiang 
6704418919fSjohnjiang 	if (cc->dev == NULL && msg.type != MEMIF_MSG_TYPE_INIT) {
6714418919fSjohnjiang 		MIF_LOG(DEBUG, "Unexpected message.");
6724418919fSjohnjiang 		memif_msg_enq_disconnect(cc, "Unexpected message", 0);
6734418919fSjohnjiang 		return -1;
6744418919fSjohnjiang 	}
6754418919fSjohnjiang 
6764418919fSjohnjiang 	/* get device from hash data */
6774418919fSjohnjiang 	switch (msg.type) {
6784418919fSjohnjiang 	case MEMIF_MSG_TYPE_ACK:
6794418919fSjohnjiang 		break;
6804418919fSjohnjiang 	case MEMIF_MSG_TYPE_HELLO:
6814418919fSjohnjiang 		ret = memif_msg_receive_hello(cc->dev, &msg);
6824418919fSjohnjiang 		if (ret < 0)
6834418919fSjohnjiang 			goto exit;
6844418919fSjohnjiang 		ret = memif_init_regions_and_queues(cc->dev);
6854418919fSjohnjiang 		if (ret < 0)
6864418919fSjohnjiang 			goto exit;
6874418919fSjohnjiang 		ret = memif_msg_enq_init(cc->dev);
6884418919fSjohnjiang 		if (ret < 0)
6894418919fSjohnjiang 			goto exit;
6904418919fSjohnjiang 		pmd = cc->dev->data->dev_private;
6914418919fSjohnjiang 		proc_private = cc->dev->process_private;
6924418919fSjohnjiang 		for (i = 0; i < proc_private->regions_num; i++) {
6934418919fSjohnjiang 			ret = memif_msg_enq_add_region(cc->dev, i);
6944418919fSjohnjiang 			if (ret < 0)
6954418919fSjohnjiang 				goto exit;
6964418919fSjohnjiang 		}
697*2d9fd380Sjfb8856606 		for (i = 0; i < pmd->run.num_c2s_rings; i++) {
6984418919fSjohnjiang 			ret = memif_msg_enq_add_ring(cc->dev, i,
699*2d9fd380Sjfb8856606 						     MEMIF_RING_C2S);
7004418919fSjohnjiang 			if (ret < 0)
7014418919fSjohnjiang 				goto exit;
7024418919fSjohnjiang 		}
703*2d9fd380Sjfb8856606 		for (i = 0; i < pmd->run.num_s2c_rings; i++) {
7044418919fSjohnjiang 			ret = memif_msg_enq_add_ring(cc->dev, i,
705*2d9fd380Sjfb8856606 						     MEMIF_RING_S2C);
7064418919fSjohnjiang 			if (ret < 0)
7074418919fSjohnjiang 				goto exit;
7084418919fSjohnjiang 		}
7094418919fSjohnjiang 		ret = memif_msg_enq_connect(cc->dev);
7104418919fSjohnjiang 		if (ret < 0)
7114418919fSjohnjiang 			goto exit;
7124418919fSjohnjiang 		break;
7134418919fSjohnjiang 	case MEMIF_MSG_TYPE_INIT:
7144418919fSjohnjiang 		/*
7154418919fSjohnjiang 		 * This cc does not have an interface asociated with it.
7164418919fSjohnjiang 		 * If suitable interface is found it will be assigned here.
7174418919fSjohnjiang 		 */
7184418919fSjohnjiang 		ret = memif_msg_receive_init(cc, &msg);
7194418919fSjohnjiang 		if (ret < 0)
7204418919fSjohnjiang 			goto exit;
7214418919fSjohnjiang 		ret = memif_msg_enq_ack(cc->dev);
7224418919fSjohnjiang 		if (ret < 0)
7234418919fSjohnjiang 			goto exit;
7244418919fSjohnjiang 		break;
7254418919fSjohnjiang 	case MEMIF_MSG_TYPE_ADD_REGION:
7264418919fSjohnjiang 		ret = memif_msg_receive_add_region(cc->dev, &msg, afd);
7274418919fSjohnjiang 		if (ret < 0)
7284418919fSjohnjiang 			goto exit;
7294418919fSjohnjiang 		ret = memif_msg_enq_ack(cc->dev);
7304418919fSjohnjiang 		if (ret < 0)
7314418919fSjohnjiang 			goto exit;
7324418919fSjohnjiang 		break;
7334418919fSjohnjiang 	case MEMIF_MSG_TYPE_ADD_RING:
7344418919fSjohnjiang 		ret = memif_msg_receive_add_ring(cc->dev, &msg, afd);
7354418919fSjohnjiang 		if (ret < 0)
7364418919fSjohnjiang 			goto exit;
7374418919fSjohnjiang 		ret = memif_msg_enq_ack(cc->dev);
7384418919fSjohnjiang 		if (ret < 0)
7394418919fSjohnjiang 			goto exit;
7404418919fSjohnjiang 		break;
7414418919fSjohnjiang 	case MEMIF_MSG_TYPE_CONNECT:
7424418919fSjohnjiang 		ret = memif_msg_receive_connect(cc->dev, &msg);
7434418919fSjohnjiang 		if (ret < 0)
7444418919fSjohnjiang 			goto exit;
7454418919fSjohnjiang 		ret = memif_msg_enq_connected(cc->dev);
7464418919fSjohnjiang 		if (ret < 0)
7474418919fSjohnjiang 			goto exit;
7484418919fSjohnjiang 		break;
7494418919fSjohnjiang 	case MEMIF_MSG_TYPE_CONNECTED:
7504418919fSjohnjiang 		ret = memif_msg_receive_connected(cc->dev, &msg);
7514418919fSjohnjiang 		break;
7524418919fSjohnjiang 	case MEMIF_MSG_TYPE_DISCONNECT:
7534418919fSjohnjiang 		ret = memif_msg_receive_disconnect(cc->dev, &msg);
7544418919fSjohnjiang 		if (ret < 0)
7554418919fSjohnjiang 			goto exit;
7564418919fSjohnjiang 		break;
7574418919fSjohnjiang 	default:
7584418919fSjohnjiang 		memif_msg_enq_disconnect(cc, "Unknown message type", 0);
7594418919fSjohnjiang 		ret = -1;
7604418919fSjohnjiang 		goto exit;
7614418919fSjohnjiang 	}
7624418919fSjohnjiang 
7634418919fSjohnjiang  exit:
7644418919fSjohnjiang 	return ret;
7654418919fSjohnjiang }
7664418919fSjohnjiang 
7674418919fSjohnjiang static void
memif_intr_handler(void * arg)7684418919fSjohnjiang memif_intr_handler(void *arg)
7694418919fSjohnjiang {
7704418919fSjohnjiang 	struct memif_control_channel *cc = arg;
7714418919fSjohnjiang 	int ret;
7724418919fSjohnjiang 
7734418919fSjohnjiang 	ret = memif_msg_receive(cc);
7744418919fSjohnjiang 	/* if driver failed to assign device */
7754418919fSjohnjiang 	if (cc->dev == NULL) {
7760c6bd470Sfengbojiang 		memif_msg_send_from_queue(cc);
7774418919fSjohnjiang 		ret = rte_intr_callback_unregister_pending(&cc->intr_handle,
7784418919fSjohnjiang 							   memif_intr_handler,
7794418919fSjohnjiang 							   cc,
7804418919fSjohnjiang 							   memif_intr_unregister_handler);
7814418919fSjohnjiang 		if (ret < 0)
7824418919fSjohnjiang 			MIF_LOG(WARNING,
7834418919fSjohnjiang 				"Failed to unregister control channel callback.");
7844418919fSjohnjiang 		return;
7854418919fSjohnjiang 	}
7864418919fSjohnjiang 	/* if memif_msg_receive failed */
7874418919fSjohnjiang 	if (ret < 0)
7884418919fSjohnjiang 		goto disconnect;
7894418919fSjohnjiang 
7904418919fSjohnjiang 	ret = memif_msg_send_from_queue(cc);
7914418919fSjohnjiang 	if (ret < 0)
7924418919fSjohnjiang 		goto disconnect;
7934418919fSjohnjiang 
7944418919fSjohnjiang 	return;
7954418919fSjohnjiang 
7964418919fSjohnjiang  disconnect:
7974418919fSjohnjiang 	if (cc->dev == NULL) {
7984418919fSjohnjiang 		MIF_LOG(WARNING, "eth dev not allocated");
7994418919fSjohnjiang 		return;
8004418919fSjohnjiang 	}
8014418919fSjohnjiang 	memif_disconnect(cc->dev);
8024418919fSjohnjiang }
8034418919fSjohnjiang 
8044418919fSjohnjiang static void
memif_listener_handler(void * arg)8054418919fSjohnjiang memif_listener_handler(void *arg)
8064418919fSjohnjiang {
8074418919fSjohnjiang 	struct memif_socket *socket = arg;
8084418919fSjohnjiang 	int sockfd;
8094418919fSjohnjiang 	int addr_len;
8104418919fSjohnjiang 	struct sockaddr_un client;
8114418919fSjohnjiang 	struct memif_control_channel *cc;
8124418919fSjohnjiang 	int ret;
8134418919fSjohnjiang 
8144418919fSjohnjiang 	addr_len = sizeof(client);
8154418919fSjohnjiang 	sockfd = accept(socket->intr_handle.fd, (struct sockaddr *)&client,
8164418919fSjohnjiang 			(socklen_t *)&addr_len);
8174418919fSjohnjiang 	if (sockfd < 0) {
8184418919fSjohnjiang 		MIF_LOG(ERR,
8194418919fSjohnjiang 			"Failed to accept connection request on socket fd %d",
8204418919fSjohnjiang 			socket->intr_handle.fd);
8214418919fSjohnjiang 		return;
8224418919fSjohnjiang 	}
8234418919fSjohnjiang 
8244418919fSjohnjiang 	MIF_LOG(DEBUG, "%s: Connection request accepted.", socket->filename);
8254418919fSjohnjiang 
8264418919fSjohnjiang 	cc = rte_zmalloc("memif-cc", sizeof(struct memif_control_channel), 0);
8274418919fSjohnjiang 	if (cc == NULL) {
8284418919fSjohnjiang 		MIF_LOG(ERR, "Failed to allocate control channel.");
8294418919fSjohnjiang 		goto error;
8304418919fSjohnjiang 	}
8314418919fSjohnjiang 
8324418919fSjohnjiang 	cc->intr_handle.fd = sockfd;
8334418919fSjohnjiang 	cc->intr_handle.type = RTE_INTR_HANDLE_EXT;
8344418919fSjohnjiang 	cc->socket = socket;
8354418919fSjohnjiang 	cc->dev = NULL;
8364418919fSjohnjiang 	TAILQ_INIT(&cc->msg_queue);
8374418919fSjohnjiang 
8384418919fSjohnjiang 	ret = rte_intr_callback_register(&cc->intr_handle, memif_intr_handler, cc);
8394418919fSjohnjiang 	if (ret < 0) {
8404418919fSjohnjiang 		MIF_LOG(ERR, "Failed to register control channel callback.");
8414418919fSjohnjiang 		goto error;
8424418919fSjohnjiang 	}
8434418919fSjohnjiang 
8444418919fSjohnjiang 	ret = memif_msg_enq_hello(cc);
8454418919fSjohnjiang 	if (ret < 0) {
8464418919fSjohnjiang 		MIF_LOG(ERR, "Failed to enqueue hello message.");
8474418919fSjohnjiang 		goto error;
8484418919fSjohnjiang 	}
8494418919fSjohnjiang 	ret = memif_msg_send_from_queue(cc);
8504418919fSjohnjiang 	if (ret < 0)
8514418919fSjohnjiang 		goto error;
8524418919fSjohnjiang 
8534418919fSjohnjiang 	return;
8544418919fSjohnjiang 
8554418919fSjohnjiang  error:
8564418919fSjohnjiang 	if (sockfd >= 0) {
8574418919fSjohnjiang 		close(sockfd);
8584418919fSjohnjiang 		sockfd = -1;
8594418919fSjohnjiang 	}
8604418919fSjohnjiang 	if (cc != NULL)
8614418919fSjohnjiang 		rte_free(cc);
8624418919fSjohnjiang }
8634418919fSjohnjiang 
8644418919fSjohnjiang static struct memif_socket *
memif_socket_create(char * key,uint8_t listener,bool is_abstract)865*2d9fd380Sjfb8856606 memif_socket_create(char *key, uint8_t listener, bool is_abstract)
8664418919fSjohnjiang {
8674418919fSjohnjiang 	struct memif_socket *sock;
868*2d9fd380Sjfb8856606 	struct sockaddr_un un = { 0 };
8694418919fSjohnjiang 	int sockfd;
8704418919fSjohnjiang 	int ret;
8714418919fSjohnjiang 	int on = 1;
8724418919fSjohnjiang 
8734418919fSjohnjiang 	sock = rte_zmalloc("memif-socket", sizeof(struct memif_socket), 0);
8744418919fSjohnjiang 	if (sock == NULL) {
8754418919fSjohnjiang 		MIF_LOG(ERR, "Failed to allocate memory for memif socket");
8764418919fSjohnjiang 		return NULL;
8774418919fSjohnjiang 	}
8784418919fSjohnjiang 
8794418919fSjohnjiang 	sock->listener = listener;
8804418919fSjohnjiang 	strlcpy(sock->filename, key, MEMIF_SOCKET_UN_SIZE);
8814418919fSjohnjiang 	TAILQ_INIT(&sock->dev_queue);
8824418919fSjohnjiang 
8834418919fSjohnjiang 	if (listener != 0) {
8844418919fSjohnjiang 		sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
8854418919fSjohnjiang 		if (sockfd < 0)
8864418919fSjohnjiang 			goto error;
8874418919fSjohnjiang 
8884418919fSjohnjiang 		un.sun_family = AF_UNIX;
889*2d9fd380Sjfb8856606 		if (is_abstract) {
890*2d9fd380Sjfb8856606 			/* abstract address */
891*2d9fd380Sjfb8856606 			un.sun_path[0] = '\0';
892*2d9fd380Sjfb8856606 			strlcpy(un.sun_path + 1, sock->filename, MEMIF_SOCKET_UN_SIZE - 1);
893*2d9fd380Sjfb8856606 		} else {
8944418919fSjohnjiang 			strlcpy(un.sun_path, sock->filename, MEMIF_SOCKET_UN_SIZE);
895*2d9fd380Sjfb8856606 		}
8964418919fSjohnjiang 
8974418919fSjohnjiang 		ret = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &on,
8984418919fSjohnjiang 				 sizeof(on));
8994418919fSjohnjiang 		if (ret < 0)
9004418919fSjohnjiang 			goto error;
9014418919fSjohnjiang 
9024418919fSjohnjiang 		ret = bind(sockfd, (struct sockaddr *)&un, sizeof(un));
9034418919fSjohnjiang 		if (ret < 0)
9044418919fSjohnjiang 			goto error;
9054418919fSjohnjiang 
9064418919fSjohnjiang 		ret = listen(sockfd, 1);
9074418919fSjohnjiang 		if (ret < 0)
9084418919fSjohnjiang 			goto error;
9094418919fSjohnjiang 
9104418919fSjohnjiang 		MIF_LOG(DEBUG, "Memif listener socket %s created.", sock->filename);
9114418919fSjohnjiang 
9124418919fSjohnjiang 		sock->intr_handle.fd = sockfd;
9134418919fSjohnjiang 		sock->intr_handle.type = RTE_INTR_HANDLE_EXT;
9144418919fSjohnjiang 		ret = rte_intr_callback_register(&sock->intr_handle,
9154418919fSjohnjiang 						 memif_listener_handler, sock);
9164418919fSjohnjiang 		if (ret < 0) {
9174418919fSjohnjiang 			MIF_LOG(ERR, "Failed to register interrupt "
9184418919fSjohnjiang 				"callback for listener socket");
9194418919fSjohnjiang 			return NULL;
9204418919fSjohnjiang 		}
9214418919fSjohnjiang 	}
9224418919fSjohnjiang 
9234418919fSjohnjiang 	return sock;
9244418919fSjohnjiang 
9254418919fSjohnjiang  error:
9264418919fSjohnjiang 	MIF_LOG(ERR, "Failed to setup socket %s: %s", key, strerror(errno));
9274418919fSjohnjiang 	if (sock != NULL)
9284418919fSjohnjiang 		rte_free(sock);
9294418919fSjohnjiang 	if (sockfd >= 0)
9304418919fSjohnjiang 		close(sockfd);
9314418919fSjohnjiang 	return NULL;
9324418919fSjohnjiang }
9334418919fSjohnjiang 
9344418919fSjohnjiang static struct rte_hash *
memif_create_socket_hash(void)9354418919fSjohnjiang memif_create_socket_hash(void)
9364418919fSjohnjiang {
9374418919fSjohnjiang 	struct rte_hash_parameters params = { 0 };
9384418919fSjohnjiang 
9394418919fSjohnjiang 	params.name = MEMIF_SOCKET_HASH_NAME;
9404418919fSjohnjiang 	params.entries = 256;
9414418919fSjohnjiang 	params.key_len = MEMIF_SOCKET_UN_SIZE;
9424418919fSjohnjiang 	params.hash_func = rte_jhash;
9434418919fSjohnjiang 	params.hash_func_init_val = 0;
9444418919fSjohnjiang 	return rte_hash_create(&params);
9454418919fSjohnjiang }
9464418919fSjohnjiang 
9474418919fSjohnjiang int
memif_socket_init(struct rte_eth_dev * dev,const char * socket_filename)9484418919fSjohnjiang memif_socket_init(struct rte_eth_dev *dev, const char *socket_filename)
9494418919fSjohnjiang {
9504418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
9514418919fSjohnjiang 	struct memif_socket *socket = NULL;
9524418919fSjohnjiang 	struct memif_socket_dev_list_elt *elt;
9534418919fSjohnjiang 	struct pmd_internals *tmp_pmd;
9544418919fSjohnjiang 	struct rte_hash *hash;
9554418919fSjohnjiang 	int ret;
9564418919fSjohnjiang 	char key[MEMIF_SOCKET_UN_SIZE];
9574418919fSjohnjiang 
9584418919fSjohnjiang 	hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME);
9594418919fSjohnjiang 	if (hash == NULL) {
9604418919fSjohnjiang 		hash = memif_create_socket_hash();
9614418919fSjohnjiang 		if (hash == NULL) {
9624418919fSjohnjiang 			MIF_LOG(ERR, "Failed to create memif socket hash.");
9634418919fSjohnjiang 			return -1;
9644418919fSjohnjiang 		}
9654418919fSjohnjiang 	}
9664418919fSjohnjiang 
9674418919fSjohnjiang 	memset(key, 0, MEMIF_SOCKET_UN_SIZE);
9684418919fSjohnjiang 	strlcpy(key, socket_filename, MEMIF_SOCKET_UN_SIZE);
9694418919fSjohnjiang 	ret = rte_hash_lookup_data(hash, key, (void **)&socket);
9704418919fSjohnjiang 	if (ret < 0) {
9714418919fSjohnjiang 		socket = memif_socket_create(key,
972*2d9fd380Sjfb8856606 			(pmd->role == MEMIF_ROLE_CLIENT) ? 0 : 1,
973*2d9fd380Sjfb8856606 			pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT);
9744418919fSjohnjiang 		if (socket == NULL)
9754418919fSjohnjiang 			return -1;
9764418919fSjohnjiang 		ret = rte_hash_add_key_data(hash, key, socket);
9774418919fSjohnjiang 		if (ret < 0) {
9784418919fSjohnjiang 			MIF_LOG(ERR, "Failed to add socket to socket hash.");
9794418919fSjohnjiang 			return ret;
9804418919fSjohnjiang 		}
9814418919fSjohnjiang 	}
9824418919fSjohnjiang 	pmd->socket_filename = socket->filename;
9834418919fSjohnjiang 
9844418919fSjohnjiang 	TAILQ_FOREACH(elt, &socket->dev_queue, next) {
9854418919fSjohnjiang 		tmp_pmd = elt->dev->data->dev_private;
986*2d9fd380Sjfb8856606 		if (tmp_pmd->id == pmd->id && tmp_pmd->role == pmd->role) {
987*2d9fd380Sjfb8856606 			MIF_LOG(ERR, "Two interfaces with the same id (%d) can "
988*2d9fd380Sjfb8856606 				"not have the same role.", pmd->id);
9894418919fSjohnjiang 			return -1;
9904418919fSjohnjiang 		}
9914418919fSjohnjiang 	}
9924418919fSjohnjiang 
9934418919fSjohnjiang 	elt = rte_malloc("pmd-queue", sizeof(struct memif_socket_dev_list_elt), 0);
9944418919fSjohnjiang 	if (elt == NULL) {
9954418919fSjohnjiang 		MIF_LOG(ERR, "Failed to add device to socket device list.");
9964418919fSjohnjiang 		return -1;
9974418919fSjohnjiang 	}
9984418919fSjohnjiang 	elt->dev = dev;
9994418919fSjohnjiang 	TAILQ_INSERT_TAIL(&socket->dev_queue, elt, next);
10004418919fSjohnjiang 
10014418919fSjohnjiang 	return 0;
10024418919fSjohnjiang }
10034418919fSjohnjiang 
10044418919fSjohnjiang void
memif_socket_remove_device(struct rte_eth_dev * dev)10054418919fSjohnjiang memif_socket_remove_device(struct rte_eth_dev *dev)
10064418919fSjohnjiang {
10074418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
10084418919fSjohnjiang 	struct memif_socket *socket = NULL;
10094418919fSjohnjiang 	struct memif_socket_dev_list_elt *elt, *next;
10104418919fSjohnjiang 	struct rte_hash *hash;
10114418919fSjohnjiang 	int ret;
10124418919fSjohnjiang 
10134418919fSjohnjiang 	hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME);
10144418919fSjohnjiang 	if (hash == NULL)
10154418919fSjohnjiang 		return;
10164418919fSjohnjiang 
10174418919fSjohnjiang 	if (pmd->socket_filename == NULL)
10184418919fSjohnjiang 		return;
10194418919fSjohnjiang 
10204418919fSjohnjiang 	if (rte_hash_lookup_data(hash, pmd->socket_filename, (void **)&socket) < 0)
10214418919fSjohnjiang 		return;
10224418919fSjohnjiang 
10234418919fSjohnjiang 	for (elt = TAILQ_FIRST(&socket->dev_queue); elt != NULL; elt = next) {
10244418919fSjohnjiang 		next = TAILQ_NEXT(elt, next);
10254418919fSjohnjiang 		if (elt->dev == dev) {
10264418919fSjohnjiang 			TAILQ_REMOVE(&socket->dev_queue, elt, next);
10274418919fSjohnjiang 			rte_free(elt);
10284418919fSjohnjiang 			pmd->socket_filename = NULL;
10294418919fSjohnjiang 		}
10304418919fSjohnjiang 	}
10314418919fSjohnjiang 
10324418919fSjohnjiang 	/* remove socket, if this was the last device using it */
10334418919fSjohnjiang 	if (TAILQ_EMPTY(&socket->dev_queue)) {
10344418919fSjohnjiang 		rte_hash_del_key(hash, socket->filename);
1035*2d9fd380Sjfb8856606 		if (socket->listener && !(pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT)) {
10364418919fSjohnjiang 			/* remove listener socket file,
10374418919fSjohnjiang 			 * so we can create new one later.
10384418919fSjohnjiang 			 */
10394418919fSjohnjiang 			ret = remove(socket->filename);
10404418919fSjohnjiang 			if (ret < 0)
10414418919fSjohnjiang 				MIF_LOG(ERR, "Failed to remove socket file: %s",
10424418919fSjohnjiang 					socket->filename);
10434418919fSjohnjiang 		}
10444418919fSjohnjiang 		rte_free(socket);
10454418919fSjohnjiang 	}
10464418919fSjohnjiang }
10474418919fSjohnjiang 
10484418919fSjohnjiang int
memif_connect_server(struct rte_eth_dev * dev)1049*2d9fd380Sjfb8856606 memif_connect_server(struct rte_eth_dev *dev)
10504418919fSjohnjiang {
10514418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
10524418919fSjohnjiang 
10534418919fSjohnjiang 	memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE);
10544418919fSjohnjiang 	memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE);
10554418919fSjohnjiang 	pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED;
10564418919fSjohnjiang 	return 0;
10574418919fSjohnjiang }
10584418919fSjohnjiang 
10594418919fSjohnjiang int
memif_connect_client(struct rte_eth_dev * dev)1060*2d9fd380Sjfb8856606 memif_connect_client(struct rte_eth_dev *dev)
10614418919fSjohnjiang {
10624418919fSjohnjiang 	int sockfd;
10634418919fSjohnjiang 	int ret;
1064*2d9fd380Sjfb8856606 	struct sockaddr_un sun = { 0 };
10654418919fSjohnjiang 	struct pmd_internals *pmd = dev->data->dev_private;
10664418919fSjohnjiang 
10674418919fSjohnjiang 	memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE);
10684418919fSjohnjiang 	memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE);
10694418919fSjohnjiang 	pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED;
10704418919fSjohnjiang 
10714418919fSjohnjiang 	sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
10724418919fSjohnjiang 	if (sockfd < 0) {
10734418919fSjohnjiang 		MIF_LOG(ERR, "Failed to open socket.");
10744418919fSjohnjiang 		return -1;
10754418919fSjohnjiang 	}
10764418919fSjohnjiang 
10774418919fSjohnjiang 	sun.sun_family = AF_UNIX;
1078*2d9fd380Sjfb8856606 	if (pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT) {
1079*2d9fd380Sjfb8856606 		/* abstract address */
1080*2d9fd380Sjfb8856606 		sun.sun_path[0] = '\0';
1081*2d9fd380Sjfb8856606 		strlcpy(sun.sun_path + 1,  pmd->socket_filename, MEMIF_SOCKET_UN_SIZE - 1);
1082*2d9fd380Sjfb8856606 	} else {
1083*2d9fd380Sjfb8856606 		strlcpy(sun.sun_path,  pmd->socket_filename, MEMIF_SOCKET_UN_SIZE);
1084*2d9fd380Sjfb8856606 	}
10854418919fSjohnjiang 
10864418919fSjohnjiang 	ret = connect(sockfd, (struct sockaddr *)&sun,
10874418919fSjohnjiang 		      sizeof(struct sockaddr_un));
10884418919fSjohnjiang 	if (ret < 0) {
10894418919fSjohnjiang 		MIF_LOG(ERR, "Failed to connect socket: %s.", pmd->socket_filename);
10904418919fSjohnjiang 		goto error;
10914418919fSjohnjiang 	}
10924418919fSjohnjiang 
10934418919fSjohnjiang 	MIF_LOG(DEBUG, "Memif socket: %s connected.", pmd->socket_filename);
10944418919fSjohnjiang 
10954418919fSjohnjiang 	pmd->cc = rte_zmalloc("memif-cc",
10964418919fSjohnjiang 			      sizeof(struct memif_control_channel), 0);
10974418919fSjohnjiang 	if (pmd->cc == NULL) {
10984418919fSjohnjiang 		MIF_LOG(ERR, "Failed to allocate control channel.");
10994418919fSjohnjiang 		goto error;
11004418919fSjohnjiang 	}
11014418919fSjohnjiang 
11024418919fSjohnjiang 	pmd->cc->intr_handle.fd = sockfd;
11034418919fSjohnjiang 	pmd->cc->intr_handle.type = RTE_INTR_HANDLE_EXT;
11044418919fSjohnjiang 	pmd->cc->socket = NULL;
11054418919fSjohnjiang 	pmd->cc->dev = dev;
11064418919fSjohnjiang 	TAILQ_INIT(&pmd->cc->msg_queue);
11074418919fSjohnjiang 
11084418919fSjohnjiang 	ret = rte_intr_callback_register(&pmd->cc->intr_handle,
11094418919fSjohnjiang 					 memif_intr_handler, pmd->cc);
11104418919fSjohnjiang 	if (ret < 0) {
11114418919fSjohnjiang 		MIF_LOG(ERR, "Failed to register interrupt callback for control fd");
11124418919fSjohnjiang 		goto error;
11134418919fSjohnjiang 	}
11144418919fSjohnjiang 
11154418919fSjohnjiang 	return 0;
11164418919fSjohnjiang 
11174418919fSjohnjiang  error:
11184418919fSjohnjiang 	if (sockfd >= 0) {
11194418919fSjohnjiang 		close(sockfd);
11204418919fSjohnjiang 		sockfd = -1;
11214418919fSjohnjiang 	}
11224418919fSjohnjiang 	if (pmd->cc != NULL) {
11234418919fSjohnjiang 		rte_free(pmd->cc);
11244418919fSjohnjiang 		pmd->cc = NULL;
11254418919fSjohnjiang 	}
11264418919fSjohnjiang 	return -1;
11274418919fSjohnjiang }
1128