0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Settle time for stats protocol, documentation

This commit is contained in:
Vojtech Vilimek 2022-07-21 16:54:13 +02:00
parent 727a8f32c4
commit 1c12cc9a11
4 changed files with 124 additions and 15 deletions

View File

@ -5411,6 +5411,54 @@ protocol static {
}
</code>
<sect>Stats
<label id="stats">
<sect1>
<label id="stats-intro">
<p>The Statistics protocol allows you to measure number of exported routes from
a table. You can also narrow the view by applying export filter inside stats
channel. One instance of stats protocol can have multiple channels attached.
Stats protocol could be particullary useful when making conditional route advertising.
<p>Statistics are accessed in filters by same name as channel connected to desired
table. Value of this expresion is evaluated to the sum of all routes with
generation smaller than max generation (see below).
<sect1>Configuration
<label id="stats-config">
<p><descrtip>
<tag><label id="stats-max-generation">max generation <m/expr/</tag>
Statistics counter contains sum of all routes with generation less
than or equal to max generation. This copies behavior of pipe's
<ref id="pipe-max-generation" name="max generetion">. Must be in range
from 0 to 254. Default: 16.
<tag><label id="stats-update-after">settle time <m/time/ <m/number/</tag>
Wait given amount of time before notifying and recalculting filters
which reference this counter in seconds. If counter changes during this period,
current value is used. If set to zero, the notification is done instantly.
Default: 5 s.
</descrip>
<p>Example
<code>
protocol stats {
ipv4 stats1 { table bgp_tab1; };
}
protocol static {
# note that the stats1 is unrelated
ipv4 { import where stats1 > 200; };
route 0.0.0.0:0;
}
</code>
<p>Beware that configuration with cyclic references (even logical ones) are
considered invalid and the behaviour is not defined! You <em>should</em> avoid
them. No detection is implemented.
<chapt>Conclusions
<label id="conclusion">

View File

@ -9,18 +9,15 @@
CF_HDR
/* old: #include "proto/pipe/pipe.h" */
#include "proto/stats/stats.h"
CF_DEFINES
/* old: #define PIPE_CFG ((struct pipe_config *) this_proto) */
#define STATS_CC ((struct stats_channel_config *) this_channel)
CF_DECLS
/* TODO here add more keywords */
CF_KEYWORDS(STATS, TABLE, MAX, GENERATION)
CF_KEYWORDS(STATS, TABLE, MAX, GENERATION, SETTLE, TIME)
%type <cc> stats_channel_start
@ -48,21 +45,25 @@ channel_max_gen:
}
;
stats_settle:
SETTLE TIME time {
STATS_CC->settle = $3 S_;
}
stats_opts:
/* empty */
| stats_opts channel_item ';'
| stats_opts channel_max_gen ';'
| stats_opts stats_settle ';'
;
stats_proto_channel: stats_channel_start stats_channel_opt_list channel_end ;
/* stats_proto_channel: stats_channel_start stats_max_gen channel_opt_list channel_end ; */
stats_channel_start: net_type symbol
{
this_channel = channel_config_get(&channel_stats, $2->name, $1, this_proto);
STATS_CC->max_generation = 16;
/* from filter/config.Y:
cf_define_symbol($3, SYM_VARIABLE | $2, offset, $3->scope->slots++) */
STATS_CC->settle = 5 S_;
$2 = cf_define_symbol($2, SYM_COUNTER, ch_config, this_channel);
}

View File

@ -22,30 +22,44 @@
#include "conf/conf.h"
#include "filter/filter.h"
#include "lib/string.h"
#include "lib/timer.h"
#include "stats.h"
#ifdef CONFIG_BGP
#include "proto/bgp/bgp.h"
#endif
#define COUNTER 255
static void stats_kick_timer(struct stats_channel *c);
static void
stats_rt_notify(struct proto *P UNUSED, struct channel *src_ch, const net_addr *n UNUSED, rte *new, const rte *old)
{
struct stats_channel *ch = (void *) src_ch;
int changed = 0;
if (old)
{
ch->counters[old->generation]--;
if (old->generation < ch->max_generation)
ch->sum--;
{
changed = 1;
ch->counters[COUNTER]--;
}
}
if (new)
{
ch->counters[new->generation]++;
if (new->generation < ch->max_generation)
ch->sum++;
{
changed = 1;
ch->counters[COUNTER]++;
}
}
if (changed)
{
log(L_INFO "stats: timer kicked with time %u", ch->settle);
stats_kick_timer((struct stats_channel *) ch);
}
}
@ -69,6 +83,7 @@ stats_configure_channels(struct proto *P, struct proto_config *CF)
struct stats_channel_config *scc = (void *) cc;
sc->max_generation = scc->max_generation;
sc->settle = scc->settle;
}
}
@ -117,11 +132,17 @@ stats_reconfigure(struct proto *P, struct proto_config *CF)
struct stats_channel_config *scc = (void *) cc;
sc->max_generation = scc->max_generation;
sc->settle = scc->settle;
/* recalculate sum */
sc->sum = 0;
sc->counters[COUNTER] = 0;
for (u8 i = 0; i < sc->max_generation; i++)
sc->sum += sc->counters[i];
sc->counters[COUNTER] += sc->counters[i];
sc->sum = sc->counters[COUNTER];
/* notify all hooked filters */
// TODO here
c->stale = 0;
}
@ -161,7 +182,11 @@ stats_show_proto_info(struct proto *P)
cli_msg(-1006, " Channel %s", sc->c.name);
cli_msg(-1006, " Max generation: %3u", sc->max_generation);
cli_msg(-1006, " Exports: %10u", sc->sum);
// FIXME : actual or visible to filters ? AND TIME below in the comment
cli_msg(-1006, " Exports: %10u (currently: %10u)",
sc->sum,
sc->counters[COUNTER]);
cli_msg(-1006, " Settle time: %7u s", sc->settle / 1000000 );
cli_msg(-1006, " Counter exported");
for (u8 i = 0; i < len; i++)
@ -186,6 +211,32 @@ stats_update_debug(struct proto *P)
}
}
static void
stats_timer(timer *t)
{
log(L_INFO "timer executing update");
struct stats_channel *c = (struct stats_channel *) t->data;
/* update the sum correct counter data */
c->sum = c->counters[COUNTER];
/* notify all filters to reevaluate them */
// TODO here
}
static void
stats_kick_timer(struct stats_channel *c)
{
/* if set to zero execute immediately */
if (!c->settle)
stats_timer(c->timer);
if (!tm_active(c->timer))
tm_start(c->timer, c->settle);
}
static int
stats_channel_start(struct channel *C)
{
@ -194,6 +245,8 @@ stats_channel_start(struct channel *C)
c->pool = p->p.pool;
c->timer = tm_new_init(c->pool, stats_timer, (void *) c, 0, 0);
c->counters = mb_allocz(c->pool, 256 * sizeof(u32));
c->sum = 0;
@ -207,6 +260,10 @@ stats_channel_shutdown(struct channel *C)
mb_free(c->counters);
/* FIXME freed automatically by the resource pool ?
rfree(c->timer);
*/
c->max_generation = 0;
c->counters = NULL;
c->pool = NULL;

View File

@ -28,11 +28,14 @@ struct stats_channel {
u8 max_generation;
u32 *counters;
u32 sum;
timer *timer;
btime settle;
};
struct stats_channel_config {
struct channel_config c;
u8 max_generation;
btime settle;
};
static inline int