From: Grigorii Demidov Date: Mon, 4 Apr 2016 12:16:10 +0000 (+0200) Subject: layer/rrcache: record cache miss avoided for wcard answers X-Git-Tag: v1.0.0~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=11ee839e9158254ebcb940123fcd14106bd9ffe7;p=thirdparty%2Fknot-resolver.git layer/rrcache: record cache miss avoided for wcard answers --- diff --git a/lib/layer/rrcache.c b/lib/layer/rrcache.c index c9edde52e..cd0e75475 100644 --- a/lib/layer/rrcache.c +++ b/lib/layer/rrcache.c @@ -14,6 +14,8 @@ along with this program. If not, see . */ +#include + #include #include #include @@ -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); diff --git a/tests/test_cache.c b/tests/test_cache.c index e5a64eb92..8fcd86ab9 100644 --- a/tests/test_cache.c +++ b/tests/test_cache.c @@ -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, ×tamp), 0); assert_int_not_equal(kr_cache_peek(&global_txn, KR_CACHE_USER, NULL, KNOT_RRTYPE_TSIG, &entry, ×tamp), 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, ×tamp); + int ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, ×tamp); 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, ×tamp); + ret = kr_cache_peek_rr(txn, &cache_rr, &rank, &flags, ×tamp); 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; }