]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Route export: Common export function.
authorMaria Matejka <mq@ucw.cz>
Tue, 10 Mar 2020 15:13:41 +0000 (16:13 +0100)
committerMaria Matejka <mq@ucw.cz>
Thu, 30 Apr 2020 14:15:59 +0000 (16:15 +0200)
Also:
* Feeding request by net.
* Passing only net_addr in export structure.
* Cleanup of krt_replace_rte() call.

16 files changed:
nest/proto.c
nest/protocol.h
nest/route.h
nest/rt-table.c
proto/babel/babel.c
proto/bgp/attrs.c
proto/bgp/packets.c
proto/ospf/topology.c
proto/perf/perf.c
proto/pipe/pipe.c
proto/radv/radv.c
proto/rip/rip.c
sysdep/bsd/krt-sock.c
sysdep/linux/netlink.c
sysdep/unix/krt.c
sysdep/unix/krt.h

index 84d96273e8d9c2227c3d6d9522e45ccee8289977..1b6995d4cc40ccc4e8ca6d98e7e47cffe860df51 100644 (file)
@@ -168,6 +168,8 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
   c->last_tx_filter_change = current_time();
   c->reloadable = 1;
 
+  init_list(&c->net_feed);
+
   CALL(c->channel->init, c, cf);
 
   add_tail(&p->channels, &c->n);
@@ -279,6 +281,27 @@ channel_feed_loop(void *ptr)
     c->proto->feed_end(c);
 }
 
+static void
+channel_feed_net(void *data)
+{
+  struct channel_net_feed *nf = data;
+
+  rt_feed_channel_net(nf->c, nf->addr);
+  rem_node(&nf->n);
+  mb_free(nf);
+}
+
+static void
+channel_schedule_feed_net(struct channel *c, net_addr *n)
+{
+  struct channel_net_feed *nf = mb_alloc(c->proto->pool, sizeof(struct channel_net_feed) + n->length);
+  nf->n = (node) {};
+  nf->e = (event) { .hook = channel_feed_net, .data = nf };
+  nf->c = c;
+  net_copy(nf->addr, n);
+  add_tail(&c->net_feed, &nf->n);
+  ev_schedule(&nf->e);
+}
 
 static void
 channel_start_export(struct channel *c)
@@ -296,6 +319,16 @@ channel_stop_export(struct channel *c)
   if (c->export_state == ES_FEEDING)
     rt_feed_channel_abort(c);
 
+  /* Abort also all scheduled net feeds */
+  struct channel_net_feed *n;
+  node *nxt;
+  WALK_LIST_DELSAFE(n, nxt, c->net_feed)
+  {
+    ev_postpone(&n->e);
+    rem_node(&n->n);
+    mb_free(n);
+  }
+
   c->export_state = ES_DOWN;
   c->stats.exp_routes = 0;
   bmap_reset(&c->export_map, 1024);
@@ -515,7 +548,7 @@ channel_set_state(struct channel *c, uint state)
  * even when feeding is already running, in that case it is restarted.
  */
 void
-channel_request_feeding(struct channel *c)
+channel_request_feeding(struct channel *c, net_addr *n)
 {
   ASSERT(c->channel_state == CS_UP);
 
@@ -530,9 +563,17 @@ channel_request_feeding(struct channel *c)
     if (!c->feed_active)
        return;
 
+    /* Unless only single net is requested */
+    if (n)
+      return channel_schedule_feed_net(c, n);
+
     rt_feed_channel_abort(c);
   }
 
+  /* Single net refeed isn't counted */
+  if (n)
+    return channel_schedule_feed_net(c, n);
+
   /* Track number of exported routes during refeed */
   c->refeed_count = 0;
 
@@ -702,7 +743,7 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
     channel_request_reload(c);
 
   if (export_changed)
-    channel_request_feeding(c);
+    channel_request_feeding(c, NULL);
 
   return 1;
 }
@@ -1998,7 +2039,7 @@ proto_cmd_reload(struct proto *p, uintptr_t dir, int cnt UNUSED)
   if (dir != CMD_RELOAD_IN)
     WALK_LIST(c, p->channels)
       if (c->channel_state == CS_UP)
-       channel_request_feeding(c);
+       channel_request_feeding(c, NULL);
 
   cli_msg(-15, "%s: reloading", p->name);
 }
index 21339daa139efa9768292edcefc37956362130fb..8e94fcd57dded8acbcb928a23898ef8dbe9a7168 100644 (file)
@@ -536,9 +536,18 @@ struct channel {
   struct rte *reload_next_rte;         /* Route iterator in in_table used during reloading */
   u8 reload_active;                    /* Iterator reload_fit is linked */
 
+  list net_feed;                       /* Active net feeders (struct channel_net_feed) */
+
   struct rtable *out_table;            /* Internal table for exported routes */
 };
 
