Some fixes in route export limits.
This commit is contained in:
parent
d494df63ac
commit
ab758e4fb2
3 changed files with 43 additions and 12 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue