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>]
|
||||
debug <what> # dump debugging information to log
|
||||
show <name> # show everything you know about symbol <name>
|
||||
route [<route>] [table <name>] [filter (<name> | { <inline> })] [where <condition>] [all]
|
||||
status # router id, version etc.
|
||||
route [<route>] [table <name>] [filter (<name> | { <inline> })] [where <condition>] [all] <-- WHERE
|
||||
rip ??? [<name>]
|
||||
ospf ??? [<name>]
|
||||
static ??? [<name>]
|
||||
neighbors # ???
|
||||
filters [<name>]
|
||||
(disable|enable|restart) <protocol> # or ALL?
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ CF_DECLS
|
|||
struct f_tree *e;
|
||||
struct f_val v;
|
||||
struct password_item *p;
|
||||
struct rt_show_data *ra;
|
||||
}
|
||||
|
||||
%token END CLI_MARKER
|
||||
|
|
|
@ -18,8 +18,11 @@ Reply codes of BIRD command-line interface
|
|||
1004 Interface flags
|
||||
1005 Interface summary
|
||||
1006 Protocol details
|
||||
1007 Route list
|
||||
1008 Route details
|
||||
|
||||
8000 Reply too long
|
||||
8001 Route not found
|
||||
|
||||
9000 Command too long
|
||||
9001 Parse error
|
||||
|
|
|
@ -28,6 +28,7 @@ CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIREC
|
|||
%type <r> rtable
|
||||
%type <p> password_list password_begin
|
||||
%type <s> optsym
|
||||
%type <ra> r_args
|
||||
|
||||
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]])
|
||||
{ proto_show($4, 1); } ;
|
||||
|
||||
optsym:
|
||||
SYM
|
||||
| /* empty */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
|
||||
{ if_show(); } ;
|
||||
|
||||
CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
|
||||
{ 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. */
|
||||
CF_CLI_HELP(TEST, <subsystem>, [[Tests different subsystems]])
|
||||
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");
|
||||
} ;
|
||||
|
||||
optsym:
|
||||
SYM
|
||||
| /* empty */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
CF_CODE
|
||||
|
||||
/* FIXME: Test only, remove */
|
||||
|
|
14
nest/route.h
14
nest/route.h
|
@ -15,6 +15,9 @@
|
|||
|
||||
struct protocol;
|
||||
struct proto;
|
||||
struct symbol;
|
||||
struct filter;
|
||||
struct cli;
|
||||
|
||||
/*
|
||||
* 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_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
|
||||
*
|
||||
|
@ -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_all(void);
|
||||
static inline eattr * rta_find(rta *a, unsigned ea) { return ea_find(a->eattrs, ea); }
|
||||
void rta_show(struct cli *, rta *);
|
||||
|
||||
/*
|
||||
* Default protocol preferences
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nest/route.h"
|
||||
#include "nest/protocol.h"
|
||||
#include "nest/iface.h"
|
||||
#include "nest/cli.h"
|
||||
#include "lib/resource.h"
|
||||
|
||||
/*
|
||||
|
@ -347,12 +348,11 @@ rta_dump(rta *a)
|
|||
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP", "RTS_RIP_EXT",
|
||||
"RTS_OSPF", "RTS_OSPF_EXT", "RTS_OSPF_IA",
|
||||
"RTS_OSPF_BOUNDARY", "RTS_BGP" };
|
||||
static char *sco[] = { "HOST", "LINK", "SITE", "UNIV" };
|
||||
static char *rtc[] = { "", " BC", " MC", " AC" };
|
||||
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
|
||||
|
||||
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]);
|
||||
if (a->flags & RTF_EXTERIOR)
|
||||
debug(" EXT");
|
||||
|
@ -387,6 +387,18 @@ rta_dump_all(void)
|
|||
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
|
||||
rta_init(void)
|
||||
{
|
||||
|
|
124
nest/rt-table.c
124
nest/rt-table.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
@ -13,8 +13,11 @@
|
|||
#include "nest/bird.h"
|
||||
#include "nest/route.h"
|
||||
#include "nest/protocol.h"
|
||||
#include "nest/cli.h"
|
||||
#include "nest/iface.h"
|
||||
#include "lib/resource.h"
|
||||
#include "lib/event.h"
|
||||
#include "lib/string.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
|
||||
|
@ -489,3 +492,122 @@ rt_commit(struct config *c)
|
|||
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