net.c 45.1 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.
 */
P
Peter Maydell 已提交
24
#include "qemu/osdep.h"
B
blueswir1 已提交
25

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
#include "qemu/help_option.h"
36
#include "qapi/qmp/qerror.h"
37
#include "qemu/error-report.h"
38
#include "qemu/sockets.h"
39
#include "qemu/cutils.h"
40
#include "qemu/config-file.h"
L
Luiz Capitulino 已提交
41
#include "qmp-commands.h"
42
#include "hw/qdev.h"
43
#include "qemu/iov.h"
44
#include "qemu/main-loop.h"
45 46
#include "qapi-visit.h"
#include "qapi/opts-visitor.h"
47
#include "sysemu/sysemu.h"
48
#include "sysemu/qtest.h"
Y
Yang Hongyang 已提交
49
#include "net/filter.h"
50
#include "qapi/string-output-visitor.h"
51

52 53 54 55 56
/* Net bridge is currently not supported for W32. */
#if !defined(_WIN32)
# define CONFIG_NET_BRIDGE
#endif

57
static VMChangeStateEntry *net_change_state_entry;
58
static QTAILQ_HEAD(, NetClientState) net_clients;
59

60 61 62 63 64 65 66
const char *host_net_devices[] = {
    "tap",
    "socket",
    "dump",
#ifdef CONFIG_NET_BRIDGE
    "bridge",
#endif
67 68 69
#ifdef CONFIG_NETMAP
    "netmap",
#endif
70 71 72 73 74 75
#ifdef CONFIG_SLIRP
    "user",
#endif
#ifdef CONFIG_VDE
    "vde",
#endif
76
    "vhost-user",
77 78 79
    NULL,
};

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/***********************************************************/
/* 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;
}

103 104
int parse_host_port(struct sockaddr_in *saddr, const char *str,
                    Error **errp)
105 106 107 108 109 110 111
{
    char buf[512];
    struct hostent *he;
    const char *p, *r;
    int port;

    p = str;
112 113 114
    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
        error_setg(errp, "host address '%s' doesn't contain ':' "
                   "separating host from port", str);
115
        return -1;
116
    }
117 118 119 120
    saddr->sin_family = AF_INET;
    if (buf[0] == '\0') {
        saddr->sin_addr.s_addr = 0;
    } else {
121
        if (qemu_isdigit(buf[0])) {
122 123 124
            if (!inet_aton(buf, &saddr->sin_addr)) {
                error_setg(errp, "host address '%s' is not a valid "
                           "IPv4 address", buf);
125
                return -1;
126
            }
127
        } else {
128 129 130
            he = gethostbyname(buf);
            if (he == NULL) {
                error_setg(errp, "can't resolve host address '%s'", buf);
131
                return - 1;
132
            }
133 134 135 136
            saddr->sin_addr = *(struct in_addr *)he->h_addr;
        }
    }
    port = strtol(p, (char **)&r, 0);
137 138
    if (r == p) {
        error_setg(errp, "port number '%s' is invalid", p);
139
        return -1;
140
    }
141 142 143 144
    saddr->sin_port = htons(port);
    return 0;
}

145 146 147 148 149 150 151
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]);
}

152
void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
153
{
154
    snprintf(nc->info_str, sizeof(nc->info_str),
155
             "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
156
             nc->model,
157 158 159 160
             macaddr[0], macaddr[1], macaddr[2],
             macaddr[3], macaddr[4], macaddr[5]);
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
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 已提交
202 203 204
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
{
    static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };
205 206 207 208 209 210 211 212 213 214
    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 已提交
215 216 217 218 219 220

    macaddr->a[0] = 0x52;
    macaddr->a[1] = 0x54;
    macaddr->a[2] = 0x00;
    macaddr->a[3] = 0x12;
    macaddr->a[4] = 0x34;
221 222
    macaddr->a[5] = qemu_macaddr_get_free();
    qemu_macaddr_set_used(macaddr);
G
Gerd Hoffmann 已提交
223 224
}

225 226 227
/**
 * Generate a name for net client
 *
A
Amos Kong 已提交
228
 * Only net clients created with the legacy -net option and NICs need this.
229
 */
230
static char *assign_name(NetClientState *nc1, const char *model)
231
{
232
    NetClientState *nc;
233 234
    int id = 0;

235 236
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (nc == nc1) {
237
            continue;
238
        }
A
Amos Kong 已提交
239
        if (strcmp(nc->model, model) == 0) {
240 241 242 243
            id++;
        }
    }

244
    return g_strdup_printf("%s.%d", model, id);
245 246
}

247 248 249 250 251
static void qemu_net_client_destructor(NetClientState *nc)
{
    g_free(nc);
}

252 253 254 255
static void qemu_net_client_setup(NetClientState *nc,
                                  NetClientInfo *info,
                                  NetClientState *peer,
                                  const char *model,
256 257
                                  const char *name,
                                  NetClientDestructor *destructor)
258
{
259 260
    nc->info = info;
    nc->model = g_strdup(model);
261
    if (name) {
262
        nc->name = g_strdup(name);
263
    } else {
264
        nc->name = assign_name(nc, model);
265
    }
266

267 268
    if (peer) {
        assert(!peer->peer);
269 270
        nc->peer = peer;
        peer->peer = nc;
271
    }
272
    QTAILQ_INSERT_TAIL(&net_clients, nc, next);
273

274
    nc->incoming_queue = qemu_new_net_queue(qemu_deliver_packet_iov, nc);
275
    nc->destructor = destructor;
Y
Yang Hongyang 已提交
276
    QTAILQ_INIT(&nc->filters);
277 278 279 280 281 282 283 284 285 286 287 288
}

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);
289 290
    qemu_net_client_setup(nc, info, peer, model, name,
                          qemu_net_client_destructor);
291

292
    return nc;
