2022-07-13 13:39:14 +00:00
|
|
|
/*
|
2022-07-14 15:08:03 +00:00
|
|
|
* BIRD -- Statistics Protocol
|
2022-07-13 13:39:14 +00:00
|
|
|
*
|
2022-07-14 12:51:03 +00:00
|
|
|
* (c) 2022 Vojtech Vilimek <vojtech.vilimek@nic.cz>
|
|
|
|
* (c) 2022 CZ.NIC z.s.p.o.
|
2022-07-13 13:39:14 +00:00
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2022-07-14 12:51:03 +00:00
|
|
|
* DOC: Stats
|
2022-07-13 13:39:14 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#undef LOCAL_DEBUG
|
|
|
|
|
|
|
|
#include "nest/bird.h"
|
|
|
|
#include "nest/iface.h"
|
|
|
|
#include "nest/protocol.h"
|
|
|
|
#include "nest/rt.h"
|
|
|
|
#include "nest/cli.h"
|
|
|
|
#include "conf/conf.h"
|
|
|
|
#include "filter/filter.h"
|
|
|
|
#include "lib/string.h"
|
|
|
|
|
|
|
|
#include "stats.h"
|
|
|
|
|
|
|
|
#ifdef CONFIG_BGP
|
|
|
|
#include "proto/bgp/bgp.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void
|
|
|
|
stats_rt_notify(struct proto *P, struct channel *src_ch, const net_addr *n, rte *new, const rte *old)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (void *) P;
|
2022-07-15 11:33:42 +00:00
|
|
|
struct stats_config *cf = (void *) P->cf;
|
2022-07-14 15:08:03 +00:00
|
|
|
log(L_INFO "stats_rf_notify()");
|
|
|
|
|
|
|
|
if (new && old)
|
|
|
|
{
|
|
|
|
new->generation = old->generation + 1;
|
|
|
|
p->counters[old->generation]--;
|
|
|
|
p->counters[new->generation]++;
|
|
|
|
log(L_INFO "counter %u increased", new->generation);
|
|
|
|
}
|
|
|
|
else if (new && !old)
|
|
|
|
{
|
|
|
|
new->generation = 0;
|
|
|
|
p->counters[0]++;
|
|
|
|
log(L_INFO "counter 0 increased");
|
|
|
|
}
|
|
|
|
else if (!new && old)
|
|
|
|
{
|
|
|
|
(p->counters[old->generation])--;
|
|
|
|
log(L_INFO "counter %u decreased", old->generation);
|
|
|
|
}
|
2022-07-13 13:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
stats_preexport(struct channel *c, rte *e)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (void *) c->proto;
|
2022-07-14 15:08:03 +00:00
|
|
|
log(L_INFO "stats_preexport()");
|
2022-07-13 13:39:14 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
stats_reload_routes(struct channel *C)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (void *) C->proto;
|
|
|
|
|
|
|
|
/* Route reload on one channel is just refeed on the other */
|
2022-07-15 11:33:42 +00:00
|
|
|
//channel_request_feeding(p->c);
|
2022-07-13 13:39:14 +00:00
|
|
|
}
|
|
|
|
|
2022-07-15 11:33:42 +00:00
|
|
|
static void
|
|
|
|
stats_configure_channels(struct proto *P, struct proto_config *CF)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (void *) P;
|
|
|
|
struct stats_config *cf = (void *) CF;
|
|
|
|
|
|
|
|
struct channel_config *cc;
|
|
|
|
WALK_LIST(cc, CF->channels)
|
|
|
|
{
|
|
|
|
struct channel *c = NULL;
|
|
|
|
proto_configure_channel(P, &c, cc);
|
|
|
|
}
|
|
|
|
}
|
2022-07-13 13:39:14 +00:00
|
|
|
|
|
|
|
static struct proto *
|
|
|
|
stats_init(struct proto_config *CF)
|
|
|
|
{
|
|
|
|
struct proto *P = proto_new(CF);
|
|
|
|
struct stats_proto *p = (void *) P;
|
|
|
|
struct stats_config *cf = (void *) CF;
|
2022-07-14 15:08:03 +00:00
|
|
|
log(L_INFO "stats_init()");
|
2022-07-13 13:39:14 +00:00
|
|
|
|
|
|
|
P->rt_notify = stats_rt_notify;
|
|
|
|
P->preexport = stats_preexport;
|
|
|
|
P->reload_routes = stats_reload_routes;
|
|
|
|
|
|
|
|
p->rl_gen = (struct tbf) TBF_DEFAULT_LOG_LIMITS;
|
|
|
|
|
2022-07-15 11:33:42 +00:00
|
|
|
stats_configure_channels(P, CF);
|
2022-07-13 13:39:14 +00:00
|
|
|
|
|
|
|
return P;
|
|
|
|
}
|
|
|
|
|
2022-07-15 11:33:42 +00:00
|
|
|
static struct channel *
|
|
|
|
stats_find_channel(struct stats_proto *p, const char *name)
|
|
|
|
{
|
|
|
|
struct channel *c;
|
|
|
|
WALK_LIST(c, p->p.channels)
|
|
|
|
if (strcmp(c->name, name))
|
|
|
|
return c;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-07-14 15:08:03 +00:00
|
|
|
static int
|
|
|
|
stats_start(struct proto *P)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (struct stats_proto *) P;
|
|
|
|
log(L_INFO "stats_start() ");
|
|
|
|
|
|
|
|
p->counters = (u32 *) mb_allocz(p->p.pool, 256 * sizeof(u32));
|
|
|
|
|
|
|
|
return PS_UP;
|
|
|
|
}
|
|
|
|
|
2022-07-13 13:39:14 +00:00
|
|
|
static int
|
|
|
|
stats_reconfigure(struct proto *P, struct proto_config *CF)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (void *) P;
|
2022-07-15 11:33:42 +00:00
|
|
|
struct stats_config *new = (void *) CF;
|
|
|
|
struct stats_config *old = (void *) P->cf;
|
|
|
|
log(L_INFO "stats_reconfigure()");
|
|
|
|
|
|
|
|
struct channel *c;
|
|
|
|
WALK_LIST(c, p->p.channels)
|
|
|
|
c->stale = 1;
|
|
|
|
|
|
|
|
struct channel_config *cc;
|
|
|
|
WALK_LIST(cc, new->c.channels)
|
|
|
|
{
|
|
|
|
c = (struct channel *) stats_find_channel(p, cc->name);
|
|
|
|
if (!proto_configure_channel(P, &c, cc))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (c)
|
|
|
|
c->stale = 0;
|
|
|
|
}
|
2022-07-13 13:39:14 +00:00
|
|
|
|
2022-07-15 11:33:42 +00:00
|
|
|
struct channel *c2;
|
|
|
|
WALK_LIST_DELSAFE(c, c2, p->p.channels)
|
|
|
|
if (c->stale && !proto_configure_channel(P, &c, NULL))
|
|
|
|
return 0;
|
|
|
|
|
2022-07-14 12:51:03 +00:00
|
|
|
return 1;
|
2022-07-13 13:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
stats_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUSED)
|
|
|
|
{
|
|
|
|
/* Just a shallow copy, not many items here */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
stats_get_status(struct proto *P, byte *buf)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (void *) P;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
stats_show_proto_info(struct proto *P)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (void *) P;
|
|
|
|
|
2022-07-14 15:08:03 +00:00
|
|
|
cli_msg(-1006, " Counters contents ");
|
|
|
|
for (int i = 0; i < 64; i++)
|
|
|
|
{
|
|
|
|
cli_msg(-1006, "%3u: %10u | %3u: %10u | %3u: %10u | %3u: %10u",
|
|
|
|
i , *(p->counters + i),
|
|
|
|
(i + 64 ), *(p->counters + i + 64),
|
|
|
|
(i + 128), *(p->counters + i + 128),
|
|
|
|
(i + 192), *(p->counters + i + 192)
|
|
|
|
);
|
|
|
|
}
|
2022-07-13 13:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
stats_update_debug(struct proto *P)
|
|
|
|
{
|
|
|
|
struct stats_proto *p = (void *) P;
|
|
|
|
|
2022-07-14 12:51:03 +00:00
|
|
|
p->c->debug = p->p.debug;
|
2022-07-13 13:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct protocol proto_stats = {
|
|
|
|
.name = "Stats",
|
|
|
|
.template = "stat%d",
|
2022-07-14 12:51:03 +00:00
|
|
|
.channel_mask = NB_ANY,
|
2022-07-13 13:39:14 +00:00
|
|
|
.proto_size = sizeof(struct stats_proto),
|
|
|
|
.config_size = sizeof(struct stats_config),
|
|
|
|
.init = stats_init,
|
2022-07-14 15:08:03 +00:00
|
|
|
.start = stats_start,
|
2022-07-13 13:39:14 +00:00
|
|
|
.reconfigure = stats_reconfigure,
|
|
|
|
.copy_config = stats_copy_config,
|
|
|
|
.get_status = stats_get_status,
|
|
|
|
.show_proto_info = stats_show_proto_info
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
stats_build(void)
|
|
|
|
{
|
|
|
|
proto_build(&proto_stats);
|
|
|
|
}
|