0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-09-19 11:55:21 +00:00

Created a dedicated settle timer structure

This commit is contained in:
Maria Matejka 2022-09-09 15:04:36 +02:00
parent 31e881bcbd
commit 974f16b1f7
6 changed files with 110 additions and 47 deletions

View File

@ -14,6 +14,7 @@ CF_HDR
#include "conf/conf.h"
#include "lib/resource.h"
#include "lib/socket.h"
#include "lib/settle.h"
#include "lib/timer.h"
#include "lib/string.h"
#include "nest/protocol.h"
@ -93,6 +94,7 @@ CF_DECLS
struct proto_spec ps;
struct channel_limit cl;
struct timeformat *tf;
struct settle_config settle;
struct adata *ad;
struct bytestring *bs;
}
@ -111,6 +113,7 @@ CF_DECLS
%type <i> expr bool pxlen4
%type <time> expr_us time
%type <settle> settle
%type <a> ipa
%type <net> net_ip4_ net_ip4 net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
@ -386,6 +389,13 @@ time:
}
;
/* Settle timer configuration */
settle: expr_us expr_us {
if ($1 > $2) cf_error("Minimum settle time %t is bigger than maximum settle time %t", $1, $2);
$$.min = $1;
$$.max = $2;
};
text:
TEXT
| CF_SYM_KNOWN {

View File

@ -965,14 +965,15 @@ inherited from templates can be updated by new definitions.
<ref id="bgp-export-table" name="export table"> (for respective
direction). Default: on.
<tag><label id="rtable-min-settle-time">min settle time <m/time/</tag>
Minimum settle time is a delay from the last ROA table change to wait
for more updates before triggering automatic reload. Default: 1 s.
<tag><label id="rtable-min-settle-time">min settle time <m/time/</tag>
Maximum settle time is an upper limit to the settle time from the
initial ROA table change even if there are consecutive updates gradually
renewing the settle time. Default: 20 s.
<tag><label id="rtable-min-settle-time">roa settle time <m/time/ <m/time/</tag>
Minimum and maximum settle times, respectively, for ROA table changes.
The automatic reload is triggered after the minimum time after the last
ROA table change has been received but not later than the maximum time after
first unprocessed ROA table change. Therefore with default values, the
automatic reload happens 1 second after the ROA table stops updating, yet if it
were to be later than 20 seconds after the ROA table starts updating,
the automatic reload is triggered anyway. Default values: <cf/1 s 20 s/.
You have to always provide both values.
<tag><label id="proto-import-limit">import limit [<m/number/ | off ] [action warn | block | restart | disable]</tag>
Specify an import route limit (a maximum number of routes imported from

64
lib/settle.h Normal file
View File

@ -0,0 +1,64 @@
/*
* BIRD -- Settle timer
*
* (c) 2022 Maria Matejka <mq@jmq.cz>
* (c) 2022 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_SETTLE_H_
#define _BIRD_SETTLE_H_
#include "lib/birdlib.h"
#include "lib/timer.h"
struct settle_config {
btime min, max;
};
struct settle {
union {
/* Timer hook polymorphism. */
struct {
resource _r;
void (*hook)(struct settle *);
};
timer tm;
};
struct settle_config cf;
btime started;
};
STATIC_ASSERT(OFFSETOF(struct settle, hook) == OFFSETOF(struct settle, tm) + OFFSETOF(timer, hook));
#define SETTLE_INIT(_cfp, _hook, _data) (struct settle) { .tm = { .data = (_data), }, .hook = (_hook), .cf = ({ASSERT_DIE((_cfp)->min <= (_cfp)->max); *(_cfp); }), }
static inline void settle_init(struct settle *s, struct settle_config *cf, void (*hook)(struct settle *), void *data)
{
*s = SETTLE_INIT(cf, hook, data);
}
#define settle_active(s) tm_active(&(s)->tm)
static inline void settle_kick(struct settle *s, struct birdloop *loop)
{
if (!tm_active(&s->tm))
{
s->started = current_time();
tm_set_in(&s->tm, s->started + s->cf.min, loop);
}
else
{
btime now = current_time();
tm_set_in(&s->tm, MIN_(now + s->cf.min, s->started + s->cf.max), loop);
}
}
static inline void settle_cancel(struct settle *s)
{
tm_stop(&s->tm);
}
#endif

View File

