diff options
Diffstat (limited to 'proto/static')
-rw-r--r-- | proto/static/config.Y | 11 | ||||
-rw-r--r-- | proto/static/static.c | 69 |
2 files changed, 59 insertions, 21 deletions
diff --git a/proto/static/config.Y b/proto/static/config.Y index 9e634803..86359f0b 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -38,15 +38,16 @@ CF_GRAMMAR CF_ADDTO(proto, static_proto '}') -static_proto_start: proto_start STATIC { - this_proto = proto_config_new(&proto_static, $1); - static_init_config((struct static_config *) this_proto); - } - ; +static_proto_start: proto_start STATIC +{ + this_proto = proto_config_new(&proto_static, $1); + static_init_config(STATIC_CFG); +}; static_proto: static_proto_start proto_name '{' | static_proto proto_item ';' + | static_proto proto_channel ';' { this_proto->net_type = $2->net_type; } | 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_route_opt_list ';' { static_route_finish(); } diff --git a/proto/static/static.c b/proto/static/static.c index 809c29fb..6239fccb 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -54,7 +54,7 @@ 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; + return cf->igp_table ? cf->igp_table->table : p->main_channel->table; } static void @@ -108,11 +108,11 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa) } if (r->dest == RTDX_RECURSIVE) - rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via); + rta_set_recursive_next_hop(p->main_channel->table, &a, p_igp_table(p), &r->via, &r->via); /* We skip rta_lookup() here */ - n = net_get(p->table, r->net); + n = net_get(p->main_channel->table, r->net); e = rte_get_temp(&a); e->net = n; e->pflags = 0; @@ -136,7 +136,7 @@ static_remove(struct proto *p, struct static_route *r) return; DBG("Removing static route %N via %I\n", r->net, r->via); - n = net_find(p->table, r->net); + n = net_find(p->main_channel->table, r->net); rte_update(p, n, NULL); r->installed = 0; } @@ -309,6 +309,17 @@ static_shutdown(struct proto *p) r->installed = 0; } + /* Handle failure during channel reconfigure */ + /* FIXME: This should be handled in a better way */ + cf = (void *) p->cf_new; + if (cf) + { + WALK_LIST(r, cf->iface_routes) + r->installed = 0; + WALK_LIST(r, cf->other_routes) + r->installed = 0; + } + return PS_DOWN; } @@ -450,16 +461,40 @@ static_init_config(struct static_config *c) init_list(&c->other_routes); } +static void +static_postconfig(struct proto_config *CF) +{ + struct static_config *cf = (void *) CF; + struct static_route *r; + + if (EMPTY_LIST(CF->channels)) + cf_error("Channel not specified"); + + + WALK_LIST(r, cf->iface_routes) + if (r->net->type != CF->net_type) + cf_error("Route %N incompatible with channel type", r->net); + + WALK_LIST(r, cf->other_routes) + if (r->net->type != CF->net_type) + cf_error("Route %N incompatible with channel type", r->net); +} + + static struct proto * -static_init(struct proto_config *c) +static_init(struct proto_config *CF) { - struct proto *p = proto_new(c, sizeof(struct proto)); + struct proto *P = proto_new(CF); + // struct static_proto *p = (void *) P; + // struct static_config *cf = (void *) CF; - p->neigh_notify = static_neigh_notify; - p->if_notify = static_if_notify; - p->rte_mergable = static_rte_mergable; + P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); - return p; + P->neigh_notify = static_neigh_notify; + P->if_notify = static_if_notify; + P->rte_mergable = static_rte_mergable; + + return P; } static inline int @@ -543,15 +578,18 @@ cf_igp_table(struct static_config *cf) } static int -static_reconfigure(struct proto *p, struct proto_config *new) +static_reconfigure(struct proto *p, struct proto_config *CF) { struct static_config *o = (void *) p->cf; - struct static_config *n = (void *) new; + struct static_config *n = (void *) CF; struct static_route *r; if (cf_igp_table(o) != cf_igp_table(n)) return 0; + if (!proto_configure_channel(p, &p->main_channel, proto_cf_main_channel(CF))) + return 0; + /* Delete all obsolete routes and reset neighbor entries */ WALK_LIST(r, o->iface_routes) static_match(p, r, n); @@ -617,20 +655,19 @@ static_copy_config(struct proto_config *dest, struct proto_config *src) struct static_config *d = (struct static_config *) dest; struct static_config *s = (struct static_config *) src; - /* Shallow copy of everything */ - proto_copy_rest(dest, src, sizeof(struct static_config)); - /* Copy route lists */ static_copy_routes(&d->iface_routes, &s->iface_routes); static_copy_routes(&d->other_routes, &s->other_routes); } - struct protocol proto_static = { .name = "Static", .template = "static%d", .preference = DEF_PREF_STATIC, + .channel_mask = NB_ANY, + .proto_size = sizeof(struct proto), .config_size = sizeof(struct static_config), + .postconfig = static_postconfig, .init = static_init, .dump = static_dump, .start = static_start, |