]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
ROA reloader: fixed channel state changes
authorMaria Matejka <mq@ucw.cz>
Tue, 12 Mar 2019 16:17:34 +0000 (17:17 +0100)
committerMaria Matejka <mq@ucw.cz>
Tue, 12 Mar 2019 16:17:34 +0000 (17:17 +0100)
filter/filter.c
filter/filter.h
lib/tlists.h
nest/notify.h
nest/proto.c
nest/rt-table.c

index 43cb58871efec0726cba37870ee3bc474aa5a18f..2f84b019a2bd8a957706dab8626dc6738fb28bdd 100644 (file)
 
 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;
index a99f38cff076bc1beeb29f110416e5f52c8bd32c..47f0e77ffb2ccab60b7058e6f4c4758b7d7c6bab 100644 (file)
@@ -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);
index e066928d041575953419fcfd5bf91d27cf2f07d6..96039032d40eba311639f58b429af3f04ad63e2a 100644 (file)
@@ -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) \
index 4e006594b45e09ecd991c737735d135cd861636b..b19313d4ee2a2fd4d114eb59df2d8de5b97f8dfd 100644 (file)
@@ -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) \
index 2f03f5152749c99ae8d0c9a16f8bedac6241eabd..77053370a8af323d4093a59ad3019b6d672c41b3 100644 (file)
@@ -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;
 
index 39ae6e63add4087c9dc3c41d61788c26928fc120..c3e1a2543010b5d86c17e643751bb10e425761a6 100644 (file)
@@ -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);