]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Route export: More elegant export dispatcher.
authorMaria Matejka <mq@ucw.cz>
Tue, 10 Mar 2020 15:13:41 +0000 (16:13 +0100)
committerMaria Matejka <mq@ucw.cz>
Sat, 20 Mar 2021 22:45:32 +0000 (23:45 +0100)
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 b3b048193f99d3dd9968cdb7bd4c46c7ea42e24d..5ecbe9a22fa598af726d73f44d85f3a039567d8c 100644 (file)
@@ -186,6 +186,7 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
   c->reloadable = 1;
 
   init_list(&c->roa_subscriptions);
+  init_list(&c->net_feed);
 
   CALL(c->channel->init, c, cf);
 
@@ -304,9 +305,30 @@ channel_feed_loop(void *ptr)
 
   /* Restart feeding */
   if (c->refeed_pending)
-    channel_request_feeding(c);
+    channel_request_feeding(c, NULL);
 }
 
+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_roa_in_changed(struct rt_subscription *s)
@@ -331,7 +353,7 @@ channel_roa_out_changed(struct rt_subscription *s)
   CD(c, "Feeding triggered by RPKI change%s", active ? " - already active" : "");
 
   if (!active)
-    channel_request_feeding(c);
+    channel_request_feeding(c, NULL);
   else
     c->refeed_pending = 1;
 }
@@ -460,6 +482,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);
@@ -702,7 +734,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);
 
@@ -719,9 +751,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;
 
@@ -902,7 +942,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);
 
 done:
   CD(c, "Reconfigured");
@@ -2210,7 +2250,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 ea063326c7cb5aa2b0b6b02f9ad514a6bb5d973f..9dc7a085ed5866e46844fb4b576d034f6293ef83 100644 (file)
@@ -542,16 +542,24 @@ struct channel {
   struct fib_iterator reload_fit;      /* FIB iterator in in_table used during reloading */
   struct rte *reload_next_rte;         /* Route iterator in in_table used during reloading */
   u8 reload_active;                    /* Iterator reload_fit is linked */
-
   u8 reload_pending;                   /* Reloading and another reload is scheduled */
   u8 refeed_pending;                   /* Refeeding and another refeed is scheduled */
   u8 rpki_reload;                      /* RPKI changes trigger channel reload */
 
+  list net_feed;                       /* Active net feeders (struct channel_net_feed) */
+
   struct rtable *out_table;            /* Internal table for exported routes */
 
   list roa_subscriptions;              /* List of active ROA table subscriptions based on filters roa_check() */
 };
 
+struct channel_net_feed {
+  node n;
+  struct event e;
+  struct channel *c;
+  net_addr addr[0];
+};
+
 
 /*
  * Channel states
@@ -625,7 +633,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 2759bc172c0288ad327273dc403679cf26e5457d..bcaf15c01ebd8b2d2b74800f57233abf10dac651 100644 (file)
@@ -240,12 +240,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 */
@@ -337,7 +338,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);
@@ -352,6 +352,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 92160805634db087dd0c9660167ce57ec99ebfcb..e831a77faa6e7748094b0391c69722e664ecd67a 100644 (file)
@@ -358,11 +358,11 @@ rte_free_quick(rte *e)
 }
 
 struct rte_export_internal {
-  struct rte_export pub;
-  rte *new_best;
-  rte *old_best;
+  net *net;
+  rte *new, *old, *new_best, *old_best;
   rte *rt_free;
-  uint refeed:1;
+  struct rte_export pub;
+  _Bool refeed;
 };
 
 static int                             /* Actually better or at least as good as */
@@ -442,6 +442,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;
@@ -450,28 +451,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, c, rt, "rejected by protocol");
       goto reject;
     }
-  if (pv > 0)
+  if (v > 0)
     {
       if (!silent)
        rte_trace_out(D_FILTERS, c, 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;
@@ -491,9 +492,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)
@@ -508,13 +508,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 */
@@ -536,7 +535,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)
@@ -580,21 +579,26 @@ 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)
+  struct rte_export *ep = &e->pub;
+
+  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)
+  {
+    ep->new = export_filter(c, e->new, &e->rt_free, 0);
+    ep->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))
+  {
+    ep->old = e->old;
+    ep->old_src = e->old->attrs->src;
+  }
 
-  return 1;
+  return (ep->new || ep->old);
 }
 
 USE_RESULT static _Bool
@@ -603,6 +607,7 @@ rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
   // struct proto *p = c->proto;
   rte *new_best = NULL;
   rte *old_best = NULL;
+  rte *new_filtered = NULL;
   int new_first = 0;
 
   /*
@@ -621,17 +626,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 (e->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 = e->net->routes; rte_is_valid(r); r = r->next)
     {
       if (bmap_test(&c->export_map, r->id))
       {
@@ -640,24 +645,24 @@ 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 = e->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)))
-      new_best = e->pub.new;
+    if (new_first && (new_filtered = export_filter(c, e->new, &e->rt_free, 0)))
+      new_best = new_filtered;
     else
       return 0;
   }
@@ -665,10 +670,12 @@ rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
   if (!new_best && !old_best)
     return 0;
 
-  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;
+  e->pub = (struct rte_export) {
+    .new = new_best,
+    .new_src = new_best ? new_best->attrs->src : NULL,
+    .old = old_best,
+    .old_src = old_best ? old_best->attrs->src : NULL,
+  };
 
   return 1;
 }
@@ -744,9 +751,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)
@@ -754,23 +761,70 @@ rt_notify_merged(struct channel *c, struct rte_export_internal *e)
   else
     c->stats.exp_withdraws_received++;
 
+  struct rte_export *ep = &e->pub;
+
   /* 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);
+  {
+    ep->new = rt_export_merged(c, e->net, &(e->rt_free), rte_update_pool, 0);
+    ep->new_src = e->net->routes->attrs->src;
+  }
 
   /* Check old merged route */
-  if (e->old_best && !bmap_test(&c->export_map, e->old_best->id))
-    e->pub.old = NULL;
+  if (e->old_best)
+    ep->old = bmap_test(&c->export_map, e->old_best->id) ? e->old_best : NULL;
 
-  if (!e->pub.new && !e->pub.old)
+  if (!ep->new && !ep->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;
-
+  ep->old_src = ep->old ? ep->old->attrs->src : NULL;
   return 1;
 }
 
+static void
+rte_export(struct channel *c, struct rte_export_internal *e)
+{
+  uint ra_mode = c->ra_mode;
+  _Bool accepted = 0;
+
+  switch (ra_mode)
+  {
+    case RA_OPTIMAL:
+      if (e->new_best == e->old_best)
+       break;
+
+      e->new = e->new_best;
+      e->old = e->old_best;
+      /* fall through */
+    case RA_ANY:
+      accepted = rt_notify_basic(c, e);
+      break;
+
+    case RA_ACCEPTED:
+      accepted = rt_notify_accepted(c, e);
+      break;
+
+    case RA_MERGED:
+      accepted = rt_notify_merged(c, e);
+      break;
+
+    default:
+      bug("Strange channel route announcement mode");
+  }
+
+  if (accepted)
+  {
+    e->pub.net = e->net->n.addr;
+    do_rt_notify(c, &e->pub, e->refeed);
+  }
+
+  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);
+}
+
 
 /**
  * rte_announce - announce a routing table change
@@ -861,60 +915,13 @@ 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 = {
+      .net = net,
+      .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, &rei);
   }
 }
 
@@ -1427,37 +1434,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
@@ -2247,6 +2223,43 @@ rt_commit(struct config *new, struct config *old)
   DBG("\tdone\n");
 }
 
+static uint
+rt_feed_channel_net_internal(struct channel *c, net *nn)
+{
+  struct rte_export_internal rei = {
+    .net = nn,
+    .new_best = nn->routes,
+    .new = nn->routes,
+    .refeed = 1,
+  };
+
+  rte_update_lock();
+  if (c->ra_mode == RA_ANY)
+  {
+    uint cnt = 0;
+    for (rei.new = nn->routes; rei.new; rei.new = rei.new->next)
+      if (rte_is_valid(rei.new))
+       rte_export(c, &rei), cnt++;
+    return cnt;
+  }
+  else
+  {
+    rte_export(c, &rei);
+    return 1;
+  }
+  rte_update_unlock();
+}
+
+void
+rt_feed_channel_net(struct channel *c, net_addr *n)
+{
+  net *nn = net_find(c->table, n);
+  if (!nn)
+    return;
+
+  rt_feed_channel_net_internal(c, nn);
+}
+
 /**
  * rt_feed_channel - advertise all routes to a channel
  * @c: channel to be fed
@@ -2278,61 +2291,10 @@ 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);
-
-         /* Discard temporary rte */
-next_rte:
-         if (ee.rt_free)
-           rte_free(ee.rt_free);
-       }
-
-       if (c->ra_mode != RA_ANY)
-         break;
-      }
+      max_feed -= rt_feed_channel_net_internal(c, n);
     }
   FIB_ITERATE_END;
 
-done:
   c->feed_active = 0;
   return 1;
 }
index f00cd08feefb74c3fdf327386f5e0ec81b684bc3..9693025d1f2c474520e5e0717f4d7c3b7763a7df 100644 (file)
@@ -2137,11 +2137,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) ||
@@ -2159,7 +2159,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 4d1bd3f163b6310fb8162225c141680299c98513..f2810fd1d7217b86923df2ac52907379a1623fb1 100644 (file)
@@ -1857,7 +1857,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 841b42fba67a36b1f85a4735159fbc444cad2ffc..005c73977fa66249e4a10e21d60ce8f9ee8ab4fa 100644 (file)
@@ -2695,7 +2695,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 4c757c864d57dac0ca6ea0f9b877e99f785268fd..e1ddc106383bbe4ee23576b68d613de6429c8421 100644 (file)
@@ -1319,7 +1319,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;
@@ -1346,14 +1346,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;
   }
 
@@ -1377,12 +1377,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 a8a335f7f81acc3578433f59d37a139d576072dc..7cf1524ade81085f33c184815bb1b78481768446 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 9c84d73510c17f1a6d300aee07b95f642fb7e349..cf50a4a8285b358272ba2620560a11f55ec17273 100644 (file)
@@ -327,14 +327,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;
     }
@@ -346,7 +346,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;
 
@@ -360,7 +360,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 3b9fa81a4f9523abe1d97ef97046a09fc9cb4b5c..6a5d6487237d8225ab756e9f83a4e17a0324ed40 100644 (file)
@@ -1427,7 +1427,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 333b482ed47679fe0af269a311c5da75037adae1..bf6e43a205754f691bd6fe1fc2ce46d1d50c9bd8 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);