]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Added commands `show route protocol <p>' and `show route import <p>' which
authorMartin Mares <mj@ucw.cz>
Sat, 6 May 2000 22:57:39 +0000 (22:57 +0000)
committerMartin Mares <mj@ucw.cz>
Sat, 6 May 2000 22:57:39 +0000 (22:57 +0000)
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.

TODO
doc/reply_codes
nest/config.Y
nest/protocol.h
nest/route.h
nest/rt-attr.c
nest/rt-table.c
proto/rip/rip.c

diff --git a/TODO b/TODO
index 29a93dc684e9b13e161647e0204864521d9d316f..6faae87e37eeb86757e5cc7fcb6b6bfaa70b5562 100644 (file)
--- 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
 ~~~~~~~~~~~~~
index 91466bee46820a78a80599ca512418f45eb7632b..def809e9274e19dc0c5d0fe7d6f6e954141a1b6c 100644 (file)
@@ -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
index 26df29029c2c382de37bc7122f8a9116eac8d31a..5ac9c213f536ec492caeddd5d14fdf63a9e4f937 100644 (file)
@@ -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]])
index 768792f234c2fe032e1bcdbefb42123e581e536b..7ba44192d0cfbca748cdb92cf76acfd11ffe2af7 100644 (file)
@@ -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_*) */
 };
 
index cd9e9ff761083ec8734714353e0b3cc6d54d95c1..1e6fd64b467878e38db80d24d8c7c9cf6721d465 100644 (file)
@@ -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];
 
index fd0da97e528106497518028004f1b06ce75dfb84..38decb51b6c002196b9e1bb5bdf2f46b8c1a0c82 100644 (file)
@@ -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);
index 7883f2eb695fd6639d43561b6fd1157e9be82f71..1261aae1b21fe2d3af1c50c8bf982e1b5f62b2f9 100644 (file)
@@ -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;
 }
 
index 022d499fb1fcfe52349982ebc8896de37e1bff66..b3546ae4e237239c3bf7c54ca5d7bff9309c5801 100644 (file)
@@ -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