On Sat, Feb 7, 2026 at 9:49 PM Cindy Lu <[email protected]> wrote:
>
> Packets injected from the redirector chardev are raw Ethernet frames without a
> vnet_hdr prefix.

This may not be true as it could be the traffic from a remote
redirector that is redirecting virtio-net traffic?

Thanks

> Mark them as RAW so downstream filters (e.g. dump) do not skip
> vnet_hdr_len bytes, and strip the vnet_hdr prefix only when vnet_hdr_support 
> is
> enabled and a valid prefix is present.
>
> Signed-off-by: Cindy Lu <[email protected]>
> ---
>  net/filter-mirror.c | 30 +++++++++++++++++++++++++-----
>  1 file changed, 25 insertions(+), 5 deletions(-)
>
> diff --git a/net/filter-mirror.c b/net/filter-mirror.c
> index c1b9dabacd..de32028246 100644
> --- a/net/filter-mirror.c
> +++ b/net/filter-mirror.c
> @@ -146,6 +146,7 @@ static int filter_send(MirrorState *s,
>  }
>
>  static void redirector_to_filter(NetFilterState *nf,
> +                                 unsigned flags,
>                                   const uint8_t *buf,
>                                   int len)
>  {
> @@ -156,13 +157,13 @@ static void redirector_to_filter(NetFilterState *nf,
>
>      if (nf->direction == NET_FILTER_DIRECTION_ALL ||
>          nf->direction == NET_FILTER_DIRECTION_TX) {
> -        qemu_netfilter_pass_to_next(nf->netdev, 0, &iov, 1, nf);
> +        qemu_netfilter_pass_to_next(nf->netdev, flags, &iov, 1, nf);
>      }
>
>      if (nf->direction == NET_FILTER_DIRECTION_ALL ||
>          nf->direction == NET_FILTER_DIRECTION_RX) {
> -        qemu_netfilter_pass_to_next(nf->netdev->peer, 0, &iov, 1, nf);
> -     }
> +        qemu_netfilter_pass_to_next(nf->netdev->peer, flags, &iov, 1, nf);
> +    }
>  }
>
>  static int redirector_chr_can_read(void *opaque)
> @@ -294,12 +295,31 @@ static void redirector_rs_finalize(SocketReadState *rs)
>  {
>      MirrorState *s = container_of(rs, MirrorState, rs);
>      NetFilterState *nf = NETFILTER(s);
> +    const uint8_t *buf = rs->buf;
> +    int len = rs->packet_len;
>
>      /* Update indev statistics */
>      s->indev_packets++;
> -    s->indev_bytes += rs->packet_len;
> +    s->indev_bytes += len;
> +
> +    /*
> +     * If the sender enables vnet_hdr_support, received data includes a
> +     * vnet_hdr prefix. Skip vnet_hdr_len bytes and pass the Ethernet frame.
> +     */
> +    if (s->vnet_hdr) {
> +        if (rs->vnet_hdr_len <= 0 || rs->vnet_hdr_len >= len) {
> +            return;
> +        }
> +        buf += rs->vnet_hdr_len;
> +        len -= rs->vnet_hdr_len;
> +    }
>
> -    redirector_to_filter(nf, rs->buf, rs->packet_len);
> +    /*
> +     * Packets injected from the chardev are raw Ethernet frames without a
> +     * vnet_hdr prefix. Mark them as RAW so downstream filters (e.g. dump)
> +     * won't try to skip a vnet_hdr_len.
> +     */
> +    redirector_to_filter(nf, QEMU_NET_PACKET_FLAG_RAW, buf, len);
>  }
>
>  static void filter_redirector_vm_state_change(void *opaque, bool running,
> --
> 2.52.0
>


Reply via email to