diff options
Diffstat (limited to 'lib/nsrep.h')
-rw-r--r-- | lib/nsrep.h | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/lib/nsrep.h b/lib/nsrep.h new file mode 100644 index 0000000..cc35ca4 --- /dev/null +++ b/lib/nsrep.h @@ -0,0 +1,188 @@ +/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <netinet/in.h> +#include <sys/socket.h> +#include <libknot/dname.h> +#include <limits.h> + +#include "lib/defines.h" +#include "lib/generic/lru.h" + +struct kr_query; + +/** + * NS RTT score (special values). + * @note RTT is measured in milliseconds. + */ +enum kr_ns_score { + KR_NS_MAX_SCORE = 20 * KR_CONN_RTT_MAX, /* max possible value */ + KR_NS_FWD_TIMEOUT = (95 * 10000) / 100, /* timeout for upstream recursor, + * 95 percents from max resolution time */ + KR_NS_TIMEOUT = (95 * KR_CONN_RTT_MAX) / 100, /* timeout for upstream auth */ + KR_NS_LONG = (3 * KR_NS_TIMEOUT) / 4, + KR_NS_UNKNOWN = KR_NS_TIMEOUT / 2, + KR_NS_PENALTY = 100, + KR_NS_GLUED = 10 +}; + +/** + * See kr_nsrep_update_rtt() + */ +#define KR_NS_DEAD (((KR_NS_TIMEOUT * 4) + 3) / 3) +#define KR_NS_FWD_DEAD (((KR_NS_FWD_TIMEOUT * 4) + 3) / 3) + +/** If once NS was marked as "timeouted", it won't participate in NS elections + * at least KR_NS_TIMEOUT_RETRY_INTERVAL milliseconds (now: one second). */ +#define KR_NS_TIMEOUT_RETRY_INTERVAL 1000 + +/** + * NS QoS flags. + */ +enum kr_ns_rep { + KR_NS_NOIP4 = 1 << 0, /**< NS has no IPv4 */ + KR_NS_NOIP6 = 1 << 1, /**< NS has no IPv6 */ + KR_NS_NOEDNS = 1 << 2 /**< NS has no EDNS support */ +}; + +/** + * NS RTT update modes. + * First update is always KR_NS_RESET unless + * KR_NS_UPDATE_NORESET mode had choosen. + */ +enum kr_ns_update_mode { + KR_NS_UPDATE = 0, /**< Update as smooth over last two measurements */ + KR_NS_UPDATE_NORESET, /**< Same as KR_NS_UPDATE, but disable fallback to + * KR_NS_RESET on newly added entries. + * Zero is used as initial value. */ + KR_NS_RESET, /**< Set to given value */ + KR_NS_ADD, /**< Increment current value */ + KR_NS_MAX /**< Set to maximum of current/proposed value. */ +}; + +struct kr_nsrep_rtt_lru_entry { + unsigned score; /* combined rtt */ + uint64_t tout_timestamp; /* The time when score became + * greater or equal then KR_NS_TIMEOUT. + * Is meaningful only when score >= KR_NS_TIMEOUT */ +}; + +typedef struct kr_nsrep_rtt_lru_entry kr_nsrep_rtt_lru_entry_t; + +/** + * NS QoS tracking. + */ +typedef lru_t(kr_nsrep_rtt_lru_entry_t) kr_nsrep_rtt_lru_t; + +/** + * NS reputation tracking. + */ +typedef lru_t(unsigned) kr_nsrep_lru_t; + +/* Maximum count of addresses probed in one go (last is left empty) */ +#define KR_NSREP_MAXADDR 4 + +/** + * Name server representation. + * Contains extra information about the name server, e.g. score + * or other metadata. + */ +struct kr_nsrep +{ + unsigned score; /**< NS score */ + unsigned reputation; /**< NS reputation */ + const knot_dname_t *name; /**< NS name */ + struct kr_context *ctx; /**< Resolution context */ + union inaddr addr[KR_NSREP_MAXADDR]; /**< NS address(es) */ +}; + +/** + * Set given NS address. (Very low-level access to the list.) + * @param qry updated query + * @param index index of the updated target + * @param sock socket address to use (sockaddr_in or sockaddr_in6 or NULL) + * @return 0 or an error code, in particular kr_error(ENOENT) for net.ipvX + */ +KR_EXPORT +int kr_nsrep_set(struct kr_query *qry, size_t index, const struct sockaddr *sock); + +/** + * Elect best nameserver/address pair from the nsset. + * @param qry updated query + * @param ctx resolution context + * @return 0 or an error code + */ +KR_EXPORT +int kr_nsrep_elect(struct kr_query *qry, struct kr_context *ctx); + +/** + * Elect best nameserver/address pair from the nsset. + * @param qry updated query + * @param ctx resolution context + * @return 0 or an error code + */ +KR_EXPORT +int kr_nsrep_elect_addr(struct kr_query *qry, struct kr_context *ctx); + +/** + * Update NS address RTT information. + * + * @brief In KR_NS_UPDATE mode reputation is smoothed over last N measurements. + * + * @param ns updated NS representation + * @param addr chosen address (NULL for first) + * @param score new score (i.e. RTT), see enum kr_ns_score + * @param cache RTT LRU cache + * @param umode update mode (KR_NS_UPDATE or KR_NS_RESET or KR_NS_ADD) + * @return 0 on success, error code on failure + */ +KR_EXPORT +int kr_nsrep_update_rtt(struct kr_nsrep *ns, const struct sockaddr *addr, + unsigned score, kr_nsrep_rtt_lru_t *cache, int umode); + +/** + * Update NSSET reputation information. + * + * @param ns updated NS representation + * @param reputation combined reputation flags, see enum kr_ns_rep + * @param cache LRU cache + * @return 0 on success, error code on failure + */ +KR_EXPORT +int kr_nsrep_update_rep(struct kr_nsrep *ns, unsigned reputation, kr_nsrep_lru_t *cache); +/** + * Copy NSSET reputation information and resets score. + * + * @param dst updated NS representation + * @param src source NS representation + * @return 0 on success, error code on failure + */ +int kr_nsrep_copy_set(struct kr_nsrep *dst, const struct kr_nsrep *src); + +/** + * Sort addresses in the query nsrep list by cached RTT. + * if RTT is greater then KR_NS_TIMEOUT, address will placed at the beginning of the + * nsrep list once in cache.ns_tout() milliseconds. Otherwise it will be sorted + * as if it has cached RTT equal to KR_NS_MAX_SCORE + 1. + * @param ns updated kr_nsrep + * @param ctx name resolution context. + * @return 0 or an error code + * @note ns reputation is zeroed and score is set to KR_NS_MAX_SCORE + 1. + */ +KR_EXPORT +int kr_nsrep_sort(struct kr_nsrep *ns, struct kr_context *ctx); |