On Tue, 2021-06-22 at 15:51 +0800, Jason Wang wrote: > > @@ -2388,14 +2406,18 @@ static int tun_xdp_one(struct tun_struct *tun, > > skb_reserve(skb, xdp->data - xdp->data_hard_start); > > skb_put(skb, xdp->data_end - xdp->data); > > > > - if (virtio_net_hdr_to_skb(skb, gso, tun_is_little_endian(tun))) { > > + if (!gso) > > + skb_reset_mac_header(skb); > > + else if (virtio_net_hdr_to_skb(skb, gso, tun_is_little_endian(tun))) { > > atomic_long_inc(&tun->rx_frame_errors); > > kfree_skb(skb); > > > This should work as well. Actually there's no need for the skb_reset_mac_header() as that's going to happen anyway just a few lines down — either from eth_type_trans() or explicitly in the IFF_TUN code path that I added in my first patch. I also stripped out a lot more code from vhost_net_build_xdp() in the !sock_hlen case where it was pointless. https://git.infradead.org/users/dwmw2/linux.git/shortlog/vhost-net I'll repost the whole series after I take look at whether I can get it to work without *either* side doing the vnet header, and add a test case based on my userspace code in https://gitlab.com/openconnect/openconnect/-/blob/vhost/vhost.c