net.c 31.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * QEMU System Emulator
 *
 * Copyright (c) 2003-2008 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
B
blueswir1 已提交
24 25
#include "config-host.h"

P
Paolo Bonzini 已提交
26
#include "net/net.h"
P
Paolo Bonzini 已提交
27 28
#include "clients.h"
#include "hub.h"
P
Paolo Bonzini 已提交
29
#include "net/slirp.h"
30
#include "net/eth.h"
P
Paolo Bonzini 已提交
31
#include "util.h"
32

33
#include "monitor/monitor.h"
M
Mark McLoughlin 已提交
34
#include "qemu-common.h"
35 36
#include "qemu/sockets.h"
#include "qemu/config-file.h"
L
Luiz Capitulino 已提交
37
#include "qmp-commands.h"
38
#include "hw/qdev.h"
39
#include "qemu/iov.h"
40
#include "qemu/main-loop.h"
41 42
#include "qapi-visit.h"
#include "qapi/opts-visitor.h"
43
#include "qapi/dealloc-visitor.h"
44

45 46 47 48 49
/* Net bridge is currently not supported for W32. */
#if !defined(_WIN32)
# define CONFIG_NET_BRIDGE
#endif

50
static QTAILQ_HEAD(, NetClientState) net_clients;
51

G
Gerd Hoffmann 已提交
52 53
int default_net = 1;

54 55 56
/***********************************************************/
/* network device redirectors */

57
#if defined(DEBUG_NET)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
static void hex_dump(FILE *f, const uint8_t *buf, int size)
{
    int len, i, j, c;

    for(i=0;i<size;i+=16) {
        len = size - i;
        if (len > 16)
            len = 16;
        fprintf(f, "%08x ", i);
        for(j=0;j<16;j++) {
            if (j < len)
                fprintf(f, " %02x", buf[i+j]);
            else
                fprintf(f, "   ");
        }
        fprintf(f, " ");
        for(j=0;j<len;j++) {
            c = buf[i+j];
            if (c < ' ' || c > '~')
                c = '.';
            fprintf(f, "%c", c);
        }
        fprintf(f, "\n");
    }
}
#endif

static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
{
    const char *p, *p1;
    int len;
    p = *pp;
    p1 = strchr(p, sep);
    if (!p1)
        return -1;
    len = p1 - p;
    p1++;
    if (buf_size > 0) {
        if (len > buf_size - 1)
            len = buf_size - 1;
        memcpy(buf, p, len);
        buf[len] = '\0';
    }
    *pp = p1;
    return 0;
}

int parse_host_port(struct sockaddr_in *saddr, const char *str)
{
    char buf[512];
    struct hostent *he;
    const char *p, *r;
    int port;

    p = str;
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
        return -1;
    saddr->sin_family = AF_INET;
    if (buf[0] == '\0') {
        saddr->sin_addr.s_addr = 0;
    } else {
119
        if (qemu_isdigit(buf[0])) {
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
            if (!inet_aton(buf, &saddr->sin_addr))
                return -1;
        } else {
            if ((he = gethostbyname(buf)) == NULL)
                return - 1;
            saddr->sin_addr = *(struct in_addr *)he->h_addr;
        }
    }
    port = strtol(p, (char **)&r, 0);
    if (r == p)
        return -1;
    saddr->sin_port = htons(port);
    return 0;
}

135
void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
136
{
137
    snprintf(nc->info_str, sizeof(nc->info_str),
138
             "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
139
             nc->model,
140 141 142 143
             macaddr[0], macaddr[1], macaddr[2],
             macaddr[3], macaddr[4], macaddr[5]);
}

G
Gerd Hoffmann 已提交
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
{
    static int index = 0;
    static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };

    if (memcmp(macaddr, &zero, sizeof(zero)) != 0)
        return;
    macaddr->a[0] = 0x52;
    macaddr->a[1] = 0x54;
    macaddr->a[2] = 0x00;
    macaddr->a[3] = 0x12;
    macaddr->a[4] = 0x34;
    macaddr->a[5] = 0x56 + index++;
}

159 160 161
/**
 * Generate a name for net client
 *
A
Amos Kong 已提交
162
 * Only net clients created with the legacy -net option and NICs need this.
163
 */
164
static char *assign_name(NetClientState *nc1, const char *model)
165
{
166
    NetClientState *nc;
167 168
    int id = 0;

169 170
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (nc == nc1) {
171
            continue;
172
        }
A
Amos Kong 已提交
173
        if (strcmp(nc->model, model) == 0) {
174 175 176 177
            id++;
        }
    }

178
    return g_strdup_printf("%s.%d", model, id);
179 180
}

181 182 183 184 185
static void qemu_net_client_destructor(NetClientState *nc)
{
    g_free(nc);
}

186 187 188 189
static void qemu_net_client_setup(NetClientState *nc,
                                  NetClientInfo *info,
                                  NetClientState *peer,
                                  const char *model,
190 191
                                  const char *name,
                                  NetClientDestructor *destructor)
