diff options
Diffstat (limited to 'sys/netinet/tcp_lro.c')
-rw-r--r-- | sys/netinet/tcp_lro.c | 68 |
1 files changed, 37 insertions, 31 deletions
diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c index 7067abe..bd323bf 100644 --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -67,6 +67,8 @@ static MALLOC_DEFINE(M_LRO, "LRO", "LRO control structures"); #define TCP_LRO_INVALID_CSUM 0x0000 #endif +static void tcp_lro_rx_done(struct lro_ctrl *lc); + int tcp_lro_init(struct lro_ctrl *lc) { @@ -91,8 +93,8 @@ tcp_lro_init_args(struct lro_ctrl *lc, struct ifnet *ifp, lc->lro_ackcnt_lim = TCP_LRO_ACKCNT_MAX; lc->lro_length_lim = TCP_LRO_LENGTH_MAX; lc->ifp = ifp; - SLIST_INIT(&lc->lro_free); - SLIST_INIT(&lc->lro_active); + LIST_INIT(&lc->lro_free); + LIST_INIT(&lc->lro_active); /* compute size to allocate */ size = (lro_mbufs * sizeof(struct mbuf *)) + @@ -111,7 +113,7 @@ tcp_lro_init_args(struct lro_ctrl *lc, struct ifnet *ifp, /* setup linked list */ for (i = 0; i != lro_entries; i++) - SLIST_INSERT_HEAD(&lc->lro_free, le + i, next); + LIST_INSERT_HEAD(&lc->lro_free, le + i, next); return (0); } @@ -123,11 +125,11 @@ tcp_lro_free(struct lro_ctrl *lc) unsigned x; /* reset LRO free list */ - SLIST_INIT(&lc->lro_free); + LIST_INIT(&lc->lro_free); /* free active mbufs, if any */ - while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) { - SLIST_REMOVE_HEAD(&lc->lro_active, next); + while ((le = LIST_FIRST(&lc->lro_active)) != NULL) { + LIST_REMOVE(le, next); m_freem(le->m_head); } @@ -226,20 +228,31 @@ tcp_lro_rx_csum_fixup(struct lro_entry *le, void *l3hdr, struct tcphdr *th, } #endif +static void +tcp_lro_rx_done(struct lro_ctrl *lc) +{ + struct lro_entry *le; + + while ((le = LIST_FIRST(&lc->lro_active)) != NULL) { + LIST_REMOVE(le, next); + tcp_lro_flush(lc, le); + } +} + void tcp_lro_flush_inactive(struct lro_ctrl *lc, const struct timeval *timeout) { struct lro_entry *le, *le_tmp; struct timeval tv; - if (SLIST_EMPTY(&lc->lro_active)) + if (LIST_EMPTY(&lc->lro_active)) return; getmicrotime(&tv); timevalsub(&tv, timeout); - SLIST_FOREACH_SAFE(le, &lc->lro_active, next, le_tmp) { + LIST_FOREACH_SAFE(le, &lc->lro_active, next, le_tmp) { if (timevalcmp(&tv, &le->mtime, >=)) { - SLIST_REMOVE(&lc->lro_active, le, lro_entry, next); + LIST_REMOVE(le, next); tcp_lro_flush(lc, le); } } @@ -335,7 +348,7 @@ tcp_lro_flush(struct lro_ctrl *lc, struct lro_entry *le) lc->lro_queued += le->append_cnt + 1; lc->lro_flushed++; bzero(le, sizeof(*le)); - SLIST_INSERT_HEAD(&lc->lro_free, le, next); + LIST_INSERT_HEAD(&lc->lro_free, le, next); } static int @@ -362,13 +375,12 @@ done: void tcp_lro_flush_all(struct lro_ctrl *lc) { - struct lro_entry *le; uint32_t hashtype; uint32_t flowid; unsigned x; /* check if no mbufs to flush */ - if (__predict_false(lc->lro_mbuf_count == 0)) + if (lc->lro_mbuf_count == 0) goto done; /* sort all mbufs according to stream */ @@ -390,10 +402,7 @@ tcp_lro_flush_all(struct lro_ctrl *lc) hashtype = M_HASHTYPE_GET(mb); /* flush active streams */ - while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) { - SLIST_REMOVE_HEAD(&lc->lro_active, next); - tcp_lro_flush(lc, le); - } + tcp_lro_rx_done(lc); } #ifdef TCP_LRO_RESET_SEQUENCE /* reset sequence number */ @@ -409,10 +418,8 @@ tcp_lro_flush_all(struct lro_ctrl *lc) } done: /* flush active streams */ - while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) { - SLIST_REMOVE_HEAD(&lc->lro_active, next); - tcp_lro_flush(lc, le); - } + tcp_lro_rx_done(lc); + lc->lro_mbuf_count = 0; } @@ -586,7 +593,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum) seq = ntohl(th->th_seq); /* Try to find a matching previous segment. */ - SLIST_FOREACH(le, &lc->lro_active, next) { + LIST_FOREACH(le, &lc->lro_active, next) { if (le->eh_type != eh_type) continue; if (le->source_port != th->th_sport || @@ -613,7 +620,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum) /* Flush now if appending will result in overflow. */ if (le->p_len > (lc->lro_length_lim - tcp_data_len)) { - SLIST_REMOVE(&lc->lro_active, le, lro_entry, next); + LIST_REMOVE(le, next); tcp_lro_flush(lc, le); break; } @@ -622,7 +629,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum) if (__predict_false(seq != le->next_seq || (tcp_data_len == 0 && le->ack_seq == th->th_ack))) { /* Out of order packet or duplicate ACK. */ - SLIST_REMOVE(&lc->lro_active, le, lro_entry, next); + LIST_REMOVE(le, next); tcp_lro_flush(lc, le); return (TCP_LRO_CANNOT); } @@ -655,8 +662,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum) * be further delayed. */ if (le->append_cnt >= lc->lro_ackcnt_lim) { - SLIST_REMOVE(&lc->lro_active, le, lro_entry, - next); + LIST_REMOVE(le, next); tcp_lro_flush(lc, le); } return (0); @@ -680,7 +686,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum) * overflow, pro-actively flush now. */ if (le->p_len > (lc->lro_length_lim - lc->ifp->if_mtu)) { - SLIST_REMOVE(&lc->lro_active, le, lro_entry, next); + LIST_REMOVE(le, next); tcp_lro_flush(lc, le); } else getmicrotime(&le->mtime); @@ -689,13 +695,13 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum) } /* Try to find an empty slot. */ - if (SLIST_EMPTY(&lc->lro_free)) - return (TCP_LRO_CANNOT); + if (LIST_EMPTY(&lc->lro_free)) + return (TCP_LRO_NO_ENTRIES); /* Start a new segment chain. */ - le = SLIST_FIRST(&lc->lro_free); - SLIST_REMOVE_HEAD(&lc->lro_free, next); - SLIST_INSERT_HEAD(&lc->lro_active, le, next); + le = LIST_FIRST(&lc->lro_free); + LIST_REMOVE(le, next); + LIST_INSERT_HEAD(&lc->lro_active, le, next); getmicrotime(&le->mtime); /* Start filling in details. */ |