Statistics
| Branch: | Revision:

root / hw / net / virtio-net.c @ 1773d9ee

History | View | Annotate | Download (42.1 kB)

1 fbe78f4f aliguori
/*
2 fbe78f4f aliguori
 * Virtio Network Device
3 fbe78f4f aliguori
 *
4 fbe78f4f aliguori
 * Copyright IBM, Corp. 2007
5 fbe78f4f aliguori
 *
6 fbe78f4f aliguori
 * Authors:
7 fbe78f4f aliguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 fbe78f4f aliguori
 *
9 fbe78f4f aliguori
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 fbe78f4f aliguori
 * the COPYING file in the top-level directory.
11 fbe78f4f aliguori
 *
12 fbe78f4f aliguori
 */
13 fbe78f4f aliguori
14 1de7afc9 Paolo Bonzini
#include "qemu/iov.h"
15 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio.h"
16 1422e32d Paolo Bonzini
#include "net/net.h"
17 7200ac3c Mark McLoughlin
#include "net/checksum.h"
18 a8ed73f7 Mark McLoughlin
#include "net/tap.h"
19 1de7afc9 Paolo Bonzini
#include "qemu/error-report.h"
20 1de7afc9 Paolo Bonzini
#include "qemu/timer.h"
21 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio-net.h"
22 0d09e41a Paolo Bonzini
#include "net/vhost_net.h"
23 17ec5a86 KONRAD Frederic
#include "hw/virtio/virtio-bus.h"
24 fbe78f4f aliguori
25 0ce0e8f4 Mark McLoughlin
#define VIRTIO_NET_VM_VERSION    11
26 b6503ed9 aliguori
27 4ffb17f5 Alex Williamson
#define MAC_TABLE_ENTRIES    64
28 f21c0ed9 aliguori
#define MAX_VLAN    (1 << 12)   /* Per 802.1Q definition */
29 9d6271b8 aliguori
30 14f9b664 Jesse Larrew
/*
31 14f9b664 Jesse Larrew
 * Calculate the number of bytes up to and including the given 'field' of
32 14f9b664 Jesse Larrew
 * 'container'.
33 14f9b664 Jesse Larrew
 */
34 14f9b664 Jesse Larrew
#define endof(container, field) \
35 14f9b664 Jesse Larrew
    (offsetof(container, field) + sizeof(((container *)0)->field))
36 14f9b664 Jesse Larrew
37 14f9b664 Jesse Larrew
typedef struct VirtIOFeature {
38 14f9b664 Jesse Larrew
    uint32_t flags;
39 14f9b664 Jesse Larrew
    size_t end;
40 14f9b664 Jesse Larrew
} VirtIOFeature;
41 14f9b664 Jesse Larrew
42 14f9b664 Jesse Larrew
static VirtIOFeature feature_sizes[] = {
43 14f9b664 Jesse Larrew
    {.flags = 1 << VIRTIO_NET_F_MAC,
44 14f9b664 Jesse Larrew
     .end = endof(struct virtio_net_config, mac)},
45 14f9b664 Jesse Larrew
    {.flags = 1 << VIRTIO_NET_F_STATUS,
46 14f9b664 Jesse Larrew
     .end = endof(struct virtio_net_config, status)},
47 14f9b664 Jesse Larrew
    {.flags = 1 << VIRTIO_NET_F_MQ,
48 14f9b664 Jesse Larrew
     .end = endof(struct virtio_net_config, max_virtqueue_pairs)},
49 14f9b664 Jesse Larrew
    {}
50 14f9b664 Jesse Larrew
};
51 14f9b664 Jesse Larrew
52 fed699f9 Jason Wang
static VirtIONetQueue *virtio_net_get_subqueue(NetClientState *nc)
53 0c87e93e Jason Wang
{
54 0c87e93e Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
55 0c87e93e Jason Wang
56 fed699f9 Jason Wang
    return &n->vqs[nc->queue_index];
57 0c87e93e Jason Wang
}
58 fed699f9 Jason Wang
59 fed699f9 Jason Wang
static int vq2q(int queue_index)
60 fed699f9 Jason Wang
{
61 fed699f9 Jason Wang
    return queue_index / 2;
62 fed699f9 Jason Wang
}
63 fed699f9 Jason Wang
64 fbe78f4f aliguori
/* TODO
65 fbe78f4f aliguori
 * - we could suppress RX interrupt if we were so inclined.
66 fbe78f4f aliguori
 */
67 fbe78f4f aliguori
68 0f03eca6 aliguori
static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
69 fbe78f4f aliguori
{
70 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
71 fbe78f4f aliguori
    struct virtio_net_config netcfg;
72 fbe78f4f aliguori
73 b46d97f2 Stefan Hajnoczi
    stw_p(&netcfg.status, n->status);
74 fed699f9 Jason Wang
    stw_p(&netcfg.max_virtqueue_pairs, n->max_queues);
75 79674068 aliguori
    memcpy(netcfg.mac, n->mac, ETH_ALEN);
76 14f9b664 Jesse Larrew
    memcpy(config, &netcfg, n->config_size);
77 fbe78f4f aliguori
}
78 fbe78f4f aliguori
79 0f03eca6 aliguori
static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
80 0f03eca6 aliguori
{
81 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
82 14f9b664 Jesse Larrew
    struct virtio_net_config netcfg = {};
83 0f03eca6 aliguori
84 14f9b664 Jesse Larrew
    memcpy(&netcfg, config, n->config_size);
85 0f03eca6 aliguori
86 17a0ca55 KONRAD Frederic
    if (!(vdev->guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) &&
87 c1943a3f Amos Kong
        memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
88 79674068 aliguori
        memcpy(n->mac, netcfg.mac, ETH_ALEN);
89 b356f76d Jason Wang
        qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
90 0f03eca6 aliguori
    }
91 0f03eca6 aliguori
}
92 0f03eca6 aliguori
93 783e7706 Michael S. Tsirkin
static bool virtio_net_started(VirtIONet *n, uint8_t status)
94 783e7706 Michael S. Tsirkin
{
95 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
96 783e7706 Michael S. Tsirkin
    return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
97 17a0ca55 KONRAD Frederic
        (n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running;
98 783e7706 Michael S. Tsirkin
}
99 783e7706 Michael S. Tsirkin
100 783e7706 Michael S. Tsirkin
static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
101 afbaa7b4 Michael S. Tsirkin
{
102 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
103 b356f76d Jason Wang
    NetClientState *nc = qemu_get_queue(n->nic);
104 fed699f9 Jason Wang
    int queues = n->multiqueue ? n->max_queues : 1;
105 b356f76d Jason Wang
106 b356f76d Jason Wang
    if (!nc->peer) {
107 afbaa7b4 Michael S. Tsirkin
        return;
108 afbaa7b4 Michael S. Tsirkin
    }
109 b356f76d Jason Wang
    if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
110 afbaa7b4 Michael S. Tsirkin
        return;
111 afbaa7b4 Michael S. Tsirkin
    }
112 afbaa7b4 Michael S. Tsirkin
113 b356f76d Jason Wang
    if (!tap_get_vhost_net(nc->peer)) {
114 afbaa7b4 Michael S. Tsirkin
        return;
115 afbaa7b4 Michael S. Tsirkin
    }
116 fed699f9 Jason Wang
117 32993698 Michael S. Tsirkin
    if (!!n->vhost_started == virtio_net_started(n, status) &&
118 b356f76d Jason Wang
                              !nc->peer->link_down) {
119 afbaa7b4 Michael S. Tsirkin
        return;
120 afbaa7b4 Michael S. Tsirkin
    }
121 afbaa7b4 Michael S. Tsirkin
    if (!n->vhost_started) {
122 5430a28f mst@redhat.com
        int r;
123 17a0ca55 KONRAD Frederic
        if (!vhost_net_query(tap_get_vhost_net(nc->peer), vdev)) {
124 5430a28f mst@redhat.com
            return;
125 5430a28f mst@redhat.com
        }
126 1830b80f Michael S. Tsirkin
        n->vhost_started = 1;
127 17a0ca55 KONRAD Frederic
        r = vhost_net_start(vdev, n->nic->ncs, queues);
128 afbaa7b4 Michael S. Tsirkin
        if (r < 0) {
129 e7b43f7e Stefan Hajnoczi
            error_report("unable to start vhost net: %d: "
130 e7b43f7e Stefan Hajnoczi
                         "falling back on userspace virtio", -r);
131 1830b80f Michael S. Tsirkin
            n->vhost_started = 0;
132 afbaa7b4 Michael S. Tsirkin
        }
133 afbaa7b4 Michael S. Tsirkin
    } else {
134 17a0ca55 KONRAD Frederic
        vhost_net_stop(vdev, n->nic->ncs, queues);
135 afbaa7b4 Michael S. Tsirkin
        n->vhost_started = 0;
136 afbaa7b4 Michael S. Tsirkin
    }
137 afbaa7b4 Michael S. Tsirkin
}
138 afbaa7b4 Michael S. Tsirkin
139 783e7706 Michael S. Tsirkin
static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
140 783e7706 Michael S. Tsirkin
{
141 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
142 fed699f9 Jason Wang
    VirtIONetQueue *q;
143 fed699f9 Jason Wang
    int i;
144 fed699f9 Jason Wang
    uint8_t queue_status;
145 783e7706 Michael S. Tsirkin
146 783e7706 Michael S. Tsirkin
    virtio_net_vhost_status(n, status);
147 783e7706 Michael S. Tsirkin
148 fed699f9 Jason Wang
    for (i = 0; i < n->max_queues; i++) {
149 fed699f9 Jason Wang
        q = &n->vqs[i];
150 783e7706 Michael S. Tsirkin
151 fed699f9 Jason Wang
        if ((!n->multiqueue && i != 0) || i >= n->curr_queues) {
152 fed699f9 Jason Wang
            queue_status = 0;
153 783e7706 Michael S. Tsirkin
        } else {
154 fed699f9 Jason Wang
            queue_status = status;
155 783e7706 Michael S. Tsirkin
        }
156 fed699f9 Jason Wang
157 fed699f9 Jason Wang
        if (!q->tx_waiting) {
158 fed699f9 Jason Wang
            continue;
159 fed699f9 Jason Wang
        }
160 fed699f9 Jason Wang
161 fed699f9 Jason Wang
        if (virtio_net_started(n, queue_status) && !n->vhost_started) {
162 fed699f9 Jason Wang
            if (q->tx_timer) {
163 fed699f9 Jason Wang
                qemu_mod_timer(q->tx_timer,
164 fed699f9 Jason Wang
                               qemu_get_clock_ns(vm_clock) + n->tx_timeout);
165 fed699f9 Jason Wang
            } else {
166 fed699f9 Jason Wang
                qemu_bh_schedule(q->tx_bh);
167 fed699f9 Jason Wang
            }
168 783e7706 Michael S. Tsirkin
        } else {
169 fed699f9 Jason Wang
            if (q->tx_timer) {
170 fed699f9 Jason Wang
                qemu_del_timer(q->tx_timer);
171 fed699f9 Jason Wang
            } else {
172 fed699f9 Jason Wang
                qemu_bh_cancel(q->tx_bh);
173 fed699f9 Jason Wang
            }
174 783e7706 Michael S. Tsirkin
        }
175 783e7706 Michael S. Tsirkin
    }
176 783e7706 Michael S. Tsirkin
}
177 783e7706 Michael S. Tsirkin
178 4e68f7a0 Stefan Hajnoczi
static void virtio_net_set_link_status(NetClientState *nc)
179 554c97dd aliguori
{
180 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
181 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
182 554c97dd aliguori
    uint16_t old_status = n->status;
183 554c97dd aliguori
184 eb6b6c12 Mark McLoughlin
    if (nc->link_down)
185 554c97dd aliguori
        n->status &= ~VIRTIO_NET_S_LINK_UP;
186 554c97dd aliguori
    else
187 554c97dd aliguori
        n->status |= VIRTIO_NET_S_LINK_UP;
188 554c97dd aliguori
189 554c97dd aliguori
    if (n->status != old_status)
190 17a0ca55 KONRAD Frederic
        virtio_notify_config(vdev);
191 afbaa7b4 Michael S. Tsirkin
192 17a0ca55 KONRAD Frederic
    virtio_net_set_status(vdev, vdev->status);
193 554c97dd aliguori
}
194 554c97dd aliguori
195 002437cd aliguori
static void virtio_net_reset(VirtIODevice *vdev)
196 002437cd aliguori
{
197 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
198 002437cd aliguori
199 002437cd aliguori
    /* Reset back to compatibility mode */
200 002437cd aliguori
    n->promisc = 1;
201 002437cd aliguori
    n->allmulti = 0;
202 015cb166 Alex Williamson
    n->alluni = 0;
203 015cb166 Alex Williamson
    n->nomulti = 0;
204 015cb166 Alex Williamson
    n->nouni = 0;
205 015cb166 Alex Williamson
    n->nobcast = 0;
206 fed699f9 Jason Wang
    /* multiqueue is disabled by default */
207 fed699f9 Jason Wang
    n->curr_queues = 1;
208 b6503ed9 aliguori
209 f21c0ed9 aliguori
    /* Flush any MAC and VLAN filter table state */
210 b6503ed9 aliguori
    n->mac_table.in_use = 0;
211 2d9aba39 Alex Williamson
    n->mac_table.first_multi = 0;
212 8fd2a2f1 Alex Williamson
    n->mac_table.multi_overflow = 0;
213 8fd2a2f1 Alex Williamson
    n->mac_table.uni_overflow = 0;
214 b6503ed9 aliguori
    memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
215 41dc8a67 Michael S. Tsirkin
    memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
216 f21c0ed9 aliguori
    memset(n->vlans, 0, MAX_VLAN >> 3);
217 002437cd aliguori
}
218 002437cd aliguori
219 6e371ab8 Michael S. Tsirkin
static void peer_test_vnet_hdr(VirtIONet *n)
220 3a330134 Mark McLoughlin
{
221 b356f76d Jason Wang
    NetClientState *nc = qemu_get_queue(n->nic);
222 b356f76d Jason Wang
    if (!nc->peer) {
223 6e371ab8 Michael S. Tsirkin
        return;
224 b356f76d Jason Wang
    }
225 3a330134 Mark McLoughlin
226 b356f76d Jason Wang
    if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
227 6e371ab8 Michael S. Tsirkin
        return;
228 b356f76d Jason Wang
    }
229 3a330134 Mark McLoughlin
230 b356f76d Jason Wang
    n->has_vnet_hdr = tap_has_vnet_hdr(nc->peer);
231 6e371ab8 Michael S. Tsirkin
}
232 3a330134 Mark McLoughlin
233 6e371ab8 Michael S. Tsirkin
static int peer_has_vnet_hdr(VirtIONet *n)
234 6e371ab8 Michael S. Tsirkin
{
235 3a330134 Mark McLoughlin
    return n->has_vnet_hdr;
236 3a330134 Mark McLoughlin
}
237 3a330134 Mark McLoughlin
238 0ce0e8f4 Mark McLoughlin
static int peer_has_ufo(VirtIONet *n)
239 0ce0e8f4 Mark McLoughlin
{
240 0ce0e8f4 Mark McLoughlin
    if (!peer_has_vnet_hdr(n))
241 0ce0e8f4 Mark McLoughlin
        return 0;
242 0ce0e8f4 Mark McLoughlin
243 b356f76d Jason Wang
    n->has_ufo = tap_has_ufo(qemu_get_queue(n->nic)->peer);
244 0ce0e8f4 Mark McLoughlin
245 0ce0e8f4 Mark McLoughlin
    return n->has_ufo;
246 0ce0e8f4 Mark McLoughlin
}
247 0ce0e8f4 Mark McLoughlin
248 ff3a8066 Michael S. Tsirkin
static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs)
249 ff3a8066 Michael S. Tsirkin
{
250 fed699f9 Jason Wang
    int i;
251 fed699f9 Jason Wang
    NetClientState *nc;
252 fed699f9 Jason Wang
253 ff3a8066 Michael S. Tsirkin
    n->mergeable_rx_bufs = mergeable_rx_bufs;
254 ff3a8066 Michael S. Tsirkin
255 ff3a8066 Michael S. Tsirkin
    n->guest_hdr_len = n->mergeable_rx_bufs ?
256 ff3a8066 Michael S. Tsirkin
        sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
257 ff3a8066 Michael S. Tsirkin
258 fed699f9 Jason Wang
    for (i = 0; i < n->max_queues; i++) {
259 fed699f9 Jason Wang
        nc = qemu_get_subqueue(n->nic, i);
260 fed699f9 Jason Wang
261 fed699f9 Jason Wang
        if (peer_has_vnet_hdr(n) &&
262 fed699f9 Jason Wang
            tap_has_vnet_hdr_len(nc->peer, n->guest_hdr_len)) {
263 fed699f9 Jason Wang
            tap_set_vnet_hdr_len(nc->peer, n->guest_hdr_len);
264 fed699f9 Jason Wang
            n->host_hdr_len = n->guest_hdr_len;
265 fed699f9 Jason Wang
        }
266 ff3a8066 Michael S. Tsirkin
    }
267 ff3a8066 Michael S. Tsirkin
}
268 ff3a8066 Michael S. Tsirkin
269 fed699f9 Jason Wang
static int peer_attach(VirtIONet *n, int index)
270 fed699f9 Jason Wang
{
271 fed699f9 Jason Wang
    NetClientState *nc = qemu_get_subqueue(n->nic, index);
272 fed699f9 Jason Wang
273 fed699f9 Jason Wang
    if (!nc->peer) {
274 fed699f9 Jason Wang
        return 0;
275 fed699f9 Jason Wang
    }
276 fed699f9 Jason Wang
277 fed699f9 Jason Wang
    if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
278 fed699f9 Jason Wang
        return 0;
279 fed699f9 Jason Wang
    }
280 fed699f9 Jason Wang
281 fed699f9 Jason Wang
    return tap_enable(nc->peer);
282 fed699f9 Jason Wang
}
283 fed699f9 Jason Wang
284 fed699f9 Jason Wang
static int peer_detach(VirtIONet *n, int index)
285 fed699f9 Jason Wang
{
286 fed699f9 Jason Wang
    NetClientState *nc = qemu_get_subqueue(n->nic, index);
287 fed699f9 Jason Wang
288 fed699f9 Jason Wang
    if (!nc->peer) {
289 fed699f9 Jason Wang
        return 0;
290 fed699f9 Jason Wang
    }
291 fed699f9 Jason Wang
292 fed699f9 Jason Wang
    if (nc->peer->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
293 fed699f9 Jason Wang
        return 0;
294 fed699f9 Jason Wang
    }
295 fed699f9 Jason Wang
296 fed699f9 Jason Wang
    return tap_disable(nc->peer);
297 fed699f9 Jason Wang
}
298 fed699f9 Jason Wang
299 fed699f9 Jason Wang
static void virtio_net_set_queues(VirtIONet *n)
300 fed699f9 Jason Wang
{
301 fed699f9 Jason Wang
    int i;
302 fed699f9 Jason Wang
303 fed699f9 Jason Wang
    for (i = 0; i < n->max_queues; i++) {
304 fed699f9 Jason Wang
        if (i < n->curr_queues) {
305 fed699f9 Jason Wang
            assert(!peer_attach(n, i));
306 fed699f9 Jason Wang
        } else {
307 fed699f9 Jason Wang
            assert(!peer_detach(n, i));
308 fed699f9 Jason Wang
        }
309 fed699f9 Jason Wang
    }
310 fed699f9 Jason Wang
}
311 fed699f9 Jason Wang
312 fed699f9 Jason Wang
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue, int ctrl);
313 fed699f9 Jason Wang
314 8172539d Michael S. Tsirkin
static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
315 fbe78f4f aliguori
{
316 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
317 b356f76d Jason Wang
    NetClientState *nc = qemu_get_queue(n->nic);
318 fbe78f4f aliguori
319 c9f79a3f Michael S. Tsirkin
    features |= (1 << VIRTIO_NET_F_MAC);
320 c9f79a3f Michael S. Tsirkin
321 6e371ab8 Michael S. Tsirkin
    if (!peer_has_vnet_hdr(n)) {
322 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_CSUM);
323 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4);
324 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6);
325 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN);
326 8172539d Michael S. Tsirkin
327 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM);
328 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4);
329 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6);
330 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN);
331 8172539d Michael S. Tsirkin
    }
332 3a330134 Mark McLoughlin
333 8172539d Michael S. Tsirkin
    if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
334 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO);
335 8172539d Michael S. Tsirkin
        features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
336 3a330134 Mark McLoughlin
    }
337 3a330134 Mark McLoughlin
338 b356f76d Jason Wang
    if (!nc->peer || nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
339 9bc6304c Michael S. Tsirkin
        return features;
340 9bc6304c Michael S. Tsirkin
    }
341 b356f76d Jason Wang
    if (!tap_get_vhost_net(nc->peer)) {
342 9bc6304c Michael S. Tsirkin
        return features;
343 9bc6304c Michael S. Tsirkin
    }
344 b356f76d Jason Wang
    return vhost_net_get_features(tap_get_vhost_net(nc->peer), features);
345 fbe78f4f aliguori
}
346 fbe78f4f aliguori
347 8eca6b1b aliguori
static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
348 8eca6b1b aliguori
{
349 8eca6b1b aliguori
    uint32_t features = 0;
350 8eca6b1b aliguori
351 8eca6b1b aliguori
    /* Linux kernel 2.6.25.  It understood MAC (as everyone must),
352 8eca6b1b aliguori
     * but also these: */
353 8eca6b1b aliguori
    features |= (1 << VIRTIO_NET_F_MAC);
354 184bd048 Dustin Kirkland
    features |= (1 << VIRTIO_NET_F_CSUM);
355 184bd048 Dustin Kirkland
    features |= (1 << VIRTIO_NET_F_HOST_TSO4);
356 184bd048 Dustin Kirkland
    features |= (1 << VIRTIO_NET_F_HOST_TSO6);
357 184bd048 Dustin Kirkland
    features |= (1 << VIRTIO_NET_F_HOST_ECN);
358 8eca6b1b aliguori
359 8172539d Michael S. Tsirkin
    return features;
360 8eca6b1b aliguori
}
361 8eca6b1b aliguori
362 fbe78f4f aliguori
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
363 fbe78f4f aliguori
{
364 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
365 fed699f9 Jason Wang
    int i;
366 fed699f9 Jason Wang
367 fed699f9 Jason Wang
    virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ)),
368 fed699f9 Jason Wang
                              !!(features & (1 << VIRTIO_NET_F_CTRL_VQ)));
369 fbe78f4f aliguori
370 ff3a8066 Michael S. Tsirkin
    virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)));
371 f5436dd9 Mark McLoughlin
372 f5436dd9 Mark McLoughlin
    if (n->has_vnet_hdr) {
373 fed699f9 Jason Wang
        tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer,
374 f5436dd9 Mark McLoughlin
                        (features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
375 f5436dd9 Mark McLoughlin
                        (features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
376 f5436dd9 Mark McLoughlin
                        (features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
377 6c9f58ba Sridhar Samudrala
                        (features >> VIRTIO_NET_F_GUEST_ECN)  & 1,
378 6c9f58ba Sridhar Samudrala
                        (features >> VIRTIO_NET_F_GUEST_UFO)  & 1);
379 f5436dd9 Mark McLoughlin
    }
380 fed699f9 Jason Wang
381 fed699f9 Jason Wang
    for (i = 0;  i < n->max_queues; i++) {
382 fed699f9 Jason Wang
        NetClientState *nc = qemu_get_subqueue(n->nic, i);
383 fed699f9 Jason Wang
384 fed699f9 Jason Wang
        if (!nc->peer || nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
385 fed699f9 Jason Wang
            continue;
386 fed699f9 Jason Wang
        }
387 fed699f9 Jason Wang
        if (!tap_get_vhost_net(nc->peer)) {
388 fed699f9 Jason Wang
            continue;
389 fed699f9 Jason Wang
        }
390 fed699f9 Jason Wang
        vhost_net_ack_features(tap_get_vhost_net(nc->peer), features);
391 dc14a397 David L Stevens
    }
392 fbe78f4f aliguori
}
393 fbe78f4f aliguori
394 002437cd aliguori
static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
395 921ac5d0 Michael S. Tsirkin
                                     struct iovec *iov, unsigned int iov_cnt)
