net.c 32.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
bool qemu_has_ufo(NetClientState *nc)
382
{
383
    if (!nc || !nc->info->has_ufo) {
384 385 386
        return false;
    }

387
    return nc->info->has_ufo(nc);
388 389
}

390
bool qemu_has_vnet_hdr(NetClientState *nc)
391
{
392
    if (!nc || !nc->info->has_vnet_hdr) {
393 394 395
        return false;
    }

396
    return nc->info->has_vnet_hdr(nc);
397 398
}

399
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
400
{
401
    if (!nc || !nc->info->has_vnet_hdr_len) {
402 403 404
        return false;
    }

405
    return nc->info->has_vnet_hdr_len(nc, len);
406 407
}

408
void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
409
{
410
    if (!nc || !nc->info->using_vnet_hdr) {
411 412 413
        return;
    }

414
    nc->info->using_vnet_hdr(nc, enable);
415 416
}

417
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
418 419
                          int ecn, int ufo)
{
420
    if (!nc || !nc->info->set_offload) {
421 422 423
        return;
    }

424
    nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo);
425 426
}

427
void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
428
{
429
    if (!nc || !nc->info->set_vnet_hdr_len) {
430 431 432
        return;
    }

433
    nc->info->set_vnet_hdr_len(nc, len);
434 435
}

436
int qemu_can_send_packet(NetClientState *sender)
437
{
S
Stefan Hajnoczi 已提交
438
    if (!sender->peer) {
439 440 441
        return 1;
    }

S
Stefan Hajnoczi 已提交
442 443 444 445 446
    if (sender->peer->receive_disabled) {
        return 0;
    } else if (sender->peer->info->can_receive &&
               !sender->peer->info->can_receive(sender->peer)) {
        return 0;
447
    }
448
    return 1;
449 450
}

451 452 453 454 455
ssize_t qemu_deliver_packet(NetClientState *sender,
                            unsigned flags,
                            const uint8_t *data,
                            size_t size,
                            void *opaque)
456
{
457
    NetClientState *nc = opaque;
458
    ssize_t ret;
459

460
    if (nc->link_down) {
461 462 463
        return size;
    }

464
    if (nc->receive_disabled) {
465 466 467
        return 0;
    }

468 469
    if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
        ret = nc->info->receive_raw(nc, data, size);
470
    } else {
471
        ret = nc->info->receive(nc, data, size);
472 473 474
    }

    if (ret == 0) {
475
        nc->receive_disabled = 1;
476 477 478
    };

    return ret;
479 480
}

481
void qemu_purge_queued_packets(NetClientState *nc)
482
{
483
    if (!nc->peer) {
484
        return;
485
    }
486

487
    qemu_net_queue_purge(nc->peer->incoming_queue, nc);
488 489
}

490
void qemu_flush_queued_packets(NetClientState *nc)
491
{
492
    nc->receive_disabled = 0;
493

494 495 496 497 498
    if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
        if (net_hub_flush(nc->peer)) {
            qemu_notify_event();
        }
    }
499
    if (qemu_net_queue_flush(nc->incoming_queue)) {
500 501 502 503 504
        /* We emptied the queue successfully, signal to the IO thread to repoll
         * the file descriptor (for tap, for example).
         */
        qemu_notify_event();
    }
505 506
}

507
static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
508 509 510
                                                 unsigned flags,
                                                 const uint8_t *buf, int size,
                                                 NetPacketSent *sent_cb)
511
{
512
    NetQueue *queue;
513

514
#ifdef DEBUG_NET
515
    printf("qemu_send_packet_async:\n");
516 517
    hex_dump(stdout, buf, size);
#endif
518

S
Stefan Hajnoczi 已提交
519
    if (sender->link_down || !sender->peer) {
520 521 522
        return size;
    }

523
    queue = sender->peer->incoming_queue;
524

525 526 527
    return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
}

528
ssize_t qemu_send_packet_async(NetClientState *sender,
529 530 531 532 533
                               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);
