]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
ROA change notifications: simple variant
authorMaria Matejka <mq@ucw.cz>
Tue, 5 Mar 2019 23:11:40 +0000 (00:11 +0100)
committerMaria Matejka <mq@ucw.cz>
Wed, 6 Mar 2019 11:51:38 +0000 (12:51 +0100)
This implementation will just automatically request channel reload/refeed
when ROA change is detected. It may be sufficient for many uses;
performance impact for big IXPs is unclear.

12 files changed:
filter/filter.c
filter/filter.h
nest/notify.h [new file with mode: 0644]
nest/proto.c
nest/protocol.h
nest/route.h
nest/rt-show.c
nest/rt-table.c
proto/mrt/mrt.c
proto/pipe/pipe.c
proto/radv/radv.c
sysdep/unix/krt.c

index 37cf16a3857edd63eb8e8410e4881ef973de9762..ec7e8997e70db536949db6905c9d4b49ddd142b1 100644 (file)
@@ -45,6 +45,7 @@
 #include "nest/protocol.h"
 #include "nest/iface.h"
 #include "nest/attrs.h"
+#include "nest/notify.h"
 #include "conf/conf.h"
 #include "filter/filter.h"
 
 
 void (*bt_assert_hook)(int result, struct f_inst *assert);
 
+struct filter_roa_notifier {
+  resource r;
+  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_notifier_unsubscribe(struct listener *L) {
+  struct filter_roa_notifier *frn = SKIP_BACK(struct filter_roa_notifier, L, L);
+  rfree(frn);
+}
+
+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;
+  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));
+}
+
 static struct adata undef_adata;       /* adata of length 0 used for undefined */
 
 /* Special undef value for paths and clists */
@@ -542,6 +596,7 @@ static struct ea_list **f_eattrs;
 static struct linpool *f_pool;
 static struct buffer f_buf;
 static int f_flags;
+static struct filter_slot *f_slot;
 
 static inline void f_cache_eattrs(void)
 {
@@ -1555,7 +1610,12 @@ interpret(struct f_inst *what)
     if (table->addr_type != (v1.val.net->type == NET_IP4 ? NET_ROA4 : NET_ROA6))
       res.val.i = ROA_UNKNOWN; /* Prefix and table type mismatch */
     else
+    {
+      if (f_slot)
+       filter_roa_notifier_subscribe(table, f_slot, v1.val.net, as);
+
       res.val.i = net_roa_check(table, v1.val.net, as);
+    }
 
     break;
 
@@ -1754,12 +1814,12 @@ i_same(struct f_inst *f1, struct f_inst *f2)
  * modified in place, old cached rta is possibly freed.
  */
 int
-f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags)
+f_run(struct filter_slot *filter_slot, struct rte **rte, struct linpool *tmp_pool, int flags)
 {
-  if (filter == FILTER_ACCEPT)
+  if (filter_slot->filter == FILTER_ACCEPT)
     return F_ACCEPT;
 
-  if (filter == FILTER_REJECT)
+  if (filter_slot->filter == FILTER_REJECT)
     return F_REJECT;
 
   int rte_cow = ((*rte)->flags & REF_COW);
@@ -1770,10 +1830,11 @@ f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int fla
   f_old_rta = NULL;
   f_pool = tmp_pool;
   f_flags = flags;
+  f_slot = filter_slot;
 
   LOG_BUFFER_INIT(f_buf);
 
-  struct f_val res = interpret(filter->root);
+  struct f_val res = interpret(filter_slot->filter->root);
 
   if (f_old_rta) {
     /*
@@ -1797,7 +1858,7 @@ f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int fla
 
   if (res.type != T_RETURN) {
     if (!(f_flags & FF_SILENT))
-      log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
+      log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter_slot->filter->name);
     return F_ERROR;
   }
   DBG( "done (%u)\n", res.val.i );
@@ -1815,6 +1876,7 @@ f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
   f_old_rta = NULL;
   f_pool = tmp_pool;
   f_flags = 0;
+  f_slot = NULL;
 
   LOG_BUFFER_INIT(f_buf);
 
@@ -1831,6 +1893,7 @@ f_eval(struct f_inst *expr, struct linpool *tmp_pool)
   f_eattrs = NULL;
   f_rte = NULL;
   f_pool = tmp_pool;
+  f_slot = NULL;
 
   LOG_BUFFER_INIT(f_buf);
 
index a8c33287875ac6557c7eb4ae05f1c89861dfcfde..2f0fa735cb96490d94ae0577b815b313863dd544 100644 (file)
@@ -149,6 +149,13 @@ struct filter {
   struct f_inst *root;
 };
 
+struct filter_slot {
+  struct filter *filter;
+  void (*reloader)(struct filter_slot *);
+  pool *p;
+  list notifiers;
+};
+
 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);
@@ -175,7 +182,7 @@ void trie_format(struct f_trie *t, buffer *buf);
 struct ea_list;
 struct rte;
 
-int f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
+int f_run(struct filter_slot *filter_slot, struct rte **rte, struct linpool *tmp_pool, int flags);
 struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool);
 struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
 uint f_eval_int(struct f_inst *expr);
@@ -286,6 +293,7 @@ struct f_trie
 #define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
 
 #define FF_SILENT 2                    /* Silent filter execution */
+#define FF_TEMP 4                      /* Result of this filter is dropped */
 
 /* Custom route attributes */
 struct custom_attribute {
diff --git a/nest/notify.h b/nest/notify.h
new file mode 100644 (file)
index 0000000..9ae736d
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *     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.
+ */
+
+#ifndef _BIRD_NOTIFY_H_
+#define _BIRD_NOTIFY_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");
+    }
+}
+
+
+#endif
index d4a333d077adb9a5814720fe3eab6b870ce8e784..123f3eed861f70b2fffde2f707ac65f9ef24b5a0 100644 (file)
@@ -125,6 +125,16 @@ proto_find_channel_by_name(struct proto *p, const char *n)
   return NULL;
 }
 
