Commit bf2abe2f authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Merge branch 'soon'

Conflicts:

	nest/proto.c
	nest/rt-table.c
parents fb829de6 c0adf7e9
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ void dump_attrs(rte *e)
 * @p: protocol instance
 *
 * The start() hook is called by the core when it wishes to start
 * the instance.
 * the instance. Multitable protocols should lock their tables here.
 *
 * Result: new protocol state
 */
@@ -109,6 +109,17 @@ int start(struct proto *p)
int shutdown(struct proto *p)
{ DUMMY; }

/**
 * cleanup - request instance cleanup
 * @p: protocol instance
 *
 * The cleanup() hook is called by the core when the protocol became
 * hungry/down, i.e. all protocol ahooks and routes are flushed.
 * Multitable protocols should unlock their tables here.
 */
void cleanup(struct proto *p)
{ DUMMY; }

/**
 * get_status - get instance status
 * @p: protocol instance
+122 −89
Original line number Diff line number Diff line
@@ -112,8 +112,6 @@ proto_new(struct proto_config *c, unsigned size)
  p->disabled = c->disabled;
  p->proto = pr;
  p->table = c->table->table;
  p->in_filter = c->in_filter;
  p->out_filter = c->out_filter;
  p->hash_key = random_u32();
  c->proto = p;
  return p;
@@ -126,49 +124,102 @@ proto_init_instance(struct proto *p)
  p->pool = rp_new(proto_pool, p->proto->name);
  p->attn = ev_new(p->pool);
  p->attn->data = p;

  if (! p->proto->multitable)
    rt_lock_table(p->table);
}

extern pool *rt_table_pool;
/**
 * proto_add_announce_hook - connect protocol to a routing table
 * @p: protocol instance
 * @t: routing table to connect to
 * @in: input filter
 * @out: output filter
 * @stats: per-table protocol statistics
 *
 * This function creates a connection between the protocol instance @p
 * and the routing table @t, making the protocol hear all changes in
 * the table.
 *
 * The announce hook is linked in the protocol ahook list and, if the
 * protocol accepts routes, also in the table ahook list. Announce
 * hooks are allocated from the routing table resource pool, they are
 * unlinked from the table ahook list after the protocol went down,
 * (in proto_schedule_flush()) and they are automatically freed after the
 * protocol is flushed (in proto_fell_down()).
 *
 * Unless you want to listen to multiple routing tables (as the Pipe
 * protocol does), you needn't to worry about this function since the
 * connection to the protocol's primary routing table is initialized
 * automatically by the core code.
 */
struct announce_hook *
proto_add_announce_hook(struct proto *p, struct rtable *t)
proto_add_announce_hook(struct proto *p, struct rtable *t, struct filter *in,
			struct filter *out, struct proto_stats *stats)
{
  struct announce_hook *h;

  if (!p->rt_notify)
    return NULL;
  DBG("Connecting protocol %s to table %s\n", p->name, t->name);
  PD(p, "Connected to table %s", t->name);
  h = mb_alloc(p->pool, sizeof(struct announce_hook));

  h = mb_allocz(rt_table_pool, sizeof(struct announce_hook));
  h->table = t;
  h->proto = p;
  h->in_filter = in;
  h->out_filter = out;
  h->stats = stats;

  h->next = p->ahooks;
  p->ahooks = h;

  if (p->rt_notify)
    add_tail(&t->hooks, &h->n);
  return h;
}

/**
 * proto_find_announce_hook - find announce hooks
 * @p: protocol instance
 * @t: routing table
 *
 * Returns pointer to announce hook or NULL
 */
struct announce_hook *
proto_find_announce_hook(struct proto *p, struct rtable *t)
{
  struct announce_hook *a;

  for (a = p->ahooks; a; a = a->next)
    if (a->table == t)
      return a;

  return NULL;
}

static void
proto_flush_hooks(struct proto *p)
proto_unlink_ahooks(struct proto *p)
{
  struct announce_hook *h;

  if (p->rt_notify)
    for(h=p->ahooks; h; h=h->next)
      rem_node(&h->n);
}

static void
proto_free_ahooks(struct proto *p)
{
  struct announce_hook *h, *hn;

  for(h = p->ahooks; h; h = hn)
  {
    hn = h->next;
    mb_free(h);
  }

  p->ahooks = NULL;
  p->main_ahook = NULL;
}

/**
@@ -322,6 +373,8 @@ proto_init(struct proto_config *c)
  return q;
}

int proto_reconfig_type;  /* Hack to propagate type info to pipe reconfigure hook */

static int
proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
{
@@ -336,23 +389,10 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config
      (proto_get_router_id(nc) != proto_get_router_id(oc)))
    return 0;

  int import_changed = (type != RECONFIG_SOFT) && ! filter_same(nc->in_filter, oc->in_filter);
  int export_changed = (type != RECONFIG_SOFT) && ! filter_same(nc->out_filter, oc->out_filter);

  /* We treat a change in preferences by reimporting routes */
  if (nc->preference != oc->preference)
    import_changed = 1;

  /* If the protocol in not UP, it has no routes and we can ignore such changes */
  if (p->proto_state != PS_UP)
    import_changed = export_changed = 0;

  /* Without this hook we cannot reload routes and have to restart the protocol */
  if (import_changed && ! p->reload_routes)
    return 0;

  p->debug = nc->debug;
  p->mrtdump = nc->mrtdump;
  proto_reconfig_type = type;

  /* Execute protocol specific reconfigure hook */
  if (! (p->proto->reconfigure && p->proto->reconfigure(p, nc)))
