aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gschwantner <tharre3@gmail.com>2019-07-18 02:49:05 +0200
committerThomas Gschwantner <tharre3@gmail.com>2019-07-18 15:14:46 +0200
commitf302fdecb5492fd43b647f0f60ca35427bf2987e (patch)
tree3b12e518b5f9edad1dc4dc05688ca605954a6f8d
parentImplement lease expiration (diff)
downloadwg-dynamic-f302fdecb5492fd43b647f0f60ca35427bf2987e.tar.xz
wg-dynamic-f302fdecb5492fd43b647f0f60ca35427bf2987e.zip
Move counting logic from lease.c to radix-trie.c
-rw-r--r--lease.c105
-rw-r--r--radix-trie.c92
-rw-r--r--radix-trie.h5
3 files changed, 94 insertions, 108 deletions
diff --git a/lease.c b/lease.c
index b105bc5..fc8eebf 100644
--- a/lease.c
+++ b/lease.c
@@ -17,15 +17,12 @@
#define TIME_T_MAX (((time_t)1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1
-static struct ip_pool pools;
+static struct ip_pool pool;
static time_t gexpires = TIME_T_MAX;
KHASH_MAP_INIT_WGKEY(leaseht, struct wg_dynamic_lease *)
khash_t(leaseht) * leases_ht;
-static uint64_t totall_ipv6;
-static uint32_t totalh_ipv6, total_ipv4;
-
static time_t get_monotonic_time()
{
struct timespec monotime;
@@ -51,9 +48,9 @@ void leases_init(char *fname)
leases_ht = kh_init(leaseht);
- ipp_init(&pools);
+ ipp_init(&pool);
- /* TODO: initialize pools properly from routes */
+ /* TODO: initialize pool properly from routes */
struct in_addr pool1_v4, pool2_v4;
struct in6_addr pool1_v6, pool2_v6;
inet_pton(AF_INET, "192.168.4.0", &pool1_v4);
@@ -61,87 +58,72 @@ void leases_init(char *fname)
inet_pton(AF_INET6, "2001:db8:1234::", &pool1_v6);
inet_pton(AF_INET6, "2001:db8:7777::", &pool2_v6);
- ipp_addpool_v4(&pools, &pool1_v4, 28);
- ipp_addpool_v4(&pools, &pool2_v4, 27);
- ipp_addpool_v6(&pools, &pool1_v6, 124);
- ipp_addpool_v6(&pools, &pool2_v6, 124);
-
- total_ipv4 = ipp_gettotal_v4(&pools);
- totall_ipv6 = ipp_gettotal_v6(&pools, &totalh_ipv6);
+ ipp_addpool_v4(&pool, &pool1_v4, 28);
+ ipp_addpool_v4(&pool, &pool2_v4, 27);
+ ipp_addpool_v6(&pool, &pool1_v6, 124);
+ ipp_addpool_v6(&pool, &pool2_v6, 124);
}
void leases_free()
{
kh_destroy(leaseht, leases_ht);
- ipp_free(&pools);
+ ipp_free(&pool);
}
struct wg_dynamic_lease *new_lease(wg_key pubkey, uint32_t leasetime,
struct in_addr *ipv4, struct in6_addr *ipv6)
{
struct wg_dynamic_lease *lease, *parent;
- uint64_t index_low;
- uint32_t index, index_high;
+ uint64_t index_l;
+ uint32_t index, index_h;
struct timespec tp;
khiter_t k;
int ret;
+ bool wants_ipv4 = !ipv4 || ipv4->s_addr;
+ bool wants_ipv6 = !ipv6 || !IN6_IS_ADDR_UNSPECIFIED(ipv6);
lease = malloc(sizeof *lease);
if (!lease)
fatal("malloc()");
- if (!ipv4 || ipv4->s_addr) {
- if (total_ipv4 == 0)
- return NULL;
+ if (wants_ipv4 && !pool.total_ipv4)
+ return NULL; /* no ipv4 addresses available */
- --total_ipv4;
- }
- if (!ipv6 || !IN6_IS_ADDR_UNSPECIFIED(ipv6)) {
- if (totalh_ipv6 == 0 && totall_ipv6 == 0) {
- if (!ipv4 || ipv4->s_addr)
- ++total_ipv4;
+ if (wants_ipv6 && !pool.totalh_ipv6 && !pool.totall_ipv6)
+ return NULL; /* no ipv6 addresses available */
- return NULL;
- }
-
- if (totall_ipv6 == 0)
- --totalh_ipv6;
-
- --totall_ipv6;
- }
-
- if (!ipv4 || ipv4->s_addr) {
+ if (wants_ipv4) {
if (!ipv4) {
- index = random_bounded(total_ipv4);
- debug("new_lease(v4): %u of %u\n", index, total_ipv4);
- ipp_addnth_v4(&pools, &lease->ipv4, index);
+ index = random_bounded(pool.total_ipv4 - 1);
+ debug("new_lease(v4): %u of %u\n", index,
+ pool.total_ipv4);
+
+ ipp_addnth_v4(&pool, &lease->ipv4, index);
} else {
- if (ipp_add_v4(&pools, ipv4, 32))
+ if (ipp_add_v4(&pool, ipv4, 32))
return NULL;
+
memcpy(&lease->ipv4, ipv4, sizeof *ipv4);
}
}
- if (!ipv6 || !IN6_IS_ADDR_UNSPECIFIED(ipv6)) {
- if (!ipv6) {
- if (totalh_ipv6 > 0) {
- index_low = random_bounded(UINT64_MAX);
- if (totall_ipv6 - index_low > totall_ipv6)
- --totalh_ipv6;
- index_high = random_bounded(totalh_ipv6);
+ if (wants_ipv6) {
+ if (!ipv6) {
+ if (pool.totalh_ipv6 > 0) {
+ index_l = random_bounded(UINT64_MAX);
+ index_h = random_bounded(pool.totalh_ipv6 - 1);
} else {
- index_low = random_bounded(totall_ipv6);
- index_high = 0;
+ index_l = random_bounded(pool.totall_ipv6 - 1);
+ index_h = 0;
}
- debug("new_lease(v6): %u:%ju of %u:%ju\n", index_high,
- index_low, totalh_ipv6, totall_ipv6);
- ipp_addnth_v6(&pools, &lease->ipv6, index_low,
- index_high);
+ debug("new_lease(v6): %u:%ju of %u:%ju\n", index_h,
+ index_l, pool.totalh_ipv6, pool.totall_ipv6);
+ ipp_addnth_v6(&pool, &lease->ipv6, index_l, index_h);
} else {
- if (ipp_add_v6(&pools, ipv6, 128)) {
+ if (ipp_add_v6(&pool, ipv6, 128)) {
if (!ipv4 || ipv4->s_addr)
- ipp_del_v4(&pools, ipv4, 32);
+ ipp_del_v4(&pool, ipv4, 32);
return NULL;
}
@@ -215,16 +197,11 @@ int leases_refresh()
struct in6_addr *ipv6 = &(*pp)->ipv6;
time_t expires = (*pp)->start_mono + (*pp)->leasetime;
if (cur_time >= expires) {
- if (ipv4->s_addr) {
- ipp_del_v4(&pools, ipv4, 32);
- ++total_ipv4;
- }
- if (!IN6_IS_ADDR_UNSPECIFIED(ipv6)) {
- ipp_del_v6(&pools, ipv6, 128);
- ++totall_ipv6;
- if (totall_ipv6 == 0)
- ++totalh_ipv6;
- }
+ if (ipv4->s_addr)
+ ipp_del_v4(&pool, ipv4, 32);
+
+ if (!IN6_IS_ADDR_UNSPECIFIED(ipv6))
+ ipp_del_v6(&pool, ipv6, 128);
tmp = *pp;
*pp = (*pp)->next;
diff --git a/radix-trie.c b/radix-trie.c
index f88d5f9..062490f 100644
--- a/radix-trie.c
+++ b/radix-trie.c
@@ -475,6 +475,7 @@ void ipp_init(struct ip_pool *pool)
{
pool->ip4_root = pool->ip6_root = NULL;
pool->ip4_pool = pool->ip6_pool = NULL;
+ pool->totall_ipv6 = pool->totalh_ipv6 = pool->total_ipv4 = 0;
}
void ipp_free(struct ip_pool *pool)
@@ -497,86 +498,90 @@ void ipp_free(struct ip_pool *pool)
int ipp_add_v4(struct ip_pool *pool, const struct in_addr *ip, uint8_t cidr)
{
- return insert_v4(&pool->ip4_root, ip, cidr);
+ int ret = insert_v4(&pool->ip4_root, ip, cidr);
+ if (!ret)
+ --pool->total_ipv4;
+
+ return ret;
}
int ipp_add_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr)
{
- return insert_v6(&pool->ip6_root, ip, cidr);
+ int ret = insert_v6(&pool->ip6_root, ip, cidr);
+ if (!ret) {
+ if (pool->totall_ipv6 == 0)
+ --pool->totalh_ipv6;
+
+ --pool->totall_ipv6;
+ }
+
+ return ret;
}
int ipp_del_v4(struct ip_pool *pool, const struct in_addr *ip, uint8_t cidr)
{
uint8_t key[4] __aligned(__alignof(uint32_t));
+ int ret;
+
swap_endian(key, (const uint8_t *)ip, 32);
+ ret = remove_node(pool->ip4_root, key, cidr);
+ if (!ret)
+ ++pool->total_ipv4;
- return remove_node(pool->ip4_root, key, cidr);
+ return ret;
}
int ipp_del_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr)
{
uint8_t key[16] __aligned(__alignof(uint64_t));
+ int ret;
+
swap_endian(key, (const uint8_t *)ip, 128);
+ ret = remove_node(pool->ip6_root, key, cidr);
+ if (!ret) {
+ ++pool->totall_ipv6;
+ if (pool->totall_ipv6 == 0)
+ ++pool->totalh_ipv6;
+ }
- return remove_node(pool->ip6_root, key, cidr);
+ return ret;
}
int ipp_addpool_v4(struct ip_pool *pool, const struct in_addr *ip, uint8_t cidr)
{
uint8_t key[4] __aligned(__alignof(uint32_t));
+ int ret;
if (cidr <= 0 || cidr >= 32)
return -1;
swap_endian(key, (const uint8_t *)ip, 32);
- return ipp_addpool(&pool->ip4_pool, &pool->ip4_root, 32, key, cidr);
+ ret = ipp_addpool(&pool->ip4_pool, &pool->ip4_root, 32, key, cidr);
+ if (!ret)
+ pool->total_ipv4 += 1 << (32 - cidr);
+
+ return ret;
}
int ipp_addpool_v6(struct ip_pool *pool, const struct in6_addr *ip,
uint8_t cidr)
{
uint8_t key[16] __aligned(__alignof(uint64_t));
+ int ret;
- if (cidr <= 0 || cidr < 64 || cidr >= 128)
+ if (cidr < 64 || cidr >= 128)
return -1;
swap_endian(key, (const uint8_t *)ip, 128);
- return ipp_addpool(&pool->ip6_pool, &pool->ip6_root, 128, key, cidr);
-}
-
-uint32_t ipp_gettotal_v4(struct ip_pool *pool)
-{
- struct radix_pool *current = pool->ip4_pool;
- uint32_t total = 0;
-
- for (current = pool->ip4_pool; current; current = current->next)
- total += current->node->left + current->node->right;
-
- return total;
-}
-
-uint64_t ipp_gettotal_v6(struct ip_pool *pool, uint32_t *high)
-{
- struct radix_pool *current = pool->ip6_pool;
- uint64_t t_low = 0, tmp;
- uint32_t t_high = 0;
-
- while (current) {
- if (current->node->left == 0 && current->node->right == 0) {
- current = current->next;
- continue;
- }
-
- tmp = t_low + current->node->left + current->node->right;
- if (tmp <= t_low)
- ++t_high;
-
- t_low = tmp;
- current = current->next;
+ ret = ipp_addpool(&pool->ip6_pool, &pool->ip6_root, 128, key, cidr);
+ if (!ret) {
+ uint64_t tmp = pool->totall_ipv6;
+ pool->totall_ipv6 += (cidr <= 64) ? 0 : 1 << (128 - cidr);
+ if (pool->totall_ipv6 <= tmp)
+ ++pool->totalh_ipv6;
}
- *high = t_high;
- return t_low;
+ return ret;
}
void ipp_addnth_v4(struct ip_pool *pool, struct in_addr *dest, uint32_t index)
@@ -593,6 +598,7 @@ void ipp_addnth_v4(struct ip_pool *pool, struct in_addr *dest, uint32_t index)
BUG_ON(!current);
add_nth(current->node, 32, index, (uint8_t *)&dest->s_addr);
+ --pool->total_ipv4;
}
void ipp_addnth_v6(struct ip_pool *pool, struct in6_addr *dest,
@@ -621,7 +627,11 @@ void ipp_addnth_v6(struct ip_pool *pool, struct in6_addr *dest,
current = current->next;
}
- BUG_ON(!pool || index_high);
+ BUG_ON(!current || index_high);
add_nth(current->node, 128, index_low, (uint8_t *)&dest->s6_addr);
+ if (pool->totall_ipv6 == 0)
+ --pool->totalh_ipv6;
+
+ --pool->totall_ipv6;
}
diff --git a/radix-trie.h b/radix-trie.h
index 9475cdb..60d383b 100644
--- a/radix-trie.h
+++ b/radix-trie.h
@@ -11,6 +11,8 @@
#include <stdint.h>
struct ip_pool {
+ uint64_t totall_ipv6;
+ uint32_t totalh_ipv6, total_ipv4;
struct radix_node *ip4_root, *ip6_root;
struct radix_pool *ip4_pool, *ip6_pool;
};
@@ -24,9 +26,6 @@ int ipp_add_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr);
int ipp_del_v4(struct ip_pool *pool, const struct in_addr *ip, uint8_t cidr);
int ipp_del_v6(struct ip_pool *pool, const struct in6_addr *ip, uint8_t cidr);
-uint32_t ipp_gettotal_v4(struct ip_pool *pool);
-uint64_t ipp_gettotal_v6(struct ip_pool *pool, uint32_t *high);
-
void ipp_addnth_v4(struct ip_pool *pool, struct in_addr *dest, uint32_t index);
void ipp_addnth_v6(struct ip_pool *pool, struct in6_addr *dest,
uint32_t index_low, uint64_t index_high);