]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements static recursive routes.
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 24 Sep 2011 00:21:52 +0000 (02:21 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 24 Sep 2011 00:24:34 +0000 (02:24 +0200)
doc/bird.sgml
proto/static/config.Y
proto/static/static.c
proto/static/static.h

index d96d19dec5bd1037cc76e2dfb2d2a008a1864413..c929dbebdb66c86054c55793d8e2b5d5473fe367 100644 (file)
@@ -2420,11 +2420,13 @@ telling to return packets as undeliverable if they are in your IP block,
 you don't have any specific destination for them and you don't want to send
 them out through the default route to prevent routing loops).
 
-<p>There are three types of static routes: `classical' routes telling to
-forward packets to a neighboring router, device routes specifying forwarding
-to hosts on a directly connected network and special routes (sink, blackhole
-etc.) which specify a special action to be done instead of forwarding the
-packet.
+<p>There are five types of static routes: `classical' routes telling
+to forward packets to a neighboring router, multipath routes
+specifying several (possibly weighted) neighboring routers, device
+routes specifying forwarding to hosts on a directly connected network,
+recursive routes computing their nexthops by doing route table lookups
+for a given IP and special routes (sink, blackhole etc.) which specify
+a special action to be done instead of forwarding the packet.
 
 <p>When the particular destination is not available (the interface is down or
 the next hop of the route is not a neighbor at the moment), Static just
@@ -2442,17 +2444,22 @@ definition of the protocol contains mainly a list of static routes:
        with their weights.
        <tag>route <m/prefix/ via <m/"interface"/</tag> Static device
        route through an interface to hosts on a directly connected network.
+       <tag>route <m/prefix/ recursive <m/ip/</tag> Static recursive route,
+       its nexthop depends on a route table lookup for given IP address.
        <tag>route <m/prefix/ drop|reject|prohibit</tag> Special routes
        specifying to drop the packet, return it as unreachable or return
        it as administratively prohibited.
 
-       <tag>check link <M>switch</M></tag>
-       The only option of the static protocol. If set, hardware link
-       states of network interfaces are taken into consideration.
-       When link disappears (e.g. ethernet cable is unplugged),
-       static routes directing to that interface are removed. It is
-       possible that some hardware drivers or platforms do not
-       implement this feature. Default: off.
+       <tag>check link <m/switch/</tag>
+       If set, hardware link states of network interfaces are taken
+       into consideration.  When link disappears (e.g. ethernet cable
+       is unplugged), static routes directing to that interface are
+       removed. It is possible that some hardware drivers or
+       platforms do not implement this feature. Default: off.
+
+       <tag>igp table <m/name/</tag> Specifies a table that is used
+       for route table lookups of recursive routes. Default: the
+       same table as the protocol is connected to.
 </descrip>
 
 <p>Static routes have no specific attributes.
index 46debbc3d05f69c824442f883febb92b255d1ea8..77d2419f1957e6e398064e5a5d41b64a54f672a2 100644 (file)
@@ -18,7 +18,7 @@ static struct static_route *this_srt, *this_srt_nh, *last_srt_nh;
 CF_DECLS
 
 CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE, CHECK, LINK)
-CF_KEYWORDS(MULTIPATH, WEIGHT)
+CF_KEYWORDS(MULTIPATH, WEIGHT, RECURSIVE, IGP, TABLE)
 
 
 CF_GRAMMAR
@@ -35,6 +35,7 @@ static_proto:
    static_proto_start proto_name '{'
  | static_proto proto_item ';'
  | static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
+ | static_proto IGP TABLE rtable ';' { STATIC_CFG->igp_table = $4; }
  | static_proto stat_route ';'
  ;
 
@@ -79,6 +80,10 @@ stat_route:
  | stat_route0 MULTIPATH stat_multipath {
       this_srt->dest = RTD_MULTIPATH;
    }
+ | stat_route0 RECURSIVE ipa {
+      this_srt->dest = RTDX_RECURSIVE;
+      this_srt->via = $3;
+   }
  | stat_route0 DROP { this_srt->dest = RTD_BLACKHOLE; }
  | stat_route0 REJECT { this_srt->dest = RTD_UNREACHABLE; }
  | stat_route0 PROHIBIT { this_srt->dest = RTD_PROHIBIT; }
index b9534882b2f416f8dc739c888ce009a4276b8643..2f33d817c53330deebfa200294a898324b45174f 100644 (file)
 
 #include "static.h"
 
