]> git.proxmox.com Git - mirror_qemu.git/blame - hw/net/vhost_net.c
Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into...
[mirror_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 <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.
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"
a6945f22 25#include "qapi/error.h"
1de7afc9 26#include "qemu/error-report.h"
db725815 27#include "qemu/main-loop.h"
d5970055 28
d5970055 29#include <sys/socket.h>
d5970055
MT
30#include <net/if.h>
31#include <netinet/in.h>
32
d5970055 33
4fbe0f32 34#include "standard-headers/linux/virtio_ring.h"
0d09e41a 35#include "hw/virtio/vhost.h"
1c819449 36#include "hw/virtio/virtio-bus.h"
10f8a115 37#include "linux-headers/linux/vhost.h"
d5970055 38
d5970055 39
2e6d46d7
NN
40/* Features supported by host kernel. */
41static const int kernel_feature_bits[] = {
42 VIRTIO_F_NOTIFY_ON_EMPTY,
43 VIRTIO_RING_F_INDIRECT_DESC,
44 VIRTIO_RING_F_EVENT_IDX,
45 VIRTIO_NET_F_MRG_RXBUF,
b1506132 46 VIRTIO_F_VERSION_1,
45a368ad 47 VIRTIO_NET_F_MTU,
c471ad0e 48 VIRTIO_F_IOMMU_PLATFORM,
dfea7930 49 VIRTIO_F_RING_PACKED,
2a3552ba 50 VIRTIO_F_RING_RESET,
0145c393 51 VIRTIO_NET_F_HASH_REPORT,
2e6d46d7
NN
52 VHOST_INVALID_FEATURE_BIT
53};
54
5f4c01ca 55/* Features supported by others. */
d122f1a2 56static const int user_feature_bits[] = {
5f4c01ca
NN
57 VIRTIO_F_NOTIFY_ON_EMPTY,
58 VIRTIO_RING_F_INDIRECT_DESC,
59 VIRTIO_RING_F_EVENT_IDX,
60
61 VIRTIO_F_ANY_LAYOUT,
b1506132 62 VIRTIO_F_VERSION_1,
5f4c01ca
NN
63 VIRTIO_NET_F_CSUM,
64 VIRTIO_NET_F_GUEST_CSUM,
65 VIRTIO_NET_F_GSO,
66 VIRTIO_NET_F_GUEST_TSO4,
67 VIRTIO_NET_F_GUEST_TSO6,
68 VIRTIO_NET_F_GUEST_ECN,
69 VIRTIO_NET_F_GUEST_UFO,
70 VIRTIO_NET_F_HOST_TSO4,
71 VIRTIO_NET_F_HOST_TSO6,
72 VIRTIO_NET_F_HOST_ECN,
73 VIRTIO_NET_F_HOST_UFO,
74 VIRTIO_NET_F_MRG_RXBUF,
45a368ad 75 VIRTIO_NET_F_MTU,
6dcdd06e 76 VIRTIO_F_IOMMU_PLATFORM,
dfea7930 77 VIRTIO_F_RING_PACKED,
562a7d23 78 VIRTIO_F_RING_RESET,
0145c393
AM
79 VIRTIO_NET_F_RSS,
80 VIRTIO_NET_F_HASH_REPORT,
5f4c01ca 81
72018d1e 82 /* This bit implies RARP isn't sent by QEMU out of band */
f6f56291
TC
83 VIRTIO_NET_F_GUEST_ANNOUNCE,
84
5f4c01ca
NN
85 VIRTIO_NET_F_MQ,
86
87 VHOST_INVALID_FEATURE_BIT
88};
89
2e6d46d7 90static const int *vhost_net_get_feature_bits(struct vhost_net *net)
d5970055 91{
2e6d46d7
NN
92 const int *feature_bits = 0;
93
94 switch (net->nc->info->type) {
f394b2e2 95 case NET_CLIENT_DRIVER_TAP:
2e6d46d7
NN
96 feature_bits = kernel_feature_bits;
97 break;
f394b2e2 98 case NET_CLIENT_DRIVER_VHOST_USER:
5f4c01ca
NN
99 feature_bits = user_feature_bits;
100 break;
108a6481
CL
101#ifdef CONFIG_VHOST_NET_VDPA
102 case NET_CLIENT_DRIVER_VHOST_VDPA:
103 feature_bits = vdpa_feature_bits;
104 break;
105#endif
2e6d46d7
NN
106 default:
107 error_report("Feature bits not defined for this type: %d",
108 net->nc->info->type);
109 break;
ca736c8e 110 }
2e6d46d7
NN
111
112 return feature_bits;
113}
114
9a2ba823 115uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
2e6d46d7
NN
116{
117 return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net),
118 features);
d5970055 119}
38140cc4
CL
120int vhost_net_get_config(struct vhost_net *net, uint8_t *config,
121 uint32_t config_len)
122{
50de5138 123 return vhost_dev_get_config(&net->dev, config, config_len, NULL);
38140cc4
CL
124}
125int vhost_net_set_config(struct vhost_net *net, const uint8_t *data,
126 uint32_t offset, uint32_t size, uint32_t flags)
127{
128 return vhost_dev_set_config(&net->dev, data, offset, size, flags);
129}
d5970055 130
9a2ba823 131void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
d5970055 132{
b49ae913 133 net->dev.acked_features = net->dev.backend_features;
2e6d46d7 134 vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
d5970055
MT
135}
136
e2051e9e
YL
137uint64_t vhost_net_get_max_queues(VHostNetState *net)
138{
139 return net->dev.max_queues;
140}
141
a463215b
MAL
142uint64_t vhost_net_get_acked_features(VHostNetState *net)
143{
144 return net->dev.acked_features;
145}
146
c9bdc449
HH
147void vhost_net_save_acked_features(NetClientState *nc)
148{
149#ifdef CONFIG_VHOST_NET_USER
150 if (nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
151 vhost_user_save_acked_features(nc);
152 }
153#endif
154}
155
4e68f7a0 156static int vhost_net_get_fd(NetClientState *backend)
d5970055
MT
157{
158 switch (backend->info->type) {
f394b2e2 159 case NET_CLIENT_DRIVER_TAP:
d5970055
MT
160 return tap_get_fd(backend);
161 default:
162 fprintf(stderr, "vhost-net requires tap backend\n");
af3bba76 163 return -ENOSYS;
d5970055
MT
164 }
165}
166
81647a65 167struct vhost_net *vhost_net_init(VhostNetOptions *options)
d5970055
MT
168{
169 int r;
1a1bfac9 170 bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL;
f1a0365b 171 struct vhost_net *net = g_new0(struct vhost_net, 1);
a463215b 172 uint64_t features = 0;
a6945f22 173 Error *local_err = NULL;
81647a65
NN
174
175 if (!options->net_backend) {
176 fprintf(stderr, "vhost-net requires net backend to be setup\n");
d5970055
MT
177 goto fail;
178 }
b931bfbf 179 net->nc = options->net_backend;
6a756d14 180 net->dev.nvqs = options->nvqs;
81647a65 181
e2051e9e 182 net->dev.max_queues = 1;
b931bfbf 183 net->dev.vqs = net->vqs;
e2051e9e 184
1a1bfac9
NN
185 if (backend_kernel) {
186 r = vhost_net_get_fd(options->net_backend);
187 if (r < 0) {
188 goto fail;
189 }
190 net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend)
9a2ba823 191 ? 0 : (1ULL << VHOST_NET_F_VIRTIO_NET_HDR);
1a1bfac9 192 net->backend = r;
dcb10c00 193 net->dev.protocol_features = 0;
1a1bfac9
NN
194 } else {
195 net->dev.backend_features = 0;
dcb10c00 196 net->dev.protocol_features = 0;
1a1bfac9 197 net->backend = -1;
d5970055 198
b931bfbf
CO
199 /* vhost-user needs vq_index to initiate a specific queue pair */
200 net->dev.vq_index = net->nc->queue_index * net->dev.nvqs;
201 }
f56a1247 202
81647a65 203 r = vhost_dev_init(&net->dev, options->opaque,
a6945f22
KW
204 options->backend_type, options->busyloop_timeout,
205 &local_err);
d5970055 206 if (r < 0) {
a6945f22 207 error_report_err(local_err);
d5970055
MT
208 goto fail;
209 }
1a1bfac9 210 if (backend_kernel) {
d8e80ae3
DM
211 if (!qemu_has_vnet_hdr_len(options->net_backend,
212 sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
9a2ba823 213 net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF);
d8e80ae3 214 }
1a1bfac9 215 if (~net->dev.features & net->dev.backend_features) {
1eed051c 216 fprintf(stderr, "vhost lacks feature mask 0x%" PRIx64
1a1bfac9
NN
217 " for backend\n",
218 (uint64_t)(~net->dev.features & net->dev.backend_features));
1a1bfac9
NN
219 goto fail;
220 }
d5970055 221 }
a463215b 222
d5970055 223 /* Set sane init value. Override when guest acks. */
56f41de7 224#ifdef CONFIG_VHOST_NET_USER
f394b2e2 225 if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
a463215b
MAL
226 features = vhost_user_get_acked_features(net->nc);
227 if (~net->dev.features & features) {
1eed051c 228 fprintf(stderr, "vhost lacks feature mask 0x%" PRIx64
a463215b
MAL
229 " for backend\n",
230 (uint64_t)(~net->dev.features & features));
a463215b
MAL
231 goto fail;
232 }
233 }
56f41de7 234#endif
a463215b
MAL
235
236 vhost_net_ack_features(net, features);
237
d5970055 238 return net;
f1a0365b 239
d5970055 240fail:
f1a0365b 241 vhost_dev_cleanup(&net->dev);
7267c094 242 g_free(net);
d5970055
MT
243 return NULL;
244}
245
049eb15b 246static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index,
245cf2c2 247 int vq_index_end)
cd7d1d26
JW
248{
249 net->dev.vq_index = vq_index;
245cf2c2 250 net->dev.vq_index_end = vq_index_end;
cd7d1d26
JW
251}
252
a9f98bb5 253static int vhost_net_start_one(struct vhost_net *net,
cd7d1d26 254 VirtIODevice *dev)
d5970055
MT
255{
256 struct vhost_vring_file file = { };
257 int r;
b0b3db79 258
eb92b753
EP
259 if (net->nc->info->start) {
260 r = net->nc->info->start(net->nc);
261 if (r < 0) {
262 return r;
263 }
264 }
265
b0b3db79
MT
266 r = vhost_dev_enable_notifiers(&net->dev, dev);
267 if (r < 0) {
268 goto fail_notifiers;
269 }
d5970055 270
4daa5054 271 r = vhost_dev_start(&net->dev, dev, false);
d5970055 272 if (r < 0) {
b0b3db79 273 goto fail_start;
d5970055
MT
274 }
275
212d69f2
NN
276 if (net->nc->info->poll) {
277 net->nc->info->poll(net->nc, false);
278 }
279
f394b2e2 280 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
1a1bfac9
NN
281 qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
282 file.fd = net->backend;
283 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
23bfaf77
JW
284 if (!virtio_queue_enabled(dev, net->dev.vq_index +
285 file.index)) {
286 /* Queue might not be ready for start */
287 continue;
288 }
950d94ba 289 r = vhost_net_set_backend(&net->dev, &file);
1a1bfac9
NN
290 if (r < 0) {
291 r = -errno;
292 goto fail;
293 }
d5970055
MT
294 }
295 }
539573c3
EP
296
297 if (net->nc->info->load) {
298 r = net->nc->info->load(net->nc);
299 if (r < 0) {
300 goto fail;
301 }
302 }
d5970055
MT
303 return 0;
304fail:
305 file.fd = -1;
f394b2e2 306 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
1a1bfac9 307 while (file.index-- > 0) {
23bfaf77
JW
308 if (!virtio_queue_enabled(dev, net->dev.vq_index +
309 file.index)) {
310 /* Queue might not be ready for start */
311 continue;
312 }
950d94ba 313 int r = vhost_net_set_backend(&net->dev, &file);
1a1bfac9
NN
314 assert(r >= 0);
315 }
d5970055 316 }
212d69f2
NN
317 if (net->nc->info->poll) {
318 net->nc->info->poll(net->nc, true);
319 }
4daa5054 320 vhost_dev_stop(&net->dev, dev, false);
b0b3db79
MT
321fail_start:
322 vhost_dev_disable_notifiers(&net->dev, dev);
323fail_notifiers:
d5970055
MT
324 return r;
325}
326
a9f98bb5
JW
327static void vhost_net_stop_one(struct vhost_net *net,
328 VirtIODevice *dev)
d5970055
MT
329{
330 struct vhost_vring_file file = { .fd = -1 };
331
f394b2e2 332 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
1a1bfac9 333 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
950d94ba 334 int r = vhost_net_set_backend(&net->dev, &file);
1a1bfac9
NN
335 assert(r >= 0);
336 }
d5970055 337 }
212d69f2
NN
338 if (net->nc->info->poll) {
339 net->nc->info->poll(net->nc, true);
340 }
4daa5054 341 vhost_dev_stop(&net->dev, dev, false);
c5e5269d
EP
342 if (net->nc->info->stop) {
343 net->nc->info->stop(net->nc);
344 }
b0b3db79 345 vhost_dev_disable_notifiers(&net->dev, dev);
d5970055
MT
346}
347
a9f98bb5 348int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
05ba3f63 349 int data_queue_pairs, int cvq)
a9f98bb5 350{
1c819449
FK
351 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
352 VirtioBusState *vbus = VIRTIO_BUS(qbus);
353 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
05ba3f63
JW
354 int total_notifiers = data_queue_pairs * 2 + cvq;
355 VirtIONet *n = VIRTIO_NET(dev);
356 int nvhosts = data_queue_pairs + cvq;
92fbc3e0 357 struct vhost_net *net;
14c81b21 358 int r, e, i, index_end = data_queue_pairs * 2;
92fbc3e0 359 NetClientState *peer;
a9f98bb5 360
14c81b21
EP
361 if (cvq) {
362 index_end += 1;
049eb15b
JW
363 }
364
1c819449 365 if (!k->set_guest_notifiers) {
312fd5f2 366 error_report("binding does not support guest notifiers");
a4076440 367 return -ENOSYS;
a9f98bb5
JW
368 }
369
05ba3f63
JW
370 for (i = 0; i < nvhosts; i++) {
371
372 if (i < data_queue_pairs) {
373 peer = qemu_get_peer(ncs, i);
374 } else { /* Control Virtqueue */
441537f1 375 peer = qemu_get_peer(ncs, n->max_queue_pairs);
05ba3f63 376 }
5669655a 377
92fbc3e0 378 net = get_vhost_net(peer);
14c81b21 379 vhost_net_set_vq_index(net, i * 2, index_end);
5669655a
VK
380
381 /* Suppress the masking guest notifiers on vhost user
382 * because vhost user doesn't interrupt masking/unmasking
383 * properly.
384 */
f394b2e2 385 if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
01edc230 386 dev->use_guest_notifier_mask = false;
5669655a
VK
387 }
388 }
a9f98bb5 389
05ba3f63 390 r = k->set_guest_notifiers(qbus->parent, total_notifiers, true);
a9f98bb5 391 if (r < 0) {
312fd5f2 392 error_report("Error binding guest notifier: %d", -r);
3154d1e4 393 goto err;
a9f98bb5
JW
394 }
395
05ba3f63
JW
396 for (i = 0; i < nvhosts; i++) {
397 if (i < data_queue_pairs) {
398 peer = qemu_get_peer(ncs, i);
399 } else {
441537f1 400 peer = qemu_get_peer(ncs, n->max_queue_pairs);
05ba3f63 401 }
bfc6cf31 402
92fbc3e0 403 if (peer->vring_enable) {
bfc6cf31 404 /* restore vring enable state */
92fbc3e0 405 r = vhost_set_vring_enable(peer, peer->vring_enable);
bfc6cf31
MAL
406
407 if (r < 0) {
408 goto err_start;
409 }
410 }
8b67fe00
YW
411
412 r = vhost_net_start_one(get_vhost_net(peer), dev);
413 if (r < 0) {
414 goto err_start;
415 }
cd7d1d26
JW
416 }
417
a9f98bb5
JW
418 return 0;
419
cd7d1d26 420err_start:
a9f98bb5 421 while (--i >= 0) {
6f3910b5
SWL
422 peer = qemu_get_peer(ncs, i < data_queue_pairs ?
423 i : n->max_queue_pairs);
92fbc3e0 424 vhost_net_stop_one(get_vhost_net(peer), dev);
a9f98bb5 425 }
05ba3f63 426 e = k->set_guest_notifiers(qbus->parent, total_notifiers, false);
cd7d1d26
JW
427 if (e < 0) {
428 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
429 fflush(stderr);
430 }
3154d1e4 431err:
a9f98bb5
JW
432 return r;
433}
434
435void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
05ba3f63 436 int data_queue_pairs, int cvq)
a9f98bb5 437{
1c819449
FK
438 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
439 VirtioBusState *vbus = VIRTIO_BUS(qbus);
440 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
05ba3f63
JW
441 VirtIONet *n = VIRTIO_NET(dev);
442 NetClientState *peer;
443 int total_notifiers = data_queue_pairs * 2 + cvq;
444 int nvhosts = data_queue_pairs + cvq;
a9f98bb5
JW
445 int i, r;
446
05ba3f63
JW
447 for (i = 0; i < nvhosts; i++) {
448 if (i < data_queue_pairs) {
449 peer = qemu_get_peer(ncs, i);
450 } else {
441537f1 451 peer = qemu_get_peer(ncs, n->max_queue_pairs);
05ba3f63
JW
452 }
453 vhost_net_stop_one(get_vhost_net(peer), dev);
cd7d1d26
JW
454 }
455
05ba3f63 456 r = k->set_guest_notifiers(qbus->parent, total_notifiers, false);
a9f98bb5
JW
457 if (r < 0) {
458 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
459 fflush(stderr);
460 }
461 assert(r >= 0);
a9f98bb5
JW
462}
463
d5970055
MT
464void vhost_net_cleanup(struct vhost_net *net)
465{
466 vhost_dev_cleanup(&net->dev);
d5970055 467}
f56a1247 468
3e866365
TC
469int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
470{
471 const VhostOps *vhost_ops = net->dev.vhost_ops;
3e866365 472
51f7aca9
MAL
473 assert(vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
474 assert(vhost_ops->vhost_migration_done);
3e866365 475
51f7aca9 476 return vhost_ops->vhost_migration_done(&net->dev, mac_addr);
3e866365
TC
477}
478
f56a1247
MT
479bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
480{
481 return vhost_virtqueue_pending(&net->dev, idx);
482}
483
484void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
485 int idx, bool mask)
486{
487 vhost_virtqueue_mask(&net->dev, dev, idx, mask);
488}
ed8b4afe 489
8aab0d1d
CL
490bool vhost_net_config_pending(VHostNetState *net)
491{
492 return vhost_config_pending(&net->dev);
493}
494
495void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask)
496{
497 vhost_config_mask(&net->dev, dev, mask);
498}
ed8b4afe
NN
499VHostNetState *get_vhost_net(NetClientState *nc)
500{
501 VHostNetState *vhost_net = 0;
502
503 if (!nc) {
504 return 0;
505 }
506
507 switch (nc->info->type) {
f394b2e2 508 case NET_CLIENT_DRIVER_TAP:
ed8b4afe 509 vhost_net = tap_get_vhost_net(nc);
0e994668 510 assert(vhost_net);
ed8b4afe 511 break;
56f41de7 512#ifdef CONFIG_VHOST_NET_USER
f394b2e2 513 case NET_CLIENT_DRIVER_VHOST_USER:
03ce5744 514 vhost_net = vhost_user_get_vhost_net(nc);
1a5b68ce 515 assert(vhost_net);
03ce5744 516 break;
108a6481
CL
517#endif
518#ifdef CONFIG_VHOST_NET_VDPA
519 case NET_CLIENT_DRIVER_VHOST_VDPA:
520 vhost_net = vhost_vdpa_get_vhost_net(nc);
521 assert(vhost_net);
522 break;
56f41de7 523#endif
ed8b4afe
NN
524 default:
525 break;
526 }
527
528 return vhost_net;
529}
7263a0ad
CO
530
531int vhost_set_vring_enable(NetClientState *nc, int enable)
532{
533 VHostNetState *net = get_vhost_net(nc);
bb12e761 534 const VhostOps *vhost_ops = net->dev.vhost_ops;
72b65f92 535
bfc6cf31
MAL
536 nc->vring_enable = enable;
537
ca10203c 538 if (vhost_ops && vhost_ops->vhost_set_vring_enable) {
21e70425 539 return vhost_ops->vhost_set_vring_enable(&net->dev, enable);
7263a0ad
CO
540 }
541
542 return 0;
543}
544
45a368ad
MC
545int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
546{
547 const VhostOps *vhost_ops = net->dev.vhost_ops;
548
549 if (!vhost_ops->vhost_net_set_mtu) {
550 return 0;
551 }
552
553 return vhost_ops->vhost_net_set_mtu(&net->dev, mtu);
554}
c2daa08e
KX
555
556void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
557 int vq_index)
558{
559 VHostNetState *net = get_vhost_net(nc->peer);
560 const VhostOps *vhost_ops = net->dev.vhost_ops;
561 struct vhost_vring_file file = { .fd = -1 };
562 int idx;
563
564 /* should only be called after backend is connected */
565 assert(vhost_ops);
566
567 idx = vhost_ops->vhost_get_vq_index(&net->dev, vq_index);
568
569 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
570 file.index = idx;
571 int r = vhost_net_set_backend(&net->dev, &file);
572 assert(r >= 0);
573 }
574
575 vhost_virtqueue_stop(&net->dev,
576 vdev,
577 net->dev.vqs + idx,
578 net->dev.vq_index + idx);
579}
10f8a115
KX
580
581int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
582 int vq_index)
583{
584 VHostNetState *net = get_vhost_net(nc->peer);
585 const VhostOps *vhost_ops = net->dev.vhost_ops;
586 struct vhost_vring_file file = { };
587 int idx, r;
588
589 if (!net->dev.started) {
590 return -EBUSY;
591 }
592
593 /* should only be called after backend is connected */
594 assert(vhost_ops);
595
596 idx = vhost_ops->vhost_get_vq_index(&net->dev, vq_index);
597
598 r = vhost_virtqueue_start(&net->dev,
599 vdev,
600 net->dev.vqs + idx,
601 net->dev.vq_index + idx);
602 if (r < 0) {
603 goto err_start;
604 }
605
606 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
607 file.index = idx;
608 file.fd = net->backend;
609 r = vhost_net_set_backend(&net->dev, &file);
610 if (r < 0) {
611 r = -errno;
612 goto err_start;
613 }
614 }
615
616 return 0;
617
618err_start:
619 error_report("Error when restarting the queue.");
620
621 if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
622 file.fd = VHOST_FILE_UNBIND;
623 file.index = idx;
624 int r = vhost_net_set_backend(&net->dev, &file);
625 assert(r >= 0);
626 }
627
4daa5054 628 vhost_dev_stop(&net->dev, vdev, false);
10f8a115
KX
629
630 return r;
631}