Compare commits
54
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c3af708ef | ||
|
|
db6e1379ca | ||
|
|
c7b5c0d9ba | ||
|
|
be27968e24 | ||
|
|
e5bda0d2e8 | ||
|
|
19c11103f0 | ||
|
|
1cf25df406 | ||
|
|
b0c1765501 | ||
|
|
1b10390863 | ||
|
|
661b15f25b | ||
|
|
e8dc021560 | ||
|
|
7c806002c3 | ||
|
|
cf367bd64f | ||
|
|
c9e6c59bc2 | ||
|
|
96ff385777 | ||
|
|
36bc9ac28b | ||
|
|
0b517735f2 | ||
|
|
3edde4d190 | ||
|
|
918af04b9d | ||
|
|
8279b866bc | ||
|
|
ac88ecbbaa | ||
|
|
bb1bd0bcac | ||
|
|
d1b608e7a2 | ||
|
|
6d69556eea | ||
|
|
a65d7597a9 | ||
|
|
cc0b84e84b | ||
|
|
55ce821070 | ||
|
|
6c4447015d | ||
|
|
0209c9f9ac | ||
|
|
56d8a6060b | ||
|
|
2a82f35029 | ||
|
|
14a852b86d | ||
|
|
30675428d8 | ||
|
|
627bf906ab | ||
|
|
16dd6d8068 | ||
|
|
46fe61d359 | ||
|
|
9fda4a4cbf | ||
|
|
e80ac06ed4 | ||
|
|
aaa13532c2 | ||
|
|
91d5c3313c | ||
|
|
abc7b247e5 | ||
|
|
a1b6eae847 | ||
|
|
efc2a21590 | ||
|
|
0a21285b11 | ||
|
|
2985bcd7ef | ||
|
|
caf309a80f | ||
|
|
85a3cc6ffa | ||
|
|
235c3e8685 | ||
|
|
666b0f7564 | ||
|
|
bcb55107ac | ||
|
|
b5afff59c2 | ||
|
|
79fc0e3f01 | ||
|
|
b21e515e1b | ||
|
|
b42ac28eb1 |
+2
-2
@@ -1344,7 +1344,7 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
|
||||
break;
|
||||
}
|
||||
if (isc_sockaddr_getport(&sa) == 0) {
|
||||
attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
|
||||
// attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
|
||||
maxdispatchbuffers = EXCLBUFFERS;
|
||||
} else {
|
||||
INSIST(obj != NULL);
|
||||
@@ -9544,7 +9544,7 @@ run_server(isc_task_t *task, isc_event_t *event) {
|
||||
named_g_nm,
|
||||
named_g_dispatchmgr,
|
||||
server->task, named_g_udpdisp, geoip,
|
||||
&server->interfacemgr),
|
||||
named_g_cpus, &server->interfacemgr),
|
||||
"creating interface manager");
|
||||
|
||||
CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive,
|
||||
|
||||
@@ -471,6 +471,9 @@
|
||||
/* Define to 1 if you have the `uv_handle_set_data' function. */
|
||||
#undef HAVE_UV_HANDLE_SET_DATA
|
||||
|
||||
/* Define to 1 if you have the `uv_import' function. */
|
||||
#undef HAVE_UV_IMPORT
|
||||
|
||||
/* Use zlib library */
|
||||
#undef HAVE_ZLIB
|
||||
|
||||
|
||||
@@ -355,6 +355,15 @@ typedef __int64 off_t;
|
||||
/* Define to 1 if you have the `HMAC_CTX_reset' function. */
|
||||
@HAVE_HMAC_CTX_RESET@
|
||||
|
||||
/* Define to 1 if you have the `uv_handle_get_data' function. */
|
||||
@HAVE_UV_HANDLE_GET_DATA@
|
||||
|
||||
/* Define to 1 if you have the `uv_handle_set_data' function. */
|
||||
@HAVE_UV_HANDLE_SET_DATA@
|
||||
|
||||
/* Define to 1 if you have the `uv_import' function. */
|
||||
@HAVE_UV_IMPORT@
|
||||
|
||||
/*
|
||||
* Define to nothing if C supports flexible array members, and to 1 if it does
|
||||
* not. That way, with a declaration like `struct s { int n; double
|
||||
|
||||
@@ -852,6 +852,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -1025,6 +1026,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -1277,6 +1279,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1414,7 +1425,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1567,6 +1578,7 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -4011,7 +4023,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -4057,7 +4069,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -4081,7 +4093,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -4126,7 +4138,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -4150,7 +4162,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -15582,8 +15594,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS -lck $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS -I/usr/include/ck"
|
||||
CC="$PTHREAD_CC"
|
||||
|
||||
for ac_func in pthread_attr_getstacksize pthread_attr_setstacksize
|
||||
@@ -15948,7 +15960,7 @@ LIBS="$LIBS $LIBUV_LIBS"
|
||||
|
||||
# Those functions are only provided in newer versions of libuv, we'll be emulating them
|
||||
# for now
|
||||
for ac_func in uv_handle_get_data uv_handle_set_data
|
||||
for ac_func in uv_handle_get_data uv_handle_set_data uv_import
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
@@ -16070,10 +16082,6 @@ $as_echo "#define USE_PTHREAD_RWLOCK 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
if test "$enable_pthread_rwlock" = "yes" -a "$enable_developer" != "yes"; then :
|
||||
as_fn_error $? "pthread rwlock is not meant used in production and the developer mode must be enabled" "$LINENO" 5
|
||||
fi
|
||||
|
||||
CRYPTO=OpenSSL
|
||||
|
||||
#
|
||||
|
||||
+3
-6
@@ -607,8 +607,8 @@ AC_CHECK_FUNCS(arc4random arc4random_buf arc4random_uniform getrandom)
|
||||
|
||||
AX_PTHREAD
|
||||
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS -lck $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS -I/usr/include/ck"
|
||||
CC="$PTHREAD_CC"
|
||||
|
||||
AC_CHECK_FUNCS([pthread_attr_getstacksize pthread_attr_setstacksize])
|
||||
@@ -667,7 +667,7 @@ LIBS="$LIBS $LIBUV_LIBS"
|
||||
|
||||
# Those functions are only provided in newer versions of libuv, we'll be emulating them
|
||||
# for now
|
||||
AC_CHECK_FUNCS([uv_handle_get_data uv_handle_set_data])
|
||||
AC_CHECK_FUNCS([uv_handle_get_data uv_handle_set_data uv_import])
|
||||
|
||||
#
|
||||
# flockfile is usually provided by pthreads
|
||||
@@ -729,9 +729,6 @@ AS_IF([test "$enable_pthread_rwlock" = "yes"],
|
||||
AC_DEFINE([USE_PTHREAD_RWLOCK],[1],[Define if you want to use pthread rwlock implementation])
|
||||
])
|
||||
|
||||
AS_IF([test "$enable_pthread_rwlock" = "yes" -a "$enable_developer" != "yes"],
|
||||
[AC_MSG_ERROR([pthread rwlock is not meant used in production and the developer mode must be enabled])])
|
||||
|
||||
CRYPTO=OpenSSL
|
||||
|
||||
#
|
||||
|
||||
+2
-2
@@ -77,7 +77,7 @@ DNSOBJS = acl.@O@ adb.@O@ badcache.@O@ byaddr.@O@ \
|
||||
stats.@O@ tcpmsg.@O@ time.@O@ timer.@O@ tkey.@O@ \
|
||||
tsec.@O@ tsig.@O@ ttl.@O@ update.@O@ validator.@O@ \
|
||||
version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ \
|
||||
zoneverify.@O@ zt.@O@
|
||||
zoneverify.@O@ zt.@O@ lowac.@O@
|
||||
PORTDNSOBJS = client.@O@ ecdb.@O@
|
||||
|
||||
OBJS= @DNSTAPOBJS@ ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} \
|
||||
@@ -112,7 +112,7 @@ DNSSRCS = acl.c adb.c badcache. byaddr.c \
|
||||
stats.c tcpmsg.c time.c timer.c tkey.c \
|
||||
tsec.c tsig.c ttl.c update.c validator.c \
|
||||
version.c view.c xfrin.c zone.c zoneverify.c \
|
||||
zonekey.c zt.c ${OTHERSRCS}
|
||||
zonekey.c zt.c ${OTHERSRCS} lowac.c
|
||||
PORTDNSSRCS = client.c ecdb.c
|
||||
|
||||
SRCS = ${DSTSRCS} ${DNSSRCS} \
|
||||
|
||||
+18
-4
@@ -149,6 +149,7 @@ dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) {
|
||||
cctx->mctx = mctx;
|
||||
cctx->count = 0;
|
||||
cctx->allowed = DNS_COMPRESS_ENABLED;
|
||||
cctx->arena_off = 0;
|
||||
|
||||
memset(&cctx->table[0], 0, sizeof(cctx->table));
|
||||
|
||||
@@ -386,6 +387,7 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
|
||||
uint16_t toffset;
|
||||
unsigned char *tmp;
|
||||
isc_region_t r;
|
||||
bool allocated = false;
|
||||
|
||||
REQUIRE(VALID_CCTX(cctx));
|
||||
REQUIRE(dns_name_isabsolute(name));
|
||||
@@ -407,7 +409,13 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
|
||||
start = 0;
|
||||
dns_name_toregion(name, &r);
|
||||
length = r.length;
|
||||
tmp = isc_mem_get(cctx->mctx, length);
|
||||
if (cctx->arena_off + length < DNS_COMPRESS_ARENA_SIZE) {
|
||||
tmp = &cctx->arena[cctx->arena_off];
|
||||
cctx->arena_off += length;
|
||||
} else {
|
||||
allocated = true;
|
||||
tmp = isc_mem_get(cctx->mctx, length);
|
||||
}
|
||||
/*
|
||||
* Copy name data to 'tmp' and make 'r' use 'tmp'.
|
||||
*/
|
||||
@@ -446,8 +454,9 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
|
||||
* 'node->r.base' becomes 'tmp' when start == 0.
|
||||
* Record this by setting 0x8000 so it can be freed later.
|
||||
*/
|
||||
if (start == 0)
|
||||
if (start == 0 && allocated) {
|
||||
toffset |= 0x8000;
|
||||
}
|
||||
node->offset = toffset;
|
||||
dns_name_toregion(&tname, &node->r);
|
||||
dns_name_init(&node->name, NULL);
|
||||
@@ -462,8 +471,13 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
|
||||
count--;
|
||||
}
|
||||
|
||||
if (start == 0)
|
||||
isc_mem_put(cctx->mctx, tmp, length);
|
||||
if (start == 0) {
|
||||
if (!allocated) {
|
||||
cctx->arena_off -= length;
|
||||
} else {
|
||||
isc_mem_put(cctx->mctx, tmp, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -51,7 +51,8 @@ ISC_LANG_BEGINDECLS
|
||||
#define DNS_COMPRESS_TABLEBITS 6
|
||||
#define DNS_COMPRESS_TABLESIZE (1U << DNS_COMPRESS_TABLEBITS)
|
||||
#define DNS_COMPRESS_TABLEMASK (DNS_COMPRESS_TABLESIZE - 1)
|
||||
#define DNS_COMPRESS_INITIALNODES 16
|
||||
#define DNS_COMPRESS_INITIALNODES 24
|
||||
#define DNS_COMPRESS_ARENA_SIZE 640
|
||||
|
||||
typedef struct dns_compressnode dns_compressnode_t;
|
||||
|
||||
@@ -69,6 +70,9 @@ struct dns_compress {
|
||||
int edns; /*%< Edns version or -1. */
|
||||
/*% Global compression table. */
|
||||
dns_compressnode_t *table[DNS_COMPRESS_TABLESIZE];
|
||||
/*% Preallocated arena for names. */
|
||||
unsigned char arena[DNS_COMPRESS_ARENA_SIZE];
|
||||
off_t arena_off;
|
||||
/*% Preallocated nodes for the table. */
|
||||
dns_compressnode_t initialnodes[DNS_COMPRESS_INITIALNODES];
|
||||
uint16_t count; /*%< Number of nodes. */
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <isc/mem.h>
|
||||
#include <dns/name.h>
|
||||
typedef struct dns_lowac_entry dns_lowac_entry_t;
|
||||
typedef struct dns_lowac dns_lowac_t;
|
||||
|
||||
dns_lowac_t*
|
||||
dns_lowac_create(isc_mem_t *mctx);
|
||||
|
||||
void
|
||||
dns_lowac_destroy(dns_lowac_t *lowac);
|
||||
|
||||
isc_result_t
|
||||
dns_lowac_put(dns_lowac_t *lowac, dns_name_t *name, char* packet, int size);
|
||||
|
||||
isc_result_t
|
||||
dns_lowac_get(dns_lowac_t *lowac, dns_name_t *name, unsigned char* blob, int* blobsize, bool tcp);
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
#include <dns/rpz.h>
|
||||
#include <dns/types.h>
|
||||
#include <dns/zt.h>
|
||||
#include <dns/lowac.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
@@ -240,6 +241,7 @@ struct dns_view {
|
||||
void *hooktable; /* ns_hooktable */
|
||||
void (*hooktable_free)(isc_mem_t *, void **);
|
||||
|
||||
dns_lowac_t* lowac;
|
||||
};
|
||||
|
||||
#define DNS_VIEW_MAGIC ISC_MAGIC('V','i','e','w')
|
||||
|
||||
+488
@@ -0,0 +1,488 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/thread.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/time.h>
|
||||
#include <isc/util.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/lowac.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ck_ht.h>
|
||||
#include <ck_fifo.h>
|
||||
#include <ck_queue.h>
|
||||
#define fprintf(...) {}
|
||||
#define MAXIMUM_PKT_SIZE 1024
|
||||
|
||||
#define LENTRY_MAGIC ISC_MAGIC('L', 'o', 'w', 'E')
|
||||
#define VALID_LENTRY(c) ISC_MAGIC_VALID(c, LENTRY_MAGIC)
|
||||
|
||||
struct dns_lowac_entry {
|
||||
unsigned int magic;
|
||||
dns_name_t name;
|
||||
isc_region_t key;
|
||||
uint16_t flags;
|
||||
int64_t expire;
|
||||
ck_ht_hash_t hash;
|
||||
unsigned char *blob;
|
||||
uint32_t blobsize;
|
||||
isc_refcount_t refcount;
|
||||
/*
|
||||
* Set to 'true' when we enqueue this entry on remq.
|
||||
* Nothing serious will happen if we enqueue the entry
|
||||
* on remq multiple times as we're refcounting.
|
||||
* It's not locked in any way as it can only change
|
||||
* from false to true during runtime.
|
||||
*/
|
||||
bool remq_enqueued;
|
||||
bool inht;
|
||||
isc_refcount_t rqrefcount;
|
||||
|
||||
|
||||
|
||||
atomic_int_fast64_t lastusage;
|
||||
};
|
||||
|
||||
|
||||
struct dns_lowac {
|
||||
isc_mem_t * mctx;
|
||||
isc_thread_t thread;
|
||||
int expiry; /* Time after which records expire */
|
||||
|
||||
bool running; /* We're not shut down */
|
||||
bool accepting; /* We're accepting packets into cache */
|
||||
|
||||
ck_ht_t ht; /* Cache hash table */
|
||||
ck_ht_iterator_t htit; /* Hashtable maintenance iterator */
|
||||
|
||||
ck_fifo_mpmc_t inq; /* Packet input queue */
|
||||
ck_fifo_mpmc_t remq; /* Removal queue */
|
||||
|
||||
atomic_int_fast64_t now; /* Epoch time, updated at every loop */
|
||||
int count;
|
||||
|
||||
};
|
||||
|
||||
static void *
|
||||
rthread(void*d);
|
||||
|
||||
static void *
|
||||
ht_malloc(size_t r)
|
||||
{
|
||||
return(malloc(r));
|
||||
}
|
||||
|
||||
static void
|
||||
ht_free(void *p, size_t b, bool r)
|
||||
{
|
||||
(void)b;
|
||||
(void)r;
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ht_hash_wrapper(struct ck_ht_hash *h, const void *key, size_t length,
|
||||
uint64_t seed)
|
||||
{
|
||||
(void)seed;
|
||||
h->value = isc_hash_function(key, length, false);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = ht_malloc,
|
||||
.free = ht_free
|
||||
};
|
||||
|
||||
static void
|
||||
free_entry(dns_lowac_t *lowac, dns_lowac_entry_t *entry) {
|
||||
entry->magic = 0xffffffff;
|
||||
dns_name_free(&entry->name, lowac->mctx);
|
||||
isc_mem_put(lowac->mctx, entry->blob, entry->blobsize);
|
||||
isc_mem_put(lowac->mctx, entry, sizeof(*entry));
|
||||
}
|
||||
|
||||
static bool
|
||||
dequeue_input_entry(dns_lowac_t*lowac) {
|
||||
dns_lowac_entry_t *entry = NULL;
|
||||
ck_fifo_mpmc_entry_t *garbage = NULL;
|
||||
if (ck_fifo_mpmc_dequeue(&lowac->inq, &entry,
|
||||
&garbage) == true) {
|
||||
REQUIRE(VALID_LENTRY(entry));
|
||||
isc_mem_put(lowac->mctx, garbage,
|
||||
sizeof(*garbage));
|
||||
ck_ht_entry_t htentry;
|
||||
ck_ht_entry_t oldhtentry;
|
||||
|
||||
ck_ht_entry_set(&htentry, entry->hash, entry->key.base,
|
||||
entry->key.length, entry);
|
||||
ck_ht_entry_set(&oldhtentry, entry->hash, entry->key.base,
|
||||
entry->key.length, NULL);
|
||||
|
||||
if (ck_ht_get_spmc(&lowac->ht, entry->hash,
|
||||
&oldhtentry) == false) {
|
||||
/* We don't have this entry in hashtable */
|
||||
entry->inht = true;
|
||||
if (ck_ht_put_spmc(&lowac->ht, entry->hash,
|
||||
&htentry) == false) {
|
||||
abort();
|
||||
printf("oddness but might happen\n");
|
||||
/* We can do it safely as it never was in
|
||||
* hashtable */
|
||||
RUNTIME_CHECK(isc_refcount_decrement(&entry->
|
||||
refcount) ==
|
||||
1);
|
||||
free_entry(lowac, entry);
|
||||
} else {
|
||||
fprintf(stderr, "XXXInsert %p %d\n", entry, lowac->count);
|
||||
lowac->count++;
|
||||
}
|
||||
} else {
|
||||
dns_lowac_entry_t *oldentry =
|
||||
ck_ht_entry_value(&oldhtentry);
|
||||
/* Note: set without remove doesn't seem to work
|
||||
* properly */
|
||||
oldentry->inht = false;
|
||||
RUNTIME_CHECK(ck_ht_remove_spmc(&lowac->ht,
|
||||
entry->hash,
|
||||
&oldhtentry) == true);
|
||||
entry->inht = true;
|
||||
RUNTIME_CHECK(ck_ht_set_spmc(&lowac->ht, entry->hash,
|
||||
&htentry) == true);
|
||||
lowac->count++;
|
||||
|
||||
/*
|
||||
* We don't need to increment refcount since we
|
||||
* have not decremented it
|
||||
* when removing from hashtable
|
||||
*/
|
||||
ck_fifo_mpmc_entry_t *qentry =
|
||||
isc_mem_get(lowac->mctx,
|
||||
(sizeof(
|
||||
ck_fifo_mpmc_entry_t)));
|
||||
oldentry->remq_enqueued = true;
|
||||
isc_refcount_increment0(&oldentry->rqrefcount);
|
||||
fprintf(stderr, "XXXenq %p %d\n", oldentry, __LINE__);
|
||||
ck_fifo_mpmc_enqueue(&lowac->remq, qentry,
|
||||
oldentry);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
static int
|
||||
expire_entries(dns_lowac_t *lowac) {
|
||||
int iterated = 0;
|
||||
|
||||
ck_ht_entry_t *htitentry = NULL;
|
||||
bool iterok = ck_ht_next(&lowac->ht, &lowac->htit, &htitentry);
|
||||
if (!iterok) {
|
||||
ck_ht_iterator_init(&lowac->htit);
|
||||
iterok = ck_ht_next(&lowac->ht, &lowac->htit, &htitentry);
|
||||
}
|
||||
while (iterok && htitentry != NULL && iterated < 2048) {
|
||||
dns_lowac_entry_t *entry = ck_ht_entry_value(htitentry);
|
||||
REQUIRE(VALID_LENTRY(entry));
|
||||
if (entry->expire < atomic_load(&lowac->now)) {
|
||||
if (!ck_ht_remove_spmc(&lowac->ht, entry->hash, htitentry)) {
|
||||
abort();
|
||||
/*
|
||||
* Very unlikely, but can happen when we're between generations.
|
||||
* TODO verify that it's ok at all, maybe we're using the iterator wrong?
|
||||
*/
|
||||
isc_refcount_increment0(&entry->refcount);
|
||||
fprintf(stderr, "INCREF %d %p\n", __LINE__, entry);
|
||||
} else {
|
||||
dns_lowac_entry_t *ent2 = ck_ht_entry_value(htitentry);
|
||||
RUNTIME_CHECK(ent2 == entry);
|
||||
}
|
||||
entry->inht = false;
|
||||
/*
|
||||
* We don't need to increment refcount since we have
|
||||
* not decremented it when removing from hashtable.
|
||||
*/
|
||||
ck_fifo_mpmc_entry_t *qentry =
|
||||
isc_mem_get(lowac->mctx,
|
||||
(sizeof(
|
||||
ck_fifo_mpmc_entry_t)));
|
||||
entry->remq_enqueued = true;
|
||||
isc_refcount_increment0(&entry->rqrefcount);
|
||||
fprintf(stderr, "XXXenq %p %d\n", entry, __LINE__);
|
||||
ck_fifo_mpmc_enqueue(&lowac->remq, qentry, entry);
|
||||
}
|
||||
htitentry = NULL;
|
||||
iterok = ck_ht_next(&lowac->ht, &lowac->htit, &htitentry);
|
||||
iterated++;
|
||||
}
|
||||
|
||||
if (!iterok) {
|
||||
ck_ht_iterator_init(&lowac->htit);
|
||||
}
|
||||
return (iterated);
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over remq.
|
||||
* If the entry is in HT - remove it, requeue.
|
||||
* If the entry is not in HT but it is referenced - requeue.
|
||||
* If the entry is not referenced - free.
|
||||
*/
|
||||
static int
|
||||
cleanup_entries(dns_lowac_t *lowac) {
|
||||
ck_ht_entry_t htentry;
|
||||
dns_lowac_entry_t *entry;
|
||||
ck_fifo_mpmc_entry_t *qentry = NULL;
|
||||
int removed = 0;
|
||||
int max = 100;
|
||||
|
||||
while (--max > 0 &&
|
||||
ck_fifo_mpmc_dequeue(&lowac->remq, &entry, &qentry) == true)
|
||||
{
|
||||
REQUIRE(VALID_LENTRY(entry));
|
||||
int rc = isc_refcount_decrement(&entry->refcount);
|
||||
int rqrc = isc_refcount_decrement(&entry->rqrefcount);
|
||||
fprintf(stderr, "DECREF %d %p %d\n", __LINE__, entry, lowac->count);
|
||||
if (entry->inht) {
|
||||
/*
|
||||
* Remove entry from the hashtable, we'll remove the
|
||||
* entry itself in the next iteration.
|
||||
*/
|
||||
ck_ht_entry_set(&htentry, entry->hash, entry->key.base,
|
||||
entry->key.length, entry);
|
||||
RUNTIME_CHECK(ck_ht_remove_spmc(&lowac->ht,
|
||||
entry->hash,
|
||||
&htentry) == true);
|
||||
entry->inht = false;
|
||||
isc_refcount_increment0(&entry->rqrefcount);
|
||||
/* We don't increment refcount - it was at 2 (remq + ht), it stays at 1 (remq) */
|
||||
fprintf(stderr, "INCREF %d %p\n", __LINE__, entry);
|
||||
fprintf(stderr, "XXXenq %p %d\n", entry, __LINE__);
|
||||
ck_fifo_mpmc_enqueue(&lowac->remq, qentry, entry);
|
||||
} else {
|
||||
if (rc > 1) {
|
||||
/* Requeue if still in use and there's no other request in queue */
|
||||
/* TODO that's completely wrong, if we have two instances in the queue they will always have rc > 1 !!! */
|
||||
if (rqrc == 0) {
|
||||
int p1 = isc_refcount_increment0(&entry->rqrefcount);
|
||||
int p2 = isc_refcount_increment0(&entry->refcount);
|
||||
(void) p1;
|
||||
(void) p2;
|
||||
fprintf(stderr, "INCREF %d %p %d %d\n", __LINE__, entry, p1, p2);
|
||||
fprintf(stderr, "XXXenq %p %d\n", entry, __LINE__);
|
||||
ck_fifo_mpmc_enqueue(&lowac->remq, qentry,
|
||||
entry);
|
||||
} else {
|
||||
isc_mem_put(lowac->mctx, qentry,
|
||||
sizeof(*qentry));
|
||||
}
|
||||
fprintf(stderr, "IGNREF %d %p\n", __LINE__, entry);
|
||||
} else {
|
||||
isc_mem_put(lowac->mctx, qentry,
|
||||
sizeof(*qentry));
|
||||
removed++;
|
||||
free_entry(lowac, entry);
|
||||
fprintf(stderr, "XXXFree %p %d\n", entry, lowac->count);
|
||||
lowac->count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (removed);
|
||||
}
|
||||
|
||||
static void *
|
||||
rthread(void *d) {
|
||||
dns_lowac_t *lowac = (dns_lowac_t*) d;
|
||||
ck_ht_iterator_init(&lowac->htit);
|
||||
while (lowac->running) {
|
||||
isc_time_t now;
|
||||
isc_time_now(&now);
|
||||
atomic_store(&lowac->now, now.seconds);
|
||||
bool dequeued = dequeue_input_entry(lowac);
|
||||
if (!dequeued) {
|
||||
expire_entries(lowac);
|
||||
int removed = cleanup_entries(lowac);
|
||||
if (removed < 256) {
|
||||
usleep(1000);
|
||||
} else {
|
||||
RUNTIME_CHECK(ck_ht_gc(&lowac->ht, 128,
|
||||
isc_random32()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
dns_lowac_t*
|
||||
dns_lowac_create(isc_mem_t *mctx) {
|
||||
dns_lowac_t *lowac = isc_mem_get(mctx, sizeof(dns_lowac_t));
|
||||
lowac->expiry = 600;
|
||||
lowac->count = 0;
|
||||
lowac->running = true;
|
||||
|
||||
if (ck_ht_init(&lowac->ht,
|
||||
CK_HT_MODE_BYTESTRING | CK_HT_WORKLOAD_DELETE,
|
||||
ht_hash_wrapper,
|
||||
&my_allocator, 32, isc_random32()) == false) {
|
||||
abort();
|
||||
}
|
||||
|
||||
ck_fifo_mpmc_entry_t *inq_stub =
|
||||
isc_mem_get(mctx, sizeof(ck_fifo_mpmc_entry_t));
|
||||
ck_fifo_mpmc_entry_t *remq_stub =
|
||||
isc_mem_get(mctx, sizeof(ck_fifo_mpmc_entry_t));
|
||||
|
||||
ck_fifo_mpmc_init(&lowac->inq, inq_stub);
|
||||
ck_fifo_mpmc_init(&lowac->remq, remq_stub);
|
||||
|
||||
|
||||
lowac->mctx = NULL;
|
||||
isc_mem_attach(mctx, &lowac->mctx);
|
||||
|
||||
isc_thread_create(rthread, lowac, &lowac->thread);
|
||||
return (lowac);
|
||||
}
|
||||
|
||||
void
|
||||
dns_lowac_destroy(dns_lowac_t *lowac) {
|
||||
lowac->running = false;
|
||||
isc_thread_join(lowac->thread, NULL);
|
||||
dns_lowac_entry_t *entry;
|
||||
ck_fifo_mpmc_entry_t *fentry;
|
||||
|
||||
/* Entries in inq can only be in inq, it's safe to free them */
|
||||
while (ck_fifo_mpmc_dequeue(&lowac->inq,
|
||||
&entry,
|
||||
&fentry))
|
||||
{
|
||||
isc_mem_put(lowac->mctx, fentry, sizeof(*fentry));
|
||||
free_entry(lowac, entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* Entries in remq can be freed only if they're no longer referenced
|
||||
* by either multiple occurences in queue or HT
|
||||
*/
|
||||
while (ck_fifo_mpmc_dequeue(&lowac->remq,
|
||||
&entry,
|
||||
&fentry))
|
||||
{
|
||||
if (isc_refcount_decrement(&entry->refcount) == 1) {
|
||||
fprintf(stderr, "DECREF %d %p\n", __LINE__, entry);
|
||||
free_entry(lowac, entry);
|
||||
} else {
|
||||
fprintf(stderr, "Non-unreferenced entry in remq %p\n", entry);
|
||||
}
|
||||
isc_mem_put(lowac->mctx, fentry, sizeof(*fentry));
|
||||
}
|
||||
|
||||
/* Finally we free rest of entries from HT */
|
||||
while (ck_ht_count(&lowac->ht) > 0) {
|
||||
ck_ht_gc(&lowac->ht, 0, 0);
|
||||
ck_ht_iterator_t htit = CK_HT_ITERATOR_INITIALIZER;
|
||||
ck_ht_entry_t *htitentry = NULL;
|
||||
while (ck_ht_next(&lowac->ht, &htit, &htitentry)) {
|
||||
entry = ck_ht_entry_value(htitentry);
|
||||
ck_ht_remove_spmc(&lowac->ht, entry->hash, htitentry);
|
||||
free_entry(lowac, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ck_fifo_mpmc_deinit(&lowac->inq, &fentry);
|
||||
isc_mem_put(lowac->mctx, fentry, sizeof(*fentry));
|
||||
|
||||
ck_fifo_mpmc_deinit(&lowac->remq, &fentry);
|
||||
isc_mem_put(lowac->mctx, fentry, sizeof(*fentry));
|
||||
|
||||
ck_ht_destroy(&lowac->ht);
|
||||
isc_mem_putanddetach(&lowac->mctx, lowac, sizeof(*lowac));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_lowac_put(dns_lowac_t *lowac, dns_name_t *name, char*packet, int size) {
|
||||
if (!lowac->running) {
|
||||
return (ISC_R_SHUTTINGDOWN);
|
||||
}
|
||||
if (size > MAXIMUM_PKT_SIZE) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
dns_lowac_entry_t *entry = isc_mem_get(lowac->mctx, sizeof(*entry));
|
||||
dns_name_init(&entry->name, NULL);
|
||||
dns_name_dup(name, lowac->mctx, &entry->name);
|
||||
entry->blob = isc_mem_get(lowac->mctx, size);
|
||||
memcpy(entry->blob, packet, size);
|
||||
entry->blobsize = size;
|
||||
isc_refcount_init(&entry->refcount, 1);
|
||||
isc_refcount_init(&entry->rqrefcount, 0);
|
||||
entry->expire = atomic_load(&lowac->now) + lowac->expiry;
|
||||
entry->remq_enqueued = false;
|
||||
entry->inht = false;
|
||||
entry->magic = LENTRY_MAGIC;
|
||||
|
||||
dns_name_toregion(&entry->name, &entry->key);
|
||||
|
||||
ck_ht_hash(&entry->hash, &lowac->ht, entry->key.base,
|
||||
entry->key.length);
|
||||
ck_fifo_mpmc_entry_t *qentry =
|
||||
isc_mem_get(lowac->mctx, (sizeof(ck_fifo_mpmc_entry_t)));
|
||||
ck_fifo_mpmc_enqueue(&lowac->inq, qentry, entry);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
isc_result_t
|
||||
dns_lowac_get(dns_lowac_t *lowac, dns_name_t *name, unsigned char *blob,
|
||||
int *blobsize, bool tcp) {
|
||||
ck_ht_entry_t htentry;
|
||||
ck_ht_hash_t h;
|
||||
isc_region_t r;
|
||||
|
||||
dns_name_toregion(name, &r);
|
||||
ck_ht_hash(&h, &lowac->ht, r.base, r.length);
|
||||
ck_ht_entry_key_set(&htentry, r.base, r.length);
|
||||
if (ck_ht_get_spmc(&lowac->ht, h, &htentry) == false) {
|
||||
return (ISC_R_NOTFOUND);
|
||||
} else {
|
||||
dns_lowac_entry_t *entry = ck_ht_entry_value(&htentry);
|
||||
REQUIRE(VALID_LENTRY(entry));
|
||||
int oldrc = isc_refcount_increment0(&entry->refcount);
|
||||
fprintf(stderr, "INCREF %d %p\n", __LINE__, entry, oldrc);
|
||||
RUNTIME_CHECK(oldrc > 0);
|
||||
if (entry->remq_enqueued || !entry->inht) {
|
||||
/* This entry is being removed, bail */
|
||||
isc_refcount_decrement(&entry->refcount);
|
||||
fprintf(stderr, "DECREF %d %p\n", __LINE__, entry);
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
if (entry->expire < atomic_load(&lowac->now)) {
|
||||
ck_fifo_mpmc_entry_t *qentry =
|
||||
isc_mem_get(lowac->mctx,
|
||||
(sizeof(ck_fifo_mpmc_entry_t)));
|
||||
entry->remq_enqueued = true;
|
||||
isc_refcount_increment0(&entry->rqrefcount);
|
||||
fprintf(stderr, "XXXenq %p %d\n", entry, __LINE__);
|
||||
ck_fifo_mpmc_enqueue(&lowac->remq, qentry, entry);
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
if (tcp) {
|
||||
blob[0] = entry->blobsize >> 8;
|
||||
blob[1] = entry->blobsize;
|
||||
memcpy(blob + 2, entry->blob, entry->blobsize);
|
||||
*blobsize = entry->blobsize + 2;
|
||||
} else {
|
||||
memcpy(blob, entry->blob, entry->blobsize);
|
||||
*blobsize = entry->blobsize;
|
||||
}
|
||||
isc_refcount_decrement(&entry->refcount);
|
||||
fprintf(stderr, "DECREF %d %p\n", __LINE__, entry);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
+15
-1
@@ -1777,7 +1777,21 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
|
||||
if (c == 0)
|
||||
done = true;
|
||||
n = c;
|
||||
state = fw_ordinary;
|
||||
if (downcase) {
|
||||
state = fw_ordinary;
|
||||
} else {
|
||||
current += n;
|
||||
if (current >= source->active) {
|
||||
return (ISC_R_UNEXPECTEDEND);
|
||||
}
|
||||
memcpy(ndata, cdata, n);
|
||||
cdata += n;
|
||||
ndata += n;
|
||||
if (!seen_pointer) {
|
||||
cused+=n;
|
||||
}
|
||||
state = fw_start;
|
||||
}
|
||||
} else if (c >= 128 && c < 192) {
|
||||
/*
|
||||
* 14 bit local compression pointer.
|
||||
|
||||
+8
-5
@@ -172,9 +172,12 @@ typedef isc_rwlock_t nodelock_t;
|
||||
* to be 0 by default either with or without threads.
|
||||
*/
|
||||
#ifndef DNS_RBTDB_LIMITLRUUPDATE
|
||||
#define DNS_RBTDB_LIMITLRUUPDATE 0
|
||||
#define DNS_RBTDB_LIMITLRUUPDATE 1
|
||||
#endif
|
||||
|
||||
#define DNS_RBTDB_LRUUPDATE_GLUE 300
|
||||
#define DNS_RBTDB_LRUUPDATE_REGULAR 600
|
||||
|
||||
/*
|
||||
* Allow clients with a virtual time of up to 5 minutes in the past to see
|
||||
* records that would have otherwise have expired.
|
||||
@@ -309,7 +312,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
|
||||
(((header)->rdh_ttl > (now)) || \
|
||||
((header)->rdh_ttl == (now) && ZEROTTL(header)))
|
||||
|
||||
#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
|
||||
#define DEFAULT_NODE_LOCK_COUNT 53 /*%< Should be prime. */
|
||||
#define RBTDB_GLUE_TABLE_INIT_SIZE 2U
|
||||
|
||||
/*%
|
||||
@@ -329,7 +332,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
|
||||
#define DEFAULT_CACHE_NODE_LOCK_COUNT DNS_RBTDB_CACHE_NODE_LOCK_COUNT
|
||||
#endif
|
||||
#else
|
||||
#define DEFAULT_CACHE_NODE_LOCK_COUNT 16
|
||||
#define DEFAULT_CACHE_NODE_LOCK_COUNT 97
|
||||
#endif /* DNS_RBTDB_CACHE_NODE_LOCK_COUNT */
|
||||
|
||||
typedef struct {
|
||||
@@ -10088,11 +10091,11 @@ need_headerupdate(rdatasetheader_t *header, isc_stdtime_t now) {
|
||||
* Glue records are updated if at least 60 seconds have passed
|
||||
* since the previous update time.
|
||||
*/
|
||||
return (header->last_used + 60 <= now);
|
||||
return (header->last_used + DNS_RBTDB_LRUUPDATE_GLUE <= now);
|
||||
}
|
||||
|
||||
/* Other records are updated if 5 minutes have passed. */
|
||||
return (header->last_used + 300 <= now);
|
||||
return (header->last_used + DNS_RBTDB_LRUUPDATE_REGULAR <= now);
|
||||
#else
|
||||
UNUSED(now);
|
||||
|
||||
|
||||
+1
-1
@@ -4832,7 +4832,7 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
|
||||
fctx->vresult = ISC_R_SUCCESS;
|
||||
fctx->exitline = -1; /* sentinel */
|
||||
fctx->logged = false;
|
||||
atomic_store(&fctx->attributes, 0);
|
||||
atomic_init(&fctx->attributes, 0);
|
||||
fctx->spilled = false;
|
||||
fctx->nqueries = 0;
|
||||
fctx->reason = NULL;
|
||||
|
||||
@@ -279,6 +279,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
||||
view, NULL, NULL, NULL);
|
||||
view->viewlist = NULL;
|
||||
view->magic = DNS_VIEW_MAGIC;
|
||||
/* TODO we might destroy the view (and LOWAC) when we still need it on shutdown! */
|
||||
view->lowac = dns_lowac_create(view->mctx);
|
||||
|
||||
*viewp = view;
|
||||
|
||||
@@ -610,6 +612,9 @@ view_flushanddetach(dns_view_t **viewp, bool flush) {
|
||||
if (view->catzs != NULL) {
|
||||
dns_catz_catzs_detach(&view->catzs);
|
||||
}
|
||||
if (view->lowac != NULL) {
|
||||
dns_lowac_destroy(view->lowac);
|
||||
}
|
||||
UNLOCK(&view->lock);
|
||||
|
||||
/* Need to detach zones outside view lock */
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ void
|
||||
isc_hp_destroy(isc_hp_t *hp) {
|
||||
for (int i = 0; i < isc__hp_max_threads; i++) {
|
||||
isc_mem_put(hp->mctx, hp->hp[i],
|
||||
CLPAD * 2 * sizeof(uintptr_t));
|
||||
CLPAD * 2 * sizeof(hp->hp[i][0]));
|
||||
|
||||
for (int j = 0; j < hp->rl[i]->size; j++) {
|
||||
void *data = (void *)hp->rl[i]->list[j];
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "uv-compat.h"
|
||||
|
||||
#define ISC_NETMGR_TID_UNKNOWN -1
|
||||
|
||||
#define ISC_NETMGR_RECVBUF_SIZE (20*65536)
|
||||
/*
|
||||
* Single network event loop worker.
|
||||
*/
|
||||
@@ -55,7 +55,7 @@ typedef struct isc__networker {
|
||||
* worker is paused */
|
||||
isc_refcount_t references;
|
||||
atomic_int_fast64_t pktcount;
|
||||
char recvbuf[65536];
|
||||
char * recvbuf;
|
||||
bool recvbuf_inuse;
|
||||
} isc__networker_t;
|
||||
|
||||
|
||||
+10
-5
@@ -210,6 +210,7 @@ isc_nm_start(isc_mem_t *mctx, uint32_t workers) {
|
||||
|
||||
worker->ievents = isc_queue_new(mgr->mctx, 128);
|
||||
worker->ievents_prio = isc_queue_new(mgr->mctx, 128);
|
||||
worker->recvbuf = isc_mem_get(mctx, ISC_NETMGR_RECVBUF_SIZE);
|
||||
|
||||
/*
|
||||
* We need to do this here and not in nm_thread to avoid a
|
||||
@@ -281,6 +282,7 @@ nm_destroy(isc_nm_t **mgr0) {
|
||||
|
||||
isc_queue_destroy(worker->ievents);
|
||||
isc_queue_destroy(worker->ievents_prio);
|
||||
isc_mem_put(mgr->mctx, worker->recvbuf, ISC_NETMGR_RECVBUF_SIZE);
|
||||
isc_thread_join(worker->thread, NULL);
|
||||
}
|
||||
|
||||
@@ -921,8 +923,8 @@ isc__nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr,
|
||||
.iface = iface,
|
||||
.fd = -1,
|
||||
.ah_size = 32,
|
||||
.inactivehandles = isc_astack_new(mgr->mctx, 60),
|
||||
.inactivereqs = isc_astack_new(mgr->mctx, 60)
|
||||
.inactivehandles = isc_astack_new(mgr->mctx, 600),
|
||||
.inactivereqs = isc_astack_new(mgr->mctx, 600)
|
||||
};
|
||||
|
||||
isc_nm_attach(mgr, &sock->mgr);
|
||||
@@ -982,14 +984,14 @@ isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(isc__nm_in_netthread());
|
||||
REQUIRE(size <= 65536);
|
||||
REQUIRE(size <= ISC_NETMGR_RECVBUF_SIZE);
|
||||
|
||||
worker = &sock->mgr->workers[sock->tid];
|
||||
INSIST(!worker->recvbuf_inuse);
|
||||
|
||||
buf->base = worker->recvbuf;
|
||||
worker->recvbuf_inuse = true;
|
||||
buf->len = size;
|
||||
buf->len = ISC_NETMGR_RECVBUF_SIZE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1004,8 +1006,11 @@ isc__nm_free_uvbuf(isc_nmsocket_t *sock, const uv_buf_t *buf) {
|
||||
worker = &sock->mgr->workers[sock->tid];
|
||||
|
||||
REQUIRE(worker->recvbuf_inuse);
|
||||
if (buf->base > worker->recvbuf && buf->base <= worker->recvbuf + ISC_NETMGR_RECVBUF_SIZE) {
|
||||
/* Can happen in case of recvmmsg */
|
||||
return;
|
||||
}
|
||||
REQUIRE(buf->base == worker->recvbuf);
|
||||
|
||||
worker->recvbuf_inuse = false;
|
||||
}
|
||||
|
||||
|
||||
+13
-5
@@ -291,8 +291,8 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
||||
isc_result_t result;
|
||||
isc_nmhandle_t *nmhandle = NULL;
|
||||
isc_sockaddr_t sockaddr;
|
||||
isc_sockaddr_t localaddr;
|
||||
struct sockaddr_storage laddr;
|
||||
/* isc_sockaddr_t localaddr;
|
||||
struct sockaddr_storage laddr; */
|
||||
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)handle);
|
||||
isc_region_t region;
|
||||
uint32_t maxudp;
|
||||
@@ -326,13 +326,13 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
||||
|
||||
result = isc_sockaddr_fromsockaddr(&sockaddr, addr);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
uv_udp_getsockname(handle, (struct sockaddr *) &laddr,
|
||||
/* uv_udp_getsockname(handle, (struct sockaddr *) &laddr,
|
||||
&(int){sizeof(struct sockaddr_storage)});
|
||||
result = isc_sockaddr_fromsockaddr(&localaddr,
|
||||
(struct sockaddr *) &laddr);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS); */
|
||||
|
||||
nmhandle = isc__nmhandle_get(sock, &sockaddr, &localaddr);
|
||||
nmhandle = isc__nmhandle_get(sock, &sockaddr, NULL);
|
||||
region.base = (unsigned char *) buf->base;
|
||||
region.length = nrecv;
|
||||
|
||||
@@ -391,8 +391,16 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region,
|
||||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're in netthread - send it directly
|
||||
* If the original packet was received over a regular socket
|
||||
* - send it over the same thread (assuming cpu affinity)
|
||||
* Otherwise - use a random thread.
|
||||
*/
|
||||
if (isc__nm_in_netthread()) {
|
||||
ntid = isc_nm_tid();
|
||||
} else if (sock->type == isc_nm_udpsocket) {
|
||||
ntid = sock->tid;
|
||||
} else {
|
||||
ntid = (int) isc_random_uniform(sock->nchildren);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <isc/util.h>
|
||||
#include "uv-compat.h"
|
||||
|
||||
#ifndef HAVE_UV_IMPORT
|
||||
/*
|
||||
* XXXWPK: This code goes into libuv internals and it's platform dependent.
|
||||
* It's ugly, we shouldn't do it, but the alternative with passing sockets
|
||||
@@ -190,3 +191,5 @@ isc_uv_import(uv_stream_t *stream, isc_uv_stream_info_t *info) {
|
||||
return (uv_tcp_open(tcp, info->fd));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,14 @@ uv_handle_set_data(uv_handle_t *handle, void *data) {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UV_IMPORT
|
||||
|
||||
#define isc_uv_stream_info_t uv_stream_info_t
|
||||
#define isc_uv_export uv_export
|
||||
#define isc_uv_import uv_import
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* These functions are not available in libuv, but they're very internal
|
||||
* to libuv. We should try to get them merged upstream.
|
||||
@@ -69,3 +77,5 @@ isc_uv_import(uv_stream_t *stream, isc_uv_stream_info_t *info);
|
||||
* Imports uv_stream_info_t value into uv_stream_t to initialize a
|
||||
* shared stream.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
+7
-7
@@ -15,9 +15,9 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <isc/lib.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/once.h>
|
||||
#include <isc/resultclass.h>
|
||||
#include <isc/rwlock.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
typedef struct resulttable {
|
||||
@@ -182,7 +182,7 @@ static const char *identifier[ISC_R_NRESULTS] = {
|
||||
static isc_once_t once = ISC_ONCE_INIT;
|
||||
static resulttable_list_t description_tables;
|
||||
static resulttable_list_t identifier_tables;
|
||||
static isc_mutex_t lock;
|
||||
static isc_rwlock_t lock;
|
||||
|
||||
static isc_result_t
|
||||
register_table(resulttable_list_t *tables, unsigned int base,
|
||||
@@ -208,11 +208,11 @@ register_table(resulttable_list_t *tables, unsigned int base,
|
||||
table->set = set;
|
||||
ISC_LINK_INIT(table, link);
|
||||
|
||||
LOCK(&lock);
|
||||
RWLOCK(&lock, isc_rwlocktype_write);
|
||||
|
||||
ISC_LIST_APPEND(*tables, table, link);
|
||||
|
||||
UNLOCK(&lock);
|
||||
RWUNLOCK(&lock, isc_rwlocktype_write);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@@ -221,7 +221,7 @@ static void
|
||||
initialize_action(void) {
|
||||
isc_result_t result;
|
||||
|
||||
isc_mutex_init(&lock);
|
||||
isc_rwlock_init(&lock, 0, 0);
|
||||
ISC_LIST_INIT(description_tables);
|
||||
ISC_LIST_INIT(identifier_tables);
|
||||
|
||||
@@ -257,7 +257,7 @@ isc_result_tomany_helper(resulttable_list_t *tables, isc_result_t result) {
|
||||
|
||||
initialize();
|
||||
|
||||
LOCK(&lock);
|
||||
RWLOCK(&lock, isc_rwlocktype_read);
|
||||
|
||||
text = NULL;
|
||||
for (table = ISC_LIST_HEAD(*tables);
|
||||
@@ -273,7 +273,7 @@ isc_result_tomany_helper(resulttable_list_t *tables, isc_result_t result) {
|
||||
text = "(result code text not available)";
|
||||
}
|
||||
|
||||
UNLOCK(&lock);
|
||||
RWUNLOCK(&lock, isc_rwlocktype_read);
|
||||
|
||||
return (text);
|
||||
}
|
||||
|
||||
+6
-1
@@ -17,7 +17,12 @@
|
||||
#include <isc/util.h>
|
||||
#include <isc/siphash.h>
|
||||
|
||||
#if HAVE_OPENSSL_SIPHASH
|
||||
/*
|
||||
* Creation of EVP_MD_CTX and EVP_PKEY is quite expensive, until
|
||||
* we fix the code to reuse the context and key we'll use our own
|
||||
* implementation of siphash.
|
||||
*/
|
||||
#if 0 /* HAVE_OPENSSL_SIPHASH */
|
||||
#include <openssl/evp.h>
|
||||
|
||||
void
|
||||
|
||||
+44
-11
@@ -23,11 +23,14 @@
|
||||
#include <isc/print.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/stats.h>
|
||||
#include <isc/thread.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#define ISC_STATS_MAGIC ISC_MAGIC('S', 't', 'a', 't')
|
||||
#define ISC_STATS_VALID(x) ISC_MAGIC_VALID(x, ISC_STATS_MAGIC)
|
||||
|
||||
#define STATS_BUCKETS 64
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
typedef atomic_int_fast32_t isc__atomic_statcounter_t;
|
||||
#else
|
||||
@@ -42,6 +45,17 @@ struct isc_stats {
|
||||
isc__atomic_statcounter_t *counters;
|
||||
};
|
||||
|
||||
ISC_THREAD_LOCAL int isc__stats_thread_v = -1;
|
||||
static atomic_uint_fast32_t isc__stats_thread_n = 0;
|
||||
|
||||
static int
|
||||
threadhash() {
|
||||
if (isc__stats_thread_v < 0) {
|
||||
isc__stats_thread_v = atomic_fetch_add_relaxed(&isc__stats_thread_n, 1) % STATS_BUCKETS;
|
||||
}
|
||||
return (isc__stats_thread_v);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
|
||||
isc_stats_t *stats;
|
||||
@@ -50,7 +64,7 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
|
||||
REQUIRE(statsp != NULL && *statsp == NULL);
|
||||
|
||||
stats = isc_mem_get(mctx, sizeof(*stats));
|
||||
counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters;
|
||||
counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters * STATS_BUCKETS;
|
||||
stats->counters = isc_mem_get(mctx, counters_alloc_size);
|
||||
isc_refcount_init(&stats->references, 1);
|
||||
memset(stats->counters, 0, counters_alloc_size);
|
||||
@@ -85,7 +99,8 @@ isc_stats_detach(isc_stats_t **statsp) {
|
||||
isc_refcount_destroy(&stats->references);
|
||||
isc_mem_put(stats->mctx, stats->counters,
|
||||
sizeof(isc__atomic_statcounter_t) *
|
||||
stats->ncounters);
|
||||
stats->ncounters *
|
||||
STATS_BUCKETS);
|
||||
isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
|
||||
}
|
||||
}
|
||||
@@ -108,8 +123,8 @@ void
|
||||
isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter) {
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(counter < stats->ncounters);
|
||||
|
||||
atomic_fetch_add_explicit(&stats->counters[counter], 1,
|
||||
int idx = threadhash() * stats->ncounters + counter;
|
||||
atomic_fetch_add_explicit(&stats->counters[idx], 1,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
|
||||
@@ -118,7 +133,8 @@ isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter) {
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(counter < stats->ncounters);
|
||||
|
||||
atomic_fetch_sub_explicit(&stats->counters[counter], 1,
|
||||
int idx = threadhash() * stats->ncounters + counter;
|
||||
atomic_fetch_sub_explicit(&stats->counters[idx], 1,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
|
||||
@@ -131,8 +147,13 @@ isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn,
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
|
||||
for (i = 0; i < stats->ncounters; i++) {
|
||||
uint32_t counter = atomic_load_explicit(&stats->counters[i],
|
||||
uint32_t counter = 0;
|
||||
int b;
|
||||
for (b = 0; b < STATS_BUCKETS; b++) {
|
||||
int idx = stats->ncounters * b + i;
|
||||
counter += atomic_load_explicit(&stats->counters[idx],
|
||||
memory_order_relaxed);
|
||||
}
|
||||
if ((options & ISC_STATSDUMP_VERBOSE) == 0 && counter == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -144,11 +165,17 @@ void
|
||||
isc_stats_set(isc_stats_t *stats, uint64_t val,
|
||||
isc_statscounter_t counter)
|
||||
{
|
||||
int i;
|
||||
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(counter < stats->ncounters);
|
||||
|
||||
atomic_store_explicit(&stats->counters[counter], val,
|
||||
memory_order_relaxed);
|
||||
for (i = 1; i < STATS_BUCKETS; i++) {
|
||||
int idx = stats->ncounters * i + counter;
|
||||
atomic_store_explicit(&stats->counters[idx], val,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
void isc_stats_update_if_greater(isc_stats_t *stats,
|
||||
@@ -158,9 +185,9 @@ void isc_stats_update_if_greater(isc_stats_t *stats,
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(counter < stats->ncounters);
|
||||
|
||||
isc_statscounter_t curr_value =
|
||||
atomic_load_relaxed(&stats->counters[counter]);
|
||||
isc_statscounter_t curr_value;
|
||||
do {
|
||||
curr_value = atomic_load_relaxed(&stats->counters[counter]);
|
||||
if (curr_value >= value) {
|
||||
break;
|
||||
}
|
||||
@@ -172,9 +199,15 @@ void isc_stats_update_if_greater(isc_stats_t *stats,
|
||||
isc_statscounter_t
|
||||
isc_stats_get_counter(isc_stats_t *stats, isc_statscounter_t counter)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
int i;
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
REQUIRE(counter < stats->ncounters);
|
||||
|
||||
return (atomic_load_explicit(&stats->counters[counter],
|
||||
memory_order_relaxed));
|
||||
for (i = 0; i < STATS_BUCKETS; i++) {
|
||||
int idx = i * stats->ncounters + counter;
|
||||
value += atomic_load_explicit(&stats->counters[idx],
|
||||
memory_order_relaxed);
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
+46
-28
@@ -106,6 +106,7 @@ struct isc__task {
|
||||
isc_mutex_t lock;
|
||||
/* Locked by task lock. */
|
||||
task_state_t state;
|
||||
int pause_cnt;
|
||||
isc_refcount_t references;
|
||||
isc_eventlist_t events;
|
||||
isc_eventlist_t on_shutdown;
|
||||
@@ -308,6 +309,7 @@ isc_task_create_bound(isc_taskmgr_t *manager0, unsigned int quantum,
|
||||
|
||||
isc_mutex_init(&task->lock);
|
||||
task->state = task_state_idle;
|
||||
task->pause_cnt = 0;
|
||||
|
||||
isc_refcount_init(&task->references, 1);
|
||||
INIT_LIST(task->events);
|
||||
@@ -407,7 +409,7 @@ task_shutdown(isc__task_t *task) {
|
||||
/*
|
||||
* Moves a task onto the appropriate run queue.
|
||||
*
|
||||
* Caller must NOT hold manager lock.
|
||||
* Caller must NOT hold queue lock.
|
||||
*/
|
||||
static inline void
|
||||
task_ready(isc__task_t *task) {
|
||||
@@ -415,7 +417,6 @@ task_ready(isc__task_t *task) {
|
||||
bool has_privilege = isc_task_privilege((isc_task_t *) task);
|
||||
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
REQUIRE(task->state == task_state_ready);
|
||||
|
||||
XTRACE("task_ready");
|
||||
LOCK(&manager->queues[task->threadid].lock);
|
||||
@@ -967,10 +968,13 @@ pop_readyq(isc__taskmgr_t *manager, int c) {
|
||||
* Push 'task' onto the ready_tasks queue. If 'task' has the privilege
|
||||
* flag set, then also push it onto the ready_priority_tasks queue.
|
||||
*
|
||||
* Caller must hold the task manager lock.
|
||||
* Caller must hold the task queue lock.
|
||||
*/
|
||||
static inline void
|
||||
push_readyq(isc__taskmgr_t *manager, isc__task_t *task, int c) {
|
||||
if (ISC_LINK_LINKED(task, ready_link)) {
|
||||
return;
|
||||
}
|
||||
ENQUEUE(manager->queues[c].ready_tasks, task, ready_link);
|
||||
if (TASK_PRIVILEGED(task)) {
|
||||
ENQUEUE(manager->queues[c].ready_priority_tasks, task,
|
||||
@@ -1128,6 +1132,17 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
|
||||
memory_order_acquire);
|
||||
|
||||
LOCK(&task->lock);
|
||||
/*
|
||||
* It is possible because that we have a paused task
|
||||
* in the queue - it might have been paused in the
|
||||
* meantime and we never hold both queue and task lock
|
||||
* to avoid deadlocks, just bail then.
|
||||
*/
|
||||
if (task->state != task_state_ready) {
|
||||
UNLOCK(&task->lock);
|
||||
LOCK(&manager->queues[threadid].lock);
|
||||
continue;
|
||||
}
|
||||
INSIST(task->state == task_state_ready);
|
||||
task->state = task_state_running;
|
||||
XTRACE("running");
|
||||
@@ -1215,6 +1230,15 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
} else if (task->state == task_state_pausing) {
|
||||
/*
|
||||
* We got a pause request on this task,
|
||||
* stop working on it and switch the state
|
||||
* to paused.
|
||||
*/
|
||||
XTRACE("pausing");
|
||||
task->state = task_state_paused;
|
||||
done = true;
|
||||
} else if (dispatch_count >= task->quantum) {
|
||||
/*
|
||||
* Our quantum has expired, but
|
||||
@@ -1227,17 +1251,8 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
|
||||
* so the minimum quantum is one.
|
||||
*/
|
||||
XTRACE("quantum");
|
||||
if (task->state == task_state_running) {
|
||||
/*
|
||||
* We requeue only if it's
|
||||
* not paused.
|
||||
*/
|
||||
task->state = task_state_ready;
|
||||
requeue = true;
|
||||
} else if (task->state ==
|
||||
task_state_pausing) {
|
||||
task->state = task_state_paused;
|
||||
}
|
||||
task->state = task_state_ready;
|
||||
requeue = true;
|
||||
done = true;
|
||||
}
|
||||
} while (!done);
|
||||
@@ -1686,31 +1701,27 @@ void
|
||||
isc_task_pause(isc_task_t *task0) {
|
||||
REQUIRE(ISCAPI_TASK_VALID(task0));
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
isc__taskmgr_t *manager = task->manager;
|
||||
bool running = false;
|
||||
|
||||
LOCK(&task->lock);
|
||||
task->pause_cnt++;
|
||||
if (task->pause_cnt > 1) {
|
||||
/*
|
||||
* Someone already paused this thread, just increase
|
||||
* the number of pausing clients.
|
||||
*/
|
||||
UNLOCK(&task->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
INSIST(task->state == task_state_idle ||
|
||||
task->state == task_state_ready ||
|
||||
task->state == task_state_running);
|
||||
if (task->state == task_state_running) {
|
||||
running = true;
|
||||
task->state = task_state_pausing;
|
||||
} else {
|
||||
task->state = task_state_paused;
|
||||
}
|
||||
UNLOCK(&task->lock);
|
||||
|
||||
if (running) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK(&manager->queues[task->threadid].lock);
|
||||
if (ISC_LINK_LINKED(task, ready_link)) {
|
||||
DEQUEUE(manager->queues[task->threadid].ready_tasks,
|
||||
task, ready_link);
|
||||
}
|
||||
UNLOCK(&manager->queues[task->threadid].lock);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1721,6 +1732,13 @@ isc_task_unpause(isc_task_t *task0) {
|
||||
REQUIRE(ISCAPI_TASK_VALID(task0));
|
||||
|
||||
LOCK(&task->lock);
|
||||
task->pause_cnt--;
|
||||
INSIST(task->pause_cnt >= 0);
|
||||
if (task->pause_cnt > 0) {
|
||||
UNLOCK(&task->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
INSIST(task->state == task_state_paused ||
|
||||
task->state == task_state_pausing);
|
||||
/* If the task was pausing we can't reschedule it */
|
||||
|
||||
+14
-14
@@ -135,11 +135,7 @@ int isc_dscp_check_value = -1;
|
||||
*/
|
||||
#ifndef ISC_SOCKET_MAXSOCKETS
|
||||
#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
|
||||
#ifdef TUNE_LARGE
|
||||
#define ISC_SOCKET_MAXSOCKETS 21000
|
||||
#else
|
||||
#define ISC_SOCKET_MAXSOCKETS 4096
|
||||
#endif /* TUNE_LARGE */
|
||||
#define ISC_SOCKET_MAXSOCKETS 65536
|
||||
#elif defined(USE_SELECT)
|
||||
#define ISC_SOCKET_MAXSOCKETS FD_SETSIZE
|
||||
#endif /* USE_KQUEUE... */
|
||||
@@ -1834,7 +1830,6 @@ destroy(isc__socket_t **sockp) {
|
||||
|
||||
socket_log(sock, NULL, CREATION, "destroying");
|
||||
|
||||
isc_refcount_destroy(&sock->references);
|
||||
|
||||
LOCK(&sock->lock);
|
||||
INSIST(ISC_LIST_EMPTY(sock->connect_list));
|
||||
@@ -1862,6 +1857,7 @@ destroy(isc__socket_t **sockp) {
|
||||
if (ISC_LIST_EMPTY(manager->socklist)) {
|
||||
SIGNAL(&manager->shutdown_ok);
|
||||
}
|
||||
isc_refcount_destroy(&sock->references);
|
||||
|
||||
/* can't unlock manager as its memory context is still used */
|
||||
free_socket(sockp);
|
||||
@@ -2631,7 +2627,6 @@ isc_socket_detach(isc_socket_t **socketp) {
|
||||
REQUIRE(socketp != NULL);
|
||||
sock = (isc__socket_t *)*socketp;
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
|
||||
if (isc_refcount_decrement(&sock->references) == 1) {
|
||||
destroy(&sock);
|
||||
}
|
||||
@@ -3149,16 +3144,20 @@ process_fd(isc__socketthread_t *thread, int fd, bool readable,
|
||||
return;
|
||||
}
|
||||
|
||||
if (isc_refcount_increment0(&sock->references) == 0) {
|
||||
LOCK(&sock->lock);
|
||||
if (isc_refcount_current(&sock->references) == 0) {
|
||||
/*
|
||||
* Sock is being closed, it will be destroyed, bail.
|
||||
* Sock is being closed - the final external reference
|
||||
* is gone but it was not yet removed from event loop
|
||||
* and fdstate[]/fds[] as destroy() is waiting on
|
||||
* thread->fdlock[lockid] or sock->lock that we're holding.
|
||||
* Just release the locks and bail.
|
||||
*/
|
||||
(void)isc_refcount_decrement(&sock->references);
|
||||
UNLOCK(&sock->lock);
|
||||
UNLOCK(&thread->fdlock[lockid]);
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK(&sock->lock);
|
||||
if (readable) {
|
||||
if (sock->listener) {
|
||||
internal_accept(sock);
|
||||
@@ -3177,9 +3176,10 @@ process_fd(isc__socketthread_t *thread, int fd, bool readable,
|
||||
UNLOCK(&sock->lock);
|
||||
|
||||
UNLOCK(&thread->fdlock[lockid]);
|
||||
if (isc_refcount_decrement(&sock->references) == 1) {
|
||||
destroy(&sock);
|
||||
}
|
||||
/*
|
||||
* Socket destruction might be pending, it will resume
|
||||
* after releasing fdlock and sock->lock.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -685,8 +685,6 @@ isc_timermgr_destroy
|
||||
isc_timermgr_poke
|
||||
isc_tm_timegm
|
||||
isc_tm_strptime
|
||||
isc_uv_export
|
||||
isc_uv_import
|
||||
isc_win32os_versioncheck
|
||||
openlog
|
||||
@IF PKCS11
|
||||
|
||||
+122
-73
@@ -79,7 +79,6 @@
|
||||
* task to change the client, then the client will have to be locked.
|
||||
*/
|
||||
|
||||
#define NS_CLIENT_TRACE
|
||||
#ifdef NS_CLIENT_TRACE
|
||||
#define CTRACE(m) ns_client_log(client, \
|
||||
NS_LOGCATEGORY_CLIENT, \
|
||||
@@ -132,6 +131,8 @@ static void compute_cookie(ns_client_t *client, uint32_t when,
|
||||
isc_buffer_t *buf);
|
||||
static void
|
||||
get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp);
|
||||
static void
|
||||
get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp);
|
||||
|
||||
void
|
||||
ns_client_recursing(ns_client_t *client) {
|
||||
@@ -171,21 +172,19 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
|
||||
|
||||
static void
|
||||
ns_client_endrequest(ns_client_t *client) {
|
||||
INSIST(client->naccepts == 0);
|
||||
INSIST(client->nreads == 0);
|
||||
INSIST(client->nsends == 0);
|
||||
INSIST(client->nrecvs == 0);
|
||||
INSIST(client->nupdates == 0);
|
||||
INSIST(client->state == NS_CLIENTSTATE_WORKING ||
|
||||
client->state == NS_CLIENTSTATE_RECURSING);
|
||||
|
||||
CTRACE("endrequest");
|
||||
|
||||
LOCK(&client->manager->reclock);
|
||||
if (ISC_LINK_LINKED(client, rlink)) {
|
||||
ISC_LIST_UNLINK(client->manager->recursing, client, rlink);
|
||||
if (client->state == NS_CLIENTSTATE_RECURSING) {
|
||||
LOCK(&client->manager->reclock);
|
||||
if (ISC_LINK_LINKED(client, rlink)) {
|
||||
ISC_LIST_UNLINK(client->manager->recursing, client, rlink);
|
||||
}
|
||||
UNLOCK(&client->manager->reclock);
|
||||
}
|
||||
UNLOCK(&client->manager->reclock);
|
||||
|
||||
if (client->cleanup != NULL) {
|
||||
(client->cleanup)(client);
|
||||
@@ -338,13 +337,15 @@ client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
|
||||
client_sendpkg(ns_client_t *client, isc_buffer_t *buffer, bool lowac) {
|
||||
isc_region_t r;
|
||||
|
||||
isc_buffer_usedregion(buffer, &r);
|
||||
|
||||
INSIST(client->handle != NULL);
|
||||
|
||||
if (lowac && client->view != NULL) {
|
||||
dns_lowac_put(client->view->lowac, ISC_LIST_HEAD(client->message->sections[0]), (char*) r.base, r.length);
|
||||
}
|
||||
return (isc_nm_send(client->handle, &r, client_senddone, client));
|
||||
}
|
||||
|
||||
@@ -380,7 +381,7 @@ ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
|
||||
r.base[0] = (client->message->id >> 8) & 0xff;
|
||||
r.base[1] = client->message->id & 0xff;
|
||||
|
||||
result = client_sendpkg(client, &buffer);
|
||||
result = client_sendpkg(client, &buffer, true);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
@@ -597,7 +598,7 @@ ns_client_send(ns_client_t *client) {
|
||||
respsize = isc_buffer_usedlength(&tcpbuffer) - 2;
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
result = client_sendpkg(client, &tcpbuffer);
|
||||
result = client_sendpkg(client, &tcpbuffer, true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* We won't get a callback to clean it up */
|
||||
isc_nmhandle_unref(client->handle);
|
||||
@@ -634,7 +635,7 @@ ns_client_send(ns_client_t *client) {
|
||||
respsize = isc_buffer_usedlength(&buffer);
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
result = client_sendpkg(client, &buffer);
|
||||
result = client_sendpkg(client, &buffer, true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* We won't get a callback to clean it up */
|
||||
isc_nmhandle_unref(client->handle);
|
||||
@@ -1571,7 +1572,7 @@ ns__client_put_cb(void *client0) {
|
||||
clientmgr_detach(&client->manager);
|
||||
}
|
||||
|
||||
isc_mem_put(client->mctx, client->recvbuf, NS_CLIENT_RECV_BUFFER_SIZE);
|
||||
isc_mem_put(client->mctx, client->sendbuf, NS_CLIENT_SEND_BUFFER_SIZE);
|
||||
if (client->opt != NULL) {
|
||||
INSIST(dns_rdataset_isassociated(client->opt));
|
||||
dns_rdataset_disassociate(client->opt);
|
||||
@@ -1605,6 +1606,51 @@ ns__client_put_cb(void *client0) {
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
lowac_checksend(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
unsigned char *data;
|
||||
isc_buffer_t buffer;
|
||||
isc_buffer_t tcpbuffer;
|
||||
isc_region_t r;
|
||||
result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
|
||||
&data);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
int blen;
|
||||
result = dns_lowac_get(client->view->lowac, ISC_LIST_HEAD(client->message->sections[0]), data, &blen, false);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
if (TCP_CLIENT(client)) {
|
||||
data[2] = (client->message->id >> 8) & 0xff;
|
||||
data[3] = client->message->id & 0xff;
|
||||
} else {
|
||||
data[0] = (client->message->id >> 8) & 0xff;
|
||||
data[1] = client->message->id & 0xff;
|
||||
}
|
||||
isc_buffer_add(&buffer, blen);
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
if (client->sendcb != NULL) {
|
||||
client->sendcb(&buffer);
|
||||
} else if (TCP_CLIENT(client)) {
|
||||
isc_buffer_usedregion(&buffer, &r);
|
||||
isc_buffer_putuint16(&tcpbuffer, (uint16_t) r.length);
|
||||
isc_buffer_add(&tcpbuffer, r.length);
|
||||
result = client_sendpkg(client, &tcpbuffer, false);
|
||||
} else {
|
||||
result = client_sendpkg(client, &buffer, false);
|
||||
}
|
||||
done:
|
||||
if (client->tcpbuf != NULL) {
|
||||
isc_mem_put(client->mctx, client->tcpbuf, NS_CLIENT_TCP_BUFFER_SIZE);
|
||||
client->tcpbuf = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle an incoming request event from the socket (UDP case)
|
||||
* or tcpmsg (TCP case).
|
||||
@@ -1662,7 +1708,6 @@ ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
|
||||
}
|
||||
|
||||
client->state = NS_CLIENTSTATE_READY;
|
||||
client->dscp = ifp->dscp;
|
||||
|
||||
isc_task_pause(client->task);
|
||||
if (client->handle == NULL) {
|
||||
@@ -1997,6 +2042,12 @@ ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
|
||||
"using view '%s'", client->view->name);
|
||||
|
||||
result = lowac_checksend(client);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_task_unpause(client->task);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a signature. We log bad signatures regardless of
|
||||
* whether they ultimately cause the request to be rejected or
|
||||
@@ -2212,38 +2263,33 @@ ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
static void
|
||||
get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
|
||||
isc_mem_t *clientmctx;
|
||||
#if CLIENT_NMCTXS > 0
|
||||
unsigned int nextmctx;
|
||||
#endif
|
||||
|
||||
MTRACE("clientmctx");
|
||||
|
||||
#if CLIENT_NMCTXS > 0
|
||||
LOCK(&manager->lock);
|
||||
if (isc_nm_tid() >= 0) {
|
||||
nextmctx = isc_nm_tid();
|
||||
} else {
|
||||
nextmctx = manager->nextmctx++;
|
||||
if (manager->nextmctx == CLIENT_NMCTXS)
|
||||
manager->nextmctx = 0;
|
||||
|
||||
INSIST(nextmctx < CLIENT_NMCTXS);
|
||||
int tid = isc_nm_tid();
|
||||
if (tid < 0) {
|
||||
tid = isc_random_uniform(manager->ncpus);
|
||||
}
|
||||
|
||||
int rand = isc_random_uniform(CLIENT_NMCTXS_PERCPU);
|
||||
int nextmctx = (rand * manager->ncpus) + tid;
|
||||
clientmctx = manager->mctxpool[nextmctx];
|
||||
if (clientmctx == NULL) {
|
||||
isc_mem_create(&clientmctx);
|
||||
isc_mem_setname(clientmctx, "client", NULL);
|
||||
manager->mctxpool[nextmctx] = clientmctx;
|
||||
}
|
||||
UNLOCK(&manager->lock);
|
||||
#else
|
||||
clientmctx = manager->mctx;
|
||||
#endif
|
||||
|
||||
isc_mem_attach(clientmctx, mctxp);
|
||||
}
|
||||
|
||||
static void
|
||||
get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp) {
|
||||
MTRACE("clienttask");
|
||||
|
||||
int tid = isc_nm_tid();
|
||||
if (tid < 0) {
|
||||
tid = isc_random_uniform(manager->ncpus);
|
||||
}
|
||||
|
||||
int rand = isc_random_uniform(CLIENT_NTASKS_PERCPU);
|
||||
int nexttask = (rand * manager->ncpus) + tid;
|
||||
isc_task_attach(manager->taskpool[nexttask], taskp);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
isc_result_t result;
|
||||
@@ -2267,10 +2313,8 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
get_clientmctx(mgr, &client->mctx);
|
||||
clientmgr_attach(mgr, &client->manager);
|
||||
ns_server_attach(mgr->sctx, &client->sctx);
|
||||
result = isc_task_create(mgr->taskmgr, 20, &client->task);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
get_clienttask(mgr, &client->task);
|
||||
|
||||
result = dns_message_create(client->mctx,
|
||||
DNS_MESSAGE_INTENTPARSE,
|
||||
&client->message);
|
||||
@@ -2279,8 +2323,8 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
}
|
||||
|
||||
|
||||
client->recvbuf = isc_mem_get(client->mctx,
|
||||
NS_CLIENT_RECV_BUFFER_SIZE);
|
||||
client->sendbuf = isc_mem_get(client->mctx,
|
||||
NS_CLIENT_SEND_BUFFER_SIZE);
|
||||
/*
|
||||
* Set magic earlier than usual because ns_query_init()
|
||||
* and the functions it calls will require it.
|
||||
@@ -2294,7 +2338,7 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
ns_clientmgr_t *oldmgr = client->manager;
|
||||
ns_server_t *sctx = client->sctx;
|
||||
isc_task_t *task = client->task;
|
||||
unsigned char *recvbuf = client->recvbuf;
|
||||
unsigned char *sendbuf = client->sendbuf;
|
||||
dns_message_t *message = client->message;
|
||||
isc_mem_t *oldmctx = client->mctx;
|
||||
ns_query_t query = client->query;
|
||||
@@ -2305,7 +2349,7 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
.manager = oldmgr,
|
||||
.sctx = sctx,
|
||||
.task = task,
|
||||
.recvbuf = recvbuf,
|
||||
.sendbuf = sendbuf,
|
||||
.message = message,
|
||||
.query = query
|
||||
};
|
||||
@@ -2313,7 +2357,6 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
|
||||
client->state = NS_CLIENTSTATE_INACTIVE;
|
||||
client->udpsize = 512;
|
||||
client->dscp = -1;
|
||||
client->ednsversion = -1;
|
||||
dns_name_init(&client->signername, NULL);
|
||||
dns_ecs_init(&client->ecs);
|
||||
@@ -2330,9 +2373,9 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
if (client->recvbuf != NULL) {
|
||||
isc_mem_put(client->mctx, client->recvbuf,
|
||||
NS_CLIENT_RECV_BUFFER_SIZE);
|
||||
if (client->sendbuf != NULL) {
|
||||
isc_mem_put(client->mctx, client->sendbuf,
|
||||
NS_CLIENT_SEND_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
if (client->message != NULL) {
|
||||
@@ -2397,21 +2440,18 @@ clientmgr_detach(ns_clientmgr_t **mp) {
|
||||
|
||||
static void
|
||||
clientmgr_destroy(ns_clientmgr_t *manager) {
|
||||
#if CLIENT_NMCTXS > 0
|
||||
int i;
|
||||
#endif
|
||||
|
||||
MTRACE("clientmgr_destroy");
|
||||
|
||||
isc_refcount_destroy(&manager->references);
|
||||
manager->magic = 0;
|
||||
|
||||
#if CLIENT_NMCTXS > 0
|
||||
for (i = 0; i < CLIENT_NMCTXS; i++) {
|
||||
if (manager->mctxpool[i] != NULL)
|
||||
isc_mem_detach(&manager->mctxpool[i]);
|
||||
for (i = 0; i < manager->ncpus * CLIENT_NMCTXS_PERCPU; i++) {
|
||||
isc_mem_detach(&manager->mctxpool[i]);
|
||||
}
|
||||
#endif
|
||||
isc_mem_put(manager->mctx, manager->mctxpool,
|
||||
manager->ncpus * CLIENT_NMCTXS_PERCPU * sizeof(isc_mem_t*));
|
||||
|
||||
if (manager->interface != NULL) {
|
||||
ns_interface_detach(&manager->interface);
|
||||
@@ -2423,13 +2463,14 @@ clientmgr_destroy(ns_clientmgr_t *manager) {
|
||||
if (manager->excl != NULL)
|
||||
isc_task_detach(&manager->excl);
|
||||
|
||||
for (i = 0; i < CLIENT_NTASKS; i++) {
|
||||
for (i = 0; i < manager->ncpus * CLIENT_NTASKS_PERCPU; i++) {
|
||||
if (manager->taskpool[i] != NULL) {
|
||||
isc_task_detach(&manager->taskpool[i]);
|
||||
}
|
||||
}
|
||||
isc_mem_put(manager->mctx, manager->taskpool,
|
||||
CLIENT_NTASKS * sizeof(isc_task_t *));
|
||||
manager->ncpus * CLIENT_NTASKS_PERCPU *
|
||||
sizeof(isc_task_t *));
|
||||
ns_server_detach(&manager->sctx);
|
||||
|
||||
isc_mem_put(manager->mctx, manager, sizeof(*manager));
|
||||
@@ -2438,13 +2479,12 @@ clientmgr_destroy(ns_clientmgr_t *manager) {
|
||||
isc_result_t
|
||||
ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr, ns_interface_t *interface,
|
||||
ns_clientmgr_t **managerp)
|
||||
int ncpus, ns_clientmgr_t **managerp)
|
||||
{
|
||||
ns_clientmgr_t *manager;
|
||||
isc_result_t result;
|
||||
#if CLIENT_NMCTXS > 0
|
||||
int i;
|
||||
#endif
|
||||
int npools;
|
||||
|
||||
manager = isc_mem_get(mctx, sizeof(*manager));
|
||||
*manager = (ns_clientmgr_t) { .magic = 0 };
|
||||
@@ -2461,26 +2501,35 @@ ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
|
||||
manager->mctx = mctx;
|
||||
manager->taskmgr = taskmgr;
|
||||
manager->timermgr = timermgr;
|
||||
manager->ncpus = ncpus;
|
||||
|
||||
ns_interface_attach(interface, &manager->interface);
|
||||
|
||||
manager->exiting = false;
|
||||
manager->taskpool =
|
||||
isc_mem_get(mctx, CLIENT_NTASKS*sizeof(isc_task_t *));
|
||||
for (i = 0; i < CLIENT_NTASKS; i++) {
|
||||
int ntasks = CLIENT_NTASKS_PERCPU * manager->ncpus;
|
||||
manager->taskpool = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
|
||||
for (i = 0; i < ntasks; i++) {
|
||||
manager->taskpool[i] = NULL;
|
||||
isc_task_create(manager->taskmgr, 20, &manager->taskpool[i]);
|
||||
result = isc_task_create_bound(manager->taskmgr, 20,
|
||||
&manager->taskpool[i],
|
||||
i % CLIENT_NTASKS_PERCPU);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
}
|
||||
isc_refcount_init(&manager->references, 1);
|
||||
manager->sctx = NULL;
|
||||
ns_server_attach(sctx, &manager->sctx);
|
||||
|
||||
ISC_LIST_INIT(manager->recursing);
|
||||
#if CLIENT_NMCTXS > 0
|
||||
manager->nextmctx = 0;
|
||||
for (i = 0; i < CLIENT_NMCTXS; i++)
|
||||
manager->mctxpool[i] = NULL; /* will be created on-demand */
|
||||
#endif
|
||||
|
||||
npools = CLIENT_NMCTXS_PERCPU * manager->ncpus;
|
||||
manager->mctxpool = isc_mem_get(manager->mctx,
|
||||
npools * sizeof(isc_mem_t*));
|
||||
for (i = 0; i < npools; i++) {
|
||||
manager->mctxpool[i] = NULL;
|
||||
isc_mem_create(&manager->mctxpool[i]);
|
||||
isc_mem_setname(manager->mctxpool[i], "client", NULL);
|
||||
}
|
||||
|
||||
manager->magic = MANAGER_MAGIC;
|
||||
|
||||
MTRACE("create");
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
#define NS_CLIENT_SEND_BUFFER_SIZE 4096
|
||||
#define NS_CLIENT_RECV_BUFFER_SIZE 4096
|
||||
|
||||
#define CLIENT_NMCTXS 100
|
||||
#define CLIENT_NMCTXS_PERCPU 8
|
||||
/*%<
|
||||
* Number of 'mctx pools' for clients. (Should this be configurable?)
|
||||
* When enabling threads, we use a pool of memory contexts shared by
|
||||
@@ -95,7 +95,7 @@
|
||||
* server.
|
||||
*/
|
||||
|
||||
#define CLIENT_NTASKS 100
|
||||
#define CLIENT_NTASKS_PERCPU 32
|
||||
/*%<
|
||||
* Number of tasks to be used by clients - those are used only when recursing
|
||||
*/
|
||||
@@ -166,6 +166,7 @@ struct ns_clientmgr {
|
||||
isc_timermgr_t * timermgr;
|
||||
isc_task_t * excl;
|
||||
isc_refcount_t references;
|
||||
int ncpus;
|
||||
|
||||
/* Attached by clients, needed for e.g. recursion */
|
||||
isc_task_t ** taskpool;
|
||||
@@ -180,11 +181,8 @@ struct ns_clientmgr {
|
||||
isc_mutex_t reclock;
|
||||
client_list_t recursing; /*%< Recursing clients */
|
||||
|
||||
#if CLIENT_NMCTXS > 0
|
||||
/*%< mctx pool for clients. */
|
||||
unsigned int nextmctx;
|
||||
isc_mem_t * mctxpool[CLIENT_NMCTXS];
|
||||
#endif
|
||||
isc_mem_t ** mctxpool;
|
||||
};
|
||||
|
||||
/*% nameserver client structure */
|
||||
@@ -195,12 +193,7 @@ struct ns_client {
|
||||
ns_server_t *sctx;
|
||||
ns_clientmgr_t *manager;
|
||||
ns_clientstate_t state;
|
||||
int naccepts;
|
||||
int nreads;
|
||||
int nsends;
|
||||
int nrecvs;
|
||||
int nupdates;
|
||||
int nctls;
|
||||
bool shuttingdown;
|
||||
unsigned int attributes;
|
||||
isc_task_t *task;
|
||||
@@ -209,8 +202,7 @@ struct ns_client {
|
||||
isc_nmhandle_t *handle;
|
||||
unsigned char *tcpbuf;
|
||||
dns_message_t *message;
|
||||
unsigned char *recvbuf;
|
||||
unsigned char sendbuf[NS_CLIENT_SEND_BUFFER_SIZE];
|
||||
unsigned char *sendbuf;
|
||||
dns_rdataset_t *opt;
|
||||
uint16_t udpsize;
|
||||
uint16_t extflags;
|
||||
@@ -224,7 +216,6 @@ struct ns_client {
|
||||
isc_time_t tnow;
|
||||
dns_name_t signername; /*%< [T]SIG key name */
|
||||
dns_name_t *signer; /*%< NULL if not valid sig */
|
||||
bool mortal; /*%< Die after handling request */
|
||||
isc_quota_t *recursionquota;
|
||||
|
||||
isc_sockaddr_t peeraddr;
|
||||
@@ -234,8 +225,6 @@ struct ns_client {
|
||||
|
||||
dns_ecs_t ecs; /*%< EDNS client subnet sent by client */
|
||||
|
||||
struct in6_pktinfo pktinfo;
|
||||
isc_dscp_t dscp;
|
||||
/*%
|
||||
* Information about recent FORMERR response(s), for
|
||||
* FORMERR loop avoidance. This is separate for each
|
||||
@@ -364,7 +353,7 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds);
|
||||
|
||||
isc_result_t
|
||||
ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr, ns_interface_t *ifp,
|
||||
isc_timermgr_t *timermgr, ns_interface_t *ifp, int ncpus,
|
||||
ns_clientmgr_t **managerp);
|
||||
/*%<
|
||||
* Create a client manager.
|
||||
|
||||
@@ -103,7 +103,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
|
||||
isc_socketmgr_t *socketmgr, isc_nm_t *nm,
|
||||
dns_dispatchmgr_t *dispatchmgr, isc_task_t *task,
|
||||
unsigned int udpdisp, dns_geoip_databases_t *geoip,
|
||||
ns_interfacemgr_t **mgrp);
|
||||
int ncpus, ns_interfacemgr_t **mgrp);
|
||||
/*%<
|
||||
* Create a new interface manager.
|
||||
*
|
||||
|
||||
@@ -75,6 +75,7 @@ struct ns_interfacemgr {
|
||||
isc_timermgr_t * timermgr; /*%< Timer manager. */
|
||||
isc_socketmgr_t * socketmgr; /*%< Socket manager. */
|
||||
isc_nm_t * nm; /*%< Net manager. */
|
||||
int ncpus; /*%< Number of workers . */
|
||||
dns_dispatchmgr_t * dispatchmgr;
|
||||
unsigned int generation; /*%< Current generation no. */
|
||||
ns_listenlist_t * listenon4;
|
||||
@@ -181,6 +182,7 @@ ns_interfacemgr_create(isc_mem_t *mctx,
|
||||
isc_task_t *task,
|
||||
unsigned int udpdisp,
|
||||
dns_geoip_databases_t *geoip,
|
||||
int ncpus,
|
||||
ns_interfacemgr_t **mgrp)
|
||||
{
|
||||
isc_result_t result;
|
||||
@@ -219,6 +221,7 @@ ns_interfacemgr_create(isc_mem_t *mctx,
|
||||
mgr->listenon4 = NULL;
|
||||
mgr->listenon6 = NULL;
|
||||
mgr->udpdisp = udpdisp;
|
||||
mgr->ncpus = ncpus;
|
||||
atomic_init(&mgr->shuttingdown, false);
|
||||
|
||||
ISC_LIST_INIT(mgr->interfaces);
|
||||
@@ -425,7 +428,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
|
||||
result = ns_clientmgr_create(mgr->mctx, mgr->sctx,
|
||||
mgr->taskmgr, mgr->timermgr, ifp,
|
||||
&ifp->clientmgr);
|
||||
mgr->ncpus, &ifp->clientmgr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"ns_clientmgr_create() failed: %s",
|
||||
|
||||
@@ -237,7 +237,7 @@ create_managers(void) {
|
||||
|
||||
CHECK(ns_interfacemgr_create(mctx, sctx, taskmgr, timermgr,
|
||||
socketmgr, nm, dispatchmgr, maintask,
|
||||
ncpus, NULL, &interfacemgr));
|
||||
ncpus, NULL, 1, &interfacemgr));
|
||||
|
||||
CHECK(ns_listenlist_default(mctx, port, -1, true, &listenon));
|
||||
ns_interfacemgr_setlistenon4(interfacemgr, listenon);
|
||||
|
||||
@@ -223,6 +223,9 @@ my @substdefh = ("CONFIGARGS",
|
||||
"HAVE_HMAC_CTX_GET_MD",
|
||||
"HAVE_HMAC_CTX_NEW",
|
||||
"HAVE_HMAC_CTX_RESET",
|
||||
"HAVE_UV_HANDLE_GET_DATA",
|
||||
"HAVE_UV_HANDLE_SET_DATA",
|
||||
"HAVE_UV_IMPORT",
|
||||
);
|
||||
|
||||
# for platform.h
|
||||
@@ -1321,6 +1324,10 @@ if ($use_libuv eq "auto") {
|
||||
last;
|
||||
}
|
||||
}
|
||||
$configdefh{"HAVE_UV_HANDLE_SET_DATA"} = 1;
|
||||
$configdefh{"HAVE_UV_HANDLE_GET_DATA"} = 1;
|
||||
$configdefh{"HAVE_UV_IMPORT"} = 1;
|
||||
|
||||
|
||||
# If we have one use it otherwise report the error
|
||||
if ($use_libuv eq "auto") {
|
||||
|
||||
Reference in New Issue
Block a user