Statistics
| Branch: | Revision:

root / net / net.c @ 0d09e41a

History | View | Annotate | Download (30.1 kB)

1 63a01ef8 aliguori
/*
2 63a01ef8 aliguori
 * QEMU System Emulator
3 63a01ef8 aliguori
 *
4 63a01ef8 aliguori
 * Copyright (c) 2003-2008 Fabrice Bellard
5 63a01ef8 aliguori
 *
6 63a01ef8 aliguori
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 63a01ef8 aliguori
 * of this software and associated documentation files (the "Software"), to deal
8 63a01ef8 aliguori
 * in the Software without restriction, including without limitation the rights
9 63a01ef8 aliguori
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 63a01ef8 aliguori
 * copies of the Software, and to permit persons to whom the Software is
11 63a01ef8 aliguori
 * furnished to do so, subject to the following conditions:
12 63a01ef8 aliguori
 *
13 63a01ef8 aliguori
 * The above copyright notice and this permission notice shall be included in
14 63a01ef8 aliguori
 * all copies or substantial portions of the Software.
15 63a01ef8 aliguori
 *
16 63a01ef8 aliguori
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 63a01ef8 aliguori
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 63a01ef8 aliguori
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 63a01ef8 aliguori
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 63a01ef8 aliguori
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 63a01ef8 aliguori
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 63a01ef8 aliguori
 * THE SOFTWARE.
23 63a01ef8 aliguori
 */
24 d40cdb10 blueswir1
#include "config-host.h"
25 d40cdb10 blueswir1
26 1422e32d Paolo Bonzini
#include "net/net.h"
27 fd9400b3 Paolo Bonzini
#include "clients.h"
28 fd9400b3 Paolo Bonzini
#include "hub.h"
29 1422e32d Paolo Bonzini
#include "net/slirp.h"
30 fd9400b3 Paolo Bonzini
#include "util.h"
31 a245fc18 Paolo Bonzini
32 83c9089e Paolo Bonzini
#include "monitor/monitor.h"
33 1df49e04 Mark McLoughlin
#include "qemu-common.h"
34 1de7afc9 Paolo Bonzini
#include "qemu/sockets.h"
35 1de7afc9 Paolo Bonzini
#include "qemu/config-file.h"
36 4b37156c Luiz Capitulino
#include "qmp-commands.h"
37 75422b0d Amit Shah
#include "hw/qdev.h"
38 1de7afc9 Paolo Bonzini
#include "qemu/iov.h"
39 6687b79d Laszlo Ersek
#include "qapi-visit.h"
40 6687b79d Laszlo Ersek
#include "qapi/opts-visitor.h"
41 7b1b5d19 Paolo Bonzini
#include "qapi/dealloc-visitor.h"
42 511d2b14 blueswir1
43 2944e4ec Stefan Weil
/* Net bridge is currently not supported for W32. */
44 2944e4ec Stefan Weil
#if !defined(_WIN32)
45 2944e4ec Stefan Weil
# define CONFIG_NET_BRIDGE
46 2944e4ec Stefan Weil
#endif
47 2944e4ec Stefan Weil
48 4e68f7a0 Stefan Hajnoczi
static QTAILQ_HEAD(, NetClientState) net_clients;
49 63a01ef8 aliguori
50 cb4522cc Gerd Hoffmann
int default_net = 1;
51 cb4522cc Gerd Hoffmann
52 63a01ef8 aliguori
/***********************************************************/
53 63a01ef8 aliguori
/* network device redirectors */
54 63a01ef8 aliguori
55 68ac40d2 Mark McLoughlin
#if defined(DEBUG_NET)
56 63a01ef8 aliguori
static void hex_dump(FILE *f, const uint8_t *buf, int size)
57 63a01ef8 aliguori
{
58 63a01ef8 aliguori
    int len, i, j, c;
59 63a01ef8 aliguori
60 63a01ef8 aliguori
    for(i=0;i<size;i+=16) {
61 63a01ef8 aliguori
        len = size - i;
62 63a01ef8 aliguori
        if (len > 16)
63 63a01ef8 aliguori
            len = 16;
64 63a01ef8 aliguori
        fprintf(f, "%08x ", i);
65 63a01ef8 aliguori
        for(j=0;j<16;j++) {
66 63a01ef8 aliguori
            if (j < len)
67 63a01ef8 aliguori
                fprintf(f, " %02x", buf[i+j]);
68 63a01ef8 aliguori
            else
69 63a01ef8 aliguori
                fprintf(f, "   ");
70 63a01ef8 aliguori
        }
71 63a01ef8 aliguori
        fprintf(f, " ");
72 63a01ef8 aliguori
        for(j=0;j<len;j++) {
73 63a01ef8 aliguori
            c = buf[i+j];
74 63a01ef8 aliguori
            if (c < ' ' || c > '~')
75 63a01ef8 aliguori
                c = '.';
76 63a01ef8 aliguori
            fprintf(f, "%c", c);
77 63a01ef8 aliguori
        }
78 63a01ef8 aliguori
        fprintf(f, "\n");
79 63a01ef8 aliguori
    }
80 63a01ef8 aliguori
}
81 63a01ef8 aliguori
#endif
82 63a01ef8 aliguori
83 63a01ef8 aliguori
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
84 63a01ef8 aliguori
{
85 63a01ef8 aliguori
    const char *p, *p1;
86 63a01ef8 aliguori
    int len;
87 63a01ef8 aliguori
    p = *pp;
88 63a01ef8 aliguori
    p1 = strchr(p, sep);
89 63a01ef8 aliguori
    if (!p1)
90 63a01ef8 aliguori
        return -1;
91 63a01ef8 aliguori
    len = p1 - p;
92 63a01ef8 aliguori
    p1++;
93 63a01ef8 aliguori
    if (buf_size > 0) {
94 63a01ef8 aliguori
        if (len > buf_size - 1)
95 63a01ef8 aliguori
            len = buf_size - 1;
96 63a01ef8 aliguori
        memcpy(buf, p, len);
97 63a01ef8 aliguori
        buf[len] = '\0';
98 63a01ef8 aliguori
    }
99 63a01ef8 aliguori
    *pp = p1;
100 63a01ef8 aliguori
    return 0;
101 63a01ef8 aliguori
}
102 63a01ef8 aliguori
103 63a01ef8 aliguori
int parse_host_port(struct sockaddr_in *saddr, const char *str)
104 63a01ef8 aliguori
{
105 63a01ef8 aliguori
    char buf[512];
106 63a01ef8 aliguori
    struct hostent *he;
107 63a01ef8 aliguori
    const char *p, *r;
108 63a01ef8 aliguori
    int port;
109 63a01ef8 aliguori
110 63a01ef8 aliguori
    p = str;
111 63a01ef8 aliguori
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
112 63a01ef8 aliguori
        return -1;
113 63a01ef8 aliguori
    saddr->sin_family = AF_INET;
114 63a01ef8 aliguori
    if (buf[0] == '\0') {
115 63a01ef8 aliguori
        saddr->sin_addr.s_addr = 0;
116 63a01ef8 aliguori
    } else {
117 cd390083 blueswir1
        if (qemu_isdigit(buf[0])) {
118 63a01ef8 aliguori
            if (!inet_aton(buf, &saddr->sin_addr))
119 63a01ef8 aliguori
                return -1;
120 63a01ef8 aliguori
        } else {
121 63a01ef8 aliguori
            if ((he = gethostbyname(buf)) == NULL)
122 63a01ef8 aliguori
                return - 1;
123 63a01ef8 aliguori
            saddr->sin_addr = *(struct in_addr *)he->h_addr;
124 63a01ef8 aliguori
        }
125 63a01ef8 aliguori
    }
126 63a01ef8 aliguori
    port = strtol(p, (char **)&r, 0);
127 63a01ef8 aliguori
    if (r == p)
128 63a01ef8 aliguori
        return -1;
129 63a01ef8 aliguori
    saddr->sin_port = htons(port);
130 63a01ef8 aliguori
    return 0;
131 63a01ef8 aliguori
}
132 63a01ef8 aliguori
133 35277d14 Stefan Hajnoczi
void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
134 7cb7434b aliguori
{
135 35277d14 Stefan Hajnoczi
    snprintf(nc->info_str, sizeof(nc->info_str),
136 4dda4063 aliguori
             "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
137 35277d14 Stefan Hajnoczi
             nc->model,
138 7cb7434b aliguori
             macaddr[0], macaddr[1], macaddr[2],
139 7cb7434b aliguori
             macaddr[3], macaddr[4], macaddr[5]);
140 7cb7434b aliguori
}
141 7cb7434b aliguori
142 76d32cba Gerd Hoffmann
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
143 76d32cba Gerd Hoffmann
{
144 76d32cba Gerd Hoffmann
    static int index = 0;
145 76d32cba Gerd Hoffmann
    static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };
146 76d32cba Gerd Hoffmann
147 76d32cba Gerd Hoffmann
    if (memcmp(macaddr, &zero, sizeof(zero)) != 0)
148 76d32cba Gerd Hoffmann
        return;
149 76d32cba Gerd Hoffmann
    macaddr->a[0] = 0x52;
150 76d32cba Gerd Hoffmann
    macaddr->a[1] = 0x54;
151 76d32cba Gerd Hoffmann
    macaddr->a[2] = 0x00;
152 76d32cba Gerd Hoffmann
    macaddr->a[3] = 0x12;
153 76d32cba Gerd Hoffmann
    macaddr->a[4] = 0x34;
154 76d32cba Gerd Hoffmann
    macaddr->a[5] = 0x56 + index++;
155 76d32cba Gerd Hoffmann
}
156 76d32cba Gerd Hoffmann
157 d33d93b2 Stefan Hajnoczi
/**
158 d33d93b2 Stefan Hajnoczi
 * Generate a name for net client
159 d33d93b2 Stefan Hajnoczi
 *
160 d33d93b2 Stefan Hajnoczi
 * Only net clients created with the legacy -net option need this.  Naming is
161 d33d93b2 Stefan Hajnoczi
 * mandatory for net clients created with -netdev.
162 d33d93b2 Stefan Hajnoczi
 */
