Commit 7d0a31de authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Fixes in generalized import limits.

parent 334a0ed2
Loading
Loading
Loading
Loading
+24 −21
Original line number Diff line number Diff line
@@ -785,7 +785,9 @@ proto_schedule_feed(struct proto *p, int initial)
      p->main_ahook->in_filter = p->cf->in_filter;
      p->main_ahook->out_filter = p->cf->out_filter;
      p->main_ahook->in_limit = p->cf->in_limit;
      proto_reset_limit(p->main_ahook->in_limit);
      // p->main_ahook->out_limit = p->cf->out_limit;
      // proto_reset_limit(p->main_ahook->out_limit);
    }

  proto_relink(p);
@@ -953,43 +955,42 @@ proto_limit_name(struct proto_limit *l)
 * proto_notify_limit: notify about limit hit and take appropriate action
 * @ah: announce hook
 * @l: limit being hit
 * @rt_count: the number of routes 
 *
 * The function is called by the route processing core when limit @l
 * is breached. It activates the limit and tooks appropriate action
 * according to @l->action. It also says what should be done with the
 * route that breached the limit.
 *
 * Returns 1 if the route should be freed, 0 otherwise.
 * according to @l->action.
 */
int
proto_notify_limit(struct announce_hook *ah, struct proto_limit *l)
void
proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count)
{
  struct proto *p = ah->proto;
  int dir = (ah->in_limit == l);

  if (l->active)
    return (l->action != PLA_WARN);
  if (l->state == PLS_BLOCKED)
    return;

  l->active = 1;
  if (rt_count == l->limit)
    log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
	p->name, dir ? "import" : "export", l->limit, proto_limit_name(l));

  switch (l->action)
    {
    case PLA_WARN:
      return 0;
      l->state = PLS_ACTIVE;
      break;

    case PLA_BLOCK:
      return 1;
      l->state = PLS_BLOCKED;
      break;

    case PLA_RESTART:
    case PLA_DISABLE:
      l->state = PLS_BLOCKED;
      proto_schedule_down(p, l->action == PLA_RESTART,
			  dir ? PDC_IN_LIMIT_HIT : PDC_OUT_LIMIT_HIT);
      return 1;
      break;
    }

  return 0;
}

/**
@@ -1101,9 +1102,11 @@ proto_show_stats(struct proto_stats *s)
void
proto_show_limit(struct proto_limit *l, const char *dsc)
{
  if (l)
    cli_msg(-1006, "  %16s%d, action: %s%s", dsc, l->limit,
	    proto_limit_name(l), l->active ? " [HIT]" : "");
  if (!l)
    return;

  cli_msg(-1006, "  %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
  cli_msg(-1006, "    Action:       %s", proto_limit_name(l));
}

void
@@ -1233,8 +1236,8 @@ proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
       * Should be done before reload_routes() hook?
       * Perhaps, but these hooks work asynchronously.
       */
      if (!p->proto->multitable && p->main_ahook->in_limit)
	p->main_ahook->in_limit->active = 0;
      if (!p->proto->multitable)
	proto_reset_limit(p->main_ahook->in_limit);
    }

  /* re-exporting routes */
+13 −2
Original line number Diff line number Diff line
@@ -375,13 +375,24 @@ extern struct proto_config *cf_dev_proto;
#define PLA_RESTART	4	/* Force protocol restart */
#define PLA_DISABLE	5	/* Shutdown and disable protocol */

#define PLS_INITIAL	0	/* Initial limit state after protocol start */
#define PLS_ACTIVE	1	/* Limit was hit */
#define PLS_BLOCKED	2	/* Limit is active and blocking new routes */

struct proto_limit {
  u32 limit;			/* Maximum number of prefixes */
  byte action;			/* Action to take (PLA_*) */
  byte active;			/* Limit is active */
  byte state;			/* State of limit (PLS_*) */
};

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

static inline void proto_reset_limit(struct proto_limit *l)
{
  if (l)
    l->state = PLS_INITIAL;
}

 
/*
 *	Route Announcement Hook
+11 −5
Original line number Diff line number Diff line
@@ -485,13 +485,19 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
    }

  struct proto_limit *l = ah->in_limit;
  if (l && !old && new && (stats->imp_routes >= l->limit) && proto_notify_limit(ah, l))
  if (l && !old && new)
    {
      if (stats->imp_routes >= l->limit)
	proto_notify_limit(ah, l, stats->imp_routes);

      if (l->state == PLS_BLOCKED)
	{
	  stats->imp_updates_ignored++;
	  rte_trace_in(D_FILTERS, p, new, "ignored [limit]");
	  rte_free_quick(new);
	  return;
	}
    }

  if (new)
    stats->imp_updates_accepted++;
+2 −2
Original line number Diff line number Diff line
@@ -1165,9 +1165,9 @@ bgp_show_proto_info(struct proto *P)
	      p->rs_client ? " route-server" : "",
	      p->as4_session ? " AS4" : "");
      cli_msg(-1006, "    Source address:   %I", p->source_addr);
      if (p->cf->route_limit)
      if (P->cf->in_limit)
	cli_msg(-1006, "    Route limit:      %d/%d",
		p->p.stats.imp_routes, p->cf->route_limit);
		p->p.stats.imp_routes, P->cf->in_limit->limit);
      cli_msg(-1006, "    Hold timer:       %d/%d",
	      tm_remains(c->hold_timer), c->hold_time);
      cli_msg(-1006, "    Keepalive timer:  %d/%d",
+0 −1
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ struct bgp_config {
  int rr_client;			/* Whether neighbor is RR client of me */
  int rs_client;			/* Whether neighbor is RS client of me */
  int advertise_ipv4;			/* Whether we should add IPv4 capability advertisement to OPEN message */
  u32 route_limit;			/* Number of routes that may be imported, 0 means disable limit */
  int passive;				/* Do not initiate outgoing connection */
  int interpret_communities;		/* Hardwired handling of well-known communities */
  unsigned connect_retry_time;
Loading