diff options
Diffstat (limited to 'proto/static')
-rw-r--r-- | proto/static/config.Y | 87 | ||||
-rw-r--r-- | proto/static/static.c | 53 |
2 files changed, 71 insertions, 69 deletions
diff --git a/proto/static/config.Y b/proto/static/config.Y index 2fb54448..16c276ce 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -13,9 +13,33 @@ CF_HDR CF_DEFINES #define STATIC_CFG ((struct static_config *) this_proto) -static struct static_route *this_srt, *last_srt; +static struct static_route *this_srt, *this_snh; static struct f_inst **this_srt_last_cmd; +static struct static_route * +static_nexthop_new(void) +{ + struct static_route *nh; + + if (!this_snh) + { + /* First next hop */ + nh = this_srt; + rem_node(&this_srt->n); + } + else + { + /* Additional next hop */ + nh = cfg_allocz(sizeof(struct static_route)); + nh->net = this_srt->net; + this_snh->mp_next = nh; + } + + nh->dest = RTD_UNICAST; + nh->mp_head = this_srt; + return nh; +}; + static void static_route_finish(void) { } @@ -45,48 +69,35 @@ static_proto: | static_proto stat_route stat_route_opt_list ';' { static_route_finish(); } ; -stat_nexthop_via: VIA -{ - if (last_srt) - { - last_srt = (last_srt->mp_next = cfg_allocz(sizeof(struct static_route))); - last_srt->net = this_srt->net; - } - else - { - last_srt = this_srt; - rem_node(&this_srt->n); - } - - last_srt->mp_head = this_srt; - last_srt->dest = RTD_UNICAST; -}; - -stat_nexthop_ident: - stat_nexthop_via ipa ipa_scope { - last_srt->via = $2; - last_srt->iface = $3; - add_tail(&STATIC_CFG->neigh_routes, &last_srt->n); +stat_nexthop: + VIA ipa ipa_scope { + this_snh = static_nexthop_new(); + this_snh->via = $2; + this_snh->iface = $3; + add_tail(&STATIC_CFG->neigh_routes, &this_snh->n); } - | stat_nexthop_via TEXT { - last_srt->via = IPA_NONE; - last_srt->if_name = $2; - add_tail(&STATIC_CFG->iface_routes, &last_srt->n); + | VIA TEXT { + this_snh = static_nexthop_new(); + this_snh->via = IPA_NONE; + this_snh->if_name = $2; + add_tail(&STATIC_CFG->iface_routes, &this_snh->n); } - | stat_nexthop_ident MPLS label_stack { - last_srt->label_count = $3[0]; - last_srt->label_stack = &($3[1]); + | stat_nexthop MPLS label_stack { + this_snh->label_count = $3[0]; + this_snh->label_stack = &($3[1]); } - | stat_nexthop_ident WEIGHT expr { - last_srt->weight = $3 - 1; + | stat_nexthop WEIGHT expr { + this_snh->weight = $3 - 1; if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256"); } - | stat_nexthop_ident BFD bool { last_srt->use_bfd = $3; cf_check_bfd($3); } + | stat_nexthop BFD bool { + this_snh->use_bfd = $3; cf_check_bfd($3); + } ; -stat_nexthop: - stat_nexthop_ident - | stat_nexthop stat_nexthop_ident +stat_nexthops: + stat_nexthop + | stat_nexthops stat_nexthop ; stat_route0: ROUTE net_any { @@ -95,12 +106,12 @@ stat_route0: ROUTE net_any { this_srt->net = $2; this_srt_last_cmd = &(this_srt->cmds); this_srt->mp_next = NULL; - last_srt = NULL; + this_snh = NULL; } ; stat_route: - stat_route0 stat_nexthop + stat_route0 stat_nexthops | stat_route0 RECURSIVE ipa { this_srt->dest = RTDX_RECURSIVE; this_srt->via = $3; diff --git a/proto/static/static.c b/proto/static/static.c index 3e03708c..e5251bf6 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -60,54 +60,44 @@ p_igp_table(struct proto *p) static void static_install(struct proto *p, struct static_route *r) { - rta *ap = alloca(RTA_MAX_SIZE); + rta *ap = allocz(RTA_MAX_SIZE); rte *e; if (!(r->state & STS_WANT) && (r->state & (STS_INSTALLED | STS_FORCE)) && r->dest != RTD_UNICAST) goto drop; DBG("Installing static route %N, rtd=%d\n", r->net, r->dest); - bzero(ap, RTA_MAX_SIZE); ap->src = p->main_source; - ap->source = ((r->dest == RTD_UNICAST) && ipa_zero(r->via)) ? RTS_STATIC_DEVICE : RTS_STATIC; + ap->source = RTS_STATIC; ap->scope = SCOPE_UNIVERSE; ap->dest = r->dest; if (r->dest == RTD_UNICAST) { + struct nexthop *nhs = NULL; struct static_route *r2; - int num = 0, update = 0; + int update = 0; + r = r->mp_head; for (r2 = r; r2; r2 = r2->mp_next) { - if ((r2->state & STS_FORCE) || (!!(r2->state & STS_INSTALLED) != !!(r2->state & STS_WANT))) update++; if (r2->state & STS_WANT) - { - struct nexthop *nh = (ap->nh.next) ? alloca(NEXTHOP_MAX_SIZE) : &(ap->nh); - if (ipa_zero(r2->via)) // Device nexthop - { - nh->gw = IPA_NONE; - nh->iface = r2->iface; - } - else // Router nexthop - { - nh->gw = r2->via; - nh->iface = r2->neigh->iface; - } - nh->weight = r2->weight; - nh->labels = r2->label_count; - for (int i=0; i<nh->labels; i++) - nh->label[i] = r2->label_stack[i]; - - if (ap->nh.next) - nexthop_insert(&(ap->nh), nh); - r2->state |= STS_INSTALLED; - num++; - } + { + struct nexthop *nh = allocz(NEXTHOP_MAX_SIZE); + + nh->gw = r2->via; + nh->iface = r2->neigh ? r2->neigh->iface : r2->iface; + nh->weight = r2->weight; + nh->labels = r2->label_count; + memcpy(nh->label, r2->label_stack, r2->label_count * sizeof(u32)); + + r2->state |= STS_INSTALLED; + nexthop_insert(&nhs, nh); + } else r2->state = 0; } @@ -115,18 +105,19 @@ static_install(struct proto *p, struct static_route *r) if (!update) // Nothing changed return; - r = r->mp_head; - - if (!num) // No nexthop to install + if (!nhs) // No nexthop to install { drop: rte_update(p, r->net, NULL); return; } + + ap->dest = RTD_UNICAST; + nexthop_link(ap, nhs); } else r->state |= STS_INSTALLED; - + if (r->dest == RTDX_RECURSIVE) { ap->nh.labels_append = ap->nh.labels = r->label_count; |