163 35277d14 Stefan Hajnoczi
static char *assign_name(NetClientState *nc1, const char *model)
164 676cff29 aliguori
{
165 35277d14 Stefan Hajnoczi
    NetClientState *nc;
166 676cff29 aliguori
    char buf[256];
167 676cff29 aliguori
    int id = 0;
168 676cff29 aliguori
169 35277d14 Stefan Hajnoczi
    QTAILQ_FOREACH(nc, &net_clients, next) {
170 35277d14 Stefan Hajnoczi
        if (nc == nc1) {
171 d33d93b2 Stefan Hajnoczi
            continue;
172 5610c3aa Mark McLoughlin
        }
173 d33d93b2 Stefan Hajnoczi
        /* For compatibility only bump id for net clients on a vlan */
174 35277d14 Stefan Hajnoczi
        if (strcmp(nc->model, model) == 0 &&
175 35277d14 Stefan Hajnoczi
            net_hub_id_for_client(nc, NULL) == 0) {
176 53e51d85 Markus Armbruster
            id++;
177 53e51d85 Markus Armbruster
        }
178 53e51d85 Markus Armbruster
    }
179 53e51d85 Markus Armbruster
180 676cff29 aliguori
    snprintf(buf, sizeof(buf), "%s.%d", model, id);
181 676cff29 aliguori
182 7267c094 Anthony Liguori
    return g_strdup(buf);
183 676cff29 aliguori
}
184 676cff29 aliguori
185 f7860455 Jason Wang
static void qemu_net_client_destructor(NetClientState *nc)
186 f7860455 Jason Wang
{
187 f7860455 Jason Wang
    g_free(nc);
188 f7860455 Jason Wang
}
189 f7860455 Jason Wang
190 18a1541a Jason Wang
static void qemu_net_client_setup(NetClientState *nc,
191 18a1541a Jason Wang
                                  NetClientInfo *info,
192 18a1541a Jason Wang
                                  NetClientState *peer,
193 18a1541a Jason Wang
                                  const char *model,
194 f7860455 Jason Wang
                                  const char *name,
195 f7860455 Jason Wang
                                  NetClientDestructor *destructor)
196 63a01ef8 aliguori
{
197 35277d14 Stefan Hajnoczi
    nc->info = info;
198 35277d14 Stefan Hajnoczi
    nc->model = g_strdup(model);
199 45460d1a Mark McLoughlin
    if (name) {
200 35277d14 Stefan Hajnoczi
        nc->name = g_strdup(name);
201 45460d1a Mark McLoughlin
    } else {
202 35277d14 Stefan Hajnoczi
        nc->name = assign_name(nc, model);
203 45460d1a Mark McLoughlin
    }
204 5610c3aa Mark McLoughlin
205 ab5f3f84 Stefan Hajnoczi
    if (peer) {
206 ab5f3f84 Stefan Hajnoczi
        assert(!peer->peer);
207 35277d14 Stefan Hajnoczi
        nc->peer = peer;
208 35277d14 Stefan Hajnoczi
        peer->peer = nc;
209 d80b9fc6 Mark McLoughlin
    }
210 35277d14 Stefan Hajnoczi
    QTAILQ_INSERT_TAIL(&net_clients, nc, next);
211 63a01ef8 aliguori
212 86a77c38 Zhi Yong Wu
    nc->send_queue = qemu_new_net_queue(nc);
213 f7860455 Jason Wang
    nc->destructor = destructor;
214 18a1541a Jason Wang
}
215 18a1541a Jason Wang
216 18a1541a Jason Wang
NetClientState *qemu_new_net_client(NetClientInfo *info,
217 18a1541a Jason Wang
                                    NetClientState *peer,
218 18a1541a Jason Wang
                                    const char *model,
219 18a1541a Jason Wang
                                    const char *name)
220 18a1541a Jason Wang
{
221 18a1541a Jason Wang
    NetClientState *nc;
222 18a1541a Jason Wang
223 18a1541a Jason Wang
    assert(info->size >= sizeof(NetClientState));
224 18a1541a Jason Wang
225 18a1541a Jason Wang
    nc = g_malloc0(info->size);
226 f7860455 Jason Wang
    qemu_net_client_setup(nc, info, peer, model, name,
227 f7860455 Jason Wang
                          qemu_net_client_destructor);
228 18a1541a Jason Wang
229 35277d14 Stefan Hajnoczi
    return nc;
230 63a01ef8 aliguori
}
231 63a01ef8 aliguori
232 ebef2c09 Mark McLoughlin
NICState *qemu_new_nic(NetClientInfo *info,
233 ebef2c09 Mark McLoughlin
                       NICConf *conf,
234 ebef2c09 Mark McLoughlin
                       const char *model,
235 ebef2c09 Mark McLoughlin
                       const char *name,
236 ebef2c09 Mark McLoughlin
                       void *opaque)
237 ebef2c09 Mark McLoughlin
{
238 1ceef9f2 Jason Wang
    NetClientState **peers = conf->peers.ncs;
239 ebef2c09 Mark McLoughlin
    NICState *nic;
240 f6b26cf2 Jason Wang
    int i, queues = MAX(1, conf->queues);
241 ebef2c09 Mark McLoughlin
242 2be64a68 Laszlo Ersek
    assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
243 ebef2c09 Mark McLoughlin
    assert(info->size >= sizeof(NICState));
244 ebef2c09 Mark McLoughlin
245 f6b26cf2 Jason Wang
    nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
246 f6b26cf2 Jason Wang
    nic->ncs = (void *)nic + info->size;
247 ebef2c09 Mark McLoughlin
    nic->conf = conf;
248 ebef2c09 Mark McLoughlin
    nic->opaque = opaque;
249 ebef2c09 Mark McLoughlin
250 f6b26cf2 Jason Wang
    for (i = 0; i < queues; i++) {
251 f6b26cf2 Jason Wang
        qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
252 1ceef9f2 Jason Wang
                              NULL);
253 1ceef9f2 Jason Wang
        nic->ncs[i].queue_index = i;
254 1ceef9f2 Jason Wang
    }
255 1ceef9f2 Jason Wang
256 ebef2c09 Mark McLoughlin
    return nic;
257 ebef2c09 Mark McLoughlin
}
258 ebef2c09 Mark McLoughlin
259 1ceef9f2 Jason Wang
NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
260 1ceef9f2 Jason Wang
{
261 f6b26cf2 Jason Wang
    return nic->ncs + queue_index;
262 1ceef9f2 Jason Wang
}
263 1ceef9f2 Jason Wang
264 b356f76d Jason Wang
NetClientState *qemu_get_queue(NICState *nic)
265 b356f76d Jason Wang
{
266 1ceef9f2 Jason Wang
    return qemu_get_subqueue(nic, 0);
267 b356f76d Jason Wang
}
268 b356f76d Jason Wang
269 cc1f0f45 Jason Wang
NICState *qemu_get_nic(NetClientState *nc)
270 cc1f0f45 Jason Wang
{
271 1ceef9f2 Jason Wang
    NetClientState *nc0 = nc - nc->queue_index;
272 1ceef9f2 Jason Wang
273 f6b26cf2 Jason Wang
    return (NICState *)((void *)nc0 - nc->info->size);
274 cc1f0f45 Jason Wang
}
275 cc1f0f45 Jason Wang
276 cc1f0f45 Jason Wang
void *qemu_get_nic_opaque(NetClientState *nc)
277 cc1f0f45 Jason Wang
{
278 cc1f0f45 Jason Wang
    NICState *nic = qemu_get_nic(nc);
279 cc1f0f45 Jason Wang
280 cc1f0f45 Jason Wang
    return nic->opaque;
281 cc1f0f45 Jason Wang
}
282 cc1f0f45 Jason Wang
283 b20c6b9e Stefan Hajnoczi
static void qemu_cleanup_net_client(NetClientState *nc)
284 63a01ef8 aliguori
{
285 35277d14 Stefan Hajnoczi
    QTAILQ_REMOVE(&net_clients, nc, next);
286 63a01ef8 aliguori
287 cc2a9043 Andreas Fรคrber
    if (nc->info->cleanup) {
288 cc2a9043 Andreas Fรคrber
        nc->info->cleanup(nc);
289 cc2a9043 Andreas Fรคrber
    }
290 a083a89d Michael S. Tsirkin
}
291 5610c3aa Mark McLoughlin
292 b20c6b9e Stefan Hajnoczi
static void qemu_free_net_client(NetClientState *nc)
293 a083a89d Michael S. Tsirkin
{
294 35277d14 Stefan Hajnoczi
    if (nc->send_queue) {
295 35277d14 Stefan Hajnoczi
        qemu_del_net_queue(nc->send_queue);
296 a005d073 Stefan Hajnoczi
    }
297 35277d14 Stefan Hajnoczi
    if (nc->peer) {
298 35277d14 Stefan Hajnoczi
        nc->peer->peer = NULL;
299 a083a89d Michael S. Tsirkin
    }
300 35277d14 Stefan Hajnoczi
    g_free(nc->name);
301 35277d14 Stefan Hajnoczi
    g_free(nc->model);
302 f7860455 Jason Wang
    if (nc->destructor) {
303 f7860455 Jason Wang
        nc->destructor(nc);
304 f7860455 Jason Wang
    }
305 63a01ef8 aliguori
}
306 63a01ef8 aliguori
307 b20c6b9e Stefan Hajnoczi
void qemu_del_net_client(NetClientState *nc)
308 a083a89d Michael S. Tsirkin
{
309 1ceef9f2 Jason Wang
    NetClientState *ncs[MAX_QUEUE_NUM];
310 1ceef9f2 Jason Wang
    int queues, i;
311 1ceef9f2 Jason Wang
312 1ceef9f2 Jason Wang
    /* If the NetClientState belongs to a multiqueue backend, we will change all
313 1ceef9f2 Jason Wang
     * other NetClientStates also.
314 1ceef9f2 Jason Wang
     */
315 1ceef9f2 Jason Wang
    queues = qemu_find_net_clients_except(nc->name, ncs,
316 1ceef9f2 Jason Wang
                                          NET_CLIENT_OPTIONS_KIND_NIC,
317 1ceef9f2 Jason Wang
                                          MAX_QUEUE_NUM);
318 1ceef9f2 Jason Wang
    assert(queues != 0);
319 1ceef9f2 Jason Wang
320 a083a89d Michael S. Tsirkin
    /* If there is a peer NIC, delete and cleanup client, but do not free. */
321 35277d14 Stefan Hajnoczi
    if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
322 cc1f0f45 Jason Wang
        NICState *nic = qemu_get_nic(nc->peer);
323 a083a89d Michael S. Tsirkin
        if (nic->peer_deleted) {
324 a083a89d Michael S. Tsirkin
            return;
325 a083a89d Michael S. Tsirkin
        }
326 a083a89d Michael S. Tsirkin
        nic->peer_deleted = true;
327 1ceef9f2 Jason Wang
328 1ceef9f2 Jason Wang
        for (i = 0; i < queues; i++) {
329 1ceef9f2 Jason Wang
            ncs[i]->peer->link_down = true;
330 1ceef9f2 Jason Wang
        }
331 1ceef9f2 Jason Wang
332 35277d14 Stefan Hajnoczi
        if (nc->peer->info->link_status_changed) {
333 35277d14 Stefan Hajnoczi
            nc->peer->info->link_status_changed(nc->peer);
334 a083a89d Michael S. Tsirkin
        }
335 1ceef9f2 Jason Wang
336 1ceef9f2 Jason Wang
        for (i = 0; i < queues; i++) {
337 1ceef9f2 Jason Wang
            qemu_cleanup_net_client(ncs[i]);
338 1ceef9f2 Jason Wang
        }
339 1ceef9f2 Jason Wang
340 a083a89d Michael S. Tsirkin
        return;
341 a083a89d Michael S. Tsirkin
    }
