]> Git Repo - qemu.git/blame - hw/net/vhost_net.c
vhost_net should call the poll callback only when it is set
[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
MT
17#include "net/tap.h"
18
0d09e41a
PB
19#include "hw/virtio/virtio-net.h"
20#include "net/vhost_net.h"
1de7afc9 21#include "qemu/error-report.h"
d5970055
MT
22
23#include "config.h"
24
25#ifdef CONFIG_VHOST_NET
26#include <linux/vhost.h>
d5970055
MT
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
0d09e41a 39#include "hw/virtio/vhost.h"
1c819449 40#include "hw/virtio/virtio-bus.h"
d5970055
MT
41
42struct vhost_net {
43 struct vhost_dev dev;
44 struct vhost_virtqueue vqs[2];
45 int backend;
35277d14 46 NetClientState *nc;
d5970055
MT
47};
48
2e6d46d7
NN
49/* Features supported by host kernel. */
50static const int kernel_feature_bits[] = {
51 VIRTIO_F_NOTIFY_ON_EMPTY,
52 VIRTIO_RING_F_INDIRECT_DESC,
53 VIRTIO_RING_F_EVENT_IDX,
54 VIRTIO_NET_F_MRG_RXBUF,
55 VHOST_INVALID_FEATURE_BIT
56};
57
58static const int *vhost_net_get_feature_bits(struct vhost_net *net)
d5970055 59{
2e6d46d7
NN
60 const int *feature_bits = 0;
61
62 switch (net->nc->info->type) {
63 case NET_CLIENT_OPTIONS_KIND_TAP:
64 feature_bits = kernel_feature_bits;
65 break;
66 default:
67 error_report("Feature bits not defined for this type: %d",
68 net->nc->info->type);
69 break;
ca736c8e 70 }
2e6d46d7
NN
71
72 return feature_bits;
73}
74
75unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
76{
77 return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net),
78 features);
d5970055
MT
79}
80
81void vhost_net_ack_features(struct vhost_net *net, unsigned features)
82{
2e6d46d7 83 vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
d5970055
MT
84}
85
4e68f7a0 86static int vhost_net_get_fd(NetClientState *backend)
d5970055
MT
87{
88 switch (backend->info->type) {
2be64a68 89 case NET_CLIENT_OPTIONS_KIND_TAP:
d5970055
MT
90 return tap_get_fd(backend);
91 default:
92 fprintf(stderr, "vhost-net requires tap backend\n");
93 return -EBADFD;
94 }
95}
96
4e68f7a0 97struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
5430a28f 98 bool force)
d5970055
MT
99{
100 int r;
7267c094 101 struct vhost_net *net = g_malloc(sizeof *net);
d5970055
MT
102 if (!backend) {
103 fprintf(stderr, "vhost-net requires backend to be setup\n");
104 goto fail;
105 }
106 r = vhost_net_get_fd(backend);
107 if (r < 0) {
108 goto fail;
109 }
35277d14 110 net->nc = backend;
e3e48565 111 net->dev.backend_features = qemu_has_vnet_hdr(backend) ? 0 :
d5970055
MT
112 (1 << VHOST_NET_F_VIRTIO_NET_HDR);
113 net->backend = r;
114
f56a1247
MT
115 net->dev.nvqs = 2;
116 net->dev.vqs = net->vqs;
117
1241ed94 118 r = vhost_dev_init(&net->dev, devfd, "/dev/vhost-net", force);
d5970055
MT
119 if (r < 0) {
120 goto fail;
121 }
e3e48565
SH
122 if (!qemu_has_vnet_hdr_len(backend,
123 sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
ca736c8e
MT
124 net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
125 }
d5970055 126 if (~net->dev.features & net->dev.backend_features) {
0bfcd599 127 fprintf(stderr, "vhost lacks feature mask %" PRIu64 " for backend\n",
29f91781 128 (uint64_t)(~net->dev.features & net->dev.backend_features));
d5970055
MT
129 vhost_dev_cleanup(&net->dev);
130 goto fail;
131 }
132
133 /* Set sane init value. Override when guest acks. */
134 vhost_net_ack_features(net, 0);
135 return net;
136fail:
7267c094 137 g_free(net);
d5970055
MT
138 return NULL;
139}
140
5430a28f
MT
141bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
142{
143 return vhost_dev_query(&net->dev, dev);
144}
145
a9f98bb5
JW
146static int vhost_net_start_one(struct vhost_net *net,
147 VirtIODevice *dev,
148 int vq_index)
d5970055
MT
149{
150 struct vhost_vring_file file = { };
151 int r;
b0b3db79 152
a9f98bb5
JW
153 if (net->dev.started) {
154 return 0;
155 }
156
157 net->dev.nvqs = 2;
158 net->dev.vqs = net->vqs;
159 net->dev.vq_index = vq_index;
160
b0b3db79
MT
161 r = vhost_dev_enable_notifiers(&net->dev, dev);
162 if (r < 0) {
163 goto fail_notifiers;
164 }
d5970055 165
d5970055
MT
166 r = vhost_dev_start(&net->dev, dev);
167 if (r < 0) {
b0b3db79 168 goto fail_start;
d5970055
MT
169 }
170
212d69f2
NN
171 if (net->nc->info->poll) {
172 net->nc->info->poll(net->nc, false);
173 }
174
d5970055
MT
175 qemu_set_fd_handler(net->backend, NULL, NULL, NULL);
176 file.fd = net->backend;
177 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
178 r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
179 if (r < 0) {
180 r = -errno;
181 goto fail;
182 }
183 }
184 return 0;
185fail:
186 file.fd = -1;
6b37c87c 187 while (file.index-- > 0) {
d5970055
MT
188 int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
189 assert(r >= 0);
190 }
212d69f2
NN
191 if (net->nc->info->poll) {
192 net->nc->info->poll(net->nc, true);
193 }
d5970055 194 vhost_dev_stop(&net->dev, dev);
b0b3db79
MT
195fail_start:
196 vhost_dev_disable_notifiers(&net->dev, dev);
197fail_notifiers:
d5970055
MT
198 return r;
199}
200
a9f98bb5
JW
201static void vhost_net_stop_one(struct vhost_net *net,
202 VirtIODevice *dev)
d5970055
MT
203{
204 struct vhost_vring_file file = { .fd = -1 };
205
a9f98bb5
JW
206 if (!net->dev.started) {
207 return;
208 }
209
d5970055
MT
210 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
211 int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
212 assert(r >= 0);
213 }
212d69f2
NN
214 if (net->nc->info->poll) {
215 net->nc->info->poll(net->nc, true);
216 }
d5970055 217 vhost_dev_stop(&net->dev, dev);
b0b3db79 218 vhost_dev_disable_notifiers(&net->dev, dev);
d5970055
MT
219}
220
a9f98bb5
JW
221int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
222 int total_queues)
223{
1c819449
FK
224 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
225 VirtioBusState *vbus = VIRTIO_BUS(qbus);
226 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
a9f98bb5
JW
227 int r, i = 0;
228
1c819449 229 if (!k->set_guest_notifiers) {
312fd5f2 230 error_report("binding does not support guest notifiers");
a9f98bb5
JW
231 r = -ENOSYS;
232 goto err;
233 }
234
235 for (i = 0; i < total_queues; i++) {
236 r = vhost_net_start_one(tap_get_vhost_net(ncs[i].peer), dev, i * 2);
237
238 if (r < 0) {
239 goto err;
240 }
241 }
242
1c819449 243 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
a9f98bb5 244 if (r < 0) {
312fd5f2 245 error_report("Error binding guest notifier: %d", -r);
a9f98bb5
JW
246 goto err;
247 }
248
249 return 0;
250
251err:
252 while (--i >= 0) {
253 vhost_net_stop_one(tap_get_vhost_net(ncs[i].peer), dev);
254 }
255 return r;
256}
257
258void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
259 int total_queues)
260{
1c819449
FK
261 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
262 VirtioBusState *vbus = VIRTIO_BUS(qbus);
263 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
a9f98bb5
JW
264 int i, r;
265
1c819449 266 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
a9f98bb5
JW
267 if (r < 0) {
268 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
269 fflush(stderr);
270 }
271 assert(r >= 0);
272
273 for (i = 0; i < total_queues; i++) {
274 vhost_net_stop_one(tap_get_vhost_net(ncs[i].peer), dev);
275 }
276}
277
d5970055
MT
278void vhost_net_cleanup(struct vhost_net *net)
279{
280 vhost_dev_cleanup(&net->dev);
7267c094 281 g_free(net);
d5970055 282}
f56a1247
MT
283
284bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
285{
286 return vhost_virtqueue_pending(&net->dev, idx);
287}
288
289void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
290 int idx, bool mask)
291{
292 vhost_virtqueue_mask(&net->dev, dev, idx, mask);
293}
d5970055 294#else
4e68f7a0 295struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
5430a28f
MT
296 bool force)
297{
35f75462 298 error_report("vhost-net support is not compiled in");
5430a28f
MT
299 return NULL;
300}
301
302bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
d5970055 303{
5430a28f 304 return false;
d5970055
MT
305}
306
a9f98bb5
JW
307int vhost_net_start(VirtIODevice *dev,
308 NetClientState *ncs,
309 int total_queues)
d5970055 310{
5430a28f 311 return -ENOSYS;
d5970055 312}
a9f98bb5
JW
313void vhost_net_stop(VirtIODevice *dev,
314 NetClientState *ncs,
315 int total_queues)
d5970055
MT
316{
317}
318
319void vhost_net_cleanup(struct vhost_net *net)
320{
321}
322
323unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
324{
5430a28f 325 return features;
d5970055
MT
326}
327void vhost_net_ack_features(struct vhost_net *net, unsigned features)
328{
329}
f56a1247
MT
330
331bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
332{
4dd72e04 333 return false;
f56a1247
MT
334}
335
336void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
337 int idx, bool mask)
338{
339}
d5970055 340#endif
This page took 0.55405 seconds and 4 git commands to generate.