static TAPState *net_tap_fd_init(NetClientState *peer, const char *model, const char *name, int fd, int vnet_hdr) { NetClientState *nc; TAPState *s; nc = qemu_new_net_client(&net_tap_info, peer, model, name); s = DO_UPCAST(TAPState, nc, nc); s->fd = fd; s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; s->using_vnet_hdr = false; s->has_ufo = tap_probe_has_ufo(s->fd); s->enabled = true; tap_set_offload(&s->nc, 0, 0, 0, 0, 0); /* * Make sure host header length is set correctly in tap: * it might have been modified by another instance of qemu. */ if (tap_probe_vnet_hdr_len(s->fd, s->host_vnet_hdr_len)) { tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len); } tap_read_poll(s, true); s->vhost_net = NULL; return s; }
static int tap_win32_init(VLANState *vlan, const char *model, const char *name, const char *ifname) { VLANClientState *nc; TAPState *s; tap_win32_overlapped_t *handle; if (tap_win32_open(&handle, ifname) < 0) { printf("tap: Could not open '%s'\n", ifname); return -1; } nc = qemu_new_net_client(&net_tap_win32_info, vlan, NULL, model, name); s = DO_UPCAST(TAPState, nc, nc); snprintf(s->nc.info_str, sizeof(s->nc.info_str), "tap: ifname=%s", ifname); s->handle = handle; qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s); return 0; }
/* The exported init function * * ... -net netmap,ifname="..." */ int net_init_netmap(const Netdev *netdev, const char *name, NetClientState *peer, Error **errp) { const NetdevNetmapOptions *netmap_opts = &netdev->u.netmap; struct nm_desc *nmd; NetClientState *nc; Error *err = NULL; NetmapState *s; nmd = netmap_open(netmap_opts, &err); if (err) { error_propagate(errp, err); return -1; } /* Create the object. */ nc = qemu_new_net_client(&net_netmap_info, peer, "netmap", name); s = DO_UPCAST(NetmapState, nc, nc); s->nmd = nmd; s->tx = NETMAP_TXRING(nmd->nifp, 0); s->rx = NETMAP_RXRING(nmd->nifp, 0); s->vnet_hdr_len = 0; pstrcpy(s->ifname, sizeof(s->ifname), netmap_opts->ifname); netmap_read_poll(s, true); /* Initially only poll for reads. */ return 0; }
static int net_vhost_user_init(NetClientState *peer, const char *device, const char *name, CharDriverState *chr, int queues) { NetClientState *nc; VhostUserState *s; int i; assert(name); assert(queues > 0); for (i = 0; i < queues; i++) { nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name); snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s", i, chr->label); nc->queue_index = i; s = DO_UPCAST(VhostUserState, nc, nc); s->chr = chr; } qemu_chr_add_handlers(chr, NULL, NULL, net_vhost_user_event, nc[0].name); return 0; }
static int net_vde_init(NetClientState *peer, const char *model, const char *name, const char *sock, int port, const char *group, int mode) { NetClientState *nc; VDEState *s; VDECONN *vde; char *init_group = (char *)group; char *init_sock = (char *)sock; struct vde_open_args args = { .port = port, .group = init_group, .mode = mode, }; vde = vde_open(init_sock, (char *)"QEMU", &args); if (!vde){ return -1; } nc = qemu_new_net_client(&net_vde_info, peer, model, name); snprintf(nc->info_str, sizeof(nc->info_str), "sock=%s,fd=%d", sock, vde_datafd(vde)); s = DO_UPCAST(VDEState, nc, nc); s->vde = vde; qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); return 0; }
static int net_socket_listen_init(NetClientState *peer, const char *model, const char *name, const char *host_str) { NetClientState *nc; NetSocketState *s; struct sockaddr_in saddr; int fd, val, ret; if (parse_host_port(&saddr, host_str) < 0) return -1; fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); return -1; } socket_set_nonblock(fd); /* allow fast reuse */ val = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { perror("bind"); closesocket(fd); return -1; } ret = listen(fd, 0); if (ret < 0) { perror("listen"); closesocket(fd); return -1; } nc = qemu_new_net_client(&net_socket_info, peer, model, name); s = DO_UPCAST(NetSocketState, nc, nc); s->fd = -1; s->listen_fd = fd; s->nc.link_down = true; qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); return 0; }
static int net_dump_init(NetClientState *peer, const char *device, const char *name, const char *filename, int len, Error **errp) { struct pcap_file_hdr hdr; NetClientState *nc; DumpState *s; struct tm tm; int fd; fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644); if (fd < 0) { error_setg_errno(errp, errno, "-net dump: can't open %s", filename); return -1; } hdr.magic = PCAP_MAGIC; hdr.version_major = 2; hdr.version_minor = 4; hdr.thiszone = 0; hdr.sigfigs = 0; hdr.snaplen = len; hdr.linktype = 1; if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { error_setg_errno(errp, errno, "-net dump write error"); close(fd); return -1; } nc = qemu_new_net_client(&net_dump_info, peer, device, name); snprintf(nc->info_str, sizeof(nc->info_str), "dump to %s (len=%d)", filename, len); s = DO_UPCAST(DumpState, nc, nc); s->fd = fd; s->pcap_caplen = len; qemu_get_timedate(&tm, 0); s->start_ts = mktime(&tm); return 0; }
static int net_vhost_user_init(NetClientState *peer, const char *device, const char *name, Chardev *chr, int queues) { Error *err = NULL; NetClientState *nc, *nc0 = NULL; VhostUserState *s; int i; assert(name); assert(queues > 0); for (i = 0; i < queues; i++) { nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name); snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s", i, chr->label); nc->queue_index = i; if (!nc0) { nc0 = nc; s = DO_UPCAST(VhostUserState, nc, nc); if (!qemu_chr_fe_init(&s->chr, chr, &err)) { error_report_err(err); return -1; } } } s = DO_UPCAST(VhostUserState, nc, nc0); do { if (qemu_chr_fe_wait_connected(&s->chr, &err) < 0) { error_report_err(err); return -1; } qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, NULL, nc0->name, NULL, true); } while (!s->started); assert(s->vhost_net); return 0; }
static TAPState *net_tap_fd_init(VLANState *vlan, const char *model, const char *name, int fd, int vnet_hdr) { VLANClientState *nc; TAPState *s; nc = qemu_new_net_client(&net_tap_info, vlan, NULL, model, name); s = DO_UPCAST(TAPState, nc, nc); s->fd = fd; s->has_vnet_hdr = vnet_hdr != 0; s->using_vnet_hdr = 0; s->has_ufo = tap_probe_has_ufo(s->fd); tap_set_offload(&s->nc, 0, 0, 0, 0, 0); tap_read_poll(s, 1); return s; }
static int net_vhost_user_init(NetClientState *peer, const char *device, const char *name, CharDriverState *chr) { NetClientState *nc; VhostUserState *s; nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name); snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s", chr->label); s = DO_UPCAST(VhostUserState, nc, nc); /* We don't provide a receive callback */ s->nc.receive_disabled = 1; s->chr = chr; qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s); return 0; }
static TAPState *net_tap_fd_init(NetClientState *peer, const char *model, const char *name, int fd, int vnet_hdr) { NetClientState *nc; TAPState *s; nc = qemu_new_net_client(&net_tap_info, peer, model, name); s = DO_UPCAST(TAPState, nc, nc); s->fd = fd; s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; s->using_vnet_hdr = 0; s->has_ufo = tap_probe_has_ufo(s->fd); tap_set_offload(&s->nc, 0, 0, 0, 0, 0); tap_read_poll(s, 1); s->vhost_net = NULL; return s; }
static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, const char *model, const char *name, int fd, int is_connected) { VLANClientState *nc; NetSocketState *s; nc = qemu_new_net_client(&net_socket_info, vlan, NULL, model, name); snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd); s = DO_UPCAST(NetSocketState, nc, nc); s->fd = fd; if (is_connected) { net_socket_connect(s); } else { qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s); } return s; }
static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, const char *model, const char *name, int fd, int is_connected) { struct sockaddr_in saddr; int newfd; socklen_t saddr_len; NetClientState *nc; NetSocketState *s; /* fd passed: multicast: "learn" dgram_dst address from bound address and save it * Because this may be "shared" socket from a "master" process, datagrams would be recv() * by ONLY ONE process: we must "clone" this dgram socket --jjo */ if (is_connected) { if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) { /* must be bound */ if (saddr.sin_addr.s_addr == 0) { fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, " "cannot setup multicast dst addr\n", fd); goto err; } /* clone dgram socket */ newfd = net_socket_mcast_create(&saddr, NULL); if (newfd < 0) { /* error already reported by net_socket_mcast_create() */ goto err; } /* clone newfd to fd, close newfd */ dup2(newfd, fd); close(newfd); } else { fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n", fd, strerror(errno)); goto err; } } nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name); snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d (%s mcast=%s:%d)", fd, is_connected ? "cloned" : "", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); s = DO_UPCAST(NetSocketState, nc, nc); s->fd = fd; s->listen_fd = -1; qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); /* mcast: save bound address as dst */ if (is_connected) { s->dgram_dst = saddr; } return s; err: closesocket(fd); return NULL; }
int net_init_vnic(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan) { int fd, len, vnderr, syserr; const char *ifname, *mac; uchar_t *macaddr; VLANClientState *ncp; VNICState *vsp; vnd_prop_buf_t vib; if ((ifname = qemu_opt_get(opts, "ifname")) == NULL) { error_report("missing ifname required for vnic\n"); return (-1); } mac = qemu_opt_get(opts, "macaddr"); if (mac != NULL) { macaddr = _link_aton(mac, &len); if (macaddr == NULL || len != ETHERADDRL) { error_report("invalid macaddr for vnic: %s\n", mac); return (-1); } } ncp = qemu_new_net_client(&net_vnic_info, vlan, NULL, "vnic", name); vsp = DO_UPCAST(VNICState, vns_nc, ncp); vsp->vns_hdl = vnd_open(NULL, ifname, &vnderr, &syserr); if (vsp->vns_hdl == NULL) { const char *err = vnderr != VND_E_SYS ? vnd_strerror(vnderr) : vnd_strsyserror(syserr); error_report("vnic: failed to open interface %s - %s\n", ifname, err); return (-1); } vib.vpb_size = 1024 * 1024 * 4; /* 4 MB */ if (vnd_prop_set(vsp->vns_hdl, VND_PROP_RXBUF, &vib, sizeof (vib)) != 0) { const char *err = vnderr != VND_E_SYS ? vnd_strerror(vnderr) : vnd_strsyserror(syserr); error_report("failed to change rx buf size: %s\n", err); return (-1); } vib.vpb_size = 1024 * 1024 * 4; /* 4 MB */ if (vnd_prop_set(vsp->vns_hdl, VND_PROP_TXBUF, &vib, sizeof (vib)) != 0) { const char *err = vnderr != VND_E_SYS ? vnd_strerror(vnderr) : vnd_strsyserror(syserr); error_report("failed to change tx buf size: %s\n", err); return (-1); } fd = vnd_pollfd(vsp->vns_hdl); if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { error_report("vnic: failed to set fd on interface %s to " "non-blocking: %s\n", ifname, strerror(errno)); return (-1); } vsp->vns_fd = fd; snprintf(vsp->vns_nc.info_str, sizeof (vsp->vns_nc.info_str), "ifname=%s", qemu_opt_get(opts, "ifname")); if (vnic_dhcp_init(&vsp->vns_ds, opts) == 0) return (-1); if (vnic_frameio_init(vsp) != 0) { error_report("vnic: failed initialize frameio: %s\n", strerror(errno)); return (-1); } /* We have to manually intialize the polling for read */ vnic_read_poll(vsp, 1); return (0); }