1*4418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause 2*4418919fSjohnjiang * Copyright 2018-2019 Cisco Systems, Inc. All rights reserved. 3*4418919fSjohnjiang */ 4*4418919fSjohnjiang 5*4418919fSjohnjiang #include <stdlib.h> 6*4418919fSjohnjiang #include <fcntl.h> 7*4418919fSjohnjiang #include <unistd.h> 8*4418919fSjohnjiang #include <sys/types.h> 9*4418919fSjohnjiang #include <sys/socket.h> 10*4418919fSjohnjiang #include <sys/ioctl.h> 11*4418919fSjohnjiang #include <errno.h> 12*4418919fSjohnjiang 13*4418919fSjohnjiang #include <rte_version.h> 14*4418919fSjohnjiang #include <rte_mbuf.h> 15*4418919fSjohnjiang #include <rte_ether.h> 16*4418919fSjohnjiang #include <rte_ethdev_driver.h> 17*4418919fSjohnjiang #include <rte_ethdev_vdev.h> 18*4418919fSjohnjiang #include <rte_malloc.h> 19*4418919fSjohnjiang #include <rte_kvargs.h> 20*4418919fSjohnjiang #include <rte_bus_vdev.h> 21*4418919fSjohnjiang #include <rte_hash.h> 22*4418919fSjohnjiang #include <rte_jhash.h> 23*4418919fSjohnjiang #include <rte_string_fns.h> 24*4418919fSjohnjiang 25*4418919fSjohnjiang #include "rte_eth_memif.h" 26*4418919fSjohnjiang #include "memif_socket.h" 27*4418919fSjohnjiang 28*4418919fSjohnjiang static void memif_intr_handler(void *arg); 29*4418919fSjohnjiang 30*4418919fSjohnjiang static ssize_t 31*4418919fSjohnjiang memif_msg_send(int fd, memif_msg_t *msg, int afd) 32*4418919fSjohnjiang { 33*4418919fSjohnjiang struct msghdr mh = { 0 }; 34*4418919fSjohnjiang struct iovec iov[1]; 35*4418919fSjohnjiang struct cmsghdr *cmsg; 36*4418919fSjohnjiang char ctl[CMSG_SPACE(sizeof(int))]; 37*4418919fSjohnjiang 38*4418919fSjohnjiang iov[0].iov_base = msg; 39*4418919fSjohnjiang iov[0].iov_len = sizeof(memif_msg_t); 40*4418919fSjohnjiang mh.msg_iov = iov; 41*4418919fSjohnjiang mh.msg_iovlen = 1; 42*4418919fSjohnjiang 43*4418919fSjohnjiang if (afd > 0) { 44*4418919fSjohnjiang memset(&ctl, 0, sizeof(ctl)); 45*4418919fSjohnjiang mh.msg_control = ctl; 46*4418919fSjohnjiang mh.msg_controllen = sizeof(ctl); 47*4418919fSjohnjiang cmsg = CMSG_FIRSTHDR(&mh); 48*4418919fSjohnjiang cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 49*4418919fSjohnjiang cmsg->cmsg_level = SOL_SOCKET; 50*4418919fSjohnjiang cmsg->cmsg_type = SCM_RIGHTS; 51*4418919fSjohnjiang rte_memcpy(CMSG_DATA(cmsg), &afd, sizeof(int)); 52*4418919fSjohnjiang } 53*4418919fSjohnjiang 54*4418919fSjohnjiang return sendmsg(fd, &mh, 0); 55*4418919fSjohnjiang } 56*4418919fSjohnjiang 57*4418919fSjohnjiang static int 58*4418919fSjohnjiang memif_msg_send_from_queue(struct memif_control_channel *cc) 59*4418919fSjohnjiang { 60*4418919fSjohnjiang ssize_t size; 61*4418919fSjohnjiang int ret = 0; 62*4418919fSjohnjiang struct memif_msg_queue_elt *e; 63*4418919fSjohnjiang 64*4418919fSjohnjiang e = TAILQ_FIRST(&cc->msg_queue); 65*4418919fSjohnjiang if (e == NULL) 66*4418919fSjohnjiang return 0; 67*4418919fSjohnjiang 68*4418919fSjohnjiang size = memif_msg_send(cc->intr_handle.fd, &e->msg, e->fd); 69*4418919fSjohnjiang if (size != sizeof(memif_msg_t)) { 70*4418919fSjohnjiang MIF_LOG(ERR, "sendmsg fail: %s.", strerror(errno)); 71*4418919fSjohnjiang ret = -1; 72*4418919fSjohnjiang } else { 73*4418919fSjohnjiang MIF_LOG(DEBUG, "Sent msg type %u.", e->msg.type); 74*4418919fSjohnjiang } 75*4418919fSjohnjiang TAILQ_REMOVE(&cc->msg_queue, e, next); 76*4418919fSjohnjiang rte_free(e); 77*4418919fSjohnjiang 78*4418919fSjohnjiang return ret; 79*4418919fSjohnjiang } 80*4418919fSjohnjiang 81*4418919fSjohnjiang static struct memif_msg_queue_elt * 82*4418919fSjohnjiang memif_msg_enq(struct memif_control_channel *cc) 83*4418919fSjohnjiang { 84*4418919fSjohnjiang struct memif_msg_queue_elt *e; 85*4418919fSjohnjiang 86*4418919fSjohnjiang e = rte_zmalloc("memif_msg", sizeof(struct memif_msg_queue_elt), 0); 87*4418919fSjohnjiang if (e == NULL) { 88*4418919fSjohnjiang MIF_LOG(ERR, "Failed to allocate control message."); 89*4418919fSjohnjiang return NULL; 90*4418919fSjohnjiang } 91*4418919fSjohnjiang 92*4418919fSjohnjiang e->fd = -1; 93*4418919fSjohnjiang TAILQ_INSERT_TAIL(&cc->msg_queue, e, next); 94*4418919fSjohnjiang 95*4418919fSjohnjiang return e; 96*4418919fSjohnjiang } 97*4418919fSjohnjiang 98*4418919fSjohnjiang void 99*4418919fSjohnjiang memif_msg_enq_disconnect(struct memif_control_channel *cc, const char *reason, 100*4418919fSjohnjiang int err_code) 101*4418919fSjohnjiang { 102*4418919fSjohnjiang struct memif_msg_queue_elt *e; 103*4418919fSjohnjiang struct pmd_internals *pmd; 104*4418919fSjohnjiang memif_msg_disconnect_t *d; 105*4418919fSjohnjiang 106*4418919fSjohnjiang if (cc == NULL) { 107*4418919fSjohnjiang MIF_LOG(DEBUG, "Missing control channel."); 108*4418919fSjohnjiang return; 109*4418919fSjohnjiang } 110*4418919fSjohnjiang 111*4418919fSjohnjiang e = memif_msg_enq(cc); 112*4418919fSjohnjiang if (e == NULL) { 113*4418919fSjohnjiang MIF_LOG(WARNING, "Failed to enqueue disconnect message."); 114*4418919fSjohnjiang return; 115*4418919fSjohnjiang } 116*4418919fSjohnjiang 117*4418919fSjohnjiang d = &e->msg.disconnect; 118*4418919fSjohnjiang 119*4418919fSjohnjiang e->msg.type = MEMIF_MSG_TYPE_DISCONNECT; 120*4418919fSjohnjiang d->code = err_code; 121*4418919fSjohnjiang 122*4418919fSjohnjiang if (reason != NULL) { 123*4418919fSjohnjiang strlcpy((char *)d->string, reason, sizeof(d->string)); 124*4418919fSjohnjiang if (cc->dev != NULL) { 125*4418919fSjohnjiang pmd = cc->dev->data->dev_private; 126*4418919fSjohnjiang strlcpy(pmd->local_disc_string, reason, 127*4418919fSjohnjiang sizeof(pmd->local_disc_string)); 128*4418919fSjohnjiang } 129*4418919fSjohnjiang } 130*4418919fSjohnjiang } 131*4418919fSjohnjiang 132*4418919fSjohnjiang static int 133*4418919fSjohnjiang memif_msg_enq_hello(struct memif_control_channel *cc) 134*4418919fSjohnjiang { 135*4418919fSjohnjiang struct memif_msg_queue_elt *e = memif_msg_enq(cc); 136*4418919fSjohnjiang memif_msg_hello_t *h; 137*4418919fSjohnjiang 138*4418919fSjohnjiang if (e == NULL) 139*4418919fSjohnjiang return -1; 140*4418919fSjohnjiang 141*4418919fSjohnjiang h = &e->msg.hello; 142*4418919fSjohnjiang 143*4418919fSjohnjiang e->msg.type = MEMIF_MSG_TYPE_HELLO; 144*4418919fSjohnjiang h->min_version = MEMIF_VERSION; 145*4418919fSjohnjiang h->max_version = MEMIF_VERSION; 146*4418919fSjohnjiang h->max_s2m_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS; 147*4418919fSjohnjiang h->max_m2s_ring = ETH_MEMIF_MAX_NUM_Q_PAIRS; 148*4418919fSjohnjiang h->max_region = ETH_MEMIF_MAX_REGION_NUM - 1; 149*4418919fSjohnjiang h->max_log2_ring_size = ETH_MEMIF_MAX_LOG2_RING_SIZE; 150*4418919fSjohnjiang 151*4418919fSjohnjiang strlcpy((char *)h->name, rte_version(), sizeof(h->name)); 152*4418919fSjohnjiang 153*4418919fSjohnjiang return 0; 154*4418919fSjohnjiang } 155*4418919fSjohnjiang 156*4418919fSjohnjiang static int 157*4418919fSjohnjiang memif_msg_receive_hello(struct rte_eth_dev *dev, memif_msg_t *msg) 158*4418919fSjohnjiang { 159*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 160*4418919fSjohnjiang memif_msg_hello_t *h = &msg->hello; 161*4418919fSjohnjiang 162*4418919fSjohnjiang if (h->min_version > MEMIF_VERSION || h->max_version < MEMIF_VERSION) { 163*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Incompatible memif version", 0); 164*4418919fSjohnjiang return -1; 165*4418919fSjohnjiang } 166*4418919fSjohnjiang 167*4418919fSjohnjiang /* Set parameters for active connection */ 168*4418919fSjohnjiang pmd->run.num_s2m_rings = RTE_MIN(h->max_s2m_ring + 1, 169*4418919fSjohnjiang pmd->cfg.num_s2m_rings); 170*4418919fSjohnjiang pmd->run.num_m2s_rings = RTE_MIN(h->max_m2s_ring + 1, 171*4418919fSjohnjiang pmd->cfg.num_m2s_rings); 172*4418919fSjohnjiang pmd->run.log2_ring_size = RTE_MIN(h->max_log2_ring_size, 173*4418919fSjohnjiang pmd->cfg.log2_ring_size); 174*4418919fSjohnjiang pmd->run.pkt_buffer_size = pmd->cfg.pkt_buffer_size; 175*4418919fSjohnjiang 176*4418919fSjohnjiang strlcpy(pmd->remote_name, (char *)h->name, sizeof(pmd->remote_name)); 177*4418919fSjohnjiang 178*4418919fSjohnjiang MIF_LOG(DEBUG, "Connecting to %s.", pmd->remote_name); 179*4418919fSjohnjiang 180*4418919fSjohnjiang return 0; 181*4418919fSjohnjiang } 182*4418919fSjohnjiang 183*4418919fSjohnjiang static int 184*4418919fSjohnjiang memif_msg_receive_init(struct memif_control_channel *cc, memif_msg_t *msg) 185*4418919fSjohnjiang { 186*4418919fSjohnjiang memif_msg_init_t *i = &msg->init; 187*4418919fSjohnjiang struct memif_socket_dev_list_elt *elt; 188*4418919fSjohnjiang struct pmd_internals *pmd; 189*4418919fSjohnjiang struct rte_eth_dev *dev; 190*4418919fSjohnjiang 191*4418919fSjohnjiang if (i->version != MEMIF_VERSION) { 192*4418919fSjohnjiang memif_msg_enq_disconnect(cc, "Incompatible memif version", 0); 193*4418919fSjohnjiang return -1; 194*4418919fSjohnjiang } 195*4418919fSjohnjiang 196*4418919fSjohnjiang if (cc->socket == NULL) { 197*4418919fSjohnjiang memif_msg_enq_disconnect(cc, "Device error", 0); 198*4418919fSjohnjiang return -1; 199*4418919fSjohnjiang } 200*4418919fSjohnjiang 201*4418919fSjohnjiang /* Find device with requested ID */ 202*4418919fSjohnjiang TAILQ_FOREACH(elt, &cc->socket->dev_queue, next) { 203*4418919fSjohnjiang dev = elt->dev; 204*4418919fSjohnjiang pmd = dev->data->dev_private; 205*4418919fSjohnjiang if (((pmd->flags & ETH_MEMIF_FLAG_DISABLED) == 0) && 206*4418919fSjohnjiang pmd->id == i->id) { 207*4418919fSjohnjiang /* assign control channel to device */ 208*4418919fSjohnjiang cc->dev = dev; 209*4418919fSjohnjiang pmd->cc = cc; 210*4418919fSjohnjiang 211*4418919fSjohnjiang if (i->mode != MEMIF_INTERFACE_MODE_ETHERNET) { 212*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, 213*4418919fSjohnjiang "Only ethernet mode supported", 214*4418919fSjohnjiang 0); 215*4418919fSjohnjiang return -1; 216*4418919fSjohnjiang } 217*4418919fSjohnjiang 218*4418919fSjohnjiang if (pmd->flags & (ETH_MEMIF_FLAG_CONNECTING | 219*4418919fSjohnjiang ETH_MEMIF_FLAG_CONNECTED)) { 220*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, 221*4418919fSjohnjiang "Already connected", 0); 222*4418919fSjohnjiang return -1; 223*4418919fSjohnjiang } 224*4418919fSjohnjiang strlcpy(pmd->remote_name, (char *)i->name, 225*4418919fSjohnjiang sizeof(pmd->remote_name)); 226*4418919fSjohnjiang 227*4418919fSjohnjiang if (*pmd->secret != '\0') { 228*4418919fSjohnjiang if (*i->secret == '\0') { 229*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, 230*4418919fSjohnjiang "Secret required", 0); 231*4418919fSjohnjiang return -1; 232*4418919fSjohnjiang } 233*4418919fSjohnjiang if (strncmp(pmd->secret, (char *)i->secret, 234*4418919fSjohnjiang ETH_MEMIF_SECRET_SIZE) != 0) { 235*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, 236*4418919fSjohnjiang "Incorrect secret", 0); 237*4418919fSjohnjiang return -1; 238*4418919fSjohnjiang } 239*4418919fSjohnjiang } 240*4418919fSjohnjiang 241*4418919fSjohnjiang pmd->flags |= ETH_MEMIF_FLAG_CONNECTING; 242*4418919fSjohnjiang return 0; 243*4418919fSjohnjiang } 244*4418919fSjohnjiang } 245*4418919fSjohnjiang 246*4418919fSjohnjiang /* ID not found on this socket */ 247*4418919fSjohnjiang MIF_LOG(DEBUG, "ID %u not found.", i->id); 248*4418919fSjohnjiang memif_msg_enq_disconnect(cc, "ID not found", 0); 249*4418919fSjohnjiang return -1; 250*4418919fSjohnjiang } 251*4418919fSjohnjiang 252*4418919fSjohnjiang static int 253*4418919fSjohnjiang memif_msg_receive_add_region(struct rte_eth_dev *dev, memif_msg_t *msg, 254*4418919fSjohnjiang int fd) 255*4418919fSjohnjiang { 256*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 257*4418919fSjohnjiang struct pmd_process_private *proc_private = dev->process_private; 258*4418919fSjohnjiang memif_msg_add_region_t *ar = &msg->add_region; 259*4418919fSjohnjiang struct memif_region *r; 260*4418919fSjohnjiang 261*4418919fSjohnjiang if (fd < 0) { 262*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Missing region fd", 0); 263*4418919fSjohnjiang return -1; 264*4418919fSjohnjiang } 265*4418919fSjohnjiang 266*4418919fSjohnjiang if (ar->index >= ETH_MEMIF_MAX_REGION_NUM || 267*4418919fSjohnjiang ar->index != proc_private->regions_num || 268*4418919fSjohnjiang proc_private->regions[ar->index] != NULL) { 269*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Invalid region index", 0); 270*4418919fSjohnjiang return -1; 271*4418919fSjohnjiang } 272*4418919fSjohnjiang 273*4418919fSjohnjiang r = rte_zmalloc("region", sizeof(struct memif_region), 0); 274*4418919fSjohnjiang if (r == NULL) { 275*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Failed to alloc memif region.", 0); 276*4418919fSjohnjiang return -ENOMEM; 277*4418919fSjohnjiang } 278*4418919fSjohnjiang 279*4418919fSjohnjiang r->fd = fd; 280*4418919fSjohnjiang r->region_size = ar->size; 281*4418919fSjohnjiang r->addr = NULL; 282*4418919fSjohnjiang 283*4418919fSjohnjiang proc_private->regions[ar->index] = r; 284*4418919fSjohnjiang proc_private->regions_num++; 285*4418919fSjohnjiang 286*4418919fSjohnjiang return 0; 287*4418919fSjohnjiang } 288*4418919fSjohnjiang 289*4418919fSjohnjiang static int 290*4418919fSjohnjiang memif_msg_receive_add_ring(struct rte_eth_dev *dev, memif_msg_t *msg, int fd) 291*4418919fSjohnjiang { 292*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 293*4418919fSjohnjiang memif_msg_add_ring_t *ar = &msg->add_ring; 294*4418919fSjohnjiang struct memif_queue *mq; 295*4418919fSjohnjiang 296*4418919fSjohnjiang if (fd < 0) { 297*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Missing interrupt fd", 0); 298*4418919fSjohnjiang return -1; 299*4418919fSjohnjiang } 300*4418919fSjohnjiang 301*4418919fSjohnjiang /* check if we have enough queues */ 302*4418919fSjohnjiang if (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M) { 303*4418919fSjohnjiang if (ar->index >= pmd->cfg.num_s2m_rings) { 304*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0); 305*4418919fSjohnjiang return -1; 306*4418919fSjohnjiang } 307*4418919fSjohnjiang pmd->run.num_s2m_rings++; 308*4418919fSjohnjiang } else { 309*4418919fSjohnjiang if (ar->index >= pmd->cfg.num_m2s_rings) { 310*4418919fSjohnjiang memif_msg_enq_disconnect(pmd->cc, "Invalid ring index", 0); 311*4418919fSjohnjiang return -1; 312*4418919fSjohnjiang } 313*4418919fSjohnjiang pmd->run.num_m2s_rings++; 314*4418919fSjohnjiang } 315*4418919fSjohnjiang 316*4418919fSjohnjiang mq = (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M) ? 317*4418919fSjohnjiang dev->data->rx_queues[ar->index] : dev->data->tx_queues[ar->index]; 318*4418919fSjohnjiang 319*4418919fSjohnjiang mq->intr_handle.fd = fd; 320*4418919fSjohnjiang mq->log2_ring_size = ar->log2_ring_size; 321*4418919fSjohnjiang mq->region = ar->region; 322*4418919fSjohnjiang mq->ring_offset = ar->offset; 323*4418919fSjohnjiang 324*4418919fSjohnjiang return 0; 325*4418919fSjohnjiang } 326*4418919fSjohnjiang 327*4418919fSjohnjiang static int 328*4418919fSjohnjiang memif_msg_receive_connect(struct rte_eth_dev *dev, memif_msg_t *msg) 329*4418919fSjohnjiang { 330*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 331*4418919fSjohnjiang memif_msg_connect_t *c = &msg->connect; 332*4418919fSjohnjiang int ret; 333*4418919fSjohnjiang 334*4418919fSjohnjiang ret = memif_connect(dev); 335*4418919fSjohnjiang if (ret < 0) 336*4418919fSjohnjiang return ret; 337*4418919fSjohnjiang 338*4418919fSjohnjiang strlcpy(pmd->remote_if_name, (char *)c->if_name, 339*4418919fSjohnjiang sizeof(pmd->remote_if_name)); 340*4418919fSjohnjiang MIF_LOG(INFO, "Remote interface %s connected.", pmd->remote_if_name); 341*4418919fSjohnjiang 342*4418919fSjohnjiang return 0; 343*4418919fSjohnjiang } 344*4418919fSjohnjiang 345*4418919fSjohnjiang static int 346*4418919fSjohnjiang memif_msg_receive_connected(struct rte_eth_dev *dev, memif_msg_t *msg) 347*4418919fSjohnjiang { 348*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 349*4418919fSjohnjiang memif_msg_connected_t *c = &msg->connected; 350*4418919fSjohnjiang int ret; 351*4418919fSjohnjiang 352*4418919fSjohnjiang ret = memif_connect(dev); 353*4418919fSjohnjiang if (ret < 0) 354*4418919fSjohnjiang return ret; 355*4418919fSjohnjiang 356*4418919fSjohnjiang strlcpy(pmd->remote_if_name, (char *)c->if_name, 357*4418919fSjohnjiang sizeof(pmd->remote_if_name)); 358*4418919fSjohnjiang MIF_LOG(INFO, "Remote interface %s connected.", pmd->remote_if_name); 359*4418919fSjohnjiang 360*4418919fSjohnjiang return 0; 361*4418919fSjohnjiang } 362*4418919fSjohnjiang 363*4418919fSjohnjiang static int 364*4418919fSjohnjiang memif_msg_receive_disconnect(struct rte_eth_dev *dev, memif_msg_t *msg) 365*4418919fSjohnjiang { 366*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 367*4418919fSjohnjiang memif_msg_disconnect_t *d = &msg->disconnect; 368*4418919fSjohnjiang 369*4418919fSjohnjiang memset(pmd->remote_disc_string, 0, sizeof(pmd->remote_disc_string)); 370*4418919fSjohnjiang strlcpy(pmd->remote_disc_string, (char *)d->string, 371*4418919fSjohnjiang sizeof(pmd->remote_disc_string)); 372*4418919fSjohnjiang 373*4418919fSjohnjiang MIF_LOG(INFO, "Disconnect received: %s", pmd->remote_disc_string); 374*4418919fSjohnjiang 375*4418919fSjohnjiang memset(pmd->local_disc_string, 0, 96); 376*4418919fSjohnjiang memif_disconnect(dev); 377*4418919fSjohnjiang return 0; 378*4418919fSjohnjiang } 379*4418919fSjohnjiang 380*4418919fSjohnjiang static int 381*4418919fSjohnjiang memif_msg_enq_ack(struct rte_eth_dev *dev) 382*4418919fSjohnjiang { 383*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 384*4418919fSjohnjiang struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 385*4418919fSjohnjiang if (e == NULL) 386*4418919fSjohnjiang return -1; 387*4418919fSjohnjiang 388*4418919fSjohnjiang e->msg.type = MEMIF_MSG_TYPE_ACK; 389*4418919fSjohnjiang 390*4418919fSjohnjiang return 0; 391*4418919fSjohnjiang } 392*4418919fSjohnjiang 393*4418919fSjohnjiang static int 394*4418919fSjohnjiang memif_msg_enq_init(struct rte_eth_dev *dev) 395*4418919fSjohnjiang { 396*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 397*4418919fSjohnjiang struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 398*4418919fSjohnjiang memif_msg_init_t *i = &e->msg.init; 399*4418919fSjohnjiang 400*4418919fSjohnjiang if (e == NULL) 401*4418919fSjohnjiang return -1; 402*4418919fSjohnjiang 403*4418919fSjohnjiang i = &e->msg.init; 404*4418919fSjohnjiang e->msg.type = MEMIF_MSG_TYPE_INIT; 405*4418919fSjohnjiang i->version = MEMIF_VERSION; 406*4418919fSjohnjiang i->id = pmd->id; 407*4418919fSjohnjiang i->mode = MEMIF_INTERFACE_MODE_ETHERNET; 408*4418919fSjohnjiang 409*4418919fSjohnjiang strlcpy((char *)i->name, rte_version(), sizeof(i->name)); 410*4418919fSjohnjiang 411*4418919fSjohnjiang if (*pmd->secret != '\0') 412*4418919fSjohnjiang strlcpy((char *)i->secret, pmd->secret, sizeof(i->secret)); 413*4418919fSjohnjiang 414*4418919fSjohnjiang return 0; 415*4418919fSjohnjiang } 416*4418919fSjohnjiang 417*4418919fSjohnjiang static int 418*4418919fSjohnjiang memif_msg_enq_add_region(struct rte_eth_dev *dev, uint8_t idx) 419*4418919fSjohnjiang { 420*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 421*4418919fSjohnjiang struct pmd_process_private *proc_private = dev->process_private; 422*4418919fSjohnjiang struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 423*4418919fSjohnjiang memif_msg_add_region_t *ar; 424*4418919fSjohnjiang struct memif_region *mr = proc_private->regions[idx]; 425*4418919fSjohnjiang 426*4418919fSjohnjiang if (e == NULL) 427*4418919fSjohnjiang return -1; 428*4418919fSjohnjiang 429*4418919fSjohnjiang ar = &e->msg.add_region; 430*4418919fSjohnjiang e->msg.type = MEMIF_MSG_TYPE_ADD_REGION; 431*4418919fSjohnjiang e->fd = mr->fd; 432*4418919fSjohnjiang ar->index = idx; 433*4418919fSjohnjiang ar->size = mr->region_size; 434*4418919fSjohnjiang 435*4418919fSjohnjiang return 0; 436*4418919fSjohnjiang } 437*4418919fSjohnjiang 438*4418919fSjohnjiang static int 439*4418919fSjohnjiang memif_msg_enq_add_ring(struct rte_eth_dev *dev, uint8_t idx, 440*4418919fSjohnjiang memif_ring_type_t type) 441*4418919fSjohnjiang { 442*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 443*4418919fSjohnjiang struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 444*4418919fSjohnjiang struct memif_queue *mq; 445*4418919fSjohnjiang memif_msg_add_ring_t *ar; 446*4418919fSjohnjiang 447*4418919fSjohnjiang if (e == NULL) 448*4418919fSjohnjiang return -1; 449*4418919fSjohnjiang 450*4418919fSjohnjiang ar = &e->msg.add_ring; 451*4418919fSjohnjiang mq = (type == MEMIF_RING_S2M) ? dev->data->tx_queues[idx] : 452*4418919fSjohnjiang dev->data->rx_queues[idx]; 453*4418919fSjohnjiang 454*4418919fSjohnjiang e->msg.type = MEMIF_MSG_TYPE_ADD_RING; 455*4418919fSjohnjiang e->fd = mq->intr_handle.fd; 456*4418919fSjohnjiang ar->index = idx; 457*4418919fSjohnjiang ar->offset = mq->ring_offset; 458*4418919fSjohnjiang ar->region = mq->region; 459*4418919fSjohnjiang ar->log2_ring_size = mq->log2_ring_size; 460*4418919fSjohnjiang ar->flags = (type == MEMIF_RING_S2M) ? MEMIF_MSG_ADD_RING_FLAG_S2M : 0; 461*4418919fSjohnjiang ar->private_hdr_size = 0; 462*4418919fSjohnjiang 463*4418919fSjohnjiang return 0; 464*4418919fSjohnjiang } 465*4418919fSjohnjiang 466*4418919fSjohnjiang static int 467*4418919fSjohnjiang memif_msg_enq_connect(struct rte_eth_dev *dev) 468*4418919fSjohnjiang { 469*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 470*4418919fSjohnjiang struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 471*4418919fSjohnjiang memif_msg_connect_t *c; 472*4418919fSjohnjiang 473*4418919fSjohnjiang if (e == NULL) 474*4418919fSjohnjiang return -1; 475*4418919fSjohnjiang 476*4418919fSjohnjiang c = &e->msg.connect; 477*4418919fSjohnjiang e->msg.type = MEMIF_MSG_TYPE_CONNECT; 478*4418919fSjohnjiang strlcpy((char *)c->if_name, dev->data->name, sizeof(c->if_name)); 479*4418919fSjohnjiang 480*4418919fSjohnjiang return 0; 481*4418919fSjohnjiang } 482*4418919fSjohnjiang 483*4418919fSjohnjiang static int 484*4418919fSjohnjiang memif_msg_enq_connected(struct rte_eth_dev *dev) 485*4418919fSjohnjiang { 486*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 487*4418919fSjohnjiang struct memif_msg_queue_elt *e = memif_msg_enq(pmd->cc); 488*4418919fSjohnjiang memif_msg_connected_t *c; 489*4418919fSjohnjiang 490*4418919fSjohnjiang if (e == NULL) 491*4418919fSjohnjiang return -1; 492*4418919fSjohnjiang 493*4418919fSjohnjiang c = &e->msg.connected; 494*4418919fSjohnjiang e->msg.type = MEMIF_MSG_TYPE_CONNECTED; 495*4418919fSjohnjiang strlcpy((char *)c->if_name, dev->data->name, sizeof(c->if_name)); 496*4418919fSjohnjiang 497*4418919fSjohnjiang return 0; 498*4418919fSjohnjiang } 499*4418919fSjohnjiang 500*4418919fSjohnjiang static void 501*4418919fSjohnjiang memif_intr_unregister_handler(struct rte_intr_handle *intr_handle, void *arg) 502*4418919fSjohnjiang { 503*4418919fSjohnjiang struct memif_msg_queue_elt *elt; 504*4418919fSjohnjiang struct memif_control_channel *cc = arg; 505*4418919fSjohnjiang 506*4418919fSjohnjiang /* close control channel fd */ 507*4418919fSjohnjiang close(intr_handle->fd); 508*4418919fSjohnjiang /* clear message queue */ 509*4418919fSjohnjiang while ((elt = TAILQ_FIRST(&cc->msg_queue)) != NULL) { 510*4418919fSjohnjiang TAILQ_REMOVE(&cc->msg_queue, elt, next); 511*4418919fSjohnjiang rte_free(elt); 512*4418919fSjohnjiang } 513*4418919fSjohnjiang /* free control channel */ 514*4418919fSjohnjiang rte_free(cc); 515*4418919fSjohnjiang } 516*4418919fSjohnjiang 517*4418919fSjohnjiang void 518*4418919fSjohnjiang memif_disconnect(struct rte_eth_dev *dev) 519*4418919fSjohnjiang { 520*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 521*4418919fSjohnjiang struct memif_msg_queue_elt *elt, *next; 522*4418919fSjohnjiang struct memif_queue *mq; 523*4418919fSjohnjiang struct rte_intr_handle *ih; 524*4418919fSjohnjiang int i; 525*4418919fSjohnjiang int ret; 526*4418919fSjohnjiang 527*4418919fSjohnjiang dev->data->dev_link.link_status = ETH_LINK_DOWN; 528*4418919fSjohnjiang pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTING; 529*4418919fSjohnjiang pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTED; 530*4418919fSjohnjiang 531*4418919fSjohnjiang if (pmd->cc != NULL) { 532*4418919fSjohnjiang /* Clear control message queue (except disconnect message if any). */ 533*4418919fSjohnjiang for (elt = TAILQ_FIRST(&pmd->cc->msg_queue); elt != NULL; elt = next) { 534*4418919fSjohnjiang next = TAILQ_NEXT(elt, next); 535*4418919fSjohnjiang if (elt->msg.type != MEMIF_MSG_TYPE_DISCONNECT) { 536*4418919fSjohnjiang TAILQ_REMOVE(&pmd->cc->msg_queue, elt, next); 537*4418919fSjohnjiang rte_free(elt); 538*4418919fSjohnjiang } 539*4418919fSjohnjiang } 540*4418919fSjohnjiang /* send disconnect message (if there is any in queue) */ 541*4418919fSjohnjiang memif_msg_send_from_queue(pmd->cc); 542*4418919fSjohnjiang 543*4418919fSjohnjiang /* at this point, there should be no more messages in queue */ 544*4418919fSjohnjiang if (TAILQ_FIRST(&pmd->cc->msg_queue) != NULL) { 545*4418919fSjohnjiang MIF_LOG(WARNING, 546*4418919fSjohnjiang "Unexpected message(s) in message queue."); 547*4418919fSjohnjiang } 548*4418919fSjohnjiang 549*4418919fSjohnjiang ih = &pmd->cc->intr_handle; 550*4418919fSjohnjiang if (ih->fd > 0) { 551*4418919fSjohnjiang ret = rte_intr_callback_unregister(ih, 552*4418919fSjohnjiang memif_intr_handler, 553*4418919fSjohnjiang pmd->cc); 554*4418919fSjohnjiang /* 555*4418919fSjohnjiang * If callback is active (disconnecting based on 556*4418919fSjohnjiang * received control message). 557*4418919fSjohnjiang */ 558*4418919fSjohnjiang if (ret == -EAGAIN) { 559*4418919fSjohnjiang ret = rte_intr_callback_unregister_pending(ih, 560*4418919fSjohnjiang memif_intr_handler, 561*4418919fSjohnjiang pmd->cc, 562*4418919fSjohnjiang memif_intr_unregister_handler); 563*4418919fSjohnjiang } else if (ret > 0) { 564*4418919fSjohnjiang close(ih->fd); 565*4418919fSjohnjiang rte_free(pmd->cc); 566*4418919fSjohnjiang } 567*4418919fSjohnjiang pmd->cc = NULL; 568*4418919fSjohnjiang if (ret <= 0) 569*4418919fSjohnjiang MIF_LOG(WARNING, 570*4418919fSjohnjiang "Failed to unregister control channel callback."); 571*4418919fSjohnjiang } 572*4418919fSjohnjiang } 573*4418919fSjohnjiang 574*4418919fSjohnjiang /* unconfig interrupts */ 575*4418919fSjohnjiang for (i = 0; i < pmd->cfg.num_s2m_rings; i++) { 576*4418919fSjohnjiang if (pmd->role == MEMIF_ROLE_SLAVE) { 577*4418919fSjohnjiang if (dev->data->tx_queues != NULL) 578*4418919fSjohnjiang mq = dev->data->tx_queues[i]; 579*4418919fSjohnjiang else 580*4418919fSjohnjiang continue; 581*4418919fSjohnjiang } else { 582*4418919fSjohnjiang if (dev->data->rx_queues != NULL) 583*4418919fSjohnjiang mq = dev->data->rx_queues[i]; 584*4418919fSjohnjiang else 585*4418919fSjohnjiang continue; 586*4418919fSjohnjiang } 587*4418919fSjohnjiang if (mq->intr_handle.fd > 0) { 588*4418919fSjohnjiang close(mq->intr_handle.fd); 589*4418919fSjohnjiang mq->intr_handle.fd = -1; 590*4418919fSjohnjiang } 591*4418919fSjohnjiang } 592*4418919fSjohnjiang for (i = 0; i < pmd->cfg.num_m2s_rings; i++) { 593*4418919fSjohnjiang if (pmd->role == MEMIF_ROLE_MASTER) { 594*4418919fSjohnjiang if (dev->data->tx_queues != NULL) 595*4418919fSjohnjiang mq = dev->data->tx_queues[i]; 596*4418919fSjohnjiang else 597*4418919fSjohnjiang continue; 598*4418919fSjohnjiang } else { 599*4418919fSjohnjiang if (dev->data->rx_queues != NULL) 600*4418919fSjohnjiang mq = dev->data->rx_queues[i]; 601*4418919fSjohnjiang else 602*4418919fSjohnjiang continue; 603*4418919fSjohnjiang } 604*4418919fSjohnjiang if (mq->intr_handle.fd > 0) { 605*4418919fSjohnjiang close(mq->intr_handle.fd); 606*4418919fSjohnjiang mq->intr_handle.fd = -1; 607*4418919fSjohnjiang } 608*4418919fSjohnjiang } 609*4418919fSjohnjiang 610*4418919fSjohnjiang memif_free_regions(dev); 611*4418919fSjohnjiang 612*4418919fSjohnjiang /* reset connection configuration */ 613*4418919fSjohnjiang memset(&pmd->run, 0, sizeof(pmd->run)); 614*4418919fSjohnjiang 615*4418919fSjohnjiang MIF_LOG(DEBUG, "Disconnected."); 616*4418919fSjohnjiang } 617*4418919fSjohnjiang 618*4418919fSjohnjiang static int 619*4418919fSjohnjiang memif_msg_receive(struct memif_control_channel *cc) 620*4418919fSjohnjiang { 621*4418919fSjohnjiang char ctl[CMSG_SPACE(sizeof(int)) + 622*4418919fSjohnjiang CMSG_SPACE(sizeof(struct ucred))] = { 0 }; 623*4418919fSjohnjiang struct msghdr mh = { 0 }; 624*4418919fSjohnjiang struct iovec iov[1]; 625*4418919fSjohnjiang memif_msg_t msg = { 0 }; 626*4418919fSjohnjiang ssize_t size; 627*4418919fSjohnjiang int ret = 0; 628*4418919fSjohnjiang struct ucred *cr __rte_unused; 629*4418919fSjohnjiang cr = 0; 630*4418919fSjohnjiang struct cmsghdr *cmsg; 631*4418919fSjohnjiang int afd = -1; 632*4418919fSjohnjiang int i; 633*4418919fSjohnjiang struct pmd_internals *pmd; 634*4418919fSjohnjiang struct pmd_process_private *proc_private; 635*4418919fSjohnjiang 636*4418919fSjohnjiang iov[0].iov_base = (void *)&msg; 637*4418919fSjohnjiang iov[0].iov_len = sizeof(memif_msg_t); 638*4418919fSjohnjiang mh.msg_iov = iov; 639*4418919fSjohnjiang mh.msg_iovlen = 1; 640*4418919fSjohnjiang mh.msg_control = ctl; 641*4418919fSjohnjiang mh.msg_controllen = sizeof(ctl); 642*4418919fSjohnjiang 643*4418919fSjohnjiang size = recvmsg(cc->intr_handle.fd, &mh, 0); 644*4418919fSjohnjiang if (size != sizeof(memif_msg_t)) { 645*4418919fSjohnjiang MIF_LOG(DEBUG, "Invalid message size."); 646*4418919fSjohnjiang memif_msg_enq_disconnect(cc, "Invalid message size", 0); 647*4418919fSjohnjiang return -1; 648*4418919fSjohnjiang } 649*4418919fSjohnjiang MIF_LOG(DEBUG, "Received msg type: %u.", msg.type); 650*4418919fSjohnjiang 651*4418919fSjohnjiang cmsg = CMSG_FIRSTHDR(&mh); 652*4418919fSjohnjiang while (cmsg) { 653*4418919fSjohnjiang if (cmsg->cmsg_level == SOL_SOCKET) { 654*4418919fSjohnjiang if (cmsg->cmsg_type == SCM_CREDENTIALS) 655*4418919fSjohnjiang cr = (struct ucred *)CMSG_DATA(cmsg); 656*4418919fSjohnjiang else if (cmsg->cmsg_type == SCM_RIGHTS) 657*4418919fSjohnjiang rte_memcpy(&afd, CMSG_DATA(cmsg), sizeof(int)); 658*4418919fSjohnjiang } 659*4418919fSjohnjiang cmsg = CMSG_NXTHDR(&mh, cmsg); 660*4418919fSjohnjiang } 661*4418919fSjohnjiang 662*4418919fSjohnjiang if (cc->dev == NULL && msg.type != MEMIF_MSG_TYPE_INIT) { 663*4418919fSjohnjiang MIF_LOG(DEBUG, "Unexpected message."); 664*4418919fSjohnjiang memif_msg_enq_disconnect(cc, "Unexpected message", 0); 665*4418919fSjohnjiang return -1; 666*4418919fSjohnjiang } 667*4418919fSjohnjiang 668*4418919fSjohnjiang /* get device from hash data */ 669*4418919fSjohnjiang switch (msg.type) { 670*4418919fSjohnjiang case MEMIF_MSG_TYPE_ACK: 671*4418919fSjohnjiang break; 672*4418919fSjohnjiang case MEMIF_MSG_TYPE_HELLO: 673*4418919fSjohnjiang ret = memif_msg_receive_hello(cc->dev, &msg); 674*4418919fSjohnjiang if (ret < 0) 675*4418919fSjohnjiang goto exit; 676*4418919fSjohnjiang ret = memif_init_regions_and_queues(cc->dev); 677*4418919fSjohnjiang if (ret < 0) 678*4418919fSjohnjiang goto exit; 679*4418919fSjohnjiang ret = memif_msg_enq_init(cc->dev); 680*4418919fSjohnjiang if (ret < 0) 681*4418919fSjohnjiang goto exit; 682*4418919fSjohnjiang pmd = cc->dev->data->dev_private; 683*4418919fSjohnjiang proc_private = cc->dev->process_private; 684*4418919fSjohnjiang for (i = 0; i < proc_private->regions_num; i++) { 685*4418919fSjohnjiang ret = memif_msg_enq_add_region(cc->dev, i); 686*4418919fSjohnjiang if (ret < 0) 687*4418919fSjohnjiang goto exit; 688*4418919fSjohnjiang } 689*4418919fSjohnjiang for (i = 0; i < pmd->run.num_s2m_rings; i++) { 690*4418919fSjohnjiang ret = memif_msg_enq_add_ring(cc->dev, i, 691*4418919fSjohnjiang MEMIF_RING_S2M); 692*4418919fSjohnjiang if (ret < 0) 693*4418919fSjohnjiang goto exit; 694*4418919fSjohnjiang } 695*4418919fSjohnjiang for (i = 0; i < pmd->run.num_m2s_rings; i++) { 696*4418919fSjohnjiang ret = memif_msg_enq_add_ring(cc->dev, i, 697*4418919fSjohnjiang MEMIF_RING_M2S); 698*4418919fSjohnjiang if (ret < 0) 699*4418919fSjohnjiang goto exit; 700*4418919fSjohnjiang } 701*4418919fSjohnjiang ret = memif_msg_enq_connect(cc->dev); 702*4418919fSjohnjiang if (ret < 0) 703*4418919fSjohnjiang goto exit; 704*4418919fSjohnjiang break; 705*4418919fSjohnjiang case MEMIF_MSG_TYPE_INIT: 706*4418919fSjohnjiang /* 707*4418919fSjohnjiang * This cc does not have an interface asociated with it. 708*4418919fSjohnjiang * If suitable interface is found it will be assigned here. 709*4418919fSjohnjiang */ 710*4418919fSjohnjiang ret = memif_msg_receive_init(cc, &msg); 711*4418919fSjohnjiang if (ret < 0) 712*4418919fSjohnjiang goto exit; 713*4418919fSjohnjiang ret = memif_msg_enq_ack(cc->dev); 714*4418919fSjohnjiang if (ret < 0) 715*4418919fSjohnjiang goto exit; 716*4418919fSjohnjiang break; 717*4418919fSjohnjiang case MEMIF_MSG_TYPE_ADD_REGION: 718*4418919fSjohnjiang ret = memif_msg_receive_add_region(cc->dev, &msg, afd); 719*4418919fSjohnjiang if (ret < 0) 720*4418919fSjohnjiang goto exit; 721*4418919fSjohnjiang ret = memif_msg_enq_ack(cc->dev); 722*4418919fSjohnjiang if (ret < 0) 723*4418919fSjohnjiang goto exit; 724*4418919fSjohnjiang break; 725*4418919fSjohnjiang case MEMIF_MSG_TYPE_ADD_RING: 726*4418919fSjohnjiang ret = memif_msg_receive_add_ring(cc->dev, &msg, afd); 727*4418919fSjohnjiang if (ret < 0) 728*4418919fSjohnjiang goto exit; 729*4418919fSjohnjiang ret = memif_msg_enq_ack(cc->dev); 730*4418919fSjohnjiang if (ret < 0) 731*4418919fSjohnjiang goto exit; 732*4418919fSjohnjiang break; 733*4418919fSjohnjiang case MEMIF_MSG_TYPE_CONNECT: 734*4418919fSjohnjiang ret = memif_msg_receive_connect(cc->dev, &msg); 735*4418919fSjohnjiang if (ret < 0) 736*4418919fSjohnjiang goto exit; 737*4418919fSjohnjiang ret = memif_msg_enq_connected(cc->dev); 738*4418919fSjohnjiang if (ret < 0) 739*4418919fSjohnjiang goto exit; 740*4418919fSjohnjiang break; 741*4418919fSjohnjiang case MEMIF_MSG_TYPE_CONNECTED: 742*4418919fSjohnjiang ret = memif_msg_receive_connected(cc->dev, &msg); 743*4418919fSjohnjiang break; 744*4418919fSjohnjiang case MEMIF_MSG_TYPE_DISCONNECT: 745*4418919fSjohnjiang ret = memif_msg_receive_disconnect(cc->dev, &msg); 746*4418919fSjohnjiang if (ret < 0) 747*4418919fSjohnjiang goto exit; 748*4418919fSjohnjiang break; 749*4418919fSjohnjiang default: 750*4418919fSjohnjiang memif_msg_enq_disconnect(cc, "Unknown message type", 0); 751*4418919fSjohnjiang ret = -1; 752*4418919fSjohnjiang goto exit; 753*4418919fSjohnjiang } 754*4418919fSjohnjiang 755*4418919fSjohnjiang exit: 756*4418919fSjohnjiang return ret; 757*4418919fSjohnjiang } 758*4418919fSjohnjiang 759*4418919fSjohnjiang static void 760*4418919fSjohnjiang memif_intr_handler(void *arg) 761*4418919fSjohnjiang { 762*4418919fSjohnjiang struct memif_control_channel *cc = arg; 763*4418919fSjohnjiang int ret; 764*4418919fSjohnjiang 765*4418919fSjohnjiang ret = memif_msg_receive(cc); 766*4418919fSjohnjiang /* if driver failed to assign device */ 767*4418919fSjohnjiang if (cc->dev == NULL) { 768*4418919fSjohnjiang ret = rte_intr_callback_unregister_pending(&cc->intr_handle, 769*4418919fSjohnjiang memif_intr_handler, 770*4418919fSjohnjiang cc, 771*4418919fSjohnjiang memif_intr_unregister_handler); 772*4418919fSjohnjiang if (ret < 0) 773*4418919fSjohnjiang MIF_LOG(WARNING, 774*4418919fSjohnjiang "Failed to unregister control channel callback."); 775*4418919fSjohnjiang return; 776*4418919fSjohnjiang } 777*4418919fSjohnjiang /* if memif_msg_receive failed */ 778*4418919fSjohnjiang if (ret < 0) 779*4418919fSjohnjiang goto disconnect; 780*4418919fSjohnjiang 781*4418919fSjohnjiang ret = memif_msg_send_from_queue(cc); 782*4418919fSjohnjiang if (ret < 0) 783*4418919fSjohnjiang goto disconnect; 784*4418919fSjohnjiang 785*4418919fSjohnjiang return; 786*4418919fSjohnjiang 787*4418919fSjohnjiang disconnect: 788*4418919fSjohnjiang if (cc->dev == NULL) { 789*4418919fSjohnjiang MIF_LOG(WARNING, "eth dev not allocated"); 790*4418919fSjohnjiang return; 791*4418919fSjohnjiang } 792*4418919fSjohnjiang memif_disconnect(cc->dev); 793*4418919fSjohnjiang } 794*4418919fSjohnjiang 795*4418919fSjohnjiang static void 796*4418919fSjohnjiang memif_listener_handler(void *arg) 797*4418919fSjohnjiang { 798*4418919fSjohnjiang struct memif_socket *socket = arg; 799*4418919fSjohnjiang int sockfd; 800*4418919fSjohnjiang int addr_len; 801*4418919fSjohnjiang struct sockaddr_un client; 802*4418919fSjohnjiang struct memif_control_channel *cc; 803*4418919fSjohnjiang int ret; 804*4418919fSjohnjiang 805*4418919fSjohnjiang addr_len = sizeof(client); 806*4418919fSjohnjiang sockfd = accept(socket->intr_handle.fd, (struct sockaddr *)&client, 807*4418919fSjohnjiang (socklen_t *)&addr_len); 808*4418919fSjohnjiang if (sockfd < 0) { 809*4418919fSjohnjiang MIF_LOG(ERR, 810*4418919fSjohnjiang "Failed to accept connection request on socket fd %d", 811*4418919fSjohnjiang socket->intr_handle.fd); 812*4418919fSjohnjiang return; 813*4418919fSjohnjiang } 814*4418919fSjohnjiang 815*4418919fSjohnjiang MIF_LOG(DEBUG, "%s: Connection request accepted.", socket->filename); 816*4418919fSjohnjiang 817*4418919fSjohnjiang cc = rte_zmalloc("memif-cc", sizeof(struct memif_control_channel), 0); 818*4418919fSjohnjiang if (cc == NULL) { 819*4418919fSjohnjiang MIF_LOG(ERR, "Failed to allocate control channel."); 820*4418919fSjohnjiang goto error; 821*4418919fSjohnjiang } 822*4418919fSjohnjiang 823*4418919fSjohnjiang cc->intr_handle.fd = sockfd; 824*4418919fSjohnjiang cc->intr_handle.type = RTE_INTR_HANDLE_EXT; 825*4418919fSjohnjiang cc->socket = socket; 826*4418919fSjohnjiang cc->dev = NULL; 827*4418919fSjohnjiang TAILQ_INIT(&cc->msg_queue); 828*4418919fSjohnjiang 829*4418919fSjohnjiang ret = rte_intr_callback_register(&cc->intr_handle, memif_intr_handler, cc); 830*4418919fSjohnjiang if (ret < 0) { 831*4418919fSjohnjiang MIF_LOG(ERR, "Failed to register control channel callback."); 832*4418919fSjohnjiang goto error; 833*4418919fSjohnjiang } 834*4418919fSjohnjiang 835*4418919fSjohnjiang ret = memif_msg_enq_hello(cc); 836*4418919fSjohnjiang if (ret < 0) { 837*4418919fSjohnjiang MIF_LOG(ERR, "Failed to enqueue hello message."); 838*4418919fSjohnjiang goto error; 839*4418919fSjohnjiang } 840*4418919fSjohnjiang ret = memif_msg_send_from_queue(cc); 841*4418919fSjohnjiang if (ret < 0) 842*4418919fSjohnjiang goto error; 843*4418919fSjohnjiang 844*4418919fSjohnjiang return; 845*4418919fSjohnjiang 846*4418919fSjohnjiang error: 847*4418919fSjohnjiang if (sockfd >= 0) { 848*4418919fSjohnjiang close(sockfd); 849*4418919fSjohnjiang sockfd = -1; 850*4418919fSjohnjiang } 851*4418919fSjohnjiang if (cc != NULL) 852*4418919fSjohnjiang rte_free(cc); 853*4418919fSjohnjiang } 854*4418919fSjohnjiang 855*4418919fSjohnjiang static struct memif_socket * 856*4418919fSjohnjiang memif_socket_create(char *key, uint8_t listener) 857*4418919fSjohnjiang { 858*4418919fSjohnjiang struct memif_socket *sock; 859*4418919fSjohnjiang struct sockaddr_un un; 860*4418919fSjohnjiang int sockfd; 861*4418919fSjohnjiang int ret; 862*4418919fSjohnjiang int on = 1; 863*4418919fSjohnjiang 864*4418919fSjohnjiang sock = rte_zmalloc("memif-socket", sizeof(struct memif_socket), 0); 865*4418919fSjohnjiang if (sock == NULL) { 866*4418919fSjohnjiang MIF_LOG(ERR, "Failed to allocate memory for memif socket"); 867*4418919fSjohnjiang return NULL; 868*4418919fSjohnjiang } 869*4418919fSjohnjiang 870*4418919fSjohnjiang sock->listener = listener; 871*4418919fSjohnjiang strlcpy(sock->filename, key, MEMIF_SOCKET_UN_SIZE); 872*4418919fSjohnjiang TAILQ_INIT(&sock->dev_queue); 873*4418919fSjohnjiang 874*4418919fSjohnjiang if (listener != 0) { 875*4418919fSjohnjiang sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 876*4418919fSjohnjiang if (sockfd < 0) 877*4418919fSjohnjiang goto error; 878*4418919fSjohnjiang 879*4418919fSjohnjiang un.sun_family = AF_UNIX; 880*4418919fSjohnjiang strlcpy(un.sun_path, sock->filename, MEMIF_SOCKET_UN_SIZE); 881*4418919fSjohnjiang 882*4418919fSjohnjiang ret = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &on, 883*4418919fSjohnjiang sizeof(on)); 884*4418919fSjohnjiang if (ret < 0) 885*4418919fSjohnjiang goto error; 886*4418919fSjohnjiang 887*4418919fSjohnjiang ret = bind(sockfd, (struct sockaddr *)&un, sizeof(un)); 888*4418919fSjohnjiang if (ret < 0) 889*4418919fSjohnjiang goto error; 890*4418919fSjohnjiang 891*4418919fSjohnjiang ret = listen(sockfd, 1); 892*4418919fSjohnjiang if (ret < 0) 893*4418919fSjohnjiang goto error; 894*4418919fSjohnjiang 895*4418919fSjohnjiang MIF_LOG(DEBUG, "Memif listener socket %s created.", sock->filename); 896*4418919fSjohnjiang 897*4418919fSjohnjiang sock->intr_handle.fd = sockfd; 898*4418919fSjohnjiang sock->intr_handle.type = RTE_INTR_HANDLE_EXT; 899*4418919fSjohnjiang ret = rte_intr_callback_register(&sock->intr_handle, 900*4418919fSjohnjiang memif_listener_handler, sock); 901*4418919fSjohnjiang if (ret < 0) { 902*4418919fSjohnjiang MIF_LOG(ERR, "Failed to register interrupt " 903*4418919fSjohnjiang "callback for listener socket"); 904*4418919fSjohnjiang return NULL; 905*4418919fSjohnjiang } 906*4418919fSjohnjiang } 907*4418919fSjohnjiang 908*4418919fSjohnjiang return sock; 909*4418919fSjohnjiang 910*4418919fSjohnjiang error: 911*4418919fSjohnjiang MIF_LOG(ERR, "Failed to setup socket %s: %s", key, strerror(errno)); 912*4418919fSjohnjiang if (sock != NULL) 913*4418919fSjohnjiang rte_free(sock); 914*4418919fSjohnjiang if (sockfd >= 0) 915*4418919fSjohnjiang close(sockfd); 916*4418919fSjohnjiang return NULL; 917*4418919fSjohnjiang } 918*4418919fSjohnjiang 919*4418919fSjohnjiang static struct rte_hash * 920*4418919fSjohnjiang memif_create_socket_hash(void) 921*4418919fSjohnjiang { 922*4418919fSjohnjiang struct rte_hash_parameters params = { 0 }; 923*4418919fSjohnjiang 924*4418919fSjohnjiang params.name = MEMIF_SOCKET_HASH_NAME; 925*4418919fSjohnjiang params.entries = 256; 926*4418919fSjohnjiang params.key_len = MEMIF_SOCKET_UN_SIZE; 927*4418919fSjohnjiang params.hash_func = rte_jhash; 928*4418919fSjohnjiang params.hash_func_init_val = 0; 929*4418919fSjohnjiang return rte_hash_create(¶ms); 930*4418919fSjohnjiang } 931*4418919fSjohnjiang 932*4418919fSjohnjiang int 933*4418919fSjohnjiang memif_socket_init(struct rte_eth_dev *dev, const char *socket_filename) 934*4418919fSjohnjiang { 935*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 936*4418919fSjohnjiang struct memif_socket *socket = NULL; 937*4418919fSjohnjiang struct memif_socket_dev_list_elt *elt; 938*4418919fSjohnjiang struct pmd_internals *tmp_pmd; 939*4418919fSjohnjiang struct rte_hash *hash; 940*4418919fSjohnjiang int ret; 941*4418919fSjohnjiang char key[MEMIF_SOCKET_UN_SIZE]; 942*4418919fSjohnjiang 943*4418919fSjohnjiang hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME); 944*4418919fSjohnjiang if (hash == NULL) { 945*4418919fSjohnjiang hash = memif_create_socket_hash(); 946*4418919fSjohnjiang if (hash == NULL) { 947*4418919fSjohnjiang MIF_LOG(ERR, "Failed to create memif socket hash."); 948*4418919fSjohnjiang return -1; 949*4418919fSjohnjiang } 950*4418919fSjohnjiang } 951*4418919fSjohnjiang 952*4418919fSjohnjiang memset(key, 0, MEMIF_SOCKET_UN_SIZE); 953*4418919fSjohnjiang strlcpy(key, socket_filename, MEMIF_SOCKET_UN_SIZE); 954*4418919fSjohnjiang ret = rte_hash_lookup_data(hash, key, (void **)&socket); 955*4418919fSjohnjiang if (ret < 0) { 956*4418919fSjohnjiang socket = memif_socket_create(key, 957*4418919fSjohnjiang (pmd->role == MEMIF_ROLE_SLAVE) ? 0 : 1); 958*4418919fSjohnjiang if (socket == NULL) 959*4418919fSjohnjiang return -1; 960*4418919fSjohnjiang ret = rte_hash_add_key_data(hash, key, socket); 961*4418919fSjohnjiang if (ret < 0) { 962*4418919fSjohnjiang MIF_LOG(ERR, "Failed to add socket to socket hash."); 963*4418919fSjohnjiang return ret; 964*4418919fSjohnjiang } 965*4418919fSjohnjiang } 966*4418919fSjohnjiang pmd->socket_filename = socket->filename; 967*4418919fSjohnjiang 968*4418919fSjohnjiang if (socket->listener != 0 && pmd->role == MEMIF_ROLE_SLAVE) { 969*4418919fSjohnjiang MIF_LOG(ERR, "Socket is a listener."); 970*4418919fSjohnjiang return -1; 971*4418919fSjohnjiang } else if ((socket->listener == 0) && (pmd->role == MEMIF_ROLE_MASTER)) { 972*4418919fSjohnjiang MIF_LOG(ERR, "Socket is not a listener."); 973*4418919fSjohnjiang return -1; 974*4418919fSjohnjiang } 975*4418919fSjohnjiang 976*4418919fSjohnjiang TAILQ_FOREACH(elt, &socket->dev_queue, next) { 977*4418919fSjohnjiang tmp_pmd = elt->dev->data->dev_private; 978*4418919fSjohnjiang if (tmp_pmd->id == pmd->id) { 979*4418919fSjohnjiang MIF_LOG(ERR, "Memif device with id %d already " 980*4418919fSjohnjiang "exists on socket %s", 981*4418919fSjohnjiang pmd->id, socket->filename); 982*4418919fSjohnjiang return -1; 983*4418919fSjohnjiang } 984*4418919fSjohnjiang } 985*4418919fSjohnjiang 986*4418919fSjohnjiang elt = rte_malloc("pmd-queue", sizeof(struct memif_socket_dev_list_elt), 0); 987*4418919fSjohnjiang if (elt == NULL) { 988*4418919fSjohnjiang MIF_LOG(ERR, "Failed to add device to socket device list."); 989*4418919fSjohnjiang return -1; 990*4418919fSjohnjiang } 991*4418919fSjohnjiang elt->dev = dev; 992*4418919fSjohnjiang TAILQ_INSERT_TAIL(&socket->dev_queue, elt, next); 993*4418919fSjohnjiang 994*4418919fSjohnjiang return 0; 995*4418919fSjohnjiang } 996*4418919fSjohnjiang 997*4418919fSjohnjiang void 998*4418919fSjohnjiang memif_socket_remove_device(struct rte_eth_dev *dev) 999*4418919fSjohnjiang { 1000*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 1001*4418919fSjohnjiang struct memif_socket *socket = NULL; 1002*4418919fSjohnjiang struct memif_socket_dev_list_elt *elt, *next; 1003*4418919fSjohnjiang struct rte_hash *hash; 1004*4418919fSjohnjiang int ret; 1005*4418919fSjohnjiang 1006*4418919fSjohnjiang hash = rte_hash_find_existing(MEMIF_SOCKET_HASH_NAME); 1007*4418919fSjohnjiang if (hash == NULL) 1008*4418919fSjohnjiang return; 1009*4418919fSjohnjiang 1010*4418919fSjohnjiang if (pmd->socket_filename == NULL) 1011*4418919fSjohnjiang return; 1012*4418919fSjohnjiang 1013*4418919fSjohnjiang if (rte_hash_lookup_data(hash, pmd->socket_filename, (void **)&socket) < 0) 1014*4418919fSjohnjiang return; 1015*4418919fSjohnjiang 1016*4418919fSjohnjiang for (elt = TAILQ_FIRST(&socket->dev_queue); elt != NULL; elt = next) { 1017*4418919fSjohnjiang next = TAILQ_NEXT(elt, next); 1018*4418919fSjohnjiang if (elt->dev == dev) { 1019*4418919fSjohnjiang TAILQ_REMOVE(&socket->dev_queue, elt, next); 1020*4418919fSjohnjiang rte_free(elt); 1021*4418919fSjohnjiang pmd->socket_filename = NULL; 1022*4418919fSjohnjiang } 1023*4418919fSjohnjiang } 1024*4418919fSjohnjiang 1025*4418919fSjohnjiang /* remove socket, if this was the last device using it */ 1026*4418919fSjohnjiang if (TAILQ_EMPTY(&socket->dev_queue)) { 1027*4418919fSjohnjiang rte_hash_del_key(hash, socket->filename); 1028*4418919fSjohnjiang if (socket->listener) { 1029*4418919fSjohnjiang /* remove listener socket file, 1030*4418919fSjohnjiang * so we can create new one later. 1031*4418919fSjohnjiang */ 1032*4418919fSjohnjiang ret = remove(socket->filename); 1033*4418919fSjohnjiang if (ret < 0) 1034*4418919fSjohnjiang MIF_LOG(ERR, "Failed to remove socket file: %s", 1035*4418919fSjohnjiang socket->filename); 1036*4418919fSjohnjiang } 1037*4418919fSjohnjiang rte_free(socket); 1038*4418919fSjohnjiang } 1039*4418919fSjohnjiang } 1040*4418919fSjohnjiang 1041*4418919fSjohnjiang int 1042*4418919fSjohnjiang memif_connect_master(struct rte_eth_dev *dev) 1043*4418919fSjohnjiang { 1044*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 1045*4418919fSjohnjiang 1046*4418919fSjohnjiang memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 1047*4418919fSjohnjiang memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 1048*4418919fSjohnjiang pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED; 1049*4418919fSjohnjiang return 0; 1050*4418919fSjohnjiang } 1051*4418919fSjohnjiang 1052*4418919fSjohnjiang int 1053*4418919fSjohnjiang memif_connect_slave(struct rte_eth_dev *dev) 1054*4418919fSjohnjiang { 1055*4418919fSjohnjiang int sockfd; 1056*4418919fSjohnjiang int ret; 1057*4418919fSjohnjiang struct sockaddr_un sun; 1058*4418919fSjohnjiang struct pmd_internals *pmd = dev->data->dev_private; 1059*4418919fSjohnjiang 1060*4418919fSjohnjiang memset(pmd->local_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 1061*4418919fSjohnjiang memset(pmd->remote_disc_string, 0, ETH_MEMIF_DISC_STRING_SIZE); 1062*4418919fSjohnjiang pmd->flags &= ~ETH_MEMIF_FLAG_DISABLED; 1063*4418919fSjohnjiang 1064*4418919fSjohnjiang sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 1065*4418919fSjohnjiang if (sockfd < 0) { 1066*4418919fSjohnjiang MIF_LOG(ERR, "Failed to open socket."); 1067*4418919fSjohnjiang return -1; 1068*4418919fSjohnjiang } 1069*4418919fSjohnjiang 1070*4418919fSjohnjiang sun.sun_family = AF_UNIX; 1071*4418919fSjohnjiang 1072*4418919fSjohnjiang memcpy(sun.sun_path, pmd->socket_filename, sizeof(sun.sun_path) - 1); 1073*4418919fSjohnjiang 1074*4418919fSjohnjiang ret = connect(sockfd, (struct sockaddr *)&sun, 1075*4418919fSjohnjiang sizeof(struct sockaddr_un)); 1076*4418919fSjohnjiang if (ret < 0) { 1077*4418919fSjohnjiang MIF_LOG(ERR, "Failed to connect socket: %s.", pmd->socket_filename); 1078*4418919fSjohnjiang goto error; 1079*4418919fSjohnjiang } 1080*4418919fSjohnjiang 1081*4418919fSjohnjiang MIF_LOG(DEBUG, "Memif socket: %s connected.", pmd->socket_filename); 1082*4418919fSjohnjiang 1083*4418919fSjohnjiang pmd->cc = rte_zmalloc("memif-cc", 1084*4418919fSjohnjiang sizeof(struct memif_control_channel), 0); 1085*4418919fSjohnjiang if (pmd->cc == NULL) { 1086*4418919fSjohnjiang MIF_LOG(ERR, "Failed to allocate control channel."); 1087*4418919fSjohnjiang goto error; 1088*4418919fSjohnjiang } 1089*4418919fSjohnjiang 1090*4418919fSjohnjiang pmd->cc->intr_handle.fd = sockfd; 1091*4418919fSjohnjiang pmd->cc->intr_handle.type = RTE_INTR_HANDLE_EXT; 1092*4418919fSjohnjiang pmd->cc->socket = NULL; 1093*4418919fSjohnjiang pmd->cc->dev = dev; 1094*4418919fSjohnjiang TAILQ_INIT(&pmd->cc->msg_queue); 1095*4418919fSjohnjiang 1096*4418919fSjohnjiang ret = rte_intr_callback_register(&pmd->cc->intr_handle, 1097*4418919fSjohnjiang memif_intr_handler, pmd->cc); 1098*4418919fSjohnjiang if (ret < 0) { 1099*4418919fSjohnjiang MIF_LOG(ERR, "Failed to register interrupt callback for control fd"); 1100*4418919fSjohnjiang goto error; 1101*4418919fSjohnjiang } 1102*4418919fSjohnjiang 1103*4418919fSjohnjiang return 0; 1104*4418919fSjohnjiang 1105*4418919fSjohnjiang error: 1106*4418919fSjohnjiang if (sockfd >= 0) { 1107*4418919fSjohnjiang close(sockfd); 1108*4418919fSjohnjiang sockfd = -1; 1109*4418919fSjohnjiang } 1110*4418919fSjohnjiang if (pmd->cc != NULL) { 1111*4418919fSjohnjiang rte_free(pmd->cc); 1112*4418919fSjohnjiang pmd->cc = NULL; 1113*4418919fSjohnjiang } 1114*4418919fSjohnjiang return -1; 1115*4418919fSjohnjiang } 1116