Commit 8f3942a9 authored by Maria Matejka's avatar Maria Matejka
Browse files

Route export: rejected by filter bitmap

If a route has been rejected by filter, store that information
to avoid repeated export filter runs on rejected routes.
parent c56752e4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -463,6 +463,7 @@ channel_stop_export(struct channel *c)
  c->export_state = ES_DOWN;
  c->export_stats.routes = 0;
  bmap_reset(&c->export_map, 1024);
  bmap_reset(&c->export_reject_map, 1024);
}


@@ -551,6 +552,7 @@ channel_do_start(struct channel *c)
  c->feed_event = ev_new_init(c->proto->pool, channel_feed_loop, c);

  bmap_init(&c->export_map, c->proto->pool, 1024);
  bmap_init(&c->export_reject_map, c->proto->pool, 1024);
  memset(&c->export_stats, 0, sizeof(struct export_stats));
  memset(&c->import_stats, 0, sizeof(struct import_stats));

@@ -585,6 +587,7 @@ channel_do_flush(struct channel *c)

  /* This have to be done in here, as channel pool is freed before channel_do_down() */
  bmap_free(&c->export_map);
  bmap_free(&c->export_reject_map);
  c->in_table = NULL;
  c->reload_event = NULL;
  c->out_table = NULL;
+2 −1
Original line number Diff line number Diff line
@@ -511,7 +511,8 @@ struct channel {
  struct rtable *table;
  const struct filter *in_filter;	/* Input filter */
  const struct filter *out_filter;	/* Output filter */
  struct bmap export_map;		/* Keeps track which routes passed export filter */
  struct bmap export_map;		/* Keeps track which routes were really exported */
  struct bmap export_reject_map;	/* Keeps track which routes were rejected by export 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 */
+31 −20
Original line number Diff line number Diff line
@@ -376,18 +376,22 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent)
  struct proto *p = c->proto;
  const struct filter *filter = c->out_filter;
  struct export_stats *stats = &c->export_stats;
  int v;

  v = p->preexport ? p->preexport(c, rt) : 0;
  /* Do nothing if we have already rejected the route */
  if (silent && bmap_test(&c->export_reject_map, rt->id))
    goto reject_noset;

  int v = p->preexport ? p->preexport(c, rt) : 0;
  if (v < 0)
    {
      if (silent)
	goto reject;
	goto reject_noset;

      stats->updates_rejected++;
      if (v == RIC_REJECT)
	rte_trace_out(D_FILTERS, c, rt, "rejected by protocol");
      goto reject;
      goto reject_noset;

    }
  if (v > 0)
    {
@@ -410,9 +414,16 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent)
    }

 accept:
  /* We have accepted the route */
  bmap_clear(&c->export_reject_map, rt->id);
  return rt;

 reject:
  /* We have rejected the route by filter */
  bmap_set(&c->export_reject_map, rt->id);

reject_noset:
  /* Invalidate the route */
  /* Discard temporary rte */
  return NULL;
}
@@ -565,9 +576,15 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
  {
    /* Feed or old_best changed -> find first accepted by filters */
    for (struct rte_storage *r = net->routes; r && rte_is_valid(&r->rte); r = r->next)
    {
      /* Already rejected before */
      if (!refeed && bmap_test(&c->export_reject_map, r->rte.id))
	continue;

      if (new_best = export_filter(c, ((nb0 = r->rte), &nb0), 0))
	break;
    }
  }
  else
  {
    /* Other cases -> either new_changed, or old_best (and nothing changed) */
@@ -677,7 +694,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
/**
 * rte_announce - announce a routing table change
 * @tab: table the route has been added to
 * @type: type of route announcement (RA_UNDEF or RA_ANY)
 * @net: network in question
 * @new: the new or changed route
 * @old: the previous route replaced by the new one
@@ -693,13 +709,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
 * and @new_best and @old_best describes best routes. Other routes are not
 * affected, but in sorted table the order of other routes might change.
 *
 * Second, There is a bulk change of multiple routes in @net, with shared best
 * route selection. In such case separate route changes are described using
 * @type of %RA_ANY, with @new and @old specifying the changed route, while
 * @new_best and @old_best are NULL. After that, another notification is done
 * where @new_best and @old_best are filled (may be the same), but @new and @old
 * are NULL.
 *
 * The function announces the change to all associated channels. For each
 * channel, an appropriate preprocessing is done according to channel &ra_mode.
 * For example, %RA_OPTIMAL channels receive just changes of best routes.
@@ -714,7 +723,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
 * done outside of scope of rte_announce().
 */
static void
rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct rte_storage *old,
rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage *old,
	     struct rte_storage *new_best, struct rte_storage *old_best)
{
  if (!new || !rte_is_valid(&new->rte))
@@ -751,9 +760,6 @@ rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct r
    if (c->export_state == ES_DOWN)
      continue;

    if (type && (type != c->ra_mode))
      continue;

    rte n0;
    switch (c->ra_mode)
    {
@@ -775,6 +781,11 @@ rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct r
      rt_notify_merged(c, net, RTE_OR_NULL(new), RTE_OR_NULL(old), RTE_OR_NULL(new_best), RTE_OR_NULL(old_best), 0);
      break;
    }

    /* Drop the old stored rejection if applicable.
     * new->id == old->id happens when updating hostentries. */
    if (old && (!new || (new->rte.id != old->rte.id)))
      bmap_clear(&c->export_reject_map, old->rte.id);
  }
}

@@ -1083,7 +1094,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
    }

  /* Propagate the route change */
  rte_announce(table, RA_UNDEF, net, new_stored, old_stored,
  rte_announce(table, net, new_stored, old_stored,
      net->routes, old_best_stored);

  if (!net->routes &&
@@ -1208,11 +1219,11 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
/* Independent call to rte_announce(), used from next hop
   recalculation, outside of rte_update(). new must be non-NULL */
static inline void
rte_announce_i(rtable *tab, uint type, net *net, struct rte_storage *new, struct rte_storage *old,
rte_announce_i(rtable *tab, net *net, struct rte_storage *new, struct rte_storage *old,
	       struct rte_storage *new_best, struct rte_storage *old_best)
{
  rte_update_lock();
  rte_announce(tab, type, net, new, old, new_best, old_best);
  rte_announce(tab, net, new, old, new_best, old_best);
  rte_update_unlock();
}

@@ -1938,7 +1949,7 @@ rt_next_hop_update_net(rtable *tab, net *n)
    _Bool nb = (new == updates[i].new), ob = (old_best == updates[i].old);
    const char *best_indicator[2][2] = { { "updated", "updated [-best]" }, { "updated [+best]", "updated [best]" } };
    rte_trace_in(D_ROUTES, new->rte.sender, &updates[i].new->rte, best_indicator[nb][ob]);
    rte_announce_i(tab, RA_UNDEF, n, updates[i].new, updates[i].old, new, old_best);
    rte_announce_i(tab, n, updates[i].new, updates[i].old, new, old_best);
  }

  for (int i=0; i<count; i++)