Download raw body.
Use SoftLRO in em(4)
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
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);
Use SoftLRO in em(4)