svn commit: r356613 - head/sys/dev/virtio/network

Gleb Smirnoff glebius at FreeBSD.org
Fri Jan 10 21:22:04 UTC 2020


Author: glebius
Date: Fri Jan 10 21:22:03 2020
New Revision: 356613
URL: https://svnweb.freebsd.org/changeset/base/356613

Log:
  Add pfil(9) hook to vtnet(4).
  
  The patch could be simplier, using only the second chunk to
  vtnet_rxq_eof(), that passes full mbufs to pfil(9). Packet
  filter would m_free() them in case of returning PFIL_DROPPED.
  
  However, we pretend to be a hardware driver, so we first try
  to pass a memory buffer via PFIL_MEMPTR feature. This is mostly
  done for debugging purposes, so that one can experiment in bhyve
  with packet filters utilizing same features as a true driver.

Modified:
  head/sys/dev/virtio/network/if_vtnet.c
  head/sys/dev/virtio/network/if_vtnetvar.h

Modified: head/sys/dev/virtio/network/if_vtnet.c
==============================================================================
--- head/sys/dev/virtio/network/if_vtnet.c	Fri Jan 10 20:53:58 2020	(r356612)
+++ head/sys/dev/virtio/network/if_vtnet.c	Fri Jan 10 21:22:03 2020	(r356613)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 
 #include <net/debugnet.h>
 #include <net/ethernet.h>
+#include <net/pfil.h>
 #include <net/if.h>
 #include <net/if_var.h>
 #include <net/if_arp.h>
@@ -935,6 +936,7 @@ static int
 vtnet_setup_interface(struct vtnet_softc *sc)
 {
 	device_t dev;
+	struct pfil_head_args pa;
 	struct ifnet *ifp;
 
 	dev = sc->vtnet_dev;
@@ -1038,6 +1040,12 @@ vtnet_setup_interface(struct vtnet_softc *sc)
 
 	DEBUGNET_SET(ifp, vtnet);
 
+	pa.pa_version = PFIL_VERSION;
+	pa.pa_flags = PFIL_IN;
+	pa.pa_type = PFIL_TYPE_ETHERNET;
+	pa.pa_headname = ifp->if_xname;
+	sc->vtnet_pfil = pfil_head_register(&pa);
+
 	return (0);
 }
 
@@ -1773,9 +1781,11 @@ vtnet_rxq_eof(struct vtnet_rxq *rxq)
 	struct vtnet_softc *sc;
 	struct ifnet *ifp;
 	struct virtqueue *vq;
-	struct mbuf *m;
+	struct mbuf *m, *mr;
 	struct virtio_net_hdr_mrg_rxbuf *mhdr;
 	int len, deq, nbufs, adjsz, count;
+	pfil_return_t pfil;
+	bool pfil_done;
 
 	sc = rxq->vtnrx_sc;
 	vq = rxq->vtnrx_vq;
@@ -1812,6 +1822,35 @@ vtnet_rxq_eof(struct vtnet_rxq *rxq)
 			adjsz = sizeof(struct virtio_net_hdr_mrg_rxbuf);
 		}
 
+		/*
+		 * If we have enough data in first mbuf, run it through
+		 * pfil as a memory buffer before dequeueing the rest.
+		 */
+		if (PFIL_HOOKED_IN(sc->vtnet_pfil) &&
+		    len - adjsz >= ETHER_HDR_LEN + max_protohdr) {
+			pfil = pfil_run_hooks(sc->vtnet_pfil,
+			    m->m_data + adjsz, ifp,
+			    len - adjsz | PFIL_MEMPTR | PFIL_IN, NULL);
+			switch (pfil) {
+			case PFIL_REALLOCED:
+				mr = pfil_mem2mbuf(m->m_data + adjsz);
+				vtnet_rxq_input(rxq, mr, hdr);
+				/* FALLTHROUGH */
+			case PFIL_DROPPED:
+			case PFIL_CONSUMED:
+				vtnet_rxq_discard_buf(rxq, m);
+				if (nbufs > 1)
+					vtnet_rxq_discard_merged_bufs(rxq,
+					    nbufs);
+				continue;
+			default:
+				KASSERT(pfil == PFIL_PASS,
+				    ("Filter returned %d!\n", pfil));
+			};
+			pfil_done = true;
+		} else
+			pfil_done = false;
+
 		if (vtnet_rxq_replace_buf(rxq, m, len) != 0) {
 			rxq->vtnrx_stats.vrxs_iqdrops++;
 			vtnet_rxq_discard_buf(rxq, m);
@@ -1841,6 +1880,19 @@ vtnet_rxq_eof(struct vtnet_rxq *rxq)
 		 */
 		memcpy(hdr, mtod(m, void *), sizeof(struct virtio_net_hdr));
 		m_adj(m, adjsz);
+
+		if (PFIL_HOOKED_IN(sc->vtnet_pfil) && pfil_done == false) {
+			pfil = pfil_run_hooks(sc->vtnet_pfil, &m, ifp, PFIL_IN,
+			    NULL);
+			switch (pfil) {
+			case PFIL_DROPPED:
+			case PFIL_CONSUMED:
+				continue;
+			default:
+				KASSERT(pfil == PFIL_PASS,
+				    ("Filter returned %d!\n", pfil));
+			}
+		}
 
 		vtnet_rxq_input(rxq, m, hdr);
 

Modified: head/sys/dev/virtio/network/if_vtnetvar.h
==============================================================================
--- head/sys/dev/virtio/network/if_vtnetvar.h	Fri Jan 10 20:53:58 2020	(r356612)
+++ head/sys/dev/virtio/network/if_vtnetvar.h	Fri Jan 10 21:22:03 2020	(r356613)
@@ -136,6 +136,7 @@ struct vtnet_softc {
 	struct ifnet		*vtnet_ifp;
 	struct vtnet_rxq	*vtnet_rxqs;
 	struct vtnet_txq	*vtnet_txqs;
+	pfil_head_t		 vtnet_pfil;
 
 	uint32_t		 vtnet_flags;
 #define VTNET_FLAG_SUSPENDED	 0x0001


More information about the svn-src-all mailing list