Added debugging of communication between protocols and routing tables.
Just ask for "debug routes" if you want to see the routes and "debug filters" if you want even the rejected ones.
This commit is contained in:
parent
c8d5ffafb7
commit
cfd46ee4c5
2 changed files with 98 additions and 19 deletions
4
TODO
4
TODO
|
@ -1,7 +1,6 @@
|
||||||
Core
|
Core
|
||||||
~~~~
|
~~~~
|
||||||
- debug: interfaces
|
- debug: interfaces
|
||||||
- debug: route updates
|
|
||||||
- debug: static
|
- debug: static
|
||||||
- debug: pipe
|
- debug: pipe
|
||||||
- debug: krt
|
- debug: krt
|
||||||
|
@ -9,9 +8,6 @@ Core
|
||||||
- static: check validity of route destination?
|
- static: check validity of route destination?
|
||||||
- static: allow specifying a per-route filter program for setting route attributes?
|
- static: allow specifying a per-route filter program for setting route attributes?
|
||||||
|
|
||||||
- rte_update: check whether all bits not covered by masklen are zero
|
|
||||||
- rte_update: debug mode
|
|
||||||
|
|
||||||
- krt: rescan interfaces when route addition fails?
|
- krt: rescan interfaces when route addition fails?
|
||||||
|
|
||||||
- tagging of external routes?
|
- tagging of external routes?
|
||||||
|
|
107
nest/rt-table.c
107
nest/rt-table.c
|
@ -27,6 +27,8 @@ static linpool *rte_update_pool;
|
||||||
static pool *rt_table_pool;
|
static pool *rt_table_pool;
|
||||||
static list routing_tables;
|
static list routing_tables;
|
||||||
|
|
||||||
|
static void rt_format_via(rte *e, byte *via);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rte_init(struct fib_node *N)
|
rte_init(struct fib_node *N)
|
||||||
{
|
{
|
||||||
|
@ -93,6 +95,29 @@ rte_better(rte *new, rte *old)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rte_trace(struct proto *p, rte *e, int dir, char *msg)
|
||||||
|
{
|
||||||
|
byte via[STD_ADDRESS_P_LENGTH+32];
|
||||||
|
|
||||||
|
rt_format_via(e, via);
|
||||||
|
log(L_TRACE "%s %c %s %I/%d %s", p->name, dir, msg, e->net->n.prefix, e->net->n.pxlen, via);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rte_trace_in(unsigned int flag, struct proto *p, rte *e, char *msg)
|
||||||
|
{
|
||||||
|
if (p->debug & flag)
|
||||||
|
rte_trace(p, e, '<', msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
|
||||||
|
{
|
||||||
|
if (p->debug & flag)
|
||||||
|
rte_trace(p, e, '>', msg);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list *tmpa, int class)
|
do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list *tmpa, int class)
|
||||||
{
|
{
|
||||||
|
@ -103,14 +128,25 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list *
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
int ok;
|
int ok;
|
||||||
if ((class & IADDR_SCOPE_MASK) < p->min_scope ||
|
if ((class & IADDR_SCOPE_MASK) < p->min_scope)
|
||||||
(ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0 ||
|
{
|
||||||
(!ok && (p->out_filter == FILTER_REJECT ||
|
rte_trace_out(D_FILTERS, p, new, "out of scope");
|
||||||
p->out_filter && f_run(p->out_filter, &new, &tmpa, rte_update_pool) > F_ACCEPT)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
new = NULL;
|
new = NULL;
|
||||||
}
|
}
|
||||||
|
else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
|
||||||
|
{
|
||||||
|
rte_trace_out(D_FILTERS, p, new, "rejected by protocol");
|
||||||
|
new = NULL;
|
||||||
|
}
|
||||||
|
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) > F_ACCEPT)
|
||||||
|
{
|
||||||
|
rte_trace_out(D_FILTERS, p, new, "filtered out");
|
||||||
|
new = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (old && p->out_filter)
|
if (old && p->out_filter)
|
||||||
{
|
{
|
||||||
/* FIXME: Do we really need to filter old routes? */
|
/* FIXME: Do we really need to filter old routes? */
|
||||||
|
@ -123,6 +159,15 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list *
|
||||||
old = NULL;
|
old = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (p->debug & D_ROUTES)
|
||||||
|
{
|
||||||
|
if (new && old)
|
||||||
|
rte_trace_out(D_ROUTES, p, new, "replaced");
|
||||||
|
else if (new)
|
||||||
|
rte_trace_out(D_ROUTES, p, new, "added");
|
||||||
|
else
|
||||||
|
rte_trace_out(D_ROUTES, p, old, "removed");
|
||||||
|
}
|
||||||
if (new || old)
|
if (new || old)
|
||||||
p->rt_notify(p, net, new, old, tmpa);
|
p->rt_notify(p, net, new, old, tmpa);
|
||||||
if (new && new != new0) /* Discard temporary rte's */
|
if (new && new != new0) /* Discard temporary rte's */
|
||||||
|
@ -177,7 +222,12 @@ rte_validate(rte *e)
|
||||||
int c;
|
int c;
|
||||||
net *n = e->net;
|
net *n = e->net;
|
||||||
|
|
||||||
ASSERT(!ipa_nonzero(ipa_and(n->n.prefix, ipa_not(ipa_mkmask(n->n.pxlen)))));
|
if (ipa_nonzero(ipa_and(n->n.prefix, ipa_not(ipa_mkmask(n->n.pxlen)))))
|
||||||
|
{
|
||||||
|
log(L_BUG "Ignoring bogus prefix %I/%d received via %s",
|
||||||
|
n->n.prefix, n->n.pxlen, e->attrs->proto->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (n->n.pxlen)
|
if (n->n.pxlen)
|
||||||
{
|
{
|
||||||
c = ipa_classify(n->n.prefix);
|
c = ipa_classify(n->n.prefix);
|
||||||
|
@ -238,6 +288,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, rte *new, ea_list *tmp
|
||||||
rte_announce(table, net, new, old_best, tmpa);
|
rte_announce(table, net, new, old_best, tmpa);
|
||||||
new->next = net->routes;
|
new->next = net->routes;
|
||||||
net->routes = new;
|
net->routes = new;
|
||||||
|
rte_trace_in(D_ROUTES, p, new, "added [best]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -272,6 +323,16 @@ rte_recalculate(rtable *table, net *net, struct proto *p, rte *new, ea_list *tmp
|
||||||
{
|
{
|
||||||
new->next = old_best->next;
|
new->next = old_best->next;
|
||||||
old_best->next = new;
|
old_best->next = new;
|
||||||
|
rte_trace_in(D_ROUTES, p, new, "added");
|
||||||
|
}
|
||||||
|
else if (old && (p->debug & D_ROUTES))
|
||||||
|
{
|
||||||
|
if (old != old_best)
|
||||||
|
rte_trace_in(D_ROUTES, p, old, "removed");
|
||||||
|
else if (net->routes)
|
||||||
|
rte_trace_in(D_ROUTES, p, old, "removed [replaced]");
|
||||||
|
else
|
||||||
|
rte_trace_in(D_ROUTES, p, old, "removed [sole]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (old)
|
if (old)
|
||||||
|
@ -311,8 +372,16 @@ rte_update(rtable *table, net *net, struct proto *p, rte *new)
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
if (!rte_validate(new) || p->in_filter == FILTER_REJECT)
|
if (!rte_validate(new))
|
||||||
|
{
|
||||||
|
rte_trace_in(D_FILTERS, p, new, "invalid");
|
||||||
goto drop;
|
goto drop;
|
||||||
|
}
|
||||||
|
if (p->in_filter == FILTER_REJECT)
|
||||||
|
{
|
||||||
|
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
if (p->make_tmp_attrs)
|
if (p->make_tmp_attrs)
|
||||||
tmpa = p->make_tmp_attrs(new, rte_update_pool);
|
tmpa = p->make_tmp_attrs(new, rte_update_pool);
|
||||||
if (p->in_filter)
|
if (p->in_filter)
|
||||||
|
@ -320,7 +389,10 @@ rte_update(rtable *table, net *net, struct proto *p, rte *new)
|
||||||
ea_list *old_tmpa = tmpa;
|
ea_list *old_tmpa = tmpa;
|
||||||
int fr = f_run(p->in_filter, &new, &tmpa, rte_update_pool);
|
int fr = f_run(p->in_filter, &new, &tmpa, rte_update_pool);
|
||||||
if (fr > F_ACCEPT)
|
if (fr > F_ACCEPT)
|
||||||
|
{
|
||||||
|
rte_trace_in(D_FILTERS, p, new, "filtered out");
|
||||||
goto drop;
|
goto drop;
|
||||||
|
}
|
||||||
if (tmpa != old_tmpa && p->store_tmp_attrs)
|
if (tmpa != old_tmpa && p->store_tmp_attrs)
|
||||||
p->store_tmp_attrs(new, tmpa);
|
p->store_tmp_attrs(new, tmpa);
|
||||||
}
|
}
|
||||||
|
@ -340,8 +412,11 @@ drop:
|
||||||
void
|
void
|
||||||
rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
|
rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
|
||||||
{
|
{
|
||||||
|
net *n = old->net;
|
||||||
|
struct proto *p = old->attrs->proto;
|
||||||
|
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
rte_recalculate(t, old->net, old->attrs->proto, NULL, NULL);
|
rte_recalculate(t, n, p, NULL, NULL);
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,10 +642,8 @@ rt_commit(struct config *new, struct config *old)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
|
rt_format_via(rte *e, byte *via)
|
||||||
{
|
{
|
||||||
byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH];
|
|
||||||
byte tm[TM_RELTIME_BUFFER_SIZE], info[256];
|
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
|
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
|
@ -582,6 +655,16 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
|
||||||
case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
|
case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
|
||||||
default: bsprintf(via, "???");
|
default: bsprintf(via, "???");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
|
||||||
|
{
|
||||||
|
byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH];
|
||||||
|
byte tm[TM_RELTIME_BUFFER_SIZE], info[256];
|
||||||
|
rta *a = e->attrs;
|
||||||
|
|
||||||
|
rt_format_via(e, via);
|
||||||
tm_format_reltime(tm, e->lastmod);
|
tm_format_reltime(tm, e->lastmod);
|
||||||
if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw))
|
if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw))
|
||||||
bsprintf(from, " from %I", a->from);
|
bsprintf(from, " from %I", a->from);
|
||||||
|
|
Loading…
Reference in a new issue