mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
- Draft the idea of unjostable queries if upstreams are explicitly configured.
This commit is contained in:
+50
-25
@@ -43,6 +43,8 @@
|
||||
* send back to clients.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/outbound_list.h"
|
||||
#include "services/cache/dns.h"
|
||||
@@ -275,37 +277,60 @@ mesh_delete_all(struct mesh_area* mesh)
|
||||
int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
|
||||
{
|
||||
struct mesh_state* m = mesh->jostle_first;
|
||||
/* free space is available */
|
||||
if(mesh->num_reply_states < mesh->max_reply_states)
|
||||
if(mesh->num_reply_states < mesh->max_reply_states) {
|
||||
/* free space is available */
|
||||
return 1;
|
||||
}
|
||||
/* try to kick out a jostle-list item */
|
||||
if(m && m->reply_list && m->list_select == mesh_jostle_list) {
|
||||
/* how old is it? */
|
||||
struct timeval age;
|
||||
struct iter_hints_stub* stub = NULL;
|
||||
struct delegpt* fwd = NULL;
|
||||
/* how old is it? */
|
||||
timeval_subtract(&age, mesh->env->now_tv,
|
||||
&m->reply_list->start_time);
|
||||
if(timeval_smaller(&mesh->jostle_max, &age)) {
|
||||
/* its a goner */
|
||||
log_nametypeclass(VERB_ALGO, "query jostled out to "
|
||||
"make space for a new one",
|
||||
m->s.qinfo.qname, m->s.qinfo.qtype,
|
||||
m->s.qinfo.qclass);
|
||||
/* backup the query */
|
||||
if(qbuf) sldns_buffer_copy(mesh->qbuf_bak, qbuf);
|
||||
/* notify supers */
|
||||
if(m->super_set.count > 0) {
|
||||
verbose(VERB_ALGO, "notify supers of failure");
|
||||
m->s.return_msg = NULL;
|
||||
m->s.return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
mesh_walk_supers(mesh, m);
|
||||
}
|
||||
mesh->stats_jostled ++;
|
||||
mesh_state_delete(&m->s);
|
||||
/* restore the query - note that the qinfo ptr to
|
||||
* the querybuffer is then correct again. */
|
||||
if(qbuf) sldns_buffer_copy(qbuf, mesh->qbuf_bak);
|
||||
return 1;
|
||||
if(!timeval_smaller(&mesh->jostle_max, &age)
|
||||
|| m->has_configured_upstream) {
|
||||
/* can't jostle out; still fresh or has configured
|
||||
* upstreams */
|
||||
return 0;
|
||||
}
|
||||
if((stub=hints_lookup_stub(mesh->env->hints,
|
||||
m->s.qinfo.qname, m->s.qinfo.qclass, NULL, 0))
|
||||
|| (fwd=forwards_find(mesh->env->fwds,
|
||||
m->s.qinfo.qname, m->s.qinfo.qclass, 0))) {
|
||||
/* can't jostle out; there is a configured upstream
|
||||
* for this */
|
||||
m->has_configured_upstream = 1;
|
||||
if(stub) {
|
||||
lock_rw_unlock(&mesh->env->hints->lock);
|
||||
}
|
||||
if(fwd) {
|
||||
lock_rw_unlock(&mesh->env->fwds->lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* its a goner; older than jostle-timeout and there are no
|
||||
* configured upstreams that could give it 'persistence' */
|
||||
log_nametypeclass(VERB_ALGO, "query jostled out to "
|
||||
"make space for a new one",
|
||||
m->s.qinfo.qname, m->s.qinfo.qtype,
|
||||
m->s.qinfo.qclass);
|
||||
/* backup the query */
|
||||
if(qbuf) sldns_buffer_copy(mesh->qbuf_bak, qbuf);
|
||||
/* notify supers */
|
||||
if(m->super_set.count > 0) {
|
||||
verbose(VERB_ALGO, "notify supers of failure");
|
||||
m->s.return_msg = NULL;
|
||||
m->s.return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
mesh_walk_supers(mesh, m);
|
||||
}
|
||||
mesh->stats_jostled ++;
|
||||
mesh_state_delete(&m->s);
|
||||
/* restore the query - note that the qinfo ptr to
|
||||
* the querybuffer is then correct again. */
|
||||
if(qbuf) sldns_buffer_copy(qbuf, mesh->qbuf_bak);
|
||||
return 1;
|
||||
}
|
||||
/* no space for new item */
|
||||
return 0;
|
||||
@@ -1441,7 +1466,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
* Need to explicitly check for rep->security otherwise failed
|
||||
* validation paths may attach to a secure answer. */
|
||||
if(m->s.env->cfg->ede && rep &&
|
||||
(rep->security <= sec_status_bogus ||
|
||||
(rep->security <= sec_status_bogus || rep->security == sec_status_insecure ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
mesh_find_and_attach_ede_and_reason(m, rep, r);
|
||||
}
|
||||
|
||||
@@ -206,6 +206,12 @@ struct mesh_state {
|
||||
/** pointer to this state for uniqueness or NULL */
|
||||
struct mesh_state* unique;
|
||||
|
||||
/** if the qname of this mesh state will go out to one of the
|
||||
* configured upstreams (stub-zone or forward-zone).
|
||||
* Only used when trying to make space (jostle) for new client
|
||||
* queries. */
|
||||
int has_configured_upstream;
|
||||
|
||||
/** true if replies have been sent out (at end for alignment) */
|
||||
uint8_t replies_sent;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
server:
|
||||
num-threads: 1
|
||||
verbosity: 5
|
||||
use-syslog: no
|
||||
directory: ""
|
||||
pidfile: "unbound.pid"
|
||||
chroot: ""
|
||||
username: ""
|
||||
do-not-query-localhost: no
|
||||
use-caps-for-id: no
|
||||
port: @SERVER_PORT@
|
||||
interface: 127.0.0.1
|
||||
|
||||
num-queries-per-thread: 2
|
||||
infra-cache-min-rtt: 1000
|
||||
|
||||
stub-zone:
|
||||
name: "a.slow"
|
||||
stub-addr: 127.0.0.1@@SLOW_STUB_PORT@
|
||||
|
||||
stub-zone:
|
||||
name: "b.slow"
|
||||
stub-addr: 127.0.0.1@@SLOW_STUB_PORT@
|
||||
|
||||
stub-zone:
|
||||
name: "c.fast"
|
||||
stub-addr: 127.0.0.1@@FAST_STUB_PORT@
|
||||
@@ -0,0 +1,16 @@
|
||||
BaseName: mesh_jostle_priority
|
||||
Version: 1.0
|
||||
Description: Check that mesh items will not be jostled if there is a explicitly configured upstream
|
||||
CreationDate: Tue 3 Dec 11:00:00 CEST 2024
|
||||
Maintainer:
|
||||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends:
|
||||
Help:
|
||||
Pre: mesh_jostle_priority.pre
|
||||
Post: mesh_jostle_priority.post
|
||||
Test: mesh_jostle_priority.test
|
||||
AuxFiles:
|
||||
Passed:
|
||||
Failure:
|
||||
@@ -0,0 +1,12 @@
|
||||
# #-- mesh_jostle_priority.post --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# source the test var file when it's there
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
#
|
||||
# do your teardown here
|
||||
. ../common.sh
|
||||
kill_from_pidfile "unbound.pid"
|
||||
kill_pid $SLOW_STUB_PID
|
||||
kill_pid $FAST_STUB_PID
|
||||
cat unbound.log
|
||||
@@ -0,0 +1,36 @@
|
||||
# #-- mesh_jostle_priority.pre--#
|
||||
PRE="../.."
|
||||
. ../common.sh
|
||||
|
||||
get_random_port 3
|
||||
SERVER_PORT=$RND_PORT
|
||||
SLOW_STUB_PORT=$(($RND_PORT + 1))
|
||||
FAST_STUB_PORT=$(($RND_PORT + 2))
|
||||
echo "SERVER_PORT=$SERVER_PORT" >> .tpkg.var.test
|
||||
echo "SLOW_STUB_PORT=$SLOW_STUB_PORT" >> .tpkg.var.test
|
||||
echo "FAST_STUB_PORT=$FAST_STUB_PORT" >> .tpkg.var.test
|
||||
|
||||
# start stub
|
||||
get_ldns_testns
|
||||
$LDNS_TESTNS -v -p $SLOW_STUB_PORT mesh_jostle_priority.testns >stub_slow.log 2>&1 &
|
||||
SLOW_STUB_PID=$!
|
||||
echo "SLOW_STUB_PID=$SLOW_STUB_PID" >> .tpkg.var.test
|
||||
|
||||
$LDNS_TESTNS -v -p $FAST_STUB_PORT mesh_jostle_priority.testns >stub_fast.log 2>&1 &
|
||||
FAST_STUB_PID=$!
|
||||
echo "FAST_STUB_PID=$FAST_STUB_PID" >> .tpkg.var.test
|
||||
|
||||
# make config file
|
||||
sed \
|
||||
-e 's/@SERVER_PORT\@/'$SERVER_PORT'/' \
|
||||
-e 's/@SLOW_STUB_PORT\@/'$SLOW_STUB_PORT'/' \
|
||||
-e 's/@FAST_STUB_PORT\@/'$FAST_STUB_PORT'/' \
|
||||
< mesh_jostle_priority.conf > ub.conf
|
||||
|
||||
# start unbound in the background
|
||||
$PRE/unbound -d -c ub.conf > unbound.log 2>&1 &
|
||||
|
||||
cat .tpkg.var.test
|
||||
wait_ldns_testns_up stub_slow.log
|
||||
wait_ldns_testns_up stub_fast.log
|
||||
wait_unbound_up unbound.log
|
||||
@@ -0,0 +1,31 @@
|
||||
# #-- mesh_jostle_priority.test --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
PRE="../.."
|
||||
. ../common.sh
|
||||
|
||||
get_make
|
||||
(cd $PRE; $MAKE streamtcp)
|
||||
|
||||
teststep "Fire up and forget the two slow queries"
|
||||
$PRE/streamtcp -f 127.0.0.1@$SERVER_PORT -u -n a.slow. A IN b.slow. A IN
|
||||
if test "$?" -ne 0
|
||||
then
|
||||
echo "error with streamtcp"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
teststep "Let time pass so that queries can be jostled based on time"
|
||||
sleep 1
|
||||
|
||||
teststep "Check that the fast query is dropped because the slow ones have explicitly configured upstreams"
|
||||
dig @127.0.0.1 -p $SERVER_PORT +retry=0 +timeout=1 c.fast. > outfile
|
||||
if grep "10.20.30.40" outfile
|
||||
then
|
||||
cat outfile
|
||||
echo "Did not get a drop"
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
@@ -0,0 +1,35 @@
|
||||
$ORIGIN slow.
|
||||
$TTL 3600
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
REPLY QR AA NOERROR
|
||||
ADJUST copy_id sleep=5
|
||||
SECTION QUESTION
|
||||
a IN A
|
||||
SECTION ANSWER
|
||||
a IN A 1.1.1.1
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
REPLY QR AA NOERROR
|
||||
ADJUST copy_id sleep=5
|
||||
SECTION QUESTION
|
||||
b IN A
|
||||
SECTION ANSWER
|
||||
b IN A 2.2.2.2
|
||||
ENTRY_END
|
||||
|
||||
$ORIGIN fast.
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
REPLY QR AA NOERROR
|
||||
ADJUST copy_id
|
||||
SECTION QUESTION
|
||||
c IN A
|
||||
SECTION ANSWER
|
||||
c IN A 10.20.30.40
|
||||
ENTRY_END
|
||||
|
||||
Reference in New Issue
Block a user