]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
rrcache: avoid knot_pkt_put
authorVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 31 Mar 2017 14:18:56 +0000 (16:18 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 31 Mar 2017 14:29:56 +0000 (16:29 +0200)
Constructing the wire format in rrcache was useless and it took 2-4 %
of time in the resperf profile.  Let's also pass the rank (used soon).

lib/cache.h
lib/layer/rrcache.c
lib/resolve.c
lib/utils.h

index 7a6f2af40f6d98021ff198721ab189e83a3c74d5..d694f4ab688f8fcc844e5250953d5bffeb3c4c6f 100644 (file)
@@ -21,6 +21,9 @@
 #include "lib/defines.h"
 #include "contrib/ucw/config.h" /*uint*/
 
+/** When knot_pkt is passed from cache without ->wire, this is the ->size. */
+static const size_t PKT_SIZE_NOWIRE = -1;
+
 /** Cache entry tag */
 enum kr_cache_tag {
        KR_CACHE_RR   = 'R',
index e7f3a0f853d9c12f55d7c5518ec725e5a5ddbf43..cc45e0acc1de702e28abb911e7fdb80c17b84c92 100644 (file)
     along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+/** @file rrcache.c
+ *
+ * This builtin module caches resource records from/for positive answers.
+ *
+ * Produce phase: if an RRset answering the query exists, the packet is filled
+ * by it, including the corresponding RRSIGs (subject to some conditions).
+ * Such a packet is recognizable: pkt->size == PKT_SIZE_NOWIRE.
+ * The ranks are stored in *rrset->additional.
+ *
+ * TODO
+ */
+
 #include <assert.h>
 
 #include <libknot/descriptor.h>
@@ -43,6 +55,11 @@ static int loot_rr(struct kr_cache *cache, knot_pkt_t *pkt, const knot_dname_t *
                   uint16_t rrclass, uint16_t rrtype, struct kr_query *qry,
                   uint8_t *rank, uint8_t *flags, bool fetch_rrsig, uint8_t lowest_rank)
 {
+       const bool precond = rank && flags;
+       if (!precond) {
+               assert(false);
+               return kr_error(EINVAL);
+       }
        /* Check if record exists in cache */
        int ret = 0;
        uint32_t drift = qry->timestamp.tv_sec;
@@ -57,7 +74,7 @@ static int loot_rr(struct kr_cache *cache, knot_pkt_t *pkt, const knot_dname_t *
                return ret;
        }
 
-       if (rank && (*rank < lowest_rank)) {
+       if (*rank < lowest_rank) {
                return kr_error(ENOENT);
        }
 
@@ -66,7 +83,6 @@ static int loot_rr(struct kr_cache *cache, 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. */
@@ -83,13 +99,42 @@ static int loot_rr(struct kr_cache *cache, knot_pkt_t *pkt, const knot_dname_t *
        /* Update packet answer */
        knot_rrset_t rr_copy;
        ret = kr_cache_materialize(&rr_copy, &cache_rr, drift, qry->reorder, &pkt->mm);
-       if (ret == 0) {
-               ret = knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &rr_copy, KNOT_PF_FREE);
-               if (ret != 0) {
-                       knot_rrset_clear(&rr_copy, &pkt->mm);
+       if (ret) {
+               return ret;
+       }
+
+       uint8_t *rr_rank = mm_alloc(&pkt->mm, sizeof(*rr_rank));
+       if (!rr_rank) {
+               goto enomem;
+       }
+       *rr_rank = *rank;
+       rr_copy.additional = rr_rank;
+       /* Ensure the pkt->rr array is long enough. */
+       if (pkt->rrset_count + 1 > pkt->rrset_allocd) {
+               size_t rrset_allocd = pkt->rrset_count + 2;
+               pkt->rr = mm_realloc(&pkt->mm, pkt->rr,
+                                       sizeof(pkt->rr[0]) * rrset_allocd,
+                                       sizeof(pkt->rr[0]) * pkt->rrset_allocd);
+               if (!pkt->rr) {
+                       goto enomem;
+               }
+               pkt->rr_info = mm_realloc(&pkt->mm, pkt->rr,
+                                       sizeof(pkt->rr_info[0]) * rrset_allocd,
+                                       sizeof(pkt->rr_info[0]) * pkt->rrset_allocd);
+               if (!pkt->rr_info) {
+                       goto enomem;
                }
+               pkt->rrset_allocd = rrset_allocd;
        }
+       /* Append the RR array. */
+       assert(pkt->sections[pkt->current].count == pkt->rrset_count);
+       pkt->rr[pkt->rrset_count] = rr_copy;
+       pkt->sections[pkt->current].count = ++pkt->rrset_count;
        return ret;
+enomem:
+       knot_rrset_clear(&rr_copy, &pkt->mm);
+       mm_free(&pkt->mm, rr_rank);
+       return kr_error(ENOMEM);
 }
 
 /** @internal Try to find a shortcut directly to searched record. */
@@ -153,7 +198,7 @@ static int rrcache_peek(kr_layer_t *ctx, knot_pkt_t *pkt)
        if (ret == 0) {
                VERBOSE_MSG(qry, "=> satisfied from cache\n");
                qry->flags |= QUERY_CACHED|QUERY_NO_MINIMIZE;
-               pkt->parsed = pkt->size;
+               pkt->parsed = pkt->size = PKT_SIZE_NOWIRE;
                knot_wire_set_qr(pkt->wire);
                knot_wire_set_aa(pkt->wire);
                return KR_STATE_DONE;
index 34915be29f6516cbf2dd65a86a422b0933b81983..b484db6893cf53f2dffe356f102269dd65b4e7a9 100644 (file)
@@ -1025,7 +1025,7 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
                request->state = KR_STATE_PRODUCE;
                ITERATE_LAYERS(request, qry, produce, packet);
                if (request->state != KR_STATE_FAIL && knot_wire_get_qr(packet->wire)) {
-                       /* Produced an answer, consume it. */
+                       /* Produced an answer from cache, consume it. */
                        qry->secret = 0;
                        request->state = KR_STATE_CONSUME;
                        ITERATE_LAYERS(request, qry, consume, packet);
index da87e64c5543758e8f680b1c5ba2b991347d20b1..1b57417a538eb76b4674f2f827ced7b20050e68a 100644 (file)
@@ -66,12 +66,30 @@ static inline void *mm_alloc(knot_mm_t *mm, size_t size)
 }
 static inline void mm_free(knot_mm_t *mm, void *what)
 {
-       if (mm) { 
+       if (mm) {
                if (mm->free)
                        mm->free(what);
        }
        else free(what);
 }
+static inline void *mm_realloc(knot_mm_t *mm, void *what, size_t size, size_t prev_size)
+{
+       if (mm) {
+               void *p = mm->alloc(mm->ctx, size);
+               if (p == NULL) {
+                       return NULL;
+               } else {
+                       if (what) {
+                               memcpy(p, what,
+                                      prev_size < size ? prev_size : size);
+                       }
+                       mm_free(mm, what);
+                       return p;
+               }
+       } else {
+               return realloc(what, size);
+       }
+}
 /* @endcond */
 
 /** Return time difference in miliseconds.