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 | */ |
24 | |
25 | #include "qemu/osdep.h" |
26 | |
27 | #include "net/net.h" |
28 | #include "clients.h" |
29 | #include "hub.h" |
30 | #include "hw/qdev-properties.h" |
31 | #include "net/slirp.h" |
32 | #include "net/eth.h" |
33 | #include "util.h" |
34 | |
35 | #include "monitor/monitor.h" |
36 | #include "qemu/help_option.h" |
37 | #include "qapi/qapi-commands-net.h" |
38 | #include "qapi/qapi-visit-net.h" |
39 | #include "qapi/qmp/qdict.h" |
40 | #include "qapi/qmp/qerror.h" |
41 | #include "qemu/error-report.h" |
42 | #include "qemu/sockets.h" |
43 | #include "qemu/cutils.h" |
44 | #include "qemu/config-file.h" |
45 | #include "qemu/ctype.h" |
46 | #include "qemu/iov.h" |
47 | #include "qemu/main-loop.h" |
48 | #include "qemu/option.h" |
49 | #include "qapi/error.h" |
50 | #include "qapi/opts-visitor.h" |
51 | #include "sysemu/sysemu.h" |
52 | #include "sysemu/qtest.h" |
53 | #include "sysemu/runstate.h" |
54 | #include "sysemu/sysemu.h" |
55 | #include "net/filter.h" |
56 | #include "qapi/string-output-visitor.h" |
57 | |
58 | /* Net bridge is currently not supported for W32. */ |
59 | #if !defined(_WIN32) |
60 | # define CONFIG_NET_BRIDGE |
61 | #endif |
62 | |
63 | static VMChangeStateEntry *net_change_state_entry; |
64 | static QTAILQ_HEAD(, NetClientState) net_clients; |
65 | |
66 | /***********************************************************/ |
67 | /* network device redirectors */ |
68 | |
69 | int parse_host_port(struct sockaddr_in *saddr, const char *str, |
70 | Error **errp) |
71 | { |
72 | gchar **substrings; |
73 | struct hostent *he; |
74 | const char *addr, *p, *r; |
75 | int port, ret = 0; |
76 | |
77 | substrings = g_strsplit(str, ":" , 2); |
78 | if (!substrings || !substrings[0] || !substrings[1]) { |
79 | error_setg(errp, "host address '%s' doesn't contain ':' " |
80 | "separating host from port" , str); |
81 | ret = -1; |
82 | goto out; |
83 | } |
84 | |
85 | addr = substrings[0]; |
86 | p = substrings[1]; |
87 | |
88 | saddr->sin_family = AF_INET; |
89 | if (addr[0] == '\0') { |
90 | saddr->sin_addr.s_addr = 0; |
91 | } else { |
92 | if (qemu_isdigit(addr[0])) { |
93 | if (!inet_aton(addr, &saddr->sin_addr)) { |
94 | error_setg(errp, "host address '%s' is not a valid " |
95 | "IPv4 address" , addr); |
96 | ret = -1; |
97 | goto out; |
98 | } |
99 | } else { |
100 | he = gethostbyname(addr); |
101 | if (he == NULL) { |
102 | error_setg(errp, "can't resolve host address '%s'" , addr); |
103 | ret = -1; |
104 | goto out; |
105 | } |
106 | saddr->sin_addr = *(struct in_addr *)he->h_addr; |
107 | } |
108 | } |
109 | port = strtol(p, (char **)&r, 0); |
110 | if (r == p) { |
111 | error_setg(errp, "port number '%s' is invalid" , p); |
112 | ret = -1; |
113 | goto out; |
114 | } |
115 | saddr->sin_port = htons(port); |
116 | |
117 | out: |
118 | g_strfreev(substrings); |
119 | return ret; |
120 | } |
121 | |
122 | char *qemu_mac_strdup_printf(const uint8_t *macaddr) |
123 | { |
124 | return g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" , |
125 | macaddr[0], macaddr[1], macaddr[2], |
126 | macaddr[3], macaddr[4], macaddr[5]); |
127 | } |
128 | |
129 | void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]) |
130 | { |
131 | snprintf(nc->info_str, sizeof(nc->info_str), |
132 | "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x" , |
133 | nc->model, |
134 | macaddr[0], macaddr[1], macaddr[2], |
135 | macaddr[3], macaddr[4], macaddr[5]); |
136 | } |
137 | |
138 | static int mac_table[256] = {0}; |
139 | |
140 | static void qemu_macaddr_set_used(MACAddr *macaddr) |
141 | { |
142 | int index; |
143 | |
144 | for (index = 0x56; index < 0xFF; index++) { |
145 | if (macaddr->a[5] == index) { |
146 | mac_table[index]++; |
147 | } |
148 | } |
149 | } |
150 | |
151 | static void qemu_macaddr_set_free(MACAddr *macaddr) |
152 | { |
153 | int index; |
154 | static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } }; |
155 | |
156 | if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) { |
157 | return; |
158 | } |
159 | for (index = 0x56; index < 0xFF; index++) { |
160 | if (macaddr->a[5] == index) { |
161 | mac_table[index]--; |
162 | } |
163 | } |
164 | } |
165 | |
166 | static int qemu_macaddr_get_free(void) |
167 | { |
168 | int index; |
169 | |
170 | for (index = 0x56; index < 0xFF; index++) { |
171 | if (mac_table[index] == 0) { |
172 | return index; |
173 | } |
174 | } |
175 | |
176 | return -1; |
177 | } |
178 | |
179 | void qemu_macaddr_default_if_unset(MACAddr *macaddr) |
180 | { |
181 | static const MACAddr zero = { .a = { 0,0,0,0,0,0 } }; |
182 | static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } }; |
183 | |
184 | if (memcmp(macaddr, &zero, sizeof(zero)) != 0) { |
185 | if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) { |
186 | return; |
187 | } else { |
188 | qemu_macaddr_set_used(macaddr); |
189 | return; |
190 | } |
191 | } |
192 | |
193 | macaddr->a[0] = 0x52; |
194 | macaddr->a[1] = 0x54; |
195 | macaddr->a[2] = 0x00; |
196 | macaddr->a[3] = 0x12; |
197 | macaddr->a[4] = 0x34; |
198 | macaddr->a[5] = qemu_macaddr_get_free(); |
199 | qemu_macaddr_set_used(macaddr); |
200 | } |
201 | |
202 | /** |
203 | * Generate a name for net client |
204 | * |
205 | * Only net clients created with the legacy -net option and NICs need this. |
206 | */ |
207 | static char *assign_name(NetClientState *nc1, const char *model) |
208 | { |
209 | NetClientState *nc; |
210 | int id = 0; |
211 | |
212 | QTAILQ_FOREACH(nc, &net_clients, next) { |
213 | if (nc == nc1) { |
214 | continue; |
215 | } |
216 | if (strcmp(nc->model, model) == 0) { |
217 | id++; |
218 | } |
219 | } |
220 | |
221 | return g_strdup_printf("%s.%d" , model, id); |
222 | } |
223 | |
224 | static void qemu_net_client_destructor(NetClientState *nc) |
225 | { |
226 | g_free(nc); |
227 | } |
228 | static ssize_t qemu_deliver_packet_iov(NetClientState *sender, |
229 | unsigned flags, |
230 | const struct iovec *iov, |
231 | int iovcnt, |
232 | void *opaque); |
233 | |
234 | static void qemu_net_client_setup(NetClientState *nc, |
235 | NetClientInfo *info, |
236 | NetClientState *peer, |
237 | const char *model, |
238 | const char *name, |
239 | NetClientDestructor *destructor) |
240 | { |
241 | nc->info = info; |
242 | nc->model = g_strdup(model); |
243 | if (name) { |
244 | nc->name = g_strdup(name); |
245 | } else { |
246 | nc->name = assign_name(nc, model); |
247 | } |
248 | |
249 | if (peer) { |
250 | assert(!peer->peer); |
251 | nc->peer = peer; |
252 | peer->peer = nc; |
253 | } |
254 | QTAILQ_INSERT_TAIL(&net_clients, nc, next); |
255 | |
256 | nc->incoming_queue = qemu_new_net_queue(qemu_deliver_packet_iov, nc); |
257 | nc->destructor = destructor; |
258 | QTAILQ_INIT(&nc->filters); |
259 | } |
260 | |
261 | NetClientState *qemu_new_net_client(NetClientInfo *info, |
262 | NetClientState *peer, |
263 | const char *model, |
264 | const char *name) |
265 | { |
266 | NetClientState *nc; |
267 | |
268 | assert(info->size >= sizeof(NetClientState)); |
269 | |
270 | nc = g_malloc0(info->size); |
271 | qemu_net_client_setup(nc, info, peer, model, name, |
272 | qemu_net_client_destructor); |
273 | |
274 | return nc; |
275 | } |
276 | |
277 | NICState *qemu_new_nic(NetClientInfo *info, |
278 | NICConf *conf, |
279 | const char *model, |
280 | const char *name, |
281 | void *opaque) |
282 | { |
283 | NetClientState **peers = conf->peers.ncs; |
284 | NICState *nic; |
285 | int i, queues = MAX(1, conf->peers.queues); |
286 | |
287 | assert(info->type == NET_CLIENT_DRIVER_NIC); |
288 | assert(info->size >= sizeof(NICState)); |
289 | |
290 | nic = g_malloc0(info->size + sizeof(NetClientState) * queues); |
291 | nic->ncs = (void *)nic + info->size; |
292 | nic->conf = conf; |
293 | nic->opaque = opaque; |
294 | |
295 | for (i = 0; i < queues; i++) { |
296 | qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name, |
297 | NULL); |
298 | nic->ncs[i].queue_index = i; |
299 | } |
300 | |
301 | return nic; |
302 | } |
303 | |
304 | NetClientState *qemu_get_subqueue(NICState *nic, int queue_index) |
305 | { |
306 | return nic->ncs + queue_index; |
307 | } |
308 | |
309 | NetClientState *qemu_get_queue(NICState *nic) |
310 | { |
311 | return qemu_get_subqueue(nic, 0); |
312 | } |
313 | |
314 | NICState *qemu_get_nic(NetClientState *nc) |
315 | { |
316 | NetClientState *nc0 = nc - nc->queue_index; |
317 | |
318 | return (NICState *)((void *)nc0 - nc->info->size); |
319 | } |
320 | |
321 | void *qemu_get_nic_opaque(NetClientState *nc) |
322 | { |
323 | NICState *nic = qemu_get_nic(nc); |
324 | |
325 | return nic->opaque; |
326 | } |
327 | |
328 | static void qemu_cleanup_net_client(NetClientState *nc) |
329 | { |
330 | QTAILQ_REMOVE(&net_clients, nc, next); |
331 | |
332 | if (nc->info->cleanup) { |
333 | nc->info->cleanup(nc); |
334 | } |
335 | } |
336 | |
337 | static void qemu_free_net_client(NetClientState *nc) |
338 | { |
339 | if (nc->incoming_queue) { |
340 | qemu_del_net_queue(nc->incoming_queue); |
341 | } |
342 | if (nc->peer) { |
343 | nc->peer->peer = NULL; |
344 | } |
345 | g_free(nc->name); |
346 | g_free(nc->model); |
347 | if (nc->destructor) { |
348 | nc->destructor(nc); |
349 | } |
350 | } |
351 | |
352 | void qemu_del_net_client(NetClientState *nc) |
353 | { |
354 | NetClientState *ncs[MAX_QUEUE_NUM]; |
355 | int queues, i; |
356 | NetFilterState *nf, *next; |
357 | |
358 | assert(nc->info->type != NET_CLIENT_DRIVER_NIC); |
359 | |
360 | /* If the NetClientState belongs to a multiqueue backend, we will change all |
361 | * other NetClientStates also. |
362 | */ |
363 | queues = qemu_find_net_clients_except(nc->name, ncs, |
364 | NET_CLIENT_DRIVER_NIC, |
365 | MAX_QUEUE_NUM); |
366 | assert(queues != 0); |
367 | |
368 | QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) { |
369 | object_unparent(OBJECT(nf)); |
370 | } |
371 | |
372 | /* If there is a peer NIC, delete and cleanup client, but do not free. */ |
373 | if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) { |
374 | NICState *nic = qemu_get_nic(nc->peer); |
375 | if (nic->peer_deleted) { |
376 | return; |
377 | } |
378 | nic->peer_deleted = true; |
379 | |
380 | for (i = 0; i < queues; i++) { |
381 | ncs[i]->peer->link_down = true; |
382 | } |
383 | |
384 | if (nc->peer->info->link_status_changed) { |
385 | nc->peer->info->link_status_changed(nc->peer); |
386 | } |
387 | |
388 | for (i = 0; i < queues; i++) { |
389 | qemu_cleanup_net_client(ncs[i]); |
390 | } |
391 | |
392 | return; |
393 | } |
394 | |
395 | for (i = 0; i < queues; i++) { |
396 | qemu_cleanup_net_client(ncs[i]); |
397 | qemu_free_net_client(ncs[i]); |
398 | } |
399 | } |
400 | |
401 | void qemu_del_nic(NICState *nic) |
402 | { |
403 | int i, queues = MAX(nic->conf->peers.queues, 1); |
404 | |
405 | qemu_macaddr_set_free(&nic->conf->macaddr); |
406 | |
407 | /* If this is a peer NIC and peer has already been deleted, free it now. */ |
408 | if (nic->peer_deleted) { |
409 | for (i = 0; i < queues; i++) { |
410 | qemu_free_net_client(qemu_get_subqueue(nic, i)->peer); |
411 | } |
412 | } |
413 | |
414 | for (i = queues - 1; i >= 0; i--) { |
415 | NetClientState *nc = qemu_get_subqueue(nic, i); |
416 | |
417 | qemu_cleanup_net_client(nc); |
418 | qemu_free_net_client(nc); |
419 | } |
420 | |
421 | g_free(nic); |
422 | } |
423 | |
424 | void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) |
425 | { |
426 | NetClientState *nc; |
427 | |
428 | QTAILQ_FOREACH(nc, &net_clients, next) { |
429 | if (nc->info->type == NET_CLIENT_DRIVER_NIC) { |
430 | if (nc->queue_index == 0) { |
431 | func(qemu_get_nic(nc), opaque); |
432 | } |
433 | } |
434 | } |
435 | } |
436 | |
437 | bool qemu_has_ufo(NetClientState *nc) |
438 | { |
439 | if (!nc || !nc->info->has_ufo) { |
440 | return false; |
441 | } |
442 | |
443 | return nc->info->has_ufo(nc); |
444 | } |
445 | |
446 | bool qemu_has_vnet_hdr(NetClientState *nc) |
447 | { |
448 | if (!nc || !nc->info->has_vnet_hdr) { |
449 | return false; |
450 | } |
451 | |
452 | return nc->info->has_vnet_hdr(nc); |
453 | } |
454 | |
455 | bool qemu_has_vnet_hdr_len(NetClientState *nc, int len) |
456 | { |
457 | if (!nc || !nc->info->has_vnet_hdr_len) { |
458 | return false; |
459 | } |
460 | |
461 | return nc->info->has_vnet_hdr_len(nc, len); |
462 | } |
463 | |
464 | void qemu_using_vnet_hdr(NetClientState *nc, bool enable) |
465 | { |
466 | if (!nc || !nc->info->using_vnet_hdr) { |
467 | return; |
468 | } |
469 | |
470 | nc->info->using_vnet_hdr(nc, enable); |
471 | } |
472 | |
473 | void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6, |
474 | int ecn, int ufo) |
475 | { |
476 | if (!nc || !nc->info->set_offload) { |
477 | return; |
478 | } |
479 | |
480 | nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo); |
481 | } |
482 | |
483 | void qemu_set_vnet_hdr_len(NetClientState *nc, int len) |
484 | { |
485 | if (!nc || !nc->info->set_vnet_hdr_len) { |
486 | return; |
487 | } |
488 | |
489 | nc->vnet_hdr_len = len; |
490 | nc->info->set_vnet_hdr_len(nc, len); |
491 | } |
492 | |
493 | int qemu_set_vnet_le(NetClientState *nc, bool is_le) |
494 | { |
495 | #ifdef HOST_WORDS_BIGENDIAN |
496 | if (!nc || !nc->info->set_vnet_le) { |
497 | return -ENOSYS; |
498 | } |
499 | |
500 | return nc->info->set_vnet_le(nc, is_le); |
501 | #else |
502 | return 0; |
503 | #endif |
504 | } |
505 | |
506 | int qemu_set_vnet_be(NetClientState *nc, bool is_be) |
507 | { |
508 | #ifdef HOST_WORDS_BIGENDIAN |
509 | return 0; |
510 | #else |
511 | if (!nc || !nc->info->set_vnet_be) { |
512 | return -ENOSYS; |
513 | } |
514 | |
515 | return nc->info->set_vnet_be(nc, is_be); |
516 | #endif |
517 | } |
518 | |
519 | int qemu_can_send_packet(NetClientState *sender) |
520 | { |
521 | int vm_running = runstate_is_running(); |
522 | |
523 | if (!vm_running) { |
524 | return 0; |
525 | } |
526 | |
527 | if (!sender->peer) { |
528 | return 1; |
529 | } |
530 | |
531 | if (sender->peer->receive_disabled) { |
532 | return 0; |
533 | } else if (sender->peer->info->can_receive && |
534 | !sender->peer->info->can_receive(sender->peer)) { |
535 | return 0; |
536 | } |
537 | return 1; |
538 | } |
539 | |
540 | static ssize_t filter_receive_iov(NetClientState *nc, |
541 | NetFilterDirection direction, |
542 | NetClientState *sender, |
543 | unsigned flags, |
544 | const struct iovec *iov, |
545 | int iovcnt, |
546 | NetPacketSent *sent_cb) |
547 | { |
548 | ssize_t ret = 0; |
549 | NetFilterState *nf = NULL; |
550 | |
551 | if (direction == NET_FILTER_DIRECTION_TX) { |
552 | QTAILQ_FOREACH(nf, &nc->filters, next) { |
553 | ret = qemu_netfilter_receive(nf, direction, sender, flags, iov, |
554 | iovcnt, sent_cb); |
555 | if (ret) { |
556 | return ret; |
557 | } |
558 | } |
559 | } else { |
560 | QTAILQ_FOREACH_REVERSE(nf, &nc->filters, next) { |
561 | ret = qemu_netfilter_receive(nf, direction, sender, flags, iov, |
562 | iovcnt, sent_cb); |
563 | if (ret) { |
564 | return ret; |
565 | } |
566 | } |
567 | } |
568 | |
569 | return ret; |
570 | } |
571 | |
572 | static ssize_t filter_receive(NetClientState *nc, |
573 | NetFilterDirection direction, |
574 | NetClientState *sender, |
575 | unsigned flags, |
576 | const uint8_t *data, |
577 | size_t size, |
578 | NetPacketSent *sent_cb) |
579 | { |
580 | struct iovec iov = { |
581 | .iov_base = (void *)data, |
582 | .iov_len = size |
583 | }; |
584 | |
585 | return filter_receive_iov(nc, direction, sender, flags, &iov, 1, sent_cb); |
586 | } |
587 | |
588 | void qemu_purge_queued_packets(NetClientState *nc) |
589 | { |
590 | if (!nc->peer) { |
591 | return; |
592 | } |
593 | |
594 | qemu_net_queue_purge(nc->peer->incoming_queue, nc); |
595 | } |
596 | |
597 | void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge) |
598 | { |
599 | nc->receive_disabled = 0; |
600 | |
601 | if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_HUBPORT) { |
602 | if (net_hub_flush(nc->peer)) { |
603 | qemu_notify_event(); |
604 | } |
605 | } |
606 | if (qemu_net_queue_flush(nc->incoming_queue)) { |
607 | /* We emptied the queue successfully, signal to the IO thread to repoll |
608 | * the file descriptor (for tap, for example). |
609 | */ |
610 | qemu_notify_event(); |
611 | } else if (purge) { |
612 | /* Unable to empty the queue, purge remaining packets */ |
613 | qemu_net_queue_purge(nc->incoming_queue, nc); |
614 | } |
615 | } |
616 | |
617 | void qemu_flush_queued_packets(NetClientState *nc) |
618 | { |
619 | qemu_flush_or_purge_queued_packets(nc, false); |
620 | } |
621 | |
622 | static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender, |
623 | unsigned flags, |
624 | const uint8_t *buf, int size, |
625 | NetPacketSent *sent_cb) |
626 | { |
627 | NetQueue *queue; |
628 | int ret; |
629 | |
630 | #ifdef DEBUG_NET |
631 | printf("qemu_send_packet_async:\n" ); |
632 | qemu_hexdump((const char *)buf, stdout, "net" , size); |
633 | #endif |
634 | |
635 | if (sender->link_down || !sender->peer) { |
636 | return size; |
637 | } |
638 | |
639 | /* Let filters handle the packet first */ |
640 | ret = filter_receive(sender, NET_FILTER_DIRECTION_TX, |
641 | sender, flags, buf, size, sent_cb); |
642 | if (ret) { |
643 | return ret; |
644 | } |
645 | |
646 | ret = filter_receive(sender->peer, NET_FILTER_DIRECTION_RX, |
647 | sender, flags, buf, size, sent_cb); |
648 | if (ret) { |
649 | return ret; |
650 | } |
651 | |
652 | queue = sender->peer->incoming_queue; |
653 | |
654 | return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb); |
655 | } |
656 | |
657 | ssize_t qemu_send_packet_async(NetClientState *sender, |
658 | const uint8_t *buf, int size, |
659 | NetPacketSent *sent_cb) |
660 | { |
661 | return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE, |
662 | buf, size, sent_cb); |
663 | } |
664 | |
665 | ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size) |
666 | { |
667 | return qemu_send_packet_async(nc, buf, size, NULL); |
668 | } |
669 | |
670 | ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size) |
671 | { |
672 | return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW, |
673 | buf, size, NULL); |
674 | } |
675 | |
676 | static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov, |
677 | int iovcnt, unsigned flags) |
678 | { |
679 | uint8_t *buf = NULL; |
680 | uint8_t *buffer; |
681 | size_t offset; |
682 | ssize_t ret; |
683 | |
684 | if (iovcnt == 1) { |
685 | buffer = iov[0].iov_base; |
686 | offset = iov[0].iov_len; |
687 | } else { |
688 | offset = iov_size(iov, iovcnt); |
689 | if (offset > NET_BUFSIZE) { |
690 | return -1; |
691 | } |
692 | buf = g_malloc(offset); |
693 | buffer = buf; |
694 | offset = iov_to_buf(iov, iovcnt, 0, buf, offset); |
695 | } |
696 | |
697 | if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) { |
698 | ret = nc->info->receive_raw(nc, buffer, offset); |
699 | } else { |
700 | ret = nc->info->receive(nc, buffer, offset); |
701 | } |
702 | |
703 | g_free(buf); |
704 | return ret; |
705 | } |
706 | |
707 | static ssize_t qemu_deliver_packet_iov(NetClientState *sender, |
708 | unsigned flags, |
709 | const struct iovec *iov, |
710 | int iovcnt, |
711 | void *opaque) |
712 | { |
713 | NetClientState *nc = opaque; |
714 | int ret; |
715 | |
716 | |
717 | if (nc->link_down) { |
718 | return iov_size(iov, iovcnt); |
719 | } |
720 | |
721 | if (nc->receive_disabled) { |
722 | return 0; |
723 | } |
724 | |
725 | if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) { |
726 | ret = nc->info->receive_iov(nc, iov, iovcnt); |
727 | } else { |
728 | ret = nc_sendv_compat(nc, iov, iovcnt, flags); |
729 | } |
730 | |
731 | if (ret == 0) { |
732 | nc->receive_disabled = 1; |
733 | } |
734 | |
735 | return ret; |
736 | } |
737 | |
738 | ssize_t qemu_sendv_packet_async(NetClientState *sender, |
739 | const struct iovec *iov, int iovcnt, |
740 | NetPacketSent *sent_cb) |
741 | { |
742 | NetQueue *queue; |
743 | size_t size = iov_size(iov, iovcnt); |
744 | int ret; |
745 | |
746 | if (size > NET_BUFSIZE) { |
747 | return size; |
748 | } |
749 | |
750 | if (sender->link_down || !sender->peer) { |
751 | return size; |
752 | } |
753 | |
754 | /* Let filters handle the packet first */ |
755 | ret = filter_receive_iov(sender, NET_FILTER_DIRECTION_TX, sender, |
756 | QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb); |
757 | if (ret) { |
758 | return ret; |
759 | } |
760 | |
761 | ret = filter_receive_iov(sender->peer, NET_FILTER_DIRECTION_RX, sender, |
762 | QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb); |
763 | if (ret) { |
764 | return ret; |
765 | } |
766 | |
767 | queue = sender->peer->incoming_queue; |
768 | |
769 | return qemu_net_queue_send_iov(queue, sender, |
770 | QEMU_NET_PACKET_FLAG_NONE, |
771 | iov, iovcnt, sent_cb); |
772 | } |
773 | |
774 | ssize_t |
775 | qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt) |
776 | { |
777 | return qemu_sendv_packet_async(nc, iov, iovcnt, NULL); |
778 | } |
779 | |
780 | NetClientState *qemu_find_netdev(const char *id) |
781 | { |
782 | NetClientState *nc; |
783 | |
784 | QTAILQ_FOREACH(nc, &net_clients, next) { |
785 | if (nc->info->type == NET_CLIENT_DRIVER_NIC) |
786 | continue; |
787 | if (!strcmp(nc->name, id)) { |
788 | return nc; |
789 | } |
790 | } |
791 | |
792 | return NULL; |
793 | } |
794 | |
795 | int qemu_find_net_clients_except(const char *id, NetClientState **ncs, |
796 | NetClientDriver type, int max) |
797 | { |
798 | NetClientState *nc; |
799 | int ret = 0; |
800 | |
801 | QTAILQ_FOREACH(nc, &net_clients, next) { |
802 | if (nc->info->type == type) { |
803 | continue; |
804 | } |
805 | if (!id || !strcmp(nc->name, id)) { |
806 | if (ret < max) { |
807 | ncs[ret] = nc; |
808 | } |
809 | ret++; |
810 | } |
811 | } |
812 | |
813 | return ret; |
814 | } |
815 | |
816 | static int nic_get_free_idx(void) |
817 | { |
818 | int index; |
819 | |
820 | for (index = 0; index < MAX_NICS; index++) |
821 | if (!nd_table[index].used) |
822 | return index; |
823 | return -1; |
824 | } |
825 | |
826 | int qemu_show_nic_models(const char *arg, const char *const *models) |
827 | { |
828 | int i; |
829 | |
830 | if (!arg || !is_help_option(arg)) { |
831 | return 0; |
832 | } |
833 | |
834 | printf("Supported NIC models:\n" ); |
835 | for (i = 0 ; models[i]; i++) { |
836 | printf("%s\n" , models[i]); |
837 | } |
838 | return 1; |
839 | } |
840 | |
841 | void qemu_check_nic_model(NICInfo *nd, const char *model) |
842 | { |
843 | const char *models[2]; |
844 | |
845 | models[0] = model; |
846 | models[1] = NULL; |
847 | |
848 | if (qemu_show_nic_models(nd->model, models)) |
849 | exit(0); |
850 | if (qemu_find_nic_model(nd, models, model) < 0) |
851 | exit(1); |
852 | } |
853 | |
854 | int qemu_find_nic_model(NICInfo *nd, const char * const *models, |
855 | const char *default_model) |
856 | { |
857 | int i; |
858 | |
859 | if (!nd->model) |
860 | nd->model = g_strdup(default_model); |
861 | |
862 | for (i = 0 ; models[i]; i++) { |
863 | if (strcmp(nd->model, models[i]) == 0) |
864 | return i; |
865 | } |
866 | |
867 | error_report("Unsupported NIC model: %s" , nd->model); |
868 | return -1; |
869 | } |
870 | |
871 | static int net_init_nic(const Netdev *netdev, const char *name, |
872 | NetClientState *peer, Error **errp) |
873 | { |
874 | int idx; |
875 | NICInfo *nd; |
876 | const NetLegacyNicOptions *nic; |
877 | |
878 | assert(netdev->type == NET_CLIENT_DRIVER_NIC); |
879 | nic = &netdev->u.nic; |
880 | |
881 | idx = nic_get_free_idx(); |
882 | if (idx == -1 || nb_nics >= MAX_NICS) { |
883 | error_setg(errp, "too many NICs" ); |
884 | return -1; |
885 | } |
886 | |
887 | nd = &nd_table[idx]; |
888 | |
889 | memset(nd, 0, sizeof(*nd)); |
890 | |
891 | if (nic->has_netdev) { |
892 | nd->netdev = qemu_find_netdev(nic->netdev); |
893 | if (!nd->netdev) { |
894 | error_setg(errp, "netdev '%s' not found" , nic->netdev); |
895 | return -1; |
896 | } |
897 | } else { |
898 | assert(peer); |
899 | nd->netdev = peer; |
900 | } |
901 | nd->name = g_strdup(name); |
902 | if (nic->has_model) { |
903 | nd->model = g_strdup(nic->model); |
904 | } |
905 | if (nic->has_addr) { |
906 | nd->devaddr = g_strdup(nic->addr); |
907 | } |
908 | |
909 | if (nic->has_macaddr && |
910 | net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) { |
911 | error_setg(errp, "invalid syntax for ethernet address" ); |
912 | return -1; |
913 | } |
914 | if (nic->has_macaddr && |
915 | is_multicast_ether_addr(nd->macaddr.a)) { |
916 | error_setg(errp, |
917 | "NIC cannot have multicast MAC address (odd 1st byte)" ); |
918 | return -1; |
919 | } |
920 | qemu_macaddr_default_if_unset(&nd->macaddr); |
921 | |
922 | if (nic->has_vectors) { |
923 | if (nic->vectors > 0x7ffffff) { |
924 | error_setg(errp, "invalid # of vectors: %" PRIu32, nic->vectors); |
925 | return -1; |
926 | } |
927 | nd->nvectors = nic->vectors; |
928 | } else { |
929 | nd->nvectors = DEV_NVECTORS_UNSPECIFIED; |
930 | } |
931 | |
932 | nd->used = 1; |
933 | nb_nics++; |
934 | |
935 | return idx; |
936 | } |
937 | |
938 | |
939 | static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])( |
940 | const Netdev *netdev, |
941 | const char *name, |
942 | NetClientState *peer, Error **errp) = { |
943 | [NET_CLIENT_DRIVER_NIC] = net_init_nic, |
944 | #ifdef CONFIG_SLIRP |
945 | [NET_CLIENT_DRIVER_USER] = net_init_slirp, |
946 | #endif |
947 | [NET_CLIENT_DRIVER_TAP] = net_init_tap, |
948 | [NET_CLIENT_DRIVER_SOCKET] = net_init_socket, |
949 | #ifdef CONFIG_VDE |
950 | [NET_CLIENT_DRIVER_VDE] = net_init_vde, |
951 | #endif |
952 | #ifdef CONFIG_NETMAP |
953 | [NET_CLIENT_DRIVER_NETMAP] = net_init_netmap, |
954 | #endif |
955 | #ifdef CONFIG_NET_BRIDGE |
956 | [NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge, |
957 | #endif |
958 | [NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport, |
959 | #ifdef CONFIG_VHOST_NET_USER |
960 | [NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user, |
961 | #endif |
962 | #ifdef CONFIG_L2TPV3 |
963 | [NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3, |
964 | #endif |
965 | }; |
966 | |
967 | |
968 | static int net_client_init1(const void *object, bool is_netdev, Error **errp) |
969 | { |
970 | Netdev legacy = {0}; |
971 | const Netdev *netdev; |
972 | const char *name; |
973 | NetClientState *peer = NULL; |
974 | |
975 | if (is_netdev) { |
976 | netdev = object; |
977 | name = netdev->id; |
978 | |
979 | if (netdev->type == NET_CLIENT_DRIVER_NIC || |
980 | !net_client_init_fun[netdev->type]) { |
981 | error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type" , |
982 | "a netdev backend type" ); |
983 | return -1; |
984 | } |
985 | } else { |
986 | const NetLegacy *net = object; |
987 | const NetLegacyOptions *opts = net->opts; |
988 | legacy.id = net->id; |
989 | netdev = &legacy; |
990 | /* missing optional values have been initialized to "all bits zero" */ |
991 | name = net->has_id ? net->id : net->name; |
992 | |
993 | if (net->has_name) { |
994 | warn_report("The 'name' parameter is deprecated, use 'id' instead" ); |
995 | } |
996 | |
997 | /* Map the old options to the new flat type */ |
998 | switch (opts->type) { |
999 | case NET_LEGACY_OPTIONS_TYPE_NONE: |
1000 | return 0; /* nothing to do */ |
1001 | case NET_LEGACY_OPTIONS_TYPE_NIC: |
1002 | legacy.type = NET_CLIENT_DRIVER_NIC; |
1003 | legacy.u.nic = opts->u.nic; |
1004 | break; |
1005 | case NET_LEGACY_OPTIONS_TYPE_USER: |
1006 | legacy.type = NET_CLIENT_DRIVER_USER; |
1007 | legacy.u.user = opts->u.user; |
1008 | break; |
1009 | case NET_LEGACY_OPTIONS_TYPE_TAP: |
1010 | legacy.type = NET_CLIENT_DRIVER_TAP; |
1011 | legacy.u.tap = opts->u.tap; |
1012 | break; |
1013 | case NET_LEGACY_OPTIONS_TYPE_L2TPV3: |
1014 | legacy.type = NET_CLIENT_DRIVER_L2TPV3; |
1015 | legacy.u.l2tpv3 = opts->u.l2tpv3; |
1016 | break; |
1017 | case NET_LEGACY_OPTIONS_TYPE_SOCKET: |
1018 | legacy.type = NET_CLIENT_DRIVER_SOCKET; |
1019 | legacy.u.socket = opts->u.socket; |
1020 | break; |
1021 | case NET_LEGACY_OPTIONS_TYPE_VDE: |
1022 | legacy.type = NET_CLIENT_DRIVER_VDE; |
1023 | legacy.u.vde = opts->u.vde; |
1024 | break; |
1025 | case NET_LEGACY_OPTIONS_TYPE_BRIDGE: |
1026 | legacy.type = NET_CLIENT_DRIVER_BRIDGE; |
1027 | legacy.u.bridge = opts->u.bridge; |
1028 | break; |
1029 | case NET_LEGACY_OPTIONS_TYPE_NETMAP: |
1030 | legacy.type = NET_CLIENT_DRIVER_NETMAP; |
1031 | legacy.u.netmap = opts->u.netmap; |
1032 | break; |
1033 | case NET_LEGACY_OPTIONS_TYPE_VHOST_USER: |
1034 | legacy.type = NET_CLIENT_DRIVER_VHOST_USER; |
1035 | legacy.u.vhost_user = opts->u.vhost_user; |
1036 | break; |
1037 | default: |
1038 | abort(); |
1039 | } |
1040 | |
1041 | if (!net_client_init_fun[netdev->type]) { |
1042 | error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type" , |
1043 | "a net backend type (maybe it is not compiled " |
1044 | "into this binary)" ); |
1045 | return -1; |
1046 | } |
1047 | |
1048 | /* Do not add to a hub if it's a nic with a netdev= parameter. */ |
1049 | if (netdev->type != NET_CLIENT_DRIVER_NIC || |
1050 | !opts->u.nic.has_netdev) { |
1051 | peer = net_hub_add_port(0, NULL, NULL); |
1052 | } |
1053 | } |
1054 | |
1055 | if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) { |
1056 | /* FIXME drop when all init functions store an Error */ |
1057 | if (errp && !*errp) { |
1058 | error_setg(errp, QERR_DEVICE_INIT_FAILED, |
1059 | NetClientDriver_str(netdev->type)); |
1060 | } |
1061 | return -1; |
1062 | } |
1063 | return 0; |
1064 | } |
1065 | |
1066 | static void show_netdevs(void) |
1067 | { |
1068 | int idx; |
1069 | const char *available_netdevs[] = { |
1070 | "socket" , |
1071 | "hubport" , |
1072 | "tap" , |
1073 | #ifdef CONFIG_SLIRP |
1074 | "user" , |
1075 | #endif |
1076 | #ifdef CONFIG_L2TPV3 |
1077 | "l2tpv3" , |
1078 | #endif |
1079 | #ifdef CONFIG_VDE |
1080 | "vde" , |
1081 | #endif |
1082 | #ifdef CONFIG_NET_BRIDGE |
1083 | "bridge" , |
1084 | #endif |
1085 | #ifdef CONFIG_NETMAP |
1086 | "netmap" , |
1087 | #endif |
1088 | #ifdef CONFIG_POSIX |
1089 | "vhost-user" , |
1090 | #endif |
1091 | }; |
1092 | |
1093 | printf("Available netdev backend types:\n" ); |
1094 | for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) { |
1095 | puts(available_netdevs[idx]); |
1096 | } |
1097 | } |
1098 | |
1099 | static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) |
1100 | { |
1101 | gchar **substrings = NULL; |
1102 | void *object = NULL; |
1103 | Error *err = NULL; |
1104 | int ret = -1; |
1105 | Visitor *v = opts_visitor_new(opts); |
1106 | |
1107 | const char *type = qemu_opt_get(opts, "type" ); |
1108 | |
1109 | if (is_netdev && type && is_help_option(type)) { |
1110 | show_netdevs(); |
1111 | exit(0); |
1112 | } else { |
1113 | /* Parse convenience option format ip6-net=fec0::0[/64] */ |
1114 | const char *ip6_net = qemu_opt_get(opts, "ipv6-net" ); |
1115 | |
1116 | if (ip6_net) { |
1117 | char *prefix_addr; |
1118 | unsigned long prefix_len = 64; /* Default 64bit prefix length. */ |
1119 | |
1120 | substrings = g_strsplit(ip6_net, "/" , 2); |
1121 | if (!substrings || !substrings[0]) { |
1122 | error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net" , |
1123 | "a valid IPv6 prefix" ); |
1124 | goto out; |
1125 | } |
1126 | |
1127 | prefix_addr = substrings[0]; |
1128 | |
1129 | if (substrings[1]) { |
1130 | /* User-specified prefix length. */ |
1131 | int err; |
1132 | |
1133 | err = qemu_strtoul(substrings[1], NULL, 10, &prefix_len); |
1134 | if (err) { |
1135 | error_setg(errp, QERR_INVALID_PARAMETER_VALUE, |
1136 | "ipv6-prefixlen" , "a number" ); |
1137 | goto out; |
1138 | } |
1139 | } |
1140 | |
1141 | qemu_opt_set(opts, "ipv6-prefix" , prefix_addr, &error_abort); |
1142 | qemu_opt_set_number(opts, "ipv6-prefixlen" , prefix_len, |
1143 | &error_abort); |
1144 | qemu_opt_unset(opts, "ipv6-net" ); |
1145 | } |
1146 | } |
1147 | |
1148 | if (is_netdev) { |
1149 | visit_type_Netdev(v, NULL, (Netdev **)&object, &err); |
1150 | } else { |
1151 | visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err); |
1152 | } |
1153 | |
1154 | if (!err) { |
1155 | ret = net_client_init1(object, is_netdev, &err); |
1156 | } |
1157 | |
1158 | if (is_netdev) { |
1159 | qapi_free_Netdev(object); |
1160 | } else { |
1161 | qapi_free_NetLegacy(object); |
1162 | } |
1163 | |
1164 | out: |
1165 | error_propagate(errp, err); |
1166 | g_strfreev(substrings); |
1167 | visit_free(v); |
1168 | return ret; |
1169 | } |
1170 | |
1171 | void netdev_add(QemuOpts *opts, Error **errp) |
1172 | { |
1173 | net_client_init(opts, true, errp); |
1174 | } |
1175 | |
1176 | void qmp_netdev_add(QDict *qdict, QObject **ret, Error **errp) |
1177 | { |
1178 | Error *local_err = NULL; |
1179 | QemuOptsList *opts_list; |
1180 | QemuOpts *opts; |
1181 | |
1182 | opts_list = qemu_find_opts_err("netdev" , &local_err); |
1183 | if (local_err) { |
1184 | goto out; |
1185 | } |
1186 | |
1187 | opts = qemu_opts_from_qdict(opts_list, qdict, &local_err); |
1188 | if (local_err) { |
1189 | goto out; |
1190 | } |
1191 | |
1192 | netdev_add(opts, &local_err); |
1193 | if (local_err) { |
1194 | qemu_opts_del(opts); |
1195 | goto out; |
1196 | } |
1197 | |
1198 | out: |
1199 | error_propagate(errp, local_err); |
1200 | } |
1201 | |
1202 | void qmp_netdev_del(const char *id, Error **errp) |
1203 | { |
1204 | NetClientState *nc; |
1205 | QemuOpts *opts; |
1206 | |
1207 | nc = qemu_find_netdev(id); |
1208 | if (!nc) { |
1209 | error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, |
1210 | "Device '%s' not found" , id); |
1211 | return; |
1212 | } |
1213 | |
1214 | opts = qemu_opts_find(qemu_find_opts_err("netdev" , NULL), id); |
1215 | if (!opts) { |
1216 | error_setg(errp, "Device '%s' is not a netdev" , id); |
1217 | return; |
1218 | } |
1219 | |
1220 | qemu_del_net_client(nc); |
1221 | qemu_opts_del(opts); |
1222 | } |
1223 | |
1224 | static void netfilter_print_info(Monitor *mon, NetFilterState *nf) |
1225 | { |
1226 | char *str; |
1227 | ObjectProperty *prop; |
1228 | ObjectPropertyIterator iter; |
1229 | Visitor *v; |
1230 | |
1231 | /* generate info str */ |
1232 | object_property_iter_init(&iter, OBJECT(nf)); |
1233 | while ((prop = object_property_iter_next(&iter))) { |
1234 | if (!strcmp(prop->name, "type" )) { |
1235 | continue; |
1236 | } |
1237 | v = string_output_visitor_new(false, &str); |
1238 | object_property_get(OBJECT(nf), v, prop->name, NULL); |
1239 | visit_complete(v, &str); |
1240 | visit_free(v); |
1241 | monitor_printf(mon, ",%s=%s" , prop->name, str); |
1242 | g_free(str); |
1243 | } |
1244 | monitor_printf(mon, "\n" ); |
1245 | } |
1246 | |
1247 | void print_net_client(Monitor *mon, NetClientState *nc) |
1248 | { |
1249 | NetFilterState *nf; |
1250 | |
1251 | monitor_printf(mon, "%s: index=%d,type=%s,%s\n" , nc->name, |
1252 | nc->queue_index, |
1253 | NetClientDriver_str(nc->info->type), |
1254 | nc->info_str); |
1255 | if (!QTAILQ_EMPTY(&nc->filters)) { |
1256 | monitor_printf(mon, "filters:\n" ); |
1257 | } |
1258 | QTAILQ_FOREACH(nf, &nc->filters, next) { |
1259 | char *path = object_get_canonical_path_component(OBJECT(nf)); |
1260 | |
1261 | monitor_printf(mon, " - %s: type=%s" , path, |
1262 | object_get_typename(OBJECT(nf))); |
1263 | netfilter_print_info(mon, nf); |
1264 | g_free(path); |
1265 | } |
1266 | } |
1267 | |
1268 | RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name, |
1269 | Error **errp) |
1270 | { |
1271 | NetClientState *nc; |
1272 | RxFilterInfoList *filter_list = NULL, *last_entry = NULL; |
1273 | |
1274 | QTAILQ_FOREACH(nc, &net_clients, next) { |
1275 | RxFilterInfoList *entry; |
1276 | RxFilterInfo *info; |
1277 | |
1278 | if (has_name && strcmp(nc->name, name) != 0) { |
1279 | continue; |
1280 | } |
1281 | |
1282 | /* only query rx-filter information of NIC */ |
1283 | if (nc->info->type != NET_CLIENT_DRIVER_NIC) { |
1284 | if (has_name) { |
1285 | error_setg(errp, "net client(%s) isn't a NIC" , name); |
1286 | return NULL; |
1287 | } |
1288 | continue; |
1289 | } |
1290 | |
1291 | /* only query information on queue 0 since the info is per nic, |
1292 | * not per queue |
1293 | */ |
1294 | if (nc->queue_index != 0) |
1295 | continue; |
1296 | |
1297 | if (nc->info->query_rx_filter) { |
1298 | info = nc->info->query_rx_filter(nc); |
1299 | entry = g_malloc0(sizeof(*entry)); |
1300 | entry->value = info; |
1301 | |
1302 | if (!filter_list) { |
1303 | filter_list = entry; |
1304 | } else { |
1305 | last_entry->next = entry; |
1306 | } |
1307 | last_entry = entry; |
1308 | } else if (has_name) { |
1309 | error_setg(errp, "net client(%s) doesn't support" |
1310 | " rx-filter querying" , name); |
1311 | return NULL; |
1312 | } |
1313 | |
1314 | if (has_name) { |
1315 | break; |
1316 | } |
1317 | } |
1318 | |
1319 | if (filter_list == NULL && has_name) { |
1320 | error_setg(errp, "invalid net client name: %s" , name); |
1321 | } |
1322 | |
1323 | return filter_list; |
1324 | } |
1325 | |
1326 | void hmp_info_network(Monitor *mon, const QDict *qdict) |
1327 | { |
1328 | NetClientState *nc, *peer; |
1329 | NetClientDriver type; |
1330 | |
1331 | net_hub_info(mon); |
1332 | |
1333 | QTAILQ_FOREACH(nc, &net_clients, next) { |
1334 | peer = nc->peer; |
1335 | type = nc->info->type; |
1336 | |
1337 | /* Skip if already printed in hub info */ |
1338 | if (net_hub_id_for_client(nc, NULL) == 0) { |
1339 | continue; |
1340 | } |
1341 | |
1342 | if (!peer || type == NET_CLIENT_DRIVER_NIC) { |
1343 | print_net_client(mon, nc); |
1344 | } /* else it's a netdev connected to a NIC, printed with the NIC */ |
1345 | if (peer && type == NET_CLIENT_DRIVER_NIC) { |
1346 | monitor_printf(mon, " \\ " ); |
1347 | print_net_client(mon, peer); |
1348 | } |
1349 | } |
1350 | } |
1351 | |
1352 | void colo_notify_filters_event(int event, Error **errp) |
1353 | { |
1354 | NetClientState *nc; |
1355 | NetFilterState *nf; |
1356 | NetFilterClass *nfc = NULL; |
1357 | Error *local_err = NULL; |
1358 | |
1359 | QTAILQ_FOREACH(nc, &net_clients, next) { |
1360 | QTAILQ_FOREACH(nf, &nc->filters, next) { |
1361 | nfc = NETFILTER_GET_CLASS(OBJECT(nf)); |
1362 | nfc->handle_event(nf, event, &local_err); |
1363 | if (local_err) { |
1364 | error_propagate(errp, local_err); |
1365 | return; |
1366 | } |
1367 | } |
1368 | } |
1369 | } |
1370 | |
1371 | void qmp_set_link(const char *name, bool up, Error **errp) |
1372 | { |
1373 | NetClientState *ncs[MAX_QUEUE_NUM]; |
1374 | NetClientState *nc; |
1375 | int queues, i; |
1376 | |
1377 | queues = qemu_find_net_clients_except(name, ncs, |
1378 | NET_CLIENT_DRIVER__MAX, |
1379 | MAX_QUEUE_NUM); |
1380 | |
1381 | if (queues == 0) { |
1382 | error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, |
1383 | "Device '%s' not found" , name); |
1384 | return; |
1385 | } |
1386 | nc = ncs[0]; |
1387 | |
1388 | for (i = 0; i < queues; i++) { |
1389 | ncs[i]->link_down = !up; |
1390 | } |
1391 | |
1392 | if (nc->info->link_status_changed) { |
1393 | nc->info->link_status_changed(nc); |
1394 | } |
1395 | |
1396 | if (nc->peer) { |
1397 | /* Change peer link only if the peer is NIC and then notify peer. |
1398 | * If the peer is a HUBPORT or a backend, we do not change the |
1399 | * link status. |
1400 | * |
1401 | * This behavior is compatible with qemu hubs where there could be |
1402 | * multiple clients that can still communicate with each other in |
1403 | * disconnected mode. For now maintain this compatibility. |
1404 | */ |
1405 | if (nc->peer->info->type == NET_CLIENT_DRIVER_NIC) { |
1406 | for (i = 0; i < queues; i++) { |
1407 | ncs[i]->peer->link_down = !up; |
1408 | } |
1409 | } |
1410 | if (nc->peer->info->link_status_changed) { |
1411 | nc->peer->info->link_status_changed(nc->peer); |
1412 | } |
1413 | } |
1414 | } |
1415 | |
1416 | static void net_vm_change_state_handler(void *opaque, int running, |
1417 | RunState state) |
1418 | { |
1419 | NetClientState *nc; |
1420 | NetClientState *tmp; |
1421 | |
1422 | QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) { |
1423 | if (running) { |
1424 | /* Flush queued packets and wake up backends. */ |
1425 | if (nc->peer && qemu_can_send_packet(nc)) { |
1426 | qemu_flush_queued_packets(nc->peer); |
1427 | } |
1428 | } else { |
1429 | /* Complete all queued packets, to guarantee we don't modify |
1430 | * state later when VM is not running. |
1431 | */ |
1432 | qemu_flush_or_purge_queued_packets(nc, true); |
1433 | } |
1434 | } |
1435 | } |
1436 | |
1437 | void net_cleanup(void) |
1438 | { |
1439 | NetClientState *nc; |
1440 | |
1441 | /* We may del multiple entries during qemu_del_net_client(), |
1442 | * so QTAILQ_FOREACH_SAFE() is also not safe here. |
1443 | */ |
1444 | while (!QTAILQ_EMPTY(&net_clients)) { |
1445 | nc = QTAILQ_FIRST(&net_clients); |
1446 | if (nc->info->type == NET_CLIENT_DRIVER_NIC) { |
1447 | qemu_del_nic(qemu_get_nic(nc)); |
1448 | } else { |
1449 | qemu_del_net_client(nc); |
1450 | } |
1451 | } |
1452 | |
1453 | qemu_del_vm_change_state_handler(net_change_state_entry); |
1454 | } |
1455 | |
1456 | void net_check_clients(void) |
1457 | { |
1458 | NetClientState *nc; |
1459 | int i; |
1460 | |
1461 | net_hub_check_clients(); |
1462 | |
1463 | QTAILQ_FOREACH(nc, &net_clients, next) { |
1464 | if (!nc->peer) { |
1465 | warn_report("%s %s has no peer" , |
1466 | nc->info->type == NET_CLIENT_DRIVER_NIC |
1467 | ? "nic" : "netdev" , |
1468 | nc->name); |
1469 | } |
1470 | } |
1471 | |
1472 | /* Check that all NICs requested via -net nic actually got created. |
1473 | * NICs created via -device don't need to be checked here because |
1474 | * they are always instantiated. |
1475 | */ |
1476 | for (i = 0; i < MAX_NICS; i++) { |
1477 | NICInfo *nd = &nd_table[i]; |
1478 | if (nd->used && !nd->instantiated) { |
1479 | warn_report("requested NIC (%s, model %s) " |
1480 | "was not created (not supported by this machine?)" , |
1481 | nd->name ? nd->name : "anonymous" , |
1482 | nd->model ? nd->model : "unspecified" ); |
1483 | } |
1484 | } |
1485 | } |
1486 | |
1487 | static int net_init_client(void *dummy, QemuOpts *opts, Error **errp) |
1488 | { |
1489 | return net_client_init(opts, false, errp); |
1490 | } |
1491 | |
1492 | static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp) |
1493 | { |
1494 | return net_client_init(opts, true, errp); |
1495 | } |
1496 | |
1497 | /* For the convenience "--nic" parameter */ |
1498 | static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp) |
1499 | { |
1500 | char *mac, *nd_id; |
1501 | int idx, ret; |
1502 | NICInfo *ni; |
1503 | const char *type; |
1504 | |
1505 | type = qemu_opt_get(opts, "type" ); |
1506 | if (type && g_str_equal(type, "none" )) { |
1507 | return 0; /* Nothing to do, default_net is cleared in vl.c */ |
1508 | } |
1509 | |
1510 | idx = nic_get_free_idx(); |
1511 | if (idx == -1 || nb_nics >= MAX_NICS) { |
1512 | error_setg(errp, "no more on-board/default NIC slots available" ); |
1513 | return -1; |
1514 | } |
1515 | |
1516 | if (!type) { |
1517 | qemu_opt_set(opts, "type" , "user" , &error_abort); |
1518 | } |
1519 | |
1520 | ni = &nd_table[idx]; |
1521 | memset(ni, 0, sizeof(*ni)); |
1522 | ni->model = qemu_opt_get_del(opts, "model" ); |
1523 | |
1524 | /* Create an ID if the user did not specify one */ |
1525 | nd_id = g_strdup(qemu_opts_id(opts)); |
1526 | if (!nd_id) { |
1527 | nd_id = g_strdup_printf("__org.qemu.nic%i\n" , idx); |
1528 | qemu_opts_set_id(opts, nd_id); |
1529 | } |
1530 | |
1531 | /* Handle MAC address */ |
1532 | mac = qemu_opt_get_del(opts, "mac" ); |
1533 | if (mac) { |
1534 | ret = net_parse_macaddr(ni->macaddr.a, mac); |
1535 | g_free(mac); |
1536 | if (ret) { |
1537 | error_setg(errp, "invalid syntax for ethernet address" ); |
1538 | goto out; |
1539 | } |
1540 | if (is_multicast_ether_addr(ni->macaddr.a)) { |
1541 | error_setg(errp, "NIC cannot have multicast MAC address" ); |
1542 | ret = -1; |
1543 | goto out; |
1544 | } |
1545 | } |
1546 | qemu_macaddr_default_if_unset(&ni->macaddr); |
1547 | |
1548 | ret = net_client_init(opts, true, errp); |
1549 | if (ret == 0) { |
1550 | ni->netdev = qemu_find_netdev(nd_id); |
1551 | ni->used = true; |
1552 | nb_nics++; |
1553 | } |
1554 | |
1555 | out: |
1556 | g_free(nd_id); |
1557 | return ret; |
1558 | } |
1559 | |
1560 | int net_init_clients(Error **errp) |
1561 | { |
1562 | net_change_state_entry = |
1563 | qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL); |
1564 | |
1565 | QTAILQ_INIT(&net_clients); |
1566 | |
1567 | if (qemu_opts_foreach(qemu_find_opts("netdev" ), |
1568 | net_init_netdev, NULL, errp)) { |
1569 | return -1; |
1570 | } |
1571 | |
1572 | if (qemu_opts_foreach(qemu_find_opts("nic" ), net_param_nic, NULL, errp)) { |
1573 | return -1; |
1574 | } |
1575 | |
1576 | if (qemu_opts_foreach(qemu_find_opts("net" ), net_init_client, NULL, errp)) { |
1577 | return -1; |
1578 | } |
1579 | |
1580 | return 0; |
1581 | } |
1582 | |
1583 | int net_client_parse(QemuOptsList *opts_list, const char *optarg) |
1584 | { |
1585 | if (!qemu_opts_parse_noisily(opts_list, optarg, true)) { |
1586 | return -1; |
1587 | } |
1588 | |
1589 | return 0; |
1590 | } |
1591 | |
1592 | /* From FreeBSD */ |
1593 | /* XXX: optimize */ |
1594 | uint32_t net_crc32(const uint8_t *p, int len) |
1595 | { |
1596 | uint32_t crc; |
1597 | int carry, i, j; |
1598 | uint8_t b; |
1599 | |
1600 | crc = 0xffffffff; |
1601 | for (i = 0; i < len; i++) { |
1602 | b = *p++; |
1603 | for (j = 0; j < 8; j++) { |
1604 | carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); |
1605 | crc <<= 1; |
1606 | b >>= 1; |
1607 | if (carry) { |
1608 | crc = ((crc ^ POLYNOMIAL_BE) | carry); |
1609 | } |
1610 | } |
1611 | } |
1612 | |
1613 | return crc; |
1614 | } |
1615 | |
1616 | uint32_t net_crc32_le(const uint8_t *p, int len) |
1617 | { |
1618 | uint32_t crc; |
1619 | int carry, i, j; |
1620 | uint8_t b; |
1621 | |
1622 | crc = 0xffffffff; |
1623 | for (i = 0; i < len; i++) { |
1624 | b = *p++; |
1625 | for (j = 0; j < 8; j++) { |
1626 | carry = (crc & 0x1) ^ (b & 0x01); |
1627 | crc >>= 1; |
1628 | b >>= 1; |
1629 | if (carry) { |
1630 | crc ^= POLYNOMIAL_LE; |
1631 | } |
1632 | } |
1633 | } |
1634 | |
1635 | return crc; |
1636 | } |
1637 | |
1638 | QemuOptsList qemu_netdev_opts = { |
1639 | .name = "netdev" , |
1640 | .implied_opt_name = "type" , |
1641 | .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head), |
1642 | .desc = { |
1643 | /* |
1644 | * no elements => accept any params |
1645 | * validation will happen later |
1646 | */ |
1647 | { /* end of list */ } |
1648 | }, |
1649 | }; |
1650 | |
1651 | QemuOptsList qemu_nic_opts = { |
1652 | .name = "nic" , |
1653 | .implied_opt_name = "type" , |
1654 | .head = QTAILQ_HEAD_INITIALIZER(qemu_nic_opts.head), |
1655 | .desc = { |
1656 | /* |
1657 | * no elements => accept any params |
1658 | * validation will happen later |
1659 | */ |
1660 | { /* end of list */ } |
1661 | }, |
1662 | }; |
1663 | |
1664 | QemuOptsList qemu_net_opts = { |
1665 | .name = "net" , |
1666 | .implied_opt_name = "type" , |
1667 | .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head), |
1668 | .desc = { |
1669 | /* |
1670 | * no elements => accept any params |
1671 | * validation will happen later |
1672 | */ |
1673 | { /* end of list */ } |
1674 | }, |
1675 | }; |
1676 | |
1677 | void net_socket_rs_init(SocketReadState *rs, |
1678 | SocketReadStateFinalize *finalize, |
1679 | bool vnet_hdr) |
1680 | { |
1681 | rs->state = 0; |
1682 | rs->vnet_hdr = vnet_hdr; |
1683 | rs->index = 0; |
1684 | rs->packet_len = 0; |
1685 | rs->vnet_hdr_len = 0; |
1686 | memset(rs->buf, 0, sizeof(rs->buf)); |
1687 | rs->finalize = finalize; |
1688 | } |
1689 | |
1690 | /* |
1691 | * Returns |
1692 | * 0: success |
1693 | * -1: error occurs |
1694 | */ |
1695 | int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size) |
1696 | { |
1697 | unsigned int l; |
1698 | |
1699 | while (size > 0) { |
1700 | /* Reassemble a packet from the network. |
1701 | * 0 = getting length. |
1702 | * 1 = getting vnet header length. |
1703 | * 2 = getting data. |
1704 | */ |
1705 | switch (rs->state) { |
1706 | case 0: |
1707 | l = 4 - rs->index; |
1708 | if (l > size) { |
1709 | l = size; |
1710 | } |
1711 | memcpy(rs->buf + rs->index, buf, l); |
1712 | buf += l; |
1713 | size -= l; |
1714 | rs->index += l; |
1715 | if (rs->index == 4) { |
1716 | /* got length */ |
1717 | rs->packet_len = ntohl(*(uint32_t *)rs->buf); |
1718 | rs->index = 0; |
1719 | if (rs->vnet_hdr) { |
1720 | rs->state = 1; |
1721 | } else { |
1722 | rs->state = 2; |
1723 | rs->vnet_hdr_len = 0; |
1724 | } |
1725 | } |
1726 | break; |
1727 | case 1: |
1728 | l = 4 - rs->index; |
1729 | if (l > size) { |
1730 | l = size; |
1731 | } |
1732 | memcpy(rs->buf + rs->index, buf, l); |
1733 | buf += l; |
1734 | size -= l; |
1735 | rs->index += l; |
1736 | if (rs->index == 4) { |
1737 | /* got vnet header length */ |
1738 | rs->vnet_hdr_len = ntohl(*(uint32_t *)rs->buf); |
1739 | rs->index = 0; |
1740 | rs->state = 2; |
1741 | } |
1742 | break; |
1743 | case 2: |
1744 | l = rs->packet_len - rs->index; |
1745 | if (l > size) { |
1746 | l = size; |
1747 | } |
1748 | if (rs->index + l <= sizeof(rs->buf)) { |
1749 | memcpy(rs->buf + rs->index, buf, l); |
1750 | } else { |
1751 | fprintf(stderr, "serious error: oversized packet received," |
1752 | "connection terminated.\n" ); |
1753 | rs->index = rs->state = 0; |
1754 | return -1; |
1755 | } |
1756 | |
1757 | rs->index += l; |
1758 | buf += l; |
1759 | size -= l; |
1760 | if (rs->index >= rs->packet_len) { |
1761 | rs->index = 0; |
1762 | rs->state = 0; |
1763 | assert(rs->finalize); |
1764 | rs->finalize(rs); |
1765 | } |
1766 | break; |
1767 | } |
1768 | } |
1769 | |
1770 | assert(size == 0); |
1771 | return 0; |
1772 | } |
1773 | |