1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

Merge pull request #11841 from keszybz/dns-packet-speedup

DNS packet speedup
This commit is contained in:
Lennart Poettering 2019-03-04 19:30:23 +01:00 committed by GitHub
commit bb5e88a226
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 79 additions and 48 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

@ -7,6 +7,7 @@
#include "alloc-util.h"
#include "dns-domain.h"
#include "resolved-dns-packet.h"
#include "set.h"
#include "string-table.h"
#include "strv.h"
#include "unaligned.h"
@ -2133,6 +2134,17 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
if (!question)
return -ENOMEM;
_cleanup_set_free_ Set *keys = NULL; /* references to keys are kept by Question */
keys = set_new(&dns_resource_key_hash_ops);
if (!keys)
return log_oom();
r = set_reserve(keys, n * 2); /* Higher multipliers give slightly higher efficiency through
* hash collisions, but the gains quickly drop of after 2. */
if (r < 0)
return r;
for (i = 0; i < n; i++) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
bool cache_flush;
@ -2147,7 +2159,14 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
if (!dns_type_is_valid_query(key->type))
return -EBADMSG;
r = dns_question_add(question, key);
r = set_put(keys, key);
if (r < 0)
return r;
if (r == 0)
/* Already in the Question, let's skip */
continue;
r = dns_question_add_raw(question, key);
if (r < 0)
return r;
}
@ -2239,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;
}

View File

@ -32,8 +32,20 @@ static DnsQuestion *dns_question_free(DnsQuestion *q) {
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsQuestion, dns_question, dns_question_free);
int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key) {
/* Insert without checking for duplicates. */
assert(key);
assert(q);
if (q->n_keys >= q->n_allocated)
return -ENOSPC;
q->keys[q->n_keys++] = dns_resource_key_ref(key);
return 0;
}
int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
size_t i;
int r;
assert(key);
@ -41,7 +53,7 @@ int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
if (!q)
return -ENOSPC;
for (i = 0; i < q->n_keys; i++) {
for (size_t i = 0; i < q->n_keys; i++) {
r = dns_resource_key_equal(q->keys[i], key);
if (r < 0)
return r;
@ -49,11 +61,7 @@ int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
return 0;
}
if (q->n_keys >= q->n_allocated)
return -ENOSPC;
q->keys[q->n_keys++] = dns_resource_key_ref(key);
return 0;
return dns_question_add_raw(q, key);
}
int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {

View File

@ -22,6 +22,7 @@ int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bo
int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a);
int dns_question_new_service(DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna);
int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key);
int dns_question_add(DnsQuestion *q, DnsResourceKey *key);
int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain);

View File

@ -557,18 +557,10 @@ int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const u
((a).field ## _size == (b).field ## _size && \
memcmp((a).field, (b).field, (a).field ## _size) == 0)
int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
int r;
assert(a);
assert(b);
if (a == b)
return 1;
r = dns_resource_key_equal(a->key, b->key);
if (r <= 0)
return r;
/* Check if a and b are the same, but don't look at their keys */
if (a->unparseable != b->unparseable)
return 0;
@ -692,6 +684,22 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
}
}
int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
int r;
assert(a);
assert(b);
if (a == b)
return 1;
r = dns_resource_key_equal(a->key, b->key);
if (r <= 0)
return r;
return dns_resource_record_payload_equal(a, b);
}
static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
char *s;

View File

@ -308,6 +308,8 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr);
int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
const char* dns_resource_record_to_string(DnsResourceRecord *rr);
DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);

Binary file not shown.