]> git.proxmox.com Git - qemu.git/blame - net.c
net: Rename VLANClientState to NetClientState
[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
4e68f7a0 135void qemu_format_nic_info_str(NetClientState *vc, uint8_t macaddr[6])
7cb7434b
AL
136{
137 snprintf(vc->info_str, sizeof(vc->info_str),
4dda4063
AL
138 "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
139 vc->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 */
4e68f7a0 165static char *assign_name(NetClientState *vc1, const char *model)
676cff29 166{
4e68f7a0 167 NetClientState *vc;
676cff29
AL
168 char buf[256];
169 int id = 0;
170
94878994 171 QTAILQ_FOREACH(vc, &net_clients, next) {
d33d93b2
SH
172 if (vc == vc1) {
173 continue;
174 }
175 /* For compatibility only bump id for net clients on a vlan */
176 if (strcmp(vc->model, model) == 0 &&
177 net_hub_id_for_client(vc, 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{
4e68f7a0 203 NetClientState *vc;
5610c3aa 204
4e68f7a0 205 assert(info->size >= sizeof(NetClientState));
45460d1a 206
7267c094 207 vc = g_malloc0(info->size);
5610c3aa 208
665a3b07 209 vc->info = info;
7267c094 210 vc->model = g_strdup(model);
45460d1a 211 if (name) {
7267c094 212 vc->name = g_strdup(name);
45460d1a 213 } else {
7a9f6e4a 214 vc->name = assign_name(vc, model);
45460d1a 215 }
5610c3aa 216
ab5f3f84
SH
217 if (peer) {
218 assert(!peer->peer);
219 vc->peer = peer;
220 peer->peer = vc;
d80b9fc6 221 }
94878994 222 QTAILQ_INSERT_TAIL(&net_clients, vc, next);
ab5f3f84
SH
223
224 vc->send_queue = qemu_new_net_queue(qemu_deliver_packet,
225 qemu_deliver_packet_iov,
226 vc);
63a01ef8 227
63a01ef8
AL
228 return vc;
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
4e68f7a0 252static void qemu_cleanup_vlan_client(NetClientState *vc)
63a01ef8 253{
94878994 254 QTAILQ_REMOVE(&net_clients, vc, next);
63a01ef8 255
665a3b07
MM
256 if (vc->info->cleanup) {
257 vc->info->cleanup(vc);
5610c3aa 258 }
a083a89d 259}
5610c3aa 260
4e68f7a0 261static void qemu_free_vlan_client(NetClientState *vc)
a083a89d 262{
a005d073
SH
263 if (vc->send_queue) {
264 qemu_del_net_queue(vc->send_queue);
265 }
266 if (vc->peer) {
267 vc->peer->peer = NULL;
a083a89d 268 }
7267c094
AL
269 g_free(vc->name);
270 g_free(vc->model);
271 g_free(vc);
63a01ef8
AL
272}
273
4e68f7a0 274void qemu_del_vlan_client(NetClientState *vc)
a083a89d
MT
275{
276 /* If there is a peer NIC, delete and cleanup client, but do not free. */
a005d073 277 if (vc->peer && vc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
a083a89d
MT
278 NICState *nic = DO_UPCAST(NICState, nc, vc->peer);
279 if (nic->peer_deleted) {
280 return;
281 }
282 nic->peer_deleted = true;
283 /* Let NIC know peer is gone. */
284 vc->peer->link_down = true;
285 if (vc->peer->info->link_status_changed) {
286 vc->peer->info->link_status_changed(vc->peer);
287 }
288 qemu_cleanup_vlan_client(vc);
289 return;
290 }
291
292 /* If this is a peer NIC and peer has already been deleted, free it now. */
a005d073 293 if (vc->peer && vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
a083a89d
MT
294 NICState *nic = DO_UPCAST(NICState, nc, vc);
295 if (nic->peer_deleted) {
296 qemu_free_vlan_client(vc->peer);
297 }
298 }
299
300 qemu_cleanup_vlan_client(vc);
301 qemu_free_vlan_client(vc);
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{
4e68f7a0 336 NetClientState *vc = opaque;
893379ef 337 ssize_t ret;
9a6ecb30
MM
338
339 if (vc->link_down) {
340 return size;
341 }
342
893379ef
MM
343 if (vc->receive_disabled) {
344 return 0;
345 }
346
665a3b07
MM
347 if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->info->receive_raw) {
348 ret = vc->info->receive_raw(vc, data, size);
893379ef 349 } else {
665a3b07 350 ret = vc->info->receive(vc, data, size);
893379ef
MM
351 }
352
353 if (ret == 0) {
354 vc->receive_disabled = 1;
355 };
356
357 return ret;
9a6ecb30
MM
358}
359
4e68f7a0 360void qemu_purge_queued_packets(NetClientState *vc)
8cad5516 361{
a005d073 362 if (!vc->peer) {
d80b9fc6 363 return;
9a6ecb30 364 }
d80b9fc6 365
a005d073 366 qemu_net_queue_purge(vc->peer->send_queue, vc);
8cad5516
MM
367}
368
4e68f7a0 369void qemu_flush_queued_packets(NetClientState *vc)
e94667b9 370{
893379ef
MM
371 vc->receive_disabled = 0;
372
a005d073 373 qemu_net_queue_flush(vc->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
4e68f7a0 405void qemu_send_packet(NetClientState *vc, const uint8_t *buf, int size)
f3b6c7fc
MM
406{
407 qemu_send_packet_async(vc, buf, size, NULL);
63a01ef8
AL
408}
409
4e68f7a0 410ssize_t qemu_send_packet_raw(NetClientState *vc, const uint8_t *buf, int size)
ca77d175
MM
411{
412 return qemu_send_packet_async_with_flags(vc, QEMU_NET_PACKET_FLAG_RAW,
413 buf, size, NULL);
414}
415
4e68f7a0 416static ssize_t vc_sendv_compat(NetClientState *vc, 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
665a3b07 424 return vc->info->receive(vc, 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{
4e68f7a0 433 NetClientState *vc = opaque;
9a6ecb30
MM
434
435 if (vc->link_down) {
ce053661 436 return iov_size(iov, iovcnt);
9a6ecb30
MM
437 }
438
665a3b07
MM
439 if (vc->info->receive_iov) {
440 return vc->info->receive_iov(vc, iov, iovcnt);
9a6ecb30
MM
441 } else {
442 return vc_sendv_compat(vc, iov, iovcnt);
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
4e68f7a0 464qemu_sendv_packet(NetClientState *vc, const struct iovec *iov, int iovcnt)
f3b6c7fc
MM
465{
466 return qemu_sendv_packet_async(vc, iov, iovcnt, NULL);
467}
468
4e68f7a0 469NetClientState *qemu_find_netdev(const char *id)
5869c4d5 470{
4e68f7a0 471 NetClientState *vc;
5869c4d5 472
94878994 473 QTAILQ_FOREACH(vc, &net_clients, next) {
2be64a68 474 if (vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC)
85dde9a9 475 continue;
5869c4d5
MM
476 if (!strcmp(vc->name, id)) {
477 return vc;
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{
4e68f7a0 794 NetClientState *vc;
f18c16de
LC
795 int vlan_id = qdict_get_int(qdict, "vlan_id");
796 const char *device = qdict_get_str(qdict, "device");
6f338c34 797
90d87a33 798 vc = net_hub_find_client_by_name(vlan_id, device);
6f338c34 799 if (!vc) {
6f338c34
AL
800 return;
801 }
e8f1f9db
AL
802 if (!net_host_check_device(vc->model)) {
803 monitor_printf(mon, "invalid host network device %s\n", device);
804 return;
805 }
6f338c34
AL
806 qemu_del_vlan_client(vc);
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{
4e68f7a0 846 NetClientState *vc;
ae82d324
MA
847
848 vc = qemu_find_netdev(id);
85dde9a9 849 if (!vc) {
5f964155
LC
850 error_set(errp, QERR_DEVICE_NOT_FOUND, id);
851 return;
ae82d324 852 }
5f964155 853
ae82d324 854 qemu_del_vlan_client(vc);
5f964155 855 qemu_opts_del(qemu_opts_find(qemu_find_opts_err("netdev", errp), id));
ae82d324
MA
856}
857
4e68f7a0 858static void print_net_client(Monitor *mon, NetClientState *vc)
44e798d3
JK
859{
860 monitor_printf(mon, "%s: type=%s,%s\n", vc->name,
6687b79d 861 NetClientOptionsKind_lookup[vc->info->type], vc->info_str);
44e798d3
JK
862}
863
376253ec 864void do_info_network(Monitor *mon)
63a01ef8 865{
4e68f7a0 866 NetClientState *vc, *peer;
2be64a68 867 NetClientOptionsKind type;
63a01ef8 868
a0104e0e 869 monitor_printf(mon, "Devices not on any VLAN:\n");
94878994 870 QTAILQ_FOREACH(vc, &net_clients, next) {
19061e63
JK
871 peer = vc->peer;
872 type = vc->info->type;
2be64a68 873 if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) {
44e798d3
JK
874 monitor_printf(mon, " ");
875 print_net_client(mon, vc);
19061e63 876 } /* else it's a netdev connected to a NIC, printed with the NIC */
2be64a68 877 if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) {
44e798d3
JK
878 monitor_printf(mon, " \\ ");
879 print_net_client(mon, peer);
a0104e0e 880 }
a0104e0e 881 }
d33d93b2 882 net_hub_info(mon);
63a01ef8
AL
883}
884
4b37156c 885void qmp_set_link(const char *name, bool up, Error **errp)
436e5e53 886{
4e68f7a0 887 NetClientState *vc = NULL;
436e5e53 888
94878994 889 QTAILQ_FOREACH(vc, &net_clients, next) {
85dde9a9
MA
890 if (!strcmp(vc->name, name)) {
891 goto done;
892 }
893 }
dd5de373 894done:
436e5e53 895 if (!vc) {
4b37156c
LC
896 error_set(errp, QERR_DEVICE_NOT_FOUND, name);
897 return;
436e5e53
AL
898 }
899
c9b26a4c 900 vc->link_down = !up;
436e5e53 901
665a3b07
MM
902 if (vc->info->link_status_changed) {
903 vc->info->link_status_changed(vc);
904 }
ab1cbe1c
MT
905
906 /* Notify peer. Don't update peer link status: this makes it possible to
907 * disconnect from host network without notifying the guest.
908 * FIXME: is disconnected link status change operation useful?
909 *
910 * Current behaviour is compatible with qemu vlans where there could be
911 * multiple clients that can still communicate with each other in
912 * disconnected mode. For now maintain this compatibility. */
913 if (vc->peer && vc->peer->info->link_status_changed) {
914 vc->peer->info->link_status_changed(vc->peer);
915 }
436e5e53
AL
916}
917
63a01ef8
AL
918void net_cleanup(void)
919{
4e68f7a0 920 NetClientState *vc, *next_vc;
63a01ef8 921
94878994 922 QTAILQ_FOREACH_SAFE(vc, &net_clients, next, next_vc) {
577c4af9
MM
923 qemu_del_vlan_client(vc);
924 }
63a01ef8
AL
925}
926
668680f7 927void net_check_clients(void)
63a01ef8 928{
4e68f7a0 929 NetClientState *vc;
48e2faf2 930 int i;
63a01ef8 931
641f6eae
PM
932 /* Don't warn about the default network setup that you get if
933 * no command line -net or -netdev options are specified. There
934 * are two cases that we would otherwise complain about:
935 * (1) board doesn't support a NIC but the implicit "-net nic"
936 * requested one
937 * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic"
938 * sets up a nic that isn't connected to anything.
939 */
940 if (default_net) {
941 return;
942 }
943
81017645 944 net_hub_check_clients();
ac60cc18 945
94878994 946 QTAILQ_FOREACH(vc, &net_clients, next) {
efe32fdd
MA
947 if (!vc->peer) {
948 fprintf(stderr, "Warning: %s %s has no peer\n",
2be64a68 949 vc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ? "nic" : "netdev",
efe32fdd
MA
950 vc->name);
951 }
952 }
48e2faf2
PM
953
954 /* Check that all NICs requested via -net nic actually got created.
955 * NICs created via -device don't need to be checked here because
956 * they are always instantiated.
957 */
958 for (i = 0; i < MAX_NICS; i++) {
959 NICInfo *nd = &nd_table[i];
960 if (nd->used && !nd->instantiated) {
961 fprintf(stderr, "Warning: requested NIC (%s, model %s) "
962 "was not created (not supported by this machine?)\n",
963 nd->name ? nd->name : "anonymous",
964 nd->model ? nd->model : "unspecified");
965 }
966 }
63a01ef8 967}
dc1c9fe8
MM
968
969static int net_init_client(QemuOpts *opts, void *dummy)
970{
4559a1db
LC
971 Error *local_err = NULL;
972
973 net_client_init(opts, 0, &local_err);
974 if (error_is_set(&local_err)) {
975 qerror_report_err(local_err);
976 error_free(local_err);
c1671a08 977 return -1;
4559a1db
LC
978 }
979
c1671a08 980 return 0;
f6b134ac
MM
981}
982
983static int net_init_netdev(QemuOpts *opts, void *dummy)
984{
4559a1db
LC
985 Error *local_err = NULL;
986 int ret;
987
988 ret = net_client_init(opts, 1, &local_err);
989 if (error_is_set(&local_err)) {
990 qerror_report_err(local_err);
991 error_free(local_err);
992 return -1;
993 }
994
995 return ret;
dc1c9fe8
MM
996}
997
998int net_init_clients(void)
999{
3329f07b
GH
1000 QemuOptsList *net = qemu_find_opts("net");
1001
cb4522cc 1002 if (default_net) {
dc1c9fe8 1003 /* if no clients, we use a default config */
3329f07b 1004 qemu_opts_set(net, NULL, "type", "nic");
dc1c9fe8 1005#ifdef CONFIG_SLIRP
3329f07b 1006 qemu_opts_set(net, NULL, "type", "user");
dc1c9fe8
MM
1007#endif
1008 }
1009
94878994 1010 QTAILQ_INIT(&net_clients);
5610c3aa 1011
3329f07b 1012 if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1)
f6b134ac
MM
1013 return -1;
1014
3329f07b 1015 if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) {
dc1c9fe8
MM
1016 return -1;
1017 }
1018
dc1c9fe8
MM
1019 return 0;
1020}
1021
7f161aae 1022int net_client_parse(QemuOptsList *opts_list, const char *optarg)
dc1c9fe8 1023{
a3a766e7 1024#if defined(CONFIG_SLIRP)
68ac40d2
MM
1025 int ret;
1026 if (net_slirp_parse_legacy(opts_list, optarg, &ret)) {
dc1c9fe8
MM
1027 return ret;
1028 }
a3a766e7 1029#endif
68ac40d2 1030
8212c64f 1031 if (!qemu_opts_parse(opts_list, optarg, 1)) {
dc1c9fe8
MM
1032 return -1;
1033 }
1034
cb4522cc 1035 default_net = 0;
dc1c9fe8
MM
1036 return 0;
1037}
7fc8d918
JW
1038
1039/* From FreeBSD */
1040/* XXX: optimize */
1041unsigned compute_mcast_idx(const uint8_t *ep)
1042{
1043 uint32_t crc;
1044 int carry, i, j;
1045 uint8_t b;
1046
1047 crc = 0xffffffff;
1048 for (i = 0; i < 6; i++) {
1049 b = *ep++;
1050 for (j = 0; j < 8; j++) {
1051 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
1052 crc <<= 1;
1053 b >>= 1;
1054 if (carry) {
1055 crc = ((crc ^ POLYNOMIAL) | carry);
1056 }
1057 }
1058 }
1059 return crc >> 26;
1060}