0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-17 16:48:43 +00:00

Implements route statistics and fixes some minor bugs.

This commit is contained in:
Ondrej Zajicek 2009-06-04 01:22:56 +02:00
parent c07c65d6d0
commit 925fe2d3de
4 changed files with 124 additions and 13 deletions

View File

@ -1450,7 +1450,7 @@ of routes from the primary table to the secondary one, import filters control th
direction. direction.
<p>The Pipe protocol may work in the opaque mode or in the transparent <p>The Pipe protocol may work in the opaque mode or in the transparent
mode. In the opaque mode, thee Pipe protocol retransmits optimal route mode. In the opaque mode, the Pipe protocol retransmits optimal route
from one table to the other table in a similar way like other from one table to the other table in a similar way like other
protocols send and receive routes. Retransmitted route will have the protocols send and receive routes. Retransmitted route will have the
source set to the Pipe protocol, which may limit access to protocol source set to the Pipe protocol, which may limit access to protocol

View File

@ -512,6 +512,9 @@ static void
proto_fell_down(struct proto *p) proto_fell_down(struct proto *p)
{ {
DBG("Protocol %s down\n", p->name); DBG("Protocol %s down\n", p->name);
ASSERT(p->stats.imp_routes == 0);
bzero(&p->stats, sizeof(struct proto_stats));
rt_unlock_table(p->table); rt_unlock_table(p->table);
proto_rethink_goal(p); proto_rethink_goal(p);
} }
@ -693,9 +696,30 @@ proto_do_show(struct proto *p, int verbose)
buf); buf);
if (verbose) if (verbose)
{ {
cli_msg(-1006, "\tPreference: %d", p->preference); cli_msg(-1006, " Preference: %d", p->preference);
cli_msg(-1006, "\tInput filter: %s", filter_name(p->in_filter)); cli_msg(-1006, " Input filter: %s", filter_name(p->in_filter));
cli_msg(-1006, "\tOutput filter: %s", filter_name(p->out_filter)); cli_msg(-1006, " Output filter: %s", filter_name(p->out_filter));
if (p->proto_state != PS_DOWN)
{
cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred",
p->stats.imp_routes, p->stats.exp_routes, p->stats.pref_routes);
cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
p->stats.imp_updates_received, p->stats.imp_updates_invalid,
p->stats.imp_updates_filtered, p->stats.imp_updates_ignored,
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, "");
} }
} }

View File

@ -87,6 +87,31 @@ struct proto_config {
/* Protocol-specific data follow... */ /* Protocol-specific data follow... */
}; };
/* Protocol statistics */
struct proto_stats {
/* Import - from protocol to core */
u32 imp_routes; /* Number of routes successfully imported to the (adjacent) routing table */
u32 pref_routes; /* Number of routes that are preferred, sum over all routing table */
u32 imp_updates_received; /* Number of route updates received */
u32 imp_updates_invalid; /* Number of route updates rejected as invalid */
u32 imp_updates_filtered; /* Number of route updates rejected by filters */
u32 imp_updates_ignored; /* Number of route updates rejected as already in route table */
u32 imp_updates_accepted; /* Number of route updates accepted and imported */
u32 imp_withdraws_received; /* Number of route withdraws received */
u32 imp_withdraws_invalid; /* Number of route withdraws rejected as invalid */
u32 imp_withdraws_ignored; /* Number of route withdraws rejected as already not in route table */
u32 imp_withdraws_accepted; /* Number of route withdraws accepted and processed */
/* Export - from core to protocol */
u32 exp_routes; /* Number of routes successfully exported to the protocol */
u32 exp_updates_received; /* Number of route updates received */
u32 exp_updates_rejected; /* Number of route updates rejected by protocol */
u32 exp_updates_filtered; /* Number of route updates rejected by filters */
u32 exp_updates_accepted; /* Number of route updates accepted and exported */
u32 exp_withdraws_received; /* Number of route withdraws received */
u32 exp_withdraws_accepted; /* Number of route withdraws accepted and processed */
};
struct proto { struct proto {
node n; /* Node in *_proto_list */ node n; /* Node in *_proto_list */
node glob_node; /* Node in global proto_list */ node glob_node; /* Node in global proto_list */
@ -109,6 +134,7 @@ struct proto {
u32 hash_key; /* Random key used for hashing of neighbors */ u32 hash_key; /* Random key used for hashing of neighbors */
bird_clock_t last_state_change; /* Time of last state transition */ bird_clock_t last_state_change; /* Time of last state transition */
char *last_state_name_announced; /* Last state name we've announced to the user */ char *last_state_name_announced; /* Last state name we've announced to the user */
struct proto_stats stats; /* Current protocol statistics */
/* /*
* General protocol hooks: * General protocol hooks:

View File

@ -167,16 +167,27 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
if (new) if (new)
{ {
p->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)
drop_reason = "out of scope"; {
p->stats.exp_updates_rejected++;
drop_reason = "out of scope";
}
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)
drop_reason = "rejected by protocol"; {
p->stats.exp_updates_rejected++;
drop_reason = "rejected by protocol";
}
else if (ok) else if (ok)
rte_trace_out(D_FILTERS, p, new, "forced accept by protocol"); rte_trace_out(D_FILTERS, p, new, "forced accept by protocol");
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)
drop_reason = "filtered out"; {
p->stats.exp_updates_filtered++;
drop_reason = "filtered out";
}
if (drop_reason) if (drop_reason)
{ {
rte_trace_out(D_FILTERS, p, new, drop_reason); rte_trace_out(D_FILTERS, p, new, drop_reason);
@ -185,7 +196,10 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
new = NULL; new = NULL;
} }
} }
if (old && p->out_filter) else
p->stats.exp_withdraws_received++;
if (old)
{ {
if (p->out_filter == FILTER_REJECT) if (p->out_filter == FILTER_REJECT)
old = NULL; old = NULL;
@ -193,7 +207,7 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
{ {
ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL; ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL;
ok = p->import_control ? p->import_control(p, &old, &tmpb, rte_update_pool) : 0; ok = p->import_control ? p->import_control(p, &old, &tmpb, rte_update_pool) : 0;
if (ok < 0 || (!ok && f_run(p->out_filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)) if (ok < 0 || (!ok && p->out_filter && f_run(p->out_filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
{ {
if (old != old0) if (old != old0)
rte_free(old); rte_free(old);
@ -201,6 +215,20 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
} }
} }
} }
if (!new && !old)
return;
if (new)
p->stats.exp_updates_accepted++;
else
p->stats.exp_withdraws_accepted++;
if (new)
p->stats.exp_routes++;
if (old)
p->stats.exp_routes--;
if (p->debug & D_ROUTES) if (p->debug & D_ROUTES)
{ {
if (new && old) if (new && old)
@ -210,8 +238,6 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
else if (old) else if (old)
rte_trace_out(D_ROUTES, p, old, "removed"); rte_trace_out(D_ROUTES, p, old, "removed");
} }
if (!new && !old)
return;
if (!new) if (!new)
p->rt_notify(p, net, NULL, old, NULL); p->rt_notify(p, net, NULL, old, NULL);
else if (tmpa) else if (tmpa)
@ -266,6 +292,14 @@ rte_announce(rtable *tab, int type, net *net, rte *new, rte *old, ea_list *tmpa)
struct announce_hook *a; struct announce_hook *a;
int class = ipa_classify(net->n.prefix); int class = ipa_classify(net->n.prefix);
if (type == RA_OPTIMAL)
{
if (new)
new->attrs->proto->stats.pref_routes++;
if (old)
old->attrs->proto->stats.pref_routes--;
}
WALK_LIST(a, tab->hooks) WALK_LIST(a, tab->hooks)
{ {
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING); ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
@ -363,6 +397,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++;
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;
@ -374,6 +409,22 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
k = &old->next; k = &old->next;
} }
if (!old && !new)
{
p->stats.imp_withdraws_ignored++;
return;
}
if (new)
p->stats.imp_updates_accepted++;
else
p->stats.imp_withdraws_accepted++;
if (new)
p->stats.imp_routes++;
if (old)
p->stats.imp_routes--;
rte_announce(table, RA_ANY, net, new, old, tmpa); rte_announce(table, RA_ANY, net, new, old, tmpa);
if (new && rte_better(new, old_best)) /* It's a new optimal route => announce and relink it */ if (new && rte_better(new, old_best)) /* It's a new optimal route => announce and relink it */
@ -514,13 +565,16 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
if (p->table != table) if (p->table != table)
filter = FILTER_ACCEPT; filter = FILTER_ACCEPT;
p->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++;
goto drop; goto drop;
} }
if (filter == FILTER_REJECT) if (filter == FILTER_REJECT)
{ {
p->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;
} }
@ -532,6 +586,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++;
rte_trace_in(D_FILTERS, p, new, "filtered out"); rte_trace_in(D_FILTERS, p, new, "filtered out");
goto drop; goto drop;
} }
@ -542,6 +597,9 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
new->attrs = rta_lookup(new->attrs); new->attrs = rta_lookup(new->attrs);
new->flags |= REF_COW; new->flags |= REF_COW;
} }
else
p->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();
return; return;
@ -1025,8 +1083,11 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
if (p2 && p2 != p0) ok = 0; if (p2 && p2 != p0) ok = 0;
if (ok && d->export_mode) if (ok && d->export_mode)
{ {
int ic = (p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0); int class = ipa_classify(n->n.prefix);
if (ic < 0) int ic;
if ((class & IADDR_SCOPE_MASK) < p1->min_scope)
ok = 0;
else if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
ok = 0; ok = 0;
else if (!ic && d->export_mode > 1) else if (!ic && d->export_mode > 1)
{ {