return 1;
}
-int
+int
cachedb_init(struct module_env* env, int id)
{
struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1,
return 1;
}
-void
+void
cachedb_deinit(struct module_env* env, int id)
{
struct cachedb_env* cachedb_env;
if(!env || !env->modinfo[id])
return;
cachedb_env = (struct cachedb_env*)env->modinfo[id];
- /* free contents */
- /* TODO */
if(cachedb_env->enabled) {
(*cachedb_env->backend->deinit)(env, cachedb_env);
}
-
free(cachedb_env);
env->modinfo[id] = NULL;
}
struct cachedb_qstate* ATTR_UNUSED(iq),
struct cachedb_env* ie, int id)
{
+ qstate->is_cachedb_answer = 0;
/* check if we are enabled, and skip if so */
if(!ie->enabled) {
/* pass request to next module */
qstate->ext_state[id] = module_wait_module;
return;
}
+ qstate->is_cachedb_answer = 1;
/* we are done with the query */
qstate->ext_state[id] = module_finished;
return;
cachedb_handle_response(struct module_qstate* qstate,
struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id)
{
+ qstate->is_cachedb_answer = 0;
/* check if we are not enabled or instructed to not cache, and skip */
if(!ie->enabled || qstate->no_cache_store) {
/* we are done with the query */
if(!ssl_printf(ssl, "num.query.subnet_cache"SQ"%lu\n",
(unsigned long)s->svr.num_query_subnet_cache)) return 0;
#endif /* CLIENT_SUBNET */
+#ifdef USE_CACHEDB
+ if(!ssl_printf(ssl, "num.query.cachedb"SQ"%lu\n",
+ (unsigned long)s->svr.num_query_cachedb)) return 0;
+#endif /* USE_CACHEDB */
return 1;
}
s->svr.num_query_subnet = 0;
s->svr.num_query_subnet_cache = 0;
#endif
+#ifdef USE_CACHEDB
+ s->svr.num_query_cachedb += (long long)worker->env.mesh->ans_cachedb;
+#else
+ s->svr.num_query_cachedb = 0;
+#endif
/* get tcp accept usage */
s->svr.tcp_accept_usage = 0;
total->svr.unwanted_replies += a->svr.unwanted_replies;
total->svr.unwanted_queries += a->svr.unwanted_queries;
total->svr.tcp_accept_usage += a->svr.tcp_accept_usage;
+#ifdef USE_CACHEDB
+ total->svr.num_query_cachedb += a->svr.num_query_cachedb;
+#endif
for(i=0; i<UB_STATS_QTYPE_NUM; i++)
total->svr.qtype[i] += a->svr.qtype[i];
for(i=0; i<UB_STATS_QCLASS_NUM; i++)
.I num.query.subnet_cache
Number of queries answered from the edns client subnet cache. These are
counted as cachemiss by the main counters, but hit the client subnet
-specific cache, after getting processed by the edns client subnet module.
+specific cache after getting processed by the edns client subnet module.
+.TP
+.I num.query.cachedb
+Number of queries answered from the external cache of cachedb.
+These are counted as cachemiss by the main counters, but hit the cachedb
+external cache after getting processed by the cachedb module.
.TP
.I num.rpz.action.<rpz_action>
Number of queries answered using configured RPZ policy, per RPZ action type.
/** number of queries answered from edns-subnet specific data, and
* the answer was from the edns-subnet cache. */
long long num_query_subnet_cache;
+ /** number of queries served from cachedb */
+ long long num_query_cachedb;
/** number of bytes in the stream wait buffers */
long long mem_stream_wait;
/** number of bytes in the HTTP2 query buffers */
mesh->stats_jostled = 0;
mesh->stats_dropped = 0;
mesh->ans_expired = 0;
+ mesh->ans_cachedb = 0;
mesh->max_reply_states = env->cfg->num_queries_per_thread;
mesh->max_forever_states = (mesh->max_reply_states+1)/2;
#ifndef S_SPLINT_S
}
prev = r;
prev_buffer = r_buffer;
+
+ /* Account for each reply sent. */
+ if(mstate->s.env->cfg->stat_extended
+ && mstate->s.is_cachedb_answer) {
+ mstate->s.env->mesh->ans_cachedb++;
+ }
}
}
if(mstate->reply_list) {
if(!mstate->reply_list && !mstate->cb_list &&
mstate->super_set.count == 0)
mstate->s.env->mesh->num_detached_states++;
+ /* Account for each callback. */
+ if(mstate->s.env->cfg->stat_extended
+ && mstate->s.is_cachedb_answer) {
+ mstate->s.env->mesh->ans_cachedb++;
+ }
mesh_do_callback(mstate, mstate->s.return_rcode, rep, c, &tv);
}
}
mesh->ans_secure = 0;
mesh->ans_bogus = 0;
mesh->ans_expired = 0;
+ mesh->ans_cachedb = 0;
memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM);
memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
mesh->ans_nodata = 0;
if(!mstate->reply_list && !mstate->cb_list &&
mstate->super_set.count == 0)
qstate->env->mesh->num_detached_states++;
+ /* Account for each callback. */
+ mesh->ans_expired++;
mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c, &tv);
}
}
size_t stats_dropped;
/** stats, number of expired replies sent */
size_t ans_expired;
+ /** stats, number of cached replies from cachedb */
+ size_t ans_cachedb;
/** number of replies sent */
size_t replies_sent;
/** sum of waiting times for the replies */
PR_UL("num.query.subnet", s->svr.num_query_subnet);
PR_UL("num.query.subnet_cache", s->svr.num_query_subnet_cache);
#endif
+#ifdef USE_CACHEDB
+ PR_UL("num.query.cachedb", s->svr.num_query_cachedb);
+#endif
}
/** print statistics out of memory structures */
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh
+
+PRE="../.."
+if grep "define USE_CACHEDB 1" $PRE/config.h; then
+ USE_CACHEDB=1
+ echo "USE_CACHEDB=1" >> .tpkg.var.test
+fi
+
get_random_port 4
UNBOUND_PORT=$RND_PORT
FWD_PORT=$(($RND_PORT + 1))
# make config file
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' -e 's/@EXPIREDPORT\@/'$FWD_EXPIRED_PORT'/' -e 's/@CONTROL_PORT\@/'$CONTROL_PORT'/' < stat_values.conf > ub.conf
+sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' -e 's/@EXPIREDPORT\@/'$FWD_EXPIRED_PORT'/' -e 's/@CONTROL_PORT\@/'$CONTROL_PORT'/' < stat_values_cachedb.conf > ub_cachedb.conf
# start unbound in the background
-PRE="../.."
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
FOUND_STATS_FILE=found_stats.$$
REST_STATS_FILE=rest_stats.$$
-DEBUG=0
+DEBUG=1
# Write stats to $STATS_FILE.
# Call this when you want to get stats from unbound.
infra.cache.count=2"
+if test x$USE_CACHEDB == "x1"; then
+
+# Bring the cachedb configured Unbound up
+kill_pid $UNBOUND_PID # kill current Unbound
+$PRE/unbound -d -c ub_cachedb.conf >unbound.log 2>&1 &
+UNBOUND_PID=$!
+echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
+wait_unbound_up unbound.log
+
+echo
+echo "[ Check cachedb cache miss. ]"
+echo "> dig www.example.com."
+dig @127.0.0.1 -p $UNBOUND_PORT 0ttl.example.com. | tee outfile
+echo "> check answer"
+if grep "0.0.0.1" outfile; then
+ echo "OK"
+else
+ end 1
+fi
+check_stats "\
+total.num.queries=1
+total.num.cachemiss=1
+total.num.cachehits=0
+total.num.recursivereplies=1
+num.query.type.A=1
+num.query.class.IN=1
+num.query.opcode.QUERY=1
+num.query.flags.RD=1
+num.query.flags.AD=1
+num.query.edns.present=1
+num.query.udpout=1
+num.query.cachedb=0
+msg.cache.count=0
+rrset.cache.count=1
+infra.cache.count=1
+num.answer.rcode.NOERROR=1"
+
+echo
+echo "[ Check cachedb cache hit. ]"
+echo "> dig www.example.com."
+dig @127.0.0.1 -p $UNBOUND_PORT 0ttl.example.com. | tee outfile
+echo "> check answer"
+if grep "0.0.0.1" outfile; then
+ echo "OK"
+else
+ end 1
+fi
+check_stats "\
+total.num.queries=1
+total.num.cachemiss=1
+total.num.cachehits=0
+total.num.recursivereplies=1
+num.query.type.A=1
+num.query.class.IN=1
+num.query.opcode.QUERY=1
+num.query.flags.RD=1
+num.query.flags.AD=1
+num.query.edns.present=1
+num.query.udpout=0
+num.query.cachedb=1
+msg.cache.count=1
+rrset.cache.count=1
+infra.cache.count=1
+num.answer.rcode.NOERROR=1"
+
+echo
+echo "[ Check cachedb cache hit with stat reset ]"
+echo "> dig www.example.com."
+dig @127.0.0.1 -p $UNBOUND_PORT 0ttl.example.com. | tee outfile
+echo "> check answer"
+if grep "0.0.0.1" outfile; then
+ echo "OK"
+else
+ end 1
+fi
+check_stats "\
+total.num.queries=1
+total.num.cachemiss=0
+total.num.cachehits=1
+total.num.recursivereplies=0
+num.query.type.A=1
+num.query.class.IN=1
+num.query.opcode.QUERY=1
+num.query.flags.RD=1
+num.query.flags.AD=1
+num.query.edns.present=1
+num.query.cachedb=0
+msg.cache.count=1
+rrset.cache.count=1
+infra.cache.count=1
+num.answer.rcode.NOERROR=1"
+
+fi # USE_CACHEDB
+
end 0
SECTION ANSWER
1ttl 1 IN A 1.1.1.1
ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+REPLY QR AA NOERROR
+ADJUST copy_id
+SECTION QUESTION
+0ttl IN A
+SECTION ANSWER
+0ttl 0 IN A 0.0.0.1
+ENTRY_END
--- /dev/null
+server:
+ verbosity: 5
+ module-config: "cachedb iterator"
+ serve-expired: yes
+ num-threads: 1
+ interface: 127.0.0.1
+ port: @PORT@
+ use-syslog: no
+ directory: ""
+ pidfile: "unbound.pid"
+ chroot: ""
+ username: ""
+ do-not-query-localhost: no
+ extended-statistics: yes
+ identity: "stat_values"
+ outbound-msg-retry: 0
+ root-key-sentinel: no
+ trust-anchor-signaling: no
+
+ local-zone: local.zone static
+ local-data: "www.local.zone A 192.0.2.1"
+remote-control:
+ control-enable: yes
+ control-interface: 127.0.0.1
+ # control-interface: ::1
+ control-port: @CONTROL_PORT@
+ server-key-file: "unbound_server.key"
+ server-cert-file: "unbound_server.pem"
+ control-key-file: "unbound_control.key"
+ control-cert-file: "unbound_control.pem"
+forward-zone:
+ name: "."
+ forward-addr: "127.0.0.1@@TOPORT@"
+forward-zone:
+ name: "expired."
+ forward-addr: "127.0.0.1@@EXPIREDPORT@"
* those servers. By comparing expiry time with qstarttime for type NS.
*/
time_t qstarttime;
+ /** whether a message from cachedb will be used for the reply */
+ int is_cachedb_answer;
/**
* Attributes of clients that share the qstate that may affect IP-based