net.c 44.9 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.
 */
24

P
Peter Maydell 已提交
25
#include "qemu/osdep.h"
B
blueswir1 已提交
26

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

34
#include "monitor/monitor.h"
35
#include "qemu/help_option.h"
36 37
#include "qapi/qapi-commands-net.h"
#include "qapi/qapi-visit-net.h"
38
#include "qapi/qmp/qdict.h"
39
#include "qapi/qmp/qerror.h"
40
#include "qemu/error-report.h"
41
#include "qemu/sockets.h"
42
#include "qemu/cutils.h"
43
#include "qemu/config-file.h"
44
#include "hw/qdev.h"
45
#include "qemu/iov.h"
46
#include "qemu/main-loop.h"
47
#include "qemu/option.h"
48
#include "qapi/error.h"
49
#include "qapi/opts-visitor.h"
50
#include "sysemu/sysemu.h"
51
#include "sysemu/qtest.h"
Y
Yang Hongyang 已提交
52
#include "net/filter.h"
53
#include "qapi/string-output-visitor.h"
54

55 56 57 58 59
/* Net bridge is currently not supported for W32. */
#if !defined(_WIN32)
# define CONFIG_NET_BRIDGE
#endif

60
static VMChangeStateEntry *net_change_state_entry;
61
static QTAILQ_HEAD(, NetClientState) net_clients;
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

/***********************************************************/
/* network device redirectors */

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

86 87
int parse_host_port(struct sockaddr_in *saddr, const char *str,
                    Error **errp)
88 89 90 91 92 93 94
{
    char buf[512];
    struct hostent *he;
    const char *p, *r;
    int port;

    p = str;
95 96 97
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
        error_setg(errp, "host address '%s' doesn't contain ':' "
                   "separating host from port", str);
98
        return -1;
99
    }
100 101 102 103
    saddr->sin_family = AF_INET;
    if (buf[0] == '\0') {
        saddr->sin_addr.s_addr = 0;
    } else {
104
        if (qemu_isdigit(buf[0])) {
105 106 107
            if (!inet_aton(buf, &saddr->sin_addr)) {
                error_setg(errp, "host address '%s' is not a valid "
                           "IPv4 address", buf);
108
                return -1;
109
            }
110
        } else {
111 112 113
            he = gethostbyname(buf);
            if (he == NULL) {
                error_setg(errp, "can't resolve host address '%s'", buf);
114
                return - 1;
115
            }
116 117 118 119
            saddr->sin_addr = *(struct in_addr *)he->h_addr;
        }
    }
    port = strtol(p, (char **)&r, 0);
120 121
    if (r == p) {
        error_setg(errp, "port number '%s' is invalid", p);
122
        return -1;
123
    }
124 125 126 127
    saddr->sin_port = htons(port);
    return 0;
}

128 129 130 131 132 133 134
char *qemu_mac_strdup_printf(const uint8_t *macaddr)
{
    return g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
                           macaddr[0], macaddr[1], macaddr[2],
                           macaddr[3], macaddr[4], macaddr[5]);
}

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]);
}

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
static int mac_table[256] = {0};

static void qemu_macaddr_set_used(MACAddr *macaddr)
{
    int index;

    for (index = 0x56; index < 0xFF; index++) {
        if (macaddr->a[5] == index) {
            mac_table[index]++;
        }
    }
}

static void qemu_macaddr_set_free(MACAddr *macaddr)
{
    int index;
    static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } };

    if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) {
        return;
    }
    for (index = 0x56; index < 0xFF; index++) {
        if (macaddr->a[5] == index) {
            mac_table[index]--;
        }
    }
}

static int qemu_macaddr_get_free(void)
{
    int index;

    for (index = 0x56; index < 0xFF; index++) {
        if (mac_table[index] == 0) {
            return index;
        }
    }

    return -1;
}

G
Gerd Hoffmann 已提交
185 186 187
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
{
    static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };
188 189 190 191 192 193 194 195 196 197
    static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } };

    if (memcmp(macaddr, &zero, sizeof(zero)) != 0) {
        if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) {
            return;
        } else {
            qemu_macaddr_set_used(macaddr);
            return;
        }
    }
G
Gerd Hoffmann 已提交
198 199 200 201 202 203

    macaddr->a[0] = 0x52;
    macaddr->a[1] = 0x54;
    macaddr->a[2] = 0x00;
    macaddr->a[3] = 0x12;
    macaddr->a[4] = 0x34;
204 205
    macaddr->a[5] = qemu_macaddr_get_free();
    qemu_macaddr_set_used(macaddr);
G
Gerd Hoffmann 已提交
206 207
}

208 209 210
/**
 * Generate a name for net client
 *
A
Amos Kong 已提交
211
 * Only net clients created with the legacy -net option and NICs need this.
212
 */
213
static char *assign_name(NetClientState *nc1, const char *model)
214
{
215
    NetClientState *nc;
216 217
    int id = 0;

218 219
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (nc == nc1) {
220
            continue;
221
        }
A
Amos Kong 已提交
222
        if (strcmp(nc->model, model) == 0) {
223 224 225 226
            id++;
        }
    }

227
    return g_strdup_printf("%s.%d", model, id);
228 229
}

230 231 232 233 234
static void qemu_net_client_destructor(NetClientState *nc)
{
    g_free(nc);
}

235 236 237 238
static void qemu_net_client_setup(NetClientState *nc,
                                  NetClientInfo *info,
                                  NetClientState *peer,
                                  const char *model,
239 240
                                  const char *name,
                                  NetClientDestructor *destructor)
241
{
242 243
    nc->info = info;
    nc->model = g_strdup(model);
244
    if (name) {
245
        nc->name = g_strdup(name);
246
    } else {
247
        nc->name = assign_name(nc, model);
248
    }
249

250 251
    if (peer) {
        assert(!peer->peer);
252 253
        nc->peer = peer;
        peer->peer = nc;
254
    }
255
    QTAILQ_INSERT_TAIL(&net_clients, nc, next);
256

257
    nc->incoming_queue = qemu_new_net_queue(qemu_deliver_packet_iov, nc);
258
    nc->destructor = destructor;
Y
Yang Hongyang 已提交
259
    QTAILQ_INIT(&nc->filters);
260 261 262 263 264 265 266 267 268 269 270 271
}

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);
272 273
    qemu_net_client_setup(nc, info, peer, model, name,
                          qemu_net_client_destructor);
