Re: git: 6e4b811009d6 - main - vtnet: disable hardware TCP LRO by default

Michael Tuexen <[email protected]> Thu, 23 Jul 2026 09:29:11 +0200
Newsgroups gmane.os.freebsd.devel.net
Message-ID <[email protected]>
> On 22. Jul 2026, at 15:34, Micka=C3=ABl Maillot =
<[email protected]> wrote:
>=20
> Hi,
>=20
> I'd like to report that a problem still exists with vtnet LRO on =
15.1-RELEASE =E2=80=94 but in the software LRO path, which remains =
enabled by default (this commit only disables hardware LRO).
>=20
> Environment: FreeBSD 15.1-RELEASE-p1 guests (vtnet/virtio) on =
Proxmox/KVM, running haproxy in front of Linux backends. After upgrading =
the guests from 14.3 to 15.1, we started seeing intermittent =
mid-transfer TCP stalls on responses larger than ~100 KB (roughly 1 in 5 =
transfers under production load), ending in a 30 s application timeout.
>=20
> Packet captures on the FreeBSD side show the following sequence:
>=20
> 1. The FreeBSD receiver's window closes under application =
back-pressure (win goes down to 0-2 with wscale 8), the sender fits one =
last small segment into it.
> 2. FreeBSD then sends a window-update ACK reopening the window (win =
257).
> 3. The Linux sender never acts on it: its subsequent zero-window =
probes keep echoing the previous timestamp, i.e. the window update was =
never received/processed, and it stays in persist mode.
> 4. FreeBSD does not respond to the zero-length probes, so the =
connection deadlocks until the application gives up.
>=20
> The window-update ACK is visible in the capture taken on the FreeBSD =
guest itself (BPF), so it is generated but apparently lost on the way =
out.
>=20
> The issue is correlated with software LRO: with LRO enabled we =
reproduced 10 failures out of 60 transfers; after ifconfig vtnet0 -lro =
(TSO4 still enabled) we got 0 out of 60, across several identical =
guests. Disabling LRO fleet-wide made the problem disappear entirely. =
14.x guests with the same workload never showed this.
>=20
> Happy to provide the pcaps or test patches.
Hi Micka=C3=ABl,

thanks for reaching out. It would be great to initially have a .pcap =
file
to look at. Will then most likely ask for some BBLog files. But let us
start with a .pcap file first.

You can send them directly to my mail address.

Best regards
Michael
>=20
> Le mar. 30 sept. 2025 =C3=A0 19:14, Michael Tuexen =
<[email protected]> a =C3=A9crit :
> The branch main has been updated by tuexen:
>=20
> URL: =
https://cgit.FreeBSD.org/src/commit/?id=3D6e4b811009d63f33c59d51f28fd4a030=
ca90843e
>=20
> commit 6e4b811009d63f33c59d51f28fd4a030ca90843e
> Author:     Michael Tuexen <[email protected]>
> AuthorDate: 2025-09-29 23:58:37 +0000
> Commit:     Michael Tuexen <[email protected]>
> CommitDate: 2025-09-30 00:03:49 +0000
>=20
>     vtnet: disable hardware TCP LRO by default
>=20
>     Hardware TCP LRO results in problems in settings with IP =
forwarding
>     being enabled. In case of nodes without IP forwarding, using
>     software LRO is also beneficial in general, since it can provide =
better
>     information about what was received on the wire.
>     Therefore, disable hardware TCP LRO by default.
>     By tuning the loader tunable, this can be changed.
>=20
>     PR:                     263229
>     Reviewed by:            Timo V=C3=B6lker
>     MFC after:              3 days
>     Differential Revision:  https://reviews.freebsd.org/D52684
> ---
>  share/man/man4/vtnet.4            | 22 +++++++++++++++++-----
>  sys/dev/virtio/network/if_vtnet.c |  2 +-
>  2 files changed, 18 insertions(+), 6 deletions(-)
>=20
> diff --git a/share/man/man4/vtnet.4 b/share/man/man4/vtnet.4
> index 636ce4cc9b60..fd41b36882a6 100644
> --- a/share/man/man4/vtnet.4
> +++ b/share/man/man4/vtnet.4
> @@ -22,7 +22,7 @@
>  .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE =
POSSIBILITY OF
>  .\" SUCH DAMAGE.
>  .\"
> -.Dd September 26, 2025
> +.Dd September 30, 2025
>  .Dt VTNET 4
>  .Os
>  .Sh NAME
> @@ -54,6 +54,18 @@ TCP segmentation offload (TSO), TCP large receive =
offload (LRO),
>  hardware VLAN tag stripping/insertion features, a multicast hash =
filter,
>  as well as Jumbo Frames (up to 9216 bytes), which can be
>  configured via the interface MTU setting.
> +.Pp
> +Two flavors of TCP LRO are supported:
> +Hardware TCP LRO, which is performed by the host providing TCP =
segments larger
> +than the MTU to the guest, and Software TCP LRO, which is performed =
by the
> +network stack of the guest processing TCP segments in an optimized =
way.
> +Only one flavour of TCP LRO should be used.
> +Since hardware TCP LRO can have bad interactions with IP forwarding =
and
> +software TCP LRO mitigates several drawbacks of hardware TCP LRO, the =
default
> +setting is to disable hardware TCP LRO.
> +See the loader tunable
> +.Va hw.vtnet. Ns Ar X Ns Va .lro_disable .
> +.Pp
>  TCP/UDP receive checksum offload cannot be configured independently =
for IPv4
>  and IPv6.
>  Selecting an MTU larger than 1500 bytes with the
> @@ -94,8 +106,8 @@ This tunable disables TCP segmentation offloading.
>  The default value is 0.
>  .It Va hw.vtnet.lro_disable
>  .It Va hw.vtnet. Ns Ar X Ns Va .lro_disable
> -This tunable disables large receive offload.
> -The default value is 0.
> +This tunable disables hardware TCP LRO.
> +The default value is 1.
>  .It Va hw.vtnet.mq_disable
>  .It Va hw.vtnet. Ns Ar X Ns Va .mq_disable
>  This tunable disables multiqueue.
> @@ -119,11 +131,11 @@ This tunable sets the number of RX segments =
processed in one pass.
>  The default value is 1024.
>  .It Va hw.vtnet.lro_entry_count
>  .It Va hw.vtnet. Ns Ar X Ns Va .lro_entry_count
> -This tunable sets the software LRO entry count.
> +This tunable sets the software TCP LRO entry count.
>  The default value is 128, the minimum value is 8.
>  .It Va hw.vtnet.lro_mbufq_depth
>  .It Va hw.vtnet. Ns Ar X Ns Va .lro_mbufq_depth
> -This tunable sets the depth of the software LRO mbuf queue.
> +This tunable sets the depth of the software TCP LRO mbuf queue.
>  The default value is 0.
>  .It Va hw.vtnet.altq_disable
>  This tunable disables ALTQ support, allowing the use of multiqueue =
instead.
> diff --git a/sys/dev/virtio/network/if_vtnet.c =
b/sys/dev/virtio/network/if_vtnet.c
> index 634ba0de2d55..471c6b3714b2 100644
> --- a/sys/dev/virtio/network/if_vtnet.c
> +++ b/sys/dev/virtio/network/if_vtnet.c
> @@ -281,7 +281,7 @@ static int vtnet_tso_disable =3D 0;
>  SYSCTL_INT(_hw_vtnet, OID_AUTO, tso_disable, CTLFLAG_RDTUN,
>      &vtnet_tso_disable, 0, "Disables TSO");
>=20
> -static int vtnet_lro_disable =3D 0;
> +static int vtnet_lro_disable =3D 1;
>  SYSCTL_INT(_hw_vtnet, OID_AUTO, lro_disable, CTLFLAG_RDTUN,
>      &vtnet_lro_disable, 0, "Disables hardware LRO");
>=20
>=20