192
{
193 194
    nc->info = info;
    nc->model = g_strdup(model);
195
    if (name) {
196
        nc->name = g_strdup(name);
197
    } else {
198
        nc->name = assign_name(nc, model);
199
    }
200

201 202
    if (peer) {
        assert(!peer->peer);
203 204
        nc->peer = peer;
        peer->peer = nc;
205
    }
206
    QTAILQ_INSERT_TAIL(&net_clients, nc, next);
207

208
    nc->incoming_queue = qemu_new_net_queue(nc);
209
    nc->destructor = destructor;
210 211 212 213 214 215 216 217 218 219 220 221
}

NetClientState *qemu_new_net_client(NetClientInfo *info,
                                    NetClientState *peer,
                                    const char *model,
                                    const char *name)
{
    NetClientState *nc;

    assert(info->size >= sizeof(NetClientState));

    nc = g_malloc0(info->size);
222 223
    qemu_net_client_setup(nc, info, peer, model, name,
                          qemu_net_client_destructor);
224

225
    return nc;
226 227
}

228 229 230 231 232 233
NICState *qemu_new_nic(NetClientInfo *info,
                       NICConf *conf,
                       const char *model,
                       const char *name,
                       void *opaque)
{
J
Jason Wang 已提交
234
    NetClientState **peers = conf->peers.ncs;
235
    NICState *nic;
236
    int i, queues = MAX(1, conf->queues);
237

238
    assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
239 240
    assert(info->size >= sizeof(NICState));

241 242
    nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
    nic->ncs = (void *)nic + info->size;
243 244 245
    nic->conf = conf;
    nic->opaque = opaque;

246 247
    for (i = 0; i < queues; i++) {
        qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
J
Jason Wang 已提交
248 249 250 251
                              NULL);
        nic->ncs[i].queue_index = i;
    }

252 253 254
    return nic;
}

J
Jason Wang 已提交
255 256
NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
{
257
    return nic->ncs + queue_index;
J
Jason Wang 已提交
258 259
}

J
Jason Wang 已提交
260 261
NetClientState *qemu_get_queue(NICState *nic)
{
J
Jason Wang 已提交
262
    return qemu_get_subqueue(nic, 0);
J
Jason Wang 已提交
263 264
}

J
Jason Wang 已提交
265 266
NICState *qemu_get_nic(NetClientState *nc)
{
J
Jason Wang 已提交
267 268
    NetClientState *nc0 = nc - nc->queue_index;

269
    return (NICState *)((void *)nc0 - nc->info->size);
J
Jason Wang 已提交
270 271 272 273 274 275 276 277 278
}

void *qemu_get_nic_opaque(NetClientState *nc)
{
    NICState *nic = qemu_get_nic(nc);

    return nic->opaque;
}

279
static void qemu_cleanup_net_client(NetClientState *nc)
280
{
281
    QTAILQ_REMOVE(&net_clients, nc, next);
282

283 284 285
    if (nc->info->cleanup) {
        nc->info->cleanup(nc);
    }
286
}
287

288
static void qemu_free_net_client(NetClientState *nc)
289
{
290 291
    if (nc->incoming_queue) {
        qemu_del_net_queue(nc->incoming_queue);
S
Stefan Hajnoczi 已提交
292
    }
293 294
    if (nc->peer) {
        nc->peer->peer = NULL;
295
    }
296 297
    g_free(nc->name);
    g_free(nc->model);
298 299 300
    if (nc->destructor) {
        nc->destructor(nc);
    }
301 302
}

303
void qemu_del_net_client(NetClientState *nc)
304
{
J
Jason Wang 已提交
305 306 307 308 309 310 311 312 313 314 315
    NetClientState *ncs[MAX_QUEUE_NUM];
    int queues, i;

    /* If the NetClientState belongs to a multiqueue backend, we will change all
     * other NetClientStates also.
     */
    queues = qemu_find_net_clients_except(nc->name, ncs,
                                          NET_CLIENT_OPTIONS_KIND_NIC,
                                          MAX_QUEUE_NUM);
    assert(queues != 0);

316
    /* If there is a peer NIC, delete and cleanup client, but do not free. */
317
    if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
J
Jason Wang 已提交
318
        NICState *nic = qemu_get_nic(nc->peer);
319 320 321 322
        if (nic->peer_deleted) {
            return;
        }
        nic->peer_deleted = true;
J
Jason Wang 已提交
323 324 325 326 327

        for (i = 0; i < queues; i++) {
            ncs[i]->peer->link_down = true;
        }

328 329
        if (nc->peer->info->link_status_changed) {
            nc->peer->info->link_status_changed(nc->peer);
330
        }
J
Jason Wang 已提交
331 332 333 334 335

        for (i = 0; i < queues; i++) {
            qemu_cleanup_net_client(ncs[i]);
        }

336 337 338
        return;
    }