342 a083a89d Michael S. Tsirkin
343 948ecf21 Jason Wang
    assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
344 948ecf21 Jason Wang
345 1ceef9f2 Jason Wang
    for (i = 0; i < queues; i++) {
346 1ceef9f2 Jason Wang
        qemu_cleanup_net_client(ncs[i]);
347 1ceef9f2 Jason Wang
        qemu_free_net_client(ncs[i]);
348 1ceef9f2 Jason Wang
    }
349 948ecf21 Jason Wang
}
350 948ecf21 Jason Wang
351 948ecf21 Jason Wang
void qemu_del_nic(NICState *nic)
352 948ecf21 Jason Wang
{
353 b8904921 Michael Roth
    int i, queues = MAX(nic->conf->queues, 1);
354 1ceef9f2 Jason Wang
355 a083a89d Michael S. Tsirkin
    /* If this is a peer NIC and peer has already been deleted, free it now. */
356 1ceef9f2 Jason Wang
    if (nic->peer_deleted) {
357 1ceef9f2 Jason Wang
        for (i = 0; i < queues; i++) {
358 1ceef9f2 Jason Wang
            qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);
359 1a609520 Jan Kiszka
        }
360 1a609520 Jan Kiszka
    }
361 1a609520 Jan Kiszka
362 1ceef9f2 Jason Wang
    for (i = queues - 1; i >= 0; i--) {
363 1ceef9f2 Jason Wang
        NetClientState *nc = qemu_get_subqueue(nic, i);
364 1ceef9f2 Jason Wang
365 1ceef9f2 Jason Wang
        qemu_cleanup_net_client(nc);
366 1ceef9f2 Jason Wang
        qemu_free_net_client(nc);
367 1ceef9f2 Jason Wang
    }
368 f6b26cf2 Jason Wang
369 f6b26cf2 Jason Wang
    g_free(nic);
370 1a609520 Jan Kiszka
}
371 1a609520 Jan Kiszka
372 57f9ef17 Mark McLoughlin
void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
373 57f9ef17 Mark McLoughlin
{
374 4e68f7a0 Stefan Hajnoczi
    NetClientState *nc;
375 57f9ef17 Mark McLoughlin
376 94878994 Stefan Hajnoczi
    QTAILQ_FOREACH(nc, &net_clients, next) {
377 2be64a68 Laszlo Ersek
        if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
378 1ceef9f2 Jason Wang
            if (nc->queue_index == 0) {
379 1ceef9f2 Jason Wang
                func(qemu_get_nic(nc), opaque);
380 1ceef9f2 Jason Wang
            }
381 57f9ef17 Mark McLoughlin
        }
382 57f9ef17 Mark McLoughlin
    }
383 57f9ef17 Mark McLoughlin
}
384 57f9ef17 Mark McLoughlin
385 4e68f7a0 Stefan Hajnoczi
int qemu_can_send_packet(NetClientState *sender)
386 63a01ef8 aliguori
{
387 a005d073 Stefan Hajnoczi
    if (!sender->peer) {
388 d80b9fc6 Mark McLoughlin
        return 1;
389 d80b9fc6 Mark McLoughlin
    }
390 d80b9fc6 Mark McLoughlin
391 a005d073 Stefan Hajnoczi
    if (sender->peer->receive_disabled) {
392 a005d073 Stefan Hajnoczi
        return 0;
393 a005d073 Stefan Hajnoczi
    } else if (sender->peer->info->can_receive &&
394 a005d073 Stefan Hajnoczi
               !sender->peer->info->can_receive(sender->peer)) {
395 a005d073 Stefan Hajnoczi
        return 0;
396 63a01ef8 aliguori
    }
397 60c07d93 Vincent Palatin
    return 1;
398 63a01ef8 aliguori
}
399 63a01ef8 aliguori
400 86a77c38 Zhi Yong Wu
ssize_t qemu_deliver_packet(NetClientState *sender,
401 86a77c38 Zhi Yong Wu
                            unsigned flags,
402 86a77c38 Zhi Yong Wu
                            const uint8_t *data,
403 86a77c38 Zhi Yong Wu
                            size_t size,
404 86a77c38 Zhi Yong Wu
                            void *opaque)
405 9a6ecb30 Mark McLoughlin
{
406 35277d14 Stefan Hajnoczi
    NetClientState *nc = opaque;
407 893379ef Mark McLoughlin
    ssize_t ret;
408 9a6ecb30 Mark McLoughlin
409 35277d14 Stefan Hajnoczi
    if (nc->link_down) {
410 9a6ecb30 Mark McLoughlin
        return size;
411 9a6ecb30 Mark McLoughlin
    }
412 9a6ecb30 Mark McLoughlin
413 35277d14 Stefan Hajnoczi
    if (nc->receive_disabled) {
414 893379ef Mark McLoughlin
        return 0;
415 893379ef Mark McLoughlin
    }
416 893379ef Mark McLoughlin
417 35277d14 Stefan Hajnoczi
    if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
418 35277d14 Stefan Hajnoczi
        ret = nc->info->receive_raw(nc, data, size);
419 893379ef Mark McLoughlin
    } else {
420 35277d14 Stefan Hajnoczi
        ret = nc->info->receive(nc, data, size);
421 893379ef Mark McLoughlin
    }
422 893379ef Mark McLoughlin
423 893379ef Mark McLoughlin
    if (ret == 0) {
424 35277d14 Stefan Hajnoczi
        nc->receive_disabled = 1;
425 893379ef Mark McLoughlin
    };
426 893379ef Mark McLoughlin
427 893379ef Mark McLoughlin
    return ret;
428 9a6ecb30 Mark McLoughlin
}
429 9a6ecb30 Mark McLoughlin
430 35277d14 Stefan Hajnoczi
void qemu_purge_queued_packets(NetClientState *nc)
431 8cad5516 Mark McLoughlin
{
432 35277d14 Stefan Hajnoczi
    if (!nc->peer) {
433 d80b9fc6 Mark McLoughlin
        return;
434 9a6ecb30 Mark McLoughlin
    }
435 d80b9fc6 Mark McLoughlin
436 35277d14 Stefan Hajnoczi
    qemu_net_queue_purge(nc->peer->send_queue, nc);
437 8cad5516 Mark McLoughlin
}
438 8cad5516 Mark McLoughlin
439 35277d14 Stefan Hajnoczi
void qemu_flush_queued_packets(NetClientState *nc)
440 e94667b9 Mark McLoughlin
{
441 35277d14 Stefan Hajnoczi
    nc->receive_disabled = 0;
442 9a6ecb30 Mark McLoughlin
443 199ee608 Luigi Rizzo
    if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
444 199ee608 Luigi Rizzo
        if (net_hub_flush(nc->peer)) {
445 199ee608 Luigi Rizzo
            qemu_notify_event();
446 199ee608 Luigi Rizzo
        }
447 199ee608 Luigi Rizzo
        return;
448 199ee608 Luigi Rizzo
    }
449 987a9b48 Paolo Bonzini
    if (qemu_net_queue_flush(nc->send_queue)) {
450 987a9b48 Paolo Bonzini
        /* We emptied the queue successfully, signal to the IO thread to repoll
451 987a9b48 Paolo Bonzini
         * the file descriptor (for tap, for example).
452 987a9b48 Paolo Bonzini
         */
453 987a9b48 Paolo Bonzini
        qemu_notify_event();
454 987a9b48 Paolo Bonzini
    }
455 e94667b9 Mark McLoughlin
}
456 e94667b9 Mark McLoughlin
457 4e68f7a0 Stefan Hajnoczi
static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
458 ca77d175 Mark McLoughlin
                                                 unsigned flags,
459 ca77d175 Mark McLoughlin
                                                 const uint8_t *buf, int size,
460 ca77d175 Mark McLoughlin
                                                 NetPacketSent *sent_cb)
