diff --git a/sys/netinet/tcp_lro.h b/sys/netinet/tcp_lro.h --- a/sys/netinet/tcp_lro.h +++ b/sys/netinet/tcp_lro.h @@ -146,7 +146,8 @@ uint16_t compressed; uint16_t uncompressed; uint16_t window; - uint16_t timestamp; /* flag, not a TCP hdr field. */ + uint16_t timestamp : 1; + uint16_t needs_merge : 1; struct bintime alloc_time; /* time when entry was allocated */ }; diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -820,7 +820,7 @@ tcp_flush_out_entry(struct lro_ctrl *lc, struct lro_entry *le) { /* Check if we need to recompute any checksums. */ - if (le->m_head->m_pkthdr.lro_nsegs > 1) { + if (le->needs_merge) { uint16_t csum; switch (le->inner.data.lro_type) { @@ -921,6 +921,7 @@ le->next_seq = ntohl(th->th_seq) + tcp_data_len; le->ack_seq = th->th_ack; le->window = th->th_win; + le->needs_merge = 0; /* Setup new data pointers. */ le->m_head = m; @@ -962,10 +963,12 @@ } static void -tcp_lro_mbuf_append_pkthdr(struct mbuf *m, const struct mbuf *p) +tcp_lro_mbuf_append_pkthdr(struct lro_entry *le, const struct mbuf *p) { + struct mbuf *m; uint32_t csum; + m = le->m_head; if (m->m_pkthdr.lro_nsegs == 1) { /* Compute relative checksum. */ csum = p->m_pkthdr.lro_tcp_d_csum; @@ -982,6 +985,7 @@ m->m_pkthdr.lro_tcp_d_csum = csum; m->m_pkthdr.lro_tcp_d_len += p->m_pkthdr.lro_tcp_d_len; m->m_pkthdr.lro_nsegs += p->m_pkthdr.lro_nsegs; + le->needs_merge = 1; } static void @@ -1100,8 +1104,12 @@ le->next_seq += tcp_data_len; le->ack_seq = th->th_ack; le->window = th->th_win; + le->needs_merge = 1; } else if (th->th_ack == le->ack_seq) { - le->window = WIN_MAX(le->window, th->th_win); + if (WIN_GT(th->th_win, le->window)) { + le->window = th->th_win; + le->needs_merge = 1; + } } if (tcp_data_len == 0) { @@ -1110,7 +1118,7 @@ } /* Merge TCP data checksum and length to head mbuf. */ - tcp_lro_mbuf_append_pkthdr(le->m_head, m); + tcp_lro_mbuf_append_pkthdr(le, m); /* * Adjust the mbuf so that m_data points to the first byte of