Packets injected from the redirector chardev are raw Ethernet frames without a vnet_hdr prefix. 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
