Lines Matching +full:event +full:- +full:tap
4 * Copyright (c) 2003-2008 Fabrice Bellard
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
42 #include "qemu/error-report.h"
43 #include "qemu/main-loop.h"
46 #include "net/tap.h"
75 qemu_set_fd_handler(s->fd, in tap_update_fd_handler()
76 s->read_poll && s->enabled ? tap_send : NULL, in tap_update_fd_handler()
77 s->write_poll && s->enabled ? tap_writable : NULL, in tap_update_fd_handler()
83 s->read_poll = enable; in tap_read_poll()
89 s->write_poll = enable; in tap_write_poll()
99 qemu_flush_queued_packets(&s->nc); in tap_writable()
106 len = RETRY_ON_EINTR(writev(s->fd, iov, iovcnt)); in tap_write_packet()
108 if (len == -1 && errno == EAGAIN) { in tap_write_packet()
124 if (s->host_vnet_hdr_len && !s->using_vnet_hdr) { in tap_receive_iov()
127 iov_copy[0].iov_len = s->host_vnet_hdr_len; in tap_receive_iov()
166 uint8_t *buf = s->buf; in tap_send()
170 size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); in tap_send()
175 if (s->host_vnet_hdr_len && !s->using_vnet_hdr) { in tap_send()
176 buf += s->host_vnet_hdr_len; in tap_send()
177 size -= s->host_vnet_hdr_len; in tap_send()
180 if (net_peer_needs_padding(&s->nc)) { in tap_send()
187 size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed); in tap_send()
212 assert(nc->info->type == NET_CLIENT_DRIVER_TAP); in tap_has_ufo()
214 return s->has_ufo; in tap_has_ufo()
221 assert(nc->info->type == NET_CLIENT_DRIVER_TAP); in tap_has_uso()
223 return s->has_uso; in tap_has_uso()
230 assert(nc->info->type == NET_CLIENT_DRIVER_TAP); in tap_has_vnet_hdr()
232 return !!s->host_vnet_hdr_len; in tap_has_vnet_hdr()
244 assert(nc->info->type == NET_CLIENT_DRIVER_TAP); in tap_set_vnet_hdr_len()
246 tap_fd_set_vnet_hdr_len(s->fd, len); in tap_set_vnet_hdr_len()
247 s->host_vnet_hdr_len = len; in tap_set_vnet_hdr_len()
248 s->using_vnet_hdr = true; in tap_set_vnet_hdr_len()
255 return tap_fd_set_vnet_le(s->fd, is_le); in tap_set_vnet_le()
262 return tap_fd_set_vnet_be(s->fd, is_be); in tap_set_vnet_be()
269 if (s->fd < 0) { in tap_set_offload()
273 tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo, uso4, uso6); in tap_set_offload()
281 if (s->down_script[0]) { in tap_exit_notify()
282 launch_script(s->down_script, s->down_script_arg, s->fd, &err); in tap_exit_notify()
293 if (s->vhost_net) { in tap_cleanup()
294 vhost_net_cleanup(s->vhost_net); in tap_cleanup()
295 g_free(s->vhost_net); in tap_cleanup()
296 s->vhost_net = NULL; in tap_cleanup()
301 tap_exit_notify(&s->exit, NULL); in tap_cleanup()
302 qemu_remove_exit_notifier(&s->exit); in tap_cleanup()
306 close(s->fd); in tap_cleanup()
307 s->fd = -1; in tap_cleanup()
320 assert(nc->info->type == NET_CLIENT_DRIVER_TAP); in tap_set_steering_ebpf()
322 return tap_fd_set_steering_ebpf(s->fd, prog_fd) == 0; in tap_set_steering_ebpf()
328 assert(nc->info->type == NET_CLIENT_DRIVER_TAP); in tap_get_fd()
329 return s->fd; in tap_get_fd()
365 s->fd = fd; in net_tap_fd_init()
366 s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; in net_tap_fd_init()
367 s->using_vnet_hdr = false; in net_tap_fd_init()
368 s->has_ufo = tap_probe_has_ufo(s->fd); in net_tap_fd_init()
369 s->has_uso = tap_probe_has_uso(s->fd); in net_tap_fd_init()
370 s->enabled = true; in net_tap_fd_init()
371 tap_set_offload(&s->nc, 0, 0, 0, 0, 0, 0, 0); in net_tap_fd_init()
373 * Make sure host header length is set correctly in tap: in net_tap_fd_init()
377 tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len); in net_tap_fd_init()
380 s->vhost_net = NULL; in net_tap_fd_init()
382 s->exit.notify = tap_exit_notify; in net_tap_fd_init()
383 qemu_add_exit_notifier(&s->exit); in net_tap_fd_init()
396 * excluded_fd if already included in the [STDIN_FILENO - STDERR_FILENO] in close_all_fds_after_fork()
400 nskip--; in close_all_fds_after_fork()
455 cmsg->cmsg_level = SOL_SOCKET; in recv_fd()
456 cmsg->cmsg_type = SCM_RIGHTS; in recv_fd()
457 cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); in recv_fd()
458 msg.msg_controllen = cmsg->cmsg_len; in recv_fd()
493 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { in net_bridge_run_helper()
495 return -1; in net_bridge_run_helper()
502 return -1; in net_bridge_run_helper()
510 fd_buf = g_strdup_printf("%s%d", "--fd=", sv[1]); in net_bridge_run_helper()
515 if (strstr(helper, "--br=") == NULL) { in net_bridge_run_helper()
516 br_buf = g_strdup_printf("%s%s", "--br=", bridge); in net_bridge_run_helper()
520 "--use-vnet", fd_buf, br_buf ? br_buf : ""); in net_bridge_run_helper()
524 *parg++ = (char *)"-c"; in net_bridge_run_helper()
533 br_buf = g_strdup_printf("%s%s", "--br=", bridge); in net_bridge_run_helper()
537 *parg++ = (char *)"--use-vnet"; in net_bridge_run_helper()
566 return -1; in net_bridge_run_helper()
570 return -1; in net_bridge_run_helper()
584 assert(netdev->type == NET_CLIENT_DRIVER_BRIDGE); in net_init_bridge()
585 bridge = &netdev->u.bridge; in net_init_bridge()
586 helper = bridge->helper; in net_init_bridge()
587 br = bridge->br ?: DEFAULT_BRIDGE_INTERFACE; in net_init_bridge()
590 if (fd == -1) { in net_init_bridge()
591 return -1; in net_init_bridge()
596 return -1; in net_init_bridge()
601 return -1; in net_init_bridge()
605 qemu_set_info_str(&s->nc, "helper=%s,br=%s", helper, br); in net_init_bridge()
610 static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, in net_tap_init() argument
617 if (tap->has_vnet_hdr) { in net_tap_init()
618 *vnet_hdr = tap->vnet_hdr; in net_tap_init()
628 return -1; in net_tap_init()
638 return -1; in net_tap_init()
647 static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, in net_init_tap_one() argument
657 tap_set_sndbuf(s->fd, tap, &err); in net_init_tap_one()
663 if (tap->fd || tap->fds) { in net_init_tap_one()
664 qemu_set_info_str(&s->nc, "fd=%d", fd); in net_init_tap_one()
665 } else if (tap->helper) { in net_init_tap_one()
666 qemu_set_info_str(&s->nc, "helper=%s", tap->helper); in net_init_tap_one()
668 qemu_set_info_str(&s->nc, "ifname=%s,script=%s,downscript=%s", ifname, in net_init_tap_one()
672 snprintf(s->down_script, sizeof(s->down_script), "%s", downscript); in net_init_tap_one()
673 snprintf(s->down_script_arg, sizeof(s->down_script_arg), in net_init_tap_one()
678 if (tap->has_vhost ? tap->vhost : in net_init_tap_one()
679 vhostfdname || (tap->has_vhostforce && tap->vhostforce)) { in net_init_tap_one()
683 options.net_backend = &s->nc; in net_init_tap_one()
684 if (tap->has_poll_us) { in net_init_tap_one()
685 options.busyloop_timeout = tap->poll_us; in net_init_tap_one()
692 if (vhostfd == -1) { in net_init_tap_one()
702 vhostfd = open("/dev/vhost-net", O_RDWR); in net_init_tap_one()
705 "tap: open vhost char device failed"); in net_init_tap_one()
716 s->vhost_net = vhost_net_init(&options); in net_init_tap_one()
717 if (!s->vhost_net) { in net_init_tap_one()
719 "vhost-net requested but could not be initialized"); in net_init_tap_one()
730 qemu_del_net_client(&s->nc); in net_init_tap_one()
745 fds[i] = g_strndup(ptr, this - ptr); in get_fds()
762 const NetdevTapOptions *tap; in net_init_tap() local
764 /* for the no-fd, no-helper case */ in net_init_tap()
772 assert(netdev->type == NET_CLIENT_DRIVER_TAP); in net_init_tap()
773 tap = &netdev->u.tap; in net_init_tap()
774 queues = tap->has_queues ? tap->queues : 1; in net_init_tap()
775 vhostfdname = tap->vhostfd; in net_init_tap()
776 script = tap->script; in net_init_tap()
777 downscript = tap->downscript; in net_init_tap()
779 /* QEMU hubs do not support multiqueue tap, in this case peer is set. in net_init_tap()
780 * For -netdev, peer is always NULL. */ in net_init_tap()
781 if (peer && (tap->has_queues || tap->fds || tap->vhostfds)) { in net_init_tap()
782 error_setg(errp, "Multiqueue tap cannot be used with hubs"); in net_init_tap()
783 return -1; in net_init_tap()
786 if (tap->fd) { in net_init_tap()
787 if (tap->ifname || tap->script || tap->downscript || in net_init_tap()
788 tap->has_vnet_hdr || tap->helper || tap->has_queues || in net_init_tap()
789 tap->fds || tap->vhostfds) { in net_init_tap()
793 return -1; in net_init_tap()
796 fd = monitor_fd_param(monitor_cur(), tap->fd, errp); in net_init_tap()
797 if (fd == -1) { in net_init_tap()
798 return -1; in net_init_tap()
805 return -1; in net_init_tap()
811 return -1; in net_init_tap()
814 net_init_tap_one(tap, peer, "tap", name, NULL, in net_init_tap()
820 return -1; in net_init_tap()
822 } else if (tap->fds) { in net_init_tap()
827 if (tap->ifname || tap->script || tap->downscript || in net_init_tap()
828 tap->has_vnet_hdr || tap->helper || tap->has_queues || in net_init_tap()
829 tap->vhostfd) { in net_init_tap()
833 return -1; in net_init_tap()
839 nfds = get_fds(tap->fds, fds, MAX_TAP_QUEUES); in net_init_tap()
840 if (tap->vhostfds) { in net_init_tap()
841 nvhosts = get_fds(tap->vhostfds, vhost_fds, MAX_TAP_QUEUES); in net_init_tap()
845 ret = -1; in net_init_tap()
852 if (fd == -1) { in net_init_tap()
853 ret = -1; in net_init_tap()
867 ret = -1; in net_init_tap()
872 "vnet_hdr not consistent across given tap fds"); in net_init_tap()
873 ret = -1; in net_init_tap()
877 net_init_tap_one(tap, peer, "tap", name, ifname, in net_init_tap()
879 tap->vhostfds ? vhost_fds[i] : NULL, in net_init_tap()
883 ret = -1; in net_init_tap()
898 } else if (tap->helper) { in net_init_tap()
899 if (tap->ifname || tap->script || tap->downscript || in net_init_tap()
900 tap->has_vnet_hdr || tap->has_queues || tap->vhostfds) { in net_init_tap()
903 return -1; in net_init_tap()
906 fd = net_bridge_run_helper(tap->helper, in net_init_tap()
907 tap->br ?: DEFAULT_BRIDGE_INTERFACE, in net_init_tap()
909 if (fd == -1) { in net_init_tap()
910 return -1; in net_init_tap()
915 return -1; in net_init_tap()
920 return -1; in net_init_tap()
923 net_init_tap_one(tap, peer, "bridge", name, ifname, in net_init_tap()
929 return -1; in net_init_tap()
934 if (tap->vhostfds) { in net_init_tap()
936 return -1; in net_init_tap()
947 if (tap->ifname) { in net_init_tap()
948 pstrcpy(ifname, sizeof ifname, tap->ifname); in net_init_tap()
954 fd = net_tap_init(tap, &vnet_hdr, i >= 1 ? "no" : script, in net_init_tap()
956 if (fd == -1) { in net_init_tap()
957 return -1; in net_init_tap()
960 if (queues > 1 && i == 0 && !tap->ifname) { in net_init_tap()
964 return -1; in net_init_tap()
968 net_init_tap_one(tap, peer, "tap", name, ifname, in net_init_tap()
975 return -1; in net_init_tap()
986 assert(nc->info->type == NET_CLIENT_DRIVER_TAP); in tap_get_vhost_net()
987 return s->vhost_net; in tap_get_vhost_net()
995 if (s->enabled) { in tap_enable()
998 ret = tap_fd_enable(s->fd); in tap_enable()
1000 s->enabled = true; in tap_enable()
1012 if (s->enabled == 0) { in tap_disable()
1015 ret = tap_fd_disable(s->fd); in tap_disable()
1018 s->enabled = false; in tap_disable()