@@ -362,14 +402,37 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config
  PD(p, "Reconfigured");
  p->cf = nc;
  p->name = nc->name;
  p->in_filter = nc->in_filter;
  p->out_filter = nc->out_filter;
  p->preference = nc->preference;


  /* Multitable protocols handle rest in their reconfigure hooks */
  if (p->proto->multitable)
    return 1;

  /* Update filters in the main announce hook */
  if (p->main_ahook)
    {
      p->main_ahook->in_filter = nc->in_filter;
      p->main_ahook->out_filter = nc->out_filter;
    }

  /* Update routes when filters changed. If the protocol in not UP,
     it has no routes and we can ignore such changes */
  if ((p->proto_state != PS_UP) || (type == RECONFIG_SOFT))
    return 1;

  int import_changed = ! filter_same(nc->in_filter, oc->in_filter);
  int export_changed = ! filter_same(nc->out_filter, oc->out_filter);

  /* We treat a change in preferences by reimporting routes */
  if (nc->preference != oc->preference)
    import_changed = 1;

  if (import_changed || export_changed)
    log(L_INFO "Reloading protocol %s", p->name);

  if (import_changed && ! p->reload_routes(p))
  /* If import filter changed, call reload hook */
  if (import_changed && ! (p->reload_routes && p->reload_routes(p)))
    {
      /* Now, the protocol is reconfigured. But route reload failed
	 and we have to do regular protocol restart. */
@@ -553,6 +616,7 @@ void
protos_dump_all(void)
{
  struct proto *p;
  struct announce_hook *a;

  debug("Protocols:\n");

@@ -560,10 +624,14 @@ protos_dump_all(void)
    {
      debug("  protocol %s state %s/%s\n", p->name,
	    p_states[p->proto_state], c_states[p->core_state]);
      if (p->in_filter)
	debug("\tInput filter: %s\n", filter_name(p->in_filter));
      if (p->out_filter != FILTER_REJECT)
	debug("\tOutput filter: %s\n", filter_name(p->out_filter));
      for (a = p->ahooks; a; a = a->next)
	{
	  debug("\tTABLE %s\n", a->table->name);
	  if (a->in_filter)
	    debug("\tInput filter: %s\n", filter_name(a->in_filter));
	  if (a->out_filter != FILTER_REJECT)
	    debug("\tOutput filter: %s\n", filter_name(a->out_filter));
	}
      if (p->disabled)
	debug("\tDISABLED\n");
      else if (p->proto->dump)
@@ -647,6 +715,9 @@ proto_fell_down(struct proto *p)
    log(L_ERR "Protocol %s is down but still has %d routes", p->name, p->stats.imp_routes);

  bzero(&p->stats, sizeof(struct proto_stats));
  proto_free_ahooks(p);

  if (! p->proto->multitable)
    rt_unlock_table(p->table);

  if (p->proto->cleanup)
@@ -686,7 +757,7 @@ proto_feed_initial(void *P)
    return;

  DBG("Feeding protocol %s\n", p->name);
  proto_add_announce_hook(p, p->table);

  if_feed_baby(p);
  proto_feed_more(P);
}
@@ -702,6 +773,11 @@ proto_schedule_feed(struct proto *p, int initial)
  if (!initial)
    p->stats.exp_routes = 0;

  /* Connect protocol to routing table */
  if (initial && !p->proto->multitable)
    p->main_ahook = proto_add_announce_hook(p, p->table,
      p->cf->in_filter, p->cf->out_filter, &p->stats);

  proto_relink(p);
  p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
  ev_schedule(p->attn);
@@ -780,12 +856,11 @@ proto_schedule_flush(struct proto *p)
  DBG("%s: Scheduling flush\n", p->name);
  p->core_state = FS_FLUSHING;
  proto_relink(p);
  proto_flush_hooks(p);
  proto_unlink_ahooks(p);
  proto_schedule_flush_loop();
}



/**
 * proto_request_feeding - request feeding routes to the protocol
 * @p: given protocol 
@@ -899,9 +974,8 @@ proto_state_name(struct proto *p)
}

static void
proto_do_show_stats(struct proto *p)
proto_show_stats(struct proto_stats *s)
{
  struct proto_stats *s = &p->stats;
  cli_msg(-1006, "  Routes:         %u imported, %u exported, %u preferred", 
	  s->imp_routes, s->exp_routes, s->pref_routes);
  cli_msg(-1006, "  Route change stats:     received   rejected   filtered    ignored   accepted");
@@ -919,47 +993,17 @@ proto_do_show_stats(struct proto *p)
	  s->exp_withdraws_received, s->exp_withdraws_accepted);
}

#ifdef CONFIG_PIPE
static void
proto_do_show_pipe_stats(struct proto *p)
void
proto_show_basic_info(struct proto *p)
{
  struct proto_stats *s1 = &p->stats;
  struct proto_stats *s2 = pipe_get_peer_stats(p);

  /*
   * Pipe stats (as anything related to pipes) are a bit tricky. There
   * are two sets of stats - s1 for routes going from the primary
   * routing table to the secondary routing table ('exported' from the
   * user point of view) and s2 for routes going in the other
   * direction ('imported' from the user point of view).
   *
   * Each route going through a pipe is, technically, first exported
   * to the pipe and then imported from that pipe and such operations
   * are counted in one set of stats according to the direction of the
   * route propagation. Filtering is done just in the first part
   * (export). Therefore, we compose stats for one directon for one
   * user direction from both import and export stats, skipping
   * immediate and irrelevant steps (exp_updates_accepted,
   * imp_updates_received, imp_updates_filtered, ...)
   */
  // cli_msg(-1006, "  Table:          %s", p->table->name);
  cli_msg(-1006, "  Preference:     %d", p->preference);
  cli_msg(-1006, "  Input filter:   %s", filter_name(p->cf->in_filter));
  cli_msg(-1006, "  Output filter:  %s", filter_name(p->cf->out_filter));

  cli_msg(-1006, "  Routes:         %u imported, %u exported", 
	  s2->imp_routes, s1->imp_routes);
  cli_msg(-1006, "  Route change stats:     received   rejected   filtered    ignored   accepted");
  cli_msg(-1006, "    Import updates:     %10u %10u %10u %10u %10u",
	  s2->exp_updates_received, s2->exp_updates_rejected + s2->imp_updates_invalid,
	  s2->exp_updates_filtered, s2->imp_updates_ignored, s2->imp_updates_accepted);
  cli_msg(-1006, "    Import withdraws:   %10u %10u        --- %10u %10u",
	  s2->exp_withdraws_received, s2->imp_withdraws_invalid,
	  s2->imp_withdraws_ignored, s2->imp_withdraws_accepted);
  cli_msg(-1006, "    Export updates:     %10u %10u %10u %10u %10u",
	  s1->exp_updates_received, s1->exp_updates_rejected + s1->imp_updates_invalid,
	  s1->exp_updates_filtered, s1->imp_updates_ignored, s1->imp_updates_accepted);
  cli_msg(-1006, "    Export withdraws:   %10u %10u        --- %10u %10u",
	  s1->exp_withdraws_received, s1->imp_withdraws_invalid,
	  s1->imp_withdraws_ignored, s1->imp_withdraws_accepted);
  if (p->proto_state != PS_DOWN)
    proto_show_stats(&p->stats);
}
#endif

void
proto_cmd_show(struct proto *p, unsigned int verbose, int cnt)
@@ -987,22 +1031,11 @@ proto_cmd_show(struct proto *p, unsigned int verbose, int cnt)
	cli_msg(-1006, "  Description:    %s", p->cf->dsc);
      if (p->cf->router_id)
	cli_msg(-1006, "  Router ID:      %R", p->cf->router_id);
      cli_msg(-1006, "  Preference:     %d", p->preference);
      cli_msg(-1006, "  Input filter:   %s", filter_name(p->in_filter));
      cli_msg(-1006, "  Output filter:  %s", filter_name(p->out_filter));

      if (p->proto_state != PS_DOWN)
	{
#ifdef CONFIG_PIPE
	  if (proto_is_pipe(p))
	    proto_do_show_pipe_stats(p);
	  else
#endif
	    proto_do_show_stats(p);
	}

      if (p->proto->show_proto_info)
	p->proto->show_proto_info(p);
      else
	proto_show_basic_info(p);

      cli_msg(-1006, "");
    }
+10 −12
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ struct protocol {
  char *template;			/* Template for automatic generation of names */
  int name_counter;			/* Counter for automatic name generation */
  int attr_class;			/* Attribute class known to this protocol */
  int multitable;			/* Protocol handles all announce hooks itself */
  unsigned preference;			/* Default protocol preference */

  void (*preconfig)(struct protocol *, struct config *);	/* Just before configuring */
@@ -194,8 +195,7 @@ struct proto {
  void (*rte_remove)(struct network *, struct rte *);

  struct rtable *table;			/* Our primary routing table */
  struct filter *in_filter;		/* Input filter */
  struct filter *out_filter;		/* Output filter */
  struct announce_hook *main_ahook;	/* Primary announcement hook */
  struct announce_hook *ahooks;		/* Announcement hooks for this protocol */

  struct fib_iterator *feed_iterator;	/* Routing table iterator used during protocol feeding */
@@ -219,6 +219,9 @@ static inline void
proto_copy_rest(struct proto_config *dest, struct proto_config *src, unsigned size)
{ memcpy(dest + 1, src + 1, size - sizeof(struct proto_config)); }


void proto_show_basic_info(struct proto *p);

void proto_cmd_show(struct proto *, unsigned int, int);
void proto_cmd_disable(struct proto *, unsigned int, int);
void proto_cmd_enable(struct proto *, unsigned int, int);
@@ -353,18 +356,13 @@ struct announce_hook {
  node n;
  struct rtable *table;
  struct proto *proto;
  struct filter *in_filter;		/* Input filter */
  struct filter *out_filter;		/* Output filter */
  struct proto_stats *stats;		/* Per-table protocol statistics */
  struct announce_hook *next;		/* Next hook for the same protocol */
};

struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);

/*
 *	Some pipe-specific nest hacks
 */

#ifdef CONFIG_PIPE
#include "proto/pipe/pipe.h"
#endif

struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *, struct filter *, struct filter *, struct proto_stats *);
struct announce_hook *proto_find_announce_hook(struct proto *p, struct rtable *t);

#endif
+4 −2
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include "lib/lists.h"
#include "lib/resource.h"
#include "lib/timer.h"
#include "nest/protocol.h"

struct protocol;
struct proto;
@@ -181,7 +182,7 @@ struct hostentry {
typedef struct rte {
  struct rte *next;
  net *net;				/* Network this RTE belongs to */
  struct proto *sender;			/* Protocol instance that sent the route to the routing table */
  struct announce_hook *sender;		/* Announce hook used to send the route to the routing table */
  struct rta *attrs;			/* Attributes of this route */
  byte flags;				/* Flags (REF_...) */
  byte pflags;				/* Protocol-specific flags */
@@ -236,7 +237,8 @@ static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (n
static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
rte *rte_find(net *net, struct proto *p);
rte *rte_get_temp(struct rta *);
void rte_update(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new);
void rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src);
static inline void rte_update(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new) { rte_update2(p->main_ahook, net, new, src); }
void rte_discard(rtable *tab, rte *old);
void rte_dump(rte *);
void rte_free(rte *);
+31 −51
Original line number Diff line number Diff line
@@ -183,24 +183,16 @@ rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
}

static inline void
do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
do_rte_announce(struct announce_hook *ah, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
{
  struct proto *p = a->proto;
  struct filter *filter = p->out_filter;
  struct proto_stats *stats = &p->stats;
  struct proto *p = ah->proto;
  struct filter *filter = ah->out_filter;
  struct proto_stats *stats = ah->stats;

  rte *new0 = new;
  rte *old0 = old;
  int ok;

#ifdef CONFIG_PIPE
  /* The secondary direction of the pipe */
  if (proto_is_pipe(p) && (p->table != a->table))
    {
      filter = p->in_filter;
      stats = pipe_get_peer_stats(p);
    }
#endif

  if (new)
    {
      stats->exp_updates_received++;
@@ -293,18 +285,18 @@ do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rt
	rte_trace_out(D_ROUTES, p, old, "removed");
    }
  if (!new)
    p->rt_notify(p, a->table, net, NULL, old, NULL);
    p->rt_notify(p, ah->table, net, NULL, old, NULL);
  else if (tmpa)
    {
      ea_list *t = tmpa;
      while (t->next)
	t = t->next;
      t->next = new->attrs->eattrs;
      p->rt_notify(p, a->table, net, new, old, tmpa);
      p->rt_notify(p, ah->table, net, new, old, tmpa);
      t->next = NULL;
    }
  else
    p->rt_notify(p, a->table, net, new, old, new->attrs->eattrs);
    p->rt_notify(p, ah->table, net, new, old, new->attrs->eattrs);
  if (new && new != new0)	/* Discard temporary rte's */
    rte_free(new);
  if (old && old != old0)
@@ -374,7 +366,7 @@ rte_validate(rte *e)
  if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
    {
      log(L_WARN "Ignoring bogus prefix %I/%d received via %s",
	  n->n.prefix, n->n.pxlen, e->sender->name);
	  n->n.prefix, n->n.pxlen, e->sender->proto->name);
      return 0;
    }

@@ -382,7 +374,7 @@ rte_validate(rte *e)
  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
    {
      log(L_WARN "Ignoring bogus route %I/%d received via %s",
	  n->n.prefix, n->n.pxlen, e->sender->name);
	  n->n.prefix, n->n.pxlen, e->sender->proto->name);
      return 0;
    }

@@ -422,18 +414,15 @@ rte_same(rte *x, rte *y)
}

static void
rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte *new, ea_list *tmpa)
rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct proto *src)
{
  struct proto_stats *stats = &p->stats;
  struct proto *p = ah->proto;
  struct rtable *table = ah->table;
  struct proto_stats *stats = ah->stats;
  rte *old_best = net->routes;
  rte *old = NULL;
  rte **k, *r, *s;

#ifdef CONFIG_PIPE
  if (proto_is_pipe(p) && (p->table == table))
    stats = pipe_get_peer_stats(p);
#endif

  k = &net->routes;			/* Find and remove original route from the same protocol */
  while (old = *k)
    {
@@ -448,7 +437,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
	   * ignore it completely (there might be 'spurious withdraws',
	   * see FIXME in do_rte_announce())
	   */
	  if (old->sender != p)
	  if (old->sender->proto != p)
	    {
	      if (new)
		{
@@ -612,6 +601,7 @@ rte_update_unlock(void)
/**
 * rte_update - enter a new update to a routing table
 * @table: table to be updated
 * @ah: pointer to table announce hook
 * @net: network node
 * @p: protocol submitting the update
 * @src: protocol originating the update
@@ -651,28 +641,17 @@ rte_update_unlock(void)
 */

void
rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new)
rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src)
{
  struct proto *p = ah->proto;
  struct proto_stats *stats = ah->stats;
  struct filter *filter = ah->in_filter;
  ea_list *tmpa = NULL;
  struct proto_stats *stats = &p->stats;

#ifdef CONFIG_PIPE
  if (proto_is_pipe(p) && (p->table == table))
    stats = pipe_get_peer_stats(p);
#endif

  rte_update_lock();
  if (new)
    {
      new->sender = p;
      struct filter *filter = p->in_filter;

      /* Do not filter routes going through the pipe, 
	 they are filtered in the export filter only. */
#ifdef CONFIG_PIPE
      if (proto_is_pipe(p))
	filter = FILTER_ACCEPT;
#endif
      new->sender = ah;

      stats->imp_updates_received++;
      if (!rte_validate(new))
@@ -709,13 +688,13 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
  else
    stats->imp_withdraws_received++;

  rte_recalculate(table, net, p, src, new, tmpa);
  rte_recalculate(ah, net, new, tmpa, src);
  rte_update_unlock();
  return;

drop:
  rte_free(new);
  rte_recalculate(table, net, p, src, NULL, NULL);
  rte_recalculate(ah, net, NULL, NULL, src);
  rte_update_unlock();
}

@@ -738,7 +717,7 @@ void
rte_discard(rtable *t, rte *old)	/* Non-filtered route deletion, used during garbage collection */
{
  rte_update_lock();
  rte_recalculate(t, old->net, old->sender, old->attrs->proto, NULL, NULL);
  rte_recalculate(old->sender, old->net, NULL, NULL, old->attrs->proto);
  rte_update_unlock();
}

@@ -955,8 +934,8 @@ again:

    rescan:
      for (e=n->routes; e; e=e->next)
	if (e->sender->core_state != FS_HAPPY &&
	    e->sender->core_state != FS_FEEDING)
	if (e->sender->proto->core_state != FS_HAPPY &&
	    e->sender->proto->core_state != FS_FEEDING)
	  {
	    if (*max_feed <= 0)
	      {
@@ -1083,7 +1062,7 @@ rt_next_hop_update_net(rtable *tab, net *n)
	*k = new;

	rte_announce_i(tab, RA_ANY, n, new, e);
	rte_trace_in(D_ROUTES, new->sender, new, "updated");
	rte_trace_in(D_ROUTES, new->sender->proto, new, "updated");

	/* Call a pre-comparison hook */
	/* Not really an efficient way to compute this */
@@ -1123,7 +1102,7 @@ rt_next_hop_update_net(rtable *tab, net *n)
  if (new != old_best)
    {
      rte_announce_i(tab, RA_OPTIMAL, n, new, old_best);
      rte_trace_in(D_ROUTES, new->sender, new, "updated [best]");
      rte_trace_in(D_ROUTES, new->sender->proto, new, "updated [best]");
    }

   if (free_old_best)
@@ -1750,6 +1729,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
  rte *e, *ee;
  byte ia[STD_ADDRESS_P_LENGTH+8];
  struct announce_hook *a;
  int ok;

  bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
@@ -1779,8 +1759,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
		 'configure soft' command may change the export filter
		 and do not update routes */

	      if ((p1->out_filter == FILTER_REJECT) ||
		  (p1->out_filter && f_run(p1->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
	      if ((a = proto_find_announce_hook(p1, d->table)) && ((a->out_filter == FILTER_REJECT) ||
		  (a->out_filter && f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)))
		ok = 0;
	    }
	}
Loading