~ubuntu-branches/ubuntu/saucy/qemu/saucy

« back to all changes in this revision

Viewing changes to hw/vhost_net.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-05-28 08:18:30 UTC
  • mfrom: (1.8.2) (10.1.37 sid)
  • Revision ID: package-import@ubuntu.com-20130528081830-87xl2z9fq516a814
Tags: 1.5.0+dfsg-2ubuntu1
* Merge 1.5.0+dfs-2 from debian unstable.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - Dropped patches:
    * 0001-fix-wrong-output-with-info-chardev-for-tcp-socket.patch
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * gridcentric patch - updated
    * linaro arm patches from qemu-linaro rebasing branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 "net/net.h"
17
 
#include "net/tap.h"
18
 
 
19
 
#include "virtio-net.h"
20
 
#include "vhost_net.h"
21
 
#include "qemu/error-report.h"
22
 
 
23
 
#include "config.h"
24
 
 
25
 
#ifdef CONFIG_VHOST_NET
26
 
#include <linux/vhost.h>
27
 
#include <sys/socket.h>
28
 
#include <linux/kvm.h>
29
 
#include <fcntl.h>
30
 
#include <sys/ioctl.h>
31
 
#include <linux/virtio_ring.h>
32
 
#include <netpacket/packet.h>
33
 
#include <net/ethernet.h>
34
 
#include <net/if.h>
35
 
#include <netinet/in.h>
36
 
 
37
 
#include <stdio.h>
38
 
 
39
 
#include "vhost.h"
40
 
 
41
 
struct vhost_net {
42
 
    struct vhost_dev dev;
43
 
    struct vhost_virtqueue vqs[2];
44
 
    int backend;
45
 
    NetClientState *nc;
46
 
};
47
 
 
48
 
unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
49
 
{
50
 
    /* Clear features not supported by host kernel. */
51
 
    if (!(net->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))) {
52
 
        features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
53
 
    }
54
 
    if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
55
 
        features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
56
 
    }
57
 
    if (!(net->dev.features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
58
 
        features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
59
 
    }
60
 
    if (!(net->dev.features & (1 << VIRTIO_NET_F_MRG_RXBUF))) {
61
 
        features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
62
 
    }
63
 
    return features;
64
 
}
65
 
 
66
 
void vhost_net_ack_features(struct vhost_net *net, unsigned features)
67
 
{
68
 
    net->dev.acked_features = net->dev.backend_features;
69
 
    if (features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) {
70
 
        net->dev.acked_features |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
71
 
    }
72
 
    if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC)) {
73
 
        net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
74
 
    }
75
 
    if (features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
76
 
        net->dev.acked_features |= (1 << VIRTIO_RING_F_EVENT_IDX);
77
 
    }
78
 
    if (features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
79
 
        net->dev.acked_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
80
 
    }
81
 
}
82
 
 
83
 
static int vhost_net_get_fd(NetClientState *backend)
84
 
{
85
 
    switch (backend->info->type) {
86
 
    case NET_CLIENT_OPTIONS_KIND_TAP:
87
 
        return tap_get_fd(backend);
88
 
    default:
89
 
        fprintf(stderr, "vhost-net requires tap backend\n");
90
 
        return -EBADFD;
91
 
    }
92
 
}
93
 
 
94
 
struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
95
 
                                 bool force)
96
 
{
97
 
    int r;
98
 
    struct vhost_net *net = g_malloc(sizeof *net);
99
 
    if (!backend) {
100
 
        fprintf(stderr, "vhost-net requires backend to be setup\n");
101
 
        goto fail;
102
 
    }
103
 
    r = vhost_net_get_fd(backend);
104
 
    if (r < 0) {
105
 
        goto fail;
106
 
    }
107
 
    net->nc = backend;
108
 
    net->dev.backend_features = tap_has_vnet_hdr(backend) ? 0 :
109
 
        (1 << VHOST_NET_F_VIRTIO_NET_HDR);
110
 
    net->backend = r;
111
 
 
112
 
    net->dev.nvqs = 2;
113
 
    net->dev.vqs = net->vqs;
114
 
 
115
 
    r = vhost_dev_init(&net->dev, devfd, "/dev/vhost-net", force);
116
 
    if (r < 0) {
117
 
        goto fail;
118
 
    }
119
 
    if (!tap_has_vnet_hdr_len(backend,
120
 
                              sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
121
 
        net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
122
 
    }
123
 
    if (~net->dev.features & net->dev.backend_features) {
124
 
        fprintf(stderr, "vhost lacks feature mask %" PRIu64 " for backend\n",
125
 
                (uint64_t)(~net->dev.features & net->dev.backend_features));
126
 
        vhost_dev_cleanup(&net->dev);
127
 
        goto fail;
128
 
    }
129
 
 
130
 
    /* Set sane init value. Override when guest acks. */
131
 
    vhost_net_ack_features(net, 0);
132
 
    return net;
133
 
fail:
134
 
    g_free(net);
135
 
    return NULL;
136
 
}
137
 
 
138
 
bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
139
 
{
140
 
    return vhost_dev_query(&net->dev, dev);
141
 
}
142
 
 
143
 
static int vhost_net_start_one(struct vhost_net *net,
144
 
                               VirtIODevice *dev,
145
 
                               int vq_index)
146
 
{
147
 
    struct vhost_vring_file file = { };
148
 
    int r;
149
 
 
150
 
    if (net->dev.started) {
151
 
        return 0;
152
 
    }
153
 
 
154
 
    net->dev.nvqs = 2;
155
 
    net->dev.vqs = net->vqs;
156
 
    net->dev.vq_index = vq_index;
157
 
 
158
 
    r = vhost_dev_enable_notifiers(&net->dev, dev);
159
 
    if (r < 0) {
160
 
        goto fail_notifiers;
161
 
    }
162
 
 
163
 
    r = vhost_dev_start(&net->dev, dev);
164
 
    if (r < 0) {
165
 
        goto fail_start;
166
 
    }
167
 
 
168
 
    net->nc->info->poll(net->nc, false);
169
 
    qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
170
 
    file.fd = net->backend;
171
 
    for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
172
 
        r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
173
 
        if (r < 0) {
174
 
            r = -errno;
175
 
            goto fail;
176
 
        }
177
 
    }
178
 
    return 0;
179
 
fail:
180
 
    file.fd = -1;
181
 
    while (file.index-- > 0) {
182
 
        int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
183
 
        assert(r >= 0);
184
 
    }
185
 
    net->nc->info->poll(net->nc, true);
186
 
    vhost_dev_stop(&net->dev, dev);
187
 
fail_start:
188
 
    vhost_dev_disable_notifiers(&net->dev, dev);
189
 
fail_notifiers:
190
 
    return r;
191
 
}
192
 
 
193
 
