static unsigned eval_addr_set(pack_t *addr_set, kr_nsrep_lru_t *rttcache, unsigned score, uint8_t *addr[], uint32_t opts) { /* Name server is better candidate if it has address record. */ uint8_t *it = pack_head(*addr_set); while (it != pack_tail(*addr_set)) { void *val = pack_obj_val(it); size_t len = pack_obj_len(it); unsigned favour = 0; bool is_valid = false; /* Check if the address isn't disabled. */ if (len == sizeof(struct in6_addr)) { is_valid = !(opts & QUERY_NO_IPV6); favour = FAVOUR_IPV6; } else { is_valid = !(opts & QUERY_NO_IPV4); } /* Get RTT for this address (if known) */ if (is_valid) { unsigned *cached = rttcache ? lru_get(rttcache, val, len) : NULL; unsigned addr_score = (cached) ? *cached : KR_NS_GLUED; if (addr_score < score + favour) { /* Shake down previous contenders */ for (size_t i = KR_NSREP_MAXADDR - 1; i > 0; --i) addr[i] = addr[i - 1]; addr[0] = it; score = addr_score; } } it = pack_obj_next(it); } return score; }
static int eval_nsrep(const char *k, void *v, void *baton) { struct kr_query *qry = baton; struct kr_nsrep *ns = &qry->ns; struct kr_context *ctx = ns->ctx; unsigned score = KR_NS_MAX_SCORE; unsigned reputation = 0; uint8_t *addr = NULL; /* Fetch NS reputation */ if (ctx->cache_rep) { unsigned *cached = lru_get(ctx->cache_rep, k, knot_dname_size((const uint8_t *)k)); if (cached) { reputation = *cached; } } /* Favour nameservers with unknown addresses to probe them, * otherwise discover the current best address for the NS. */ pack_t *addr_set = (pack_t *)v; if (addr_set->len == 0) { score = KR_NS_UNKNOWN; /* If the server doesn't have IPv6, give it disadvantage. */ if (reputation & KR_NS_NOIP6) { score += FAVOUR_IPV6; /* If the server is unknown but has rep record, treat it as timeouted */ if (reputation & KR_NS_NOIP4) { score = KR_NS_TIMEOUT; reputation = 0; /* Start with clean slate */ } } } else { score = eval_addr_set(addr_set, ctx->cache_rtt, score, &addr); } /* Probabilistic bee foraging strategy (naive). * The fastest NS is preferred by workers until it is depleted (timeouts or degrades), * at the same time long distance scouts probe other sources (low probability). * Servers on TIMEOUT (depleted) can be probed by the dice roll only */ if (score < ns->score && (qry->flags & QUERY_NO_THROTTLE || score < KR_NS_TIMEOUT)) { update_nsrep(ns, (const knot_dname_t *)k, addr, score); ns->reputation = reputation; } else { /* With 5% chance, probe server with a probability given by its RTT / MAX_RTT */ if ((kr_rand_uint(100) < 5) && (kr_rand_uint(KR_NS_MAX_SCORE) >= score)) { /* If this is a low-reliability probe, go with TCP to get ICMP reachability check. */ if (score >= KR_NS_LONG) { qry->flags |= QUERY_TCP; } update_nsrep(ns, (const knot_dname_t *)k, addr, score); ns->reputation = reputation; return 1; /* Stop evaluation */ } } return kr_ok(); }
static int lf_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { if (strcmp(path, "/") != 0) return -ENOENT; unsigned int item_count = lru_count(); filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); for (unsigned int i = 0; i < item_count; i++) { char *path = lru_get(i); filler(buf, path+1, NULL, 0); } return 0; }
static unsigned eval_addr_set(pack_t *addr_set, kr_nsrep_lru_t *rttcache, unsigned score, uint8_t **addr) { /* Name server is better candidate if it has address record. */ uint8_t *it = pack_head(*addr_set); while (it != pack_tail(*addr_set)) { void *val = pack_obj_val(it); size_t len = pack_obj_len(it); /* Get RTT for this address (if known) */ unsigned *cached = rttcache ? lru_get(rttcache, val, len) : NULL; unsigned addr_score = (cached) ? *cached : KR_NS_GLUED; /* Give v6 a head start */ unsigned favour = (len == sizeof(struct in6_addr)) ? FAVOUR_IPV6 : 0; if (addr_score < score + favour) { *addr = it; score = addr_score; } it = pack_obj_next(it); } return score; }
int object_cache_isvalid(u64 oid) { return objectroot != NULL && lru_get(object_cache_status, &oid) != NULL; }