274

275
    return nc;
276 277
}

278 279 280 281 282 283
NICState *qemu_new_nic(NetClientInfo *info,
                       NICConf *conf,
                       const char *model,
                       const char *name,
                       void *opaque)
{
J
Jason Wang 已提交
284
    NetClientState **peers = conf->peers.ncs;
285
    NICState *nic;
286
    int i, queues = MAX(1, conf->peers.queues);
287

288
    assert(info->type == NET_CLIENT_DRIVER_NIC);
289 290
    assert(info->size >= sizeof(NICState));

291 292
    nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
    nic->ncs = (void *)nic + info->size;
293 294 295
    nic->conf = conf;
    nic->opaque = opaque;

296 297
    for (i = 0; i < queues; i++) {
        qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
J
Jason Wang 已提交
298 299 300 301
                              NULL);
        nic->ncs[i].queue_index = i;
    }

302 303 304
    return nic;
}

J
Jason Wang 已提交
305 306
NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
{
307
    return nic->ncs + queue_index;
J
Jason Wang 已提交
308 309
}

J
Jason Wang 已提交
310 311
NetClientState *qemu_get_queue(NICState *nic)
{
J
Jason Wang 已提交
312
    return qemu_get_subqueue(nic, 0);
J
Jason Wang 已提交
313 314
}

J
Jason Wang 已提交
315 316
NICState *qemu_get_nic(NetClientState *nc)
{
J
Jason Wang 已提交
317 318
    NetClientState *nc0 = nc - nc->queue_index;

319
    return (NICState *)((void *)nc0 - nc->info->size);
J
Jason Wang 已提交
320 321 322 323 324 325 326 327 328
}

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

    return nic->opaque;
}

329
static void qemu_cleanup_net_client(NetClientState *nc)
330
{
331
    QTAILQ_REMOVE(&net_clients, nc, next);
332

333 334 335
    if (nc->info->cleanup) {
        nc->info->cleanup(nc);
    }
336
}
337

338
static void qemu_free_net_client(NetClientState *nc)
339
{
340 341
    if (nc->incoming_queue) {
        qemu_del_net_queue(nc->incoming_queue);
S
Stefan Hajnoczi 已提交
342
    }
343 344
    if (nc->peer) {
        nc->peer->peer = NULL;
345
    }
346 347
    g_free(nc->name);
    g_free(nc->model);
348 349 350
    if (nc->destructor) {
        nc->destructor(nc);
    }
351 352
}

353
void qemu_del_net_client(NetClientState *nc)
354
{
J
Jason Wang 已提交
355 356
    NetClientState *ncs[MAX_QUEUE_NUM];
    int queues, i;
Y
Yang Hongyang 已提交
357
    NetFilterState *nf, *next;
J
Jason Wang 已提交
358

359
    assert(nc->info->type != NET_CLIENT_DRIVER_NIC);
360

J
Jason Wang 已提交
361 362 363 364
    /* If the NetClientState belongs to a multiqueue backend, we will change all
     * other NetClientStates also.
     */
    queues = qemu_find_net_clients_except(nc->name, ncs,
365
                                          NET_CLIENT_DRIVER_NIC,
J
Jason Wang 已提交
366 367 368
                                          MAX_QUEUE_NUM);
    assert(queues != 0);

Y
Yang Hongyang 已提交
369 370 371 372
    QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
        object_unparent(OBJECT(nf));
    }

373
    /* If there is a peer NIC, delete and cleanup client, but do not free. */
374
    if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
J
Jason Wang 已提交
375
        NICState *nic = qemu_get_nic(nc->peer);
376 377 378 379
        if (nic->peer_deleted) {
            return;
        }
        nic->peer_deleted = true;
J
Jason Wang 已提交
380 381 382 383 384

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

385 386
        if (nc->peer->info->link_status_changed) {
            nc->peer->info->link_status_changed(nc->peer);
387
        }
J
Jason Wang 已提交
388 389 390 391 392

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

393 394 395
        return;
    }

J
Jason Wang 已提交
396 397 398 399
    for (i = 0; i < queues; i++) {
        qemu_cleanup_net_client(ncs[i]);
        qemu_free_net_client(ncs[i]);
    }
J
Jason Wang 已提交
400 401 402 403
}

void qemu_del_nic(NICState *nic)
{
404
    int i, queues = MAX(nic->conf->peers.queues, 1);
J
Jason Wang 已提交
405

406 407
    qemu_macaddr_set_free(&nic->conf->macaddr);

408
    /* If this is a peer NIC and peer has already been deleted, free it now. */
J
Jason Wang 已提交
409 410 411
    if (nic->peer_deleted) {
        for (i = 0; i < queues; i++) {
            qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);
412 413 414
        }
    }

J
Jason Wang 已提交
415 416 417 418 419 420
    for (i = queues - 1; i >= 0; i--) {
        NetClientState *nc = qemu_get_subqueue(nic, i);

        qemu_cleanup_net_client(nc);
        qemu_free_net_client(nc);
    }
421 422

    g_free(nic);
423 424
}

M
Mark McLoughlin 已提交
425 426
void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
{
427
    NetClientState *nc;
M
Mark McLoughlin 已提交
428

429
    QTAILQ_FOREACH(nc, &net_clients, next) {
430
        if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
J
Jason Wang 已提交
431 432 433
            if (nc->queue_index == 0) {
                func(qemu_get_nic(nc), opaque);
            }
M
Mark McLoughlin 已提交
434 435 436 437
        }
    }
}

438
bool qemu_has_ufo(NetClientState *nc)
439
{
440
    if (!nc || !nc->info->has_ufo) {
441 442 443
        return false;
    }

444
    return nc->info->has_ufo(nc);
445 446
}

447
bool qemu_has_vnet_hdr(NetClientState *nc)
448
{
449
    if (!nc || !nc->info->has_vnet_hdr) {
450 451 452
        return false;
    }

453
    return nc->info->has_vnet_hdr(nc);
454 455
}

456
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
457
{
458
    if (!nc || !nc->info->has_vnet_hdr_len) {
459 460 461
        return false;
    }

462
    return nc->info->has_vnet_hdr_len(nc, len);
463 464
}

465
void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
466
{
467
    if (!nc || !nc->info->using_vnet_hdr) {
468 469 470
        return;
    }

471
    nc->info->using_vnet_hdr(nc, enable);
472 473
}

