Commit 370958af authored by Maria Matejka's avatar Maria Matejka
Browse files

Filter slots a bit more encapsulated.

parent 368e0ef1
Loading
Loading
Loading
Loading
+22 −43
Original line number Diff line number Diff line
@@ -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))
  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);
    }
+15 −0
Original line number Diff line number Diff line
@@ -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 −1
Original line number Diff line number Diff line
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)

nest/notify.c

0 → 100644
+72 −0
Original line number Diff line number Diff line
/*
 *	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);
}
+6 −72
Original line number Diff line number Diff line
@@ -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
Loading