resolved: when adding RR to an answer, avoid comparing keys twice

We'd call dns_resource_record_equal(), which calls dns_resource_key_equal()
internally, and then dns_resource_key_equal() a second time. Let's be
a bit smarter, and call dns_resource_key_equal() only once.

(before)
dns_resource_key_hash_func_count=514
dns_resource_key_compare_func_count=275
dns_resource_key_equal_count=62371
4.13s user 0.01s system 99% cpu 4.153 total

(after)
dns_resource_key_hash_func_count=514
dns_resource_key_compare_func_count=276
dns_resource_key_equal_count=31337
2.13s user 0.01s system 99% cpu 2.139 total
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-02-27 10:37:40 +01:00
parent 51969a5893
commit dffb827772
2 changed files with 23 additions and 30 deletions

View File

@ -87,40 +87,33 @@ int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFl
if (a->items[i].ifindex != ifindex)
continue;
r = dns_resource_record_equal(a->items[i].rr, rr);
if (r < 0)
return r;
if (r > 0) {
/* Don't mix contradicting TTLs (see below) */
if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
return -EINVAL;
/* Entry already exists, keep the entry with
* the higher RR. */
if (rr->ttl > a->items[i].rr->ttl) {
dns_resource_record_ref(rr);
dns_resource_record_unref(a->items[i].rr);
a->items[i].rr = rr;
}
a->items[i].flags |= flags;
return 0;
}
r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
if (r < 0)
return r;
if (r > 0) {
/* There's already an RR of the same RRset in
* place! Let's see if the TTLs more or less
* match. We don't really care if they match
* precisely, but we do care whether one is 0
* and the other is not. See RFC 2181, Section
* 5.2. */
if (r == 0)
continue;
if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
return -EINVAL;
/* There's already an RR of the same RRset in place! Let's see if the TTLs more or less
* match. We don't really care if they match precisely, but we do care whether one is 0 and
* the other is not. See RFC 2181, Section 5.2. */
if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
return -EINVAL;
r = dns_resource_record_payload_equal(a->items[i].rr, rr);
if (r < 0)
return r;
if (r == 0)
continue;
/* Entry already exists, keep the entry with the higher RR. */
if (rr->ttl > a->items[i].rr->ttl) {
dns_resource_record_ref(rr);
dns_resource_record_unref(a->items[i].rr);
a->items[i].rr = rr;
}
a->items[i].flags |= flags;
return 0;
}
return dns_answer_add_raw(a, rr, ifindex, flags);

View File

@ -2258,7 +2258,7 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
* be contained in questions, never in replies. Crappy
* Belkin routers copy the OPT data for example, hence let's
* detect this so that we downgrade early. */
log_debug("OPT RR contained RFC6975 data, ignoring.");
log_debug("OPT RR contains RFC6975 data, ignoring.");
bad_opt = true;
continue;
}