diff options
author | andre <andre@FreeBSD.org> | 2007-03-19 18:35:13 +0000 |
---|---|---|
committer | andre <andre@FreeBSD.org> | 2007-03-19 18:35:13 +0000 |
commit | 515a501549ecde68391cfcda8fa7589d3be40b09 (patch) | |
tree | 2990be3a6e9bba0c00c062b7e5afbdc1fb30ba4f /sys/netinet/tcp_output.c | |
parent | 52a90d88fa8297a87f870f937e67657a45d52f71 (diff) | |
download | FreeBSD-src-515a501549ecde68391cfcda8fa7589d3be40b09.zip FreeBSD-src-515a501549ecde68391cfcda8fa7589d3be40b09.tar.gz |
Maintain a pointer and offset pair into the socket buffer mbuf chain to
avoid traversal of the entire socket buffer for larger offsets on stream
sockets.
Adjust tcp_output() make use of it.
Tested by: gallatin
Diffstat (limited to 'sys/netinet/tcp_output.c')
-rw-r--r-- | sys/netinet/tcp_output.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 09f7db3..9196529 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -744,6 +744,9 @@ send: * the template for sends on this connection. */ if (len) { + struct mbuf *mb; + u_int moff; + if ((tp->t_flags & TF_FORCEDATA) && len == 1) tcpstat.tcps_sndprobe++; else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { @@ -785,13 +788,20 @@ send: #endif m->m_data += max_linkhdr; m->m_len = hdrlen; + + /* + * Start the m_copy functions from the closest mbuf + * to the offset in the socket buffer chain. + */ + mb = sbsndptr(&so->so_snd, off, len, &moff); + if (len <= MHLEN - hdrlen - max_linkhdr) { - m_copydata(so->so_snd.sb_mb, off, (int)len, + m_copydata(mb, moff, (int)len, mtod(m, caddr_t) + hdrlen); m->m_len += len; } else { - m->m_next = m_copy(so->so_snd.sb_mb, off, (int)len); - if (m->m_next == 0) { + m->m_next = m_copy(mb, moff, (int)len); + if (m->m_next == NULL) { SOCKBUF_UNLOCK(&so->so_snd); (void) m_free(m); error = ENOBUFS; |