]> Git Repo - qemu.git/blame - net.c
net: Make "info network" output more readable info
[qemu.git] / net.c
CommitLineData
63a01ef8
AL
1/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
1df49e04 24#include "net.h"
63a01ef8 25
d40cdb10
BS
26#include "config-host.h"
27
a8ed73f7 28#include "net/tap.h"
42281ac9 29#include "net/socket.h"
1abecf77 30#include "net/dump.h"
68ac40d2 31#include "net/slirp.h"
5c361cc3 32#include "net/vde.h"
f6c874e3 33#include "net/hub.h"
f1d078c3 34#include "net/util.h"
511d2b14 35#include "monitor.h"
1df49e04 36#include "qemu-common.h"
511d2b14 37#include "qemu_socket.h"
4b37156c 38#include "qmp-commands.h"
75422b0d 39#include "hw/qdev.h"
ce053661 40#include "iov.h"
6687b79d
LE
41#include "qapi-visit.h"
42#include "qapi/opts-visitor.h"
43#include "qapi/qapi-dealloc-visitor.h"
511d2b14 44
2944e4ec
SW
45/* Net bridge is currently not supported for W32. */
46#if !defined(_WIN32)
47# define CONFIG_NET_BRIDGE
48#endif
49
4e68f7a0 50static QTAILQ_HEAD(, NetClientState) net_clients;
63a01ef8 51
cb4522cc
GH
52int default_net = 1;
53
63a01ef8
AL
54/***********************************************************/
55/* network device redirectors */
56
68ac40d2 57#if defined(DEBUG_NET)
63a01ef8
AL
58static void hex_dump(FILE *f, const uint8_t *buf, int size)
59{
60 int len, i, j, c;
61
62 for(i=0;i<size;i+=16) {
63 len = size - i;
64 if (len > 16)
65 len = 16;
66 fprintf(f, "%08x ", i);
67 for(j=0;j<16;j++) {
68 if (j < len)
69 fprintf(f, " %02x", buf[i+j]);
70 else
71 fprintf(f, " ");
72 }
73 fprintf(f, " ");
74 for(j=0;j<len;j++) {
75 c = buf[i+j];
76 if (c < ' ' || c > '~')
77 c = '.';
78 fprintf(f, "%c", c);
79 }
80 fprintf(f, "\n");
81 }
82}
83#endif
84
63a01ef8
AL
85static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
86{
87 const char *p, *p1;
88 int len;
89 p = *pp;
90 p1 = strchr(p, sep);
91 if (!p1)
92 return -1;
93 len = p1 - p;
94 p1++;
95 if (buf_size > 0) {
96 if (len > buf_size - 1)
97 len = buf_size - 1;
98 memcpy(buf, p, len);
99 buf[len] = '\0';
100 }
101 *pp = p1;
102 return 0;
103}
104
63a01ef8
AL
105int parse_host_port(struct sockaddr_in *saddr, const char *str)
106{
107 char buf[512];
108 struct hostent *he;
109 const char *p, *r;
110 int port;
111
112 p = str;
113 if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
114 return -1;
115 saddr->sin_family = AF_INET;
116 if (buf[0] == '\0') {
117 saddr->sin_addr.s_addr = 0;
118 } else {
cd390083 119 if (qemu_isdigit(buf[0])) {
63a01ef8
AL
120 if (!inet_aton(buf, &saddr->sin_addr))
121 return -1;
122 } else {
123 if ((he = gethostbyname(buf)) == NULL)
124 return - 1;
125 saddr->sin_addr = *(struct in_addr *)he->h_addr;
126 }
127 }
128 port = strtol(p, (char **)&r, 0);
129 if (r == p)
130 return -1;
131 saddr->sin_port = htons(port);
132 return 0;
133}
134
35277d14 135void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
7cb7434b 136{
35277d14 137 snprintf(nc->info_str, sizeof(nc->info_str),
4dda4063 138 "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
35277d14 139 nc->model,
7cb7434b
AL
140 macaddr[0], macaddr[1], macaddr[2],
141 macaddr[3], macaddr[4], macaddr[5]);
142}
143
76d32cba
GH
144void qemu_macaddr_default_if_unset(MACAddr *macaddr)
145{
146 static int index = 0;
147 static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };
148
149 if (memcmp(macaddr, &zero, sizeof(zero)) != 0)
150 return;
151 macaddr->a[0] = 0x52;
152 macaddr->a[1] = 0x54;
153 macaddr->a[2] = 0x00;
154 macaddr->a[3] = 0x12;
155 macaddr->a[4] = 0x34;
156 macaddr->a[5] = 0x56 + index++;
157}
158
d33d93b2
SH
159/**
160 * Generate a name for net client
161 *
162 * Only net clients created with the legacy -net option need this. Naming is
163 * mandatory for net clients created with -netdev.
164 */
35277d14 165static char *assign_name(NetClientState *nc1, const char *model)
676cff29 166{
35277d14 167 NetClientState *nc;
676cff29
AL
168 char buf[256];
169 int id = 0;
170
35277d14
SH
171 QTAILQ_FOREACH(nc, &net_clients, next) {
172 if (nc == nc1) {
d33d93b2
SH
173 continue;
174 }
175 /* For compatibility only bump id for net clients on a vlan */
35277d14
SH
176 if (strcmp(nc->model, model) == 0 &&
177 net_hub_id_for_client(nc, NULL) == 0) {
53e51d85
MA
178 id++;
179 }
180 }
181
676cff29
AL
182 snprintf(buf, sizeof(buf), "%s.%d", model, id);
183
7267c094 184 return g_strdup(buf);
676cff29
AL
185}
186
4e68f7a0 187static ssize_t qemu_deliver_packet(NetClientState *sender,
c0b8e49c 188 unsigned flags,
9a6ecb30
MM
189 const uint8_t *data,
190 size_t size,
191 void *opaque);
4e68f7a0 192static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
c0b8e49c 193 unsigned flags,
9a6ecb30
MM
194 const struct iovec *iov,
195 int iovcnt,
196 void *opaque);
197
4e68f7a0
SH
198NetClientState *qemu_new_net_client(NetClientInfo *info,
199 NetClientState *peer,
200 const char *model,
201 const char *name)
63a01ef8 202{
35277d14 203 NetClientState *nc;
5610c3aa 204
4e68f7a0 205 assert(info->size >= sizeof(NetClientState));
45460d1a 206
35277d14 207 nc = g_malloc0(info->size);
5610c3aa 208
35277d14
SH
209 nc->info = info;
210 nc->model = g_strdup(model);
45460d1a 211 if (name) {
35277d14 212 nc->name = g_strdup(name);
45460d1a 213 } else {
35277d14 214 nc->name = assign_name(nc, model);
45460d1a 215 }
5610c3aa 216
ab5f3f84
SH
217 if (peer) {
218 assert(!peer->peer);
35277d14
SH
219 nc->peer = peer;
220 peer->peer = nc;
d80b9fc6 221 }
35277d14 222 QTAILQ_INSERT_TAIL(&net_clients, nc, next);
ab5f3f84 223
35277d14 224 nc->send_queue = qemu_new_net_queue(qemu_deliver_packet,
ab5f3f84 225 qemu_deliver_packet_iov,
35277d14 226 nc);
63a01ef8 227
35277d14 228 return nc;
63a01ef8
AL
229}
230
ebef2c09
MM
231NICState *qemu_new_nic(NetClientInfo *info,
232 NICConf *conf,
233 const char *model,
234 const char *name,
235 void *opaque)
236{
4e68f7a0 237 NetClientState *nc;
ebef2c09
MM
238 NICState *nic;
239
2be64a68 240 assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
ebef2c09
MM
241 assert(info->size >= sizeof(NICState));
242
ab5f3f84 243 nc = qemu_new_net_client(info, conf->peer, model, name);
ebef2c09
MM
244
245 nic = DO_UPCAST(NICState, nc, nc);
246 nic->conf = conf;
247 nic->opaque = opaque;
248
249 return nic;
250}
251
b20c6b9e 252static void qemu_cleanup_net_client(NetClientState *nc)
63a01ef8 253{
35277d14 254 QTAILQ_REMOVE(&net_clients, nc, next);
63a01ef8 255
35277d14
SH
256 if (nc->info->cleanup) {
257 nc->info->cleanup(nc);
5610c3aa 258 }
a083a89d 259}
5610c3aa 260
b20c6b9e 261static void qemu_free_net_client(NetClientState *nc)
a083a89d 262{
35277d14
SH
263 if (nc->send_queue) {
264 qemu_del_net_queue(nc->send_queue);
a005d073 265 }
35277d14
SH
266 if (nc->peer) {
267 nc->peer->peer = NULL;
a083a89d 268 }
35277d14
SH
269 g_free(nc->name);
270 g_free(nc->model);
271 g_free(nc);
63a01ef8
AL
272}
273
b20c6b9e 274void qemu_del_net_client(NetClientState *nc)
a083a89d
MT
275{
276 /* If there is a peer NIC, delete and cleanup client, but do not free. */
35277d14
SH
277 if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
278 NICState *nic = DO_UPCAST(NICState, nc, nc->peer);
a083a89d
MT
279 if (nic->peer_deleted) {
280 return;
281 }
282 nic->peer_deleted = true;
283 /* Let NIC know peer is gone. */
35277d14
SH
284 nc->peer->link_down = true;
285 if (nc->peer->info->link_status_changed) {
286 nc->peer->info->link_status_changed(nc->peer);
a083a89d 287 }
b20c6b9e 288 qemu_cleanup_net_client(nc);
a083a89d
MT
289 return;
290 }
291
292 /* If this is a peer NIC and peer has already been deleted, free it now. */
35277d14
SH
293 if (nc->peer && nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
294 NICState *nic = DO_UPCAST(NICState, nc, nc);
a083a89d 295 if (nic->peer_deleted) {
b20c6b9e 296 qemu_free_net_client(nc->peer);
a083a89d
MT
297 }
298 }
299
b20c6b9e
SH
300 qemu_cleanup_net_client(nc);
301 qemu_free_net_client(nc);
a083a89d
MT
302}
303
57f9ef17
MM
304void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
305{
4e68f7a0 306 NetClientState *nc;
57f9ef17 307
94878994 308 QTAILQ_FOREACH(nc, &net_clients, next) {
2be64a68 309 if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
57f9ef17
MM
310 func(DO_UPCAST(NICState, nc, nc), opaque);
311 }
312 }
57f9ef17
MM
313}
314
4e68f7a0 315int qemu_can_send_packet(NetClientState *sender)
63a01ef8 316{
a005d073 317 if (!sender->peer) {
d80b9fc6
MM
318 return 1;
319 }
320
a005d073
SH
321 if (sender->peer->receive_disabled) {
322 return 0;
323 } else if (sender->peer->info->can_receive &&
324 !sender->peer->info->can_receive(sender->peer)) {
325 return 0;
63a01ef8 326 }
60c07d93 327 return 1;
63a01ef8
AL
328}
329
4e68f7a0 330static ssize_t qemu_deliver_packet(NetClientState *sender,
c0b8e49c 331 unsigned flags,
9a6ecb30
MM
332 const uint8_t *data,
333 size_t size,
334 void *opaque)
335{
35277d14 336 NetClientState *nc = opaque;
893379ef 337 ssize_t ret;
9a6ecb30 338
35277d14 339 if (nc->link_down) {
9a6ecb30
MM
340 return size;
341 }
342
35277d14 343 if (nc->receive_disabled) {
893379ef
MM
344 return 0;
345 }
346
35277d14
SH
347 if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
348 ret = nc->info->receive_raw(nc, data, size);
893379ef 349 } else {
35277d14 350 ret = nc->info->receive(nc, data, size);
893379ef
MM
351 }
352
353 if (ret == 0) {
35277d14 354 nc->receive_disabled = 1;
893379ef
MM
355 };
356
357 return ret;
9a6ecb30
MM
358}
359
35277d14 360void qemu_purge_queued_packets(NetClientState *nc)
8cad5516 361{
35277d14 362 if (!nc->peer) {
d80b9fc6 363 return;
9a6ecb30 364 }
d80b9fc6 365
35277d14 366 qemu_net_queue_purge(nc->peer->send_queue, nc);
8cad5516
MM
367}
368
35277d14 369void qemu_flush_queued_packets(NetClientState *nc)
e94667b9 370{
35277d14 371 nc->receive_disabled = 0;
893379ef 372
35277d14 373 qemu_net_queue_flush(nc->send_queue);
e94667b9
MM
374}
375
4e68f7a0 376static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
ca77d175
MM
377 unsigned flags,
378 const uint8_t *buf, int size,
379 NetPacketSent *sent_cb)
764a4d1d 380{
9a6ecb30 381 NetQueue *queue;
436e5e53 382
63a01ef8 383#ifdef DEBUG_NET
d80b9fc6 384 printf("qemu_send_packet_async:\n");
63a01ef8
AL
385 hex_dump(stdout, buf, size);
386#endif
f3b6c7fc 387
a005d073 388 if (sender->link_down || !sender->peer) {
9a6ecb30
MM
389 return size;
390 }
391
a005d073 392 queue = sender->peer->send_queue;
9a6ecb30 393
ca77d175
MM
394 return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
395}
396
4e68f7a0 397ssize_t qemu_send_packet_async(NetClientState *sender,
ca77d175
MM
398 const uint8_t *buf, int size,
399 NetPacketSent *sent_cb)
400{
401 return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
402 buf, size, sent_cb);
f3b6c7fc
MM
403}
404
35277d14 405void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
f3b6c7fc 406{
35277d14 407 qemu_send_packet_async(nc, buf, size, NULL);
63a01ef8
AL
408}
409
35277d14 410ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
ca77d175 411{
35277d14 412 return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
ca77d175
MM
413 buf, size, NULL);
414}
415
35277d14 416static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
fbe78f4f
AL
417 int iovcnt)
418{
419 uint8_t buffer[4096];
ce053661 420 size_t offset;
fbe78f4f 421
dcf6f5e1 422 offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
fbe78f4f 423
35277d14 424 return nc->info->receive(nc, buffer, offset);
fbe78f4f
AL
425}
426
4e68f7a0 427static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
c0b8e49c 428 unsigned flags,
9a6ecb30
MM
429 const struct iovec *iov,
430 int iovcnt,
431 void *opaque)
432{
35277d14 433 NetClientState *nc = opaque;
9a6ecb30 434
35277d14 435 if (nc->link_down) {
ce053661 436 return iov_size(iov, iovcnt);
9a6ecb30
MM
437 }
438
35277d14
SH
439 if (nc->info->receive_iov) {
440 return nc->info->receive_iov(nc, iov, iovcnt);
9a6ecb30 441 } else {
35277d14 442 return nc_sendv_compat(nc, iov, iovcnt);
9a6ecb30
MM
443 }
444}
445
4e68f7a0 446ssize_t qemu_sendv_packet_async(NetClientState *sender,
f3b6c7fc
MM
447 const struct iovec *iov, int iovcnt,
448 NetPacketSent *sent_cb)
e94667b9 449{
9a6ecb30
MM
450 NetQueue *queue;
451
a005d073 452 if (sender->link_down || !sender->peer) {
ce053661 453 return iov_size(iov, iovcnt);
e94667b9
MM
454 }
455
a005d073 456 queue = sender->peer->send_queue;
9a6ecb30 457
c0b8e49c
MM
458 return qemu_net_queue_send_iov(queue, sender,
459 QEMU_NET_PACKET_FLAG_NONE,
460 iov, iovcnt, sent_cb);
fbe78f4f
AL
461}
462
f3b6c7fc 463ssize_t
35277d14 464qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
f3b6c7fc 465{
35277d14 466 return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
f3b6c7fc
MM
467}
468
4e68f7a0 469NetClientState *qemu_find_netdev(const char *id)
5869c4d5 470{
35277d14 471 NetClientState *nc;
5869c4d5 472
35277d14
SH
473 QTAILQ_FOREACH(nc, &net_clients, next) {
474 if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC)
85dde9a9 475 continue;
35277d14
SH
476 if (!strcmp(nc->name, id)) {
477 return nc;
5869c4d5
MM
478 }
479 }
480
481 return NULL;
482}
483
7697079b
AL
484static int nic_get_free_idx(void)
485{
486 int index;
487
488 for (index = 0; index < MAX_NICS; index++)
489 if (!nd_table[index].used)
490 return index;
491 return -1;
492}
493
07caea31
MA
494int qemu_show_nic_models(const char *arg, const char *const *models)
495{
496 int i;
497
498 if (!arg || strcmp(arg, "?"))
499 return 0;
500
501 fprintf(stderr, "qemu: Supported NIC models: ");
502 for (i = 0 ; models[i]; i++)
503 fprintf(stderr, "%s%c", models[i], models[i+1] ? ',' : '\n');
504 return 1;
505}
506
d07f22c5
AL
507void qemu_check_nic_model(NICInfo *nd, const char *model)
508{
509 const char *models[2];
510
511 models[0] = model;
512 models[1] = NULL;
513
07caea31
MA
514 if (qemu_show_nic_models(nd->model, models))
515 exit(0);
516 if (qemu_find_nic_model(nd, models, model) < 0)
517 exit(1);
d07f22c5
AL
518}
519
07caea31
MA
520int qemu_find_nic_model(NICInfo *nd, const char * const *models,
521 const char *default_model)
d07f22c5 522{
07caea31 523 int i;
d07f22c5
AL
524
525 if (!nd->model)
7267c094 526 nd->model = g_strdup(default_model);
d07f22c5 527
07caea31
MA
528 for (i = 0 ; models[i]; i++) {
529 if (strcmp(nd->model, models[i]) == 0)
530 return i;
d07f22c5
AL
531 }
532
6daf194d 533 error_report("Unsupported NIC model: %s", nd->model);
07caea31 534 return -1;
d07f22c5
AL
535}
536
5281d757 537int net_handle_fd_param(Monitor *mon, const char *param)
c1d6eed7 538{
f7c31d63
JW
539 int fd;
540
541 if (!qemu_isdigit(param[0]) && mon) {
c1d6eed7
MM
542
543 fd = monitor_get_fd(mon, param);
544 if (fd == -1) {
1ecda02b 545 error_report("No file descriptor named %s found", param);
c1d6eed7
MM
546 return -1;
547 }
c1d6eed7 548 } else {
443916d1 549 fd = qemu_parse_fd(param);
c1d6eed7 550 }
f7c31d63
JW
551
552 return fd;
c1d6eed7
MM
553}
554
1a0c0958 555static int net_init_nic(const NetClientOptions *opts, const char *name,
4e68f7a0 556 NetClientState *peer)
f83c6e10
MM
557{
558 int idx;
559 NICInfo *nd;
2456f36f
LE
560 const NetLegacyNicOptions *nic;
561
562 assert(opts->kind == NET_CLIENT_OPTIONS_KIND_NIC);
563 nic = opts->nic;
f83c6e10
MM
564
565 idx = nic_get_free_idx();
566 if (idx == -1 || nb_nics >= MAX_NICS) {
1ecda02b 567 error_report("Too Many NICs");
f83c6e10
MM
568 return -1;
569 }
570
571 nd = &nd_table[idx];
572
573 memset(nd, 0, sizeof(*nd));
574
2456f36f
LE
575 if (nic->has_netdev) {
576 nd->netdev = qemu_find_netdev(nic->netdev);
5869c4d5 577 if (!nd->netdev) {
2456f36f 578 error_report("netdev '%s' not found", nic->netdev);
5869c4d5
MM
579 return -1;
580 }
581 } else {
d33d93b2
SH
582 assert(peer);
583 nd->netdev = peer;
5869c4d5 584 }
6d952ebe 585 if (name) {
7267c094 586 nd->name = g_strdup(name);
6d952ebe 587 }
2456f36f
LE
588 if (nic->has_model) {
589 nd->model = g_strdup(nic->model);
f83c6e10 590 }
2456f36f
LE
591 if (nic->has_addr) {
592 nd->devaddr = g_strdup(nic->addr);
f83c6e10
MM
593 }
594
2456f36f
LE
595 if (nic->has_macaddr &&
596 net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
1ecda02b 597 error_report("invalid syntax for ethernet address");
f83c6e10
MM
598 return -1;
599 }
6eed1856 600 qemu_macaddr_default_if_unset(&nd->macaddr);
f83c6e10 601
2456f36f
LE
602 if (nic->has_vectors) {
603 if (nic->vectors > 0x7ffffff) {
604 error_report("invalid # of vectors: %"PRIu32, nic->vectors);
605 return -1;
606 }
607 nd->nvectors = nic->vectors;
608 } else {
609 nd->nvectors = DEV_NVECTORS_UNSPECIFIED;
f83c6e10
MM
610 }
611
612 nd->used = 1;
f83c6e10
MM
613 nb_nics++;
614
615 return idx;
616}
617
6687b79d
LE
618
619static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
1a0c0958 620 const NetClientOptions *opts,
6687b79d 621 const char *name,
4e68f7a0 622 NetClientState *peer) = {
f6c874e3 623 [NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic,
ec302ffd 624#ifdef CONFIG_SLIRP
f6c874e3 625 [NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp,
2944e4ec 626#endif
f6c874e3
SH
627 [NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap,
628 [NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket,
dd51058d 629#ifdef CONFIG_VDE
f6c874e3 630 [NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde,
dd51058d 631#endif
f6c874e3 632 [NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump,
2944e4ec 633#ifdef CONFIG_NET_BRIDGE
f6c874e3 634 [NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge,
6687b79d 635#endif
f6c874e3 636 [NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport,
f83c6e10
MM
637};
638
6687b79d 639
1a0c0958 640static int net_client_init1(const void *object, int is_netdev, Error **errp)
f83c6e10 641{
6687b79d
LE
642 union {
643 const Netdev *netdev;
644 const NetLegacy *net;
645 } u;
646 const NetClientOptions *opts;
6d952ebe 647 const char *name;
f83c6e10 648
5294e2c7 649 if (is_netdev) {
6687b79d
LE
650 u.netdev = object;
651 opts = u.netdev->opts;
652 name = u.netdev->id;
653
654 switch (opts->kind) {
f6b134ac 655#ifdef CONFIG_SLIRP
6687b79d 656 case NET_CLIENT_OPTIONS_KIND_USER:
f6b134ac 657#endif
6687b79d
LE
658 case NET_CLIENT_OPTIONS_KIND_TAP:
659 case NET_CLIENT_OPTIONS_KIND_SOCKET:
f6b134ac 660#ifdef CONFIG_VDE
6687b79d
LE
661 case NET_CLIENT_OPTIONS_KIND_VDE:
662#endif
663#ifdef CONFIG_NET_BRIDGE
664 case NET_CLIENT_OPTIONS_KIND_BRIDGE:
f6b134ac 665#endif
f6c874e3 666 case NET_CLIENT_OPTIONS_KIND_HUBPORT:
6687b79d
LE
667 break;
668
669 default:
4559a1db
LC
670 error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
671 "a netdev backend type");
f6b134ac
MM
672 return -1;
673 }
6687b79d
LE
674 } else {
675 u.net = object;
676 opts = u.net->opts;
677 /* missing optional values have been initialized to "all bits zero" */
678 name = u.net->has_id ? u.net->id : u.net->name;
679 }
f6b134ac 680
6687b79d 681 if (net_client_init_fun[opts->kind]) {
4e68f7a0 682 NetClientState *peer = NULL;
6687b79d
LE
683
684 /* Do not add to a vlan if it's a -netdev or a nic with a netdev=
685 * parameter. */
686 if (!is_netdev &&
687 (opts->kind != NET_CLIENT_OPTIONS_KIND_NIC ||
688 !opts->nic->has_netdev)) {
d33d93b2 689 peer = net_hub_add_port(u.net->has_vlan ? u.net->vlan : 0, NULL);
f6b134ac 690 }
6687b79d 691
d33d93b2 692 if (net_client_init_fun[opts->kind](opts, name, peer) < 0) {
6687b79d
LE
693 /* TODO push error reporting into init() methods */
694 error_set(errp, QERR_DEVICE_INIT_FAILED,
695 NetClientOptionsKind_lookup[opts->kind]);
f6b134ac
MM
696 return -1;
697 }
698 }
6687b79d
LE
699 return 0;
700}
701
f6b134ac 702
6687b79d
LE
703static void net_visit(Visitor *v, int is_netdev, void **object, Error **errp)
704{
705 if (is_netdev) {
706 visit_type_Netdev(v, (Netdev **)object, NULL, errp);
707 } else {
708 visit_type_NetLegacy(v, (NetLegacy **)object, NULL, errp);
6d952ebe 709 }
6687b79d 710}
6d952ebe 711
f6b134ac 712
6687b79d
LE
713int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
714{
715 void *object = NULL;
716 Error *err = NULL;
717 int ret = -1;
f83c6e10 718
6687b79d
LE
719 {
720 OptsVisitor *ov = opts_visitor_new(opts);
f6b134ac 721
6687b79d
LE
722 net_visit(opts_get_visitor(ov), is_netdev, &object, &err);
723 opts_visitor_cleanup(ov);
f83c6e10
MM
724 }
725
6687b79d 726 if (!err) {
1a0c0958 727 ret = net_client_init1(object, is_netdev, &err);
6687b79d
LE
728 }
729
730 if (object) {
731 QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();
732
733 net_visit(qapi_dealloc_get_visitor(dv), is_netdev, &object, NULL);
734 qapi_dealloc_visitor_cleanup(dv);
735 }
736
737 error_propagate(errp, err);
738 return ret;
f83c6e10
MM
739}
740
6687b79d 741
6f338c34
AL
742static int net_host_check_device(const char *device)
743{
744 int i;
bb9ea79e 745 const char *valid_param_list[] = { "tap", "socket", "dump"
2944e4ec
SW
746#ifdef CONFIG_NET_BRIDGE
747 , "bridge"
748#endif
6f338c34
AL
749#ifdef CONFIG_SLIRP
750 ,"user"
751#endif
752#ifdef CONFIG_VDE
753 ,"vde"
754#endif
755 };
756 for (i = 0; i < sizeof(valid_param_list) / sizeof(char *); i++) {
757 if (!strncmp(valid_param_list[i], device,
758 strlen(valid_param_list[i])))
759 return 1;
760 }
761
762 return 0;
763}
764
f18c16de 765void net_host_device_add(Monitor *mon, const QDict *qdict)
6f338c34 766{
f18c16de 767 const char *device = qdict_get_str(qdict, "device");
7f1c9d20 768 const char *opts_str = qdict_get_try_str(qdict, "opts");
4559a1db 769 Error *local_err = NULL;
7f1c9d20 770 QemuOpts *opts;
f18c16de 771
6f338c34 772 if (!net_host_check_device(device)) {
376253ec 773 monitor_printf(mon, "invalid host network device %s\n", device);
6f338c34
AL
774 return;
775 }
7f1c9d20 776
3329f07b 777 opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0);
7f1c9d20 778 if (!opts) {
7f1c9d20
MM
779 return;
780 }
781
782 qemu_opt_set(opts, "type", device);
783
4559a1db
LC
784 net_client_init(opts, 0, &local_err);
785 if (error_is_set(&local_err)) {
786 qerror_report_err(local_err);
787 error_free(local_err);
5c8be678
AL
788 monitor_printf(mon, "adding host network device %s failed\n", device);
789 }
6f338c34
AL
790}
791
f18c16de 792void net_host_device_remove(Monitor *mon, const QDict *qdict)
6f338c34 793{
35277d14 794 NetClientState *nc;
f18c16de
LC
795 int vlan_id = qdict_get_int(qdict, "vlan_id");
796 const char *device = qdict_get_str(qdict, "device");
6f338c34 797
35277d14
SH
798 nc = net_hub_find_client_by_name(vlan_id, device);
799 if (!nc) {
6f338c34
AL
800 return;
801 }
35277d14 802 if (!net_host_check_device(nc->model)) {
e8f1f9db
AL
803 monitor_printf(mon, "invalid host network device %s\n", device);
804 return;
805 }
b20c6b9e 806 qemu_del_net_client(nc);
6f338c34
AL
807}
808
928059a3
LC
809void netdev_add(QemuOpts *opts, Error **errp)
810{
811 net_client_init(opts, 1, errp);
812}
813
814int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret)
ae82d324 815{
4e89978e 816 Error *local_err = NULL;
928059a3 817 QemuOptsList *opts_list;
ae82d324 818 QemuOpts *opts;
ae82d324 819
928059a3
LC
820 opts_list = qemu_find_opts_err("netdev", &local_err);
821 if (error_is_set(&local_err)) {
822 goto exit_err;
ae82d324
MA
823 }
824
928059a3
LC
825 opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
826 if (error_is_set(&local_err)) {
827 goto exit_err;
828 }
829
830 netdev_add(opts, &local_err);
831 if (error_is_set(&local_err)) {
410cbafe 832 qemu_opts_del(opts);
928059a3 833 goto exit_err;
410cbafe
YT
834 }
835
928059a3
LC
836 return 0;
837
838exit_err:
839 qerror_report_err(local_err);
840 error_free(local_err);
841 return -1;
ae82d324
MA
842}
843
5f964155 844void qmp_netdev_del(const char *id, Error **errp)
ae82d324 845{
35277d14 846 NetClientState *nc;
ae82d324 847
35277d14
SH
848 nc = qemu_find_netdev(id);
849 if (!nc) {
5f964155
LC
850 error_set(errp, QERR_DEVICE_NOT_FOUND, id);
851 return;
ae82d324 852 }
5f964155 853
b20c6b9e 854 qemu_del_net_client(nc);
5f964155 855 qemu_opts_del(qemu_opts_find(qemu_find_opts_err("netdev", errp), id));
ae82d324
MA
856}
857
1a859593 858void print_net_client(Monitor *mon, NetClientState *nc)
44e798d3 859{
35277d14
SH
860 monitor_printf(mon, "%s: type=%s,%s\n", nc->name,
861 NetClientOptionsKind_lookup[nc->info->type], nc->info_str);
44e798d3
JK
862}
863
376253ec 864void do_info_network(Monitor *mon)
63a01ef8 865{
35277d14 866 NetClientState *nc, *peer;
2be64a68 867 NetClientOptionsKind type;
63a01ef8 868
1a859593
ZYW
869 net_hub_info(mon);
870
35277d14
SH
871 QTAILQ_FOREACH(nc, &net_clients, next) {
872 peer = nc->peer;
873 type = nc->info->type;
1a859593
ZYW
874
875 /* Skip if already printed in hub info */
876 if (net_hub_id_for_client(nc, NULL) == 0) {
877 continue;
878 }
879
2be64a68 880 if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) {
35277d14 881 print_net_client(mon, nc);
19061e63 882 } /* else it's a netdev connected to a NIC, printed with the NIC */
2be64a68 883 if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) {
1a859593 884 monitor_printf(mon, " \\ ");
44e798d3 885 print_net_client(mon, peer);
a0104e0e 886 }
a0104e0e 887 }
63a01ef8
AL
888}
889
4b37156c 890void qmp_set_link(const char *name, bool up, Error **errp)
436e5e53 891{
35277d14 892 NetClientState *nc = NULL;
436e5e53 893
35277d14
SH
894 QTAILQ_FOREACH(nc, &net_clients, next) {
895 if (!strcmp(nc->name, name)) {
85dde9a9
MA
896 goto done;
897 }
898 }
dd5de373 899done:
35277d14 900 if (!nc) {
4b37156c
LC
901 error_set(errp, QERR_DEVICE_NOT_FOUND, name);
902 return;
436e5e53
AL
903 }
904
35277d14 905 nc->link_down = !up;
436e5e53 906
35277d14
SH
907 if (nc->info->link_status_changed) {
908 nc->info->link_status_changed(nc);
665a3b07 909 }
ab1cbe1c
MT
910
911 /* Notify peer. Don't update peer link status: this makes it possible to
912 * disconnect from host network without notifying the guest.
913 * FIXME: is disconnected link status change operation useful?
914 *
915 * Current behaviour is compatible with qemu vlans where there could be
916 * multiple clients that can still communicate with each other in
917 * disconnected mode. For now maintain this compatibility. */
35277d14
SH
918 if (nc->peer && nc->peer->info->link_status_changed) {
919 nc->peer->info->link_status_changed(nc->peer);
ab1cbe1c 920 }
436e5e53
AL
921}
922
63a01ef8
AL
923void net_cleanup(void)
924{
35277d14 925 NetClientState *nc, *next_vc;
63a01ef8 926
35277d14 927 QTAILQ_FOREACH_SAFE(nc, &net_clients, next, next_vc) {
b20c6b9e 928 qemu_del_net_client(nc);
577c4af9 929 }
63a01ef8
AL
930}
931
668680f7 932void net_check_clients(void)
63a01ef8 933{
35277d14 934 NetClientState *nc;
48e2faf2 935 int i;
63a01ef8 936
641f6eae
PM
937 /* Don't warn about the default network setup that you get if
938 * no command line -net or -netdev options are specified. There
939 * are two cases that we would otherwise complain about:
940 * (1) board doesn't support a NIC but the implicit "-net nic"
941 * requested one
942 * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic"
943 * sets up a nic that isn't connected to anything.
944 */
945 if (default_net) {
946 return;
947 }
948
81017645 949 net_hub_check_clients();
ac60cc18 950
35277d14
SH
951 QTAILQ_FOREACH(nc, &net_clients, next) {
952 if (!nc->peer) {
efe32fdd 953 fprintf(stderr, "Warning: %s %s has no peer\n",
35277d14
SH
954 nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ?
955 "nic" : "netdev", nc->name);
efe32fdd
MA
956 }
957 }
48e2faf2
PM
958
959 /* Check that all NICs requested via -net nic actually got created.
960 * NICs created via -device don't need to be checked here because
961 * they are always instantiated.
962 */
963 for (i = 0; i < MAX_NICS; i++) {
964 NICInfo *nd = &nd_table[i];
965 if (nd->used && !nd->instantiated) {
966 fprintf(stderr, "Warning: requested NIC (%s, model %s) "
967 "was not created (not supported by this machine?)\n",
968 nd->name ? nd->name : "anonymous",
969 nd->model ? nd->model : "unspecified");
970 }
971 }
63a01ef8 972}
dc1c9fe8
MM
973
974static int net_init_client(QemuOpts *opts, void *dummy)
975{
4559a1db
LC
976 Error *local_err = NULL;
977
978 net_client_init(opts, 0, &local_err);
979 if (error_is_set(&local_err)) {
980 qerror_report_err(local_err);
981 error_free(local_err);
c1671a08 982 return -1;
4559a1db
LC
983 }
984
c1671a08 985 return 0;
f6b134ac
MM
986}
987
988static int net_init_netdev(QemuOpts *opts, void *dummy)
989{
4559a1db
LC
990 Error *local_err = NULL;
991 int ret;
992
993 ret = net_client_init(opts, 1, &local_err);
994 if (error_is_set(&local_err)) {
995 qerror_report_err(local_err);
996 error_free(local_err);
997 return -1;
998 }
999
1000 return ret;
dc1c9fe8
MM
1001}
1002
1003int net_init_clients(void)
1004{
3329f07b
GH
1005 QemuOptsList *net = qemu_find_opts("net");
1006
cb4522cc 1007 if (default_net) {
dc1c9fe8 1008 /* if no clients, we use a default config */
3329f07b 1009 qemu_opts_set(net, NULL, "type", "nic");
dc1c9fe8 1010#ifdef CONFIG_SLIRP
3329f07b 1011 qemu_opts_set(net, NULL, "type", "user");
dc1c9fe8
MM
1012#endif
1013 }
1014
94878994 1015 QTAILQ_INIT(&net_clients);
5610c3aa 1016
3329f07b 1017 if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1)
f6b134ac
MM
1018 return -1;
1019
3329f07b 1020 if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) {
dc1c9fe8
MM
1021 return -1;
1022 }
1023
dc1c9fe8
MM
1024 return 0;
1025}
1026
7f161aae 1027int net_client_parse(QemuOptsList *opts_list, const char *optarg)
dc1c9fe8 1028{
a3a766e7 1029#if defined(CONFIG_SLIRP)
68ac40d2
MM
1030 int ret;
1031 if (net_slirp_parse_legacy(opts_list, optarg, &ret)) {
dc1c9fe8
MM
1032 return ret;
1033 }
a3a766e7 1034#endif
68ac40d2 1035
8212c64f 1036 if (!qemu_opts_parse(opts_list, optarg, 1)) {
dc1c9fe8
MM
1037 return -1;
1038 }
1039
cb4522cc 1040 default_net = 0;
dc1c9fe8
MM
1041 return 0;
1042}
7fc8d918
JW
1043
1044/* From FreeBSD */
1045/* XXX: optimize */
1046unsigned compute_mcast_idx(const uint8_t *ep)
1047{
1048 uint32_t crc;
1049 int carry, i, j;
1050 uint8_t b;
1051
1052 crc = 0xffffffff;
1053 for (i = 0; i < 6; i++) {
1054 b = *ep++;
1055 for (j = 0; j < 8; j++) {
1056 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
1057 crc <<= 1;
1058 b >>= 1;
1059 if (carry) {
1060 crc = ((crc ^ POLYNOMIAL) | carry);
1061 }
1062 }
1063 }
1064 return crc >> 26;
1065}
This page took 0.692334 seconds and 4 git commands to generate.