summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_lro.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/tcp_lro.c')
-rw-r--r--sys/netinet/tcp_lro.c68
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. */
OpenPOWER on IntegriCloud