293 294
}

295 296 297 298 299 300
NICState *qemu_new_nic(NetClientInfo *info,
                       NICConf *conf,
                       const char *model,
                       const char *name,
                       void *opaque)
{
J
Jason Wang 已提交
301
    NetClientState **peers = conf->peers.ncs;
302
    NICState *nic;
303
    int i, queues = MAX(1, conf->peers.queues);
304

305
    assert(info->type == NET_CLIENT_DRIVER_NIC);
306 307
    assert(info->size >= sizeof(NICState));

308 309
    nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
    nic->ncs = (void *)nic + info->size;
310 311 312
    nic->conf = conf;
    nic->opaque = opaque;

313 314
    for (i = 0; i < queues; i++) {
        qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
J
Jason Wang 已提交
315 316 317 318
                              NULL);
        nic->ncs[i].queue_index = i;
    }

319 320 321
    return nic;
}

J
Jason Wang 已提交
322 323
NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
{
324
    return nic->ncs + queue_index;
J
Jason Wang 已提交
325 326
}

J
Jason Wang 已提交
327 328
NetClientState *qemu_get_queue(NICState *nic)
{
J
Jason Wang 已提交
329
    return qemu_get_subqueue(nic, 0);
J
Jason Wang 已提交
330 331
}

J
Jason Wang 已提交
332 333
NICState *qemu_get_nic(NetClientState *nc)
{
J
Jason Wang 已提交
334 335
    NetClientState *nc0 = nc - nc->queue_index;

336
    return (NICState *)((void *)nc0 - nc->info->size);
J
Jason Wang 已提交
337 338 339 340 341 342 343 344 345
}

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

    return nic->opaque;
}

346
static void qemu_cleanup_net_client(NetClientState *nc)
347
{
348
    QTAILQ_REMOVE(&net_clients, nc, next);
349

350 351 352
    if (nc->info->cleanup) {
        nc->info->cleanup(nc);
    }
353
}
354

355
static void qemu_free_net_client(NetClientState *nc)
356
{
357 358
    if (nc->incoming_queue) {
        qemu_del_net_queue(nc->incoming_queue);
S
Stefan Hajnoczi 已提交
359
    }
360 361
    if (nc->peer) {
        nc->peer->peer = NULL;
362
    }
363 364
    g_free(nc->name);
    g_free(nc->model);
365 366 367
    if (nc->destructor) {
        nc->destructor(nc);
    }
368 369
}

370
void qemu_del_net_client(NetClientState *nc)
371
{
J
Jason Wang 已提交
372 373
    NetClientState *ncs[MAX_QUEUE_NUM];
    int queues, i;
Y
Yang Hongyang 已提交
374
    NetFilterState *nf, *next;
J
Jason Wang 已提交
375

376
    assert(nc->info->type != NET_CLIENT_DRIVER_NIC);
377

J
Jason Wang 已提交
378 379 380 381
    /* If the NetClientState belongs to a multiqueue backend, we will change all
     * other NetClientStates also.
     */
    queues = qemu_find_net_clients_except(nc->name, ncs,
382
                                          NET_CLIENT_DRIVER_NIC,
J
Jason Wang 已提交
383 384 385
                                          MAX_QUEUE_NUM);
    assert(queues != 0);

Y
Yang Hongyang 已提交
386 387 388 389
    QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
        object_unparent(OBJECT(nf));
    }

390
    /* If there is a peer NIC, delete and cleanup client, but do not free. */
391
    if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
J
Jason Wang 已提交
392
        NICState *nic = qemu_get_nic(nc->peer);
393 394 395 396
        if (nic->peer_deleted) {
            return;
        }
        nic->peer_deleted = true;
J
Jason Wang 已提交
397 398 399 400 401

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

402 403
        if (nc->peer->info->link_status_changed) {
            nc->peer->info->link_status_changed(nc->peer);
404
        }
J
Jason Wang 已提交
405 406 407 408 409

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

410 411 412
        return;
    }

J
Jason Wang 已提交
413 414 415 416
    for (i = 0; i < queues; i++) {
        qemu_cleanup_net_client(ncs[i]);
        qemu_free_net_client(ncs[i]);
    }
J
Jason Wang 已提交
417 418 419 420
}

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

423 424
    qemu_macaddr_set_free(&nic->conf->macaddr);

425
    /* If this is a peer NIC and peer has already been deleted, free it now. */
J
Jason Wang 已提交
426 427 428
    if (nic->peer_deleted) {
        for (i = 0; i < queues; i++) {
            qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);
429 430 431
        }
    }

J
Jason Wang 已提交
432 433 434 435 436 437
    for (i = queues - 1; i >= 0; i--) {
        NetClientState *nc = qemu_get_subqueue(nic, i);

        qemu_cleanup_net_client(nc);
        qemu_free_net_client(nc);
    }
438 439

    g_free(nic);
440 441
}

M
Mark McLoughlin 已提交
442 443
void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
{
444
    NetClientState *nc;
M
Mark McLoughlin 已提交
445

446
    QTAILQ_FOREACH(nc, &net_clients, next) {
447
        if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
J
Jason Wang 已提交
448 449 450
            if (nc->queue_index == 0) {
                func(qemu_get_nic(nc), opaque);
            }
M
Mark McLoughlin 已提交
451 452 453 454
        }
    }
}

455
bool qemu_has_ufo(NetClientState *nc)
456
{
457
    if (!nc || !nc->info->has_ufo) {
458 459 460
        return false;
    }

461
    return nc->info->has_ufo(nc);
462 463
}

464
bool qemu_has_vnet_hdr(NetClientState *nc)
465
{
466
    if (!nc || !nc->info->has_vnet_hdr) {
467 468 469
        return false;
    }

470
    return nc->info->has_vnet_hdr(nc);
471 472
}