396 002437cd aliguori
{
397 002437cd aliguori
    uint8_t on;
398 921ac5d0 Michael S. Tsirkin
    size_t s;
399 002437cd aliguori
400 921ac5d0 Michael S. Tsirkin
    s = iov_to_buf(iov, iov_cnt, 0, &on, sizeof(on));
401 921ac5d0 Michael S. Tsirkin
    if (s != sizeof(on)) {
402 921ac5d0 Michael S. Tsirkin
        return VIRTIO_NET_ERR;
403 002437cd aliguori
    }
404 002437cd aliguori
405 dd23454b Amos Kong
    if (cmd == VIRTIO_NET_CTRL_RX_PROMISC) {
406 002437cd aliguori
        n->promisc = on;
407 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_ALLMULTI) {
408 002437cd aliguori
        n->allmulti = on;
409 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_ALLUNI) {
410 015cb166 Alex Williamson
        n->alluni = on;
411 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_NOMULTI) {
412 015cb166 Alex Williamson
        n->nomulti = on;
413 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_NOUNI) {
414 015cb166 Alex Williamson
        n->nouni = on;
415 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_NOBCAST) {
416 015cb166 Alex Williamson
        n->nobcast = on;
417 921ac5d0 Michael S. Tsirkin
    } else {
418 002437cd aliguori
        return VIRTIO_NET_ERR;
419 921ac5d0 Michael S. Tsirkin
    }
420 002437cd aliguori
421 002437cd aliguori
    return VIRTIO_NET_OK;
422 002437cd aliguori
}
423 002437cd aliguori
424 b6503ed9 aliguori
static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
425 921ac5d0 Michael S. Tsirkin
                                 struct iovec *iov, unsigned int iov_cnt)
426 b6503ed9 aliguori
{
427 b6503ed9 aliguori
    struct virtio_net_ctrl_mac mac_data;
428 921ac5d0 Michael S. Tsirkin
    size_t s;
429 b6503ed9 aliguori
430 c1943a3f Amos Kong
    if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {
431 c1943a3f Amos Kong
        if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {
432 c1943a3f Amos Kong
            return VIRTIO_NET_ERR;
433 c1943a3f Amos Kong
        }
434 c1943a3f Amos Kong
        s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));
435 c1943a3f Amos Kong
        assert(s == sizeof(n->mac));
436 b356f76d Jason Wang
        qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
437 c1943a3f Amos Kong
        return VIRTIO_NET_OK;
438 c1943a3f Amos Kong
    }
439 c1943a3f Amos Kong
440 921ac5d0 Michael S. Tsirkin
    if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) {
441 b6503ed9 aliguori
        return VIRTIO_NET_ERR;
442 921ac5d0 Michael S. Tsirkin
    }
443 b6503ed9 aliguori
444 b6503ed9 aliguori
    n->mac_table.in_use = 0;
445 2d9aba39 Alex Williamson
    n->mac_table.first_multi = 0;
446 8fd2a2f1 Alex Williamson
    n->mac_table.uni_overflow = 0;
447 8fd2a2f1 Alex Williamson
    n->mac_table.multi_overflow = 0;
448 b6503ed9 aliguori
    memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
449 b6503ed9 aliguori
450 921ac5d0 Michael S. Tsirkin
    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
451 921ac5d0 Michael S. Tsirkin
                   sizeof(mac_data.entries));
452 921ac5d0 Michael S. Tsirkin
    mac_data.entries = ldl_p(&mac_data.entries);
453 921ac5d0 Michael S. Tsirkin
    if (s != sizeof(mac_data.entries)) {
454 921ac5d0 Michael S. Tsirkin
        return VIRTIO_NET_ERR;
455 921ac5d0 Michael S. Tsirkin
    }
456 921ac5d0 Michael S. Tsirkin
    iov_discard_front(&iov, &iov_cnt, s);
457 b6503ed9 aliguori
458 921ac5d0 Michael S. Tsirkin
    if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) {
459 b6503ed9 aliguori
        return VIRTIO_NET_ERR;
460 921ac5d0 Michael S. Tsirkin
    }
461 b6503ed9 aliguori
462 b6503ed9 aliguori
    if (mac_data.entries <= MAC_TABLE_ENTRIES) {
463 921ac5d0 Michael S. Tsirkin
        s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
464 921ac5d0 Michael S. Tsirkin
                       mac_data.entries * ETH_ALEN);
465 921ac5d0 Michael S. Tsirkin
        if (s != mac_data.entries * ETH_ALEN) {
466 921ac5d0 Michael S. Tsirkin
            return VIRTIO_NET_ERR;
467 921ac5d0 Michael S. Tsirkin
        }
468 b6503ed9 aliguori
        n->mac_table.in_use += mac_data.entries;
469 b6503ed9 aliguori
    } else {
470 8fd2a2f1 Alex Williamson
        n->mac_table.uni_overflow = 1;
471 b6503ed9 aliguori
    }
472 b6503ed9 aliguori
473 921ac5d0 Michael S. Tsirkin
    iov_discard_front(&iov, &iov_cnt, mac_data.entries * ETH_ALEN);
474 921ac5d0 Michael S. Tsirkin
475 2d9aba39 Alex Williamson
    n->mac_table.first_multi = n->mac_table.in_use;
476 2d9aba39 Alex Williamson
477 921ac5d0 Michael S. Tsirkin
    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
478 921ac5d0 Michael S. Tsirkin
                   sizeof(mac_data.entries));
479 921ac5d0 Michael S. Tsirkin
    mac_data.entries = ldl_p(&mac_data.entries);
480 921ac5d0 Michael S. Tsirkin
    if (s != sizeof(mac_data.entries)) {
481 921ac5d0 Michael S. Tsirkin
        return VIRTIO_NET_ERR;
482 921ac5d0 Michael S. Tsirkin
    }
483 921ac5d0 Michael S. Tsirkin
484 921ac5d0 Michael S. Tsirkin
    iov_discard_front(&iov, &iov_cnt, s);
485 b6503ed9 aliguori
486 921ac5d0 Michael S. Tsirkin
    if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) {
487 b6503ed9 aliguori
        return VIRTIO_NET_ERR;
488 921ac5d0 Michael S. Tsirkin
    }
489 b6503ed9 aliguori
490 921ac5d0 Michael S. Tsirkin
    if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
491 921ac5d0 Michael S. Tsirkin
        s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
492 921ac5d0 Michael S. Tsirkin
                       mac_data.entries * ETH_ALEN);
493 921ac5d0 Michael S. Tsirkin
        if (s != mac_data.entries * ETH_ALEN) {
494 921ac5d0 Michael S. Tsirkin
            return VIRTIO_NET_ERR;
495 8fd2a2f1 Alex Williamson
        }
496 921ac5d0 Michael S. Tsirkin
        n->mac_table.in_use += mac_data.entries;
497 921ac5d0 Michael S. Tsirkin
    } else {
498 921ac5d0 Michael S. Tsirkin
        n->mac_table.multi_overflow = 1;
499 b6503ed9 aliguori
    }
500 b6503ed9 aliguori
501 b6503ed9 aliguori
    return VIRTIO_NET_OK;
502 b6503ed9 aliguori
}
503 b6503ed9 aliguori
504 f21c0ed9 aliguori
static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
505 921ac5d0 Michael S. Tsirkin
                                        struct iovec *iov, unsigned int iov_cnt)
506 f21c0ed9 aliguori
{
507 f21c0ed9 aliguori
    uint16_t vid;
508 921ac5d0 Michael S. Tsirkin
    size_t s;
509 f21c0ed9 aliguori
510 921ac5d0 Michael S. Tsirkin
    s = iov_to_buf(iov, iov_cnt, 0, &vid, sizeof(vid));
511 921ac5d0 Michael S. Tsirkin
    vid = lduw_p(&vid);
512 921ac5d0 Michael S. Tsirkin
    if (s != sizeof(vid)) {
513 f21c0ed9 aliguori
        return VIRTIO_NET_ERR;
514 f21c0ed9 aliguori
    }
515 f21c0ed9 aliguori
516 f21c0ed9 aliguori
    if (vid >= MAX_VLAN)
517 f21c0ed9 aliguori
        return VIRTIO_NET_ERR;
518 f21c0ed9 aliguori
519 f21c0ed9 aliguori
    if (cmd == VIRTIO_NET_CTRL_VLAN_ADD)
520 f21c0ed9 aliguori
        n->vlans[vid >> 5] |= (1U << (vid & 0x1f));
521 f21c0ed9 aliguori
    else if (cmd == VIRTIO_NET_CTRL_VLAN_DEL)
522 f21c0ed9 aliguori
        n->vlans[vid >> 5] &= ~(1U << (vid & 0x1f));
523 f21c0ed9 aliguori
    else
524 f21c0ed9 aliguori
        return VIRTIO_NET_ERR;
525 f21c0ed9 aliguori
526 f21c0ed9 aliguori
    return VIRTIO_NET_OK;
527 f21c0ed9 aliguori
}
528 f21c0ed9 aliguori
529 fed699f9 Jason Wang
static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
530 f8f7c533 Jason Wang
                                struct iovec *iov, unsigned int iov_cnt)
531 fed699f9 Jason Wang
{
532 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
533 f8f7c533 Jason Wang
    struct virtio_net_ctrl_mq mq;
534 f8f7c533 Jason Wang
    size_t s;
535 f8f7c533 Jason Wang
    uint16_t queues;
536 fed699f9 Jason Wang
537 f8f7c533 Jason Wang
    s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq));
538 f8f7c533 Jason Wang
    if (s != sizeof(mq)) {
539 fed699f9 Jason Wang
        return VIRTIO_NET_ERR;
540 fed699f9 Jason Wang
    }
541 fed699f9 Jason Wang
542 fed699f9 Jason Wang
    if (cmd != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
543 fed699f9 Jason Wang
        return VIRTIO_NET_ERR;
544 fed699f9 Jason Wang
    }
545 fed699f9 Jason Wang
546 f8f7c533 Jason Wang
    queues = lduw_p(&mq.virtqueue_pairs);
547 fed699f9 Jason Wang
548 f8f7c533 Jason Wang
    if (queues < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
549 f8f7c533 Jason Wang
        queues > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
550 f8f7c533 Jason Wang
        queues > n->max_queues ||
551 fed699f9 Jason Wang
        !n->multiqueue) {
552 fed699f9 Jason Wang
        return VIRTIO_NET_ERR;
553 fed699f9 Jason Wang
    }
554 fed699f9 Jason Wang
555 f8f7c533 Jason Wang
    n->curr_queues = queues;
556 fed699f9 Jason Wang
    /* stop the backend before changing the number of queues to avoid handling a
557 fed699f9 Jason Wang
     * disabled queue */
558 17a0ca55 KONRAD Frederic
    virtio_net_set_status(vdev, vdev->status);
559 fed699f9 Jason Wang
    virtio_net_set_queues(n);
560 fed699f9 Jason Wang
561 fed699f9 Jason Wang
    return VIRTIO_NET_OK;
562 fed699f9 Jason Wang
}
563 3d11d36c aliguori
static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
564 3d11d36c aliguori
{
565 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
566 3d11d36c aliguori
    struct virtio_net_ctrl_hdr ctrl;
567 3d11d36c aliguori
    virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
568 3d11d36c aliguori
    VirtQueueElement elem;
569 921ac5d0 Michael S. Tsirkin
    size_t s;
570 921ac5d0 Michael S. Tsirkin
    struct iovec *iov;
571 921ac5d0 Michael S. Tsirkin
    unsigned int iov_cnt;
572 3d11d36c aliguori
573 3d11d36c aliguori
    while (virtqueue_pop(vq, &elem)) {
574 921ac5d0 Michael S. Tsirkin
        if (iov_size(elem.in_sg, elem.in_num) < sizeof(status) ||
575 921ac5d0 Michael S. Tsirkin
            iov_size(elem.out_sg, elem.out_num) < sizeof(ctrl)) {
576 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net ctrl missing headers");
577 3d11d36c aliguori
            exit(1);
578 3d11d36c aliguori
        }
579 3d11d36c aliguori
580 921ac5d0 Michael S. Tsirkin
        iov = elem.out_sg;
581 921ac5d0 Michael S. Tsirkin
        iov_cnt = elem.out_num;
582 921ac5d0 Michael S. Tsirkin
        s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
583 921ac5d0 Michael S. Tsirkin
        iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
584 921ac5d0 Michael S. Tsirkin
        if (s != sizeof(ctrl)) {
585 921ac5d0 Michael S. Tsirkin
            status = VIRTIO_NET_ERR;
586 dd23454b Amos Kong
        } else if (ctrl.class == VIRTIO_NET_CTRL_RX) {
587 921ac5d0 Michael S. Tsirkin
            status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, iov_cnt);
588 921ac5d0 Michael S. Tsirkin
        } else if (ctrl.class == VIRTIO_NET_CTRL_MAC) {
589 921ac5d0 Michael S. Tsirkin
            status = virtio_net_handle_mac(n, ctrl.cmd, iov, iov_cnt);
590 921ac5d0 Michael S. Tsirkin
        } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
591 921ac5d0 Michael S. Tsirkin
            status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
592 fed699f9 Jason Wang
        } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) {
593 f8f7c533 Jason Wang
            status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt);
594 3d11d36c aliguori
        }
595 3d11d36c aliguori
596 921ac5d0 Michael S. Tsirkin
        s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status));
597 921ac5d0 Michael S. Tsirkin
        assert(s == sizeof(status));
598 3d11d36c aliguori
599 3d11d36c aliguori
        virtqueue_push(vq, &elem, sizeof(status));
600 3d11d36c aliguori
        virtio_notify(vdev, vq);
601 3d11d36c aliguori
    }
602 3d11d36c aliguori
}
603 3d11d36c aliguori
604 fbe78f4f aliguori
/* RX */
605 fbe78f4f aliguori
606 fbe78f4f aliguori
static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
607 fbe78f4f aliguori
{
608 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
609 fed699f9 Jason Wang
    int queue_index = vq2q(virtio_get_queue_index(vq));
610 8aeff62d Mark McLoughlin
611 fed699f9 Jason Wang
    qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index));
612 fbe78f4f aliguori
}
613 fbe78f4f aliguori
614 4e68f7a0 Stefan Hajnoczi
static int virtio_net_can_receive(NetClientState *nc)
615 fbe78f4f aliguori
{
616 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
617 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
618 fed699f9 Jason Wang
    VirtIONetQueue *q = virtio_net_get_subqueue(nc);
619 0c87e93e Jason Wang
620 17a0ca55 KONRAD Frederic
    if (!vdev->vm_running) {
621 95477323 Michael S. Tsirkin
        return 0;
622 95477323 Michael S. Tsirkin
    }
623 cdd5cc12 Mark McLoughlin
624 fed699f9 Jason Wang
    if (nc->queue_index >= n->curr_queues) {
625 fed699f9 Jason Wang
        return 0;
626 fed699f9 Jason Wang
    }
627 fed699f9 Jason Wang
628 0c87e93e Jason Wang
    if (!virtio_queue_ready(q->rx_vq) ||
629 17a0ca55 KONRAD Frederic
        !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
630 fbe78f4f aliguori
        return 0;
631 0c87e93e Jason Wang
    }
632 fbe78f4f aliguori
633 cdd5cc12 Mark McLoughlin
    return 1;
634 cdd5cc12 Mark McLoughlin
}
635 cdd5cc12 Mark McLoughlin
636 0c87e93e Jason Wang
static int virtio_net_has_buffers(VirtIONetQueue *q, int bufsize)
637 cdd5cc12 Mark McLoughlin
{
638 0c87e93e Jason Wang
    VirtIONet *n = q->n;
639 0c87e93e Jason Wang
    if (virtio_queue_empty(q->rx_vq) ||
640 fbe78f4f aliguori
        (n->mergeable_rx_bufs &&
641 0c87e93e Jason Wang
         !virtqueue_avail_bytes(q->rx_vq, bufsize, 0))) {
642 0c87e93e Jason Wang
        virtio_queue_set_notification(q->rx_vq, 1);
643 06b12970 Tom Lendacky
644 06b12970 Tom Lendacky
        /* To avoid a race condition where the guest has made some buffers
645 06b12970 Tom Lendacky
         * available after the above check but before notification was
646 06b12970 Tom Lendacky
         * enabled, check for available buffers again.
647 06b12970 Tom Lendacky
         */
648 0c87e93e Jason Wang
        if (virtio_queue_empty(q->rx_vq) ||
649 06b12970 Tom Lendacky
            (n->mergeable_rx_bufs &&
650 0c87e93e Jason Wang
             !virtqueue_avail_bytes(q->rx_vq, bufsize, 0))) {
651 06b12970 Tom Lendacky
            return 0;
652 0c87e93e Jason Wang
        }
653 fbe78f4f aliguori
    }
654 fbe78f4f aliguori
655 0c87e93e Jason Wang
    virtio_queue_set_notification(q->rx_vq, 0);
656 fbe78f4f aliguori
    return 1;
657 fbe78f4f aliguori
}
658 fbe78f4f aliguori
659 1d41b0c1 Anthony Liguori
/* dhclient uses AF_PACKET but doesn't pass auxdata to the kernel so
660 1d41b0c1 Anthony Liguori
 * it never finds out that the packets don't have valid checksums.  This
661 1d41b0c1 Anthony Liguori
 * causes dhclient to get upset.  Fedora's carried a patch for ages to
662 1d41b0c1 Anthony Liguori
 * fix this with Xen but it hasn't appeared in an upstream release of
663 1d41b0c1 Anthony Liguori
 * dhclient yet.
664 1d41b0c1 Anthony Liguori
 *
665 1d41b0c1 Anthony Liguori
 * To avoid breaking existing guests, we catch udp packets and add
666 1d41b0c1 Anthony Liguori
 * checksums.  This is terrible but it's better than hacking the guest
667 1d41b0c1 Anthony Liguori
 * kernels.
668 1d41b0c1 Anthony Liguori
 *
669 1d41b0c1 Anthony Liguori
 * N.B. if we introduce a zero-copy API, this operation is no longer free so
670 1d41b0c1 Anthony Liguori
 * we should provide a mechanism to disable it to avoid polluting the host
671 1d41b0c1 Anthony Liguori
 * cache.
672 1d41b0c1 Anthony Liguori
 */
673 1d41b0c1 Anthony Liguori
static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
674 22cc84db Michael S. Tsirkin
                                        uint8_t *buf, size_t size)
675 1d41b0c1 Anthony Liguori
{
676 1d41b0c1 Anthony Liguori
    if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
677 1d41b0c1 Anthony Liguori
        (size > 27 && size < 1500) && /* normal sized MTU */
678 1d41b0c1 Anthony Liguori
        (buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
679 1d41b0c1 Anthony Liguori
        (buf[23] == 17) && /* ip.protocol == UDP */
680 1d41b0c1 Anthony Liguori
        (buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
681 22cc84db Michael S. Tsirkin
        net_checksum_calculate(buf, size);
682 1d41b0c1 Anthony Liguori
        hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
683 1d41b0c1 Anthony Liguori
    }
684 1d41b0c1 Anthony Liguori
}
685 1d41b0c1 Anthony Liguori
686 280598b7 Michael S. Tsirkin
static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt,
687 280598b7 Michael S. Tsirkin
                           const void *buf, size_t size)
688 fbe78f4f aliguori
{
689 3a330134 Mark McLoughlin
    if (n->has_vnet_hdr) {
690 22cc84db Michael S. Tsirkin
        /* FIXME this cast is evil */
691 22cc84db Michael S. Tsirkin
        void *wbuf = (void *)buf;
692 280598b7 Michael S. Tsirkin
        work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len,
693 280598b7 Michael S. Tsirkin
                                    size - n->host_hdr_len);
694 280598b7 Michael S. Tsirkin
        iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
695 22cc84db Michael S. Tsirkin
    } else {
696 22cc84db Michael S. Tsirkin
        struct virtio_net_hdr hdr = {
697 22cc84db Michael S. Tsirkin
            .flags = 0,
698 22cc84db Michael S. Tsirkin
            .gso_type = VIRTIO_NET_HDR_GSO_NONE
699 22cc84db Michael S. Tsirkin
        };
700 22cc84db Michael S. Tsirkin
        iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr);
701 3a330134 Mark McLoughlin
    }
702 fbe78f4f aliguori
}
703 fbe78f4f aliguori
704 3831ab20 aliguori
static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
705 3831ab20 aliguori
{
706 3831ab20 aliguori
    static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
707 f21c0ed9 aliguori
    static const uint8_t vlan[] = {0x81, 0x00};
708 3831ab20 aliguori
    uint8_t *ptr = (uint8_t *)buf;
709 b6503ed9 aliguori
    int i;
710 3831ab20 aliguori
711 3831ab20 aliguori
    if (n->promisc)
712 3831ab20 aliguori
        return 1;
713 3831ab20 aliguori
714 e043ebc6 Michael S. Tsirkin
    ptr += n->host_hdr_len;
715 3a330134 Mark McLoughlin
716 f21c0ed9 aliguori
    if (!memcmp(&ptr[12], vlan, sizeof(vlan))) {
717 f21c0ed9 aliguori
        int vid = be16_to_cpup((uint16_t *)(ptr + 14)) & 0xfff;
718 f21c0ed9 aliguori
        if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f))))
719 f21c0ed9 aliguori
            return 0;
720 f21c0ed9 aliguori
    }
721 f21c0ed9 aliguori
722 bbe2f399 Alex Williamson
    if (ptr[0] & 1) { // multicast
723 bbe2f399 Alex Williamson
        if (!memcmp(ptr, bcast, sizeof(bcast))) {
724 015cb166 Alex Williamson
            return !n->nobcast;
725 015cb166 Alex Williamson
        } else if (n->nomulti) {
726 015cb166 Alex Williamson
            return 0;
727 8fd2a2f1 Alex Williamson
        } else if (n->allmulti || n->mac_table.multi_overflow) {
728 bbe2f399 Alex Williamson
            return 1;
729 bbe2f399 Alex Williamson
        }
730 2d9aba39 Alex Williamson
731 2d9aba39 Alex Williamson
        for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
732 2d9aba39 Alex Williamson
            if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) {
733 2d9aba39 Alex Williamson
                return 1;
734 2d9aba39 Alex Williamson
            }
735 2d9aba39 Alex Williamson
        }
736 bbe2f399 Alex Williamson
    } else { // unicast
737 015cb166 Alex Williamson
        if (n->nouni) {
738 015cb166 Alex Williamson
            return 0;
739 015cb166 Alex Williamson
        } else if (n->alluni || n->mac_table.uni_overflow) {
740 8fd2a2f1 Alex Williamson
            return 1;
741 8fd2a2f1 Alex Williamson
        } else if (!memcmp(ptr, n->mac, ETH_ALEN)) {
742 bbe2f399 Alex Williamson
            return 1;
743 bbe2f399 Alex Williamson
        }
744 3831ab20 aliguori
745 2d9aba39 Alex Williamson
        for (i = 0; i < n->mac_table.first_multi; i++) {
746 2d9aba39 Alex Williamson
            if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) {
747 2d9aba39 Alex Williamson
                return 1;
748 2d9aba39 Alex Williamson
            }
749 2d9aba39 Alex Williamson
        }
750 b6503ed9 aliguori
    }
751 b6503ed9 aliguori
752 3831ab20 aliguori
    return 0;
753 3831ab20 aliguori
}
754 3831ab20 aliguori
755 4e68f7a0 Stefan Hajnoczi
static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t size)
756 fbe78f4f aliguori
{
757 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
758 fed699f9 Jason Wang
    VirtIONetQueue *q = virtio_net_get_subqueue(nc);
759 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
760 63c58728 Michael S. Tsirkin
    struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
761 63c58728 Michael S. Tsirkin
    struct virtio_net_hdr_mrg_rxbuf mhdr;
762 63c58728 Michael S. Tsirkin
    unsigned mhdr_cnt = 0;
763 22cc84db Michael S. Tsirkin
    size_t offset, i, guest_offset;
764 fbe78f4f aliguori
765 fed699f9 Jason Wang
    if (!virtio_net_can_receive(nc)) {
766 cdd5cc12 Mark McLoughlin
        return -1;
767 b356f76d Jason Wang
    }
768 cdd5cc12 Mark McLoughlin
769 940cda94 Michael S. Tsirkin
    /* hdr_len refers to the header we supply to the guest */
770 0c87e93e Jason Wang
    if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
771 8aeff62d Mark McLoughlin
        return 0;
772 0c87e93e Jason Wang
    }
773 fbe78f4f aliguori
774 3831ab20 aliguori
    if (!receive_filter(n, buf, size))
775 4f1c942b Mark McLoughlin
        return size;
776 3831ab20 aliguori
777 fbe78f4f aliguori
    offset = i = 0;
778 fbe78f4f aliguori
779 fbe78f4f aliguori
    while (offset < size) {
780 fbe78f4f aliguori
        VirtQueueElement elem;
781 fbe78f4f aliguori
        int len, total;
782 22cc84db Michael S. Tsirkin
        const struct iovec *sg = elem.in_sg;
783 fbe78f4f aliguori
784 22c253d9 Amit Shah
        total = 0;
785 fbe78f4f aliguori
786 0c87e93e Jason Wang
        if (virtqueue_pop(q->rx_vq, &elem) == 0) {
787 fbe78f4f aliguori
            if (i == 0)
788 4f1c942b Mark McLoughlin
                return -1;
789 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net unexpected empty queue: "
790 279a4253 Michael S. Tsirkin
                    "i %zd mergeable %d offset %zd, size %zd, "
791 e7b43f7e Stefan Hajnoczi
                    "guest hdr len %zd, host hdr len %zd guest features 0x%x",
792 279a4253 Michael S. Tsirkin
                    i, n->mergeable_rx_bufs, offset, size,
793 17a0ca55 KONRAD Frederic
                    n->guest_hdr_len, n->host_hdr_len, vdev->guest_features);
794 fbe78f4f aliguori
            exit(1);
795 fbe78f4f aliguori
        }
796 fbe78f4f aliguori
797 fbe78f4f aliguori
        if (elem.in_num < 1) {
798 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net receive queue contains no in buffers");
799 fbe78f4f aliguori
            exit(1);
800 fbe78f4f aliguori
        }
801 fbe78f4f aliguori
802 fbe78f4f aliguori
        if (i == 0) {
803 c8d28e7e Michael S. Tsirkin
            assert(offset == 0);
804 63c58728 Michael S. Tsirkin
            if (n->mergeable_rx_bufs) {
805 63c58728 Michael S. Tsirkin
                mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg),
806 63c58728 Michael S. Tsirkin
                                    sg, elem.in_num,
807 63c58728 Michael S. Tsirkin
                                    offsetof(typeof(mhdr), num_buffers),
808 63c58728 Michael S. Tsirkin
                                    sizeof(mhdr.num_buffers));
809 63c58728 Michael S. Tsirkin
            }
810 fbe78f4f aliguori
811 c8d28e7e Michael S. Tsirkin
            receive_header(n, sg, elem.in_num, buf, size);
812 c8d28e7e Michael S. Tsirkin
            offset = n->host_hdr_len;
813 e35e23f6 Michael S. Tsirkin
            total += n->guest_hdr_len;
814 22cc84db Michael S. Tsirkin
            guest_offset = n->guest_hdr_len;
815 22cc84db Michael S. Tsirkin
        } else {
816 22cc84db Michael S. Tsirkin
            guest_offset = 0;
817 fbe78f4f aliguori
        }
818 fbe78f4f aliguori
819 fbe78f4f aliguori
        /* copy in packet.  ugh */
820 22cc84db Michael S. Tsirkin
        len = iov_from_buf(sg, elem.in_num, guest_offset,
821 dcf6f5e1 Michael Tokarev
                           buf + offset, size - offset);
822 fbe78f4f aliguori
        total += len;
823 279a4253 Michael S. Tsirkin
        offset += len;
824 279a4253 Michael S. Tsirkin
        /* If buffers can't be merged, at this point we
825 279a4253 Michael S. Tsirkin
         * must have consumed the complete packet.
826 279a4253 Michael S. Tsirkin
         * Otherwise, drop it. */
827 279a4253 Michael S. Tsirkin
        if (!n->mergeable_rx_bufs && offset < size) {
828 279a4253 Michael S. Tsirkin
#if 0
829 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net truncated non-mergeable packet: "
830 e7b43f7e Stefan Hajnoczi
                         "i %zd mergeable %d offset %zd, size %zd, "
831 e7b43f7e Stefan Hajnoczi
                         "guest hdr len %zd, host hdr len %zd",
832 e7b43f7e Stefan Hajnoczi
                         i, n->mergeable_rx_bufs,
833 e35e23f6 Michael S. Tsirkin
                         offset, size, n->guest_hdr_len, n->host_hdr_len);
834 279a4253 Michael S. Tsirkin
#endif
835 279a4253 Michael S. Tsirkin
            return size;
836 279a4253 Michael S. Tsirkin
        }
837 fbe78f4f aliguori
838 fbe78f4f aliguori
        /* signal other side */
839 0c87e93e Jason Wang
        virtqueue_fill(q->rx_vq, &elem, total, i++);
840 fbe78f4f aliguori
    }
841 fbe78f4f aliguori
842 63c58728 Michael S. Tsirkin
    if (mhdr_cnt) {
843 63c58728 Michael S. Tsirkin
        stw_p(&mhdr.num_buffers, i);
844 63c58728 Michael S. Tsirkin
        iov_from_buf(mhdr_sg, mhdr_cnt,
845 63c58728 Michael S. Tsirkin
                     0,
846 63c58728 Michael S. Tsirkin
                     &mhdr.num_buffers, sizeof mhdr.num_buffers);
847 44b15bc5 Aurelien Jarno
    }
848 fbe78f4f aliguori
849 0c87e93e Jason Wang
    virtqueue_flush(q->rx_vq, i);
850 17a0ca55 KONRAD Frederic
    virtio_notify(vdev, q->rx_vq);
851 4f1c942b Mark McLoughlin
852 4f1c942b Mark McLoughlin
    return size;
853 fbe78f4f aliguori
}
854 fbe78f4f aliguori
855 0c87e93e Jason Wang
static int32_t virtio_net_flush_tx(VirtIONetQueue *q);
856 6243375f Mark McLoughlin
857 4e68f7a0 Stefan Hajnoczi
static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
858 6243375f Mark McLoughlin
{
859 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
860 fed699f9 Jason Wang
    VirtIONetQueue *q = virtio_net_get_subqueue(nc);
861 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
862 6243375f Mark McLoughlin
863 0c87e93e Jason Wang
    virtqueue_push(q->tx_vq, &q->async_tx.elem, 0);
864 17a0ca55 KONRAD Frederic
    virtio_notify(vdev, q->tx_vq);
865 6243375f Mark McLoughlin
866 0c87e93e Jason Wang
    q->async_tx.elem.out_num = q->async_tx.len = 0;
867 6243375f Mark McLoughlin
868 0c87e93e Jason Wang
    virtio_queue_set_notification(q->tx_vq, 1);
869 0c87e93e Jason Wang
    virtio_net_flush_tx(q);
870 6243375f Mark McLoughlin
}
871 6243375f Mark McLoughlin
872 fbe78f4f aliguori
/* TX */
873 0c87e93e Jason Wang
static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
874 fbe78f4f aliguori
{
875 0c87e93e Jason Wang
    VirtIONet *n = q->n;
876 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
877 fbe78f4f aliguori
    VirtQueueElement elem;
878 e3f30488 Alex Williamson
    int32_t num_packets = 0;
879 fed699f9 Jason Wang
    int queue_index = vq2q(virtio_get_queue_index(q->tx_vq));
880 17a0ca55 KONRAD Frederic
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
881 e3f30488 Alex Williamson
        return num_packets;
882 e3f30488 Alex Williamson
    }
883 fbe78f4f aliguori
884 17a0ca55 KONRAD Frederic
    assert(vdev->vm_running);
885 783e7706 Michael S. Tsirkin
886 0c87e93e Jason Wang
    if (q->async_tx.elem.out_num) {
887 0c87e93e Jason Wang
        virtio_queue_set_notification(q->tx_vq, 0);
888 e3f30488 Alex Williamson
        return num_packets;
889 6243375f Mark McLoughlin
    }
890 6243375f Mark McLoughlin
891 0c87e93e Jason Wang
    while (virtqueue_pop(q->tx_vq, &elem)) {
892 14761f9c Michael S. Tsirkin
        ssize_t ret, len;
893 fbe78f4f aliguori
        unsigned int out_num = elem.out_num;
894 fbe78f4f aliguori
        struct iovec *out_sg = &elem.out_sg[0];
895 14761f9c Michael S. Tsirkin
        struct iovec sg[VIRTQUEUE_MAX_SIZE];
896 fbe78f4f aliguori
897 7b80d08e Michael S. Tsirkin
        if (out_num < 1) {
898 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net header not in first element");
899 fbe78f4f aliguori
            exit(1);
900 fbe78f4f aliguori
        }
901 fbe78f4f aliguori
902 14761f9c Michael S. Tsirkin
        /*
903 14761f9c Michael S. Tsirkin
         * If host wants to see the guest header as is, we can
904 14761f9c Michael S. Tsirkin
         * pass it on unchanged. Otherwise, copy just the parts
905 14761f9c Michael S. Tsirkin
         * that host is interested in.
906 14761f9c Michael S. Tsirkin
         */
907 14761f9c Michael S. Tsirkin
        assert(n->host_hdr_len <= n->guest_hdr_len);
908 14761f9c Michael S. Tsirkin
        if (n->host_hdr_len != n->guest_hdr_len) {
909 14761f9c Michael S. Tsirkin
            unsigned sg_num = iov_copy(sg, ARRAY_SIZE(sg),
910 14761f9c Michael S. Tsirkin
                                       out_sg, out_num,
911 14761f9c Michael S. Tsirkin
                                       0, n->host_hdr_len);
912 14761f9c Michael S. Tsirkin
            sg_num += iov_copy(sg + sg_num, ARRAY_SIZE(sg) - sg_num,
913 14761f9c Michael S. Tsirkin
                             out_sg, out_num,
914 14761f9c Michael S. Tsirkin
                             n->guest_hdr_len, -1);
915 14761f9c Michael S. Tsirkin
            out_num = sg_num;
916 14761f9c Michael S. Tsirkin
            out_sg = sg;
917 fbe78f4f aliguori
        }
918 fbe78f4f aliguori
919 7b80d08e Michael S. Tsirkin
        len = n->guest_hdr_len;
920 14761f9c Michael S. Tsirkin
921 fed699f9 Jason Wang
        ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index),
922 fed699f9 Jason Wang
                                      out_sg, out_num, virtio_net_tx_complete);
923 6243375f Mark McLoughlin
        if (ret == 0) {
924 0c87e93e Jason Wang
            virtio_queue_set_notification(q->tx_vq, 0);
925 0c87e93e Jason Wang
            q->async_tx.elem = elem;
926 0c87e93e Jason Wang
            q->async_tx.len  = len;
927 e3f30488 Alex Williamson
            return -EBUSY;
928 6243375f Mark McLoughlin
        }
