speedup stream socket recv handling by tracking the tail of
the mbuf chain instead of walking the list for each append Submitted by: ps/jayanth Obtained from: netbsd (jason thorpe)
This commit is contained in:
parent
d7d75245e8
commit
395bb18680
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121628
@ -2295,6 +2295,7 @@ options INIT_PATH=/sbin/init:/stand/sysinstall
|
||||
# Debug options
|
||||
options BUS_DEBUG # enable newbus debugging
|
||||
options DEBUG_VFS_LOCKS # enable vfs lock debugging
|
||||
options SOCKBUF_DEBUG # enable sockbuf last record/mb tail checking
|
||||
|
||||
#####################################################################
|
||||
# SYSV IPC KERNEL PARAMETERS
|
||||
|
@ -622,6 +622,8 @@ WI_SYMBOL_FIRMWARE opt_wi.h
|
||||
# XXX bogusly global.
|
||||
DEVICE_POLLING opt_global.h
|
||||
|
||||
SOCKBUF_DEBUG opt_global.h
|
||||
|
||||
# options for ubsec driver
|
||||
UBSEC_DEBUG opt_ubsec.h
|
||||
UBSEC_RNDTEST opt_ubsec.h
|
||||
|
@ -468,6 +468,60 @@ sbrelease(sb, so)
|
||||
* or sbdroprecord() when the data is acknowledged by the peer.
|
||||
*/
|
||||
|
||||
#ifdef SOCKBUF_DEBUG
|
||||
void
|
||||
sblastrecordchk(struct sockbuf *sb, const char *file, int line)
|
||||
{
|
||||
struct mbuf *m = sb->sb_mb;
|
||||
|
||||
while (m && m->m_nextpkt)
|
||||
m = m->m_nextpkt;
|
||||
|
||||
if (m != sb->sb_lastrecord) {
|
||||
printf("%s: sb_mb %p sb_lastrecord %p last %p\n",
|
||||
__func__, sb->sb_mb, sb->sb_lastrecord, m);
|
||||
printf("packet chain:\n");
|
||||
for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt)
|
||||
printf("\t%p\n", m);
|
||||
panic("%s from %s:%u", __func__, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sblastmbufchk(struct sockbuf *sb, const char *file, int line)
|
||||
{
|
||||
struct mbuf *m = sb->sb_mb;
|
||||
struct mbuf *n;
|
||||
|
||||
while (m && m->m_nextpkt)
|
||||
m = m->m_nextpkt;
|
||||
|
||||
while (m && m->m_next)
|
||||
m = m->m_next;
|
||||
|
||||
if (m != sb->sb_mbtail) {
|
||||
printf("%s: sb_mb %p sb_mbtail %p last %p\n",
|
||||
__func__, sb->sb_mb, sb->sb_mbtail, m);
|
||||
printf("packet tree:\n");
|
||||
for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) {
|
||||
printf("\t");
|
||||
for (n = m; n != NULL; n = n->m_next)
|
||||
printf("%p ", n);
|
||||
printf("\n");
|
||||
}
|
||||
panic("%s from %s:%u", __func__, file, line);
|
||||
}
|
||||
}
|
||||
#endif /* SOCKBUF_DEBUG */
|
||||
|
||||
#define SBLINKRECORD(sb, m0) do { \
|
||||
if ((sb)->sb_lastrecord != NULL) \
|
||||
(sb)->sb_lastrecord->m_nextpkt = (m0); \
|
||||
else \
|
||||
(sb)->sb_mb = (m0); \
|
||||
(sb)->sb_lastrecord = (m0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* Append mbuf chain m to the last record in the
|
||||
* socket buffer sb. The additional space associated
|
||||
@ -483,6 +537,7 @@ sbappend(sb, m)
|
||||
|
||||
if (m == 0)
|
||||
return;
|
||||
SBLASTRECORDCHK(sb);
|
||||
n = sb->sb_mb;
|
||||
if (n) {
|
||||
while (n->m_nextpkt)
|
||||
@ -493,8 +548,53 @@ sbappend(sb, m)
|
||||
return;
|
||||
}
|
||||
} while (n->m_next && (n = n->m_next));
|
||||
} else {
|
||||
/*
|
||||
* XXX Would like to simply use sb_mbtail here, but
|
||||
* XXX I need to verify that I won't miss an EOR that
|
||||
* XXX way.
|
||||
*/
|
||||
if ((n = sb->sb_lastrecord) != NULL) {
|
||||
do {
|
||||
if (n->m_flags & M_EOR) {
|
||||
sbappendrecord(sb, m); /* XXXXXX!!!! */
|
||||
return;
|
||||
}
|
||||
} while (n->m_next && (n = n->m_next));
|
||||
} else {
|
||||
/*
|
||||
* If this is the first record in the socket buffer,
|
||||
* it's also the last record.
|
||||
*/
|
||||
sb->sb_lastrecord = m;
|
||||
}
|
||||
}
|
||||
sbcompress(sb, m, n);
|
||||
SBLASTRECORDCHK(sb);
|
||||
}
|
||||
|
||||
/*
|
||||
* This version of sbappend() should only be used when the caller
|
||||
* absolutely knows that there will never be more than one record
|
||||
* in the socket buffer, that is, a stream protocol (such as TCP).
|
||||
*/
|
||||
void
|
||||
sbappendstream(struct sockbuf *sb, struct mbuf *m)
|
||||
{
|
||||
|
||||
KASSERT(m->m_nextpkt == NULL,("sbappendstream 0"));
|
||||
KASSERT(sb->sb_mb == sb->sb_lastrecord,("sbappendstream 1"));
|
||||
|
||||
SBLASTMBUFCHK(sb);
|
||||
|
||||
#ifdef MBUFTRACE
|
||||
m_claim(m, sb->sb_mowner);
|
||||
#endif
|
||||
|
||||
sbcompress(sb, m, sb->sb_mbtail);
|
||||
|
||||
sb->sb_lastrecord = sb->sb_mb;
|
||||
SBLASTRECORDCHK(sb);
|
||||
}
|
||||
|
||||
#ifdef SOCKBUF_DEBUG
|
||||
@ -516,7 +616,7 @@ sbcheck(sb)
|
||||
}
|
||||
}
|
||||
if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
|
||||
printf("cc %ld != %ld || mbcnt %ld != %ld\n", len, sb->sb_cc,
|
||||
printf("cc %ld != %u || mbcnt %ld != %u\n", len, sb->sb_cc,
|
||||
mbcnt, sb->sb_mbcnt);
|
||||
panic("sbcheck");
|
||||
}
|
||||
@ -545,6 +645,8 @@ sbappendrecord(sb, m0)
|
||||
* Note this permits zero length records.
|
||||
*/
|
||||
sballoc(sb, m0);
|
||||
SBLASTRECORDCHK(sb);
|
||||
SBLINKRECORD(sb, m0);
|
||||
if (m)
|
||||
m->m_nextpkt = m0;
|
||||
else
|
||||
@ -616,7 +718,7 @@ sbappendaddr(sb, asa, m0, control)
|
||||
struct sockaddr *asa;
|
||||
struct mbuf *m0, *control;
|
||||
{
|
||||
struct mbuf *m, *n;
|
||||
struct mbuf *m, *n, *nlast;
|
||||
int space = asa->sa_len;
|
||||
|
||||
if (m0 && (m0->m_flags & M_PKTHDR) == 0)
|
||||
@ -640,15 +742,16 @@ sbappendaddr(sb, asa, m0, control)
|
||||
else
|
||||
control = m0;
|
||||
m->m_next = control;
|
||||
for (n = m; n; n = n->m_next)
|
||||
for (n = m; n->m_next != NULL; n = n->m_next)
|
||||
sballoc(sb, n);
|
||||
n = sb->sb_mb;
|
||||
if (n) {
|
||||
while (n->m_nextpkt)
|
||||
n = n->m_nextpkt;
|
||||
n->m_nextpkt = m;
|
||||
} else
|
||||
sb->sb_mb = m;
|
||||
sballoc(sb, n);
|
||||
nlast = n;
|
||||
SBLINKRECORD(sb, m);
|
||||
|
||||
sb->sb_mbtail = nlast;
|
||||
SBLASTMBUFCHK(sb);
|
||||
|
||||
SBLASTRECORDCHK(sb);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -657,7 +760,7 @@ sbappendcontrol(sb, m0, control)
|
||||
struct sockbuf *sb;
|
||||
struct mbuf *control, *m0;
|
||||
{
|
||||
struct mbuf *m, *n;
|
||||
struct mbuf *m, *n, *mlast;
|
||||
int space;
|
||||
|
||||
if (control == 0)
|
||||
@ -666,15 +769,19 @@ sbappendcontrol(sb, m0, control)
|
||||
if (space > sbspace(sb))
|
||||
return (0);
|
||||
n->m_next = m0; /* concatenate data to control */
|
||||
for (m = control; m; m = m->m_next)
|
||||
|
||||
SBLASTRECORDCHK(sb);
|
||||
|
||||
for (m = control; m->m_next; m = m->m_next)
|
||||
sballoc(sb, m);
|
||||
n = sb->sb_mb;
|
||||
if (n) {
|
||||
while (n->m_nextpkt)
|
||||
n = n->m_nextpkt;
|
||||
n->m_nextpkt = control;
|
||||
} else
|
||||
sb->sb_mb = control;
|
||||
sballoc(sb, m);
|
||||
mlast = m;
|
||||
SBLINKRECORD(sb, control);
|
||||
|
||||
sb->sb_mbtail = mlast;
|
||||
SBLASTMBUFCHK(sb);
|
||||
|
||||
SBLASTRECORDCHK(sb);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -697,6 +804,8 @@ sbcompress(sb, m, n)
|
||||
(eor == 0 ||
|
||||
(((o = m->m_next) || (o = n)) &&
|
||||
o->m_type == m->m_type))) {
|
||||
if (sb->sb_lastrecord == m)
|
||||
sb->sb_lastrecord = m->m_next;
|
||||
m = m_free(m);
|
||||
continue;
|
||||
}
|
||||
@ -720,6 +829,7 @@ sbcompress(sb, m, n)
|
||||
n->m_next = m;
|
||||
else
|
||||
sb->sb_mb = m;
|
||||
sb->sb_mbtail = m;
|
||||
sballoc(sb, m);
|
||||
n = m;
|
||||
m->m_flags &= ~M_EOR;
|
||||
@ -732,6 +842,7 @@ sbcompress(sb, m, n)
|
||||
else
|
||||
printf("semi-panic: sbcompress\n");
|
||||
}
|
||||
SBLASTMBUFCHK(sb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -800,6 +911,18 @@ sbdrop(sb, len)
|
||||
m->m_nextpkt = next;
|
||||
} else
|
||||
sb->sb_mb = next;
|
||||
/*
|
||||
* First part is an inline SB_EMPTY_FIXUP(). Second part
|
||||
* makes sure sb_lastrecord is up-to-date if we dropped
|
||||
* part of the last record.
|
||||
*/
|
||||
m = sb->sb_mb;
|
||||
if (m == NULL) {
|
||||
sb->sb_mbtail = NULL;
|
||||
sb->sb_lastrecord = NULL;
|
||||
} else if (m->m_nextpkt == NULL) {
|
||||
sb->sb_lastrecord = m;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -820,6 +943,7 @@ sbdroprecord(sb)
|
||||
m = m_free(m);
|
||||
} while (m);
|
||||
}
|
||||
SB_EMPTY_FIXUP(sb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -888,6 +888,8 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
error = EWOULDBLOCK;
|
||||
goto release;
|
||||
}
|
||||
SBLASTRECORDCHK(&so->so_rcv);
|
||||
SBLASTMBUFCHK(&so->so_rcv);
|
||||
sbunlock(&so->so_rcv);
|
||||
error = sbwait(&so->so_rcv);
|
||||
splx(s);
|
||||
@ -898,6 +900,8 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
dontblock:
|
||||
if (uio->uio_td)
|
||||
uio->uio_td->td_proc->p_stats->p_ru.ru_msgrcv++;
|
||||
SBLASTRECORDCHK(&so->so_rcv);
|
||||
SBLASTMBUFCHK(&so->so_rcv);
|
||||
nextrecord = m->m_nextpkt;
|
||||
if (pr->pr_flags & PR_ADDR) {
|
||||
KASSERT(m->m_type == MT_SONAME,
|
||||
@ -939,12 +943,32 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
}
|
||||
}
|
||||
if (m) {
|
||||
if ((flags & MSG_PEEK) == 0)
|
||||
if ((flags & MSG_PEEK) == 0) {
|
||||
m->m_nextpkt = nextrecord;
|
||||
/*
|
||||
* If nextrecord == NULL (this is a single chain),
|
||||
* then sb_lastrecord may not be valid here if m
|
||||
* was changed earlier.
|
||||
*/
|
||||
if (nextrecord == NULL) {
|
||||
KASSERT(so->so_rcv.sb_mb == m,
|
||||
("receive tailq 1"));
|
||||
so->so_rcv.sb_lastrecord = m;
|
||||
}
|
||||
}
|
||||
type = m->m_type;
|
||||
if (type == MT_OOBDATA)
|
||||
flags |= MSG_OOB;
|
||||
} else {
|
||||
if ((flags & MSG_PEEK) == 0) {
|
||||
KASSERT(so->so_rcv.sb_mb == m,("receive tailq 2"));
|
||||
so->so_rcv.sb_mb = nextrecord;
|
||||
SB_EMPTY_FIXUP(&so->so_rcv);
|
||||
}
|
||||
}
|
||||
SBLASTRECORDCHK(&so->so_rcv);
|
||||
SBLASTMBUFCHK(&so->so_rcv);
|
||||
|
||||
moff = 0;
|
||||
offset = 0;
|
||||
while (m && uio->uio_resid > 0 && error == 0) {
|
||||
@ -971,6 +995,8 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
* block interrupts again.
|
||||
*/
|
||||
if (mp == 0) {
|
||||
SBLASTRECORDCHK(&so->so_rcv);
|
||||
SBLASTMBUFCHK(&so->so_rcv);
|
||||
splx(s);
|
||||
#ifdef ZERO_COPY_SOCKETS
|
||||
if (so_zero_copy_receive) {
|
||||
@ -1018,8 +1044,16 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
so->so_rcv.sb_mb = m_free(m);
|
||||
m = so->so_rcv.sb_mb;
|
||||
}
|
||||
if (m)
|
||||
if (m) {
|
||||
m->m_nextpkt = nextrecord;
|
||||
if (nextrecord == NULL)
|
||||
so->so_rcv.sb_lastrecord = m;
|
||||
} else {
|
||||
so->so_rcv.sb_mb = nextrecord;
|
||||
SB_EMPTY_FIXUP(&so->so_rcv);
|
||||
}
|
||||
SBLASTRECORDCHK(&so->so_rcv);
|
||||
SBLASTMBUFCHK(&so->so_rcv);
|
||||
}
|
||||
} else {
|
||||
if (flags & MSG_PEEK)
|
||||
@ -1064,6 +1098,8 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
*/
|
||||
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
|
||||
SBLASTRECORDCHK(&so->so_rcv);
|
||||
SBLASTMBUFCHK(&so->so_rcv);
|
||||
error = sbwait(&so->so_rcv);
|
||||
if (error) {
|
||||
sbunlock(&so->so_rcv);
|
||||
@ -1082,8 +1118,21 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
(void) sbdroprecord(&so->so_rcv);
|
||||
}
|
||||
if ((flags & MSG_PEEK) == 0) {
|
||||
if (m == 0)
|
||||
if (m == 0) {
|
||||
/*
|
||||
* First part is an inline SB_EMPTY_FIXUP(). Second
|
||||
* part makes sure sb_lastrecord is up-to-date if
|
||||
* there is still data in the socket buffer.
|
||||
*/
|
||||
so->so_rcv.sb_mb = nextrecord;
|
||||
if (so->so_rcv.sb_mb == NULL) {
|
||||
so->so_rcv.sb_mbtail = NULL;
|
||||
so->so_rcv.sb_lastrecord = NULL;
|
||||
} else if (nextrecord->m_nextpkt == NULL)
|
||||
so->so_rcv.sb_lastrecord = nextrecord;
|
||||
}
|
||||
SBLASTRECORDCHK(&so->so_rcv);
|
||||
SBLASTMBUFCHK(&so->so_rcv);
|
||||
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
|
||||
}
|
||||
|
@ -468,6 +468,60 @@ sbrelease(sb, so)
|
||||
* or sbdroprecord() when the data is acknowledged by the peer.
|
||||
*/
|
||||
|
||||
#ifdef SOCKBUF_DEBUG
|
||||
void
|
||||
sblastrecordchk(struct sockbuf *sb, const char *file, int line)
|
||||
{
|
||||
struct mbuf *m = sb->sb_mb;
|
||||
|
||||
while (m && m->m_nextpkt)
|
||||
m = m->m_nextpkt;
|
||||
|
||||
if (m != sb->sb_lastrecord) {
|
||||
printf("%s: sb_mb %p sb_lastrecord %p last %p\n",
|
||||
__func__, sb->sb_mb, sb->sb_lastrecord, m);
|
||||
printf("packet chain:\n");
|
||||
for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt)
|
||||
printf("\t%p\n", m);
|
||||
panic("%s from %s:%u", __func__, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sblastmbufchk(struct sockbuf *sb, const char *file, int line)
|
||||
{
|
||||
struct mbuf *m = sb->sb_mb;
|
||||
struct mbuf *n;
|
||||
|
||||
while (m && m->m_nextpkt)
|
||||
m = m->m_nextpkt;
|
||||
|
||||
while (m && m->m_next)
|
||||
m = m->m_next;
|
||||
|
||||
if (m != sb->sb_mbtail) {
|
||||
printf("%s: sb_mb %p sb_mbtail %p last %p\n",
|
||||
__func__, sb->sb_mb, sb->sb_mbtail, m);
|
||||
printf("packet tree:\n");
|
||||
for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) {
|
||||
printf("\t");
|
||||
for (n = m; n != NULL; n = n->m_next)
|
||||
printf("%p ", n);
|
||||
printf("\n");
|
||||
}
|
||||
panic("%s from %s:%u", __func__, file, line);
|
||||
}
|
||||
}
|
||||
#endif /* SOCKBUF_DEBUG */
|
||||
|
||||
#define SBLINKRECORD(sb, m0) do { \
|
||||
if ((sb)->sb_lastrecord != NULL) \
|
||||
(sb)->sb_lastrecord->m_nextpkt = (m0); \
|
||||
else \
|
||||
(sb)->sb_mb = (m0); \
|
||||
(sb)->sb_lastrecord = (m0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* Append mbuf chain m to the last record in the
|
||||
* socket buffer sb. The additional space associated
|
||||
@ -483,6 +537,7 @@ sbappend(sb, m)
|
||||
|
||||
if (m == 0)
|
||||
return;
|
||||
SBLASTRECORDCHK(sb);
|
||||
n = sb->sb_mb;
|
||||
if (n) {
|
||||
while (n->m_nextpkt)
|
||||
@ -493,8 +548,53 @@ sbappend(sb, m)
|
||||
return;
|
||||
}
|
||||
} while (n->m_next && (n = n->m_next));
|
||||
} else {
|
||||
/*
|
||||
* XXX Would like to simply use sb_mbtail here, but
|
||||
* XXX I need to verify that I won't miss an EOR that
|
||||
* XXX way.
|
||||
*/
|
||||
if ((n = sb->sb_lastrecord) != NULL) {
|
||||
do {
|
||||
if (n->m_flags & M_EOR) {
|
||||
sbappendrecord(sb, m); /* XXXXXX!!!! */
|
||||
return;
|
||||
}
|
||||
} while (n->m_next && (n = n->m_next));
|
||||
} else {
|
||||
/*
|
||||
* If this is the first record in the socket buffer,
|
||||
* it's also the last record.
|
||||
*/
|
||||
sb->sb_lastrecord = m;
|
||||
}
|
||||
}
|
||||
sbcompress(sb, m, n);
|
||||
SBLASTRECORDCHK(sb);
|
||||
}
|
||||
|
||||
/*
|
||||
* This version of sbappend() should only be used when the caller
|
||||
* absolutely knows that there will never be more than one record
|
||||
* in the socket buffer, that is, a stream protocol (such as TCP).
|
||||
*/
|
||||
void
|
||||
sbappendstream(struct sockbuf *sb, struct mbuf *m)
|
||||
{
|
||||
|
||||
KASSERT(m->m_nextpkt == NULL,("sbappendstream 0"));
|
||||
KASSERT(sb->sb_mb == sb->sb_lastrecord,("sbappendstream 1"));
|
||||
|
||||
SBLASTMBUFCHK(sb);
|
||||
|
||||
#ifdef MBUFTRACE
|
||||
m_claim(m, sb->sb_mowner);
|
||||
#endif
|
||||
|
||||
sbcompress(sb, m, sb->sb_mbtail);
|
||||
|
||||
sb->sb_lastrecord = sb->sb_mb;
|
||||
SBLASTRECORDCHK(sb);
|
||||
}
|
||||
|
||||
#ifdef SOCKBUF_DEBUG
|
||||
@ -516,7 +616,7 @@ sbcheck(sb)
|
||||
}
|
||||
}
|
||||
if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
|
||||
printf("cc %ld != %ld || mbcnt %ld != %ld\n", len, sb->sb_cc,
|
||||
printf("cc %ld != %u || mbcnt %ld != %u\n", len, sb->sb_cc,
|
||||
mbcnt, sb->sb_mbcnt);
|
||||
panic("sbcheck");
|
||||
}
|
||||
@ -545,6 +645,8 @@ sbappendrecord(sb, m0)
|
||||
* Note this permits zero length records.
|
||||
*/
|
||||
sballoc(sb, m0);
|
||||
SBLASTRECORDCHK(sb);
|
||||
SBLINKRECORD(sb, m0);
|
||||
if (m)
|
||||
m->m_nextpkt = m0;
|
||||
else
|
||||
@ -616,7 +718,7 @@ sbappendaddr(sb, asa, m0, control)
|
||||
struct sockaddr *asa;
|
||||
struct mbuf *m0, *control;
|
||||
{
|
||||
struct mbuf *m, *n;
|
||||
struct mbuf *m, *n, *nlast;
|
||||
int space = asa->sa_len;
|
||||
|
||||
if (m0 && (m0->m_flags & M_PKTHDR) == 0)
|
||||
@ -640,15 +742,16 @@ sbappendaddr(sb, asa, m0, control)
|
||||
else
|
||||
control = m0;
|
||||
m->m_next = control;
|
||||
for (n = m; n; n = n->m_next)
|
||||
for (n = m; n->m_next != NULL; n = n->m_next)
|
||||
sballoc(sb, n);
|
||||
n = sb->sb_mb;
|
||||
if (n) {
|
||||
while (n->m_nextpkt)
|
||||
n = n->m_nextpkt;
|
||||
n->m_nextpkt = m;
|
||||
} else
|
||||
sb->sb_mb = m;
|
||||
sballoc(sb, n);
|
||||
nlast = n;
|
||||
SBLINKRECORD(sb, m);
|
||||
|
||||
sb->sb_mbtail = nlast;
|
||||
SBLASTMBUFCHK(sb);
|
||||
|
||||
SBLASTRECORDCHK(sb);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -657,7 +760,7 @@ sbappendcontrol(sb, m0, control)
|
||||
struct sockbuf *sb;
|
||||
struct mbuf *control, *m0;
|
||||
{
|
||||
struct mbuf *m, *n;
|
||||
struct mbuf *m, *n, *mlast;
|
||||
int space;
|
||||
|
||||
if (control == 0)
|
||||
@ -666,15 +769,19 @@ sbappendcontrol(sb, m0, control)
|
||||
if (space > sbspace(sb))
|
||||
return (0);
|
||||
n->m_next = m0; /* concatenate data to control */
|
||||
for (m = control; m; m = m->m_next)
|
||||
|
||||
SBLASTRECORDCHK(sb);
|
||||
|
||||
for (m = control; m->m_next; m = m->m_next)
|
||||
sballoc(sb, m);
|
||||
n = sb->sb_mb;
|
||||
if (n) {
|
||||
while (n->m_nextpkt)
|
||||
n = n->m_nextpkt;
|
||||
n->m_nextpkt = control;
|
||||
} else
|
||||
sb->sb_mb = control;
|
||||
sballoc(sb, m);
|
||||
mlast = m;
|
||||
SBLINKRECORD(sb, control);
|
||||
|
||||
sb->sb_mbtail = mlast;
|
||||
SBLASTMBUFCHK(sb);
|
||||
|
||||
SBLASTRECORDCHK(sb);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -697,6 +804,8 @@ sbcompress(sb, m, n)
|
||||
(eor == 0 ||
|
||||
(((o = m->m_next) || (o = n)) &&
|
||||
o->m_type == m->m_type))) {
|
||||
if (sb->sb_lastrecord == m)
|
||||
sb->sb_lastrecord = m->m_next;
|
||||
m = m_free(m);
|
||||
continue;
|
||||
}
|
||||
@ -720,6 +829,7 @@ sbcompress(sb, m, n)
|
||||
n->m_next = m;
|
||||
else
|
||||
sb->sb_mb = m;
|
||||
sb->sb_mbtail = m;
|
||||
sballoc(sb, m);
|
||||
n = m;
|
||||
m->m_flags &= ~M_EOR;
|
||||
@ -732,6 +842,7 @@ sbcompress(sb, m, n)
|
||||
else
|
||||
printf("semi-panic: sbcompress\n");
|
||||
}
|
||||
SBLASTMBUFCHK(sb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -800,6 +911,18 @@ sbdrop(sb, len)
|
||||
m->m_nextpkt = next;
|
||||
} else
|
||||
sb->sb_mb = next;
|
||||
/*
|
||||
* First part is an inline SB_EMPTY_FIXUP(). Second part
|
||||
* makes sure sb_lastrecord is up-to-date if we dropped
|
||||
* part of the last record.
|
||||
*/
|
||||
m = sb->sb_mb;
|
||||
if (m == NULL) {
|
||||
sb->sb_mbtail = NULL;
|
||||
sb->sb_lastrecord = NULL;
|
||||
} else if (m->m_nextpkt == NULL) {
|
||||
sb->sb_lastrecord = m;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -820,6 +943,7 @@ sbdroprecord(sb)
|
||||
m = m_free(m);
|
||||
} while (m);
|
||||
}
|
||||
SB_EMPTY_FIXUP(sb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -296,7 +296,7 @@ tcp_reass(tp, th, tlenp, m)
|
||||
if (so->so_state & SS_CANTRCVMORE)
|
||||
m_freem(q->tqe_m);
|
||||
else
|
||||
sbappend(&so->so_rcv, q->tqe_m);
|
||||
sbappendstream(&so->so_rcv, q->tqe_m);
|
||||
FREE(q, M_TSEGQ);
|
||||
q = nq;
|
||||
} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
|
||||
@ -1124,7 +1124,7 @@ tcp_input(m, off0)
|
||||
m_freem(m);
|
||||
} else {
|
||||
m_adj(m, drop_hdrlen); /* delayed header drop */
|
||||
sbappend(&so->so_rcv, m);
|
||||
sbappendstream(&so->so_rcv, m);
|
||||
}
|
||||
sorwakeup(so);
|
||||
if (DELAY_ACK(tp)) {
|
||||
@ -2178,7 +2178,7 @@ tcp_input(m, off0)
|
||||
if (so->so_state & SS_CANTRCVMORE)
|
||||
m_freem(m);
|
||||
else
|
||||
sbappend(&so->so_rcv, m);
|
||||
sbappendstream(&so->so_rcv, m);
|
||||
sorwakeup(so);
|
||||
} else {
|
||||
thflags = tcp_reass(tp, th, &tlen, m);
|
||||
|
@ -296,7 +296,7 @@ tcp_reass(tp, th, tlenp, m)
|
||||
if (so->so_state & SS_CANTRCVMORE)
|
||||
m_freem(q->tqe_m);
|
||||
else
|
||||
sbappend(&so->so_rcv, q->tqe_m);
|
||||
sbappendstream(&so->so_rcv, q->tqe_m);
|
||||
FREE(q, M_TSEGQ);
|
||||
q = nq;
|
||||
} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
|
||||
@ -1124,7 +1124,7 @@ tcp_input(m, off0)
|
||||
m_freem(m);
|
||||
} else {
|
||||
m_adj(m, drop_hdrlen); /* delayed header drop */
|
||||
sbappend(&so->so_rcv, m);
|
||||
sbappendstream(&so->so_rcv, m);
|
||||
}
|
||||
sorwakeup(so);
|
||||
if (DELAY_ACK(tp)) {
|
||||
@ -2178,7 +2178,7 @@ tcp_input(m, off0)
|
||||
if (so->so_state & SS_CANTRCVMORE)
|
||||
m_freem(m);
|
||||
else
|
||||
sbappend(&so->so_rcv, m);
|
||||
sbappendstream(&so->so_rcv, m);
|
||||
sorwakeup(so);
|
||||
} else {
|
||||
thflags = tcp_reass(tp, th, &tlen, m);
|
||||
|
@ -685,7 +685,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
|
||||
m_freem(control); /* empty control, just free it */
|
||||
}
|
||||
if (!(flags & PRUS_OOB)) {
|
||||
sbappend(&so->so_snd, m);
|
||||
sbappendstream(&so->so_snd, m);
|
||||
if (nam && tp->t_state < TCPS_SYN_SENT) {
|
||||
/*
|
||||
* Do implied connect if not yet connected,
|
||||
@ -734,7 +734,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
|
||||
* of data past the urgent section.
|
||||
* Otherwise, snd_up should be one lower.
|
||||
*/
|
||||
sbappend(&so->so_snd, m);
|
||||
sbappendstream(&so->so_snd, m);
|
||||
if (nam && tp->t_state < TCPS_SYN_SENT) {
|
||||
/*
|
||||
* Do implied connect if not yet connected,
|
||||
|
@ -102,6 +102,9 @@ struct socket {
|
||||
struct selinfo sb_sel; /* process selecting read/write */
|
||||
#define sb_startzero sb_mb
|
||||
struct mbuf *sb_mb; /* the mbuf chain */
|
||||
struct mbuf *sb_mbtail; /* the last mbuf in the chain */
|
||||
struct mbuf *sb_lastrecord; /* first mbuf of last record in
|
||||
* socket buffer */
|
||||
u_int sb_cc; /* actual chars in buffer */
|
||||
u_int sb_hiwat; /* max actual char count */
|
||||
u_int sb_mbcnt; /* chars of mbufs used */
|
||||
@ -137,6 +140,13 @@ struct socket {
|
||||
} *so_accf;
|
||||
};
|
||||
|
||||
#define SB_EMPTY_FIXUP(sb) do { \
|
||||
if ((sb)->sb_mb == NULL) { \
|
||||
(sb)->sb_mbtail = NULL; \
|
||||
(sb)->sb_lastrecord = NULL; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* Socket state bits.
|
||||
*/
|
||||
@ -353,6 +363,7 @@ struct sockaddr *dup_sockaddr(struct sockaddr *sa, int canwait);
|
||||
int sockargs(struct mbuf **mp, caddr_t buf, int buflen, int type);
|
||||
int getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len);
|
||||
void sbappend(struct sockbuf *sb, struct mbuf *m);
|
||||
void sbappendstream(struct sockbuf *sb, struct mbuf *m);
|
||||
int sbappendaddr(struct sockbuf *sb, struct sockaddr *asa,
|
||||
struct mbuf *m0, struct mbuf *control);
|
||||
int sbappendcontrol(struct sockbuf *sb, struct mbuf *m0,
|
||||
@ -422,6 +433,17 @@ int soshutdown(struct socket *so, int how);
|
||||
void sotoxsocket(struct socket *so, struct xsocket *xso);
|
||||
void sowakeup(struct socket *so, struct sockbuf *sb);
|
||||
|
||||
#ifdef SOCKBUF_DEBUG
|
||||
void sblastrecordchk(struct sockbuf *, const char *, int);
|
||||
#define SBLASTRECORDCHK(sb) sblastrecordchk((sb), __FILE__, __LINE__)
|
||||
|
||||
void sblastmbufchk(struct sockbuf *, const char *, int);
|
||||
#define SBLASTMBUFCHK(sb) sblastmbufchk((sb), __FILE__, __LINE__)
|
||||
#else
|
||||
#define SBLASTRECORDCHK(sb) /* nothing */
|
||||
#define SBLASTMBUFCHK(sb) /* nothing */
|
||||
#endif /* SOCKBUF_DEBUG */
|
||||
|
||||
/*
|
||||
* Accept filter functions (duh).
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user