static void vhost_net_stop_one(struct vhost_net *net,
194
 
                               VirtIODevice *dev)
195
 
{
196
 
    struct vhost_vring_file file = { .fd = -1 };
197
 
 
198
 
    if (!net->dev.started) {
199
 
        return;
200
 
    }
201
 
 
202
 
    for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
203
 
        int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
204
 
        assert(r >= 0);
205
 
    }
206
 
    net->nc->info->poll(net->nc, true);
207
 
    vhost_dev_stop(&net->dev, dev);
208
 
    vhost_dev_disable_notifiers(&net->dev, dev);
209
 
}
210
 
 
211
 
int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
212
 
                    int total_queues)
213
 
{
214
 
    int r, i = 0;
215
 
 
216
 
    if (!dev->binding->set_guest_notifiers) {
217
 
        error_report("binding does not support guest notifiers");
218
 
        r = -ENOSYS;
219
 
        goto err;
220
 
    }
221
 
 
222
 
    for (i = 0; i < total_queues; i++) {
223
 
        r = vhost_net_start_one(tap_get_vhost_net(ncs[i].peer), dev, i * 2);
224
 
 
225
 
        if (r < 0) {
226
 
            goto err;
227
 
        }
228
 
    }
229
 
 
230
 
    r = dev->binding->set_guest_notifiers(dev->binding_opaque,
231
 
                                          total_queues * 2,
232
 
                                          true);
233
 
    if (r < 0) {
234
 
        error_report("Error binding guest notifier: %d", -r);
235
 
        goto err;
236
 
    }
237
 
 
238
 
    return 0;
239
 
 
240
 
err:
241
 
    while (--i >= 0) {
242
 
        vhost_net_stop_one(tap_get_vhost_net(ncs[i].peer), dev);
243
 
    }
244
 
    return r;
245
 
}
246
 
 
247
 
void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
248
 
                    int total_queues)
249
 
{
250
 
    int i, r;
251
 
 
252
 
    r = dev->binding->set_guest_notifiers(dev->binding_opaque,
253
 
                                          total_queues * 2,
254
 
                                          false);
255
 
    if (r < 0) {
256
 
        fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
257
 
        fflush(stderr);
258
 
    }
259
 
    assert(r >= 0);
260
 
 
261
 
    for (i = 0; i < total_queues; i++) {
262
 
        vhost_net_stop_one(tap_get_vhost_net(ncs[i].peer), dev);
263
 
    }
264
 
}
265
 
 
266
 
void vhost_net_cleanup(struct vhost_net *net)
267
 
{
268
 
    vhost_dev_cleanup(&net->dev);
269
 
    g_free(net);
270
 
}
271
 
 
272
 
bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
273
 
{
274
 
    return vhost_virtqueue_pending(&net->dev, idx);
275
 
}
276
 
 
277
 
void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
278
 
                              int idx, bool mask)
279
 
{
280
 
    vhost_virtqueue_mask(&net->dev, dev, idx, mask);
281
 
}
282
 
#else
283
 
struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
284
 
                                 bool force)
285
 
{
286
 
    error_report("vhost-net support is not compiled in");
287
 
    return NULL;
288
 
}
289
 
 
290
 
bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
291
 
{
292
 
    return false;
293
 
}
294
 
 
295
 
int vhost_net_start(VirtIODevice *dev,
296
 
                    NetClientState *ncs,
297
 
                    int total_queues)
298
 
{
299
 
    return -ENOSYS;
300
 
}
301
 
void vhost_net_stop(VirtIODevice *dev,
302
 
                    NetClientState *ncs,
303
 
                    int total_queues)
304
 
{
305
 
}
306
 
 
307
 
void vhost_net_cleanup(struct vhost_net *net)
308
 
{
309
 
}
310
 
 
311
 
unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
312
 
{
313
 
    return features;
314
 
}
315
 
void vhost_net_ack_features(struct vhost_net *net, unsigned features)
316
 
{
317
 
}
318
 
 
319
 
bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
320
 
{
321
 
    return -ENOSYS;
322
 
}
323
 
 
324
 
void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
325
 
                              int idx, bool mask)
326
 
{
327
 
}
328
 
#endif