Download raw body.
Use SoftLRO in em(4)
On Tue, Nov 11, 2025 at 07:01:34PM +0100, Jan Klemkow wrote:
> Hi Stefan,
>
> On Tue, Nov 11, 2025 at 03:05:02PM +0100, Stefan Sperling wrote:
> > On Tue, Nov 04, 2025 at 01:27:20PM +0100, Jan Klemkow wrote:
> > > This diff adds the use of SoftLRO in em(4).
> > >
> > > It uses the E1000_RXD_STAT_TCPCS and E1000_RXD_STAT_UDPCS flags to
> > > distinguish between TCP and non-TCP packets. Both flags are set on UDP
> > > packets and just E1000_RXD_STAT_TCPCS and TCP ones. Thus, I ended up
> > > with the TCP and !UDP logic below.
> > >
> > > More tests especially on older hardware are welcome.
> > >
> > > I tested it with:
> > > em0 at pci2 dev 0 function 0 "Intel I210" rev 0x03: msi, address a8:a1:59:f2:a4:81
> > > em1 at pci3 dev 0 function 0 "Intel I210" rev 0x03: msi, address a8:a1:59:f2:a4:82
> > >
> > > ok?
> > >
> > > bye,
> > > Jan
> >
> > This diff breaks the RAMDISK_CD build:
> >
> > ld: error: undefined symbol: tcp_softlro_glue
> > >>> referenced by if_em.c:3196 (/usr/src/sys/dev/pci/if_em.c:3196)
> > >>> if_em.o:(em_rxeof)
> >
> > Looks like some more ifndef SMALL will be needed.
>
> Yes, I missed that.
>
Thanks, this diff builds fine.
> ok?
Yes, ok stsp@
Please keep an eye out for bug reports against em after comitting this.
We can never be really sure, but I am fairly confident that this change
will not break anything because the E1000_RXD_STAT_TCPCS has existed since
the initial version of this driver. It should be safe to rely on this flag
for all models of this device.
The UDP flag only appeared in 2005, in commit 416c6952 from the Git's
conversion point of view. I don't know if pre-2005 firmware supports this
flag. But since the UDP flag is just used as a sanity check, checking this
flag should be fine. This would only become a problem in the unlikely case
where buggy firmware sets both flags (TCP and UDP).
> Index: dev/pci/if_em.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_em.c,v
> diff -u -p -r1.379 if_em.c
> --- dev/pci/if_em.c 14 Jul 2025 11:52:43 -0000 1.379
> +++ dev/pci/if_em.c 11 Nov 2025 17:40:38 -0000
> @@ -2013,6 +2013,9 @@ em_setup_interface(struct em_softc *sc)
> ifp->if_capabilities |= IFCAP_TSOv4 | IFCAP_TSOv6;
> }
>
> + ifp->if_capabilities |= IFCAP_LRO;
> + ifp->if_xflags |= IFXF_LRO;
> +
> /*
> * Specify the media types supported by this adapter and register
> * callbacks to update media and link information
> @@ -3066,12 +3069,13 @@ em_rxeof(struct em_queue *que)
> {
> struct em_softc *sc = que->sc;
> struct ifnet *ifp = &sc->sc_ac.ac_if;
> + struct mbuf_list mltcp = MBUF_LIST_INITIALIZER();
> struct mbuf_list ml = MBUF_LIST_INITIALIZER();
> struct mbuf *m;
> u_int8_t accept_frame = 0;
> u_int8_t eop = 0;
> u_int16_t len, desc_len, prev_len_adj;
> - int i, rv = 0;
> + int i, rv = 0, livelocked = 0;
>
> /* Pointer to the receive descriptor being examined. */
> struct em_rx_desc *desc;
> @@ -3186,7 +3190,14 @@ em_rxeof(struct em_queue *que)
> m->m_flags |= M_VLANTAG;
> }
> #endif
> - ml_enqueue(&ml, m);
> +#ifndef SMALL_KERNEL
> + if (ISSET(ifp->if_xflags, IFXF_LRO) &&
> + desc->status & E1000_RXD_STAT_TCPCS &&
> + !(desc->status & E1000_RXD_STAT_UDPCS))
> + tcp_softlro_glue(&mltcp, m, ifp);
> + else
> +#endif
> + ml_enqueue(&ml, m);
>
> que->rx.fmp = NULL;
> que->rx.lmp = NULL;
> @@ -3214,7 +3225,11 @@ em_rxeof(struct em_queue *que)
>
> que->rx.sc_rx_desc_tail = i;
>
> + if (ifiq_input(&ifp->if_rcv, &mltcp))
> + livelocked = 1;
> if (ifiq_input(&ifp->if_rcv, &ml))
> + livelocked = 1;
> + if (livelocked)
> if_rxr_livelocked(&que->rx.sc_rx_ring);
>
> return (rv);
>
>
Use SoftLRO in em(4)