J
Jason Wang 已提交
339 340
    assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);

J
Jason Wang 已提交
341 342 343 344
    for (i = 0; i < queues; i++) {
        qemu_cleanup_net_client(ncs[i]);
        qemu_free_net_client(ncs[i]);
    }
J
Jason Wang 已提交
345 346 347 348
}

void qemu_del_nic(NICState *nic)
{
M
Michael Roth 已提交
349
    int i, queues = MAX(nic->conf->queues, 1);
J
Jason Wang 已提交
350

351
    /* If this is a peer NIC and peer has already been deleted, free it now. */
J
Jason Wang 已提交
352 353 354
    if (nic->peer_deleted) {
        for (i = 0; i < queues; i++) {
            qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);
355 356 357
        }
    }

J
Jason Wang 已提交
358 359 360 361 362 363
    for (i = queues - 1; i >= 0; i--) {
        NetClientState *nc = qemu_get_subqueue(nic, i);

        qemu_cleanup_net_client(nc);
        qemu_free_net_client(nc);
    }
364 365

    g_free(nic);
366 367
}

M
Mark McLoughlin 已提交
368 369
void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
{
370
    NetClientState *nc;
M
Mark McLoughlin 已提交
371

372
    QTAILQ_FOREACH(nc, &net_clients, next) {
373
        if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
J
Jason Wang 已提交
374 375 376
            if (nc->queue_index == 0) {
                func(qemu_get_nic(nc), opaque);
            }
M
Mark McLoughlin 已提交
377 378 379 380
        }
    }
}

381
int qemu_can_send_packet(NetClientState *sender)
382
{
S
Stefan Hajnoczi 已提交
383
    if (!sender->peer) {
384 385 386
        return 1;
    }

S
Stefan Hajnoczi 已提交
387 388 389 390 391
    if (sender->peer->receive_disabled) {
        return 0;
    } else if (sender->peer->info->can_receive &&
               !sender->peer->info->can_receive(sender->peer)) {
        return 0;
392
    }
393
    return 1;
394 395
}

396 397 398 399 400
ssize_t qemu_deliver_packet(NetClientState *sender,
                            unsigned flags,
                            const uint8_t *data,
                            size_t size,
                            void *opaque)
401
{
402
    NetClientState *nc = opaque;
403
    ssize_t ret;
404

405
    if (nc->link_down) {
406 407 408
        return size;
    }

409
    if (nc->receive_disabled) {
410 411 412
        return 0;
    }

413 414
    if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
        ret = nc->info->receive_raw(nc, data, size);
415
    } else {
416
        ret = nc->info->receive(nc, data, size);
417 418 419
    }

    if (ret == 0) {
420
        nc->receive_disabled = 1;
421 422 423
    };

    return ret;
424 425
}

426
void qemu_purge_queued_packets(NetClientState *nc)
427
{
428
    if (!nc->peer) {
429
        return;
430
    }
431

432
    qemu_net_queue_purge(nc->peer->incoming_queue, nc);
433 434
}

435
void qemu_flush_queued_packets(NetClientState *nc)
436
{
437
    nc->receive_disabled = 0;
438

439 440 441 442 443
    if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
        if (net_hub_flush(nc->peer)) {
            qemu_notify_event();
        }
    }
444
    if (qemu_net_queue_flush(nc->incoming_queue)) {
445 446 447 448 449
        /* We emptied the queue successfully, signal to the IO thread to repoll
         * the file descriptor (for tap, for example).
         */
        qemu_notify_event();
    }
450 451
}

452
static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
453 454 455
                                                 unsigned flags,
                                                 const uint8_t *buf, int size,
                                                 NetPacketSent *sent_cb)
456
{
457
    NetQueue *queue;
458

459
#ifdef DEBUG_NET
460
    printf("qemu_send_packet_async:\n");
461 462
    hex_dump(stdout, buf, size);
#endif
463

S
Stefan Hajnoczi 已提交
464
    if (sender->link_down || !sender->peer) {
465 466 467
        return size;
    }

468
    queue = sender->peer->incoming_queue;
469

470 471 472
    return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
}

473
ssize_t qemu_send_packet_async(NetClientState *sender,
474 475 476 477 478
                               const uint8_t *buf, int size,
                               NetPacketSent *sent_cb)
{
    return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
                                             buf, size, sent_cb);
479 480
}

481
void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
482
{
483
    qemu_send_packet_async(nc, buf, size, NULL);
484 485
}

486
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
487
{
488
    return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
489 490 491
                                             buf, size, NULL);
}

492
static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
A
aliguori 已提交
493 494
                               int iovcnt)
{
495
    uint8_t buffer[NET_BUFSIZE];
B
Benjamin Poirier 已提交
496
    size_t offset;
A
aliguori 已提交
497

498
    offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
A
aliguori 已提交
499

500
    return nc->info->receive(nc, buffer, offset);
A
aliguori 已提交
501 502
}