929 6243375f Mark McLoughlin
930 6243375f Mark McLoughlin
        len += ret;
931 fbe78f4f aliguori
932 0c87e93e Jason Wang
        virtqueue_push(q->tx_vq, &elem, 0);
933 17a0ca55 KONRAD Frederic
        virtio_notify(vdev, q->tx_vq);
934 e3f30488 Alex Williamson
935 e3f30488 Alex Williamson
        if (++num_packets >= n->tx_burst) {
936 e3f30488 Alex Williamson
            break;
937 e3f30488 Alex Williamson
        }
938 fbe78f4f aliguori
    }
939 e3f30488 Alex Williamson
    return num_packets;
940 fbe78f4f aliguori
}
941 fbe78f4f aliguori
942 a697a334 Alex Williamson
static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
943 fbe78f4f aliguori
{
944 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
945 fed699f9 Jason Wang
    VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
946 fbe78f4f aliguori
947 783e7706 Michael S. Tsirkin
    /* This happens when device was stopped but VCPU wasn't. */
948 17a0ca55 KONRAD Frederic
    if (!vdev->vm_running) {
949 0c87e93e Jason Wang
        q->tx_waiting = 1;
950 783e7706 Michael S. Tsirkin
        return;
951 783e7706 Michael S. Tsirkin
    }
952 783e7706 Michael S. Tsirkin
953 0c87e93e Jason Wang
    if (q->tx_waiting) {
954 fbe78f4f aliguori
        virtio_queue_set_notification(vq, 1);
955 0c87e93e Jason Wang
        qemu_del_timer(q->tx_timer);
956 0c87e93e Jason Wang
        q->tx_waiting = 0;
957 0c87e93e Jason Wang
        virtio_net_flush_tx(q);
958 fbe78f4f aliguori
    } else {
959 0c87e93e Jason Wang
        qemu_mod_timer(q->tx_timer,
960 74475455 Paolo Bonzini
                       qemu_get_clock_ns(vm_clock) + n->tx_timeout);
961 0c87e93e Jason Wang
        q->tx_waiting = 1;
962 fbe78f4f aliguori
        virtio_queue_set_notification(vq, 0);
963 fbe78f4f aliguori
    }
964 fbe78f4f aliguori
}
965 fbe78f4f aliguori
966 a697a334 Alex Williamson
static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
967 a697a334 Alex Williamson
{
968 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
969 fed699f9 Jason Wang
    VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
970 a697a334 Alex Williamson
971 0c87e93e Jason Wang
    if (unlikely(q->tx_waiting)) {
972 a697a334 Alex Williamson
        return;
973 a697a334 Alex Williamson
    }
974 0c87e93e Jason Wang
    q->tx_waiting = 1;
975 783e7706 Michael S. Tsirkin
    /* This happens when device was stopped but VCPU wasn't. */
976 17a0ca55 KONRAD Frederic
    if (!vdev->vm_running) {
977 783e7706 Michael S. Tsirkin
        return;
978 783e7706 Michael S. Tsirkin
    }
979 a697a334 Alex Williamson
    virtio_queue_set_notification(vq, 0);
980 0c87e93e Jason Wang
    qemu_bh_schedule(q->tx_bh);
981 a697a334 Alex Williamson
}
982 a697a334 Alex Williamson
983 fbe78f4f aliguori
static void virtio_net_tx_timer(void *opaque)
984 fbe78f4f aliguori
{
985 0c87e93e Jason Wang
    VirtIONetQueue *q = opaque;
986 0c87e93e Jason Wang
    VirtIONet *n = q->n;
987 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
988 17a0ca55 KONRAD Frederic
    assert(vdev->vm_running);
989 fbe78f4f aliguori
990 0c87e93e Jason Wang
    q->tx_waiting = 0;
991 fbe78f4f aliguori
992 fbe78f4f aliguori
    /* Just in case the driver is not ready on more */
993 17a0ca55 KONRAD Frederic
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
994 fbe78f4f aliguori
        return;
995 17a0ca55 KONRAD Frederic
    }
996 fbe78f4f aliguori
997 0c87e93e Jason Wang
    virtio_queue_set_notification(q->tx_vq, 1);
998 0c87e93e Jason Wang
    virtio_net_flush_tx(q);
999 fbe78f4f aliguori
}
1000 fbe78f4f aliguori
1001 a697a334 Alex Williamson
static void virtio_net_tx_bh(void *opaque)
1002 a697a334 Alex Williamson
{
1003 0c87e93e Jason Wang
    VirtIONetQueue *q = opaque;
1004 0c87e93e Jason Wang
    VirtIONet *n = q->n;
1005 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1006 a697a334 Alex Williamson
    int32_t ret;
1007 a697a334 Alex Williamson
1008 17a0ca55 KONRAD Frederic
    assert(vdev->vm_running);
1009 783e7706 Michael S. Tsirkin
1010 0c87e93e Jason Wang
    q->tx_waiting = 0;
1011 a697a334 Alex Williamson
1012 a697a334 Alex Williamson
    /* Just in case the driver is not ready on more */
1013 17a0ca55 KONRAD Frederic
    if (unlikely(!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))) {
1014 a697a334 Alex Williamson
        return;
1015 17a0ca55 KONRAD Frederic
    }
1016 a697a334 Alex Williamson
1017 0c87e93e Jason Wang
    ret = virtio_net_flush_tx(q);
1018 a697a334 Alex Williamson
    if (ret == -EBUSY) {
1019 a697a334 Alex Williamson
        return; /* Notification re-enable handled by tx_complete */
1020 a697a334 Alex Williamson
    }
1021 a697a334 Alex Williamson
1022 a697a334 Alex Williamson
    /* If we flush a full burst of packets, assume there are
1023 a697a334 Alex Williamson
     * more coming and immediately reschedule */
1024 a697a334 Alex Williamson
    if (ret >= n->tx_burst) {
1025 0c87e93e Jason Wang
        qemu_bh_schedule(q->tx_bh);
1026 0c87e93e Jason Wang
        q->tx_waiting = 1;
1027 a697a334 Alex Williamson
        return;
1028 a697a334 Alex Williamson
    }
1029 a697a334 Alex Williamson
1030 a697a334 Alex Williamson
    /* If less than a full burst, re-enable notification and flush
1031 a697a334 Alex Williamson
     * anything that may have come in while we weren't looking.  If
1032 a697a334 Alex Williamson
     * we find something, assume the guest is still active and reschedule */
1033 0c87e93e Jason Wang
    virtio_queue_set_notification(q->tx_vq, 1);
1034 0c87e93e Jason Wang
    if (virtio_net_flush_tx(q) > 0) {
1035 0c87e93e Jason Wang
        virtio_queue_set_notification(q->tx_vq, 0);
1036 0c87e93e Jason Wang
        qemu_bh_schedule(q->tx_bh);
1037 0c87e93e Jason Wang
        q->tx_waiting = 1;
1038 a697a334 Alex Williamson
    }
1039 a697a334 Alex Williamson
}
1040 a697a334 Alex Williamson
1041 fed699f9 Jason Wang
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue, int ctrl)
1042 fed699f9 Jason Wang
{
1043 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1044 fed699f9 Jason Wang
    int i, max = multiqueue ? n->max_queues : 1;
1045 fed699f9 Jason Wang
1046 fed699f9 Jason Wang
    n->multiqueue = multiqueue;
1047 fed699f9 Jason Wang
1048 fed699f9 Jason Wang
    for (i = 2; i <= n->max_queues * 2 + 1; i++) {
1049 fed699f9 Jason Wang
        virtio_del_queue(vdev, i);
1050 fed699f9 Jason Wang
    }
1051 fed699f9 Jason Wang
1052 fed699f9 Jason Wang
    for (i = 1; i < max; i++) {
1053 fed699f9 Jason Wang
        n->vqs[i].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
1054 fed699f9 Jason Wang
        if (n->vqs[i].tx_timer) {
1055 fed699f9 Jason Wang
            n->vqs[i].tx_vq =
1056 fed699f9 Jason Wang
                virtio_add_queue(vdev, 256, virtio_net_handle_tx_timer);
1057 fed699f9 Jason Wang
            n->vqs[i].tx_timer = qemu_new_timer_ns(vm_clock,
1058 fed699f9 Jason Wang
                                                   virtio_net_tx_timer,
1059 fed699f9 Jason Wang
                                                   &n->vqs[i]);
1060 fed699f9 Jason Wang
        } else {
1061 fed699f9 Jason Wang
            n->vqs[i].tx_vq =
1062 fed699f9 Jason Wang
                virtio_add_queue(vdev, 256, virtio_net_handle_tx_bh);
1063 fed699f9 Jason Wang
            n->vqs[i].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[i]);
1064 fed699f9 Jason Wang
        }
1065 fed699f9 Jason Wang
1066 fed699f9 Jason Wang
        n->vqs[i].tx_waiting = 0;
1067 fed699f9 Jason Wang
        n->vqs[i].n = n;
1068 fed699f9 Jason Wang
    }
1069 fed699f9 Jason Wang
1070 fed699f9 Jason Wang
    if (ctrl) {
1071 fed699f9 Jason Wang
        n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
1072 fed699f9 Jason Wang
    }
1073 fed699f9 Jason Wang
1074 fed699f9 Jason Wang
    virtio_net_set_queues(n);
1075 fed699f9 Jason Wang
}
1076 fed699f9 Jason Wang
1077 fbe78f4f aliguori
static void virtio_net_save(QEMUFile *f, void *opaque)
1078 fbe78f4f aliguori
{
1079 5f800801 Jason Wang
    int i;
1080 fbe78f4f aliguori
    VirtIONet *n = opaque;
1081 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1082 fbe78f4f aliguori
1083 afbaa7b4 Michael S. Tsirkin
    /* At this point, backend must be stopped, otherwise
1084 afbaa7b4 Michael S. Tsirkin
     * it might keep writing to memory. */
1085 afbaa7b4 Michael S. Tsirkin
    assert(!n->vhost_started);
1086 17a0ca55 KONRAD Frederic
    virtio_save(vdev, f);
1087 fbe78f4f aliguori
1088 79674068 aliguori
    qemu_put_buffer(f, n->mac, ETH_ALEN);
1089 5f800801 Jason Wang
    qemu_put_be32(f, n->vqs[0].tx_waiting);
1090 e46cb38f aliguori
    qemu_put_be32(f, n->mergeable_rx_bufs);
1091 9d6271b8 aliguori
    qemu_put_be16(f, n->status);
1092 f10c592e Alex Williamson
    qemu_put_byte(f, n->promisc);
1093 f10c592e Alex Williamson
    qemu_put_byte(f, n->allmulti);
1094 b6503ed9 aliguori
    qemu_put_be32(f, n->mac_table.in_use);
1095 b6503ed9 aliguori
    qemu_put_buffer(f, n->mac_table.macs, n->mac_table.in_use * ETH_ALEN);
1096 f21c0ed9 aliguori
    qemu_put_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);
1097 3a330134 Mark McLoughlin
    qemu_put_be32(f, n->has_vnet_hdr);
1098 8fd2a2f1 Alex Williamson
    qemu_put_byte(f, n->mac_table.multi_overflow);
1099 8fd2a2f1 Alex Williamson
    qemu_put_byte(f, n->mac_table.uni_overflow);
1100 015cb166 Alex Williamson
    qemu_put_byte(f, n->alluni);
1101 015cb166 Alex Williamson
    qemu_put_byte(f, n->nomulti);
1102 015cb166 Alex Williamson
    qemu_put_byte(f, n->nouni);
1103 015cb166 Alex Williamson
    qemu_put_byte(f, n->nobcast);
1104 0ce0e8f4 Mark McLoughlin
    qemu_put_byte(f, n->has_ufo);
1105 5f800801 Jason Wang
    if (n->max_queues > 1) {
1106 5f800801 Jason Wang
        qemu_put_be16(f, n->max_queues);
1107 5f800801 Jason Wang
        qemu_put_be16(f, n->curr_queues);
1108 5f800801 Jason Wang
        for (i = 1; i < n->curr_queues; i++) {
1109 5f800801 Jason Wang
            qemu_put_be32(f, n->vqs[i].tx_waiting);
1110 5f800801 Jason Wang
        }
1111 5f800801 Jason Wang
    }
