Index: sys/netinet/tcp_lro.c =================================================================== --- sys/netinet/tcp_lro.c +++ sys/netinet/tcp_lro.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,7 @@ #include #include #include +#include #include #include @@ -66,6 +68,13 @@ #define TCP_LRO_INVALID_CSUM 0x0000 #endif +static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, lro, + CTLFLAG_RW, 0, "LRO parameters"); + +static int tcp_lro_use_qsort; +SYSCTL_INT(_net_inet_tcp_lro, OID_AUTO, use_qsort, CTLFLAG_RWTUN, + &tcp_lro_use_qsort, 0, "Set to use QuickSort else MergeSort is used"); + int tcp_lro_init(struct lro_ctrl *lc) { @@ -92,7 +101,7 @@ SLIST_INIT(&lc->lro_active); /* compute size to allocate */ - size = (lro_mbufs * sizeof(struct mbuf *)) + + size = (2 * lro_mbufs * sizeof(struct mbuf *)) + (lro_entries * sizeof(*le)); lc->lro_mbuf_data = (struct mbuf **) malloc(size, M_LRO, M_NOWAIT | M_ZERO); @@ -104,7 +113,7 @@ } /* compute offset for LRO entries */ le = (struct lro_entry *) - (lc->lro_mbuf_data + lro_mbufs); + (lc->lro_mbuf_data + 2 * lro_mbufs); /* setup linked list */ for (i = 0; i != lro_entries; i++) @@ -340,19 +349,26 @@ { const struct mbuf *ma = *((const struct mbuf * const *)ppa); const struct mbuf *mb = *((const struct mbuf * const *)ppb); - int ret; + int64_t ret; ret = M_HASHTYPE_GET(ma) - M_HASHTYPE_GET(mb); if (ret != 0) goto done; - ret = ma->m_pkthdr.flowid - mb->m_pkthdr.flowid; + ret = ((uint64_t)(uint32_t)ma->m_pkthdr.flowid) - + ((uint64_t)(uint32_t)mb->m_pkthdr.flowid); if (ret != 0) goto done; ret = TCP_LRO_SEQUENCE(ma) - TCP_LRO_SEQUENCE(mb); + if (ret != 0) + goto done; + return (0); done: - return (ret); + if (ret < 0) + return (-1); + else + return (1); } void @@ -367,9 +383,14 @@ if (__predict_false(lc->lro_mbuf_count == 0)) goto done; - /* sort all mbufs according to stream */ - qsort(lc->lro_mbuf_data, lc->lro_mbuf_count, sizeof(struct mbuf *), - &tcp_lro_mbuf_compare_header); + if (__predict_false(tcp_lro_use_qsort)) { + qsort(lc->lro_mbuf_data, lc->lro_mbuf_count, + sizeof(struct mbuf *), &tcp_lro_mbuf_compare_header); + } else { + mergesort_by_pointer((void **)lc->lro_mbuf_data, + (void **)(lc->lro_mbuf_data + lc->lro_mbuf_count), + lc->lro_mbuf_count, &tcp_lro_mbuf_compare_header); + } /* input data into LRO engine, stream by stream */ flowid = 0; @@ -391,10 +412,6 @@ tcp_lro_flush(lc, le); } } -#ifdef TCP_LRO_RESET_SEQUENCE - /* reset sequence number */ - TCP_LRO_SEQUENCE(mb) = 0; -#endif /* add packet to LRO engine */ if (tcp_lro_rx(lc, mb, 0) != 0) { /* input packet to network layer */