0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-11 03:21:53 +00:00

Filter slots a bit more encapsulated.

This commit is contained in:
Maria Matejka 2019-03-07 17:17:34 +01:00
parent 368e0ef15b
commit 370958afc2
6 changed files with 131 additions and 144 deletions

View File

@ -53,57 +53,36 @@
void (*bt_assert_hook)(int result, struct f_inst *assert);
struct filter_roa_notifier {
resource r;
struct listener L;
struct filter_roa_reloader {
node n;
struct listener *L;
struct rtable *roa_table;
struct filter_slot *slot;
};
static void filter_roa_notifier_hook(struct listener *L, void *data UNUSED) {
struct filter_roa_notifier *frn = SKIP_BACK(struct filter_roa_notifier, L, L);
frn->slot->reloader(frn->slot);
static void filter_roa_reloader_notify(void *self, const void *data UNUSED) {
struct filter_roa_reloader *frr = self;
frr->slot->reloader(frr->slot);
}
static void filter_roa_notifier_unsubscribe(struct listener *L) {
struct filter_roa_notifier *frn = SKIP_BACK(struct filter_roa_notifier, L, L);
rfree(frn);
static void filter_roa_reloader_unsubscribe(void *self) {
struct filter_roa_reloader *frr = self;
rem_node(&(frr->n));
mb_free(self);
}
static void filter_roa_notifier_free(resource *r) {
struct filter_roa_notifier *frn = (void *) r;
unsubscribe(&(frn->L));
}
static struct resclass filter_roa_notifier_class = {
.name = "Filter ROA Notifier",
.size = sizeof(struct filter_roa_notifier),
.free = filter_roa_notifier_free,
.dump = NULL,
.lookup = NULL,
.memsize = NULL,
};
static void filter_roa_notifier_subscribe(struct rtable *roa_table, struct filter_slot *slot, const net_addr *n UNUSED, u32 as UNUSED) {
struct listener *oldL;
static void filter_roa_reloader_subscribe(struct rtable *roa_table, struct filter_slot *slot, const net_addr *n UNUSED, u32 as UNUSED) {
struct filter_roa_reloader *oldfrr;
node *x;
WALK_LIST2(oldL, x, slot->notifiers, receiver_node)
if (oldL->hook == filter_roa_notifier_hook)
{
struct filter_roa_notifier *old = SKIP_BACK(struct filter_roa_notifier, L, oldL);
if ((old->roa_table == roa_table) && (old->slot == slot))
return; /* Old notifier found for the same event. */
}
WALK_LIST2(oldfrr, x, slot->notifiers, n)
if (oldfrr->roa_table == roa_table)
return; /* Old notifier found for the same event. */
struct filter_roa_notifier *frn = ralloc(slot->p, &filter_roa_notifier_class);
frn->L = (struct listener) {
.hook = filter_roa_notifier_hook,
.unsub = filter_roa_notifier_unsubscribe,
};
frn->roa_table = roa_table;
frn->slot = slot;
subscribe(&(frn->L), &(roa_table->listeners), &(slot->notifiers));
struct filter_roa_reloader *frr = mb_allocz(slot->p, sizeof(struct filter_roa_reloader));
frr->roa_table = roa_table;
frr->slot = slot;
add_tail(&(slot->notifiers), &(frr->n));
frr->L = subscribe(slot->p, &(roa_table->listeners), filter_roa_reloader_notify, filter_roa_reloader_unsubscribe, frr);
}
static struct adata undef_adata; /* adata of length 0 used for undefined */
@ -1612,7 +1591,7 @@ interpret(struct f_inst *what)
else
{
if (f_slot)
filter_roa_notifier_subscribe(table, f_slot, v1.val.net, as);
filter_roa_reloader_subscribe(table, f_slot, v1.val.net, as);
res.val.i = net_roa_check(table, v1.val.net, as);
}

View File

@ -156,6 +156,21 @@ struct filter_slot {
list notifiers;
};
static inline void filter_slot_init(struct filter_slot *fs, pool *pp, struct filter *filter, void (*reloader)(struct filter_slot *))
{
fs->filter = filter;
fs->reloader = reloader;
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_da(enum f_instruction_code fi_code, struct f_dynamic_attr da);
struct f_inst *f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa);

View File

@ -1,4 +1,4 @@
src := a-path.c a-set.c cli.c cmds.c iface.c locks.c neighbor.c password.c proto.c rt-attr.c rt-dev.c rt-fib.c rt-show.c rt-table.c
src := a-path.c a-set.c cli.c cmds.c iface.c locks.c neighbor.c notify.c password.c proto.c rt-attr.c rt-dev.c rt-fib.c rt-show.c rt-table.c
obj := $(src-o-files)
$(all-daemon)
$(cf-local)

72
nest/notify.c Normal file
View File

@ -0,0 +1,72 @@
/*
* BIRD Internet Routing Daemon -- Notificators and Listeners
*
* (c) 2019 Maria Matejka <mq@jmq.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include "nest/bird.h"
#include "lib/resource.h"
#include "nest/notify.h"
struct listener {
resource r;
node n;
void (*notify)(void *self, const void *data);
void (*unsubscribe)(void *self);
void *self;
};
static void
listener_unsubscribe(resource *r)
{
struct listener *L = (struct listener *) r;
rem_node(&(L->n));
CALL(L->unsubscribe, L->self);
}
static struct resclass listener_class = {
.name = "Listener",
.size = sizeof(struct listener),
.free = listener_unsubscribe,
.dump = NULL,
.lookup = NULL,
.memsize = NULL,
};
struct listener *
subscribe(pool *p, list *sender, void (*notify)(void *, const void *), void (*unsubscribe)(void *), void *self)
{
struct listener *L = ralloc(p, &listener_class);
L->notify = notify;
L->unsubscribe = unsubscribe;
L->self = self;
add_tail(sender, &(L->n));
return L;
}
void unsubscribe(struct listener *L)
{
L->unsubscribe = NULL;
rfree(L);
}
void unsubscribe_all(list *sender)
{
struct listener *L;
node *x, *y;
WALK_LIST2_DELSAFE(L, x, y, *sender, n)
rfree(L);
}
void notify(list *sender, const void *data)
{
struct listener *L;
node *x, *y;
WALK_LIST2_DELSAFE(L, x, y, *sender, n)
L->notify(L->self, data);
}

View File

@ -9,80 +9,14 @@
#ifndef _BIRD_NOTIFY_H_
#define _BIRD_NOTIFY_H_
#include "lib/resource.h"
#include "lib/lists.h"
struct listener {
node sender_node;
node receiver_node;
void (*hook)(struct listener *who, void *data);
void (*dump)(struct listener *who);
void (*unsub)(struct listener *who);
};
static inline void subscribe(struct listener *who, list *sender, list *receiver)
{
ASSERT(!NODE_VALID(&(who->sender_node)));
ASSERT(!NODE_VALID(&(who->receiver_node)));
add_tail(sender, &(who->sender_node));
add_tail(receiver, &(who->receiver_node));
}
static inline void unsubscribe(struct listener *who)
{
/* Allow multiple unsubscribe */
if (!NODE_VALID(&(who->sender_node))
&& !NODE_VALID(&(who->receiver_node)))
return;
ASSERT(NODE_VALID(&(who->sender_node))
&& NODE_VALID(&(who->receiver_node)));
rem_node(&(who->sender_node));
rem_node(&(who->receiver_node));
who->sender_node = who->receiver_node = (node) {};
CALL(who->unsub, who);
}
static inline void unsubscribe_all(list *receiver)
{
struct listener *n;
node *x, *y;
WALK_LIST2_DELSAFE(n, x, y, *receiver, receiver_node)
unsubscribe(n);
}
static inline void notify(list *sender, void *data)
{
struct listener *n;
node *x, *y;
WALK_LIST2_DELSAFE(n, x, y, *sender, sender_node)
n->hook(n, data);
}
static inline void listeners_dump(list *sender, list *receiver)
{
ASSERT((!sender) || (!receiver));
ASSERT(sender || receiver);
struct listener *n;
node *x;
if (sender)
WALK_LIST2(n, x, *sender, sender_node) {
debug("\t\tNotifier: hook %p", n->hook);
CALL(n->dump, n);
debug("\n");
}
if (receiver)
WALK_LIST2(n, x, *receiver, receiver_node) {
debug("\t\tNotifier: hook %p", n->hook);
CALL(n->dump, n);
debug("\n");
}
}
struct listener;
struct listener *subscribe(pool *p, list *sender, void (*notify)(void *self, const void *data), void (*unsubscribe)(void *self), void *self);
void unsubscribe(struct listener *L);
void unsubscribe_all(list *sender);
void notify(list *sender, const void *data);
#endif

View File

@ -160,15 +160,8 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
c->proto = p;
c->table = cf->table->table;
c->in_filter.filter = cf->in_filter;
c->in_filter.reloader = channel_filter_slot_reimport;
c->in_filter.p = p->pool;
init_list(&c->in_filter.notifiers);
c->out_filter.filter = cf->out_filter;
c->out_filter.reloader = channel_filter_slot_reexport;
c->out_filter.p = p->pool;
init_list(&c->out_filter.notifiers);
filter_slot_init(&(c->in_filter), p->pool, cf->in_filter, channel_filter_slot_reimport);
filter_slot_init(&(c->out_filter), p->pool, cf->out_filter, channel_filter_slot_reexport);
c->rx_limit = cf->rx_limit;
c->in_limit = cf->in_limit;
@ -418,8 +411,8 @@ channel_set_state(struct channel *c, uint state)
/* No filter notifier shall remain after transitioning from CS_UP state. */
if (cs == CS_UP)
{
unsubscribe_all(&(c->in_filter.notifiers));
unsubscribe_all(&(c->out_filter.notifiers));
filter_slot_deactivate(&(c->in_filter));
filter_slot_deactivate(&(c->out_filter));
}
switch (state)
@ -626,16 +619,20 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
if (c->merge_limit != cf->merge_limit)
export_changed = 1;
/* Reconfigure channel fields */
c->in_filter.filter = cf->in_filter;
c->out_filter.filter = cf->out_filter;
/* Reconfigure filter slots */
if (import_changed) {
filter_slot_deactivate(&(c->in_filter));
filter_slot_init(&(c->in_filter), c->proto->pool, cf->in_filter, channel_filter_slot_reimport);
} else
c->in_filter.filter = cf->in_filter;
if (import_changed)
unsubscribe_all(&(c->in_filter.notifiers));
if (export_changed)
unsubscribe_all(&(c->out_filter.notifiers));
if (export_changed) {
filter_slot_deactivate(&(c->out_filter));
filter_slot_init(&(c->out_filter), c->proto->pool, cf->out_filter, channel_filter_slot_reexport);
} else
c->out_filter.filter = cf->out_filter;
/* Reconfigure other channel fields */
c->rx_limit = cf->rx_limit;
c->in_limit = cf->in_limit;
c->out_limit = cf->out_limit;
@ -1335,18 +1332,8 @@ protos_dump_all(void)
debug("\tTABLE %s\n", c->table->name);
if (c->in_filter.filter)
debug("\tInput filter: %s\n", filter_name(c->in_filter.filter));
if (!EMPTY_LIST(c->in_filter.notifiers))
{
debug("\tInput filter notifiers:\n");
listeners_dump(NULL, &(c->in_filter.notifiers));
}
if (c->out_filter.filter)
debug("\tOutput filter: %s\n", filter_name(c->out_filter.filter));
if (!EMPTY_LIST(c->out_filter.notifiers))
{
debug("\tOutput filter notifiers:\n");
listeners_dump(NULL, &(c->out_filter.notifiers));
}
}
if (p->proto->dump && (p->proto_state != PS_DOWN))