From: Richard von Seck Subject: Enable ix(4) softLRO for IPv6 traffic To: "tech@openbsd.org" Date: Mon, 8 Jun 2026 13:40:32 +0000 Hi, this patch enables software large receive offload (LRO) for ix(4) devices on IPv6 traffic. IPv6 traffic is identified and then forwarded to the existing TCP softLRO implementation as e.g., already used in ixl(4). rvs diff --git sys/dev/pci/if_ix.c sys/dev/pci/if_ix.c index 0ef30ea6355..5a41f8cc455 100644 --- sys/dev/pci/if_ix.c +++ sys/dev/pci/if_ix.c @@ -3279,14 +3279,15 @@ ixgbe_rxeof(struct ix_rxring *rxr) struct ix_softc *sc = rxr->sc; struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf_list ml = MBUF_LIST_INITIALIZER(); + struct mbuf_list mltcp6 = MBUF_LIST_INITIALIZER(); struct mbuf *mp, *sendmp; uint8_t eop = 0; - uint16_t len, vtag; + uint16_t len, vtag, ptype; uint32_t staterr = 0; struct ixgbe_rx_buf *rxbuf, *nxbuf; union ixgbe_adv_rx_desc *rxdesc; size_t dsize = sizeof(union ixgbe_adv_rx_desc); - int i, nextp, rsccnt; + int i, nextp, rsccnt, livelocked; if (!ISSET(ifp->if_flags, IFF_RUNNING)) return FALSE; @@ -3322,9 +3323,15 @@ ixgbe_rxeof(struct ix_rxring *rxr) vtag = letoh16(rxdesc->wb.upper.vlan); eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0); hash = lemtoh32(&rxdesc->wb.lower.hi_dword.rss); - hashtype = - lemtoh16(&rxdesc->wb.lower.lo_dword.hs_rss.pkt_info) & - IXGBE_RXDADV_RSSTYPE_MASK; + hashtype = ptype = + lemtoh16(&rxdesc->wb.lower.lo_dword.hs_rss.pkt_info); + hashtype &= IXGBE_RXDADV_RSSTYPE_MASK; + ptype &= IXGBE_RXDADV_PKTTYPE_MASK; + + /* + * since the NIC doesn't support RSC for IPv6 packets, rsccnt + * should be read as zero for incoming IPv6 traffic + */ rsccnt = lemtoh32(&rxdesc->wb.lower.lo_dword.data) & IXGBE_RXDADV_RSCCNT_MASK; rsccnt >>= IXGBE_RXDADV_RSCCNT_SHIFT; @@ -3408,7 +3415,11 @@ ixgbe_rxeof(struct ix_rxring *rxr) SET(sendmp->m_pkthdr.csum_flags, M_FLOWID); } - ml_enqueue(&ml, sendmp); + if (ISSET(ifp->if_xflags, IFXF_LRO) && + ISSET(ptype, IXGBE_RXDADV_PKTTYPE_IPV6)) + tcp_softlro_glue(&mltcp6, sendmp, ifp); + else + ml_enqueue(&ml, sendmp); } next_desc: if_rxr_put(&rxr->rx_ring, 1); @@ -3422,7 +3433,12 @@ next_desc: } rxr->next_to_check = i; + livelocked = 0; + if (ifiq_input(rxr->ifiq, &mltcp6)) + livelocked = 1; if (ifiq_input(rxr->ifiq, &ml)) + livelocked = 1; + if (livelocked) if_rxr_livelocked(&rxr->rx_ring); if (!(staterr & IXGBE_RXD_STAT_DD))