503 504 505 506 507
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
                                unsigned flags,
                                const struct iovec *iov,
                                int iovcnt,
                                void *opaque)
508
{
509
    NetClientState *nc = opaque;
510
    int ret;
511

512
    if (nc->link_down) {
B
Benjamin Poirier 已提交
513
        return iov_size(iov, iovcnt);
514 515
    }

516 517 518 519
    if (nc->receive_disabled) {
        return 0;
    }

520
    if (nc->info->receive_iov) {
521
        ret = nc->info->receive_iov(nc, iov, iovcnt);
522
    } else {
523 524 525 526 527
        ret = nc_sendv_compat(nc, iov, iovcnt);
    }

    if (ret == 0) {
        nc->receive_disabled = 1;
528
    }
529 530

    return ret;
531 532
}

533
ssize_t qemu_sendv_packet_async(NetClientState *sender,
534 535
                                const struct iovec *iov, int iovcnt,
                                NetPacketSent *sent_cb)
536
{
537 538
    NetQueue *queue;

S
Stefan Hajnoczi 已提交
539
    if (sender->link_down || !sender->peer) {
B
Benjamin Poirier 已提交
540
        return iov_size(iov, iovcnt);
541 542
    }

543
    queue = sender->peer->incoming_queue;
544

545 546 547
    return qemu_net_queue_send_iov(queue, sender,
                                   QEMU_NET_PACKET_FLAG_NONE,
                                   iov, iovcnt, sent_cb);
A
aliguori 已提交
548 549
}

550
ssize_t
551
qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
552
{
553
    return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
554 555
}

556
NetClientState *qemu_find_netdev(const char *id)
M
Mark McLoughlin 已提交
557
{
558
    NetClientState *nc;
M
Mark McLoughlin 已提交
559

560 561
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC)
562
            continue;
563 564
        if (!strcmp(nc->name, id)) {
            return nc;
M
Mark McLoughlin 已提交
565 566 567 568 569 570
        }
    }

    return NULL;
}

571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
                                 NetClientOptionsKind type, int max)
{
    NetClientState *nc;
    int ret = 0;

    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (nc->info->type == type) {
            continue;
        }
        if (!strcmp(nc->name, id)) {
            if (ret < max) {
                ncs[ret] = nc;
            }
            ret++;
        }
    }

    return ret;
}

592 593 594 595 596 597 598 599 600 601
static int nic_get_free_idx(void)
{
    int index;

    for (index = 0; index < MAX_NICS; index++)
        if (!nd_table[index].used)
            return index;
    return -1;
}

602 603 604 605
int qemu_show_nic_models(const char *arg, const char *const *models)
{
    int i;

606
    if (!arg || !is_help_option(arg)) {
607
        return 0;
608
    }
609 610 611 612 613 614 615

    fprintf(stderr, "qemu: Supported NIC models: ");
    for (i = 0 ; models[i]; i++)
        fprintf(stderr, "%s%c", models[i], models[i+1] ? ',' : '\n');
    return 1;
}

616 617 618 619 620 621 622
void qemu_check_nic_model(NICInfo *nd, const char *model)
{
    const char *models[2];

    models[0] = model;
    models[1] = NULL;

623 624 625 626
    if (qemu_show_nic_models(nd->model, models))
        exit(0);
    if (qemu_find_nic_model(nd, models, model) < 0)
        exit(1);
627 628
}

629 630
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                        const char *default_model)
631
{
632
    int i;
633 634

    if (!nd->model)
635
        nd->model = g_strdup(default_model);
636

637 638 639
    for (i = 0 ; models[i]; i++) {
        if (strcmp(nd->model, models[i]) == 0)
            return i;
640 641
    }

642
    error_report("Unsupported NIC model: %s", nd->model);
643
    return -1;
644 645
}

646
static int net_init_nic(const NetClientOptions *opts, const char *name,
647
                        NetClientState *peer)
648 649 650
{
    int idx;
    NICInfo *nd;
651 652 653 654
    const NetLegacyNicOptions *nic;

    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_NIC);
    nic = opts->nic;
655 656 657

    idx = nic_get_free_idx();
    if (idx == -1 || nb_nics >= MAX_NICS) {
658
        error_report("Too Many NICs");
659 660 661 662 663 664 665
        return -1;
    }

    nd = &nd_table[idx];

    memset(nd, 0, sizeof(*nd));

666 667
    if (nic->has_netdev) {
        nd->netdev = qemu_find_netdev(nic->netdev);
M
Mark McLoughlin 已提交
668
        if (!nd->netdev) {
669
            error_report("netdev '%s' not found", nic->netdev);
M
Mark McLoughlin 已提交
670 671 672
            return -1;
        }
    } else {
673 674
        assert(peer);
        nd->netdev = peer;
M
Mark McLoughlin 已提交
675
    }
