Implements static recursive routes.
This commit is contained in:
parent
4271f2b77e
commit
4116db182d
4 changed files with 75 additions and 20 deletions
|
@ -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.
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -47,6 +47,14 @@
|
|||
|
||||
#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)");
|
||||
|
|
|
@ -14,6 +14,7 @@ struct static_config {
|
|||
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 */
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue