Statistics
| Branch: | Revision:

root / hw / net / virtio-net.c @ 96478592

History | View | Annotate | Download (44.6 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 d7108d90 Jason Wang
    if (!!n->vhost_started ==
118 d7108d90 Jason Wang
        (virtio_net_started(n, status) && !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 ec57db16 Jason Wang
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
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 644c9858 Dmitry Fleytman
static void virtio_net_apply_guest_offloads(VirtIONet *n)
363 644c9858 Dmitry Fleytman
{
364 644c9858 Dmitry Fleytman
    tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer,
365 644c9858 Dmitry Fleytman
            !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)),
366 644c9858 Dmitry Fleytman
            !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)),
367 644c9858 Dmitry Fleytman
            !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)),
368 644c9858 Dmitry Fleytman
            !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_ECN)),
369 644c9858 Dmitry Fleytman
            !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO)));
370 644c9858 Dmitry Fleytman
}
371 644c9858 Dmitry Fleytman
372 644c9858 Dmitry Fleytman
static uint64_t virtio_net_guest_offloads_by_features(uint32_t features)
373 644c9858 Dmitry Fleytman
{
374 644c9858 Dmitry Fleytman
    static const uint64_t guest_offloads_mask =
375 644c9858 Dmitry Fleytman
        (1ULL << VIRTIO_NET_F_GUEST_CSUM) |
376 644c9858 Dmitry Fleytman
        (1ULL << VIRTIO_NET_F_GUEST_TSO4) |
377 644c9858 Dmitry Fleytman
        (1ULL << VIRTIO_NET_F_GUEST_TSO6) |
378 644c9858 Dmitry Fleytman
        (1ULL << VIRTIO_NET_F_GUEST_ECN)  |
379 644c9858 Dmitry Fleytman
        (1ULL << VIRTIO_NET_F_GUEST_UFO);
380 644c9858 Dmitry Fleytman
381 644c9858 Dmitry Fleytman
    return guest_offloads_mask & features;
382 644c9858 Dmitry Fleytman
}
383 644c9858 Dmitry Fleytman
384 644c9858 Dmitry Fleytman
static inline uint64_t virtio_net_supported_guest_offloads(VirtIONet *n)
385 644c9858 Dmitry Fleytman
{
386 644c9858 Dmitry Fleytman
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
387 644c9858 Dmitry Fleytman
    return virtio_net_guest_offloads_by_features(vdev->guest_features);
388 644c9858 Dmitry Fleytman
}
389 644c9858 Dmitry Fleytman
390 fbe78f4f aliguori
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
391 fbe78f4f aliguori
{
392 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
393 fed699f9 Jason Wang
    int i;
394 fed699f9 Jason Wang
395 ec57db16 Jason Wang
    virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ)));
396 fbe78f4f aliguori
397 ff3a8066 Michael S. Tsirkin
    virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)));
398 f5436dd9 Mark McLoughlin
399 f5436dd9 Mark McLoughlin
    if (n->has_vnet_hdr) {
400 644c9858 Dmitry Fleytman
        n->curr_guest_offloads =
401 644c9858 Dmitry Fleytman
            virtio_net_guest_offloads_by_features(features);
402 644c9858 Dmitry Fleytman
        virtio_net_apply_guest_offloads(n);
403 f5436dd9 Mark McLoughlin
    }
404 fed699f9 Jason Wang
405 fed699f9 Jason Wang
    for (i = 0;  i < n->max_queues; i++) {
406 fed699f9 Jason Wang
        NetClientState *nc = qemu_get_subqueue(n->nic, i);
407 fed699f9 Jason Wang
408 fed699f9 Jason Wang
        if (!nc->peer || nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
409 fed699f9 Jason Wang
            continue;
410 fed699f9 Jason Wang
        }
411 fed699f9 Jason Wang
        if (!tap_get_vhost_net(nc->peer)) {
412 fed699f9 Jason Wang
            continue;
413 fed699f9 Jason Wang
        }
414 fed699f9 Jason Wang
        vhost_net_ack_features(tap_get_vhost_net(nc->peer), features);
415 dc14a397 David L Stevens
    }
416 fbe78f4f aliguori
}
417 fbe78f4f aliguori
418 002437cd aliguori
static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
419 921ac5d0 Michael S. Tsirkin
                                     struct iovec *iov, unsigned int iov_cnt)
420 002437cd aliguori
{
421 002437cd aliguori
    uint8_t on;
422 921ac5d0 Michael S. Tsirkin
    size_t s;
423 002437cd aliguori
424 921ac5d0 Michael S. Tsirkin
    s = iov_to_buf(iov, iov_cnt, 0, &on, sizeof(on));
425 921ac5d0 Michael S. Tsirkin
    if (s != sizeof(on)) {
426 921ac5d0 Michael S. Tsirkin
        return VIRTIO_NET_ERR;
427 002437cd aliguori
    }
428 002437cd aliguori
429 dd23454b Amos Kong
    if (cmd == VIRTIO_NET_CTRL_RX_PROMISC) {
430 002437cd aliguori
        n->promisc = on;
431 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_ALLMULTI) {
432 002437cd aliguori
        n->allmulti = on;
433 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_ALLUNI) {
434 015cb166 Alex Williamson
        n->alluni = on;
435 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_NOMULTI) {
436 015cb166 Alex Williamson
        n->nomulti = on;
437 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_NOUNI) {
438 015cb166 Alex Williamson
        n->nouni = on;
439 dd23454b Amos Kong
    } else if (cmd == VIRTIO_NET_CTRL_RX_NOBCAST) {
440 015cb166 Alex Williamson
        n->nobcast = on;
441 921ac5d0 Michael S. Tsirkin
    } else {
442 002437cd aliguori
        return VIRTIO_NET_ERR;
443 921ac5d0 Michael S. Tsirkin
    }
444 002437cd aliguori
445 002437cd aliguori
    return VIRTIO_NET_OK;
446 002437cd aliguori
}
447 002437cd aliguori
448 644c9858 Dmitry Fleytman
static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
449 644c9858 Dmitry Fleytman
                                     struct iovec *iov, unsigned int iov_cnt)
450 644c9858 Dmitry Fleytman
{
451 644c9858 Dmitry Fleytman
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
452 644c9858 Dmitry Fleytman
    uint64_t offloads;
453 644c9858 Dmitry Fleytman
    size_t s;
454 644c9858 Dmitry Fleytman
455 644c9858 Dmitry Fleytman
    if (!((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features)) {
456 644c9858 Dmitry Fleytman
        return VIRTIO_NET_ERR;
457 644c9858 Dmitry Fleytman
    }
458 644c9858 Dmitry Fleytman
459 644c9858 Dmitry Fleytman
    s = iov_to_buf(iov, iov_cnt, 0, &offloads, sizeof(offloads));
460 644c9858 Dmitry Fleytman
    if (s != sizeof(offloads)) {
461 644c9858 Dmitry Fleytman
        return VIRTIO_NET_ERR;
462 644c9858 Dmitry Fleytman
    }
463 644c9858 Dmitry Fleytman
464 644c9858 Dmitry Fleytman
    if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) {
465 644c9858 Dmitry Fleytman
        uint64_t supported_offloads;
466 644c9858 Dmitry Fleytman
467 644c9858 Dmitry Fleytman
        if (!n->has_vnet_hdr) {
468 644c9858 Dmitry Fleytman
            return VIRTIO_NET_ERR;
469 644c9858 Dmitry Fleytman
        }
470 644c9858 Dmitry Fleytman
471 644c9858 Dmitry Fleytman
        supported_offloads = virtio_net_supported_guest_offloads(n);
472 644c9858 Dmitry Fleytman
        if (offloads & ~supported_offloads) {
473 644c9858 Dmitry Fleytman
            return VIRTIO_NET_ERR;
474 644c9858 Dmitry Fleytman
        }
475 644c9858 Dmitry Fleytman
476 644c9858 Dmitry Fleytman
        n->curr_guest_offloads = offloads;
477 644c9858 Dmitry Fleytman
        virtio_net_apply_guest_offloads(n);
478 644c9858 Dmitry Fleytman
479 644c9858 Dmitry Fleytman
        return VIRTIO_NET_OK;
480 644c9858 Dmitry Fleytman
    } else {
481 644c9858 Dmitry Fleytman
        return VIRTIO_NET_ERR;
482 644c9858 Dmitry Fleytman
    }
483 644c9858 Dmitry Fleytman
}
484 644c9858 Dmitry Fleytman
485 b6503ed9 aliguori
static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
486 921ac5d0 Michael S. Tsirkin
                                 struct iovec *iov, unsigned int iov_cnt)
487 b6503ed9 aliguori
{
488 b6503ed9 aliguori
    struct virtio_net_ctrl_mac mac_data;
489 921ac5d0 Michael S. Tsirkin
    size_t s;
490 b6503ed9 aliguori
491 c1943a3f Amos Kong
    if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {
492 c1943a3f Amos Kong
        if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {
493 c1943a3f Amos Kong
            return VIRTIO_NET_ERR;
494 c1943a3f Amos Kong
        }
495 c1943a3f Amos Kong
        s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));
496 c1943a3f Amos Kong
        assert(s == sizeof(n->mac));
497 b356f76d Jason Wang
        qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
498 c1943a3f Amos Kong
        return VIRTIO_NET_OK;
499 c1943a3f Amos Kong
    }
500 c1943a3f Amos Kong
501 921ac5d0 Michael S. Tsirkin
    if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) {
502 b6503ed9 aliguori
        return VIRTIO_NET_ERR;
503 921ac5d0 Michael S. Tsirkin
    }
504 b6503ed9 aliguori
505 b6503ed9 aliguori
    n->mac_table.in_use = 0;
506 2d9aba39 Alex Williamson
    n->mac_table.first_multi = 0;
507 8fd2a2f1 Alex Williamson
    n->mac_table.uni_overflow = 0;
508 8fd2a2f1 Alex Williamson
    n->mac_table.multi_overflow = 0;
509 b6503ed9 aliguori
    memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
510 b6503ed9 aliguori
511 921ac5d0 Michael S. Tsirkin
    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
512 921ac5d0 Michael S. Tsirkin
                   sizeof(mac_data.entries));
513 921ac5d0 Michael S. Tsirkin
    mac_data.entries = ldl_p(&mac_data.entries);
514 921ac5d0 Michael S. Tsirkin
    if (s != sizeof(mac_data.entries)) {
515 921ac5d0 Michael S. Tsirkin
        return VIRTIO_NET_ERR;
516 921ac5d0 Michael S. Tsirkin
    }
517 921ac5d0 Michael S. Tsirkin
    iov_discard_front(&iov, &iov_cnt, s);
518 b6503ed9 aliguori
519 921ac5d0 Michael S. Tsirkin
    if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) {
520 b6503ed9 aliguori
        return VIRTIO_NET_ERR;
521 921ac5d0 Michael S. Tsirkin
    }
522 b6503ed9 aliguori
523 b6503ed9 aliguori
    if (mac_data.entries <= MAC_TABLE_ENTRIES) {
524 921ac5d0 Michael S. Tsirkin
        s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
525 921ac5d0 Michael S. Tsirkin
                       mac_data.entries * ETH_ALEN);
526 921ac5d0 Michael S. Tsirkin
        if (s != mac_data.entries * ETH_ALEN) {
527 921ac5d0 Michael S. Tsirkin
            return VIRTIO_NET_ERR;
528 921ac5d0 Michael S. Tsirkin
        }
529 b6503ed9 aliguori
        n->mac_table.in_use += mac_data.entries;
530 b6503ed9 aliguori
    } else {
531 8fd2a2f1 Alex Williamson
        n->mac_table.uni_overflow = 1;
532 b6503ed9 aliguori
    }
533 b6503ed9 aliguori
534 921ac5d0 Michael S. Tsirkin
    iov_discard_front(&iov, &iov_cnt, mac_data.entries * ETH_ALEN);
535 921ac5d0 Michael S. Tsirkin
536 2d9aba39 Alex Williamson
    n->mac_table.first_multi = n->mac_table.in_use;
537 2d9aba39 Alex Williamson
538 921ac5d0 Michael S. Tsirkin
    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
539 921ac5d0 Michael S. Tsirkin
                   sizeof(mac_data.entries));
540 921ac5d0 Michael S. Tsirkin
    mac_data.entries = ldl_p(&mac_data.entries);
541 921ac5d0 Michael S. Tsirkin
    if (s != sizeof(mac_data.entries)) {
542 921ac5d0 Michael S. Tsirkin
        return VIRTIO_NET_ERR;
543 921ac5d0 Michael S. Tsirkin
    }
544 921ac5d0 Michael S. Tsirkin
545 921ac5d0 Michael S. Tsirkin
    iov_discard_front(&iov, &iov_cnt, s);
546 b6503ed9 aliguori
547 921ac5d0 Michael S. Tsirkin
    if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) {
548 b6503ed9 aliguori
        return VIRTIO_NET_ERR;
549 921ac5d0 Michael S. Tsirkin
    }
550 b6503ed9 aliguori
551 921ac5d0 Michael S. Tsirkin
    if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
552 921ac5d0 Michael S. Tsirkin
        s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
553 921ac5d0 Michael S. Tsirkin
                       mac_data.entries * ETH_ALEN);
554 921ac5d0 Michael S. Tsirkin
        if (s != mac_data.entries * ETH_ALEN) {
555 921ac5d0 Michael S. Tsirkin
            return VIRTIO_NET_ERR;
556 8fd2a2f1 Alex Williamson
        }
557 921ac5d0 Michael S. Tsirkin
        n->mac_table.in_use += mac_data.entries;
558 921ac5d0 Michael S. Tsirkin
    } else {
559 921ac5d0 Michael S. Tsirkin
        n->mac_table.multi_overflow = 1;
560 b6503ed9 aliguori
    }
561 b6503ed9 aliguori
562 b6503ed9 aliguori
    return VIRTIO_NET_OK;
563 b6503ed9 aliguori
}
564 b6503ed9 aliguori
565 f21c0ed9 aliguori
static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
566 921ac5d0 Michael S. Tsirkin
                                        struct iovec *iov, unsigned int iov_cnt)
567 f21c0ed9 aliguori
{
568 f21c0ed9 aliguori
    uint16_t vid;
569 921ac5d0 Michael S. Tsirkin
    size_t s;
570 f21c0ed9 aliguori
571 921ac5d0 Michael S. Tsirkin
    s = iov_to_buf(iov, iov_cnt, 0, &vid, sizeof(vid));
572 921ac5d0 Michael S. Tsirkin
    vid = lduw_p(&vid);
573 921ac5d0 Michael S. Tsirkin
    if (s != sizeof(vid)) {
574 f21c0ed9 aliguori
        return VIRTIO_NET_ERR;
575 f21c0ed9 aliguori
    }
576 f21c0ed9 aliguori
577 f21c0ed9 aliguori
    if (vid >= MAX_VLAN)
578 f21c0ed9 aliguori
        return VIRTIO_NET_ERR;
579 f21c0ed9 aliguori
580 f21c0ed9 aliguori
    if (cmd == VIRTIO_NET_CTRL_VLAN_ADD)
581 f21c0ed9 aliguori
        n->vlans[vid >> 5] |= (1U << (vid & 0x1f));
582 f21c0ed9 aliguori
    else if (cmd == VIRTIO_NET_CTRL_VLAN_DEL)
583 f21c0ed9 aliguori
        n->vlans[vid >> 5] &= ~(1U << (vid & 0x1f));
584 f21c0ed9 aliguori
    else
585 f21c0ed9 aliguori
        return VIRTIO_NET_ERR;
586 f21c0ed9 aliguori
587 f21c0ed9 aliguori
    return VIRTIO_NET_OK;
588 f21c0ed9 aliguori
}
589 f21c0ed9 aliguori
590 fed699f9 Jason Wang
static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
591 f8f7c533 Jason Wang
                                struct iovec *iov, unsigned int iov_cnt)
592 fed699f9 Jason Wang
{
593 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
594 f8f7c533 Jason Wang
    struct virtio_net_ctrl_mq mq;
595 f8f7c533 Jason Wang
    size_t s;
596 f8f7c533 Jason Wang
    uint16_t queues;
597 fed699f9 Jason Wang
598 f8f7c533 Jason Wang
    s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq));
599 f8f7c533 Jason Wang
    if (s != sizeof(mq)) {
600 fed699f9 Jason Wang
        return VIRTIO_NET_ERR;
601 fed699f9 Jason Wang
    }
602 fed699f9 Jason Wang
603 fed699f9 Jason Wang
    if (cmd != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
604 fed699f9 Jason Wang
        return VIRTIO_NET_ERR;
605 fed699f9 Jason Wang
    }
606 fed699f9 Jason Wang
607 f8f7c533 Jason Wang
    queues = lduw_p(&mq.virtqueue_pairs);
608 fed699f9 Jason Wang
609 f8f7c533 Jason Wang
    if (queues < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
610 f8f7c533 Jason Wang
        queues > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
611 f8f7c533 Jason Wang
        queues > n->max_queues ||
612 fed699f9 Jason Wang
        !n->multiqueue) {
613 fed699f9 Jason Wang
        return VIRTIO_NET_ERR;
614 fed699f9 Jason Wang
    }
615 fed699f9 Jason Wang
616 f8f7c533 Jason Wang
    n->curr_queues = queues;
617 fed699f9 Jason Wang
    /* stop the backend before changing the number of queues to avoid handling a
618 fed699f9 Jason Wang
     * disabled queue */
619 17a0ca55 KONRAD Frederic
    virtio_net_set_status(vdev, vdev->status);
620 fed699f9 Jason Wang
    virtio_net_set_queues(n);
621 fed699f9 Jason Wang
622 fed699f9 Jason Wang
    return VIRTIO_NET_OK;
623 fed699f9 Jason Wang
}
624 3d11d36c aliguori
static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
625 3d11d36c aliguori
{
626 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
627 3d11d36c aliguori
    struct virtio_net_ctrl_hdr ctrl;
628 3d11d36c aliguori
    virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
629 3d11d36c aliguori
    VirtQueueElement elem;
630 921ac5d0 Michael S. Tsirkin
    size_t s;
631 921ac5d0 Michael S. Tsirkin
    struct iovec *iov;
632 921ac5d0 Michael S. Tsirkin
    unsigned int iov_cnt;
633 3d11d36c aliguori
634 3d11d36c aliguori
    while (virtqueue_pop(vq, &elem)) {
635 921ac5d0 Michael S. Tsirkin
        if (iov_size(elem.in_sg, elem.in_num) < sizeof(status) ||
636 921ac5d0 Michael S. Tsirkin
            iov_size(elem.out_sg, elem.out_num) < sizeof(ctrl)) {
637 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net ctrl missing headers");
638 3d11d36c aliguori
            exit(1);
639 3d11d36c aliguori
        }
640 3d11d36c aliguori
641 921ac5d0 Michael S. Tsirkin
        iov = elem.out_sg;
642 921ac5d0 Michael S. Tsirkin
        iov_cnt = elem.out_num;
643 921ac5d0 Michael S. Tsirkin
        s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
644 921ac5d0 Michael S. Tsirkin
        iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
645 921ac5d0 Michael S. Tsirkin
        if (s != sizeof(ctrl)) {
646 921ac5d0 Michael S. Tsirkin
            status = VIRTIO_NET_ERR;
647 dd23454b Amos Kong
        } else if (ctrl.class == VIRTIO_NET_CTRL_RX) {
648 921ac5d0 Michael S. Tsirkin
            status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, iov_cnt);
649 921ac5d0 Michael S. Tsirkin
        } else if (ctrl.class == VIRTIO_NET_CTRL_MAC) {
650 921ac5d0 Michael S. Tsirkin
            status = virtio_net_handle_mac(n, ctrl.cmd, iov, iov_cnt);
651 921ac5d0 Michael S. Tsirkin
        } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
652 921ac5d0 Michael S. Tsirkin
            status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
653 fed699f9 Jason Wang
        } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) {
654 f8f7c533 Jason Wang
            status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt);
655 644c9858 Dmitry Fleytman
        } else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) {
656 644c9858 Dmitry Fleytman
            status = virtio_net_handle_offloads(n, ctrl.cmd, iov, iov_cnt);
657 3d11d36c aliguori
        }
658 3d11d36c aliguori
659 921ac5d0 Michael S. Tsirkin
        s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status));
660 921ac5d0 Michael S. Tsirkin
        assert(s == sizeof(status));
661 3d11d36c aliguori
662 3d11d36c aliguori
        virtqueue_push(vq, &elem, sizeof(status));
663 3d11d36c aliguori
        virtio_notify(vdev, vq);
664 3d11d36c aliguori
    }
665 3d11d36c aliguori
}
666 3d11d36c aliguori
667 fbe78f4f aliguori
/* RX */
668 fbe78f4f aliguori
669 fbe78f4f aliguori
static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
670 fbe78f4f aliguori
{
671 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
672 fed699f9 Jason Wang
    int queue_index = vq2q(virtio_get_queue_index(vq));
673 8aeff62d Mark McLoughlin
674 fed699f9 Jason Wang
    qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index));
675 fbe78f4f aliguori
}
676 fbe78f4f aliguori
677 4e68f7a0 Stefan Hajnoczi
static int virtio_net_can_receive(NetClientState *nc)
678 fbe78f4f aliguori
{
679 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
680 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
681 fed699f9 Jason Wang
    VirtIONetQueue *q = virtio_net_get_subqueue(nc);
682 0c87e93e Jason Wang
683 17a0ca55 KONRAD Frederic
    if (!vdev->vm_running) {
684 95477323 Michael S. Tsirkin
        return 0;
685 95477323 Michael S. Tsirkin
    }
686 cdd5cc12 Mark McLoughlin
687 fed699f9 Jason Wang
    if (nc->queue_index >= n->curr_queues) {
688 fed699f9 Jason Wang
        return 0;
689 fed699f9 Jason Wang
    }
690 fed699f9 Jason Wang
691 0c87e93e Jason Wang
    if (!virtio_queue_ready(q->rx_vq) ||
692 17a0ca55 KONRAD Frederic
        !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
693 fbe78f4f aliguori
        return 0;
694 0c87e93e Jason Wang
    }
695 fbe78f4f aliguori
696 cdd5cc12 Mark McLoughlin
    return 1;
697 cdd5cc12 Mark McLoughlin
}
698 cdd5cc12 Mark McLoughlin
699 0c87e93e Jason Wang
static int virtio_net_has_buffers(VirtIONetQueue *q, int bufsize)
700 cdd5cc12 Mark McLoughlin
{
701 0c87e93e Jason Wang
    VirtIONet *n = q->n;
702 0c87e93e Jason Wang
    if (virtio_queue_empty(q->rx_vq) ||
703 fbe78f4f aliguori
        (n->mergeable_rx_bufs &&
704 0c87e93e Jason Wang
         !virtqueue_avail_bytes(q->rx_vq, bufsize, 0))) {
705 0c87e93e Jason Wang
        virtio_queue_set_notification(q->rx_vq, 1);
706 06b12970 Tom Lendacky
707 06b12970 Tom Lendacky
        /* To avoid a race condition where the guest has made some buffers
708 06b12970 Tom Lendacky
         * available after the above check but before notification was
709 06b12970 Tom Lendacky
         * enabled, check for available buffers again.
710 06b12970 Tom Lendacky
         */
711 0c87e93e Jason Wang
        if (virtio_queue_empty(q->rx_vq) ||
712 06b12970 Tom Lendacky
            (n->mergeable_rx_bufs &&
713 0c87e93e Jason Wang
             !virtqueue_avail_bytes(q->rx_vq, bufsize, 0))) {
714 06b12970 Tom Lendacky
            return 0;
715 0c87e93e Jason Wang
        }
716 fbe78f4f aliguori
    }
717 fbe78f4f aliguori
718 0c87e93e Jason Wang
    virtio_queue_set_notification(q->rx_vq, 0);
719 fbe78f4f aliguori
    return 1;
720 fbe78f4f aliguori
}
721 fbe78f4f aliguori
722 1d41b0c1 Anthony Liguori
/* dhclient uses AF_PACKET but doesn't pass auxdata to the kernel so
723 1d41b0c1 Anthony Liguori
 * it never finds out that the packets don't have valid checksums.  This
724 1d41b0c1 Anthony Liguori
 * causes dhclient to get upset.  Fedora's carried a patch for ages to
725 1d41b0c1 Anthony Liguori
 * fix this with Xen but it hasn't appeared in an upstream release of
726 1d41b0c1 Anthony Liguori
 * dhclient yet.
727 1d41b0c1 Anthony Liguori
 *
728 1d41b0c1 Anthony Liguori
 * To avoid breaking existing guests, we catch udp packets and add
729 1d41b0c1 Anthony Liguori
 * checksums.  This is terrible but it's better than hacking the guest
730 1d41b0c1 Anthony Liguori
 * kernels.
731 1d41b0c1 Anthony Liguori
 *
732 1d41b0c1 Anthony Liguori
 * N.B. if we introduce a zero-copy API, this operation is no longer free so
733 1d41b0c1 Anthony Liguori
 * we should provide a mechanism to disable it to avoid polluting the host
734 1d41b0c1 Anthony Liguori
 * cache.
735 1d41b0c1 Anthony Liguori
 */
736 1d41b0c1 Anthony Liguori
static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
737 22cc84db Michael S. Tsirkin
                                        uint8_t *buf, size_t size)
738 1d41b0c1 Anthony Liguori
{
739 1d41b0c1 Anthony Liguori
    if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
740 1d41b0c1 Anthony Liguori
        (size > 27 && size < 1500) && /* normal sized MTU */
741 1d41b0c1 Anthony Liguori
        (buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
742 1d41b0c1 Anthony Liguori
        (buf[23] == 17) && /* ip.protocol == UDP */
743 1d41b0c1 Anthony Liguori
        (buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
744 22cc84db Michael S. Tsirkin
        net_checksum_calculate(buf, size);
745 1d41b0c1 Anthony Liguori
        hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
746 1d41b0c1 Anthony Liguori
    }
747 1d41b0c1 Anthony Liguori
}
748 1d41b0c1 Anthony Liguori
749 280598b7 Michael S. Tsirkin
static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt,
750 280598b7 Michael S. Tsirkin
                           const void *buf, size_t size)
751 fbe78f4f aliguori
{
752 3a330134 Mark McLoughlin
    if (n->has_vnet_hdr) {
753 22cc84db Michael S. Tsirkin
        /* FIXME this cast is evil */
754 22cc84db Michael S. Tsirkin
        void *wbuf = (void *)buf;
755 280598b7 Michael S. Tsirkin
        work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len,
756 280598b7 Michael S. Tsirkin
                                    size - n->host_hdr_len);
757 280598b7 Michael S. Tsirkin
        iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
758 22cc84db Michael S. Tsirkin
    } else {
759 22cc84db Michael S. Tsirkin
        struct virtio_net_hdr hdr = {
760 22cc84db Michael S. Tsirkin
            .flags = 0,
761 22cc84db Michael S. Tsirkin
            .gso_type = VIRTIO_NET_HDR_GSO_NONE
762 22cc84db Michael S. Tsirkin
        };
763 22cc84db Michael S. Tsirkin
        iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr);
764 3a330134 Mark McLoughlin
    }
765 fbe78f4f aliguori
}
766 fbe78f4f aliguori
767 3831ab20 aliguori
static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
768 3831ab20 aliguori
{
769 3831ab20 aliguori
    static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
770 f21c0ed9 aliguori
    static const uint8_t vlan[] = {0x81, 0x00};
771 3831ab20 aliguori
    uint8_t *ptr = (uint8_t *)buf;
772 b6503ed9 aliguori
    int i;
773 3831ab20 aliguori
774 3831ab20 aliguori
    if (n->promisc)
775 3831ab20 aliguori
        return 1;
776 3831ab20 aliguori
777 e043ebc6 Michael S. Tsirkin
    ptr += n->host_hdr_len;
778 3a330134 Mark McLoughlin
779 f21c0ed9 aliguori
    if (!memcmp(&ptr[12], vlan, sizeof(vlan))) {
780 f21c0ed9 aliguori
        int vid = be16_to_cpup((uint16_t *)(ptr + 14)) & 0xfff;
781 f21c0ed9 aliguori
        if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f))))
782 f21c0ed9 aliguori
            return 0;
783 f21c0ed9 aliguori
    }
784 f21c0ed9 aliguori
785 bbe2f399 Alex Williamson
    if (ptr[0] & 1) { // multicast
786 bbe2f399 Alex Williamson
        if (!memcmp(ptr, bcast, sizeof(bcast))) {
787 015cb166 Alex Williamson
            return !n->nobcast;
788 015cb166 Alex Williamson
        } else if (n->nomulti) {
789 015cb166 Alex Williamson
            return 0;
790 8fd2a2f1 Alex Williamson
        } else if (n->allmulti || n->mac_table.multi_overflow) {
791 bbe2f399 Alex Williamson
            return 1;
792 bbe2f399 Alex Williamson
        }
793 2d9aba39 Alex Williamson
794 2d9aba39 Alex Williamson
        for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
795 2d9aba39 Alex Williamson
            if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) {
796 2d9aba39 Alex Williamson
                return 1;
797 2d9aba39 Alex Williamson
            }
798 2d9aba39 Alex Williamson
        }
799 bbe2f399 Alex Williamson
    } else { // unicast
800 015cb166 Alex Williamson
        if (n->nouni) {
801 015cb166 Alex Williamson
            return 0;
802 015cb166 Alex Williamson
        } else if (n->alluni || n->mac_table.uni_overflow) {
803 8fd2a2f1 Alex Williamson
            return 1;
804 8fd2a2f1 Alex Williamson
        } else if (!memcmp(ptr, n->mac, ETH_ALEN)) {
805 bbe2f399 Alex Williamson
            return 1;
806 bbe2f399 Alex Williamson
        }
807 3831ab20 aliguori
808 2d9aba39 Alex Williamson
        for (i = 0; i < n->mac_table.first_multi; i++) {
809 2d9aba39 Alex Williamson
            if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) {
810 2d9aba39 Alex Williamson
                return 1;
811 2d9aba39 Alex Williamson
            }
812 2d9aba39 Alex Williamson
        }
813 b6503ed9 aliguori
    }
814 b6503ed9 aliguori
815 3831ab20 aliguori
    return 0;
816 3831ab20 aliguori
}
817 3831ab20 aliguori
818 4e68f7a0 Stefan Hajnoczi
static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t size)
819 fbe78f4f aliguori
{
820 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
821 fed699f9 Jason Wang
    VirtIONetQueue *q = virtio_net_get_subqueue(nc);
822 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
823 63c58728 Michael S. Tsirkin
    struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
824 63c58728 Michael S. Tsirkin
    struct virtio_net_hdr_mrg_rxbuf mhdr;
825 63c58728 Michael S. Tsirkin
    unsigned mhdr_cnt = 0;
826 22cc84db Michael S. Tsirkin
    size_t offset, i, guest_offset;
827 fbe78f4f aliguori
828 fed699f9 Jason Wang
    if (!virtio_net_can_receive(nc)) {
829 cdd5cc12 Mark McLoughlin
        return -1;
830 b356f76d Jason Wang
    }
831 cdd5cc12 Mark McLoughlin
832 940cda94 Michael S. Tsirkin
    /* hdr_len refers to the header we supply to the guest */
833 0c87e93e Jason Wang
    if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
834 8aeff62d Mark McLoughlin
        return 0;
835 0c87e93e Jason Wang
    }
836 fbe78f4f aliguori
837 3831ab20 aliguori
    if (!receive_filter(n, buf, size))
838 4f1c942b Mark McLoughlin
        return size;
839 3831ab20 aliguori
840 fbe78f4f aliguori
    offset = i = 0;
841 fbe78f4f aliguori
842 fbe78f4f aliguori
    while (offset < size) {
843 fbe78f4f aliguori
        VirtQueueElement elem;
844 fbe78f4f aliguori
        int len, total;
845 22cc84db Michael S. Tsirkin
        const struct iovec *sg = elem.in_sg;
846 fbe78f4f aliguori
847 22c253d9 Amit Shah
        total = 0;
848 fbe78f4f aliguori
849 0c87e93e Jason Wang
        if (virtqueue_pop(q->rx_vq, &elem) == 0) {
850 fbe78f4f aliguori
            if (i == 0)
851 4f1c942b Mark McLoughlin
                return -1;
852 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net unexpected empty queue: "
853 279a4253 Michael S. Tsirkin
                    "i %zd mergeable %d offset %zd, size %zd, "
854 e7b43f7e Stefan Hajnoczi
                    "guest hdr len %zd, host hdr len %zd guest features 0x%x",
855 279a4253 Michael S. Tsirkin
                    i, n->mergeable_rx_bufs, offset, size,
856 17a0ca55 KONRAD Frederic
                    n->guest_hdr_len, n->host_hdr_len, vdev->guest_features);
857 fbe78f4f aliguori
            exit(1);
858 fbe78f4f aliguori
        }
859 fbe78f4f aliguori
860 fbe78f4f aliguori
        if (elem.in_num < 1) {
861 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net receive queue contains no in buffers");
862 fbe78f4f aliguori
            exit(1);
863 fbe78f4f aliguori
        }
864 fbe78f4f aliguori
865 fbe78f4f aliguori
        if (i == 0) {
866 c8d28e7e Michael S. Tsirkin
            assert(offset == 0);
867 63c58728 Michael S. Tsirkin
            if (n->mergeable_rx_bufs) {
868 63c58728 Michael S. Tsirkin
                mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg),
869 63c58728 Michael S. Tsirkin
                                    sg, elem.in_num,
870 63c58728 Michael S. Tsirkin
                                    offsetof(typeof(mhdr), num_buffers),
871 63c58728 Michael S. Tsirkin
                                    sizeof(mhdr.num_buffers));
872 63c58728 Michael S. Tsirkin
            }
873 fbe78f4f aliguori
874 c8d28e7e Michael S. Tsirkin
            receive_header(n, sg, elem.in_num, buf, size);
875 c8d28e7e Michael S. Tsirkin
            offset = n->host_hdr_len;
876 e35e23f6 Michael S. Tsirkin
            total += n->guest_hdr_len;
877 22cc84db Michael S. Tsirkin
            guest_offset = n->guest_hdr_len;
878 22cc84db Michael S. Tsirkin
        } else {
879 22cc84db Michael S. Tsirkin
            guest_offset = 0;
880 fbe78f4f aliguori
        }
881 fbe78f4f aliguori
882 fbe78f4f aliguori
        /* copy in packet.  ugh */
883 22cc84db Michael S. Tsirkin
        len = iov_from_buf(sg, elem.in_num, guest_offset,
884 dcf6f5e1 Michael Tokarev
                           buf + offset, size - offset);
885 fbe78f4f aliguori
        total += len;
886 279a4253 Michael S. Tsirkin
        offset += len;
887 279a4253 Michael S. Tsirkin
        /* If buffers can't be merged, at this point we
888 279a4253 Michael S. Tsirkin
         * must have consumed the complete packet.
889 279a4253 Michael S. Tsirkin
         * Otherwise, drop it. */
890 279a4253 Michael S. Tsirkin
        if (!n->mergeable_rx_bufs && offset < size) {
891 279a4253 Michael S. Tsirkin
#if 0
892 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net truncated non-mergeable packet: "
893 e7b43f7e Stefan Hajnoczi
                         "i %zd mergeable %d offset %zd, size %zd, "
894 e7b43f7e Stefan Hajnoczi
                         "guest hdr len %zd, host hdr len %zd",
895 e7b43f7e Stefan Hajnoczi
                         i, n->mergeable_rx_bufs,
896 e35e23f6 Michael S. Tsirkin
                         offset, size, n->guest_hdr_len, n->host_hdr_len);
897 279a4253 Michael S. Tsirkin
#endif
898 279a4253 Michael S. Tsirkin
            return size;
899 279a4253 Michael S. Tsirkin
        }
900 fbe78f4f aliguori
901 fbe78f4f aliguori
        /* signal other side */
902 0c87e93e Jason Wang
        virtqueue_fill(q->rx_vq, &elem, total, i++);
903 fbe78f4f aliguori
    }
904 fbe78f4f aliguori
905 63c58728 Michael S. Tsirkin
    if (mhdr_cnt) {
906 63c58728 Michael S. Tsirkin
        stw_p(&mhdr.num_buffers, i);
907 63c58728 Michael S. Tsirkin
        iov_from_buf(mhdr_sg, mhdr_cnt,
908 63c58728 Michael S. Tsirkin
                     0,
909 63c58728 Michael S. Tsirkin
                     &mhdr.num_buffers, sizeof mhdr.num_buffers);
910 44b15bc5 Aurelien Jarno
    }
911 fbe78f4f aliguori
912 0c87e93e Jason Wang
    virtqueue_flush(q->rx_vq, i);
913 17a0ca55 KONRAD Frederic
    virtio_notify(vdev, q->rx_vq);
914 4f1c942b Mark McLoughlin
915 4f1c942b Mark McLoughlin
    return size;
916 fbe78f4f aliguori
}
917 fbe78f4f aliguori
918 0c87e93e Jason Wang
static int32_t virtio_net_flush_tx(VirtIONetQueue *q);
919 6243375f Mark McLoughlin
920 4e68f7a0 Stefan Hajnoczi
static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
921 6243375f Mark McLoughlin
{
922 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
923 fed699f9 Jason Wang
    VirtIONetQueue *q = virtio_net_get_subqueue(nc);
924 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
925 6243375f Mark McLoughlin
926 0c87e93e Jason Wang
    virtqueue_push(q->tx_vq, &q->async_tx.elem, 0);
927 17a0ca55 KONRAD Frederic
    virtio_notify(vdev, q->tx_vq);
928 6243375f Mark McLoughlin
929 0c87e93e Jason Wang
    q->async_tx.elem.out_num = q->async_tx.len = 0;
930 6243375f Mark McLoughlin
931 0c87e93e Jason Wang
    virtio_queue_set_notification(q->tx_vq, 1);
932 0c87e93e Jason Wang
    virtio_net_flush_tx(q);
933 6243375f Mark McLoughlin
}
934 6243375f Mark McLoughlin
935 fbe78f4f aliguori
/* TX */
936 0c87e93e Jason Wang
static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
937 fbe78f4f aliguori
{
938 0c87e93e Jason Wang
    VirtIONet *n = q->n;
939 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
940 fbe78f4f aliguori
    VirtQueueElement elem;
941 e3f30488 Alex Williamson
    int32_t num_packets = 0;
942 fed699f9 Jason Wang
    int queue_index = vq2q(virtio_get_queue_index(q->tx_vq));
943 17a0ca55 KONRAD Frederic
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
944 e3f30488 Alex Williamson
        return num_packets;
945 e3f30488 Alex Williamson
    }
946 fbe78f4f aliguori
947 17a0ca55 KONRAD Frederic
    assert(vdev->vm_running);
948 783e7706 Michael S. Tsirkin
949 0c87e93e Jason Wang
    if (q->async_tx.elem.out_num) {
950 0c87e93e Jason Wang
        virtio_queue_set_notification(q->tx_vq, 0);
951 e3f30488 Alex Williamson
        return num_packets;
952 6243375f Mark McLoughlin
    }
953 6243375f Mark McLoughlin
954 0c87e93e Jason Wang
    while (virtqueue_pop(q->tx_vq, &elem)) {
955 14761f9c Michael S. Tsirkin
        ssize_t ret, len;
956 fbe78f4f aliguori
        unsigned int out_num = elem.out_num;
957 fbe78f4f aliguori
        struct iovec *out_sg = &elem.out_sg[0];
958 14761f9c Michael S. Tsirkin
        struct iovec sg[VIRTQUEUE_MAX_SIZE];
959 fbe78f4f aliguori
960 7b80d08e Michael S. Tsirkin
        if (out_num < 1) {
961 e7b43f7e Stefan Hajnoczi
            error_report("virtio-net header not in first element");
962 fbe78f4f aliguori
            exit(1);
963 fbe78f4f aliguori
        }
964 fbe78f4f aliguori
965 14761f9c Michael S. Tsirkin
        /*
966 14761f9c Michael S. Tsirkin
         * If host wants to see the guest header as is, we can
967 14761f9c Michael S. Tsirkin
         * pass it on unchanged. Otherwise, copy just the parts
968 14761f9c Michael S. Tsirkin
         * that host is interested in.
969 14761f9c Michael S. Tsirkin
         */
970 14761f9c Michael S. Tsirkin
        assert(n->host_hdr_len <= n->guest_hdr_len);
971 14761f9c Michael S. Tsirkin
        if (n->host_hdr_len != n->guest_hdr_len) {
972 14761f9c Michael S. Tsirkin
            unsigned sg_num = iov_copy(sg, ARRAY_SIZE(sg),
973 14761f9c Michael S. Tsirkin
                                       out_sg, out_num,
974 14761f9c Michael S. Tsirkin
                                       0, n->host_hdr_len);
975 14761f9c Michael S. Tsirkin
            sg_num += iov_copy(sg + sg_num, ARRAY_SIZE(sg) - sg_num,
976 14761f9c Michael S. Tsirkin
                             out_sg, out_num,
977 14761f9c Michael S. Tsirkin
                             n->guest_hdr_len, -1);
978 14761f9c Michael S. Tsirkin
            out_num = sg_num;
979 14761f9c Michael S. Tsirkin
            out_sg = sg;
980 fbe78f4f aliguori
        }
981 fbe78f4f aliguori
982 7b80d08e Michael S. Tsirkin
        len = n->guest_hdr_len;
983 14761f9c Michael S. Tsirkin
984 fed699f9 Jason Wang
        ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index),
985 fed699f9 Jason Wang
                                      out_sg, out_num, virtio_net_tx_complete);
986 6243375f Mark McLoughlin
        if (ret == 0) {
987 0c87e93e Jason Wang
            virtio_queue_set_notification(q->tx_vq, 0);
988 0c87e93e Jason Wang
            q->async_tx.elem = elem;
989 0c87e93e Jason Wang
            q->async_tx.len  = len;
990 e3f30488 Alex Williamson
            return -EBUSY;
991 6243375f Mark McLoughlin
        }
992 6243375f Mark McLoughlin
993 6243375f Mark McLoughlin
        len += ret;
994 fbe78f4f aliguori
995 0c87e93e Jason Wang
        virtqueue_push(q->tx_vq, &elem, 0);
996 17a0ca55 KONRAD Frederic
        virtio_notify(vdev, q->tx_vq);
997 e3f30488 Alex Williamson
998 e3f30488 Alex Williamson
        if (++num_packets >= n->tx_burst) {
999 e3f30488 Alex Williamson
            break;
1000 e3f30488 Alex Williamson
        }
1001 fbe78f4f aliguori
    }
1002 e3f30488 Alex Williamson
    return num_packets;
1003 fbe78f4f aliguori
}
1004 fbe78f4f aliguori
1005 a697a334 Alex Williamson
static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
1006 fbe78f4f aliguori
{
1007 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
1008 fed699f9 Jason Wang
    VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
1009 fbe78f4f aliguori
1010 783e7706 Michael S. Tsirkin
    /* This happens when device was stopped but VCPU wasn't. */
1011 17a0ca55 KONRAD Frederic
    if (!vdev->vm_running) {
1012 0c87e93e Jason Wang
        q->tx_waiting = 1;
1013 783e7706 Michael S. Tsirkin
        return;
1014 783e7706 Michael S. Tsirkin
    }
1015 783e7706 Michael S. Tsirkin
1016 0c87e93e Jason Wang
    if (q->tx_waiting) {
1017 fbe78f4f aliguori
        virtio_queue_set_notification(vq, 1);
1018 0c87e93e Jason Wang
        qemu_del_timer(q->tx_timer);
1019 0c87e93e Jason Wang
        q->tx_waiting = 0;
1020 0c87e93e Jason Wang
        virtio_net_flush_tx(q);
1021 fbe78f4f aliguori
    } else {
1022 0c87e93e Jason Wang
        qemu_mod_timer(q->tx_timer,
1023 74475455 Paolo Bonzini
                       qemu_get_clock_ns(vm_clock) + n->tx_timeout);
1024 0c87e93e Jason Wang
        q->tx_waiting = 1;
1025 fbe78f4f aliguori
        virtio_queue_set_notification(vq, 0);
1026 fbe78f4f aliguori
    }
1027 fbe78f4f aliguori
}
1028 fbe78f4f aliguori
1029 a697a334 Alex Williamson
static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
1030 a697a334 Alex Williamson
{
1031 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
1032 fed699f9 Jason Wang
    VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
1033 a697a334 Alex Williamson
1034 0c87e93e Jason Wang
    if (unlikely(q->tx_waiting)) {
1035 a697a334 Alex Williamson
        return;
1036 a697a334 Alex Williamson
    }
1037 0c87e93e Jason Wang
    q->tx_waiting = 1;
1038 783e7706 Michael S. Tsirkin
    /* This happens when device was stopped but VCPU wasn't. */
1039 17a0ca55 KONRAD Frederic
    if (!vdev->vm_running) {
1040 783e7706 Michael S. Tsirkin
        return;
1041 783e7706 Michael S. Tsirkin
    }
1042 a697a334 Alex Williamson
    virtio_queue_set_notification(vq, 0);
1043 0c87e93e Jason Wang
    qemu_bh_schedule(q->tx_bh);
1044 a697a334 Alex Williamson
}
1045 a697a334 Alex Williamson
1046 fbe78f4f aliguori
static void virtio_net_tx_timer(void *opaque)
1047 fbe78f4f aliguori
{
1048 0c87e93e Jason Wang
    VirtIONetQueue *q = opaque;
1049 0c87e93e Jason Wang
    VirtIONet *n = q->n;
1050 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1051 17a0ca55 KONRAD Frederic
    assert(vdev->vm_running);
1052 fbe78f4f aliguori
1053 0c87e93e Jason Wang
    q->tx_waiting = 0;
1054 fbe78f4f aliguori
1055 fbe78f4f aliguori
    /* Just in case the driver is not ready on more */
1056 17a0ca55 KONRAD Frederic
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
1057 fbe78f4f aliguori
        return;
1058 17a0ca55 KONRAD Frederic
    }
1059 fbe78f4f aliguori
1060 0c87e93e Jason Wang
    virtio_queue_set_notification(q->tx_vq, 1);
1061 0c87e93e Jason Wang
    virtio_net_flush_tx(q);
1062 fbe78f4f aliguori
}
1063 fbe78f4f aliguori
1064 a697a334 Alex Williamson
static void virtio_net_tx_bh(void *opaque)
1065 a697a334 Alex Williamson
{
1066 0c87e93e Jason Wang
    VirtIONetQueue *q = opaque;
1067 0c87e93e Jason Wang
    VirtIONet *n = q->n;
1068 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1069 a697a334 Alex Williamson
    int32_t ret;
1070 a697a334 Alex Williamson
1071 17a0ca55 KONRAD Frederic
    assert(vdev->vm_running);
1072 783e7706 Michael S. Tsirkin
1073 0c87e93e Jason Wang
    q->tx_waiting = 0;
1074 a697a334 Alex Williamson
1075 a697a334 Alex Williamson
    /* Just in case the driver is not ready on more */
1076 17a0ca55 KONRAD Frederic
    if (unlikely(!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))) {
1077 a697a334 Alex Williamson
        return;
1078 17a0ca55 KONRAD Frederic
    }
1079 a697a334 Alex Williamson
1080 0c87e93e Jason Wang
    ret = virtio_net_flush_tx(q);
1081 a697a334 Alex Williamson
    if (ret == -EBUSY) {
1082 a697a334 Alex Williamson
        return; /* Notification re-enable handled by tx_complete */
1083 a697a334 Alex Williamson
    }
1084 a697a334 Alex Williamson
1085 a697a334 Alex Williamson
    /* If we flush a full burst of packets, assume there are
1086 a697a334 Alex Williamson
     * more coming and immediately reschedule */
1087 a697a334 Alex Williamson
    if (ret >= n->tx_burst) {
1088 0c87e93e Jason Wang
        qemu_bh_schedule(q->tx_bh);
1089 0c87e93e Jason Wang
        q->tx_waiting = 1;
1090 a697a334 Alex Williamson
        return;
1091 a697a334 Alex Williamson
    }
1092 a697a334 Alex Williamson
1093 a697a334 Alex Williamson
    /* If less than a full burst, re-enable notification and flush
1094 a697a334 Alex Williamson
     * anything that may have come in while we weren't looking.  If
1095 a697a334 Alex Williamson
     * we find something, assume the guest is still active and reschedule */
1096 0c87e93e Jason Wang
    virtio_queue_set_notification(q->tx_vq, 1);
1097 0c87e93e Jason Wang
    if (virtio_net_flush_tx(q) > 0) {
1098 0c87e93e Jason Wang
        virtio_queue_set_notification(q->tx_vq, 0);
1099 0c87e93e Jason Wang
        qemu_bh_schedule(q->tx_bh);
1100 0c87e93e Jason Wang
        q->tx_waiting = 1;
1101 a697a334 Alex Williamson
    }
1102 a697a334 Alex Williamson
}
1103 a697a334 Alex Williamson
1104 ec57db16 Jason Wang
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
1105 fed699f9 Jason Wang
{
1106 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1107 fed699f9 Jason Wang
    int i, max = multiqueue ? n->max_queues : 1;
1108 fed699f9 Jason Wang
1109 fed699f9 Jason Wang
    n->multiqueue = multiqueue;
1110 fed699f9 Jason Wang
1111 fed699f9 Jason Wang
    for (i = 2; i <= n->max_queues * 2 + 1; i++) {
1112 fed699f9 Jason Wang
        virtio_del_queue(vdev, i);
1113 fed699f9 Jason Wang
    }
1114 fed699f9 Jason Wang
1115 fed699f9 Jason Wang
    for (i = 1; i < max; i++) {
1116 fed699f9 Jason Wang
        n->vqs[i].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
1117 fed699f9 Jason Wang
        if (n->vqs[i].tx_timer) {
1118 fed699f9 Jason Wang
            n->vqs[i].tx_vq =
1119 fed699f9 Jason Wang
                virtio_add_queue(vdev, 256, virtio_net_handle_tx_timer);
1120 fed699f9 Jason Wang
            n->vqs[i].tx_timer = qemu_new_timer_ns(vm_clock,
1121 fed699f9 Jason Wang
                                                   virtio_net_tx_timer,
1122 fed699f9 Jason Wang
                                                   &n->vqs[i]);
1123 fed699f9 Jason Wang
        } else {
1124 fed699f9 Jason Wang
            n->vqs[i].tx_vq =
1125 fed699f9 Jason Wang
                virtio_add_queue(vdev, 256, virtio_net_handle_tx_bh);
1126 fed699f9 Jason Wang
            n->vqs[i].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[i]);
1127 fed699f9 Jason Wang
        }
1128 fed699f9 Jason Wang
1129 fed699f9 Jason Wang
        n->vqs[i].tx_waiting = 0;
1130 fed699f9 Jason Wang
        n->vqs[i].n = n;
1131 fed699f9 Jason Wang
    }
