xref: /qemu/hw/net/vhost_net.c (revision 212d69f25e8bff3e9dc8af6ca30a6556094fc5a5)
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 "hw/virtio/virtio-net.h"
20 #include "net/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 "hw/virtio/vhost.h"
40 #include "hw/virtio/virtio-bus.h"
41 
42 struct vhost_net {
43     struct vhost_dev dev;
44     struct vhost_virtqueue vqs[2];
45     int backend;
46     NetClientState *nc;
47 };
48 
49 /* Features supported by host kernel. */
50 static 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 
58 static const int *vhost_net_get_feature_bits(struct vhost_net *net)
59 {
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;
70     }
71 
72     return feature_bits;
73 }
74 
75 unsigned 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);
79 }
80 
81 void vhost_net_ack_features(struct vhost_net *net, unsigned features)
82 {
83     vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
84 }
85 
86 static int vhost_net_get_fd(NetClientState *backend)
87 {
88     switch (backend->info->type) {
89     case NET_CLIENT_OPTIONS_KIND_TAP:
90         return tap_get_fd(backend);
91     default:
92         fprintf(stderr, "vhost-net requires tap backend\n");
93         return -EBADFD;
94     }
95 }
96 
97 struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
98                                  bool force)
99 {
100     int r;
101     struct vhost_net *net = g_malloc(sizeof *net);
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     }
110     net->nc = backend;
111     net->dev.backend_features = qemu_has_vnet_hdr(backend) ? 0 :
112         (1 << VHOST_NET_F_VIRTIO_NET_HDR);
113     net->backend = r;
114 
115     net->dev.nvqs = 2;
116     net->dev.vqs = net->vqs;
117 
118     r = vhost_dev_init(&net->dev, devfd, "/dev/vhost-net", force);
119     if (r < 0) {
120         goto fail;
121     }
122     if (!qemu_has_vnet_hdr_len(backend,
123                                sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
124         net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
125     }
126     if (~net->dev.features & net->dev.backend_features) {
127         fprintf(stderr, "vhost lacks feature mask %" PRIu64 " for backend\n",
128                 (uint64_t)(~net->dev.features & net->dev.backend_features));
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;
136 fail:
137     g_free(net);
138     return NULL;
139 }
140 
141 bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
142 {
143     return vhost_dev_query(&net->dev, dev);
144 }
145 
146 static int vhost_net_start_one(struct vhost_net *net,
147                                VirtIODevice *dev,
148                                int vq_index)
149 {
150     struct vhost_vring_file file = { };
151     int r;
152 
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 
161     r = vhost_dev_enable_notifiers(&net->dev, dev);
162     if (r < 0) {
163         goto fail_notifiers;
164     }
165 
166     r = vhost_dev_start(&net->dev, dev);
167     if (r < 0) {
168         goto fail_start;
169     }
170 
171     if (net->nc->info->poll) {
172         net->nc->info->poll(net->nc, false);
173     }
174 
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;
185 fail:
186     file.fd = -1;
187     while (file.index-- > 0) {
188         int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file);
189         assert(r >= 0);
190     }
191     if (net->nc->info->poll) {
192         net->nc->info->poll(net->nc, true);
193     }
194     vhost_dev_stop(&net->dev, dev);
195 fail_start:
196     vhost_dev_disable_notifiers(&net->dev, dev);
197 fail_notifiers:
198     return r;
199 }
200 
201 static void vhost_net_stop_one(struct vhost_net *net,
202                                VirtIODevice *dev)
203 {
204     struct vhost_vring_file file = { .fd = -1 };
205 
206     if (!net->dev.started) {
207         return;
208     }
209 
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     }
214     if (net->nc->info->poll) {
215         net->nc->info->poll(net->nc, true);
216     }
217     vhost_dev_stop(&net->dev, dev);
218     vhost_dev_disable_notifiers(&net->dev, dev);
219 }
220 
221 int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
222                     int total_queues)
223 {
224     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
225     VirtioBusState *vbus = VIRTIO_BUS(qbus);
226     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
227     int r, i = 0;
228 
229     if (!k->set_guest_notifiers) {
230         error_report("binding does not support guest notifiers");
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 
243     r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
244     if (r < 0) {
245         error_report("Error binding guest notifier: %d", -r);
246         goto err;
247     }
248 
249     return 0;
250 
251 err:
252     while (--i >= 0) {
253         vhost_net_stop_one(tap_get_vhost_net(ncs[i].peer), dev);
254     }
255     return r;
256 }
257 
258 void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
259                     int total_queues)
260 {
261     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
262     VirtioBusState *vbus = VIRTIO_BUS(qbus);
263     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
264     int i, r;
265 
266     r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
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 
278 void vhost_net_cleanup(struct vhost_net *net)
279 {
280     vhost_dev_cleanup(&net->dev);
281     g_free(net);
282 }
283 
284 bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
285 {
286     return vhost_virtqueue_pending(&net->dev, idx);
287 }
288 
289 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
290                               int idx, bool mask)
291 {
292     vhost_virtqueue_mask(&net->dev, dev, idx, mask);
293 }
294 #else
295 struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
296                                  bool force)
297 {
298     error_report("vhost-net support is not compiled in");
299     return NULL;
300 }
301 
302 bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
303 {
304     return false;
305 }
306 
307 int vhost_net_start(VirtIODevice *dev,
308                     NetClientState *ncs,
309                     int total_queues)
310 {
311     return -ENOSYS;
312 }
313 void vhost_net_stop(VirtIODevice *dev,
314                     NetClientState *ncs,
315                     int total_queues)
316 {
317 }
318 
319 void vhost_net_cleanup(struct vhost_net *net)
320 {
321 }
322 
323 unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
324 {
325     return features;
326 }
327 void vhost_net_ack_features(struct vhost_net *net, unsigned features)
328 {
329 }
330 
331 bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
332 {
333     return false;
334 }
335 
336 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
337                               int idx, bool mask)
338 {
339 }
340 #endif
341