mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-16 10:20:30 +00:00
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
This commit is contained in:
parent
c53fb74f0e
commit
4e02375908
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=167715
@ -852,6 +852,8 @@ sbdrop_internal(struct sockbuf *sb, int len)
|
||||
m->m_len -= len;
|
||||
m->m_data += len;
|
||||
sb->sb_cc -= len;
|
||||
if (sb->sb_sndptroff != 0)
|
||||
sb->sb_sndptroff -= len;
|
||||
if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA)
|
||||
sb->sb_ctl -= len;
|
||||
break;
|
||||
@ -903,6 +905,45 @@ sbdrop(struct sockbuf *sb, int len)
|
||||
SOCKBUF_UNLOCK(sb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Maintain a pointer and offset pair into the socket buffer mbuf chain to
|
||||
* avoid traversal of the entire socket buffer for larger offsets.
|
||||
*/
|
||||
struct mbuf *
|
||||
sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff)
|
||||
{
|
||||
struct mbuf *m, *ret;
|
||||
|
||||
KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__));
|
||||
KASSERT(off + len <= sb->sb_cc, ("%s: beyond sb", __func__));
|
||||
KASSERT(sb->sb_sndptroff <= sb->sb_cc, ("%s: sndptroff broken", __func__));
|
||||
|
||||
/*
|
||||
* Is off below stored offset? Happens on retransmits.
|
||||
* Just return, we can't help here.
|
||||
*/
|
||||
if (sb->sb_sndptroff > off) {
|
||||
*moff = off;
|
||||
return (sb->sb_mb);
|
||||
}
|
||||
|
||||
/* Return closest mbuf in chain for current offset. */
|
||||
*moff = off - sb->sb_sndptroff;
|
||||
m = ret = sb->sb_sndptr ? sb->sb_sndptr : sb->sb_mb;
|
||||
|
||||
/* Advance by len to be as close as possible for the next transmit. */
|
||||
for (off = off - sb->sb_sndptroff + len - 1;
|
||||
off > 0 && off >= m->m_len;
|
||||
m = m->m_next) {
|
||||
sb->sb_sndptroff += m->m_len;
|
||||
off -= m->m_len;
|
||||
}
|
||||
sb->sb_sndptr = m;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop a record off the front of a sockbuf and move the next record to the
|
||||
* front.
|
||||
|
@ -744,6 +744,9 @@ tcp_output(struct tcpcb *tp)
|
||||
* 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 @@ tcp_output(struct tcpcb *tp)
|
||||
#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;
|
||||
|
@ -103,6 +103,8 @@ struct socket {
|
||||
struct mbuf *sb_mbtail; /* (c/d) the last mbuf in the chain */
|
||||
struct mbuf *sb_lastrecord; /* (c/d) first mbuf of last
|
||||
* record in socket buffer */
|
||||
struct mbuf *sb_sndptr; /* (c/d) pointer into mbuf chain */
|
||||
u_int sb_sndptroff; /* (c/d) byte offset of ptr into chain */
|
||||
u_int sb_cc; /* (c/d) actual chars in buffer */
|
||||
u_int sb_hiwat; /* (c/d) max actual char count */
|
||||
u_int sb_mbcnt; /* (c/d) chars of mbufs used */
|
||||
@ -321,6 +323,12 @@ struct xsocket {
|
||||
(sb)->sb_mbcnt -= MSIZE; \
|
||||
if ((m)->m_flags & M_EXT) \
|
||||
(sb)->sb_mbcnt -= (m)->m_ext.ext_size; \
|
||||
if ((sb)->sb_sndptr == (m)) { \
|
||||
(sb)->sb_sndptr = NULL; \
|
||||
(sb)->sb_sndptroff = 0; \
|
||||
} \
|
||||
if ((sb)->sb_sndptroff != 0) \
|
||||
(sb)->sb_sndptroff -= (m)->m_len; \
|
||||
}
|
||||
|
||||
/*
|
||||
@ -491,6 +499,8 @@ int sbreserve(struct sockbuf *sb, u_long cc, struct socket *so,
|
||||
struct thread *td);
|
||||
int sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so,
|
||||
struct thread *td);
|
||||
struct mbuf *
|
||||
sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff);
|
||||
void sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb);
|
||||
int sbwait(struct sockbuf *sb);
|
||||
int sb_lock(struct sockbuf *sb);
|
||||
|
Loading…
Reference in New Issue
Block a user