From: Christopher Faulet Date: Tue, 29 Sep 2026 09:07:34 +0000 (+0200) Subject: OPTIM: resolvers: only walk duplicates when looking up an existing record X-Git-Url: https://git.kaiwu.me/$%7BGITURL%7D$%7Bcid%7D?a=commitdiff_plain;h=dc537b91a62bbeda4de950fffd8909ab81d78399;p=haproxy.git OPTIM: resolvers: only walk duplicates when looking up an existing record When parsing answer records, resolv_validate_dns_response() looks up the record's hash key in the answer tree to detect duplicates, then walks the following nodes with eb32_next(), which doesn't stop at the end of the duplicates of this key. When the key already exists but the record differs (i.e. on a hash collision), all the remaining nodes of the tree are compared, which is quadratic in the number of records for crafted responses of colliding records (up to ~4000 records per 64kB TCP response). In normal operation the lookup returns NULL for new records and the first node is the duplicate for repeated ones, so no difference could be measured (60 resolutions of 4000 distinct A records over TCP cost the same CPU time before and after). Still, let's use eb32_next_dup() to only walk the nodes sharing the looked up key, as intended. No backport is needed. --- diff --git a/src/resolvers.c b/src/resolvers.c index a9953fcf5..51fd04ca4 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -1409,7 +1409,7 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe /* Lookup to see if we already had this entry */ found = 0; - for (eb32 = eb32_lookup(&r_res->answer_tree, key); eb32 != NULL; eb32 = eb32_next(eb32)) { + for (eb32 = eb32_lookup(&r_res->answer_tree, key); eb32 != NULL; eb32 = eb32_next_dup(eb32)) { tmp_record = eb32_entry(eb32, typeof(*tmp_record), link); if (tmp_record->type != answer_record->type) continue;