summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-11-30 18:16:49 +0100
committerMaria Matejka <mq@ucw.cz>2021-11-30 21:38:25 +0100
commit385b3ea3956aefc2868cdd838fc0a90f1d8a7857 (patch)
treed954b853724153e4a2411d57be5f29e5b9236251 /nest
parentab0994a10c26bd76b4154a675267d96d19dfb509 (diff)
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.
Diffstat (limited to 'nest')
-rw-r--r--nest/a-path_test.c12
-rw-r--r--nest/a-set_test.c13
-rw-r--r--nest/cli.c8
-rw-r--r--nest/cmds.c8
-rw-r--r--nest/config.Y2
-rw-r--r--nest/iface.c2
-rw-r--r--nest/proto.c41
-rw-r--r--nest/route.h4
-rw-r--r--nest/rt-attr.c4
-rw-r--r--nest/rt-table.c69
10 files changed, 73 insertions, 90 deletions
diff --git a/nest/a-path_test.c b/nest/a-path_test.c
index 2e6e4956..2e6683f2 100644
--- a/nest/a-path_test.c
+++ b/nest/a-path_test.c
@@ -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");
diff --git a/nest/a-set_test.c b/nest/a-set_test.c
index efd1b67d..f8f6e781 100644
--- a/nest/a-set_test.c
+++ b/nest/a-set_test.c
@@ -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");
diff --git a/nest/cli.c b/nest/cli.c
index b54a0d76..7e5d2151 100644
--- a/nest/cli.c
+++ b/nest/cli.c
@@ -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;
}
diff --git a/nest/cmds.c b/nest/cmds.c
index 18f39eb5..2f2ad94c 100644
--- a/nest/cmds.c
+++ b/nest/cmds.c
@@ -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, "");
}
diff --git a/nest/config.Y b/nest/config.Y
index 0914048b..f9ed0e69 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -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]])
diff --git a/nest/iface.c b/nest/iface.c
index 5cb9e814..dd4af243 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -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);
diff --git a/nest/proto.c b/nest/proto.c
index 2d30e640..a18d9332 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -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;
}
diff --git a/nest/route.h b/nest/route.h
index b5d44040..f060ad63 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -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_*) */
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 9a5498ed..357cd216 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -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));
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 8566fbf8..cd0d6291 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -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);
-
- struct rtable_config *tc = t->config;
- struct config *c = tc->config;
-
- tc->table = NULL;
- rem_node(&t->n);
-
- if (t->hostcache)
- rt_free_hostcache(t);
+ RT_LOCKED((rtable *) data, t)
+ {
+ struct rtable_config *tc = t->config;
+ struct config *c = tc->owner;
- rfree(t->delete_event);
- rfree(t->rp);
+ tc->table = NULL;
+ rem_node(&t->n);
- 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);
}