0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

For safer memory allocations, resources are bound to loops.

Also all loops have their basic resource pool for allocations which are
auto-freed when the loop is stopping.
This commit is contained in:
Maria Matejka 2021-11-30 18:16:49 +01:00
parent ab0994a10c
commit 385b3ea395
32 changed files with 303 additions and 159 deletions

View File

@ -89,7 +89,7 @@ int undo_available; /* Undo was not requested from last reconfiguration */
struct config *
config_alloc(const char *name)
{
pool *p = rp_new(&root_pool, "Config");
pool *p = rp_new(&root_pool, &main_birdloop, "Config");
linpool *l = lp_new_default(p);
struct config *c = lp_allocz(l, sizeof(struct config));
@ -196,7 +196,7 @@ void
config_free(struct config *c)
{
if (c)
rfree(c->pool);
rp_free(c->pool, &root_pool);
}
void

View File

@ -20,7 +20,7 @@ start_conf_env(void)
{
bt_bird_init();
pool *p = rp_new(&root_pool, "helper_pool");
pool *p = rp_new(&root_pool, &main_birdloop, "helper_pool");
linpool *l = lp_new_default(p);
cfg_mem = l;
}

View File

@ -57,8 +57,8 @@ t_ev_run_list(void)
resource_sys_init();
resource_init();
olock_init();
birdloop_init();
olock_init();
io_init();
rt_init();
if_init();

View File

@ -8,6 +8,7 @@
#include "test/birdtest.h"
#include "lib/flowspec.h"
#include "lib/io-loop.h"
#define NET_ADDR_FLOW4_(what,prefix,pxlen,data_) \
do \
@ -446,8 +447,6 @@ t_validation6(void)
static int
t_builder4(void)
{
resource_init();
struct flow_builder *fb = flow_builder_init(&root_pool);
linpool *lp = lp_new_default(&root_pool);
@ -529,7 +528,6 @@ t_builder6(void)
{
net_addr_ip6 ip;
resource_init();
linpool *lp = lp_new_default(&root_pool);
struct flow_builder *fb = flow_builder_init(&root_pool);
fb->ipv6 = 1;
@ -673,6 +671,9 @@ main(int argc, char *argv[])
{
bt_init(argc, argv);
resource_sys_init();
resource_init();
the_bird_lock();
birdloop_init();
bt_test_suite(t_read_length, "Testing get NLRI length");
bt_test_suite(t_write_length, "Testing set NLRI length");
@ -688,5 +689,6 @@ main(int argc, char *argv[])
bt_test_suite(t_formatting4, "Formatting Flow Specification (IPv4) into text representation");
bt_test_suite(t_formatting6, "Formatting Flow Specification (IPv6) into text representation");
the_bird_unlock();
return bt_exit_value();
}

View File

@ -9,7 +9,9 @@
#undef LOCAL_DEBUG
#include "test/birdtest.h"
#include "test/bt-utils.h"
#include "lib/io-loop.h"
#include "lib/hash.h"
struct test_node {
@ -61,8 +63,7 @@ dump_nodes(void)
static void
init_hash_(uint order)
{
resource_init();
my_pool = rp_new(&root_pool, "Test pool");
my_pool = rp_new(&root_pool, &main_birdloop, "Test pool");
HASH_INIT(hash, my_pool, order);
@ -290,6 +291,7 @@ int
main(int argc, char *argv[])
{
bt_init(argc, argv);
bt_bird_init();
bt_test_suite(t_insert_find, "HASH_INSERT and HASH_FIND");
bt_test_suite(t_insert_find_random, "HASH_INSERT pseudo-random keys and HASH_FIND");

View File

@ -20,15 +20,15 @@ void sk_reloop(sock *s, struct birdloop *loop);
extern struct birdloop main_birdloop;
/* Start a new birdloop owned by given pool and domain */
/* Start a new birdloop owned by given pool and domain.
* The loop allocates its internal pool for local allocations
* which is freed when the loop itself is stopped. */
struct birdloop *birdloop_new(pool *p, uint order, const char *name);
/* Stop the loop. At the end, the @stopped callback is called unlocked in tail
* position to finish cleanup. Run birdloop_free() from that callback to free
* the loop itself. */
/* Stop the loop. At the end, the @stopped callback is called with locked
* parent to finish cleanup. The loop then frees itself together with its pool. */
void birdloop_stop(struct birdloop *loop, void (*stopped)(void *data), void *data);
void birdloop_stop_self(struct birdloop *loop, void (*stopped)(void *data), void *data);
void birdloop_free(struct birdloop *loop);
/* Get birdloop's event list */
event_list *birdloop_event_list(struct birdloop *loop);
@ -36,6 +36,9 @@ event_list *birdloop_event_list(struct birdloop *loop);
/* Get birdloop's time heap */
struct timeloop *birdloop_time_loop(struct birdloop *loop);
/* Get birdloop's resource pool */
pool *birdloop_pool(struct birdloop *loop);
/* Enter and exit the birdloop */
void birdloop_enter(struct birdloop *loop);
void birdloop_leave(struct birdloop *loop);

View File

@ -14,6 +14,7 @@
#include "lib/resource.h"
#include "lib/string.h"
#include "lib/rcu.h"
#include "lib/io-loop.h"
/**
* DOC: Resource pools
@ -29,13 +30,6 @@
* is freed upon shutdown of the module.
*/
struct pool {
resource r;
list inside;
struct pool_pages *pages;
const char *name;
};
struct pool_pages {
uint free;
uint used;
@ -68,26 +62,39 @@ static int indent;
/**
* rp_new - create a resource pool
* @p: parent pool
* @l: loop to assign
* @name: pool name (to be included in debugging dumps)
*
* rp_new() creates a new resource pool inside the specified
* parent pool.
*/
pool *
rp_new(pool *p, const char *name)
rp_new(pool *p, struct birdloop *loop, const char *name)
{
ASSERT_DIE(birdloop_inside(p->loop));
ASSERT_DIE(birdloop_inside(loop));
pool *z = ralloc(p, &pool_class);
z->loop = loop;
z->name = name;
init_list(&z->inside);
return z;
}
_Thread_local static pool *pool_parent = NULL;
static void
pool_free(resource *P)
{
pool *p = (pool *) P;
resource *r, *rr;
ASSERT_DIE(pool_parent);
pool *p = (pool *) P;
ASSERT_DIE(birdloop_inside(p->loop));
pool *parent = pool_parent;
pool_parent = p;
resource *r, *rr;
r = HEAD(p->inside);
while (rr = (resource *) r->n.next)
{
@ -105,14 +112,25 @@ pool_free(resource *P)
free_sys_page(p->pages);
}
pool_parent = parent;
}
void
rp_free(pool *p, pool *parent)
{
ASSERT_DIE(pool_parent == NULL);
pool_parent = parent;
rfree(p);
ASSERT_DIE(pool_parent == parent);
pool_parent = NULL;
}
static void
pool_dump(resource *P)
pool_dump_locked(pool *p)
{
pool *p = (pool *) P;
resource *r;
debug("%s\n", p->name);
indent += 3;
WALK_LIST(r, p->inside)
@ -120,10 +138,47 @@ pool_dump(resource *P)
indent -= 3;
}
static size_t
pool_memsize(resource *P)
static void
pool_dump(resource *P)
{
pool *p = (pool *) P;
if (p->loop != pool_parent->loop)
birdloop_enter(p->loop);
pool *parent = pool_parent;
pool_parent = p;
pool_dump_locked(p);
pool_parent = parent;
if (p->loop != pool_parent->loop)
birdloop_leave(p->loop);
}
void
rp_dump(pool *p)
{
int inside = birdloop_inside(p->loop);
if (!inside)
birdloop_enter(p->loop);
ASSERT_DIE(pool_parent == NULL);
pool_parent = p;
pool_dump_locked(p);
ASSERT_DIE(pool_parent == p);
pool_parent = NULL;
if (!inside)
birdloop_leave(p->loop);
}
static size_t
pool_memsize_locked(pool *p)
{
resource *r;
size_t sum = sizeof(pool) + ALLOC_OVERHEAD;
@ -136,6 +191,46 @@ pool_memsize(resource *P)
return sum;
}
static size_t
pool_memsize(resource *P)
{
pool *p = (pool *) P;
pool *parent = pool_parent;
pool_parent = p;
if (p->loop != parent->loop)
birdloop_enter(p->loop);
size_t sum = pool_memsize_locked(p);
if (p->loop != parent->loop)
birdloop_leave(p->loop);
pool_parent = parent;
return sum;
}
size_t
rp_memsize(pool *p)
{
int inside = birdloop_inside(p->loop);
if (!inside)
birdloop_enter(p->loop);
ASSERT_DIE(pool_parent == NULL);
pool_parent = p;
size_t sum = pool_memsize_locked(p);
ASSERT_DIE(pool_parent == p);
pool_parent = NULL;
if (!inside)
birdloop_leave(p->loop);
return sum;
}
static resource *
pool_lookup(resource *P, unsigned long a)
{
@ -243,12 +338,15 @@ rmemsize(void *res)
void *
ralloc(pool *p, struct resclass *c)
{
ASSERT_DIE(p);
ASSERT_DIE(birdloop_inside(p->loop));
resource *r = xmalloc(c->size);
bzero(r, c->size);
r->class = c;
if (p)
add_tail(&p->inside, &r->n);
add_tail(&p->inside, &r->n);
return r;
}

View File

@ -34,10 +34,16 @@ struct resclass {
/* Generic resource manipulation */
typedef struct pool pool;
typedef struct pool {
resource r;
list inside;
struct pool_pages *pages;
struct birdloop *loop;
const char *name;
} pool;
void resource_init(void);
pool *rp_new(pool *, const char *); /* Create new pool */
void rfree(void *); /* Free single resource */
void rdump(void *); /* Dump to debug output */
size_t rmemsize(void *res); /* Return size of memory used by the resource */
@ -46,6 +52,11 @@ void rmove(void *, pool *); /* Move to a different pool */
void *ralloc(pool *, struct resclass *);
pool *rp_new(pool *, struct birdloop *loop, const char *); /* Create new pool */
void rp_free(pool *p, pool *parent); /* Free parent pool */
size_t rp_memsize(pool *p); /* Return size of memory used by the pool */
void rp_dump(pool *p); /* Dump pool to debug output */
extern pool root_pool;
/* Normal memory blocks */

View File

@ -12,6 +12,7 @@
#include "nest/route.h"
#include "nest/attrs.h"
#include "lib/resource.h"
#include "lib/io-loop.h"
#define TESTS_NUM 30
#define AS_PATH_LENGTH 1000
@ -23,8 +24,6 @@
static int
t_as_path_match(void)
{
resource_init();
int round;
for (round = 0; round < TESTS_NUM; round++)
{
@ -70,8 +69,6 @@ t_as_path_match(void)
static int
t_path_format(void)
{
resource_init();
struct adata empty_as_path = {};
struct adata *as_path = &empty_as_path;
struct linpool *lp = lp_new_default(&root_pool);
@ -116,8 +113,6 @@ count_asn_in_array(const u32 *array, u32 asn)
static int
t_path_include(void)
{
resource_init();
struct adata empty_as_path = {};
struct adata *as_path = &empty_as_path;
struct linpool *lp = lp_new_default(&root_pool);
@ -161,8 +156,6 @@ t_path_include(void)
static int
t_as_path_converting(void)
{
resource_init();
struct adata empty_as_path = {};
struct adata *as_path = &empty_as_path;
struct linpool *lp = lp_new_default(&root_pool);
@ -211,6 +204,9 @@ main(int argc, char *argv[])
{
bt_init(argc, argv);
resource_sys_init();
resource_init();
the_bird_lock();
birdloop_init();
bt_test_suite(t_as_path_match, "Testing AS path matching and some a-path utilities.");
bt_test_suite(t_path_format, "Testing formating as path into byte buffer");

View File

@ -13,6 +13,7 @@
#include "nest/route.h"
#include "nest/attrs.h"
#include "lib/resource.h"
#include "lib/io-loop.h"
#define SET_SIZE 10
static const struct adata *set_sequence; /* <0; SET_SIZE) */
@ -71,7 +72,6 @@ t_set_int_contains(void)
{
int i;
resource_init();
generate_set_sequence(SET_TYPE_INT, SET_SIZE);
bt_assert(int_set_get_size(set_sequence) == SET_SIZE);
@ -92,7 +92,6 @@ t_set_int_contains(void)
static int
t_set_int_union(void)
{
resource_init();
generate_set_sequence(SET_TYPE_INT, SET_SIZE);
const struct adata *set_union;
@ -111,7 +110,6 @@ t_set_int_union(void)
static int
t_set_int_format(void)
{
resource_init();
generate_set_sequence(SET_TYPE_INT, SET_SIZE_FOR_FORMAT_OUTPUT);
bt_assert(int_set_format(set_sequence, 0, 0, buf, BUFFER_SIZE) == 0);
@ -132,7 +130,6 @@ t_set_int_format(void)
static int
t_set_int_delete(void)
{
resource_init();
generate_set_sequence(SET_TYPE_INT, SET_SIZE);
const struct adata *deleting_sequence = set_sequence;
@ -160,7 +157,6 @@ t_set_ec_contains(void)
{
u32 i;
resource_init();
generate_set_sequence(SET_TYPE_EC, SET_SIZE);
bt_assert(ec_set_get_size(set_sequence) == SET_SIZE);
@ -181,7 +177,6 @@ t_set_ec_contains(void)
static int
t_set_ec_union(void)
{
resource_init();
generate_set_sequence(SET_TYPE_EC, SET_SIZE);
const struct adata *set_union;
@ -200,8 +195,6 @@ t_set_ec_union(void)
static int
t_set_ec_format(void)
{
resource_init();
const struct adata empty_as_path = {};
set_sequence = set_sequence_same = set_sequence_higher = set_random = &empty_as_path;
lp = lp_new_default(&root_pool);
@ -222,7 +215,6 @@ t_set_ec_format(void)
static int
t_set_ec_delete(void)
{
resource_init();
generate_set_sequence(SET_TYPE_EC, SET_SIZE);
const struct adata *deleting_sequence = set_sequence;
@ -248,6 +240,9 @@ main(int argc, char *argv[])
{
bt_init(argc, argv);
resource_sys_init();
resource_init();
the_bird_lock();
birdloop_init();
bt_test_suite(t_set_int_contains, "Testing sets of integers: contains, get_data");
bt_test_suite(t_set_int_format, "Testing sets of integers: format");

View File

@ -262,7 +262,7 @@ cli_command(struct cli *c)
log(L_TRACE "CLI: %s", c->rx_buf);
bzero(&f, sizeof(f));
f.mem = c->parser_pool;
f.pool = rp_new(c->pool, "Config");
f.pool = rp_new(c->pool, &main_birdloop, "Config");
init_list(&f.symbols);
cf_read_hook = cli_cmd_read_hook;
cli_rh_pos = c->rx_buf;
@ -308,7 +308,7 @@ cli_event(void *data)
cli *
cli_new(void *priv)
{
pool *p = rp_new(cli_pool, "CLI");
pool *p = rp_new(cli_pool, &main_birdloop, "CLI");
cli *c = mb_alloc(p, sizeof(cli));
bzero(c, sizeof(cli));
@ -413,7 +413,7 @@ cli_free(cli *c)
c->cleanup(c);
if (c == cmd_reconfig_stored_cli)
cmd_reconfig_stored_cli = NULL;
rfree(c->pool);
rp_free(c->pool, &root_pool);
}
/**
@ -425,7 +425,7 @@ cli_free(cli *c)
void
cli_init(void)
{
cli_pool = rp_new(&root_pool, "CLI");
cli_pool = rp_new(&root_pool, &main_birdloop, "CLI");
init_list(&cli_log_hooks);
cli_log_inited = 1;
}

View File

@ -88,10 +88,10 @@ void
cmd_show_memory(void)
{
cli_msg(-1018, "BIRD memory usage");
print_size("Routing tables:", rmemsize(rt_table_pool));
print_size("Route attributes:", rmemsize(rta_pool));
print_size("Protocols:", rmemsize(proto_pool));
print_size("Total:", rmemsize(&root_pool));
print_size("Routing tables:", rp_memsize(rt_table_pool));
print_size("Route attributes:", rp_memsize(rta_pool));
print_size("Protocols:", rp_memsize(proto_pool));
print_size("Total:", rp_memsize(&root_pool));
cli_msg(0, "");
}

View File

@ -810,7 +810,7 @@ sym_args:
CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
{ rdump(&root_pool); cli_msg(0, ""); } ;
{ rp_dump(&root_pool); cli_msg(0, ""); } ;
CF_CLI(DUMP SOCKETS,,, [[Dump open sockets]])
{ sk_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP EVENTS,,, [[Dump event log]])

View File

@ -713,7 +713,7 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
void
if_init(void)
{
if_pool = rp_new(&root_pool, "Interfaces");
if_pool = rp_new(&root_pool, &main_birdloop, "Interfaces");
init_list(&iface_list);
strcpy(default_vrf.name, "default");
neigh_init(if_pool);

View File

@ -666,7 +666,10 @@ static uint channel_aux_imex(struct channel_aux_table *cat)
static void
channel_aux_stopped(void *data)
{
struct channel_aux_table *cat = data;
struct channel_aux_table *cat;
RT_LOCKED((rtable *) data, t)
cat = t->config->owner;
struct channel *c = cat->c;
if (channel_aux_imex(cat))
@ -674,7 +677,6 @@ channel_aux_stopped(void *data)
else
c->in_table = NULL;
rfree(cat->tab->priv.rp);
mb_free(cat);
channel_check_stopped(c);
}
@ -694,7 +696,7 @@ channel_aux_export_stopped(struct rt_export_request *req)
int del;
RT_LOCKED(cat->tab, t)
del = !!t->delete_event;
del = !!t->delete;
if (del)
return;
@ -708,10 +710,7 @@ static void
channel_aux_stop(struct channel_aux_table *cat)
{
RT_LOCKED(cat->tab, t)
{
t->delete_event = ev_new_init(t->rp, channel_aux_stopped, cat);
t->delete_event->list = proto_event_list(cat->c->proto);
}
t->delete = channel_aux_stopped;
cat->push_stopped = (event) {
.hook = channel_aux_import_stopped,
@ -889,6 +888,7 @@ channel_setup_in_table(struct channel *c, int best)
bsprintf(cat->name, "%s.%s.import", c->proto->name, c->name);
cat->tab_cf.owner = cat;
cat->tab_cf.name = cat->name;
cat->tab_cf.addr_type = c->net_type;
cat->tab_cf.cork_limit = 4 * page_size / sizeof(struct rt_pending_export);
@ -933,6 +933,7 @@ channel_setup_out_table(struct channel *c)
bsprintf(cat->name, "%s.%s.export", c->proto->name, c->name);
cat->tab_cf.owner = cat;
cat->tab_cf.name = cat->name;
cat->tab_cf.addr_type = c->net_type;
cat->tab_cf.cork_limit = 4 * page_size / sizeof(struct rt_pending_export);
@ -1387,9 +1388,6 @@ proto_configure_channel(struct proto *p, struct channel **pc, struct channel_con
static void
proto_cleanup(struct proto *p)
{
rfree(p->pool);
p->pool = NULL;
p->active = 0;
proto_log_state_change(p);
proto_rethink_goal(p);
@ -1400,13 +1398,13 @@ proto_loop_stopped(void *ptr)
{
struct proto *p = ptr;
birdloop_enter(&main_birdloop);
ASSERT_DIE(birdloop_inside(&main_birdloop));
p->loop = &main_birdloop;
p->pool = NULL;
p->event->list = NULL;
proto_cleanup(p);
birdloop_leave(&main_birdloop);
proto_cleanup(p);
}
static void
@ -1426,7 +1424,11 @@ proto_event(void *ptr)
if (p->loop != &main_birdloop)
birdloop_stop_self(p->loop, proto_loop_stopped, p);
else
{
rp_free(p->pool, proto_pool);
p->pool = NULL;
proto_cleanup(p);
}
}
@ -1490,13 +1492,16 @@ proto_start(struct proto *p)
void *nb = mb_alloc(proto_pool, ns);
ASSERT_DIE(ns - 1 == bsnprintf(nb, ns, "Protocol %s", p->cf->name));
p->pool = rp_new(proto_pool, nb);
if (graceful_restart_state == GRS_INIT)
p->gr_recovery = 1;
if (p->cf->loop_order != DOMAIN_ORDER(the_bird))
p->loop = birdloop_new(p->pool, p->cf->loop_order, nb);
if (p->cf->loop_order == DOMAIN_ORDER(the_bird))
p->pool = rp_new(proto_pool, &main_birdloop, nb);
else
{
p->loop = birdloop_new(proto_pool, p->cf->loop_order, nb);
p->pool = birdloop_pool(p->loop);
}
p->event->list = proto_event_list(p);
@ -2177,7 +2182,7 @@ protos_build(void)
proto_build(&proto_perf);
#endif
proto_pool = rp_new(&root_pool, "Protocols");
proto_pool = rp_new(&root_pool, &main_birdloop, "Protocols");
proto_shutdown_timer = tm_new(proto_pool);
proto_shutdown_timer->hook = proto_shutdown_loop;
}

View File

@ -174,7 +174,7 @@ typedef struct rtable_private {
struct event *announce_event; /* Event to announce pending exports */
struct event *ec_event; /* Event to prune finished exports */
struct event *hcu_event; /* Event to update host cache */
struct event *delete_event; /* Event to delete the table */
void (*delete)(void *); /* Delete callback (in parent loop context) */
btime last_rt_change; /* Last time when route changed */
btime base_settle_time; /* Start time of rtable settling interval */
btime gc_time; /* Time of last GC */
@ -212,7 +212,7 @@ typedef union {
struct rtable_config {
node n;
char *name;
struct config *config;
void *owner; /* Main config if global table, channel_aux_table if channel table */
rtable *table;
struct proto_config *krt_attached; /* Kernel syncer attached to this table */
uint addr_type; /* Type of address data stored in table (NET_*) */

View File

@ -117,7 +117,7 @@ static void
rte_src_init(void)
{
src_domain = DOMAIN_NEW(attrs, "Route sources");
src_pool = rp_new(&root_pool, "Route sources");
src_pool = rp_new(&root_pool, &main_birdloop, "Route sources");
rte_src_slab = sl_new(src_pool, sizeof(struct rte_src));
idm_init(&src_ids, src_pool, SRC_ID_INIT_SIZE);
@ -1534,7 +1534,7 @@ rta_init(void)
{
attrs_domain = DOMAIN_NEW(attrs, "Attributes");
rta_pool = rp_new(&root_pool, "Attributes");
rta_pool = rp_new(&root_pool, &main_birdloop, "Attributes");
rta_slab_[0] = sl_new(rta_pool, sizeof(rta));
rta_slab_[1] = sl_new(rta_pool, sizeof(rta) + sizeof(u32));

View File

@ -1695,7 +1695,7 @@ rt_export_stopped(void *data)
RT_LOCKED(hook->table, tab)
{
/* Free the hook together with its coroutine. */
rfree(hook->pool);
rp_free(hook->pool, tab->rp);
rt_unlock_table(tab);
DBG("Export hook %p in table %s finished uc=%u\n", hook, tab->name, tab->use_count);
@ -1777,7 +1777,7 @@ rt_request_export(rtable *t, struct rt_export_request *req)
rtable_private *tab = RT_PRIV(t);
rt_lock_table(tab);
pool *p = rp_new(tab->rp, "Export hook");
pool *p = rp_new(tab->rp, tab->loop, "Export hook");
struct rt_export_hook *hook = req->hook = mb_allocz(p, sizeof(struct rt_export_hook));
hook->pool = p;
@ -1935,7 +1935,7 @@ rt_dump(rtable *tab)
{
RT_LOCK(tab);
rtable_private *t = RT_PRIV(tab);
debug("Dump of routing table <%s>%s\n", t->name, t->delete_event ? " (deleted)" : "");
debug("Dump of routing table <%s>%s\n", t->name, t->delete ? " (deleted)" : "");
#ifdef DEBUGGING
fib_check(&t->fib);
#endif
@ -1969,7 +1969,7 @@ rt_dump_hooks(rtable *t)
{
RT_LOCK(t);
rtable_private *tab = RT_PRIV(t);
debug("Dump of hooks in routing table <%s>%s\n", tab->name, tab->delete_event ? " (deleted)" : "");
debug("Dump of hooks in routing table <%s>%s\n", tab->name, tab->delete ? " (deleted)" : "");
debug(" nhu_state=%u hcu_scheduled=%u use_count=%d rt_count=%u\n",
atomic_load(&tab->nhu_state), ev_active(tab->hcu_event), tab->use_count, tab->rt_count);
debug(" last_rt_change=%t gc_time=%t gc_counter=%d prune_state=%u\n",
@ -2142,6 +2142,9 @@ rt_free(resource *_r)
ASSERT_DIE(EMPTY_LIST(r->imports));
ASSERT_DIE(EMPTY_LIST(r->exports));
if (r->hostcache)
rt_free_hostcache(r);
/* Freed automagically by the resource pool
fib_free(&r->fib);
hmap_free(&r->id_map);
@ -2175,10 +2178,14 @@ rt_setup(pool *pp, struct rtable_config *cf)
void *nb = mb_alloc(pp, ns);
ASSERT_DIE(ns - 1 == bsnprintf(nb, ns, "Routing table %s", cf->name));
pool *p = rp_new(pp, nb);
struct birdloop *l = birdloop_new(pp, DOMAIN_ORDER(rtable), nb);
pool *p = birdloop_pool(l);
birdloop_enter(l);
rtable_private *t = ralloc(p, &rt_class);
t->rp = p;
t->loop = l;
t->rte_slab = sl_new(p, sizeof(struct rte_storage));
@ -2197,8 +2204,6 @@ rt_setup(pool *pp, struct rtable_config *cf)
init_list(&t->pending_exports);
init_list(&t->subscribers);
t->loop = birdloop_new(p, DOMAIN_ORDER(rtable), nb);
t->announce_event = ev_new_init(p, rt_announce_exports, t);
t->ec_event = ev_new_init(p, rt_export_cleanup, t);
t->prune_event = ev_new_init(p, rt_prune_table, t);
@ -2216,6 +2221,8 @@ rt_setup(pool *pp, struct rtable_config *cf)
t->nhu_lp = lp_new_default(p);
mb_move(nb, p);
birdloop_leave(l);
return (rtable *) t;
}
@ -2229,7 +2236,7 @@ void
rt_init(void)
{
rta_init();
rt_table_pool = rp_new(&root_pool, "Routing tables");
rt_table_pool = rp_new(&root_pool, &main_birdloop, "Routing tables");
init_list(&routing_tables);
ev_init_cork(&rt_cork, "Route Table Cork");
}
@ -2819,7 +2826,7 @@ rt_new_table(struct symbol *s, uint addr_type)
c->min_rr_settle_time = 30 S;
c->max_rr_settle_time = 90 S;
c->cork_limit = 4 * page_size / sizeof(struct rt_pending_export);
c->config = new_config;
c->owner = new_config;
add_tail(&new_config->tables, &c->n);
@ -2844,18 +2851,6 @@ rt_lock_table(rtable_private *r)
r->use_count++;
}
static void
rt_loop_stopped(void *data)
{
rtable_private *r = data;
birdloop_free(r->loop);
r->loop = NULL;
r->prune_event->list = r->ec_event->list = NULL;
r->nhu_event->list = r->hcu_event->list = NULL;
r->announce_event->list = NULL;
ev_send(r->delete_event->list, r->delete_event);
}
/**
* rt_unlock_table - unlock a routing table
* @r: routing table to be unlocked
@ -2867,10 +2862,9 @@ rt_loop_stopped(void *data)
void
rt_unlock_table(rtable_private *r)
{
if (!--r->use_count && r->delete_event &&
if (!--r->use_count && r->delete &&
!r->prune_state && !atomic_load_explicit(&r->nhu_state, memory_order_acquire))
/* Delete the routing table by freeing its pool */
birdloop_stop_self(r->loop, rt_loop_stopped, r);
birdloop_stop_self(r->loop, r->delete, r);
}
static struct rtable_config *
@ -2883,22 +2877,16 @@ rt_find_table_config(struct config *cf, char *name)
static void
rt_done(void *data)
{
rtable_private *t = data;
ASSERT_DIE(t->loop == NULL);
RT_LOCKED((rtable *) data, t)
{
struct rtable_config *tc = t->config;
struct config *c = tc->owner;
struct rtable_config *tc = t->config;
struct config *c = tc->config;
tc->table = NULL;
rem_node(&t->n);
tc->table = NULL;
rem_node(&t->n);
if (t->hostcache)
rt_free_hostcache(t);
rfree(t->delete_event);
rfree(t->rp);
config_del_obstacle(c);
config_del_obstacle(c);
}
}
/**
@ -2925,7 +2913,7 @@ rt_commit(struct config *new, struct config *old)
{
RT_LOCK(o->table);
rtable_private *ot = RT_PRIV(o->table);
if (!ot->delete_event)
if (!ot->delete)
{
r = rt_find_table_config(new, o->name);
if (r && (r->addr_type == o->addr_type) && !new->shutdown)
@ -2941,8 +2929,7 @@ rt_commit(struct config *new, struct config *old)
{
DBG("\t%s: deleted\n", o->name);
rt_lock_table(ot);
ot->delete_event = ev_new_init(&root_pool, rt_done, ot);
ot->delete_event->list = &global_event_list;
ot->delete = rt_done;
config_add_obstacle(old);
rt_unlock_table(ot);
}

View File

@ -1747,7 +1747,7 @@ babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_con
TRACE(D_EVENTS, "Adding interface %s", new->name);
pool *pool = rp_new(p->p.pool, new->name);
pool *pool = rp_new(p->p.pool, p->p.loop, new->name);
ifa = mb_allocz(pool, sizeof(struct babel_iface));
ifa->proto = p;

View File

@ -452,8 +452,8 @@ bfd_add_session(struct bfd_proto *p, ip_addr addr, ip_addr local, struct iface *
s->passive = s->cf.passive;
s->tx_csn = random_u32();
s->tx_timer = tm_new_init(p->tpool, bfd_tx_timer_hook, s, 0, 0);
s->hold_timer = tm_new_init(p->tpool, bfd_hold_timer_hook, s, 0, 0);
s->tx_timer = tm_new_init(p->p.pool, bfd_tx_timer_hook, s, 0, 0);
s->hold_timer = tm_new_init(p->p.pool, bfd_hold_timer_hook, s, 0, 0);
bfd_session_update_tx_interval(s);
bfd_session_control_tx_timer(s, 1);
@ -581,7 +581,7 @@ bfd_get_iface(struct bfd_proto *p, ip_addr local, struct iface *iface)
struct bfd_config *cf = (struct bfd_config *) (p->p.cf);
struct bfd_iface_config *ic = bfd_find_iface_config(cf, iface);
ifa = mb_allocz(p->tpool, sizeof(struct bfd_iface));
ifa = mb_allocz(p->p.pool, sizeof(struct bfd_iface));
ifa->local = local;
ifa->iface = iface;
ifa->cf = ic;
@ -1062,8 +1062,6 @@ bfd_start(struct proto *P)
pthread_spin_init(&p->lock, PTHREAD_PROCESS_PRIVATE);
p->tpool = rp_new(P->pool, "BFD loop pool");
p->session_slab = sl_new(P->pool, sizeof(struct bfd_session));
HASH_INIT(p->session_hash_id, P->pool, 8);
HASH_INIT(p->session_hash_ip, P->pool, 8);

View File

@ -90,8 +90,6 @@ struct bfd_proto
pthread_spinlock_t lock;
pool *tpool;
node bfd_node;
slab *session_slab;

View File

@ -561,10 +561,11 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path)
static struct mrt_table_dump_state *
mrt_table_dump_init(pool *pp)
{
pool *pool = rp_new(pp, "MRT Table Dump");
pool *pool = rp_new(pp, &main_birdloop, "MRT Table Dump");
struct mrt_table_dump_state *s = mb_allocz(pool, sizeof(struct mrt_table_dump_state));
s->pool = pool;
s->parent = pp;
s->linpool = lp_new(pool, 4080);
s->peer_lp = lp_new(pool, 4080);
mrt_buffer_init(&s->buf, pool, 2 * MRT_ATTR_BUFFER_SIZE);
@ -601,7 +602,7 @@ mrt_table_dump_free(struct mrt_table_dump_state *s)
config_del_obstacle(s->config);
rfree(s->pool);
rp_free(s->pool, s->parent);
}

View File

@ -67,6 +67,7 @@ struct mrt_table_dump_state {
/* Allocated by mrt_table_dump_init() */
pool *pool; /* Pool for table dump */
pool *parent; /* Parent pool for cleanup */
linpool *linpool; /* Temporary linear pool */
linpool *peer_lp; /* Linear pool for peer entries in peer_hash */
buffer buf; /* Buffer for MRT messages */

View File

@ -311,7 +311,7 @@ ospf_iface_remove(struct ospf_iface *ifa)
ospf_iface_sm(ifa, ISM_DOWN);
rem_node(NODE ifa);
rfree(ifa->pool);
rp_free(ifa->pool, p->p.pool);
}
void
@ -567,7 +567,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
OSPF_TRACE(D_EVENTS, "Adding interface %s (%N) to area %R",
iface->name, &addr->prefix, oa->areaid);
pool = rp_new(p->p.pool, "OSPF Interface");
pool = rp_new(p->p.pool, p->p.loop, "OSPF Interface");
ifa = mb_allocz(pool, sizeof(struct ospf_iface));
ifa->iface = iface;
ifa->addr = addr;
@ -687,7 +687,7 @@ ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
/* Vlink ifname is stored just after the ospf_iface structure */
pool = rp_new(p->p.pool, "OSPF Vlink");
pool = rp_new(p->p.pool, p->p.loop, "OSPF Vlink");
ifa = mb_allocz(pool, sizeof(struct ospf_iface) + 16);
ifa->oa = p->backbone;
ifa->cf = ip;

View File

@ -80,7 +80,7 @@ struct ospf_neighbor *
ospf_neighbor_new(struct ospf_iface *ifa)
{
struct ospf_proto *p = ifa->oa->po;
struct pool *pool = rp_new(p->p.pool, "OSPF Neighbor");
struct pool *pool = rp_new(p->p.pool, p->p.loop, "OSPF Neighbor");
struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
n->pool = pool;
@ -120,7 +120,7 @@ ospf_neigh_down(struct ospf_neighbor *n)
s_get(&(n->dbsi));
release_lsrtl(p, n);
rem_node(NODE n);
rfree(n->pool);
rp_free(n->pool, p->p.pool);
OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", rid, ifa->ifname);
}

View File

@ -284,7 +284,7 @@ radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_conf
RADV_TRACE(D_EVENTS, "Adding interface %s", iface->name);
pool *pool = rp_new(p->p.pool, iface->name);
pool *pool = rp_new(p->p.pool, p->p.loop, iface->name);
ifa = mb_allocz(pool, sizeof(struct radv_iface));
ifa->pool = pool;
ifa->ra = p;
@ -317,7 +317,7 @@ radv_iface_remove(struct radv_iface *ifa)
rem_node(NODE ifa);
rfree(ifa->pool);
rp_free(ifa->pool, p->p.pool);
}
static void

View File

@ -596,7 +596,7 @@ rpki_check_expire_interval(uint seconds)
static struct rpki_cache *
rpki_init_cache(struct rpki_proto *p, struct rpki_config *cf)
{
pool *pool = rp_new(p->p.pool, cf->hostname);
pool *pool = rp_new(p->p.pool, p->p.loop, cf->hostname);
struct rpki_cache *cache = mb_allocz(pool, sizeof(struct rpki_cache));

View File

@ -48,6 +48,12 @@ birdloop_time_loop(struct birdloop *loop)
return &loop->time;
}
pool *
birdloop_pool(struct birdloop *loop)
{
return loop->pool;
}
_Bool
birdloop_inside(struct birdloop *loop)
{
@ -333,31 +339,59 @@ birdloop_init(void)
times_update();
timers_init(&main_birdloop.time, &root_pool);
root_pool.loop = &main_birdloop;
birdloop_enter_locked(&main_birdloop);
}
static void birdloop_main(void *arg);
void
birdloop_free(resource *r)
{
struct birdloop *loop = (void *) r;
ASSERT_DIE(loop->links == 0);
domain_free(loop->time.domain);
}
void
birdloop_dump(resource *r)
{
struct birdloop *loop = (void *) r;
debug("%s\n", loop->pool->name);
}
struct resclass birdloop_class = {
.name = "IO Loop",
.size = sizeof(struct birdloop),
.free = birdloop_free,
.dump = birdloop_dump,
};
struct birdloop *
birdloop_new(pool *pp, uint order, const char *name)
{
struct domain_generic *dg = domain_new(name, order);
pool *p = rp_new(pp, name);
struct birdloop *loop = mb_allocz(p, sizeof(struct birdloop));
loop->pool = p;
struct birdloop *loop = ralloc(pp, &birdloop_class);
loop->time.domain = dg;
loop->time.loop = loop;
birdloop_enter(loop);
loop->pool = rp_new(pp, loop, name);
loop->parent = pp;
rmove(&loop->r, loop->pool);
wakeup_init(loop);
ev_init_list(&loop->event_list, loop, name);
timers_init(&loop->time, p);
timers_init(&loop->time, loop->pool);
sockets_init(loop);
loop->time.coro = coro_run(p, birdloop_main, loop);
loop->time.coro = coro_run(loop->pool, birdloop_main, loop);
birdloop_leave(loop);
@ -389,14 +423,6 @@ birdloop_stop_self(struct birdloop *loop, void (*stopped)(void *data), void *dat
birdloop_do_stop(loop, stopped, data);
}
void
birdloop_free(struct birdloop *loop)
{
ASSERT_DIE(loop->links == 0);
domain_free(loop->time.domain);
rfree(loop->pool);
}
static void
birdloop_enter_locked(struct birdloop *loop)
{
@ -529,7 +555,25 @@ birdloop_main(void *arg)
ASSERT_DIE(loop->sock_num == 0);
birdloop_leave(loop);
/* Lock parent loop */
pool *parent = loop->parent;
birdloop_enter(parent->loop);
/* Move the loop temporarily to parent pool */
birdloop_enter(loop);
rmove(&loop->r, parent);
birdloop_leave(loop);
/* Announce loop stop */
loop->stopped(loop->stop_data);
/* Free the pool and loop */
birdloop_enter(loop);
rp_free(loop->pool, parent);
birdloop_leave(loop);
rfree(&loop->r);
/* And finally leave the parent loop before finishing */
birdloop_leave(parent->loop);
}

View File

@ -9,7 +9,10 @@
struct birdloop
{
resource r;
pool *pool;
pool *parent;
struct timeloop time;
event_list event_list;

View File

@ -74,7 +74,7 @@ static list krt_proto_list;
void
krt_io_init(void)
{
krt_pool = rp_new(&root_pool, "Kernel Syncer");
krt_pool = rp_new(&root_pool, &main_birdloop, "Kernel Syncer");
krt_filter_lp = lp_new_default(krt_pool);
init_list(&krt_proto_list);
krt_sys_io_init();

View File

@ -52,7 +52,7 @@ async_dump(void)
{
debug("INTERNAL STATE DUMP\n\n");
rdump(&root_pool);
rp_dump(&root_pool);
sk_dump_all();
// XXXX tm_dump_all();
if_dump_all();

View File

@ -65,8 +65,8 @@ bt_bird_init(void)
the_bird_lock();
resource_init();
olock_init();
birdloop_init();
olock_init();
io_init();
rt_init();
if_init();