Index: sys/net/iflib.c =================================================================== --- sys/net/iflib.c +++ sys/net/iflib.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,8 @@ #include #include #include +#include +#include #include #include @@ -2463,7 +2466,48 @@ return (m); } +#if defined(INET6) || defined(INET) +/* + * Returns true if it's possible this packet could be LROed. + * if it returns false, it is guaranteed that tcp_lro_rx() + * would not return zero. + */ static bool +iflib_check_lro_possible(struct lro_ctrl *lc, struct mbuf *m) +{ + struct ether_header *eh; + uint16_t eh_type; + + eh = mtod(m, struct ether_header *); + eh_type = ntohs(eh->ether_type); + switch (eh_type) { + case ETHERTYPE_IPV6: + { + CURVNET_SET(lc->ifp->if_vnet); + if (VNET(ip6_forwarding) == 0) { + CURVNET_RESTORE(); + return true; + } + CURVNET_RESTORE(); + break; + } + case ETHERTYPE_IP: + { + CURVNET_SET(lc->ifp->if_vnet); + if (VNET(ipforwarding) == 0) { + CURVNET_RESTORE(); + return true; + } + CURVNET_RESTORE(); + break; + } + } + + return false; +} +#endif + +static bool iflib_rxeof(iflib_rxq_t rxq, qidx_t budget) { if_ctx_t ctx = rxq->ifr_ctx; @@ -2476,6 +2520,7 @@ iflib_fl_t fl; struct ifnet *ifp; int lro_enabled; + bool lro_possible = false; /* * XXX early demux data packets so that if_input processing only handles @@ -2555,8 +2600,6 @@ mt = mf = NULL; while (mh != NULL) { m = mh; - if (mf == NULL) - mf = m; mh = mh->m_nextpkt; m->m_nextpkt = NULL; #ifndef __NO_STRICT_ALIGNMENT @@ -2566,12 +2609,27 @@ rx_bytes += m->m_pkthdr.len; rx_pkts++; #if defined(INET6) || defined(INET) - if (lro_enabled && tcp_lro_rx(&rxq->ifr_lc, m, 0) == 0) { - if (mf == m) - mf = NULL; - continue; + if (lro_enabled) { + if (!lro_possible) { + lro_possible = iflib_check_lro_possible(&rxq->ifr_lc, m); + if (lro_possible && mf != NULL) { + ifp->if_input(ifp, mf); + DBG_COUNTER_INC(rx_if_input); + mt = mf = NULL; + } + } + if (lro_possible && tcp_lro_rx(&rxq->ifr_lc, m, 0) == 0) + continue; } #endif + if (lro_possible) { + ifp->if_input(ifp, m); + DBG_COUNTER_INC(rx_if_input); + continue; + } + + if (mf == NULL) + mf = m; if (mt != NULL) mt->m_nextpkt = m; mt = m;