]> Git Repo - qemu.git/blame - hw/net/vhost_net.c
pci: Don't register a specialized 'config_write' if default behavior is intended
[qemu.git] / hw / net / vhost_net.c
CommitLineData
d5970055
MT
1/*
2 * vhost-net support
3 *
4 * Copyright Red Hat, Inc. 2010
5 *
6 * Authors:
7 * Michael S. Tsirkin <[email protected]>
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.
6b620ca3
PB
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.
d5970055
MT
14 */
15
1422e32d 16#include "net/net.h"
d5970055 17#include "net/tap.h"
03ce5744 18#include "net/vhost-user.h"
d5970055 19
0d09e41a
PB
20#include "hw/virtio/virtio-net.h"
21#include "net/vhost_net.h"
1de7afc9 22#include "qemu/error-report.h"
d5970055
MT
23
24#include "config.h"
25
26#ifdef CONFIG_VHOST_NET
27#include <linux/vhost.h>
d5970055
MT
28#include <sys/socket.h>
29#include <linux/kvm.h>
30#include <fcntl.h>
d5970055
MT
31#include <netpacket/packet.h>
32#include <net/ethernet.h>
33#include <net/if.h>
34#include <netinet/in.h>
35
36#include <stdio.h>
37
4fbe0f32 38#include "standard-headers/linux/virtio_ring.h"
0d09e41a 39#include "hw/virtio/vhost.h"
1c819449 40#include "hw/virtio/virtio-bus.h"
5be7d9f1 41#include "hw/virtio/virtio-access.h"
d5970055
MT
42
43struct vhost_net {
44 struct vhost_dev dev;
45 struct vhost_virtqueue vqs[2];
46 int backend;
35277d14 47 NetClientState *nc;
d5970055
MT
48};
49
2e6d46d7
NN
50/* Features supported by host kernel. */
51static const int kernel_feature_bits[] = {
52 VIRTIO_F_NOTIFY_ON_EMPTY,
53 VIRTIO_RING_F_INDIRECT_DESC,
54 VIRTIO_RING_F_EVENT_IDX,
55 VIRTIO_NET_F_MRG_RXBUF,
b1506132 56 VIRTIO_F_VERSION_1,
2e6d46d7
NN
57 VHOST_INVALID_FEATURE_BIT
58};
59
5f4c01ca 60/* Features supported by others. */
d122f1a2 61static const int user_feature_bits[] = {
5f4c01ca
NN
62 VIRTIO_F_NOTIFY_ON_EMPTY,
63 VIRTIO_RING_F_INDIRECT_DESC,
64 VIRTIO_RING_F_EVENT_IDX,
65
66 VIRTIO_F_ANY_LAYOUT,
b1506132 67 VIRTIO_F_VERSION_1,
5f4c01ca
NN
68 VIRTIO_NET_F_CSUM,
69 VIRTIO_NET_F_GUEST_CSUM,
70 VIRTIO_NET_F_GSO,
71 VIRTIO_NET_F_GUEST_TSO4,
72 VIRTIO_NET_F_GUEST_TSO6,
73 VIRTIO_NET_F_GUEST_ECN,
74 VIRTIO_NET_F_GUEST_UFO,
75 VIRTIO_NET_F_HOST_TSO4,
76 VIRTIO_NET_F_HOST_TSO6,
77 VIRTIO_NET_F_HOST_ECN,
78 VIRTIO_NET_F_HOST_UFO,
79 VIRTIO_NET_F_MRG_RXBUF,
80 VIRTIO_NET_F_STATUS,
81 VIRTIO_NET_F_CTRL_VQ,
82 VIRTIO_NET_F_CTRL_RX,
83 VIRTIO_NET_F_CTRL_VLAN,
84 VIRTIO_NET_F_CTRL_RX_EXTRA,
85 VIRTIO_NET_F_CTRL_MAC_ADDR,
86 VIRTIO_NET_F_CTRL_GUEST_OFFLOADS,
87
88 VIRTIO_NET_F_MQ,
89
90 VHOST_INVALID_FEATURE_BIT
91};
92
2e6d46d7 93static const int *vhost_net_get_feature_bits(struct vhost_net *net)
d5970055 94{
2e6d46d7
NN
95 const int *feature_bits = 0;
96
97 switch (net->nc->info->type) {
98 case NET_CLIENT_OPTIONS_KIND_TAP:
99 feature_bits = kernel_feature_bits;
100 break;
5f4c01ca
NN
101 case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
102 feature_bits = user_feature_bits;
103 break;
2e6d46d7
NN
104 default:
105 error_report("Feature bits not defined for this type: %d",
106 net->nc->info->type);
107 break;
ca736c8e 108 }
2e6d46d7
NN
109
110 return feature_bits;
111}
112
9a2ba823 113uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
2e6d46d7
NN
114{
115 return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net),
116 features);
d5970055
MT
117}
118
9a2ba823 119void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
d5970055 120{
b49ae913 121 net->dev.acked_features = net->dev.backend_features;
2e6d46d7 122 vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
d5970055
MT
123}
124
4e68f7a0 125static int vhost_net_get_fd(NetClientState *backend)
d5970055
MT
126{
127 switch (backend->info->type) {
2be64a68 128 case NET_CLIENT_OPTIONS_KIND_TAP:
d5970055
MT
129 return tap_get_fd(backend);
130 default:
131 fprintf(stderr, "vhost-net requires tap backend\n");
132 return -EBADFD;
133 }
134}
135
81647a65 136struct vhost_net *vhost_net_init(VhostNetOptions *options)
d5970055
MT
137{
138 int r;
1a1bfac9 139 bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL;
7267c094 140 struct vhost_net *net = g_malloc(sizeof *net);
81647a65
NN
141
142 if (!options->net_backend) {
143 fprintf(stderr, "vhost-net requires net backend to be setup\n");
d5970055
MT
144 goto fail;
145 }
81647a65 146
1a1bfac9
NN
147 if (backend_kernel) {
148 r = vhost_net_get_fd(options->net_backend);
149 if (r < 0) {
150 goto fail;
151 }
152 net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend)
9a2ba823 153 ? 0 : (1ULL << VHOST_NET_F_VIRTIO_NET_HDR);
1a1bfac9
NN
154 net->backend = r;
155 } else {
156 net->dev.backend_features = 0;
157 net->backend = -1;
d5970055 158 }
81647a65 159 net->nc = options->net_backend;
d5970055 160
f56a1247
MT
161 net->dev.nvqs = 2;
162 net->dev.vqs = net->vqs;
830d70db 163 net->dev.vq_index = net->nc->queue_index;
f56a1247 164
81647a65 165 r = vhost_dev_init(&net->dev, options->opaque,
1a1bfac9 166 options->backend_type, options->force);
d5970055
MT
167 if (r < 0) {
168 goto fail;
169 }
1a1bfac9 170 if (backend_kernel) {
d8e80ae3
DM
171 if (!qemu_has_vnet_hdr_len(options->net_backend,
172 sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
9a2ba823 173 net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF);
d8e80ae3 174 }
1a1bfac9
NN
175 if (~net->dev.features & net->dev.backend_features) {
176 fprintf(stderr, "vhost lacks feature mask %" PRIu64
177 " for backend\n",
178 (uint64_t)(~net->dev.features & net->dev.backend_features));
179 vhost_dev_cleanup(&net->dev);
180 goto fail;
181 }
d5970055 182 }
d5970055
MT
183 /* Set sane init value. Override when guest acks. */
184 vhost_net_ack_features(net, 0);
185 return net;
186fail:
7267c094 187 g_free(net);
d5970055
MT
188 return NULL;
189}
190
5430a28f
MT
191bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
192{
193 return vhost_dev_query(&net->dev, dev);
194}
195
cd7d1d26
JW
196static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index)
197{
198 net->dev.vq_index = vq_index;
199}
200
5be7d9f1
GK
201static int vhost_net_set_vnet_endian(VirtIODevice *dev, NetClientState *peer,
202 bool set)
203{
204 int r = 0;
205
206 if (virtio_has_feature(dev, VIRTIO_F_VERSION_1) ||
207 (virtio_legacy_is_cross_endian(dev) && !virtio_is_big_endian(dev))) {
208 r = qemu_set_vnet_le(peer, set);
209 if (r) {
210 error_report("backend does not support LE vnet headers");
211 }
212 } else if (virtio_legacy_is_cross_endian(dev)) {
213 r = qemu_set_vnet_be(peer, set);
214 if (r) {
215 error_report("backend does not support BE vnet headers");
216 }
217 }
218
219 return r;
220}
221
a9f98bb5 222static int vhost_net_start_one(struct vhost_net *net,
cd7d1d26 223 VirtIODevice *dev)
d5970055
MT
224{
225 struct vhost_vring_file file = { };
226 int r;
b0b3db79 227
a9f98bb5
JW
228 net->dev.nvqs = 2;
229 net->dev.vqs = net->vqs;
a9f98bb5 230
b0b3db79
MT
231 r = vhost_dev_enable_notifiers(&net->dev, dev);
232 if (r < 0) {
233 goto fail_notifiers;
234 }
d5970055 235
d5970055
MT
236 r = vhost_dev_start(&net->dev, dev);
237 if (r < 0) {
b0b3db79 238 goto fail_start;
d5970055
MT
239 }
240
212d69f2
NN
241 if (net->nc->info->poll) {
242 net->nc->info->poll(net->nc, false);
243 }
244
1a1bfac9
NN
245 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_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 const VhostOps *vhost_ops = net->dev.vhost_ops;
250 r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND,
251 &file);
252 if (r < 0) {
253 r = -errno;
254 goto fail;
255 }
d5970055
MT
256 }
257 }
258 return 0;
259fail:
260 file.fd = -1;
1a1bfac9
NN
261 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
262 while (file.index-- > 0) {
263 const VhostOps *vhost_ops = net->dev.vhost_ops;
264 int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND,
265 &file);
266 assert(r >= 0);
267 }
d5970055 268 }
212d69f2
NN
269 if (net->nc->info->poll) {
270 net->nc->info->poll(net->nc, true);
271 }
d5970055 272 vhost_dev_stop(&net->dev, dev);
b0b3db79
MT
273fail_start:
274 vhost_dev_disable_notifiers(&net->dev, dev);
275fail_notifiers:
d5970055
MT
276 return r;
277}
278
a9f98bb5
JW
279static void vhost_net_stop_one(struct vhost_net *net,
280 VirtIODevice *dev)
d5970055
MT
281{
282 struct vhost_vring_file file = { .fd = -1 };
283
1a1bfac9
NN
284 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
285 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
286 const VhostOps *vhost_ops = net->dev.vhost_ops;
287 int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND,
288 &file);
289 assert(r >= 0);
290 }
294ce717
LG
291 } else if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
292 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
293 const VhostOps *vhost_ops = net->dev.vhost_ops;
294 int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
830d70db 295 &file);
294ce717
LG
296 assert(r >= 0);
297 }
d5970055 298 }
212d69f2
NN
299 if (net->nc->info->poll) {
300 net->nc->info->poll(net->nc, true);
301 }
d5970055 302 vhost_dev_stop(&net->dev, dev);
b0b3db79 303 vhost_dev_disable_notifiers(&net->dev, dev);
d5970055
MT
304}
305
a9f98bb5
JW
306int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
307 int total_queues)
308{
1c819449
FK
309 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
310 VirtioBusState *vbus = VIRTIO_BUS(qbus);
311 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
cd7d1d26 312 int r, e, i;
a9f98bb5 313
1c819449 314 if (!k->set_guest_notifiers) {
312fd5f2 315 error_report("binding does not support guest notifiers");
a9f98bb5
JW
316 r = -ENOSYS;
317 goto err;
318 }
319
5be7d9f1
GK
320 r = vhost_net_set_vnet_endian(dev, ncs[0].peer, true);
321 if (r < 0) {
322 goto err;
323 }
324
a9f98bb5 325 for (i = 0; i < total_queues; i++) {
cd7d1d26 326 vhost_net_set_vq_index(get_vhost_net(ncs[i].peer), i * 2);
a9f98bb5
JW
327 }
328
1c819449 329 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
a9f98bb5 330 if (r < 0) {
312fd5f2 331 error_report("Error binding guest notifier: %d", -r);
5be7d9f1 332 goto err_endian;
a9f98bb5
JW
333 }
334
cd7d1d26
JW
335 for (i = 0; i < total_queues; i++) {
336 r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev);
337
338 if (r < 0) {
339 goto err_start;
340 }
341 }
342
a9f98bb5
JW
343 return 0;
344
cd7d1d26 345err_start:
a9f98bb5 346 while (--i >= 0) {
ed8b4afe 347 vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
a9f98bb5 348 }
cd7d1d26
JW
349 e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
350 if (e < 0) {
351 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
352 fflush(stderr);
353 }
5be7d9f1
GK
354err_endian:
355 vhost_net_set_vnet_endian(dev, ncs[0].peer, false);
cd7d1d26 356err:
a9f98bb5
JW
357 return r;
358}
359
360void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
361 int total_queues)
362{
1c819449
FK
363 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
364 VirtioBusState *vbus = VIRTIO_BUS(qbus);
365 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
a9f98bb5
JW
366 int i, r;
367
cd7d1d26
JW
368 for (i = 0; i < total_queues; i++) {
369 vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
370 }
371
1c819449 372 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
a9f98bb5
JW
373 if (r < 0) {
374 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
375 fflush(stderr);
376 }
377 assert(r >= 0);
5be7d9f1
GK
378
379 assert(vhost_net_set_vnet_endian(dev, ncs[0].peer, false) >= 0);
a9f98bb5
JW
380}
381
d5970055
MT
382void vhost_net_cleanup(struct vhost_net *net)
383{
384 vhost_dev_cleanup(&net->dev);
7267c094 385 g_free(net);
d5970055 386}
f56a1247
MT
387
388bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
389{
390 return vhost_virtqueue_pending(&net->dev, idx);
391}
392
393void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
394 int idx, bool mask)
395{
396 vhost_virtqueue_mask(&net->dev, dev, idx, mask);
397}
ed8b4afe
NN
398
399VHostNetState *get_vhost_net(NetClientState *nc)
400{
401 VHostNetState *vhost_net = 0;
402
403 if (!nc) {
404 return 0;
405 }
406
407 switch (nc->info->type) {
408 case NET_CLIENT_OPTIONS_KIND_TAP:
409 vhost_net = tap_get_vhost_net(nc);
410 break;
03ce5744
NN
411 case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
412 vhost_net = vhost_user_get_vhost_net(nc);
413 break;
ed8b4afe
NN
414 default:
415 break;
416 }
417
418 return vhost_net;
419}
d5970055 420#else
81647a65 421struct vhost_net *vhost_net_init(VhostNetOptions *options)
5430a28f 422{
35f75462 423 error_report("vhost-net support is not compiled in");
5430a28f
MT
424 return NULL;
425}
426
427bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
d5970055 428{
5430a28f 429 return false;
d5970055
MT
430}
431
a9f98bb5
JW
432int vhost_net_start(VirtIODevice *dev,
433 NetClientState *ncs,
434 int total_queues)
d5970055 435{
5430a28f 436 return -ENOSYS;
d5970055 437}
a9f98bb5
JW
438void vhost_net_stop(VirtIODevice *dev,
439 NetClientState *ncs,
440 int total_queues)
d5970055
MT
441{
442}
443
444void vhost_net_cleanup(struct vhost_net *net)
445{
446}
447
9a2ba823 448uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
d5970055 449{
5430a28f 450 return features;
d5970055 451}
9a2ba823 452void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
d5970055
MT
453{
454}
f56a1247
MT
455
456bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
457{
4dd72e04 458 return false;
f56a1247
MT
459}
460
461void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
462 int idx, bool mask)
463{
464}
ed8b4afe
NN
465
466VHostNetState *get_vhost_net(NetClientState *nc)
467{
468 return 0;
469}
d5970055 470#endif
This page took 0.605264 seconds and 4 git commands to generate.