1112 fbe78f4f aliguori
}
1113 fbe78f4f aliguori
1114 fbe78f4f aliguori
static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
1115 fbe78f4f aliguori
{
1116 fbe78f4f aliguori
    VirtIONet *n = opaque;
1117 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1118 5f800801 Jason Wang
    int ret, i, link_down;
1119 fbe78f4f aliguori
1120 9d6271b8 aliguori
    if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
1121 fbe78f4f aliguori
        return -EINVAL;
1122 fbe78f4f aliguori
1123 17a0ca55 KONRAD Frederic
    ret = virtio_load(vdev, f);
1124 2a633c46 Orit Wassermann
    if (ret) {
1125 2a633c46 Orit Wassermann
        return ret;
1126 2a633c46 Orit Wassermann
    }
1127 fbe78f4f aliguori
1128 79674068 aliguori
    qemu_get_buffer(f, n->mac, ETH_ALEN);
1129 5f800801 Jason Wang
    n->vqs[0].tx_waiting = qemu_get_be32(f);
1130 ff3a8066 Michael S. Tsirkin
1131 ff3a8066 Michael S. Tsirkin
    virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f));
1132 fbe78f4f aliguori
1133 9d6271b8 aliguori
    if (version_id >= 3)
1134 9d6271b8 aliguori
        n->status = qemu_get_be16(f);
1135 9d6271b8 aliguori
1136 002437cd aliguori
    if (version_id >= 4) {
1137 f10c592e Alex Williamson
        if (version_id < 8) {
1138 f10c592e Alex Williamson
            n->promisc = qemu_get_be32(f);
1139 f10c592e Alex Williamson
            n->allmulti = qemu_get_be32(f);
1140 f10c592e Alex Williamson
        } else {
1141 f10c592e Alex Williamson
            n->promisc = qemu_get_byte(f);
1142 f10c592e Alex Williamson
            n->allmulti = qemu_get_byte(f);
1143 f10c592e Alex Williamson
        }
1144 002437cd aliguori
    }
1145 002437cd aliguori
1146 b6503ed9 aliguori
    if (version_id >= 5) {
1147 b6503ed9 aliguori
        n->mac_table.in_use = qemu_get_be32(f);
1148 b6503ed9 aliguori
        /* MAC_TABLE_ENTRIES may be different from the saved image */
1149 b6503ed9 aliguori
        if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
1150 b6503ed9 aliguori
            qemu_get_buffer(f, n->mac_table.macs,
1151 b6503ed9 aliguori
                            n->mac_table.in_use * ETH_ALEN);
1152 b6503ed9 aliguori
        } else if (n->mac_table.in_use) {
1153 e398d61b Juan Quintela
            uint8_t *buf = g_malloc0(n->mac_table.in_use);
1154 e398d61b Juan Quintela
            qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN);
1155 e398d61b Juan Quintela
            g_free(buf);
1156 8fd2a2f1 Alex Williamson
            n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1;
1157 b6503ed9 aliguori
            n->mac_table.in_use = 0;
1158 b6503ed9 aliguori
        }
1159 b6503ed9 aliguori
    }
1160 b6503ed9 aliguori
 
1161 f21c0ed9 aliguori
    if (version_id >= 6)
1162 f21c0ed9 aliguori
        qemu_get_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);
1163 f21c0ed9 aliguori
1164 3a330134 Mark McLoughlin
    if (version_id >= 7) {
1165 3a330134 Mark McLoughlin
        if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) {
1166 1ecda02b Markus Armbruster
            error_report("virtio-net: saved image requires vnet_hdr=on");
1167 3a330134 Mark McLoughlin
            return -1;
1168 3a330134 Mark McLoughlin
        }
1169 3a330134 Mark McLoughlin
1170 3a330134 Mark McLoughlin
        if (n->has_vnet_hdr) {
1171 b356f76d Jason Wang
            tap_set_offload(qemu_get_queue(n->nic)->peer,
1172 17a0ca55 KONRAD Frederic
                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
1173 17a0ca55 KONRAD Frederic
                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
1174 17a0ca55 KONRAD Frederic
                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
1175 17a0ca55 KONRAD Frederic
                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_ECN)  & 1,
1176 17a0ca55 KONRAD Frederic
                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_UFO)  & 1);
1177 3a330134 Mark McLoughlin
        }
1178 6c042c16 Alex Williamson
    }
1179 6c042c16 Alex Williamson
1180 8fd2a2f1 Alex Williamson
    if (version_id >= 9) {
1181 8fd2a2f1 Alex Williamson
        n->mac_table.multi_overflow = qemu_get_byte(f);
1182 8fd2a2f1 Alex Williamson
        n->mac_table.uni_overflow = qemu_get_byte(f);
1183 8fd2a2f1 Alex Williamson
    }
1184 8fd2a2f1 Alex Williamson
1185 015cb166 Alex Williamson
    if (version_id >= 10) {
1186 015cb166 Alex Williamson
        n->alluni = qemu_get_byte(f);
1187 015cb166 Alex Williamson
        n->nomulti = qemu_get_byte(f);
1188 015cb166 Alex Williamson
        n->nouni = qemu_get_byte(f);
1189 015cb166 Alex Williamson
        n->nobcast = qemu_get_byte(f);
1190 015cb166 Alex Williamson
    }
1191 015cb166 Alex Williamson
1192 0ce0e8f4 Mark McLoughlin
    if (version_id >= 11) {
1193 0ce0e8f4 Mark McLoughlin
        if (qemu_get_byte(f) && !peer_has_ufo(n)) {
1194 1ecda02b Markus Armbruster
            error_report("virtio-net: saved image requires TUN_F_UFO support");
1195 0ce0e8f4 Mark McLoughlin
            return -1;
1196 0ce0e8f4 Mark McLoughlin
        }
1197 0ce0e8f4 Mark McLoughlin
    }
1198 0ce0e8f4 Mark McLoughlin
1199 5f800801 Jason Wang
    if (n->max_queues > 1) {
1200 5f800801 Jason Wang
        if (n->max_queues != qemu_get_be16(f)) {
1201 5f800801 Jason Wang
            error_report("virtio-net: different max_queues ");
1202 5f800801 Jason Wang
            return -1;
1203 5f800801 Jason Wang
        }
1204 5f800801 Jason Wang
1205 5f800801 Jason Wang
        n->curr_queues = qemu_get_be16(f);
1206 5f800801 Jason Wang
        for (i = 1; i < n->curr_queues; i++) {
1207 5f800801 Jason Wang
            n->vqs[i].tx_waiting = qemu_get_be32(f);
1208 5f800801 Jason Wang
        }
1209 5f800801 Jason Wang
    }
1210 5f800801 Jason Wang
1211 5f800801 Jason Wang
    virtio_net_set_queues(n);
1212 5f800801 Jason Wang
1213 2d9aba39 Alex Williamson
    /* Find the first multicast entry in the saved MAC filter */
1214 2d9aba39 Alex Williamson
    for (i = 0; i < n->mac_table.in_use; i++) {
1215 2d9aba39 Alex Williamson
        if (n->mac_table.macs[i * ETH_ALEN] & 1) {
1216 2d9aba39 Alex Williamson
            break;
1217 2d9aba39 Alex Williamson
        }
1218 2d9aba39 Alex Williamson
    }
1219 2d9aba39 Alex Williamson
    n->mac_table.first_multi = i;
1220 98991481 Amos Kong
1221 98991481 Amos Kong
    /* nc.link_down can't be migrated, so infer link_down according
1222 98991481 Amos Kong
     * to link status bit in n->status */
1223 5f800801 Jason Wang
    link_down = (n->status & VIRTIO_NET_S_LINK_UP) == 0;
1224 5f800801 Jason Wang
    for (i = 0; i < n->max_queues; i++) {
1225 5f800801 Jason Wang
        qemu_get_subqueue(n->nic, i)->link_down = link_down;
1226 5f800801 Jason Wang
    }
1227 98991481 Amos Kong
1228 fbe78f4f aliguori
    return 0;
1229 fbe78f4f aliguori
}
1230 fbe78f4f aliguori
1231 4e68f7a0 Stefan Hajnoczi
static void virtio_net_cleanup(NetClientState *nc)
1232 b946a153 aliguori
{
1233 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
1234 b946a153 aliguori
1235 eb6b6c12 Mark McLoughlin
    n->nic = NULL;
1236 b946a153 aliguori
}
1237 b946a153 aliguori
1238 eb6b6c12 Mark McLoughlin
static NetClientInfo net_virtio_info = {
1239 2be64a68 Laszlo Ersek
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
1240 eb6b6c12 Mark McLoughlin
    .size = sizeof(NICState),
1241 eb6b6c12 Mark McLoughlin
    .can_receive = virtio_net_can_receive,
1242 eb6b6c12 Mark McLoughlin
    .receive = virtio_net_receive,
1243 eb6b6c12 Mark McLoughlin
        .cleanup = virtio_net_cleanup,
1244 eb6b6c12 Mark McLoughlin
    .link_status_changed = virtio_net_set_link_status,
1245 eb6b6c12 Mark McLoughlin
};
1246 eb6b6c12 Mark McLoughlin
1247 f56a1247 Michael S. Tsirkin
static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
1248 f56a1247 Michael S. Tsirkin
{
1249 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
1250 fed699f9 Jason Wang
    NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
1251 f56a1247 Michael S. Tsirkin
    assert(n->vhost_started);
1252 b356f76d Jason Wang
    return vhost_net_virtqueue_pending(tap_get_vhost_net(nc->peer), idx);
1253 f56a1247 Michael S. Tsirkin
}
1254 f56a1247 Michael S. Tsirkin
1255 f56a1247 Michael S. Tsirkin
static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
1256 f56a1247 Michael S. Tsirkin
                                           bool mask)
1257 f56a1247 Michael S. Tsirkin
{
1258 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
1259 fed699f9 Jason Wang
    NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
1260 f56a1247 Michael S. Tsirkin
    assert(n->vhost_started);
1261 b356f76d Jason Wang
    vhost_net_virtqueue_mask(tap_get_vhost_net(nc->peer),
1262 f56a1247 Michael S. Tsirkin
                             vdev, idx, mask);
1263 f56a1247 Michael S. Tsirkin
}
1264 f56a1247 Michael S. Tsirkin
1265 17ec5a86 KONRAD Frederic
void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
1266 fbe78f4f aliguori
{
1267 14f9b664 Jesse Larrew
    int i, config_size = 0;
1268 14f9b664 Jesse Larrew
    for (i = 0; feature_sizes[i].flags != 0; i++) {
1269 14f9b664 Jesse Larrew
        if (host_features & feature_sizes[i].flags) {
1270 14f9b664 Jesse Larrew
            config_size = MAX(feature_sizes[i].end, config_size);
1271 14f9b664 Jesse Larrew
        }
1272 14f9b664 Jesse Larrew
    }
1273 17ec5a86 KONRAD Frederic
    n->config_size = config_size;
1274 17ec5a86 KONRAD Frederic
}
1275 17ec5a86 KONRAD Frederic
1276 1773d9ee KONRAD Frederic
static int virtio_net_device_init(VirtIODevice *vdev)
1277 17ec5a86 KONRAD Frederic
{
1278 1773d9ee KONRAD Frederic
    int i;
1279 fbe78f4f aliguori
1280 1773d9ee KONRAD Frederic
    DeviceState *qdev = DEVICE(vdev);
1281 1773d9ee KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
1282 1773d9ee KONRAD Frederic
1283 1773d9ee KONRAD Frederic
    virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
1284 1773d9ee KONRAD Frederic
                                  n->config_size);
1285 fbe78f4f aliguori
1286 17a0ca55 KONRAD Frederic
    vdev->get_config = virtio_net_get_config;
1287 17a0ca55 KONRAD Frederic
    vdev->set_config = virtio_net_set_config;
