0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-18 06:51:54 +00:00

ROA reloader: fixed channel state changes

This commit is contained in:
Maria Matejka 2019-03-12 17:17:34 +01:00
parent 9d27e7c98b
commit be721bc65f
6 changed files with 73 additions and 43 deletions

View File

@ -53,8 +53,45 @@
void (*bt_assert_hook)(int result, struct f_inst *assert); void (*bt_assert_hook)(int result, struct f_inst *assert);
struct filter_roa_reloader { struct filter_notifier {
node n; node n;
void (*unsubscribe)(struct filter_notifier *);
};
void filter_slot_init(struct filter_slot *fs, pool *pp, struct filter *filter)
{
fs->filter = filter;
fs->p = rp_new(pp, "filter slot pool");
init_list(&(fs->notifiers));
}
void filter_slot_flush(struct filter_slot *fs)
{
filter_slot_stop(fs);
fs->filter = NULL;
rfree(fs->p);
}
void filter_slot_start(struct filter_slot *fs, void (*reloader)(struct filter_slot *))
{
ASSERT(EMPTY_LIST(fs->notifiers));
fs->reloader = reloader;
}
void filter_slot_stop(struct filter_slot *fs)
{
fs->reloader = NULL;
struct filter_notifier *n;
node *x;
WALK_LIST_DELSAFE(n, x, fs->notifiers)
n->unsubscribe(n);
ASSERT(EMPTY_LIST(fs->notifiers));
}
struct filter_roa_reloader {
struct filter_notifier n;
LISTENER(rt_notify_data) *L; LISTENER(rt_notify_data) *L;
struct rtable *roa_table; struct rtable *roa_table;
struct filter_slot *slot; struct filter_slot *slot;
@ -62,16 +99,19 @@ struct filter_roa_reloader {
static void filter_roa_reloader_notify(void *self, const rt_notify_data *data UNUSED) { static void filter_roa_reloader_notify(void *self, const rt_notify_data *data UNUSED) {
struct filter_roa_reloader *frr = self; struct filter_roa_reloader *frr = self;
debug("notify %p\n", frr);
frr->slot->reloader(frr->slot); frr->slot->reloader(frr->slot);
} }
static void filter_roa_reloader_unsubscribe(void *self) { static void filter_roa_reloader_unsubscribe(struct filter_notifier *n) {
struct filter_roa_reloader *frr = self; struct filter_roa_reloader *frr = (void *) n;
rem_node(&(frr->n)); UNSUBSCRIBE(rt_notify_data, frr->L);
mb_free(self); rem_node(&(n->n));
mb_free(n);
} }
static void filter_roa_reloader_subscribe(struct rtable *roa_table, struct filter_slot *slot, const net_addr *n UNUSED, u32 as UNUSED) { static void filter_roa_reloader_subscribe(struct rtable *roa_table, struct filter_slot *slot, const net_addr *n UNUSED, u32 as UNUSED) {
debug("subscribe t%p s%p\n", roa_table, slot);
struct filter_roa_reloader *oldfrr; struct filter_roa_reloader *oldfrr;
node *x; node *x;
WALK_LIST2(oldfrr, x, slot->notifiers, n) WALK_LIST2(oldfrr, x, slot->notifiers, n)
@ -79,10 +119,12 @@ static void filter_roa_reloader_subscribe(struct rtable *roa_table, struct filte
return; /* Old notifier found for the same event. */ return; /* Old notifier found for the same event. */
struct filter_roa_reloader *frr = mb_allocz(slot->p, sizeof(struct filter_roa_reloader)); struct filter_roa_reloader *frr = mb_allocz(slot->p, sizeof(struct filter_roa_reloader));
debug("subscribe new %p\n", frr);
frr->roa_table = roa_table; frr->roa_table = roa_table;
frr->slot = slot; frr->slot = slot;
add_tail(&(slot->notifiers), &(frr->n)); add_tail(&(slot->notifiers), &(frr->n.n));
frr->L = SUBSCRIBE(rt_notify_data, slot->p, roa_table->listeners, frr, filter_roa_reloader_notify, filter_roa_reloader_unsubscribe); frr->n.unsubscribe = filter_roa_reloader_unsubscribe;
frr->L = SUBSCRIBE(rt_notify_data, slot->p, roa_table->listeners, frr, filter_roa_reloader_notify);
} }
static struct adata undef_adata; /* adata of length 0 used for undefined */ static struct adata undef_adata; /* adata of length 0 used for undefined */
@ -1802,7 +1844,7 @@ f_run(struct filter_slot *filter_slot, struct rte **rte, struct linpool *tmp_poo
return F_REJECT; return F_REJECT;
int rte_cow = ((*rte)->flags & REF_COW); int rte_cow = ((*rte)->flags & REF_COW);
DBG( "Running filter `%s'...", filter->name ); DBG( "Running filter `%s'...", filter_slot->filter->name );
f_rte = rte; f_rte = rte;
f_eattrs = NULL; f_eattrs = NULL;

View File

@ -156,20 +156,10 @@ struct filter_slot {
list notifiers; list notifiers;
}; };
static inline void filter_slot_init(struct filter_slot *fs, pool *pp, struct filter *filter, void (*reloader)(struct filter_slot *)) void filter_slot_init(struct filter_slot *fs, pool *pp, struct filter *filter);
{ void filter_slot_flush(struct filter_slot *fs);
fs->filter = filter; void filter_slot_start(struct filter_slot *fs, void (*reloader)(struct filter_slot *));
fs->reloader = reloader; void filter_slot_stop(struct filter_slot *fs);
fs->p = rp_new(pp, "filter slot pool");
init_list(&(fs->notifiers));
}
static inline void filter_slot_deactivate(struct filter_slot *fs)
{
rfree(fs->p);
ASSERT(EMPTY_LIST(fs->notifiers));
fs->p = NULL;
}
struct f_inst *f_new_inst(enum f_instruction_code fi_code); struct f_inst *f_new_inst(enum f_instruction_code fi_code);
struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da); struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da);

View File

@ -38,6 +38,8 @@
list.tail_node.prev = &(list.head_node); \ list.tail_node.prev = &(list.head_node); \
} while (0) } while (0)
#define EMPTY_TLIST(t, list) (!((list).head->next))
#define TNODE_VALID(t, n) ((n)->next) #define TNODE_VALID(t, n) ((n)->next)
#define WALK_TLIST(t, n, list) for (TNODE(t) *n = list.head; TNODE_VALID(t, n); n = n->next) #define WALK_TLIST(t, n, list) for (TNODE(t) *n = list.head; TNODE_VALID(t, n); n = n->next)
#define WALK_TLIST_DELSAFE(t, n, list) \ #define WALK_TLIST_DELSAFE(t, n, list) \