474
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
475 476
                          int ecn, int ufo)
{
477
    if (!nc || !nc->info->set_offload) {
478 479 480
        return;
    }

481
    nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo);
482 483
}

484
void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
485
{
486
    if (!nc || !nc->info->set_vnet_hdr_len) {
487 488 489
        return;
    }

490
    nc->vnet_hdr_len = len;
491
    nc->info->set_vnet_hdr_len(nc, len);
492 493
}

G
Greg Kurz 已提交
494 495
int qemu_set_vnet_le(NetClientState *nc, bool is_le)
{
496
#ifdef HOST_WORDS_BIGENDIAN
G
Greg Kurz 已提交
497 498 499 500 501
    if (!nc || !nc->info->set_vnet_le) {
        return -ENOSYS;
    }

    return nc->info->set_vnet_le(nc, is_le);
502 503 504
#else
    return 0;
#endif
G
Greg Kurz 已提交
505 506 507 508
}

int qemu_set_vnet_be(NetClientState *nc, bool is_be)
{
509 510 511
#ifdef HOST_WORDS_BIGENDIAN
    return 0;
#else
G
Greg Kurz 已提交
512 513 514 515 516
    if (!nc || !nc->info->set_vnet_be) {
        return -ENOSYS;
    }

    return nc->info->set_vnet_be(nc, is_be);
517
#endif
G
Greg Kurz 已提交
518 519
}

520
int qemu_can_send_packet(NetClientState *sender)
521
{
522 523 524 525 526 527
    int vm_running = runstate_is_running();

    if (!vm_running) {
        return 0;
    }

S
Stefan Hajnoczi 已提交
528
    if (!sender->peer) {
529 530 531
        return 1;
    }

S
Stefan Hajnoczi 已提交
532 533 534 535 536
    if (sender->peer->receive_disabled) {
        return 0;
    } else if (sender->peer->info->can_receive &&
               !sender->peer->info->can_receive(sender->peer)) {
        return 0;
537
    }
538
    return 1;
539 540
}

541 542 543 544 545 546 547 548 549 550 551
static ssize_t filter_receive_iov(NetClientState *nc,
                                  NetFilterDirection direction,
                                  NetClientState *sender,
                                  unsigned flags,
                                  const struct iovec *iov,
                                  int iovcnt,
                                  NetPacketSent *sent_cb)
{
    ssize_t ret = 0;
    NetFilterState *nf = NULL;

552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
    if (direction == NET_FILTER_DIRECTION_TX) {
        QTAILQ_FOREACH(nf, &nc->filters, next) {
            ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
                                         iovcnt, sent_cb);
            if (ret) {
                return ret;
            }
        }
    } else {
        QTAILQ_FOREACH_REVERSE(nf, &nc->filters, NetFilterHead, next) {
            ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
                                         iovcnt, sent_cb);
            if (ret) {
                return ret;
            }
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
        }
    }

    return ret;
}

static ssize_t filter_receive(NetClientState *nc,
                              NetFilterDirection direction,
                              NetClientState *sender,
                              unsigned flags,
                              const uint8_t *data,
                              size_t size,
                              NetPacketSent *sent_cb)
{
    struct iovec iov = {
        .iov_base = (void *)data,
        .iov_len = size
    };

    return filter_receive_iov(nc, direction, sender, flags, &iov, 1, sent_cb);
}

589
void qemu_purge_queued_packets(NetClientState *nc)
590
{
591
    if (!nc->peer) {
592
        return;
593
    }
594

595
    qemu_net_queue_purge(nc->peer->incoming_queue, nc);
596 597
}

598
void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
599
{
600
    nc->receive_disabled = 0;
601

602
    if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_HUBPORT) {
603 604 605 606
        if (net_hub_flush(nc->peer)) {
            qemu_notify_event();
        }
    }
607
    if (qemu_net_queue_flush(nc->incoming_queue)) {
608 609 610 611
        /* We emptied the queue successfully, signal to the IO thread to repoll
         * the file descriptor (for tap, for example).
         */
        qemu_notify_event();
612 613 614
    } else if (purge) {
        /* Unable to empty the queue, purge remaining packets */
        qemu_net_queue_purge(nc->incoming_queue, nc);
615
    }
616 617
}

618 619 620 621 622
void qemu_flush_queued_packets(NetClientState *nc)
{
    qemu_flush_or_purge_queued_packets(nc, false);
}

623
static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
624 625 626
                                                 unsigned flags,
                                                 const uint8_t *buf, int size,
                                                 NetPacketSent *sent_cb)
627
{
628
    NetQueue *queue;
629
    int ret;
630

631
#ifdef DEBUG_NET
632
    printf("qemu_send_packet_async:\n");
633
    qemu_hexdump((const char *)buf, stdout, "net", size);
634
#endif
635

S
Stefan Hajnoczi 已提交
636
    if (sender->link_down || !sender->peer) {
637 638 639
        return size;
    }

640 641 642 643 644 645 646 647 648 649 650 651 652
    /* Let filters handle the packet first */
    ret = filter_receive(sender, NET_FILTER_DIRECTION_TX,
                         sender, flags, buf, size, sent_cb);
    if (ret) {
        return ret;
    }

    ret = filter_receive(sender->peer, NET_FILTER_DIRECTION_RX,
                         sender, flags, buf, size, sent_cb);
    if (ret) {
        return ret;
    }

653
    queue = sender->peer->incoming_queue;
654

655 656 657
    return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
}

658
ssize_t qemu_send_packet_async(NetClientState *sender,
659 660 661 662 663
                               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);
664 665
}

666
void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
667
{
668
    qemu_send_packet_async(nc, buf, size, NULL);
669 670
}

671
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
672
{
673
    return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
674 675 676
                                             buf, size, NULL);
}

677
static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
678
                               int iovcnt, unsigned flags)
A
aliguori 已提交
679
{
680
    uint8_t *buf = NULL;
681
    uint8_t *buffer;
B
Benjamin Poirier 已提交
682
    size_t offset;
683
    ssize_t ret;
A
aliguori 已提交
684

685 686 687 688
    if (iovcnt == 1) {
        buffer = iov[0].iov_base;
        offset = iov[0].iov_len;
    } else {
689 690 691 692 693
        offset = iov_size(iov, iovcnt);
        if (offset > NET_BUFSIZE) {
            return -1;
        }
        buf = g_malloc(offset);
694
        buffer = buf;
695
        offset = iov_to_buf(iov, iovcnt, 0, buf, offset);
696
    }
A
aliguori 已提交
697

698
    if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
699
        ret = nc->info->receive_raw(nc, buffer, offset);
700
    } else {
701
        ret = nc->info->receive(nc, buffer, offset);
702
    }
703 704 705

    g_free(buf);
    return ret;
A
aliguori 已提交
706 707
}

708 709 710 711 712
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
                                unsigned flags,
                                const struct iovec *iov,
                                int iovcnt,
                                void *opaque)
713
{
714
    NetClientState *nc = opaque;
715
    int ret;
716

717
    if (nc->link_down) {
B
Benjamin Poirier 已提交
718
        return iov_size(iov, iovcnt);
719 720
    }

721 722 723 724
    if (nc->receive_disabled) {
        return 0;
    }

725
    if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) {
726
        ret = nc->info->receive_iov(nc, iov, iovcnt);
727
    } else {
728
        ret = nc_sendv_compat(nc, iov, iovcnt, flags);
729 730 731 732
    }

    if (ret == 0) {
        nc->receive_disabled = 1;
733
    }
734 735

    return ret;
736 737
}

738
ssize_t qemu_sendv_packet_async(NetClientState *sender,
739 740
                                const struct iovec *iov, int iovcnt,
                                NetPacketSent *sent_cb)
741
{
742
    NetQueue *queue;
743
    int ret;
744

S
Stefan Hajnoczi 已提交
745
    if (sender->link_down || !sender->peer) {
B
Benjamin Poirier 已提交
746
        return iov_size(iov, iovcnt);
747 748
    }

749 750 751 752 753 754 755 756 757 758 759 760 761
    /* Let filters handle the packet first */
    ret = filter_receive_iov(sender, NET_FILTER_DIRECTION_TX, sender,
                             QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
    if (ret) {
        return ret;
    }

    ret = filter_receive_iov(sender->peer, NET_FILTER_DIRECTION_RX, sender,
                             QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
    if (ret) {
        return ret;
    }

762
    queue = sender->peer->incoming_queue;
763

764 765 766
    return qemu_net_queue_send_iov(queue, sender,
                                   QEMU_NET_PACKET_FLAG_NONE,
                                   iov, iovcnt, sent_cb);
A
aliguori 已提交
767 768
}

769
ssize_t
770
qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
771
{
772
    return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
773 774
}

775
NetClientState *qemu_find_netdev(const char *id)
M
Mark McLoughlin 已提交
776
{
777
    NetClientState *nc;
M
Mark McLoughlin 已提交
778

779
    QTAILQ_FOREACH(nc, &net_clients, next) {
780
        if (nc->info->type == NET_CLIENT_DRIVER_NIC)
781
            continue;
782 783
        if (!strcmp(nc->name, id)) {
            return nc;
M
Mark McLoughlin 已提交
784 785 786 787 788 789
        }
    }

    return NULL;
}

790
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
791
                                 NetClientDriver type, int max)
792 793 794 795 796 797 798 799
{
    NetClientState *nc;
    int ret = 0;

    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (nc->info->type == type) {
            continue;
        }
800
        if (!id || !strcmp(nc->name, id)) {
801 802 803 804 805 806 807 808 809 810
            if (ret < max) {
                ncs[ret] = nc;
            }
            ret++;
        }
    }

    return ret;
}

811 812 813 814 815 816 817 818 819 820
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;
}

821 822 823 824
int qemu_show_nic_models(const char *arg, const char *const *models)
{
    int i;

825
    if (!arg || !is_help_option(arg)) {
826
        return 0;
827
    }
828 829 830 831 832 833 834

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

835 836 837 838 839 840 841
void qemu_check_nic_model(NICInfo *nd, const char *model)
{
    const char *models[2];

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

842 843 844 845
    if (qemu_show_nic_models(nd->model, models))
        exit(0);
    if (qemu_find_nic_model(nd, models, model) < 0)
        exit(1);
846 847
}

848 849
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                        const char *default_model)
850
{
851
    int i;
852 853

    if (!nd->model)
854
        nd->model = g_strdup(default_model);
855

856 857 858
    for (i = 0 ; models[i]; i++) {
        if (strcmp(nd->model, models[i]) == 0)
            return i;
859 860
    }

861
    error_report("Unsupported NIC model: %s", nd->model);
862
    return -1;
863 864
}

865
static int net_init_nic(const Netdev *netdev, const char *name,
866
                        NetClientState *peer, Error **errp)
867 868 869
{
    int idx;
    NICInfo *nd;
870 871
    const NetLegacyNicOptions *nic;

872 873
    assert(netdev->type == NET_CLIENT_DRIVER_NIC);
    nic = &netdev->u.nic;
874 875 876

    idx = nic_get_free_idx();
    if (idx == -1 || nb_nics >= MAX_NICS) {
877
        error_setg(errp, "too many NICs");
878 879 880 881 882 883 884
        return -1;
    }

    nd = &nd_table[idx];

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

885 886
    if (nic->has_netdev) {
        nd->netdev = qemu_find_netdev(nic->netdev);
M
Mark McLoughlin 已提交
887
        if (!nd->netdev) {
888
            error_setg(errp, "netdev '%s' not found", nic->netdev);
M
Mark McLoughlin 已提交
889 890 891
            return -1;
        }
    } else {
892 893
        assert(peer);
        nd->netdev = peer;
M
Mark McLoughlin 已提交
894
    }
895
    nd->name = g_strdup(name);
896 897
    if (nic->has_model) {
        nd->model = g_strdup(nic->model);
898
    }
899 900
    if (nic->has_addr) {
        nd->devaddr = g_strdup(nic->addr);
901 902
    }

903 904
    if (nic->has_macaddr &&
        net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
905
        error_setg(errp, "invalid syntax for ethernet address");
906 907
        return -1;
    }
908 909
    if (nic->has_macaddr &&
        is_multicast_ether_addr(nd->macaddr.a)) {
910 911
        error_setg(errp,
                   "NIC cannot have multicast MAC address (odd 1st byte)");
912 913
        return -1;
    }
914
    qemu_macaddr_default_if_unset(&nd->macaddr);
915

916 917
    if (nic->has_vectors) {
        if (nic->vectors > 0x7ffffff) {
918
            error_setg(errp, "invalid # of vectors: %"PRIu32, nic->vectors);
919 920 921 922 923
            return -1;
        }
        nd->nvectors = nic->vectors;
    } else {
        nd->nvectors = DEV_NVECTORS_UNSPECIFIED;
924 925 926 927 928 929 930 931
    }

    nd->used = 1;
    nb_nics++;

    return idx;
}

932

933
static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
934
    const Netdev *netdev,
935
    const char *name,
936
    NetClientState *peer, Error **errp) = {
937
        [NET_CLIENT_DRIVER_NIC]       = net_init_nic,
M
Mark McLoughlin 已提交
938
#ifdef CONFIG_SLIRP
939
        [NET_CLIENT_DRIVER_USER]      = net_init_slirp,
940
#endif
941 942
        [NET_CLIENT_DRIVER_TAP]       = net_init_tap,
        [NET_CLIENT_DRIVER_SOCKET]    = net_init_socket,
M
Mark McLoughlin 已提交
943
#ifdef CONFIG_VDE
944
        [NET_CLIENT_DRIVER_VDE]       = net_init_vde,
945 946
#endif
#ifdef CONFIG_NETMAP
947
        [NET_CLIENT_DRIVER_NETMAP]    = net_init_netmap,
M
Mark McLoughlin 已提交
948
#endif
949
#ifdef CONFIG_NET_BRIDGE
950
        [NET_CLIENT_DRIVER_BRIDGE]    = net_init_bridge,
951
#endif
952
        [NET_CLIENT_DRIVER_HUBPORT]   = net_init_hubport,
953
#ifdef CONFIG_VHOST_NET_USED
954
        [NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
955
#endif
956
#ifdef CONFIG_L2TPV3
957
        [NET_CLIENT_DRIVER_L2TPV3]    = net_init_l2tpv3,
A
Anton Ivanov 已提交
958
#endif
959 960
};

961

E
Eric Blake 已提交
962
static int net_client_init1(const void *object, bool is_netdev, Error **errp)
963
{
964 965
    Netdev legacy = {0};
    const Netdev *netdev;
966
    const char *name;
967
    NetClientState *peer = NULL;
968

969
    if (is_netdev) {
970
        netdev = object;
971
        name = netdev->id;
972

973
        if (netdev->type == NET_CLIENT_DRIVER_NIC ||
974
            !net_client_init_fun[netdev->type]) {
975 976
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
                       "a netdev backend type");
M
Mark McLoughlin 已提交
977 978
            return -1;
        }
979
    } else {
980
        const NetLegacy *net = object;
981
        const NetLegacyOptions *opts = net->opts;
982 983
        legacy.id = net->id;
        netdev = &legacy;
984
        /* missing optional values have been initialized to "all bits zero" */
985
        name = net->has_id ? net->id : net->name;
986

987 988 989 990
        if (net->has_name) {
            warn_report("The 'name' parameter is deprecated, use 'id' instead");
        }

991 992
        /* Map the old options to the new flat type */
        switch (opts->type) {
993
        case NET_LEGACY_OPTIONS_TYPE_NONE:
994
            return 0; /* nothing to do */
995
        case NET_LEGACY_OPTIONS_TYPE_NIC:
996
            legacy.type = NET_CLIENT_DRIVER_NIC;
997
            legacy.u.nic = opts->u.nic;
998
            break;
999
        case NET_LEGACY_OPTIONS_TYPE_USER:
1000
            legacy.type = NET_CLIENT_DRIVER_USER;
1001
            legacy.u.user = opts->u.user;
1002
            break;
1003
        case NET_LEGACY_OPTIONS_TYPE_TAP:
1004
            legacy.type = NET_CLIENT_DRIVER_TAP;
1005
            legacy.u.tap = opts->u.tap;
1006
            break;
1007
        case NET_LEGACY_OPTIONS_TYPE_L2TPV3:
1008
            legacy.type = NET_CLIENT_DRIVER_L2TPV3;
1009
            legacy.u.l2tpv3 = opts->u.l2tpv3;
1010
            break;
1011
        case NET_LEGACY_OPTIONS_TYPE_SOCKET:
1012
            legacy.type = NET_CLIENT_DRIVER_SOCKET;
1013
            legacy.u.socket = opts->u.socket;
1014
            break;
1015
        case NET_LEGACY_OPTIONS_TYPE_VDE:
1016
            legacy.type = NET_CLIENT_DRIVER_VDE;
1017
            legacy.u.vde = opts->u.vde;
1018
            break;
1019
        case NET_LEGACY_OPTIONS_TYPE_BRIDGE:
1020
            legacy.type = NET_CLIENT_DRIVER_BRIDGE;
1021
            legacy.u.bridge = opts->u.bridge;
1022
            break;
1023
        case NET_LEGACY_OPTIONS_TYPE_NETMAP:
1024
            legacy.type = NET_CLIENT_DRIVER_NETMAP;
1025
            legacy.u.netmap = opts->u.netmap;
1026
            break;
1027
        case NET_LEGACY_OPTIONS_TYPE_VHOST_USER:
1028
            legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
1029
            legacy.u.vhost_user = opts->u.vhost_user;
1030 1031 1032
            break;
        default:
            abort();
1033
        }
1034

1035
        if (!net_client_init_fun[netdev->type]) {
1036 1037 1038 1039 1040
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
                       "a net backend type (maybe it is not compiled "
                       "into this binary)");
            return -1;
        }
M
Mark McLoughlin 已提交
1041

1042
        /* Do not add to a hub if it's a nic with a netdev= parameter. */
1043
        if (netdev->type != NET_CLIENT_DRIVER_NIC ||
1044
            !opts->u.nic.has_netdev) {
1045
            peer = net_hub_add_port(0, NULL, NULL);
1046
        }
1047
    }
1048

1049
    if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) {
1050 1051 1052
        /* FIXME drop when all init functions store an Error */
        if (errp && !*errp) {
            error_setg(errp, QERR_DEVICE_INIT_FAILED,
1053
                       NetClientDriver_str(netdev->type));
M
Mark McLoughlin 已提交
1054
        }
1055
        return -1;
M
Mark McLoughlin 已提交
1056
    }
1057 1058 1059
    return 0;
}

