Fix incorrect scaling of weight 0 SRV records
Loosely based on patch by Nico.
This commit is contained in:
@@ -659,12 +659,15 @@ rk_dns_srv_order(struct rk_dns_reply *r)
|
|||||||
|
|
||||||
headp = &r->head;
|
headp = &r->head;
|
||||||
|
|
||||||
for(ss = srvs; ss < srvs + num_srv; ) {
|
for (ss = srvs; ss < srvs + num_srv; ) {
|
||||||
int sum, zeros, rnd, count;
|
int sum, zeros, rnd, count; /* zeros -> weight scaling */
|
||||||
struct rk_resource_record **ee, **tt;
|
struct rk_resource_record **ee, **tt;
|
||||||
/* find the last record with the same priority and count the
|
|
||||||
sum of all weights */
|
/*
|
||||||
for(sum = 0, zeros = 0, tt = ss; tt < srvs + num_srv; tt++) {
|
* find the last record with the same priority and count the sum of all
|
||||||
|
* weights
|
||||||
|
*/
|
||||||
|
for (sum = 0, zeros = 0, tt = ss; tt < srvs + num_srv; tt++) {
|
||||||
assert(*tt != NULL);
|
assert(*tt != NULL);
|
||||||
if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
|
if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
|
||||||
break;
|
break;
|
||||||
@@ -672,36 +675,43 @@ rk_dns_srv_order(struct rk_dns_reply *r)
|
|||||||
if ((*tt)->u.srv->weight == 0)
|
if ((*tt)->u.srv->weight == 0)
|
||||||
zeros++;
|
zeros++;
|
||||||
}
|
}
|
||||||
/* With no zeros, add 0 and scale * 1 */
|
/* make sure scale (`zeros') is > 0 then scale out */
|
||||||
sum += zeros ? zeros : zeros++;
|
sum += zeros ? 1 : zeros++;
|
||||||
sum *= zeros;
|
sum *= zeros;
|
||||||
ee = tt;
|
ee = tt;
|
||||||
/* ss is now the first record of this priority and ee is the
|
|
||||||
first of the next */
|
/*
|
||||||
while(ss < ee) {
|
* ss is now the first record of this priority and ee is the first of
|
||||||
|
* the next or the first past the end of srvs
|
||||||
|
*/
|
||||||
|
while (ss < ee) {
|
||||||
rnd = rk_random() % sum + 1;
|
rnd = rk_random() % sum + 1;
|
||||||
for(count = 0, tt = ss; ; tt++) {
|
for (count = 0, tt = ss; tt < ee; tt++) {
|
||||||
if(*tt == NULL)
|
if (*tt == NULL)
|
||||||
continue;
|
continue; /* this one's already been picked */
|
||||||
count += (*tt)->u.srv->weight * zeros;
|
|
||||||
if ((*tt)->u.srv->weight == 0)
|
if ((*tt)->u.srv->weight == 0)
|
||||||
count++;
|
count++;
|
||||||
if(count >= rnd)
|
else
|
||||||
|
count += (*tt)->u.srv->weight * zeros;
|
||||||
|
if (count >= rnd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(tt < ee);
|
assert(tt < ee);
|
||||||
|
|
||||||
/* insert the selected record at the tail (of the head) of
|
/* push the selected record */
|
||||||
the list */
|
|
||||||
(*tt)->next = *headp;
|
(*tt)->next = *headp;
|
||||||
*headp = *tt;
|
*headp = *tt;
|
||||||
headp = &(*tt)->next;
|
headp = &(*tt)->next;
|
||||||
sum -= (*tt)->u.srv->weight * zeros;
|
/*
|
||||||
|
* reduce the sum so the next iteration is sure to reach the random
|
||||||
|
* total after examining all the remaining records.
|
||||||
|
*/
|
||||||
if ((*tt)->u.srv->weight == 0)
|
if ((*tt)->u.srv->weight == 0)
|
||||||
sum--;
|
sum--;
|
||||||
|
else
|
||||||
|
sum -= (*tt)->u.srv->weight * zeros;
|
||||||
*tt = NULL;
|
*tt = NULL;
|
||||||
while(ss < ee && *ss == NULL)
|
while (ss < ee && *ss == NULL)
|
||||||
ss++;
|
ss++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user