676
    nd->name = g_strdup(name);
677 678
    if (nic->has_model) {
        nd->model = g_strdup(nic->model);
679
    }
680 681
    if (nic->has_addr) {
        nd->devaddr = g_strdup(nic->addr);
682 683
    }

684 685
    if (nic->has_macaddr &&
        net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
686
        error_report("invalid syntax for ethernet address");
687 688
        return -1;
    }
689 690 691 692 693
    if (nic->has_macaddr &&
        is_multicast_ether_addr(nd->macaddr.a)) {
        error_report("NIC cannot have multicast MAC address (odd 1st byte)");
        return -1;
    }
694
    qemu_macaddr_default_if_unset(&nd->macaddr);
695

696 697 698 699 700 701 702 703
    if (nic->has_vectors) {
        if (nic->vectors > 0x7ffffff) {
            error_report("invalid # of vectors: %"PRIu32, nic->vectors);
            return -1;
        }
        nd->nvectors = nic->vectors;
    } else {
        nd->nvectors = DEV_NVECTORS_UNSPECIFIED;
704 705 706 707 708 709 710 711
    }

    nd->used = 1;
    nb_nics++;

    return idx;
}

712 713

static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
714
    const NetClientOptions *opts,
715
    const char *name,
716
    NetClientState *peer) = {
S
Stefan Hajnoczi 已提交
717
        [NET_CLIENT_OPTIONS_KIND_NIC]       = net_init_nic,
M
Mark McLoughlin 已提交
718
#ifdef CONFIG_SLIRP
S
Stefan Hajnoczi 已提交
719
        [NET_CLIENT_OPTIONS_KIND_USER]      = net_init_slirp,
720
#endif
S
Stefan Hajnoczi 已提交
721 722
        [NET_CLIENT_OPTIONS_KIND_TAP]       = net_init_tap,
        [NET_CLIENT_OPTIONS_KIND_SOCKET]    = net_init_socket,
M
Mark McLoughlin 已提交
723
#ifdef CONFIG_VDE
S
Stefan Hajnoczi 已提交
724
        [NET_CLIENT_OPTIONS_KIND_VDE]       = net_init_vde,
725 726 727
#endif
#ifdef CONFIG_NETMAP
        [NET_CLIENT_OPTIONS_KIND_NETMAP]    = net_init_netmap,
M
Mark McLoughlin 已提交
728
#endif
S
Stefan Hajnoczi 已提交
729
        [NET_CLIENT_OPTIONS_KIND_DUMP]      = net_init_dump,
730
#ifdef CONFIG_NET_BRIDGE
S
Stefan Hajnoczi 已提交
731
        [NET_CLIENT_OPTIONS_KIND_BRIDGE]    = net_init_bridge,
732
#endif
S
Stefan Hajnoczi 已提交
733
        [NET_CLIENT_OPTIONS_KIND_HUBPORT]   = net_init_hubport,
734 735
};

736

737
static int net_client_init1(const void *object, int is_netdev, Error **errp)
738
{
739 740 741 742 743
    union {
        const Netdev    *netdev;
        const NetLegacy *net;
    } u;
    const NetClientOptions *opts;
744
    const char *name;
745

746
    if (is_netdev) {
747 748 749 750 751
        u.netdev = object;
        opts = u.netdev->opts;
        name = u.netdev->id;

        switch (opts->kind) {
M
Mark McLoughlin 已提交
752
#ifdef CONFIG_SLIRP
753
        case NET_CLIENT_OPTIONS_KIND_USER:
M
Mark McLoughlin 已提交
754
#endif
755 756
        case NET_CLIENT_OPTIONS_KIND_TAP:
        case NET_CLIENT_OPTIONS_KIND_SOCKET:
M
Mark McLoughlin 已提交
757
#ifdef CONFIG_VDE
758 759
        case NET_CLIENT_OPTIONS_KIND_VDE:
#endif
760 761 762
#ifdef CONFIG_NETMAP
        case NET_CLIENT_OPTIONS_KIND_NETMAP:
#endif
763 764
#ifdef CONFIG_NET_BRIDGE
        case NET_CLIENT_OPTIONS_KIND_BRIDGE:
M
Mark McLoughlin 已提交
765
#endif
S
Stefan Hajnoczi 已提交
766
        case NET_CLIENT_OPTIONS_KIND_HUBPORT:
767 768 769
            break;

        default:
770 771
            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
                      "a netdev backend type");
M
Mark McLoughlin 已提交
772 773
            return -1;
        }
774 775 776 777 778 779
    } else {
        u.net = object;
        opts = u.net->opts;
        /* missing optional values have been initialized to "all bits zero" */
        name = u.net->has_id ? u.net->id : u.net->name;
    }
M
Mark McLoughlin 已提交
780

