Added commands show route protocol <p>' and show route import <p>' which

show the routing table as exported to the protocol given resp. as returned
from its import control hook.

To get handling of filtered extended attributes right (even in the old
`show route where <filter>' command), the get_route_info hook gets an
attribute list and all protocol specific rte attributes are contained
there as temporary ones. Updated RIP to do that.

Added ea_append() which joins two ea_list's.
This commit is contained in:
Martin Mares 2000-05-06 22:57:39 +00:00
parent 84f0700205
commit ce1da96ee7
8 changed files with 103 additions and 20 deletions

6
TODO
View file

@ -13,11 +13,9 @@ Core
- filter-defined internal attributes - filter-defined internal attributes
- netlink: realms - netlink: realms
- bgp: wait on restart - filters: deletion of mandatory attributes?
Commands - bgp: wait on restart
~~~~~~~~
- showing of routing table as seen by given protocol
Documentation Documentation
~~~~~~~~~~~~~ ~~~~~~~~~~~~~

View file

@ -41,6 +41,8 @@ Reply codes of BIRD command-line interface
8001 Route not found 8001 Route not found
8002 Configuration file error 8002 Configuration file error
8003 No protocols match 8003 No protocols match
8004 Stopped due to reconfiguration
8005 Protocol is down => cannot dump
9000 Command too long 9000 Command too long
9001 Parse error 9001 Parse error

View file

@ -22,6 +22,7 @@ CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS) CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY)
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
RIP, OSPF, OSPF_EXT, OSPF_IA, OSPF_BOUNDARY, BGP, PIPE) RIP, OSPF, OSPF_EXT, OSPF_IA, OSPF_BOUNDARY, BGP, PIPE)
@ -32,7 +33,7 @@ CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIREC
%type <p> password_list password_begin %type <p> password_list password_begin
%type <s> optsym %type <s> optsym
%type <ra> r_args %type <ra> r_args
%type <i> echo_mask echo_size debug_mask debug_list debug_flag %type <i> echo_mask echo_size debug_mask debug_list debug_flag import_or_proto
%type <t> proto_patt %type <t> proto_patt
CF_GRAMMAR CF_GRAMMAR
@ -239,7 +240,7 @@ CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
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]]) CF_CLI(SHOW ROUTE, r_args, [<prefix>] [table <t>] [filter <f>] [all] [primary] [(import|protocol) <p>], [[Show routing table]])
{ rt_show($3); } ; { rt_show($3); } ;
r_args: r_args:
@ -275,6 +276,25 @@ r_args:
$$ = $1; $$ = $1;
$$->verbose = 1; $$->verbose = 1;
} }
| r_args PRIMARY {
$$ = $1;
$$->primary_only = 1;
}
| r_args import_or_proto SYM {
struct proto_config *c = (struct proto_config *) $3->def;
$$ = $1;
if ($$->import_mode) cf_error("Protocol specified twice");
if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
$$->import_mode = $2;
$$->primary_only = 1;
$$->import_protocol = c->proto;
$$->running_on_config = c->proto->cf->global;
}
;
import_or_proto:
IMPORT { $$ = 1; }
| PROTOCOL { $$ = 2; }
; ;
CF_CLI(SHOW SYMBOLS, optsym, [<symbol>], [[Show all known symbolic names]]) CF_CLI(SHOW SYMBOLS, optsym, [<symbol>], [[Show all known symbolic names]])

View file

@ -47,7 +47,7 @@ struct protocol {
int (*start)(struct proto *); /* Start the instance */ int (*start)(struct proto *); /* Start the instance */
int (*shutdown)(struct proto *); /* Stop the instance */ int (*shutdown)(struct proto *); /* Stop the instance */
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */ void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */ void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
int (*get_attr)(struct eattr *, byte *buf); /* ASCIIfy dynamic attribute (returns GA_*) */ int (*get_attr)(struct eattr *, byte *buf); /* ASCIIfy dynamic attribute (returns GA_*) */
}; };

View file

@ -206,6 +206,9 @@ struct rt_show_data {
struct filter *filter; struct filter *filter;
int verbose; int verbose;
struct fib_iterator fit; struct fib_iterator fit;
struct proto *import_protocol;
int import_mode, primary_only;
struct config *running_on_config;
}; };
void rt_show(struct rt_show_data *); void rt_show(struct rt_show_data *);
@ -326,6 +329,7 @@ int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical
unsigned int ea_hash(ea_list *e); /* Calculate 16-bit hash value */ unsigned int ea_hash(ea_list *e); /* Calculate 16-bit hash value */
void ea_format(eattr *e, byte *buf); void ea_format(eattr *e, byte *buf);
#define EA_FORMAT_BUF_SIZE 256 #define EA_FORMAT_BUF_SIZE 256
ea_list *ea_append(ea_list *to, ea_list *what);
void rta_init(void); void rta_init(void);
rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */ rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */
@ -335,7 +339,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 *); void rta_show(struct cli *, rta *, ea_list *);
extern struct protocol *attr_class_to_protocol[EAP_MAX]; extern struct protocol *attr_class_to_protocol[EAP_MAX];

View file

@ -380,6 +380,20 @@ ea_hash(ea_list *e)
return h; return h;
} }
ea_list *
ea_append(ea_list *to, ea_list *what)
{
ea_list *res;
if (!to)
return what;
res = to;
while (to->next)
to = to->next;
to->next = what;
return res;
}
/* /*
* rta's * rta's
*/ */
@ -551,18 +565,19 @@ rta_dump_all(void)
} }
void void
rta_show(struct cli *c, rta *a) rta_show(struct cli *c, rta *a, ea_list *eal)
{ {
static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect", static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect",
"RIP", "RIP-ext", "OSPF", "OSPF-ext", "OSPF-IA", "OSPF-boundary", "RIP", "RIP-ext", "OSPF", "OSPF-ext", "OSPF-IA", "OSPF-boundary",
"BGP" }; "BGP" };
static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" }; static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" };
ea_list *eal;
int i; int i;
byte buf[EA_FORMAT_BUF_SIZE]; byte buf[EA_FORMAT_BUF_SIZE];
cli_printf(c, -1008, "\tType: %s %s %s", src_names[a->source], cast_names[a->cast], ip_scope_text(a->scope)); cli_printf(c, -1008, "\tType: %s %s %s", src_names[a->source], cast_names[a->cast], ip_scope_text(a->scope));
for(eal=a->eattrs; eal; eal=eal->next) if (!eal)
eal = a->eattrs;
for(; eal; eal=eal->next)
for(i=0; i<eal->count; i++) for(i=0; i<eal->count; i++)
{ {
ea_format(&eal->attrs[i], buf); ea_format(&eal->attrs[i], buf);

View file

@ -683,7 +683,7 @@ rt_format_via(rte *e, byte *via)
} }
static void static void
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d) rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
{ {
byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+6]; byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+6];
byte tm[TM_RELTIME_BUFFER_SIZE], info[256]; byte tm[TM_RELTIME_BUFFER_SIZE], info[256];
@ -695,13 +695,21 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
bsprintf(from, " from %I", a->from); bsprintf(from, " from %I", a->from);
else else
from[0] = 0; from[0] = 0;
if (a->proto->proto->get_route_info || d->verbose)
{
/* Need to normalize the extended attributes */
ea_list *t = tmpa;
t = ea_append(t, a->eattrs);
tmpa = alloca(ea_scan(t));
ea_merge(t, tmpa);
}
if (a->proto->proto->get_route_info) if (a->proto->proto->get_route_info)
a->proto->proto->get_route_info(e, info); a->proto->proto->get_route_info(e, info, tmpa);
else else
bsprintf(info, " (%d)", e->pref); bsprintf(info, " (%d)", e->pref);
cli_printf(c, -1007, "%-18s %s [%s %s%s]%s", ia, via, a->proto->name, tm, from, info); cli_printf(c, -1007, "%-18s %s [%s %s%s]%s", ia, via, a->proto->name, tm, from, info);
if (d->verbose) if (d->verbose)
rta_show(c, a); rta_show(c, a, tmpa);
} }
static void static void
@ -709,21 +717,40 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{ {
rte *e, *ee; rte *e, *ee;
byte ia[STD_ADDRESS_P_LENGTH+8]; byte ia[STD_ADDRESS_P_LENGTH+8];
int ok;
bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen); bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
for(e=n->routes; e; e=e->next) for(e=n->routes; e; e=e->next)
{ {
struct ea_list *tmpa = NULL; struct ea_list *tmpa, *old_tmpa;
struct proto *p0 = e->attrs->proto;
struct proto *p1 = d->import_protocol;
ee = e; ee = e;
rte_update_lock(); /* We use the update buffer for filtering */ rte_update_lock(); /* We use the update buffer for filtering */
if (d->filter == FILTER_ACCEPT || f_run(d->filter, &ee, &tmpa, rte_update_pool, 0) <= F_ACCEPT) old_tmpa = tmpa = p0->make_tmp_attrs ? p0->make_tmp_attrs(e, rte_update_pool) : NULL;
ok = (d->filter == FILTER_ACCEPT || f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
if (ok && d->import_mode)
{ {
rt_show_rte(c, ia, e, d); int ic = (p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0);
if (ic < 0)
ok = 0;
else if (!ic && d->import_mode > 1)
{
if (p1->out_filter == FILTER_REJECT ||
p1->out_filter && f_run(p1->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
ok = 0;
}
}
if (ok)
{
rt_show_rte(c, ia, e, d, tmpa);
ia[0] = 0; ia[0] = 0;
} }
if (e != ee) if (e != ee)
rte_free(ee); rte_free(ee);
rte_update_unlock(); rte_update_unlock();
if (d->import_mode) /* In import mode, accept only the primary route */
break;
} }
} }
@ -742,6 +769,18 @@ rt_show_cont(struct cli *c)
FIB_ITERATE_START(fib, it, f) FIB_ITERATE_START(fib, it, f)
{ {
net *n = (net *) f; net *n = (net *) f;
if (d->running_on_config && d->running_on_config != config)
{
cli_printf(c, 8004, "Stopped due to reconfiguration");
goto done;
}
if (d->import_protocol &&
d->import_protocol->core_state != FS_HAPPY &&
d->import_protocol->core_state != FS_FEEDING)
{
cli_printf(c, 8005, "Protocol is down");
goto done;
}
if (!max--) if (!max--)
{ {
FIB_ITERATE_PUT(it, f); FIB_ITERATE_PUT(it, f);
@ -751,6 +790,7 @@ rt_show_cont(struct cli *c)
} }
FIB_ITERATE_END(f); FIB_ITERATE_END(f);
cli_printf(c, 0, ""); cli_printf(c, 0, "");
done:
c->cont = c->cleanup = NULL; c->cont = c->cleanup = NULL;
} }

View file

@ -535,10 +535,14 @@ rip_dump(struct proto *p)
} }
static void static void
rip_get_route_info(rte *rte, byte *buf) rip_get_route_info(rte *rte, byte *buf, ea_list *attrs)
{ {
buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric ); eattr *metric = ea_find(attrs, EA_RIP_METRIC);
bsprintf(buf, " t%04x", rte->u.rip.tag ); eattr *tag = ea_find(attrs, EA_RIP_TAG);
buf += bsprintf(buf, " (%d/%d)", rte->pref, metric ? metric->u.data : 0);
if (tag && tag->u.data)
bsprintf(buf, " t%04x", tag->u.data);
} }
static int static int