+struct channel_net_feed {
+  node n;
+  struct event e;
+  struct channel *c;
+  net_addr addr[0];
+};
+
 
 /*
  * Channel states
@@ -612,7 +621,7 @@ static inline void channel_init(struct channel *c) { channel_set_state(c, CS_STA
 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_feeding(struct channel *c, net_addr *n);
 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 3a44f4a1c874dd159583905008000be5b22d9599..bb6677e1f1a869d5fd34830a7de67f47d09050ea 100644 (file)
@@ -225,12 +225,13 @@ typedef struct rte {
 
 /* Route export structure. Protocols get this structure as an information about
  * new routes on the channel. */
+
 struct rte_export {
-  net *net;                            /* Network information */
-  struct rte_src *new_src;             /* New route src (NULL for withdraw) */
+  net_addr *net;                       /* Network information */
   rte *new;                            /* New route (NULL for withdraw) */
+  struct rte_src *new_src;             /* New route src (kept if route is rejected by preexport or filter) */
+  rte *old;                            /* Old route (only if export table is on) */
   struct rte_src *old_src;             /* Old route src */
-  rte *old;                            /* Old route */
 };
 
 #define REF_COW                1               /* Copy this rte on write */
@@ -320,7 +321,6 @@ static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) f
 void *net_route(rtable *tab, const net_addr *n);
 int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
 rte *rte_find(net *net, struct rte_src *src);
-int rt_examine(struct channel *c, net_addr *a);
 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);
@@ -335,6 +335,7 @@ rte *rte_cow_rta(rte *r, linpool *lp);
 void rt_dump(rtable *);
 void rt_dump_all(void);
 int rt_feed_channel(struct channel *c);
+void rt_feed_channel_net(struct channel *c, net_addr *n);
 void rt_feed_channel_abort(struct channel *c);
 int rt_reload_channel(struct channel *c);
 void rt_reload_channel_abort(struct channel *c);
index f666bd92ae8951f53493242b05f7fb9acb01bf32..5d23ba0acb4ac1d7b95d7e703816e8358e7d720a 100644 (file)
@@ -353,12 +353,13 @@ rte_free_quick(rte *e)
 
 struct rte_export_internal {
   struct rte_export pub;
-  rte *new_best;
-  rte *old_best;
+  rte *new, *old, *new_best, *old_best;
   rte *rt_free;
-  uint refeed:1;
+  _Bool refeed;
 };
 
+//_Thread_local static struct rte_export_internal rei;
+
 static int                             /* Actually better or at least as good as */
 rte_better(rte *new, rte *old)
 {
@@ -434,6 +435,7 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
   const struct filter *filter = c->out_filter;
   struct proto_stats *stats = &c->stats;
   rte *rt;
+  int v;
 
   rt = rt0;
   *rt_free = NULL;
@@ -442,28 +444,28 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
   if (silent && bmap_test(&c->export_reject_map, rt0->id))
     return NULL;
 
-  int pv = p->preexport ? p->preexport(p, &rt, pool) : 0;
-  if (pv < 0)
+  v = p->preexport ? p->preexport(p, &rt, pool) : 0;
+  if (v < 0)
     {
       if (silent)
        goto reject;
 
       stats->exp_updates_rejected++;
-      if (pv == RIC_REJECT)
+      if (v == RIC_REJECT)
        rte_trace_out(D_FILTERS, p, rt, "rejected by protocol");
       goto reject;
     }
-  if (pv > 0)
+  if (v > 0)
     {
       if (!silent)
        rte_trace_out(D_FILTERS, p, rt, "forced accept by protocol");
       goto accept;
     }
 
-  int fv = filter && ((filter == FILTER_REJECT) ||
+  v = filter && ((filter == FILTER_REJECT) ||
                 (f_run(filter, &rt, pool,
                        (silent ? FF_SILENT : 0)) > F_ACCEPT));
-  if (fv)
+  if (v)
     {
       if (silent)
        goto reject;
@@ -483,9 +485,8 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
   return rt;
 
  reject:
-  /* We have rejected the route by filter */
-  if (pv == 0)
-    bmap_set(&c->export_reject_map, rt0->id);
+  /* We have rejected the route */
+  bmap_set(&c->export_reject_map, rt0->id);
 
   /* Discard temporary rte */
   if (rt != rt0)
@@ -500,13 +501,12 @@ export_filter(struct channel *c, rte *rt0, rte **rt_free, int silent)
 }
 
 static void
-do_rt_notify(struct channel *c, struct rte_export_internal *e)
+do_rt_notify(struct channel *c, struct rte_export *ep, _Bool refeed)
 {
   struct proto *p = c->proto;
   struct proto_stats *stats = &c->stats;
-  struct rte_export *ep = &(e->pub);
 
-  if (e->refeed && ep->new)
+  if (refeed && ep->new)
     c->refeed_count++;
 
   /* Apply export limit */
@@ -528,7 +528,7 @@ do_rt_notify(struct channel *c, struct rte_export_internal *e)
   rte *old_exported = NULL;
   if (c->out_table)
   {
-    if (!rte_update_out(c, ep->net->n.addr, ep->old_src, ep->new, &(old_exported), e->refeed))
+    if (!rte_update_out(c, ep->net, ep->old_src, ep->new, &(old_exported), refeed))
       return;
   }
   else if (c->out_filter == FILTER_ACCEPT)
@@ -572,25 +572,28 @@ do_rt_notify(struct channel *c, struct rte_export_internal *e)
 USE_RESULT static _Bool
 rt_notify_basic(struct channel *c, struct rte_export_internal *e)
 {
-  if (e->pub.new)
+  if (e->new)
     c->stats.exp_updates_received++;
   else
     c->stats.exp_withdraws_received++;
 
-  if (e->pub.new)
-    e->pub.new = export_filter(c, e->pub.new, &e->rt_free, 0);
-
-  if (e->pub.old && !bmap_test(&c->export_map, e->pub.old->id))
-    e->pub.old = NULL;
+  if (e->new)
+  {
+    e->pub.new = export_filter(c, e->new, &e->rt_free, 0);
+    e->pub.new_src = e->new->attrs->src;
+  }
 
-  if (!e->pub.new && !e->pub.old)
-    return 0;
+  if (e->old && bmap_test(&c->export_map, e->old->id))
+  {
+    e->pub.old = e->old;
+    e->pub.old_src = e->old->attrs->src;
+  }
 
-  return 1;
+  return e->pub.new || e->pub.old;
 }
 
 USE_RESULT static _Bool
-rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
+rt_notify_accepted(struct channel *c, net *net, struct rte_export_internal *e)
 {
   // struct proto *p = c->proto;
   rte *new_best = NULL;
@@ -613,17 +616,17 @@ rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
    * old_best is after new_changed -> try new_changed, otherwise old_best
    */
 
-  if (e->pub.net->routes)
+  if (net->routes)
     c->stats.exp_updates_received++;
   else
     c->stats.exp_withdraws_received++;
 
   /* Find old_best - either old_changed, or route for net->routes */
-  if (e->pub.old && bmap_test(&c->export_map, e->pub.old->id))
-    old_best = e->pub.old;
+  if (e->old && bmap_test(&c->export_map, e->old->id))
+    old_best = e->old;
   else
   {
-    for (rte *r = e->pub.net->routes; rte_is_valid(r); r = r->next)
+    for (rte *r = net->routes; rte_is_valid(r); r = r->next)
     {
       if (bmap_test(&c->export_map, r->id))
       {
@@ -632,23 +635,23 @@ rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
       }
 
       /* Note if new_changed found before old_best */
-      if (r == e->pub.new)
+      if (r == e->new)
        new_first = 1;
     }
   }
 
   /* Find new_best */
-  if ((e->pub.new == e->pub.old) || (old_best == e->pub.old))
+  if ((e->new == e->old) || (old_best == e->old))
   {
     /* Feed or old_best changed -> find first accepted by filters */
-    for (rte *r = e->pub.net->routes; rte_is_valid(r); r = r->next)
+    for (rte *r = net->routes; rte_is_valid(r); r = r->next)
       if (new_best = export_filter(c, r, &e->rt_free, 0))
        break;
   }
   else
   {
     /* Other cases -> either new_changed, or old_best (and nothing changed) */
-    if (new_first && (e->pub.new = export_filter(c, e->pub.new, &e->rt_free, 0)))
+    if (new_first && (e->pub.new = export_filter(c, e->new, &e->rt_free, 0)))
       new_best = e->pub.new;
     else
       return 0;
@@ -726,7 +729,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int
 
 
 USE_RESULT static _Bool
-rt_notify_merged(struct channel *c, struct rte_export_internal *e)
+rt_notify_merged(struct channel *c, net *net, struct rte_export_internal *e)
 {
   /* We assume that all rte arguments are either NULL or rte_is_valid() */
 
@@ -736,9 +739,9 @@ rt_notify_merged(struct channel *c, struct rte_export_internal *e)
 
   /* Check whether the change is relevant to the merged route */
   if ((e->new_best == e->old_best) &&
-      (e->pub.new != e->pub.old) &&
-      !rte_mergable(e->new_best, e->pub.new) &&
-      !rte_mergable(e->old_best, e->pub.old))
+      (e->new != e->old) &&
+      !rte_mergable(e->new_best, e->new) &&
+      !rte_mergable(e->old_best, e->old))
     return 0;
 
   if (e->new_best)
@@ -748,7 +751,10 @@ rt_notify_merged(struct channel *c, struct rte_export_internal *e)
 
   /* Prepare new merged route */
   if (e->new_best)
-    e->pub.new = rt_export_merged(c, e->pub.net, &(e->rt_free), rte_update_pool, 0);
+  {
+    e->pub.new = rt_export_merged(c, net, &(e->rt_free), rte_update_pool, 0);
+    e->pub.new_src = net->routes->attrs->src;
+  }
 
   /* Check old merged route */
   if (e->old_best && !bmap_test(&c->export_map, e->old_best->id))
@@ -757,12 +763,84 @@ rt_notify_merged(struct channel *c, struct rte_export_internal *e)
   if (!e->pub.new && !e->pub.old)
     return 0;
 
-  e->pub.new_src = e->pub.new ? e->pub.new->attrs->src : NULL;
   e->pub.old_src = e->pub.old ? e->pub.old->attrs->src : NULL;
 
   return 1;
 }
 
+static inline void
+rte_export_finish(struct channel *c, struct rte_export_internal *e)
+{
+  if (e->rt_free)
+    rte_free(e->rt_free);
+
+  if (e->old && (!e->new || (e->new->id != e->old->id)))
+    bmap_clear(&c->export_reject_map, e->old->id);
+}
+
+static uint
+rte_export(struct channel *c, net *n, struct rte_export_internal *e)
+{
+  e->pub.net = n->n.addr;
+
+  uint ra_mode = c->ra_mode;
+  switch (ra_mode)
+  {
+    case RA_OPTIMAL:
+      if (e->new_best == e->old_best)
+       return 0;
+
+      e->new = e->new_best;
+      e->old = e->old_best;
+      /* fall through */
+    case RA_ANY:
+      if (!e->new && !e->old)
+       break;
+
+      if (rt_notify_basic(c, e))
+       do_rt_notify(c, &e->pub, e->refeed);
+
+      rte_export_finish(c, e);
+      return 1;
+
+    case RA_ACCEPTED:
+      if (rt_notify_accepted(c, n, e))
+       do_rt_notify(c, &e->pub, e->refeed);
+
+      rte_export_finish(c, e);
+      return 1;
+
+    case RA_MERGED:
+      if (rt_notify_merged(c, n, e))
+       do_rt_notify(c, &e->pub, e->refeed);
+
+      rte_export_finish(c, e);
+      return 1;
+  }
+
+  uint cnt = 0;
+
+  for (rte *ee = n->routes; ee; ee = ee->next)
+  {
+    if (!rte_is_valid(ee))
+      continue;
+
+    switch (ra_mode)
+    {
+      case RA_ANY:
+       cnt++;
+       e->new = ee;
+       e->old = ee;
+       rte_export(c, n, e);
+       break;
+      default:
+       bug("strange export mode");
+    }
+  }
+
+  return cnt;
+}
+
 
 /**
  * rte_announce - announce a routing table change
@@ -851,60 +929,12 @@ rte_announce(rtable *tab, uint type, net *net, rte *new, rte *old,
       continue;
     }
 
-    struct rte_export_internal e = {
-      .pub = {
-       .net = net,
-       .new_src = new ? new->attrs->src : NULL,
-       .new = new,
-       .old_src = old ? old->attrs->src : NULL,
-       .old = old,
-      },
-      .new_best = new_best,
-      .old_best = old_best,
+    struct rte_export_internal rei = {
+      .new = new, .old = old,
+      .new_best = new_best, .old_best = old_best,
     };
-
-    switch (c->ra_mode)
-    {
-    case RA_OPTIMAL:
-      if (new_best != old_best)
-      {
-       e.pub.new = new_best;
-       e.pub.new_src = new_best ? new_best->attrs->src : NULL;
-       e.pub.old = old_best;
-       e.pub.old_src = old_best ? old_best->attrs->src : NULL;
-       if (!rt_notify_basic(c, &e))
-         goto next_channel;
-      }
-      break;
-
-    case RA_ANY:
-      if (new != old)
-       if (!rt_notify_basic(c, &e))
-         goto next_channel;
-      break;
-
-    case RA_ACCEPTED:
-      if (!rt_notify_accepted(c, &e))
-       goto next_channel;
-      break;
-
-    case RA_MERGED:
-      if (!rt_notify_merged(c, &e))
-       goto next_channel;
-      break;
-    }
-
-    do_rt_notify(c, &e);
-
-next_channel:
-    /* Discard temporary rte */
-    if (e.rt_free)
-      rte_free(e.rt_free);
-
-    /* Drop the old stored rejection if applicable.
-     * new->id == old->id happens when updating hostentries. */
-    if (old && (!new || (new->id != old->id)))
-      bmap_clear(&c->export_reject_map, old->id);
+    
+    rte_export(c, net, &rei);
   }
 }
 
@@ -1408,37 +1438,6 @@ rte_modify(rte *old)
   rte_update_unlock();
 }
 
-/* Check channel for best route to given net whether it would be exported */
-int
-rt_examine(struct channel *c, net_addr *a)
-{
-  net *n = net_find(c->table, a);
-  rte *rt = n ? n->routes : NULL;
-
-  if (!rte_is_valid(rt))
-    return 0;
-
-  if (bmap_test(&c->export_reject_map, rt->id))
-    return 0;
-
-  rte_update_lock();
-
-  struct proto *p = c->proto;
-  /* Rest is stripped down export_filter() */
-  int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0;
-  if (v == RIC_PROCESS)
-    v = (f_run(c->out_filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
-
-  /* Discard temporary rte */
-  if (rt != n->routes)
-    rte_free(rt);
-
-  rte_update_unlock();
-
-  return v > 0;
-}
-
-
 /**
  * rt_refresh_begin - start a refresh cycle
  * @t: related routing table
@@ -2182,65 +2181,37 @@ rt_feed_channel(struct channel *c)
          return 0;
        }
 
-      for (rte *e = n->routes; e; e = e->next)
-      {
-       if (c->export_state != ES_FEEDING)
-         goto done;
-
-       if (rte_is_valid(e))
-       {
-         max_feed--;
-
-         struct rte_export_internal ee = {
-           .pub = {
-             .net = n,
-           },
-           .new_best = n->routes,
-           .old_best = n->routes,
-           .refeed = c->refeeding,
-         };
-
-         switch (c->ra_mode) {
-           case RA_OPTIMAL:
-           case RA_ANY:
-             ee.pub.new = e;
-             ee.pub.new_src = e->attrs->src;
-             ee.pub.old = e;
-             ee.pub.old_src = e->attrs->src;
-             if (!rt_notify_basic(c, &ee))
-               goto next_rte;
-             break;
-           case RA_ACCEPTED:
-             if (!rt_notify_accepted(c, &ee))
-               goto next_rte;
-             break;
-           case RA_MERGED:
-             if (!rt_notify_merged(c, &ee))
-               goto next_rte;
-             break;
-           default:
-             ASSERT(0);
-         }
-
-         do_rt_notify(c, &ee);
+      struct rte_export_internal rei = {
+       .new_best = n->routes,
+       .refeed = 1,
+      };
 
-         /* Discard temporary rte */
-next_rte:
-         if (ee.rt_free)
-           rte_free(ee.rt_free);
-       }
-
-       if (c->ra_mode != RA_ANY)
-         break;
-      }
+      rte_update_lock();
+      max_feed -= rte_export(c, n, &rei);
+      rte_update_unlock();
     }
   FIB_ITERATE_END;
 
