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/ioctl.h> 1109c7e63aSJakub Grajciar #include <errno.h> 1209c7e63aSJakub Grajciar 1309c7e63aSJakub Grajciar #include <rte_version.h> 1409c7e63aSJakub Grajciar #include <rte_mbuf.h> 1509c7e63aSJakub Grajciar #include <rte_ether.h> 16df96fd0dSBruce Richardson #include <ethdev_driver.h> 17df96fd0dSBruce Richardson #include <ethdev_vdev.h> 1809c7e63aSJakub Grajciar #include <rte_malloc.h> 1909c7e63aSJakub Grajciar #include <rte_kvargs.h> 2009c7e63aSJakub Grajciar #include <rte_bus_vdev.h> 2109c7e63aSJakub Grajciar #include <rte_hash.h> 2209c7e63aSJakub Grajciar #include <rte_jhash.h> 2309c7e63aSJakub Grajciar #include <rte_string_fns.h> 2409c7e63aSJakub Grajciar 2509c7e63aSJakub Grajciar #include "rte_eth_memif.h" 2609c7e63aSJakub Grajciar #include "memif_socket.h" 2709c7e63aSJakub Grajciar 2809c7e63aSJakub Grajciar static void memif_intr_handler(void *arg); 2909c7e63aSJakub Grajciar 3009c7e63aSJakub Grajciar static ssize_t 3109c7e63aSJakub Grajciar memif_msg_send(int fd, memif_msg_t *msg, int afd) 3209c7e63aSJakub Grajciar { 3309c7e63aSJakub Grajciar struct msghdr mh = { 0 }; 3409c7e63aSJakub Grajciar struct iovec iov[1]; 3509c7e63aSJakub Grajciar struct cmsghdr *cmsg; 3609c7e63aSJakub Grajciar char ctl[CMSG_SPACE(sizeof(int))]; 3709c7e63aSJakub Grajciar 3809c7e63aSJakub Grajciar iov[0].iov_base = msg; 3909c7e63aSJakub Grajciar iov[0].iov_len = sizeof(memif_msg_t); 4009c7e63aSJakub Grajciar mh.msg_iov = iov; 4109c7e63aSJakub Grajciar mh.msg_iovlen = 1; 4209c7e63aSJakub Grajciar 4309c7e63aSJakub Grajciar if (afd > 0) { 4409c7e63aSJakub Grajciar memset(&ctl, 0, sizeof(ctl)); 4509c7e63aSJakub Grajciar mh.msg_control = ctl; 4609c7e63aSJakub Grajciar mh.msg_controllen = sizeof(ctl); 4709c7e63aSJakub Grajciar cmsg = CMSG_FIRSTHDR(&mh); 4809c7e63aSJakub Grajciar cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 4909c7e63aSJakub Grajciar cmsg->cmsg_level = SOL_SOCKET; 5009c7e63aSJakub Grajciar cmsg->cmsg_type = SCM_RIGHTS; 5109c7e63aSJakub Grajciar rte_memcpy(CMSG_DATA(cmsg), &afd, sizeof(int)); 5209c7e63aSJakub Grajciar } 5309c7e63aSJakub Grajciar 5409c7e63aSJakub Grajciar return sendmsg(fd, &mh, 0); 5509c7e63aSJakub Grajciar } 5609c7e63aSJakub Grajciar 5709c7e63aSJakub Grajciar static int 5809c7e63aSJakub Grajciar memif_msg_send_from_queue(struct memif_control_channel *cc) 5909c7e63aSJakub Grajciar { 6009c7e63aSJakub Grajciar ssize_t size; 6109c7e63aSJakub Grajciar int ret = 0; 6209c7e63aSJakub Grajciar struct memif_msg_queue_elt *e; 6309c7e63aSJakub Grajciar 6409c7e63aSJakub Grajciar e = TAILQ_FIRST(&cc->msg_queue); 6509c7e63aSJakub Grajciar if (e == NULL) 6609c7e63aSJakub Grajciar return 0; 6709c7e63aSJakub Grajciar 68*d61138d4SHarman Kalra size = memif_msg_send(rte_intr_fd_get(cc->intr_handle), &e->msg, 69*d61138d4SHarman Kalra e->fd); 7009c7e63aSJakub Grajciar if (size != sizeof(memif_msg_t)) { 7109c7e63aSJakub Grajciar MIF_LOG(ERR, "sendmsg fail: %s.", strerror(errno)); 7209c7e63aSJakub Grajciar ret = -1; 7309c7e63aSJakub Grajciar } else { 7409c7e63aSJakub Grajciar MIF_LOG(DEBUG, "Sent msg type %u.", e->msg.type); 7509c7e63aSJakub Grajciar } 7609c7e63aSJakub Grajciar TAILQ_REMOVE(&cc->msg_queue, e, next); 7709c7e63aSJakub Grajciar rte_free(e); 7809c7e63aSJakub Grajciar 7909c7e63aSJakub Grajciar return ret; 8009c7e63aSJakub Grajciar } 8109c7e63aSJakub Grajciar 8209c7e63aSJakub Grajciar static struct memif_msg_queue_elt * 8309c7e63aSJakub Grajciar memif_msg_enq(struct memif_control_channel *cc) 8409c7e63aSJakub Grajciar { 8509c7e63aSJakub Grajciar struct memif_msg_queue_elt *e; 8609c7e63aSJakub Grajciar 8709c7e63aSJakub Grajciar e = rte_zmalloc("memif_msg", sizeof(struct memif_msg_queue_elt), 0); 8809c7e63aSJakub Grajciar if (e == NULL) { 8909c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to allocate control message."); 9009c7e63aSJakub Grajciar return NULL; 9109c7e63aSJakub Grajciar } 9209c7e63aSJakub Grajciar 9309c7e63aSJakub Grajciar e->fd = -1; 9409c7e63aSJakub Grajciar TAILQ_INSERT_TAIL(&cc->msg_queue, e, next); 9509c7e63aSJakub Grajciar 9609c7e63aSJakub Grajciar return e; 9709c7e63aSJakub Grajciar } 9809c7e63aSJakub Grajciar 9909c7e63aSJakub Grajciar void 10009c7e63aSJakub Grajciar memif_msg_enq_disconnect(struct memif_control_channel *cc, const char *reason, 10109c7e63aSJakub Grajciar int err_code) 10209c7e63aSJakub Grajciar { 10309c7e63aSJakub Grajciar struct memif_msg_queue_elt *e; 10409c7e63aSJakub Grajciar struct pmd_internals *pmd; 10509c7e63aSJakub Grajciar memif_msg_disconnect_t *d; 10609c7e63aSJakub Grajciar 10709c7e63aSJakub Grajciar if (cc == NULL) { 10809c7e63aSJakub Grajciar MIF_LOG(DEBUG, "Missing control channel."); 10909c7e63aSJakub Grajciar return; 11009c7e63aSJakub Grajciar } 11109c7e63aSJakub Grajciar 11209c7e63aSJakub Grajciar e = memif_msg_enq(cc); 11309c7e63aSJakub Grajciar if (e == NULL) { 11409c7e63aSJakub Grajciar MIF_LOG(WARNING, "Failed to enqueue disconnect message."); 11509c7e63aSJakub Grajciar return; 11609c7e63aSJakub Grajciar } 11709c7e63aSJakub Grajciar 11809c7e63aSJakub Grajciar d = &e->msg.disconnect; 11909c7e63aSJakub Grajciar 12009c7e63aSJakub Grajciar e->msg.type = MEMIF_MSG_TYPE_DISCONNECT; 12109c7e63aSJakub Grajciar d->code = err_code; 12209c7e63aSJakub Grajciar 12309c7e63aSJakub Grajciar if (reason != NULL) { 12409c7e63aSJakub Grajciar strlcpy((char *)d->string, reason, sizeof(d->string)); 12509c7e63aSJakub Grajciar if (cc->dev != NULL) { 12609c7e63aSJakub Grajciar pmd = cc->dev->data->dev_private; 12709c7e63aSJakub Grajciar strlcpy(pmd->local_disc_string, reason, 12809c7e63aSJakub Grajciar sizeof(pmd->local_disc_string)); 12909c7e63aSJakub Grajciar } 13009c7e63aSJakub Grajciar } 13109c7e63aSJakub Grajciar } 13209c7e63aSJakub Grajciar 13309c7e63aSJakub Grajciar static int 13409c7e63aSJakub Grajciar memif_msg_enq_hello(struct memif_control_channel *cc) 13509c7e63aSJakub Grajciar { 13609c7e63aSJakub Grajciar struct memif_msg_queue_elt *e = memif_msg_enq(cc); 13709c7e63aSJakub Grajciar memif_msg_hello_t *h; 13809c7e63aSJakub Grajciar 13909c7e63aSJakub Grajciar if (e == NULL) 14009c7e63aSJakub Grajciar return -1; 14109c7e63aSJakub Grajciar 14209c7e63aSJakub Grajciar h = &e->msg.hello; 14309c7e63aSJakub Grajciar 14409c7e63aSJakub Grajciar e->msg.type = MEMIF_MSG_TYPE_HELLO; 14509c7e63aSJakub Grajciar h->min_version = MEMIF_VERSION; 14609c7e63aSJakub Grajciar h->max_version = MEMIF_VERSION; 147d250589dSStephen Hemminger h->max_c2s_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS; 148d250589dSStephen Hemminger h->max_s2c_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS; 14909c7e63aSJakub Grajciar h->max_region = ETH_MEMIF_MAX_REGION_NUM - 1; 15009c7e63aSJakub Grajciar h->max_log2_ring_size = ETH_MEMIF_MAX_LOG2_RING_SIZE; 15109c7e63aSJakub Grajciar 15209c7e63aSJakub Grajciar strlcpy((char *)h->name, rte_version(), sizeof(h->name)); 15309c7e63aSJakub Grajciar 15409c7e63aSJakub Grajciar return 0; 15509c7e63aSJakub Grajciar } 15609c7e63aSJakub Grajciar 15709c7e63aSJakub Grajciar static int 15809c7e63aSJakub Grajciar memif_msg_receive_hello(struct rte_eth_dev *dev, memif_msg_t *msg) 15909c7e63aSJakub Grajciar { 16009c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 16109c7e63aSJakub Grajciar memif_msg_hello_t *h = &msg->hello; 16209c7e63aSJakub Grajciar 16309c7e63aSJakub Grajciar if (h->min_version > MEMIF_VERSION || h->max_version < MEMIF_VERSION) { 16409c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, "Incompatible memif version", 0); 16509c7e63aSJakub Grajciar return -1; 16609c7e63aSJakub Grajciar } 16709c7e63aSJakub Grajciar 16809c7e63aSJakub Grajciar /* Set parameters for active connection */ 169d250589dSStephen Hemminger pmd->run.num_c2s_rings = RTE_MIN(h->max_c2s_ring + 1, 170d250589dSStephen Hemminger pmd->cfg.num_c2s_rings); 171d250589dSStephen Hemminger pmd->run.num_s2c_rings = RTE_MIN(h->max_s2c_ring + 1, 172d250589dSStephen Hemminger pmd->cfg.num_s2c_rings); 17309c7e63aSJakub Grajciar pmd->run.log2_ring_size = RTE_MIN(h->max_log2_ring_size, 17409c7e63aSJakub Grajciar pmd->cfg.log2_ring_size); 17509c7e63aSJakub Grajciar pmd->run.pkt_buffer_size = pmd->cfg.pkt_buffer_size; 17609c7e63aSJakub Grajciar 17709c7e63aSJakub Grajciar strlcpy(pmd->remote_name, (char *)h->name, sizeof(pmd->remote_name)); 17809c7e63aSJakub Grajciar 17943b815d8SJakub Grajciar MIF_LOG(DEBUG, "Connecting to %s.", pmd->remote_name); 18009c7e63aSJakub Grajciar 18109c7e63aSJakub Grajciar return 0; 18209c7e63aSJakub Grajciar } 18309c7e63aSJakub Grajciar 18409c7e63aSJakub Grajciar static int 18509c7e63aSJakub Grajciar memif_msg_receive_init(struct memif_control_channel *cc, memif_msg_t *msg) 18609c7e63aSJakub Grajciar { 18709c7e63aSJakub Grajciar memif_msg_init_t *i = &msg->init; 18809c7e63aSJakub Grajciar struct memif_socket_dev_list_elt *elt; 18909c7e63aSJakub Grajciar struct pmd_internals *pmd; 19009c7e63aSJakub Grajciar struct rte_eth_dev *dev; 19109c7e63aSJakub Grajciar 19209c7e63aSJakub Grajciar if (i->version != MEMIF_VERSION) { 19309c7e63aSJakub Grajciar memif_msg_enq_disconnect(cc, "Incompatible memif version", 0); 19409c7e63aSJakub Grajciar return -1; 19509c7e63aSJakub Grajciar } 19609c7e63aSJakub Grajciar 19709c7e63aSJakub Grajciar if (cc->socket == NULL) { 19809c7e63aSJakub Grajciar memif_msg_enq_disconnect(cc, "Device error", 0); 19909c7e63aSJakub Grajciar return -1; 20009c7e63aSJakub Grajciar } 20109c7e63aSJakub Grajciar 20209c7e63aSJakub Grajciar /* Find device with requested ID */ 20309c7e63aSJakub Grajciar TAILQ_FOREACH(elt, &cc->socket->dev_queue, next) { 20409c7e63aSJakub Grajciar dev = elt->dev; 20509c7e63aSJakub Grajciar pmd = dev->data->dev_private; 20609c7e63aSJakub Grajciar if (((pmd->flags & ETH_MEMIF_FLAG_DISABLED) == 0) && 207d250589dSStephen Hemminger (pmd->id == i->id) && (pmd->role == MEMIF_ROLE_SERVER)) { 20806123fddSJúlius Milan if (pmd->flags & (ETH_MEMIF_FLAG_CONNECTING | 20906123fddSJúlius Milan ETH_MEMIF_FLAG_CONNECTED)) { 21006123fddSJúlius Milan memif_msg_enq_disconnect(cc, 21106123fddSJúlius Milan "Already connected", 0); 21206123fddSJúlius Milan return -1; 21306123fddSJúlius Milan } 21406123fddSJúlius Milan 21509c7e63aSJakub Grajciar /* assign control channel to device */ 21609c7e63aSJakub Grajciar cc->dev = dev; 21709c7e63aSJakub Grajciar pmd->cc = cc; 21809c7e63aSJakub Grajciar 21909c7e63aSJakub Grajciar if (i->mode != MEMIF_INTERFACE_MODE_ETHERNET) { 22009c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, 22109c7e63aSJakub Grajciar "Only ethernet mode supported", 22209c7e63aSJakub Grajciar 0); 22309c7e63aSJakub Grajciar return -1; 22409c7e63aSJakub Grajciar } 22509c7e63aSJakub Grajciar 22609c7e63aSJakub Grajciar strlcpy(pmd->remote_name, (char *)i->name, 22709c7e63aSJakub Grajciar sizeof(pmd->remote_name)); 22809c7e63aSJakub Grajciar 22909c7e63aSJakub Grajciar if (*pmd->secret != '\0') { 23009c7e63aSJakub Grajciar if (*i->secret == '\0') { 23109c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, 23209c7e63aSJakub Grajciar "Secret required", 0); 23309c7e63aSJakub Grajciar return -1; 23409c7e63aSJakub Grajciar } 23509c7e63aSJakub Grajciar if (strncmp(pmd->secret, (char *)i->secret, 23609c7e63aSJakub Grajciar ETH_MEMIF_SECRET_SIZE) != 0) { 23709c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, 23809c7e63aSJakub Grajciar "Incorrect secret", 0); 23909c7e63aSJakub Grajciar return -1; 24009c7e63aSJakub Grajciar } 24109c7e63aSJakub Grajciar } 24209c7e63aSJakub Grajciar 24309c7e63aSJakub Grajciar pmd->flags |= ETH_MEMIF_FLAG_CONNECTING; 24409c7e63aSJakub Grajciar return 0; 24509c7e63aSJakub Grajciar } 24609c7e63aSJakub Grajciar } 24709c7e63aSJakub Grajciar 24809c7e63aSJakub Grajciar /* ID not found on this socket */ 24909c7e63aSJakub Grajciar MIF_LOG(DEBUG, "ID %u not found.", i->id); 25009c7e63aSJakub Grajciar memif_msg_enq_disconnect(cc, "ID not found", 0); 25109c7e63aSJakub Grajciar return -1; 25209c7e63aSJakub Grajciar } 25309c7e63aSJakub Grajciar 25409c7e63aSJakub Grajciar static int 25509c7e63aSJakub Grajciar memif_msg_receive_add_region(struct rte_eth_dev *dev, memif_msg_t *msg, 25609c7e63aSJakub Grajciar int fd) 25709c7e63aSJakub Grajciar { 25809c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 259c41a0495SJakub Grajciar struct pmd_process_private *proc_private = dev->process_private; 26009c7e63aSJakub Grajciar memif_msg_add_region_t *ar = &msg->add_region; 26109c7e63aSJakub Grajciar struct memif_region *r; 26209c7e63aSJakub Grajciar 26309c7e63aSJakub Grajciar if (fd < 0) { 26409c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, "Missing region fd", 0); 26509c7e63aSJakub Grajciar return -1; 26609c7e63aSJakub Grajciar } 26709c7e63aSJakub Grajciar 268c41a0495SJakub Grajciar if (ar->index >= ETH_MEMIF_MAX_REGION_NUM || 269c41a0495SJakub Grajciar ar->index != proc_private->regions_num || 270c41a0495SJakub Grajciar proc_private->regions[ar->index] != NULL) { 27109c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, "Invalid region index", 0); 27209c7e63aSJakub Grajciar return -1; 27309c7e63aSJakub Grajciar } 27409c7e63aSJakub Grajciar 27509c7e63aSJakub Grajciar r = rte_zmalloc("region", sizeof(struct memif_region), 0); 27609c7e63aSJakub Grajciar if (r == NULL) { 277c41a0495SJakub Grajciar memif_msg_enq_disconnect(pmd->cc, "Failed to alloc memif region.", 0); 27809c7e63aSJakub Grajciar return -ENOMEM; 27909c7e63aSJakub Grajciar } 28009c7e63aSJakub Grajciar 28109c7e63aSJakub Grajciar r->fd = fd; 28209c7e63aSJakub Grajciar r->region_size = ar->size; 28309c7e63aSJakub Grajciar r->addr = NULL; 28409c7e63aSJakub Grajciar 285c41a0495SJakub Grajciar proc_private->regions[ar->index] = r; 286c41a0495SJakub Grajciar proc_private->regions_num++; 28709c7e63aSJakub Grajciar 28809c7e63aSJakub Grajciar return 0; 28909c7e63aSJakub Grajciar } 29009c7e63aSJakub Grajciar 29109c7e63aSJakub Grajciar static int 29209c7e63aSJakub Grajciar memif_msg_receive_add_ring(struct rte_eth_dev *dev, memif_msg_t *msg, int fd) 29309c7e63aSJakub Grajciar { 29409c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 29509c7e63aSJakub Grajciar memif_msg_add_ring_t *ar = &msg->add_ring; 29609c7e63aSJakub Grajciar struct memif_queue *mq; 29709c7e63aSJakub Grajciar 29809c7e63aSJakub Grajciar if (fd < 0) { 29909c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, "Missing interrupt fd", 0); 30009c7e63aSJakub Grajciar return -1; 30109c7e63aSJakub Grajciar } 30209c7e63aSJakub Grajciar 30309c7e63aSJakub Grajciar /* check if we have enough queues */ 304d250589dSStephen Hemminger if (ar->flags & MEMIF_MSG_ADD_RING_FLAG_C2S) { 305d250589dSStephen Hemminger if (ar->index >= pmd->cfg.num_c2s_rings) { 30609c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0); 30709c7e63aSJakub Grajciar return -1; 30809c7e63aSJakub Grajciar } 309d250589dSStephen Hemminger pmd->run.num_c2s_rings++; 31009c7e63aSJakub Grajciar } else { 311d250589dSStephen Hemminger if (ar->index >= pmd->cfg.num_s2c_rings) { 31209c7e63aSJakub Grajciar memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0); 31309c7e63aSJakub Grajciar return -1; 31409c7e63aSJakub Grajciar } 315d250589dSStephen Hemminger pmd->run.num_s2c_rings++; 31609c7e63aSJakub Grajciar } 31709c7e63aSJakub Grajciar 318d250589dSStephen Hemminger mq = (ar->flags & MEMIF_MSG_ADD_RING_FLAG_C2S) ? 31909c7e63aSJakub Grajciar dev->data->rx_queues[ar->index] : dev->data->tx_queues[ar->index]; 32009c7e63aSJakub Grajciar 321*d61138d4SHarman Kalra if (rte_intr_fd_set(mq->intr_handle, fd)) 322*d61138d4SHarman Kalra return -1; 323*d61138d4SHarman Kalra 32409c7e63aSJakub Grajciar mq->log2_ring_size = ar->log2_ring_size; 32509c7e63aSJakub Grajciar mq->region = ar->region; 32609c7e63aSJakub Grajciar mq->ring_offset = ar->offset; 32709c7e63aSJakub Grajciar 32809c7e63aSJakub Grajciar return 0; 32909c7e63aSJakub Grajciar } 33009c7e63aSJakub Grajciar 33109c7e63aSJakub Grajciar static int 33209c7e63aSJakub Grajciar memif_msg_receive_connect(struct rte_eth_dev *dev, memif_msg_t *msg) 33309c7e63aSJakub Grajciar { 33409c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 33509c7e63aSJakub Grajciar memif_msg_connect_t *c = &msg->connect; 33609c7e63aSJakub Grajciar int ret; 33709c7e63aSJakub Grajciar 33809c7e63aSJakub Grajciar ret = memif_connect(dev); 33909c7e63aSJakub Grajciar if (ret < 0) 34009c7e63aSJakub Grajciar return ret; 34109c7e63aSJakub Grajciar 34209c7e63aSJakub Grajciar strlcpy(pmd->remote_if_name, (char *)c->if_name, 34309c7e63aSJakub Grajciar sizeof(pmd->remote_if_name)); 34443b815d8SJakub Grajciar MIF_LOG(INFO, "Remote interface %s connected.", pmd->remote_if_name); 34509c7e63aSJakub Grajciar 34609c7e63aSJakub Grajciar return 0; 34709c7e63aSJakub Grajciar } 34809c7e63aSJakub Grajciar 34909c7e63aSJakub Grajciar static int 35009c7e63aSJakub Grajciar memif_msg_receive_connected(struct rte_eth_dev *dev, memif_msg_t *msg) 35109c7e63aSJakub Grajciar { 35209c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 35309c7e63aSJakub Grajciar memif_msg_connected_t *c = &msg->connected; 35409c7e63aSJakub Grajciar int ret; 35509c7e63aSJakub Grajciar 35609c7e63aSJakub Grajciar ret = memif_connect(dev); 35709c7e63aSJakub Grajciar if (ret < 0) 35809c7e63aSJakub Grajciar return ret; 35909c7e63aSJakub Grajciar 36009c7e63aSJakub Grajciar strlcpy(pmd->remote_if_name, (char *)c->if_name, 36109c7e63aSJakub Grajciar sizeof(pmd->remote_if_name)); 36243b815d8SJakub Grajciar MIF_LOG(INFO, "Remote interface %s connected.", pmd->remote_if_name); 36309c7e63aSJakub Grajciar 36409c7e63aSJakub Grajciar return 0; 36509c7e63aSJakub Grajciar } 36609c7e63aSJakub Grajciar 36709c7e63aSJakub Grajciar static int 36809c7e63aSJakub Grajciar memif_msg_receive_disconnect(struct rte_eth_dev *dev, memif_msg_t *msg) 36909c7e63aSJakub Grajciar { 37009c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 37109c7e63aSJakub Grajciar memif_msg_disconnect_t *d = &msg->disconnect; 37209c7e63aSJakub Grajciar 37343b815d8SJakub Grajciar memset(pmd->remote_disc_string, 0, sizeof(pmd->remote_disc_string)); 37409c7e63aSJakub Grajciar strlcpy(pmd->remote_disc_string, (char *)d->string, 37509c7e63aSJakub Grajciar sizeof(pmd->remote_disc_string)); 37609c7e63aSJakub Grajciar 37743b815d8SJakub Grajciar MIF_LOG(INFO, "Disconnect received: %s", pmd->remote_disc_string); 37809c7e63aSJakub Grajciar 37943b815d8SJakub Grajciar memset(pmd->local_disc_string, 0, 96); 380c41a0495SJakub Grajciar memif_disconnect(dev); 38109c7e63aSJakub Grajciar return 0; 38209c7e63aSJakub Grajciar } 38309c7e63aSJakub Grajciar 38409c7e63aSJakub Grajciar static int 38509c7e63aSJakub Grajciar memif_msg_enq_ack(struct rte_eth_dev *dev) 38609c7e63aSJakub Grajciar { 38709c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 38809c7e63aSJakub Grajciar struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 38909c7e63aSJakub Grajciar if (e == NULL) 39009c7e63aSJakub Grajciar return -1; 39109c7e63aSJakub Grajciar 39209c7e63aSJakub Grajciar e->msg.type = MEMIF_MSG_TYPE_ACK; 39309c7e63aSJakub Grajciar 39409c7e63aSJakub Grajciar return 0; 39509c7e63aSJakub Grajciar } 39609c7e63aSJakub Grajciar 39709c7e63aSJakub Grajciar static int 39809c7e63aSJakub Grajciar memif_msg_enq_init(struct rte_eth_dev *dev) 39909c7e63aSJakub Grajciar { 40009c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 40109c7e63aSJakub Grajciar struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 40209c7e63aSJakub Grajciar memif_msg_init_t *i = &e->msg.init; 40309c7e63aSJakub Grajciar 40409c7e63aSJakub Grajciar if (e == NULL) 40509c7e63aSJakub Grajciar return -1; 40609c7e63aSJakub Grajciar 40709c7e63aSJakub Grajciar i = &e->msg.init; 40809c7e63aSJakub Grajciar e->msg.type = MEMIF_MSG_TYPE_INIT; 40909c7e63aSJakub Grajciar i->version = MEMIF_VERSION; 41009c7e63aSJakub Grajciar i->id = pmd->id; 41109c7e63aSJakub Grajciar i->mode = MEMIF_INTERFACE_MODE_ETHERNET; 41209c7e63aSJakub Grajciar 41309c7e63aSJakub Grajciar strlcpy((char *)i->name, rte_version(), sizeof(i->name)); 41409c7e63aSJakub Grajciar 41509c7e63aSJakub Grajciar if (*pmd->secret != '\0') 41609c7e63aSJakub Grajciar strlcpy((char *)i->secret, pmd->secret, sizeof(i->secret)); 41709c7e63aSJakub Grajciar 41809c7e63aSJakub Grajciar return 0; 41909c7e63aSJakub Grajciar } 42009c7e63aSJakub Grajciar 42109c7e63aSJakub Grajciar static int 42209c7e63aSJakub Grajciar memif_msg_enq_add_region(struct rte_eth_dev *dev, uint8_t idx) 42309c7e63aSJakub Grajciar { 42409c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 425c41a0495SJakub Grajciar struct pmd_process_private *proc_private = dev->process_private; 42609c7e63aSJakub Grajciar struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 42709c7e63aSJakub Grajciar memif_msg_add_region_t *ar; 428c41a0495SJakub Grajciar struct memif_region *mr = proc_private->regions[idx]; 42909c7e63aSJakub Grajciar 43009c7e63aSJakub Grajciar if (e == NULL) 43109c7e63aSJakub Grajciar return -1; 43209c7e63aSJakub Grajciar 43309c7e63aSJakub Grajciar ar = &e->msg.add_region; 43409c7e63aSJakub Grajciar e->msg.type = MEMIF_MSG_TYPE_ADD_REGION; 43509c7e63aSJakub Grajciar e->fd = mr->fd; 43609c7e63aSJakub Grajciar ar->index = idx; 43709c7e63aSJakub Grajciar ar->size = mr->region_size; 43809c7e63aSJakub Grajciar 43909c7e63aSJakub Grajciar return 0; 44009c7e63aSJakub Grajciar } 44109c7e63aSJakub Grajciar 44209c7e63aSJakub Grajciar static int 44309c7e63aSJakub Grajciar memif_msg_enq_add_ring(struct rte_eth_dev *dev, uint8_t idx, 44409c7e63aSJakub Grajciar memif_ring_type_t type) 44509c7e63aSJakub Grajciar { 44609c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 44709c7e63aSJakub Grajciar struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 44809c7e63aSJakub Grajciar struct memif_queue *mq; 44909c7e63aSJakub Grajciar memif_msg_add_ring_t *ar; 45009c7e63aSJakub Grajciar 45109c7e63aSJakub Grajciar if (e == NULL) 45209c7e63aSJakub Grajciar return -1; 45309c7e63aSJakub Grajciar 45409c7e63aSJakub Grajciar ar = &e->msg.add_ring; 455d250589dSStephen Hemminger mq = (type == MEMIF_RING_C2S) ? dev->data->tx_queues[idx] : 45609c7e63aSJakub Grajciar dev->data->rx_queues[idx]; 45709c7e63aSJakub Grajciar 45809c7e63aSJakub Grajciar e->msg.type = MEMIF_MSG_TYPE_ADD_RING; 459*d61138d4SHarman Kalra e->fd = rte_intr_fd_get(mq->intr_handle); 46009c7e63aSJakub Grajciar ar->index = idx; 46109c7e63aSJakub Grajciar ar->offset = mq->ring_offset; 46209c7e63aSJakub Grajciar ar->region = mq->region; 46309c7e63aSJakub Grajciar ar->log2_ring_size = mq->log2_ring_size; 464d250589dSStephen Hemminger ar->flags = (type == MEMIF_RING_C2S) ? MEMIF_MSG_ADD_RING_FLAG_C2S : 0; 46509c7e63aSJakub Grajciar ar->private_hdr_size = 0; 46609c7e63aSJakub Grajciar 46709c7e63aSJakub Grajciar return 0; 46809c7e63aSJakub Grajciar } 46909c7e63aSJakub Grajciar 47009c7e63aSJakub Grajciar static int 47109c7e63aSJakub Grajciar memif_msg_enq_connect(struct rte_eth_dev *dev) 47209c7e63aSJakub Grajciar { 47309c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 47409c7e63aSJakub Grajciar struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 47509c7e63aSJakub Grajciar memif_msg_connect_t *c; 47609c7e63aSJakub Grajciar 47709c7e63aSJakub Grajciar if (e == NULL) 47809c7e63aSJakub Grajciar return -1; 47909c7e63aSJakub Grajciar 48009c7e63aSJakub Grajciar c = &e->msg.connect; 48109c7e63aSJakub Grajciar e->msg.type = MEMIF_MSG_TYPE_CONNECT; 48243b815d8SJakub Grajciar strlcpy((char *)c->if_name, dev->data->name, sizeof(c->if_name)); 48309c7e63aSJakub Grajciar 48409c7e63aSJakub Grajciar return 0; 48509c7e63aSJakub Grajciar } 48609c7e63aSJakub Grajciar 48709c7e63aSJakub Grajciar static int 48809c7e63aSJakub Grajciar memif_msg_enq_connected(struct rte_eth_dev *dev) 48909c7e63aSJakub Grajciar { 49009c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 49109c7e63aSJakub Grajciar struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 49209c7e63aSJakub Grajciar memif_msg_connected_t *c; 49309c7e63aSJakub Grajciar 49409c7e63aSJakub Grajciar if (e == NULL) 49509c7e63aSJakub Grajciar return -1; 49609c7e63aSJakub Grajciar 49709c7e63aSJakub Grajciar c = &e->msg.connected; 49809c7e63aSJakub Grajciar e->msg.type = MEMIF_MSG_TYPE_CONNECTED; 49943b815d8SJakub Grajciar strlcpy((char *)c->if_name, dev->data->name, sizeof(c->if_name)); 50009c7e63aSJakub Grajciar 50109c7e63aSJakub Grajciar return 0; 50209c7e63aSJakub Grajciar } 50309c7e63aSJakub Grajciar 50409c7e63aSJakub Grajciar static void 50509c7e63aSJakub Grajciar memif_intr_unregister_handler(struct rte_intr_handle *intr_handle, void *arg) 50609c7e63aSJakub Grajciar { 50709c7e63aSJakub Grajciar struct memif_msg_queue_elt *elt; 50809c7e63aSJakub Grajciar struct memif_control_channel *cc = arg; 50909c7e63aSJakub Grajciar 51009c7e63aSJakub Grajciar /* close control channel fd */ 511*d61138d4SHarman Kalra close(rte_intr_fd_get(intr_handle)); 51209c7e63aSJakub Grajciar /* clear message queue */ 51309c7e63aSJakub Grajciar while ((elt = TAILQ_FIRST(&cc->msg_queue)) != NULL) { 51409c7e63aSJakub Grajciar TAILQ_REMOVE(&cc->msg_queue, elt, next); 51509c7e63aSJakub Grajciar rte_free(elt); 51609c7e63aSJakub Grajciar } 517*d61138d4SHarman Kalra rte_intr_instance_free(cc->intr_handle); 51809c7e63aSJakub Grajciar /* free control channel */ 51909c7e63aSJakub Grajciar rte_free(cc); 52009c7e63aSJakub Grajciar } 52109c7e63aSJakub Grajciar 52209c7e63aSJakub Grajciar void 52309c7e63aSJakub Grajciar memif_disconnect(struct rte_eth_dev *dev) 52409c7e63aSJakub Grajciar { 52509c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 52609c7e63aSJakub Grajciar struct memif_msg_queue_elt *elt, *next; 52709c7e63aSJakub Grajciar struct memif_queue *mq; 52809c7e63aSJakub Grajciar struct rte_intr_handle *ih; 52909c7e63aSJakub Grajciar int i; 53009c7e63aSJakub Grajciar int ret; 53109c7e63aSJakub Grajciar 532295968d1SFerruh Yigit dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN; 533c41a0495SJakub Grajciar pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTING; 534c41a0495SJakub Grajciar pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTED; 535c41a0495SJakub Grajciar 536cbbbbd33SJúlius Milan rte_spinlock_lock(&pmd->cc_lock); 53709c7e63aSJakub Grajciar if (pmd->cc != NULL) { 53809c7e63aSJakub Grajciar /* Clear control message queue (except disconnect message if any). */ 53909c7e63aSJakub Grajciar for (elt = TAILQ_FIRST(&pmd->cc->msg_queue); elt != NULL; elt = next) { 54009c7e63aSJakub Grajciar next = TAILQ_NEXT(elt, next); 54109c7e63aSJakub Grajciar if (elt->msg.type != MEMIF_MSG_TYPE_DISCONNECT) { 54209c7e63aSJakub Grajciar TAILQ_REMOVE(&pmd->cc->msg_queue, elt, next); 54309c7e63aSJakub Grajciar rte_free(elt); 54409c7e63aSJakub Grajciar } 54509c7e63aSJakub Grajciar } 54609c7e63aSJakub Grajciar /* send disconnect message (if there is any in queue) */ 54709c7e63aSJakub Grajciar memif_msg_send_from_queue(pmd->cc); 54809c7e63aSJakub Grajciar 54909c7e63aSJakub Grajciar /* at this point, there should be no more messages in queue */ 55009c7e63aSJakub Grajciar if (TAILQ_FIRST(&pmd->cc->msg_queue) != NULL) { 55109c7e63aSJakub Grajciar MIF_LOG(WARNING, 552c41a0495SJakub Grajciar "Unexpected message(s) in message queue."); 55309c7e63aSJakub Grajciar } 55409c7e63aSJakub Grajciar 555*d61138d4SHarman Kalra ih = pmd->cc->intr_handle; 556*d61138d4SHarman Kalra if (rte_intr_fd_get(ih) > 0) { 55709c7e63aSJakub Grajciar ret = rte_intr_callback_unregister(ih, 55809c7e63aSJakub Grajciar memif_intr_handler, 55909c7e63aSJakub Grajciar pmd->cc); 56009c7e63aSJakub Grajciar /* 56109c7e63aSJakub Grajciar * If callback is active (disconnecting based on 56209c7e63aSJakub Grajciar * received control message). 56309c7e63aSJakub Grajciar */ 56409c7e63aSJakub Grajciar if (ret == -EAGAIN) { 56509c7e63aSJakub Grajciar ret = rte_intr_callback_unregister_pending(ih, 56609c7e63aSJakub Grajciar memif_intr_handler, 56709c7e63aSJakub Grajciar pmd->cc, 56809c7e63aSJakub Grajciar memif_intr_unregister_handler); 56909c7e63aSJakub Grajciar } else if (ret > 0) { 570*d61138d4SHarman Kalra close(rte_intr_fd_get(ih)); 571*d61138d4SHarman Kalra rte_intr_instance_free(ih); 57209c7e63aSJakub Grajciar rte_free(pmd->cc); 57309c7e63aSJakub Grajciar } 57409c7e63aSJakub Grajciar pmd->cc = NULL; 57509c7e63aSJakub Grajciar if (ret <= 0) 576c41a0495SJakub Grajciar MIF_LOG(WARNING, 577c41a0495SJakub Grajciar "Failed to unregister control channel callback."); 57809c7e63aSJakub Grajciar } 57909c7e63aSJakub Grajciar } 580cbbbbd33SJúlius Milan rte_spinlock_unlock(&pmd->cc_lock); 58109c7e63aSJakub Grajciar 58209c7e63aSJakub Grajciar /* unconfig interrupts */ 583d250589dSStephen Hemminger for (i = 0; i < pmd->cfg.num_c2s_rings; i++) { 584d250589dSStephen Hemminger if (pmd->role == MEMIF_ROLE_CLIENT) { 58509c7e63aSJakub Grajciar if (dev->data->tx_queues != NULL) 58609c7e63aSJakub Grajciar mq = dev->data->tx_queues[i]; 58709c7e63aSJakub Grajciar else 58809c7e63aSJakub Grajciar continue; 58909c7e63aSJakub Grajciar } else { 59009c7e63aSJakub Grajciar if (dev->data->rx_queues != NULL) 59109c7e63aSJakub Grajciar mq = dev->data->rx_queues[i]; 59209c7e63aSJakub Grajciar else 59309c7e63aSJakub Grajciar continue; 59409c7e63aSJakub Grajciar } 595*d61138d4SHarman Kalra 596*d61138d4SHarman Kalra if (rte_intr_fd_get(mq->intr_handle) > 0) { 597*d61138d4SHarman Kalra close(rte_intr_fd_get(mq->intr_handle)); 598*d61138d4SHarman Kalra rte_intr_fd_set(mq->intr_handle, -1); 59909c7e63aSJakub Grajciar } 60009c7e63aSJakub Grajciar } 601d250589dSStephen Hemminger for (i = 0; i < pmd->cfg.num_s2c_rings; i++) { 602d250589dSStephen Hemminger if (pmd->role == MEMIF_ROLE_SERVER) { 60309c7e63aSJakub Grajciar if (dev->data->tx_queues != NULL) 60409c7e63aSJakub Grajciar mq = dev->data->tx_queues[i]; 60509c7e63aSJakub Grajciar else 60609c7e63aSJakub Grajciar continue; 60709c7e63aSJakub Grajciar } else { 60809c7e63aSJakub Grajciar if (dev->data->rx_queues != NULL) 60909c7e63aSJakub Grajciar mq = dev->data->rx_queues[i]; 61009c7e63aSJakub Grajciar else 61109c7e63aSJakub Grajciar continue; 61209c7e63aSJakub Grajciar } 613*d61138d4SHarman Kalra 614*d61138d4SHarman Kalra if (rte_intr_fd_get(mq->intr_handle) > 0) { 615*d61138d4SHarman Kalra close(rte_intr_fd_get(mq->intr_handle)); 616*d61138d4SHarman Kalra rte_intr_fd_set(mq->intr_handle, -1); 61709c7e63aSJakub Grajciar } 61809c7e63aSJakub Grajciar } 61909c7e63aSJakub Grajciar 62043b815d8SJakub Grajciar memif_free_regions(dev); 62109c7e63aSJakub Grajciar 62209c7e63aSJakub Grajciar /* reset connection configuration */ 62309c7e63aSJakub Grajciar memset(&pmd->run, 0, sizeof(pmd->run)); 62409c7e63aSJakub Grajciar 625cbbbbd33SJúlius Milan MIF_LOG(DEBUG, "Disconnected, id: %d, role: %s.", pmd->id, 626d250589dSStephen Hemminger (pmd->role == MEMIF_ROLE_SERVER) ? "server" : "client"); 62709c7e63aSJakub Grajciar } 62809c7e63aSJakub Grajciar 62909c7e63aSJakub Grajciar static int 63009c7e63aSJakub Grajciar memif_msg_receive(struct memif_control_channel *cc) 63109c7e63aSJakub Grajciar { 63209c7e63aSJakub Grajciar char ctl[CMSG_SPACE(sizeof(int)) + 63309c7e63aSJakub Grajciar CMSG_SPACE(sizeof(struct ucred))] = { 0 }; 63409c7e63aSJakub Grajciar struct msghdr mh = { 0 }; 63509c7e63aSJakub Grajciar struct iovec iov[1]; 63609c7e63aSJakub Grajciar memif_msg_t msg = { 0 }; 63709c7e63aSJakub Grajciar ssize_t size; 63809c7e63aSJakub Grajciar int ret = 0; 63909c7e63aSJakub Grajciar struct ucred *cr __rte_unused; 64009c7e63aSJakub Grajciar cr = 0; 64109c7e63aSJakub Grajciar struct cmsghdr *cmsg; 64209c7e63aSJakub Grajciar int afd = -1; 64309c7e63aSJakub Grajciar int i; 64409c7e63aSJakub Grajciar struct pmd_internals *pmd; 645c41a0495SJakub Grajciar struct pmd_process_private *proc_private; 64609c7e63aSJakub Grajciar 64709c7e63aSJakub Grajciar iov[0].iov_base = (void *)&msg; 64809c7e63aSJakub Grajciar iov[0].iov_len = sizeof(memif_msg_t); 64909c7e63aSJakub Grajciar mh.msg_iov = iov; 65009c7e63aSJakub Grajciar mh.msg_iovlen = 1; 65109c7e63aSJakub Grajciar mh.msg_control = ctl; 65209c7e63aSJakub Grajciar mh.msg_controllen = sizeof(ctl); 65309c7e63aSJakub Grajciar 654*d61138d4SHarman Kalra size = recvmsg(rte_intr_fd_get(cc->intr_handle), &mh, 0); 65509c7e63aSJakub Grajciar if (size != sizeof(memif_msg_t)) { 656cbbbbd33SJúlius Milan MIF_LOG(DEBUG, "Invalid message size = %zd", size); 657cbbbbd33SJúlius Milan if (size > 0) 658cbbbbd33SJúlius Milan /* 0 means end-of-file, negative size means error, 659cbbbbd33SJúlius Milan * don't send further disconnect message in such cases. 660cbbbbd33SJúlius Milan */ 66109c7e63aSJakub Grajciar memif_msg_enq_disconnect(cc, "Invalid message size", 0); 66209c7e63aSJakub Grajciar return -1; 66309c7e63aSJakub Grajciar } 66409c7e63aSJakub Grajciar MIF_LOG(DEBUG, "Received msg type: %u.", msg.type); 66509c7e63aSJakub Grajciar 66609c7e63aSJakub Grajciar cmsg = CMSG_FIRSTHDR(&mh); 66709c7e63aSJakub Grajciar while (cmsg) { 66809c7e63aSJakub Grajciar if (cmsg->cmsg_level == SOL_SOCKET) { 66909c7e63aSJakub Grajciar if (cmsg->cmsg_type == SCM_CREDENTIALS) 67009c7e63aSJakub Grajciar cr = (struct ucred *)CMSG_DATA(cmsg); 67109c7e63aSJakub Grajciar else if (cmsg->cmsg_type == SCM_RIGHTS) 67243b815d8SJakub Grajciar rte_memcpy(&afd, CMSG_DATA(cmsg), sizeof(int)); 67309c7e63aSJakub Grajciar } 67409c7e63aSJakub Grajciar cmsg = CMSG_NXTHDR(&mh, cmsg); 67509c7e63aSJakub Grajciar } 67609c7e63aSJakub Grajciar 67709c7e63aSJakub Grajciar if (cc->dev == NULL && msg.type != MEMIF_MSG_TYPE_INIT) { 67809c7e63aSJakub Grajciar MIF_LOG(DEBUG, "Unexpected message."); 67909c7e63aSJakub Grajciar memif_msg_enq_disconnect(cc, "Unexpected message", 0); 68009c7e63aSJakub Grajciar return -1; 68109c7e63aSJakub Grajciar } 68209c7e63aSJakub Grajciar 68309c7e63aSJakub Grajciar /* get device from hash data */ 68409c7e63aSJakub Grajciar switch (msg.type) { 68509c7e63aSJakub Grajciar case MEMIF_MSG_TYPE_ACK: 68609c7e63aSJakub Grajciar break; 68709c7e63aSJakub Grajciar case MEMIF_MSG_TYPE_HELLO: 68809c7e63aSJakub Grajciar ret = memif_msg_receive_hello(cc->dev, &msg); 68909c7e63aSJakub Grajciar if (ret < 0) 69009c7e63aSJakub Grajciar goto exit; 69109c7e63aSJakub Grajciar ret = memif_init_regions_and_queues(cc->dev); 69209c7e63aSJakub Grajciar if (ret < 0) 69309c7e63aSJakub Grajciar goto exit; 69409c7e63aSJakub Grajciar ret = memif_msg_enq_init(cc->dev); 69509c7e63aSJakub Grajciar if (ret < 0) 69609c7e63aSJakub Grajciar goto exit; 69709c7e63aSJakub Grajciar pmd = cc->dev->data->dev_private; 698c41a0495SJakub Grajciar proc_private = cc->dev->process_private; 699c41a0495SJakub Grajciar for (i = 0; i < proc_private->regions_num; i++) { 70009c7e63aSJakub Grajciar ret = memif_msg_enq_add_region(cc->dev, i); 70109c7e63aSJakub Grajciar if (ret < 0) 70209c7e63aSJakub Grajciar goto exit; 70309c7e63aSJakub Grajciar } 704d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_c2s_rings; i++) { 70509c7e63aSJakub Grajciar ret = memif_msg_enq_add_ring(cc->dev, i, 706d250589dSStephen Hemminger MEMIF_RING_C2S); 70709c7e63aSJakub Grajciar if (ret < 0) 70809c7e63aSJakub Grajciar goto exit; 70909c7e63aSJakub Grajciar } 710d250589dSStephen Hemminger for (i = 0; i < pmd->run.num_s2c_rings; i++) { 71109c7e63aSJakub Grajciar ret = memif_msg_enq_add_ring(cc->dev, i, 712d250589dSStephen Hemminger MEMIF_RING_S2C); 71309c7e63aSJakub Grajciar if (ret < 0) 71409c7e63aSJakub Grajciar goto exit; 71509c7e63aSJakub Grajciar } 71609c7e63aSJakub Grajciar ret = memif_msg_enq_connect(cc->dev); 71709c7e63aSJakub Grajciar if (ret < 0) 71809c7e63aSJakub Grajciar goto exit; 71909c7e63aSJakub Grajciar break; 72009c7e63aSJakub Grajciar case MEMIF_MSG_TYPE_INIT: 72109c7e63aSJakub Grajciar /* 72209c7e63aSJakub Grajciar * This cc does not have an interface asociated with it. 72309c7e63aSJakub Grajciar * If suitable interface is found it will be assigned here. 72409c7e63aSJakub Grajciar */ 72509c7e63aSJakub Grajciar ret = memif_msg_receive_init(cc, &msg); 72609c7e63aSJakub Grajciar if (ret < 0) 72709c7e63aSJakub Grajciar goto exit; 72809c7e63aSJakub Grajciar ret = memif_msg_enq_ack(cc->dev); 72909c7e63aSJakub Grajciar if (ret < 0) 73009c7e63aSJakub Grajciar goto exit; 73109c7e63aSJakub Grajciar break; 73209c7e63aSJakub Grajciar case MEMIF_MSG_TYPE_ADD_REGION: 73309c7e63aSJakub Grajciar ret = memif_msg_receive_add_region(cc->dev, &msg, afd); 73409c7e63aSJakub Grajciar if (ret < 0) 73509c7e63aSJakub Grajciar goto exit; 73609c7e63aSJakub Grajciar ret = memif_msg_enq_ack(cc->dev); 73709c7e63aSJakub Grajciar if (ret < 0) 73809c7e63aSJakub Grajciar goto exit; 73909c7e63aSJakub Grajciar break; 74009c7e63aSJakub Grajciar case MEMIF_MSG_TYPE_ADD_RING: 74109c7e63aSJakub Grajciar ret = memif_msg_receive_add_ring(cc->dev, &msg, afd); 74209c7e63aSJakub Grajciar if (ret < 0) 74309c7e63aSJakub Grajciar goto exit; 74409c7e63aSJakub Grajciar ret = memif_msg_enq_ack(cc->dev); 74509c7e63aSJakub Grajciar if (ret < 0) 74609c7e63aSJakub Grajciar goto exit; 74709c7e63aSJakub Grajciar break; 74809c7e63aSJakub Grajciar case MEMIF_MSG_TYPE_CONNECT: 74909c7e63aSJakub Grajciar ret = memif_msg_receive_connect(cc->dev, &msg); 75009c7e63aSJakub Grajciar if (ret < 0) 75109c7e63aSJakub Grajciar goto exit; 75209c7e63aSJakub Grajciar ret = memif_msg_enq_connected(cc->dev); 75309c7e63aSJakub Grajciar if (ret < 0) 75409c7e63aSJakub Grajciar goto exit; 75509c7e63aSJakub Grajciar break; 75609c7e63aSJakub Grajciar case MEMIF_MSG_TYPE_CONNECTED: 75709c7e63aSJakub Grajciar ret = memif_msg_receive_connected(cc->dev, &msg); 75809c7e63aSJakub Grajciar break; 75909c7e63aSJakub Grajciar case MEMIF_MSG_TYPE_DISCONNECT: 76009c7e63aSJakub Grajciar ret = memif_msg_receive_disconnect(cc->dev, &msg); 76109c7e63aSJakub Grajciar if (ret < 0) 76209c7e63aSJakub Grajciar goto exit; 76309c7e63aSJakub Grajciar break; 76409c7e63aSJakub Grajciar default: 76509c7e63aSJakub Grajciar memif_msg_enq_disconnect(cc, "Unknown message type", 0); 76609c7e63aSJakub Grajciar ret = -1; 76709c7e63aSJakub Grajciar goto exit; 76809c7e63aSJakub Grajciar } 76909c7e63aSJakub Grajciar 77009c7e63aSJakub Grajciar exit: 77109c7e63aSJakub Grajciar return ret; 77209c7e63aSJakub Grajciar } 77309c7e63aSJakub Grajciar 77409c7e63aSJakub Grajciar static void 77509c7e63aSJakub Grajciar memif_intr_handler(void *arg) 77609c7e63aSJakub Grajciar { 77709c7e63aSJakub Grajciar struct memif_control_channel *cc = arg; 77809c7e63aSJakub Grajciar int ret; 77909c7e63aSJakub Grajciar 78009c7e63aSJakub Grajciar ret = memif_msg_receive(cc); 78109c7e63aSJakub Grajciar /* if driver failed to assign device */ 78209c7e63aSJakub Grajciar if (cc->dev == NULL) { 78306123fddSJúlius Milan memif_msg_send_from_queue(cc); 784*d61138d4SHarman Kalra ret = rte_intr_callback_unregister_pending(cc->intr_handle, 78509c7e63aSJakub Grajciar memif_intr_handler, 78609c7e63aSJakub Grajciar cc, 78709c7e63aSJakub Grajciar memif_intr_unregister_handler); 78809c7e63aSJakub Grajciar if (ret < 0) 78909c7e63aSJakub Grajciar MIF_LOG(WARNING, 79009c7e63aSJakub Grajciar "Failed to unregister control channel callback."); 79109c7e63aSJakub Grajciar return; 79209c7e63aSJakub Grajciar } 79309c7e63aSJakub Grajciar /* if memif_msg_receive failed */ 79409c7e63aSJakub Grajciar if (ret < 0) 79509c7e63aSJakub Grajciar goto disconnect; 79609c7e63aSJakub Grajciar 79709c7e63aSJakub Grajciar ret = memif_msg_send_from_queue(cc); 79809c7e63aSJakub Grajciar if (ret < 0) 79909c7e63aSJakub Grajciar goto disconnect; 80009c7e63aSJakub Grajciar 80109c7e63aSJakub Grajciar return; 80209c7e63aSJakub Grajciar 80309c7e63aSJakub Grajciar disconnect: 80409c7e63aSJakub Grajciar if (cc->dev == NULL) { 80509c7e63aSJakub Grajciar MIF_LOG(WARNING, "eth dev not allocated"); 80609c7e63aSJakub Grajciar return; 80709c7e63aSJakub Grajciar } 80809c7e63aSJakub Grajciar memif_disconnect(cc->dev); 80909c7e63aSJakub Grajciar } 81009c7e63aSJakub Grajciar 81109c7e63aSJakub Grajciar static void 81209c7e63aSJakub Grajciar memif_listener_handler(void *arg) 81309c7e63aSJakub Grajciar { 81409c7e63aSJakub Grajciar struct memif_socket *socket = arg; 81509c7e63aSJakub Grajciar int sockfd; 81609c7e63aSJakub Grajciar int addr_len; 81709c7e63aSJakub Grajciar struct sockaddr_un client; 81809c7e63aSJakub Grajciar struct memif_control_channel *cc; 81909c7e63aSJakub Grajciar int ret; 82009c7e63aSJakub Grajciar 82109c7e63aSJakub Grajciar addr_len = sizeof(client); 822*d61138d4SHarman Kalra sockfd = accept(rte_intr_fd_get(socket->intr_handle), 823*d61138d4SHarman Kalra (struct sockaddr *)&client, (socklen_t *)&addr_len); 82409c7e63aSJakub Grajciar if (sockfd < 0) { 82509c7e63aSJakub Grajciar MIF_LOG(ERR, 82609c7e63aSJakub Grajciar "Failed to accept connection request on socket fd %d", 827*d61138d4SHarman Kalra rte_intr_fd_get(socket->intr_handle)); 82809c7e63aSJakub Grajciar return; 82909c7e63aSJakub Grajciar } 83009c7e63aSJakub Grajciar 83109c7e63aSJakub Grajciar MIF_LOG(DEBUG, "%s: Connection request accepted.", socket->filename); 83209c7e63aSJakub Grajciar 83309c7e63aSJakub Grajciar cc = rte_zmalloc("memif-cc", sizeof(struct memif_control_channel), 0); 83409c7e63aSJakub Grajciar if (cc == NULL) { 83509c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to allocate control channel."); 83609c7e63aSJakub Grajciar goto error; 83709c7e63aSJakub Grajciar } 83809c7e63aSJakub Grajciar 839*d61138d4SHarman Kalra /* Allocate interrupt instance */ 840*d61138d4SHarman Kalra cc->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED); 841*d61138d4SHarman Kalra if (cc->intr_handle == NULL) { 842*d61138d4SHarman Kalra MIF_LOG(ERR, "Failed to allocate intr handle"); 843*d61138d4SHarman Kalra goto error; 844*d61138d4SHarman Kalra } 845*d61138d4SHarman Kalra 846*d61138d4SHarman Kalra if (rte_intr_fd_set(cc->intr_handle, sockfd)) 847*d61138d4SHarman Kalra goto error; 848*d61138d4SHarman Kalra 849*d61138d4SHarman Kalra if (rte_intr_type_set(cc->intr_handle, RTE_INTR_HANDLE_EXT)) 850*d61138d4SHarman Kalra goto error; 851*d61138d4SHarman Kalra 85209c7e63aSJakub Grajciar cc->socket = socket; 85309c7e63aSJakub Grajciar cc->dev = NULL; 85409c7e63aSJakub Grajciar TAILQ_INIT(&cc->msg_queue); 85509c7e63aSJakub Grajciar 856*d61138d4SHarman Kalra ret = rte_intr_callback_register(cc->intr_handle, memif_intr_handler, 857*d61138d4SHarman Kalra cc); 85809c7e63aSJakub Grajciar if (ret < 0) { 85909c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to register control channel callback."); 86009c7e63aSJakub Grajciar goto error; 86109c7e63aSJakub Grajciar } 86209c7e63aSJakub Grajciar 86309c7e63aSJakub Grajciar ret = memif_msg_enq_hello(cc); 86409c7e63aSJakub Grajciar if (ret < 0) { 86509c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to enqueue hello message."); 86609c7e63aSJakub Grajciar goto error; 86709c7e63aSJakub Grajciar } 86809c7e63aSJakub Grajciar ret = memif_msg_send_from_queue(cc); 86909c7e63aSJakub Grajciar if (ret < 0) 87009c7e63aSJakub Grajciar goto error; 87109c7e63aSJakub Grajciar 87209c7e63aSJakub Grajciar return; 87309c7e63aSJakub Grajciar 87409c7e63aSJakub Grajciar error: 87510bd0ad5SJakub Grajciar if (sockfd >= 0) { 87609c7e63aSJakub Grajciar close(sockfd); 87709c7e63aSJakub Grajciar sockfd = -1; 87809c7e63aSJakub Grajciar } 879*d61138d4SHarman Kalra if (cc != NULL) { 880*d61138d4SHarman Kalra rte_intr_instance_free(cc->intr_handle); 88109c7e63aSJakub Grajciar rte_free(cc); 88209c7e63aSJakub Grajciar } 883*d61138d4SHarman Kalra } 88409c7e63aSJakub Grajciar 88509c7e63aSJakub Grajciar static struct memif_socket * 8862f865ed0SJakub Grajciar memif_socket_create(char *key, uint8_t listener, bool is_abstract) 88709c7e63aSJakub Grajciar { 88809c7e63aSJakub Grajciar struct memif_socket *sock; 8892f865ed0SJakub Grajciar struct sockaddr_un un = { 0 }; 8904e30586dSNathan Skrzypczak uint32_t sunlen; 89109c7e63aSJakub Grajciar int sockfd; 89209c7e63aSJakub Grajciar int ret; 89309c7e63aSJakub Grajciar int on = 1; 89409c7e63aSJakub Grajciar 89509c7e63aSJakub Grajciar sock = rte_zmalloc("memif-socket", sizeof(struct memif_socket), 0); 89609c7e63aSJakub Grajciar if (sock == NULL) { 89709c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to allocate memory for memif socket"); 89809c7e63aSJakub Grajciar return NULL; 89909c7e63aSJakub Grajciar } 90009c7e63aSJakub Grajciar 90109c7e63aSJakub Grajciar sock->listener = listener; 902d803feecSJakub Grajciar strlcpy(sock->filename, key, MEMIF_SOCKET_UN_SIZE); 90309c7e63aSJakub Grajciar TAILQ_INIT(&sock->dev_queue); 90409c7e63aSJakub Grajciar 90509c7e63aSJakub Grajciar if (listener != 0) { 90609c7e63aSJakub Grajciar sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 90709c7e63aSJakub Grajciar if (sockfd < 0) 90809c7e63aSJakub Grajciar goto error; 90909c7e63aSJakub Grajciar 910d803feecSJakub Grajciar un.sun_family = AF_UNIX; 9112f865ed0SJakub Grajciar if (is_abstract) { 9122f865ed0SJakub Grajciar /* abstract address */ 9132f865ed0SJakub Grajciar un.sun_path[0] = '\0'; 9142f865ed0SJakub Grajciar strlcpy(un.sun_path + 1, sock->filename, MEMIF_SOCKET_UN_SIZE - 1); 9154e30586dSNathan Skrzypczak sunlen = RTE_MIN(1 + strlen(sock->filename), 9164e30586dSNathan Skrzypczak MEMIF_SOCKET_UN_SIZE) + 9174e30586dSNathan Skrzypczak sizeof(un) - sizeof(un.sun_path); 9182f865ed0SJakub Grajciar } else { 9194e30586dSNathan Skrzypczak sunlen = sizeof(un); 920d803feecSJakub Grajciar strlcpy(un.sun_path, sock->filename, MEMIF_SOCKET_UN_SIZE); 9212f865ed0SJakub Grajciar } 92209c7e63aSJakub Grajciar 92309c7e63aSJakub Grajciar ret = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &on, 92409c7e63aSJakub Grajciar sizeof(on)); 92509c7e63aSJakub Grajciar if (ret < 0) 92609c7e63aSJakub Grajciar goto error; 927d803feecSJakub Grajciar 9284e30586dSNathan Skrzypczak ret = bind(sockfd, (struct sockaddr *)&un, sunlen); 92909c7e63aSJakub Grajciar if (ret < 0) 93009c7e63aSJakub Grajciar goto error; 931d803feecSJakub Grajciar 93209c7e63aSJakub Grajciar ret = listen(sockfd, 1); 93309c7e63aSJakub Grajciar if (ret < 0) 93409c7e63aSJakub Grajciar goto error; 93509c7e63aSJakub Grajciar 93643b815d8SJakub Grajciar MIF_LOG(DEBUG, "Memif listener socket %s created.", sock->filename); 93709c7e63aSJakub Grajciar 938*d61138d4SHarman Kalra /* Allocate interrupt instance */ 939*d61138d4SHarman Kalra sock->intr_handle = 940*d61138d4SHarman Kalra rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED); 941*d61138d4SHarman Kalra if (sock->intr_handle == NULL) { 942*d61138d4SHarman Kalra MIF_LOG(ERR, "Failed to allocate intr handle"); 943*d61138d4SHarman Kalra goto error; 944*d61138d4SHarman Kalra } 945*d61138d4SHarman Kalra 946*d61138d4SHarman Kalra if (rte_intr_fd_set(sock->intr_handle, sockfd)) 947*d61138d4SHarman Kalra goto error; 948*d61138d4SHarman Kalra 949*d61138d4SHarman Kalra if (rte_intr_type_set(sock->intr_handle, RTE_INTR_HANDLE_EXT)) 950*d61138d4SHarman Kalra goto error; 951*d61138d4SHarman Kalra 952*d61138d4SHarman Kalra ret = rte_intr_callback_register(sock->intr_handle, 95309c7e63aSJakub Grajciar memif_listener_handler, sock); 95409c7e63aSJakub Grajciar if (ret < 0) { 95543b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to register interrupt " 95643b815d8SJakub Grajciar "callback for listener socket"); 95709c7e63aSJakub Grajciar return NULL; 95809c7e63aSJakub Grajciar } 95909c7e63aSJakub Grajciar } 96009c7e63aSJakub Grajciar 96109c7e63aSJakub Grajciar return sock; 96209c7e63aSJakub Grajciar 96309c7e63aSJakub Grajciar error: 96443b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to setup socket %s: %s", key, strerror(errno)); 965*d61138d4SHarman Kalra if (sock != NULL) { 966*d61138d4SHarman Kalra rte_intr_instance_free(sock->intr_handle); 96709c7e63aSJakub Grajciar rte_free(sock); 968*d61138d4SHarman Kalra } 96910bd0ad5SJakub Grajciar if (sockfd >= 0) 97010bd0ad5SJakub Grajciar close(sockfd); 97109c7e63aSJakub Grajciar return NULL; 97209c7e63aSJakub Grajciar } 97309c7e63aSJakub Grajciar 97409c7e63aSJakub Grajciar static struct rte_hash * 97509c7e63aSJakub Grajciar memif_create_socket_hash(void) 97609c7e63aSJakub Grajciar { 97709c7e63aSJakub Grajciar struct rte_hash_parameters params = { 0 }; 978b923866cSStephen Hemminger 97909c7e63aSJakub Grajciar params.name = MEMIF_SOCKET_HASH_NAME; 98009c7e63aSJakub Grajciar params.entries = 256; 981d803feecSJakub Grajciar params.key_len = MEMIF_SOCKET_UN_SIZE; 98209c7e63aSJakub Grajciar params.hash_func = rte_jhash; 98309c7e63aSJakub Grajciar params.hash_func_init_val = 0; 98418627cedSJunxiao Shi params.socket_id = SOCKET_ID_ANY; 98509c7e63aSJakub Grajciar return rte_hash_create(¶ms); 98609c7e63aSJakub Grajciar } 98709c7e63aSJakub Grajciar 98809c7e63aSJakub Grajciar int 98909c7e63aSJakub Grajciar memif_socket_init(struct rte_eth_dev *dev, const char *socket_filename) 99009c7e63aSJakub Grajciar { 99109c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 99209c7e63aSJakub Grajciar struct memif_socket *socket = NULL; 99309c7e63aSJakub Grajciar struct memif_socket_dev_list_elt *elt; 99409c7e63aSJakub Grajciar struct pmd_internals *tmp_pmd; 99509c7e63aSJakub Grajciar struct rte_hash *hash; 99609c7e63aSJakub Grajciar int ret; 997d803feecSJakub Grajciar char key[MEMIF_SOCKET_UN_SIZE]; 99809c7e63aSJakub Grajciar 99909c7e63aSJakub Grajciar hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME); 100009c7e63aSJakub Grajciar if (hash == NULL) { 100109c7e63aSJakub Grajciar hash = memif_create_socket_hash(); 100209c7e63aSJakub Grajciar if (hash == NULL) { 100309c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to create memif socket hash."); 100409c7e63aSJakub Grajciar return -1; 100509c7e63aSJakub Grajciar } 100609c7e63aSJakub Grajciar } 100709c7e63aSJakub Grajciar 1008d803feecSJakub Grajciar memset(key, 0, MEMIF_SOCKET_UN_SIZE); 1009d803feecSJakub Grajciar strlcpy(key, socket_filename, MEMIF_SOCKET_UN_SIZE); 101009c7e63aSJakub Grajciar ret = rte_hash_lookup_data(hash, key, (void **)&socket); 101109c7e63aSJakub Grajciar if (ret < 0) { 101243b815d8SJakub Grajciar socket = memif_socket_create(key, 1013d250589dSStephen Hemminger (pmd->role == MEMIF_ROLE_CLIENT) ? 0 : 1, 10142f865ed0SJakub Grajciar pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT); 101509c7e63aSJakub Grajciar if (socket == NULL) 101609c7e63aSJakub Grajciar return -1; 101709c7e63aSJakub Grajciar ret = rte_hash_add_key_data(hash, key, socket); 101809c7e63aSJakub Grajciar if (ret < 0) { 101909c7e63aSJakub Grajciar MIF_LOG(ERR, "Failed to add socket to socket hash."); 102009c7e63aSJakub Grajciar return ret; 102109c7e63aSJakub Grajciar } 102209c7e63aSJakub Grajciar } 102309c7e63aSJakub Grajciar pmd->socket_filename = socket->filename; 102409c7e63aSJakub Grajciar 102509c7e63aSJakub Grajciar TAILQ_FOREACH(elt, &socket->dev_queue, next) { 102609c7e63aSJakub Grajciar tmp_pmd = elt->dev->data->dev_private; 1027cbbbbd33SJúlius Milan if (tmp_pmd->id == pmd->id && tmp_pmd->role == pmd->role) { 1028cbbbbd33SJúlius Milan MIF_LOG(ERR, "Two interfaces with the same id (%d) can " 1029cbbbbd33SJúlius Milan "not have the same role.", pmd->id); 103009c7e63aSJakub Grajciar return -1; 103109c7e63aSJakub Grajciar } 103209c7e63aSJakub Grajciar } 103309c7e63aSJakub Grajciar 103409c7e63aSJakub Grajciar elt = rte_malloc("pmd-queue", sizeof(struct memif_socket_dev_list_elt), 0); 103509c7e63aSJakub Grajciar if (elt == NULL) { 103643b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to add device to socket device list."); 103709c7e63aSJakub Grajciar return -1; 103809c7e63aSJakub Grajciar } 103909c7e63aSJakub Grajciar elt->dev = dev; 104009c7e63aSJakub Grajciar TAILQ_INSERT_TAIL(&socket->dev_queue, elt, next); 104109c7e63aSJakub Grajciar 104209c7e63aSJakub Grajciar return 0; 104309c7e63aSJakub Grajciar } 104409c7e63aSJakub Grajciar 104509c7e63aSJakub Grajciar void 104609c7e63aSJakub Grajciar memif_socket_remove_device(struct rte_eth_dev *dev) 104709c7e63aSJakub Grajciar { 104809c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 104909c7e63aSJakub Grajciar struct memif_socket *socket = NULL; 105009c7e63aSJakub Grajciar struct memif_socket_dev_list_elt *elt, *next; 105109c7e63aSJakub Grajciar struct rte_hash *hash; 105210bd0ad5SJakub Grajciar int ret; 105309c7e63aSJakub Grajciar 105409c7e63aSJakub Grajciar hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME); 105509c7e63aSJakub Grajciar if (hash == NULL) 105609c7e63aSJakub Grajciar return; 105709c7e63aSJakub Grajciar 105809c7e63aSJakub Grajciar if (pmd->socket_filename == NULL) 105909c7e63aSJakub Grajciar return; 106009c7e63aSJakub Grajciar 106109c7e63aSJakub Grajciar if (rte_hash_lookup_data(hash, pmd->socket_filename, (void **)&socket) < 0) 106209c7e63aSJakub Grajciar return; 106309c7e63aSJakub Grajciar 106409c7e63aSJakub Grajciar for (elt = TAILQ_FIRST(&socket->dev_queue); elt != NULL; elt = next) { 106509c7e63aSJakub Grajciar next = TAILQ_NEXT(elt, next); 106609c7e63aSJakub Grajciar if (elt->dev == dev) { 106709c7e63aSJakub Grajciar TAILQ_REMOVE(&socket->dev_queue, elt, next); 106809c7e63aSJakub Grajciar rte_free(elt); 106909c7e63aSJakub Grajciar pmd->socket_filename = NULL; 107009c7e63aSJakub Grajciar } 107109c7e63aSJakub Grajciar } 107209c7e63aSJakub Grajciar 107309c7e63aSJakub Grajciar /* remove socket, if this was the last device using it */ 107409c7e63aSJakub Grajciar if (TAILQ_EMPTY(&socket->dev_queue)) { 107509c7e63aSJakub Grajciar rte_hash_del_key(hash, socket->filename); 10762f865ed0SJakub Grajciar if (socket->listener && !(pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT)) { 107709c7e63aSJakub Grajciar /* remove listener socket file, 107809c7e63aSJakub Grajciar * so we can create new one later. 107909c7e63aSJakub Grajciar */ 108010bd0ad5SJakub Grajciar ret = remove(socket->filename); 108110bd0ad5SJakub Grajciar if (ret < 0) 108210bd0ad5SJakub Grajciar MIF_LOG(ERR, "Failed to remove socket file: %s", 108310bd0ad5SJakub Grajciar socket->filename); 108409c7e63aSJakub Grajciar } 1085*d61138d4SHarman Kalra if (pmd->role != MEMIF_ROLE_CLIENT) 1086*d61138d4SHarman Kalra rte_intr_instance_free(socket->intr_handle); 108709c7e63aSJakub Grajciar rte_free(socket); 108809c7e63aSJakub Grajciar } 108909c7e63aSJakub Grajciar } 109009c7e63aSJakub Grajciar 109109c7e63aSJakub Grajciar int 1092d250589dSStephen Hemminger memif_connect_server(struct rte_eth_dev *dev) 109309c7e63aSJakub Grajciar { 109409c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 109509c7e63aSJakub Grajciar 109609c7e63aSJakub Grajciar memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 109709c7e63aSJakub Grajciar memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 109809c7e63aSJakub Grajciar pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED; 109909c7e63aSJakub Grajciar return 0; 110009c7e63aSJakub Grajciar } 110109c7e63aSJakub Grajciar 110209c7e63aSJakub Grajciar int 1103d250589dSStephen Hemminger memif_connect_client(struct rte_eth_dev *dev) 110409c7e63aSJakub Grajciar { 110509c7e63aSJakub Grajciar int sockfd; 110609c7e63aSJakub Grajciar int ret; 11074e30586dSNathan Skrzypczak uint32_t sunlen; 11082f865ed0SJakub Grajciar struct sockaddr_un sun = { 0 }; 110909c7e63aSJakub Grajciar struct pmd_internals *pmd = dev->data->dev_private; 111009c7e63aSJakub Grajciar 111109c7e63aSJakub Grajciar memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 111209c7e63aSJakub Grajciar memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 111309c7e63aSJakub Grajciar pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED; 111409c7e63aSJakub Grajciar 111509c7e63aSJakub Grajciar sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 111609c7e63aSJakub Grajciar if (sockfd < 0) { 111743b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to open socket."); 111809c7e63aSJakub Grajciar return -1; 111909c7e63aSJakub Grajciar } 112009c7e63aSJakub Grajciar 112109c7e63aSJakub Grajciar sun.sun_family = AF_UNIX; 11224e30586dSNathan Skrzypczak sunlen = sizeof(struct sockaddr_un); 11232f865ed0SJakub Grajciar if (pmd->flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT) { 11242f865ed0SJakub Grajciar /* abstract address */ 11252f865ed0SJakub Grajciar sun.sun_path[0] = '\0'; 11262f865ed0SJakub Grajciar strlcpy(sun.sun_path + 1, pmd->socket_filename, MEMIF_SOCKET_UN_SIZE - 1); 11274e30586dSNathan Skrzypczak sunlen = RTE_MIN(strlen(pmd->socket_filename) + 1, 11284e30586dSNathan Skrzypczak MEMIF_SOCKET_UN_SIZE) + 11294e30586dSNathan Skrzypczak sizeof(sun) - sizeof(sun.sun_path); 11302f865ed0SJakub Grajciar } else { 11312f865ed0SJakub Grajciar strlcpy(sun.sun_path, pmd->socket_filename, MEMIF_SOCKET_UN_SIZE); 11322f865ed0SJakub Grajciar } 113309c7e63aSJakub Grajciar 11344e30586dSNathan Skrzypczak ret = connect(sockfd, (struct sockaddr *)&sun, sunlen); 113509c7e63aSJakub Grajciar if (ret < 0) { 113643b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to connect socket: %s.", pmd->socket_filename); 113709c7e63aSJakub Grajciar goto error; 113809c7e63aSJakub Grajciar } 113909c7e63aSJakub Grajciar 114043b815d8SJakub Grajciar MIF_LOG(DEBUG, "Memif socket: %s connected.", pmd->socket_filename); 114109c7e63aSJakub Grajciar 114209c7e63aSJakub Grajciar pmd->cc = rte_zmalloc("memif-cc", 114309c7e63aSJakub Grajciar sizeof(struct memif_control_channel), 0); 114409c7e63aSJakub Grajciar if (pmd->cc == NULL) { 114543b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to allocate control channel."); 114609c7e63aSJakub Grajciar goto error; 114709c7e63aSJakub Grajciar } 114809c7e63aSJakub Grajciar 1149*d61138d4SHarman Kalra /* Allocate interrupt instance */ 1150*d61138d4SHarman Kalra pmd->cc->intr_handle = 1151*d61138d4SHarman Kalra rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED); 1152*d61138d4SHarman Kalra if (pmd->cc->intr_handle == NULL) { 1153*d61138d4SHarman Kalra MIF_LOG(ERR, "Failed to allocate intr handle"); 1154*d61138d4SHarman Kalra goto error; 1155*d61138d4SHarman Kalra } 1156*d61138d4SHarman Kalra 1157*d61138d4SHarman Kalra if (rte_intr_fd_set(pmd->cc->intr_handle, sockfd)) 1158*d61138d4SHarman Kalra goto error; 1159*d61138d4SHarman Kalra 1160*d61138d4SHarman Kalra if (rte_intr_type_set(pmd->cc->intr_handle, RTE_INTR_HANDLE_EXT)) 1161*d61138d4SHarman Kalra goto error; 1162*d61138d4SHarman Kalra 116309c7e63aSJakub Grajciar pmd->cc->socket = NULL; 116409c7e63aSJakub Grajciar pmd->cc->dev = dev; 116509c7e63aSJakub Grajciar TAILQ_INIT(&pmd->cc->msg_queue); 116609c7e63aSJakub Grajciar 1167*d61138d4SHarman Kalra ret = rte_intr_callback_register(pmd->cc->intr_handle, 116809c7e63aSJakub Grajciar memif_intr_handler, pmd->cc); 116909c7e63aSJakub Grajciar if (ret < 0) { 117043b815d8SJakub Grajciar MIF_LOG(ERR, "Failed to register interrupt callback for control fd"); 117109c7e63aSJakub Grajciar goto error; 117209c7e63aSJakub Grajciar } 117309c7e63aSJakub Grajciar 117409c7e63aSJakub Grajciar return 0; 117509c7e63aSJakub Grajciar 117609c7e63aSJakub Grajciar error: 117710bd0ad5SJakub Grajciar if (sockfd >= 0) { 117809c7e63aSJakub Grajciar close(sockfd); 117909c7e63aSJakub Grajciar sockfd = -1; 118009c7e63aSJakub Grajciar } 118109c7e63aSJakub Grajciar if (pmd->cc != NULL) { 1182*d61138d4SHarman Kalra rte_intr_instance_free(pmd->cc->intr_handle); 118309c7e63aSJakub Grajciar rte_free(pmd->cc); 118409c7e63aSJakub Grajciar pmd->cc = NULL; 118509c7e63aSJakub Grajciar } 118609c7e63aSJakub Grajciar return -1; 118709c7e63aSJakub Grajciar } 1188