534 535
}

536
void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
537
{
538
    qemu_send_packet_async(nc, buf, size, NULL);
539 540
}

541
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
542
{
543
    return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
544 545 546
                                             buf, size, NULL);
}

547
static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
A
aliguori 已提交
548 549
                               int iovcnt)
{
550
    uint8_t buffer[NET_BUFSIZE];
B
Benjamin Poirier 已提交
551
    size_t offset;
A
aliguori 已提交
552

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

555
    return nc->info->receive(nc, buffer, offset);
A
aliguori 已提交
556 557
}

558 559 560 561 562
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
                                unsigned flags,
                                const struct iovec *iov,
                                int iovcnt,
                                void *opaque)
563
{
564
    NetClientState *nc = opaque;
565
    int ret;
566

567
    if (nc->link_down) {
B
Benjamin Poirier 已提交
568
        return iov_size(iov, iovcnt);
569 570
    }

571 572 573 574
    if (nc->receive_disabled) {
        return 0;
    }

575
    if (nc->info->receive_iov) {
576
        ret = nc->info->receive_iov(nc, iov, iovcnt);
577
    } else {
578 579 580 581 582
        ret = nc_sendv_compat(nc, iov, iovcnt);
    }

    if (ret == 0) {
        nc->receive_disabled = 1;
583
    }
584 585

    return ret;
586 587
}

588
ssize_t qemu_sendv_packet_async(NetClientState *sender,
589 590
                                const struct iovec *iov, int iovcnt,
                                NetPacketSent *sent_cb)
591
{
592 593
    NetQueue *queue;

S
Stefan Hajnoczi 已提交
594
    if (sender->link_down || !sender->peer) {
B
Benjamin Poirier 已提交
595
        return iov_size(iov, iovcnt);
596 597
    }

598
    queue = sender->peer->incoming_queue;
599

600 601 602
    return qemu_net_queue_send_iov(queue, sender,
                                   QEMU_NET_PACKET_FLAG_NONE,
                                   iov, iovcnt, sent_cb);
A
aliguori 已提交
603 604
}

605
ssize_t
606
qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
607
{
608
    return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
609 610
}

611
NetClientState *qemu_find_netdev(const char *id)
M
Mark McLoughlin 已提交
612
{
613
    NetClientState *nc;
M
Mark McLoughlin 已提交
614

615 616
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC)
617
            continue;
618 619
        if (!strcmp(nc->name, id)) {
            return nc;
M
Mark McLoughlin 已提交
620 621 622 623 624 625
        }
    }

    return NULL;
}

626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
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;
}

647 648 649 650 651 652 653 654 655 656
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;
}

657 658 659 660
int qemu_show_nic_models(const char *arg, const char *const *models)
{
    int i;

661
    if (!arg || !is_help_option(arg)) {
662
        return 0;
663
    }
664 665 666 667 668 669 670

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

671 672 673 674 675 676 677
void qemu_check_nic_model(NICInfo *nd, const char *model)
{
    const char *models[2];

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

678 679 680 681
    if (qemu_show_nic_models(nd->model, models))
        exit(0);
    if (qemu_find_nic_model(nd, models, model) < 0)
        exit(1);
682 683
}

684 685
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                        const char *default_model)
686
{
687
    int i;
688 689

    if (!nd->model)
690
        nd->model = g_strdup(default_model);
691

692 693 694
    for (i = 0 ; models[i]; i++) {
        if (strcmp(nd->model, models[i]) == 0)
            return i;
695 696
    }

697
    error_report("Unsupported NIC model: %s", nd->model);
698
    return -1;
699 700
}

701
static int net_init_nic(const NetClientOptions *opts, const char *name,
702
                        NetClientState *peer)
703 704 705
{
    int idx;
    NICInfo *nd;
706 707 708 709
    const NetLegacyNicOptions *nic;

    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_NIC);
    nic = opts->nic;