-done:
   c->feed_active = 0;
   return 1;
 }
 
+void rt_feed_channel_net(struct channel *c, net_addr *n)
+{
+  net *nn = net_find(c->table, n);
+  if (!nn)
+    return;
+
+  struct rte_export_internal rei = {
+    .new_best = nn->routes,
+    .refeed = 1,
+  };
+
+  rte_update_lock();
+  rte_export(c, nn, &rei);
+  rte_update_unlock();
+}
+
 /**
  * rt_feed_baby_abort - abort protocol feeding
  * @c: channel
index 0cc633fa694968fa37d69fd179ab7d6955f2e518..6765b8952e76ba8678edc2f5c3359062cc22bace 100644 (file)
@@ -2142,11 +2142,11 @@ babel_rt_notify(struct channel *c, struct rte_export *export)
     if (rt_metric > BABEL_INFINITY)
     {
       log(L_WARN "%s: Invalid babel_metric value %u for route %N",
-         p->p.name, rt_metric, export->net->n.addr);
+         p->p.name, rt_metric, export->net);
       rt_metric = BABEL_INFINITY;
     }
 
-    e = babel_get_entry(p, export->net->n.addr);
+    e = babel_get_entry(p, export->net);
 
     /* Activate triggered updates */
     if ((e->valid != BABEL_ENTRY_VALID) ||
@@ -2164,7 +2164,7 @@ babel_rt_notify(struct channel *c, struct rte_export *export)
   else
   {
     /* Withdraw */
-    e = babel_find_entry(p, export->net->n.addr);
+    e = babel_find_entry(p, export->net);
 
     if (!e || e->valid != BABEL_ENTRY_VALID)
       return;
index 281b98890eca373bcf7190ac3eb1d46897384981..e8bbafc644b95c1f650bc4c390be164a24c82905 100644 (file)
@@ -1826,7 +1826,7 @@ bgp_rt_notify(struct channel *C, struct rte_export *e)
     path = e->old_src->global_id;
   }
 
-  px = bgp_get_prefix(c, e->net->n.addr, c->add_path_tx ? path : 0);
+  px = bgp_get_prefix(c, e->net, c->add_path_tx ? path : 0);
   add_tail(&buck->prefixes, &px->buck_node);
 
   bgp_schedule_packet(p->conn, c, PKT_UPDATE);
index 8e591022c12d2e0872d78996d7b328fdc8a7534c..23e42ec33fef52ff8857260783d01539ff5648ab 100644 (file)
@@ -2651,7 +2651,7 @@ bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, uint len)
   {
   case BGP_RR_REQUEST:
     BGP_TRACE(D_PACKETS, "Got ROUTE-REFRESH");
-    channel_request_feeding(&c->c);
+    channel_request_feeding(&c->c, NULL);
     break;
 
   case BGP_RR_BEGIN:
index 3822e4c02225b6c3e644d981b62943334aa9a976..959e73396f64c503091533f475833a2bc4e61da7 100644 (file)
@@ -1322,7 +1322,7 @@ ospf_rt_notify(struct channel *ch, struct rte_export *e)
 
   if (!e->new)
   {
-    nf = fib_find(&p->rtf, e->net->n.addr);
+    nf = fib_find(&p->rtf, e->net);
 
     if (!nf || !nf->external_rte)
       return;
@@ -1349,14 +1349,14 @@ ospf_rt_notify(struct channel *ch, struct rte_export *e)
   if (m1 > LSINFINITY)
   {
     log(L_WARN "%s: Invalid ospf_metric1 value %u for route %N",
-       p->p.name, m1, e->net->n.addr);
+       p->p.name, m1, e->net);
     m1 = LSINFINITY;
   }
 
   if (m2 > LSINFINITY)
   {
     log(L_WARN "%s: Invalid ospf_metric2 value %u for route %N",
-       p->p.name, m2, e->net->n.addr);
+       p->p.name, m2, e->net);
     m2 = LSINFINITY;
   }
 
@@ -1380,12 +1380,12 @@ ospf_rt_notify(struct channel *ch, struct rte_export *e)
     if (ipa_zero(fwd))
     {
       log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %N",
-         p->p.name, e->net->n.addr);
+         p->p.name, e->net);
       return;
     }
   }
 
-  nf = fib_get(&p->rtf, e->net->n.addr);
+  nf = fib_get(&p->rtf, e->net);
   ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1, p->vpn_pe);
   nf->external_rte = 1;
 }
index 452821b8c14ca2087b94e2066a6d67ddf0b32ea8..a6681592a98a401b408148ae86a362d540eef91b 100644 (file)
@@ -238,7 +238,7 @@ perf_feed_end(struct channel *c)
   p->feed_begin = NULL;
 
   if (p->run < p->repeat)
-    channel_request_feeding(c);
+    channel_request_feeding(c, NULL);
   else
     PLOG("feed done");
 }
index e5b27717ffc5d3bd687100b0294a63c4bea0f523..4942cbc925ef8c0d00a8ee7cf2c1881cbf03205d 100644 (file)
@@ -59,7 +59,7 @@ pipe_rt_notify(struct channel *src_ch, struct rte_export *export)
   if (dst->table->pipe_busy)
     {
       log(L_ERR "Pipe loop detected when sending %N to table %s",
-         export->net->n.addr, dst->table->name);
+         export->net, dst->table->name);
       return;
     }
 
