the default socket rcvbuf for L2CAP is only 4Kbytes which is only

2 and a bit ethernet packets. Check and increase SO_RCVBUF on startup
so that we have buffers for 10 complete packets, should solve a
reported problem with overruns at higher connection speeds (our L2CAP
does not have any flow control).

(the default can still be adjusted upwards using sysctl)
This commit is contained in:
plunky 2011-02-08 21:59:50 +00:00
parent bc0aea6bfb
commit 9119e9c88f
2 changed files with 33 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: client.c,v 1.4 2009/05/12 21:50:38 plunky Exp $ */ /* $NetBSD: client.c,v 1.5 2011/02/08 21:59:50 plunky Exp $ */
/*- /*-
* Copyright (c) 2008-2009 Iain Hibbert * Copyright (c) 2008-2009 Iain Hibbert
@ -26,7 +26,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: client.c,v 1.4 2009/05/12 21:50:38 plunky Exp $"); __RCSID("$NetBSD: client.c,v 1.5 2011/02/08 21:59:50 plunky Exp $");
#include <bluetooth.h> #include <bluetooth.h>
#include <errno.h> #include <errno.h>
@ -45,7 +45,7 @@ client_init(void)
struct sockaddr_bt sa; struct sockaddr_bt sa;
channel_t *chan; channel_t *chan;
socklen_t len; socklen_t len;
int fd; int fd, bufsize;
uint16_t mru, mtu; uint16_t mru, mtu;
if (bdaddr_any(&remote_bdaddr)) if (bdaddr_any(&remote_bdaddr))
@ -102,6 +102,19 @@ client_init(void)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
len = sizeof(bufsize);
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsize, &len) == -1) {
log_err("Could not read SO_RCVBUF");
exit(EXIT_FAILURE);
}
if (bufsize < 10 * mru) {
bufsize = 10 * mru;
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsize,
sizeof(bufsize)) == -1)
log_info("Could not increase SO_RCVBUF (from %d)",
bufsize);
}
len = sizeof(mtu); len = sizeof(mtu);
if (getsockopt(fd, BTPROTO_L2CAP, SO_L2CAP_OMTU, &mtu, &len) == -1) { if (getsockopt(fd, BTPROTO_L2CAP, SO_L2CAP_OMTU, &mtu, &len) == -1) {
log_err("Could not get L2CAP OMTU: %m"); log_err("Could not get L2CAP OMTU: %m");

View File

@ -1,4 +1,4 @@
/* $NetBSD: server.c,v 1.6 2009/10/25 19:28:45 plunky Exp $ */ /* $NetBSD: server.c,v 1.7 2011/02/08 21:59:50 plunky Exp $ */
/*- /*-
* Copyright (c) 2008-2009 Iain Hibbert * Copyright (c) 2008-2009 Iain Hibbert
@ -26,7 +26,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: server.c,v 1.6 2009/10/25 19:28:45 plunky Exp $"); __RCSID("$NetBSD: server.c,v 1.7 2011/02/08 21:59:50 plunky Exp $");
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -134,7 +134,7 @@ server_read(int s, short ev, void *arg)
struct sockaddr_bt ra, la; struct sockaddr_bt ra, la;
channel_t *chan; channel_t *chan;
socklen_t len; socklen_t len;
int fd, n; int fd, n, bufsize;
uint16_t mru, mtu; uint16_t mru, mtu;
assert(server_count < server_limit); assert(server_count < server_limit);
@ -163,6 +163,20 @@ server_read(int s, short ev, void *arg)
return; return;
} }
len = sizeof(bufsize);
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsize, &len) == -1) {
log_err("Could not read SO_RCVBUF");
close(fd);
return;
}
if (bufsize < 10 * mru) {
bufsize = 10 * mru;
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsize,
sizeof(bufsize)) == -1)
log_info("Could not increase SO_RCVBUF (from %d)",
bufsize);
}
len = sizeof(mtu); len = sizeof(mtu);
if (getsockopt(fd, BTPROTO_L2CAP, SO_L2CAP_OMTU, &mtu, &len) == -1) { if (getsockopt(fd, BTPROTO_L2CAP, SO_L2CAP_OMTU, &mtu, &len) == -1) {
log_err("Could not get L2CAP OMTU: %m"); log_err("Could not get L2CAP OMTU: %m");