0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-08 12:18:42 +00:00

Some fixes in route export limits.

This commit is contained in:
Ondrej Zajicek 2012-04-28 12:59:40 +02:00
parent d494df63ac
commit ab758e4fb2
3 changed files with 43 additions and 12 deletions

View File

@ -443,7 +443,13 @@ to zero to disable it. An empty <cf><m/switch/</cf> is equivalent to <cf/on/
<tag>export limit <m/number/ [exceed warn | block | restart | disable]</tag> <tag>export limit <m/number/ [exceed warn | block | restart | disable]</tag>
Specify an export route limit, works similarly to Specify an export route limit, works similarly to
the <cf>import limit</cf> option, but for the routes exported the <cf>import limit</cf> option, but for the routes exported
to the protocol. Default: <cf/none/. to the protocol. This option is experimental, there are some
problems in details of its behavior -- the number of exported
routes can temporarily exceed the limit without triggering it
during protocol reload, exported routes counter ignores route
blocking and block action also blocks route updates of alread
accepted routes -- and these details will probably change in
the future. Default: <cf/none/.
<tag>description "<m/text/"</tag> This is an optional <tag>description "<m/text/"</tag> This is an optional
description of the protocol. It is displayed as a part of the description of the protocol. It is displayed as a part of the

View File

@ -387,7 +387,8 @@ struct proto_limit {
void proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count); 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) static inline void
proto_reset_limit(struct proto_limit *l)
{ {
if (l) if (l)
l->state = PLS_INITIAL; l->state = PLS_INITIAL;

View File

@ -269,27 +269,52 @@ do_rte_announce(struct announce_hook *ah, int type UNUSED, net *net, rte *new, r
} }
} }
/* FIXME - This is broken because of incorrect 'old' value (see above) */ /*
if (!new && !old) * Export route limits has several problems. Because exp_routes
return; * counter is reset before refeed, we don't really know whether
* limit is breached and whether the update is new or not Therefore
* the number of really exported routes may exceed the limit
* temporarily (routes exported before and new routes in refeed).
*
* Minor advantage is that if the limit is decreased and refeed is
* requested, the number of exported routes really decrease.
*
* Second problem is that with export limits, we don't know whether
* old was really exported (it might be blocked by limit). When a
* withdraw is exported, we announce it even when the previous
* update was blocked. This is not a big issue, but the same problem
* is in updating exp_routes counter. Therefore, to be consistent in
* increases and decreases of exp_routes, we count exported routes
* regardless of blocking by limits.
*
* Similar problem is in handling updates - when a new route is
* received and blocking is active, the route would be blocked, but
* when an update for the route will be received later, the update
* would be propagated (as old != NULL). Therefore, we have to block
* also non-new updates (contrary to import blocking).
*/
struct proto_limit *l = ah->out_limit; struct proto_limit *l = ah->out_limit;
if (l && new && (!old || refeed)) if (l && new)
{ {
if (stats->exp_routes >= l->limit) if ((!old || refeed) && (stats->exp_routes >= l->limit))
proto_notify_limit(ah, l, stats->exp_routes); proto_notify_limit(ah, l, stats->exp_routes);
if (l->state == PLS_BLOCKED) if (l->state == PLS_BLOCKED)
{ {
/* Exported route counter ignores whether the route was stats->exp_routes++; /* see note above */
blocked by limit, to be consistent when limits change */
stats->exp_routes++;
stats->exp_updates_rejected++; stats->exp_updates_rejected++;
rte_trace_out(D_FILTERS, p, new, "rejected [limit]"); rte_trace_out(D_FILTERS, p, new, "rejected [limit]");
goto done; if (new != new0)
rte_free(new);
new = NULL;
} }
} }
/* FIXME - This is broken because of incorrect 'old' value (see above) */
if (!new && !old)
return;
if (new) if (new)
stats->exp_updates_accepted++; stats->exp_updates_accepted++;
else else
@ -325,7 +350,6 @@ do_rte_announce(struct announce_hook *ah, int type UNUSED, net *net, rte *new, r
else else
p->rt_notify(p, ah->table, net, new, old, new->attrs->eattrs); p->rt_notify(p, ah->table, net, new, old, new->attrs->eattrs);
done:
if (new && new != new0) /* Discard temporary rte's */ if (new && new != new0) /* Discard temporary rte's */
rte_free(new); rte_free(new);
if (old && old != old0) if (old && old != old0)