@@ -77,13 +77,13 @@ pipe_rt_notify(struct channel *src_ch, struct rte_export *export)
       };
 
       src_ch->table->pipe_busy = 1;
-      rte_update(dst, export->net->n.addr, &e0);
+      rte_update(dst, export->net, &e0);
       src_ch->table->pipe_busy = 0;
     }
   else
     {
       src_ch->table->pipe_busy = 1;
-      rte_withdraw(dst, export->net->n.addr, export->old_src);
+      rte_withdraw(dst, export->net, export->old_src);
       src_ch->table->pipe_busy = 0;
     }
 }
@@ -105,7 +105,7 @@ pipe_reload_routes(struct channel *C)
   struct pipe_proto *p = (void *) C->proto;
 
   /* Route reload on one channel is just refeed on the other */
-  channel_request_feeding((C == p->pri) ? p->sec : p->pri);
+  channel_request_feeding((C == p->pri) ? p->sec : p->pri, NULL);
 }
 
 
index 2f95a0bbce76e612cf0dd18d6cf7127f79cb2731..c924ef84f1f98a0d9f60c7ec665bcf7c8b99284a 100644 (file)
@@ -33,7 +33,7 @@
  * The RAdv protocol could receive routes (through radv_preexport() and
  * radv_rt_notify()), but only the configured trigger route is tracked (in
  * &active var).  When a radv protocol is reconfigured, the connected routing