473
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
474
{
475
    if (!nc || !nc->info->has_vnet_hdr_len) {
476 477 478
        return false;
    }

479
    return nc->info->has_vnet_hdr_len(nc, len);
480 481
}

482
void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
483
{
484
    if (!nc || !nc->info->using_vnet_hdr) {
485 486 487
        return;
    }

488
    nc->info->using_vnet_hdr(nc, enable);
489 490
}

491
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
492 493
                          int ecn, int ufo)
{
494
    if (!nc || !nc->info->set_offload) {
495 496 497
        return;
    }

498
    nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo);
499 500
}

501
void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
502
{
503
    if (!nc || !nc->info->set_vnet_hdr_len) {
504 505 506
        return;
    }

507
    nc->vnet_hdr_len = len;
508
    nc->info->set_vnet_hdr_len(nc, len);
509 510
}

G
Greg Kurz 已提交
511 512
int qemu_set_vnet_le(NetClientState *nc, bool is_le)
{
513
#ifdef HOST_WORDS_BIGENDIAN
G
Greg Kurz 已提交
514 515 516 517 518
    if (!nc || !nc->info->set_vnet_le) {
        return -ENOSYS;
    }

    return nc->info->set_vnet_le(nc, is_le);
519 520 521
#else
    return 0;
#endif
G
Greg Kurz 已提交
522 523 524 525
}

int qemu_set_vnet_be(NetClientState *nc, bool is_be)
{
526 527 528
#ifdef HOST_WORDS_BIGENDIAN
    return 0;
#else
G
Greg Kurz 已提交
529 530 531 532 533
    if (!nc || !nc->info->set_vnet_be) {
        return -ENOSYS;
    }

    return nc->info->set_vnet_be(nc, is_be);
534
#endif
G
Greg Kurz 已提交
535 536
}

537
int qemu_can_send_packet(NetClientState *sender)
538
{
539 540 541 542 543 544
    int vm_running = runstate_is_running();

    if (!vm_running) {
        return 0;
    }

S
Stefan Hajnoczi 已提交
545
    if (!sender->peer) {
546 547 548
        return 1;
    }

S
Stefan Hajnoczi 已提交
549 550 551 552 553
    if (sender->peer->receive_disabled) {
        return 0;
    } else if (sender->peer->info->can_receive &&
               !sender->peer->info->can_receive(sender->peer)) {
        return 0;
554
    }
555
    return 1;
556 557
}

558 559 560 561 562 563 564 565 566 567 568
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;

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
    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;
            }
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
        }
    }

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

606
void qemu_purge_queued_packets(NetClientState *nc)
607
{
608
    if (!nc->peer) {
609
        return;
610
    }
611

612
    qemu_net_queue_purge(nc->peer->incoming_queue, nc);
613 614
}

615 616
static
void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
617
{
618
    nc->receive_disabled = 0;
619

620
    if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_HUBPORT) {
621 622 623 624
        if (net_hub_flush(nc->peer)) {
            qemu_notify_event();
        }
    }
625
    if (qemu_net_queue_flush(nc->incoming_queue)) {
626 627 628 629
        /* We emptied the queue successfully, signal to the IO thread to repoll
         * the file descriptor (for tap, for example).
         */
        qemu_notify_event();
630 631 632
    } else if (purge) {
        /* Unable to empty the queue, purge remaining packets */
        qemu_net_queue_purge(nc->incoming_queue, nc);
633
    }
634 635
}

636 637 638 639 640
void qemu_flush_queued_packets(NetClientState *nc)
{
    qemu_flush_or_purge_queued_packets(nc, false);
}

641
static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
642 643 644
                                                 unsigned flags,
                                                 const uint8_t *buf, int size,
                                                 NetPacketSent *sent_cb)
