diff options
Diffstat (limited to 'proto/static/static.c')
-rw-r--r-- | proto/static/static.c | 98 |
1 files changed, 66 insertions, 32 deletions
diff --git a/proto/static/static.c b/proto/static/static.c index be808593..6239fccb 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -26,7 +26,7 @@ * nodes (of dest RTD_NONE), which stores info about nexthops and are * connected to neighbor entries and neighbor notifications. Dummy * nodes are chained using mp_next, they aren't in other_routes list, - * and abuse some fields (masklen, if_name) for other purposes. + * and abuse if_name field for other purposes. * * The only other thing worth mentioning is that when asked for reconfiguration, * Static not only compares the two configurations, but it also calculates @@ -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 @@ -67,7 +67,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa) if (r->installed > 0) return; - DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest); + DBG("Installing static route %N, rtd=%d\n", r->net, r->dest); bzero(&a, sizeof(a)); a.src = p->main_source; a.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC; @@ -89,7 +89,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa) struct mpnh *nh = alloca(sizeof(struct mpnh)); nh->gw = r2->via; nh->iface = r2->neigh->iface; - nh->weight = r2->masklen; /* really */ + nh->weight = r2->weight; nh->next = NULL; *nhp = nh; nhp = &(nh->next); @@ -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, r->masklen); + n = net_get(p->main_channel->table, r->net); e = rte_get_temp(&a); e->net = n; e->pflags = 0; @@ -135,8 +135,8 @@ static_remove(struct proto *p, struct static_route *r) if (!r->installed) return; - DBG("Removing static route %I/%d via %I\n", r->net, r->masklen, r->via); - n = net_find(p->table, r->net, r->masklen); + DBG("Removing static route %N via %I\n", r->net, r->via); + n = net_find(p->main_channel->table, r->net); rte_update(p, n, NULL); r->installed = 0; } @@ -186,7 +186,7 @@ static_decide(struct static_config *cf, struct static_route *r) static void static_add(struct proto *p, struct static_config *cf, struct static_route *r) { - DBG("static_add(%I/%d,%d)\n", r->net, r->masklen, r->dest); + DBG("static_add(%N,%d)\n", r->net, r->dest); switch (r->dest) { case RTD_ROUTER: @@ -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; } @@ -388,7 +399,7 @@ static_bfd_notify(struct bfd_request *req) static void static_dump_rt(struct static_route *r) { - debug("%-1I/%2d: ", r->net, r->masklen); + debug("%-1N: ", r->net); switch (r->dest) { case RTD_ROUTER: @@ -450,22 +461,40 @@ static_init_config(struct static_config *c) init_list(&c->other_routes); } -static struct proto * -static_init(struct proto_config *c) +static void +static_postconfig(struct proto_config *CF) { - struct proto *p = proto_new(c, sizeof(struct proto)); + struct static_config *cf = (void *) CF; + struct static_route *r; + + if (EMPTY_LIST(CF->channels)) + cf_error("Channel not specified"); - p->neigh_notify = static_neigh_notify; - p->if_notify = static_if_notify; - p->rte_mergable = static_rte_mergable; - return p; + 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 inline int -static_same_net(struct static_route *x, struct static_route *y) + +static struct proto * +static_init(struct proto_config *CF) { - return ipa_equal(x->net, y->net) && (x->masklen == y->masklen); + struct proto *P = proto_new(CF); + // struct static_proto *p = (void *) P; + // struct static_config *cf = (void *) CF; + + P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); + + P->neigh_notify = static_neigh_notify; + P->if_notify = static_if_notify; + P->rte_mergable = static_rte_mergable; + + return P; } static inline int @@ -486,7 +515,10 @@ static_same_dest(struct static_route *x, struct static_route *y) for (x = x->mp_next, y = y->mp_next; x && y; x = x->mp_next, y = y->mp_next) - if (!ipa_equal(x->via, y->via) || (x->via_if != y->via_if) || (x->use_bfd != y->use_bfd)) + if (!ipa_equal(x->via, y->via) || + (x->via_if != y->via_if) || + (x->use_bfd != y->use_bfd) || + (x->weight != y->weight)) return 0; return !x && !y; @@ -521,11 +553,11 @@ static_match(struct proto *p, struct static_route *r, struct static_config *n) r->neigh->data = NULL; WALK_LIST(t, n->iface_routes) - if (static_same_net(r, t)) + if (net_equal(r->net, t->net)) goto found; WALK_LIST(t, n->other_routes) - if (static_same_net(r, t)) + if (net_equal(r->net, t->net)) goto found; static_remove(p, r); @@ -546,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); @@ -620,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, @@ -646,7 +680,7 @@ struct protocol proto_static = { static void static_show_rt(struct static_route *r) { - byte via[STD_ADDRESS_P_LENGTH + 16]; + byte via[IPA_MAX_TEXT_LENGTH + 25]; switch (r->dest) { @@ -659,13 +693,13 @@ static_show_rt(struct static_route *r) case RTDX_RECURSIVE: bsprintf(via, "recursive %I", r->via); break; default: bsprintf(via, "???"); } - cli_msg(-1009, "%I/%d %s%s%s", r->net, r->masklen, via, + cli_msg(-1009, "%N %s%s%s", r->net, via, r->bfd_req ? " (bfd)" : "", r->installed ? "" : " (dormant)"); struct static_route *r2; if (r->dest == RTD_MULTIPATH) for (r2 = r->mp_next; r2; r2 = r2->mp_next) - cli_msg(-1009, "\tvia %I%J weight %d%s%s", r2->via, r2->via_if, r2->masklen + 1, /* really */ + cli_msg(-1009, "\tvia %I%J weight %d%s%s", r2->via, r2->via_if, r2->weight + 1, r2->bfd_req ? " (bfd)" : "", r2->installed ? "" : " (dormant)"); } |