- Applied patch from Daisuke HIGASHI for rrset-roundrobin and

minimal-responses features.


git-svn-id: file:///svn/unbound/trunk@2658 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2012-04-10 09:16:39 +00:00
parent 279f409636
commit cf147df593
14 changed files with 1668 additions and 1479 deletions

View file

@ -18,3 +18,4 @@ cz.nic - sponsoring 'summer of code' development by Zdenek and Marek.
Brett Carr - windows beta testing.
Luca Bruno - patch for windows support in libunbound hosts and resolvconf().
Tom Hendrikx - contributed split-itar.sh a useful script to 5011-track ITAR.
Daisuke HIGASHI - patch for rrset-roundrobin and minimal-responses.

View file

@ -1,3 +1,7 @@
10 April 2012: Wouter
- Applied patch from Daisuke HIGASHI for rrset-roundrobin and
minimal-responses features.
5 April 2012: Wouter
- fix bug #443: --with-chroot-dir not honoured by configure.
- fix bug #444: setusercontext was called too late (thanks Bjorn

View file

@ -309,6 +309,13 @@ server:
# if yes, perform key lookups adjacent to normal lookups.
# prefetch-key: no
# if yes, Unbound rotates RRSet order in response.
# rrset-roundrobin: no
# if yes, Unbound doesn't insert authority/additional sections
# into response messages when those sections are not required.
# minimal-responses: no
# module configuration of the server. A string with identifiers
# separated by spaces. "iterator" or "validator iterator"
# module-config: "validator iterator"

View file

@ -570,6 +570,18 @@ If yes, fetch the DNSKEYs earlier in the validation process, when a DS
record is encountered. This lowers the latency of requests. It does use
a little more CPU. Also if the cache is set to 0, it is no use. Default is no.
.TP
.B rrset-roundrobin: \fI<yes or no>
If yes, Unbound rotates RRSet order in response (the random number is taken
from the query ID, for speed and thread safety). Default is no.
.TP
.B minimal-responses: \fI<yes or no>
If yes, Unbound doesn't insert authority/additional sections into response
messages when those sections are not required. This reduces response
size significantly, and may avoid TCP fallback for some responses.
This may cause a slight speedup. The default is no, because the DNS
protocol RFCs mandate these sections, and the additional content could
be of use and save roundtrips for clients.
.TP
.B module\-config: \fI<"module names">
Module configuration, a list of module names separated by spaces, surround
the string with quotes (""). The modules can be validator, iterator.

View file

@ -195,6 +195,8 @@ config_create(void)
cfg->remote_control_enable = 0;
cfg->control_ifs = NULL;
cfg->control_port = UNBOUND_CONTROL_PORT;
cfg->minimal_responses = 0;
cfg->rrset_roundrobin = 0;
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
goto error_exit;
if(!(cfg->server_cert_file = strdup(RUN_DIR"/unbound_server.pem")))
@ -399,6 +401,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_MEMSIZE("key-cache-size:", key_cache_size)
else S_POW2("key-cache-slabs:", key_cache_slabs)
else S_MEMSIZE("neg-cache-size:", neg_cache_size)
else S_YNO("minimal-responses:", minimal_responses)
else S_YNO("rrset-roundrobin:", rrset_roundrobin)
else S_STRLIST("local-data:", local_data)
else S_YNO("control-enable:", remote_control_enable)
else S_STRLIST("control-interface:", control_ifs)
@ -651,6 +655,8 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LST(opt, "control-interface", control_ifs)
else O_LST(opt, "domain-insecure", domain_insecure)
else O_UNS(opt, "val-override-date", val_date_override)
else O_YNO(opt, "minimal-responses", minimal_responses)
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
/* not here:
* outgoing-permit, outgoing-avoid - have list of ports
* local-zone - zones and nodefault variables
@ -1079,6 +1085,8 @@ config_apply(struct config_file* config)
MAX_TTL = (uint32_t)config->max_ttl;
MIN_TTL = (uint32_t)config->min_ttl;
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
MINIMAL_RESPONSES = config->minimal_responses;
RRSET_ROUNDROBIN = config->rrset_roundrobin;
log_set_time_asc(config->log_time_ascii);
}

View file

@ -290,6 +290,12 @@ struct config_file {
/** daemonize, i.e. fork into the background. */
int do_daemonize;
/* minimal response when positive answer */
int minimal_responses;
/* RRSet roundrobin */
int rrset_roundrobin;
};
/**

File diff suppressed because it is too large Load diff

View file

@ -241,6 +241,8 @@ control-cert-file{COLON} { YDVAR(1, VAR_CONTROL_CERT_FILE) }
python-script{COLON} { YDVAR(1, VAR_PYTHON_SCRIPT) }
python{COLON} { YDVAR(0, VAR_PYTHON) }
domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) }
minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) }
rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
/* Quoted strings. Strip leading and ending quotes */

File diff suppressed because it is too large Load diff

View file

@ -161,7 +161,9 @@
VAR_SSL_SERVICE_PEM = 379,
VAR_SSL_PORT = 380,
VAR_FORWARD_FIRST = 381,
VAR_STUB_FIRST = 382
VAR_STUB_FIRST = 382,
VAR_MINIMAL_RESPONSES = 383,
VAR_RRSET_ROUNDROBIN = 384
};
#endif
/* Tokens. */
@ -290,6 +292,8 @@
#define VAR_SSL_PORT 380
#define VAR_FORWARD_FIRST 381
#define VAR_STUB_FIRST 382
#define VAR_MINIMAL_RESPONSES 383
#define VAR_RRSET_ROUNDROBIN 384
@ -306,7 +310,7 @@ typedef union YYSTYPE
/* Line 2068 of yacc.c */
#line 310 "util/configparser.h"
#line 314 "util/configparser.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

View file

@ -104,7 +104,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_HARDEN_BELOW_NXDOMAIN
%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
%token VAR_STUB_FIRST
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -160,7 +160,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_edns_buffer_size | server_prefetch | server_prefetch_key |
server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag |
server_log_queries | server_tcp_upstream | server_ssl_upstream |
server_ssl_service_key | server_ssl_service_pem | server_ssl_port
server_ssl_service_key | server_ssl_service_pem | server_ssl_port |
server_minimal_responses | server_rrset_roundrobin
;
stubstart: VAR_STUB_ZONE
{
@ -1096,6 +1097,26 @@ server_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG
}
}
;
server_minimal_responses: VAR_MINIMAL_RESPONSES STRING_ARG
{
OUTYY(("P(server_minimal_responses:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->minimal_responses =
(strcmp($2, "yes")==0);
free($2);
}
;
server_rrset_roundrobin: VAR_RRSET_ROUNDROBIN STRING_ARG
{
OUTYY(("P(server_rrset_roundrobin:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->rrset_roundrobin =
(strcmp($2, "yes")==0);
free($2);
}
;
stub_name: VAR_NAME STRING_ARG
{
OUTYY(("P(name:%s)\n", $2));

View file

@ -443,9 +443,9 @@ static int
packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
uint16_t* num_rrs, uint32_t timenow, struct regional* region,
int do_data, int do_sig, struct compress_tree_node** tree,
ldns_pkt_section s, uint16_t qtype, int dnssec)
ldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
{
size_t i, owner_pos;
size_t i, j, owner_pos;
int r, owner_labs;
uint16_t owner_ptr = 0;
struct packed_rrset_data* data = (struct packed_rrset_data*)
@ -461,26 +461,28 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
if(do_data) {
const ldns_rr_descriptor* c = type_rdata_compressable(key);
for(i=0; i<data->count; i++) {
/* rrset roundrobin */
j = (i + rr_offset) % data->count;
if((r=compress_owner(key, pkt, region, tree,
owner_pos, &owner_ptr, owner_labs))
!= RETVAL_OK)
return r;
ldns_buffer_write(pkt, &key->rk.type, 2);
ldns_buffer_write(pkt, &key->rk.rrset_class, 2);
if(data->rr_ttl[i] < timenow)
if(data->rr_ttl[j] < timenow)
ldns_buffer_write_u32(pkt, 0);
else ldns_buffer_write_u32(pkt,
data->rr_ttl[i]-timenow);
data->rr_ttl[j]-timenow);
if(c) {
if((r=compress_rdata(pkt, data->rr_data[i],
data->rr_len[i], region, tree, c))
if((r=compress_rdata(pkt, data->rr_data[j],
data->rr_len[j], region, tree, c))
!= RETVAL_OK)
return r;
} else {
if(ldns_buffer_remaining(pkt) < data->rr_len[i])
if(ldns_buffer_remaining(pkt) < data->rr_len[j])
return RETVAL_TRUNC;
ldns_buffer_write(pkt, data->rr_data[i],
data->rr_len[i]);
ldns_buffer_write(pkt, data->rr_data[j],
data->rr_len[j]);
}
}
}
@ -528,7 +530,7 @@ static int
insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
ldns_buffer* pkt, size_t rrsets_before, uint32_t timenow,
struct regional* region, struct compress_tree_node** tree,
ldns_pkt_section s, uint16_t qtype, int dnssec)
ldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
{
int r;
size_t i, setstart;
@ -540,7 +542,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
setstart = ldns_buffer_position(pkt);
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
pkt, num_rrs, timenow, region, 1, 1, tree,
s, qtype, dnssec))
s, qtype, dnssec, rr_offset))
!= RETVAL_OK) {
/* Bad, but if due to size must set TC bit */
/* trim off the rrset neatly. */
@ -553,7 +555,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
setstart = ldns_buffer_position(pkt);
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
pkt, num_rrs, timenow, region, 1, 0, tree,
s, qtype, dnssec))
s, qtype, dnssec, rr_offset))
!= RETVAL_OK) {
ldns_buffer_set_position(pkt, setstart);
return r;
@ -564,7 +566,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
setstart = ldns_buffer_position(pkt);
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
pkt, num_rrs, timenow, region, 0, 1, tree,
s, qtype, dnssec))
s, qtype, dnssec, rr_offset))
!= RETVAL_OK) {
ldns_buffer_set_position(pkt, setstart);
return r;
@ -595,6 +597,31 @@ insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
return RETVAL_OK;
}
static int
positive_answer(struct reply_info* rep, uint16_t qtype) {
size_t i;
if (FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR)
return 0;
for(i=0;i<rep->an_numrrsets; i++) {
if(ntohs(rep->rrsets[i]->rk.type) == qtype) {
/* in case it is a wildcard with DNSSEC, there will
* be NSEC/NSEC3 records in the authority section
* that we cannot remove */
for(i=rep->an_numrrsets; i<rep->an_numrrsets+
rep->ns_numrrsets; i++) {
if(ntohs(rep->rrsets[i]->rk.type) ==
LDNS_RR_TYPE_NSEC ||
ntohs(rep->rrsets[i]->rk.type) ==
LDNS_RR_TYPE_NSEC3)
return 0;
}
return 1;
}
}
return 0;
}
int
reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow,
@ -603,6 +630,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
uint16_t ancount=0, nscount=0, arcount=0;
struct compress_tree_node* tree = 0;
int r;
size_t rr_offset;
ldns_buffer_clear(buffer);
if(udpsize < ldns_buffer_limit(buffer))
@ -630,11 +658,13 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
return 0;
}
}
/* roundrobin offset. using query id for random number */
rr_offset = RRSET_ROUNDROBIN?id:0;
/* insert answer section */
if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
dnssec)) != RETVAL_OK) {
dnssec, rr_offset)) != RETVAL_OK) {
if(r == RETVAL_TRUNC) {
/* create truncated message */
ldns_buffer_write_u16_at(buffer, 6, ancount);
@ -646,35 +676,42 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
}
ldns_buffer_write_u16_at(buffer, 6, ancount);
/* insert auth section */
if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
rep->an_numrrsets, timenow, region, &tree,
LDNS_SECTION_AUTHORITY, qinfo->qtype, dnssec)) != RETVAL_OK) {
if(r == RETVAL_TRUNC) {
/* create truncated message */
ldns_buffer_write_u16_at(buffer, 8, nscount);
LDNS_TC_SET(ldns_buffer_begin(buffer));
ldns_buffer_flip(buffer);
return 1;
/* if response is positive answer, auth/add sections are not required */
if( ! (MINIMAL_RESPONSES && positive_answer(rep, qinfo->qtype)) ) {
/* insert auth section */
if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
rep->an_numrrsets, timenow, region, &tree,
LDNS_SECTION_AUTHORITY, qinfo->qtype,
dnssec, rr_offset)) != RETVAL_OK) {
if(r == RETVAL_TRUNC) {
/* create truncated message */
ldns_buffer_write_u16_at(buffer, 8, nscount);
LDNS_TC_SET(ldns_buffer_begin(buffer));
ldns_buffer_flip(buffer);
return 1;
}
return 0;
}
return 0;
}
ldns_buffer_write_u16_at(buffer, 8, nscount);
ldns_buffer_write_u16_at(buffer, 8, nscount);
/* insert add section */
if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
&tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype,
dnssec)) != RETVAL_OK) {
if(r == RETVAL_TRUNC) {
/* no need to set TC bit, this is the additional */
ldns_buffer_write_u16_at(buffer, 10, arcount);
ldns_buffer_flip(buffer);
return 1;
/* insert add section */
if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
&tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype,
dnssec, rr_offset)) != RETVAL_OK) {
if(r == RETVAL_TRUNC) {
/* no need to set TC bit, this is the additional */
ldns_buffer_write_u16_at(buffer, 10, arcount);
ldns_buffer_flip(buffer);
return 1;
}
return 0;
}
return 0;
ldns_buffer_write_u16_at(buffer, 10, arcount);
} else {
ldns_buffer_write_u16_at(buffer, 8, nscount);
ldns_buffer_write_u16_at(buffer, 10, arcount);
}
ldns_buffer_write_u16_at(buffer, 10, arcount);
ldns_buffer_flip(buffer);
return 1;
}

View file

@ -53,6 +53,12 @@
/** default value for EDNS ADVERTISED size */
uint16_t EDNS_ADVERTISED_SIZE = 4096;
/** minimal responses when positive answer: default is no */
int MINIMAL_RESPONSES = 0;
/** rrset order roundrobin: default is no */
int RRSET_ROUNDROBIN = 0;
/* returns true is string addr is an ip6 specced address */
int
str_is_ip6(const char* str)

View file

@ -93,6 +93,12 @@ extern uint16_t EDNS_ADVERTISED_SIZE;
/** DNSKEY secure entry point, KSK flag */
#define DNSKEY_BIT_SEP 0x0001
/** minimal responses when positive answer */
extern int MINIMAL_RESPONSES;
/** rrset order roundrobin */
extern int RRSET_ROUNDROBIN;
/**
* See if string is ip4 or ip6.
* @param str: IP specification.