Added dumping of routing tables (`show route'). This includes filtering.
This commit is contained in:
parent
04a60c689a
commit
730f2e2c8c
7 changed files with 194 additions and 11 deletions
4
TODO
4
TODO
|
@ -48,12 +48,10 @@ shutdown # order system shutdown
|
||||||
configure [<file>]
|
configure [<file>]
|
||||||
debug <what> # dump debugging information to log
|
debug <what> # dump debugging information to log
|
||||||
show <name> # show everything you know about symbol <name>
|
show <name> # show everything you know about symbol <name>
|
||||||
route [<route>] [table <name>] [filter (<name> | { <inline> })] [where <condition>] [all]
|
route [<route>] [table <name>] [filter (<name> | { <inline> })] [where <condition>] [all] <-- WHERE
|
||||||
status # router id, version etc.
|
|
||||||
rip ??? [<name>]
|
rip ??? [<name>]
|
||||||
ospf ??? [<name>]
|
ospf ??? [<name>]
|
||||||
static ??? [<name>]
|
static ??? [<name>]
|
||||||
neighbors # ???
|
|
||||||
filters [<name>]
|
filters [<name>]
|
||||||
(disable|enable|restart) <protocol> # or ALL?
|
(disable|enable|restart) <protocol> # or ALL?
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ CF_DECLS
|
||||||
struct f_tree *e;
|
struct f_tree *e;
|
||||||
struct f_val v;
|
struct f_val v;
|
||||||
struct password_item *p;
|
struct password_item *p;
|
||||||
|
struct rt_show_data *ra;
|
||||||
}
|
}
|
||||||
|
|
||||||
%token END CLI_MARKER
|
%token END CLI_MARKER
|
||||||
|
|
|
@ -18,8 +18,11 @@ Reply codes of BIRD command-line interface
|
||||||
1004 Interface flags
|
1004 Interface flags
|
||||||
1005 Interface summary
|
1005 Interface summary
|
||||||
1006 Protocol details
|
1006 Protocol details
|
||||||
|
1007 Route list
|
||||||
|
1008 Route details
|
||||||
|
|
||||||
8000 Reply too long
|
8000 Reply too long
|
||||||
|
8001 Route not found
|
||||||
|
|
||||||
9000 Command too long
|
9000 Command too long
|
||||||
9001 Parse error
|
9001 Parse error
|
||||||
|
|
|
@ -28,6 +28,7 @@ CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIREC
|
||||||
%type <r> rtable
|
%type <r> rtable
|
||||||
%type <p> password_list password_begin
|
%type <p> password_list password_begin
|
||||||
%type <s> optsym
|
%type <s> optsym
|
||||||
|
%type <ra> r_args
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
|
@ -201,12 +202,49 @@ CF_CLI(SHOW PROTOCOLS, optsym, [<name>], [[Show routing protocols]])
|
||||||
CF_CLI(SHOW PROTOCOLS VERBOSE, optsym, [<name>], [[Show routing protocol details]])
|
CF_CLI(SHOW PROTOCOLS VERBOSE, optsym, [<name>], [[Show routing protocol details]])
|
||||||
{ proto_show($4, 1); } ;
|
{ proto_show($4, 1); } ;
|
||||||
|
|
||||||
|
optsym:
|
||||||
|
SYM
|
||||||
|
| /* empty */ { $$ = NULL; }
|
||||||
|
;
|
||||||
|
|
||||||
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
|
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
|
||||||
{ if_show(); } ;
|
{ if_show(); } ;
|
||||||
|
|
||||||
CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
|
CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
|
||||||
{ if_show_summary(); } ;
|
{ if_show_summary(); } ;
|
||||||
|
|
||||||
|
CF_CLI(SHOW ROUTE, r_args, [<prefix>] [table <t>] [filter <f>] [all], [[Show routing table]])
|
||||||
|
{ rt_show($3); } ;
|
||||||
|
|
||||||
|
r_args:
|
||||||
|
/* empty */ {
|
||||||
|
$$ = cfg_allocz(sizeof(struct rt_show_data));
|
||||||
|
$$->pxlen = 256;
|
||||||
|
$$->filter = FILTER_ACCEPT;
|
||||||
|
$$->table = config->master_rtc->table;
|
||||||
|
}
|
||||||
|
| r_args IPA pxlen {
|
||||||
|
$$ = $1;
|
||||||
|
if ($$->pxlen != 256) cf_error("Only one prefix expected");
|
||||||
|
if (!ip_is_prefix($2, $3)) cf_error("Invalid prefix");
|
||||||
|
$$->prefix = $2;
|
||||||
|
$$->pxlen = $3;
|
||||||
|
}
|
||||||
|
| r_args TABLE SYM {
|
||||||
|
$$ = $1;
|
||||||
|
if ($3->class != SYM_TABLE) cf_error("%s is not a table", $3->name);
|
||||||
|
$$->table = ((struct rtable_config *)$3->def)->table;
|
||||||
|
}
|
||||||
|
| r_args FILTER filter {
|
||||||
|
$$ = $1;
|
||||||
|
$$->filter = $3;
|
||||||
|
}
|
||||||
|
| r_args ALL {
|
||||||
|
$$ = $1;
|
||||||
|
$$->verbose = 1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/* FIXME: These are examples. Remove them soon. */
|
/* FIXME: These are examples. Remove them soon. */
|
||||||
CF_CLI_HELP(TEST, <subsystem>, [[Tests different subsystems]])
|
CF_CLI_HELP(TEST, <subsystem>, [[Tests different subsystems]])
|
||||||
CF_CLI(TEST LEDS, NUM, <N>, [[Flash each LED <N> times]]) { cli_msg(0, "%d", $3); } ;
|
CF_CLI(TEST LEDS, NUM, <N>, [[Flash each LED <N> times]]) { cli_msg(0, "%d", $3); } ;
|
||||||
|
@ -218,11 +256,6 @@ CF_CLI(TEST LONG,,, [[Test long replies]]) {
|
||||||
cli_msg(-2, "Start");
|
cli_msg(-2, "Start");
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
optsym:
|
|
||||||
SYM
|
|
||||||
| /* empty */ { $$ = NULL; }
|
|
||||||
;
|
|
||||||
|
|
||||||
CF_CODE
|
CF_CODE
|
||||||
|
|
||||||
/* FIXME: Test only, remove */
|
/* FIXME: Test only, remove */
|
||||||
|
|
14
nest/route.h
14
nest/route.h
|
@ -15,6 +15,9 @@
|
||||||
|
|
||||||
struct protocol;
|
struct protocol;
|
||||||
struct proto;
|
struct proto;
|
||||||
|
struct symbol;
|
||||||
|
struct filter;
|
||||||
|
struct cli;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic data structure for storing network prefixes. Also used
|
* Generic data structure for storing network prefixes. Also used
|
||||||
|
@ -186,6 +189,16 @@ void rt_feed_baby(struct proto *p);
|
||||||
void rt_prune(rtable *tab);
|
void rt_prune(rtable *tab);
|
||||||
void rt_prune_all(void);
|
void rt_prune_all(void);
|
||||||
|
|
||||||
|
struct rt_show_data {
|
||||||
|
ip_addr prefix;
|
||||||
|
unsigned pxlen;
|
||||||
|
rtable *table;
|
||||||
|
struct filter *filter;
|
||||||
|
int verbose;
|
||||||
|
struct fib_iterator fit;
|
||||||
|
};
|
||||||
|
void rt_show(struct rt_show_data *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Route Attributes
|
* Route Attributes
|
||||||
*
|
*
|
||||||
|
@ -311,6 +324,7 @@ static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); }
|
||||||
void rta_dump(rta *);
|
void rta_dump(rta *);
|
||||||
void rta_dump_all(void);
|
void rta_dump_all(void);
|
||||||
static inline eattr * rta_find(rta *a, unsigned ea) { return ea_find(a->eattrs, ea); }
|
static inline eattr * rta_find(rta *a, unsigned ea) { return ea_find(a->eattrs, ea); }
|
||||||
|
void rta_show(struct cli *, rta *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default protocol preferences
|
* Default protocol preferences
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
|
#include "nest/cli.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -347,12 +348,11 @@ rta_dump(rta *a)
|
||||||
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP", "RTS_RIP_EXT",
|
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP", "RTS_RIP_EXT",
|
||||||
"RTS_OSPF", "RTS_OSPF_EXT", "RTS_OSPF_IA",
|
"RTS_OSPF", "RTS_OSPF_EXT", "RTS_OSPF_IA",
|
||||||
"RTS_OSPF_BOUNDARY", "RTS_BGP" };
|
"RTS_OSPF_BOUNDARY", "RTS_BGP" };
|
||||||
static char *sco[] = { "HOST", "LINK", "SITE", "UNIV" };
|
|
||||||
static char *rtc[] = { "", " BC", " MC", " AC" };
|
static char *rtc[] = { "", " BC", " MC", " AC" };
|
||||||
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
|
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
|
||||||
|
|
||||||
debug("p=%s uc=%d %s %s%s%s",
|
debug("p=%s uc=%d %s %s%s%s",
|
||||||
a->proto->name, a->uc, rts[a->source], sco[a->scope], rtc[a->cast],
|
a->proto->name, a->uc, rts[a->source], ip_scope_text(a->scope), rtc[a->cast],
|
||||||
rtd[a->dest]);
|
rtd[a->dest]);
|
||||||
if (a->flags & RTF_EXTERIOR)
|
if (a->flags & RTF_EXTERIOR)
|
||||||
debug(" EXT");
|
debug(" EXT");
|
||||||
|
@ -387,6 +387,18 @@ rta_dump_all(void)
|
||||||
debug("\n");
|
debug("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rta_show(struct cli *c, rta *a)
|
||||||
|
{
|
||||||
|
static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect",
|
||||||
|
"RIP", "RIP-ext", "OSPF", "OSPF-ext", "OSPF-IA", "OSPF-boundary",
|
||||||
|
"BGP" };
|
||||||
|
static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" };
|
||||||
|
|
||||||
|
cli_printf(c, -1008, "\tType: %s %s %s", src_names[a->source], cast_names[a->cast], ip_scope_text(a->scope));
|
||||||
|
/* FIXME: Here we probably should print the dynamic attributes... */
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rta_init(void)
|
rta_init(void)
|
||||||
{
|
{
|
||||||
|
|
124
nest/rt-table.c
124
nest/rt-table.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* BIRD -- Routing Table
|
* BIRD -- Routing Table
|
||||||
*
|
*
|
||||||
* (c) 1998 Martin Mares <mj@ucw.cz>
|
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
||||||
*
|
*
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*/
|
*/
|
||||||
|
@ -13,8 +13,11 @@
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
|
#include "nest/cli.h"
|
||||||
|
#include "nest/iface.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/event.h"
|
#include "lib/event.h"
|
||||||
|
#include "lib/string.h"
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
|
|
||||||
|
@ -489,3 +492,122 @@ rt_commit(struct config *c)
|
||||||
r->table = t;
|
r->table = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CLI commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
switch (a->dest)
|
||||||
|
{
|
||||||
|
case RTD_ROUTER: bsprintf(via, "via %I on %s", a->gw, a->iface->name); break;
|
||||||
|
case RTD_DEVICE: bsprintf(via, "dev %s", a->iface->name); break;
|
||||||
|
case RTD_BLACKHOLE: bsprintf(via, "blackhole"); break;
|
||||||
|
case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
|
||||||
|
case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
|
||||||
|
default: bsprintf(via, "???");
|
||||||
|
}
|
||||||
|
tm_format_reltime(tm, e->lastmod);
|
||||||
|
if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw))
|
||||||
|
bsprintf(from, " from %I", a->from);
|
||||||
|
else
|
||||||
|
from[0] = 0;
|
||||||
|
if (a->proto->proto->get_route_info)
|
||||||
|
a->proto->proto->get_route_info(e, info);
|
||||||
|
else
|
||||||
|
bsprintf(info, " (%d)", e->pref);
|
||||||
|
cli_printf(c, -1007, "%-18s %s [%s %s%s]%s", ia, via, a->proto->name, tm, from, info);
|
||||||
|
if (d->verbose)
|
||||||
|
{
|
||||||
|
rta_show(c, a);
|
||||||
|
if (a->proto->proto->show_route_data)
|
||||||
|
a->proto->proto->show_route_data(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
|
{
|
||||||
|
rte *e, *ee;
|
||||||
|
byte ia[STD_ADDRESS_P_LENGTH+8];
|
||||||
|
|
||||||
|
bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
|
||||||
|
for(e=n->routes; e; e=e->next)
|
||||||
|
{
|
||||||
|
struct ea_list *tmpa = NULL;
|
||||||
|
ee = e;
|
||||||
|
rte_update_lock(); /* We use the update buffer for filtering */
|
||||||
|
if (d->filter == FILTER_ACCEPT || f_run(d->filter, &ee, &tmpa, rte_update_pool) <= F_MODIFY)
|
||||||
|
{
|
||||||
|
rt_show_rte(c, ia, e, d);
|
||||||
|
ia[0] = 0;
|
||||||
|
}
|
||||||
|
if (e != ee)
|
||||||
|
rte_free(ee);
|
||||||
|
rte_update_unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rt_show_cont(struct cli *c)
|
||||||
|
{
|
||||||
|
struct rt_show_data *d = c->rover;
|
||||||
|
unsigned max = 1; /* FIXME: After some debugging, increase to reasonable amount */
|
||||||
|
struct fib *fib = &d->table->fib;
|
||||||
|
struct fib_iterator *it = &d->fit;
|
||||||
|
|
||||||
|
FIB_ITERATE_START(fib, it, f)
|
||||||
|
{
|
||||||
|
net *n = (net *) f;
|
||||||
|
if (!max--)
|
||||||
|
{
|
||||||
|
FIB_ITERATE_PUT(it, f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rt_show_net(c, n, d);
|
||||||
|
}
|
||||||
|
FIB_ITERATE_END(f);
|
||||||
|
cli_printf(c, 0, "");
|
||||||
|
c->cont = c->cleanup = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rt_show_cleanup(struct cli *c)
|
||||||
|
{
|
||||||
|
struct rt_show_data *d = c->rover;
|
||||||
|
|
||||||
|
/* Unlink the iterator */
|
||||||
|
fit_get(&d->table->fib, &d->fit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rt_show(struct rt_show_data *d)
|
||||||
|
{
|
||||||
|
struct rtable_config *tc;
|
||||||
|
net *n;
|
||||||
|
|
||||||
|
if (d->pxlen == 256)
|
||||||
|
{
|
||||||
|
FIB_ITERATE_INIT(&d->fit, &d->table->fib);
|
||||||
|
this_cli->cont = rt_show_cont;
|
||||||
|
this_cli->cleanup = rt_show_cleanup;
|
||||||
|
this_cli->rover = d;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = fib_find(&d->table->fib, &d->prefix, d->pxlen);
|
||||||
|
if (n)
|
||||||
|
{
|
||||||
|
rt_show_net(this_cli, n, d);
|
||||||
|
cli_msg(0, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cli_msg(8001, "Network not in table");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue