From: Stefan Sperling Subject: Re: Use SoftLRO in em(4) To: Jan Klemkow Cc: tech@openbsd.org Date: Tue, 11 Nov 2025 15:05:02 +0100 On Tue, Nov 04, 2025 at 01:27:20PM +0100, Jan Klemkow wrote: > Hi, > > 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 Hi 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. > 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 4 Nov 2025 10:24:35 -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,12 @@ em_rxeof(struct em_queue *que) > m->m_flags |= M_VLANTAG; > } > #endif > - ml_enqueue(&ml, m); > + 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 > + ml_enqueue(&ml, m); > > que->rx.fmp = NULL; > que->rx.lmp = NULL; > @@ -3214,7 +3223,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); > >