645
{
646
    NetQueue *queue;
647
    int ret;
648

649
#ifdef DEBUG_NET
650
    printf("qemu_send_packet_async:\n");
651
    qemu_hexdump((const char *)buf, stdout, "net", size);
652
#endif
653

S
Stefan Hajnoczi 已提交
654
    if (sender->link_down || !sender->peer) {
655 656 657
        return size;
    }

658 659 660 661 662 663 664 665 666 667 668 669 670
    /* 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;
    }

671
    queue = sender->peer->incoming_queue;
672

673 674 675
    return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
}

676
ssize_t qemu_send_packet_async(NetClientState *sender,
677 678 679 680 681
                               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);
682 683
}

684
void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
685
{
686
    qemu_send_packet_async(nc, buf, size, NULL);
687 688
}

689
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
690
{
691
    return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
692 693 694
                                             buf, size, NULL);
}

695
static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
696
                               int iovcnt, unsigned flags)
A
aliguori 已提交
697
{
698
    uint8_t *buf = NULL;
699
    uint8_t *buffer;
B
Benjamin Poirier 已提交
700
    size_t offset;
701
    ssize_t ret;
A
aliguori 已提交
702

703 704 705 706
    if (iovcnt == 1) {
        buffer = iov[0].iov_base;
        offset = iov[0].iov_len;
    } else {
707 708 709 710 711
        offset = iov_size(iov, iovcnt);
        if (offset > NET_BUFSIZE) {
            return -1;
        }
        buf = g_malloc(offset);
712
        buffer = buf;
713
        offset = iov_to_buf(iov, iovcnt, 0, buf, offset);
714
    }
A
aliguori 已提交
715

716
    if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
717
        ret = nc->info->receive_raw(nc, buffer, offset);
718
    } else {
719
        ret = nc->info->receive(nc, buffer, offset);
720
    }
721 722 723

    g_free(buf);
    return ret;
A
aliguori 已提交
724 725
}

726 727 728 729 730
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
                                unsigned flags,
                                const struct iovec *iov,
                                int iovcnt,
                                void *opaque)
731
{
732
    NetClientState *nc = opaque;
733
    int ret;
734

735
    if (nc->link_down) {
B
Benjamin Poirier 已提交
736
        return iov_size(iov, iovcnt);
737 738
    }

739 740 741 742
    if (nc->receive_disabled) {
        return 0;
    }

743
    if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) {
744
        ret = nc->info->receive_iov(nc, iov, iovcnt);
745
    } else {
746
        ret = nc_sendv_compat(nc, iov, iovcnt, flags);
747 748 749 750
    }

    if (ret == 0) {
        nc->receive_disabled = 1;
751
    }
752 753

    return ret;
754 755
}

756
ssize_t qemu_sendv_packet_async(NetClientState *sender,
757 758
                                const struct iovec *iov, int iovcnt,
                                NetPacketSent *sent_cb)
759
{
760
    NetQueue *queue;
761
    int ret;
762

S
Stefan Hajnoczi 已提交
763
    if (sender->link_down || !sender->peer) {
B
Benjamin Poirier 已提交
764
        return iov_size(iov, iovcnt);
765 766
    }

767 768 769 770 771 772 773 774 775 776 777 778 779
    /* 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;
    }

780
    queue = sender->peer->incoming_queue;
781

782 783 784
    return qemu_net_queue_send_iov(queue, sender,
                                   QEMU_NET_PACKET_FLAG_NONE,
                                   iov, iovcnt, sent_cb);
A
aliguori 已提交
785 786
}

787
ssize_t
788
qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
789
{
790
    return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
791 792
}

793
NetClientState *qemu_find_netdev(const char *id)
M
Mark McLoughlin 已提交
794
{
795
    NetClientState *nc;
M
Mark McLoughlin 已提交
796

797
    QTAILQ_FOREACH(nc, &net_clients, next) {
798
        if (nc->info->type == NET_CLIENT_DRIVER_NIC)
799
            continue;
800 801
        if (!strcmp(nc->name, id)) {
            return nc;
M
Mark McLoughlin 已提交
802 803 804 805 806 807
        }
    }

    return NULL;
}

808
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
809
                                 NetClientDriver type, int max)
810 811 812 813 814 815 816 817
{
    NetClientState *nc;
    int ret = 0;

    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (nc->info->type == type) {
            continue;
        }
818
        if (!id || !strcmp(nc->name, id)) {
819 820 821 822 823 824 825 826 827 828
            if (ret < max) {
                ncs[ret] = nc;
            }
            ret++;
        }
    }

    return ret;
}

829 830 831 832 833 834 835 836 837 838
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;
}

839 840 841 842
int qemu_show_nic_models(const char *arg, const char *const *models)
{
    int i;

843
    if (!arg || !is_help_option(arg)) {
844
        return 0;
845
    }
846 847 848 849 850 851 852

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

853 854 855 856 857 858 859
void qemu_check_nic_model(NICInfo *nd, const char *model)
{
    const char *models[2];

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

860 861 862 863
    if (qemu_show_nic_models(nd->model, models))
        exit(0);
    if (qemu_find_nic_model(nd, models, model) < 0)
        exit(1);
864 865
}

866 867
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                        const char *default_model)
868
{
869
    int i;
870 871

    if (!nd->model)
872
        nd->model = g_strdup(default_model);
873

874 875 876
    for (i = 0 ; models[i]; i++) {
        if (strcmp(nd->model, models[i]) == 0)
            return i;
877 878
    }

879
    error_report("Unsupported NIC model: %s", nd->model);
880
    return -1;
881 882
}

883
static int net_init_nic(const Netdev *netdev, const char *name,
884
                        NetClientState *peer, Error **errp)
885 886 887
{
    int idx;
    NICInfo *nd;
888 889
    const NetLegacyNicOptions *nic;

890 891
    assert(netdev->type == NET_CLIENT_DRIVER_NIC);
    nic = &netdev->u.nic;
892 893 894

    idx = nic_get_free_idx();
    if (idx == -1 || nb_nics >= MAX_NICS) {
895
        error_setg(errp, "too many NICs");
896 897 898 899 900 901 902
        return -1;
    }

    nd = &nd_table[idx];

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

903 904
    if (nic->has_netdev) {
        nd->netdev = qemu_find_netdev(nic->netdev);
M
Mark McLoughlin 已提交
905
        if (!nd->netdev) {
906
            error_setg(errp, "netdev '%s' not found", nic->netdev);
M
Mark McLoughlin 已提交
907 908 909
            return -1;
        }
    } else {
910 911
        assert(peer);
        nd->netdev = peer;
M
Mark McLoughlin 已提交
912
    }
913
    nd->name = g_strdup(name);
914 915
    if (nic->has_model) {
        nd->model = g_strdup(nic->model);
916
    }
917 918
    if (nic->has_addr) {
        nd->devaddr = g_strdup(nic->addr);
919 920
    }

921 922
    if (nic->has_macaddr &&
        net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
923
        error_setg(errp, "invalid syntax for ethernet address");
924 925
        return -1;
    }
926 927
    if (nic->has_macaddr &&
        is_multicast_ether_addr(nd->macaddr.a)) {
928 929
        error_setg(errp,
                   "NIC cannot have multicast MAC address (odd 1st byte)");
930 931
        return -1;
    }
932
    qemu_macaddr_default_if_unset(&nd->macaddr);
933

934 935
    if (nic->has_vectors) {
        if (nic->vectors > 0x7ffffff) {
936
            error_setg(errp, "invalid # of vectors: %"PRIu32, nic->vectors);
937 938 939 940 941
            return -1;
        }
        nd->nvectors = nic->vectors;
    } else {
        nd->nvectors = DEV_NVECTORS_UNSPECIFIED;
942 943 944 945 946 947 948 949
    }

    nd->used = 1;
    nb_nics++;

    return idx;
}

950

951
static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
952
    const Netdev *netdev,
953
    const char *name,
954
    NetClientState *peer, Error **errp) = {
955
        [NET_CLIENT_DRIVER_NIC]       = net_init_nic,
M
Mark McLoughlin 已提交
956
#ifdef CONFIG_SLIRP
957
        [NET_CLIENT_DRIVER_USER]      = net_init_slirp,
958
#endif
959 960
        [NET_CLIENT_DRIVER_TAP]       = net_init_tap,
        [NET_CLIENT_DRIVER_SOCKET]    = net_init_socket,
M
Mark McLoughlin 已提交
961
#ifdef CONFIG_VDE
962
        [NET_CLIENT_DRIVER_VDE]       = net_init_vde,
963 964
#endif
#ifdef CONFIG_NETMAP
965
        [NET_CLIENT_DRIVER_NETMAP]    = net_init_netmap,
M
Mark McLoughlin 已提交
966
#endif
967
        [NET_CLIENT_DRIVER_DUMP]      = net_init_dump,
968
#ifdef CONFIG_NET_BRIDGE
969
        [NET_CLIENT_DRIVER_BRIDGE]    = net_init_bridge,
970
#endif
971
        [NET_CLIENT_DRIVER_HUBPORT]   = net_init_hubport,
972
#ifdef CONFIG_VHOST_NET_USED
973
        [NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
974
#endif
975
#ifdef CONFIG_L2TPV3
976
        [NET_CLIENT_DRIVER_L2TPV3]    = net_init_l2tpv3,
A
Anton Ivanov 已提交
977
#endif
978 979
};

980

E
Eric Blake 已提交
981
static int net_client_init1(const void *object, bool is_netdev, Error **errp)
982
{
983 984
    Netdev legacy = {0};
    const Netdev *netdev;
985
    const char *name;
986
    NetClientState *peer = NULL;
987
    static bool vlan_warned;
988

989
    if (is_netdev) {
990
        netdev = object;
991
        name = netdev->id;
992

993 994 995
        if (netdev->type == NET_CLIENT_DRIVER_DUMP ||
            netdev->type == NET_CLIENT_DRIVER_NIC ||
            !net_client_init_fun[netdev->type]) {
996 997
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
                       "a netdev backend type");
M
Mark McLoughlin 已提交
998 999
            return -1;
        }
1000
    } else {
1001
        const NetLegacy *net = object;
1002
        const NetLegacyOptions *opts = net->opts;
1003 1004
        legacy.id = net->id;
        netdev = &legacy;
1005
        /* missing optional values have been initialized to "all bits zero" */
1006
        name = net->has_id ? net->id : net->name;
1007

1008 1009
        /* Map the old options to the new flat type */
        switch (opts->type) {
1010
        case NET_LEGACY_OPTIONS_TYPE_NONE:
1011
            return 0; /* nothing to do */
1012
        case NET_LEGACY_OPTIONS_TYPE_NIC:
1013
            legacy.type = NET_CLIENT_DRIVER_NIC;
1014
            legacy.u.nic = opts->u.nic;
1015
            break;
1016
        case NET_LEGACY_OPTIONS_TYPE_USER:
1017
            legacy.type = NET_CLIENT_DRIVER_USER;
1018
            legacy.u.user = opts->u.user;
1019
            break;
1020
        case NET_LEGACY_OPTIONS_TYPE_TAP:
1021
            legacy.type = NET_CLIENT_DRIVER_TAP;
1022
            legacy.u.tap = opts->u.tap;
1023
            break;
1024
        case NET_LEGACY_OPTIONS_TYPE_L2TPV3:
1025
            legacy.type = NET_CLIENT_DRIVER_L2TPV3;
1026
            legacy.u.l2tpv3 = opts->u.l2tpv3;
1027
            break;
1028
        case NET_LEGACY_OPTIONS_TYPE_SOCKET:
1029
            legacy.type = NET_CLIENT_DRIVER_SOCKET;
1030
            legacy.u.socket = opts->u.socket;
1031
            break;
1032
        case NET_LEGACY_OPTIONS_TYPE_VDE:
1033
            legacy.type = NET_CLIENT_DRIVER_VDE;
1034
            legacy.u.vde = opts->u.vde;
1035
            break;
1036
        case NET_LEGACY_OPTIONS_TYPE_DUMP:
1037
            legacy.type = NET_CLIENT_DRIVER_DUMP;
1038
            legacy.u.dump = opts->u.dump;
1039
            break;
1040
        case NET_LEGACY_OPTIONS_TYPE_BRIDGE:
1041
            legacy.type = NET_CLIENT_DRIVER_BRIDGE;
1042
            legacy.u.bridge = opts->u.bridge;
1043
            break;
1044
        case NET_LEGACY_OPTIONS_TYPE_NETMAP:
1045
            legacy.type = NET_CLIENT_DRIVER_NETMAP;
1046
            legacy.u.netmap = opts->u.netmap;
1047
            break;
1048
        case NET_LEGACY_OPTIONS_TYPE_VHOST_USER:
1049
            legacy.type = NET_CLIENT_DRIVER_VHOST_USER;
1050
            legacy.u.vhost_user = opts->u.vhost_user;
1051 1052 1053
            break;
        default:
            abort();
1054
        }
1055

1056
        if (!net_client_init_fun[netdev->type]) {
1057 1058 1059 1060 1061
            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 已提交
1062

1063
        /* Do not add to a vlan if it's a nic with a netdev= parameter. */
1064
        if (netdev->type != NET_CLIENT_DRIVER_NIC ||
1065
            !opts->u.nic.has_netdev) {
1066 1067
            peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
        }
1068 1069 1070 1071 1072

        if (net->has_vlan && !vlan_warned) {
            error_report("'vlan' is deprecated. Please use 'netdev' instead.");
            vlan_warned = true;
        }
1073
    }
1074

1075
    if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) {
1076 1077 1078
        /* FIXME drop when all init functions store an Error */
        if (errp && !*errp) {
            error_setg(errp, QERR_DEVICE_INIT_FAILED,
1079
                       NetClientDriver_str(netdev->type));
M
Mark McLoughlin 已提交
1080
        }
1081
        return -1;
M
Mark McLoughlin 已提交
1082
    }
