diff options
author | Maria Matejka <mq@ucw.cz> | 2021-11-30 18:16:49 +0100 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2021-11-30 21:38:25 +0100 |
commit | 385b3ea3956aefc2868cdd838fc0a90f1d8a7857 (patch) | |
tree | d954b853724153e4a2411d57be5f29e5b9236251 /nest | |
parent | ab0994a10c26bd76b4154a675267d96d19dfb509 (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.c | 12 | ||||
-rw-r--r-- | nest/a-set_test.c | 13 | ||||
-rw-r--r-- | nest/cli.c | 8 | ||||
-rw-r--r-- | nest/cmds.c | 8 | ||||
-rw-r--r-- | nest/config.Y | 2 | ||||
-rw-r--r-- | nest/iface.c | 2 | ||||
-rw-r--r-- | nest/proto.c | 41 | ||||
-rw-r--r-- | nest/route.h | 4 | ||||
-rw-r--r-- | nest/rt-attr.c | 4 | ||||
-rw-r--r-- | nest/rt-table.c | 69 |
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"); @@ -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); } |