1288 17a0ca55 KONRAD Frederic
    vdev->get_features = virtio_net_get_features;
1289 17a0ca55 KONRAD Frederic
    vdev->set_features = virtio_net_set_features;
1290 17a0ca55 KONRAD Frederic
    vdev->bad_features = virtio_net_bad_features;
1291 17a0ca55 KONRAD Frederic
    vdev->reset = virtio_net_reset;
1292 17a0ca55 KONRAD Frederic
    vdev->set_status = virtio_net_set_status;
1293 17a0ca55 KONRAD Frederic
    vdev->guest_notifier_mask = virtio_net_guest_notifier_mask;
1294 17a0ca55 KONRAD Frederic
    vdev->guest_notifier_pending = virtio_net_guest_notifier_pending;
1295 1773d9ee KONRAD Frederic
    n->max_queues = MAX(n->nic_conf.queues, 1);
1296 f6b26cf2 Jason Wang
    n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
1297 17a0ca55 KONRAD Frederic
    n->vqs[0].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
1298 fed699f9 Jason Wang
    n->curr_queues = 1;
1299 fed699f9 Jason Wang
    n->vqs[0].n = n;
1300 1773d9ee KONRAD Frederic
    n->tx_timeout = n->net_conf.txtimer;
1301 a697a334 Alex Williamson
1302 1773d9ee KONRAD Frederic
    if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer")
1303 1773d9ee KONRAD Frederic
                       && strcmp(n->net_conf.tx, "bh")) {
1304 e7b43f7e Stefan Hajnoczi
        error_report("virtio-net: "
1305 e7b43f7e Stefan Hajnoczi
                     "Unknown option tx=%s, valid options: \"timer\" \"bh\"",
1306 1773d9ee KONRAD Frederic
                     n->net_conf.tx);
1307 e7b43f7e Stefan Hajnoczi
        error_report("Defaulting to \"bh\"");
1308 a697a334 Alex Williamson
    }
1309 a697a334 Alex Williamson
1310 1773d9ee KONRAD Frederic
    if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) {
1311 17a0ca55 KONRAD Frederic
        n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
1312 fed699f9 Jason Wang
                                           virtio_net_handle_tx_timer);
1313 fed699f9 Jason Wang
        n->vqs[0].tx_timer = qemu_new_timer_ns(vm_clock, virtio_net_tx_timer,
1314 fed699f9 Jason Wang
                                               &n->vqs[0]);
1315 a697a334 Alex Williamson
    } else {
1316 17a0ca55 KONRAD Frederic
        n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
1317 fed699f9 Jason Wang
                                           virtio_net_handle_tx_bh);
1318 fed699f9 Jason Wang
        n->vqs[0].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[0]);
1319 a697a334 Alex Williamson
    }
1320 17a0ca55 KONRAD Frederic
    n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
1321 1773d9ee KONRAD Frederic
    qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
1322 1773d9ee KONRAD Frederic
    memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
1323 554c97dd aliguori
    n->status = VIRTIO_NET_S_LINK_UP;
1324 fbe78f4f aliguori
1325 1773d9ee KONRAD Frederic
    n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
1326 1773d9ee KONRAD Frederic
                          object_get_typename(OBJECT(qdev)), qdev->id, n);
1327 6e371ab8 Michael S. Tsirkin
    peer_test_vnet_hdr(n);
1328 6e371ab8 Michael S. Tsirkin
    if (peer_has_vnet_hdr(n)) {
1329 fed699f9 Jason Wang
        for (i = 0; i < n->max_queues; i++) {
1330 fed699f9 Jason Wang
            tap_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true);
1331 fed699f9 Jason Wang
        }
1332 6e371ab8 Michael S. Tsirkin
        n->host_hdr_len = sizeof(struct virtio_net_hdr);
1333 6e371ab8 Michael S. Tsirkin
    } else {
1334 6e371ab8 Michael S. Tsirkin
        n->host_hdr_len = 0;
1335 6e371ab8 Michael S. Tsirkin
    }
1336 eb6b6c12 Mark McLoughlin
1337 1773d9ee KONRAD Frederic
    qemu_format_nic_info_str(qemu_get_queue(n->nic), n->nic_conf.macaddr.a);
1338 96d5e201 aliguori
1339 fed699f9 Jason Wang
    n->vqs[0].tx_waiting = 0;
1340 1773d9ee KONRAD Frederic
    n->tx_burst = n->net_conf.txburst;
1341 ff3a8066 Michael S. Tsirkin
    virtio_net_set_mrg_rx_bufs(n, 0);
1342 002437cd aliguori
    n->promisc = 1; /* for compatibility */
1343 fbe78f4f aliguori
1344 7267c094 Anthony Liguori
    n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
1345 b6503ed9 aliguori
1346 7267c094 Anthony Liguori
    n->vlans = g_malloc0(MAX_VLAN >> 3);
1347 f21c0ed9 aliguori
1348 1773d9ee KONRAD Frederic
    n->qdev = qdev;
1349 1773d9ee KONRAD Frederic
    register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
1350 fbe78f4f aliguori
                    virtio_net_save, virtio_net_load, n);
1351 cf21e106 Paul Brook
1352 1773d9ee KONRAD Frederic
    add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy@0");
1353 17ec5a86 KONRAD Frederic
    return 0;
1354 17ec5a86 KONRAD Frederic
}
1355 17ec5a86 KONRAD Frederic
1356 17ec5a86 KONRAD Frederic
static int virtio_net_device_exit(DeviceState *qdev)
1357 17ec5a86 KONRAD Frederic
{
1358 17ec5a86 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(qdev);
1359 17ec5a86 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
1360 17ec5a86 KONRAD Frederic
    int i;
1361 17ec5a86 KONRAD Frederic
1362 17ec5a86 KONRAD Frederic
    /* This will stop vhost backend if appropriate. */
1363 17ec5a86 KONRAD Frederic
    virtio_net_set_status(vdev, 0);
1364 17ec5a86 KONRAD Frederic
1365 17ec5a86 KONRAD Frederic
    unregister_savevm(qdev, "virtio-net", n);
1366 17ec5a86 KONRAD Frederic
1367 17ec5a86 KONRAD Frederic
    g_free(n->mac_table.macs);
1368 17ec5a86 KONRAD Frederic
    g_free(n->vlans);
1369 17ec5a86 KONRAD Frederic
1370 17ec5a86 KONRAD Frederic
    for (i = 0; i < n->max_queues; i++) {
1371 17ec5a86 KONRAD Frederic
        VirtIONetQueue *q = &n->vqs[i];
1372 17ec5a86 KONRAD Frederic
        NetClientState *nc = qemu_get_subqueue(n->nic, i);
1373 17ec5a86 KONRAD Frederic
1374 17ec5a86 KONRAD Frederic
        qemu_purge_queued_packets(nc);
1375 17ec5a86 KONRAD Frederic
1376 17ec5a86 KONRAD Frederic
        if (q->tx_timer) {
1377 17ec5a86 KONRAD Frederic
            qemu_del_timer(q->tx_timer);
1378 17ec5a86 KONRAD Frederic
            qemu_free_timer(q->tx_timer);
1379 17ec5a86 KONRAD Frederic
        } else {
1380 17ec5a86 KONRAD Frederic
            qemu_bh_delete(q->tx_bh);
1381 17ec5a86 KONRAD Frederic
        }
1382 17ec5a86 KONRAD Frederic
    }
1383 17ec5a86 KONRAD Frederic
1384 17ec5a86 KONRAD Frederic
    g_free(n->vqs);
1385 17ec5a86 KONRAD Frederic
    qemu_del_nic(n->nic);
1386 17a0ca55 KONRAD Frederic
    virtio_common_cleanup(vdev);
1387 17ec5a86 KONRAD Frederic
1388 17ec5a86 KONRAD Frederic
    return 0;
1389 17ec5a86 KONRAD Frederic
}
1390 17ec5a86 KONRAD Frederic
1391 17ec5a86 KONRAD Frederic
static void virtio_net_instance_init(Object *obj)
1392 17ec5a86 KONRAD Frederic
{
1393 17ec5a86 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(obj);
1394 17ec5a86 KONRAD Frederic
1395 17ec5a86 KONRAD Frederic
    /*
1396 17ec5a86 KONRAD Frederic
     * The default config_size is sizeof(struct virtio_net_config).
1397 17ec5a86 KONRAD Frederic
     * Can be overriden with virtio_net_set_config_size.
1398 17ec5a86 KONRAD Frederic
     */
1399 17ec5a86 KONRAD Frederic
    n->config_size = sizeof(struct virtio_net_config);
1400 17ec5a86 KONRAD Frederic
}
1401 17ec5a86 KONRAD Frederic
1402 17ec5a86 KONRAD Frederic
static Property virtio_net_properties[] = {
1403 17ec5a86 KONRAD Frederic
    DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf),
1404 17ec5a86 KONRAD Frederic
    DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer,
1405 17ec5a86 KONRAD Frederic
                                               TX_TIMER_INTERVAL),
1406 17ec5a86 KONRAD Frederic
    DEFINE_PROP_INT32("x-txburst", VirtIONet, net_conf.txburst, TX_BURST),
1407 17ec5a86 KONRAD Frederic
    DEFINE_PROP_STRING("tx", VirtIONet, net_conf.tx),
1408 17ec5a86 KONRAD Frederic
    DEFINE_PROP_END_OF_LIST(),
1409 17ec5a86 KONRAD Frederic
};
1410 17ec5a86 KONRAD Frederic
1411 17ec5a86 KONRAD Frederic
static void virtio_net_class_init(ObjectClass *klass, void *data)
1412 17ec5a86 KONRAD Frederic
{
1413 17ec5a86 KONRAD Frederic
    DeviceClass *dc = DEVICE_CLASS(klass);
1414 17ec5a86 KONRAD Frederic
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1415 17ec5a86 KONRAD Frederic
    dc->exit = virtio_net_device_exit;
1416 17ec5a86 KONRAD Frederic
    dc->props = virtio_net_properties;
1417 17ec5a86 KONRAD Frederic
    vdc->init = virtio_net_device_init;
1418 17ec5a86 KONRAD Frederic
    vdc->get_config = virtio_net_get_config;
1419 17ec5a86 KONRAD Frederic
    vdc->set_config = virtio_net_set_config;
1420 17ec5a86 KONRAD Frederic
    vdc->get_features = virtio_net_get_features;
1421 17ec5a86 KONRAD Frederic
    vdc->set_features = virtio_net_set_features;
1422 17ec5a86 KONRAD Frederic
    vdc->bad_features = virtio_net_bad_features;
1423 17ec5a86 KONRAD Frederic
    vdc->reset = virtio_net_reset;
1424 17ec5a86 KONRAD Frederic
    vdc->set_status = virtio_net_set_status;
1425 17ec5a86 KONRAD Frederic
    vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
1426 17ec5a86 KONRAD Frederic
    vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
1427 17ec5a86 KONRAD Frederic
}
1428 17ec5a86 KONRAD Frederic
1429 17ec5a86 KONRAD Frederic
static const TypeInfo virtio_net_info = {
1430 17ec5a86 KONRAD Frederic
    .name = TYPE_VIRTIO_NET,
1431 17ec5a86 KONRAD Frederic
    .parent = TYPE_VIRTIO_DEVICE,
1432 17ec5a86 KONRAD Frederic
    .instance_size = sizeof(VirtIONet),
1433 17ec5a86 KONRAD Frederic
    .instance_init = virtio_net_instance_init,
1434 17ec5a86 KONRAD Frederic
    .class_init = virtio_net_class_init,
1435 17ec5a86 KONRAD Frederic
};
1436 17ec5a86 KONRAD Frederic
1437 17ec5a86 KONRAD Frederic
static void virtio_register_types(void)
1438 17ec5a86 KONRAD Frederic
{
1439 17ec5a86 KONRAD Frederic
    type_register_static(&virtio_net_info);
1440 17ec5a86 KONRAD Frederic
}
1441 17ec5a86 KONRAD Frederic
1442 17ec5a86 KONRAD Frederic
type_init(virtio_register_types)