- * table is examined (in radv_check_active()) to have proper &active value in
+ * table is examined to have proper &active value in
  * case of the specified trigger prefix was changed.
  *
  * Supported standards:
@@ -385,9 +385,9 @@ radv_trigger_valid(struct radv_config *cf)
 }
 
 static inline int
-radv_net_match_trigger(struct radv_config *cf, net *n)
+radv_net_match_trigger(struct radv_config *cf, net_addr *n)
 {
-  return radv_trigger_valid(cf) && net_equal(n->n.addr, &cf->trigger);
+  return radv_trigger_valid(cf) && net_equal(n, &cf->trigger);
 }
 
 int
@@ -396,7 +396,7 @@ radv_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
   // struct radv_proto *p = (struct radv_proto *) P;
   struct radv_config *cf = (struct radv_config *) (P->cf);
 
-  if (radv_net_match_trigger(cf, (*new)->net))
+  if (radv_net_match_trigger(cf, (*new)->net->n.addr))
     return RIC_PROCESS;
 
   if (cf->propagate_routes)
@@ -457,14 +457,14 @@ radv_rt_notify(struct channel *ch, struct rte_export *e)
        (preference != RA_PREF_HIGH))
     {
       log(L_WARN "%s: Invalid ra_preference value %u on route %N",
-         p->p.name, preference, e->net->n.addr);
+         p->p.name, preference, e->net);
       preference = RA_PREF_MEDIUM;
       preference_set = 1;
       lifetime = 0;
       lifetime_set = 1;
     }
 
-    rt = fib_get(&p->routes, e->net->n.addr);
+    rt = fib_get(&p->routes, e->net);
 
     /* Ignore update if nothing changed */
     if (rt->valid &&
@@ -487,7 +487,7 @@ radv_rt_notify(struct channel *ch, struct rte_export *e)
   else
   {
     /* Withdraw */
-    rt = fib_find(&p->routes, e->net->n.addr);
+    rt = fib_find(&p->routes, e->net);
 
     if (!rt || !rt->valid)
       return;
@@ -546,18 +546,6 @@ again:
   p->prune_time = next;
 }
 
-static int
-radv_check_active(struct radv_proto *p)
-{
-  struct radv_config *cf = (struct radv_config *) (p->p.cf);
-
-  if (!radv_trigger_valid(cf))
-    return 1;
-
-  struct channel *c = p->p.main_channel;
-  return rt_examine(c, &cf->trigger);
-}
-
 static void
 radv_postconfig(struct proto_config *CF)
 {
@@ -650,15 +638,21 @@ radv_reconfigure(struct proto *P, struct proto_config *CF)
   if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
     return 0;
 
-  P->cf = CF; /* radv_check_active() requires proper P->cf */
-  p->active = radv_check_active(p);
+  P->cf = CF;
 
   /* Allocate or free FIB */
   radv_set_fib(p, new->propagate_routes);
 
   /* We started to accept routes so we need to refeed them */
   if (!old->propagate_routes && new->propagate_routes)
-    channel_request_feeding(p->p.main_channel);
+    channel_request_feeding(p->p.main_channel, NULL);
+  else if (!net_equal(&old->trigger, &new->trigger))
+  {
+    /* On trigger change, refeed the routes for which the preexport may have changed */
+    channel_request_feeding(p->p.main_channel, &old->trigger);
+    channel_request_feeding(p->p.main_channel, &new->trigger);
+  }
+
 
   struct iface *iface;
   WALK_LIST(iface, iface_list)
index 5ac8a10668bfcf22684a324fef0f13749904913e..d19588bdfb3e2662bbe2f5cead89214f7d6fdec5 100644 (file)
@@ -326,14 +326,14 @@ rip_rt_notify(struct channel *ch, struct rte_export *e)
     if (rt_metric > p->infinity)
     {
       log(L_WARN "%s: Invalid rip_metric value %u for route %N",
-         p->p.name, rt_metric, e->net->n.addr);
+         p->p.name, rt_metric, e->net);
       rt_metric = p->infinity;
     }
 
     if (rt_tag > 0xffff)
     {
       log(L_WARN "%s: Invalid rip_tag value %u for route %N",
-         p->p.name, rt_tag, e->net->n.addr);
+         p->p.name, rt_tag, e->net);
       rt_metric = p->infinity;
       rt_tag = 0;
     }
@@ -345,7 +345,7 @@ rip_rt_notify(struct channel *ch, struct rte_export *e)
      * collection.
      */
 
-    en = fib_get(&p->rtable, e->net->n.addr);
+    en = fib_get(&p->rtable, e->net);
 
     old_metric = en->valid ? en->metric : -1;
 
@@ -359,7 +359,7 @@ rip_rt_notify(struct channel *ch, struct rte_export *e)
   else
   {
     /* Withdraw */
-    en = fib_find(&p->rtable, e->net->n.addr);
+    en = fib_find(&p->rtable, e->net);
 
     if (!en || en->valid != RIP_ENTRY_VALID)
       return;
index bca2d9d254ab96d2063b6a729657b6d4dfd828f4..ec928480891857d922c1492c03720d1124adc7d3 100644 (file)
@@ -347,7 +347,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
 }
 
 void
-krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
+krt_replace_rte(struct krt_proto *p, rte *new, rte *old)
 {
   int err = 0;
 
index ae33a14494dbe1faee27344951cb16a79a20d6e0..87c157fa6e0733e1fd3731cc26f44d55cb79b8cd 100644 (file)
@@ -1394,7 +1394,7 @@ nl_replace_rte(struct krt_proto *p, rte *e)
 
 
 void
-krt_replace_rte(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
+krt_replace_rte(struct krt_proto *p, rte *new, rte *old)
 {
   int err = 0;
 
index 16b3d2e147b8ad1b91ecb0b3bbe7ea1fb6c40bfb..e6176b3a72938ee597d2d6092cc17601e3a15b61 100644 (file)
@@ -552,7 +552,7 @@ krt_flush_routes(struct krt_proto *p)
       if (krt_is_installed(p, n))
        {
          /* FIXME: this does not work if gw is changed in export filter */
-         krt_replace_rte(p, n, NULL, n->routes);
+         krt_replace_rte(p, NULL, n->routes);
        }
     }
   FIB_WALK_END;
@@ -682,12 +682,12 @@ ignore:
 
 update:
   krt_trace_in(p, new, "updating");
-  krt_replace_rte(p, n, new, e);
+  krt_replace_rte(p, new, e);
   goto done;
 
 delete:
   krt_trace_in(p, e, "deleting");
-  krt_replace_rte(p, n, NULL, e);
+  krt_replace_rte(p, NULL, e);
   goto done;
 
 done:
@@ -719,7 +719,7 @@ krt_prune(struct krt_proto *p)
       if (new)
       {
        krt_trace_in(p, new, "installing");
-       krt_replace_rte(p, n, new, NULL);
+       krt_replace_rte(p, new, NULL);
       }
 
       if (rt_free)
@@ -742,8 +742,6 @@ krt_prune(struct krt_proto *p)
 void
 krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
 {
-  net *net = e->net;
-
   switch (src)
     {
     case KRT_SRC_BIRD:
@@ -754,7 +752,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
       if (new)
        {
          krt_trace_in(p, e, "[redirect] deleting");
-         krt_replace_rte(p, net, NULL, e);
+         krt_replace_rte(p, NULL, e);
        }
       /* If !new, it is probably echo of our deletion */
       break;
@@ -903,13 +901,12 @@ krt_rt_notify(struct channel *ch, struct rte_export *e)
    * but if we processed the update as usual, we would send withdraw to the
    * kernel, which would remove the new imported route instead.
    */
-  rte *best = e->net->routes;
-  if (!e->new && best && (best->attrs->src->proto == ch->proto))
+  if (!e->new && (e->new_src->proto == ch->proto))
     return;
 #endif
 
   if (p->initialized)          /* Before first scan we don't touch the routes */
-    krt_replace_rte(p, e->net, e->new, e->old);
+    krt_replace_rte(p, e->new, e->old);
 }
 
 static void
index 310a2d1138f32dffe22af4f344aab71fb055564f..72659a3a6813193ca2361f83847cd73b8963c5dd 100644 (file)
@@ -143,7 +143,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *);
 
 int  krt_capable(rte *e);
 void krt_do_scan(struct krt_proto *);
-void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old);
+void krt_replace_rte(struct krt_proto *p, rte *new, rte *old);
 int krt_sys_get_attr(const eattr *a, byte *buf, int buflen);