781
    if (net_client_init_fun[opts->kind]) {
782
        NetClientState *peer = NULL;
783 784 785 786 787 788

        /* Do not add to a vlan if it's a -netdev or a nic with a netdev=
         * parameter. */
        if (!is_netdev &&
            (opts->kind != NET_CLIENT_OPTIONS_KIND_NIC ||
             !opts->nic->has_netdev)) {
789
            peer = net_hub_add_port(u.net->has_vlan ? u.net->vlan : 0, NULL);
M
Mark McLoughlin 已提交
790
        }
791

792
        if (net_client_init_fun[opts->kind](opts, name, peer) < 0) {
793 794 795
            /* TODO push error reporting into init() methods */
            error_set(errp, QERR_DEVICE_INIT_FAILED,
                      NetClientOptionsKind_lookup[opts->kind]);
M
Mark McLoughlin 已提交
796 797 798
            return -1;
        }
    }
799 800 801
    return 0;
}

M
Mark McLoughlin 已提交
802

803 804 805 806 807 808
static void net_visit(Visitor *v, int is_netdev, void **object, Error **errp)
{
    if (is_netdev) {
        visit_type_Netdev(v, (Netdev **)object, NULL, errp);
    } else {
        visit_type_NetLegacy(v, (NetLegacy **)object, NULL, errp);
809
    }
810
}
811

M
Mark McLoughlin 已提交
812

813 814 815 816 817
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
{
    void *object = NULL;
    Error *err = NULL;
    int ret = -1;
818

819 820
    {
        OptsVisitor *ov = opts_visitor_new(opts);
M
Mark McLoughlin 已提交
821

822 823
        net_visit(opts_get_visitor(ov), is_netdev, &object, &err);
        opts_visitor_cleanup(ov);
824 825
    }

826
    if (!err) {
827
        ret = net_client_init1(object, is_netdev, &err);
828 829 830 831 832 833 834 835 836 837 838
    }

    if (object) {
        QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();

        net_visit(qapi_dealloc_get_visitor(dv), is_netdev, &object, NULL);
        qapi_dealloc_visitor_cleanup(dv);
    }

    error_propagate(errp, err);
    return ret;
839 840
}

841

842 843 844
static int net_host_check_device(const char *device)
{
    int i;
845
    const char *valid_param_list[] = { "tap", "socket", "dump"
846 847 848
#ifdef CONFIG_NET_BRIDGE
                                       , "bridge"
#endif
849 850 851 852 853 854 855
#ifdef CONFIG_SLIRP
                                       ,"user"
#endif
#ifdef CONFIG_VDE
                                       ,"vde"
#endif
    };
856
    for (i = 0; i < ARRAY_SIZE(valid_param_list); i++) {
857 858 859 860 861 862 863 864
        if (!strncmp(valid_param_list[i], device,
                     strlen(valid_param_list[i])))
            return 1;
    }

    return 0;
}

865
void net_host_device_add(Monitor *mon, const QDict *qdict)
866
{
867
    const char *device = qdict_get_str(qdict, "device");
868
    const char *opts_str = qdict_get_try_str(qdict, "opts");
869
    Error *local_err = NULL;
870
    QemuOpts *opts;
871

872
    if (!net_host_check_device(device)) {
A
aliguori 已提交
873
        monitor_printf(mon, "invalid host network device %s\n", device);
874 875
        return;
    }
876

877
    opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0);
878 879 880 881 882 883
    if (!opts) {
        return;
    }

    qemu_opt_set(opts, "type", device);

884 885 886 887
    net_client_init(opts, 0, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
888 889
        monitor_printf(mon, "adding host network device %s failed\n", device);
    }
890 891
}

892
void net_host_device_remove(Monitor *mon, const QDict *qdict)
893
{
894
    NetClientState *nc;
895 896
    int vlan_id = qdict_get_int(qdict, "vlan_id");
    const char *device = qdict_get_str(qdict, "device");
897

898 899
    nc = net_hub_find_client_by_name(vlan_id, device);
    if (!nc) {
900 901
        return;
    }
902
    if (!net_host_check_device(nc->model)) {
903 904 905
        monitor_printf(mon, "invalid host network device %s\n", device);
        return;
    }
906
    qemu_del_net_client(nc);
907 908
}

L
Luiz Capitulino 已提交
909 910 911 912 913 914
void netdev_add(QemuOpts *opts, Error **errp)
{
    net_client_init(opts, 1, errp);
}

int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret)
915
{
916
    Error *local_err = NULL;
L
Luiz Capitulino 已提交
917
    QemuOptsList *opts_list;
918 919
    QemuOpts *opts;

L
Luiz Capitulino 已提交
920 921 922
    opts_list = qemu_find_opts_err("netdev", &local_err);
    if (error_is_set(&local_err)) {
        goto exit_err;
923 924
    }

L
Luiz Capitulino 已提交
925 926 927 928 929 930 931
    opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
    if (error_is_set(&local_err)) {
        goto exit_err;
    }

    netdev_add(opts, &local_err);
    if (error_is_set(&local_err)) {
932
        qemu_opts_del(opts);
L
Luiz Capitulino 已提交
933
        goto exit_err;
934 935
    }

L
Luiz Capitulino 已提交
936 937 938 939 940 941
    return 0;

exit_err:
    qerror_report_err(local_err);
    error_free(local_err);
    return -1;
942 943
}