@ -125,7 +125,7 @@ CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, AS)
CF_KEYWORDS(MIN, IDLE, RX, TX, INTERVAL, MULTIPLIER, PASSIVE)
CF_KEYWORDS(CHECK, LINK)
CF_KEYWORDS(CORK, SORTED, TRIE, MIN, MAX, SETTLE, TIME, GC, THRESHOLD, PERIOD)
CF_KEYWORDS(CORK, SORTED, TRIE, MIN, MAX, ROA, SETTLE, TIME, GC, THRESHOLD, PERIOD)
/* For r_args_channel */
CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC)
@ -321,8 +321,7 @@ channel_item_:
| RECEIVE LIMIT limit_spec { this_channel->rx_limit = $3; }
| IMPORT LIMIT limit_spec { this_channel->in_limit = $3; }
| EXPORT LIMIT limit_spec { this_channel->out_limit = $3; }
| MIN SETTLE TIME expr_us { this_channel->min_settle_time = $4; }
| MAX SETTLE TIME expr_us { this_channel->max_settle_time = $4; }
| ROA SETTLE TIME settle { this_channel->roa_settle = $4; }
| PREFERENCE expr { this_channel->preference = $2; check_u16($2); }
| IMPORT KEEP FILTERED bool {
if ($4)
@ -424,7 +423,6 @@ timeformat_base:
TIMEFORMAT timeformat_spec ';'
;
/* Interface patterns */
iface_patt_node_init:

View File

@ -315,16 +315,15 @@ proto_remove_channels(struct proto *p)
struct roa_subscription {
node roa_node;
timer t;
btime base_settle_time; /* Start of settling interval */
struct settle settle;
struct channel *c;
struct rt_export_request req;
};
static void
channel_roa_in_changed(struct timer *t)
channel_roa_in_changed(struct settle *se)
{
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, t, t);
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, settle, se);
struct channel *c = s->c;
int active = !!c->reload_req.hook;
@ -337,9 +336,9 @@ channel_roa_in_changed(struct timer *t)
}
static void
channel_roa_out_changed(struct timer *t)
channel_roa_out_changed(struct settle *se)
{
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, t, t);
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, settle, se);
struct channel *c = s->c;
CD(c, "Feeding triggered by RPKI change");
@ -356,17 +355,7 @@ channel_export_one_roa(struct rt_export_request *req, const net_addr *net UNUSED
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, req, req);
/* TODO: use the information about what roa has changed */
if (!tm_active(&s->t))
{
s->base_settle_time = current_time();
tm_start(&s->t, s->base_settle_time + s->c->min_settle_time);
}
else
tm_set(&s->t,
MIN(s->base_settle_time + s->c->max_settle_time,
current_time() + s->c->min_settle_time));
settle_kick(&s->settle, &main_birdloop);
rpe_mark_seen_all(req->hook, first, NULL);
}
@ -380,14 +369,14 @@ channel_dump_roa_req(struct rt_export_request *req)
debug(" Channel %s.%s ROA %s change notifier from table %s request %p\n",
c->proto->name, c->name,
(s->t.hook == channel_roa_in_changed) ? "import" : "export",
(s->settle.hook == channel_roa_in_changed) ? "import" : "export",
tab->name, req);
}
static int
channel_roa_is_subscribed(struct channel *c, rtable *tab, int dir)
{
void (*hook)(struct timer *) =
void (*hook)(struct settle *) =
dir ? channel_roa_in_changed : channel_roa_out_changed;
struct roa_subscription *s;
@ -395,7 +384,7 @@ channel_roa_is_subscribed(struct channel *c, rtable *tab, int dir)
WALK_LIST2(s, n, c->roa_subscriptions, roa_node)
if ((tab == SKIP_BACK(rtable, priv.exporter.e, s->req.hook->table))
&& (s->t.hook == hook))
&& (s->settle.hook == hook))
return 1;
return 0;
@ -410,7 +399,7 @@ channel_roa_subscribe(struct channel *c, rtable *tab, int dir)
struct roa_subscription *s = mb_allocz(c->proto->pool, sizeof(struct roa_subscription));
*s = (struct roa_subscription) {
.t = { .hook = dir ? channel_roa_in_changed : channel_roa_out_changed, },
.settle = SETTLE_INIT(&c->roa_settle, dir ? channel_roa_in_changed : channel_roa_out_changed, NULL),
.c = c,
.req = {
.name = mb_sprintf(c->proto->pool, "%s.%s.roa-%s.%s",
@ -934,8 +923,10 @@ channel_config_new(const struct channel_class *cc, const char *name, uint net_ty
cf->debug = new_config->channel_default_debug;
cf->rpki_reload = 1;
cf->min_settle_time = 1 S;
cf->max_settle_time = 20 S;
cf->roa_settle = (struct settle_config) {
.min = 1 S,
.max = 20 S,
};
add_tail(&proto->channels, &cf->n);
@ -1017,20 +1008,20 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
c->in_req.trace_routes = c->out_req.trace_routes = c->debug | c->proto->debug;
c->rpki_reload = cf->rpki_reload;
if ( (c->min_settle_time != cf->min_settle_time)
|| (c->max_settle_time != cf->max_settle_time))
if ( (c->roa_settle.min != cf->roa_settle.min)
|| (c->roa_settle.max != cf->roa_settle.max))
{
c->min_settle_time = cf->min_settle_time;
c->max_settle_time = cf->max_settle_time;
c->roa_settle = cf->roa_settle;
struct roa_subscription *s;
node *n;
WALK_LIST2(s, n, c->roa_subscriptions, roa_node)
if (tm_active(&s->t))
tm_set(&s->t,
MIN(s->base_settle_time + c->max_settle_time,
current_time() + c->min_settle_time));
{
s->settle.cf = cf->roa_settle;
if (settle_active(&s->settle))
settle_kick(&s->settle, &main_birdloop);
}
}
/* Execute channel-specific reconfigure hook */

View File

@ -12,6 +12,7 @@
#include "lib/lists.h"
#include "lib/resource.h"
#include "lib/event.h"
#include "lib/settle.h"
#include "nest/rt.h"
#include "nest/limit.h"
#include "conf/conf.h"
@ -462,8 +463,7 @@ struct channel_config {
struct channel_limit in_limit; /* Limit for importing routes from protocol */
struct channel_limit out_limit; /* Limit for exporting routes to protocol */
btime min_settle_time; /* Minimum settle time for ROA-induced reload */
btime max_settle_time; /* Maximum settle time for ROA-induced reload */
struct settle_config roa_settle; /* Settle times for ROA-induced reload */
u8 net_type; /* Routing table network type (NET_*), 0 for undefined */
u8 ra_mode; /* Mode of received route advertisements (RA_*) */
@ -492,8 +492,7 @@ struct channel {
struct limit in_limit; /* Input limit */
struct limit out_limit; /* Output limit */
btime min_settle_time; /* Minimum settle time for ROA-induced reload */
btime max_settle_time; /* Maximum settle time for ROA-induced reload */
struct settle_config roa_settle; /* Settle times for ROA-induced reload */
u8 limit_actions[PLD_MAX]; /* Limit actions enum */
u8 limit_active; /* Flags for active limits */