461 764a4d1d aliguori
{
462 9a6ecb30 Mark McLoughlin
    NetQueue *queue;
463 436e5e53 aliguori
464 63a01ef8 aliguori
#ifdef DEBUG_NET
465 d80b9fc6 Mark McLoughlin
    printf("qemu_send_packet_async:\n");
466 63a01ef8 aliguori
    hex_dump(stdout, buf, size);
467 63a01ef8 aliguori
#endif
468 f3b6c7fc Mark McLoughlin
469 a005d073 Stefan Hajnoczi
    if (sender->link_down || !sender->peer) {
470 9a6ecb30 Mark McLoughlin
        return size;
471 9a6ecb30 Mark McLoughlin
    }
472 9a6ecb30 Mark McLoughlin
473 a005d073 Stefan Hajnoczi
    queue = sender->peer->send_queue;
474 9a6ecb30 Mark McLoughlin
475 ca77d175 Mark McLoughlin
    return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
476 ca77d175 Mark McLoughlin
}
477 ca77d175 Mark McLoughlin
478 4e68f7a0 Stefan Hajnoczi
ssize_t qemu_send_packet_async(NetClientState *sender,
479 ca77d175 Mark McLoughlin
                               const uint8_t *buf, int size,
480 ca77d175 Mark McLoughlin
                               NetPacketSent *sent_cb)
481 ca77d175 Mark McLoughlin
{
482 ca77d175 Mark McLoughlin
    return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
483 ca77d175 Mark McLoughlin
                                             buf, size, sent_cb);
484 f3b6c7fc Mark McLoughlin
}
485 f3b6c7fc Mark McLoughlin
486 35277d14 Stefan Hajnoczi
void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
487 f3b6c7fc Mark McLoughlin
{
488 35277d14 Stefan Hajnoczi
    qemu_send_packet_async(nc, buf, size, NULL);
489 63a01ef8 aliguori
}
490 63a01ef8 aliguori
491 35277d14 Stefan Hajnoczi
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
492 ca77d175 Mark McLoughlin
{
493 35277d14 Stefan Hajnoczi
    return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
494 ca77d175 Mark McLoughlin
                                             buf, size, NULL);
495 ca77d175 Mark McLoughlin
}
496 ca77d175 Mark McLoughlin
497 35277d14 Stefan Hajnoczi
static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
498 fbe78f4f aliguori
                               int iovcnt)
499 fbe78f4f aliguori
{
500 d32fcad3 Scott Feldman
    uint8_t buffer[NET_BUFSIZE];
501 ce053661 Benjamin Poirier
    size_t offset;
502 fbe78f4f aliguori
503 dcf6f5e1 Michael Tokarev
    offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
504 fbe78f4f aliguori
505 35277d14 Stefan Hajnoczi
    return nc->info->receive(nc, buffer, offset);
506 fbe78f4f aliguori
}
507 fbe78f4f aliguori
508 86a77c38 Zhi Yong Wu
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
509 86a77c38 Zhi Yong Wu
                                unsigned flags,
510 86a77c38 Zhi Yong Wu
                                const struct iovec *iov,
511 86a77c38 Zhi Yong Wu
                                int iovcnt,
512 86a77c38 Zhi Yong Wu
                                void *opaque)
513 9a6ecb30 Mark McLoughlin
{
514 35277d14 Stefan Hajnoczi
    NetClientState *nc = opaque;
515 c67f5dc1 Stefan Hajnoczi
    int ret;
516 9a6ecb30 Mark McLoughlin
517 35277d14 Stefan Hajnoczi
    if (nc->link_down) {
518 ce053661 Benjamin Poirier
        return iov_size(iov, iovcnt);
519 9a6ecb30 Mark McLoughlin
    }
520 9a6ecb30 Mark McLoughlin
521 c67f5dc1 Stefan Hajnoczi
    if (nc->receive_disabled) {
522 c67f5dc1 Stefan Hajnoczi
        return 0;
523 c67f5dc1 Stefan Hajnoczi
    }
524 c67f5dc1 Stefan Hajnoczi
525 35277d14 Stefan Hajnoczi
    if (nc->info->receive_iov) {
526 c67f5dc1 Stefan Hajnoczi
        ret = nc->info->receive_iov(nc, iov, iovcnt);
527 9a6ecb30 Mark McLoughlin
    } else {
528 c67f5dc1 Stefan Hajnoczi
        ret = nc_sendv_compat(nc, iov, iovcnt);
529 c67f5dc1 Stefan Hajnoczi
    }
530 c67f5dc1 Stefan Hajnoczi
531 c67f5dc1 Stefan Hajnoczi
    if (ret == 0) {
532 c67f5dc1 Stefan Hajnoczi
        nc->receive_disabled = 1;
533 e94667b9 Mark McLoughlin
    }
534 c67f5dc1 Stefan Hajnoczi
535 c67f5dc1 Stefan Hajnoczi
    return ret;
536 e94667b9 Mark McLoughlin
}
537 e94667b9 Mark McLoughlin
538 4e68f7a0 Stefan Hajnoczi
ssize_t qemu_sendv_packet_async(NetClientState *sender,
539 f3b6c7fc Mark McLoughlin
                                const struct iovec *iov, int iovcnt,
540 f3b6c7fc Mark McLoughlin
                                NetPacketSent *sent_cb)
541 e94667b9 Mark McLoughlin
{
542 9a6ecb30 Mark McLoughlin
    NetQueue *queue;
543 9a6ecb30 Mark McLoughlin
544 a005d073 Stefan Hajnoczi
    if (sender->link_down || !sender->peer) {
545 ce053661 Benjamin Poirier
        return iov_size(iov, iovcnt);
546 e94667b9 Mark McLoughlin
    }
547 e94667b9 Mark McLoughlin
548 a005d073 Stefan Hajnoczi
    queue = sender->peer->send_queue;
549 9a6ecb30 Mark McLoughlin
550 c0b8e49c Mark McLoughlin
    return qemu_net_queue_send_iov(queue, sender,
551 c0b8e49c Mark McLoughlin
                                   QEMU_NET_PACKET_FLAG_NONE,
552 c0b8e49c Mark McLoughlin
                                   iov, iovcnt, sent_cb);
553 fbe78f4f aliguori
}
554 fbe78f4f aliguori
555 f3b6c7fc Mark McLoughlin
ssize_t
556 35277d14 Stefan Hajnoczi
qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
557 f3b6c7fc Mark McLoughlin
{
558 35277d14 Stefan Hajnoczi
    return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
559 63a01ef8 aliguori
}
560 63a01ef8 aliguori
561 4e68f7a0 Stefan Hajnoczi
NetClientState *qemu_find_netdev(const char *id)
562 5869c4d5 Mark McLoughlin
{
563 35277d14 Stefan Hajnoczi
    NetClientState *nc;
564 5869c4d5 Mark McLoughlin
565 35277d14 Stefan Hajnoczi
    QTAILQ_FOREACH(nc, &net_clients, next) {
566 35277d14 Stefan Hajnoczi
        if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC)
567 85dde9a9 Markus Armbruster
            continue;
568 35277d14 Stefan Hajnoczi
        if (!strcmp(nc->name, id)) {
569 35277d14 Stefan Hajnoczi
            return nc;
570 5869c4d5 Mark McLoughlin
        }
571 5869c4d5 Mark McLoughlin
    }
572 5869c4d5 Mark McLoughlin
573 5869c4d5 Mark McLoughlin
    return NULL;
574 5869c4d5 Mark McLoughlin
}
575 5869c4d5 Mark McLoughlin
576 6c51ae73 Jason Wang
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
577 6c51ae73 Jason Wang
                                 NetClientOptionsKind type, int max)
578 6c51ae73 Jason Wang
{
579 6c51ae73 Jason Wang
    NetClientState *nc;
580 6c51ae73 Jason Wang
    int ret = 0;
581 6c51ae73 Jason Wang
582 6c51ae73 Jason Wang
    QTAILQ_FOREACH(nc, &net_clients, next) {
583 6c51ae73 Jason Wang
        if (nc->info->type == type) {
584 6c51ae73 Jason Wang
            continue;
585 6c51ae73 Jason Wang
        }
586 6c51ae73 Jason Wang
        if (!strcmp(nc->name, id)) {
587 6c51ae73 Jason Wang
            if (ret < max) {
588 6c51ae73 Jason Wang
                ncs[ret] = nc;
589 6c51ae73 Jason Wang
            }
590 6c51ae73 Jason Wang
            ret++;
591 6c51ae73 Jason Wang
        }
592 6c51ae73 Jason Wang
    }
593 6c51ae73 Jason Wang
594 6c51ae73 Jason Wang
    return ret;
595 6c51ae73 Jason Wang
}
596 6c51ae73 Jason Wang
597 7697079b aliguori
static int nic_get_free_idx(void)
598 7697079b aliguori
{
599 7697079b aliguori
    int index;
600 7697079b aliguori
601 7697079b aliguori
    for (index = 0; index < MAX_NICS; index++)
602 7697079b aliguori
        if (!nd_table[index].used)
603 7697079b aliguori
            return index;
604 7697079b aliguori
    return -1;
605 7697079b aliguori
}
606 7697079b aliguori
607 07caea31 Markus Armbruster
int qemu_show_nic_models(const char *arg, const char *const *models)
608 07caea31 Markus Armbruster
{
609 07caea31 Markus Armbruster
    int i;
610 07caea31 Markus Armbruster
611 c8057f95 Peter Maydell
    if (!arg || !is_help_option(arg)) {
612 07caea31 Markus Armbruster
        return 0;
613 c8057f95 Peter Maydell
    }
614 07caea31 Markus Armbruster
615 07caea31 Markus Armbruster
    fprintf(stderr, "qemu: Supported NIC models: ");
616 07caea31 Markus Armbruster
    for (i = 0 ; models[i]; i++)
617 07caea31 Markus Armbruster
        fprintf(stderr, "%s%c", models[i], models[i+1] ? ',' : '\n');
618 07caea31 Markus Armbruster
    return 1;
619 07caea31 Markus Armbruster
}
620 07caea31 Markus Armbruster
621 d07f22c5 aliguori
void qemu_check_nic_model(NICInfo *nd, const char *model)
622 d07f22c5 aliguori
{
623 d07f22c5 aliguori
    const char *models[2];
624 d07f22c5 aliguori
625 d07f22c5 aliguori
    models[0] = model;
626 d07f22c5 aliguori
    models[1] = NULL;
627 d07f22c5 aliguori
628 07caea31 Markus Armbruster
    if (qemu_show_nic_models(nd->model, models))
629 07caea31 Markus Armbruster
        exit(0);
630 07caea31 Markus Armbruster
    if (qemu_find_nic_model(nd, models, model) < 0)
631 07caea31 Markus Armbruster
        exit(1);
632 d07f22c5 aliguori
}
633 d07f22c5 aliguori
634 07caea31 Markus Armbruster
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
635 07caea31 Markus Armbruster
                        const char *default_model)
636 d07f22c5 aliguori
{
637 07caea31 Markus Armbruster
    int i;
638 d07f22c5 aliguori
639 d07f22c5 aliguori
    if (!nd->model)
640 7267c094 Anthony Liguori
        nd->model = g_strdup(default_model);
641 d07f22c5 aliguori
642 07caea31 Markus Armbruster
    for (i = 0 ; models[i]; i++) {
643 07caea31 Markus Armbruster
        if (strcmp(nd->model, models[i]) == 0)
644 07caea31 Markus Armbruster
            return i;
645 d07f22c5 aliguori
    }
646 d07f22c5 aliguori
647 6daf194d Markus Armbruster
    error_report("Unsupported NIC model: %s", nd->model);
648 07caea31 Markus Armbruster
    return -1;
649 d07f22c5 aliguori
}
650 d07f22c5 aliguori
651 1a0c0958 Laszlo Ersek
static int net_init_nic(const NetClientOptions *opts, const char *name,
652 4e68f7a0 Stefan Hajnoczi
                        NetClientState *peer)
653 f83c6e10 Mark McLoughlin
{
654 f83c6e10 Mark McLoughlin
    int idx;
655 f83c6e10 Mark McLoughlin
    NICInfo *nd;
656 2456f36f Laszlo Ersek
    const NetLegacyNicOptions *nic;
657 2456f36f Laszlo Ersek
658 2456f36f Laszlo Ersek
    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_NIC);
659 2456f36f Laszlo Ersek
    nic = opts->nic;
660 f83c6e10 Mark McLoughlin
661 f83c6e10 Mark McLoughlin
    idx = nic_get_free_idx();
662 f83c6e10 Mark McLoughlin
    if (idx == -1 || nb_nics >= MAX_NICS) {
663 1ecda02b Markus Armbruster
        error_report("Too Many NICs");
664 f83c6e10 Mark McLoughlin
        return -1;
665 f83c6e10 Mark McLoughlin
    }
666 f83c6e10 Mark McLoughlin
667 f83c6e10 Mark McLoughlin
    nd = &nd_table[idx];
668 f83c6e10 Mark McLoughlin
669 f83c6e10 Mark McLoughlin
    memset(nd, 0, sizeof(*nd));
670 f83c6e10 Mark McLoughlin
671 2456f36f Laszlo Ersek
    if (nic->has_netdev) {
672 2456f36f Laszlo Ersek
        nd->netdev = qemu_find_netdev(nic->netdev);
673 5869c4d5 Mark McLoughlin
        if (!nd->netdev) {
674 2456f36f Laszlo Ersek
            error_report("netdev '%s' not found", nic->netdev);
675 5869c4d5 Mark McLoughlin
            return -1;
676 5869c4d5 Mark McLoughlin
        }
677 5869c4d5 Mark McLoughlin
    } else {
678 d33d93b2 Stefan Hajnoczi
        assert(peer);
679 d33d93b2 Stefan Hajnoczi
        nd->netdev = peer;
680 5869c4d5 Mark McLoughlin
    }
681 c64f50d1 Markus Armbruster
    nd->name = g_strdup(name);
682 2456f36f Laszlo Ersek
    if (nic->has_model) {
683 2456f36f Laszlo Ersek
        nd->model = g_strdup(nic->model);
684 f83c6e10 Mark McLoughlin
    }
685 2456f36f Laszlo Ersek
    if (nic->has_addr) {
686 2456f36f Laszlo Ersek
        nd->devaddr = g_strdup(nic->addr);
687 f83c6e10 Mark McLoughlin
    }
688 f83c6e10 Mark McLoughlin
689 2456f36f Laszlo Ersek
    if (nic->has_macaddr &&
690 2456f36f Laszlo Ersek
        net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
691 1ecda02b Markus Armbruster
        error_report("invalid syntax for ethernet address");
692 f83c6e10 Mark McLoughlin
        return -1;
693 f83c6e10 Mark McLoughlin
    }
694 6eed1856 Jan Kiszka
    qemu_macaddr_default_if_unset(&nd->macaddr);
695 f83c6e10 Mark McLoughlin
696 2456f36f Laszlo Ersek
    if (nic->has_vectors) {
697 2456f36f Laszlo Ersek
        if (nic->vectors > 0x7ffffff) {
698 2456f36f Laszlo Ersek
            error_report("invalid # of vectors: %"PRIu32, nic->vectors);
699 2456f36f Laszlo Ersek
            return -1;
700 2456f36f Laszlo Ersek
        }
701 2456f36f Laszlo Ersek
        nd->nvectors = nic->vectors;
702 2456f36f Laszlo Ersek
    } else {
703 2456f36f Laszlo Ersek
        nd->nvectors = DEV_NVECTORS_UNSPECIFIED;
704 f83c6e10 Mark McLoughlin
    }
705 f83c6e10 Mark McLoughlin
706 f83c6e10 Mark McLoughlin
    nd->used = 1;
707 f83c6e10 Mark McLoughlin
    nb_nics++;
708 f83c6e10 Mark McLoughlin
709 f83c6e10 Mark McLoughlin
    return idx;
710 f83c6e10 Mark McLoughlin
}
711 f83c6e10 Mark McLoughlin
712 6687b79d Laszlo Ersek
713 6687b79d Laszlo Ersek
static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
714 1a0c0958 Laszlo Ersek
    const NetClientOptions *opts,
715 6687b79d Laszlo Ersek
    const char *name,
716 4e68f7a0 Stefan Hajnoczi
    NetClientState *peer) = {
717 f6c874e3 Stefan Hajnoczi
        [NET_CLIENT_OPTIONS_KIND_NIC]       = net_init_nic,
718 ec302ffd Mark McLoughlin
#ifdef CONFIG_SLIRP
719 f6c874e3 Stefan Hajnoczi
        [NET_CLIENT_OPTIONS_KIND_USER]      = net_init_slirp,
720 2944e4ec Stefan Weil
#endif
721 f6c874e3 Stefan Hajnoczi
        [NET_CLIENT_OPTIONS_KIND_TAP]       = net_init_tap,
722 f6c874e3 Stefan Hajnoczi
        [NET_CLIENT_OPTIONS_KIND_SOCKET]    = net_init_socket,
723 dd51058d Mark McLoughlin
#ifdef CONFIG_VDE
724 f6c874e3 Stefan Hajnoczi
        [NET_CLIENT_OPTIONS_KIND_VDE]       = net_init_vde,
725 dd51058d Mark McLoughlin
#endif
726 f6c874e3 Stefan Hajnoczi
        [NET_CLIENT_OPTIONS_KIND_DUMP]      = net_init_dump,
727 2944e4ec Stefan Weil
#ifdef CONFIG_NET_BRIDGE
728 f6c874e3 Stefan Hajnoczi
        [NET_CLIENT_OPTIONS_KIND_BRIDGE]    = net_init_bridge,
729 6687b79d Laszlo Ersek
#endif
730 f6c874e3 Stefan Hajnoczi
        [NET_CLIENT_OPTIONS_KIND_HUBPORT]   = net_init_hubport,
731 f83c6e10 Mark McLoughlin
};
732 f83c6e10 Mark McLoughlin
733 6687b79d Laszlo Ersek
734 1a0c0958 Laszlo Ersek
static int net_client_init1(const void *object, int is_netdev, Error **errp)
735 f83c6e10 Mark McLoughlin
{
736 6687b79d Laszlo Ersek
    union {
737 6687b79d Laszlo Ersek
        const Netdev    *netdev;
738 6687b79d Laszlo Ersek
        const NetLegacy *net;
739 6687b79d Laszlo Ersek
    } u;
740 6687b79d Laszlo Ersek
    const NetClientOptions *opts;
741 6d952ebe Mark McLoughlin
    const char *name;
742 f83c6e10 Mark McLoughlin
743 5294e2c7 Markus Armbruster
    if (is_netdev) {
744 6687b79d Laszlo Ersek
        u.netdev = object;
745 6687b79d Laszlo Ersek
        opts = u.netdev->opts;
746 6687b79d Laszlo Ersek
        name = u.netdev->id;
747 6687b79d Laszlo Ersek
748 6687b79d Laszlo Ersek
        switch (opts->kind) {
749 f6b134ac Mark McLoughlin
#ifdef CONFIG_SLIRP
750 6687b79d Laszlo Ersek
        case NET_CLIENT_OPTIONS_KIND_USER:
751 f6b134ac Mark McLoughlin
#endif
752 6687b79d Laszlo Ersek
        case NET_CLIENT_OPTIONS_KIND_TAP:
753 6687b79d Laszlo Ersek
        case NET_CLIENT_OPTIONS_KIND_SOCKET:
754 f6b134ac Mark McLoughlin
#ifdef CONFIG_VDE
755 6687b79d Laszlo Ersek
        case NET_CLIENT_OPTIONS_KIND_VDE:
756 6687b79d Laszlo Ersek
#endif
757 6687b79d Laszlo Ersek
#ifdef CONFIG_NET_BRIDGE
758 6687b79d Laszlo Ersek
        case NET_CLIENT_OPTIONS_KIND_BRIDGE:
759 f6b134ac Mark McLoughlin
#endif
760 f6c874e3 Stefan Hajnoczi
        case NET_CLIENT_OPTIONS_KIND_HUBPORT:
761 6687b79d Laszlo Ersek
            break;
762 6687b79d Laszlo Ersek
763 6687b79d Laszlo Ersek
        default:
764 4559a1db Luiz Capitulino
            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
765 4559a1db Luiz Capitulino
                      "a netdev backend type");
766 f6b134ac Mark McLoughlin
            return -1;
767 f6b134ac Mark McLoughlin
        }
768 6687b79d Laszlo Ersek
    } else {
769 6687b79d Laszlo Ersek
        u.net = object;
770 6687b79d Laszlo Ersek
        opts = u.net->opts;
771 6687b79d Laszlo Ersek
        /* missing optional values have been initialized to "all bits zero" */
772 6687b79d Laszlo Ersek
        name = u.net->has_id ? u.net->id : u.net->name;
773 6687b79d Laszlo Ersek
    }
