From: Maria Matejka Date: Mon, 10 Feb 2020 07:41:05 +0000 (+0100) Subject: Preference moved to RTA and set explicitly in protocols X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1fd32f9562634697d5c35bd1d9984e04fb3f6497;p=thirdparty%2Fbird.git Preference moved to RTA and set explicitly in protocols --- diff --git a/filter/config.Y b/filter/config.Y index 49c59efca..df424fa4a 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -248,10 +248,6 @@ assert_assign(struct f_lval *lval, struct f_inst *expr, const char *start, const setter = f_new_inst(FI_VAR_SET, expr, lval->sym); getter = f_new_inst(FI_VAR_GET, lval->sym); break; - case F_LVAL_PREFERENCE: - setter = f_new_inst(FI_PREF_SET, expr); - getter = f_new_inst(FI_PREF_GET); - break; case F_LVAL_SA: setter = f_new_inst(FI_RTA_SET, expr, lval->sa); getter = f_new_inst(FI_RTA_GET, lval->sa); @@ -749,6 +745,7 @@ static_attr: | DEST { $$ = f_new_static_attr(T_ENUM_RTD, SA_DEST, 0); } | IFNAME { $$ = f_new_static_attr(T_STRING, SA_IFNAME, 0); } | IFINDEX { $$ = f_new_static_attr(T_INT, SA_IFINDEX, 1); } + | PREFERENCE { $$ = f_new_static_attr(T_INT, SA_PREF, 0); } ; term: @@ -774,8 +771,6 @@ term: | constant { $$ = $1; } | constructor { $$ = $1; } - | PREFERENCE { $$ = f_new_inst(FI_PREF_GET); } - | static_attr { $$ = f_new_inst(FI_RTA_GET, $1); } | dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); } @@ -869,9 +864,6 @@ cmd: cf_error( "This static attribute is read-only."); $$ = f_new_inst(FI_RTA_SET, $3, $1); } - | PREFERENCE '=' term ';' { - $$ = f_new_inst(FI_PREF_SET, $3); - } | UNSET '(' dynamic_attr ')' ';' { $$ = f_new_inst(FI_EA_UNSET, $3); } @@ -914,7 +906,6 @@ get_cf_position: lvalue: CF_SYM_KNOWN { cf_assert_symbol($1, SYM_VARIABLE); $$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 }; } - | PREFERENCE { $$ = (struct f_lval) { .type = F_LVAL_PREFERENCE }; } | static_attr { $$ = (struct f_lval) { .type = F_LVAL_SA, .sa = $1 }; } | dynamic_attr { $$ = (struct f_lval) { .type = F_LVAL_EA, .da = $1 }; }; diff --git a/filter/data.h b/filter/data.h index 4ebce73b6..28b8b310b 100644 --- a/filter/data.h +++ b/filter/data.h @@ -99,6 +99,7 @@ enum f_sa_code { SA_DEST, SA_IFNAME, SA_IFINDEX, + SA_PREF, } PACKED; /* Static attribute definition (members of struct rta) */ diff --git a/filter/f-inst.c b/filter/f-inst.c index 3d1859181..52b6d81d9 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -507,6 +507,7 @@ case SA_DEST: RESULT(sa.f_type, i, rta->dest); break; case SA_IFNAME: RESULT(sa.f_type, s, rta->nh.iface ? rta->nh.iface->name : ""); break; case SA_IFINDEX: RESULT(sa.f_type, i, rta->nh.iface ? rta->nh.iface->index : 0); break; + case SA_PREF: RESULT(sa.f_type, i, rta->pref); break; default: bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code); @@ -577,6 +578,10 @@ } break; + case SA_PREF: + rta->pref = v1.val.i; + break; + default: bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code); } @@ -744,20 +749,6 @@ } } - INST(FI_PREF_GET, 0, 1) { - ACCESS_RTE; - RESULT(T_INT, i, (*fs->rte)->pref); - } - - INST(FI_PREF_SET, 1, 0) { - ACCESS_RTE; - ARG(1,T_INT); - if (v1.val.i > 0xFFFF) - runtime( "Setting preference value out of bounds" ); - f_rte_cow(fs); - (*fs->rte)->pref = v1.val.i; - } - INST(FI_LENGTH, 1, 1) { /* Get length of */ ARG_ANY(1); switch(v1.type) { diff --git a/lib/hash.h b/lib/hash.h index ea4ca6dde..8febb33fa 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -215,6 +215,12 @@ mem_hash_mix(u64 *h, const void *p, uint s) *h = *h * multiplier + pp[i]; } +static inline void +mem_hash_mix_num(u64 *h, u64 val) +{ + mem_hash_mix(h, &val, sizeof(val)); +} + static inline uint mem_hash_value(u64 *h) { diff --git a/nest/route.h b/nest/route.h index 045e45240..ac59ed84b 100644 --- a/nest/route.h +++ b/nest/route.h @@ -220,7 +220,6 @@ typedef struct rte { u32 id; /* Table specific route id */ byte flags; /* Flags (REF_...) */ byte pflags; /* Protocol-specific flags */ - word pref; /* Route preference */ btime lastmod; /* Last modified */ union { /* Protocol-dependent data (metrics etc.) */ #ifdef CONFIG_RIP @@ -463,10 +462,11 @@ typedef struct rta { struct hostentry *hostentry; /* Hostentry for recursive next-hops */ ip_addr from; /* Advertising router */ u32 igp_metric; /* IGP metric to next hop (for iBGP routes) */ - u8 source; /* Route source (RTS_...) */ - u8 scope; /* Route scope (SCOPE_... -- see ip.h) */ - u8 dest; /* Route destination type (RTD_...) */ - u8 aflags; + u16 cached:1; /* Are attributes cached? */ + u16 source:7; /* Route source (RTS_...) */ + u16 scope:4; /* Route scope (SCOPE_... -- see ip.h) */ + u16 dest:4; /* Route destination type (RTD_...) */ + word pref; struct nexthop nh; /* Next hop */ } rta; @@ -488,11 +488,6 @@ typedef struct rta { #define RTS_PERF 15 /* Perf checker */ #define RTS_MAX 16 -#define RTC_UNICAST 0 -#define RTC_BROADCAST 1 -#define RTC_MULTICAST 2 -#define RTC_ANYCAST 3 /* IPv6 Anycast */ - #define RTD_NONE 0 /* Undefined next hop */ #define RTD_UNICAST 1 /* Next hop is neighbor router */ #define RTD_BLACKHOLE 2 /* Silently drop packets */ @@ -500,8 +495,6 @@ typedef struct rta { #define RTD_PROHIBIT 4 /* Administratively prohibited */ #define RTD_MAX 5 -#define RTAF_CACHED 1 /* This is a cached rta */ - #define IGP_METRIC_UNKNOWN 0x80000000 /* Default igp_metric used when no other protocol-specific metric is availabe */ @@ -690,7 +683,7 @@ void rta_init(void); static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a->nh.labels; } #define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK) rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */ -static inline int rta_is_cached(rta *r) { return r->aflags & RTAF_CACHED; } +static inline int rta_is_cached(rta *r) { return r->cached; } static inline rta *rta_clone(rta *r) { r->uc++; return r; } void rta__free(rta *r); static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); } diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 28d956bc6..4c07e9b13 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -1099,13 +1099,15 @@ rta_hash(rta *a) u64 h; mem_hash_init(&h); #define MIX(f) mem_hash_mix(&h, &(a->f), sizeof(a->f)); +#define BMIX(f) mem_hash_mix_num(&h, a->f); MIX(src); MIX(hostentry); MIX(from); MIX(igp_metric); - MIX(source); - MIX(scope); - MIX(dest); + BMIX(source); + BMIX(scope); + BMIX(dest); + MIX(pref); #undef MIX return mem_hash_value(&h) ^ nexthop_hash(&(a->nh)) ^ ea_hash(a->eattrs); @@ -1193,7 +1195,7 @@ rta_lookup(rta *o) rta *r; uint h; - ASSERT(!(o->aflags & RTAF_CACHED)); + ASSERT(!o->cached); if (o->eattrs) ea_normalize(o->eattrs); @@ -1204,7 +1206,7 @@ rta_lookup(rta *o) r = rta_copy(o); r->hash_key = h; - r->aflags = RTAF_CACHED; + r->cached = 1; rt_lock_source(r->src); rt_lock_hostentry(r->hostentry); rta_insert(r); @@ -1218,7 +1220,7 @@ rta_lookup(rta *o) void rta__free(rta *a) { - ASSERT(rta_cache_count && (a->aflags & RTAF_CACHED)); + ASSERT(rta_cache_count && a->cached); rta_cache_count--; *a->pprev = a->next; if (a->next) @@ -1228,7 +1230,7 @@ rta__free(rta *a) if (a->nh.next) nexthop_free(a->nh.next); ea_free(a->eattrs); - a->aflags = 0; /* Poison the entry */ + a->cached = 0; sl_free(rta_slab(a), a); } @@ -1243,7 +1245,7 @@ rta_do_cow(rta *o, linpool *lp) memcpy(*nhn, nho, nexthop_size(nho)); nhn = &((*nhn)->next); } - r->aflags = 0; + r->cached = 0; r->uc = 0; return r; } @@ -1263,10 +1265,10 @@ rta_dump(rta *a) "RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" }; static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" }; - debug("p=%s uc=%d %s %s%s h=%04x", - a->src->proto->name, a->uc, rts[a->source], ip_scope_text(a->scope), + debug("p=%s pref=%d uc=%d %s %s%s h=%04x", + a->src->proto->name, a->pref, a->uc, rts[a->source], ip_scope_text(a->scope), rtd[a->dest], a->hash_key); - if (!(a->aflags & RTAF_CACHED)) + if (!a->cached) debug(" !CACHED"); debug(" <-%I", a->from); if (a->dest == RTD_UNICAST) diff --git a/nest/rt-dev.c b/nest/rt-dev.c index 240cc8fc3..7a3401602 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -78,13 +78,14 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad) rta a0 = { /* Use iface ID as local source ID */ .src = rt_get_source(P, ad->iface->index), + .pref = c->preference, .source = RTS_DEVICE, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, .nh.iface = ad->iface, }; rte e0 = { - .attrs = rta_lookup(&a0), + .attrs = &a0, }; rte_update(c, net, &e0); } diff --git a/nest/rt-show.c b/nest/rt-show.c index bd0df9ee6..2b9b2bd84 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -60,7 +60,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary if (get_route_info) get_route_info(e, info); else - bsprintf(info, " (%d)", e->pref); + bsprintf(info, " (%d)", a->pref); if (d->last_table != d->tab) rt_show_table(c, d); diff --git a/nest/rt-table.c b/nest/rt-table.c index 8b0faf91d..6e92ae259 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -283,7 +283,7 @@ rte_store(rte *r) { rte *e = sl_alloc(rte_slab); memcpy(e, r, sizeof(rte)); - if (e->attrs->aflags & RTAF_CACHED) + if (e->attrs->cached) e->attrs = rta_clone(r->attrs); else e->attrs = rta_lookup(r->attrs); @@ -502,9 +502,9 @@ rte_better(rte *new, rte *old) if (!rte_is_valid(new)) return 0; - if (new->pref > old->pref) + if (new->attrs->pref > old->attrs->pref) return 1; - if (new->pref < old->pref) + if (new->attrs->pref < old->attrs->pref) return 0; if (new->attrs->src->proto->proto != old->attrs->src->proto->proto) { @@ -528,7 +528,7 @@ rte_mergable(rte *pri, rte *sec) if (!rte_is_valid(pri) || !rte_is_valid(sec)) return 0; - if (pri->pref != sec->pref) + if (pri->attrs->pref != sec->attrs->pref) return 0; if (pri->attrs->src->proto->proto != sec->attrs->src->proto->proto) @@ -1057,7 +1057,6 @@ rte_same(rte *x, rte *y) return x->attrs == y->attrs && x->pflags == y->pflags && - x->pref == y->pref && (!x->attrs->src->proto->rte_same || x->attrs->src->proto->rte_same(x, y)) && rte_is_filtered(x) == rte_is_filtered(y); } @@ -1395,9 +1394,6 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) new->net = nn; new->sender = c; - if (!new->pref) - new->pref = c->preference; - stats->imp_updates_received++; if (!rte_validate(new)) { @@ -1493,6 +1489,12 @@ rte_update(struct channel *c, const net_addr *n, struct rte *new) ASSERT(new->attrs); ASSERT(new->attrs->src); + if (!new->attrs->pref) + { + ASSERT(!new->attrs->cached); + new->attrs->pref = c->preference; + } + rte *e = sl_alloc(rte_slab); *e = *new; @@ -1659,7 +1661,7 @@ rte_dump(rte *e) { net *n = e->net; debug("%-1N ", n->n.addr); - debug("PF=%02x pref=%d ", e->pflags, e->pref); + debug("PF=%02x ", e->pflags); rta_dump(e->attrs); if (e->attrs->src->proto->proto->dump_attrs) e->attrs->src->proto->proto->dump_attrs(e); @@ -2038,7 +2040,7 @@ rt_next_hop_update_rte(rtable *tab UNUSED, rte *old) memcpy(mls.stack, &a->nh.label[a->nh.labels - mls.len], mls.len * sizeof(u32)); rta_apply_hostentry(a, old->attrs->hostentry, &mls); - a->aflags = 0; + a->cached = 0; rte *e = sl_alloc(rte_slab); memcpy(e, old, sizeof(rte)); @@ -2398,9 +2400,6 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr { net = net_get(tab, n); - if (!new->pref) - new->pref = c->preference; - if (!rta_is_cached(new->attrs)) new->attrs = rta_lookup(new->attrs); } diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 21fef030f..06adc55ed 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -635,13 +635,14 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) .source = RTS_BABEL, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, + .pref = c->preference, .from = r->neigh->addr, .nh.gw = r->next_hop, .nh.iface = r->neigh->ifa->iface, }; rte e0 = { - .attrs = rta_lookup(&a0), + .attrs = &a0, .u.babel = { .seqno = r->seqno, .metric = r->metric, @@ -661,11 +662,11 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) .source = RTS_BABEL, .scope = SCOPE_UNIVERSE, .dest = RTD_UNREACHABLE, + .pref = 1, }; rte e0 = { .attrs = &a0, - .pref = 1, }; e->unreachable = 1; @@ -1850,7 +1851,7 @@ babel_dump(struct proto *P) static void babel_get_route_info(rte *rte, byte *buf) { - buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id); + buf += bsprintf(buf, " (%d/%d) [%lR]", rte->attrs->pref, rte->u.babel.metric, rte->u.babel.router_id); } static int diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 4710bfbad..8eb7f8813 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -2087,7 +2087,7 @@ bgp_rte_mergable(rte *pri, rte *sec) static inline int same_group(rte *r, u32 lpref, u32 lasn) { - return (r->pref == lpref) && (bgp_get_neighbor(r) == lasn); + return (r->attrs->pref == lpref) && (bgp_get_neighbor(r) == lasn); } static inline int @@ -2102,7 +2102,7 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best) { rte *r, *s; rte *key = new ? new : old; - u32 lpref = key->pref; + u32 lpref = key->attrs->pref; u32 lasn = bgp_get_neighbor(key); int old_suppressed = old ? old->u.bgp.suppressed : 0; @@ -2325,7 +2325,7 @@ bgp_get_route_info(rte *e, byte *buf) eattr *o = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); u32 origas; - buf += bsprintf(buf, " (%d", e->pref); + buf += bsprintf(buf, " (%d", e->attrs->pref); if (e->u.bgp.suppressed) buf += bsprintf(buf, "-"); diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 49cbadab7..c44e16765 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -2394,6 +2394,7 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis a->scope = SCOPE_UNIVERSE; a->from = s->proto->remote_ip; a->eattrs = ea; + a->pref = c->c.preference; c->desc->decode_next_hop(s, nh, nh_len, a); bgp_finish_attrs(s, a); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index c8ed0e06d..21aa2ce91 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -607,7 +607,7 @@ ospf_get_route_info(rte * rte, byte * buf) } buf += bsprintf(buf, " %s", type); - buf += bsprintf(buf, " (%d/%d", rte->pref, rte->u.ospf.metric1); + buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, rte->u.ospf.metric1); if (rte->attrs->source == RTS_OSPF_EXT2) buf += bsprintf(buf, "/%d", rte->u.ospf.metric2); buf += bsprintf(buf, ")"); diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 811577615..21243c949 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -2048,6 +2048,7 @@ again1: .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, .nh = *(nf->n.nhs), + .pref = p->p.main_channel->preference, }; if (reload || ort_changed(nf, &a0)) diff --git a/proto/perf/perf.c b/proto/perf/perf.c index a72023b30..ec2a90144 100644 --- a/proto/perf/perf.c +++ b/proto/perf/perf.c @@ -147,6 +147,7 @@ perf_loop(void *data) .source = RTS_PERF, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, + .pref = p->p.main_channel->preference, .nh.iface = p->ifa->iface, .nh.gw = gw, .nh.weight = 1, diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index e09e2c274..284eea554 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -68,7 +68,7 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o a = alloca(rta_size(new->attrs)); memcpy(a, new->attrs, rta_size(new->attrs)); - a->aflags = 0; + a->cached = 0; a->hostentry = NULL; e->attrs = rta_lookup(a); @@ -76,7 +76,6 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o /* Copy protocol specific embedded attributes. */ memcpy(&(e->u), &(new->u), sizeof(e->u)); - e->pref = new->pref; e->pflags = new->pflags; #ifdef CONFIG_BGP diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 81dab8103..9befbbd12 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -145,6 +145,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) /* Update */ rta a0 = { .src = p->p.main_source, + .pref = p->p.main_channel->preference, .source = RTS_RIP, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, @@ -188,7 +189,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) } rte e0 = { - .attrs = rta_lookup(&a0), + .attrs = &a0, .u.rip = { .from = a0.nh.iface, .metric = rt_metric, @@ -1182,7 +1183,7 @@ rip_reconfigure(struct proto *P, struct proto_config *CF) static void rip_get_route_info(rte *rte, byte *buf) { - buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric); + buf += bsprintf(buf, " (%d/%d)", rte->attrs->pref, rte->u.rip.metric); if (rte->u.rip.tag) bsprintf(buf, " [%04x]", rte->u.rip.tag); diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index ba1cdfdf5..442ce859d 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -122,12 +122,13 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_ rta a0 = { .src = p->p.main_source, + .pref = channel->preference, .source = RTS_RPKI, .scope = SCOPE_UNIVERSE, .dest = RTD_NONE, }; - rte e0 = { .attrs = rta_lookup(&a0) }; + rte e0 = { .attrs = &a0 }; rte_update(channel, &pfxr->n, &e0); } diff --git a/proto/static/static.c b/proto/static/static.c index f68e9a449..932bef7ca 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -57,6 +57,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r) a->source = RTS_STATIC; a->scope = SCOPE_UNIVERSE; a->dest = r->dest; + a->pref = p->p.main_channel->preference; if (r->dest == RTD_UNICAST) { diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index fd0d6f68c..0617ba436 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -434,6 +434,9 @@ krt_learn_async(struct krt_proto *p, rte *e, int new) net *n = net_get(&p->krt_table, n0->n.addr); rte *g, **gg, *best, **bestp, *old_best; + ASSERT(!e->attrs->cached); + e->attrs->pref = p->p.main_channel->preference; + e = rte_store(e); old_best = n->routes;