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
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.
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
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 ';'
;
| 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; }
#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)
{
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);
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)
{
return 0;
return !x && !y;
+ case RTDX_RECURSIVE:
+ return ipa_equal(x->via, y->via);
+
default:
return 1;
}
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)
{
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);
dump: static_dump,
start: static_start,
shutdown: static_shutdown,
+ cleanup: static_cleanup,
reconfigure: static_reconfigure,
};
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)");
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 */
};
/* 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