774 f6b134ac Mark McLoughlin
775 6687b79d Laszlo Ersek
    if (net_client_init_fun[opts->kind]) {
776 4e68f7a0 Stefan Hajnoczi
        NetClientState *peer = NULL;
777 6687b79d Laszlo Ersek
778 6687b79d Laszlo Ersek
        /* Do not add to a vlan if it's a -netdev or a nic with a netdev=
779 6687b79d Laszlo Ersek
         * parameter. */
780 6687b79d Laszlo Ersek
        if (!is_netdev &&
781 6687b79d Laszlo Ersek
            (opts->kind != NET_CLIENT_OPTIONS_KIND_NIC ||
782 6687b79d Laszlo Ersek
             !opts->nic->has_netdev)) {
783 d33d93b2 Stefan Hajnoczi
            peer = net_hub_add_port(u.net->has_vlan ? u.net->vlan : 0, NULL);
784 f6b134ac Mark McLoughlin
        }
785 6687b79d Laszlo Ersek
786 d33d93b2 Stefan Hajnoczi
        if (net_client_init_fun[opts->kind](opts, name, peer) < 0) {
787 6687b79d Laszlo Ersek
            /* TODO push error reporting into init() methods */
788 6687b79d Laszlo Ersek
            error_set(errp, QERR_DEVICE_INIT_FAILED,
789 6687b79d Laszlo Ersek
                      NetClientOptionsKind_lookup[opts->kind]);
790 f6b134ac Mark McLoughlin
            return -1;
791 f6b134ac Mark McLoughlin
        }
792 f6b134ac Mark McLoughlin
    }
793 6687b79d Laszlo Ersek
    return 0;
794 6687b79d Laszlo Ersek
}
795 6687b79d Laszlo Ersek
796 f6b134ac Mark McLoughlin
797 6687b79d Laszlo Ersek
static void net_visit(Visitor *v, int is_netdev, void **object, Error **errp)
798 6687b79d Laszlo Ersek
{
799 6687b79d Laszlo Ersek
    if (is_netdev) {
800 6687b79d Laszlo Ersek
        visit_type_Netdev(v, (Netdev **)object, NULL, errp);
801 6687b79d Laszlo Ersek
    } else {
802 6687b79d Laszlo Ersek
        visit_type_NetLegacy(v, (NetLegacy **)object, NULL, errp);
803 6d952ebe Mark McLoughlin
    }
804 6687b79d Laszlo Ersek
}
805 6d952ebe Mark McLoughlin
806 f6b134ac Mark McLoughlin
807 6687b79d Laszlo Ersek
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
808 6687b79d Laszlo Ersek
{
809 6687b79d Laszlo Ersek
    void *object = NULL;
810 6687b79d Laszlo Ersek
    Error *err = NULL;
811 6687b79d Laszlo Ersek
    int ret = -1;
812 f83c6e10 Mark McLoughlin
813 6687b79d Laszlo Ersek
    {
814 6687b79d Laszlo Ersek
        OptsVisitor *ov = opts_visitor_new(opts);
815 f6b134ac Mark McLoughlin
816 6687b79d Laszlo Ersek
        net_visit(opts_get_visitor(ov), is_netdev, &object, &err);
817 6687b79d Laszlo Ersek
        opts_visitor_cleanup(ov);
818 f83c6e10 Mark McLoughlin
    }
819 f83c6e10 Mark McLoughlin
820 6687b79d Laszlo Ersek
    if (!err) {
821 1a0c0958 Laszlo Ersek
        ret = net_client_init1(object, is_netdev, &err);
822 6687b79d Laszlo Ersek
    }
823 6687b79d Laszlo Ersek
824 6687b79d Laszlo Ersek
    if (object) {
825 6687b79d Laszlo Ersek
        QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();
826 6687b79d Laszlo Ersek
827 6687b79d Laszlo Ersek
        net_visit(qapi_dealloc_get_visitor(dv), is_netdev, &object, NULL);
828 6687b79d Laszlo Ersek
        qapi_dealloc_visitor_cleanup(dv);
829 6687b79d Laszlo Ersek
    }
830 6687b79d Laszlo Ersek
831 6687b79d Laszlo Ersek
    error_propagate(errp, err);
832 6687b79d Laszlo Ersek
    return ret;
833 f83c6e10 Mark McLoughlin
}
834 f83c6e10 Mark McLoughlin
835 6687b79d Laszlo Ersek
836 6f338c34 aliguori
static int net_host_check_device(const char *device)
837 6f338c34 aliguori
{
838 6f338c34 aliguori
    int i;
839 bb9ea79e aliguori
    const char *valid_param_list[] = { "tap", "socket", "dump"
840 2944e4ec Stefan Weil
#ifdef CONFIG_NET_BRIDGE
841 2944e4ec Stefan Weil
                                       , "bridge"
842 2944e4ec Stefan Weil
#endif
843 6f338c34 aliguori
#ifdef CONFIG_SLIRP
844 6f338c34 aliguori
                                       ,"user"
845 6f338c34 aliguori
#endif
846 6f338c34 aliguori
#ifdef CONFIG_VDE
847 6f338c34 aliguori
                                       ,"vde"
848 6f338c34 aliguori
#endif
849 6f338c34 aliguori
    };
850 6f338c34 aliguori
    for (i = 0; i < sizeof(valid_param_list) / sizeof(char *); i++) {
851 6f338c34 aliguori
        if (!strncmp(valid_param_list[i], device,
852 6f338c34 aliguori
                     strlen(valid_param_list[i])))
853 6f338c34 aliguori
            return 1;
854 6f338c34 aliguori
    }
855 6f338c34 aliguori
856 6f338c34 aliguori
    return 0;
857 6f338c34 aliguori
}
858 6f338c34 aliguori
859 f18c16de Luiz Capitulino
void net_host_device_add(Monitor *mon, const QDict *qdict)
860 6f338c34 aliguori
{
861 f18c16de Luiz Capitulino
    const char *device = qdict_get_str(qdict, "device");
862 7f1c9d20 Mark McLoughlin
    const char *opts_str = qdict_get_try_str(qdict, "opts");
863 4559a1db Luiz Capitulino
    Error *local_err = NULL;
864 7f1c9d20 Mark McLoughlin
    QemuOpts *opts;
865 f18c16de Luiz Capitulino
866 6f338c34 aliguori
    if (!net_host_check_device(device)) {
867 376253ec aliguori
        monitor_printf(mon, "invalid host network device %s\n", device);
868 6f338c34 aliguori
        return;
869 6f338c34 aliguori
    }
870 7f1c9d20 Mark McLoughlin
871 3329f07b Gerd Hoffmann
    opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0);
872 7f1c9d20 Mark McLoughlin
    if (!opts) {
873 7f1c9d20 Mark McLoughlin
        return;
874 7f1c9d20 Mark McLoughlin
    }
875 7f1c9d20 Mark McLoughlin
876 7f1c9d20 Mark McLoughlin
    qemu_opt_set(opts, "type", device);
877 7f1c9d20 Mark McLoughlin
878 4559a1db Luiz Capitulino
    net_client_init(opts, 0, &local_err);
879 4559a1db Luiz Capitulino
    if (error_is_set(&local_err)) {
880 4559a1db Luiz Capitulino
        qerror_report_err(local_err);
881 4559a1db Luiz Capitulino
        error_free(local_err);
882 5c8be678 aliguori
        monitor_printf(mon, "adding host network device %s failed\n", device);
883 5c8be678 aliguori
    }