View File

@ -19,7 +19,6 @@ LISTENER(stype) { \
resource r; \ resource r; \
TNODE(listener__##stype) n; \ TNODE(listener__##stype) n; \
void *self; \ void *self; \
void (*unsubscribe)(void *self); \
void (*notify)(void *self, const stype *data); \ void (*notify)(void *self, const stype *data); \
}; \ }; \
extern struct resclass LISTENER_CLASS(stype) extern struct resclass LISTENER_CLASS(stype)
@ -27,23 +26,23 @@ extern struct resclass LISTENER_CLASS(stype)
#define LISTENERS(stype) TLIST(listener__##stype) #define LISTENERS(stype) TLIST(listener__##stype)
#define LISTENER_CLASS(stype) listener_class__##stype #define LISTENER_CLASS(stype) listener_class__##stype
#define LISTENER_CLASS_DEF(stype) static void listener_unsubscribe__##stype(resource *r) { \ #define LISTENER_CLASS_DEF(stype) static void listener_unnotify__##stype(resource *r) { \
debug("in: listener_unnotify__" #stype " %p\n", r); \
LISTENER(stype) *L = (LISTENER(stype) *) r; \ LISTENER(stype) *L = (LISTENER(stype) *) r; \
TREM_NODE(listener__##stype, L->n); \ TREM_NODE(listener__##stype, L->n); \
CALL(L->unsubscribe, L->self); \ debug("out: listener_unnotify__" #stype " %p\n", r); \
} \ } \
struct resclass LISTENER_CLASS(stype) = { \ struct resclass LISTENER_CLASS(stype) = { \
.name = "Listener " #stype, \ .name = "Listener " #stype, \
.size = sizeof(LISTENER(stype)), \ .size = sizeof(LISTENER(stype)), \
.free = listener_unsubscribe__##stype, \ .free = listener_unnotify__##stype, \
} }
#define INIT_LISTENERS(stype, sender) INIT_TLIST(listener__##stype, sender) #define INIT_LISTENERS(stype, sender) INIT_TLIST(listener__##stype, sender)
#define SUBSCRIBE(stype, pool, sender, _self, _notify, _unsubscribe) ({ \ #define SUBSCRIBE(stype, pool, sender, _self, _notify) ({ \
LISTENER(stype) *L = ralloc(pool, &listener_class__##stype); \ LISTENER(stype) *L = ralloc(pool, &listener_class__##stype); \
L->notify = _notify; \ L->notify = _notify; \
L->unsubscribe = _unsubscribe; \
L->self = _self; \ L->self = _self; \
L->n.self = L; \ L->n.self = L; \
TADD_TAIL(listener__##stype, sender, L->n); \ TADD_TAIL(listener__##stype, sender, L->n); \
@ -52,15 +51,9 @@ struct resclass LISTENER_CLASS(stype) = { \
#define UNSUBSCRIBE(stype, listener) do { \ #define UNSUBSCRIBE(stype, listener) do { \
LISTENER(stype) *L = listener; \ LISTENER(stype) *L = listener; \
L->unsubscribe = NULL; \
rfree(L); \ rfree(L); \
} while (0) } while (0)
#define UNNOTIFY(stype, sender) do { \
WALK_TLIST_DELSAFE(listener__##stype, L, sender) \
rfree(L->self); \
} while (0)
#define NOTIFY(stype, sender, data) do { \ #define NOTIFY(stype, sender, data) do { \
const stype *_d = data; \ const stype *_d = data; \
WALK_TLIST_DELSAFE(listener__##stype, L, sender) \ WALK_TLIST_DELSAFE(listener__##stype, L, sender) \

View File

@ -160,8 +160,8 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
c->proto = p; c->proto = p;
c->table = cf->table->table; c->table = cf->table->table;
filter_slot_init(&(c->in_filter), p->pool, cf->in_filter, channel_filter_slot_reimport); filter_slot_init(&(c->in_filter), p->pool, cf->in_filter);
filter_slot_init(&(c->out_filter), p->pool, cf->out_filter, channel_filter_slot_reexport); filter_slot_init(&(c->out_filter), p->pool, cf->out_filter);
c->rx_limit = cf->rx_limit; c->rx_limit = cf->rx_limit;
c->in_limit = cf->in_limit; c->in_limit = cf->in_limit;
@ -411,8 +411,8 @@ channel_set_state(struct channel *c, uint state)
/* No filter notifier shall remain after transitioning from CS_UP state. */ /* No filter notifier shall remain after transitioning from CS_UP state. */
if (cs == CS_UP) if (cs == CS_UP)
{ {
filter_slot_deactivate(&(c->in_filter)); filter_slot_stop(&(c->in_filter));
filter_slot_deactivate(&(c->out_filter)); filter_slot_stop(&(c->out_filter));
} }
switch (state) switch (state)
@ -440,6 +440,9 @@ channel_set_state(struct channel *c, uint state)
if (!c->gr_wait && c->proto->rt_notify) if (!c->gr_wait && c->proto->rt_notify)
channel_start_export(c); channel_start_export(c);
filter_slot_start(&(c->in_filter), channel_filter_slot_reimport);
filter_slot_start(&(c->out_filter), channel_filter_slot_reexport);
break; break;
case CS_FLUSHING: case CS_FLUSHING:
@ -621,14 +624,14 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
/* Reconfigure filter slots */ /* Reconfigure filter slots */
if (import_changed) { if (import_changed) {
filter_slot_deactivate(&(c->in_filter)); filter_slot_flush(&(c->in_filter));
filter_slot_init(&(c->in_filter), c->proto->pool, cf->in_filter, channel_filter_slot_reimport); filter_slot_init(&(c->in_filter), c->proto->pool, cf->in_filter);
} else } else
c->in_filter.filter = cf->in_filter; c->in_filter.filter = cf->in_filter;
if (export_changed) { if (export_changed) {
filter_slot_deactivate(&(c->out_filter)); filter_slot_flush(&(c->out_filter));
filter_slot_init(&(c->out_filter), c->proto->pool, cf->out_filter, channel_filter_slot_reexport); filter_slot_init(&(c->out_filter), c->proto->pool, cf->out_filter);
} else } else
c->out_filter.filter = cf->out_filter; c->out_filter.filter = cf->out_filter;

View File

@ -2174,7 +2174,7 @@ rt_unlock_table(rtable *r)
r->config->table = NULL; r->config->table = NULL;
if (r->hostcache) if (r->hostcache)
rt_free_hostcache(r); rt_free_hostcache(r);
UNNOTIFY(rt_notify_data, r->listeners); ASSERT(EMPTY_TLIST(rt_notify_data, r->listeners));
rem_node(&r->n); rem_node(&r->n);
fib_free(&r->fib); fib_free(&r->fib);
rfree(r->rt_event); rfree(r->rt_event);