1132 fed699f9 Jason Wang
1133 ec57db16 Jason Wang
    /* Note: Minux Guests (version 3.2.1) use ctrl vq but don't ack
1134 ec57db16 Jason Wang
     * VIRTIO_NET_F_CTRL_VQ. Create ctrl vq unconditionally to avoid
1135 ec57db16 Jason Wang
     * breaking them.
1136 ec57db16 Jason Wang
     */
1137 ec57db16 Jason Wang
    n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
1138 fed699f9 Jason Wang
1139 fed699f9 Jason Wang
    virtio_net_set_queues(n);
1140 fed699f9 Jason Wang
}
1141 fed699f9 Jason Wang
1142 fbe78f4f aliguori
static void virtio_net_save(QEMUFile *f, void *opaque)
1143 fbe78f4f aliguori
{
1144 5f800801 Jason Wang
    int i;
1145 fbe78f4f aliguori
    VirtIONet *n = opaque;
1146 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1147 fbe78f4f aliguori
1148 afbaa7b4 Michael S. Tsirkin
    /* At this point, backend must be stopped, otherwise
1149 afbaa7b4 Michael S. Tsirkin
     * it might keep writing to memory. */
1150 afbaa7b4 Michael S. Tsirkin
    assert(!n->vhost_started);
1151 17a0ca55 KONRAD Frederic
    virtio_save(vdev, f);
1152 fbe78f4f aliguori
1153 79674068 aliguori
    qemu_put_buffer(f, n->mac, ETH_ALEN);
1154 5f800801 Jason Wang
    qemu_put_be32(f, n->vqs[0].tx_waiting);
1155 e46cb38f aliguori
    qemu_put_be32(f, n->mergeable_rx_bufs);
1156 9d6271b8 aliguori
    qemu_put_be16(f, n->status);
1157 f10c592e Alex Williamson
    qemu_put_byte(f, n->promisc);
1158 f10c592e Alex Williamson
    qemu_put_byte(f, n->allmulti);
1159 b6503ed9 aliguori
    qemu_put_be32(f, n->mac_table.in_use);
1160 b6503ed9 aliguori
    qemu_put_buffer(f, n->mac_table.macs, n->mac_table.in_use * ETH_ALEN);
1161 f21c0ed9 aliguori
    qemu_put_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);
1162 3a330134 Mark McLoughlin
    qemu_put_be32(f, n->has_vnet_hdr);
1163 8fd2a2f1 Alex Williamson
    qemu_put_byte(f, n->mac_table.multi_overflow);
1164 8fd2a2f1 Alex Williamson
    qemu_put_byte(f, n->mac_table.uni_overflow);
1165 015cb166 Alex Williamson
    qemu_put_byte(f, n->alluni);
1166 015cb166 Alex Williamson
    qemu_put_byte(f, n->nomulti);
1167 015cb166 Alex Williamson
    qemu_put_byte(f, n->nouni);
1168 015cb166 Alex Williamson
    qemu_put_byte(f, n->nobcast);
1169 0ce0e8f4 Mark McLoughlin
    qemu_put_byte(f, n->has_ufo);
1170 5f800801 Jason Wang
    if (n->max_queues > 1) {
1171 5f800801 Jason Wang
        qemu_put_be16(f, n->max_queues);
1172 5f800801 Jason Wang
        qemu_put_be16(f, n->curr_queues);
1173 5f800801 Jason Wang
        for (i = 1; i < n->curr_queues; i++) {
1174 5f800801 Jason Wang
            qemu_put_be32(f, n->vqs[i].tx_waiting);
1175 5f800801 Jason Wang
        }
1176 5f800801 Jason Wang
    }
1177 644c9858 Dmitry Fleytman
1178 644c9858 Dmitry Fleytman
    if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) {
1179 644c9858 Dmitry Fleytman
        qemu_put_be64(f, n->curr_guest_offloads);
1180 644c9858 Dmitry Fleytman
    }
1181 fbe78f4f aliguori
}
1182 fbe78f4f aliguori
1183 fbe78f4f aliguori
static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
1184 fbe78f4f aliguori
{
1185 fbe78f4f aliguori
    VirtIONet *n = opaque;
1186 17a0ca55 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(n);
1187 5f800801 Jason Wang
    int ret, i, link_down;
1188 fbe78f4f aliguori
1189 9d6271b8 aliguori
    if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
1190 fbe78f4f aliguori
        return -EINVAL;
1191 fbe78f4f aliguori
1192 17a0ca55 KONRAD Frederic
    ret = virtio_load(vdev, f);
1193 2a633c46 Orit Wassermann
    if (ret) {
1194 2a633c46 Orit Wassermann
        return ret;
1195 2a633c46 Orit Wassermann
    }
1196 fbe78f4f aliguori
1197 79674068 aliguori
    qemu_get_buffer(f, n->mac, ETH_ALEN);
1198 5f800801 Jason Wang
    n->vqs[0].tx_waiting = qemu_get_be32(f);
1199 ff3a8066 Michael S. Tsirkin
1200 ff3a8066 Michael S. Tsirkin
    virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f));
1201 fbe78f4f aliguori
1202 9d6271b8 aliguori
    if (version_id >= 3)
1203 9d6271b8 aliguori
        n->status = qemu_get_be16(f);
1204 9d6271b8 aliguori
1205 002437cd aliguori
    if (version_id >= 4) {
1206 f10c592e Alex Williamson
        if (version_id < 8) {
1207 f10c592e Alex Williamson
            n->promisc = qemu_get_be32(f);
1208 f10c592e Alex Williamson
            n->allmulti = qemu_get_be32(f);
1209 f10c592e Alex Williamson
        } else {
1210 f10c592e Alex Williamson
            n->promisc = qemu_get_byte(f);
1211 f10c592e Alex Williamson
            n->allmulti = qemu_get_byte(f);
1212 f10c592e Alex Williamson
        }
1213 002437cd aliguori
    }
1214 002437cd aliguori
1215 b6503ed9 aliguori
    if (version_id >= 5) {
1216 b6503ed9 aliguori
        n->mac_table.in_use = qemu_get_be32(f);
1217 b6503ed9 aliguori
        /* MAC_TABLE_ENTRIES may be different from the saved image */
1218 b6503ed9 aliguori
        if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
1219 b6503ed9 aliguori
            qemu_get_buffer(f, n->mac_table.macs,
1220 b6503ed9 aliguori
                            n->mac_table.in_use * ETH_ALEN);
1221 b6503ed9 aliguori
        } else if (n->mac_table.in_use) {
1222 e398d61b Juan Quintela
            uint8_t *buf = g_malloc0(n->mac_table.in_use);
1223 e398d61b Juan Quintela
            qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN);
1224 e398d61b Juan Quintela
            g_free(buf);
1225 8fd2a2f1 Alex Williamson
            n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1;
1226 b6503ed9 aliguori
            n->mac_table.in_use = 0;
1227 b6503ed9 aliguori
        }
1228 b6503ed9 aliguori
    }
1229 b6503ed9 aliguori
 
1230 f21c0ed9 aliguori
    if (version_id >= 6)
1231 f21c0ed9 aliguori
        qemu_get_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);
1232 f21c0ed9 aliguori
1233 3a330134 Mark McLoughlin
    if (version_id >= 7) {
1234 3a330134 Mark McLoughlin
        if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) {
1235 1ecda02b Markus Armbruster
            error_report("virtio-net: saved image requires vnet_hdr=on");
1236 3a330134 Mark McLoughlin
            return -1;
1237 3a330134 Mark McLoughlin
        }
1238 6c042c16 Alex Williamson
    }
1239 6c042c16 Alex Williamson
1240 8fd2a2f1 Alex Williamson
    if (version_id >= 9) {
1241 8fd2a2f1 Alex Williamson
        n->mac_table.multi_overflow = qemu_get_byte(f);
1242 8fd2a2f1 Alex Williamson
        n->mac_table.uni_overflow = qemu_get_byte(f);
1243 8fd2a2f1 Alex Williamson
    }
1244 8fd2a2f1 Alex Williamson
1245 015cb166 Alex Williamson
    if (version_id >= 10) {
1246 015cb166 Alex Williamson
        n->alluni = qemu_get_byte(f);
1247 015cb166 Alex Williamson
        n->nomulti = qemu_get_byte(f);
1248 015cb166 Alex Williamson
        n->nouni = qemu_get_byte(f);
1249 015cb166 Alex Williamson
        n->nobcast = qemu_get_byte(f);
1250 015cb166 Alex Williamson
    }
1251 015cb166 Alex Williamson
1252 0ce0e8f4 Mark McLoughlin
    if (version_id >= 11) {
1253 0ce0e8f4 Mark McLoughlin
        if (qemu_get_byte(f) && !peer_has_ufo(n)) {
1254 1ecda02b Markus Armbruster
            error_report("virtio-net: saved image requires TUN_F_UFO support");
1255 0ce0e8f4 Mark McLoughlin
            return -1;
1256 0ce0e8f4 Mark McLoughlin
        }
1257 0ce0e8f4 Mark McLoughlin
    }
1258 0ce0e8f4 Mark McLoughlin
1259 5f800801 Jason Wang
    if (n->max_queues > 1) {
1260 5f800801 Jason Wang
        if (n->max_queues != qemu_get_be16(f)) {
1261 5f800801 Jason Wang
            error_report("virtio-net: different max_queues ");
1262 5f800801 Jason Wang
            return -1;
1263 5f800801 Jason Wang
        }
1264 5f800801 Jason Wang
1265 5f800801 Jason Wang
        n->curr_queues = qemu_get_be16(f);
1266 5f800801 Jason Wang
        for (i = 1; i < n->curr_queues; i++) {
1267 5f800801 Jason Wang
            n->vqs[i].tx_waiting = qemu_get_be32(f);
1268 5f800801 Jason Wang
        }
1269 5f800801 Jason Wang
    }
