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