* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox