From: Marek VavruĊĦa Date: Wed, 13 May 2015 09:52:16 +0000 (+0200) Subject: lib/layer: answer both m12n/full names from cache X-Git-Tag: v1.0.0-beta1~174 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d1ee64186c8f29c98df143b992660dfd95d4805;p=thirdparty%2Fknot-resolver.git lib/layer: answer both m12n/full names from cache previously only queried names were resolved from cache, this meant that if the target name was present in cache but a server on the search path dropped from it, it would refetch it - this is a problem when a loadbalancer with very short TTL was in search path --- diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c index 11cd46638..963cb47a7 100644 --- a/lib/layer/iterate.c +++ b/lib/layer/iterate.c @@ -50,7 +50,7 @@ static const knot_dname_t *minimized_qname(struct kr_query *query, uint16_t *qty { /* Minimization disabled. */ const knot_dname_t *qname = query->sname; - if (query->flags & QUERY_NO_MINIMIZE) { + if (query->flags & (QUERY_NO_MINIMIZE|QUERY_CACHED)) { return qname; } diff --git a/lib/layer/pktcache.c b/lib/layer/pktcache.c index 050aec156..35522c8ff 100644 --- a/lib/layer/pktcache.c +++ b/lib/layer/pktcache.c @@ -54,10 +54,9 @@ static void adjust_ttl(knot_rrset_t *rr, uint32_t drift) } } -static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint8_t tag, uint32_t timestamp) +static int loot_cache_set(namedb_txn_t *txn, knot_pkt_t *pkt, uint8_t tag, const knot_dname_t *qname, + uint16_t rrtype, uint32_t timestamp) { - const knot_dname_t *qname = knot_pkt_qname(pkt); - uint16_t rrtype = knot_pkt_qtype(pkt); struct kr_cache_entry *entry; entry = kr_cache_peek(txn, tag, qname, rrtype, ×tamp); if (!entry) { /* Not in the cache */ @@ -91,6 +90,24 @@ static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint8_t tag, uint32_t return ret; } +static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, struct kr_query *qry, uint8_t tag) +{ + uint32_t timestamp = qry->timestamp.tv_sec; + /* Try direct match first */ + const knot_dname_t *qname = qry->sname; + uint16_t rrtype = qry->stype; + int ret = loot_cache_set(txn, pkt, tag, qname, rrtype, timestamp); + if (ret == kr_error(ENOENT)) { + /* Try minimized name second */ + qname = knot_pkt_qname(pkt); + rrtype = knot_pkt_qtype(pkt); + if (!knot_dname_is_equal(qname, qry->sname)) { + ret = loot_cache_set(txn, pkt, tag, qname, rrtype, timestamp); + } + } + return ret; +} + static int peek(knot_layer_t *ctx, knot_pkt_t *pkt) { struct kr_request *req = ctx->data; @@ -109,8 +126,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt) if (kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY) != 0) { return ctx->state; } - uint32_t timestamp = qry->timestamp.tv_sec; - if (loot_cache(&txn, pkt, get_tag(req->answer), timestamp) != 0) { + if (loot_cache(&txn, pkt, qry, get_tag(req->answer)) != 0) { kr_cache_txn_abort(&txn); return ctx->state; } diff --git a/lib/layer/rrcache.c b/lib/layer/rrcache.c index 2b23742ae..8edc48d9f 100644 --- a/lib/layer/rrcache.c +++ b/lib/layer/rrcache.c @@ -53,11 +53,9 @@ static int loot_rr(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *name, return kr_ok(); } -static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint32_t timestamp) +static int loot_cache_set(namedb_txn_t *txn, knot_pkt_t *pkt, const knot_dname_t *qname, + uint16_t rrclass, uint16_t rrtype, uint32_t timestamp) { - const knot_dname_t *qname = knot_pkt_qname(pkt); - uint16_t rrclass = knot_pkt_qclass(pkt); - uint16_t rrtype = knot_pkt_qtype(pkt); int ret = loot_rr(txn, pkt, qname, rrtype, rrclass, timestamp); if (ret == kr_error(ENOENT) && rrtype != KNOT_RRTYPE_CNAME) { /* Chase CNAME if no direct hit */ ret = loot_rr(txn, pkt, qname, KNOT_RRTYPE_CNAME, rrclass, timestamp); @@ -65,6 +63,25 @@ static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, uint32_t timestamp) return ret; } +static int loot_cache(namedb_txn_t *txn, knot_pkt_t *pkt, struct kr_query *qry) +{ + uint32_t timestamp = qry->timestamp.tv_sec; + /* Try direct match first */ + const knot_dname_t *qname = qry->sname; + uint16_t rrclass = qry->sclass; + uint16_t rrtype = qry->stype; + int ret = loot_cache_set(txn, pkt, qname, rrclass, rrtype, timestamp); + if (ret == kr_error(ENOENT)) { + /* Try minimized name second */ + qname = knot_pkt_qname(pkt); + rrtype = knot_pkt_qtype(pkt); + if (!knot_dname_is_equal(qname, qry->sname)) { + ret = loot_cache_set(txn, pkt, qname, rrclass, rrtype, timestamp); + } + } + return ret; +} + static int peek(knot_layer_t *ctx, knot_pkt_t *pkt) { struct kr_request *req = ctx->data; @@ -84,8 +101,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt) * it may either be a CNAME chain or direct answer. * Only one step of the chain is resolved at a time. */ - uint32_t timestamp = qry->timestamp.tv_sec; - int ret = loot_cache(&txn, pkt, timestamp); + int ret = loot_cache(&txn, pkt, qry); kr_cache_txn_abort(&txn); if (ret == 0) { DEBUG_MSG("=> satisfied from cache\n");