mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +00:00 
			
		
		
		
	ROA reloader: fixed channel state changes
This commit is contained in:
		@@ -53,8 +53,45 @@
 | 
			
		||||
 | 
			
		||||
void (*bt_assert_hook)(int result, struct f_inst *assert);
 | 
			
		||||
 | 
			
		||||
struct filter_roa_reloader {
 | 
			
		||||
struct filter_notifier {
 | 
			
		||||
  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;
 | 
			
		||||
  struct rtable *roa_table;
 | 
			
		||||
  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) {
 | 
			
		||||
  struct filter_roa_reloader *frr = self;
 | 
			
		||||
  debug("notify %p\n", frr);
 | 
			
		||||
  frr->slot->reloader(frr->slot);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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_reloader_unsubscribe(struct filter_notifier *n) {
 | 
			
		||||
  struct filter_roa_reloader *frr = (void *) n;
 | 
			
		||||
  UNSUBSCRIBE(rt_notify_data, frr->L);
 | 
			
		||||
  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) {
 | 
			
		||||
  debug("subscribe t%p s%p\n", roa_table, slot);
 | 
			
		||||
  struct filter_roa_reloader *oldfrr;
 | 
			
		||||
  node *x;
 | 
			
		||||
  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. */
 | 
			
		||||
 | 
			
		||||
  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->slot = slot;
 | 
			
		||||
  add_tail(&(slot->notifiers), &(frr->n));
 | 
			
		||||
  frr->L = SUBSCRIBE(rt_notify_data, slot->p, roa_table->listeners, frr, filter_roa_reloader_notify, filter_roa_reloader_unsubscribe);
 | 
			
		||||
  add_tail(&(slot->notifiers), &(frr->n.n));
 | 
			
		||||
  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 */
 | 
			
		||||
@@ -1802,7 +1844,7 @@ f_run(struct filter_slot *filter_slot, struct rte **rte, struct linpool *tmp_poo
 | 
			
		||||
    return F_REJECT;
 | 
			
		||||
 | 
			
		||||
  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_eattrs = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -156,20 +156,10 @@ 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;
 | 
			
		||||
}
 | 
			
		||||
void filter_slot_init(struct filter_slot *fs, pool *pp, struct filter *filter);
 | 
			
		||||
void filter_slot_flush(struct filter_slot *fs);
 | 
			
		||||
void filter_slot_start(struct filter_slot *fs, void (*reloader)(struct filter_slot *));
 | 
			
		||||
void filter_slot_stop(struct filter_slot *fs);
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,8 @@
 | 
			
		||||
  list.tail_node.prev = &(list.head_node); \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#define EMPTY_TLIST(t, list) (!((list).head->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_DELSAFE(t, n, list) \
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@ LISTENER(stype) { \
 | 
			
		||||
  resource r; \
 | 
			
		||||
  TNODE(listener__##stype) n; \
 | 
			
		||||
  void *self; \
 | 
			
		||||
  void (*unsubscribe)(void *self); \
 | 
			
		||||
  void (*notify)(void *self, const stype *data); \
 | 
			
		||||
}; \
 | 
			
		||||
extern struct resclass LISTENER_CLASS(stype) 
 | 
			
		||||
@@ -27,23 +26,23 @@ extern struct resclass LISTENER_CLASS(stype)
 | 
			
		||||
#define LISTENERS(stype) TLIST(listener__##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; \
 | 
			
		||||
  TREM_NODE(listener__##stype, L->n); \
 | 
			
		||||
  CALL(L->unsubscribe, L->self); \
 | 
			
		||||
  debug("out: listener_unnotify__" #stype " %p\n", r); \
 | 
			
		||||
} \
 | 
			
		||||
struct resclass LISTENER_CLASS(stype) = { \
 | 
			
		||||
  .name = "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 SUBSCRIBE(stype, pool, sender, _self, _notify, _unsubscribe) ({ \
 | 
			
		||||
#define SUBSCRIBE(stype, pool, sender, _self, _notify) ({ \
 | 
			
		||||
    LISTENER(stype) *L = ralloc(pool, &listener_class__##stype); \
 | 
			
		||||
    L->notify = _notify; \
 | 
			
		||||
    L->unsubscribe = _unsubscribe; \
 | 
			
		||||
    L->self = _self; \
 | 
			
		||||
    L->n.self = L; \
 | 
			
		||||
    TADD_TAIL(listener__##stype, sender, L->n); \
 | 
			
		||||
@@ -52,15 +51,9 @@ struct resclass LISTENER_CLASS(stype) = { \
 | 
			
		||||
 | 
			
		||||
#define UNSUBSCRIBE(stype, listener) do { \
 | 
			
		||||
  LISTENER(stype) *L = listener; \
 | 
			
		||||
  L->unsubscribe = NULL; \
 | 
			
		||||
  rfree(L); \
 | 
			
		||||
} 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 { \
 | 
			
		||||
  const stype *_d = data; \
 | 
			
		||||
  WALK_TLIST_DELSAFE(listener__##stype, L, sender) \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								nest/proto.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								nest/proto.c
									
									
									
									
									
								
							@@ -160,8 +160,8 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
 | 
			
		||||
  c->proto = p;
 | 
			
		||||
  c->table = cf->table->table;
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
  filter_slot_init(&(c->in_filter),  p->pool, cf->in_filter);
 | 
			
		||||
  filter_slot_init(&(c->out_filter), p->pool, cf->out_filter);
 | 
			
		||||
 | 
			
		||||
  c->rx_limit = cf->rx_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. */
 | 
			
		||||
  if (cs == CS_UP)
 | 
			
		||||
  {
 | 
			
		||||
    filter_slot_deactivate(&(c->in_filter));
 | 
			
		||||
    filter_slot_deactivate(&(c->out_filter));
 | 
			
		||||
    filter_slot_stop(&(c->in_filter));
 | 
			
		||||
    filter_slot_stop(&(c->out_filter));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (state)
 | 
			
		||||
@@ -440,6 +440,9 @@ channel_set_state(struct channel *c, uint state)
 | 
			
		||||
    if (!c->gr_wait && c->proto->rt_notify)
 | 
			
		||||
      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;
 | 
			
		||||
 | 
			
		||||
  case CS_FLUSHING:
 | 
			
		||||
@@ -621,14 +624,14 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
 | 
			
		||||
 | 
			
		||||
  /* 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);
 | 
			
		||||
    filter_slot_flush(&(c->in_filter));
 | 
			
		||||
    filter_slot_init(&(c->in_filter),  c->proto->pool, cf->in_filter);
 | 
			
		||||
  } else
 | 
			
		||||
    c->in_filter.filter = cf->in_filter;
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
    filter_slot_flush(&(c->out_filter));
 | 
			
		||||
    filter_slot_init(&(c->out_filter), c->proto->pool, cf->out_filter);
 | 
			
		||||
  } else
 | 
			
		||||
    c->out_filter.filter = cf->out_filter;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2174,7 +2174,7 @@ rt_unlock_table(rtable *r)
 | 
			
		||||
      r->config->table = NULL;
 | 
			
		||||
      if (r->hostcache)
 | 
			
		||||
	rt_free_hostcache(r);
 | 
			
		||||
      UNNOTIFY(rt_notify_data, r->listeners);
 | 
			
		||||
      ASSERT(EMPTY_TLIST(rt_notify_data, r->listeners));
 | 
			
		||||
      rem_node(&r->n);
 | 
			
		||||
      fib_free(&r->fib);
 | 
			
		||||
      rfree(r->rt_event);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user