Use the default subsystem vendor ID for virtio devices (Mark McLoughlin)
[qemu] / hw / virtio-net.c
1 /*
2  * Virtio Network Device
3  *
4  * Copyright IBM, Corp. 2007
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.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  */
13
14 #include "virtio.h"
15 #include "net.h"
16 #include "qemu-timer.h"
17 #include "virtio-net.h"
18
19 typedef struct VirtIONet
20 {
21     VirtIODevice vdev;
22     uint8_t mac[6];
23     uint16_t status;
24     VirtQueue *rx_vq;
25     VirtQueue *tx_vq;
26     VLANClientState *vc;
27     QEMUTimer *tx_timer;
28     int tx_timer_active;
29     int mergeable_rx_bufs;
30 } VirtIONet;
31
32 /* TODO
33  * - we could suppress RX interrupt if we were so inclined.
34  */
35
36 static VirtIONet *to_virtio_net(VirtIODevice *vdev)
37 {
38     return (VirtIONet *)vdev;
39 }
40
41 static void virtio_net_update_config(VirtIODevice *vdev, uint8_t *config)
42 {
43     VirtIONet *n = to_virtio_net(vdev);
44     struct virtio_net_config netcfg;
45
46     netcfg.status = n->status;
47     memcpy(netcfg.mac, n->mac, 6);
48     memcpy(config, &netcfg, sizeof(netcfg));
49 }
50
51 static void virtio_net_set_link_status(VLANClientState *vc)
52 {
53     VirtIONet *n = vc->opaque;
54     uint16_t old_status = n->status;
55
56     if (vc->link_down)
57         n->status &= ~VIRTIO_NET_S_LINK_UP;
58     else
59         n->status |= VIRTIO_NET_S_LINK_UP;
60
61     if (n->status != old_status)
62         virtio_notify_config(&n->vdev);
63 }
64
65 static uint32_t virtio_net_get_features(VirtIODevice *vdev)
66 {
67     uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_STATUS);
68
69     return features;
70 }
71
72 static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
73 {
74     VirtIONet *n = to_virtio_net(vdev);
75
76     n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF));
77 }
78
79 /* RX */
80
81 static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
82 {
83 }
84
85 static int do_virtio_net_can_receive(VirtIONet *n, int bufsize)
86 {
87     if (!virtio_queue_ready(n->rx_vq) ||
88         !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
89         return 0;
90
91     if (virtio_queue_empty(n->rx_vq) ||
92         (n->mergeable_rx_bufs &&
93          !virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) {
94         virtio_queue_set_notification(n->rx_vq, 1);
95         return 0;
96     }
97
98     virtio_queue_set_notification(n->rx_vq, 0);
99     return 1;
100 }
101
102 static int virtio_net_can_receive(void *opaque)
103 {
104     VirtIONet *n = opaque;
105
106     return do_virtio_net_can_receive(n, VIRTIO_NET_MAX_BUFSIZE);
107 }
108
109 static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count)
110 {
111     int offset, i;
112
113     offset = i = 0;
114     while (offset < count && i < iovcnt) {
115         int len = MIN(iov[i].iov_len, count - offset);
116         memcpy(iov[i].iov_base, buf + offset, len);
117         offset += len;
118         i++;
119     }
120
121     return offset;
122 }
123
124 static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
125                           const void *buf, size_t size, size_t hdr_len)
126 {
127     struct virtio_net_hdr *hdr = iov[0].iov_base;
128     int offset = 0;
129
130     hdr->flags = 0;
131     hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
132
133     /* We only ever receive a struct virtio_net_hdr from the tapfd,
134      * but we may be passing along a larger header to the guest.
135      */
136     iov[0].iov_base += hdr_len;
137     iov[0].iov_len  -= hdr_len;
138
139     return offset;
140 }
141
142 static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
143 {
144     VirtIONet *n = opaque;
145     struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL;
146     size_t hdr_len, offset, i;
147
148     if (!do_virtio_net_can_receive(n, size))
149         return;
150
151     /* hdr_len refers to the header we supply to the guest */
152     hdr_len = n->mergeable_rx_bufs ?
153         sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
154
155     offset = i = 0;
156
157     while (offset < size) {
158         VirtQueueElement elem;
159         int len, total;
160         struct iovec sg[VIRTQUEUE_MAX_SIZE];
161
162         len = total = 0;
163
164         if ((i != 0 && !n->mergeable_rx_bufs) ||
165             virtqueue_pop(n->rx_vq, &elem) == 0) {
166             if (i == 0)
167                 return;
168             fprintf(stderr, "virtio-net truncating packet\n");
169             exit(1);
170         }
171
172         if (elem.in_num < 1) {
173             fprintf(stderr, "virtio-net receive queue contains no in buffers\n");
174             exit(1);
175         }
176
177         if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != hdr_len) {
178             fprintf(stderr, "virtio-net header not in first element\n");
179             exit(1);
180         }
181
182         memcpy(&sg, &elem.in_sg[0], sizeof(sg[0]) * elem.in_num);
183
184         if (i == 0) {
185             if (n->mergeable_rx_bufs)
186                 mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
187
188             offset += receive_header(n, sg, elem.in_num,
189                                      buf + offset, size - offset, hdr_len);
190             total += hdr_len;
191         }
192
193         /* copy in packet.  ugh */
194         len = iov_fill(sg, elem.in_num,
195                        buf + offset, size - offset);
196         total += len;
197
198         /* signal other side */
199         virtqueue_fill(n->rx_vq, &elem, total, i++);
200
201         offset += len;
202     }
203
204     if (mhdr)
205         mhdr->num_buffers = i;
206
207     virtqueue_flush(n->rx_vq, i);
208     virtio_notify(&n->vdev, n->rx_vq);
209 }
210
211 /* TX */
212 static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
213 {
214     VirtQueueElement elem;
215     int has_vnet_hdr = 0;
216
217     if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
218         return;
219
220     while (virtqueue_pop(vq, &elem)) {
221         ssize_t len = 0;
222         unsigned int out_num = elem.out_num;
223         struct iovec *out_sg = &elem.out_sg[0];
224         unsigned hdr_len;
225
226         /* hdr_len refers to the header received from the guest */
227         hdr_len = n->mergeable_rx_bufs ?
228             sizeof(struct virtio_net_hdr_mrg_rxbuf) :
229             sizeof(struct virtio_net_hdr);
230
231         if (out_num < 1 || out_sg->iov_len != hdr_len) {
232             fprintf(stderr, "virtio-net header not in first element\n");
233             exit(1);
234         }
235
236         /* ignore the header if GSO is not supported */
237         if (!has_vnet_hdr) {
238             out_num--;
239             out_sg++;
240             len += hdr_len;
241         } else if (n->mergeable_rx_bufs) {
242             /* tapfd expects a struct virtio_net_hdr */
243             hdr_len -= sizeof(struct virtio_net_hdr);
244             out_sg->iov_len -= hdr_len;
245             len += hdr_len;
246         }
247
248         len += qemu_sendv_packet(n->vc, out_sg, out_num);
249
250         virtqueue_push(vq, &elem, len);
251         virtio_notify(&n->vdev, vq);
252     }
253 }
254
255 static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
256 {
257     VirtIONet *n = to_virtio_net(vdev);
258
259     if (n->tx_timer_active) {
260         virtio_queue_set_notification(vq, 1);
261         qemu_del_timer(n->tx_timer);
262         n->tx_timer_active = 0;
263         virtio_net_flush_tx(n, vq);
264     } else {
265         qemu_mod_timer(n->tx_timer,
266                        qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
267         n->tx_timer_active = 1;
268         virtio_queue_set_notification(vq, 0);
269     }
270 }
271
272 static void virtio_net_tx_timer(void *opaque)
273 {
274     VirtIONet *n = opaque;
275
276     n->tx_timer_active = 0;
277
278     /* Just in case the driver is not ready on more */
279     if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
280         return;
281
282     virtio_queue_set_notification(n->tx_vq, 1);
283     virtio_net_flush_tx(n, n->tx_vq);
284 }
285
286 static void virtio_net_save(QEMUFile *f, void *opaque)
287 {
288     VirtIONet *n = opaque;
289
290     virtio_save(&n->vdev, f);
291
292     qemu_put_buffer(f, n->mac, 6);
293     qemu_put_be32(f, n->tx_timer_active);
294     qemu_put_be32(f, n->mergeable_rx_bufs);
295 }
296
297 static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
298 {
299     VirtIONet *n = opaque;
300
301     if (version_id != 2)
302         return -EINVAL;
303
304     virtio_load(&n->vdev, f);
305
306     qemu_get_buffer(f, n->mac, 6);
307     n->tx_timer_active = qemu_get_be32(f);
308     n->mergeable_rx_bufs = qemu_get_be32(f);
309
310     if (n->tx_timer_active) {
311         qemu_mod_timer(n->tx_timer,
312                        qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
313     }
314
315     return 0;
316 }
317
318 void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
319 {
320     VirtIONet *n;
321     static int virtio_net_id;
322
323     n = (VirtIONet *)virtio_init_pci(bus, "virtio-net",
324                                      PCI_VENDOR_ID_REDHAT_QUMRANET,
325                                      PCI_DEVICE_ID_VIRTIO_NET,
326                                      PCI_VENDOR_ID_REDHAT_QUMRANET,
327                                      VIRTIO_ID_NET,
328                                      0x02, 0x00, 0x00,
329                                      sizeof(struct virtio_net_config),
330                                      sizeof(VirtIONet));
331     if (!n)
332         return;
333
334     n->vdev.get_config = virtio_net_update_config;
335     n->vdev.get_features = virtio_net_get_features;
336     n->vdev.set_features = virtio_net_set_features;
337     n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
338     n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
339     memcpy(n->mac, nd->macaddr, 6);
340     n->status = VIRTIO_NET_S_LINK_UP;
341     n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
342                                  virtio_net_receive, virtio_net_can_receive, n);
343     n->vc->link_status_changed = virtio_net_set_link_status;
344
345     qemu_format_nic_info_str(n->vc, n->mac);
346
347     n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
348     n->tx_timer_active = 0;
349     n->mergeable_rx_bufs = 0;
350
351     register_savevm("virtio-net", virtio_net_id++, 2,
352                     virtio_net_save, virtio_net_load, n);
353 }