]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Added dumping of routing tables (`show route'). This includes filtering.
authorMartin Mares <mj@ucw.cz>
Wed, 1 Dec 1999 15:10:21 +0000 (15:10 +0000)
committerMartin Mares <mj@ucw.cz>
Wed, 1 Dec 1999 15:10:21 +0000 (15:10 +0000)
TODO
conf/confbase.Y
doc/reply_codes
nest/config.Y
nest/route.h
nest/rt-attr.c
nest/rt-table.c

diff --git a/TODO b/TODO
index d82bf811532178dbf7b0376b0c9695893a4b2ead..a1c7dc3c32999be0c60759debf09eeec0324ec9d 100644 (file)
--- a/TODO
+++ b/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?
 
index 02a86e94dc4fae699f0ed2c75e388cd967bb8f51..2a76decc3cf329d490d80f05290cb7ef134470e0 100644 (file)
@@ -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
index 3bafd74552490757f26af25538ca6b52a92eae02..abc2e6f68939d602ce0f8ae79c3b423d817a6d7a 100644 (file)
@@ -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
index b807085a68bf7dee40096a85ac19e2897bcf2ce5..89177a7a745be462afe4ed9951d07f13024bd88a 100644 (file)
@@ -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 */
index c2b21d13129314588398bed05bb3c9882096e96d..41d188da760a4ebf5b6c8d01cc6878a6151b6ddb 100644 (file)
@@ -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
index 2c50f4d29ecf43e9fa68388a96a0339bae9ccbcf..04dcf516484880b2bb0751c4ce48e81c187c6269 100644 (file)
@@ -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)
 {
index 353473d10bccc783e7dcef50bd4f6d8b8f6a54e0..edbf154d5fcc541f02c31f3dbda28558e5b4b213 100644 (file)
@@ -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.
  */
 #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");
+    }
+}