Added dumping of routing tables (`show route'). This includes filtering.

This commit is contained in:
Martin Mares 1999-12-01 15:10:21 +00:00
parent 04a60c689a
commit 730f2e2c8c
7 changed files with 194 additions and 11 deletions

4
TODO
View file

@ -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?

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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)
{ {

View file

@ -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");
}
}