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
|
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).
|
them out through the default route to prevent routing loops).
|
||||||
|
|
||||||
<p>There are three types of static routes: `classical' routes telling to
|
<p>There are five types of static routes: `classical' routes telling
|
||||||
forward packets to a neighboring router, device routes specifying forwarding
|
to forward packets to a neighboring router, multipath routes
|
||||||
to hosts on a directly connected network and special routes (sink, blackhole
|
specifying several (possibly weighted) neighboring routers, device
|
||||||
etc.) which specify a special action to be done instead of forwarding the
|
routes specifying forwarding to hosts on a directly connected network,
|
||||||
packet.
|
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
|
<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
|
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.
|
with their weights.
|
||||||
<tag>route <m/prefix/ via <m/"interface"/</tag> Static device
|
<tag>route <m/prefix/ via <m/"interface"/</tag> Static device
|
||||||
route through an interface to hosts on a directly connected network.
|
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
|
<tag>route <m/prefix/ drop|reject|prohibit</tag> Special routes
|
||||||
specifying to drop the packet, return it as unreachable or return
|
specifying to drop the packet, return it as unreachable or return
|
||||||
it as administratively prohibited.
|
it as administratively prohibited.
|
||||||
|
|
||||||
<tag>check link <M>switch</M></tag>
|
<tag>check link <m/switch/</tag>
|
||||||
The only option of the static protocol. If set, hardware link
|
If set, hardware link states of network interfaces are taken
|
||||||
states of network interfaces are taken into consideration.
|
into consideration. When link disappears (e.g. ethernet cable
|
||||||
When link disappears (e.g. ethernet cable is unplugged),
|
is unplugged), static routes directing to that interface are
|
||||||
static routes directing to that interface are removed. It is
|
removed. It is possible that some hardware drivers or
|
||||||
possible that some hardware drivers or platforms do not
|
platforms do not implement this feature. Default: off.
|
||||||
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>
|
</descrip>
|
||||||
|
|
||||||
<p>Static routes have no specific attributes.
|
<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_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE, CHECK, LINK)
|
CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE, CHECK, LINK)
|
||||||
CF_KEYWORDS(MULTIPATH, WEIGHT)
|
CF_KEYWORDS(MULTIPATH, WEIGHT, RECURSIVE, IGP, TABLE)
|
||||||
|
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
@ -35,6 +35,7 @@ static_proto:
|
||||||
static_proto_start proto_name '{'
|
static_proto_start proto_name '{'
|
||||||
| static_proto proto_item ';'
|
| static_proto proto_item ';'
|
||||||
| static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
|
| static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
|
||||||
|
| static_proto IGP TABLE rtable ';' { STATIC_CFG->igp_table = $4; }
|
||||||
| static_proto stat_route ';'
|
| static_proto stat_route ';'
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -79,6 +80,10 @@ stat_route:
|
||||||
| stat_route0 MULTIPATH stat_multipath {
|
| stat_route0 MULTIPATH stat_multipath {
|
||||||
this_srt->dest = RTD_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 DROP { this_srt->dest = RTD_BLACKHOLE; }
|
||||||
| stat_route0 REJECT { this_srt->dest = RTD_UNREACHABLE; }
|
| stat_route0 REJECT { this_srt->dest = RTD_UNREACHABLE; }
|
||||||
| stat_route0 PROHIBIT { this_srt->dest = RTD_PROHIBIT; }
|
| stat_route0 PROHIBIT { this_srt->dest = RTD_PROHIBIT; }
|
||||||
|
|
|
@ -47,6 +47,14 @@
|
||||||
|
|
||||||
#include "static.h"
|
#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 void
|
||||||
static_install(struct proto *p, struct static_route *r, struct iface *ifa)
|
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;
|
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);
|
aa = rta_lookup(&a);
|
||||||
n = net_get(p->table, r->net, r->masklen);
|
n = net_get(p->table, r->net, r->masklen);
|
||||||
e = rte_get_temp(aa);
|
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 int
|
||||||
static_start(struct proto *p)
|
static_start(struct proto *p)
|
||||||
{
|
{
|
||||||
struct static_config *c = (void *) p->cf;
|
struct static_config *cf = (void *) p->cf;
|
||||||
struct static_route *r;
|
struct static_route *r;
|
||||||
|
|
||||||
DBG("Static: take off!\n");
|
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;
|
return PS_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
static_shutdown(struct proto *p)
|
static_shutdown(struct proto *p)
|
||||||
{
|
{
|
||||||
struct static_config *c = (void *) p->cf;
|
struct static_config *cf = (void *) p->cf;
|
||||||
struct static_route *r;
|
struct static_route *r;
|
||||||
|
|
||||||
/* Just reset the flag, the routes will be flushed by the nest */
|
/* 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;
|
r->installed = 0;
|
||||||
WALK_LIST(r, c->other_routes)
|
WALK_LIST(r, cf->other_routes)
|
||||||
r->installed = 0;
|
r->installed = 0;
|
||||||
|
|
||||||
return PS_DOWN;
|
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 void
|
||||||
static_neigh_notify(struct neighbor *n)
|
static_neigh_notify(struct neighbor *n)
|
||||||
{
|
{
|
||||||
|
@ -373,6 +398,9 @@ static_same_dest(struct static_route *x, struct static_route *y)
|
||||||
return 0;
|
return 0;
|
||||||
return !x && !y;
|
return !x && !y;
|
||||||
|
|
||||||
|
case RTDX_RECURSIVE:
|
||||||
|
return ipa_equal(x->via, y->via);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -407,6 +435,12 @@ static_match(struct proto *p, struct static_route *r, struct static_config *n)
|
||||||
static_remove(p, r);
|
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 int
|
||||||
static_reconfigure(struct proto *p, struct proto_config *new)
|
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_config *n = (void *) new;
|
||||||
struct static_route *r;
|
struct static_route *r;
|
||||||
|
|
||||||
|
if (cf_igp_table(o) != cf_igp_table(n))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Delete all obsolete routes and reset neighbor entries */
|
/* Delete all obsolete routes and reset neighbor entries */
|
||||||
WALK_LIST(r, o->iface_routes)
|
WALK_LIST(r, o->iface_routes)
|
||||||
static_match(p, r, n);
|
static_match(p, r, n);
|
||||||
|
@ -440,6 +477,7 @@ struct protocol proto_static = {
|
||||||
dump: static_dump,
|
dump: static_dump,
|
||||||
start: static_start,
|
start: static_start,
|
||||||
shutdown: static_shutdown,
|
shutdown: static_shutdown,
|
||||||
|
cleanup: static_cleanup,
|
||||||
reconfigure: static_reconfigure,
|
reconfigure: static_reconfigure,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -456,6 +494,7 @@ static_show_rt(struct static_route *r)
|
||||||
case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
|
case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
|
||||||
case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
|
case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
|
||||||
case RTD_MULTIPATH: bsprintf(via, "multipath"); break;
|
case RTD_MULTIPATH: bsprintf(via, "multipath"); break;
|
||||||
|
case RTDX_RECURSIVE: bsprintf(via, "recursive %I", r->via); break;
|
||||||
default: bsprintf(via, "???");
|
default: bsprintf(via, "???");
|
||||||
}
|
}
|
||||||
cli_msg(-1009, "%I/%d %s%s", r->net, r->masklen, via, r->installed ? "" : " (dormant)");
|
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 iface_routes; /* Routes to search on interface events */
|
||||||
list other_routes; /* Routes hooked to neighbor cache and reject routes */
|
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
|
/* Dummy nodes (parts of multipath route) abuses masklen field for weight
|
||||||
and if_name field for a ptr to the master (RTD_MULTIPATH) node. */
|
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 *);
|
void static_show(struct proto *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue