qemu/hw/net/vhost_net.c
<<
>>
Prefs
   1/*
   2 * vhost-net support
   3 *
   4 * Copyright Red Hat, Inc. 2010
   5 *
   6 * Authors:
   7 *  Michael S. Tsirkin <mst@redhat.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2.  See
  10 * the COPYING file in the top-level directory.
  11 *
  12 * Contributions after 2012-01-13 are licensed under the terms of the
  13 * GNU GPL, version 2 or (at your option) any later version.
  14 */
  15
  16#include "qemu/osdep.h"
  17#include "net/net.h"
  18#include "net/tap.h"
  19#include "net/vhost-user.h"
  20
  21#include "hw/virtio/virtio-net.h"
  22#include "net/vhost_net.h"
  23#include "qemu/error-report.h"
  24
  25
  26#ifdef CONFIG_VHOST_NET
  27#include <linux/vhost.h>
  28#include <sys/socket.h>
  29#include <linux/kvm.h>
  30#include <netpacket/packet.h>
  31#include <net/ethernet.h>
  32#include <net/if.h>
  33#include <netinet/in.h>
  34
  35
  36#include "standard-headers/linux/virtio_ring.h"
  37#include "hw/virtio/vhost.h"
  38#include "hw/virtio/virtio-bus.h"
  39
  40struct vhost_net {
  41    struct vhost_dev dev;
  42    struct vhost_virtqueue vqs[2];
  43    int backend;
  44    NetClientState *nc;
  45};
  46
  47/* Features supported by host kernel. */
  48static const int kernel_feature_bits[] = {
  49    VIRTIO_F_NOTIFY_ON_EMPTY,
  50    VIRTIO_RING_F_INDIRECT_DESC,
  51    VIRTIO_RING_F_EVENT_IDX,
  52    VIRTIO_NET_F_MRG_RXBUF,
  53    VIRTIO_F_VERSION_1,
  54    VIRTIO_NET_F_MTU,
  55    VIRTIO_F_IOMMU_PLATFORM,
  56    VHOST_INVALID_FEATURE_BIT
  57};
  58
  59/* Features supported by others. */
  60static const int user_feature_bits[] = {
  61    VIRTIO_F_NOTIFY_ON_EMPTY,
  62    VIRTIO_RING_F_INDIRECT_DESC,
  63    VIRTIO_RING_F_EVENT_IDX,
  64
  65    VIRTIO_F_ANY_LAYOUT,
  66    VIRTIO_F_VERSION_1,
  67    VIRTIO_NET_F_CSUM,
  68    VIRTIO_NET_F_GUEST_CSUM,
  69    VIRTIO_NET_F_GSO,
  70    VIRTIO_NET_F_GUEST_TSO4,
  71    VIRTIO_NET_F_GUEST_TSO6,
  72    VIRTIO_NET_F_GUEST_ECN,
  73    VIRTIO_NET_F_GUEST_UFO,
  74    VIRTIO_NET_F_HOST_TSO4,
  75    VIRTIO_NET_F_HOST_TSO6,
  76    VIRTIO_NET_F_HOST_ECN,
  77    VIRTIO_NET_F_HOST_UFO,
  78    VIRTIO_NET_F_MRG_RXBUF,
  79    VIRTIO_NET_F_MTU,
  80    VIRTIO_F_IOMMU_PLATFORM,
  81
  82    /* This bit implies RARP isn't sent by QEMU out of band */
  83    VIRTIO_NET_F_GUEST_ANNOUNCE,
  84
  85    VIRTIO_NET_F_MQ,
  86
  87    VHOST_INVALID_FEATURE_BIT
  88};
  89
  90static const int *vhost_net_get_feature_bits(struct vhost_net *net)
  91{
  92    const int *feature_bits = 0;
  93
  94    switch (net->nc->info->type) {
  95    case NET_CLIENT_DRIVER_TAP:
  96        feature_bits = kernel_feature_bits;
  97        break;
  98    case NET_CLIENT_DRIVER_VHOST_USER:
  99        feature_bits = user_feature_bits;
 100        break;
 101    default:
 102        error_report("Feature bits not defined for this type: %d",
 103                net->nc->info->type);
 104        break;
 105    }
 106
 107    return feature_bits;
 108}
 109
 110uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
 111{
 112    return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net),
 113            features);
 114}
 115
 116void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
 117{
 118    net->dev.acked_features = net->dev.backend_features;
 119    vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
 120}
 121
 122uint64_t vhost_net_get_max_queues(VHostNetState *net)
 123{
 124    return net->dev.max_queues;
 125}
 126
 127uint64_t vhost_net_get_acked_features(VHostNetState *net)
 128{
 129    return net->dev.acked_features;
 130}
 131
 132static int vhost_net_get_fd(NetClientState *backend)
 133{
 134    switch (backend->info->type) {
 135    case NET_CLIENT_DRIVER_TAP:
 136        return tap_get_fd(backend);
 137    default:
 138        fprintf(stderr, "vhost-net requires tap backend\n");
 139        return -EBADFD;
 140    }
 141}
 142
 143struct vhost_net *vhost_net_init(VhostNetOptions *options)
 144{
 145    int r;
 146    bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL;
 147    struct vhost_net *net = g_new0(struct vhost_net, 1);
 148    uint64_t features = 0;
 149
 150    if (!options->net_backend) {
 151        fprintf(stderr, "vhost-net requires net backend to be setup\n");
 152        goto fail;
 153    }
 154    net->nc = options->net_backend;
 155
 156    net->dev.max_queues = 1;
 157    net->dev.nvqs = 2;
 158    net->dev.vqs = net->vqs;
 159
 160    if (backend_kernel) {
 161        r = vhost_net_get_fd(options->net_backend);
 162        if (r < 0) {
 163            goto fail;
 164        }
 165        net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend)
 166            ? 0 : (1ULL << VHOST_NET_F_VIRTIO_NET_HDR);
 167        net->backend = r;
 168        net->dev.protocol_features = 0;
 169    } else {
 170        net->dev.backend_features = 0;
 171        net->dev.protocol_features = 0;
 172        net->backend = -1;
 173
 174        /* vhost-user needs vq_index to initiate a specific queue pair */
 175        net->dev.vq_index = net->nc->queue_index * net->dev.nvqs;
 176    }
 177
 178    r = vhost_dev_init(&net->dev, options->opaque,
 179                       options->backend_type, options->busyloop_timeout);
 180    if (r < 0) {
 181        goto fail;
 182    }
 183    if (backend_kernel) {
 184        if (!qemu_has_vnet_hdr_len(options->net_backend,
 185                               sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
 186            net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF);
 187        }
 188        if (~net->dev.features & net->dev.backend_features) {
 189            fprintf(stderr, "vhost lacks feature mask %" PRIu64
 190                   " for backend\n",
 191                   (uint64_t)(~net->dev.features & net->dev.backend_features));
 192            goto fail;
 193        }
 194    }
 195
 196    /* Set sane init value. Override when guest acks. */
 197    if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
 198        features = vhost_user_get_acked_features(net->nc);
 199        if (~net->dev.features & features) {
 200            fprintf(stderr, "vhost lacks feature mask %" PRIu64
 201                    " for backend\n",
 202                    (uint64_t)(~net->dev.features & features));
 203            goto fail;
 204        }
 205    }
 206
 207    vhost_net_ack_features(net, features);
 208
 209    return net;
 210
 211fail:
 212    vhost_dev_cleanup(&net->dev);
 213    g_free(net);
 214    return NULL;
 215}
 216
 217static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index)
 218{
 219    net->dev.vq_index = vq_index;
 220}
 221
 222static int vhost_net_start_one(struct vhost_net *net,
 223                               VirtIODevice *dev)
 224{
 225    struct vhost_vring_file file = { };
 226    int r;
 227
 228    net->dev.nvqs = 2;
 229    net->dev.vqs = net->vqs;
 230
 231    r = vhost_dev_enable_notifiers(&net->dev, dev);
 232    if (r < 0) {
 233        goto fail_notifiers;
 234    }
 235
 236    r = vhost_dev_start(&net->dev, dev);
 237    if (r < 0) {
 238        goto fail_start;
 239    }
 240
 241    if (net->nc->info->poll) {
 242        net->nc->info->poll(net->nc, false);
 243    }
 244
 245    if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
 246        qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
 247        file.fd = net->backend;
 248        for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
 249            r = vhost_net_set_backend(&net->dev, &file);
 250            if (r < 0) {
 251                r = -errno;
 252                goto fail;
 253            }
 254        }
 255    }
 256    return 0;
 257fail:
 258    file.fd = -1;
 259    if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
 260        while (file.index-- > 0) {
 261            int r = vhost_net_set_backend(&net->dev, &file);
 262            assert(r >= 0);
 263        }
 264    }
 265    if (net->nc->info->poll) {
 266        net->nc->info->poll(net->nc, true);
 267    }
 268    vhost_dev_stop(&net->dev, dev);
 269fail_start:
 270    vhost_dev_disable_notifiers(&net->dev, dev);
 271fail_notifiers:
 272    return r;
 273}
 274
 275static void vhost_net_stop_one(struct vhost_net *net,
 276                               VirtIODevice *dev)
 277{
 278    struct vhost_vring_file file = { .fd = -1 };
 279
 280    if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
 281        for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
 282            int r = vhost_net_set_backend(&net->dev, &file);
 283            assert(r >= 0);
 284        }
 285    }
 286    if (net->nc->info->poll) {
 287        net->nc->info->poll(net->nc, true);
 288    }
 289    vhost_dev_stop(&net->dev, dev);
 290    vhost_dev_disable_notifiers(&net->dev, dev);
 291}
 292
 293int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
 294                    int total_queues)
 295{
 296    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
 297    VirtioBusState *vbus = VIRTIO_BUS(qbus);
 298    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
 299    int r, e, i;
 300
 301    if (!k->set_guest_notifiers) {
 302        error_report("binding does not support guest notifiers");
 303        return -ENOSYS;
 304    }
 305
 306    for (i = 0; i < total_queues; i++) {
 307        struct vhost_net *net;
 308
 309        net = get_vhost_net(ncs[i].peer);
 310        vhost_net_set_vq_index(net, i * 2);
 311
 312        /* Suppress the masking guest notifiers on vhost user
 313         * because vhost user doesn't interrupt masking/unmasking
 314         * properly.
 315         */
 316        if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
 317            dev->use_guest_notifier_mask = false;
 318        }
 319     }
 320
 321    r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
 322    if (r < 0) {
 323        error_report("Error binding guest notifier: %d", -r);
 324        goto err;
 325    }
 326
 327    for (i = 0; i < total_queues; i++) {
 328        r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev);
 329
 330        if (r < 0) {
 331            goto err_start;
 332        }
 333
 334        if (ncs[i].peer->vring_enable) {
 335            /* restore vring enable state */
 336            r = vhost_set_vring_enable(ncs[i].peer, ncs[i].peer->vring_enable);
 337
 338            if (r < 0) {
 339                goto err_start;
 340            }
 341        }
 342    }
 343
 344    return 0;
 345
 346err_start:
 347    while (--i >= 0) {
 348        vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
 349    }
 350    e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
 351    if (e < 0) {
 352        fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
 353        fflush(stderr);
 354    }
 355err:
 356    return r;
 357}
 358
 359void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
 360                    int total_queues)
 361{
 362    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
 363    VirtioBusState *vbus = VIRTIO_BUS(qbus);
 364    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
 365    int i, r;
 366
 367    for (i = 0; i < total_queues; i++) {
 368        vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
 369    }
 370
 371    r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
 372    if (r < 0) {
 373        fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
 374        fflush(stderr);
 375    }
 376    assert(r >= 0);
 377}
 378
 379void vhost_net_cleanup(struct vhost_net *net)
 380{
 381    vhost_dev_cleanup(&net->dev);
 382}
 383
 384int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
 385{
 386    const VhostOps *vhost_ops = net->dev.vhost_ops;
 387
 388    assert(vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
 389    assert(vhost_ops->vhost_migration_done);
 390
 391    return vhost_ops->vhost_migration_done(&net->dev, mac_addr);
 392}
 393
 394bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
 395{
 396    return vhost_virtqueue_pending(&net->dev, idx);
 397}
 398
 399void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
 400                              int idx, bool mask)
 401{
 402    vhost_virtqueue_mask(&net->dev, dev, idx, mask);
 403}
 404
 405VHostNetState *get_vhost_net(NetClientState *nc)
 406{
 407    VHostNetState *vhost_net = 0;
 408
 409    if (!nc) {
 410        return 0;
 411    }
 412
 413    switch (nc->info->type) {
 414    case NET_CLIENT_DRIVER_TAP:
 415        vhost_net = tap_get_vhost_net(nc);
 416        break;
 417    case NET_CLIENT_DRIVER_VHOST_USER:
 418        vhost_net = vhost_user_get_vhost_net(nc);
 419        assert(vhost_net);
 420        break;
 421    default:
 422        break;
 423    }
 424
 425    return vhost_net;
 426}
 427
 428int vhost_set_vring_enable(NetClientState *nc, int enable)
 429{
 430    VHostNetState *net = get_vhost_net(nc);
 431    const VhostOps *vhost_ops = net->dev.vhost_ops;
 432
 433    nc->vring_enable = enable;
 434
 435    if (vhost_ops && vhost_ops->vhost_set_vring_enable) {
 436        return vhost_ops->vhost_set_vring_enable(&net->dev, enable);
 437    }
 438
 439    return 0;
 440}
 441
 442int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
 443{
 444    const VhostOps *vhost_ops = net->dev.vhost_ops;
 445
 446    if (!vhost_ops->vhost_net_set_mtu) {
 447        return 0;
 448    }
 449
 450    return vhost_ops->vhost_net_set_mtu(&net->dev, mtu);
 451}
 452
 453#else
 454uint64_t vhost_net_get_max_queues(VHostNetState *net)
 455{
 456    return 1;
 457}
 458
 459struct vhost_net *vhost_net_init(VhostNetOptions *options)
 460{
 461    error_report("vhost-net support is not compiled in");
 462    return NULL;
 463}
 464
 465int vhost_net_start(VirtIODevice *dev,
 466                    NetClientState *ncs,
 467                    int total_queues)
 468{
 469    return -ENOSYS;
 470}
 471void vhost_net_stop(VirtIODevice *dev,
 472                    NetClientState *ncs,
 473                    int total_queues)
 474{
 475}
 476
 477void vhost_net_cleanup(struct vhost_net *net)
 478{
 479}
 480
 481uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
 482{
 483    return features;
 484}
 485
 486void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
 487{
 488}
 489
 490uint64_t vhost_net_get_acked_features(VHostNetState *net)
 491{
 492    return 0;
 493}
 494
 495bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
 496{
 497    return false;
 498}
 499
 500void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
 501                              int idx, bool mask)
 502{
 503}
 504
 505int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
 506{
 507    return -1;
 508}
 509
 510VHostNetState *get_vhost_net(NetClientState *nc)
 511{
 512    return 0;
 513}
 514
 515int vhost_set_vring_enable(NetClientState *nc, int enable)
 516{
 517    return 0;
 518}
 519
 520int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
 521{
 522    return 0;
 523}
 524#endif
 525