From: "Ondrej Zajicek (work)" <santi...@crfreenet.org> Signed-off-by: Kenth Eriksson <kenth.eriks...@infinera.com> --- proto/static/config.Y | 2 ++ proto/static/static.c | 27 ++++++++++++++++++++------- proto/static/static.h | 1 + 3 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/proto/static/config.Y b/proto/static/config.Y index d7a02961..32eba0fe 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -135,6 +135,8 @@ stat_route: stat_route_item: cmd { *this_srt_last_cmd = $1; this_srt_last_cmd = &($1->next); } + | PREFERENCE expr ';' { this_srt->preference = $2; check_u16($2); } + | DISTANCE expr ';' { this_srt->preference = $2; check_u16($2); } ; stat_route_opts: diff --git a/proto/static/static.c b/proto/static/static.c index 75a74ad0..feb8e427 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -53,7 +53,7 @@ static void static_announce_rte(struct static_proto *p, struct static_route *r) { rta *a = allocz(RTA_MAX_SIZE); - a->src = p->p.main_source; + a->src = rt_get_source(&p->p, r->preference); a->source = RTS_STATIC; a->scope = SCOPE_UNIVERSE; a->dest = r->dest; @@ -101,11 +101,13 @@ static_announce_rte(struct static_proto *p, struct static_route *r) /* We skip rta_lookup() here */ rte *e = rte_get_temp(a); e->pflags = 0; + e->pref = r->preference; if (r->cmds) f_eval_rte(r->cmds, &e, static_lp); - rte_update(&p->p, r->net, e); + e->pref = r->preference; /* Avoid preference from filter */ + rte_update2(p->p.main_channel, r->net, e, a->src); r->state = SRS_CLEAN; if (r->cmds) @@ -117,7 +119,7 @@ withdraw: if (r->state == SRS_DOWN) return; - rte_update(&p->p, r->net, NULL); + rte_update2(p->p.main_channel, r->net, NULL, a->src); r->state = SRS_DOWN; } @@ -249,7 +251,7 @@ static void static_remove_rte(struct static_proto *p, struct static_route *r) { if (r->state) - rte_update(&p->p, r->net, NULL); + rte_update2(p->p.main_channel, r->net, NULL, rt_get_source(&p->p, r->preference)); static_reset_rte(p, r); } @@ -379,8 +381,13 @@ static_postconfig(struct proto_config *CF) cc->table : cf->c.global->def_tables[NET_IP6]; WALK_LIST(r, cf->routes) + { if (r->net && (r->net->type != CF->net_type)) cf_error("Route %N incompatible with channel type", r->net); + + if (!r->preference) + r->preference = cc->preference; + } } static struct proto * @@ -485,11 +492,17 @@ static_dump(struct proto *P) #define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL ) +static inline int srt_equal(struct static_route *a, struct static_route *b) +{ return net_equal(a->net, b->net) && (a->preference == b->preference); } + +static inline int srt_compare(struct static_route *a, struct static_route *b) +{ return net_compare(a->net, b->net) ?: uint_cmp(a->preference, b->preference); } + static inline int static_cmp_rte(const void *X, const void *Y) { struct static_route *x = *(void **)X, *y = *(void **)Y; - return net_compare(x->net, y->net); + return srt_compare(x, y); } static int @@ -518,7 +531,7 @@ static_reconfigure(struct proto *P, struct proto_config *CF) /* Reconfigure initial matching sequence */ for (or = HEAD(o->routes), nr = HEAD(n->routes); - NODE_VALID(or) && NODE_VALID(nr) && net_equal(or->net, nr->net); + NODE_VALID(or) && NODE_VALID(nr) && srt_equal(or, nr); or = NODE_NEXT(or), nr = NODE_NEXT(nr)) static_reconfigure_rte(p, or, nr); @@ -549,7 +562,7 @@ static_reconfigure(struct proto *P, struct proto_config *CF) while ((orpos < ornum) && (nrpos < nrnum)) { - int x = net_compare(orbuf[orpos]->net, nrbuf[nrpos]->net); + int x = srt_compare(orbuf[orpos], nrbuf[nrpos]); if (x < 0) static_remove_rte(p, orbuf[orpos++]); else if (x > 0) diff --git a/proto/static/static.h b/proto/static/static.h index a3c30b87..ec9dffb3 100644 --- a/proto/static/static.h +++ b/proto/static/static.h @@ -40,6 +40,7 @@ struct static_route { struct static_route *mp_head; /* First nexthop of this route */ struct static_route *mp_next; /* Nexthops for multipath routes */ struct f_inst *cmds; /* List of commands for setting attributes */ + u16 preference; /* Route preference */ byte dest; /* Destination type (RTD_*) */ byte state; /* State of route announcement (SRS_*) */ byte active; /* Next hop is active (nbr/iface/BFD available) */ -- 2.21.0