1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
static void show_netdevs(void)
{
    int idx;
    const char *available_netdevs[] = {
        "socket",
        "hubport",
        "tap",
#ifdef CONFIG_SLIRP
        "user",
#endif
#ifdef CONFIG_L2TPV3
        "l2tpv3",
#endif
#ifdef CONFIG_VDE
        "vde",
#endif
#ifdef CONFIG_NET_BRIDGE
        "bridge",
#endif
#ifdef CONFIG_NETMAP
        "netmap",
#endif
#ifdef CONFIG_POSIX
        "vhost-user",
#endif
    };

    printf("Available netdev backend types:\n");
    for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) {
        puts(available_netdevs[idx]);
    }
}
M
Mark McLoughlin 已提交
1092

T
Thomas Huth 已提交
1093
static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
1094 1095 1096 1097
{
    void *object = NULL;
    Error *err = NULL;
    int ret = -1;
1098
    Visitor *v = opts_visitor_new(opts);
1099

L
Lin Ma 已提交
1100 1101 1102
    const char *type = qemu_opt_get(opts, "type");

    if (is_netdev && type && is_help_option(type)) {
1103 1104 1105
        show_netdevs();
        exit(0);
    } else {
1106
        /* Parse convenience option format ip6-net=fec0::0[/64] */
1107
        const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
1108 1109 1110 1111 1112 1113

        if (ip6_net) {
            char buf[strlen(ip6_net) + 1];

            if (get_str_sep(buf, sizeof(buf), &ip6_net, '/') < 0) {
                /* Default 64bit prefix length.  */
1114 1115
                qemu_opt_set(opts, "ipv6-prefix", ip6_net, &error_abort);
                qemu_opt_set_number(opts, "ipv6-prefixlen", 64, &error_abort);
1116 1117 1118 1119 1120
            } else {
                /* User-specified prefix length.  */
                unsigned long len;
                int err;

1121
                qemu_opt_set(opts, "ipv6-prefix", buf, &error_abort);
1122 1123 1124 1125
                err = qemu_strtoul(ip6_net, NULL, 10, &len);

                if (err) {
                    error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1126
                              "ipv6-prefix", "a number");
1127
                } else {
1128
                    qemu_opt_set_number(opts, "ipv6-prefixlen", len,
1129 1130 1131
                                        &error_abort);
                }
            }
1132
            qemu_opt_unset(opts, "ipv6-net");
1133 1134 1135
        }
    }

1136 1137 1138 1139
    if (is_netdev) {
        visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
    } else {
        visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
1140 1141
    }

1142
    if (!err) {
1143
        ret = net_client_init1(object, is_netdev, &err);
1144 1145
    }

1146 1147 1148 1149
    if (is_netdev) {
        qapi_free_Netdev(object);
    } else {
        qapi_free_NetLegacy(object);
1150 1151 1152
    }

    error_propagate(errp, err);
1153
    visit_free(v);
1154
    return ret;
1155 1156
}

L
Luiz Capitulino 已提交
1157 1158
void netdev_add(QemuOpts *opts, Error **errp)
{
E
Eric Blake 已提交
1159
    net_client_init(opts, true, errp);
L
Luiz Capitulino 已提交
1160 1161
}

1162
void qmp_netdev_add(QDict *qdict, QObject **ret, Error **errp)
1163
{
1164
    Error *local_err = NULL;
L
Luiz Capitulino 已提交
1165
    QemuOptsList *opts_list;
1166 1167
    QemuOpts *opts;

L
Luiz Capitulino 已提交
1168
    opts_list = qemu_find_opts_err("netdev", &local_err);
1169
    if (local_err) {
1170
        goto out;
1171 1172
    }

L
Luiz Capitulino 已提交
1173
    opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
1174
    if (local_err) {
1175
        goto out;
L
Luiz Capitulino 已提交
1176 1177 1178
    }

    netdev_add(opts, &local_err);
1179
    if (local_err) {
1180
        qemu_opts_del(opts);
1181
        goto out;
1182 1183
    }

1184 1185
out:
    error_propagate(errp, local_err);
1186 1187
}

L
Luiz Capitulino 已提交
1188
void qmp_netdev_del(const char *id, Error **errp)
1189
{
1190
    NetClientState *nc;
1191
    QemuOpts *opts;
1192

1193 1194
    nc = qemu_find_netdev(id);
    if (!nc) {
1195 1196
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
                  "Device '%s' not found", id);
L
Luiz Capitulino 已提交
1197
        return;
1198
    }
L
Luiz Capitulino 已提交
1199

1200 1201 1202 1203 1204 1205
    opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), id);
    if (!opts) {
        error_setg(errp, "Device '%s' is not a netdev", id);
        return;
    }

1206
    qemu_del_net_client(nc);
1207
    qemu_opts_del(opts);
1208 1209
}

1210 1211 1212 1213 1214
static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
{
    char *str;
    ObjectProperty *prop;
    ObjectPropertyIterator iter;
1215
    Visitor *v;
1216 1217 1218 1219 1220 1221 1222

    /* generate info str */
    object_property_iter_init(&iter, OBJECT(nf));
    while ((prop = object_property_iter_next(&iter))) {
        if (!strcmp(prop->name, "type")) {
            continue;
        }
1223 1224 1225 1226
        v = string_output_visitor_new(false, &str);
        object_property_get(OBJECT(nf), v, prop->name, NULL);
        visit_complete(v, &str);
        visit_free(v);
1227 1228 1229 1230 1231 1232
        monitor_printf(mon, ",%s=%s", prop->name, str);
        g_free(str);
    }
    monitor_printf(mon, "\n");
}

1233
void print_net_client(Monitor *mon, NetClientState *nc)
1234
{
1235 1236
    NetFilterState *nf;

J
Jason Wang 已提交
1237 1238
    monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
                   nc->queue_index,
1239
                   NetClientDriver_str(nc->info->type),
J
Jason Wang 已提交
1240
                   nc->info_str);
1241 1242 1243 1244
    if (!QTAILQ_EMPTY(&nc->filters)) {
        monitor_printf(mon, "filters:\n");
    }
    QTAILQ_FOREACH(nf, &nc->filters, next) {
1245
        char *path = object_get_canonical_path_component(OBJECT(nf));
1246 1247 1248 1249

        monitor_printf(mon, "  - %s: type=%s", path,
                       object_get_typename(OBJECT(nf)));
        netfilter_print_info(mon, nf);
1250
        g_free(path);
1251
    }
