Commit 925fe2d3 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Implements route statistics and fixes some minor bugs.

parent c07c65d6
......@@ -1450,7 +1450,7 @@ of routes from the primary table to the secondary one, import filters control th
direction.
<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
protocols send and receive routes. Retransmitted route will have the
source set to the Pipe protocol, which may limit access to protocol
......
......@@ -512,6 +512,9 @@ static void
proto_fell_down(struct proto *p)
{
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);
proto_rethink_goal(p);
}
......@@ -693,9 +696,30 @@ proto_do_show(struct proto *p, int verbose)
buf);
if (verbose)
{
cli_msg(-1006, "\tPreference: %d", p->preference);
cli_msg(-1006, "\tInput filter: %s", filter_name(p->in_filter));
cli_msg(-1006, "\tOutput filter: %s", filter_name(p->out_filter));
cli_msg(-1006, " Preference: %d", p->preference);
cli_msg(-1006, " Input filter: %s", filter_name(p->in_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, "");
}
}
......
......@@ -87,6 +87,31 @@ struct proto_config {
/* 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 {
node n; /* Node in *_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 */
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 */
struct proto_stats stats; /* Current protocol statistics */
/*
* General protocol hooks:
......
......@@ -167,16 +167,27 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
if (new)
{
p->stats.exp_updates_received++;
char *drop_reason = NULL;
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)
drop_reason = "rejected by protocol";
{
p->stats.exp_updates_rejected++;
drop_reason = "rejected by protocol";
}
else if (ok)
rte_trace_out(D_FILTERS, p, new, "forced accept by protocol");
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)
drop_reason = "filtered out";
{
p->stats.exp_updates_filtered++;
drop_reason = "filtered out";
}
if (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;
}
}
if (old && p->out_filter)
else
p->stats.exp_withdraws_received++;
if (old)
{
if (p->out_filter == FILTER_REJECT)
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;
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)
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 (new && old)
......@@ -210,8 +238,6 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
else if (old)
rte_trace_out(D_ROUTES, p, old, "removed");
}
if (!new && !old)
return;
if (!new)
p->rt_notify(p, net, NULL, old, NULL);
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;
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)
{
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))
{
/* No changes, ignore the new route */
p->stats.imp_updates_ignored++;
rte_trace_in(D_ROUTES, p, new, "ignored");
rte_free_quick(new);
old->lastmod = now;
......@@ -374,6 +409,22 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
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);
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)
filter = FILTER_ACCEPT;
p->stats.imp_updates_received++;
if (!rte_validate(new))
{
rte_trace_in(D_FILTERS, p, new, "invalid");
p->stats.imp_updates_invalid++;
goto drop;
}
if (filter == FILTER_REJECT)
{
p->stats.imp_updates_filtered++;
rte_trace_in(D_FILTERS, p, new, "filtered out");
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);
if (fr > F_ACCEPT)
{
p->stats.imp_updates_filtered++;
rte_trace_in(D_FILTERS, p, new, "filtered out");
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->flags |= REF_COW;
}
else
p->stats.imp_withdraws_received++;
rte_recalculate(table, net, p, src, new, tmpa);
rte_update_unlock();
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 (ok && d->export_mode)
{
int ic = (p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0);
if (ic < 0)
int class = ipa_classify(n->n.prefix);
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;
else if (!ic && d->export_mode > 1)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment