From 8a59df2477f869eb4b3f582c36cb0e08018fbcff Mon Sep 17 00:00:00 2001
From: Dan McDonald <danmcd@omniti.com>
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 <unistd.h>
 
 #include <netpacket/packet.h>
-#include <assert.h>
 #include <net/if_dl.h>
 #include <sys/ethernet.h>
+#include <sys/dlpi.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <libvnd.h>
-#include <sys/vnd.h>
-#include <sys/frameio.h>
 
 #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, &ethtype)) {
 		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, &ethtype)) {
-		/*
-		 * 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);
