Commit 621782ec authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Merge commit 'c865cae3' into integrated

Conflicts:

	nest/rt-table.c
parents 121fd43d c865cae3
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -505,7 +505,6 @@ r_args:
     if ($$->export_mode) cf_error("Protocol specified twice");
     if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
     $$->export_mode = $2;
     $$->primary_only = 1;
     $$->export_protocol = c->proto;
     $$->running_on_config = c->proto->cf->global;
   }
+26 −21
Original line number Diff line number Diff line
@@ -403,7 +403,6 @@ int proto_reconfig_type; /* Hack to propagate type info to pipe reconfigure hoo
static int
proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
{
  struct announce_hook *ah = p->main_ahook;
  /* If the protocol is DOWN, we just restart it */
  if (p->proto_state == PS_DOWN)
    return 0;
@@ -435,31 +434,16 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config

  /* Update filters and limits in the main announce hook
     Note that this also resets limit state */
  if (ah)
  if (p->main_ahook)
    {  
      struct announce_hook *ah = p->main_ahook;
      ah->in_filter = nc->in_filter;
      ah->out_filter = nc->out_filter;
      ah->rx_limit = nc->rx_limit;
      ah->in_limit = nc->in_limit;
      ah->out_limit = nc->out_limit;
      ah->in_keep_filtered = nc->in_keep_filtered;

      if (p->proto_state == PS_UP)	/* Recheck export/import/receive limit */
        {
          struct proto_stats *stats = ah->stats;
          struct proto_limit *l = ah->in_limit;
          u32 all_routes = stats->imp_routes + stats->filt_routes;

          if (l && (stats->imp_routes >= l->limit)) proto_notify_limit(ah, l, PLD_IN, stats->imp_routes);

          l = ah->rx_limit;

          if (l && ( all_routes >= l->limit)) proto_notify_limit(ah, l, PLD_RX, all_routes );

          l = ah->out_limit;

          if (l && ( stats->exp_routes >= l->limit)) proto_notify_limit(ah, l, PLD_OUT, stats->exp_routes);
        }
      proto_verify_limits(ah);
    }

  /* Update routes when filters changed. If the protocol in not UP,
@@ -1199,11 +1183,32 @@ proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, int dir, u32
    case PLA_RESTART:
    case PLA_DISABLE:
      l->state = PLS_BLOCKED;
      if (p->proto_state == PS_UP)
	proto_schedule_down(p, l->action == PLA_RESTART, dir_down[dir]);
      break;
    }
}

void
proto_verify_limits(struct announce_hook *ah)
{
  struct proto_limit *l;
  struct proto_stats *stats = ah->stats;
  u32 all_routes = stats->imp_routes + stats->filt_routes;

  l = ah->rx_limit;
  if (l && (all_routes > l->limit))
    proto_notify_limit(ah, l, PLD_RX, all_routes);

  l = ah->in_limit;
  if (l && (stats->imp_routes > l->limit))
    proto_notify_limit(ah, l, PLD_IN, stats->imp_routes);

  l = ah->out_limit;
  if (l && (stats->exp_routes > l->limit))
    proto_notify_limit(ah, l, PLD_OUT, stats->exp_routes);
}


static void
proto_want_core_up(struct proto *p)
+1 −0
Original line number Diff line number Diff line
@@ -424,6 +424,7 @@ struct proto_limit {
};

void proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, int dir, u32 rt_count);
void proto_verify_limits(struct announce_hook *ah);

static inline void
proto_reset_limit(struct proto_limit *l)
+62 −35
Original line number Diff line number Diff line
@@ -2326,60 +2326,83 @@ static void
rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
  rte *e, *ee;
  byte prefix[MAX_ADDRESS_P_LENGTH];
  struct announce_hook *a;
  int ok;
  byte prefix[MAX_ADDRESS_P_LENGTH+8];
  struct ea_list *tmpa;
  struct announce_hook *a = NULL;
  int first = 1;
  int pass = 0;

  fn_print(prefix, sizeof(prefix), &n->n);

  if (d->export_mode)
    {
      a = proto_find_announce_hook(d->export_protocol, d->table);
      if (!a)
	return;
    }

  for (e = n->routes; e; e = e->next)
    {
      if (rte_is_filtered(e) != d->filtered)
	continue;

      struct ea_list *tmpa;
      struct rte_src *src = e->attrs->src;
      struct proto *p1 = d->export_protocol;
      struct proto *p2 = d->show_protocol;

      if (prefix[0])
	d->net_counter++;
      d->rt_counter++;
      d->net_counter += first;
      first = 0;

      if (pass)
	continue;

      ee = e;
      rte_update_lock();		/* We use the update buffer for filtering */
      tmpa = make_tmp_attrs(e, rte_update_pool);
      ok = f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT;
      if (p2 && p2 != src->proto) ok = 0;
      if (ok && d->export_mode)

      if (d->export_mode)
	{
	  int ic;
	  if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
	    ok = 0;
	  else if (!ic && d->export_mode > 1)
	  struct proto *ep = d->export_protocol;
	  int ic = ep->import_control ? ep->import_control(ep, &e, &tmpa, rte_update_pool) : 0;

	  if (ep->accept_ra_types == RA_OPTIMAL)
	    pass = 1;

	  if (ic < 0)
	    goto skip;

	  if (d->export_mode > 1)
	    {
	      /* FIXME - this shows what should be exported according
		 to current filters, but not what was really exported.
		 'configure soft' command may change the export filter
		 and do not update routes */
	      /*
	       * FIXME - This shows what should be exported according to current
	       * filters, but not what was really exported. 'configure soft'
	       * command may change the export filter and do not update routes.
	       */

	      if (!ic && (f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
		goto skip;

	      if ((a = proto_find_announce_hook(p1, d->table)) && 
		  (f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
		ok = 0;
	      if (ep->accept_ra_types == RA_ACCEPTED)
		pass = 1;
	    }
	}
      if (ok)
	{

      if (d->show_protocol && (d->show_protocol != e->attrs->src->proto))
	goto skip;

      if (f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
	goto skip;

      d->show_counter++;
      if (d->stats < 2)
	rt_show_rte(c, prefix, e, d, tmpa);
      prefix[0] = '\0';
	}

    skip:
      if (e != ee)
      {
	rte_free(e);
	e = ee;
      }
      rte_update_unlock();

      if (d->primary_only)
	break;
    }
@@ -2441,10 +2464,14 @@ rt_show(struct rt_show_data *d)
  net *n;

  /* Default is either a master table or a table related to a respective protocol */
  if ((!d->table) && d->export_protocol) d->table = d->export_protocol->table;
  if ((!d->table) && d->show_protocol) d->table = d->show_protocol->table;
  if (!d->table && d->export_protocol) d->table = d->export_protocol->table;
  if (!d->table && d->show_protocol) d->table = d->show_protocol->table;
  if (!d->table) d->table = config->master_rtc->table;

  /* Filtered routes are neither exported nor have sensible ordering */
  if (d->filtered && (d->export_mode || d->primary_only))
    cli_msg(0, "");

  if (d->pxlen == 256)
    {
      FIB_ITERATE_INIT(&d->fit, &d->table->fib);
+2 −0
Original line number Diff line number Diff line
@@ -235,12 +235,14 @@ pipe_reconfigure(struct proto *P, struct proto_config *new)
    {
      P->main_ahook->out_filter = new->out_filter;
      P->main_ahook->in_limit = new->in_limit;
      proto_verify_limits(P->main_ahook);
    }

  if (p->peer_ahook)
    {
      p->peer_ahook->out_filter = new->in_filter;
      p->peer_ahook->in_limit = new->out_limit;
      proto_verify_limits(p->peer_ahook);
    }

  if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT))