- 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:
Wouter Wijngaards 2017-02-23 12:05:05 +00:00
parent 14ec958b8f
commit 35ae8ef313
21 changed files with 3090 additions and 2323 deletions

View File

@ -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 \

View File

@ -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
View File

@ -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"

View File

@ -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])])

View File

@ -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;
}

View File

@ -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;
};
/**

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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.

View File

@ -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;

View File

@ -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)

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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) }

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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
View 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
View 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 */