Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unjostable queries for configured upstreams #1201

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 48 additions & 23 deletions services/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
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);
}
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(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;
Expand Down
6 changes: 6 additions & 0 deletions services/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
27 changes: 27 additions & 0 deletions testdata/mesh_jostle_priority.tdir/mesh_jostle_priority.conf
Original file line number Diff line number Diff line change
@@ -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@
16 changes: 16 additions & 0 deletions testdata/mesh_jostle_priority.tdir/mesh_jostle_priority.dsc
Original file line number Diff line number Diff line change
@@ -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:
12 changes: 12 additions & 0 deletions testdata/mesh_jostle_priority.tdir/mesh_jostle_priority.post
Original file line number Diff line number Diff line change
@@ -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
36 changes: 36 additions & 0 deletions testdata/mesh_jostle_priority.tdir/mesh_jostle_priority.pre
Original file line number Diff line number Diff line change
@@ -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
31 changes: 31 additions & 0 deletions testdata/mesh_jostle_priority.tdir/mesh_jostle_priority.test
Original file line number Diff line number Diff line change
@@ -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
35 changes: 35 additions & 0 deletions testdata/mesh_jostle_priority.tdir/mesh_jostle_priority.testns
Original file line number Diff line number Diff line change
@@ -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

Loading