2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

3137. [func] Improve hardware scalability by allowing multiple

worker threads to process incoming UDP packets.
			This can significantly increase query throughput
			on some systems.  [RT #22992]
This commit is contained in:
Evan Hunt
2011-07-28 04:04:37 +00:00
parent 8181aa6228
commit f07b2fccaf
17 changed files with 738 additions and 223 deletions

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.c,v 1.87 2010/12/09 06:08:05 marka Exp $ */
/* $Id: socket.c,v 1.88 2011/07/28 04:04:37 each Exp $ */
/* This code uses functions which are only available on Server 2003 and
* higher, and Windows XP and higher.
@@ -265,7 +265,8 @@ struct isc_socket {
unsigned int listener : 1, /* listener socket */
connected : 1,
pending_connect : 1, /* connect pending */
bound : 1; /* bound to local addr */
bound : 1, /* bound to local addr */
dupped : 1; /* created by isc_socket_dup() */
unsigned int pending_iocp; /* Should equal the counters below. Debug. */
unsigned int pending_recv; /* Number of outstanding recv() calls. */
unsigned int pending_send; /* Number of outstanding send() calls. */
@@ -351,6 +352,10 @@ enum {
#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER)
#define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
isc_sockettype_t type,
isc_socket_t **socketp,
isc_socket_t *dup_socket);
static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
static void maybe_free_socket(isc_socket_t **, int);
static void free_socket(isc_socket_t **, int);
@@ -1461,6 +1466,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
sock->connected = 0;
sock->pending_connect = 0;
sock->bound = 0;
sock->dupped = 0;
memset(sock->name, 0, sizeof(sock->name)); // zero the name field
_set_state(sock, SOCK_INITIALIZED);
@@ -1623,9 +1629,10 @@ free_socket(isc_socket_t **sockp, int lineno) {
* called with 'arg' as the arg value. The new socket is returned
* in 'socketp'.
*/
isc_result_t
isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
isc_socket_t **socketp) {
static isc_result_t
socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
isc_socket_t **socketp, isc_socket_t *dup_socket)
{
isc_socket_t *sock = NULL;
isc_result_t result;
#if defined(USE_CMSG)
@@ -1647,27 +1654,35 @@ isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
return (result);
sock->pf = pf;
switch (type) {
case isc_sockettype_udp:
sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
if (sock->fd != INVALID_SOCKET) {
result = connection_reset_fix(sock->fd);
if (result != ISC_R_SUCCESS) {
socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
"closed %d %d %d con_reset_fix_failed",
sock->pending_recv, sock->pending_send,
sock->references);
closesocket(sock->fd);
_set_state(sock, SOCK_CLOSED);
sock->fd = INVALID_SOCKET;
free_socket(&sock, __LINE__);
return (result);
if (dup_socket == NULL) {
switch (type) {
case isc_sockettype_udp:
sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
if (sock->fd != INVALID_SOCKET) {
result = connection_reset_fix(sock->fd);
if (result != ISC_R_SUCCESS) {
socket_log(__LINE__, sock,
NULL, EVENT, NULL, 0, 0,
"closed %d %d %d "
"con_reset_fix_failed",
sock->pending_recv,
sock->pending_send,
sock->references);
closesocket(sock->fd);
_set_state(sock, SOCK_CLOSED);
sock->fd = INVALID_SOCKET;
free_socket(&sock, __LINE__);
return (result);
}
}
break;
case isc_sockettype_tcp:
sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
break;
}
break;
case isc_sockettype_tcp:
sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
break;
} else {
sock->fd = dup(dup_socket->fd);
sock->dupped = 1;
}
if (sock->fd == INVALID_SOCKET) {
@@ -1786,12 +1801,29 @@ isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
InterlockedIncrement(&manager->totalSockets);
UNLOCK(&manager->lock);
socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_CREATED, "created %u type %u", sock->fd, type);
socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat,
ISC_MSGSET_SOCKET, ISC_MSG_CREATED,
"created %u type %u", sock->fd, type);
return (ISC_R_SUCCESS);
}
isc_result_t
isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
isc_socket_t **socketp)
{
return (socket_create(manager, pf, type, socketp, NULL));
}
isc_result_t
isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
REQUIRE(VALID_SOCKET(sock));
REQUIRE(socketp != NULL && *socketp == NULL);
return (socket_create(sock->manager, sock->pf, sock->type,
socketp, sock));
}
isc_result_t
isc_socket_open(isc_socket_t *sock) {
REQUIRE(VALID_SOCKET(sock));