Re: [PATCH] vhost/net: remove zerocopy support
On Mon, May 12, 2025 at 5:21 PM Jon Kohler wrote:
>
>
>
> > On Apr 30, 2025, at 9:21 PM, Jon Kohler wrote:
> >
> >
> >
> >> On Apr 16, 2025, at 6:15 AM, Eugenio Perez Martin
> >> wrote:
> >>
> >> !---|
> >> CAUTION: External Email
> >>
> >> |---!
> >>
> >> On Tue, Apr 8, 2025 at 8:28 AM Jason Wang wrote:
> >>>
> >>> On Tue, Apr 8, 2025 at 9:18 AM Jon Kohler wrote:
>
>
>
> > On Apr 6, 2025, at 7:14 PM, Jason Wang wrote:
> >
> > !---|
> > CAUTION: External Email
> >
> > |---!
> >
> > On Fri, Apr 4, 2025 at 10:24 PM Jon Kohler wrote:
> >>
> >> Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
> >> the module parameter for the handle_tx_zerocopy path back in 2019,
> >> nothing that many downstream distributions (e.g., RHEL7 and later) had
> >> already done the same.
> >>
> >> Both upstream and downstream disablement suggest this path is rarely
> >> used.
> >>
> >> Testing the module parameter shows that while the path allows packet
> >> forwarding, the zerocopy functionality itself is broken. On outbound
> >> traffic (guest TX -> external), zerocopy SKBs are orphaned by either
> >> skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit())
> >
> > This is by design to avoid DOS.
>
> I understand that, but it makes ZC non-functional in general, as ZC fails
> and immediately increments the error counters.
> >>>
> >>> The main issue is HOL, but zerocopy may still work in some setups that
> >>> don't need to care about HOL. One example the macvtap passthrough
> >>> mode.
> >>>
>
> >
> >> or
> >> skb_orphan_frags() elsewhere in the stack,
> >
> > Basically zerocopy is expected to work for guest -> remote case, so
> > could we still hit skb_orphan_frags() in this case?
>
> Yes, you’d hit that in tun_net_xmit().
> >>>
> >>> Only for local VM to local VM communication.
> >
> > Sure, but the tricky bit here is that if you have a mix of VM-VM and
> > VM-external
> > traffic patterns, any time the error path is hit, the zc error counter will
> > go up.
> >
> > When that happens, ZC will get silently disabled anyhow, so it leads to
> > sporadic
> > success / non-deterministic performance.
> >
> >>>
> If you punch a hole in that *and* in the
> zc error counter (such that failed ZC doesn’t disable ZC in vhost), you
> get ZC
> from vhost; however, the network interrupt handler under net_tx_action
> and
> eventually incurs the memcpy under dev_queue_xmit_nit().
> >>>
> >>> Well, yes, we need a copy if there's a packet socket. But if there's
> >>> no network interface taps, we don't need to do the copy here.
> >>>
> >
> > Agreed on the packet socket side. I recently fixed an issue in lldpd [1]
> > that prevented
> > this specific case; however, there are still other trip wires spread out
> > across the
> > stack that would need to be addressed.
> >
> > [1]
> > https://github.com/lldpd/lldpd/commit/622a91144de4ae487ceebdb333863e9f660e0717
> >
> >>
> >> Hi!
> >>
> >> I need more time diving into the issues. As Jon mentioned, vhost ZC is
> >> so little used I didn't have the chance to experiment with this until
> >> now :). But yes, I expect to be able to overcome these for pasta, by
> >> adapting buffer sizes or modifying code etc.
> >
> > Another tricky bit here is that it has been disabled both upstream and
> > downstream
> > for so long, the code naturally has a bit of wrench-in-the-engine.
> >
> > RE Buffer sizes: I tried this as well, because I think on sufficiently fast
> > systems,
> > zero copy gets especially interesting in GSO/TSO cases where you have mega
> > payloads.
> >
> > I tried playing around with the good copy value such that ZC restricted
> > itself to
> > only lets say 32K payloads and above, and while it *does* work (with enough
> > holes punched in), absolute t-put doesn’t actually go up, its just that CPU
> > utilization
> > goes down a pinch. Not a bad thing for certain, but still not great.
> >
> > In fact, I found that tput actually went down with this path, even with ZC
> > occurring
> > successfully, as there was still a mix of ZC and non-ZC because you can only
> > have so many pending at any given time before the copy path kicks in again.
> >
> >
> >>
>
> This is no more performant, and in fact is actually worse since the time
> spent
> waiting on that memcpy to resolve is longer.
>
> >
> >> as vhost_net does not set
> >> SKBFL_DONT_ORPHAN.
> >>>
> >>> Maybe we can try to set this as vhost-net can hornor ulimit now.
> >
> > Yea I tried that, and while it helps kick
Re: [PATCH] vhost/net: remove zerocopy support
On Thu, May 1, 2025 at 9:21 AM Jon Kohler wrote:
>
>
>
> > On Apr 16, 2025, at 6:15 AM, Eugenio Perez Martin
> > wrote:
> >
> > !---|
> > CAUTION: External Email
> >
> > |---!
> >
> > On Tue, Apr 8, 2025 at 8:28 AM Jason Wang wrote:
> >>
> >> On Tue, Apr 8, 2025 at 9:18 AM Jon Kohler wrote:
> >>>
> >>>
> >>>
> On Apr 6, 2025, at 7:14 PM, Jason Wang wrote:
>
> !---|
> CAUTION: External Email
>
> |---!
>
> On Fri, Apr 4, 2025 at 10:24 PM Jon Kohler wrote:
> >
> > Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
> > the module parameter for the handle_tx_zerocopy path back in 2019,
> > nothing that many downstream distributions (e.g., RHEL7 and later) had
> > already done the same.
> >
> > Both upstream and downstream disablement suggest this path is rarely
> > used.
> >
> > Testing the module parameter shows that while the path allows packet
> > forwarding, the zerocopy functionality itself is broken. On outbound
> > traffic (guest TX -> external), zerocopy SKBs are orphaned by either
> > skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit())
>
> This is by design to avoid DOS.
> >>>
> >>> I understand that, but it makes ZC non-functional in general, as ZC fails
> >>> and immediately increments the error counters.
> >>
> >> The main issue is HOL, but zerocopy may still work in some setups that
> >> don't need to care about HOL. One example the macvtap passthrough
> >> mode.
> >>
> >>>
>
> > or
> > skb_orphan_frags() elsewhere in the stack,
>
> Basically zerocopy is expected to work for guest -> remote case, so
> could we still hit skb_orphan_frags() in this case?
> >>>
> >>> Yes, you’d hit that in tun_net_xmit().
> >>
> >> Only for local VM to local VM communication.
>
> Sure, but the tricky bit here is that if you have a mix of VM-VM and
> VM-external
> traffic patterns, any time the error path is hit, the zc error counter will
> go up.
>
> When that happens, ZC will get silently disabled anyhow, so it leads to
> sporadic
> success / non-deterministic performance.
As discussed, the main issue is safety: a malicious VM can refuse to
receive packets which may cause tx to be stuck. So scarfing
performance for safety is the only way to go. If we can find a way to
fix them, it could be relaxed.
>
> >>
> >>> If you punch a hole in that *and* in the
> >>> zc error counter (such that failed ZC doesn’t disable ZC in vhost), you
> >>> get ZC
> >>> from vhost; however, the network interrupt handler under net_tx_action and
> >>> eventually incurs the memcpy under dev_queue_xmit_nit().
> >>
> >> Well, yes, we need a copy if there's a packet socket. But if there's
> >> no network interface taps, we don't need to do the copy here.
> >>
>
> Agreed on the packet socket side. I recently fixed an issue in lldpd [1] that
> prevented
> this specific case; however, there are still other trip wires spread out
> across the
> stack that would need to be addressed.
>
> [1]
> https://github.com/lldpd/lldpd/commit/622a91144de4ae487ceebdb333863e9f660e0717
I see.
>
> >
> > Hi!
> >
> > I need more time diving into the issues. As Jon mentioned, vhost ZC is
> > so little used I didn't have the chance to experiment with this until
> > now :). But yes, I expect to be able to overcome these for pasta, by
> > adapting buffer sizes or modifying code etc.
>
> Another tricky bit here is that it has been disabled both upstream and
> downstream
> for so long, the code naturally has a bit of wrench-in-the-engine.
>
> RE Buffer sizes: I tried this as well, because I think on sufficiently fast
> systems,
> zero copy gets especially interesting in GSO/TSO cases where you have mega
> payloads.
Yes.
>
> I tried playing around with the good copy value such that ZC restricted
> itself to
> only lets say 32K payloads and above, and while it *does* work (with enough
> holes punched in), absolute t-put doesn’t actually go up, its just that CPU
> utilization
> goes down a pinch. Not a bad thing for certain, but still not great.
>
> In fact, I found that tput actually went down with this path, even with ZC
> occurring
> successfully, as there was still a mix of ZC and non-ZC because you can only
> have so many pending at any given time before the copy path kicks in again.
TCP has hursitisc that may try to coalesce more writes into a larger
packet so we might get "worse" throughput when vhost becomes faster.
For example, only my testing environment, qemu, is faster than vhost
single TCP stream testing of netperf.
>
>
> >
> >>>
> >>> This is no more performant, and in fact is actually worse since the time
> >>> spent
>
Re: [PATCH] vhost/net: remove zerocopy support
> On Apr 30, 2025, at 9:21 PM, Jon Kohler wrote:
>
>
>
>> On Apr 16, 2025, at 6:15 AM, Eugenio Perez Martin
>> wrote:
>>
>> !---|
>> CAUTION: External Email
>>
>> |---!
>>
>> On Tue, Apr 8, 2025 at 8:28 AM Jason Wang wrote:
>>>
>>> On Tue, Apr 8, 2025 at 9:18 AM Jon Kohler wrote:
> On Apr 6, 2025, at 7:14 PM, Jason Wang wrote:
>
> !---|
> CAUTION: External Email
>
> |---!
>
> On Fri, Apr 4, 2025 at 10:24 PM Jon Kohler wrote:
>>
>> Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
>> the module parameter for the handle_tx_zerocopy path back in 2019,
>> nothing that many downstream distributions (e.g., RHEL7 and later) had
>> already done the same.
>>
>> Both upstream and downstream disablement suggest this path is rarely
>> used.
>>
>> Testing the module parameter shows that while the path allows packet
>> forwarding, the zerocopy functionality itself is broken. On outbound
>> traffic (guest TX -> external), zerocopy SKBs are orphaned by either
>> skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit())
>
> This is by design to avoid DOS.
I understand that, but it makes ZC non-functional in general, as ZC fails
and immediately increments the error counters.
>>>
>>> The main issue is HOL, but zerocopy may still work in some setups that
>>> don't need to care about HOL. One example the macvtap passthrough
>>> mode.
>>>
>
>> or
>> skb_orphan_frags() elsewhere in the stack,
>
> Basically zerocopy is expected to work for guest -> remote case, so
> could we still hit skb_orphan_frags() in this case?
Yes, you’d hit that in tun_net_xmit().
>>>
>>> Only for local VM to local VM communication.
>
> Sure, but the tricky bit here is that if you have a mix of VM-VM and
> VM-external
> traffic patterns, any time the error path is hit, the zc error counter will
> go up.
>
> When that happens, ZC will get silently disabled anyhow, so it leads to
> sporadic
> success / non-deterministic performance.
>
>>>
If you punch a hole in that *and* in the
zc error counter (such that failed ZC doesn’t disable ZC in vhost), you
get ZC
from vhost; however, the network interrupt handler under net_tx_action and
eventually incurs the memcpy under dev_queue_xmit_nit().
>>>
>>> Well, yes, we need a copy if there's a packet socket. But if there's
>>> no network interface taps, we don't need to do the copy here.
>>>
>
> Agreed on the packet socket side. I recently fixed an issue in lldpd [1] that
> prevented
> this specific case; however, there are still other trip wires spread out
> across the
> stack that would need to be addressed.
>
> [1]
> https://github.com/lldpd/lldpd/commit/622a91144de4ae487ceebdb333863e9f660e0717
>
>>
>> Hi!
>>
>> I need more time diving into the issues. As Jon mentioned, vhost ZC is
>> so little used I didn't have the chance to experiment with this until
>> now :). But yes, I expect to be able to overcome these for pasta, by
>> adapting buffer sizes or modifying code etc.
>
> Another tricky bit here is that it has been disabled both upstream and
> downstream
> for so long, the code naturally has a bit of wrench-in-the-engine.
>
> RE Buffer sizes: I tried this as well, because I think on sufficiently fast
> systems,
> zero copy gets especially interesting in GSO/TSO cases where you have mega
> payloads.
>
> I tried playing around with the good copy value such that ZC restricted
> itself to
> only lets say 32K payloads and above, and while it *does* work (with enough
> holes punched in), absolute t-put doesn’t actually go up, its just that CPU
> utilization
> goes down a pinch. Not a bad thing for certain, but still not great.
>
> In fact, I found that tput actually went down with this path, even with ZC
> occurring
> successfully, as there was still a mix of ZC and non-ZC because you can only
> have so many pending at any given time before the copy path kicks in again.
>
>
>>
This is no more performant, and in fact is actually worse since the time
spent
waiting on that memcpy to resolve is longer.
>
>> as vhost_net does not set
>> SKBFL_DONT_ORPHAN.
>>>
>>> Maybe we can try to set this as vhost-net can hornor ulimit now.
>
> Yea I tried that, and while it helps kick things further down the stack, its
> not actually
> faster in any testing I’ve drummed up.
>
>>>
>>
>> Orphaning enforces a memcpy and triggers the completion callback, which
>> increments the failed TX counter, effectively disabling zerocopy again.
>>
>> Even
Re: [PATCH] vhost/net: remove zerocopy support
> On Apr 16, 2025, at 6:15 AM, Eugenio Perez Martin wrote:
>
> !---|
> CAUTION: External Email
>
> |---!
>
> On Tue, Apr 8, 2025 at 8:28 AM Jason Wang wrote:
>>
>> On Tue, Apr 8, 2025 at 9:18 AM Jon Kohler wrote:
>>>
>>>
>>>
On Apr 6, 2025, at 7:14 PM, Jason Wang wrote:
!---|
CAUTION: External Email
|---!
On Fri, Apr 4, 2025 at 10:24 PM Jon Kohler wrote:
>
> Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
> the module parameter for the handle_tx_zerocopy path back in 2019,
> nothing that many downstream distributions (e.g., RHEL7 and later) had
> already done the same.
>
> Both upstream and downstream disablement suggest this path is rarely
> used.
>
> Testing the module parameter shows that while the path allows packet
> forwarding, the zerocopy functionality itself is broken. On outbound
> traffic (guest TX -> external), zerocopy SKBs are orphaned by either
> skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit())
This is by design to avoid DOS.
>>>
>>> I understand that, but it makes ZC non-functional in general, as ZC fails
>>> and immediately increments the error counters.
>>
>> The main issue is HOL, but zerocopy may still work in some setups that
>> don't need to care about HOL. One example the macvtap passthrough
>> mode.
>>
>>>
> or
> skb_orphan_frags() elsewhere in the stack,
Basically zerocopy is expected to work for guest -> remote case, so
could we still hit skb_orphan_frags() in this case?
>>>
>>> Yes, you’d hit that in tun_net_xmit().
>>
>> Only for local VM to local VM communication.
Sure, but the tricky bit here is that if you have a mix of VM-VM and VM-external
traffic patterns, any time the error path is hit, the zc error counter will go
up.
When that happens, ZC will get silently disabled anyhow, so it leads to sporadic
success / non-deterministic performance.
>>
>>> If you punch a hole in that *and* in the
>>> zc error counter (such that failed ZC doesn’t disable ZC in vhost), you get
>>> ZC
>>> from vhost; however, the network interrupt handler under net_tx_action and
>>> eventually incurs the memcpy under dev_queue_xmit_nit().
>>
>> Well, yes, we need a copy if there's a packet socket. But if there's
>> no network interface taps, we don't need to do the copy here.
>>
Agreed on the packet socket side. I recently fixed an issue in lldpd [1] that
prevented
this specific case; however, there are still other trip wires spread out across
the
stack that would need to be addressed.
[1]
https://github.com/lldpd/lldpd/commit/622a91144de4ae487ceebdb333863e9f660e0717
>
> Hi!
>
> I need more time diving into the issues. As Jon mentioned, vhost ZC is
> so little used I didn't have the chance to experiment with this until
> now :). But yes, I expect to be able to overcome these for pasta, by
> adapting buffer sizes or modifying code etc.
Another tricky bit here is that it has been disabled both upstream and
downstream
for so long, the code naturally has a bit of wrench-in-the-engine.
RE Buffer sizes: I tried this as well, because I think on sufficiently fast
systems,
zero copy gets especially interesting in GSO/TSO cases where you have mega
payloads.
I tried playing around with the good copy value such that ZC restricted itself
to
only lets say 32K payloads and above, and while it *does* work (with enough
holes punched in), absolute t-put doesn’t actually go up, its just that CPU
utilization
goes down a pinch. Not a bad thing for certain, but still not great.
In fact, I found that tput actually went down with this path, even with ZC
occurring
successfully, as there was still a mix of ZC and non-ZC because you can only
have so many pending at any given time before the copy path kicks in again.
>
>>>
>>> This is no more performant, and in fact is actually worse since the time
>>> spent
>>> waiting on that memcpy to resolve is longer.
>>>
> as vhost_net does not set
> SKBFL_DONT_ORPHAN.
>>
>> Maybe we can try to set this as vhost-net can hornor ulimit now.
Yea I tried that, and while it helps kick things further down the stack, its
not actually
faster in any testing I’ve drummed up.
>>
>
> Orphaning enforces a memcpy and triggers the completion callback, which
> increments the failed TX counter, effectively disabling zerocopy again.
>
> Even after addressing these issues to prevent SKB orphaning and error
> counter increments, performance remains poor. By default, only 64
> messages can be zerocopied, which is immediately exhausted by workloads
> like iperf, resulting in
Re: [PATCH] vhost/net: remove zerocopy support
On Tue, Apr 8, 2025 at 8:28 AM Jason Wang wrote:
>
> On Tue, Apr 8, 2025 at 9:18 AM Jon Kohler wrote:
> >
> >
> >
> > > On Apr 6, 2025, at 7:14 PM, Jason Wang wrote:
> > >
> > > !---|
> > > CAUTION: External Email
> > >
> > > |---!
> > >
> > > On Fri, Apr 4, 2025 at 10:24 PM Jon Kohler wrote:
> > >>
> > >> Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
> > >> the module parameter for the handle_tx_zerocopy path back in 2019,
> > >> nothing that many downstream distributions (e.g., RHEL7 and later) had
> > >> already done the same.
> > >>
> > >> Both upstream and downstream disablement suggest this path is rarely
> > >> used.
> > >>
> > >> Testing the module parameter shows that while the path allows packet
> > >> forwarding, the zerocopy functionality itself is broken. On outbound
> > >> traffic (guest TX -> external), zerocopy SKBs are orphaned by either
> > >> skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit())
> > >
> > > This is by design to avoid DOS.
> >
> > I understand that, but it makes ZC non-functional in general, as ZC fails
> > and immediately increments the error counters.
>
> The main issue is HOL, but zerocopy may still work in some setups that
> don't need to care about HOL. One example the macvtap passthrough
> mode.
>
> >
> > >
> > >> or
> > >> skb_orphan_frags() elsewhere in the stack,
> > >
> > > Basically zerocopy is expected to work for guest -> remote case, so
> > > could we still hit skb_orphan_frags() in this case?
> >
> > Yes, you’d hit that in tun_net_xmit().
>
> Only for local VM to local VM communication.
>
> > If you punch a hole in that *and* in the
> > zc error counter (such that failed ZC doesn’t disable ZC in vhost), you get
> > ZC
> > from vhost; however, the network interrupt handler under net_tx_action and
> > eventually incurs the memcpy under dev_queue_xmit_nit().
>
> Well, yes, we need a copy if there's a packet socket. But if there's
> no network interface taps, we don't need to do the copy here.
>
Hi!
I need more time diving into the issues. As Jon mentioned, vhost ZC is
so little used I didn't have the chance to experiment with this until
now :). But yes, I expect to be able to overcome these for pasta, by
adapting buffer sizes or modifying code etc.
> >
> > This is no more performant, and in fact is actually worse since the time
> > spent
> > waiting on that memcpy to resolve is longer.
> >
> > >
> > >> as vhost_net does not set
> > >> SKBFL_DONT_ORPHAN.
>
> Maybe we can try to set this as vhost-net can hornor ulimit now.
>
> > >>
> > >> Orphaning enforces a memcpy and triggers the completion callback, which
> > >> increments the failed TX counter, effectively disabling zerocopy again.
> > >>
> > >> Even after addressing these issues to prevent SKB orphaning and error
> > >> counter increments, performance remains poor. By default, only 64
> > >> messages can be zerocopied, which is immediately exhausted by workloads
> > >> like iperf, resulting in most messages being memcpy'd anyhow.
> > >>
> > >> Additionally, memcpy'd messages do not benefit from the XDP batching
> > >> optimizations present in the handle_tx_copy path.
> > >>
> > >> Given these limitations and the lack of any tangible benefits, remove
> > >> zerocopy entirely to simplify the code base.
> > >>
> > >> Signed-off-by: Jon Kohler
> > >
> > > Any chance we can fix those issues? Actually, we had a plan to make
> > > use of vhost-net and its tx zerocopy (or even implement the rx
> > > zerocopy) in pasta.
> >
> > Happy to take direction and ideas here, but I don’t see a clear way to fix
> > these
> > issues, without dealing with the assertions that skb_orphan_frags_rx calls
> > out.
> >
> > Said another way, I’d be interested in hearing if there is a config where
> > ZC in
> > current host-net implementation works, as I was driving myself crazy trying
> > to
> > reverse engineer.
>
> See above.
>
> >
> > Happy to collaborate if there is something we could do here.
>
> Great, we can start here by seeking a way to fix the known issues of
> the vhost-net zerocopy code.
>
Happy to help here :).
Jon, could you share more details about the orphan problem so I can
speed up the help? For example, can you describe the code changes and
the code path that would lead to that assertion of
skb_orphan_frags_rx?
Thanks!
Re: [PATCH] vhost/net: remove zerocopy support
On Tue, Apr 8, 2025 at 9:18 AM Jon Kohler wrote:
>
>
>
> > On Apr 6, 2025, at 7:14 PM, Jason Wang wrote:
> >
> > !---|
> > CAUTION: External Email
> >
> > |---!
> >
> > On Fri, Apr 4, 2025 at 10:24 PM Jon Kohler wrote:
> >>
> >> Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
> >> the module parameter for the handle_tx_zerocopy path back in 2019,
> >> nothing that many downstream distributions (e.g., RHEL7 and later) had
> >> already done the same.
> >>
> >> Both upstream and downstream disablement suggest this path is rarely
> >> used.
> >>
> >> Testing the module parameter shows that while the path allows packet
> >> forwarding, the zerocopy functionality itself is broken. On outbound
> >> traffic (guest TX -> external), zerocopy SKBs are orphaned by either
> >> skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit())
> >
> > This is by design to avoid DOS.
>
> I understand that, but it makes ZC non-functional in general, as ZC fails
> and immediately increments the error counters.
The main issue is HOL, but zerocopy may still work in some setups that
don't need to care about HOL. One example the macvtap passthrough
mode.
>
> >
> >> or
> >> skb_orphan_frags() elsewhere in the stack,
> >
> > Basically zerocopy is expected to work for guest -> remote case, so
> > could we still hit skb_orphan_frags() in this case?
>
> Yes, you’d hit that in tun_net_xmit().
Only for local VM to local VM communication.
> If you punch a hole in that *and* in the
> zc error counter (such that failed ZC doesn’t disable ZC in vhost), you get ZC
> from vhost; however, the network interrupt handler under net_tx_action and
> eventually incurs the memcpy under dev_queue_xmit_nit().
Well, yes, we need a copy if there's a packet socket. But if there's
no network interface taps, we don't need to do the copy here.
>
> This is no more performant, and in fact is actually worse since the time spent
> waiting on that memcpy to resolve is longer.
>
> >
> >> as vhost_net does not set
> >> SKBFL_DONT_ORPHAN.
Maybe we can try to set this as vhost-net can hornor ulimit now.
> >>
> >> Orphaning enforces a memcpy and triggers the completion callback, which
> >> increments the failed TX counter, effectively disabling zerocopy again.
> >>
> >> Even after addressing these issues to prevent SKB orphaning and error
> >> counter increments, performance remains poor. By default, only 64
> >> messages can be zerocopied, which is immediately exhausted by workloads
> >> like iperf, resulting in most messages being memcpy'd anyhow.
> >>
> >> Additionally, memcpy'd messages do not benefit from the XDP batching
> >> optimizations present in the handle_tx_copy path.
> >>
> >> Given these limitations and the lack of any tangible benefits, remove
> >> zerocopy entirely to simplify the code base.
> >>
> >> Signed-off-by: Jon Kohler
> >
> > Any chance we can fix those issues? Actually, we had a plan to make
> > use of vhost-net and its tx zerocopy (or even implement the rx
> > zerocopy) in pasta.
>
> Happy to take direction and ideas here, but I don’t see a clear way to fix
> these
> issues, without dealing with the assertions that skb_orphan_frags_rx calls
> out.
>
> Said another way, I’d be interested in hearing if there is a config where ZC
> in
> current host-net implementation works, as I was driving myself crazy trying to
> reverse engineer.
See above.
>
> Happy to collaborate if there is something we could do here.
Great, we can start here by seeking a way to fix the known issues of
the vhost-net zerocopy code.
Thanks
>
> >
> > Eugenio may explain more here.
> >
> > Thanks
> >
>
Re: [PATCH] vhost/net: remove zerocopy support
> On Apr 6, 2025, at 7:14 PM, Jason Wang wrote:
>
> !---|
> CAUTION: External Email
>
> |---!
>
> On Fri, Apr 4, 2025 at 10:24 PM Jon Kohler wrote:
>>
>> Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
>> the module parameter for the handle_tx_zerocopy path back in 2019,
>> nothing that many downstream distributions (e.g., RHEL7 and later) had
>> already done the same.
>>
>> Both upstream and downstream disablement suggest this path is rarely
>> used.
>>
>> Testing the module parameter shows that while the path allows packet
>> forwarding, the zerocopy functionality itself is broken. On outbound
>> traffic (guest TX -> external), zerocopy SKBs are orphaned by either
>> skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit())
>
> This is by design to avoid DOS.
I understand that, but it makes ZC non-functional in general, as ZC fails
and immediately increments the error counters.
>
>> or
>> skb_orphan_frags() elsewhere in the stack,
>
> Basically zerocopy is expected to work for guest -> remote case, so
> could we still hit skb_orphan_frags() in this case?
Yes, you’d hit that in tun_net_xmit(). If you punch a hole in that *and* in the
zc error counter (such that failed ZC doesn’t disable ZC in vhost), you get ZC
from vhost; however, the network interrupt handler under net_tx_action and
eventually incurs the memcpy under dev_queue_xmit_nit().
This is no more performant, and in fact is actually worse since the time spent
waiting on that memcpy to resolve is longer.
>
>> as vhost_net does not set
>> SKBFL_DONT_ORPHAN.
>>
>> Orphaning enforces a memcpy and triggers the completion callback, which
>> increments the failed TX counter, effectively disabling zerocopy again.
>>
>> Even after addressing these issues to prevent SKB orphaning and error
>> counter increments, performance remains poor. By default, only 64
>> messages can be zerocopied, which is immediately exhausted by workloads
>> like iperf, resulting in most messages being memcpy'd anyhow.
>>
>> Additionally, memcpy'd messages do not benefit from the XDP batching
>> optimizations present in the handle_tx_copy path.
>>
>> Given these limitations and the lack of any tangible benefits, remove
>> zerocopy entirely to simplify the code base.
>>
>> Signed-off-by: Jon Kohler
>
> Any chance we can fix those issues? Actually, we had a plan to make
> use of vhost-net and its tx zerocopy (or even implement the rx
> zerocopy) in pasta.
Happy to take direction and ideas here, but I don’t see a clear way to fix these
issues, without dealing with the assertions that skb_orphan_frags_rx calls out.
Said another way, I’d be interested in hearing if there is a config where ZC in
current host-net implementation works, as I was driving myself crazy trying to
reverse engineer.
Happy to collaborate if there is something we could do here.
>
> Eugenio may explain more here.
>
> Thanks
>
Re: [PATCH] vhost/net: remove zerocopy support
On Fri, Apr 4, 2025 at 10:24 PM Jon Kohler wrote:
>
> Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
> the module parameter for the handle_tx_zerocopy path back in 2019,
> nothing that many downstream distributions (e.g., RHEL7 and later) had
> already done the same.
>
> Both upstream and downstream disablement suggest this path is rarely
> used.
>
> Testing the module parameter shows that while the path allows packet
> forwarding, the zerocopy functionality itself is broken. On outbound
> traffic (guest TX -> external), zerocopy SKBs are orphaned by either
> skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit())
This is by design to avoid DOS.
> or
> skb_orphan_frags() elsewhere in the stack,
Basically zerocopy is expected to work for guest -> remote case, so
could we still hit skb_orphan_frags() in this case?
> as vhost_net does not set
> SKBFL_DONT_ORPHAN.
>
> Orphaning enforces a memcpy and triggers the completion callback, which
> increments the failed TX counter, effectively disabling zerocopy again.
>
> Even after addressing these issues to prevent SKB orphaning and error
> counter increments, performance remains poor. By default, only 64
> messages can be zerocopied, which is immediately exhausted by workloads
> like iperf, resulting in most messages being memcpy'd anyhow.
>
> Additionally, memcpy'd messages do not benefit from the XDP batching
> optimizations present in the handle_tx_copy path.
>
> Given these limitations and the lack of any tangible benefits, remove
> zerocopy entirely to simplify the code base.
>
> Signed-off-by: Jon Kohler
Any chance we can fix those issues? Actually, we had a plan to make
use of vhost-net and its tx zerocopy (or even implement the rx
zerocopy) in pasta.
Eugenio may explain more here.
Thanks
[PATCH] vhost/net: remove zerocopy support
Commit 098eadce3c62 ("vhost_net: disable zerocopy by default") disabled
the module parameter for the handle_tx_zerocopy path back in 2019,
nothing that many downstream distributions (e.g., RHEL7 and later) had
already done the same.
Both upstream and downstream disablement suggest this path is rarely
used.
Testing the module parameter shows that while the path allows packet
forwarding, the zerocopy functionality itself is broken. On outbound
traffic (guest TX -> external), zerocopy SKBs are orphaned by either
skb_orphan_frags_rx() (used with the tun driver via tun_net_xmit()) or
skb_orphan_frags() elsewhere in the stack, as vhost_net does not set
SKBFL_DONT_ORPHAN.
Orphaning enforces a memcpy and triggers the completion callback, which
increments the failed TX counter, effectively disabling zerocopy again.
Even after addressing these issues to prevent SKB orphaning and error
counter increments, performance remains poor. By default, only 64
messages can be zerocopied, which is immediately exhausted by workloads
like iperf, resulting in most messages being memcpy'd anyhow.
Additionally, memcpy'd messages do not benefit from the XDP batching
optimizations present in the handle_tx_copy path.
Given these limitations and the lack of any tangible benefits, remove
zerocopy entirely to simplify the code base.
Signed-off-by: Jon Kohler
---
drivers/vhost/net.c | 398 +---
1 file changed, 2 insertions(+), 396 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index b9b9e9d40951..d16cb8f69591 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -35,11 +35,6 @@
#include "vhost.h"
-static int experimental_zcopytx = 0;
-module_param(experimental_zcopytx, int, 0444);
-MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"
- " 1 -Enable; 0 - Disable");
-
/* Max number of bytes transferred before requeueing the job.
* Using this limit prevents one virtqueue from starving others. */
#define VHOST_NET_WEIGHT 0x8
@@ -50,25 +45,6 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"
*/
#define VHOST_NET_PKT_WEIGHT 256
-/* MAX number of TX used buffers for outstanding zerocopy */
-#define VHOST_MAX_PEND 128
-#define VHOST_GOODCOPY_LEN 256
-
-/*
- * For transmit, used buffer len is unused; we override it to track buffer
- * status internally; used for zerocopy tx only.
- */
-/* Lower device DMA failed */
-#define VHOST_DMA_FAILED_LEN ((__force __virtio32)3)
-/* Lower device DMA done */
-#define VHOST_DMA_DONE_LEN ((__force __virtio32)2)
-/* Lower device DMA in progress */
-#define VHOST_DMA_IN_PROGRESS ((__force __virtio32)1)
-/* Buffer unused */
-#define VHOST_DMA_CLEAR_LEN((__force __virtio32)0)
-
-#define VHOST_DMA_IS_DONE(len) ((__force u32)(len) >= (__force
u32)VHOST_DMA_DONE_LEN)
-
enum {
VHOST_NET_FEATURES = VHOST_FEATURES |
(1ULL << VHOST_NET_F_VIRTIO_NET_HDR) |
@@ -87,17 +63,6 @@ enum {
VHOST_NET_VQ_MAX = 2,
};
-struct vhost_net_ubuf_ref {
- /* refcount follows semantics similar to kref:
-* 0: object is released
-* 1: no outstanding ubufs
-* >1: outstanding ubufs
-*/
- atomic_t refcount;
- wait_queue_head_t wait;
- struct vhost_virtqueue *vq;
-};
-
#define VHOST_NET_BATCH 64
struct vhost_net_buf {
void **queue;
@@ -109,20 +74,9 @@ struct vhost_net_virtqueue {
struct vhost_virtqueue vq;
size_t vhost_hlen;
size_t sock_hlen;
- /* vhost zerocopy support fields below: */
- /* last used idx for outstanding DMA zerocopy buffers */
- int upend_idx;
- /* For TX, first used idx for DMA done zerocopy buffers
-* For RX, number of batched heads
-*/
int done_idx;
/* Number of XDP frames batched */
int batched_xdp;
- /* an array of userspace buffers info */
- struct ubuf_info_msgzc *ubuf_info;
- /* Reference counting for outstanding ubufs.
-* Protected by vq mutex. Writers must also take device mutex. */
- struct vhost_net_ubuf_ref *ubufs;
struct ptr_ring *rx_ring;
struct vhost_net_buf rxq;
/* Batched XDP buffs */
@@ -133,20 +87,10 @@ struct vhost_net {
struct vhost_dev dev;
struct vhost_net_virtqueue vqs[VHOST_NET_VQ_MAX];
struct vhost_poll poll[VHOST_NET_VQ_MAX];
- /* Number of TX recently submitted.
-* Protected by tx vq lock. */
- unsigned tx_packets;
- /* Number of times zerocopy TX recently failed.
-* Protected by tx vq lock. */
- unsigned tx_zcopy_err;
- /* Flush in progress. Protected by tx vq lock. */
- bool tx_flush;
/* Private page frag cache */
struct page_frag_cache pf_cache;
};
-static unsigned vhost_net_zcopy_mask __read_mostly;
-
static void *vhost_net_buf_get_ptr(struct vhost_net_buf *rxq)
{
if (rxq->tail