710 711 712

    idx = nic_get_free_idx();
    if (idx == -1 || nb_nics >= MAX_NICS) {
713
        error_report("Too Many NICs");
714 715 716 717 718 719 720
        return -1;
    }

    nd = &nd_table[idx];

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

721 722
    if (nic->has_netdev) {
        nd->netdev = qemu_find_netdev(nic->netdev);
M
Mark McLoughlin 已提交
723
        if (!nd->netdev) {
724
            error_report("netdev '%s' not found", nic->netdev);
M
Mark McLoughlin 已提交
725 726 727
            return -1;
        }
    } else {
728 729
        assert(peer);
        nd->netdev = peer;
M
Mark McLoughlin 已提交
730
    }
731
    nd->name = g_strdup(name);
732 733
    if (nic->has_model) {
        nd->model = g_strdup(nic->model);
734
    }
735 736
    if (nic->has_addr) {
        nd->devaddr = g_strdup(nic->addr);
737 738
    }

739 740
    if (nic->has_macaddr &&
        net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
741
        error_report("invalid syntax for ethernet address");
742 743
        return -1;
    }
744 745 746 747 748
    if (nic->has_macaddr &&
        is_multicast_ether_addr(nd->macaddr.a)) {
        error_report("NIC cannot have multicast MAC address (odd 1st byte)");
        return -1;
    }
749
    qemu_macaddr_default_if_unset(&nd->macaddr);
750

751 752 753 754 755 756 757 758
    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;
759 760 761 762 763 764 765 766
    }

    nd->used = 1;
    nb_nics++;

    return idx;
}

767 768

static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
769
    const NetClientOptions *opts,
770
    const char *name,
771
    NetClientState *peer) = {
S
Stefan Hajnoczi 已提交
772
        [NET_CLIENT_OPTIONS_KIND_NIC]       = net_init_nic,
M
Mark McLoughlin 已提交
773
#ifdef CONFIG_SLIRP
S
Stefan Hajnoczi 已提交
774
        [NET_CLIENT_OPTIONS_KIND_USER]      = net_init_slirp,
775
#endif
S
Stefan Hajnoczi 已提交
776 777
        [NET_CLIENT_OPTIONS_KIND_TAP]       = net_init_tap,
        [NET_CLIENT_OPTIONS_KIND_SOCKET]    = net_init_socket,
M
Mark McLoughlin 已提交
778
#ifdef CONFIG_VDE
S
Stefan Hajnoczi 已提交
779
        [NET_CLIENT_OPTIONS_KIND_VDE]       = net_init_vde,
780 781 782
#endif
#ifdef CONFIG_NETMAP
        [NET_CLIENT_OPTIONS_KIND_NETMAP]    = net_init_netmap,
M
Mark McLoughlin 已提交
783
#endif
S
Stefan Hajnoczi 已提交
784
        [NET_CLIENT_OPTIONS_KIND_DUMP]      = net_init_dump,
785
#ifdef CONFIG_NET_BRIDGE
S
Stefan Hajnoczi 已提交
786
        [NET_CLIENT_OPTIONS_KIND_BRIDGE]    = net_init_bridge,
787
#endif
S
Stefan Hajnoczi 已提交
788
        [NET_CLIENT_OPTIONS_KIND_HUBPORT]   = net_init_hubport,
789 790
};

791

