diff options
Diffstat (limited to 'proto')
-rw-r--r-- | proto/static/config.Y | 7 | ||||
-rw-r--r-- | proto/static/static.c | 51 | ||||
-rw-r--r-- | proto/static/static.h | 6 |
3 files changed, 56 insertions, 8 deletions
diff --git a/proto/static/config.Y b/proto/static/config.Y index 46debbc3..77d2419f 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -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; } diff --git a/proto/static/static.c b/proto/static/static.c index b9534882..2f33d817 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -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,31 +218,45 @@ 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) { struct proto *p = n->proto; @@ -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)"); diff --git a/proto/static/static.h b/proto/static/static.h index c91b9cef..775743cf 100644 --- a/proto/static/static.h +++ b/proto/static/static.h @@ -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 |