1270 5f800801 Jason Wang
1271 644c9858 Dmitry Fleytman
    if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) {
1272 644c9858 Dmitry Fleytman
        n->curr_guest_offloads = qemu_get_be64(f);
1273 644c9858 Dmitry Fleytman
    } else {
1274 644c9858 Dmitry Fleytman
        n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
1275 644c9858 Dmitry Fleytman
    }
1276 644c9858 Dmitry Fleytman
1277 644c9858 Dmitry Fleytman
    if (peer_has_vnet_hdr(n)) {
1278 644c9858 Dmitry Fleytman
        virtio_net_apply_guest_offloads(n);
1279 644c9858 Dmitry Fleytman
    }
1280 644c9858 Dmitry Fleytman
1281 5f800801 Jason Wang
    virtio_net_set_queues(n);
1282 5f800801 Jason Wang
1283 2d9aba39 Alex Williamson
    /* Find the first multicast entry in the saved MAC filter */
1284 2d9aba39 Alex Williamson
    for (i = 0; i < n->mac_table.in_use; i++) {
1285 2d9aba39 Alex Williamson
        if (n->mac_table.macs[i * ETH_ALEN] & 1) {
1286 2d9aba39 Alex Williamson
            break;
1287 2d9aba39 Alex Williamson
        }
1288 2d9aba39 Alex Williamson
    }
1289 2d9aba39 Alex Williamson
    n->mac_table.first_multi = i;
1290 98991481 Amos Kong
1291 98991481 Amos Kong
    /* nc.link_down can't be migrated, so infer link_down according
1292 98991481 Amos Kong
     * to link status bit in n->status */
1293 5f800801 Jason Wang
    link_down = (n->status & VIRTIO_NET_S_LINK_UP) == 0;
1294 5f800801 Jason Wang
    for (i = 0; i < n->max_queues; i++) {
1295 5f800801 Jason Wang
        qemu_get_subqueue(n->nic, i)->link_down = link_down;
1296 5f800801 Jason Wang
    }
1297 98991481 Amos Kong
1298 fbe78f4f aliguori
    return 0;
1299 fbe78f4f aliguori
}
1300 fbe78f4f aliguori
1301 4e68f7a0 Stefan Hajnoczi
static void virtio_net_cleanup(NetClientState *nc)
1302 b946a153 aliguori
{
1303 cc1f0f45 Jason Wang
    VirtIONet *n = qemu_get_nic_opaque(nc);
1304 b946a153 aliguori
1305 eb6b6c12 Mark McLoughlin
    n->nic = NULL;
1306 b946a153 aliguori
}
1307 b946a153 aliguori
1308 eb6b6c12 Mark McLoughlin
static NetClientInfo net_virtio_info = {
1309 2be64a68 Laszlo Ersek
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
1310 eb6b6c12 Mark McLoughlin
    .size = sizeof(NICState),
1311 eb6b6c12 Mark McLoughlin
    .can_receive = virtio_net_can_receive,
1312 eb6b6c12 Mark McLoughlin
    .receive = virtio_net_receive,
1313 eb6b6c12 Mark McLoughlin
        .cleanup = virtio_net_cleanup,
1314 eb6b6c12 Mark McLoughlin
    .link_status_changed = virtio_net_set_link_status,
1315 eb6b6c12 Mark McLoughlin
};
1316 eb6b6c12 Mark McLoughlin
1317 f56a1247 Michael S. Tsirkin
static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
1318 f56a1247 Michael S. Tsirkin
{
1319 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
1320 fed699f9 Jason Wang
    NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
1321 f56a1247 Michael S. Tsirkin
    assert(n->vhost_started);
1322 b356f76d Jason Wang
    return vhost_net_virtqueue_pending(tap_get_vhost_net(nc->peer), idx);
1323 f56a1247 Michael S. Tsirkin
}
1324 f56a1247 Michael S. Tsirkin
1325 f56a1247 Michael S. Tsirkin
static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
1326 f56a1247 Michael S. Tsirkin
                                           bool mask)
1327 f56a1247 Michael S. Tsirkin
{
1328 17a0ca55 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
1329 fed699f9 Jason Wang
    NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
1330 f56a1247 Michael S. Tsirkin
    assert(n->vhost_started);
1331 b356f76d Jason Wang
    vhost_net_virtqueue_mask(tap_get_vhost_net(nc->peer),
1332 f56a1247 Michael S. Tsirkin
                             vdev, idx, mask);
1333 f56a1247 Michael S. Tsirkin
}
1334 f56a1247 Michael S. Tsirkin
1335 17ec5a86 KONRAD Frederic
void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
1336 fbe78f4f aliguori
{
1337 14f9b664 Jesse Larrew
    int i, config_size = 0;
1338 e9016ee2 Jason Wang
    host_features |= (1 << VIRTIO_NET_F_MAC);
1339 14f9b664 Jesse Larrew
    for (i = 0; feature_sizes[i].flags != 0; i++) {
1340 14f9b664 Jesse Larrew
        if (host_features & feature_sizes[i].flags) {
1341 14f9b664 Jesse Larrew
            config_size = MAX(feature_sizes[i].end, config_size);
1342 14f9b664 Jesse Larrew
        }
1343 14f9b664 Jesse Larrew
    }
1344 17ec5a86 KONRAD Frederic
    n->config_size = config_size;
1345 17ec5a86 KONRAD Frederic
}
1346 17ec5a86 KONRAD Frederic
1347 8a253ec2 KONRAD Frederic
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
1348 8a253ec2 KONRAD Frederic
                                   const char *type)
1349 8a253ec2 KONRAD Frederic
{
1350 8a253ec2 KONRAD Frederic
    /*
1351 8a253ec2 KONRAD Frederic
     * The name can be NULL, the netclient name will be type.x.
1352 8a253ec2 KONRAD Frederic
     */
1353 8a253ec2 KONRAD Frederic
    assert(type != NULL);
1354 8a253ec2 KONRAD Frederic
1355 8a253ec2 KONRAD Frederic
    if (n->netclient_name) {
1356 8a253ec2 KONRAD Frederic
        g_free(n->netclient_name);
1357 8a253ec2 KONRAD Frederic
        n->netclient_name = NULL;
1358 8a253ec2 KONRAD Frederic
    }
1359 8a253ec2 KONRAD Frederic
    if (n->netclient_type) {
1360 8a253ec2 KONRAD Frederic
        g_free(n->netclient_type);
1361 8a253ec2 KONRAD Frederic
        n->netclient_type = NULL;
1362 8a253ec2 KONRAD Frederic
    }
1363 8a253ec2 KONRAD Frederic
1364 8a253ec2 KONRAD Frederic
    if (name != NULL) {
1365 8a253ec2 KONRAD Frederic
        n->netclient_name = g_strdup(name);
1366 8a253ec2 KONRAD Frederic
    }
1367 8a253ec2 KONRAD Frederic
    n->netclient_type = g_strdup(type);
1368 8a253ec2 KONRAD Frederic
}
1369 8a253ec2 KONRAD Frederic
1370 1773d9ee KONRAD Frederic
static int virtio_net_device_init(VirtIODevice *vdev)
1371 17ec5a86 KONRAD Frederic
{
1372 1773d9ee KONRAD Frederic
    int i;
1373 fbe78f4f aliguori
1374 1773d9ee KONRAD Frederic
    DeviceState *qdev = DEVICE(vdev);
1375 1773d9ee KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(vdev);
1376 1773d9ee KONRAD Frederic
1377 1773d9ee KONRAD Frederic
    virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
1378 1773d9ee KONRAD Frederic
                                  n->config_size);
1379 fbe78f4f aliguori
1380 1773d9ee KONRAD Frederic
    n->max_queues = MAX(n->nic_conf.queues, 1);
1381 f6b26cf2 Jason Wang
    n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
1382 17a0ca55 KONRAD Frederic
    n->vqs[0].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
1383 fed699f9 Jason Wang
    n->curr_queues = 1;
1384 fed699f9 Jason Wang
    n->vqs[0].n = n;
1385 1773d9ee KONRAD Frederic
    n->tx_timeout = n->net_conf.txtimer;
1386 a697a334 Alex Williamson
1387 1773d9ee KONRAD Frederic
    if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer")
1388 1773d9ee KONRAD Frederic
                       && strcmp(n->net_conf.tx, "bh")) {
1389 e7b43f7e Stefan Hajnoczi
        error_report("virtio-net: "
1390 e7b43f7e Stefan Hajnoczi
                     "Unknown option tx=%s, valid options: \"timer\" \"bh\"",
1391 1773d9ee KONRAD Frederic
                     n->net_conf.tx);
1392 e7b43f7e Stefan Hajnoczi
        error_report("Defaulting to \"bh\"");
1393 a697a334 Alex Williamson
    }
1394 a697a334 Alex Williamson
1395 1773d9ee KONRAD Frederic
    if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) {
1396 17a0ca55 KONRAD Frederic
        n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
1397 fed699f9 Jason Wang
                                           virtio_net_handle_tx_timer);
1398 fed699f9 Jason Wang
        n->vqs[0].tx_timer = qemu_new_timer_ns(vm_clock, virtio_net_tx_timer,
1399 fed699f9 Jason Wang
                                               &n->vqs[0]);
1400 a697a334 Alex Williamson
    } else {
1401 17a0ca55 KONRAD Frederic
        n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
1402 fed699f9 Jason Wang
                                           virtio_net_handle_tx_bh);
1403 fed699f9 Jason Wang
        n->vqs[0].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[0]);
1404 a697a334 Alex Williamson
    }
1405 17a0ca55 KONRAD Frederic
    n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
1406 1773d9ee KONRAD Frederic
    qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
1407 1773d9ee KONRAD Frederic
    memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
1408 554c97dd aliguori
    n->status = VIRTIO_NET_S_LINK_UP;
1409 fbe78f4f aliguori
1410 8a253ec2 KONRAD Frederic
    if (n->netclient_type) {
1411 8a253ec2 KONRAD Frederic
        /*
1412 8a253ec2 KONRAD Frederic
         * Happen when virtio_net_set_netclient_name has been called.
1413 8a253ec2 KONRAD Frederic
         */
1414 8a253ec2 KONRAD Frederic
        n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
1415 8a253ec2 KONRAD Frederic
                              n->netclient_type, n->netclient_name, n);
1416 8a253ec2 KONRAD Frederic
    } else {
1417 8a253ec2 KONRAD Frederic
        n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
1418 8a253ec2 KONRAD Frederic
                              object_get_typename(OBJECT(qdev)), qdev->id, n);
1419 8a253ec2 KONRAD Frederic
    }
1420 8a253ec2 KONRAD Frederic
1421 6e371ab8 Michael S. Tsirkin
    peer_test_vnet_hdr(n);
1422 6e371ab8 Michael S. Tsirkin
    if (peer_has_vnet_hdr(n)) {
1423 fed699f9 Jason Wang
        for (i = 0; i < n->max_queues; i++) {
1424 fed699f9 Jason Wang
            tap_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true);
1425 fed699f9 Jason Wang
        }
1426 6e371ab8 Michael S. Tsirkin
        n->host_hdr_len = sizeof(struct virtio_net_hdr);
1427 6e371ab8 Michael S. Tsirkin
    } else {
1428 6e371ab8 Michael S. Tsirkin
        n->host_hdr_len = 0;
1429 6e371ab8 Michael S. Tsirkin
    }
1430 eb6b6c12 Mark McLoughlin
1431 1773d9ee KONRAD Frederic
    qemu_format_nic_info_str(qemu_get_queue(n->nic), n->nic_conf.macaddr.a);
1432 96d5e201 aliguori
1433 fed699f9 Jason Wang
    n->vqs[0].tx_waiting = 0;
1434 1773d9ee KONRAD Frederic
    n->tx_burst = n->net_conf.txburst;
1435 ff3a8066 Michael S. Tsirkin
    virtio_net_set_mrg_rx_bufs(n, 0);
1436 002437cd aliguori
    n->promisc = 1; /* for compatibility */
1437 fbe78f4f aliguori
1438 7267c094 Anthony Liguori
    n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
1439 b6503ed9 aliguori
1440 7267c094 Anthony Liguori
    n->vlans = g_malloc0(MAX_VLAN >> 3);
1441 f21c0ed9 aliguori
1442 1773d9ee KONRAD Frederic
    n->qdev = qdev;
1443 1773d9ee KONRAD Frederic
    register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
1444 fbe78f4f aliguori
                    virtio_net_save, virtio_net_load, n);
1445 cf21e106 Paul Brook
1446 1773d9ee KONRAD Frederic
    add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy@0");
1447 17ec5a86 KONRAD Frederic
    return 0;
1448 17ec5a86 KONRAD Frederic
}
1449 17ec5a86 KONRAD Frederic
1450 17ec5a86 KONRAD Frederic
static int virtio_net_device_exit(DeviceState *qdev)
1451 17ec5a86 KONRAD Frederic
{
1452 17ec5a86 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(qdev);
1453 17ec5a86 KONRAD Frederic
    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
1454 17ec5a86 KONRAD Frederic
    int i;
1455 17ec5a86 KONRAD Frederic
1456 17ec5a86 KONRAD Frederic
    /* This will stop vhost backend if appropriate. */
1457 17ec5a86 KONRAD Frederic
    virtio_net_set_status(vdev, 0);
1458 17ec5a86 KONRAD Frederic
1459 17ec5a86 KONRAD Frederic
    unregister_savevm(qdev, "virtio-net", n);
1460 17ec5a86 KONRAD Frederic
1461 8a253ec2 KONRAD Frederic
    if (n->netclient_name) {
1462 8a253ec2 KONRAD Frederic
        g_free(n->netclient_name);
1463 8a253ec2 KONRAD Frederic
        n->netclient_name = NULL;
1464 8a253ec2 KONRAD Frederic
    }
1465 8a253ec2 KONRAD Frederic
    if (n->netclient_type) {
1466 8a253ec2 KONRAD Frederic
        g_free(n->netclient_type);
1467 8a253ec2 KONRAD Frederic
        n->netclient_type = NULL;
1468 8a253ec2 KONRAD Frederic
    }
1469 8a253ec2 KONRAD Frederic
1470 17ec5a86 KONRAD Frederic
    g_free(n->mac_table.macs);
1471 17ec5a86 KONRAD Frederic
    g_free(n->vlans);
1472 17ec5a86 KONRAD Frederic
1473 17ec5a86 KONRAD Frederic
    for (i = 0; i < n->max_queues; i++) {
1474 17ec5a86 KONRAD Frederic
        VirtIONetQueue *q = &n->vqs[i];
1475 17ec5a86 KONRAD Frederic
        NetClientState *nc = qemu_get_subqueue(n->nic, i);
1476 17ec5a86 KONRAD Frederic
1477 17ec5a86 KONRAD Frederic
        qemu_purge_queued_packets(nc);
1478 17ec5a86 KONRAD Frederic
1479 17ec5a86 KONRAD Frederic
        if (q->tx_timer) {
1480 17ec5a86 KONRAD Frederic
            qemu_del_timer(q->tx_timer);
1481 17ec5a86 KONRAD Frederic
            qemu_free_timer(q->tx_timer);
1482 17ec5a86 KONRAD Frederic
        } else {
1483 17ec5a86 KONRAD Frederic
            qemu_bh_delete(q->tx_bh);
1484 17ec5a86 KONRAD Frederic
        }
1485 17ec5a86 KONRAD Frederic
    }
1486 17ec5a86 KONRAD Frederic
1487 17ec5a86 KONRAD Frederic
    g_free(n->vqs);
1488 17ec5a86 KONRAD Frederic
    qemu_del_nic(n->nic);
1489 6a1a8cc7 KONRAD Frederic
    virtio_cleanup(vdev);
1490 17ec5a86 KONRAD Frederic
1491 17ec5a86 KONRAD Frederic
    return 0;
1492 17ec5a86 KONRAD Frederic
}
1493 17ec5a86 KONRAD Frederic
1494 17ec5a86 KONRAD Frederic
static void virtio_net_instance_init(Object *obj)
1495 17ec5a86 KONRAD Frederic
{
1496 17ec5a86 KONRAD Frederic
    VirtIONet *n = VIRTIO_NET(obj);
1497 17ec5a86 KONRAD Frederic
1498 17ec5a86 KONRAD Frederic
    /*
1499 17ec5a86 KONRAD Frederic
     * The default config_size is sizeof(struct virtio_net_config).
1500 17ec5a86 KONRAD Frederic
     * Can be overriden with virtio_net_set_config_size.
1501 17ec5a86 KONRAD Frederic
     */
1502 17ec5a86 KONRAD Frederic
    n->config_size = sizeof(struct virtio_net_config);
1503 17ec5a86 KONRAD Frederic
}
1504 17ec5a86 KONRAD Frederic
1505 17ec5a86 KONRAD Frederic
static Property virtio_net_properties[] = {
1506 17ec5a86 KONRAD Frederic
    DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf),
1507 17ec5a86 KONRAD Frederic
    DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer,
1508 17ec5a86 KONRAD Frederic
                                               TX_TIMER_INTERVAL),
1509 17ec5a86 KONRAD Frederic
    DEFINE_PROP_INT32("x-txburst", VirtIONet, net_conf.txburst, TX_BURST),
1510 17ec5a86 KONRAD Frederic
    DEFINE_PROP_STRING("tx", VirtIONet, net_conf.tx),
1511 17ec5a86 KONRAD Frederic
    DEFINE_PROP_END_OF_LIST(),
1512 17ec5a86 KONRAD Frederic
};
1513 17ec5a86 KONRAD Frederic
1514 17ec5a86 KONRAD Frederic
static void virtio_net_class_init(ObjectClass *klass, void *data)
1515 17ec5a86 KONRAD Frederic
{
1516 17ec5a86 KONRAD Frederic
    DeviceClass *dc = DEVICE_CLASS(klass);
1517 17ec5a86 KONRAD Frederic
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1518 17ec5a86 KONRAD Frederic
    dc->exit = virtio_net_device_exit;
1519 17ec5a86 KONRAD Frederic
    dc->props = virtio_net_properties;
1520 17ec5a86 KONRAD Frederic
    vdc->init = virtio_net_device_init;
1521 17ec5a86 KONRAD Frederic
    vdc->get_config = virtio_net_get_config;
1522 17ec5a86 KONRAD Frederic
    vdc->set_config = virtio_net_set_config;
1523 17ec5a86 KONRAD Frederic
    vdc->get_features = virtio_net_get_features;
1524 17ec5a86 KONRAD Frederic
    vdc->set_features = virtio_net_set_features;
1525 17ec5a86 KONRAD Frederic
    vdc->bad_features = virtio_net_bad_features;
1526 17ec5a86 KONRAD Frederic
    vdc->reset = virtio_net_reset;
1527 17ec5a86 KONRAD Frederic
    vdc->set_status = virtio_net_set_status;
1528 17ec5a86 KONRAD Frederic
    vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
1529 17ec5a86 KONRAD Frederic
    vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
1530 17ec5a86 KONRAD Frederic
}
1531 17ec5a86 KONRAD Frederic
1532 17ec5a86 KONRAD Frederic
static const TypeInfo virtio_net_info = {
1533 17ec5a86 KONRAD Frederic
    .name = TYPE_VIRTIO_NET,
1534 17ec5a86 KONRAD Frederic
    .parent = TYPE_VIRTIO_DEVICE,
1535 17ec5a86 KONRAD Frederic
    .instance_size = sizeof(VirtIONet),
1536 17ec5a86 KONRAD Frederic
    .instance_init = virtio_net_instance_init,
1537 17ec5a86 KONRAD Frederic
    .class_init = virtio_net_class_init,
1538 17ec5a86 KONRAD Frederic
};
1539 17ec5a86 KONRAD Frederic
1540 17ec5a86 KONRAD Frederic
static void virtio_register_types(void)
1541 17ec5a86 KONRAD Frederic
{
1542 17ec5a86 KONRAD Frederic
    type_register_static(&virtio_net_info);
1543 17ec5a86 KONRAD Frederic
}
1544 17ec5a86 KONRAD Frederic
1545 17ec5a86 KONRAD Frederic
type_init(virtio_register_types)