All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/3]  vhost-net: netfilter support for RX path
@ 2026-02-08 14:32 Cindy Lu
  2026-02-08 14:32 ` [RFC 1/3] uapi: vhost: add vhost-net netfilter offload API Cindy Lu
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Cindy Lu @ 2026-02-08 14:32 UTC (permalink / raw)
  To: lulu, mst, jasowang, kvm, virtualization, netdev, linux-kernel

This series adds a minimal vhost-net filter support for RX.
It introduces a UAPI for VHOST_NET_SET_FILTER and a simple
SOCK_SEQPACKET message header. The kernel side keeps a filter
socket reference and routes RX packets to userspace when
it was enabled.

Tested
- vhost=on  and vhost=off

Cindy Lu (3):
  uapi: vhost: add vhost-net netfilter offload API
  vhost/net: add netfilter socket support
  vhost/net: add RX netfilter offload path

 drivers/vhost/net.c        | 338 +++++++++++++++++++++++++++++++++++++
 include/uapi/linux/vhost.h |  20 +++
 2 files changed, 358 insertions(+)

-- 
2.52.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC 1/3] uapi: vhost: add vhost-net netfilter offload API
  2026-02-08 14:32 [RFC 0/3] vhost-net: netfilter support for RX path Cindy Lu
@ 2026-02-08 14:32 ` Cindy Lu
  2026-02-08 17:32   ` Michael S. Tsirkin
  2026-02-08 14:32 ` [RFC 2/3] vhost/net: add netfilter socket support Cindy Lu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Cindy Lu @ 2026-02-08 14:32 UTC (permalink / raw)
  To: lulu, mst, jasowang, kvm, virtualization, netdev, linux-kernel

Add VHOST_NET_SET_FILTER ioctl and the filter socket protocol used for
vhost-net filter offload.

Signed-off-by: Cindy Lu <lulu@redhat.com>
---
 include/uapi/linux/vhost.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
index c57674a6aa0d..d9a0ca7a3df0 100644
--- a/include/uapi/linux/vhost.h
+++ b/include/uapi/linux/vhost.h
@@ -131,6 +131,26 @@
  * device.  This can be used to stop the ring (e.g. for migration). */
 #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
 
+/* VHOST_NET filter offload (kernel vhost-net dataplane through QEMU netfilter) */
+struct vhost_net_filter {
+	__s32 fd;
+};
+
+enum {
+	VHOST_NET_FILTER_MSG_REQUEST = 1,
+};
+
+#define VHOST_NET_FILTER_DIRECTION_TX 1
+
+struct vhost_net_filter_msg {
+	__u16 type;
+	__u16 direction;
+	__u32 len;
+};
+
+
+#define VHOST_NET_SET_FILTER _IOW(VHOST_VIRTIO, 0x31, struct vhost_net_filter)
+
 /* VHOST_SCSI specific defines */
 
 #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC 2/3] vhost/net: add netfilter socket support
  2026-02-08 14:32 [RFC 0/3] vhost-net: netfilter support for RX path Cindy Lu
  2026-02-08 14:32 ` [RFC 1/3] uapi: vhost: add vhost-net netfilter offload API Cindy Lu
@ 2026-02-08 14:32 ` Cindy Lu
  2026-02-08 14:32 ` [RFC 3/3] vhost/net: add RX netfilter offload path Cindy Lu
  2026-02-09  1:46 ` [RFC 0/3] vhost-net: netfilter support for RX path Jason Wang
  3 siblings, 0 replies; 7+ messages in thread
From: Cindy Lu @ 2026-02-08 14:32 UTC (permalink / raw)
  To: lulu, mst, jasowang, kvm, virtualization, netdev, linux-kernel

Introduce the netfilter socket plumbing and the VHOST_NET_SET_FILTER ioctl.
Initialize the netfilter state on open and release it on reset/close.

Key points:
- Add filter_sock + filter_lock to vhost_net
- Validate SOCK_SEQPACKET AF_UNIX filter socket from userspace
- Add vhost_net_set_filter() and VHOST_NET_SET_FILTER ioctl handler
- Initialize filter state on open and clean up on reset/release

Signed-off-by: Cindy Lu <lulu@redhat.com>
---
 drivers/vhost/net.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 7f886d3dba7d..f02deff0e53c 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -131,6 +131,7 @@ struct vhost_net_virtqueue {
 	struct vhost_net_buf rxq;
 	/* Batched XDP buffs */
 	struct xdp_buff *xdp;
+
 };
 
 struct vhost_net {
@@ -147,6 +148,15 @@ struct vhost_net {
 	bool tx_flush;
 	/* Private page frag cache */
 	struct page_frag_cache pf_cache;
+
+	/*
+	 * Optional vhost-net filter offload socket.
+	 * When configured, RX packets can be routed through a userspace
+	 * filter chain via a SOCK_SEQPACKET control socket. Access to
+	 * filter_sock is protected by filter_lock.
+	 */
+	struct socket *filter_sock;
+	spinlock_t filter_lock;
 };
 
 static unsigned vhost_net_zcopy_mask __read_mostly;
@@ -1128,6 +1138,95 @@ static int get_rx_bufs(struct vhost_net_virtqueue *nvq,
 	return r;
 }
 
+/*
+ * Validate and acquire the filter socket from userspace.
+ *
+ * Returns:
+ *   - NULL when fd == -1 (explicitly disable filter)
+ *   - a ref-counted struct socket on success
+ *   - ERR_PTR(-errno) on validation failure
+ */
+static struct socket *get_filter_socket(int fd)
+{
+	int r;
+	struct socket *sock;
+
+	/* Special case: userspace asks to disable filter. */
+	if (fd == -1)
+		return NULL;
+
+	sock = sockfd_lookup(fd, &r);
+	if (!sock)
+		return ERR_PTR(-ENOTSOCK);
+
+	if (sock->sk->sk_family != AF_UNIX ||
+	    sock->sk->sk_type != SOCK_SEQPACKET) {
+		sockfd_put(sock);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return sock;
+}
+
+/*
+ * Drop the currently configured filter socket, if any.
+ *
+ * Caller does not need to hold filter_lock; this function clears the pointer
+ * under the lock and releases the socket reference afterwards.
+ */
+static void vhost_net_filter_stop(struct vhost_net *n)
+{
+	struct socket *sock = n->filter_sock;
+
+	spin_lock(&n->filter_lock);
+	n->filter_sock = NULL;
+	spin_unlock(&n->filter_lock);
+
+	if (sock)
+		sockfd_put(sock);
+}
+
+/*
+ * Install or remove a filter socket for this vhost-net device.
+ *
+ * The ioctl passes an fd for a SOCK_SEQPACKET AF_UNIX socket created by
+ * userspace. We validate the socket type, replace any existing filter socket,
+ * and keep a reference so RX path can safely send filter requests.
+ */
+static long vhost_net_set_filter(struct vhost_net *n, int fd)
+{
+	struct socket *sock;
+	int r;
+
+	mutex_lock(&n->dev.mutex);
+	r = vhost_dev_check_owner(&n->dev);
+	if (r)
+		goto out;
+
+	sock = get_filter_socket(fd);
+	if (IS_ERR(sock)) {
+		r = PTR_ERR(sock);
+		goto out;
+	}
+
+	vhost_net_filter_stop(n);
+
+	if (!sock) {
+		r = 0;
+		goto out;
+	}
+
+	spin_lock(&n->filter_lock);
+	n->filter_sock = sock;
+	spin_unlock(&n->filter_lock);
+
+	r = 0;
+
+out:
+	mutex_unlock(&n->dev.mutex);
+	return r;
+}
+
 /* Expects to be always run from workqueue - which acts as
  * read-size critical section for our kind of RCU. */
 static void handle_rx(struct vhost_net *net)
@@ -1383,6 +1482,8 @@ static int vhost_net_open(struct inode *inode, struct file *f)
 
 	f->private_data = n;
 	page_frag_cache_init(&n->pf_cache);
+	spin_lock_init(&n->filter_lock);
+	n->filter_sock = NULL;
 
 	return 0;
 }
@@ -1433,6 +1534,7 @@ static int vhost_net_release(struct inode *inode, struct file *f)
 	struct socket *tx_sock;
 	struct socket *rx_sock;
 
+	vhost_net_filter_stop(n);
 	vhost_net_stop(n, &tx_sock, &rx_sock);
 	vhost_net_flush(n);
 	vhost_dev_stop(&n->dev);
@@ -1637,6 +1739,8 @@ static long vhost_net_reset_owner(struct vhost_net *n)
 	err = vhost_dev_check_owner(&n->dev);
 	if (err)
 		goto done;
+
+	vhost_net_filter_stop(n);
 	umem = vhost_dev_reset_owner_prepare();
 	if (!umem) {
 		err = -ENOMEM;
@@ -1737,6 +1841,7 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
 	void __user *argp = (void __user *)arg;
 	u64 __user *featurep = argp;
 	struct vhost_vring_file backend;
+	struct vhost_net_filter filter;
 	u64 features, count, copied;
 	int r, i;
 
@@ -1745,6 +1850,10 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
 		if (copy_from_user(&backend, argp, sizeof backend))
 			return -EFAULT;
 		return vhost_net_set_backend(n, backend.index, backend.fd);
+	case VHOST_NET_SET_FILTER:
+		if (copy_from_user(&filter, argp, sizeof(filter)))
+			return -EFAULT;
+		return vhost_net_set_filter(n, filter.fd);
 	case VHOST_GET_FEATURES:
 		features = vhost_net_features[0];
 		if (copy_to_user(featurep, &features, sizeof features))
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC 3/3] vhost/net: add RX netfilter offload path
  2026-02-08 14:32 [RFC 0/3] vhost-net: netfilter support for RX path Cindy Lu
  2026-02-08 14:32 ` [RFC 1/3] uapi: vhost: add vhost-net netfilter offload API Cindy Lu
  2026-02-08 14:32 ` [RFC 2/3] vhost/net: add netfilter socket support Cindy Lu
@ 2026-02-08 14:32 ` Cindy Lu
  2026-02-09  1:46 ` [RFC 0/3] vhost-net: netfilter support for RX path Jason Wang
  3 siblings, 0 replies; 7+ messages in thread
From: Cindy Lu @ 2026-02-08 14:32 UTC (permalink / raw)
  To: lulu, mst, jasowang, kvm, virtualization, netdev, linux-kernel

Route RX packets through the netfilter socket when configured.
Key points:
- Add VHOST_NET_FILTER_MAX_LEN upper bound for filter payload size
- Introduce vhost_net_filter_request() to send REQUEST to userspace
- Add handle_rx_filter() fast path for RX when filter is active
- Hook filter path in handle_rx() when filter_sock is set

Signed-off-by: Cindy Lu <lulu@redhat.com>
---
 drivers/vhost/net.c | 229 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 229 insertions(+)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index f02deff0e53c..aa9a5ed43eae 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -161,6 +161,13 @@ struct vhost_net {
 
 static unsigned vhost_net_zcopy_mask __read_mostly;
 
+/*
+ * Upper bound for a single packet payload on the filter path.
+ * Keep this large enough for the largest expected frame plus vnet headers,
+ * but still bounded to avoid unbounded allocations.
+ */
+#define VHOST_NET_FILTER_MAX_LEN (4096 + 65536)
+
 static void *vhost_net_buf_get_ptr(struct vhost_net_buf *rxq)
 {
 	if (rxq->tail != rxq->head)
@@ -1227,6 +1234,222 @@ static long vhost_net_set_filter(struct vhost_net *n, int fd)
 	return r;
 }
 
+/*
+ * Send a filter REQUEST message to userspace for a single packet.
+ *
+ * The caller provides a writable buffer; userspace may inspect the content and
+ * optionally modify it in place. We only accept the packet if the returned
+ * length matches the original length, otherwise the packet is dropped.
+ */
+static int vhost_net_filter_request(struct vhost_net *n, u16 direction,
+				    void *buf, u32 *len)
+{
+	struct vhost_net_filter_msg msg = {
+		.type = VHOST_NET_FILTER_MSG_REQUEST,
+		.direction = direction,
+		.len = *len,
+	};
+	struct msghdr msghdr = { 0 };
+	struct kvec iov[2] = {
+		{ .iov_base = &msg, .iov_len = sizeof(msg) },
+		{ .iov_base = buf, .iov_len = *len },
+	};
+	struct socket *sock;
+	struct file *sock_file = NULL;
+	int ret;
+
+	/*
+	 * Take a temporary file reference to guard against concurrent
+	 * filter socket replacement while we send the message.
+	 */
+	spin_lock(&n->filter_lock);
+	sock = n->filter_sock;
+	if (sock)
+		sock_file = get_file(sock->file);
+	spin_unlock(&n->filter_lock);
+
+	if (!sock) {
+		ret = -ENOTCONN;
+		goto out_put;
+	}
+
+	ret = kernel_sendmsg(sock, &msghdr, iov,
+			     *len ? 2 : 1, sizeof(msg) + *len);
+
+out_put:
+	if (sock_file)
+		fput(sock_file);
+
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+/*
+ * RX fast path when filter offload is active.
+ *
+ * This mirrors handle_rx() but routes each RX packet through userspace
+ * netfilter. Packets are copied into a temporary buffer, sent to the filter
+ * socket as a REQUEST, and only delivered to the guest if userspace keeps the
+ * length unchanged. Any truncation or mismatch drops the packet.
+ */
+static void handle_rx_filter(struct vhost_net *net, struct socket *sock)
+{
+	struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_RX];
+	struct vhost_virtqueue *vq = &nvq->vq;
+	bool in_order = vhost_has_feature(vq, VIRTIO_F_IN_ORDER);
+	unsigned int count = 0;
+	unsigned int in, log;
+	struct vhost_log *vq_log;
+	struct virtio_net_hdr hdr = {
+		.flags = 0,
+		.gso_type = VIRTIO_NET_HDR_GSO_NONE
+	};
+	struct msghdr msg = {
+		.msg_name = NULL,
+		.msg_namelen = 0,
+		.msg_control = NULL,
+		.msg_controllen = 0,
+		.msg_flags = MSG_DONTWAIT,
+	};
+	size_t total_len = 0;
+	int mergeable;
+	bool set_num_buffers;
+	size_t vhost_hlen, sock_hlen;
+	size_t vhost_len, sock_len;
+	bool busyloop_intr = false;
+	struct iov_iter fixup;
+	__virtio16 num_buffers;
+	int recv_pkts = 0;
+	unsigned int ndesc;
+	void *pkt;
+
+	pkt = kvmalloc(VHOST_NET_FILTER_MAX_LEN, GFP_KERNEL | __GFP_NOWARN);
+	if (!pkt) {
+		vhost_net_enable_vq(net, vq);
+		return;
+	}
+
+	vhost_hlen = nvq->vhost_hlen;
+	sock_hlen = nvq->sock_hlen;
+
+	vq_log = unlikely(vhost_has_feature(vq, VHOST_F_LOG_ALL)) ? vq->log : NULL;
+	mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF);
+	set_num_buffers = mergeable || vhost_has_feature(vq, VIRTIO_F_VERSION_1);
+
+	do {
+		u32 pkt_len;
+		int err;
+		s16 headcount;
+		struct kvec iov;
+
+		sock_len = vhost_net_rx_peek_head_len(net, sock->sk,
+						      &busyloop_intr, &count);
+		if (!sock_len)
+			break;
+		sock_len += sock_hlen;
+		if (sock_len > VHOST_NET_FILTER_MAX_LEN) {
+			/* Consume and drop oversized packet. */
+			iov.iov_base = pkt;
+			iov.iov_len = 1;
+			kernel_recvmsg(sock, &msg, &iov, 1, 1,
+				       MSG_DONTWAIT | MSG_TRUNC);
+			continue;
+		}
+
+		vhost_len = sock_len + vhost_hlen;
+		headcount = get_rx_bufs(nvq, vq->heads + count,
+					vq->nheads + count, vhost_len, &in,
+					vq_log, &log,
+					likely(mergeable) ? UIO_MAXIOV : 1,
+					&ndesc);
+		if (unlikely(headcount < 0))
+			goto out;
+
+		if (!headcount) {
+			if (unlikely(busyloop_intr)) {
+				vhost_poll_queue(&vq->poll);
+			} else if (unlikely(vhost_enable_notify(&net->dev, vq))) {
+				vhost_disable_notify(&net->dev, vq);
+				continue;
+			}
+			goto out;
+		}
+
+		busyloop_intr = false;
+
+		if (nvq->rx_ring)
+			msg.msg_control = vhost_net_buf_consume(&nvq->rxq);
+
+		iov.iov_base = pkt;
+		iov.iov_len = sock_len;
+		err = kernel_recvmsg(sock, &msg, &iov, 1, sock_len,
+				     MSG_DONTWAIT | MSG_TRUNC);
+		if (unlikely(err != sock_len)) {
+			vhost_discard_vq_desc(vq, headcount, ndesc);
+			continue;
+		}
+
+		pkt_len = sock_len;
+		err = vhost_net_filter_request(net, VHOST_NET_FILTER_DIRECTION_TX,
+					       pkt, &pkt_len);
+		if (err < 0)
+			pkt_len = sock_len;
+		if (pkt_len != sock_len) {
+			vhost_discard_vq_desc(vq, headcount, ndesc);
+			continue;
+		}
+
+		iov_iter_init(&msg.msg_iter, ITER_DEST, vq->iov, in, vhost_len);
+		fixup = msg.msg_iter;
+		if (unlikely(vhost_hlen))
+			iov_iter_advance(&msg.msg_iter, vhost_hlen);
+
+		if (copy_to_iter(pkt, sock_len, &msg.msg_iter) != sock_len) {
+			vhost_discard_vq_desc(vq, headcount, ndesc);
+			goto out;
+		}
+
+		if (unlikely(vhost_hlen)) {
+			if (copy_to_iter(&hdr, sizeof(hdr),
+					 &fixup) != sizeof(hdr)) {
+				vhost_discard_vq_desc(vq, headcount, ndesc);
+				goto out;
+			}
+		} else {
+			iov_iter_advance(&fixup, sizeof(hdr));
+		}
+
+		num_buffers = cpu_to_vhost16(vq, headcount);
+		if (likely(set_num_buffers) &&
+		    copy_to_iter(&num_buffers, sizeof(num_buffers), &fixup) !=
+			    sizeof(num_buffers)) {
+			vhost_discard_vq_desc(vq, headcount, ndesc);
+			goto out;
+		}
+
+		nvq->done_idx += headcount;
+		count += in_order ? 1 : headcount;
+		if (nvq->done_idx > VHOST_NET_BATCH) {
+			vhost_net_signal_used(nvq, count);
+			count = 0;
+		}
+
+		if (unlikely(vq_log))
+			vhost_log_write(vq, vq_log, log, vhost_len, vq->iov, in);
+
+		total_len += vhost_len;
+	} while (likely(!vhost_exceeds_weight(vq, ++recv_pkts, total_len)));
+
+	if (unlikely(busyloop_intr))
+		vhost_poll_queue(&vq->poll);
+	else if (!sock_len)
+		vhost_net_enable_vq(net, vq);
+
+out:
+	vhost_net_signal_used(nvq, count);
+	kvfree(pkt);
+}
 /* Expects to be always run from workqueue - which acts as
  * read-size critical section for our kind of RCU. */
 static void handle_rx(struct vhost_net *net)
@@ -1281,6 +1504,11 @@ static void handle_rx(struct vhost_net *net)
 	set_num_buffers = mergeable ||
 			  vhost_has_feature(vq, VIRTIO_F_VERSION_1);
 
+	if (READ_ONCE(net->filter_sock)) {
+		handle_rx_filter(net, sock);
+		goto out_unlock;
+	}
+
 	do {
 		sock_len = vhost_net_rx_peek_head_len(net, sock->sk,
 						      &busyloop_intr, &count);
@@ -1383,6 +1611,7 @@ static void handle_rx(struct vhost_net *net)
 		vhost_net_enable_vq(net, vq);
 out:
 	vhost_net_signal_used(nvq, count);
+out_unlock:
 	mutex_unlock(&vq->mutex);
 }
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC 1/3] uapi: vhost: add vhost-net netfilter offload API
  2026-02-08 14:32 ` [RFC 1/3] uapi: vhost: add vhost-net netfilter offload API Cindy Lu
@ 2026-02-08 17:32   ` Michael S. Tsirkin
  2026-02-09  6:41     ` Cindy Lu
  0 siblings, 1 reply; 7+ messages in thread
From: Michael S. Tsirkin @ 2026-02-08 17:32 UTC (permalink / raw)
  To: Cindy Lu; +Cc: jasowang, kvm, virtualization, netdev, linux-kernel

On Sun, Feb 08, 2026 at 10:32:22PM +0800, Cindy Lu wrote:
> Add VHOST_NET_SET_FILTER ioctl and the filter socket protocol used for
> vhost-net filter offload.
> 
> Signed-off-by: Cindy Lu <lulu@redhat.com>
> ---
>  include/uapi/linux/vhost.h | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
> diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> index c57674a6aa0d..d9a0ca7a3df0 100644
> --- a/include/uapi/linux/vhost.h
> +++ b/include/uapi/linux/vhost.h
> @@ -131,6 +131,26 @@
>   * device.  This can be used to stop the ring (e.g. for migration). */
>  #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
>  
> +/* VHOST_NET filter offload (kernel vhost-net dataplane through QEMU netfilter) */
> +struct vhost_net_filter {
> +	__s32 fd;
> +};
> +
> +enum {
> +	VHOST_NET_FILTER_MSG_REQUEST = 1,
> +};
> +
> +#define VHOST_NET_FILTER_DIRECTION_TX 1
> +
> +struct vhost_net_filter_msg {
> +	__u16 type;
> +	__u16 direction;
> +	__u32 len;
> +};
> +
> +
> +#define VHOST_NET_SET_FILTER _IOW(VHOST_VIRTIO, 0x31, struct vhost_net_filter)
> +
>  /* VHOST_SCSI specific defines */

can we get some info on what this is supposed to be doing, pls?
it belongs here where userspace devs can find it, not hidden
in code.


>  
>  #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
> -- 
> 2.52.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC 0/3] vhost-net: netfilter support for RX path
  2026-02-08 14:32 [RFC 0/3] vhost-net: netfilter support for RX path Cindy Lu
                   ` (2 preceding siblings ...)
  2026-02-08 14:32 ` [RFC 3/3] vhost/net: add RX netfilter offload path Cindy Lu
@ 2026-02-09  1:46 ` Jason Wang
  3 siblings, 0 replies; 7+ messages in thread
From: Jason Wang @ 2026-02-09  1:46 UTC (permalink / raw)
  To: Cindy Lu; +Cc: mst, kvm, virtualization, netdev, linux-kernel

On Sun, Feb 8, 2026 at 10:34 PM Cindy Lu <lulu@redhat.com> wrote:
>
> This series adds a minimal vhost-net filter support for RX.
> It introduces a UAPI for VHOST_NET_SET_FILTER and a simple
> SOCK_SEQPACKET message header. The kernel side keeps a filter
> socket reference and routes RX packets to userspace when
> it was enabled.

I wonder if a packet socket is sufficient or is this for macvtap as well?

Thanks

>
> Tested
> - vhost=on  and vhost=off
>
> Cindy Lu (3):
>   uapi: vhost: add vhost-net netfilter offload API
>   vhost/net: add netfilter socket support
>   vhost/net: add RX netfilter offload path
>
>  drivers/vhost/net.c        | 338 +++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/vhost.h |  20 +++
>  2 files changed, 358 insertions(+)
>
> --
> 2.52.0
>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC 1/3] uapi: vhost: add vhost-net netfilter offload API
  2026-02-08 17:32   ` Michael S. Tsirkin
@ 2026-02-09  6:41     ` Cindy Lu
  0 siblings, 0 replies; 7+ messages in thread