884 6f338c34 aliguori
}
885 6f338c34 aliguori
886 f18c16de Luiz Capitulino
void net_host_device_remove(Monitor *mon, const QDict *qdict)
887 6f338c34 aliguori
{
888 35277d14 Stefan Hajnoczi
    NetClientState *nc;
889 f18c16de Luiz Capitulino
    int vlan_id = qdict_get_int(qdict, "vlan_id");
890 f18c16de Luiz Capitulino
    const char *device = qdict_get_str(qdict, "device");
891 6f338c34 aliguori
892 35277d14 Stefan Hajnoczi
    nc = net_hub_find_client_by_name(vlan_id, device);
893 35277d14 Stefan Hajnoczi
    if (!nc) {
894 6f338c34 aliguori
        return;
895 6f338c34 aliguori
    }
896 35277d14 Stefan Hajnoczi
    if (!net_host_check_device(nc->model)) {
897 e8f1f9db aliguori
        monitor_printf(mon, "invalid host network device %s\n", device);
898 e8f1f9db aliguori
        return;
899 e8f1f9db aliguori
    }
900 b20c6b9e Stefan Hajnoczi
    qemu_del_net_client(nc);
901 6f338c34 aliguori
}
902 6f338c34 aliguori
903 928059a3 Luiz Capitulino
void netdev_add(QemuOpts *opts, Error **errp)
904 928059a3 Luiz Capitulino
{
905 928059a3 Luiz Capitulino
    net_client_init(opts, 1, errp);
906 928059a3 Luiz Capitulino
}
907 928059a3 Luiz Capitulino
908 928059a3 Luiz Capitulino
int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret)
909 ae82d324 Markus Armbruster
{
910 4e89978e Luiz Capitulino
    Error *local_err = NULL;
911 928059a3 Luiz Capitulino
    QemuOptsList *opts_list;
912 ae82d324 Markus Armbruster
    QemuOpts *opts;
913 ae82d324 Markus Armbruster
914 928059a3 Luiz Capitulino
    opts_list = qemu_find_opts_err("netdev", &local_err);
915 928059a3 Luiz Capitulino
    if (error_is_set(&local_err)) {
916 928059a3 Luiz Capitulino
        goto exit_err;
917 ae82d324 Markus Armbruster
    }
918 ae82d324 Markus Armbruster
919 928059a3 Luiz Capitulino
    opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
920 928059a3 Luiz Capitulino
    if (error_is_set(&local_err)) {
921 928059a3 Luiz Capitulino
        goto exit_err;
922 928059a3 Luiz Capitulino
    }
923 928059a3 Luiz Capitulino
924 928059a3 Luiz Capitulino
    netdev_add(opts, &local_err);
925 928059a3 Luiz Capitulino
    if (error_is_set(&local_err)) {
926 410cbafe Yoshiaki Tamura
        qemu_opts_del(opts);
927 928059a3 Luiz Capitulino
        goto exit_err;
928 410cbafe Yoshiaki Tamura
    }
929 410cbafe Yoshiaki Tamura
930 928059a3 Luiz Capitulino
    return 0;
931 928059a3 Luiz Capitulino
932 928059a3 Luiz Capitulino
exit_err:
933 928059a3 Luiz Capitulino
    qerror_report_err(local_err);
934 928059a3 Luiz Capitulino
    error_free(local_err);
935 928059a3 Luiz Capitulino
    return -1;
936 ae82d324 Markus Armbruster
}
937 ae82d324 Markus Armbruster
938 5f964155 Luiz Capitulino
void qmp_netdev_del(const char *id, Error **errp)
939 ae82d324 Markus Armbruster
{
940 35277d14 Stefan Hajnoczi
    NetClientState *nc;
941 645c9496 Stefan Hajnoczi
    QemuOpts *opts;
942 ae82d324 Markus Armbruster
943 35277d14 Stefan Hajnoczi
    nc = qemu_find_netdev(id);
944 35277d14 Stefan Hajnoczi
    if (!nc) {
945 5f964155 Luiz Capitulino
        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
946 5f964155 Luiz Capitulino
        return;
947 ae82d324 Markus Armbruster
    }
948 5f964155 Luiz Capitulino
949 645c9496 Stefan Hajnoczi
    opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), id);
950 645c9496 Stefan Hajnoczi
    if (!opts) {
951 645c9496 Stefan Hajnoczi
        error_setg(errp, "Device '%s' is not a netdev", id);
952 645c9496 Stefan Hajnoczi
        return;
953 645c9496 Stefan Hajnoczi
    }
954 645c9496 Stefan Hajnoczi
955 b20c6b9e Stefan Hajnoczi
    qemu_del_net_client(nc);
956 645c9496 Stefan Hajnoczi
    qemu_opts_del(opts);
957 ae82d324 Markus Armbruster
}
958 ae82d324 Markus Armbruster
959 1a859593 Zhi Yong Wu
void print_net_client(Monitor *mon, NetClientState *nc)
960 44e798d3 Jan Kiszka
{
961 1ceef9f2 Jason Wang
    monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
962 1ceef9f2 Jason Wang
                   nc->queue_index,
963 1ceef9f2 Jason Wang
                   NetClientOptionsKind_lookup[nc->info->type],
964 1ceef9f2 Jason Wang
                   nc->info_str);
965 44e798d3 Jan Kiszka
}
966 44e798d3 Jan Kiszka
967 84f2d0ea Wenchao Xia
void do_info_network(Monitor *mon, const QDict *qdict)
968 63a01ef8 aliguori
{
969 35277d14 Stefan Hajnoczi
    NetClientState *nc, *peer;
970 2be64a68 Laszlo Ersek
    NetClientOptionsKind type;
971 63a01ef8 aliguori
972 1a859593 Zhi Yong Wu
    net_hub_info(mon);
973 1a859593 Zhi Yong Wu
974 35277d14 Stefan Hajnoczi
    QTAILQ_FOREACH(nc, &net_clients, next) {
975 35277d14 Stefan Hajnoczi
        peer = nc->peer;
976 35277d14 Stefan Hajnoczi
        type = nc->info->type;
977 5610c3aa Mark McLoughlin
978 1a859593 Zhi Yong Wu
        /* Skip if already printed in hub info */
979 1a859593 Zhi Yong Wu
        if (net_hub_id_for_client(nc, NULL) == 0) {
980 1a859593 Zhi Yong Wu
            continue;
981 5610c3aa Mark McLoughlin
        }
982 1a859593 Zhi Yong Wu
983 2be64a68 Laszlo Ersek
        if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) {
984 35277d14 Stefan Hajnoczi
            print_net_client(mon, nc);
985 19061e63 Jan Kiszka
        } /* else it's a netdev connected to a NIC, printed with the NIC */
986 2be64a68 Laszlo Ersek
        if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) {
987 1a859593 Zhi Yong Wu
            monitor_printf(mon, " \\ ");
988 44e798d3 Jan Kiszka
            print_net_client(mon, peer);
989 a0104e0e Markus Armbruster
        }
990 a0104e0e Markus Armbruster
    }
991 63a01ef8 aliguori
}
992 63a01ef8 aliguori
993 4b37156c Luiz Capitulino
void qmp_set_link(const char *name, bool up, Error **errp)
994 436e5e53 aliguori
{
995 1ceef9f2 Jason Wang
    NetClientState *ncs[MAX_QUEUE_NUM];
996 1ceef9f2 Jason Wang
    NetClientState *nc;
997 1ceef9f2 Jason Wang
    int queues, i;
998 436e5e53 aliguori
999 1ceef9f2 Jason Wang
    queues = qemu_find_net_clients_except(name, ncs,
1000 1ceef9f2 Jason Wang
                                          NET_CLIENT_OPTIONS_KIND_MAX,
1001 1ceef9f2 Jason Wang
                                          MAX_QUEUE_NUM);
1002 1ceef9f2 Jason Wang
1003 1ceef9f2 Jason Wang
    if (queues == 0) {
1004 4b37156c Luiz Capitulino
        error_set(errp, QERR_DEVICE_NOT_FOUND, name);
1005 4b37156c Luiz Capitulino
        return;
1006 436e5e53 aliguori
    }
1007 1ceef9f2 Jason Wang
    nc = ncs[0];
1008 436e5e53 aliguori
1009 1ceef9f2 Jason Wang
    for (i = 0; i < queues; i++) {
1010 1ceef9f2 Jason Wang
        ncs[i]->link_down = !up;
1011 1ceef9f2 Jason Wang
    }
1012 436e5e53 aliguori
1013 35277d14 Stefan Hajnoczi
    if (nc->info->link_status_changed) {
1014 35277d14 Stefan Hajnoczi
        nc->info->link_status_changed(nc);
1015 665a3b07 Mark McLoughlin
    }
1016 ab1cbe1c Michael S. Tsirkin
1017 ab1cbe1c Michael S. Tsirkin
    /* Notify peer. Don't update peer link status: this makes it possible to
1018 ab1cbe1c Michael S. Tsirkin
     * disconnect from host network without notifying the guest.
1019 ab1cbe1c Michael S. Tsirkin
     * FIXME: is disconnected link status change operation useful?
1020 ab1cbe1c Michael S. Tsirkin
     *
1021 ab1cbe1c Michael S. Tsirkin
     * Current behaviour is compatible with qemu vlans where there could be
1022 ab1cbe1c Michael S. Tsirkin
     * multiple clients that can still communicate with each other in
1023 ab1cbe1c Michael S. Tsirkin
     * disconnected mode. For now maintain this compatibility. */
1024 35277d14 Stefan Hajnoczi
    if (nc->peer && nc->peer->info->link_status_changed) {
1025 35277d14 Stefan Hajnoczi
        nc->peer->info->link_status_changed(nc->peer);
1026 ab1cbe1c Michael S. Tsirkin
    }
1027 436e5e53 aliguori
}
1028 436e5e53 aliguori
1029 63a01ef8 aliguori
void net_cleanup(void)
1030 63a01ef8 aliguori
{
1031 1ceef9f2 Jason Wang
    NetClientState *nc;
1032 577c4af9 Mark McLoughlin
1033 1ceef9f2 Jason Wang
    /* We may del multiple entries during qemu_del_net_client(),
1034 1ceef9f2 Jason Wang
     * so QTAILQ_FOREACH_SAFE() is also not safe here.
1035 1ceef9f2 Jason Wang
     */
1036 1ceef9f2 Jason Wang
    while (!QTAILQ_EMPTY(&net_clients)) {
1037 1ceef9f2 Jason Wang
        nc = QTAILQ_FIRST(&net_clients);
1038 948ecf21 Jason Wang
        if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
1039 948ecf21 Jason Wang
            qemu_del_nic(qemu_get_nic(nc));
1040 948ecf21 Jason Wang
        } else {
1041 948ecf21 Jason Wang
            qemu_del_net_client(nc);
1042 948ecf21 Jason Wang
        }
1043 577c4af9 Mark McLoughlin
    }
