Revision f83c6e10 net.c
b/net.c | ||
---|---|---|
110 | 110 |
#include "audio/audio.h" |
111 | 111 |
#include "qemu_socket.h" |
112 | 112 |
#include "qemu-log.h" |
113 |
#include "qemu-config.h" |
|
113 | 114 |
|
114 | 115 |
#include "slirp/libslirp.h" |
115 | 116 |
#include "qemu-queue.h" |
... | ... | |
2400 | 2401 |
} |
2401 | 2402 |
} |
2402 | 2403 |
|
2404 |
static int net_init_nic(QemuOpts *opts, Monitor *mon) |
|
2405 |
{ |
|
2406 |
int idx; |
|
2407 |
NICInfo *nd; |
|
2408 |
|
|
2409 |
idx = nic_get_free_idx(); |
|
2410 |
if (idx == -1 || nb_nics >= MAX_NICS) { |
|
2411 |
qemu_error("Too Many NICs\n"); |
|
2412 |
return -1; |
|
2413 |
} |
|
2414 |
|
|
2415 |
nd = &nd_table[idx]; |
|
2416 |
|
|
2417 |
memset(nd, 0, sizeof(*nd)); |
|
2418 |
|
|
2419 |
nd->vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1); |
|
2420 |
|
|
2421 |
if (qemu_opts_id(opts)) { |
|
2422 |
nd->id = qemu_strdup(qemu_opts_id(opts)); |
|
2423 |
} |
|
2424 |
if (qemu_opt_get(opts, "name")) { |
|
2425 |
nd->name = qemu_strdup(qemu_opt_get(opts, "name")); |
|
2426 |
} |
|
2427 |
if (qemu_opt_get(opts, "model")) { |
|
2428 |
nd->model = qemu_strdup(qemu_opt_get(opts, "model")); |
|
2429 |
} |
|
2430 |
if (qemu_opt_get(opts, "addr")) { |
|
2431 |
nd->devaddr = qemu_strdup(qemu_opt_get(opts, "addr")); |
|
2432 |
} |
|
2433 |
|
|
2434 |
nd->macaddr[0] = 0x52; |
|
2435 |
nd->macaddr[1] = 0x54; |
|
2436 |
nd->macaddr[2] = 0x00; |
|
2437 |
nd->macaddr[3] = 0x12; |
|
2438 |
nd->macaddr[4] = 0x34; |
|
2439 |
nd->macaddr[5] = 0x56 + idx; |
|
2440 |
|
|
2441 |
if (qemu_opt_get(opts, "macaddr") && |
|
2442 |
parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) { |
|
2443 |
qemu_error("invalid syntax for ethernet address\n"); |
|
2444 |
return -1; |
|
2445 |
} |
|
2446 |
|
|
2447 |
nd->nvectors = qemu_opt_get_number(opts, "vectors", NIC_NVECTORS_UNSPECIFIED); |
|
2448 |
if (nd->nvectors != NIC_NVECTORS_UNSPECIFIED && |
|
2449 |
(nd->nvectors < 0 || nd->nvectors > 0x7ffffff)) { |
|
2450 |
qemu_error("invalid # of vectors: %d\n", nd->nvectors); |
|
2451 |
return -1; |
|
2452 |
} |
|
2453 |
|
|
2454 |
nd->used = 1; |
|
2455 |
nd->vlan->nb_guest_devs++; |
|
2456 |
nb_nics++; |
|
2457 |
|
|
2458 |
return idx; |
|
2459 |
} |
|
2460 |
|
|
2461 |
#define NET_COMMON_PARAMS_DESC \ |
|
2462 |
{ \ |
|
2463 |
.name = "type", \ |
|
2464 |
.type = QEMU_OPT_STRING, \ |
|
2465 |
.help = "net client type (nic, tap etc.)", \ |
|
2466 |
}, { \ |
|
2467 |
.name = "vlan", \ |
|
2468 |
.type = QEMU_OPT_NUMBER, \ |
|
2469 |
.help = "vlan number", \ |
|
2470 |
}, { \ |
|
2471 |
.name = "name", \ |
|
2472 |
.type = QEMU_OPT_STRING, \ |
|
2473 |
.help = "identifier for monitor commands", \ |
|
2474 |
} |
|
2475 |
|
|
2476 |
typedef int (*net_client_init_func)(QemuOpts *opts, Monitor *mon); |
|
2477 |
|
|
2478 |
/* magic number, but compiler will warn if too small */ |
|
2479 |
#define NET_MAX_DESC 20 |
|
2480 |
|
|
2481 |
static struct { |
|
2482 |
const char *type; |
|
2483 |
net_client_init_func init; |
|
2484 |
QemuOptDesc desc[NET_MAX_DESC]; |
|
2485 |
} net_client_types[] = { |
|
2486 |
{ |
|
2487 |
.type = "none", |
|
2488 |
.desc = { |
|
2489 |
NET_COMMON_PARAMS_DESC, |
|
2490 |
{ /* end of list */ } |
|
2491 |
}, |
|
2492 |
}, { |
|
2493 |
.type = "nic", |
|
2494 |
.init = net_init_nic, |
|
2495 |
.desc = { |
|
2496 |
NET_COMMON_PARAMS_DESC, |
|
2497 |
{ |
|
2498 |
.name = "macaddr", |
|
2499 |
.type = QEMU_OPT_STRING, |
|
2500 |
.help = "MAC address", |
|
2501 |
}, { |
|
2502 |
.name = "model", |
|
2503 |
.type = QEMU_OPT_STRING, |
|
2504 |
.help = "device model (e1000, rtl8139, virtio etc.)", |
|
2505 |
}, { |
|
2506 |
.name = "addr", |
|
2507 |
.type = QEMU_OPT_STRING, |
|
2508 |
.help = "PCI device address", |
|
2509 |
}, { |
|
2510 |
.name = "vectors", |
|
2511 |
.type = QEMU_OPT_NUMBER, |
|
2512 |
.help = "number of MSI-x vectors, 0 to disable MSI-X", |
|
2513 |
}, |
|
2514 |
{ /* end of list */ } |
|
2515 |
}, |
|
2516 |
}, |
|
2517 |
{ /* end of list */ } |
|
2518 |
}; |
|
2519 |
|
|
2520 |
static int net_client_init_from_opts(Monitor *mon, QemuOpts *opts) |
|
2521 |
{ |
|
2522 |
const char *type; |
|
2523 |
int i; |
|
2524 |
|
|
2525 |
type = qemu_opt_get(opts, "type"); |
|
2526 |
if (!type) { |
|
2527 |
qemu_error("No type specified for -net\n"); |
|
2528 |
return -1; |
|
2529 |
} |
|
2530 |
|
|
2531 |
for (i = 0; net_client_types[i].type != NULL; i++) { |
|
2532 |
if (!strcmp(net_client_types[i].type, type)) { |
|
2533 |
if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) { |
|
2534 |
return -1; |
|
2535 |
} |
|
2536 |
|
|
2537 |
if (net_client_types[i].init) { |
|
2538 |
return net_client_types[i].init(opts, NULL); |
|
2539 |
} else { |
|
2540 |
return 0; |
|
2541 |
} |
|
2542 |
} |
|
2543 |
} |
|
2544 |
|
|
2545 |
qemu_error("Invalid -net type '%s'\n", type); |
|
2546 |
return -1; |
|
2547 |
} |
|
2548 |
|
|
2403 | 2549 |
int net_client_init(Monitor *mon, const char *device, const char *p) |
2404 | 2550 |
{ |
2405 | 2551 |
char buf[1024]; |
... | ... | |
2407 | 2553 |
VLANState *vlan; |
2408 | 2554 |
char *name = NULL; |
2409 | 2555 |
|
2556 |
if (!strcmp(device, "none") || |
|
2557 |
!strcmp(device, "nic")) { |
|
2558 |
QemuOpts *opts; |
|
2559 |
|
|
2560 |
opts = qemu_opts_parse(&qemu_net_opts, p, NULL); |
|
2561 |
if (!opts) { |
|
2562 |
return -1; |
|
2563 |
} |
|
2564 |
|
|
2565 |
qemu_opt_set(opts, "type", device); |
|
2566 |
|
|
2567 |
return net_client_init_from_opts(mon, opts); |
|
2568 |
} |
|
2569 |
|
|
2410 | 2570 |
vlan_id = 0; |
2411 | 2571 |
if (get_param_value(buf, sizeof(buf), "vlan", p)) { |
2412 | 2572 |
vlan_id = strtol(buf, NULL, 0); |
... | ... | |
2416 | 2576 |
if (get_param_value(buf, sizeof(buf), "name", p)) { |
2417 | 2577 |
name = qemu_strdup(buf); |
2418 | 2578 |
} |
2419 |
if (!strcmp(device, "nic")) { |
|
2420 |
static const char * const nic_params[] = { |
|
2421 |
"vlan", "name", "macaddr", "model", "addr", "id", "vectors", NULL |
|
2422 |
}; |
|
2423 |
NICInfo *nd; |
|
2424 |
uint8_t *macaddr; |
|
2425 |
int idx = nic_get_free_idx(); |
|
2426 | 2579 |
|
2427 |
if (check_params(buf, sizeof(buf), nic_params, p) < 0) { |
|
2428 |
qemu_error("invalid parameter '%s' in '%s'\n", buf, p); |
|
2429 |
ret = -1; |
|
2430 |
goto out; |
|
2431 |
} |
|
2432 |
if (idx == -1 || nb_nics >= MAX_NICS) { |
|
2433 |
qemu_error("Too Many NICs\n"); |
|
2434 |
ret = -1; |
|
2435 |
goto out; |
|
2436 |
} |
|
2437 |
nd = &nd_table[idx]; |
|
2438 |
memset(nd, 0, sizeof(*nd)); |
|
2439 |
macaddr = nd->macaddr; |
|
2440 |
macaddr[0] = 0x52; |
|
2441 |
macaddr[1] = 0x54; |
|
2442 |
macaddr[2] = 0x00; |
|
2443 |
macaddr[3] = 0x12; |
|
2444 |
macaddr[4] = 0x34; |
|
2445 |
macaddr[5] = 0x56 + idx; |
|
2446 |
|
|
2447 |
if (get_param_value(buf, sizeof(buf), "macaddr", p)) { |
|
2448 |
if (parse_macaddr(macaddr, buf) < 0) { |
|
2449 |
qemu_error("invalid syntax for ethernet address\n"); |
|
2450 |
ret = -1; |
|
2451 |
goto out; |
|
2452 |
} |
|
2453 |
} |
|
2454 |
if (get_param_value(buf, sizeof(buf), "model", p)) { |
|
2455 |
nd->model = qemu_strdup(buf); |
|
2456 |
} |
|
2457 |
if (get_param_value(buf, sizeof(buf), "addr", p)) { |
|
2458 |
nd->devaddr = qemu_strdup(buf); |
|
2459 |
} |
|
2460 |
if (get_param_value(buf, sizeof(buf), "id", p)) { |
|
2461 |
nd->id = qemu_strdup(buf); |
|
2462 |
} |
|
2463 |
nd->nvectors = NIC_NVECTORS_UNSPECIFIED; |
|
2464 |
if (get_param_value(buf, sizeof(buf), "vectors", p)) { |
|
2465 |
char *endptr; |
|
2466 |
long vectors = strtol(buf, &endptr, 0); |
|
2467 |
if (*endptr) { |
|
2468 |
qemu_error("invalid syntax for # of vectors\n"); |
|
2469 |
ret = -1; |
|
2470 |
goto out; |
|
2471 |
} |
|
2472 |
if (vectors < 0 || vectors > 0x7ffffff) { |
|
2473 |
qemu_error("invalid # of vectors\n"); |
|
2474 |
ret = -1; |
|
2475 |
goto out; |
|
2476 |
} |
|
2477 |
nd->nvectors = vectors; |
|
2478 |
} |
|
2479 |
nd->vlan = vlan; |
|
2480 |
nd->name = name; |
|
2481 |
nd->used = 1; |
|
2482 |
name = NULL; |
|
2483 |
nb_nics++; |
|
2484 |
vlan->nb_guest_devs++; |
|
2485 |
ret = idx; |
|
2486 |
} else |
|
2487 |
if (!strcmp(device, "none")) { |
|
2488 |
if (*p != '\0') { |
|
2489 |
qemu_error("'none' takes no parameters\n"); |
|
2490 |
ret = -1; |
|
2491 |
goto out; |
|
2492 |
} |
|
2493 |
/* does nothing. It is needed to signal that no network cards |
|
2494 |
are wanted */ |
|
2495 |
ret = 0; |
|
2496 |
} else |
|
2497 | 2580 |
#ifdef CONFIG_SLIRP |
2498 | 2581 |
if (!strcmp(device, "user")) { |
2499 | 2582 |
static const char * const slirp_params[] = { |
Also available in: Unified diff