+static inline rtable *
+p_igp_table(struct proto *p)
+{
+  struct static_config *cf = (void *) p->cf;
+  return cf->igp_table ? cf->igp_table->table : p->table;
+}
+
+
 static void
 static_install(struct proto *p, struct static_route *r, struct iface *ifa)
 {
@@ -97,6 +105,9 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
        a.nexthops = nhs;
     }
 
+  if (r->dest == RTDX_RECURSIVE)
+    rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via);
+
   aa = rta_lookup(&a);
   n = net_get(p->table, r->net, r->masklen);
   e = rte_get_temp(aa);
@@ -207,30 +218,44 @@ static_add(struct proto *p, struct static_config *cf, struct static_route *r)
 static int
 static_start(struct proto *p)
 {
-  struct static_config *c = (void *) p->cf;
+  struct static_config *cf = (void *) p->cf;
   struct static_route *r;
 
   DBG("Static: take off!\n");
-  WALK_LIST(r, c->other_routes)
-    static_add(p, c, r);
+
+  if (cf->igp_table)
+    rt_lock_table(cf->igp_table->table);
+
+  WALK_LIST(r, cf->other_routes)
+    static_add(p, cf, r);
   return PS_UP;
 }
 
 static int
 static_shutdown(struct proto *p)
 {
-  struct static_config *c = (void *) p->cf;
+  struct static_config *cf = (void *) p->cf;
   struct static_route *r;
 
   /* Just reset the flag, the routes will be flushed by the nest */
-  WALK_LIST(r, c->iface_routes)
+  WALK_LIST(r, cf->iface_routes)
     r->installed = 0;
-  WALK_LIST(r, c->other_routes)
+  WALK_LIST(r, cf->other_routes)
     r->installed = 0;
 
   return PS_DOWN;
 }
 
+static void
+static_cleanup(struct proto *p)
+{
+  struct static_config *cf = (void *) p->cf;
+
+  if (cf->igp_table)
+    rt_unlock_table(cf->igp_table->table);
+}
+
+
 static void
 static_neigh_notify(struct neighbor *n)
 {
@@ -373,6 +398,9 @@ static_same_dest(struct static_route *x, struct static_route *y)
          return 0;
       return !x && !y;
 
+    case RTDX_RECURSIVE:
+      return ipa_equal(x->via, y->via);
+
     default:
       return 1;
     }
@@ -407,6 +435,12 @@ static_match(struct proto *p, struct static_route *r, struct static_config *n)
   static_remove(p, r);
 }
 
+static inline rtable *
+cf_igp_table(struct static_config *cf)
+{
+  return cf->igp_table ? cf->igp_table->table : NULL;
+}
+
 static int
 static_reconfigure(struct proto *p, struct proto_config *new)
 {
@@ -414,6 +448,9 @@ static_reconfigure(struct proto *p, struct proto_config *new)
   struct static_config *n = (void *) new;
   struct static_route *r;
 
+  if (cf_igp_table(o) != cf_igp_table(n))
+    return 0;
+
   /* Delete all obsolete routes and reset neighbor entries */
   WALK_LIST(r, o->iface_routes)
     static_match(p, r, n);
@@ -440,6 +477,7 @@ struct protocol proto_static = {
   dump:                static_dump,
   start:       static_start,
   shutdown:    static_shutdown,
+  cleanup:     static_cleanup,
   reconfigure: static_reconfigure,
 };
 
@@ -456,6 +494,7 @@ static_show_rt(struct static_route *r)
     case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
     case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
     case RTD_MULTIPATH:        bsprintf(via, "multipath"); break;
+    case RTDX_RECURSIVE: bsprintf(via, "recursive %I", r->via); break;
     default:           bsprintf(via, "???");
     }
   cli_msg(-1009, "%I/%d %s%s", r->net, r->masklen, via, r->installed ? "" : " (dormant)");
index c91b9ceffbe7549e44d8f40676db4d15f65e2b0b..775743cf97b838468ba8a069473f777010a14ab2 100644 (file)
@@ -13,7 +13,8 @@ struct static_config {
   struct proto_config c;
   list iface_routes;           /* Routes to search on interface events */
   list other_routes;           /* Routes hooked to neighbor cache and reject routes */
-  int check_link;              /* Whether iface link state is used */
+  int check_link;                      /* Whether iface link state is used */
+  struct rtable_config *igp_table;     /* Table used for recursive next hop lookups */
 };
 
 
@@ -35,6 +36,9 @@ struct static_route {
 /* Dummy nodes (parts of multipath route) abuses masklen field for weight
    and if_name field for a ptr to the master (RTD_MULTIPATH) node. */
 
+
+#define RTDX_RECURSIVE 0x7f            /* Phony dest value for recursive routes */
+
 void static_show(struct proto *);
 
 #endif