mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-03 15:41:54 +00:00
Stats min/max settle time by using settle timer
This commit is contained in:
parent
84a7cb1c60
commit
0f8e23100e
@ -476,7 +476,7 @@
|
|||||||
INST(FI_COUNTER, 0, 1) {
|
INST(FI_COUNTER, 0, 1) {
|
||||||
SYMBOL;
|
SYMBOL;
|
||||||
NEVER_CONSTANT;
|
NEVER_CONSTANT;
|
||||||
RESULT(T_INT, i, get_stats_sum(sym));
|
RESULT(T_INT, i, get_stats_counter(sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
INST(FI_CONSTANT, 0, 1) {
|
INST(FI_CONSTANT, 0, 1) {
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
#include "filter/f-inst.h"
|
#include "filter/f-inst.h"
|
||||||
#include "filter/data.h"
|
#include "filter/data.h"
|
||||||
#include "proto/stats/stats.h" /* provides function get_stats_sum used in f-inst.c */
|
#include "proto/stats/stats.h" /* provides function get_stats_counter() used in f-inst.c */
|
||||||
|
|
||||||
|
|
||||||
/* Exception bits */
|
/* Exception bits */
|
||||||
|
@ -37,24 +37,21 @@ stats_channel_opt_list:
|
|||||||
| '{' stats_opts '}'
|
| '{' stats_opts '}'
|
||||||
;
|
;
|
||||||
|
|
||||||
|
stats_opt:
|
||||||
channel_max_gen:
|
type symbol '=' term {
|
||||||
MAX GENERATION expr {
|
struct f_val val;
|
||||||
if ($3 > 254) cf_error("Max generation must be in range 0..254, got %u", $3);
|
if (f_eval(f_linearize($4), &val) > F_RETURN) cf_error("Runtime error");
|
||||||
STATS_CC->max_generation = $3;
|
if (val.type != $1) cf_error("The expresion does not match defined type");
|
||||||
}
|
/* cf_define_symbol($2, SYM_VARIABLE | $1, val )*/
|
||||||
|
}
|
||||||
|
| MIN SETTLE TIME expr_us { STATS_CC->min_settle_time = $4; }
|
||||||
|
| MAX SETTLE TIME expr_us { STATS_CC->max_settle_time = $4; }
|
||||||
;
|
;
|
||||||
|
|
||||||
stats_settle:
|
|
||||||
SETTLE TIME time {
|
|
||||||
STATS_CC->settle = $3 S_;
|
|
||||||
}
|
|
||||||
|
|
||||||
stats_opts:
|
stats_opts:
|
||||||
/* empty */
|
/* empty */
|
||||||
| stats_opts channel_item ';'
|
| stats_opts channel_item ';'
|
||||||
| stats_opts channel_max_gen ';'
|
| stats_opts stats_opt ';'
|
||||||
| stats_opts stats_settle ';'
|
|
||||||
;
|
;
|
||||||
|
|
||||||
stats_proto_channel: stats_channel_start stats_channel_opt_list channel_end ;
|
stats_proto_channel: stats_channel_start stats_channel_opt_list channel_end ;
|
||||||
@ -62,8 +59,8 @@ stats_proto_channel: stats_channel_start stats_channel_opt_list channel_end ;
|
|||||||
stats_channel_start: net_type symbol
|
stats_channel_start: net_type symbol
|
||||||
{
|
{
|
||||||
this_channel = channel_config_get(&channel_stats, $2->name, $1, this_proto);
|
this_channel = channel_config_get(&channel_stats, $2->name, $1, this_proto);
|
||||||
STATS_CC->max_generation = 16;
|
STATS_CC->min_settle_time = 1 S_;
|
||||||
STATS_CC->settle = 5 S_;
|
STATS_CC->max_settle_time = 20 S_;
|
||||||
$2 = cf_define_symbol($2, SYM_COUNTER, ch_config, this_channel);
|
$2 = cf_define_symbol($2, SYM_COUNTER, ch_config, this_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,9 +26,7 @@
|
|||||||
|
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
|
||||||
#define COUNTER 255
|
static void stats_settle_timer(struct settle_timer *st);
|
||||||
|
|
||||||
static void stats_kick_timer(struct stats_channel *c);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stats_rt_notify(struct proto *P UNUSED, struct channel *src_ch, const net_addr *n UNUSED, rte *new, const rte *old)
|
stats_rt_notify(struct proto *P UNUSED, struct channel *src_ch, const net_addr *n UNUSED, rte *new, const rte *old)
|
||||||
@ -36,60 +34,54 @@ stats_rt_notify(struct proto *P UNUSED, struct channel *src_ch, const net_addr *
|
|||||||
struct stats_channel *ch = (void *) src_ch;
|
struct stats_channel *ch = (void *) src_ch;
|
||||||
|
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
if (old)
|
if (new && old)
|
||||||
|
/* count of exported routes stays the same */
|
||||||
|
log(L_INFO "nothing happen - no change of counter");
|
||||||
|
else if (!old)
|
||||||
{
|
{
|
||||||
ch->counters[old->generation]--;
|
log(L_INFO "increasing _counter");
|
||||||
if (old->generation <= ch->max_generation)
|
ch->_counter++;
|
||||||
{
|
changed = 1;
|
||||||
changed = 1;
|
if (ch->_counter > 100)
|
||||||
ch->counters[COUNTER]--;
|
log(L_INFO "underflow?");
|
||||||
}
|
}
|
||||||
}
|
else if (!new)
|
||||||
|
{
|
||||||
if (new)
|
log(L_INFO "decreasing _counter");
|
||||||
{
|
ch->_counter--;
|
||||||
ch->counters[new->generation]++;
|
changed = 1;
|
||||||
if (new->generation <= ch->max_generation)
|
if (ch->_counter > 100)
|
||||||
{
|
log(L_INFO "underflow? - ");
|
||||||
changed = 1;
|
}
|
||||||
ch->counters[COUNTER]++;
|
else /* shouldn't happen */
|
||||||
}
|
{
|
||||||
|
log(L_INFO "BUG is here !!!");
|
||||||
|
bug("Both pointers *new and *old in rt_notify are NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log(L_INFO "stats channel %s: preparing to kick the timer %d", src_ch->name,
|
||||||
|
changed);
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
log(L_INFO "stats: timer kicked with time %u", ch->settle);
|
settle_timer_changed(ch->settle_timer);
|
||||||
stats_kick_timer((struct stats_channel *) ch);
|
kick_settle_timer(ch->settle_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stats_reload_routes(struct channel *C UNUSED)
|
stats_reload_routes(struct channel *C)
|
||||||
{
|
{
|
||||||
/* Route reload on one channel is just refeed on the other */
|
// TODO
|
||||||
//channel_request_feeding(p->c);
|
struct stats_channel *c = (void *) C;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
c->_counter = c->counter = 0;
|
||||||
stats_configure_channels(struct proto *P, struct proto_config *CF)
|
channel_request_feeding(C);
|
||||||
{
|
|
||||||
struct channel_config *cc;
|
|
||||||
WALK_LIST(cc, CF->channels)
|
|
||||||
{
|
|
||||||
struct channel *c = NULL;
|
|
||||||
proto_configure_channel(P, &c, cc);
|
|
||||||
|
|
||||||
struct stats_channel *sc = (void *) c;
|
|
||||||
struct stats_channel_config *scc = (void *) cc;
|
|
||||||
|
|
||||||
sc->max_generation = scc->max_generation;
|
|
||||||
sc->settle = scc->settle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct proto *
|
static struct proto *
|
||||||
stats_init(struct proto_config *CF)
|
stats_init(struct proto_config *CF)
|
||||||
{
|
{
|
||||||
|
log(L_INFO "stats_init() ");
|
||||||
struct proto *P = proto_new(CF);
|
struct proto *P = proto_new(CF);
|
||||||
struct stats_proto *p = (void *) P;
|
struct stats_proto *p = (void *) P;
|
||||||
|
|
||||||
@ -98,14 +90,31 @@ stats_init(struct proto_config *CF)
|
|||||||
|
|
||||||
p->rl_gen = (struct tbf) TBF_DEFAULT_LOG_LIMITS;
|
p->rl_gen = (struct tbf) TBF_DEFAULT_LOG_LIMITS;
|
||||||
|
|
||||||
stats_configure_channels(P, CF);
|
|
||||||
|
|
||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static struct settle_timer_class stats_settle_class = {
|
||||||
stats_start(struct proto *P UNUSED)
|
.action = stats_settle_timer,
|
||||||
|
.kick = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
stats_configure_channels(struct proto *P, struct proto_config *CF)
|
||||||
{
|
{
|
||||||
|
log(L_INFO "stats_configure_channels()");
|
||||||
|
struct channel_config *cc;
|
||||||
|
WALK_LIST(cc, CF->channels)
|
||||||
|
{
|
||||||
|
struct channel *c = proto_find_channel_by_name(P, cc->name);
|
||||||
|
proto_configure_channel(P, &c, cc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
stats_start(struct proto *P)
|
||||||
|
{
|
||||||
|
log(L_INFO "stats_start() ");
|
||||||
|
stats_configure_channels(P, P->cf);
|
||||||
return PS_UP;
|
return PS_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,18 +140,16 @@ stats_reconfigure(struct proto *P, struct proto_config *CF)
|
|||||||
struct stats_channel *sc = (void *) c;
|
struct stats_channel *sc = (void *) c;
|
||||||
struct stats_channel_config *scc = (void *) cc;
|
struct stats_channel_config *scc = (void *) cc;
|
||||||
|
|
||||||
sc->max_generation = scc->max_generation;
|
sc->settle_timer->min_settle_time = &(scc->min_settle_time);
|
||||||
sc->settle = scc->settle;
|
sc->settle_timer->max_settle_time = &(scc->max_settle_time);
|
||||||
|
|
||||||
/* recalculate sum */
|
if (sc->counter != sc->_counter)
|
||||||
sc->counters[COUNTER] = 0;
|
{
|
||||||
for (u8 i = 0; i <= sc->max_generation; i++)
|
sc->counter = sc->_counter;
|
||||||
sc->counters[COUNTER] += sc->counters[i];
|
|
||||||
|
|
||||||
sc->sum = sc->counters[COUNTER];
|
/* notify all hooked filters */
|
||||||
|
// TODO here
|
||||||
/* notify all hooked filters */
|
}
|
||||||
// TODO here
|
|
||||||
|
|
||||||
c->stale = 0;
|
c->stale = 0;
|
||||||
}
|
}
|
||||||
@ -161,44 +168,19 @@ stats_show_proto_info(struct proto *P)
|
|||||||
{
|
{
|
||||||
struct stats_proto *p = (void *) P;
|
struct stats_proto *p = (void *) P;
|
||||||
|
|
||||||
/* indexes of non-zero counters */
|
|
||||||
u32 *arr = mb_alloc(p->p.pool, 256 * sizeof(u32));
|
|
||||||
|
|
||||||
struct stats_channel *sc;
|
struct stats_channel *sc;
|
||||||
WALK_LIST(sc, p->p.channels)
|
WALK_LIST(sc, p->p.channels)
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
arr[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 len = 0;
|
|
||||||
for (u8 i = 0; i < sc->max_generation; i++)
|
|
||||||
if (sc->counters[i])
|
|
||||||
{
|
|
||||||
arr[len] = i;
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
cli_msg(-1006, " Channel %s", sc->c.name);
|
cli_msg(-1006, " Channel %s", sc->c.name);
|
||||||
cli_msg(-1006, " Max generation: %3u", sc->max_generation);
|
|
||||||
// FIXME : actual or visible to filters ? AND TIME below in the comment
|
|
||||||
cli_msg(-1006, " Exports: %10u (currently: %10u)",
|
cli_msg(-1006, " Exports: %10u (currently: %10u)",
|
||||||
sc->sum,
|
sc->counter,
|
||||||
sc->counters[COUNTER]);
|
sc->_counter);
|
||||||
cli_msg(-1006, " Settle time: %7u s", sc->settle / 1000000 );
|
if (!P->disabled)
|
||||||
cli_msg(-1006, " Counter exported");
|
{
|
||||||
|
cli_msg(-1006, " Settle time: %4u s", (*(sc->settle_timer->min_settle_time)) TO_S);
|
||||||
for (u8 i = 0; i < len; i++)
|
cli_msg(-1006, " Settle time: %4u s", (*(sc->settle_timer->max_settle_time)) TO_S);
|
||||||
cli_msg(-1006, " %3u: %10u ", arr[i], sc->counters[arr[i]]);
|
}
|
||||||
|
|
||||||
if (!len)
|
|
||||||
cli_msg(-1006, " <all zeroes>");
|
|
||||||
|
|
||||||
cli_msg(-1006, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mb_free(arr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -212,43 +194,41 @@ stats_update_debug(struct proto *P)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stats_timer(timer *t)
|
stats_settle_timer(struct settle_timer *st)
|
||||||
{
|
{
|
||||||
log(L_INFO "timer executing update");
|
timer *t = (void *) st;
|
||||||
struct stats_channel *c = (struct stats_channel *) t->data;
|
struct stats_channel *c = t->data;
|
||||||
|
log(L_INFO "stats_settle_timer() _counter: %u, counter: %u",
|
||||||
|
c->_counter, c->counter);
|
||||||
|
|
||||||
/* update the sum correct counter data */
|
/* update only if real change happen */
|
||||||
c->sum = c->counters[COUNTER];
|
if (c->counter != c->_counter)
|
||||||
|
{
|
||||||
/* notify all filters to reevaluate them */
|
c->counter = c->_counter;
|
||||||
// TODO here
|
/* do update here */
|
||||||
|
// WALK_LIST(s, subscribers)
|
||||||
}
|
// { ... }
|
||||||
|
}
|
||||||
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
|
static int
|
||||||
stats_channel_start(struct channel *C)
|
stats_channel_start(struct channel *C)
|
||||||
{
|
{
|
||||||
struct stats_channel *c = (void *) C;
|
struct stats_channel *c = (void *) C;
|
||||||
|
struct stats_channel_config *cc = (void *) C->config;
|
||||||
struct stats_proto *p = (void *) C->proto;
|
struct stats_proto *p = (void *) C->proto;
|
||||||
|
|
||||||
c->pool = p->p.pool;
|
c->pool = p->p.pool;
|
||||||
|
|
||||||
c->timer = tm_new_init(c->pool, stats_timer, (void *) c, 0, 0);
|
if (!c->settle_timer)
|
||||||
|
c->settle_timer = stm_new_timer(
|
||||||
|
c->pool, (void *) c, &stats_settle_class);
|
||||||
|
|
||||||
c->counters = mb_allocz(c->pool, 256 * sizeof(u32));
|
c->settle_timer->min_settle_time = &(cc->min_settle_time);
|
||||||
c->sum = 0;
|
c->settle_timer->max_settle_time = &(cc->max_settle_time);
|
||||||
|
|
||||||
|
c->_counter = 0;
|
||||||
|
c->counter = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -256,16 +236,19 @@ stats_channel_start(struct channel *C)
|
|||||||
static void
|
static void
|
||||||
stats_channel_shutdown(struct channel *C)
|
stats_channel_shutdown(struct channel *C)
|
||||||
{
|
{
|
||||||
|
log(L_INFO "stats_channel_shutdown()");
|
||||||
struct stats_channel *c = (void *) C;
|
struct stats_channel *c = (void *) C;
|
||||||
|
|
||||||
mb_free(c->counters);
|
tm_stop((timer *) c->settle_timer);
|
||||||
|
|
||||||
/* FIXME freed automatically by the resource pool ?
|
c->settle_timer->min_settle_time = NULL;
|
||||||
rfree(c->timer);
|
c->settle_timer->max_settle_time = NULL;
|
||||||
*/
|
|
||||||
|
|
||||||
c->max_generation = 0;
|
mb_free(c->settle_timer);
|
||||||
c->counters = NULL;
|
c->settle_timer = NULL;
|
||||||
|
|
||||||
|
c->_counter = 0;
|
||||||
|
c->counter = 0;
|
||||||
c->pool = NULL;
|
c->pool = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#ifndef _BIRD_STATS_H_
|
#ifndef _BIRD_STATS_H_
|
||||||
#define _BIRD_STATS_H_
|
#define _BIRD_STATS_H_
|
||||||
|
#include "lib/timer.h"
|
||||||
|
|
||||||
struct stats_channel;
|
struct stats_channel;
|
||||||
|
|
||||||
@ -24,25 +25,28 @@ struct stats_proto {
|
|||||||
|
|
||||||
struct stats_channel {
|
struct stats_channel {
|
||||||
struct channel c;
|
struct channel c;
|
||||||
pool *pool;
|
pool *pool; /* copy of procotol pool */
|
||||||
u8 max_generation;
|
u32 _counter; /* internal counter */
|
||||||
u32 *counters;
|
u32 counter; /* publicly accessible counter */
|
||||||
u32 sum;
|
struct settle_timer *settle_timer;
|
||||||
timer *timer;
|
|
||||||
btime settle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stats_channel_config {
|
struct stats_channel_config {
|
||||||
struct channel_config c;
|
struct channel_config c;
|
||||||
u8 max_generation;
|
btime min_settle_time; /* wait before notifying filters */
|
||||||
btime settle;
|
btime max_settle_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_stats_counter() - extract last notified counter
|
||||||
|
* for specific stats channel if it runs
|
||||||
|
*
|
||||||
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
get_stats_sum(struct symbol *sym)
|
get_stats_counter(struct symbol *sym)
|
||||||
{
|
{
|
||||||
if (sym->ch_config->channel)
|
if (sym->ch_config->channel)
|
||||||
return (int) ((struct stats_channel *) sym->ch_config->channel)->sum;
|
return (int) ((struct stats_channel *) sym->ch_config->channel)->counter;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user