1083 1084 1085
    return 0;
}

M
Mark McLoughlin 已提交
1086

E
Eric Blake 已提交
1087
int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
1088 1089 1090 1091
{
    void *object = NULL;
    Error *err = NULL;
    int ret = -1;
1092
    Visitor *v = opts_visitor_new(opts);
1093

1094 1095
    {
        /* Parse convenience option format ip6-net=fec0::0[/64] */
1096
        const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
1097 1098 1099 1100 1101 1102

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

            if (get_str_sep(buf, sizeof(buf), &ip6_net, '/') < 0) {
                /* Default 64bit prefix length.  */
1103 1104
                qemu_opt_set(opts, "ipv6-prefix", ip6_net, &error_abort);
                qemu_opt_set_number(opts, "ipv6-prefixlen", 64, &error_abort);
1105 1106 1107 1108 1109
            } else {
                /* User-specified prefix length.  */
                unsigned long len;
                int err;

1110
                qemu_opt_set(opts, "ipv6-prefix", buf, &error_abort);
1111 1112 1113 1114
                err = qemu_strtoul(ip6_net, NULL, 10, &len);

                if (err) {
                    error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1115
                              "ipv6-prefix", "a number");
1116
                } else {
1117
                    qemu_opt_set_number(opts, "ipv6-prefixlen", len,
1118 1119 1120
                                        &error_abort);
                }
            }
1121
            qemu_opt_unset(opts, "ipv6-net");
1122 1123 1124
        }
    }