1252 1253
}

1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
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 */
1269
        if (nc->info->type != NET_CLIENT_DRIVER_NIC) {
1270 1271
            if (has_name) {
                error_setg(errp, "net client(%s) isn't a NIC", name);
1272
                return NULL;
1273 1274 1275 1276
            }
            continue;
        }

1277 1278 1279 1280 1281 1282
        /* only query information on queue 0 since the info is per nic,
         * not per queue
         */
        if (nc->queue_index != 0)
            continue;

1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
        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);
1297
            return NULL;
1298
        }
1299 1300 1301 1302

        if (has_name) {
            break;
        }
1303 1304
    }

1305
    if (filter_list == NULL && has_name) {
1306 1307 1308 1309 1310 1311
        error_setg(errp, "invalid net client name: %s", name);
    }

    return filter_list;
}

1312
void hmp_info_network(Monitor *mon, const QDict *qdict)
1313
{
1314
    NetClientState *nc, *peer;
1315
    NetClientDriver type;
1316

1317 1318
    net_hub_info(mon);

1319 1320 1321
    QTAILQ_FOREACH(nc, &net_clients, next) {
        peer = nc->peer;
        type = nc->info->type;
1322

1323 1324 1325
        /* Skip if already printed in hub info */
        if (net_hub_id_for_client(nc, NULL) == 0) {
            continue;
1326
        }
1327

1328
        if (!peer || type == NET_CLIENT_DRIVER_NIC) {
1329
            print_net_client(mon, nc);
1330
        } /* else it's a netdev connected to a NIC, printed with the NIC */
1331
        if (peer && type == NET_CLIENT_DRIVER_NIC) {
1332
            monitor_printf(mon, " \\ ");
1333
            print_net_client(mon, peer);
1334 1335
        }
    }
1336 1337
}

L
Luiz Capitulino 已提交
1338
void qmp_set_link(const char *name, bool up, Error **errp)
1339
{
J
Jason Wang 已提交
1340 1341 1342
    NetClientState *ncs[MAX_QUEUE_NUM];
    NetClientState *nc;
    int queues, i;
1343

J
Jason Wang 已提交
1344
    queues = qemu_find_net_clients_except(name, ncs,
1345
                                          NET_CLIENT_DRIVER__MAX,
J
Jason Wang 已提交
1346 1347 1348
                                          MAX_QUEUE_NUM);

    if (queues == 0) {
1349 1350
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
                  "Device '%s' not found", name);
L
Luiz Capitulino 已提交
1351
        return;
1352
    }
J
Jason Wang 已提交
1353
    nc = ncs[0];
1354

J
Jason Wang 已提交
1355 1356 1357
    for (i = 0; i < queues; i++) {
        ncs[i]->link_down = !up;
    }
1358

1359 1360
    if (nc->info->link_status_changed) {
        nc->info->link_status_changed(nc);
1361
    }
1362

1363 1364 1365 1366 1367
    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.
         *
1368
         * This behavior is compatible with qemu hubs where there could be
1369 1370 1371
         * multiple clients that can still communicate with each other in
         * disconnected mode. For now maintain this compatibility.
         */
1372
        if (nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
1373 1374 1375 1376 1377 1378 1379
            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);
        }
1380
    }
1381 1382
}

1383 1384 1385
static void net_vm_change_state_handler(void *opaque, int running,
                                        RunState state)
{
1386 1387
    NetClientState *nc;
    NetClientState *tmp;
1388

1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
    QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) {
        if (running) {
            /* Flush queued packets and wake up backends. */
            if (nc->peer && qemu_can_send_packet(nc)) {
                qemu_flush_queued_packets(nc->peer);
            }
        } else {
            /* Complete all queued packets, to guarantee we don't modify
             * state later when VM is not running.
             */
1399 1400 1401 1402 1403
            qemu_flush_or_purge_queued_packets(nc, true);
        }
    }
}

1404 1405
void net_cleanup(void)
{
J
Jason Wang 已提交
1406
    NetClientState *nc;
1407

J
Jason Wang 已提交
1408 1409 1410 1411 1412
    /* 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);
1413
        if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
J
Jason Wang 已提交
1414 1415 1416 1417
            qemu_del_nic(qemu_get_nic(nc));
        } else {
            qemu_del_net_client(nc);
        }
1418
    }
1419 1420

    qemu_del_vm_change_state_handler(net_change_state_entry);
1421 1422
}

1423
void net_check_clients(void)
1424
{
1425
    NetClientState *nc;
1426
    int i;
1427

1428
    net_hub_check_clients();
1429

1430 1431
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (!nc->peer) {
1432
            warn_report("%s %s has no peer",
A
Alistair Francis 已提交
1433 1434 1435
                        nc->info->type == NET_CLIENT_DRIVER_NIC
                        ? "nic" : "netdev",
                        nc->name);
1436 1437
        }
    }
1438 1439 1440 1441 1442 1443 1444 1445

    /* 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) {
1446 1447 1448 1449
            warn_report("requested NIC (%s, model %s) "
                        "was not created (not supported by this machine?)",
                        nd->name ? nd->name : "anonymous",
                        nd->model ? nd->model : "unspecified");
1450 1451
        }
    }
1452
}
1453

1454
static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
1455
{
1456
    return net_client_init(opts, false, errp);
M
Mark McLoughlin 已提交
1457 1458
}

1459
static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
M
Mark McLoughlin 已提交
1460
{
1461
    return net_client_init(opts, true, errp);
1462
}
1463

1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479
/* For the convenience "--nic" parameter */
static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp)
{
    char *mac, *nd_id;
    int idx, ret;
    NICInfo *ni;
    const char *type;

    type = qemu_opt_get(opts, "type");
    if (type && g_str_equal(type, "none")) {
        return 0;    /* Nothing to do, default_net is cleared in vl.c */
    }

    idx = nic_get_free_idx();
    if (idx == -1 || nb_nics >= MAX_NICS) {
        error_setg(errp, "no more on-board/default NIC slots available");
1480 1481 1482
        return -1;
    }

1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
    if (!type) {
        qemu_opt_set(opts, "type", "user", &error_abort);
    }

    ni = &nd_table[idx];
    memset(ni, 0, sizeof(*ni));
    ni->model = qemu_opt_get_del(opts, "model");

    /* Create an ID if the user did not specify one */
    nd_id = g_strdup(qemu_opts_id(opts));
    if (!nd_id) {
        nd_id = g_strdup_printf("__org.qemu.nic%i\n", idx);
        qemu_opts_set_id(opts, nd_id);
    }

    /* Handle MAC address */
    mac = qemu_opt_get_del(opts, "mac");
    if (mac) {
        ret = net_parse_macaddr(ni->macaddr.a, mac);
        g_free(mac);
        if (ret) {
            error_setg(errp, "invalid syntax for ethernet address");
1505
            goto out;
1506 1507 1508
        }
        if (is_multicast_ether_addr(ni->macaddr.a)) {
            error_setg(errp, "NIC cannot have multicast MAC address");
1509 1510
            ret = -1;
            goto out;
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
        }
    }
    qemu_macaddr_default_if_unset(&ni->macaddr);

    ret = net_client_init(opts, true, errp);
    if (ret == 0) {
        ni->netdev = qemu_find_netdev(nd_id);
        ni->used = true;
        nb_nics++;
    }

1522
out:
1523
    g_free(nd_id);
1524
    return ret;
1525 1526
}

