diff options
-rw-r--r-- | sys/netinet/tcp_reass.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 14f0e93..d7efe1d 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -214,16 +214,29 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) mq = nq; } - /* Insert the new segment queue entry into place. */ + /* + * Insert the new segment queue entry into place. Try to collapse + * mbuf chains if segments are adjacent. + */ if (mp) { - m->m_nextpkt = mp->m_nextpkt; - mp->m_nextpkt = m; + if (M_TCPHDR(mp)->th_seq + mp->m_pkthdr.len == th->th_seq) + m_catpkt(mp, m); + else { + m->m_nextpkt = mp->m_nextpkt; + mp->m_nextpkt = m; + m->m_pkthdr.pkt_tcphdr = th; + } } else { - m->m_nextpkt = tp->t_segq; - tp->t_segq = m ; + mq = tp->t_segq; + tp->t_segq = m; + if (mq && th->th_seq + *tlenp == M_TCPHDR(mq)->th_seq) { + m->m_nextpkt = mq->m_nextpkt; + m_catpkt(m, mq); + } else + m->m_nextpkt = mq; + m->m_pkthdr.pkt_tcphdr = th; } - m->m_pkthdr.pkt_tcphdr = th; - tp->t_segqlen += m->m_pkthdr.len; + tp->t_segqlen += *tlenp; present: /* |