1125 1126 1127 1128
    if (is_netdev) {
        visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
    } else {
        visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
1129 1130
    }

1131
    if (!err) {
1132
        ret = net_client_init1(object, is_netdev, &err);
1133 1134
    }

1135 1136 1137 1138
    if (is_netdev) {
        qapi_free_Netdev(object);
    } else {
        qapi_free_NetLegacy(object);
1139 1140 1141
    }

    error_propagate(errp, err);
1142
    visit_free(v);
1143
    return ret;
1144 1145
}

1146

1147 1148 1149
static int net_host_check_device(const char *device)
{
    int i;
1150 1151 1152
    for (i = 0; host_net_devices[i]; i++) {
        if (!strncmp(host_net_devices[i], device,
                     strlen(host_net_devices[i]))) {
1153
            return 1;
1154
        }
1155 1156 1157 1158 1159
    }

    return 0;
}

1160
void hmp_host_net_add(Monitor *mon, const QDict *qdict)
1161
{
1162
    const char *device = qdict_get_str(qdict, "device");
1163
    const char *opts_str = qdict_get_try_str(qdict, "opts");
1164
    Error *local_err = NULL;
1165
    QemuOpts *opts;
1166 1167 1168 1169 1170 1171
    static bool warned;

    if (!warned && !qtest_enabled()) {
        error_report("host_net_add is deprecated, use netdev_add instead");
        warned = true;
    }
1172

1173
    if (!net_host_check_device(device)) {
A
aliguori 已提交
1174
        monitor_printf(mon, "invalid host network device %s\n", device);
1175 1176
        return;
    }
1177

1178 1179
    opts = qemu_opts_parse_noisily(qemu_find_opts("net"),
                                   opts_str ? opts_str : "", false);
1180 1181 1182 1183
    if (!opts) {
        return;
    }

1184
    qemu_opt_set(opts, "type", device, &error_abort);
1185

E
Eric Blake 已提交
1186
    net_client_init(opts, false, &local_err);
1187
    if (local_err) {
1188
        error_report_err(local_err);
1189 1190
        monitor_printf(mon, "adding host network device %s failed\n", device);
    }
1191 1192
}

1193
void hmp_host_net_remove(Monitor *mon, const QDict *qdict)
1194
{
1195
    NetClientState *nc;
1196 1197
    int vlan_id = qdict_get_int(qdict, "vlan_id");
    const char *device = qdict_get_str(qdict, "device");
1198 1199 1200 1201 1202 1203
    static bool warned;

    if (!warned && !qtest_enabled()) {
        error_report("host_net_remove is deprecated, use netdev_del instead");
        warned = true;
    }
1204

1205 1206
    nc = net_hub_find_client_by_name(vlan_id, device);
    if (!nc) {
1207 1208
        error_report("Host network device '%s' on hub '%d' not found",
                     device, vlan_id);
1209 1210
        return;
    }
1211
    if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
1212
        error_report("invalid host network device '%s'", device);
1213 1214
        return;
    }
1215 1216

    qemu_del_net_client(nc->peer);
1217
    qemu_del_net_client(nc);
1218
    qemu_opts_del(qemu_opts_find(qemu_find_opts("net"), device));
1219 1220
}

L
Luiz Capitulino 已提交
1221 1222
void netdev_add(QemuOpts *opts, Error **errp)
{
E
Eric Blake 已提交
1223
    net_client_init(opts, true, errp);
L
Luiz Capitulino 已提交
1224 1225
}

1226
void qmp_netdev_add(QDict *qdict, QObject **ret, Error **errp)
1227
{
1228
    Error *local_err = NULL;
L
Luiz Capitulino 已提交
1229
    QemuOptsList *opts_list;
1230 1231
    QemuOpts *opts;

L
Luiz Capitulino 已提交
1232
    opts_list = qemu_find_opts_err("netdev", &local_err);
1233
    if (local_err) {
1234
        goto out;
1235 1236
    }

L
Luiz Capitulino 已提交
1237
    opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
1238
    if (local_err) {
1239
        goto out;
L
Luiz Capitulino 已提交
1240 1241 1242
    }

    netdev_add(opts, &local_err);
1243
    if (local_err) {
1244
        qemu_opts_del(opts);
1245
        goto out;
1246 1247
    }

1248 1249
out:
    error_propagate(errp, local_err);
1250 1251
}