1527
int net_init_clients(Error **errp)
1528
{
1529 1530 1531
    net_change_state_entry =
        qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);

1532
    QTAILQ_INIT(&net_clients);
1533

1534
    if (qemu_opts_foreach(qemu_find_opts("netdev"),
1535
                          net_init_netdev, NULL, errp)) {
M
Mark McLoughlin 已提交
1536
        return -1;
1537
    }
M
Mark McLoughlin 已提交
1538

1539 1540 1541 1542
    if (qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL, errp)) {
        return -1;
    }

1543
    if (qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, errp)) {
1544 1545 1546 1547 1548 1549
        return -1;
    }

    return 0;
}

1550
int net_client_parse(QemuOptsList *opts_list, const char *optarg)
1551
{
1552
    if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
1553 1554 1555 1556 1557
        return -1;
    }

    return 0;
}
1558 1559 1560

/* From FreeBSD */
/* XXX: optimize */
1561
uint32_t net_crc32(const uint8_t *p, int len)
1562 1563 1564 1565 1566 1567
{
    uint32_t crc;
    int carry, i, j;
    uint8_t b;

    crc = 0xffffffff;
1568 1569
    for (i = 0; i < len; i++) {
        b = *p++;
1570 1571 1572 1573 1574
        for (j = 0; j < 8; j++) {
            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
            crc <<= 1;
            b >>= 1;
            if (carry) {
1575
                crc = ((crc ^ POLYNOMIAL_BE) | carry);
1576 1577 1578
            }
        }
    }
1579 1580 1581 1582

    return crc;
}

1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604
uint32_t net_crc32_le(const uint8_t *p, int len)
{
    uint32_t crc;
    int carry, i, j;
    uint8_t b;

    crc = 0xffffffff;
    for (i = 0; i < len; i++) {
        b = *p++;
        for (j = 0; j < 8; j++) {
            carry = (crc & 0x1) ^ (b & 0x01);
            crc >>= 1;
            b >>= 1;
            if (carry) {
                crc ^= POLYNOMIAL_LE;
            }
        }
    }

    return crc;
}

1605 1606 1607 1608
QemuOptsList qemu_netdev_opts = {
    .name = "netdev",
    .implied_opt_name = "type",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621
    .desc = {
        /*
         * no elements => accept any params
         * validation will happen later
         */
        { /* end of list */ }
    },
};

QemuOptsList qemu_nic_opts = {
    .name = "nic",
    .implied_opt_name = "type",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_nic_opts.head),
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642
    .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 */ }
    },
};
1643 1644

void net_socket_rs_init(SocketReadState *rs,
1645 1646
                        SocketReadStateFinalize *finalize,
                        bool vnet_hdr)
1647 1648
{
    rs->state = 0;
1649
    rs->vnet_hdr = vnet_hdr;
1650 1651
    rs->index = 0;
    rs->packet_len = 0;
1652
    rs->vnet_hdr_len = 0;
1653 1654 1655 1656 1657 1658
    memset(rs->buf, 0, sizeof(rs->buf));
    rs->finalize = finalize;
}

/*
 * Returns
1659 1660
 * 0: success
 * -1: error occurs
1661 1662 1663 1664 1665 1666
 */
int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size)
{
    unsigned int l;

    while (size > 0) {
1667 1668 1669 1670 1671 1672
        /* Reassemble a packet from the network.
         * 0 = getting length.
         * 1 = getting vnet header length.
         * 2 = getting data.
         */
        switch (rs->state) {
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
        case 0:
            l = 4 - rs->index;
            if (l > size) {
                l = size;
            }
            memcpy(rs->buf + rs->index, buf, l);
            buf += l;
            size -= l;
            rs->index += l;
            if (rs->index == 4) {
                /* got length */
                rs->packet_len = ntohl(*(uint32_t *)rs->buf);
                rs->index = 0;
1686 1687 1688 1689 1690 1691
                if (rs->vnet_hdr) {
                    rs->state = 1;
                } else {
                    rs->state = 2;
                    rs->vnet_hdr_len = 0;
                }
1692 1693 1694
            }
            break;
        case 1:
1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710
            l = 4 - rs->index;
            if (l > size) {
                l = size;
            }
            memcpy(rs->buf + rs->index, buf, l);
            buf += l;
            size -= l;
            rs->index += l;
            if (rs->index == 4) {
                /* got vnet header length */
                rs->vnet_hdr_len = ntohl(*(uint32_t *)rs->buf);
                rs->index = 0;
                rs->state = 2;
            }
            break;
        case 2:
1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729
            l = rs->packet_len - rs->index;
            if (l > size) {
                l = size;
            }
            if (rs->index + l <= sizeof(rs->buf)) {
                memcpy(rs->buf + rs->index, buf, l);
            } else {
                fprintf(stderr, "serious error: oversized packet received,"
                    "connection terminated.\n");
                rs->index = rs->state = 0;
                return -1;
            }

            rs->index += l;
            buf += l;
            size -= l;
            if (rs->index >= rs->packet_len) {
                rs->index = 0;
                rs->state = 0;
1730 1731
                assert(rs->finalize);
                rs->finalize(rs);
1732 1733 1734 1735
            }
            break;
        }
    }
1736 1737

    assert(size == 0);
1738 1739
    return 0;
}