Fixes in generalized import limits.

This commit is contained in:
Ondrej Zajicek 2012-04-21 21:05:36 +02:00
parent 334a0ed24d
commit 7d0a31deed
6 changed files with 54 additions and 35 deletions

View file

@ -785,7 +785,9 @@ proto_schedule_feed(struct proto *p, int initial)
p->main_ahook->in_filter = p->cf->in_filter; p->main_ahook->in_filter = p->cf->in_filter;
p->main_ahook->out_filter = p->cf->out_filter; p->main_ahook->out_filter = p->cf->out_filter;
p->main_ahook->in_limit = p->cf->in_limit; 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; // p->main_ahook->out_limit = p->cf->out_limit;
// proto_reset_limit(p->main_ahook->out_limit);
} }
proto_relink(p); 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 * proto_notify_limit: notify about limit hit and take appropriate action
* @ah: announce hook * @ah: announce hook
* @l: limit being hit * @l: limit being hit
* @rt_count: the number of routes
* *
* The function is called by the route processing core when limit @l * The function is called by the route processing core when limit @l
* is breached. It activates the limit and tooks appropriate action * is breached. It activates the limit and tooks appropriate action
* according to @l->action. It also says what should be done with the * according to @l->action.
* route that breached the limit.
*
* Returns 1 if the route should be freed, 0 otherwise.
*/ */
int void
proto_notify_limit(struct announce_hook *ah, struct proto_limit *l) proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count)
{ {
struct proto *p = ah->proto; struct proto *p = ah->proto;
int dir = (ah->in_limit == l); int dir = (ah->in_limit == l);
if (l->active) if (l->state == PLS_BLOCKED)
return (l->action != PLA_WARN); return;
l->active = 1; if (rt_count == l->limit)
log(L_WARN "Protocol %s hits route %s limit (%d), action: %s", log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
p->name, dir ? "import" : "export", l->limit, proto_limit_name(l)); p->name, dir ? "import" : "export", l->limit, proto_limit_name(l));
switch (l->action) switch (l->action)
{ {
case PLA_WARN: case PLA_WARN:
return 0; l->state = PLS_ACTIVE;
break;
case PLA_BLOCK: case PLA_BLOCK:
return 1; l->state = PLS_BLOCKED;
break;
case PLA_RESTART: case PLA_RESTART:
case PLA_DISABLE: case PLA_DISABLE:
l->state = PLS_BLOCKED;
proto_schedule_down(p, l->action == PLA_RESTART, proto_schedule_down(p, l->action == PLA_RESTART,
dir ? PDC_IN_LIMIT_HIT : PDC_OUT_LIMIT_HIT); 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 void
proto_show_limit(struct proto_limit *l, const char *dsc) proto_show_limit(struct proto_limit *l, const char *dsc)
{ {
if (l) if (!l)
cli_msg(-1006, " %16s%d, action: %s%s", dsc, l->limit, return;
proto_limit_name(l), l->active ? " [HIT]" : "");
cli_msg(-1006, " %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
cli_msg(-1006, " Action: %s", proto_limit_name(l));
} }
void void
@ -1233,8 +1236,8 @@ proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
* Should be done before reload_routes() hook? * Should be done before reload_routes() hook?
* Perhaps, but these hooks work asynchronously. * Perhaps, but these hooks work asynchronously.
*/ */
if (!p->proto->multitable && p->main_ahook->in_limit) if (!p->proto->multitable)
p->main_ahook->in_limit->active = 0; proto_reset_limit(p->main_ahook->in_limit);
} }
/* re-exporting routes */ /* re-exporting routes */

View file

@ -375,13 +375,24 @@ extern struct proto_config *cf_dev_proto;
#define PLA_RESTART 4 /* Force protocol restart */ #define PLA_RESTART 4 /* Force protocol restart */
#define PLA_DISABLE 5 /* Shutdown and disable protocol */ #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 { struct proto_limit {
u32 limit; /* Maximum number of prefixes */ u32 limit; /* Maximum number of prefixes */
byte action; /* Action to take (PLA_*) */ 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 * Route Announcement Hook

View file

@ -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; 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++; stats->imp_updates_ignored++;
rte_trace_in(D_FILTERS, p, new, "ignored [limit]"); rte_trace_in(D_FILTERS, p, new, "ignored [limit]");
rte_free_quick(new); rte_free_quick(new);
return; return;
} }
}
if (new) if (new)
stats->imp_updates_accepted++; stats->imp_updates_accepted++;

View file

@ -1165,9 +1165,9 @@ bgp_show_proto_info(struct proto *P)
p->rs_client ? " route-server" : "", p->rs_client ? " route-server" : "",
p->as4_session ? " AS4" : ""); p->as4_session ? " AS4" : "");
cli_msg(-1006, " Source address: %I", p->source_addr); 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", 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", cli_msg(-1006, " Hold timer: %d/%d",
tm_remains(c->hold_timer), c->hold_time); tm_remains(c->hold_timer), c->hold_time);
cli_msg(-1006, " Keepalive timer: %d/%d", cli_msg(-1006, " Keepalive timer: %d/%d",

View file

@ -40,7 +40,6 @@ struct bgp_config {
int rr_client; /* Whether neighbor is RR client of me */ int rr_client; /* Whether neighbor is RR client of me */
int rs_client; /* Whether neighbor is RS 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 */ 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 passive; /* Do not initiate outgoing connection */
int interpret_communities; /* Hardwired handling of well-known communities */ int interpret_communities; /* Hardwired handling of well-known communities */
unsigned connect_retry_time; unsigned connect_retry_time;

View file

@ -127,10 +127,8 @@ pipe_reload_routes(struct proto *P)
*/ */
proto_request_feeding(P); proto_request_feeding(P);
if (P->main_ahook->in_limit) proto_reset_limit(P->main_ahook->in_limit);
P->main_ahook->in_limit->active = 0; proto_reset_limit(p->peer_ahook->in_limit);
if (p->peer_ahook->in_limit)
p->peer_ahook->in_limit->active = 0;
return 1; return 1;
} }
@ -168,10 +166,12 @@ pipe_start(struct proto *P)
P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats); P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats);
P->main_ahook->out_filter = cf->c.out_filter; P->main_ahook->out_filter = cf->c.out_filter;
P->main_ahook->in_limit = cf->c.in_limit; P->main_ahook->in_limit = cf->c.in_limit;
proto_reset_limit(P->main_ahook->in_limit);
p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats); p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats);
p->peer_ahook->out_filter = cf->c.in_filter; p->peer_ahook->out_filter = cf->c.in_filter;
p->peer_ahook->in_limit = cf->out_limit; p->peer_ahook->in_limit = cf->out_limit;
proto_reset_limit(p->peer_ahook->in_limit);
return PS_UP; return PS_UP;
} }