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