]> Git Repo - qemu.git/blame - hw/net/vhost_net.c
block/ssh: add support for sha256 host key fingerprints
[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
e8d40465 16#include "qemu/osdep.h"
1422e32d 17#include "net/net.h"
d5970055 18#include "net/tap.h"
03ce5744 19#include "net/vhost-user.h"
108a6481 20#include "net/vhost-vdpa.h"
d5970055 21
18658a3c 22#include "standard-headers/linux/vhost_types.h"
0d09e41a
PB
23#include "hw/virtio/virtio-net.h"
24#include "net/vhost_net.h"
1de7afc9 25#include "qemu/error-report.h"
db725815 26#include "qemu/main-loop.h"
d5970055 27
d5970055 28#include <sys/socket.h>
d5970055
MT
29#include <net/if.h>
30#include <netinet/in.h>
31
d5970055 32
4fbe0f32 33#include "standard-headers/linux/virtio_ring.h"
0d09e41a 34#include "hw/virtio/vhost.h"
1c819449 35#include "hw/virtio/virtio-bus.h"
d5970055 36
d5970055 37
2e6d46d7
NN
38/* Features supported by host kernel. */
39static const int kernel_feature_bits[] = {
40 VIRTIO_F_NOTIFY_ON_EMPTY,
41 VIRTIO_RING_F_INDIRECT_DESC,
42 VIRTIO_RING_F_EVENT_IDX,
43 VIRTIO_NET_F_MRG_RXBUF,
b1506132 44 VIRTIO_F_VERSION_1,
45a368ad 45 VIRTIO_NET_F_MTU,
c471ad0e 46 VIRTIO_F_IOMMU_PLATFORM,
dfea7930 47 VIRTIO_F_RING_PACKED,
0145c393 48 VIRTIO_NET_F_HASH_REPORT,
2e6d46d7
NN
49 VHOST_INVALID_FEATURE_BIT
50};
51
5f4c01ca 52/* Features supported by others. */
d122f1a2 53static const int user_feature_bits[] = {
5f4c01ca
NN
54 VIRTIO_F_NOTIFY_ON_EMPTY,
55 VIRTIO_RING_F_INDIRECT_DESC,
56 VIRTIO_RING_F_EVENT_IDX,
57
58 VIRTIO_F_ANY_LAYOUT,
b1506132 59 VIRTIO_F_VERSION_1,
5f4c01ca
NN
60 VIRTIO_NET_F_CSUM,
61 VIRTIO_NET_F_GUEST_CSUM,
62 VIRTIO_NET_F_GSO,
63 VIRTIO_NET_F_GUEST_TSO4,
64 VIRTIO_NET_F_GUEST_TSO6,
65 VIRTIO_NET_F_GUEST_ECN,
66 VIRTIO_NET_F_GUEST_UFO,
67 VIRTIO_NET_F_HOST_TSO4,
68 VIRTIO_NET_F_HOST_TSO6,
69 VIRTIO_NET_F_HOST_ECN,
70 VIRTIO_NET_F_HOST_UFO,
71 VIRTIO_NET_F_MRG_RXBUF,
45a368ad 72 VIRTIO_NET_F_MTU,
6dcdd06e 73 VIRTIO_F_IOMMU_PLATFORM,
dfea7930 74 VIRTIO_F_RING_PACKED,
0145c393
AM
75 VIRTIO_NET_F_RSS,
76 VIRTIO_NET_F_HASH_REPORT,
5f4c01ca 77
72018d1e 78 /* This bit implies RARP isn't sent by QEMU out of band */
f6f56291
TC
79 VIRTIO_NET_F_GUEST_ANNOUNCE,
80
5f4c01ca
NN
81 VIRTIO_NET_F_MQ,
82
83 VHOST_INVALID_FEATURE_BIT
84};
85
2e6d46d7 86static const int *vhost_net_get_feature_bits(struct vhost_net *net)
d5970055 87{
2e6d46d7
NN
88 const int *feature_bits = 0;
89
90 switch (net->nc->info->type) {
f394b2e2 91 case NET_CLIENT_DRIVER_TAP:
2e6d46d7
NN
92 feature_bits = kernel_feature_bits;
93 break;
f394b2e2 94 case NET_CLIENT_DRIVER_VHOST_USER:
5f4c01ca
NN
95 feature_bits = user_feature_bits;
96 break;
108a6481
CL
97#ifdef CONFIG_VHOST_NET_VDPA
98 case NET_CLIENT_DRIVER_VHOST_VDPA:
99 feature_bits = vdpa_feature_bits;
100 break;
101#endif
2e6d46d7
NN
102 default:
103 error_report("Feature bits not defined for this type: %d",
104 net->nc->info->type);
105 break;
ca736c8e 106 }
2e6d46d7
NN
107
108 return feature_bits;
109}
110
9a2ba823 111uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
2e6d46d7
NN
112{
113 return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net),
114 features);
d5970055 115}
38140cc4
CL
116int vhost_net_get_config(struct vhost_net *net, uint8_t *config,
117 uint32_t config_len)
118{
119 return vhost_dev_get_config(&net->dev, config, config_len);
120}
121int vhost_net_set_config(struct vhost_net *net, const uint8_t *data,
122 uint32_t offset, uint32_t size, uint32_t flags)
123{
124 return vhost_dev_set_config(&net->dev, data, offset, size, flags);
125}
d5970055 126
9a2ba823 127void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
d5970055 128{
b49ae913 129 net->dev.acked_features = net->dev.backend_features;
2e6d46d7 130 vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
d5970055
MT
131}
132
e2051e9e
YL
133uint64_t vhost_net_get_max_queues(VHostNetState *net)
134{
135 return net->dev.max_queues;
136}
137
a463215b
MAL
138uint64_t vhost_net_get_acked_features(VHostNetState *net)
139{
140 return net->dev.acked_features;
141}
142
4e68f7a0 143static int vhost_net_get_fd(NetClientState *backend)
d5970055
MT
144{
145 switch (backend->info->type) {
f394b2e2 146 case NET_CLIENT_DRIVER_TAP:
d5970055
MT
147 return tap_get_fd(backend);
148 default:
149 fprintf(stderr, "vhost-net requires tap backend\n");
af3bba76 150 return -ENOSYS;
d5970055
MT
151 }
152}
153
81647a65 154struct vhost_net *vhost_net_init(VhostNetOptions *options)
d5970055
MT
155{
156 int r;
1a1bfac9 157 bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL;
f1a0365b 158 struct vhost_net *net = g_new0(struct vhost_net, 1);
a463215b 159 uint64_t features = 0;
81647a65
NN
160
161 if (!options->net_backend) {
162 fprintf(stderr, "vhost-net requires net backend to be setup\n");
d5970055
MT
163 goto fail;
164 }
b931bfbf 165 net->nc = options->net_backend;
81647a65 166
e2051e9e 167 net->dev.max_queues = 1;
b931bfbf
CO
168 net->dev.nvqs = 2;
169 net->dev.vqs = net->vqs;
e2051e9e 170
1a1bfac9
NN
171 if (backend_kernel) {
172 r = vhost_net_get_fd(options->net_backend);
173 if (r < 0) {
174 goto fail;
175 }
176 net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend)
9a2ba823 177 ? 0 : (1ULL << VHOST_NET_F_VIRTIO_NET_HDR);
1a1bfac9 178 net->backend = r;
dcb10c00 179 net->dev.protocol_features = 0;
1a1bfac9
NN
180 } else {
181 net->dev.backend_features = 0;
dcb10c00 182 net->dev.protocol_features = 0;
1a1bfac9 183 net->backend = -1;
d5970055 184
b931bfbf
CO
185 /* vhost-user needs vq_index to initiate a specific queue pair */
186 net->dev.vq_index = net->nc->queue_index * net->dev.nvqs;
187 }
f56a1247 188
81647a65 189 r = vhost_dev_init(&net->dev, options->opaque,
69e87b32 190 options->backend_type, options->busyloop_timeout);
d5970055
MT
191 if (r < 0) {
192 goto fail;
193 }
1a1bfac9 194 if (backend_kernel) {
d8e80ae3
DM
195 if (!qemu_has_vnet_hdr_len(options->net_backend,
196 sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
9a2ba823 197 net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF);
d8e80ae3 198 }
1a1bfac9
NN
199 if (~net->dev.features & net->dev.backend_features) {
200 fprintf(stderr, "vhost lacks feature mask %" PRIu64
201 " for backend\n",
202 (uint64_t)(~net->dev.features & net->dev.backend_features));
1a1bfac9
NN
203 goto fail;
204 }
d5970055 205 }
a463215b 206
d5970055 207 /* Set sane init value. Override when guest acks. */
56f41de7 208#ifdef CONFIG_VHOST_NET_USER
f394b2e2 209 if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
a463215b
MAL
210 features = vhost_user_get_acked_features(net->nc);
211 if (~net->dev.features & features) {
212 fprintf(stderr, "vhost lacks feature mask %" PRIu64
213 " for backend\n",
214 (uint64_t)(~net->dev.features & features));
a463215b
MAL
215 goto fail;
216 }
217 }
56f41de7 218#endif
a463215b
MAL
219
220 vhost_net_ack_features(net, features);
221
d5970055 222 return net;
f1a0365b 223
d5970055 224fail:
f1a0365b 225 vhost_dev_cleanup(&net->dev);
7267c094 226 g_free(net);
d5970055
MT
227 return NULL;
228}
229
cd7d1d26
JW
230static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index)
231{
232 net->dev.vq_index = vq_index;
233}
234
a9f98bb5 235static int vhost_net_start_one(struct vhost_net *net,
cd7d1d26 236 VirtIODevice *dev)
d5970055
MT
237{
238 struct vhost_vring_file file = { };
239 int r;
b0b3db79 240
a9f98bb5
JW
241 net->dev.nvqs = 2;
242 net->dev.vqs = net->vqs;
a9f98bb5 243
b0b3db79
MT
244 r = vhost_dev_enable_notifiers(&net->dev, dev);
245 if (r < 0) {
246 goto fail_notifiers;
247 }
d5970055 248
d5970055
MT
249 r = vhost_dev_start(&net->dev, dev);
250 if (r < 0) {
b0b3db79 251 goto fail_start;
d5970055
MT
252 }
253
212d69f2
NN
254 if (net->nc->info->poll) {
255 net->nc->info->poll(net->nc, false);
256 }
257
f394b2e2 258 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
1a1bfac9
NN
259 qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
260 file.fd = net->backend;
261 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
23bfaf77
JW
262 if (!virtio_queue_enabled(dev, net->dev.vq_index +
263 file.index)) {
264 /* Queue might not be ready for start */
265 continue;
266 }
950d94ba 267 r = vhost_net_set_backend(&net->dev, &file);
1a1bfac9
NN
268 if (r < 0) {
269 r = -errno;
270 goto fail;
271 }
d5970055
MT
272 }
273 }
274 return 0;
275fail:
276 file.fd = -1;
f394b2e2 277 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
1a1bfac9 278 while (file.index-- > 0) {
23bfaf77
JW
279 if (!virtio_queue_enabled(dev, net->dev.vq_index +
280 file.index)) {
281 /* Queue might not be ready for start */
282 continue;
283 }
950d94ba 284 int r = vhost_net_set_backend(&net->dev, &file);
1a1bfac9
NN
285 assert(r >= 0);
286 }
d5970055 287 }
212d69f2
NN
288 if (net->nc->info->poll) {
289 net->nc->info->poll(net->nc, true);
290 }
d5970055 291 vhost_dev_stop(&net->dev, dev);
b0b3db79
MT
292fail_start:
293 vhost_dev_disable_notifiers(&net->dev, dev);
294fail_notifiers:
d5970055
MT
295 return r;
296}
297
a9f98bb5
JW
298static void vhost_net_stop_one(struct vhost_net *net,
299 VirtIODevice *dev)
d5970055
MT
300{
301 struct vhost_vring_file file = { .fd = -1 };
302
f394b2e2 303 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
1a1bfac9 304 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
950d94ba 305 int r = vhost_net_set_backend(&net->dev, &file);
1a1bfac9
NN
306 assert(r >= 0);
307 }
d5970055 308 }
212d69f2
NN
309 if (net->nc->info->poll) {
310 net->nc->info->poll(net->nc, true);
311 }
d5970055 312 vhost_dev_stop(&net->dev, dev);
b0b3db79 313 vhost_dev_disable_notifiers(&net->dev, dev);
d5970055
MT
314}
315
a9f98bb5
JW
316int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
317 int total_queues)
318{
1c819449
FK
319 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
320 VirtioBusState *vbus = VIRTIO_BUS(qbus);
321 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
92fbc3e0 322 struct vhost_net *net;
3154d1e4 323 int r, e, i;
92fbc3e0 324 NetClientState *peer;
a9f98bb5 325
1c819449 326 if (!k->set_guest_notifiers) {
312fd5f2 327 error_report("binding does not support guest notifiers");
a4076440 328 return -ENOSYS;
a9f98bb5
JW
329 }
330
3154d1e4 331 for (i = 0; i < total_queues; i++) {
5669655a 332
92fbc3e0
CL
333 peer = qemu_get_peer(ncs, i);
334 net = get_vhost_net(peer);
5669655a
VK
335 vhost_net_set_vq_index(net, i * 2);
336
337 /* Suppress the masking guest notifiers on vhost user
338 * because vhost user doesn't interrupt masking/unmasking
339 * properly.
340 */
f394b2e2 341 if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
01edc230 342 dev->use_guest_notifier_mask = false;
5669655a
VK
343 }
344 }
a9f98bb5 345
1c819449 346 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
a9f98bb5 347 if (r < 0) {
312fd5f2 348 error_report("Error binding guest notifier: %d", -r);
3154d1e4 349 goto err;
a9f98bb5
JW
350 }
351
cd7d1d26 352 for (i = 0; i < total_queues; i++) {
92fbc3e0
CL
353 peer = qemu_get_peer(ncs, i);
354 r = vhost_net_start_one(get_vhost_net(peer), dev);
cd7d1d26
JW
355
356 if (r < 0) {
357 goto err_start;
358 }
bfc6cf31 359
92fbc3e0 360 if (peer->vring_enable) {
bfc6cf31 361 /* restore vring enable state */
92fbc3e0 362 r = vhost_set_vring_enable(peer, peer->vring_enable);
bfc6cf31
MAL
363
364 if (r < 0) {
365 goto err_start;
366 }
367 }
cd7d1d26
JW
368 }
369
a9f98bb5
JW
370 return 0;
371
cd7d1d26 372err_start:
a9f98bb5 373 while (--i >= 0) {
92fbc3e0
CL
374 peer = qemu_get_peer(ncs , i);
375 vhost_net_stop_one(get_vhost_net(peer), dev);
a9f98bb5 376 }
cd7d1d26
JW
377 e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
378 if (e < 0) {
379 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
380 fflush(stderr);
381 }
3154d1e4 382err:
a9f98bb5
JW
383 return r;
384}
385
386void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
387 int total_queues)
388{
1c819449
FK
389 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
390 VirtioBusState *vbus = VIRTIO_BUS(qbus);
391 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
a9f98bb5
JW
392 int i, r;
393
cd7d1d26
JW
394 for (i = 0; i < total_queues; i++) {
395 vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev);
396 }
397
1c819449 398 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
a9f98bb5
JW
399 if (r < 0) {
400 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
401 fflush(stderr);
402 }
403 assert(r >= 0);
a9f98bb5
JW
404}
405
d5970055
MT
406void vhost_net_cleanup(struct vhost_net *net)
407{
408 vhost_dev_cleanup(&net->dev);
d5970055 409}
f56a1247 410
3e866365
TC
411int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
412{
413 const VhostOps *vhost_ops = net->dev.vhost_ops;
3e866365 414
51f7aca9
MAL
415 assert(vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
416 assert(vhost_ops->vhost_migration_done);
3e866365 417
51f7aca9 418 return vhost_ops->vhost_migration_done(&net->dev, mac_addr);
3e866365
TC
419}
420
f56a1247
MT
421bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
422{
423 return vhost_virtqueue_pending(&net->dev, idx);
424}
425
426void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
427 int idx, bool mask)
428{
429 vhost_virtqueue_mask(&net->dev, dev, idx, mask);
430}
ed8b4afe
NN
431
432VHostNetState *get_vhost_net(NetClientState *nc)
433{
434 VHostNetState *vhost_net = 0;
435
436 if (!nc) {
437 return 0;
438 }
439
440 switch (nc->info->type) {
f394b2e2 441 case NET_CLIENT_DRIVER_TAP:
ed8b4afe
NN
442 vhost_net = tap_get_vhost_net(nc);
443 break;
56f41de7 444#ifdef CONFIG_VHOST_NET_USER
f394b2e2 445 case NET_CLIENT_DRIVER_VHOST_USER:
03ce5744 446 vhost_net = vhost_user_get_vhost_net(nc);
1a5b68ce 447 assert(vhost_net);
03ce5744 448 break;
108a6481
CL
449#endif
450#ifdef CONFIG_VHOST_NET_VDPA
451 case NET_CLIENT_DRIVER_VHOST_VDPA:
452 vhost_net = vhost_vdpa_get_vhost_net(nc);
453 assert(vhost_net);
454 break;
56f41de7 455#endif
ed8b4afe
NN
456 default:
457 break;
458 }
459
460 return vhost_net;
461}
7263a0ad
CO
462
463int vhost_set_vring_enable(NetClientState *nc, int enable)
464{
465 VHostNetState *net = get_vhost_net(nc);
bb12e761 466 const VhostOps *vhost_ops = net->dev.vhost_ops;
72b65f92 467
bfc6cf31
MAL
468 nc->vring_enable = enable;
469
ca10203c 470 if (vhost_ops && vhost_ops->vhost_set_vring_enable) {
21e70425 471 return vhost_ops->vhost_set_vring_enable(&net->dev, enable);
7263a0ad
CO
472 }
473
474 return 0;
475}
476
45a368ad
MC
477int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
478{
479 const VhostOps *vhost_ops = net->dev.vhost_ops;
480
481 if (!vhost_ops->vhost_net_set_mtu) {
482 return 0;
483 }
484
485 return vhost_ops->vhost_net_set_mtu(&net->dev, mtu);
486}
This page took 0.832472 seconds and 4 git commands to generate.