mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 06:37:08 +00:00
- Patch from Luiz Fernando Softov for Stats Shared Memory.
- unbound-control stats_shm command prints stats using shared memory, which uses less cpu. git-svn-id: file:///svn/unbound/trunk@4020 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
14ec958b8f
commit
35ae8ef313
15
Makefile.in
15
Makefile.in
@ -104,6 +104,7 @@ iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \
|
||||
services/localzone.c services/mesh.c services/modstack.c services/view.c \
|
||||
services/outbound_list.c services/outside_network.c util/alloc.c \
|
||||
util/config_file.c util/configlexer.c util/configparser.c \
|
||||
util/shm_side/shm_main.c \
|
||||
util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
|
||||
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
|
||||
util/rtt.c util/storage/dnstree.c util/storage/lookup3.c \
|
||||
@ -156,7 +157,7 @@ UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ)
|
||||
DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \
|
||||
daemon/remote.c daemon/stats.c daemon/unbound.c daemon/worker.c @WIN_DAEMON_SRC@
|
||||
DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo remote.lo stats.lo unbound.lo \
|
||||
DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo shm_main.lo remote.lo stats.lo unbound.lo \
|
||||
worker.lo @WIN_DAEMON_OBJ@
|
||||
DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ) @WIN_DAEMON_OBJ_LINK@
|
||||
@ -180,7 +181,7 @@ daemon/worker.c daemon/acl_list.c daemon/daemon.c daemon/stats.c \
|
||||
testcode/replay.c testcode/fake_event.c
|
||||
TESTBOUND_OBJ=testbound.lo replay.lo fake_event.lo
|
||||
TESTBOUND_OBJ_LINK=$(TESTBOUND_OBJ) testpkts.lo worker.lo acl_list.lo \
|
||||
daemon.lo stats.lo $(COMMON_OBJ_WITHOUT_NETCALL) ub_event.lo $(SLDNS_OBJ) \
|
||||
daemon.lo stats.lo shm_main.lo $(COMMON_OBJ_WITHOUT_NETCALL) ub_event.lo $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ)
|
||||
LOCKVERIFY_SRC=testcode/lock_verify.c
|
||||
LOCKVERIFY_OBJ=lock_verify.lo
|
||||
@ -751,6 +752,10 @@ alloc.lo alloc.o: $(srcdir)/util/alloc.c config.h $(srcdir)/util/alloc.h $(srcdi
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
|
||||
shm_main.lo shm_main.o: $(srcdir)/util/shm_side/shm_main.c config.h $(srcdir)/daemon/worker.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/daemon/stats.h $(srcdir)/util/config_file.h $(srcdir)/validator/validator.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/log.h\
|
||||
$(srcdir)/util/shm_side/shm_main.h
|
||||
config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/configyyrename.h $(srcdir)/util/config_file.h util/configparser.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
@ -986,7 +991,7 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h
|
||||
$(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/util/shm_side/shm_main.h
|
||||
remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
|
||||
@ -1038,7 +1043,7 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/libworker.h
|
||||
$(srcdir)/libunbound/libworker.h $(srcdir)/util/shm_side/shm_main.h
|
||||
testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/testcode/testpkts.h \
|
||||
$(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h \
|
||||
$(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/daemon/unbound.c \
|
||||
@ -1084,7 +1089,7 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h
|
||||
$(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/util/shm_side/shm_main.h
|
||||
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
|
@ -385,6 +385,9 @@
|
||||
/* Define to 1 if you have the `SHA512_Update' function. */
|
||||
#undef HAVE_SHA512_UPDATE
|
||||
|
||||
/* Define to 1 if you have the `shmget' function. */
|
||||
#undef HAVE_SHMGET
|
||||
|
||||
/* Define to 1 if you have the `sigprocmask' function. */
|
||||
#undef HAVE_SIGPROCMASK
|
||||
|
||||
@ -457,6 +460,9 @@
|
||||
/* Define to 1 if systemd should be used */
|
||||
#undef HAVE_SYSTEMD
|
||||
|
||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||
#undef HAVE_SYS_IPC_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
@ -466,6 +472,9 @@
|
||||
/* Define to 1 if you have the <sys/sha2.h> header file. */
|
||||
#undef HAVE_SYS_SHA2_H
|
||||
|
||||
/* Define to 1 if you have the <sys/shm.h> header file. */
|
||||
#undef HAVE_SYS_SHM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
|
4
configure
vendored
4
configure
vendored
@ -14423,7 +14423,7 @@ CC=$lt_save_CC
|
||||
|
||||
|
||||
# Checks for header files.
|
||||
for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h
|
||||
for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/ipc.h sys/shm.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
|
||||
@ -19252,7 +19252,7 @@ if test "$ac_res" != no; then :
|
||||
|
||||
fi
|
||||
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget
|
||||
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"
|
||||
|
@ -305,7 +305,7 @@ AC_CHECK_TOOL(STRIP, strip)
|
||||
ACX_LIBTOOL_C_ONLY
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
@ -1149,7 +1149,7 @@ AC_INCLUDES_DEFAULT
|
||||
#endif
|
||||
])
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
@ -605,6 +606,9 @@ daemon_fork(struct daemon* daemon)
|
||||
#endif
|
||||
signal_handling_playback(daemon->workers[0]);
|
||||
|
||||
if (!shm_main_init(daemon))
|
||||
log_warn("SHM has failed");
|
||||
|
||||
/* Start resolver service on main thread. */
|
||||
#ifdef HAVE_SYSTEMD
|
||||
sd_notify(0, "READY=1");
|
||||
@ -619,6 +623,9 @@ daemon_fork(struct daemon* daemon)
|
||||
/* we exited! a signal happened! Stop other threads */
|
||||
daemon_stop_others(daemon);
|
||||
|
||||
/* Shutdown SHM */
|
||||
shm_main_shutdown(daemon);
|
||||
|
||||
daemon->need_to_exit = daemon->workers[0]->need_to_exit;
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ struct local_zones;
|
||||
struct views;
|
||||
struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
struct shm_main_info;
|
||||
|
||||
#include "dnstap/dnstap_config.h"
|
||||
#ifdef USE_DNSTAP
|
||||
@ -118,6 +119,7 @@ struct daemon {
|
||||
/** the dnstap environment master value, copied and changed by threads*/
|
||||
struct dt_env* dtenv;
|
||||
#endif
|
||||
struct shm_main_info* shm_info;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/libworker.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
@ -1169,6 +1170,10 @@ void worker_stat_timer_cb(void* arg)
|
||||
server_stats_log(&worker->stats, worker, worker->thread_num);
|
||||
mesh_stats(worker->env.mesh, "mesh has");
|
||||
worker_mem_report(worker, NULL);
|
||||
/* SHM is enabled, process data to SHM */
|
||||
if (worker->daemon->cfg->shm_enable) {
|
||||
shm_main_run(worker);
|
||||
}
|
||||
if(!worker->daemon->cfg->stat_cumulative) {
|
||||
worker_stats_clear(worker);
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
23 February 2017: Wouter
|
||||
- Fix doc/CNAME-basedRedirectionDesignNotes.pdf zone static to
|
||||
redirect.
|
||||
- Patch from Luiz Fernando Softov for Stats Shared Memory.
|
||||
- unbound-control stats_shm command prints stats using shared memory,
|
||||
which uses less cpu.
|
||||
|
||||
22 February 2017: Wouter
|
||||
- Fix #1224: Fix that defaults should not fall back to "Program Files
|
||||
|
@ -19,6 +19,14 @@ server:
|
||||
# Set to "" or 0 to disable. Default is disabled.
|
||||
# statistics-interval: 0
|
||||
|
||||
# enable shm for stats, default no. if you enable also enable
|
||||
# statistics-interval, every time it also writes stats to the
|
||||
# shared memory segment keyed with shm-key.
|
||||
# shm-enable: no
|
||||
|
||||
# shm for stats uses this key, and key+1 for the shared mem segment.
|
||||
# shm-key: 11777
|
||||
|
||||
# enable cumulative statistics, without clearing them after printing.
|
||||
# statistics-cumulative: no
|
||||
|
||||
|
@ -273,6 +273,12 @@ int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen)
|
||||
return sldns_wire2str_rcode_print(&s, &slen, rcode);
|
||||
}
|
||||
|
||||
int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen)
|
||||
{
|
||||
/* use arguments as temporary variables */
|
||||
return sldns_wire2str_opcode_print(&s, &slen, opcode);
|
||||
}
|
||||
|
||||
int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
|
||||
{
|
||||
/* use arguments as temporary variables */
|
||||
|
@ -441,6 +441,17 @@ int sldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len);
|
||||
*/
|
||||
int sldns_wire2str_rcode_buf(int rcode, char* str, size_t len);
|
||||
|
||||
/**
|
||||
* Convert host format opcode to a string. 'QUERY', 'NOTIFY', 'UPDATE'.
|
||||
* With user buffer.
|
||||
* @param rcode: rcode as integer in host order
|
||||
* @param str: the string to write to.
|
||||
* @param len: length of str.
|
||||
* @return the number of characters for this element, excluding zerobyte.
|
||||
* Is larger or equal than str_len if output was truncated.
|
||||
*/
|
||||
int sldns_wire2str_opcode_buf(int opcode, char* str, size_t len);
|
||||
|
||||
/**
|
||||
* Convert wire dname to a string, "example.com.". With user buffer.
|
||||
* @param dname: the dname in uncompressed wireformat.
|
||||
|
@ -58,7 +58,17 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/locks.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "daemon/stats.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/pkthdr.h"
|
||||
|
||||
#ifdef HAVE_SYS_IPC_H
|
||||
#include "sys/ipc.h"
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SHM_H
|
||||
#include "sys/shm.h"
|
||||
#endif
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
@ -81,6 +91,9 @@ usage(void)
|
||||
printf(" (this flushes data, stats, requestlist)\n");
|
||||
printf(" stats print statistics\n");
|
||||
printf(" stats_noreset peek at statistics\n");
|
||||
#ifdef HAVE_SHMGET
|
||||
printf(" stats_shm print statistics using shm\n");
|
||||
#endif
|
||||
printf(" status display status of server\n");
|
||||
printf(" verbosity <number> change logging detail\n");
|
||||
printf(" log_reopen close and open the logfile\n");
|
||||
@ -138,6 +151,246 @@ usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHMGET
|
||||
/** what to put on statistics lines between var and value, ": " or "=" */
|
||||
#define SQ "="
|
||||
/** if true, inhibits a lot of =0 lines from the stats output */
|
||||
static const int inhibit_zero = 1;
|
||||
/** divide sum of timers to get average */
|
||||
static void
|
||||
timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
size_t leftover;
|
||||
if(d == 0) {
|
||||
avg->tv_sec = 0;
|
||||
avg->tv_usec = 0;
|
||||
return;
|
||||
}
|
||||
avg->tv_sec = sum->tv_sec / d;
|
||||
avg->tv_usec = sum->tv_usec / d;
|
||||
/* handle fraction from seconds divide */
|
||||
leftover = sum->tv_sec - avg->tv_sec*d;
|
||||
avg->tv_usec += (leftover*1000000)/d;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print unsigned long stats value */
|
||||
#define PR_UL_NM(str, var) printf("%s."str SQ"%lu\n", nm, (unsigned long)(var));
|
||||
#define PR_UL(str, var) printf(str SQ"%lu\n", (unsigned long)(var));
|
||||
#define PR_UL_SUB(str, nm, var) printf(str".%s"SQ"%lu\n", nm, (unsigned long)(var));
|
||||
#define PR_TIMEVAL(str, var) printf(str SQ ARG_LL "d.%6.6d\n", \
|
||||
(long long)var.tv_sec, (unsigned)var.tv_usec);
|
||||
#define PR_LL(str, var) printf(str SQ ARG_LL"d\n", (long long)(var));
|
||||
|
||||
/** print stat block */
|
||||
static void pr_stats(const char* nm, struct stats_info* s)
|
||||
{
|
||||
struct timeval avg;
|
||||
PR_UL_NM("num.queries", s->svr.num_queries);
|
||||
PR_UL_NM("num.queries_ip_ratelimited",
|
||||
s->svr.num_queries_ip_ratelimited);
|
||||
PR_UL_NM("num.cachehits",
|
||||
s->svr.num_queries - s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.prefetch", s->svr.num_queries_prefetch);
|
||||
PR_UL_NM("num.zero_ttl", s->svr.zero_ttl_responses);
|
||||
PR_UL_NM("num.recursivereplies", s->mesh_replies_sent);
|
||||
printf("%s.requestlist.avg"SQ"%g\n", nm,
|
||||
(s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)?
|
||||
(double)s->svr.sum_query_list_size/
|
||||
(s->svr.num_queries_missed_cache+
|
||||
s->svr.num_queries_prefetch) : 0.0);
|
||||
PR_UL_NM("requestlist.max", s->svr.max_query_list_size);
|
||||
PR_UL_NM("requestlist.overwritten", s->mesh_jostled);
|
||||
PR_UL_NM("requestlist.exceeded", s->mesh_dropped);
|
||||
PR_UL_NM("requestlist.current.all", s->mesh_num_states);
|
||||
PR_UL_NM("requestlist.current.user", s->mesh_num_reply_states);
|
||||
timeval_divide(&avg, &s->mesh_replies_sum_wait, s->mesh_replies_sent);
|
||||
printf("%s.", nm);
|
||||
PR_TIMEVAL("recursion.time.avg", avg);
|
||||
printf("%s.recursion.time.median"SQ"%g\n", nm, s->mesh_time_median);
|
||||
PR_UL_NM("tcpusage", s->svr.tcp_accept_usage);
|
||||
}
|
||||
|
||||
/** print uptime */
|
||||
static void print_uptime(struct shm_stat_info* shm_stat)
|
||||
{
|
||||
PR_TIMEVAL("time.now", shm_stat->time.now);
|
||||
PR_TIMEVAL("time.up", shm_stat->time.up);
|
||||
PR_TIMEVAL("time.elapsed", shm_stat->time.elapsed);
|
||||
}
|
||||
|
||||
/** print memory usage */
|
||||
static void print_mem(struct shm_stat_info* shm_stat)
|
||||
{
|
||||
PR_LL("mem.cache.rrset", shm_stat->mem.rrset);
|
||||
PR_LL("mem.cache.message", shm_stat->mem.msg);
|
||||
PR_LL("mem.cache.iterator", shm_stat->mem.iter);
|
||||
PR_LL("mem.cache.validator", shm_stat->mem.val);
|
||||
}
|
||||
|
||||
/** print histogram */
|
||||
static void print_hist(struct stats_info* s)
|
||||
{
|
||||
struct timehist* hist;
|
||||
size_t i;
|
||||
hist = timehist_setup();
|
||||
if(!hist)
|
||||
fatal_exit("out of memory");
|
||||
timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST);
|
||||
for(i=0; i<hist->num; i++) {
|
||||
printf("histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%lu\n",
|
||||
(int)hist->buckets[i].lower.tv_sec,
|
||||
(int)hist->buckets[i].lower.tv_usec,
|
||||
(int)hist->buckets[i].upper.tv_sec,
|
||||
(int)hist->buckets[i].upper.tv_usec,
|
||||
(unsigned long)hist->buckets[i].count);
|
||||
}
|
||||
timehist_delete(hist);
|
||||
}
|
||||
|
||||
/** print extended */
|
||||
static void print_extended(struct stats_info* s)
|
||||
{
|
||||
int i;
|
||||
char nm[16];
|
||||
|
||||
/* TYPE */
|
||||
for(i=0; i<STATS_QTYPE_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qtype[i] == 0)
|
||||
continue;
|
||||
sldns_wire2str_type_buf(i, nm, sizeof(nm));
|
||||
PR_UL_SUB("num.query.type", nm, s->svr.qtype[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.qtype_big) {
|
||||
PR_UL("num.query.type.other", s->svr.qtype_big);
|
||||
}
|
||||
|
||||
/* CLASS */
|
||||
for(i=0; i<STATS_QCLASS_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qclass[i] == 0)
|
||||
continue;
|
||||
sldns_wire2str_class_buf(i, nm, sizeof(nm));
|
||||
PR_UL_SUB("num.query.class", nm, s->svr.qclass[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.qclass_big) {
|
||||
PR_UL("num.query.class.other", s->svr.qclass_big);
|
||||
}
|
||||
|
||||
/* OPCODE */
|
||||
for(i=0; i<STATS_OPCODE_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qopcode[i] == 0)
|
||||
continue;
|
||||
sldns_wire2str_opcode_buf(i, nm, sizeof(nm));
|
||||
PR_UL_SUB("num.query.opcode", nm, s->svr.qopcode[i]);
|
||||
}
|
||||
|
||||
/* transport */
|
||||
PR_UL("num.query.tcp", s->svr.qtcp);
|
||||
PR_UL("num.query.tcpout", s->svr.qtcp_outgoing);
|
||||
PR_UL("num.query.ipv6", s->svr.qipv6);
|
||||
|
||||
/* flags */
|
||||
PR_UL("num.query.flags.QR", s->svr.qbit_QR);
|
||||
PR_UL("num.query.flags.AA", s->svr.qbit_AA);
|
||||
PR_UL("num.query.flags.TC", s->svr.qbit_TC);
|
||||
PR_UL("num.query.flags.RD", s->svr.qbit_RD);
|
||||
PR_UL("num.query.flags.RA", s->svr.qbit_RA);
|
||||
PR_UL("num.query.flags.Z", s->svr.qbit_Z);
|
||||
PR_UL("num.query.flags.AD", s->svr.qbit_AD);
|
||||
PR_UL("num.query.flags.CD", s->svr.qbit_CD);
|
||||
PR_UL("num.query.edns.present", s->svr.qEDNS);
|
||||
PR_UL("num.query.edns.DO", s->svr.qEDNS_DO);
|
||||
|
||||
/* RCODE */
|
||||
for(i=0; i<STATS_RCODE_NUM; i++) {
|
||||
/* Always include RCODEs 0-5 */
|
||||
if(inhibit_zero && i > LDNS_RCODE_REFUSED && s->svr.ans_rcode[i] == 0)
|
||||
continue;
|
||||
sldns_wire2str_rcode_buf(i, nm, sizeof(nm));
|
||||
PR_UL_SUB("num.answer.rcode", nm, s->svr.ans_rcode[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.ans_rcode_nodata) {
|
||||
PR_UL("num.answer.rcode.nodata", s->svr.ans_rcode_nodata);
|
||||
}
|
||||
/* validation */
|
||||
PR_UL("num.answer.secure", s->svr.ans_secure);
|
||||
PR_UL("num.answer.bogus", s->svr.ans_bogus);
|
||||
PR_UL("num.rrset.bogus", s->svr.rrset_bogus);
|
||||
/* threat detection */
|
||||
PR_UL("unwanted.queries", s->svr.unwanted_queries);
|
||||
PR_UL("unwanted.replies", s->svr.unwanted_replies);
|
||||
/* cache counts */
|
||||
PR_UL("msg.cache.count", s->svr.msg_cache_count);
|
||||
PR_UL("rrset.cache.count", s->svr.rrset_cache_count);
|
||||
PR_UL("infra.cache.count", s->svr.infra_cache_count);
|
||||
PR_UL("key.cache.count", s->svr.key_cache_count);
|
||||
}
|
||||
|
||||
/** print statistics out of memory structures */
|
||||
static void do_stats_shm(struct config_file* cfg, struct stats_info* stats,
|
||||
struct shm_stat_info* shm_stat)
|
||||
{
|
||||
int i;
|
||||
char nm[16];
|
||||
for(i=0; i<cfg->num_threads; i++) {
|
||||
snprintf(nm, sizeof(nm), "thread%d", i);
|
||||
pr_stats(nm, &stats[i+1]);
|
||||
}
|
||||
pr_stats("total", &stats[0]);
|
||||
print_uptime(shm_stat);
|
||||
if(cfg->stat_extended) {
|
||||
print_mem(shm_stat);
|
||||
print_hist(stats);
|
||||
print_extended(stats);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SHMGET */
|
||||
|
||||
/** print statistics from shm memory segment */
|
||||
static void print_stats_shm(const char* cfgfile)
|
||||
{
|
||||
#ifdef HAVE_SHMGET
|
||||
struct config_file* cfg;
|
||||
struct stats_info* stats;
|
||||
struct shm_stat_info* shm_stat;
|
||||
int id_ctl, id_arr;
|
||||
/* read config */
|
||||
if(!(cfg = config_create()))
|
||||
fatal_exit("out of memory");
|
||||
if(!config_read(cfg, cfgfile, NULL))
|
||||
fatal_exit("could not read config file");
|
||||
/* get shm segments */
|
||||
id_ctl = shmget(cfg->shm_key, sizeof(int), SHM_R|SHM_W);
|
||||
if(id_ctl == -1) {
|
||||
fatal_exit("shmget(%d): %s", cfg->shm_key, strerror(errno));
|
||||
}
|
||||
id_arr = shmget(cfg->shm_key+1, sizeof(int), SHM_R|SHM_W);
|
||||
if(id_arr == -1) {
|
||||
fatal_exit("shmget(%d): %s", cfg->shm_key+1, strerror(errno));
|
||||
}
|
||||
shm_stat = (struct shm_stat_info*)shmat(id_ctl, NULL, 0);
|
||||
if(shm_stat == (void*)-1) {
|
||||
fatal_exit("shmat(%d): %s", id_ctl, strerror(errno));
|
||||
}
|
||||
stats = (struct stats_info*)shmat(id_arr, NULL, 0);
|
||||
if(stats == (void*)-1) {
|
||||
fatal_exit("shmat(%d): %s", id_arr, strerror(errno));
|
||||
}
|
||||
|
||||
/* print the stats */
|
||||
do_stats_shm(cfg, stats, shm_stat);
|
||||
|
||||
/* shutdown */
|
||||
shmdt(shm_stat);
|
||||
shmdt(stats);
|
||||
config_delete(cfg);
|
||||
#else
|
||||
(void)cfgfile;
|
||||
#endif /* HAVE_SHMGET */
|
||||
}
|
||||
|
||||
/** exit with ssl error */
|
||||
static void ssl_err(const char* s)
|
||||
{
|
||||
@ -160,13 +413,13 @@ setup_ctx(struct config_file* cfg)
|
||||
if(!s_cert || !c_key || !c_cert)
|
||||
fatal_exit("out of memory");
|
||||
}
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
if(!ctx)
|
||||
ssl_err("could not allocate SSL_CTX pointer");
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
|
||||
!= SSL_OP_NO_SSLv2)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv2");
|
||||
if(cfg->remote_control_use_cert) {
|
||||
if(cfg->remote_control_use_cert) {
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
|
||||
!= SSL_OP_NO_SSLv3)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv3");
|
||||
@ -441,44 +694,10 @@ int main(int argc, char* argv[])
|
||||
log_init(NULL, 0, NULL);
|
||||
checklock_start();
|
||||
#ifdef USE_WINSOCK
|
||||
if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
|
||||
fatal_exit("WSAStartup failed: %s", wsa_strerror(r));
|
||||
/* use registry config file in preference to compiletime location */
|
||||
if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile")))
|
||||
cfgfile = CONFIGFILE;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
#endif
|
||||
ERR_load_SSL_strings();
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(0, NULL);
|
||||
#endif
|
||||
|
||||
if(!RAND_status()) {
|
||||
/* try to seed it */
|
||||
unsigned char buf[256];
|
||||
unsigned int seed=(unsigned)time(NULL) ^ (unsigned)getpid();
|
||||
unsigned int v = seed;
|
||||
size_t i;
|
||||
for(i=0; i<256/sizeof(v); i++) {
|
||||
memmove(buf+i*sizeof(v), &v, sizeof(v));
|
||||
v = v*seed + (unsigned int)i;
|
||||
}
|
||||
RAND_seed(buf, 256);
|
||||
log_warn("no entropy, seeding openssl PRNG with time\n");
|
||||
}
|
||||
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "c:s:qh")) != -1) {
|
||||
switch(c) {
|
||||
@ -508,11 +727,51 @@ int main(int argc, char* argv[])
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
if(argc >= 1 && strcmp(argv[0], "stats_shm")==0) {
|
||||
print_stats_shm(cfgfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
|
||||
fatal_exit("WSAStartup failed: %s", wsa_strerror(r));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
#endif
|
||||
ERR_load_SSL_strings();
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(0, NULL);
|
||||
#endif
|
||||
|
||||
if(!RAND_status()) {
|
||||
/* try to seed it */
|
||||
unsigned char buf[256];
|
||||
unsigned int seed=(unsigned)time(NULL) ^ (unsigned)getpid();
|
||||
unsigned int v = seed;
|
||||
size_t i;
|
||||
for(i=0; i<256/sizeof(v); i++) {
|
||||
memmove(buf+i*sizeof(v), &v, sizeof(v));
|
||||
v = v*seed + (unsigned int)i;
|
||||
}
|
||||
RAND_seed(buf, 256);
|
||||
log_warn("no entropy, seeding openssl PRNG with time\n");
|
||||
}
|
||||
|
||||
ret = go(cfgfile, svr, quiet, argc, argv);
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
WSACleanup();
|
||||
#endif
|
||||
checklock_stop();
|
||||
return ret;
|
||||
|
@ -257,6 +257,8 @@ config_create(void)
|
||||
cfg->ratelimit_factor = 10;
|
||||
cfg->qname_minimisation = 0;
|
||||
cfg->qname_minimisation_strict = 0;
|
||||
cfg->shm_enable = 0;
|
||||
cfg->shm_key = 11777;
|
||||
return cfg;
|
||||
error_exit:
|
||||
config_delete(cfg);
|
||||
@ -380,6 +382,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||
else S_STR("log-identity:", log_identity)
|
||||
else S_YNO("extended-statistics:", stat_extended)
|
||||
else S_YNO("statistics-cumulative:", stat_cumulative)
|
||||
else S_YNO("shm-enable:", shm_enable)
|
||||
else S_NUMBER_OR_ZERO("shm-key:", shm_key)
|
||||
else S_YNO("do-ip4:", do_ip4)
|
||||
else S_YNO("do-ip6:", do_ip6)
|
||||
else S_YNO("do-udp:", do_udp)
|
||||
@ -697,6 +701,8 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
else O_DEC(opt, "statistics-interval", stat_interval)
|
||||
else O_YNO(opt, "statistics-cumulative", stat_cumulative)
|
||||
else O_YNO(opt, "extended-statistics", stat_extended)
|
||||
else O_YNO(opt, "shm-enable", shm_enable)
|
||||
else O_DEC(opt, "shm-key", shm_key)
|
||||
else O_YNO(opt, "use-syslog", use_syslog)
|
||||
else O_STR(opt, "log-identity", log_identity)
|
||||
else O_YNO(opt, "log-time-ascii", log_time_ascii)
|
||||
|
@ -422,6 +422,10 @@ struct config_file {
|
||||
/** minimise QNAME in strict mode, minimise according to RFC.
|
||||
* Do not apply fallback */
|
||||
int qname_minimisation_strict;
|
||||
/* SHM data - true if shm is enabled */
|
||||
int shm_enable;
|
||||
/* SHM data - key for the shm */
|
||||
int shm_key;
|
||||
};
|
||||
|
||||
/** from cfg username, after daemonise setup performed */
|
||||
|
3029
util/configlexer.c
3029
util/configlexer.c
File diff suppressed because it is too large
Load Diff
@ -343,6 +343,8 @@ insecure-lan-zones{COLON} { YDVAR(1, VAR_INSECURE_LAN_ZONES) }
|
||||
statistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) }
|
||||
statistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) }
|
||||
extended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) }
|
||||
shm-enable{COLON} { YDVAR(1, VAR_SHM_ENABLE) }
|
||||
shm-key{COLON} { YDVAR(1, VAR_SHM_KEY) }
|
||||
remote-control{COLON} { YDVAR(0, VAR_REMOTE_CONTROL) }
|
||||
control-enable{COLON} { YDVAR(1, VAR_CONTROL_ENABLE) }
|
||||
control-interface{COLON} { YDVAR(1, VAR_CONTROL_INTERFACE) }
|
||||
|
1572
util/configparser.c
1572
util/configparser.c
File diff suppressed because it is too large
Load Diff
@ -231,7 +231,9 @@ extern int yydebug;
|
||||
VAR_SERVE_EXPIRED = 441,
|
||||
VAR_FAKE_DSA = 442,
|
||||
VAR_LOG_IDENTITY = 443,
|
||||
VAR_USE_SYSTEMD = 444
|
||||
VAR_USE_SYSTEMD = 444,
|
||||
VAR_SHM_ENABLE = 445,
|
||||
VAR_SHM_KEY = 446
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
@ -422,6 +424,8 @@ extern int yydebug;
|
||||
#define VAR_FAKE_DSA 442
|
||||
#define VAR_LOG_IDENTITY 443
|
||||
#define VAR_USE_SYSTEMD 444
|
||||
#define VAR_SHM_ENABLE 445
|
||||
#define VAR_SHM_KEY 446
|
||||
|
||||
/* Value type. */
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
@ -432,7 +436,7 @@ union YYSTYPE
|
||||
|
||||
char* str;
|
||||
|
||||
#line 436 "util/configparser.h" /* yacc.c:1909 */
|
||||
#line 440 "util/configparser.h" /* yacc.c:1909 */
|
||||
};
|
||||
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
|
@ -135,7 +135,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
|
||||
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_FAKE_DSA
|
||||
%token VAR_LOG_IDENTITY
|
||||
%token VAR_USE_SYSTEMD
|
||||
%token VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
@ -213,7 +213,8 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
server_local_zone_override | server_access_control_tag_action |
|
||||
server_access_control_tag_data | server_access_control_view |
|
||||
server_qname_minimisation_strict | server_serve_expired |
|
||||
server_fake_dsa | server_log_identity | server_use_systemd
|
||||
server_fake_dsa | server_log_identity | server_use_systemd |
|
||||
server_shm_enable | server_shm_key
|
||||
;
|
||||
stubstart: VAR_STUB_ZONE
|
||||
{
|
||||
@ -314,6 +315,26 @@ server_extended_statistics: VAR_EXTENDED_STATISTICS STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_shm_enable: VAR_SHM_ENABLE STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_shm_enable:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->shm_enable = (strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_shm_key: VAR_SHM_KEY STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_shm_key:%s)\n", $2));
|
||||
if(strcmp($2, "") == 0 || strcmp($2, "0") == 0)
|
||||
cfg_parser->cfg->shm_key = 0;
|
||||
else if(atoi($2) == 0)
|
||||
yyerror("number expected");
|
||||
else cfg_parser->cfg->shm_key = atoi($2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_port: VAR_PORT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_port:%s)\n", $2));
|
||||
|
273
util/shm_side/shm_main.c
Normal file
273
util/shm_side/shm_main.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* util/shm_side/shm_main.c - SHM for statistics transport
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions for the SHM implementation.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "shm_main.h"
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_SYS_IPC_H
|
||||
#include "sys/ipc.h"
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SHM_H
|
||||
#include "sys/shm.h"
|
||||
#endif
|
||||
#include "errno.h"
|
||||
#include "config.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/stats.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "validator/validator.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/log.h"
|
||||
|
||||
#ifdef HAVE_SHMGET
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_subtract(struct timeval* d, const struct timeval* end,
|
||||
const struct timeval* start)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
time_t end_usec = end->tv_usec;
|
||||
d->tv_sec = end->tv_sec - start->tv_sec;
|
||||
if(end_usec < start->tv_usec) {
|
||||
end_usec += 1000000;
|
||||
d->tv_sec--;
|
||||
}
|
||||
d->tv_usec = end_usec - start->tv_usec;
|
||||
#endif
|
||||
}
|
||||
#endif /* HAVE_SHMGET */
|
||||
|
||||
int shm_main_init(struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SHMGET
|
||||
struct shm_stat_info *shm_stat;
|
||||
int shm_size;
|
||||
|
||||
/* sanitize */
|
||||
if(!daemon)
|
||||
return 0;
|
||||
if(daemon->cfg->stat_interval == 0)
|
||||
log_warn("shm-enable is yes but statistics-interval is 0");
|
||||
|
||||
/* Statistics to maintain the number of thread + total */
|
||||
shm_size = (sizeof(struct stats_info) * (daemon->num + 1));
|
||||
|
||||
/* Allocation of needed memory */
|
||||
daemon->shm_info = (struct shm_main_info*)calloc(1, shm_size);
|
||||
|
||||
/* Sanitize */
|
||||
if(!daemon->shm_info) {
|
||||
log_err("shm fail: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
|
||||
daemon->shm_info->key = daemon->cfg->shm_key;
|
||||
|
||||
/* Check for previous create SHM */
|
||||
daemon->shm_info->id_ctl = shmget(daemon->shm_info->key, sizeof(int), SHM_R);
|
||||
daemon->shm_info->id_arr = shmget(daemon->shm_info->key + 1, sizeof(int), SHM_R);
|
||||
|
||||
/* Destroy previous SHM */
|
||||
if (daemon->shm_info->id_ctl >= 0)
|
||||
shmctl(daemon->shm_info->id_ctl, IPC_RMID, NULL);
|
||||
|
||||
/* Destroy previous SHM */
|
||||
if (daemon->shm_info->id_arr >= 0)
|
||||
shmctl(daemon->shm_info->id_ctl, IPC_RMID, NULL);
|
||||
|
||||
/* SHM: Create the segment */
|
||||
daemon->shm_info->id_ctl = shmget(daemon->shm_info->key, sizeof(struct shm_stat_info), IPC_CREAT | 0666);
|
||||
|
||||
if (daemon->shm_info->id_ctl < 0)
|
||||
{
|
||||
log_err("SHM failed(id_ctl) cannot shmget(key %d) %s",
|
||||
daemon->shm_info->key, strerror(errno));
|
||||
|
||||
/* Just release memory unused */
|
||||
free(daemon->shm_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
daemon->shm_info->id_arr = shmget(daemon->shm_info->key + 1, shm_size, IPC_CREAT | 0666);
|
||||
|
||||
if (daemon->shm_info->id_arr < 0)
|
||||
{
|
||||
log_err("SHM failed(id_arr) cannot shmget(key %d + 1) %s",
|
||||
daemon->shm_info->key, strerror(errno));
|
||||
|
||||
/* Just release memory unused */
|
||||
free(daemon->shm_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SHM: attach the segment */
|
||||
daemon->shm_info->ptr_ctl = (struct shm_stat_info*)
|
||||
shmat(daemon->shm_info->id_ctl, NULL, 0);
|
||||
if(daemon->shm_info->ptr_ctl == (void *) -1) {
|
||||
log_err("SHM failed(ctl) cannot shmat(%d) %s",
|
||||
daemon->shm_info->id_ctl, strerror(errno));
|
||||
|
||||
/* Just release memory unused */
|
||||
free(daemon->shm_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
daemon->shm_info->ptr_arr = (struct stats_info*)
|
||||
shmat(daemon->shm_info->id_arr, NULL, 0);
|
||||
|
||||
if (daemon->shm_info->ptr_arr == (void *) -1)
|
||||
{
|
||||
log_err("SHM failed(arr) cannot shmat(%d) %s",
|
||||
daemon->shm_info->id_arr, strerror(errno));
|
||||
|
||||
/* Just release memory unused */
|
||||
free(daemon->shm_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zero fill SHM to stand clean while is not filled by other events */
|
||||
memset(daemon->shm_info->ptr_ctl, 0, sizeof(struct shm_stat_info));
|
||||
memset(daemon->shm_info->ptr_arr, 0, shm_size);
|
||||
|
||||
shm_stat = daemon->shm_info->ptr_ctl;
|
||||
shm_stat->num_threads = daemon->num;
|
||||
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif /* HAVE_SHMGET */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void shm_main_shutdown(struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SHMGET
|
||||
/* web are OK, just disabled */
|
||||
if(!daemon->cfg->shm_enable)
|
||||
return;
|
||||
|
||||
verbose(VERB_DETAIL, "SHM shutdown - KEY [%d] - ID CTL [%d] ARR [%d] - PTR CTL [%p] ARR [%p]",
|
||||
daemon->shm_info->key, daemon->shm_info->id_ctl, daemon->shm_info->id_arr, daemon->shm_info->ptr_ctl, daemon->shm_info->ptr_arr);
|
||||
|
||||
/* Destroy previous SHM */
|
||||
if (daemon->shm_info->id_ctl >= 0)
|
||||
shmctl(daemon->shm_info->id_ctl, IPC_RMID, NULL);
|
||||
|
||||
if (daemon->shm_info->id_arr >= 0)
|
||||
shmctl(daemon->shm_info->id_arr, IPC_RMID, NULL);
|
||||
|
||||
if (daemon->shm_info->ptr_ctl)
|
||||
shmdt(daemon->shm_info->ptr_ctl);
|
||||
|
||||
if (daemon->shm_info->ptr_arr)
|
||||
shmdt(daemon->shm_info->ptr_arr);
|
||||
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif /* HAVE_SHMGET */
|
||||
}
|
||||
|
||||
void shm_main_run(struct worker *worker)
|
||||
{
|
||||
#ifdef HAVE_SHMGET
|
||||
struct shm_stat_info *shm_stat;
|
||||
struct stats_info *stat_total;
|
||||
struct stats_info *stat_info;
|
||||
int modstack;
|
||||
int offset;
|
||||
|
||||
verbose(VERB_DETAIL, "SHM run - worker [%d] - daemon [%p] - timenow(%u) - timeboot(%u)",
|
||||
worker->thread_num, worker->daemon, (unsigned)worker->env.now_tv->tv_sec, (unsigned)worker->daemon->time_boot.tv_sec);
|
||||
|
||||
offset = worker->thread_num + 1;
|
||||
stat_total = worker->daemon->shm_info->ptr_arr;
|
||||
stat_info = worker->daemon->shm_info->ptr_arr + offset;
|
||||
|
||||
/* Copy data to the current position */
|
||||
server_stats_compile(worker, stat_info, 0);
|
||||
|
||||
/* First thread, zero fill total, and copy general info */
|
||||
if (worker->thread_num == 0) {
|
||||
|
||||
/* Copy data to the current position */
|
||||
memset(stat_total, 0, sizeof(struct stats_info));
|
||||
|
||||
/* Point to data into SHM */
|
||||
shm_stat = worker->daemon->shm_info->ptr_ctl;
|
||||
shm_stat->time.now = *worker->env.now_tv;
|
||||
|
||||
timeval_subtract(&shm_stat->time.up, &shm_stat->time.now, &worker->daemon->time_boot);
|
||||
timeval_subtract(&shm_stat->time.elapsed, &shm_stat->time.now, &worker->daemon->time_last_stat);
|
||||
|
||||
shm_stat->mem.msg = slabhash_get_mem(worker->env.msg_cache);
|
||||
shm_stat->mem.rrset = slabhash_get_mem(&worker->env.rrset_cache->table);
|
||||
shm_stat->mem.val = 0;
|
||||
shm_stat->mem.iter = 0;
|
||||
|
||||
modstack = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
if(modstack != -1) {
|
||||
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->mods.mod[modstack]->get_mem));
|
||||
shm_stat->mem.val = (*worker->env.mesh->mods.mod[modstack]->get_mem)(&worker->env, modstack);
|
||||
}
|
||||
modstack = modstack_find(&worker->env.mesh->mods, "iterator");
|
||||
if(modstack != -1) {
|
||||
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->mods.mod[modstack]->get_mem));
|
||||
shm_stat->mem.iter = (*worker->env.mesh->mods.mod[modstack]->get_mem)(&worker->env, modstack);
|
||||
}
|
||||
}
|
||||
|
||||
server_stats_add(stat_total, stat_info);
|
||||
|
||||
/* print the thread statistics */
|
||||
stat_total->mesh_time_median /= (double)worker->daemon->num;
|
||||
|
||||
#else
|
||||
(void)worker;
|
||||
#endif /* HAVE_SHMGET */
|
||||
}
|
85
util/shm_side/shm_main.h
Normal file
85
util/shm_side/shm_main.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* util/shm_side/shm_main.h - control the shared memory for unbound.
|
||||
*
|
||||
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions for the SHM side.
|
||||
*/
|
||||
|
||||
#ifndef UTIL_SHM_SIDE_MAIN_H
|
||||
#define UTIL_SHM_SIDE_MAIN_H
|
||||
struct daemon;
|
||||
struct worker;
|
||||
|
||||
/** Some global statistics that are not in struct stats_info,
|
||||
* this struct is shared on a shm segment */
|
||||
struct shm_stat_info {
|
||||
|
||||
int num_threads;
|
||||
|
||||
struct {
|
||||
struct timeval now;
|
||||
struct timeval up;
|
||||
struct timeval elapsed;
|
||||
} time;
|
||||
|
||||
struct {
|
||||
size_t msg;
|
||||
size_t rrset;
|
||||
size_t val;
|
||||
size_t iter;
|
||||
} mem;
|
||||
};
|
||||
|
||||
/**
|
||||
* The SHM info.
|
||||
*/
|
||||
struct shm_main_info {
|
||||
/** stats_info array, shared memory segment.
|
||||
* [0] is totals, [1..thread_num] are per-thread stats */
|
||||
struct stats_info* ptr_arr;
|
||||
/** the global stats block, shared memory segment */
|
||||
struct shm_stat_info* ptr_ctl;
|
||||
int key;
|
||||
int id_ctl;
|
||||
int id_arr;
|
||||
};
|
||||
|
||||
int shm_main_init(struct daemon* daemon);
|
||||
void shm_main_shutdown(struct daemon* daemon);
|
||||
void shm_main_run(struct worker *worker);
|
||||
|
||||
#endif /* UTIL_SHM_SIDE_MAIN_H */
|
Loading…
Reference in New Issue
Block a user