L
Luiz Capitulino 已提交
1252
void qmp_netdev_del(const char *id, Error **errp)
1253
{
1254
    NetClientState *nc;
1255
    QemuOpts *opts;
1256

1257 1258
    nc = qemu_find_netdev(id);
    if (!nc) {
1259 1260
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
                  "Device '%s' not found", id);
L
Luiz Capitulino 已提交
1261
        return;
1262
    }
L
Luiz Capitulino 已提交
1263

1264 1265 1266 1267 1268 1269
    opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), id);
    if (!opts) {
        error_setg(errp, "Device '%s' is not a netdev", id);
        return;
    }

1270
    qemu_del_net_client(nc);
1271
    qemu_opts_del(opts);
1272 1273
}

1274 1275 1276 1277 1278
static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
{
    char *str;
    ObjectProperty *prop;
    ObjectPropertyIterator iter;
1279
    Visitor *v;
1280 1281 1282 1283 1284 1285 1286

    /* generate info str */
    object_property_iter_init(&iter, OBJECT(nf));
    while ((prop = object_property_iter_next(&iter))) {
        if (!strcmp(prop->name, "type")) {
            continue;
        }
1287 1288 1289 1290
        v = string_output_visitor_new(false, &str);
        object_property_get(OBJECT(nf), v, prop->name, NULL);
        visit_complete(v, &str);
        visit_free(v);
1291 1292 1293 1294 1295 1296
        monitor_printf(mon, ",%s=%s", prop->name, str);
        g_free(str);
    }
    monitor_printf(mon, "\n");
}

1297
void print_net_client(Monitor *mon, NetClientState *nc)
1298
{
1299 1300
    NetFilterState *nf;

J
Jason Wang 已提交
1301 1302
    monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
                   nc->queue_index,
1303
                   NetClientDriver_str(nc->info->type),
J
Jason Wang 已提交
1304
                   nc->info_str);
1305 1306 1307 1308
    if (!QTAILQ_EMPTY(&nc->filters)) {
        monitor_printf(mon, "filters:\n");
    }
    QTAILQ_FOREACH(nf, &nc->filters, next) {
1309
        char *path = object_get_canonical_path_component(OBJECT(nf));
1310 1311 1312 1313

        monitor_printf(mon, "  - %s: type=%s", path,
                       object_get_typename(OBJECT(nf)));
        netfilter_print_info(mon, nf);
1314
        g_free(path);
1315
    }
1316 1317
}

1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332
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 */
1333
        if (nc->info->type != NET_CLIENT_DRIVER_NIC) {
1334 1335
            if (has_name) {
                error_setg(errp, "net client(%s) isn't a NIC", name);
1336
                return NULL;
1337 1338 1339 1340
            }
            continue;
        }

1341 1342 1343 1344 1345 1346
        /* only query information on queue 0 since the info is per nic,
         * not per queue
         */
        if (nc->queue_index != 0)
            continue;

1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
        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);
1361
            return NULL;
1362
        }
1363 1364 1365 1366

        if (has_name) {
            break;
        }
1367 1368
    }

1369
    if (filter_list == NULL && has_name) {
1370 1371 1372 1373 1374 1375
        error_setg(errp, "invalid net client name: %s", name);
    }

    return filter_list;
}

1376
void hmp_info_network(Monitor *mon, const QDict *qdict)
1377
{
1378
    NetClientState *nc, *peer;
1379
    NetClientDriver type;
1380

1381 1382
    net_hub_info(mon);

1383 1384 1385
    QTAILQ_FOREACH(nc, &net_clients, next) {
        peer = nc->peer;
        type = nc->info->type;
1386

1387 1388 1389
        /* Skip if already printed in hub info */
        if (net_hub_id_for_client(nc, NULL) == 0) {
            continue;
1390
        }
1391

1392
        if (!peer || type == NET_CLIENT_DRIVER_NIC) {
1393
            print_net_client(mon, nc);
1394
        } /* else it's a netdev connected to a NIC, printed with the NIC */
1395
        if (peer && type == NET_CLIENT_DRIVER_NIC) {
1396
            monitor_printf(mon, " \\ ");
1397
            print_net_client(mon, peer);
1398 1399
        }
    }
1400 1401
}

L
Luiz Capitulino 已提交
1402
void qmp_set_link(const char *name, bool up, Error **errp)
1403
{
J
Jason Wang 已提交
1404 1405 1406
    NetClientState *ncs[MAX_QUEUE_NUM];
    NetClientState *nc;
    int queues, i;
1407

J
Jason Wang 已提交
1408
    queues = qemu_find_net_clients_except(name, ncs,
1409
                                          NET_CLIENT_DRIVER__MAX,
J
Jason Wang 已提交
1410 1411 1412
                                          MAX_QUEUE_NUM);

    if (queues == 0) {
1413 1414
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
                  "Device '%s' not found", name);
L
Luiz Capitulino 已提交
1415
        return;
1416
    }
J
Jason Wang 已提交
1417
    nc = ncs[0];
1418

J
Jason Wang 已提交
1419 1420 1421
    for (i = 0; i < queues; i++) {
        ncs[i]->link_down = !up;
    }
1422

1423 1424
    if (nc->info->link_status_changed) {
        nc->info->link_status_changed(nc);
1425
    }
1426

1427 1428 1429 1430 1431 1432 1433 1434 1435
    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.
         */
1436
        if (nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
1437 1438 1439 1440 1441 1442 1443
            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);
        }
1444
    }
1445 1446
}

1447 1448 1449
static void net_vm_change_state_handler(void *opaque, int running,
                                        RunState state)
{
1450 1451
    NetClientState *nc;
    NetClientState *tmp;
1452

1453 1454 1455 1456 1457 1458 1459 1460 1461 1462
    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.
             */
1463 1464 1465 1466 1467
            qemu_flush_or_purge_queued_packets(nc, true);
        }
    }
}

1468 1469
void net_cleanup(void)
{
J
Jason Wang 已提交
1470
    NetClientState *nc;
1471

J
Jason Wang 已提交
1472 1473 1474 1475 1476
    /* 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);
1477
        if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
J
Jason Wang 已提交
1478 1479 1480 1481
            qemu_del_nic(qemu_get_nic(nc));
        } else {
            qemu_del_net_client(nc);
        }
1482
    }
1483 1484

    qemu_del_vm_change_state_handler(net_change_state_entry);
1485 1486
}

1487
void net_check_clients(void)
1488
{
1489
    NetClientState *nc;
1490
    int i;
1491

1492
    net_hub_check_clients();
1493

1494 1495
    QTAILQ_FOREACH(nc, &net_clients, next) {
        if (!nc->peer) {
1496
            warn_report("%s %s has no peer",
A
Alistair Francis 已提交
1497 1498 1499
                        nc->info->type == NET_CLIENT_DRIVER_NIC
                        ? "nic" : "netdev",
                        nc->name);
1500 1501
        }
    }
1502 1503 1504 1505 1506 1507 1508 1509

    /* 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) {
1510 1511 1512 1513
            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");
1514 1515
        }
    }
1516
}
1517

1518
static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
1519
{
1520 1521
    Error *local_err = NULL;

E
Eric Blake 已提交
1522
    net_client_init(opts, false, &local_err);
1523
    if (local_err) {
1524
        error_report_err(local_err);
1525
        return -1;
1526 1527
    }

1528
    return 0;
M
Mark McLoughlin 已提交
1529 1530
}

1531
static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
M
Mark McLoughlin 已提交
1532
{
1533 1534 1535
    Error *local_err = NULL;
    int ret;

E
Eric Blake 已提交
1536
    ret = net_client_init(opts, true, &local_err);
1537
    if (local_err) {
1538
        error_report_err(local_err);
1539 1540 1541 1542
        return -1;
    }

    return ret;
1543 1544 1545 1546
}

int net_init_clients(void)
{
1547 1548
    QemuOptsList *net = qemu_find_opts("net");

1549 1550 1551
    net_change_state_entry =
        qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);

1552
    QTAILQ_INIT(&net_clients);
1553

1554 1555
    if (qemu_opts_foreach(qemu_find_opts("netdev"),
                          net_init_netdev, NULL, NULL)) {
M
Mark McLoughlin 已提交
1556
        return -1;
1557
    }
M
Mark McLoughlin 已提交
1558

1559
    if (qemu_opts_foreach(net, net_init_client, NULL, NULL)) {
1560 1561 1562 1563 1564 1565
        return -1;
    }

    return 0;
}

1566
int net_client_parse(QemuOptsList *opts_list, const char *optarg)
1567
{
1568
#if defined(CONFIG_SLIRP)
1569 1570
    int ret;
    if (net_slirp_parse_legacy(opts_list, optarg, &ret)) {
1571 1572
        return ret;
    }
1573
#endif
1574

1575
    if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
1576 1577 1578 1579 1580
        return -1;
    }

    return 0;
}
1581 1582 1583

/* From FreeBSD */
/* XXX: optimize */
1584
uint32_t net_crc32(const uint8_t *p, int len)
1585 1586 1587 1588 1589 1590
{
    uint32_t crc;
    int carry, i, j;
    uint8_t b;

    crc = 0xffffffff;
1591 1592
    for (i = 0; i < len; i++) {
        b = *p++;
1593 1594 1595 1596 1597
        for (j = 0; j < 8; j++) {
            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
            crc <<= 1;
            b >>= 1;
            if (carry) {
1598
                crc = ((crc ^ POLYNOMIAL_BE) | carry);
1599 1600 1601
            }
        }
    }
1602 1603 1604 1605

    return crc;
}

1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627
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;
}

1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
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 */ }
    },
};
1653 1654

void net_socket_rs_init(SocketReadState *rs,
1655 1656
                        SocketReadStateFinalize *finalize,
                        bool vnet_hdr)
1657 1658
{
    rs->state = 0;
1659
    rs->vnet_hdr = vnet_hdr;
1660 1661
    rs->index = 0;
    rs->packet_len = 0;
1662
    rs->vnet_hdr_len = 0;
1663 1664 1665 1666 1667 1668
    memset(rs->buf, 0, sizeof(rs->buf));
    rs->finalize = finalize;
}

/*
 * Returns
1669 1670
 * 0: success
 * -1: error occurs
1671 1672 1673 1674 1675 1676
 */
int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size)
{
    unsigned int l;

    while (size > 0) {
1677 1678 1679 1680 1681 1682
        /* Reassemble a packet from the network.
         * 0 = getting length.
         * 1 = getting vnet header length.
         * 2 = getting data.
         */
        switch (rs->state) {
1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695
        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;
1696 1697 1698 1699 1700 1701
                if (rs->vnet_hdr) {
                    rs->state = 1;
                } else {
                    rs->state = 2;
                    rs->vnet_hdr_len = 0;
                }
1702 1703 1704
            }
            break;
        case 1:
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720
            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:
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739
            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;
1740 1741
                assert(rs->finalize);
                rs->finalize(rs);
1742 1743 1744 1745
            }
            break;
        }
    }
1746 1747

    assert(size == 0);
1748 1749
    return 0;
}