L
Luiz Capitulino 已提交
944
void qmp_netdev_del(const char *id, Error **errp)
945
{
946
    NetClientState *nc;
947
    QemuOpts *opts;
948

949 950
    nc = qemu_find_netdev(id);
    if (!nc) {
L
Luiz Capitulino 已提交
951 952
        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
        return;
953
    }
L
Luiz Capitulino 已提交
954

955 956 957 958 959 960
    opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), id);
    if (!opts) {
        error_setg(errp, "Device '%s' is not a netdev", id);
        return;
    }

961
    qemu_del_net_client(nc);
962
    qemu_opts_del(opts);
963 964
}

965
void print_net_client(Monitor *mon, NetClientState *nc)
966
{
J
Jason Wang 已提交
967 968 969 970
    monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
                   nc->queue_index,
                   NetClientOptionsKind_lookup[nc->info->type],
                   nc->info_str);
971 972
}

973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
                                      Error **errp)
{
    NetClientState *nc;
    RxFilterInfoList *filter_list = NULL, *last_entry = NULL;

    QTAILQ_FOREACH(nc, &net_clients, next) {
        RxFilterInfoList *entry;
        RxFilterInfo *info;

        if (has_name && strcmp(nc->name, name) != 0) {
            continue;
        }

        /* only query rx-filter information of NIC */
        if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) {
            if (has_name) {
                error_setg(errp, "net client(%s) isn't a NIC", name);
                break;
            }
            continue;
        }

        if (nc->info->query_rx_filter) {
            info = nc->info->query_rx_filter(nc);
            entry = g_malloc0(sizeof(*entry));
            entry->value = info;

            if (!filter_list) {
                filter_list = entry;
            } else {
                last_entry->next = entry;
            }
            last_entry = entry;
        } else if (has_name) {
            error_setg(errp, "net client(%s) doesn't support"
                       " rx-filter querying", name);
            break;
        }
    }

    if (filter_list == NULL && !error_is_set(errp) && has_name) {
        error_setg(errp, "invalid net client name: %s", name);
    }

    return filter_list;
}

1021
void do_info_network(Monitor *mon, const QDict *qdict)
1022
{
1023
    NetClientState *nc, *peer;
1024
    NetClientOptionsKind type;
1025

1026 1027
    net_hub_info(mon);

1028 1029 1030
    QTAILQ_FOREACH(nc, &net_clients, next) {
        peer = nc->peer;
        type = nc->info->type;
1031

1032 1033 1034
        /* Skip if already printed in hub info */
        if (net_hub_id_for_client(nc, NULL) == 0) {
            continue;
1035
        }
1036

1037
        if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) {
1038
            print_net_client(mon, nc);
1039
        } /* else it's a netdev connected to a NIC, printed with the NIC */
1040
        if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) {
1041
            monitor_printf(mon, " \\ ");
1042
            print_net_client(mon, peer);
1043 1044
        }
    }
1045 1046
}

L
Luiz Capitulino 已提交
1047
void qmp_set_link(const char *name, bool up, Error **errp)
1048
{
J
Jason Wang 已提交
1049 1050 1051
    NetClientState *ncs[MAX_QUEUE_NUM];
    NetClientState *nc;
    int queues, i;
1052

J
Jason Wang 已提交
1053 1054 1055 1056 1057
    queues = qemu_find_net_clients_except(name, ncs,
                                          NET_CLIENT_OPTIONS_KIND_MAX,
                                          MAX_QUEUE_NUM);

    if (queues == 0) {
L
Luiz Capitulino 已提交
1058 1059
        error_set(errp, QERR_DEVICE_NOT_FOUND, name);
        return;
1060
    }
J
Jason Wang 已提交
1061
    nc = ncs[0];
1062

J
Jason Wang 已提交
1063 1064 1065
    for (i = 0; i < queues; i++) {
        ncs[i]->link_down = !up;
    }
1066

1067 1068
    if (nc->info->link_status_changed) {
        nc->info->link_status_changed(nc);
1069
    }
1070

1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
    if (nc->peer) {
        /* Change peer link only if the peer is NIC and then notify peer.
         * If the peer is a HUBPORT or a backend, we do not change the
         * link status.
         *
         * This behavior is compatible with qemu vlans where there could be
         * multiple clients that can still communicate with each other in
         * disconnected mode. For now maintain this compatibility.
         */
        if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
            for (i = 0; i < queues; i++) {
                ncs[i]->peer->link_down = !up;
            }
        }
        if (nc->peer->info->link_status_changed) {
            nc->peer->info->link_status_changed(nc->peer);
        }
1088
    }
