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:
parent
c07c65d6d0
commit
925fe2d3de
@ -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
|
||||||
|
30
nest/proto.c
30
nest/proto.c
@ -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, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user