Commit 7930c03a 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 d53623f1
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->stats.exp_routes = 0;
  bmap_reset(&c->export_map, 1024);
  bmap_reset(&c->export_reject_map, 1024);
}


@@ -550,6 +551,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->stats, 0, sizeof(struct proto_stats));

  channel_reset_limit(&c->rx_limit);
@@ -583,6 +585,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
@@ -506,7 +506,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 */
+1 −1
Original line number Diff line number Diff line
@@ -337,7 +337,7 @@ 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(rtable *t, net_addr *a, struct proto *p, const struct filter *filter);
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);
+40 −11
Original line number Diff line number Diff line
@@ -442,33 +442,36 @@ 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;

  v = p->preexport ? p->preexport(p, &rt, pool) : 0;
  if (v < 0)
  /* Do nothing if we have already rejected the route */
  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)
    {
      if (silent)
	goto reject;

      stats->exp_updates_rejected++;
      if (v == RIC_REJECT)
      if (pv == RIC_REJECT)
	rte_trace_out(D_FILTERS, c, rt, "rejected by protocol");
      goto reject;
    }
  if (v > 0)
  if (pv > 0)
    {
      if (!silent)
	rte_trace_out(D_FILTERS, c, rt, "forced accept by protocol");
      goto accept;
    }

  v = filter && ((filter == FILTER_REJECT) ||
  int fv = filter && ((filter == FILTER_REJECT) ||
		 (f_run(filter, &rt, pool,
			(silent ? FF_SILENT : 0)) > F_ACCEPT));
  if (v)
  if (fv)
    {
      if (silent)
	goto reject;
@@ -479,11 +482,19 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
    }

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

  /* Discard temporary rte */
  if (rt != rt0)
    *rt_free = rt;
  return rt;

 reject:
  /* We have rejected the route by filter */
  if (pv == 0)
    bmap_set(&c->export_reject_map, rt0->id);

  /* Discard temporary rte */
  if (rt != rt0)
    rte_free(rt);
@@ -839,7 +850,16 @@ rte_announce(rtable *tab, uint type, net *net, rte *new, rte *old,
      continue;

    if (type && (type != c->ra_mode))
    {
      /* If skipping other means of announcement,
       * drop the rejection bit anyway
       * as we won't get this route as old any more.
       * This happens when updating hostentries. */
      if (old)
	bmap_clear(&c->export_reject_map, old->id);

      continue;
    }

    struct rte_export_internal e = {
      .pub = {
@@ -890,6 +910,11 @@ 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);
  }
}

@@ -1402,22 +1427,26 @@ rte_modify(rte *old)
  rte_update_unlock();
}

/* Check rtable for best route to given net whether it would be exported do p */
/* Check channel for best route to given net whether it would be exported */
int
rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter)
rt_examine(struct channel *c, net_addr *a)
{
  net *n = net_find(t, 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(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
    v = (f_run(c->out_filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);

  /* Discard temporary rte */
  if (rt != n->routes)
+1 −1
Original line number Diff line number Diff line
@@ -555,7 +555,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, &cf->trigger);
}

static void