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:
parent
368e0ef15b
commit
370958afc2
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
72
nest/notify.c
Normal 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);
|
||||
}
|
@ -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
|
||||
|
45
nest/proto.c
45
nest/proto.c
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user