diff options
Diffstat (limited to 'proto/static')
-rw-r--r-- | proto/static/config.Y | 18 | ||||
-rw-r--r-- | proto/static/static.c | 98 | ||||
-rw-r--r-- | proto/static/static.h | 4 |
3 files changed, 77 insertions, 43 deletions
diff --git a/proto/static/config.Y b/proto/static/config.Y index 182721b3..86359f0b 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -38,25 +38,25 @@ 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(); } ; -stat_route0: ROUTE prefix { +stat_route0: ROUTE net_any { this_srt = cfg_allocz(sizeof(struct static_route)); add_tail(&STATIC_CFG->other_routes, &this_srt->n); - this_srt->net = $2.addr; - this_srt->masklen = $2.len; + this_srt->net = $2; this_srt_last_cmd = &(this_srt->cmds); } ; @@ -72,7 +72,7 @@ stat_multipath1: this_srt_nh->use_bfd = -1; /* undefined */ } | stat_multipath1 WEIGHT expr { - this_srt_nh->masklen = $3 - 1; /* really */ + this_srt_nh->weight = $3 - 1; if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256"); } | stat_multipath1 BFD bool { 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)"); } diff --git a/proto/static/static.h b/proto/static/static.h index 6b047234..51486e83 100644 --- a/proto/static/static.h +++ b/proto/static/static.h @@ -26,8 +26,7 @@ void static_init_config(struct static_config *); struct static_route { node n; struct static_route *chain; /* Next for the same neighbor */ - ip_addr net; /* Network we route */ - int masklen; /* Mask length */ + net_addr *net; /* Network we route */ int dest; /* Destination type (RTD_*) */ ip_addr via; /* Destination router */ struct iface *via_if; /* Destination iface, for link-local vias */ @@ -37,6 +36,7 @@ struct static_route { struct f_inst *cmds; /* List of commands for setting attributes */ int installed; /* Installed in rt table, -1 for reinstall */ int use_bfd; /* Configured to use BFD */ + int weight; /* Multipath next hop weight */ struct bfd_request *bfd_req; /* BFD request, if BFD is used */ }; |