summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_output.c
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2007-03-19 18:35:13 +0000
committerandre <andre@FreeBSD.org>2007-03-19 18:35:13 +0000
commit515a501549ecde68391cfcda8fa7589d3be40b09 (patch)
tree2990be3a6e9bba0c00c062b7e5afbdc1fb30ba4f /sys/netinet/tcp_output.c
parent52a90d88fa8297a87f870f937e67657a45d52f71 (diff)
downloadFreeBSD-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.c16
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;
OpenPOWER on IntegriCloud