1089 1090
}

1091 1092
void net_cleanup(void)
{
J
Jason Wang 已提交
1093
    NetClientState *nc;
1094

J
Jason Wang 已提交
1095 1096 1097 1098 1099
    /* We may del multiple entries during qemu_del_net_client(),
     * so QTAILQ_FOREACH_SAFE() is also not safe here.
     */
    while (!QTAILQ_EMPTY(&net_clients)) {
        nc = QTAILQ_FIRST(&net_clients);
J
Jason Wang 已提交
1100 1101 1102 1103 1104
        if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
            qemu_del_nic(qemu_get_nic(nc));
        } else {
            qemu_del_net_client(nc);
        }
1105
    }
1106 1107
}

1108
void net_check_clients(void)
1109
{
1110
    NetClientState *nc;
1111
    int i;
1112

1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
    /* Don't warn about the default network setup that you get if
     * no command line -net or -netdev options are specified. There
     * are two cases that we would otherwise complain about:
     * (1) board doesn't support a NIC but the implicit "-net nic"
     * requested one
     * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic"
     * sets up a nic that isn't connected to anything.
     */
    if (default_net) {
        return;
    }

1125
    net_hub_check_clients();
1126

1127 1128
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (!nc->peer) {
1129
            fprintf(stderr, "Warning: %s %s has no peer\n",
1130 1131
                    nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ?
                    "nic" : "netdev", nc->name);
1132 1133
        }
    }
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147

    /* Check that all NICs requested via -net nic actually got created.
     * NICs created via -device don't need to be checked here because
     * they are always instantiated.
     */
    for (i = 0; i < MAX_NICS; i++) {
        NICInfo *nd = &nd_table[i];
        if (nd->used && !nd->instantiated) {
            fprintf(stderr, "Warning: requested NIC (%s, model %s) "
                    "was not created (not supported by this machine?)\n",
                    nd->name ? nd->name : "anonymous",
                    nd->model ? nd->model : "unspecified");
        }
    }
1148
}
1149 1150 1151

static int net_init_client(QemuOpts *opts, void *dummy)
{
1152 1153 1154 1155 1156 1157
    Error *local_err = NULL;

    net_client_init(opts, 0, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
1158
        return -1;
1159 1160
    }

1161
    return 0;
M
Mark McLoughlin 已提交
1162 1163 1164 1165
}

static int net_init_netdev(QemuOpts *opts, void *dummy)
{
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
    Error *local_err = NULL;
    int ret;

    ret = net_client_init(opts, 1, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
        return -1;
    }

    return ret;
1177 1178 1179 1180
}

int net_init_clients(void)
{
1181 1182
    QemuOptsList *net = qemu_find_opts("net");

G
Gerd Hoffmann 已提交
1183
    if (default_net) {
1184
        /* if no clients, we use a default config */
1185
        qemu_opts_set(net, NULL, "type", "nic");
1186
#ifdef CONFIG_SLIRP
1187
        qemu_opts_set(net, NULL, "type", "user");
1188 1189 1190
#endif
    }

1191
    QTAILQ_INIT(&net_clients);
1192

1193
    if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1)
M
Mark McLoughlin 已提交
1194 1195
        return -1;

1196
    if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) {
1197 1198 1199 1200 1201 1202
        return -1;
    }

    return 0;
}

1203
int net_client_parse(QemuOptsList *opts_list, const char *optarg)
1204
{
1205
#if defined(CONFIG_SLIRP)
1206 1207
    int ret;
    if (net_slirp_parse_legacy(opts_list, optarg, &ret)) {
1208 1209
        return ret;
    }
1210
#endif
1211

1212
    if (!qemu_opts_parse(opts_list, optarg, 1)) {
1213 1214 1215
        return -1;
    }

G
Gerd Hoffmann 已提交
1216
    default_net = 0;
1217 1218
    return 0;
}
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241

/* From FreeBSD */
/* XXX: optimize */
unsigned compute_mcast_idx(const uint8_t *ep)
{
    uint32_t crc;
    int carry, i, j;
    uint8_t b;

    crc = 0xffffffff;
    for (i = 0; i < 6; i++) {
        b = *ep++;
        for (j = 0; j < 8; j++) {
            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
            crc <<= 1;
            b >>= 1;
            if (carry) {
                crc = ((crc ^ POLYNOMIAL) | carry);
            }
        }
    }
    return crc >> 26;
}
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267

QemuOptsList qemu_netdev_opts = {
    .name = "netdev",
    .implied_opt_name = "type",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
    .desc = {
        /*
         * no elements => accept any params
         * validation will happen later
         */
        { /* end of list */ }
    },
};

QemuOptsList qemu_net_opts = {
    .name = "net",
    .implied_opt_name = "type",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
    .desc = {
        /*
         * no elements => accept any params
         * validation will happen later
         */
        { /* end of list */ }
    },
};