Commit 11ee839e authored by Grigorii Demidov's avatar Grigorii Demidov Committed by Marek Vavrusa
Browse files

layer/rrcache: record cache miss avoided for wcard answers

parent 18b47e33
......@@ -14,6 +14,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <libknot/descriptor.h>
#include <libknot/errcode.h>
#include <libknot/rrset.h>
......@@ -59,6 +61,14 @@ static int loot_rr(struct kr_cache_txn *txn, knot_pkt_t *pkt, const knot_dname_t
qry->flags |= QUERY_EXPIRING;
}
assert(flags != NULL);
if ((*flags) & KR_CACHE_FLAG_WCARD_PROOF) {
/* Record was found, but wildcard answer proof is needed.
* Do not update packet, try to fetch whole packet from pktcache instead. */
qry->flags |= QUERY_DNSSEC_WEXPAND;
return kr_error(ENOENT);
}
/* Update packet question */
if (!knot_dname_is_equal(knot_pkt_qname(pkt), name)) {
kr_pkt_recycle(pkt);
......@@ -87,10 +97,11 @@ static int loot_rrcache(struct kr_cache *cache, knot_pkt_t *pkt, struct kr_query
}
/* Lookup direct match first */
uint8_t rank = 0;
ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, NULL, 0);
uint8_t flags = 0;
ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, &flags, 0);
if (ret != 0 && rrtype != KNOT_RRTYPE_CNAME) { /* Chase CNAME if no direct hit */
rrtype = KNOT_RRTYPE_CNAME;
ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, NULL, 0);
ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, &flags, 0);
}
/* Record is flagged as INSECURE => doesn't have RRSIG. */
if (ret == 0 && (rank & KR_RANK_INSECURE)) {
......@@ -98,7 +109,7 @@ static int loot_rrcache(struct kr_cache *cache, knot_pkt_t *pkt, struct kr_query
qry->flags &= ~QUERY_DNSSEC_WANT;
/* Record may have RRSIG, try to find it. */
} else if (ret == 0 && dobit) {
ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, NULL, true);
ret = loot_rr(&txn, pkt, qry->sname, qry->sclass, rrtype, qry, &rank, &flags, true);
}
kr_cache_txn_abort(&txn);
return ret;
......@@ -202,7 +213,11 @@ static int commit_rr(const char *key, void *val, void *data)
knot_rrset_t query_rr;
knot_rrset_init(&query_rr, rr->owner, rr->type, rr->rclass);
return kr_cache_insert_rr(baton->txn, rr, rank, KR_CACHE_FLAG_NONE, baton->timestamp);
uint8_t flags = KR_CACHE_FLAG_NONE;
if ((rank & KR_RANK_AUTH) && (baton->qry->flags & QUERY_DNSSEC_WEXPAND)) {
flags |= KR_CACHE_FLAG_WCARD_PROOF;
}
return kr_cache_insert_rr(baton->txn, rr, rank, flags, baton->timestamp);
}
static int stash_commit(map_t *stash, struct kr_query *qry, struct kr_cache_txn *txn, struct kr_request *req)
......@@ -303,11 +318,6 @@ static int rrcache_stash(knot_layer_t *ctx, knot_pkt_t *pkt)
if (knot_wire_get_tc(pkt->wire)) {
return ctx->state;
}
/* Do not cache wildcard expanded anwsers,
* as they must deal with packet cache */
if (qry->flags & QUERY_DNSSEC_WEXPAND) {
return ctx->state;
}
/* Cache only positive answers, not meta types or RRSIG. */
const uint16_t qtype = knot_pkt_qtype(pkt);
......
......@@ -243,10 +243,10 @@ static void test_invalid(void **state)
assert_int_not_equal(kr_cache_txn_commit(NULL), 0);
assert_int_not_equal(kr_cache_peek(NULL, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, NULL, &timestamp), 0);
assert_int_not_equal(kr_cache_peek(&global_txn, KR_CACHE_USER, NULL, KNOT_RRTYPE_TSIG, &entry, &timestamp), 0);
assert_int_not_equal(kr_cache_peek_rr(NULL, NULL, NULL, NULL), 0);
assert_int_not_equal(kr_cache_peek_rr(&global_txn, NULL, NULL, NULL), 0);
assert_int_not_equal(kr_cache_insert_rr(&global_txn, NULL, 0, 0), 0);
assert_int_not_equal(kr_cache_insert_rr(NULL, NULL, 0, 0), 0);
assert_int_not_equal(kr_cache_peek_rr(NULL, NULL, NULL, NULL, NULL), 0);
assert_int_not_equal(kr_cache_peek_rr(&global_txn, NULL, NULL, NULL, NULL), 0);
assert_int_not_equal(kr_cache_insert_rr(&global_txn, NULL, 0, 0, 0), 0);
assert_int_not_equal(kr_cache_insert_rr(NULL, NULL, 0, 0, 0), 0);
assert_int_not_equal(kr_cache_insert(NULL, KR_CACHE_USER, dname,
KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data), 0);
assert_int_not_equal(kr_cache_insert(&global_txn, KR_CACHE_USER, NULL,
......@@ -264,7 +264,7 @@ static void test_insert_rr(void **state)
{
test_random_rr(&global_rr, CACHE_TTL);
struct kr_cache_txn *txn = test_txn_write(state);
int ret = kr_cache_insert_rr(txn, &global_rr, 0, CACHE_TIME);
int ret = kr_cache_insert_rr(txn, &global_rr, 0, 0, CACHE_TIME);
if (ret == KNOT_EOK) {
ret = kr_cache_txn_commit(txn);
} else {
......@@ -315,9 +315,10 @@ static void test_query(void **state)
struct kr_cache_txn *txn = test_txn_rdonly(state);
for (uint32_t timestamp = CACHE_TIME; timestamp < CACHE_TIME + CACHE_TTL; ++timestamp) {
uint16_t rank = 0;
uint8_t rank = 0;
uint8_t flags = 0;
uint32_t drift = timestamp;
int query_ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &drift);
int query_ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, &drift);
bool rr_equal = knot_rrset_equal(&global_rr, &cache_rr, KNOT_RRSET_COMPARE_WHOLE);
assert_int_equal(query_ret, KNOT_EOK);
assert_true(rr_equal);
......@@ -329,13 +330,14 @@ static void test_query(void **state)
/* Test cache read (simulate aged entry) */
static void test_query_aged(void **state)
{
uint16_t rank = 0;
uint8_t rank = 0;
uint8_t flags = 0;
uint32_t timestamp = CACHE_TIME + CACHE_TTL + 1;
knot_rrset_t cache_rr;
knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
struct kr_cache_txn *txn = test_txn_rdonly(state);
int ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &timestamp);
int ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, &timestamp);
assert_int_equal(ret, kr_error(ESTALE));
kr_cache_txn_abort(txn);
}
......@@ -343,7 +345,8 @@ static void test_query_aged(void **state)
/* Test cache removal */
static void test_remove(void **state)
{
uint16_t rank = 0;
uint8_t rank = 0;
uint8_t flags = 0;
uint32_t timestamp = CACHE_TIME;
knot_rrset_t cache_rr;
knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
......@@ -351,7 +354,7 @@ static void test_remove(void **state)
struct kr_cache_txn *txn = test_txn_write(state);
int ret = kr_cache_remove(txn, KR_CACHE_RR, cache_rr.owner, cache_rr.type);
assert_int_equal(ret, KNOT_EOK);
ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &timestamp);
ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, &timestamp);
assert_int_equal(ret, KNOT_ENOENT);
kr_cache_txn_commit(txn);
}
......@@ -366,7 +369,7 @@ static void test_fill(void **state)
for (unsigned i = 0; i < CACHE_SIZE; ++i) {
knot_rrset_t rr;
test_random_rr(&rr, CACHE_TTL);
ret = kr_cache_insert_rr(txn, &rr, 0, CACHE_TTL - 1);
ret = kr_cache_insert_rr(txn, &rr, 0, 0, CACHE_TTL - 1);
if (ret != KNOT_EOK) {
break;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment