Commit 140e028c authored by Marek Vavruša's avatar Marek Vavruša

lib: basic nameserver election

nameservers with addresses are preferred, the rest
has same weight

no blacklisting, penalization or rtt scoring yet
parent 87fffcd3
......@@ -15,9 +15,61 @@
*/
#include "lib/nsrep.h"
#include "lib/generic/pack.h"
int kr_nsrep_score(const knot_dname_t *ns, struct kr_layer_param *param)
/** @internal Macro to set address structure. */
#define ADDR_SET(sa, family, addr, len) do {\
memcpy(&sa ## _addr, (addr), (len)); \
sa ## _family = (family); \
sa ## _port = htons(KR_DNS_PORT); \
} while (0)
/** Update nameserver representation with current name/address pair. */
static void update_nsrep(struct kr_nsrep *ns, const knot_dname_t *name, uint8_t *addr, unsigned score)
{
ns->name = name;
ns->score = score;
if (addr == NULL) {
return;
}
size_t len = pack_obj_len(addr);
void *addr_val = pack_obj_val(addr);
switch(len) {
case sizeof(struct in_addr):
ADDR_SET(ns->addr.ip4.sin, AF_INET, addr_val, len); break;
case sizeof(struct in6_addr):
ADDR_SET(ns->addr.ip6.sin6, AF_INET6, addr_val, len); break;
default: assert(0); break;
}
}
#undef ADDR_SET
static int eval_nsrep(const char *k, void *v, void *baton)
{
unsigned score = KR_NS_VALID;
struct kr_nsrep *ns = baton;
pack_t *addr_set = v;
uint8_t *addr = NULL;
/* Name server is better candidate if it has address record. */
if (addr_set->len > 0) {
addr = pack_head(*addr_set);
score += 1;
}
/* Update best scoring nameserver. */
if (ns->score < score) {
update_nsrep(ns, (const knot_dname_t *)k, addr, score);
}
return kr_ok();
}
int kr_nsrep_elect(struct kr_nsrep *ns, map_t *nsset)
{
/* TODO: stub, always returns valid */
return KR_NS_VALID;
ns->addr.ip.sa_family = AF_UNSPEC;
ns->score = KR_NS_INVALID;
return map_walk(nsset, eval_nsrep, ns);
}
......@@ -20,18 +20,40 @@
#pragma once
#include <netinet/in.h>
#include "lib/generic/map.h"
#include "lib/layer.h"
enum kr_ns_score {
KR_NS_INVALID = -1,
KR_NS_VALID = 0
KR_NS_INVALID = 0,
KR_NS_VALID = 1
};
struct kr_nsrep
{
unsigned score;
const knot_dname_t *name;
union {
struct sockaddr ip;
struct sockaddr_in ip4;
struct sockaddr_in6 ip6;
} addr;
};
/** Return name server score (KR_NS_VALID is baseline, the higher the better).
* @param ns evaluated NS name
* @param param layer parameters
* @return enum kr_ns_score or higher positive value
/** @internal Address bytes for given family. */
#define kr_nsrep_inaddr(addr) \
((addr).ip.sa_family == AF_INET ? (void *)&((addr).ip4.sin_addr) : (void *)&((addr).ip6.sin6_addr))
/** @internal Address length for given family. */
#define kr_nsrep_inaddr_len(addr) \
((addr).ip.sa_family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr))
/**
* Elect best nameserver/address pair from the nsset.
* @param ns updated NS representation
* @param nsset NS set to choose from
* @return 0 if success (ns is updated), error otherwise
*/
int kr_nsrep_score(const knot_dname_t *ns, struct kr_layer_param *param);
int kr_nsrep_elect(struct kr_nsrep *ns, map_t *nsset);
/** @} */
......@@ -70,10 +70,17 @@ static int iterate(struct knot_requestor *requestor, struct kr_layer_param *para
DEBUG_MSG("query '%s %s'\n", name_str, type_str);
#endif
/* Invalid address for current zone cut. */
if (sockaddr_len((struct sockaddr *)&cur->zone_cut.addr) < 1) {
DEBUG_MSG("=> ns missing A/AAAA, fetching\n");
return ns_resolve_addr(cur, param);
/* Elect best nameserver candidate. */
kr_nsrep_elect(&cur->ns, &cur->zone_cut.nsset);
if (cur->ns.score < KR_NS_VALID) {
DEBUG_MSG("=> no valid NS left\n");
kr_rplan_pop(param->rplan, cur);
return KNOT_EOK;
} else {
if (cur->ns.addr.ip.sa_family == AF_UNSPEC) {
DEBUG_MSG("=> ns missing A/AAAA, fetching\n");
return ns_resolve_addr(cur, param);
}
}
/* Prepare query resolution. */
......@@ -120,7 +127,7 @@ static void prepare_layers(struct knot_requestor *req, struct kr_layer_param *pa
static int resolve_iterative(struct kr_layer_param *param, mm_ctx_t *pool)
{
/* Initialize requestor. */
/* Initialize requestor. */
struct knot_requestor requestor;
knot_requestor_init(&requestor, pool);
prepare_layers(&requestor, param);
......@@ -143,6 +150,7 @@ static int resolve_iterative(struct kr_layer_param *param, mm_ctx_t *pool)
}
}
DEBUG_MSG("finished: %s, mempool: %llu B\n", knot_strerror(ret), mp_total_size(pool->ctx));
knot_requestor_clear(&requestor);
return ret;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment