summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2000-05-06 22:57:39 +0000
committerMartin Mares <mj@ucw.cz>2000-05-06 22:57:39 +0000
commitce1da96ee7efc9310f138e4234495557cdef59e2 (patch)
treeb8fb1177f83a9941c7a173093a3fa20256b6c9cc
parent84f070020500de40e69e6d00df9d41ecc90a3b23 (diff)
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.
-rw-r--r--TODO6
-rw-r--r--doc/reply_codes2
-rw-r--r--nest/config.Y24
-rw-r--r--nest/protocol.h2
-rw-r--r--nest/route.h6
-rw-r--r--nest/rt-attr.c21
-rw-r--r--nest/rt-table.c52
-rw-r--r--proto/rip/rip.c10
8 files changed, 103 insertions, 20 deletions
diff --git a/TODO b/TODO
index 29a93dc6..6faae87e 100644
--- a/TODO
+++ b/TODO
@@ -13,11 +13,9 @@ Core
- filter-defined internal attributes
- netlink: realms
-- bgp: wait on restart
+- filters: deletion of mandatory attributes?
-Commands
-~~~~~~~~
-- showing of routing table as seen by given protocol
+- bgp: wait on restart
Documentation
~~~~~~~~~~~~~
diff --git a/doc/reply_codes b/doc/reply_codes
index 91466bee..def809e9 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -41,6 +41,8 @@ Reply codes of BIRD command-line interface
8001 Route not found
8002 Configuration file error
8003 No protocols match
+8004 Stopped due to reconfiguration
+8005 Protocol is down => cannot dump
9000 Command too long
9001 Parse error
diff --git a/nest/config.Y b/nest/config.Y
index 26df2902..5ac9c213 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -22,6 +22,7 @@ CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
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,
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 <s> optsym
%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
CF_GRAMMAR
@@ -239,7 +240,7 @@ CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
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]])
+CF_CLI(SHOW ROUTE, r_args, [<prefix>] [table <t>] [filter <f>] [all] [primary] [(import|protocol) <p>], [[Show routing table]])
{ rt_show($3); } ;
r_args:
@@ -275,6 +276,25 @@ r_args:
$$ = $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]])
diff --git a/nest/protocol.h b/nest/protocol.h
index 768792f2..7ba44192 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -47,7 +47,7 @@ struct protocol {
int (*start)(struct proto *); /* Start 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_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_*) */
};
diff --git a/nest/route.h b/nest/route.h
index cd9e9ff7..1e6fd64b 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -206,6 +206,9 @@ struct rt_show_data {
struct filter *filter;
int verbose;
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 *);
@@ -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 */
void ea_format(eattr *e, byte *buf);
#define EA_FORMAT_BUF_SIZE 256
+ea_list *ea_append(ea_list *to, ea_list *what);
void rta_init(void);
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_all(void);
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];
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index fd0da97e..38decb51 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -380,6 +380,20 @@ ea_hash(ea_list *e)
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
*/
@@ -551,18 +565,19 @@ rta_dump_all(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",
"RIP", "RIP-ext", "OSPF", "OSPF-ext", "OSPF-IA", "OSPF-boundary",
"BGP" };
static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" };
- ea_list *eal;
int i;
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));
- 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++)
{
ea_format(&eal->attrs[i], buf);
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 7883f2eb..1261aae1 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -683,7 +683,7 @@ rt_format_via(rte *e, byte *via)
}
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 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);
else
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)
- a->proto->proto->get_route_info(e, info);
+ a->proto->proto->get_route_info(e, info, tmpa);
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);
+ rta_show(c, a, tmpa);
}
static void
@@ -709,21 +717,40 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
rte *e, *ee;
byte ia[STD_ADDRESS_P_LENGTH+8];
+ int ok;
bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
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;
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)
+ {
+ 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);
+ rt_show_rte(c, ia, e, d, tmpa);
ia[0] = 0;
}
if (e != ee)
rte_free(ee);
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)
{
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--)
{
FIB_ITERATE_PUT(it, f);
@@ -751,6 +790,7 @@ rt_show_cont(struct cli *c)
}
FIB_ITERATE_END(f);
cli_printf(c, 0, "");
+done:
c->cont = c->cleanup = NULL;
}
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 022d499f..b3546ae4 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -535,10 +535,14 @@ rip_dump(struct proto *p)
}
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 );
- bsprintf(buf, " t%04x", rte->u.rip.tag );
+ eattr *metric = ea_find(attrs, EA_RIP_METRIC);
+ 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