1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00

Merge pull request #19608 from keszybz/resolved-pahole

Pahole optimization for resolved's DnsQuery
This commit is contained in:
Lennart Poettering 2021-05-19 16:35:16 +02:00 committed by GitHub
commit 871a3a33bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 175 additions and 157 deletions

View File

@ -35,7 +35,6 @@
uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) {
const uint8_t *p;
uint32_t sum, f;
size_t i;
/* The algorithm from RFC 4034, Appendix B. */
@ -51,7 +50,7 @@ uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) {
p = dnskey->dnskey.key;
for (i = 0; i < dnskey->dnskey.key_size; i++)
for (size_t i = 0; i < dnskey->dnskey.key_size; i++)
sum += (i & 1) == 0 ? (uint32_t) p[i] << 8 : (uint32_t) p[i];
sum += (sum >> 16) & UINT32_C(0xFFFF);
@ -483,14 +482,14 @@ static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) {
const char *name;
int r;
/* Checks whether the specified RRSIG RR is somewhat valid, and initializes the .n_skip_labels_source and
* .n_skip_labels_signer fields so that we can use them later on. */
/* Checks whether the specified RRSIG RR is somewhat valid, and initializes the .n_skip_labels_source
* and .n_skip_labels_signer fields so that we can use them later on. */
assert(rrsig);
assert(rrsig->key->type == DNS_TYPE_RRSIG);
/* Check if this RRSIG RR is already prepared */
if (rrsig->n_skip_labels_source != UINT_MAX)
if (rrsig->n_skip_labels_source != UINT8_MAX)
return 0;
if (rrsig->rrsig.inception > rrsig->rrsig.expiration)
@ -523,6 +522,7 @@ static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) {
if (r == 0)
return -EINVAL;
assert(n_key_labels < UINT8_MAX); /* UINT8_MAX/-1 means unsigned. */
rrsig->n_skip_labels_source = n_key_labels - rrsig->rrsig.labels;
rrsig->n_skip_labels_signer = n_key_labels - n_signer_labels;
@ -604,13 +604,11 @@ static void dnssec_fix_rrset_ttl(
DnsResourceRecord *rrsig,
usec_t realtime) {
unsigned k;
assert(list);
assert(n > 0);
assert(rrsig);
for (k = 0; k < n; k++) {
for (unsigned k = 0; k < n; k++) {
DnsResourceRecord *rr = list[k];
/* Pick the TTL as the minimum of the RR's TTL, the
@ -640,7 +638,7 @@ int dnssec_verify_rrset(
const char *source, *name;
_cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
int r, md_algorithm;
size_t k, n = 0;
size_t n = 0;
size_t sig_size = 0;
_cleanup_free_ char *sig_data = NULL;
_cleanup_fclose_ FILE *f = NULL;
@ -770,7 +768,7 @@ int dnssec_verify_rrset(
if (r < 0)
return r;
for (k = 0; k < n; k++) {
for (size_t k = 0; k < n; k++) {
size_t l;
rr = list[k];
@ -1210,7 +1208,6 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
size_t hash_size;
int algorithm;
void *result;
unsigned k;
int r;
assert(nsec3);
@ -1252,7 +1249,7 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
if (!result)
return -EIO;
for (k = 0; k < nsec3->nsec3.iterations; k++) {
for (unsigned k = 0; k < nsec3->nsec3.iterations; k++) {
uint8_t tmp[hash_size];
memcpy(tmp, result, hash_size);
@ -1291,10 +1288,10 @@ static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) {
/* Ignore NSEC3 RRs generated from wildcards. If these NSEC3 RRs weren't correctly signed we can't make this
* check (since rr->n_skip_labels_source is -1), but that's OK, as we won't trust them anyway in that case. */
if (!IN_SET(rr->n_skip_labels_source, 0, UINT_MAX))
if (!IN_SET(rr->n_skip_labels_source, 0, UINT8_MAX))
return 0;
/* Ignore NSEC3 RRs that are located anywhere else than one label below the zone */
if (!IN_SET(rr->n_skip_labels_signer, 1, UINT_MAX))
if (!IN_SET(rr->n_skip_labels_signer, 1, UINT8_MAX))
return 0;
if (!nsec3)

View File

@ -71,21 +71,23 @@ struct DnsPacket {
DnsAnswer *answer;
DnsResourceRecord *opt;
/* For support of truncated packets */
DnsPacket *more;
/* Packet reception metadata */
usec_t timestamp; /* CLOCK_BOOTTIME (or CLOCK_MONOTONIC if the former doesn't exist) */
int ifindex;
int family, ipproto;
union in_addr_union sender, destination;
uint16_t sender_port, destination_port;
uint32_t ttl;
usec_t timestamp; /* CLOCK_BOOTTIME (or CLOCK_MONOTONIC if the former doesn't exist) */
/* For support of truncated packets */
DnsPacket *more;
bool on_stack;
bool extracted;
bool refuse_compression;
bool canonical_form;
bool on_stack:1;
bool extracted:1;
bool refuse_compression:1;
bool canonical_form:1;
/* Note: fields should be ordered to minimize alignment gaps. Use pahole! */
};
static inline uint8_t* DNS_PACKET_DATA(const DnsPacket *p) {

View File

@ -12,6 +12,10 @@
#define QUERIES_MAX 2048
#define AUXILIARY_QUERIES_MAX 64
#define CNAME_REDIRECTS_MAX 16
assert_cc(AUXILIARY_QUERIES_MAX < UINT8_MAX);
assert_cc(CNAME_REDIRECTS_MAX < UINT8_MAX);
static int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) {
DnsQueryCandidate *c;
@ -1004,9 +1008,9 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname)
assert(q);
q->n_cname_redirects++;
if (q->n_cname_redirects > CNAME_REDIRECT_MAX)
if (q->n_cname_redirects >= CNAME_REDIRECTS_MAX)
return -ELOOP;
q->n_cname_redirects++;
r = dns_question_cname_redirect(q->question_idna, cname, &nq_idna);
if (r < 0)

View File

@ -33,14 +33,6 @@ struct DnsQueryCandidate {
struct DnsQuery {
Manager *manager;
/* When resolving a service, we first create a TXT+SRV query, and then for the hostnames we discover
* auxiliary A+AAAA queries. This pointer always points from the auxiliary queries back to the
* TXT+SRV query. */
DnsQuery *auxiliary_for;
LIST_HEAD(DnsQuery, auxiliary_queries);
unsigned n_auxiliary_queries;
int auxiliary_result;
/* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note
* that even on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names
* (in contrast to their domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference
@ -63,8 +55,12 @@ struct DnsQuery {
uint64_t flags;
int ifindex;
DnsTransactionState state;
unsigned n_cname_redirects;
/* When resolving a service, we first create a TXT+SRV query, and then for the hostnames we discover
* auxiliary A+AAAA queries. This pointer always points from the auxiliary queries back to the
* TXT+SRV query. */
int auxiliary_result;
DnsQuery *auxiliary_for;
LIST_HEAD(DnsQuery, auxiliary_queries);
LIST_HEAD(DnsQueryCandidate, candidates);
sd_event_source *timeout_event_source;
@ -76,18 +72,26 @@ struct DnsQuery {
uint64_t answer_query_flags;
DnsProtocol answer_protocol;
int answer_family;
DnsSearchDomain *answer_search_domain;
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
bool previous_redirect_unauthenticated;
bool previous_redirect_non_confidential;
bool previous_redirect_non_synthetic;
DnsPacket *answer_full_packet;
DnsSearchDomain *answer_search_domain;
DnsTransactionState state;
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
unsigned block_ready;
uint8_t n_auxiliary_queries;
uint8_t n_cname_redirects;
bool previous_redirect_unauthenticated:1;
bool previous_redirect_non_confidential:1;
bool previous_redirect_non_synthetic:1;
bool request_address_valid:1;
/* Bus + Varlink client information */
sd_bus_message *bus_request;
Varlink *varlink_request;
int request_family;
bool request_address_valid;
union in_addr_union request_address;
unsigned block_all_complete;
char *request_address_string;
@ -102,12 +106,13 @@ struct DnsQuery {
/* Completion callback */
void (*complete)(DnsQuery* q);
unsigned block_ready;
sd_bus_track *bus_track;
LIST_FIELDS(DnsQuery, queries);
LIST_FIELDS(DnsQuery, auxiliary_queries);
/* Note: fields should be ordered to minimize alignment gaps. Use pahole! */
};
enum {
@ -154,5 +159,3 @@ static inline uint64_t dns_query_reply_flags_make(DnsQuery *q) {
dns_query_fully_confidential(q)) |
(q->answer_query_flags & (SD_RESOLVED_FROM_MASK|SD_RESOLVED_SYNTHETIC));
}
#define CNAME_REDIRECT_MAX 16

View File

@ -381,8 +381,8 @@ DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
.n_ref = 1,
.key = dns_resource_key_ref(key),
.expiry = USEC_INFINITY,
.n_skip_labels_signer = UINT_MAX,
.n_skip_labels_source = UINT_MAX,
.n_skip_labels_signer = UINT8_MAX,
.n_skip_labels_source = UINT8_MAX,
};
return rr;
@ -795,14 +795,12 @@ static char *format_txt(DnsTxtItem *first) {
return NULL;
LIST_FOREACH(items, i, first) {
size_t j;
if (i != first)
*(p++) = ' ';
*(p++) = '"';
for (j = 0; j < i->length; j++) {
for (size_t j = 0; j < i->length; j++) {
if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) {
*(p++) = '\\';
*(p++) = '0' + (i->data[j] / 100);
@ -1258,7 +1256,7 @@ int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
/* Returns the RRset's signer, if it is known. */
if (rr->n_skip_labels_signer == UINT_MAX)
if (rr->n_skip_labels_signer == UINT8_MAX)
return -ENODATA;
n = dns_resource_key_name(rr->key);
@ -1281,7 +1279,7 @@ int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
/* Returns the RRset's synthesizing source, if it is known. */
if (rr->n_skip_labels_source == UINT_MAX)
if (rr->n_skip_labels_source == UINT8_MAX)
return -ENODATA;
n = dns_resource_key_name(rr->key);
@ -1315,7 +1313,7 @@ int dns_resource_record_is_synthetic(DnsResourceRecord *rr) {
/* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
if (rr->n_skip_labels_source == UINT_MAX)
if (rr->n_skip_labels_source == UINT8_MAX)
return -ENODATA;
if (rr->n_skip_labels_source == 0)

View File

@ -4,6 +4,7 @@
#include <netinet/in.h>
#include "bitmap.h"
#include "dns-def.h"
#include "dns-type.h"
#include "hashmap.h"
#include "in-addr-util.h"
@ -90,21 +91,21 @@ struct DnsTxtItem {
struct DnsResourceRecord {
unsigned n_ref;
uint32_t ttl;
usec_t expiry; /* RRSIG signature expiry */
DnsResourceKey *key;
char *to_string;
uint32_t ttl;
usec_t expiry; /* RRSIG signature expiry */
/* How many labels to strip to determine "signer" of the RRSIG (aka, the zone). -1 if not signed. */
unsigned n_skip_labels_signer;
uint8_t n_skip_labels_signer;
/* How many labels to strip to determine "synthesizing source" of this RR, i.e. the wildcard's immediate parent. -1 if not signed. */
unsigned n_skip_labels_source;
uint8_t n_skip_labels_source;
bool unparsable:1;
bool unparsable;
bool wire_format_canonical;
bool wire_format_canonical:1;
void *wire_format;
size_t wire_format_size;
size_t wire_format_rdata_offset;
@ -116,10 +117,10 @@ struct DnsResourceRecord {
} generic, opt;
struct {
char *name;
uint16_t priority;
uint16_t weight;
uint16_t port;
char *name;
} srv;
struct {
@ -154,8 +155,8 @@ struct DnsResourceRecord {
} soa;
struct {
uint16_t priority;
char *exchange;
uint16_t priority;
} mx;
/* https://tools.ietf.org/html/rfc1876 */
@ -171,23 +172,29 @@ struct DnsResourceRecord {
/* https://tools.ietf.org/html/rfc4255#section-3.1 */
struct {
uint8_t algorithm;
uint8_t fptype;
void *fingerprint;
size_t fingerprint_size;
uint8_t algorithm;
uint8_t fptype;
} sshfp;
/* http://tools.ietf.org/html/rfc4034#section-2.1 */
struct {
void* key;
size_t key_size;
uint16_t flags;
uint8_t protocol;
uint8_t algorithm;
void* key;
size_t key_size;
} dnskey;
/* http://tools.ietf.org/html/rfc4034#section-3.1 */
struct {
char *signer;
void *signature;
size_t signature_size;
uint16_t type_covered;
uint8_t algorithm;
uint8_t labels;
@ -195,9 +202,6 @@ struct DnsResourceRecord {
uint32_t expiration;
uint32_t inception;
uint16_t key_tag;
char *signer;
void *signature;
size_t signature_size;
} rrsig;
/* https://tools.ietf.org/html/rfc4034#section-4.1 */
@ -208,43 +212,52 @@ struct DnsResourceRecord {
/* https://tools.ietf.org/html/rfc4034#section-5.1 */
struct {
void *digest;
size_t digest_size;
uint16_t key_tag;
uint8_t algorithm;
uint8_t digest_type;
void *digest;
size_t digest_size;
} ds;
struct {
uint8_t algorithm;
uint8_t flags;
uint16_t iterations;
Bitmap *types;
void *salt;
size_t salt_size;
void *next_hashed_name;
size_t next_hashed_name_size;
Bitmap *types;
uint8_t algorithm;
uint8_t flags;
uint16_t iterations;
} nsec3;
/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */
struct {
void *data;
size_t data_size;
uint8_t cert_usage;
uint8_t selector;
uint8_t matching_type;
void *data;
size_t data_size;
} tlsa;
/* https://tools.ietf.org/html/rfc6844 */
struct {
uint8_t flags;
char *tag;
void *value;
size_t value_size;
uint8_t flags;
} caa;
};
/* Note: fields should be ordered to minimize alignment gaps. Use pahole! */
};
/* We use uint8_t for label counts above, and UINT8_MAX/-1 has special meaning. */
assert_cc(DNS_N_LABELS_MAX < UINT8_MAX);
static inline const void* DNS_RESOURCE_RECORD_RDATA(const DnsResourceRecord *rr) {
if (!rr)
return NULL;

View File

@ -43,7 +43,6 @@ struct DnsScope {
OrderedHashmap *conflict_queue;
sd_event_source *conflict_event_source;
bool announced:1;
sd_event_source *announce_event_source;
RateLimit ratelimit;
@ -63,6 +62,8 @@ struct DnsScope {
LIST_HEAD(DnsTransaction, transactions);
LIST_FIELDS(DnsScope, scopes);
bool announced;
};
int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol p, int family);

View File

@ -57,17 +57,6 @@ struct DnsTransaction {
uint64_t query_flags;
DnsTransactionState state;
uint16_t id;
bool tried_stream:1;
bool initial_jitter_scheduled:1;
bool initial_jitter_elapsed:1;
bool probing:1;
DnsPacket *sent, *received;
DnsAnswer *answer;
@ -77,6 +66,8 @@ struct DnsTransaction {
uint32_t answer_nsec_ttl;
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
DnsTransactionState state;
/* SD_RESOLVED_AUTHENTICATED here indicates whether the primary answer is authenticated, i.e. whether
* the RRs from answer which directly match the question are authenticated, or, if there are none,
* whether the NODATA or NXDOMAIN case is. It says nothing about additional RRs listed in the answer,
@ -93,8 +84,6 @@ struct DnsTransaction {
sd_event_source *timeout_event_source;
unsigned n_attempts;
unsigned n_picked_servers;
/* UDP connection logic, if we need it */
int dns_udp_fd;
sd_event_source *dns_udp_event_source;
@ -114,6 +103,15 @@ struct DnsTransaction {
DnsServerFeatureLevel clamp_feature_level_servfail;
DnsServerFeatureLevel clamp_feature_level_nxdomain;
uint16_t id;
bool tried_stream:1;
bool initial_jitter_scheduled:1;
bool initial_jitter_elapsed:1;
bool probing:1;
/* Query candidates this transaction is referenced by and that
* shall be notified about this specific transaction
* completing. */
@ -133,11 +131,15 @@ struct DnsTransaction {
* created in order to request DNSKEY or DS RRs. */
Set *dnssec_transactions;
unsigned n_picked_servers;
unsigned block_gc;
LIST_FIELDS(DnsTransaction, transactions_by_scope);
LIST_FIELDS(DnsTransaction, transactions_by_stream);
LIST_FIELDS(DnsTransaction, transactions_by_key);
/* Note: fields should be ordered to minimize alignment gaps. Use pahole! */
};
int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key, DnsPacket *bypass, uint64_t flags);

View File

@ -1191,13 +1191,11 @@ int dns_name_skip(const char *a, unsigned n_labels, const char **ret) {
int dns_name_count_labels(const char *name) {
unsigned n = 0;
const char *p;
int r;
assert(name);
p = name;
for (;;) {
for (const char *p = name;;) {
r = dns_name_parent(&p);
if (r < 0)
return r;
@ -1210,7 +1208,7 @@ int dns_name_count_labels(const char *name) {
n++;
}
return (int) n;
return n;
}
int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) {