From: Cindy Lu @ 2026-02-09  6:41 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: jasowang, kvm, virtualization, netdev, linux-kernel

s

On Mon, Feb 9, 2026 at 1:32 AM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Sun, Feb 08, 2026 at 10:32:22PM +0800, Cindy Lu wrote:
> > Add VHOST_NET_SET_FILTER ioctl and the filter socket protocol used for
> > vhost-net filter offload.
> >
> > Signed-off-by: Cindy Lu <lulu@redhat.com>
> > ---
> >  include/uapi/linux/vhost.h | 20 ++++++++++++++++++++
> >  1 file changed, 20 insertions(+)
> >
> > diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> > index c57674a6aa0d..d9a0ca7a3df0 100644
> > --- a/include/uapi/linux/vhost.h
> > +++ b/include/uapi/linux/vhost.h
> > @@ -131,6 +131,26 @@
> >   * device.  This can be used to stop the ring (e.g. for migration). */
> >  #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
> >
> > +/* VHOST_NET filter offload (kernel vhost-net dataplane through QEMU netfilter) */
> > +struct vhost_net_filter {
> > +     __s32 fd;
> > +};
> > +
> > +enum {
> > +     VHOST_NET_FILTER_MSG_REQUEST = 1,
> > +};
> > +
> > +#define VHOST_NET_FILTER_DIRECTION_TX 1
> > +
> > +struct vhost_net_filter_msg {
> > +     __u16 type;
> > +     __u16 direction;
> > +     __u32 len;
> > +};
> > +
> > +
> > +#define VHOST_NET_SET_FILTER _IOW(VHOST_VIRTIO, 0x31, struct vhost_net_filter)
> > +
> >  /* VHOST_SCSI specific defines */
>
> can we get some info on what this is supposed to be doing, pls?
> it belongs here where userspace devs can find it, not hidden
> in code.
>
Hi Michael
We plan to add a new feature to support zero packet loss during live
migration, so we’re introducing this new UAPI. Thanks, I'll add more
information here.
Thanks
Cindy
>
> >
> >  #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
> > --
> > 2.52.0
>


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-02-09  6:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-08 14:32 [RFC 0/3] vhost-net: netfilter support for RX path Cindy Lu
2026-02-08 14:32 ` [RFC 1/3] uapi: vhost: add vhost-net netfilter offload API Cindy Lu
2026-02-08 17:32   ` Michael S. Tsirkin
2026-02-09  6:41     ` Cindy Lu
2026-02-08 14:32 ` [RFC 2/3] vhost/net: add netfilter socket support Cindy Lu
2026-02-08 14:32 ` [RFC 3/3] vhost/net: add RX netfilter offload path Cindy Lu
2026-02-09  1:46 ` [RFC 0/3] vhost-net: netfilter support for RX path Jason Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.