]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit 'f2f3163f6c3fba7f9ef03640d7b2f6323873d2cc' into haugesund
authorMaria Matejka <mq@ucw.cz>
Mon, 30 May 2022 14:41:15 +0000 (16:41 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 30 May 2022 14:41:15 +0000 (16:41 +0200)
1  2 
filter/f-inst.c
filter/filter.c
filter/filter.h
nest/rt-show.c
nest/rt-table.c
proto/mrt/mrt.c
proto/static/static.c
sysdep/unix/krt.c

diff --cc filter/f-inst.c
Simple merge
diff --cc filter/filter.c
index 4545946f398692019c1922664ae1829f634fda06,9bedb9381df28ecef8354c03d7ac4fbb7e334dab..124c99324189971af9c62c7a8ac6f87d34867926
@@@ -117,7 -131,7 +114,7 @@@ f_rta_cow(struct filter_state *fs
     * at the end of f_run()), also the lock of hostentry is inherited (we
     * suppose hostentry is not changed by filters).
     */
-   fs->rte->attrs = rta_do_cow(fs->rte->attrs, fs->pool);
 -  (*fs->rte)->attrs = rta_do_cow((*fs->rte)->attrs, tmp_linpool);
++  fs->rte->attrs = rta_do_cow(fs->rte->attrs, tmp_linpool);
  
    /* Re-cache the ea_list */
    f_cache_eattrs(fs);
@@@ -233,11 -247,25 +230,11 @@@ interpret(struct filter_state *fs, cons
   * @tmp_pool: all filter allocations go from this pool
   * @flags: flags
   *
 - * If filter needs to modify the route, there are several
 - * posibilities. @rte might be read-only (with REF_COW flag), in that
 - * case rw copy is obtained by rte_cow() and @rte is replaced. If
 - * @rte is originally rw, it may be directly modified (and it is never
 - * copied).
 - *
 - * The returned rte may reuse the (possibly cached, cloned) rta, or
 - * (if rta was modified) contains a modified uncached rta, which
 - * uses parts allocated from @tmp_pool and parts shared from original
 - * rta. There is one exception - if @rte is rw but contains a cached
 - * rta and that is modified, rta in returned rte is also cached.
 - *
 - * Ownership of cached rtas is consistent with rte, i.e.
 - * if a new rte is returned, it has its own clone of cached rta
 - * (and cached rta of read-only source rte is intact), if rte is
 - * modified in place, old cached rta is possibly freed.
 + * If @rte->attrs is cached, the returned rte allocates a new rta on
 + * tmp_pool, otherwise the filters may modify it.
   */
  enum filter_return
- f_run(const struct filter *filter, struct rte *rte, struct linpool *tmp_pool, int flags)
 -f_run(const struct filter *filter, struct rte **rte, int flags)
++f_run(const struct filter *filter, struct rte *rte, int flags)
  {
    if (filter == FILTER_ACCEPT)
      return F_ACCEPT;
   */
  
  enum filter_return
- f_eval_rte(const struct f_line *expr, struct rte *rte, struct linpool *tmp_pool)
 -f_eval_rte(const struct f_line *expr, struct rte **rte)
++f_eval_rte(const struct f_line *expr, struct rte *rte)
  {
    filter_state = (struct filter_state) {
      .rte = rte,
diff --cc filter/filter.h
index 351174e4797b8d31592dc6fcb73c95512b922a55,43c0444387469ed03e537a94e50b9e962d83f284..0c3486e0a17e30c8b92088515fd3d48591f2783c
@@@ -51,10 -51,10 +51,10 @@@ struct filter 
  
  struct rte;
  
- enum filter_return f_run(const struct filter *filter, struct rte *rte, struct linpool *tmp_pool, int flags);
- enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte, struct linpool *tmp_pool);
 -enum filter_return f_run(const struct filter *filter, struct rte **rte, int flags);
 -enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte);
++enum filter_return f_run(const struct filter *filter, struct rte *rte, int flags);
++enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte);
  uint f_eval_int(const struct f_line *expr);
- enum filter_return f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf);
+ enum filter_return f_eval_buf(const struct f_line *expr, buffer *buf);
  
  const char *filter_name(const struct filter *filter);
  int filter_same(const struct filter *new, const struct filter *old);
diff --cc nest/rt-show.c
index 8c25375f11447356d8438596fe8f3e1400f2cbfc,7d02f52ede58c1076955a28b2cca5637348724a1..26180a8d23793f05217692ae241fa9947eb4134c
@@@ -208,10 -179,10 +208,10 @@@ rt_show_net(struct cli *c, net *n, stru
            }
        }
  
 -      if (d->show_protocol && (d->show_protocol != e->src->proto))
 +      if (d->show_protocol && (d->show_protocol != e.src->proto))
        goto skip;
  
