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 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 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 * 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 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 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; 1464418919fSjohnjiang h->max_s2m_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS; 1474418919fSjohnjiang h->max_m2s_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 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 */ 1684418919fSjohnjiang pmd->run.num_s2m_rings = RTE_MIN(h->max_s2m_ring + 1, 1694418919fSjohnjiang pmd->cfg.num_s2m_rings); 1704418919fSjohnjiang pmd->run.num_m2s_rings = RTE_MIN(h->max_m2s_ring + 1, 1714418919fSjohnjiang pmd->cfg.num_m2s_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 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) && 2064418919fSjohnjiang pmd->id == i->id) { 207*0c6bd470Sfengbojiang if (pmd->flags & (ETH_MEMIF_FLAG_CONNECTING | 208*0c6bd470Sfengbojiang ETH_MEMIF_FLAG_CONNECTED)) { 209*0c6bd470Sfengbojiang memif_msg_enq_disconnect(cc, 210*0c6bd470Sfengbojiang "Already connected", 0); 211*0c6bd470Sfengbojiang return -1; 212*0c6bd470Sfengbojiang } 213*0c6bd470Sfengbojiang 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 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 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 */ 3034418919fSjohnjiang if (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M) { 3044418919fSjohnjiang if (ar->index >= pmd->cfg.num_s2m_rings) { 3054418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0); 3064418919fSjohnjiang return -1; 3074418919fSjohnjiang } 3084418919fSjohnjiang pmd->run.num_s2m_rings++; 3094418919fSjohnjiang } else { 3104418919fSjohnjiang if (ar->index >= pmd->cfg.num_m2s_rings) { 3114418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0); 3124418919fSjohnjiang return -1; 3134418919fSjohnjiang } 3144418919fSjohnjiang pmd->run.num_m2s_rings++; 3154418919fSjohnjiang } 3164418919fSjohnjiang 3174418919fSjohnjiang mq = (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M) ? 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 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 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 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 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 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 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 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; 4524418919fSjohnjiang mq = (type == MEMIF_RING_S2M) ? 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; 4614418919fSjohnjiang ar->flags = (type == MEMIF_RING_S2M) ? MEMIF_MSG_ADD_RING_FLAG_S2M : 0; 4624418919fSjohnjiang ar->private_hdr_size = 0; 4634418919fSjohnjiang 4644418919fSjohnjiang return 0; 4654418919fSjohnjiang } 4664418919fSjohnjiang 4674418919fSjohnjiang static int 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 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 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 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 5324418919fSjohnjiang if (pmd->cc != NULL) { 5334418919fSjohnjiang /* Clear control message queue (except disconnect message if any). */ 5344418919fSjohnjiang for (elt = TAILQ_FIRST(&pmd->cc->msg_queue); elt != NULL; elt = next) { 5354418919fSjohnjiang next = TAILQ_NEXT(elt, next); 5364418919fSjohnjiang if (elt->msg.type != MEMIF_MSG_TYPE_DISCONNECT) { 5374418919fSjohnjiang TAILQ_REMOVE(&pmd->cc->msg_queue, elt, next); 5384418919fSjohnjiang rte_free(elt); 5394418919fSjohnjiang } 5404418919fSjohnjiang } 5414418919fSjohnjiang /* send disconnect message (if there is any in queue) */ 5424418919fSjohnjiang memif_msg_send_from_queue(pmd->cc); 5434418919fSjohnjiang 5444418919fSjohnjiang /* at this point, there should be no more messages in queue */ 5454418919fSjohnjiang if (TAILQ_FIRST(&pmd->cc->msg_queue) != NULL) { 5464418919fSjohnjiang MIF_LOG(WARNING, 5474418919fSjohnjiang "Unexpected message(s) in message queue."); 5484418919fSjohnjiang } 5494418919fSjohnjiang 5504418919fSjohnjiang ih = &pmd->cc->intr_handle; 5514418919fSjohnjiang if (ih->fd > 0) { 5524418919fSjohnjiang ret = rte_intr_callback_unregister(ih, 5534418919fSjohnjiang memif_intr_handler, 5544418919fSjohnjiang pmd->cc); 5554418919fSjohnjiang /* 5564418919fSjohnjiang * If callback is active (disconnecting based on 5574418919fSjohnjiang * received control message). 5584418919fSjohnjiang */ 5594418919fSjohnjiang if (ret == -EAGAIN) { 5604418919fSjohnjiang ret = rte_intr_callback_unregister_pending(ih, 5614418919fSjohnjiang memif_intr_handler, 5624418919fSjohnjiang pmd->cc, 5634418919fSjohnjiang memif_intr_unregister_handler); 5644418919fSjohnjiang } else if (ret > 0) { 5654418919fSjohnjiang close(ih->fd); 5664418919fSjohnjiang rte_free(pmd->cc); 5674418919fSjohnjiang } 5684418919fSjohnjiang pmd->cc = NULL; 5694418919fSjohnjiang if (ret <= 0) 5704418919fSjohnjiang MIF_LOG(WARNING, 5714418919fSjohnjiang "Failed to unregister control channel callback."); 5724418919fSjohnjiang } 5734418919fSjohnjiang } 5744418919fSjohnjiang 5754418919fSjohnjiang /* unconfig interrupts */ 5764418919fSjohnjiang for (i = 0; i < pmd->cfg.num_s2m_rings; i++) { 5774418919fSjohnjiang if (pmd->role == MEMIF_ROLE_SLAVE) { 5784418919fSjohnjiang if (dev->data->tx_queues != NULL) 5794418919fSjohnjiang mq = dev->data->tx_queues[i]; 5804418919fSjohnjiang else 5814418919fSjohnjiang continue; 5824418919fSjohnjiang } else { 5834418919fSjohnjiang if (dev->data->rx_queues != NULL) 5844418919fSjohnjiang mq = dev->data->rx_queues[i]; 5854418919fSjohnjiang else 5864418919fSjohnjiang continue; 5874418919fSjohnjiang } 5884418919fSjohnjiang if (mq->intr_handle.fd > 0) { 5894418919fSjohnjiang close(mq->intr_handle.fd); 5904418919fSjohnjiang mq->intr_handle.fd = -1; 5914418919fSjohnjiang } 5924418919fSjohnjiang } 5934418919fSjohnjiang for (i = 0; i < pmd->cfg.num_m2s_rings; i++) { 5944418919fSjohnjiang if (pmd->role == MEMIF_ROLE_MASTER) { 5954418919fSjohnjiang if (dev->data->tx_queues != NULL) 5964418919fSjohnjiang mq = dev->data->tx_queues[i]; 5974418919fSjohnjiang else 5984418919fSjohnjiang continue; 5994418919fSjohnjiang } else { 6004418919fSjohnjiang if (dev->data->rx_queues != NULL) 6014418919fSjohnjiang mq = dev->data->rx_queues[i]; 6024418919fSjohnjiang else 6034418919fSjohnjiang continue; 6044418919fSjohnjiang } 6054418919fSjohnjiang if (mq->intr_handle.fd > 0) { 6064418919fSjohnjiang close(mq->intr_handle.fd); 6074418919fSjohnjiang mq->intr_handle.fd = -1; 6084418919fSjohnjiang } 6094418919fSjohnjiang } 6104418919fSjohnjiang 6114418919fSjohnjiang memif_free_regions(dev); 6124418919fSjohnjiang 6134418919fSjohnjiang /* reset connection configuration */ 6144418919fSjohnjiang memset(&pmd->run, 0, sizeof(pmd->run)); 6154418919fSjohnjiang 6164418919fSjohnjiang MIF_LOG(DEBUG, "Disconnected."); 6174418919fSjohnjiang } 6184418919fSjohnjiang 6194418919fSjohnjiang static int 6204418919fSjohnjiang memif_msg_receive(struct memif_control_channel *cc) 6214418919fSjohnjiang { 6224418919fSjohnjiang char ctl[CMSG_SPACE(sizeof(int)) + 6234418919fSjohnjiang CMSG_SPACE(sizeof(struct ucred))] = { 0 }; 6244418919fSjohnjiang struct msghdr mh = { 0 }; 6254418919fSjohnjiang struct iovec iov[1]; 6264418919fSjohnjiang memif_msg_t msg = { 0 }; 6274418919fSjohnjiang ssize_t size; 6284418919fSjohnjiang int ret = 0; 6294418919fSjohnjiang struct ucred *cr __rte_unused; 6304418919fSjohnjiang cr = 0; 6314418919fSjohnjiang struct cmsghdr *cmsg; 6324418919fSjohnjiang int afd = -1; 6334418919fSjohnjiang int i; 6344418919fSjohnjiang struct pmd_internals *pmd; 6354418919fSjohnjiang struct pmd_process_private *proc_private; 6364418919fSjohnjiang 6374418919fSjohnjiang iov[0].iov_base = (void *)&msg; 6384418919fSjohnjiang iov[0].iov_len = sizeof(memif_msg_t); 6394418919fSjohnjiang mh.msg_iov = iov; 6404418919fSjohnjiang mh.msg_iovlen = 1; 6414418919fSjohnjiang mh.msg_control = ctl; 6424418919fSjohnjiang mh.msg_controllen = sizeof(ctl); 6434418919fSjohnjiang 6444418919fSjohnjiang size = recvmsg(cc->intr_handle.fd, &mh, 0); 6454418919fSjohnjiang if (size != sizeof(memif_msg_t)) { 6464418919fSjohnjiang MIF_LOG(DEBUG, "Invalid message size."); 6474418919fSjohnjiang memif_msg_enq_disconnect(cc, "Invalid message size", 0); 6484418919fSjohnjiang return -1; 6494418919fSjohnjiang } 6504418919fSjohnjiang MIF_LOG(DEBUG, "Received msg type: %u.", msg.type); 6514418919fSjohnjiang 6524418919fSjohnjiang cmsg = CMSG_FIRSTHDR(&mh); 6534418919fSjohnjiang while (cmsg) { 6544418919fSjohnjiang if (cmsg->cmsg_level == SOL_SOCKET) { 6554418919fSjohnjiang if (cmsg->cmsg_type == SCM_CREDENTIALS) 6564418919fSjohnjiang cr = (struct ucred *)CMSG_DATA(cmsg); 6574418919fSjohnjiang else if (cmsg->cmsg_type == SCM_RIGHTS) 6584418919fSjohnjiang rte_memcpy(&afd, CMSG_DATA(cmsg), sizeof(int)); 6594418919fSjohnjiang } 6604418919fSjohnjiang cmsg = CMSG_NXTHDR(&mh, cmsg); 6614418919fSjohnjiang } 6624418919fSjohnjiang 6634418919fSjohnjiang if (cc->dev == NULL && msg.type != MEMIF_MSG_TYPE_INIT) { 6644418919fSjohnjiang MIF_LOG(DEBUG, "Unexpected message."); 6654418919fSjohnjiang memif_msg_enq_disconnect(cc, "Unexpected message", 0); 6664418919fSjohnjiang return -1; 6674418919fSjohnjiang } 6684418919fSjohnjiang 6694418919fSjohnjiang /* get device from hash data */ 6704418919fSjohnjiang switch (msg.type) { 6714418919fSjohnjiang case MEMIF_MSG_TYPE_ACK: 6724418919fSjohnjiang break; 6734418919fSjohnjiang case MEMIF_MSG_TYPE_HELLO: 6744418919fSjohnjiang ret = memif_msg_receive_hello(cc->dev, &msg); 6754418919fSjohnjiang if (ret < 0) 6764418919fSjohnjiang goto exit; 6774418919fSjohnjiang ret = memif_init_regions_and_queues(cc->dev); 6784418919fSjohnjiang if (ret < 0) 6794418919fSjohnjiang goto exit; 6804418919fSjohnjiang ret = memif_msg_enq_init(cc->dev); 6814418919fSjohnjiang if (ret < 0) 6824418919fSjohnjiang goto exit; 6834418919fSjohnjiang pmd = cc->dev->data->dev_private; 6844418919fSjohnjiang proc_private = cc->dev->process_private; 6854418919fSjohnjiang for (i = 0; i < proc_private->regions_num; i++) { 6864418919fSjohnjiang ret = memif_msg_enq_add_region(cc->dev, i); 6874418919fSjohnjiang if (ret < 0) 6884418919fSjohnjiang goto exit; 6894418919fSjohnjiang } 6904418919fSjohnjiang for (i = 0; i < pmd->run.num_s2m_rings; i++) { 6914418919fSjohnjiang ret = memif_msg_enq_add_ring(cc->dev, i, 6924418919fSjohnjiang MEMIF_RING_S2M); 6934418919fSjohnjiang if (ret < 0) 6944418919fSjohnjiang goto exit; 6954418919fSjohnjiang } 6964418919fSjohnjiang for (i = 0; i < pmd->run.num_m2s_rings; i++) { 6974418919fSjohnjiang ret = memif_msg_enq_add_ring(cc->dev, i, 6984418919fSjohnjiang MEMIF_RING_M2S); 6994418919fSjohnjiang if (ret < 0) 7004418919fSjohnjiang goto exit; 7014418919fSjohnjiang } 7024418919fSjohnjiang ret = memif_msg_enq_connect(cc->dev); 7034418919fSjohnjiang if (ret < 0) 7044418919fSjohnjiang goto exit; 7054418919fSjohnjiang break; 7064418919fSjohnjiang case MEMIF_MSG_TYPE_INIT: 7074418919fSjohnjiang /* 7084418919fSjohnjiang * This cc does not have an interface asociated with it. 7094418919fSjohnjiang * If suitable interface is found it will be assigned here. 7104418919fSjohnjiang */ 7114418919fSjohnjiang ret = memif_msg_receive_init(cc, &msg); 7124418919fSjohnjiang if (ret < 0) 7134418919fSjohnjiang goto exit; 7144418919fSjohnjiang ret = memif_msg_enq_ack(cc->dev); 7154418919fSjohnjiang if (ret < 0) 7164418919fSjohnjiang goto exit; 7174418919fSjohnjiang break; 7184418919fSjohnjiang case MEMIF_MSG_TYPE_ADD_REGION: 7194418919fSjohnjiang ret = memif_msg_receive_add_region(cc->dev, &msg, afd); 7204418919fSjohnjiang if (ret < 0) 7214418919fSjohnjiang goto exit; 7224418919fSjohnjiang ret = memif_msg_enq_ack(cc->dev); 7234418919fSjohnjiang if (ret < 0) 7244418919fSjohnjiang goto exit; 7254418919fSjohnjiang break; 7264418919fSjohnjiang case MEMIF_MSG_TYPE_ADD_RING: 7274418919fSjohnjiang ret = memif_msg_receive_add_ring(cc->dev, &msg, afd); 7284418919fSjohnjiang if (ret < 0) 7294418919fSjohnjiang goto exit; 7304418919fSjohnjiang ret = memif_msg_enq_ack(cc->dev); 7314418919fSjohnjiang if (ret < 0) 7324418919fSjohnjiang goto exit; 7334418919fSjohnjiang break; 7344418919fSjohnjiang case MEMIF_MSG_TYPE_CONNECT: 7354418919fSjohnjiang ret = memif_msg_receive_connect(cc->dev, &msg); 7364418919fSjohnjiang if (ret < 0) 7374418919fSjohnjiang goto exit; 7384418919fSjohnjiang ret = memif_msg_enq_connected(cc->dev); 7394418919fSjohnjiang if (ret < 0) 7404418919fSjohnjiang goto exit; 7414418919fSjohnjiang break; 7424418919fSjohnjiang case MEMIF_MSG_TYPE_CONNECTED: 7434418919fSjohnjiang ret = memif_msg_receive_connected(cc->dev, &msg); 7444418919fSjohnjiang break; 7454418919fSjohnjiang case MEMIF_MSG_TYPE_DISCONNECT: 7464418919fSjohnjiang ret = memif_msg_receive_disconnect(cc->dev, &msg); 7474418919fSjohnjiang if (ret < 0) 7484418919fSjohnjiang goto exit; 7494418919fSjohnjiang break; 7504418919fSjohnjiang default: 7514418919fSjohnjiang memif_msg_enq_disconnect(cc, "Unknown message type", 0); 7524418919fSjohnjiang ret = -1; 7534418919fSjohnjiang goto exit; 7544418919fSjohnjiang } 7554418919fSjohnjiang 7564418919fSjohnjiang exit: 7574418919fSjohnjiang return ret; 7584418919fSjohnjiang } 7594418919fSjohnjiang 7604418919fSjohnjiang static void 7614418919fSjohnjiang memif_intr_handler(void *arg) 7624418919fSjohnjiang { 7634418919fSjohnjiang struct memif_control_channel *cc = arg; 7644418919fSjohnjiang int ret; 7654418919fSjohnjiang 7664418919fSjohnjiang ret = memif_msg_receive(cc); 7674418919fSjohnjiang /* if driver failed to assign device */ 7684418919fSjohnjiang if (cc->dev == NULL) { 769*0c6bd470Sfengbojiang memif_msg_send_from_queue(cc); 7704418919fSjohnjiang ret = rte_intr_callback_unregister_pending(&cc->intr_handle, 7714418919fSjohnjiang memif_intr_handler, 7724418919fSjohnjiang cc, 7734418919fSjohnjiang memif_intr_unregister_handler); 7744418919fSjohnjiang if (ret < 0) 7754418919fSjohnjiang MIF_LOG(WARNING, 7764418919fSjohnjiang "Failed to unregister control channel callback."); 7774418919fSjohnjiang return; 7784418919fSjohnjiang } 7794418919fSjohnjiang /* if memif_msg_receive failed */ 7804418919fSjohnjiang if (ret < 0) 7814418919fSjohnjiang goto disconnect; 7824418919fSjohnjiang 7834418919fSjohnjiang ret = memif_msg_send_from_queue(cc); 7844418919fSjohnjiang if (ret < 0) 7854418919fSjohnjiang goto disconnect; 7864418919fSjohnjiang 7874418919fSjohnjiang return; 7884418919fSjohnjiang 7894418919fSjohnjiang disconnect: 7904418919fSjohnjiang if (cc->dev == NULL) { 7914418919fSjohnjiang MIF_LOG(WARNING, "eth dev not allocated"); 7924418919fSjohnjiang return; 7934418919fSjohnjiang } 7944418919fSjohnjiang memif_disconnect(cc->dev); 7954418919fSjohnjiang } 7964418919fSjohnjiang 7974418919fSjohnjiang static void 7984418919fSjohnjiang memif_listener_handler(void *arg) 7994418919fSjohnjiang { 8004418919fSjohnjiang struct memif_socket *socket = arg; 8014418919fSjohnjiang int sockfd; 8024418919fSjohnjiang int addr_len; 8034418919fSjohnjiang struct sockaddr_un client; 8044418919fSjohnjiang struct memif_control_channel *cc; 8054418919fSjohnjiang int ret; 8064418919fSjohnjiang 8074418919fSjohnjiang addr_len = sizeof(client); 8084418919fSjohnjiang sockfd = accept(socket->intr_handle.fd, (struct sockaddr *)&client, 8094418919fSjohnjiang (socklen_t *)&addr_len); 8104418919fSjohnjiang if (sockfd < 0) { 8114418919fSjohnjiang MIF_LOG(ERR, 8124418919fSjohnjiang "Failed to accept connection request on socket fd %d", 8134418919fSjohnjiang socket->intr_handle.fd); 8144418919fSjohnjiang return; 8154418919fSjohnjiang } 8164418919fSjohnjiang 8174418919fSjohnjiang MIF_LOG(DEBUG, "%s: Connection request accepted.", socket->filename); 8184418919fSjohnjiang 8194418919fSjohnjiang cc = rte_zmalloc("memif-cc", sizeof(struct memif_control_channel), 0); 8204418919fSjohnjiang if (cc == NULL) { 8214418919fSjohnjiang MIF_LOG(ERR, "Failed to allocate control channel."); 8224418919fSjohnjiang goto error; 8234418919fSjohnjiang } 8244418919fSjohnjiang 8254418919fSjohnjiang cc->intr_handle.fd = sockfd; 8264418919fSjohnjiang cc->intr_handle.type = RTE_INTR_HANDLE_EXT; 8274418919fSjohnjiang cc->socket = socket; 8284418919fSjohnjiang cc->dev = NULL; 8294418919fSjohnjiang TAILQ_INIT(&cc->msg_queue); 8304418919fSjohnjiang 8314418919fSjohnjiang ret = rte_intr_callback_register(&cc->intr_handle, memif_intr_handler, cc); 8324418919fSjohnjiang if (ret < 0) { 8334418919fSjohnjiang MIF_LOG(ERR, "Failed to register control channel callback."); 8344418919fSjohnjiang goto error; 8354418919fSjohnjiang } 8364418919fSjohnjiang 8374418919fSjohnjiang ret = memif_msg_enq_hello(cc); 8384418919fSjohnjiang if (ret < 0) { 8394418919fSjohnjiang MIF_LOG(ERR, "Failed to enqueue hello message."); 8404418919fSjohnjiang goto error; 8414418919fSjohnjiang } 8424418919fSjohnjiang ret = memif_msg_send_from_queue(cc); 8434418919fSjohnjiang if (ret < 0) 8444418919fSjohnjiang goto error; 8454418919fSjohnjiang 8464418919fSjohnjiang return; 8474418919fSjohnjiang 8484418919fSjohnjiang error: 8494418919fSjohnjiang if (sockfd >= 0) { 8504418919fSjohnjiang close(sockfd); 8514418919fSjohnjiang sockfd = -1; 8524418919fSjohnjiang } 8534418919fSjohnjiang if (cc != NULL) 8544418919fSjohnjiang rte_free(cc); 8554418919fSjohnjiang } 8564418919fSjohnjiang 8574418919fSjohnjiang static struct memif_socket * 8584418919fSjohnjiang memif_socket_create(char *key, uint8_t listener) 8594418919fSjohnjiang { 8604418919fSjohnjiang struct memif_socket *sock; 8614418919fSjohnjiang struct sockaddr_un un; 8624418919fSjohnjiang int sockfd; 8634418919fSjohnjiang int ret; 8644418919fSjohnjiang int on = 1; 8654418919fSjohnjiang 8664418919fSjohnjiang sock = rte_zmalloc("memif-socket", sizeof(struct memif_socket), 0); 8674418919fSjohnjiang if (sock == NULL) { 8684418919fSjohnjiang MIF_LOG(ERR, "Failed to allocate memory for memif socket"); 8694418919fSjohnjiang return NULL; 8704418919fSjohnjiang } 8714418919fSjohnjiang 8724418919fSjohnjiang sock->listener = listener; 8734418919fSjohnjiang strlcpy(sock->filename, key, MEMIF_SOCKET_UN_SIZE); 8744418919fSjohnjiang TAILQ_INIT(&sock->dev_queue); 8754418919fSjohnjiang 8764418919fSjohnjiang if (listener != 0) { 8774418919fSjohnjiang sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 8784418919fSjohnjiang if (sockfd < 0) 8794418919fSjohnjiang goto error; 8804418919fSjohnjiang 8814418919fSjohnjiang un.sun_family = AF_UNIX; 8824418919fSjohnjiang strlcpy(un.sun_path, sock->filename, MEMIF_SOCKET_UN_SIZE); 8834418919fSjohnjiang 8844418919fSjohnjiang ret = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &on, 8854418919fSjohnjiang sizeof(on)); 8864418919fSjohnjiang if (ret < 0) 8874418919fSjohnjiang goto error; 8884418919fSjohnjiang 8894418919fSjohnjiang ret = bind(sockfd, (struct sockaddr *)&un, sizeof(un)); 8904418919fSjohnjiang if (ret < 0) 8914418919fSjohnjiang goto error; 8924418919fSjohnjiang 8934418919fSjohnjiang ret = listen(sockfd, 1); 8944418919fSjohnjiang if (ret < 0) 8954418919fSjohnjiang goto error; 8964418919fSjohnjiang 8974418919fSjohnjiang MIF_LOG(DEBUG, "Memif listener socket %s created.", sock->filename); 8984418919fSjohnjiang 8994418919fSjohnjiang sock->intr_handle.fd = sockfd; 9004418919fSjohnjiang sock->intr_handle.type = RTE_INTR_HANDLE_EXT; 9014418919fSjohnjiang ret = rte_intr_callback_register(&sock->intr_handle, 9024418919fSjohnjiang memif_listener_handler, sock); 9034418919fSjohnjiang if (ret < 0) { 9044418919fSjohnjiang MIF_LOG(ERR, "Failed to register interrupt " 9054418919fSjohnjiang "callback for listener socket"); 9064418919fSjohnjiang return NULL; 9074418919fSjohnjiang } 9084418919fSjohnjiang } 9094418919fSjohnjiang 9104418919fSjohnjiang return sock; 9114418919fSjohnjiang 9124418919fSjohnjiang error: 9134418919fSjohnjiang MIF_LOG(ERR, "Failed to setup socket %s: %s", key, strerror(errno)); 9144418919fSjohnjiang if (sock != NULL) 9154418919fSjohnjiang rte_free(sock); 9164418919fSjohnjiang if (sockfd >= 0) 9174418919fSjohnjiang close(sockfd); 9184418919fSjohnjiang return NULL; 9194418919fSjohnjiang } 9204418919fSjohnjiang 9214418919fSjohnjiang static struct rte_hash * 9224418919fSjohnjiang memif_create_socket_hash(void) 9234418919fSjohnjiang { 9244418919fSjohnjiang struct rte_hash_parameters params = { 0 }; 9254418919fSjohnjiang 9264418919fSjohnjiang params.name = MEMIF_SOCKET_HASH_NAME; 9274418919fSjohnjiang params.entries = 256; 9284418919fSjohnjiang params.key_len = MEMIF_SOCKET_UN_SIZE; 9294418919fSjohnjiang params.hash_func = rte_jhash; 9304418919fSjohnjiang params.hash_func_init_val = 0; 9314418919fSjohnjiang return rte_hash_create(¶ms); 9324418919fSjohnjiang } 9334418919fSjohnjiang 9344418919fSjohnjiang int 9354418919fSjohnjiang memif_socket_init(struct rte_eth_dev *dev, const char *socket_filename) 9364418919fSjohnjiang { 9374418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 9384418919fSjohnjiang struct memif_socket *socket = NULL; 9394418919fSjohnjiang struct memif_socket_dev_list_elt *elt; 9404418919fSjohnjiang struct pmd_internals *tmp_pmd; 9414418919fSjohnjiang struct rte_hash *hash; 9424418919fSjohnjiang int ret; 9434418919fSjohnjiang char key[MEMIF_SOCKET_UN_SIZE]; 9444418919fSjohnjiang 9454418919fSjohnjiang hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME); 9464418919fSjohnjiang if (hash == NULL) { 9474418919fSjohnjiang hash = memif_create_socket_hash(); 9484418919fSjohnjiang if (hash == NULL) { 9494418919fSjohnjiang MIF_LOG(ERR, "Failed to create memif socket hash."); 9504418919fSjohnjiang return -1; 9514418919fSjohnjiang } 9524418919fSjohnjiang } 9534418919fSjohnjiang 9544418919fSjohnjiang memset(key, 0, MEMIF_SOCKET_UN_SIZE); 9554418919fSjohnjiang strlcpy(key, socket_filename, MEMIF_SOCKET_UN_SIZE); 9564418919fSjohnjiang ret = rte_hash_lookup_data(hash, key, (void **)&socket); 9574418919fSjohnjiang if (ret < 0) { 9584418919fSjohnjiang socket = memif_socket_create(key, 9594418919fSjohnjiang (pmd->role == MEMIF_ROLE_SLAVE) ? 0 : 1); 9604418919fSjohnjiang if (socket == NULL) 9614418919fSjohnjiang return -1; 9624418919fSjohnjiang ret = rte_hash_add_key_data(hash, key, socket); 9634418919fSjohnjiang if (ret < 0) { 9644418919fSjohnjiang MIF_LOG(ERR, "Failed to add socket to socket hash."); 9654418919fSjohnjiang return ret; 9664418919fSjohnjiang } 9674418919fSjohnjiang } 9684418919fSjohnjiang pmd->socket_filename = socket->filename; 9694418919fSjohnjiang 9704418919fSjohnjiang if (socket->listener != 0 && pmd->role == MEMIF_ROLE_SLAVE) { 9714418919fSjohnjiang MIF_LOG(ERR, "Socket is a listener."); 9724418919fSjohnjiang return -1; 9734418919fSjohnjiang } else if ((socket->listener == 0) && (pmd->role == MEMIF_ROLE_MASTER)) { 9744418919fSjohnjiang MIF_LOG(ERR, "Socket is not a listener."); 9754418919fSjohnjiang return -1; 9764418919fSjohnjiang } 9774418919fSjohnjiang 9784418919fSjohnjiang TAILQ_FOREACH(elt, &socket->dev_queue, next) { 9794418919fSjohnjiang tmp_pmd = elt->dev->data->dev_private; 9804418919fSjohnjiang if (tmp_pmd->id == pmd->id) { 9814418919fSjohnjiang MIF_LOG(ERR, "Memif device with id %d already " 9824418919fSjohnjiang "exists on socket %s", 9834418919fSjohnjiang pmd->id, socket->filename); 9844418919fSjohnjiang return -1; 9854418919fSjohnjiang } 9864418919fSjohnjiang } 9874418919fSjohnjiang 9884418919fSjohnjiang elt = rte_malloc("pmd-queue", sizeof(struct memif_socket_dev_list_elt), 0); 9894418919fSjohnjiang if (elt == NULL) { 9904418919fSjohnjiang MIF_LOG(ERR, "Failed to add device to socket device list."); 9914418919fSjohnjiang return -1; 9924418919fSjohnjiang } 9934418919fSjohnjiang elt->dev = dev; 9944418919fSjohnjiang TAILQ_INSERT_TAIL(&socket->dev_queue, elt, next); 9954418919fSjohnjiang 9964418919fSjohnjiang return 0; 9974418919fSjohnjiang } 9984418919fSjohnjiang 9994418919fSjohnjiang void 10004418919fSjohnjiang memif_socket_remove_device(struct rte_eth_dev *dev) 10014418919fSjohnjiang { 10024418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 10034418919fSjohnjiang struct memif_socket *socket = NULL; 10044418919fSjohnjiang struct memif_socket_dev_list_elt *elt, *next; 10054418919fSjohnjiang struct rte_hash *hash; 10064418919fSjohnjiang int ret; 10074418919fSjohnjiang 10084418919fSjohnjiang hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME); 10094418919fSjohnjiang if (hash == NULL) 10104418919fSjohnjiang return; 10114418919fSjohnjiang 10124418919fSjohnjiang if (pmd->socket_filename == NULL) 10134418919fSjohnjiang return; 10144418919fSjohnjiang 10154418919fSjohnjiang if (rte_hash_lookup_data(hash, pmd->socket_filename, (void **)&socket) < 0) 10164418919fSjohnjiang return; 10174418919fSjohnjiang 10184418919fSjohnjiang for (elt = TAILQ_FIRST(&socket->dev_queue); elt != NULL; elt = next) { 10194418919fSjohnjiang next = TAILQ_NEXT(elt, next); 10204418919fSjohnjiang if (elt->dev == dev) { 10214418919fSjohnjiang TAILQ_REMOVE(&socket->dev_queue, elt, next); 10224418919fSjohnjiang rte_free(elt); 10234418919fSjohnjiang pmd->socket_filename = NULL; 10244418919fSjohnjiang } 10254418919fSjohnjiang } 10264418919fSjohnjiang 10274418919fSjohnjiang /* remove socket, if this was the last device using it */ 10284418919fSjohnjiang if (TAILQ_EMPTY(&socket->dev_queue)) { 10294418919fSjohnjiang rte_hash_del_key(hash, socket->filename); 10304418919fSjohnjiang if (socket->listener) { 10314418919fSjohnjiang /* remove listener socket file, 10324418919fSjohnjiang * so we can create new one later. 10334418919fSjohnjiang */ 10344418919fSjohnjiang ret = remove(socket->filename); 10354418919fSjohnjiang if (ret < 0) 10364418919fSjohnjiang MIF_LOG(ERR, "Failed to remove socket file: %s", 10374418919fSjohnjiang socket->filename); 10384418919fSjohnjiang } 10394418919fSjohnjiang rte_free(socket); 10404418919fSjohnjiang } 10414418919fSjohnjiang } 10424418919fSjohnjiang 10434418919fSjohnjiang int 10444418919fSjohnjiang memif_connect_master(struct rte_eth_dev *dev) 10454418919fSjohnjiang { 10464418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 10474418919fSjohnjiang 10484418919fSjohnjiang memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 10494418919fSjohnjiang memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 10504418919fSjohnjiang pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED; 10514418919fSjohnjiang return 0; 10524418919fSjohnjiang } 10534418919fSjohnjiang 10544418919fSjohnjiang int 10554418919fSjohnjiang memif_connect_slave(struct rte_eth_dev *dev) 10564418919fSjohnjiang { 10574418919fSjohnjiang int sockfd; 10584418919fSjohnjiang int ret; 10594418919fSjohnjiang struct sockaddr_un sun; 10604418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 10614418919fSjohnjiang 10624418919fSjohnjiang memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 10634418919fSjohnjiang memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 10644418919fSjohnjiang pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED; 10654418919fSjohnjiang 10664418919fSjohnjiang sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 10674418919fSjohnjiang if (sockfd < 0) { 10684418919fSjohnjiang MIF_LOG(ERR, "Failed to open socket."); 10694418919fSjohnjiang return -1; 10704418919fSjohnjiang } 10714418919fSjohnjiang 10724418919fSjohnjiang sun.sun_family = AF_UNIX; 10734418919fSjohnjiang 10744418919fSjohnjiang memcpy(sun.sun_path, pmd->socket_filename, sizeof(sun.sun_path) - 1); 10754418919fSjohnjiang 10764418919fSjohnjiang ret = connect(sockfd, (struct sockaddr *)&sun, 10774418919fSjohnjiang sizeof(struct sockaddr_un)); 10784418919fSjohnjiang if (ret < 0) { 10794418919fSjohnjiang MIF_LOG(ERR, "Failed to connect socket: %s.", pmd->socket_filename); 10804418919fSjohnjiang goto error; 10814418919fSjohnjiang } 10824418919fSjohnjiang 10834418919fSjohnjiang MIF_LOG(DEBUG, "Memif socket: %s connected.", pmd->socket_filename); 10844418919fSjohnjiang 10854418919fSjohnjiang pmd->cc = rte_zmalloc("memif-cc", 10864418919fSjohnjiang sizeof(struct memif_control_channel), 0); 10874418919fSjohnjiang if (pmd->cc == NULL) { 10884418919fSjohnjiang MIF_LOG(ERR, "Failed to allocate control channel."); 10894418919fSjohnjiang goto error; 10904418919fSjohnjiang } 10914418919fSjohnjiang 10924418919fSjohnjiang pmd->cc->intr_handle.fd = sockfd; 10934418919fSjohnjiang pmd->cc->intr_handle.type = RTE_INTR_HANDLE_EXT; 10944418919fSjohnjiang pmd->cc->socket = NULL; 10954418919fSjohnjiang pmd->cc->dev = dev; 10964418919fSjohnjiang TAILQ_INIT(&pmd->cc->msg_queue); 10974418919fSjohnjiang 10984418919fSjohnjiang ret = rte_intr_callback_register(&pmd->cc->intr_handle, 10994418919fSjohnjiang memif_intr_handler, pmd->cc); 11004418919fSjohnjiang if (ret < 0) { 11014418919fSjohnjiang MIF_LOG(ERR, "Failed to register interrupt callback for control fd"); 11024418919fSjohnjiang goto error; 11034418919fSjohnjiang } 11044418919fSjohnjiang 11054418919fSjohnjiang return 0; 11064418919fSjohnjiang 11074418919fSjohnjiang error: 11084418919fSjohnjiang if (sockfd >= 0) { 11094418919fSjohnjiang close(sockfd); 11104418919fSjohnjiang sockfd = -1; 11114418919fSjohnjiang } 11124418919fSjohnjiang if (pmd->cc != NULL) { 11134418919fSjohnjiang rte_free(pmd->cc); 11144418919fSjohnjiang pmd->cc = NULL; 11154418919fSjohnjiang } 11164418919fSjohnjiang return -1; 11174418919fSjohnjiang } 1118