+static void channel_filter_slot_reimport(struct filter_slot *fs)
+{
+  return channel_request_reload(SKIP_BACK(struct channel, in_filter, fs));
+}
+
+static void channel_filter_slot_reexport(struct filter_slot *fs)
+{
+  return channel_request_feeding(SKIP_BACK(struct channel, out_filter, fs));
+}
+
 /**
  * proto_add_channel - connect protocol to a routing table
  * @p: protocol instance
@@ -150,8 +160,16 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
   c->proto = p;
   c->table = cf->table->table;
 
-  c->in_filter = cf->in_filter;
-  c->out_filter = cf->out_filter;
+  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);
+
   c->rx_limit = cf->rx_limit;
   c->in_limit = cf->in_limit;
   c->out_limit = cf->out_limit;
@@ -397,6 +415,13 @@ channel_set_state(struct channel *c, uint state)
   c->channel_state = state;
   c->last_state_change = current_time();
 
+  /* 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));
+  }
+
   switch (state)
   {
   case CS_START:
@@ -492,7 +517,7 @@ channel_reloadable(struct channel *c)
   return c->proto->reload_routes && c->reloadable;
 }
 
-static void
+void
 channel_request_reload(struct channel *c)
 {
   ASSERT(c->channel_state == CS_UP);
@@ -592,8 +617,8 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
     return 0;
 
   /* Note that filter_same() requires arguments in (new, old) order */
-  int import_changed = !filter_same(cf->in_filter, c->in_filter);
-  int export_changed = !filter_same(cf->out_filter, c->out_filter);
+  int import_changed = !filter_same(cf->in_filter, c->in_filter.filter);
+  int export_changed = !filter_same(cf->out_filter, c->out_filter.filter);
 
   if (c->preference != cf->preference)
     import_changed = 1;
@@ -602,8 +627,15 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
     export_changed = 1;
 
   /* Reconfigure channel fields */
-  c->in_filter = cf->in_filter;
-  c->out_filter = cf->out_filter;
+  c->in_filter.filter = cf->in_filter;
+  c->out_filter.filter = cf->out_filter;
+
+  if (import_changed)
+    unsubscribe_all(&(c->in_filter.notifiers));
+
+  if (export_changed)
+    unsubscribe_all(&(c->out_filter.notifiers));
+
   c->rx_limit = cf->rx_limit;
   c->in_limit = cf->in_limit;
   c->out_limit = cf->out_limit;
@@ -1301,10 +1333,20 @@ protos_dump_all(void)
     WALK_LIST(c, p->channels)
     {
       debug("\tTABLE %s\n", c->table->name);
-      if (c->in_filter)
-       debug("\tInput filter: %s\n", filter_name(c->in_filter));
-      if (c->out_filter)
-       debug("\tOutput filter: %s\n", filter_name(c->out_filter));
+      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))
@@ -1731,8 +1773,8 @@ channel_show_info(struct channel *c)
   cli_msg(-1006, "    State:          %s", c_states[c->channel_state]);
   cli_msg(-1006, "    Table:          %s", c->table->name);
   cli_msg(-1006, "    Preference:     %d", c->preference);
-  cli_msg(-1006, "    Input filter:   %s", filter_name(c->in_filter));
-  cli_msg(-1006, "    Output filter:  %s", filter_name(c->out_filter));
+  cli_msg(-1006, "    Input filter:   %s", filter_name(c->in_filter.filter));
+  cli_msg(-1006, "    Output filter:  %s", filter_name(c->out_filter.filter));
 
   if (graceful_restart_state == GRS_ACTIVE)
     cli_msg(-1006, "    GR recovery:   %s%s",
index 6c04071b55b739fb6d1d35a05d87d4dd4dd28a4b..23dae3db3f3faaac3db62accd801a822ea622daf 100644 (file)
@@ -12,6 +12,8 @@
 #include "lib/lists.h"
 #include "lib/resource.h"
 #include "lib/event.h"
+#include "filter/filter.h"
+#include "nest/notify.h"
 #include "nest/route.h"
 #include "conf/conf.h"
 
@@ -511,8 +513,8 @@ struct channel {
   struct proto *proto;
 
   struct rtable *table;
-  struct filter *in_filter;            /* Input filter */
-  struct filter *out_filter;           /* Output filter */
+  struct filter_slot in_filter;                /* Input filter */
+  struct filter_slot out_filter;       /* Output filter */
   struct channel_limit rx_limit;       /* Receive limit (for in_keep_filtered) */
   struct channel_limit in_limit;       /* Input limit */
   struct channel_limit out_limit;      /* Output limit */
@@ -620,6 +622,7 @@ static inline void channel_open(struct channel *c) { channel_set_state(c, CS_UP)
 static inline void channel_close(struct channel *c) { channel_set_state(c, CS_FLUSHING); }
 
 void channel_request_feeding(struct channel *c);
+void channel_request_reload(struct channel *c);
 void *channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto);
 void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto);
 int channel_reconfigure(struct channel *c, struct channel_config *cf);
index 8dfbb3762713a1c54751c20ebfcff12bc6af1b5e..00747b6c5c5840ef524ca379f5041228fef1ac7c 100644 (file)
@@ -19,6 +19,7 @@ struct proto;
 struct rte_src;
 struct symbol;
 struct filter;
+struct filter_slot;
 struct cli;
 
 /*
@@ -148,6 +149,7 @@ typedef struct rtable {
   struct fib fib;
   char *name;                          /* Name of this table */
   list channels;                       /* List of attached channels (struct channel) */
+  list listeners;                      /* List of attached listeners (struct listener) */
   uint addr_type;                      /* Type of address data stored in table (NET_*) */
   int pipe_busy;                       /* Pipe loop detection */
   int use_count;                       /* Number of protocols using this table */
@@ -297,7 +299,7 @@ rte *rte_find(net *net, struct rte_src *src);
 rte *rte_get_temp(struct rta *);
 void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
 /* rte_update() moved to protocol.h to avoid dependency conflicts */
-int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
+int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter_slot *filter_slot);
 rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
 void rt_refresh_begin(rtable *t, struct channel *c);
 void rt_refresh_end(rtable *t, struct channel *c);
@@ -318,6 +320,10 @@ void rt_reload_channel_abort(struct channel *c);
 void rt_prune_sync(rtable *t, int all);
 struct rtable_config *rt_new_table(struct symbol *s, uint addr_type);
 
+struct rt_notify {
+  struct network *net;
+  rte *new, *old, *new_best, *old_best, *before_old;
+};
 
 /* Default limit for ECMP next hops, defined in sysdep code */
 extern const int rt_default_ecmp;
index c7bcdf2f6c98546cfd8705817389920513ff81ac..0e6b15f64d9a85bb9ca5dad98e8cab01ae123219 100644 (file)
@@ -149,7 +149,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
               * command may change the export filter and do not update routes.
               */
              int do_export = (ic > 0) ||
-               (f_run(ec->out_filter, &e, c->show_pool, FF_SILENT) <= F_ACCEPT);
+               (f_run(&(ec->out_filter), &e, c->show_pool, FF_SILENT | FF_TEMP) <= F_ACCEPT);
+
 
              if (do_export != (d->export_mode == RSEM_EXPORT))
                goto skip;
@@ -162,7 +163,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
       if (d->show_protocol && (d->show_protocol != e->attrs->src->proto))
        goto skip;
 
-      if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT)
+      struct filter_slot fs = { .filter = d->filter };
+      if (f_run(&fs, &e, c->show_pool, FF_TEMP) > F_ACCEPT)
        goto skip;
 
       if (d->stats < 2)
index 6bf07a091359a70fb208d5b91499646749ac8f7d..0646ece3259a1835600c198fdddcac0bb00889fb 100644 (file)
@@ -397,7 +397,7 @@ static rte *
 export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int silent)
 {
   struct proto *p = c->proto;
-  struct filter *filter = c->out_filter;
+  struct filter *filter = c->out_filter.filter;
   struct proto_stats *stats = &c->stats;
   rte *rt;
   int v;
@@ -426,7 +426,7 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
   rte_make_tmp_attrs(&rt, pool);
 
   v = filter && ((filter == FILTER_REJECT) ||
-                (f_run(filter, &rt, pool,
+                (f_run(&(c->out_filter), &rt, pool,
                        (silent ? FF_SILENT : 0)) > F_ACCEPT));
   if (v)
     {
@@ -941,6 +941,17 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old,
        else
          rt_notify_basic(c, net, new, old, 0);
     }
+
+  struct rt_notify rtn = {
+    .net = net,
+    .new = new,
+    .old = old,
+    .new_best = new_best,
+    .old_best = old_best,
+    .before_old = before_old,
+  };
+
+  notify(&(tab->listeners), &rtn);
 }
 
 static inline int
@@ -1364,7 +1375,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
 {
   struct proto *p = c->proto;
   struct proto_stats *stats = &c->stats;
-  struct filter *filter = c->in_filter;
+  struct filter *filter = c->in_filter.filter;
   rte *dummy = NULL;
   net *nn;
 
@@ -1409,7 +1420,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
          if (filter && (filter != FILTER_REJECT))
            {
              ea_list *oldea = new->attrs->eattrs;
-             int fr = f_run(filter, &new, rte_update_pool, 0);
+             int fr = f_run(&(c->in_filter), &new, rte_update_pool, 0);
              if (fr > F_ACCEPT)
                {
                  stats->imp_updates_filtered++;
@@ -1503,9 +1514,9 @@ rte_modify(rte *old)
   rte_update_unlock();
 }
 
-/* Check rtable for best route to given net whether it would be exported do p */
+/* One time check rtable for best route to given net whether it would be exported do p */
 int
-rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
+rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter_slot *filter_slot)
 {
   net *n = net_find(t, a);
   rte *rt = n ? n->routes : NULL;
@@ -1520,7 +1531,7 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
   if (v == RIC_PROCESS)
   {
     rte_make_tmp_attrs(&rt, rte_update_pool);
-    v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
+    v = (f_run(filter_slot, &rt, rte_update_pool, FF_SILENT | FF_TEMP) <= F_ACCEPT);
   }
 
   /* Discard temporary rte */
@@ -1727,6 +1738,7 @@ rt_setup(pool *p, rtable *t, struct rtable_config *cf)
   t->addr_type = cf->addr_type;
   fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL);
   init_list(&t->channels);
+  init_list(&t->listeners);
 
   t->rt_event = ev_new_init(p, rt_event, t);
   t->gc_time = current_time();
index 95014958a60069b6650f739256a6f994d9883201..5769a44bff62e1f7f7e54904237a05110afa4ece 100644 (file)
@@ -498,7 +498,8 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path)
 
     rte_make_tmp_attrs(&rt, s->linpool);
 
-    if (f_run(s->filter, &rt, s->linpool, 0) <= F_ACCEPT)
+    struct filter_slot fs = { .filter = s->filter };
+    if (f_run(&(fs), &rt, s->linpool, FF_TEMP) <= F_ACCEPT)
       mrt_rib_table_entry(s, rt);
 
     if (rt != rt0)
index efb992cab7315924e59f0016116f39e99085d417..c1f6a59a023b85bfbecc904cbd722b8d9151e977 100644 (file)
@@ -266,8 +266,8 @@ pipe_show_proto_info(struct proto *P)
   cli_msg(-1006, "    Peer table:     %s", p->sec->table->name);
   cli_msg(-1006, "    Import state:   %s", pipe_feed_state[p->sec->export_state]);
   cli_msg(-1006, "    Export state:   %s", pipe_feed_state[p->pri->export_state]);
-  cli_msg(-1006, "    Import filter:  %s", filter_name(p->sec->out_filter));
-  cli_msg(-1006, "    Export filter:  %s", filter_name(p->pri->out_filter));
+  cli_msg(-1006, "    Import filter:  %s", filter_name(p->sec->out_filter.filter));
+  cli_msg(-1006, "    Export filter:  %s", filter_name(p->pri->out_filter.filter));
 
   channel_show_limit(&p->pri->in_limit, "Import limit:");
   channel_show_limit(&p->sec->in_limit, "Export limit:");
index 990b602494540fbadb8f30632573c612e6494edb..d5b6c758fd43b76af064c9d8ef9033ece800971f 100644 (file)
@@ -560,7 +560,7 @@ radv_check_active(struct radv_proto *p)
     return 1;
 
   struct channel *c = p->p.main_channel;
-  return rt_examine(c->table, &cf->trigger, &p->p, c->out_filter);
+  return rt_examine(c->table, &cf->trigger, &p->p, &(c->out_filter));
 }
 
 static void
index ded5dfe4526c2d3193d9a5216e9eb61e27328a24..bf9274550d30b84eb140796bf8a2b441728d5ca5 100644 (file)
@@ -562,7 +562,7 @@ static struct rte *
 krt_export_net(struct krt_proto *p, net *net, rte **rt_free)
 {
   struct channel *c = p->p.main_channel;
-  struct filter *filter = c->out_filter;
+  struct filter *filter = c->out_filter.filter;
   rte *rt;
 
   if (c->ra_mode == RA_MERGED)
@@ -584,7 +584,7 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free)
   if (filter == FILTER_ACCEPT)
     goto accept;
 
-  if (f_run(filter, &rt, krt_filter_lp, FF_SILENT) > F_ACCEPT)
+  if (f_run(&(c->out_filter), &rt, krt_filter_lp, FF_SILENT | FF_TEMP) > F_ACCEPT)
     goto reject;