792
static int net_client_init1(const void *object, int is_netdev, Error **errp)
793
{
794 795 796 797 798
    union {
        const Netdev    *netdev;
        const NetLegacy *net;
    } u;
    const NetClientOptions *opts;
799
    const char *name;
800

801
    if (is_netdev) {
802 803 804 805 806
        u.netdev = object;
        opts = u.netdev->opts;
        name = u.netdev->id;

        switch (opts->kind) {
M
Mark McLoughlin 已提交
807
#ifdef CONFIG_SLIRP
808
        case NET_CLIENT_OPTIONS_KIND_USER:
M
Mark McLoughlin 已提交
809
#endif
810 811
        case NET_CLIENT_OPTIONS_KIND_TAP:
        case NET_CLIENT_OPTIONS_KIND_SOCKET:
M
Mark McLoughlin 已提交
812
#ifdef CONFIG_VDE
813 814
        case NET_CLIENT_OPTIONS_KIND_VDE:
#endif
815 816 817
#ifdef CONFIG_NETMAP
        case NET_CLIENT_OPTIONS_KIND_NETMAP:
#endif
818 819
#ifdef CONFIG_NET_BRIDGE
        case NET_CLIENT_OPTIONS_KIND_BRIDGE:
M
Mark McLoughlin 已提交
820
#endif
S
Stefan Hajnoczi 已提交
821
        case NET_CLIENT_OPTIONS_KIND_HUBPORT:
822 823 824
            break;

        default:
825 826
            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
                      "a netdev backend type");
M
Mark McLoughlin 已提交
827 828
            return -1;
        }
829 830 831 832 833 834
    } 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 已提交
835

836
    if (net_client_init_fun[opts->kind]) {
837
        NetClientState *peer = NULL;
838 839 840 841 842 843

        /* 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)) {
844
            peer = net_hub_add_port(u.net->has_vlan ? u.net->vlan : 0, NULL);
M
Mark McLoughlin 已提交
845
        }
846

847
        if (net_client_init_fun[opts->kind](opts, name, peer) < 0) {
848 849 850
            /* TODO push error reporting into init() methods */
            error_set(errp, QERR_DEVICE_INIT_FAILED,
                      NetClientOptionsKind_lookup[opts->kind]);
M
Mark McLoughlin 已提交
851 852 853
            return -1;
        }
    }
854 855 856
    return 0;
}

M
Mark McLoughlin 已提交
857

858 859 860 861 862 863
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);
864
    }
865
}
866

M
Mark McLoughlin 已提交
867

868 869 870 871 872
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
{
    void *object = NULL;
    Error *err = NULL;
    int ret = -1;
873

874 875
    {
        OptsVisitor *ov = opts_visitor_new(opts);
M
Mark McLoughlin 已提交
876

877 878
        net_visit(opts_get_visitor(ov), is_netdev, &object, &err);
        opts_visitor_cleanup(ov);
879 880
    }

881
    if (!err) {
882
        ret = net_client_init1(object, is_netdev, &err);
883 884 885 886 887 888 889 890 891 892 893
    }

    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;
894 895
}

896

897 898 899
static int net_host_check_device(const char *device)
{
    int i;
900
    const char *valid_param_list[] = { "tap", "socket", "dump"
901 902 903
#ifdef CONFIG_NET_BRIDGE
                                       , "bridge"
#endif
904 905 906 907 908 909 910
#ifdef CONFIG_SLIRP
                                       ,"user"
#endif
#ifdef CONFIG_VDE
                                       ,"vde"
#endif
    };
911
    for (i = 0; i < ARRAY_SIZE(valid_param_list); i++) {
912 913 914 915 916 917 918 919
        if (!strncmp(valid_param_list[i], device,
                     strlen(valid_param_list[i])))
            return 1;
    }

    return 0;
}

920
void net_host_device_add(Monitor *mon, const QDict *qdict)
921
{
922
    const char *device = qdict_get_str(qdict, "device");
923
    const char *opts_str = qdict_get_try_str(qdict, "opts");
924
    Error *local_err = NULL;
925
    QemuOpts *opts;
926

927
    if (!net_host_check_device(device)) {
A
aliguori 已提交
928
        monitor_printf(mon, "invalid host network device %s\n", device);
929 930
        return;
    }
931

932
    opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0);
933 934 935 936 937 938
    if (!opts) {
        return;
    }

    qemu_opt_set(opts, "type", device);

939
    net_client_init(opts, 0, &local_err);
940
    if (local_err) {
941 942
        qerror_report_err(local_err);
        error_free(local_err);
943 944
        monitor_printf(mon, "adding host network device %s failed\n", device);
    }
945 946
}

947
void net_host_device_remove(Monitor *mon, const QDict *qdict)
948
{
949
    NetClientState *nc;
950 951
    int vlan_id = qdict_get_int(qdict, "vlan_id");
    const char *device = qdict_get_str(qdict, "device");
952

953 954
    nc = net_hub_find_client_by_name(vlan_id, device);
    if (!nc) {
955 956
        return;
    }
957
    if (!net_host_check_device(nc->model)) {
958 959 960
        monitor_printf(mon, "invalid host network device %s\n", device);
        return;
    }
961
    qemu_del_net_client(nc);
962 963
}

L
Luiz Capitulino 已提交
964 965 966 967 968 969
void netdev_add(QemuOpts *opts, Error **errp)
{
    net_client_init(opts, 1, errp);
}

int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret)
970
{
971
    Error *local_err = NULL;
L
Luiz Capitulino 已提交
972
    QemuOptsList *opts_list;
973 974
    QemuOpts *opts;

L
Luiz Capitulino 已提交
975
    opts_list = qemu_find_opts_err("netdev", &local_err);
976
    if (local_err) {
L
Luiz Capitulino 已提交
977
        goto exit_err;
978 979
    }

L
Luiz Capitulino 已提交
980
    opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
981
    if (local_err) {
L
Luiz Capitulino 已提交
982 983 984 985
        goto exit_err;
    }

    netdev_add(opts, &local_err);
986
    if (local_err) {
987
        qemu_opts_del(opts);
L
Luiz Capitulino 已提交
988
        goto exit_err;
989 990
    }

L
Luiz Capitulino 已提交
991 992 993 994 995 996
    return 0;

exit_err:
    qerror_report_err(local_err);
    error_free(local_err);
    return -1;
997 998
}

L
Luiz Capitulino 已提交
999
void qmp_netdev_del(const char *id, Error **errp)
1000
{
1001
    NetClientState *nc;
1002
    QemuOpts *opts;
1003

1004 1005
    nc = qemu_find_netdev(id);
    if (!nc) {
L
Luiz Capitulino 已提交
1006 1007
        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
        return;
1008
    }
L
Luiz Capitulino 已提交
1009

1010 1011 1012 1013 1014 1015
    opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), id);
    if (!opts) {
        error_setg(errp, "Device '%s' is not a netdev", id);
        return;
    }

1016
    qemu_del_net_client(nc);
1017
    qemu_opts_del(opts);
1018 1019
}

1020
void print_net_client(Monitor *mon, NetClientState *nc)
1021
{
J
Jason Wang 已提交
1022 1023 1024 1025
    monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
                   nc->queue_index,
                   NetClientOptionsKind_lookup[nc->info->type],
                   nc->info_str);
1026 1027
}

1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
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;
}

1076
void do_info_network(Monitor *mon, const QDict *qdict)
1077
{
1078
    NetClientState *nc, *peer;
1079
    NetClientOptionsKind type;
1080

1081 1082
    net_hub_info(mon);

1083 1084 1085
    QTAILQ_FOREACH(nc, &net_clients, next) {
        peer = nc->peer;
        type = nc->info->type;
1086

1087 1088 1089
        /* Skip if already printed in hub info */
        if (net_hub_id_for_client(nc, NULL) == 0) {
            continue;
1090
        }
1091

1092
        if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) {
1093
            print_net_client(mon, nc);
1094
        } /* else it's a netdev connected to a NIC, printed with the NIC */
1095
        if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) {
1096
            monitor_printf(mon, " \\ ");
1097
            print_net_client(mon, peer);
1098 1099
        }
    }
1100 1101
}

L
Luiz Capitulino 已提交
1102
void qmp_set_link(const char *name, bool up, Error **errp)
1103
{
J
Jason Wang 已提交
1104 1105 1106
    NetClientState *ncs[MAX_QUEUE_NUM];
    NetClientState *nc;
    int queues, i;
1107

J
Jason Wang 已提交
1108 1109 1110 1111 1112
    queues = qemu_find_net_clients_except(name, ncs,
                                          NET_CLIENT_OPTIONS_KIND_MAX,
                                          MAX_QUEUE_NUM);

    if (queues == 0) {
L
Luiz Capitulino 已提交
1113 1114
        error_set(errp, QERR_DEVICE_NOT_FOUND, name);
        return;
1115
    }
J
Jason Wang 已提交
1116
    nc = ncs[0];
1117

J
Jason Wang 已提交
1118 1119 1120
    for (i = 0; i < queues; i++) {
        ncs[i]->link_down = !up;
    }
1121

1122 1123
    if (nc->info->link_status_changed) {
        nc->info->link_status_changed(nc);
1124
    }
1125

1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
    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);
        }
1143
    }
1144 1145
}

1146 1147
void net_cleanup(void)
{
J
Jason Wang 已提交
1148
    NetClientState *nc;
1149

J
Jason Wang 已提交
1150 1151 1152 1153 1154
    /* 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 已提交
1155 1156 1157 1158 1159
        if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
            qemu_del_nic(qemu_get_nic(nc));
        } else {
            qemu_del_net_client(nc);
        }
1160
    }
1161 1162
}

1163
void net_check_clients(void)
1164
{
1165
    NetClientState *nc;
1166
    int i;
1167

1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
    /* 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;
    }

1180
    net_hub_check_clients();
1181

1182 1183
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (!nc->peer) {
1184
            fprintf(stderr, "Warning: %s %s has no peer\n",
1185 1186
                    nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ?
                    "nic" : "netdev", nc->name);
1187 1188
        }
    }
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202

    /* 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");
        }
    }
1203
}
1204 1205 1206

static int net_init_client(QemuOpts *opts, void *dummy)
{
1207 1208 1209
    Error *local_err = NULL;

    net_client_init(opts, 0, &local_err);
1210
    if (local_err) {
1211 1212
        qerror_report_err(local_err);
        error_free(local_err);
1213
        return -1;
1214 1215
    }

1216
    return 0;
M
Mark McLoughlin 已提交
1217 1218 1219 1220
}

static int net_init_netdev(QemuOpts *opts, void *dummy)
{
1221 1222 1223 1224
    Error *local_err = NULL;
    int ret;

    ret = net_client_init(opts, 1, &local_err);
1225
    if (local_err) {
1226 1227 1228 1229 1230 1231
        qerror_report_err(local_err);
        error_free(local_err);
        return -1;
    }

    return ret;
1232 1233 1234 1235
}

int net_init_clients(void)
{
1236 1237
    QemuOptsList *net = qemu_find_opts("net");

G
Gerd Hoffmann 已提交
1238
    if (default_net) {
1239
        /* if no clients, we use a default config */
1240
        qemu_opts_set(net, NULL, "type", "nic");
1241
#ifdef CONFIG_SLIRP
1242
        qemu_opts_set(net, NULL, "type", "user");
1243 1244 1245
#endif
    }

1246
    QTAILQ_INIT(&net_clients);
1247

1248
    if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1)
M
Mark McLoughlin 已提交
1249 1250
        return -1;

1251
    if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) {
1252 1253 1254 1255 1256 1257
        return -1;
    }

    return 0;
}

1258
int net_client_parse(QemuOptsList *opts_list, const char *optarg)
1259
{
1260
#if defined(CONFIG_SLIRP)
1261 1262
    int ret;
    if (net_slirp_parse_legacy(opts_list, optarg, &ret)) {
1263 1264
        return ret;
    }
1265
#endif
1266

1267
    if (!qemu_opts_parse(opts_list, optarg, 1)) {
1268 1269 1270
        return -1;
    }

G
Gerd Hoffmann 已提交
1271
    default_net = 0;
1272 1273
    return 0;
}
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296

/* 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;
}
1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322

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 */ }
    },
};