-       if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT)
+       if (f_run(d->filter, &e, 0) > F_ACCEPT)
        goto skip;
  
        if (d->stats < 2)
diff --cc nest/rt-table.c
index 0873cf42bb542143b90ee0102cd98a68a710f671,049b7a7f943d76cc60d4c8056856891cafdbeae1..9c7fd5e4c927c9d82fb4f90d519047a3ff23e42c
@@@ -735,7 -713,7 +735,7 @@@ rte_feed_obtain(net *n, struct rte **fe
  }
  
  static rte *
- export_filter_(struct channel *c, rte *rt, linpool *pool, int silent)
 -export_filter(struct channel *c, rte *rt0, rte **rt_free, int silent)
++export_filter(struct channel *c, rte *rt, int silent)
  {
    struct proto *p = c->proto;
    const struct filter *filter = c->out_filter;
      }
  
    v = filter && ((filter == FILTER_REJECT) ||
-                (f_run(filter, rt, pool,
 -               (f_run(filter, &rt,
++               (f_run(filter, rt,
                        (silent ? FF_SILENT : 0)) > F_ACCEPT));
    if (v)
      {
@@@ -791,53 -765,58 +791,47 @@@ reject_noset
    return NULL;
  }
  
- static inline rte *
- export_filter(struct channel *c, rte *rt, int silent)
- {
-   return export_filter_(c, rt, rte_update_pool, silent);
- }
  static void
 -do_rt_notify(struct channel *c, net *net, rte *new, rte *old, int refeed)
 +do_rt_notify(struct channel *c, const net_addr *net, rte *new, const rte *old)
  {
    struct proto *p = c->proto;
 -  struct proto_stats *stats = &c->stats;
 +  struct channel_export_stats *stats = &c->export_stats;
  
 -  if (refeed && new)
 +  if (c->refeeding && new)
      c->refeed_count++;
  
 -  /* Apply export limit */
 -  struct channel_limit *l = &c->out_limit;
 -  if (l->action && !old && new)
 -  {
 -    if (stats->exp_routes >= l->limit)
 -      channel_notify_limit(c, l, PLD_OUT, stats->exp_routes);
 -
 -    if (l->state == PLS_BLOCKED)
 +  if (!old && new)
 +    if (CHANNEL_LIMIT_PUSH(c, OUT))
      {
 -      stats->exp_updates_rejected++;
 -      rte_trace_out(D_FILTERS, c, new, "rejected [limit]");
 +      stats->updates_rejected++;
 +      channel_rte_trace_out(D_FILTERS, c, new, "rejected [limit]");
        return;
      }
 -  }
 +
 +  if (!new && old)
 +    CHANNEL_LIMIT_POP(c, OUT);
  
    /* Apply export table */
 -  struct rte *old_exported = NULL;
 +  struct rte_storage *old_exported = NULL;
    if (c->out_table)
    {
 -    if (!rte_update_out(c, net->n.addr, new, old, &old_exported, refeed))
 +    if (!rte_update_out(c, net, new, old, &old_exported))
 +    {
 +      channel_rte_trace_out(D_ROUTES, c, new, "idempotent");
        return;
 +    }
    }
 -  else if (c->out_filter == FILTER_ACCEPT)
 -    old_exported = old;
  
    if (new)
 -    stats->exp_updates_accepted++;
 +    stats->updates_accepted++;
    else
 -    stats->exp_withdraws_accepted++;
 +    stats->withdraws_accepted++;
  
    if (old)
 -  {
      bmap_clear(&c->export_map, old->id);
 -    stats->exp_routes--;
 -  }
  
    if (new)
 -  {
      bmap_set(&c->export_map, new->id);
 -    stats->exp_routes++;
 -  }
  
    if (p->debug & D_ROUTES)
    {
@@@ -967,33 -957,26 +961,33 @@@ rt_export_merged(struct channel *c, str
    if (!rte_is_valid(best0))
      return NULL;
  
 -  best = export_filter(c, best0, rt_free, silent);
 +  /* Already rejected, no need to re-run the filter */
 +  if (!c->refeeding && bmap_test(&c->export_reject_map, best0->id))
 +    return NULL;
 +
 +  rloc = *best0;
-   best = export_filter_(c, &rloc, pool, silent);
++  best = export_filter(c, &rloc, silent);
 +
 +  if (!best)
 +    /* Best route doesn't pass the filter */
 +    return NULL;
  
 -  if (!best || !rte_is_reachable(best))
 +  if (!rte_is_reachable(best))
 +    /* Unreachable routes can't be merged */
      return best;
  
 -  for (rt0 = best0->next; rt0; rt0 = rt0->next)
 +  for (uint i = 1; i < count; i++)
    {
 -    if (!rte_mergable(best0, rt0))
 +    if (!rte_mergable(best0, feed[i]))
        continue;
  
 -    rt = export_filter(c, rt0, &tmp, 1);
 +    rte tmp0 = *feed[i];
-     rte *tmp = export_filter_(c, &tmp0, pool, 1);
++    rte *tmp = export_filter(c, &tmp0, 1);
  
 -    if (!rt)
 +    if (!tmp || !rte_is_reachable(tmp))
        continue;
  
 -    if (rte_is_reachable(rt))
 -      nhs = nexthop_merge_rta(nhs, rt->attrs, pool, c->merge_limit);
 -
 -    if (tmp)
 -      rte_free(tmp);
 +    nhs = nexthop_merge_rta(nhs, tmp->attrs, pool, c->merge_limit);
    }
  
    if (nhs)
@@@ -1544,60 -1557,81 +1538,60 @@@ rte_update_direct(struct channel *c, co
    rte_update_lock();
    if (new)
      {
 -      /* Create a temporary table node */
 -      nn = alloca(sizeof(net) + n->length);
 -      memset(nn, 0, sizeof(net) + n->length);
 -      net_copy(nn->n.addr, n);
 +      new->net = n;
  
 -      new->net = nn;
 -      new->sender = c;
 +      int fr;
  
 -      stats->imp_updates_received++;
 -      if (!rte_validate(new))
 +      stats->updates_received++;
 +      if (!rte_validate(c, new))
        {
 -        rte_trace_in(D_FILTERS, c, new, "invalid");
 -        stats->imp_updates_invalid++;
 -        goto drop;
 +        channel_rte_trace_in(D_FILTERS, c, new, "invalid");
 +        stats->updates_invalid++;
 +        new = NULL;
        }
 -
 -      if (filter == FILTER_REJECT)
 +      else if ((filter == FILTER_REJECT) ||
-       ((fr = f_run(filter, new, rte_update_pool, 0)) > F_ACCEPT))
++      ((fr = f_run(filter, new, 0)) > F_ACCEPT))
        {
 -        stats->imp_updates_filtered++;
 -        rte_trace_in(D_FILTERS, c, new, "filtered out");
 +        stats->updates_filtered++;
 +        channel_rte_trace_in(D_FILTERS, c, new, "filtered out");
  
 -        if (! c->in_keep_filtered)
 -          goto drop;
 -
 -        /* new is a private copy, i could modify it */
 -        new->flags |= REF_FILTERED;
 +        if (c->in_keep_filtered)
 +          new->flags |= REF_FILTERED;
 +        else
 +          new = NULL;
        }
 -      else if (filter)
 -      {
 -        int fr = f_run(filter, &new, 0);
 -        if (fr > F_ACCEPT)
 -        {
 -          stats->imp_updates_filtered++;
 -          rte_trace_in(D_FILTERS, c, new, "filtered out");
 +    }
 +  else
 +    stats->withdraws_received++;
  
 -          if (! c->in_keep_filtered)
 -            goto drop;
 +  rte_import(&c->in_req, n, new, src);
  
 -          new->flags |= REF_FILTERED;
 -        }
 -      }
 -      if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
 -      new->attrs = rta_lookup(new->attrs);
 -      new->flags |= REF_COW;
 +  rte_update_unlock();
 +}
 +
 +void
 +rte_import(struct rt_import_request *req, const net_addr *n, rte *new, struct rte_src *src)
 +{
 +  struct rt_import_hook *hook = req->hook;
 +  if (!hook)
 +    return;
  
 +  net *nn;
 +  if (new)
 +    {
        /* Use the actual struct network, not the dummy one */
 -      nn = net_get(c->table, n);
 -      new->net = nn;
 +      nn = net_get(hook->table, n);
 +      new->net = nn->n.addr;
 +      new->sender = hook;
      }
 -  else
 +  else if (!(nn = net_find(hook->table, n)))
      {
 -      stats->imp_withdraws_received++;
 -
 -      if (!(nn = net_find(c->table, n)) || !src)
 -      {
 -        stats->imp_withdraws_ignored++;
 -        rte_update_unlock();
 -        return;
 -      }
 +      req->hook->stats.withdraws_ignored++;
 +      return;
      }
  
 - recalc:
    /* And recalculate the best route */
 -  rte_recalculate(c, nn, new, src);
 -
 -  rte_update_unlock();
 -  return;
 -
 - drop:
 -  rte_free(new);
 -  new = NULL;
 -  if (nn = net_find(c->table, n))
 -    goto recalc;
 -
 -  rte_update_unlock();
 +  rte_recalculate(hook, nn, new, src);
  }
  
  /* Independent call to rte_announce(), used from next hop
@@@ -1651,10 -1688,14 +1645,10 @@@ rt_examine(rtable *t, net_addr *a, stru
    rte_update_lock();
  
    /* Rest is stripped down export_filter() */
 -  int v = p->preexport ? p->preexport(p, rt) : 0;
 +  int v = c->proto->preexport ? c->proto->preexport(c, &rt) : 0;
    if (v == RIC_PROCESS)
-     v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
+     v = (f_run(filter, &rt, FF_SILENT) <= F_ACCEPT);
  
 -  /* Discard temporary rte */
 -  if (rt != n->routes)
 -    rte_free(rt);
 -
    rte_update_unlock();
  
    return v > 0;
diff --cc proto/mrt/mrt.c
index 7bcf28ba47b37662d7dcd7a267d6fc82544ddb28,c595f2987e36cedfd1694024503d5fffb5aeab48..6a1869993c35478535697bd5791a4b8f9c52343c
@@@ -524,9 -525,11 +524,9 @@@ mrt_rib_table_dump(struct mrt_table_dum
        continue;
      }
  
 -    if (f_run(s->filter, &rt, 0) <= F_ACCEPT)
 -      mrt_rib_table_entry(s, rt);
 -
 -    if (rt != rt0)
 -      rte_free(rt);
 +    rte e = rt->rte;
-     if (f_run(s->filter, &e, s->linpool, 0) <= F_ACCEPT)
++    if (f_run(s->filter, &e, 0) <= F_ACCEPT)
 +      mrt_rib_table_entry(s, &e);
  
      lp_flush(s->linpool);
    }
index fe0c77bc6bc0f41c531ea5b075be2a48dc067d20,42febcd42e736d78480b879472d4d8d0ed21e5f2..87d795eeb068dc6a254812728bc633cffbfa17ed
@@@ -103,18 -101,25 +101,14 @@@ static_announce_rte(struct static_prot
      return;
  
    /* We skip rta_lookup() here */
 -  rte *e = rte_get_temp(a, src);
 -  e->pflags = 0;
 +  rte e0 = { .attrs = a, .src = src, .net = r->net, }, *e = &e0;
  
 +  /* Evaluate the filter */
    if (r->cmds)
-     f_eval_rte(r->cmds, e, static_lp);
 -  {
 -    /* Create a temporary table node */
 -    e->net = alloca(sizeof(net) + r->net->length);
 -    memset(e->net, 0, sizeof(net) + r->net->length);
 -    net_copy(e->net->n.addr, r->net);
 -
 -    /* Evaluate the filter */
 -    f_eval_rte(r->cmds, &e);
 -
 -    /* Remove the temporary node */
 -    e->net = NULL;
 -  }
++    f_eval_rte(r->cmds, e);
  
 -  rte_update2(p->p.main_channel, r->net, e, src);
 +  rte_update(p->p.main_channel, r->net, e, src);
    r->state = SRS_CLEAN;
-   if (r->cmds)
-     lp_flush(static_lp);
    return;
  
  withdraw:
Simple merge