Commit fc5168f8 authored by Marek Vavruša's avatar Marek Vavruša

zonecut: store zone cut info, allow empty root

parent 8f67f7d2
......@@ -21,8 +21,9 @@ static void delegmap_clear(struct kr_delegmap *map)
{
hattrie_iter_t *i = hattrie_iter_begin(map->trie, false);
while(!hattrie_iter_finished(i)) {
list_t *nslist = *hattrie_iter_val(i);
nslist_free(nslist, map->pool);
struct kr_zonecut *zonecut = *hattrie_iter_val(i);
nslist_free(&zonecut->nslist, map->pool);
mm_free(map->pool, zonecut->name);
hattrie_iter_next(i);
}
hattrie_iter_free(i);
......@@ -35,10 +36,17 @@ int kr_delegmap_init(struct kr_delegmap *map, mm_ctx_t *mm)
map->pool = mm;
map->trie = hattrie_create_n(TRIE_BUCKET_SIZE, mm);
if (map->trie == NULL) {
return -1;
return KNOT_ENOMEM;
}
return 0;
/* Initialize root entry. */
struct kr_zonecut *root = kr_delegmap_get(map, (const knot_dname_t*)"\0");
if (root == NULL) {
hattrie_free(map->trie);
return KNOT_ENOMEM;
}
return KNOT_EOK;
}
void kr_delegmap_deinit(struct kr_delegmap *map)
......@@ -47,30 +55,37 @@ void kr_delegmap_deinit(struct kr_delegmap *map)
hattrie_free(map->trie);
}
list_t *kr_delegmap_get(struct kr_delegmap *map, const knot_dname_t *name)
struct kr_zonecut *kr_delegmap_get(struct kr_delegmap *map, const knot_dname_t *name)
{
value_t *val = hattrie_get(map->trie, (const char *)name, knot_dname_size(name));
if (*val == NULL) {
*val = mm_alloc(map->pool, sizeof(list_t));
if (*val == NULL) {
struct kr_zonecut *dp = mm_alloc(map->pool, sizeof(struct kr_zonecut));
if (dp == NULL) {
return NULL;
}
dp->name = knot_dname_copy(name, map->pool);
if (dp->name == NULL) {
mm_free(map->pool, dp);
return NULL;
}
init_list((list_t *)*val);
init_list(&dp->nslist);
*val = dp;
}
return *val;
}
list_t *kr_delegmap_find(struct kr_delegmap *map, const knot_dname_t *name)
struct kr_zonecut *kr_delegmap_find(struct kr_delegmap *map, const knot_dname_t *name)
{
value_t *val = NULL;
while(val == NULL) {
val = hattrie_tryget(map->trie, (const char *)name, knot_dname_size(name));
if (val == NULL || EMPTY_LIST(*((list_t *)*val))) {
/* No root delegation, failure. */
/* Root delegation, may be empty. */
if (*name == '\0') {
assert(0);
return NULL;
return *val;
}
/* Look up parent. */
name = knot_wire_next_label(name, NULL);
......@@ -81,6 +96,15 @@ list_t *kr_delegmap_find(struct kr_delegmap *map, const knot_dname_t *name)
return *val;
}
struct kr_ns *kr_ns_first(list_t *list)
{
if (EMPTY_LIST(*list)) {
return NULL;
}
return HEAD(*list);
}
struct kr_ns *kr_ns_get(list_t *list, const knot_dname_t *name, mm_ctx_t *mm)
{
/* Check for duplicates. */
......@@ -96,7 +120,6 @@ struct kr_ns *kr_ns_get(list_t *list, const knot_dname_t *name, mm_ctx_t *mm)
memset(ns, 0, sizeof(struct kr_ns));
ns->name = knot_dname_copy(name, mm);
ns->flags = DP_LAME;
add_tail(list, (node_t *)ns);
......@@ -115,24 +138,8 @@ struct kr_ns *kr_ns_find(list_t *list, const knot_dname_t *name)
return NULL;
}
void kr_ns_invalidate(struct kr_ns *ns)
{
/* Slow start. */
ns->flags = DP_LAME;
ns->stat.M = KR_CONN_RTT_MAX;
ns->stat.S = 0;
ns->stat.n = 1;
/* Move to the end of the preference list. */
node_t *next = ns->node.next;
if (next->next) {
rem_node(&ns->node);
insert_node(&ns->node, next);
}
}
void kr_ns_remove(struct kr_ns *ns, mm_ctx_t *mm)
void kr_ns_del(list_t *list, struct kr_ns *ns, mm_ctx_t *mm)
{
rem_node((node_t *)ns);
rem_node(&ns->node);
ns_free(ns, mm);
}
......@@ -20,26 +20,21 @@ limitations under the License.
#include <libknot/internal/sockaddr.h>
#include <libknot/internal/trie/hat-trie.h>
/*! \brief Name server flag. */
enum kr_ns_flag {
DP_LAME = 0,
DP_PENDING = 1 << 0,
DP_RESOLVED = 1 << 1
};
struct kr_context;
/*! \brief Name server. */
struct kr_ns {
node_t node;
knot_dname_t *name;
struct sockaddr_storage addr;
unsigned valid_until;
struct {
double M, S; /* Mean, Variance S/n */
unsigned n;
} stat;
unsigned flags;
};
struct kr_zonecut {
list_t nslist;
knot_dname_t *name;
};
struct kr_delegmap {
......@@ -49,16 +44,15 @@ struct kr_delegmap {
int kr_delegmap_init(struct kr_delegmap *map, mm_ctx_t *mm);
void kr_delegmap_deinit(struct kr_delegmap *map);
list_t *kr_delegmap_get(struct kr_delegmap *map, const knot_dname_t *name);
list_t *kr_delegmap_find(struct kr_delegmap *map, const knot_dname_t *name);
struct kr_zonecut *kr_delegmap_get(struct kr_delegmap *map, const knot_dname_t *name);
struct kr_zonecut *kr_delegmap_find(struct kr_delegmap *map, const knot_dname_t *name);
/* TODO: find out how to do expire/refresh efficiently, maybe a sweep point and
* evaluate only DPs with validity before or around the sweep point, then
* choose next and move DPs from the other half for next sweep.
*/
struct kr_ns *kr_ns_first(list_t *list);
struct kr_ns *kr_ns_get(list_t *list, const knot_dname_t *name, mm_ctx_t *mm);
struct kr_ns *kr_ns_find(list_t *list, const knot_dname_t *name);
void kr_ns_invalidate(struct kr_ns *ns);
void kr_ns_remove(struct kr_ns *ns, mm_ctx_t *mm);
void kr_ns_del(list_t *list, struct kr_ns *ns, mm_ctx_t *mm);
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