1044 63a01ef8 aliguori
}
1045 63a01ef8 aliguori
1046 668680f7 Markus Armbruster
void net_check_clients(void)
1047 63a01ef8 aliguori
{
1048 35277d14 Stefan Hajnoczi
    NetClientState *nc;
1049 48e2faf2 Peter Maydell
    int i;
1050 63a01ef8 aliguori
1051 641f6eae Peter Maydell
    /* Don't warn about the default network setup that you get if
1052 641f6eae Peter Maydell
     * no command line -net or -netdev options are specified. There
1053 641f6eae Peter Maydell
     * are two cases that we would otherwise complain about:
1054 641f6eae Peter Maydell
     * (1) board doesn't support a NIC but the implicit "-net nic"
1055 641f6eae Peter Maydell
     * requested one
1056 641f6eae Peter Maydell
     * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic"
1057 641f6eae Peter Maydell
     * sets up a nic that isn't connected to anything.
1058 641f6eae Peter Maydell
     */
1059 641f6eae Peter Maydell
    if (default_net) {
1060 641f6eae Peter Maydell
        return;
1061 641f6eae Peter Maydell
    }
1062 641f6eae Peter Maydell
1063 81017645 Stefan Hajnoczi
    net_hub_check_clients();
1064 ac60cc18 Tristan Gingold
1065 35277d14 Stefan Hajnoczi
    QTAILQ_FOREACH(nc, &net_clients, next) {
1066 35277d14 Stefan Hajnoczi
        if (!nc->peer) {
1067 efe32fdd Markus Armbruster
            fprintf(stderr, "Warning: %s %s has no peer\n",
1068 35277d14 Stefan Hajnoczi
                    nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ?
1069 35277d14 Stefan Hajnoczi
                    "nic" : "netdev", nc->name);
1070 efe32fdd Markus Armbruster
        }
1071 efe32fdd Markus Armbruster
    }
1072 48e2faf2 Peter Maydell
1073 48e2faf2 Peter Maydell
    /* Check that all NICs requested via -net nic actually got created.
1074 48e2faf2 Peter Maydell
     * NICs created via -device don't need to be checked here because
1075 48e2faf2 Peter Maydell
     * they are always instantiated.
1076 48e2faf2 Peter Maydell
     */
1077 48e2faf2 Peter Maydell
    for (i = 0; i < MAX_NICS; i++) {
1078 48e2faf2 Peter Maydell
        NICInfo *nd = &nd_table[i];
1079 48e2faf2 Peter Maydell
        if (nd->used && !nd->instantiated) {
1080 48e2faf2 Peter Maydell
            fprintf(stderr, "Warning: requested NIC (%s, model %s) "
1081 48e2faf2 Peter Maydell
                    "was not created (not supported by this machine?)\n",
1082 48e2faf2 Peter Maydell
                    nd->name ? nd->name : "anonymous",
1083 48e2faf2 Peter Maydell
                    nd->model ? nd->model : "unspecified");
1084 48e2faf2 Peter Maydell
        }
1085 48e2faf2 Peter Maydell
    }
1086 63a01ef8 aliguori
}
1087 dc1c9fe8 Mark McLoughlin
1088 dc1c9fe8 Mark McLoughlin
static int net_init_client(QemuOpts *opts, void *dummy)
1089 dc1c9fe8 Mark McLoughlin
{
1090 4559a1db Luiz Capitulino
    Error *local_err = NULL;
1091 4559a1db Luiz Capitulino
1092 4559a1db Luiz Capitulino
    net_client_init(opts, 0, &local_err);
1093 4559a1db Luiz Capitulino
    if (error_is_set(&local_err)) {
1094 4559a1db Luiz Capitulino
        qerror_report_err(local_err);
1095 4559a1db Luiz Capitulino
        error_free(local_err);
1096 c1671a08 Mark McLoughlin
        return -1;
1097 4559a1db Luiz Capitulino
    }
1098 4559a1db Luiz Capitulino
1099 c1671a08 Mark McLoughlin
    return 0;
1100 f6b134ac Mark McLoughlin
}
1101 f6b134ac Mark McLoughlin
1102 f6b134ac Mark McLoughlin
static int net_init_netdev(QemuOpts *opts, void *dummy)
1103 f6b134ac Mark McLoughlin
{
1104 4559a1db Luiz Capitulino
    Error *local_err = NULL;
1105 4559a1db Luiz Capitulino
    int ret;
1106 4559a1db Luiz Capitulino
1107 4559a1db Luiz Capitulino
    ret = net_client_init(opts, 1, &local_err);
1108 4559a1db Luiz Capitulino
    if (error_is_set(&local_err)) {
1109 4559a1db Luiz Capitulino
        qerror_report_err(local_err);
1110 4559a1db Luiz Capitulino
        error_free(local_err);
1111 4559a1db Luiz Capitulino
        return -1;
1112 4559a1db Luiz Capitulino
    }
1113 4559a1db Luiz Capitulino
1114 4559a1db Luiz Capitulino
    return ret;
1115 dc1c9fe8 Mark McLoughlin
}
1116 dc1c9fe8 Mark McLoughlin
1117 dc1c9fe8 Mark McLoughlin
int net_init_clients(void)
1118 dc1c9fe8 Mark McLoughlin
{
1119 3329f07b Gerd Hoffmann
    QemuOptsList *net = qemu_find_opts("net");
1120 3329f07b Gerd Hoffmann
1121 cb4522cc Gerd Hoffmann
    if (default_net) {
1122 dc1c9fe8 Mark McLoughlin
        /* if no clients, we use a default config */
1123 3329f07b Gerd Hoffmann
        qemu_opts_set(net, NULL, "type", "nic");
1124 dc1c9fe8 Mark McLoughlin
#ifdef CONFIG_SLIRP
1125 3329f07b Gerd Hoffmann
        qemu_opts_set(net, NULL, "type", "user");
1126 dc1c9fe8 Mark McLoughlin
#endif
1127 dc1c9fe8 Mark McLoughlin
    }
1128 dc1c9fe8 Mark McLoughlin
1129 94878994 Stefan Hajnoczi
    QTAILQ_INIT(&net_clients);
1130 5610c3aa Mark McLoughlin
1131 3329f07b Gerd Hoffmann
    if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1)
1132 f6b134ac Mark McLoughlin
        return -1;
1133 f6b134ac Mark McLoughlin
1134 3329f07b Gerd Hoffmann
    if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) {
1135 dc1c9fe8 Mark McLoughlin
        return -1;
1136 dc1c9fe8 Mark McLoughlin
    }
1137 dc1c9fe8 Mark McLoughlin
1138 dc1c9fe8 Mark McLoughlin
    return 0;
1139 dc1c9fe8 Mark McLoughlin
}
1140 dc1c9fe8 Mark McLoughlin
1141 7f161aae Mark McLoughlin
int net_client_parse(QemuOptsList *opts_list, const char *optarg)
1142 dc1c9fe8 Mark McLoughlin
{
1143 a3a766e7 Juan Quintela
#if defined(CONFIG_SLIRP)
1144 68ac40d2 Mark McLoughlin
    int ret;
1145 68ac40d2 Mark McLoughlin
    if (net_slirp_parse_legacy(opts_list, optarg, &ret)) {
1146 dc1c9fe8 Mark McLoughlin
        return ret;
1147 dc1c9fe8 Mark McLoughlin
    }
1148 a3a766e7 Juan Quintela
#endif
1149 68ac40d2 Mark McLoughlin
1150 8212c64f Markus Armbruster
    if (!qemu_opts_parse(opts_list, optarg, 1)) {
1151 dc1c9fe8 Mark McLoughlin
        return -1;
1152 dc1c9fe8 Mark McLoughlin
    }
1153 dc1c9fe8 Mark McLoughlin
1154 cb4522cc Gerd Hoffmann
    default_net = 0;
1155 dc1c9fe8 Mark McLoughlin
    return 0;
1156 dc1c9fe8 Mark McLoughlin
}
1157 7fc8d918 Jason Wang
1158 7fc8d918 Jason Wang
/* From FreeBSD */
1159 7fc8d918 Jason Wang
/* XXX: optimize */
1160 7fc8d918 Jason Wang
unsigned compute_mcast_idx(const uint8_t *ep)
1161 7fc8d918 Jason Wang
{
1162 7fc8d918 Jason Wang
    uint32_t crc;
1163 7fc8d918 Jason Wang
    int carry, i, j;
1164 7fc8d918 Jason Wang
    uint8_t b;
1165 7fc8d918 Jason Wang
1166 7fc8d918 Jason Wang
    crc = 0xffffffff;
1167 7fc8d918 Jason Wang
    for (i = 0; i < 6; i++) {
1168 7fc8d918 Jason Wang
        b = *ep++;
1169 7fc8d918 Jason Wang
        for (j = 0; j < 8; j++) {
1170 7fc8d918 Jason Wang
            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
1171 7fc8d918 Jason Wang
            crc <<= 1;
1172 7fc8d918 Jason Wang
            b >>= 1;
1173 7fc8d918 Jason Wang
            if (carry) {
1174 7fc8d918 Jason Wang
                crc = ((crc ^ POLYNOMIAL) | carry);
1175 7fc8d918 Jason Wang
            }
1176 7fc8d918 Jason Wang
        }
1177 7fc8d918 Jason Wang
    }
1178 7fc8d918 Jason Wang
    return crc >> 26;
1179 7fc8d918 Jason Wang
}
1180 4d454574 Paolo Bonzini
1181 4d454574 Paolo Bonzini
QemuOptsList qemu_netdev_opts = {
1182 4d454574 Paolo Bonzini
    .name = "netdev",
1183 4d454574 Paolo Bonzini
    .implied_opt_name = "type",
1184 4d454574 Paolo Bonzini
    .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
1185 4d454574 Paolo Bonzini
    .desc = {
1186 4d454574 Paolo Bonzini
        /*
1187 4d454574 Paolo Bonzini
         * no elements => accept any params
1188 4d454574 Paolo Bonzini
         * validation will happen later
1189 4d454574 Paolo Bonzini
         */
1190 4d454574 Paolo Bonzini
        { /* end of list */ }
1191 4d454574 Paolo Bonzini
    },
1192 4d454574 Paolo Bonzini
};
1193 4d454574 Paolo Bonzini
1194 4d454574 Paolo Bonzini
QemuOptsList qemu_net_opts = {
1195 4d454574 Paolo Bonzini
    .name = "net",
1196 4d454574 Paolo Bonzini
    .implied_opt_name = "type",
1197 4d454574 Paolo Bonzini
    .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
1198 4d454574 Paolo Bonzini
    .desc = {
1199 4d454574 Paolo Bonzini
        /*
1200 4d454574 Paolo Bonzini
         * no elements => accept any params
1201 4d454574 Paolo Bonzini
         * validation will happen later
1202 4d454574 Paolo Bonzini
         */
1203 4d454574 Paolo Bonzini
        { /* end of list */ }
1204 4d454574 Paolo Bonzini
    },
1205 4d454574 Paolo Bonzini
};