]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter slots a bit more encapsulated.
authorMaria Matejka <mq@ucw.cz>
Thu, 7 Mar 2019 16:17:34 +0000 (17:17 +0100)
committerMaria Matejka <mq@ucw.cz>
Thu, 7 Mar 2019 16:35:39 +0000 (17:35 +0100)
filter/filter.c
filter/filter.h
nest/Makefile
nest/notify.c [new file with mode: 0644]
nest/notify.h
nest/proto.c

index ec7e8997e70db536949db6905c9d4b49ddd142b1..4eaf640504a0068c304681323ca4d6aa51feb1b5 100644 (file)
 
 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. */
-    }
-
-  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));
+  WALK_LIST2(oldfrr, x, slot->notifiers, n)
+    if (oldfrr->roa_table == roa_table)
+      return; /* Old notifier found for the same event. */
+
+  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);
     }
index 2f0fa735cb96490d94ae0577b815b313863dd544..a99f38cff076bc1beeb29f110416e5f52c8bd32c 100644 (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);
index 884d39506a37136e65042c4249c42f89d028c656..dae45b029e9cec9b01056d42427709f37c316c5e 100644 (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)
diff --git a/nest/notify.c b/nest/notify.c
new file mode 100644 (file)
index 0000000..fac1ac8
--- /dev/null
@@ -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);
+}
index 9ae736d0e7a24ff116f692f36ce072ac7ededfd0..22b67cc5b172cc8eba84fac688e51e0afdf4e271 100644 (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
index 123f3eed861f70b2fffde2f707ac65f9ef24b5a0..2f03f5152749c99ae8d0c9a16f8bedac6241eabd 100644 (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;
-
-  if (import_changed)
-    unsubscribe_all(&(c->in_filter.notifiers));
+  /* 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 (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))