From: Wouter Wijngaards Date: Fri, 16 Sep 2011 14:11:12 +0000 (+0000) Subject: - max sent count. EDNS1480 only for rtt < 5000. No promiscuous X-Git-Tag: release-1.4.14rc1~68 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f82a0847eb30a0f13f2d9665ba0c3fc97a0ddf6c;p=thirdparty%2Funbound.git - max sent count. EDNS1480 only for rtt < 5000. No promiscuous fetch if sentcount > 3, stop query if sentcount > 16. Count is reset when referral or CNAME happens. This makes unbound better at managing large NS sets, they are explored when there is continued interest (in the form of queries). git-svn-id: file:///svn/unbound/trunk@2499 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index f1b38fbc0..26394c237 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -4,6 +4,11 @@ - iana portlist updated. - fix EDNS1480 change memleak and TCP fallback. - fix various compiler warnings (reported by Paul Wouters). + - max sent count. EDNS1480 only for rtt < 5000. No promiscuous + fetch if sentcount > 3, stop query if sentcount > 16. Count is + reset when referral or CNAME happens. This makes unbound better + at managing large NS sets, they are explored when there is continued + interest (in the form of queries). 15 September 2011: Wouter - release 1.4.13. diff --git a/iterator/iterator.c b/iterator/iterator.c index 71682b234..cf35d0f32 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -117,6 +117,7 @@ iter_new(struct module_qstate* qstate, int id) iq->num_current_queries = 0; iq->query_restart_count = 0; iq->referral_count = 0; + iq->sent_count = 0; iq->wait_priming_stub = 0; iq->refetch_glue = 0; iq->dnssec_expected = 0; @@ -1537,8 +1538,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, log_query_info(VERB_QUERY, "processQueryTargets:", &qstate->qinfo); verbose(VERB_ALGO, "processQueryTargets: targetqueries %d, " - "currentqueries %d", iq->num_target_queries, - iq->num_current_queries); + "currentqueries %d sentcount %d", iq->num_target_queries, + iq->num_current_queries, iq->sent_count); /* Make sure that we haven't run away */ /* FIXME: is this check even necessary? */ @@ -1547,6 +1548,11 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, "number of referrrals with %d", iq->referral_count); return error_response(qstate, id, LDNS_RCODE_SERVFAIL); } + if(iq->sent_count > MAX_SENT_COUNT) { + verbose(VERB_QUERY, "request has exceeded the maximum " + "number of sends with %d", iq->sent_count); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } /* Make sure we have a delegation point, otherwise priming failed * or another failure occurred */ @@ -1573,7 +1579,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* < not <=, because although the array is large enough for <=, the * generated query will immediately be discarded due to depth and * that servfail is cached, which is not good as opportunism goes. */ - if(iq->depth < ie->max_dependency_depth) { + if(iq->depth < ie->max_dependency_depth + && iq->sent_count < TARGET_FETCH_STOP) { tf_policy = ie->target_fetch_policy[iq->depth]; } @@ -1596,7 +1603,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* the current caps_server is the number of fallbacks sent. * the original query is one that matched too, so we have * caps_server+1 number of matching queries now */ - if(iq->caps_server+1 >= naddr*3) { + if(iq->caps_server+1 >= naddr*3 || + iq->caps_server+1 >= MAX_SENT_COUNT) { /* we're done, process the response */ verbose(VERB_ALGO, "0x20 fallback had %d responses " "match for %d wanted, done.", @@ -1720,6 +1728,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, } outbound_list_insert(&iq->outlist, outq); iq->num_current_queries++; + iq->sent_count++; qstate->ext_state[id] = module_wait_reply; return 0; @@ -1896,6 +1905,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, delegpt_log(VERB_ALGO, iq->dp); /* Count this as a referral. */ iq->referral_count++; + iq->sent_count = 0; /* see if the next dp is a trust anchor, or a DS was sent * along, indicating dnssec is expected for next zone */ iq->dnssec_expected = iter_indicates_dnssec(qstate->env, @@ -1953,6 +1963,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->dp = NULL; /* Note the query restart. */ iq->query_restart_count++; + iq->sent_count = 0; /* stop current outstanding queries. * FIXME: should the outstanding queries be waited for and diff --git a/iterator/iterator.h b/iterator/iterator.h index 9137b404b..0272fe103 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -56,6 +56,10 @@ struct iter_priv; #define MAX_RESTART_COUNT 8 /** max number of referrals. Makes sure resolver does not run away */ #define MAX_REFERRAL_COUNT 130 +/** max number of queries-sent-out. Make sure large NS set does not loop */ +#define MAX_SENT_COUNT 16 +/** at what query-sent-count to stop target fetch policy */ +#define TARGET_FETCH_STOP 3 /** how nice is a server without further information, in msec * Equals rtt initial timeout value. */ @@ -252,6 +256,9 @@ struct iter_qstate { /** the number of times this query as followed a referral. */ int referral_count; + /** number of queries fired off */ + int sent_count; + /** * The query must store NS records from referrals as parentside RRs * Enabled once it hits resolution problems, to throttle retries. diff --git a/services/outside_network.c b/services/outside_network.c index 6c9664c9f..297e454ea 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1585,7 +1585,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, * by EDNS. */ sq->status = serviced_query_UDP_EDNS; } - if(sq->status == serviced_query_UDP_EDNS) { + if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) { /* fallback to 1480/1280 */ sq->status = serviced_query_UDP_EDNS_FRAG; log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,