From 8a59df2477f869eb4b3f582c36cb0e08018fbcff Mon Sep 17 00:00:00 2001 From: Dan McDonald Date: Wed, 22 Apr 2015 16:15:39 -0400 Subject: [PATCH] Revert "HVM-798 qemu could know about vnd" This reverts commit 31a39c6ea8dfc9021436264d83dc07a4d799ff61. --- build.sh | 2 +- net/vnic.c | 246 ++++++++++++++++++++++--------------------------------------- 2 files changed, 88 insertions(+), 160 deletions(-) Updated to 20190827 diff -ruN illumos-kvm-cmd-41e7c3e192eb39bb5ced7667fdc12ad2b33e646d.orig/build.sh illumos-kvm-cmd-41e7c3e192eb39bb5ced7667fdc12ad2b33e646d.patched/build.sh --- illumos-kvm-cmd-41e7c3e192eb39bb5ced7667fdc12ad2b33e646d.orig/build.sh 2020-03-19 21:53:41.308240253 +0000 +++ illumos-kvm-cmd-41e7c3e192eb39bb5ced7667fdc12ad2b33e646d.patched/build.sh 2020-03-19 21:55:18.480389342 +0000 @@ -48,7 +48,7 @@ XCFLAGS="$XCFLAGS -fno-builtin -I${PNGINC} -isystem ${DESTDIR}/usr/include -msave-args" XLDFLAGS="-nodefaultlibs -L${PNGLIB} -L${DESTDIR}/usr/lib/amd64 -L${DESTDIR}/lib/amd64" XLDFLAGS="${XLDFLAGS} -Wl,-zfatal-warnings -Wl,-zassert-deflib" -XLDFLAGS="${XLDFLAGS} -lz -lm -lc -lvnd" +XLDFLAGS="${XLDFLAGS} -lz -lm -lc" ./configure \ --cc=$CC \ --extra-cflags="${XCFLAGS}" \ diff -ruN illumos-kvm-cmd-41e7c3e192eb39bb5ced7667fdc12ad2b33e646d.orig/net/vnic.c illumos-kvm-cmd-41e7c3e192eb39bb5ced7667fdc12ad2b33e646d.patched/net/vnic.c --- illumos-kvm-cmd-41e7c3e192eb39bb5ced7667fdc12ad2b33e646d.orig/net/vnic.c 2020-03-19 21:53:41.379418566 +0000 +++ illumos-kvm-cmd-41e7c3e192eb39bb5ced7667fdc12ad2b33e646d.patched/net/vnic.c 2020-03-19 22:30:09.207208336 +0000 @@ -1,6 +1,6 @@ /* * QEMU System Emulator - * illumos VNIC/vnd support + * Solaris VNIC support * * Copyright 2016 Joyent, Inc. * @@ -33,15 +33,12 @@ #include #include -#include #include #include +#include #include #include #include -#include -#include -#include #include "net/vnic.h" #include "net/vnic-dhcp.h" @@ -65,10 +62,8 @@ uint8_t vns_buf[VNIC_BUFSIZE]; uint8_t vns_txbuf[VNIC_BUFSIZE]; uint_t vns_sap; - vnd_handle_t *vns_hdl; + dlpi_handle_t vns_hdl; VNICDHCPState vns_ds; - frameio_t *vns_rfio; - frameio_t *vns_wfio; } VNICState; static void vnic_update_fd_handler(VNICState *); @@ -95,37 +90,44 @@ vnic_write_poll(vsp, 1); } -/* - * Because this is a single packet API, just read(2). If QEMU's net backend were - * better we could send more packets at once. - */ static int vnic_read_packet(VNICState *vsp, uint8_t *buf, int len) { - int ret; + struct strbuf sbuf; + int flags, ret; + + flags = 0; + sbuf.maxlen = len; + sbuf.buf = (char *)buf; do { - ret = read(vsp->vns_fd, buf, len); + ret = getmsg(vsp->vns_fd, NULL, &sbuf, &flags); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { - vnic_read_poll(vsp, 1); + vnic_write_poll(vsp, 1); return (0); } - return (ret); + if (ret == -1) { + return (-1); + } + + return (sbuf.len); } -/* - * For a single packet, just use write(2). - */ static int vnic_write_packet(VNICState *vsp, const uint8_t *buf, int len) { - int ret; + struct strbuf sbuf; + int flags, ret; + + flags = 0; + sbuf.len = len; + sbuf.buf = (char *)buf; do { - ret = write(vsp->vns_fd, buf, len); + ret = putmsg(vsp->vns_fd, NULL, &sbuf, flags); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { @@ -133,7 +135,10 @@ return (0); } - return (ret); + if (ret == -1) + return (-1); + + return (len); } static int @@ -187,6 +192,10 @@ uint16_t ethtype; VNICState *vsp = DO_UPCAST(VNICState, vns_nc, ncp); +#if VNIC_DHCP_DEBUG + debug_eth_frame(buf, size); +#endif + if (vsp->vns_ds.vnds_enabled && get_ethertype(buf, size, ðtype)) { VNICDHCPState *vdsp = &vsp->vns_ds; int ret; @@ -220,117 +229,6 @@ return (vnic_write_packet(vsp, buf, size)); } -static ssize_t -vnic_receive_iov(VLANClientState *ncp, const struct iovec *iov, - int iovcnt) -{ - int ret, i; - uint16_t ethtype; - size_t total, altsize; - VNICState *vsp = DO_UPCAST(VNICState, vns_nc, ncp); - - for (total = 0, i = 0; i < iovcnt; i++) { - total += (iov + i)->iov_len; - } - - if (vsp->vns_ds.vnds_enabled && get_ethertypev(iov, iovcnt, ðtype)) { - /* - * Basically drop the packet because we can't send a - * reply at this time. It's unfortunate, but we don't - * really have the proper infrastructure to do something - * else with this at this time. - */ - if (!vnic_can_send(vsp)) - return (total); - - VNICDHCPState *vdsp = &vsp->vns_ds; - - switch (ethtype) { - case ETH_P_ARP: - if (!is_arp_requestv(iov, iovcnt, vdsp)) - goto send; - ret = create_arp_responsev(iov, iovcnt, vdsp); - break; - case ETH_P_IP: - if (!is_dhcp_requestv(iov, iovcnt)) - goto send; - ret = create_dhcp_responsev(iov, iovcnt, vdsp); - break; - default: - goto send; - } - - /* This failed, drop it and continue */ - if (ret == 0) - return (total); - - ret = qemu_send_packet_async(&vsp->vns_nc, - vdsp->vnds_buf, ret, vnic_send_completed); - /* - * qemu has told us that it can't receive any more data - * at this time for the guest (host->guest traffic) so - * turn off our read poll until we get that the send has - * completed. - */ - if (ret == 0) - vnic_read_poll(vsp, 0); - return (total); - } - -send: - /* - * Copy the iovcs to our write frameio. Be on the lookout for someone - * giving us more vectors than we support in frameio. In that case, - * let's go ahead and just simply concat the rest. - */ - for (i = 0; i < MIN(iovcnt, FRAMEIO_NVECS_MAX - 1); i++, iov++) { - vsp->vns_wfio->fio_vecs[i].fv_buf = iov->iov_base; - vsp->vns_wfio->fio_vecs[i].fv_buflen = iov->iov_len; - } - - altsize = 0; - for (i = MIN(iovcnt, FRAMEIO_NVECS_MAX - 1); i != iovcnt; i++, iov++) { - /* - * The packet is too large. We're goin to silently drop it... - */ - if (altsize + iov->iov_len > VNIC_BUFSIZE) - return (total); - - bcopy(iov->iov_base, vsp->vns_txbuf + altsize, iov->iov_len); - altsize += iov->iov_len; - } - if (altsize != 0) { - vsp->vns_wfio->fio_vecs[FRAMEIO_NVECS_MAX-1].fv_buf = - vsp->vns_txbuf; - vsp->vns_wfio->fio_vecs[FRAMEIO_NVECS_MAX-1].fv_buflen = - altsize; - } - - vsp->vns_wfio->fio_nvecs = MIN(iovcnt, FRAMEIO_NVECS_MAX); - vsp->vns_wfio->fio_nvpf = MIN(iovcnt, FRAMEIO_NVECS_MAX); - do { - ret = vnd_frameio_write(vsp->vns_hdl, vsp->vns_wfio); - } while (ret == -1 && errno == EINTR); - - if (ret == -1 && errno == EAGAIN) { - vnic_write_poll(vsp, 1); - return (0); - } else if (ret == -1) { - abort(); - } - - total = 0; - for (i = 0; i < vsp->vns_wfio->fio_nvecs; i++) { - if (vsp->vns_wfio->fio_vecs[i].fv_actlen == 0 && - vsp->vns_wfio->fio_vecs[i].fv_buflen == 0) - break; - - total += vsp->vns_wfio->fio_vecs[i].fv_actlen; - } - - return (total); -} - static void vnic_cleanup(VLANClientState *ncp) { @@ -340,7 +238,7 @@ qemu_purge_queued_packets(ncp); - vnd_close(vsp->vns_hdl); + dlpi_close(vsp->vns_hdl); } static void @@ -357,41 +255,42 @@ .type = NET_CLIENT_TYPE_VNIC, .size = sizeof (VNICState), .receive = vnic_receive, - .receive_iov = vnic_receive_iov, .poll = vnic_poll, .cleanup = vnic_cleanup }; -/* - * Set up all the known values for our frame I/O devices. - */ +#ifdef CONFIG_SUNOS_VNIC_KVM static int -vnic_frameio_init(VNICState *vsp) +net_init_kvm(int vfd) { - vsp->vns_rfio = qemu_mallocz(sizeof (frameio_t) + - sizeof (framevec_t) * FRAMEIO_NVECS_MAX); - if (vsp->vns_rfio == NULL) - return (1); - vsp->vns_wfio = qemu_mallocz(sizeof (frameio_t) + - sizeof (framevec_t) * FRAMEIO_NVECS_MAX); - if (vsp->vns_wfio == NULL) - return (1); - vsp->vns_rfio->fio_version = FRAMEIO_CURRENT_VERSION; - vsp->vns_rfio->fio_nvpf = 1; - vsp->vns_wfio->fio_version = FRAMEIO_CURRENT_VERSION; - vsp->vns_wfio->fio_nvpf = 1; + int kfd; + + if ((kfd = open("/dev/kvm", O_RDWR)) < 0) { + error_report("can't open /dev/kvm for vnic: %s\n", + strerror(errno)); + return (-1); + } + + /* XXX We shouldn't be embedding the KVM_NET_QUEUE fd */ + if (ioctl(kfd, 0x2000ae21, vfd) < 0) { + error_report("can't ioctl: %s\n", strerror(errno)); + return (-1); + } + + (void) close(kfd); + return (0); } +#endif int net_init_vnic(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan) { - int fd, len, vnderr, syserr; + int fd, len; 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"); @@ -411,36 +310,48 @@ ncp = qemu_new_net_client(&net_vnic_info, vlan, NULL, "vnic", name); vsp = DO_UPCAST(VNICState, vns_nc, ncp); + if (dlpi_open(ifname, &vsp->vns_hdl, DLPI_RAW) != DLPI_SUCCESS) { + error_report("vnic: failed to open interface %s", ifname); + return (-1); + } - 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); + if (dlpi_bind(vsp->vns_hdl, DLPI_ANY_SAP, &vsp->vns_sap) != DLPI_SUCCESS) { + error_report("vnic: failed to bind interface %s", ifname); 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); + /* + * We only set the mac address of the vnic if the user passed in the + * option on the command line. + */ + if (mac != NULL) { + if (dlpi_set_physaddr(vsp->vns_hdl, DL_CURR_PHYS_ADDR, macaddr, + ETHERADDRL) != DLPI_SUCCESS) { + error_report("vnic: failed to set mac address\n"); + return (-1); + } + } + + /* + * We are enabling support for two different kinds of promiscuous modes. + * The first is getting us the basics of the unicast traffic that we + * care about. The latter is going to ensure that we also get other + * types of physical traffic such as multicast and broadcast. + */ + if (dlpi_promiscon(vsp->vns_hdl, DL_PROMISC_SAP) != DLPI_SUCCESS) { + error_report("vnic: failed to be promiscous with interface %s", + ifname); 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); + if (dlpi_promiscon(vsp->vns_hdl, DL_PROMISC_PHYS) != DLPI_SUCCESS) { + error_report("vnic: failed to be promiscous with interface %s", + ifname); return (-1); } + fd = dlpi_fd(vsp->vns_hdl); - 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)); @@ -455,11 +366,9 @@ 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); - } +#ifdef CONFIG_SUNOS_VNIC_KVM + net_init_kvm(fd); +#endif /* We have to manually intialize the polling for read */ vnic_read_poll(vsp, 1);