Fixes protocol statistics for pipes.
This commit is contained in:
parent
c83876265e
commit
9db74169be
4 changed files with 108 additions and 35 deletions
82
nest/proto.c
82
nest/proto.c
|
@ -791,6 +791,67 @@ proto_state_name(struct proto *p)
|
||||||
#undef P
|
#undef P
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proto_do_show_stats(struct proto *p)
|
||||||
|
{
|
||||||
|
struct proto_stats *s = &p->stats;
|
||||||
|
cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred",
|
||||||
|
s->imp_routes, s->exp_routes, s->pref_routes);
|
||||||
|
cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
|
||||||
|
cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
|
||||||
|
s->imp_updates_received, s->imp_updates_invalid,
|
||||||
|
s->imp_updates_filtered, s->imp_updates_ignored,
|
||||||
|
s->imp_updates_accepted);
|
||||||
|
cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
|
||||||
|
s->imp_withdraws_received, s->imp_withdraws_invalid,
|
||||||
|
s->imp_withdraws_ignored, s->imp_withdraws_accepted);
|
||||||
|
cli_msg(-1006, " Export updates: %10u %10u %10u --- %10u",
|
||||||
|
s->exp_updates_received, s->exp_updates_rejected,
|
||||||
|
s->exp_updates_filtered, s->exp_updates_accepted);
|
||||||
|
cli_msg(-1006, " Export withdraws: %10u --- --- --- %10u",
|
||||||
|
s->exp_withdraws_received, s->exp_withdraws_accepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proto_do_show_pipe_stats(struct proto *p)
|
||||||
|
{
|
||||||
|
struct proto_stats *s1 = &p->stats;
|
||||||
|
struct proto_stats *s2 = pipe_get_peer_stats(p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pipe stats (as anything related to pipes) are a bit tricky. There
|
||||||
|
* are two sets of stats - s1 for routes going from the primary
|
||||||
|
* routing table to the secondary routing table ('exported' from the
|
||||||
|
* user point of view) and s2 for routes going in the other
|
||||||
|
* direction ('imported' from the user point of view).
|
||||||
|
*
|
||||||
|
* Each route going through a pipe is, technically, first exported
|
||||||
|
* to the pipe and then imported from that pipe and such operations
|
||||||
|
* are counted in one set of stats according to the direction of the
|
||||||
|
* route propagation. Filtering is done just in the first part
|
||||||
|
* (export). Therefore, we compose stats for one directon for one
|
||||||
|
* user direction from both import and export stats, skipping
|
||||||
|
* immediate and irrelevant steps (exp_updates_accepted,
|
||||||
|
* imp_updates_received, imp_updates_filtered, ...)
|
||||||
|
*/
|
||||||
|
|
||||||
|
cli_msg(-1006, " Routes: %u imported, %u exported",
|
||||||
|
s2->imp_routes, s1->imp_routes);
|
||||||
|
cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
|
||||||
|
cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
|
||||||
|
s2->exp_updates_received, s2->exp_updates_rejected + s2->imp_updates_invalid,
|
||||||
|
s2->exp_updates_filtered, s2->imp_updates_ignored, s2->imp_updates_accepted);
|
||||||
|
cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
|
||||||
|
s2->exp_withdraws_received, s2->imp_withdraws_invalid,
|
||||||
|
s2->imp_withdraws_ignored, s2->imp_withdraws_accepted);
|
||||||
|
cli_msg(-1006, " Export updates: %10u %10u %10u %10u %10u",
|
||||||
|
s1->exp_updates_received, s1->exp_updates_rejected + s1->imp_updates_invalid,
|
||||||
|
s1->exp_updates_filtered, s1->imp_updates_ignored, s1->imp_updates_accepted);
|
||||||
|
cli_msg(-1006, " Export withdraws: %10u %10u --- %10u %10u",
|
||||||
|
s1->exp_withdraws_received, s1->imp_withdraws_invalid,
|
||||||
|
s1->imp_withdraws_ignored, s1->imp_withdraws_accepted);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
proto_do_show(struct proto *p, int verbose)
|
proto_do_show(struct proto *p, int verbose)
|
||||||
{
|
{
|
||||||
|
@ -817,21 +878,12 @@ proto_do_show(struct proto *p, int verbose)
|
||||||
|
|
||||||
if (p->proto_state != PS_DOWN)
|
if (p->proto_state != PS_DOWN)
|
||||||
{
|
{
|
||||||
cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred",
|
#ifdef CONFIG_PIPE
|
||||||
p->stats.imp_routes, p->stats.exp_routes, p->stats.pref_routes);
|
if (proto_is_pipe(p))
|
||||||
cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
|
proto_do_show_pipe_stats(p);
|
||||||
cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
|
else
|
||||||
p->stats.imp_updates_received, p->stats.imp_updates_invalid,
|
#endif
|
||||||
p->stats.imp_updates_filtered, p->stats.imp_updates_ignored,
|
proto_do_show_stats(p);
|
||||||
p->stats.imp_updates_accepted);
|
|
||||||
cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
|
|
||||||
p->stats.imp_withdraws_received, p->stats.imp_withdraws_invalid,
|
|
||||||
p->stats.imp_withdraws_ignored, p->stats.imp_withdraws_accepted);
|
|
||||||
cli_msg(-1006, " Export updates: %10u %10u %10u --- %10u",
|
|
||||||
p->stats.exp_updates_received, p->stats.exp_updates_rejected,
|
|
||||||
p->stats.exp_updates_filtered, p->stats.exp_updates_accepted);
|
|
||||||
cli_msg(-1006, " Export withdraws: %10u --- --- --- %10u",
|
|
||||||
p->stats.exp_withdraws_received, p->stats.exp_withdraws_accepted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cli_msg(-1006, "");
|
cli_msg(-1006, "");
|
||||||
|
|
|
@ -344,6 +344,7 @@ static inline int proto_is_pipe(struct proto *p)
|
||||||
{ return p->proto == &proto_pipe; }
|
{ return p->proto == &proto_pipe; }
|
||||||
|
|
||||||
struct rtable *pipe_get_peer_table(struct proto *p);
|
struct rtable *pipe_get_peer_table(struct proto *p);
|
||||||
|
struct proto_stats *pipe_get_peer_stats(struct proto *p);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,7 @@ static inline void
|
||||||
do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, ea_list *tmpa, int class, int refeed)
|
do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, ea_list *tmpa, int class, int refeed)
|
||||||
{
|
{
|
||||||
struct proto *p = a->proto;
|
struct proto *p = a->proto;
|
||||||
|
struct proto_stats *stats = &p->stats;
|
||||||
rte *new0 = new;
|
rte *new0 = new;
|
||||||
rte *old0 = old;
|
rte *old0 = old;
|
||||||
int ok;
|
int ok;
|
||||||
|
@ -169,18 +170,18 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
p->stats.exp_updates_received++;
|
stats->exp_updates_received++;
|
||||||
|
|
||||||
char *drop_reason = NULL;
|
char *drop_reason = NULL;
|
||||||
if ((class & IADDR_SCOPE_MASK) < p->min_scope)
|
if ((class & IADDR_SCOPE_MASK) < p->min_scope)
|
||||||
{
|
{
|
||||||
p->stats.exp_updates_rejected++;
|
stats->exp_updates_rejected++;
|
||||||
drop_reason = "out of scope";
|
drop_reason = "out of scope";
|
||||||
fast_exit_hack = 1;
|
fast_exit_hack = 1;
|
||||||
}
|
}
|
||||||
else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
|
else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
|
||||||
{
|
{
|
||||||
p->stats.exp_updates_rejected++;
|
stats->exp_updates_rejected++;
|
||||||
drop_reason = "rejected by protocol";
|
drop_reason = "rejected by protocol";
|
||||||
}
|
}
|
||||||
else if (ok)
|
else if (ok)
|
||||||
|
@ -188,7 +189,7 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
|
||||||
else if (p->out_filter == FILTER_REJECT ||
|
else if (p->out_filter == FILTER_REJECT ||
|
||||||
p->out_filter && f_run(p->out_filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
|
p->out_filter && f_run(p->out_filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
|
||||||
{
|
{
|
||||||
p->stats.exp_updates_filtered++;
|
stats->exp_updates_filtered++;
|
||||||
drop_reason = "filtered out";
|
drop_reason = "filtered out";
|
||||||
}
|
}
|
||||||
if (drop_reason)
|
if (drop_reason)
|
||||||
|
@ -200,7 +201,7 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
p->stats.exp_withdraws_received++;
|
stats->exp_withdraws_received++;
|
||||||
|
|
||||||
/* Hack: This is here to prevent 'spurious withdraws'
|
/* Hack: This is here to prevent 'spurious withdraws'
|
||||||
for loopback addresses during reload. */
|
for loopback addresses during reload. */
|
||||||
|
@ -249,16 +250,16 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
p->stats.exp_updates_accepted++;
|
stats->exp_updates_accepted++;
|
||||||
else
|
else
|
||||||
p->stats.exp_withdraws_accepted++;
|
stats->exp_withdraws_accepted++;
|
||||||
|
|
||||||
/* Hack: We do not decrease exp_routes during refeed, we instead
|
/* Hack: We do not decrease exp_routes during refeed, we instead
|
||||||
reset exp_routes at the start of refeed. */
|
reset exp_routes at the start of refeed. */
|
||||||
if (new)
|
if (new)
|
||||||
p->stats.exp_routes++;
|
stats->exp_routes++;
|
||||||
if (old && !refeed)
|
if (old && !refeed)
|
||||||
p->stats.exp_routes--;
|
stats->exp_routes--;
|
||||||
|
|
||||||
if (p->debug & D_ROUTES)
|
if (p->debug & D_ROUTES)
|
||||||
{
|
{
|
||||||
|
@ -416,10 +417,16 @@ rte_same(rte *x, rte *y)
|
||||||
static void
|
static void
|
||||||
rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte *new, ea_list *tmpa)
|
rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte *new, ea_list *tmpa)
|
||||||
{
|
{
|
||||||
|
struct proto_stats *stats = &p->stats;
|
||||||
rte *old_best = net->routes;
|
rte *old_best = net->routes;
|
||||||
rte *old = NULL;
|
rte *old = NULL;
|
||||||
rte **k, *r, *s;
|
rte **k, *r, *s;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PIPE
|
||||||
|
if (proto_is_pipe(p) && (p->table == table))
|
||||||
|
stats = pipe_get_peer_stats(p);
|
||||||
|
#endif
|
||||||
|
|
||||||
k = &net->routes; /* Find and remove original route from the same protocol */
|
k = &net->routes; /* Find and remove original route from the same protocol */
|
||||||
while (old = *k)
|
while (old = *k)
|
||||||
{
|
{
|
||||||
|
@ -448,7 +455,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
|
||||||
if (new && rte_same(old, new))
|
if (new && rte_same(old, new))
|
||||||
{
|
{
|
||||||
/* No changes, ignore the new route */
|
/* No changes, ignore the new route */
|
||||||
p->stats.imp_updates_ignored++;
|
stats->imp_updates_ignored++;
|
||||||
rte_trace_in(D_ROUTES, p, new, "ignored");
|
rte_trace_in(D_ROUTES, p, new, "ignored");
|
||||||
rte_free_quick(new);
|
rte_free_quick(new);
|
||||||
old->lastmod = now;
|
old->lastmod = now;
|
||||||
|
@ -462,19 +469,19 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
|
||||||
|
|
||||||
if (!old && !new)
|
if (!old && !new)
|
||||||
{
|
{
|
||||||
p->stats.imp_withdraws_ignored++;
|
stats->imp_withdraws_ignored++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
p->stats.imp_updates_accepted++;
|
stats->imp_updates_accepted++;
|
||||||
else
|
else
|
||||||
p->stats.imp_withdraws_accepted++;
|
stats->imp_withdraws_accepted++;
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
p->stats.imp_routes++;
|
stats->imp_routes++;
|
||||||
if (old)
|
if (old)
|
||||||
p->stats.imp_routes--;
|
stats->imp_routes--;
|
||||||
|
|
||||||
rte_announce(table, RA_ANY, net, new, old, tmpa);
|
rte_announce(table, RA_ANY, net, new, old, tmpa);
|
||||||
|
|
||||||
|
@ -632,6 +639,12 @@ void
|
||||||
rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new)
|
rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new)
|
||||||
{
|
{
|
||||||
ea_list *tmpa = NULL;
|
ea_list *tmpa = NULL;
|
||||||
|
struct proto_stats *stats = &p->stats;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PIPE
|
||||||
|
if (proto_is_pipe(p) && (p->table == table))
|
||||||
|
stats = pipe_get_peer_stats(p);
|
||||||
|
#endif
|
||||||
|
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
if (new)
|
if (new)
|
||||||
|
@ -646,16 +659,16 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
|
||||||
filter = FILTER_ACCEPT;
|
filter = FILTER_ACCEPT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
p->stats.imp_updates_received++;
|
stats->imp_updates_received++;
|
||||||
if (!rte_validate(new))
|
if (!rte_validate(new))
|
||||||
{
|
{
|
||||||
rte_trace_in(D_FILTERS, p, new, "invalid");
|
rte_trace_in(D_FILTERS, p, new, "invalid");
|
||||||
p->stats.imp_updates_invalid++;
|
stats->imp_updates_invalid++;
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
if (filter == FILTER_REJECT)
|
if (filter == FILTER_REJECT)
|
||||||
{
|
{
|
||||||
p->stats.imp_updates_filtered++;
|
stats->imp_updates_filtered++;
|
||||||
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
@ -667,7 +680,7 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
|
||||||
int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
|
int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
|
||||||
if (fr > F_ACCEPT)
|
if (fr > F_ACCEPT)
|
||||||
{
|
{
|
||||||
p->stats.imp_updates_filtered++;
|
stats->imp_updates_filtered++;
|
||||||
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
@ -679,7 +692,7 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
|
||||||
new->flags |= REF_COW;
|
new->flags |= REF_COW;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
p->stats.imp_withdraws_received++;
|
stats->imp_withdraws_received++;
|
||||||
|
|
||||||
rte_recalculate(table, net, p, src, new, tmpa);
|
rte_recalculate(table, net, p, src, new, tmpa);
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
|
|
|
@ -234,6 +234,13 @@ pipe_get_peer_table(struct proto *P)
|
||||||
return p->peer;
|
return p->peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct proto_stats *
|
||||||
|
pipe_get_peer_stats(struct proto *P)
|
||||||
|
{
|
||||||
|
struct pipe_proto *p = (struct pipe_proto *) P;
|
||||||
|
return &p->phantom->p.stats;
|
||||||
|
}
|
||||||
|
|
||||||
struct protocol proto_pipe = {
|
struct protocol proto_pipe = {
|
||||||
name: "Pipe",
|
name: "Pipe",
|
||||||
template: "pipe%d",
|
template: "pipe%d",
|
||||||
|
|
Loading…
Reference in a new issue