Receive packets in a small pieces (NB_SORECEIVE_CHUNK), so TCP slowstart will
get its ACKs faster. From Darwin via FreeBSD. XXX I don't have any idea if this is useful or reasonable, but it looks XXX sane and the code works. "Remove if found nonuseful."
This commit is contained in:
parent
1ebbd9b463
commit
78b50cb215
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: smb_trantcp.c,v 1.10 2003/02/26 19:31:33 jdolecek Exp $ */
|
||||
/* $NetBSD: smb_trantcp.c,v 1.11 2003/03/24 18:08:51 jdolecek Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2001 Boris Popov
|
||||
@ -31,11 +31,11 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* FreeBSD: src/sys/netsmb/smb_trantcp.c,v 1.4 2001/12/02 08:47:29 bp Exp
|
||||
* FreeBSD: src/sys/netsmb/smb_trantcp.c,v 1.17 2003/02/19 05:47:38 imp Exp
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: smb_trantcp.c,v 1.10 2003/02/26 19:31:33 jdolecek Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: smb_trantcp.c,v 1.11 2003/03/24 18:08:51 jdolecek Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -444,9 +444,9 @@ nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp,
|
||||
{
|
||||
struct socket *so = nbp->nbp_tso;
|
||||
struct uio auio;
|
||||
struct mbuf *m;
|
||||
struct mbuf *m, *tm, *im;
|
||||
u_int8_t rpcode;
|
||||
int len;
|
||||
int len, resid;
|
||||
int error, rcvflg;
|
||||
|
||||
if (so == NULL)
|
||||
@ -454,8 +454,12 @@ nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp,
|
||||
|
||||
if (mpp)
|
||||
*mpp = NULL;
|
||||
m = NULL;
|
||||
for(;;) {
|
||||
m = NULL;
|
||||
/*
|
||||
* Poll for a response header.
|
||||
* If we don't have one waiting, return.
|
||||
*/
|
||||
error = nbssn_recvhdr(nbp, &len, &rpcode, MSG_DONTWAIT, p);
|
||||
if (so->so_state &
|
||||
(SS_ISDISCONNECTING | SS_ISDISCONNECTED | SS_CANTRCVMORE)) {
|
||||
@ -467,39 +471,82 @@ nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp,
|
||||
return error;
|
||||
if (len == 0 && nbp->nbp_state != NBST_SESSION)
|
||||
break;
|
||||
/* no data, try again */
|
||||
if (rpcode == NB_SSN_KEEPALIVE)
|
||||
continue;
|
||||
bzero(&auio, sizeof(auio));
|
||||
auio.uio_resid = len;
|
||||
auio.uio_procp = p;
|
||||
do {
|
||||
|
||||
/*
|
||||
* Loop, blocking, for data following the response header.
|
||||
*
|
||||
* Note that we can't simply block here with MSG_WAITALL for the
|
||||
* entire response size, as it may be larger than the TCP
|
||||
* slow-start window that the sender employs. This will result
|
||||
* in the sender stalling until the delayed ACK is sent, then
|
||||
* resuming slow-start, resulting in very poor performance.
|
||||
*
|
||||
* Instead, we never request more than NB_SORECEIVE_CHUNK
|
||||
* bytes at a time, resulting in an ack being pushed by
|
||||
* the TCP code at the completion of each call.
|
||||
*/
|
||||
resid = len;
|
||||
while (resid > 0) {
|
||||
tm = NULL;
|
||||
rcvflg = MSG_WAITALL;
|
||||
#ifndef __NetBSD__
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive
|
||||
(so, (struct sockaddr **)NULL,
|
||||
&auio, &m, (struct mbuf **)NULL, &rcvflg);
|
||||
bzero(&auio, sizeof(auio));
|
||||
auio.uio_resid = min(resid, NB_SORECEIVE_CHUNK);
|
||||
auio.uio_procp = p;
|
||||
resid -= auio.uio_resid;
|
||||
/*
|
||||
* Spin until we have collected everything in
|
||||
* this chunk.
|
||||
*/
|
||||
do {
|
||||
rcvflg = MSG_WAITALL;
|
||||
#ifdef __NetBSD__
|
||||
error = (*so->so_receive)(so, (struct mbuf **)0,
|
||||
&auio, &tm, (struct mbuf **)NULL,
|
||||
&rcvflg);
|
||||
#else
|
||||
error = (*so->so_receive)(so, (struct mbuf **)0,
|
||||
&auio, &m,
|
||||
(struct mbuf **)NULL,
|
||||
&rcvflg);
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive
|
||||
(so, (struct sockaddr **)NULL,
|
||||
&auio, &tm, (struct mbuf **)NULL, &rcvflg);
|
||||
#endif
|
||||
} while (error == EWOULDBLOCK || error == EINTR ||
|
||||
} while (error == EWOULDBLOCK || error == EINTR ||
|
||||
error == ERESTART);
|
||||
if (error)
|
||||
break;
|
||||
if (auio.uio_resid > 0) {
|
||||
SMBERROR("packet is shorter than expected\n");
|
||||
error = EPIPE;
|
||||
break;
|
||||
if (error)
|
||||
goto out;
|
||||
/* short return guarantees unhappiness */
|
||||
if (auio.uio_resid > 0) {
|
||||
SMBERROR("packet is shorter than expected\n");
|
||||
error = EPIPE;
|
||||
goto out;
|
||||
}
|
||||
/* append received chunk to previous chunk(s) */
|
||||
if (m == NULL) {
|
||||
m = tm;
|
||||
} else {
|
||||
/*
|
||||
* Just glue the new chain on the end.
|
||||
* Consumer will pullup as required.
|
||||
*/
|
||||
for (im = m; im->m_next != NULL; im = im->m_next)
|
||||
;
|
||||
im->m_next = tm;
|
||||
}
|
||||
}
|
||||
/* got a session/message packet? */
|
||||
if (nbp->nbp_state == NBST_SESSION &&
|
||||
rpcode == NB_SSN_MESSAGE)
|
||||
break;
|
||||
/* drop packet and try for another */
|
||||
NBDEBUG("non-session packet %x\n", rpcode);
|
||||
if (m)
|
||||
if (m) {
|
||||
m_freem(m);
|
||||
m = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (error) {
|
||||
if (m)
|
||||
m_freem(m);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: smb_trantcp.h,v 1.3 2003/02/21 20:12:05 jdolecek Exp $ */
|
||||
/* $NetBSD: smb_trantcp.h,v 1.4 2003/03/24 18:08:51 jdolecek Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2001, Boris Popov
|
||||
@ -31,7 +31,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* FreeBSD: src/sys/netsmb/smb_trantcp.h,v 1.2 2001/12/10 08:09:49 obrien Exp
|
||||
* FreeBSD: src/sys/netsmb/smb_trantcp.h,v 1.3 2002/09/18 07:38:10 bp Exp
|
||||
*/
|
||||
#ifndef _NETSMB_SMB_TRANTCP_H_
|
||||
#define _NETSMB_SMB_TRANTCP_H_
|
||||
@ -84,6 +84,14 @@ struct nbpcb {
|
||||
#define NB_SNDTIMEO (5 * hz)
|
||||
#define NB_RCVTIMEO (5 * hz)
|
||||
|
||||
/*
|
||||
* TCP slowstart presents a problem in conjunction with large
|
||||
* reads. To ensure a steady stream of ACKs while reading using
|
||||
* large transaction sizes, we call soreceive() with a smaller
|
||||
* buffer size. See nbssn_recv().
|
||||
*/
|
||||
#define NB_SORECEIVE_CHUNK (8 * 1024)
|
||||
|
||||
extern struct smb_tran_desc smb_tran_nbtcp_desc;
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
Loading…
Reference in New Issue
Block a user