summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-05-30 17:26:25 +0200
committerMaria Matejka <mq@ucw.cz>2022-05-30 17:26:25 +0200
commit41508ceac3cdd74ca705d3bfc6a79464bf38e0b5 (patch)
tree4a0506a93849b3b7e61faeeaba1af289e13d646a
parent65254128e105903b6b470c6b4bb4729f56cf81bc (diff)
parent1c30b689ddd032ef8000fb7836348a48ba3184ff (diff)
Merge commit '1c30b689ddd032ef8000fb7836348a48ba3184ff' into haugesund
-rw-r--r--filter/config.Y3
-rw-r--r--filter/data.h1
-rw-r--r--filter/f-inst.c1
-rw-r--r--lib/route.h12
-rw-r--r--lib/type_test.c1
-rw-r--r--nest/rt-attr.c32
-rw-r--r--nest/rt-dev.c2
-rw-r--r--nest/rt-table.c8
-rw-r--r--proto/babel/babel.c6
-rw-r--r--proto/bgp/attrs.c2
-rw-r--r--proto/bgp/config.Y2
-rw-r--r--proto/bgp/packets.c2
-rw-r--r--proto/ospf/ospf.c22
-rw-r--r--proto/ospf/rt.c21
-rw-r--r--proto/perf/perf.c2
-rw-r--r--proto/rip/rip.c4
-rw-r--r--proto/rpki/rpki.c2
-rw-r--r--proto/static/static.c2
-rw-r--r--sysdep/bsd/krt-sock.c3
-rw-r--r--sysdep/linux/netlink.c2
20 files changed, 79 insertions, 51 deletions
diff --git a/filter/config.Y b/filter/config.Y
index 6af39c10..ca792593 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -285,7 +285,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
IF, THEN, ELSE, CASE,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
- FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS,
+ FROM, GW, NET, MASK, PROTO, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS,
ROA_CHECK, ASN, SRC, DST,
IS_V4, IS_V6,
LEN, MAXLEN,
@@ -765,7 +765,6 @@ static_attr:
GW { $$ = f_new_static_attr(T_IP, SA_GW, 0); }
| NET { $$ = f_new_static_attr(T_NET, SA_NET, 1); }
| PROTO { $$ = f_new_static_attr(T_STRING, SA_PROTO, 1); }
- | SOURCE { $$ = f_new_static_attr(T_ENUM_RTS, SA_SOURCE, 1); }
| 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); }
diff --git a/filter/data.h b/filter/data.h
index 49b29499..23db4a85 100644
--- a/filter/data.h
+++ b/filter/data.h
@@ -25,7 +25,6 @@ enum f_sa_code {
SA_GW = 1,
SA_NET,
SA_PROTO,
- SA_SOURCE,
SA_DEST,
SA_IFNAME,
SA_IFINDEX,
diff --git a/filter/f-inst.c b/filter/f-inst.c
index 7fa1c8b8..caf473f0 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -536,7 +536,6 @@
case SA_GW: RESULT(sa.type, ip, rta->nh.gw); break;
case SA_NET: RESULT(sa.type, net, fs->rte->net); break;
case SA_PROTO: RESULT(sa.type, s, fs->rte->src->proto->name); break;
- case SA_SOURCE: RESULT(sa.type, i, rta->source); break;
case SA_DEST: RESULT(sa.type, i, rta->dest); break;
case SA_IFNAME: RESULT(sa.type, s, rta->nh.iface ? rta->nh.iface->name : ""); break;
case SA_IFINDEX: RESULT(sa.type, i, rta->nh.iface ? rta->nh.iface->index : 0); break;
diff --git a/lib/route.h b/lib/route.h
index 30ac2672..cfb08bbe 100644
--- a/lib/route.h
+++ b/lib/route.h
@@ -87,7 +87,6 @@ typedef struct rta {
struct ea_list *eattrs; /* Extended Attribute chain */
struct hostentry *hostentry; /* Hostentry for recursive next-hops */
u16 cached:1; /* Are attributes cached? */
- u16 source:7; /* Route source (RTS_...) */
u16 dest:4; /* Route destination type (RTD_...) */
struct nexthop nh; /* Next hop */
} rta;
@@ -133,12 +132,13 @@ static inline int rte_is_reachable(rte *r)
typedef struct eattr {
word id; /* EA_CODE(PROTOCOL_..., protocol-dependent ID) */
byte flags; /* Protocol-dependent flags */
- byte type:5; /* Attribute type */
+ byte type; /* Attribute type */
+ byte rfu:5;
byte originated:1; /* The attribute has originated locally */
byte fresh:1; /* An uncached attribute (e.g. modified in export filter) */
byte undef:1; /* Explicitly undefined */
- PADDING(unused, 0, 4);
+ PADDING(unused, 3, 3);
union bval u;
} eattr;
@@ -310,6 +310,12 @@ u32 rt_get_igp_metric(const rte *rt);
/* From: Advertising router */
extern struct ea_class ea_gen_from;
+/* Source: An old method to devise the route source protocol and kind.
+ * To be superseded in a near future by something more informative. */
+extern struct ea_class ea_gen_source;
+static inline u32 rt_get_source_attr(const rte *rt)
+{ return ea_get_int(rt->attrs->eattrs, &ea_gen_source, 0); }
+
/* Next hop structures */
#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
diff --git a/lib/type_test.c b/lib/type_test.c
index 20e7630b..b526db69 100644
--- a/lib/type_test.c
+++ b/lib/type_test.c
@@ -54,6 +54,7 @@ t_eattr(void)
e.id = ~0;
e.flags = ~0;
e.type = ~0;
+ e.rfu = ~0;
e.originated = ~0;
e.fresh = ~0;
e.undef = ~0;
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index a892bfd5..39fd7db4 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -92,6 +92,22 @@ const char * const rta_src_names[RTS_MAX] = {
[RTS_RPKI] = "RPKI",
};
+static void
+ea_gen_source_format(const eattr *a, byte *buf, uint size)
+{
+ if ((a->u.data >= RTS_MAX) || !rta_src_names[a->u.data])
+ bsnprintf(buf, size, "unknown");
+ else
+ bsnprintf(buf, size, "%s", rta_src_names[a->u.data]);
+}
+
+struct ea_class ea_gen_source = {
+ .name = "source",
+ .type = T_ENUM_RTS,
+ .readonly = 1,
+ .format = ea_gen_source_format,
+};
+
const char * rta_dest_names[RTD_MAX] = {
[RTD_NONE] = "",
[RTD_UNICAST] = "unicast",
@@ -1234,7 +1250,6 @@ rta_hash(rta *a)
#define MIX(f) mem_hash_mix(&h, &(a->f), sizeof(a->f));
#define BMIX(f) mem_hash_mix_num(&h, a->f);
MIX(hostentry);
- BMIX(source);
BMIX(dest);
#undef MIX
@@ -1244,8 +1259,7 @@ rta_hash(rta *a)
static inline int
rta_same(rta *x, rta *y)
{
- return (x->source == y->source &&
- x->dest == y->dest &&
+ return (x->dest == y->dest &&
x->hostentry == y->hostentry &&
nexthop_same(&(x->nh), &(y->nh)) &&
ea_same(x->eattrs, y->eattrs));
@@ -1388,15 +1402,10 @@ rta_do_cow(rta *o, linpool *lp)
void
rta_dump(rta *a)
{
- static char *rts[] = { "", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE",
- "RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP",
- "RTS_OSPF", "RTS_OSPF_IA", "RTS_OSPF_EXT1",
- "RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" };
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
- debug("uc=%d %s %s h=%04x",
- a->uc, rts[a->source],
- rtd[a->dest], a->hash_key);
+ debug("uc=%d %s h=%04x",
+ a->uc, rtd[a->dest], a->hash_key);
if (!a->cached)
debug(" !CACHED");
if (a->dest == RTD_UNICAST)
@@ -1441,8 +1450,6 @@ rta_dump_all(void)
void
rta_show(struct cli *c, rta *a)
{
- cli_printf(c, -1008, "\tType: %s", rta_src_names[a->source]);
-
for(ea_list *eal = a->eattrs; eal; eal=eal->next)
for(int i=0; i<eal->count; i++)
ea_show(c, &eal->attrs[i]);
@@ -1476,6 +1483,7 @@ rta_init(void)
ea_register_init(&ea_gen_preference);
ea_register_init(&ea_gen_igp_metric);
ea_register_init(&ea_gen_from);
+ ea_register_init(&ea_gen_source);
}
/*
diff --git a/nest/rt-dev.c b/nest/rt-dev.c
index 5d4233dc..b0ad34e6 100644
--- a/nest/rt-dev.c
+++ b/nest/rt-dev.c
@@ -80,12 +80,12 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
struct rte_src *src = rt_get_source(P, ad->iface->index);
rta a0 = {
- .source = RTS_DEVICE,
.dest = RTD_UNICAST,
.nh.iface = ad->iface,
};
ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, c->preference);
+ ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_DEVICE);
rte e0 = {
.attrs = rta_lookup(&a0),
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 3d42c9de..3f3aee18 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -2705,7 +2705,7 @@ rt_flowspec_check(rtable *tab_ip, rtable *tab_flow, const net_addr *n, rta *a, i
trie_add_prefix(tab_flow->flowspec_trie, &dst, (nb ? nb->n.addr->pxlen : 0), max_pxlen);
/* No best-match BGP route -> no flowspec */
- if (!rb || (rb->attrs->source != RTS_BGP))
+ if (!rb || (rt_get_source_attr(rb) != RTS_BGP))
return 0;
/* Find ORIGINATOR_ID values */
@@ -2737,7 +2737,7 @@ rt_flowspec_check(rtable *tab_ip, rtable *tab_flow, const net_addr *n, rta *a, i
continue;
const rte *rc = &nc->routes->rte;
- if (rc->attrs->source != RTS_BGP)
+ if (rt_get_source_attr(rc) != RTS_BGP)
return 0;
if (rta_get_first_asn(rc->attrs) != asn_b)
@@ -2754,7 +2754,7 @@ static struct rte_storage *
rt_flowspec_update_rte(rtable *tab, net *n, rte *r)
{
#ifdef CONFIG_BGP
- if (r->attrs->source != RTS_BGP)
+ if (rt_get_source_attr(r) != RTS_BGP)
return NULL;
struct bgp_channel *bc = (struct bgp_channel *) r->sender;
@@ -3549,7 +3549,7 @@ rt_get_igp_metric(const rte *rt)
if (ea)
return ea->u.data;
- if (rt->attrs->source == RTS_DEVICE)
+ if (rt_get_source_attr(rt) == RTS_DEVICE)
return 0;
if (rt->src->proto->rte_igp_metric)
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index d3eef506..be75694f 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -645,12 +645,13 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
{
struct {
ea_list l;
- eattr a[5];
+ eattr a[6];
} eattrs = {
.l.count = ARRAY_SIZE(eattrs.a),
.a = {
EA_LITERAL_EMBEDDED(&ea_gen_preference, 0, c->preference),
EA_LITERAL_STORE_ADATA(&ea_gen_from, 0, &r->neigh->addr, sizeof(r->neigh->addr)),
+ EA_LITERAL_EMBEDDED(&ea_gen_source, 0, RTS_BABEL),
EA_LITERAL_EMBEDDED(&ea_babel_metric, 0, r->metric),
EA_LITERAL_STORE_ADATA(&ea_babel_router_id, 0, &r->router_id, sizeof(r->router_id)),
EA_LITERAL_EMBEDDED(&ea_babel_seqno, 0, r->seqno),
@@ -658,7 +659,6 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
};
rta a0 = {
- .source = RTS_BABEL,
.dest = RTD_UNICAST,
.nh.gw = r->next_hop,
.nh.iface = r->neigh->ifa->iface,
@@ -685,11 +685,11 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
{
/* Unreachable */
rta a0 = {
- .source = RTS_BABEL,
.dest = RTD_UNREACHABLE,
};
ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, 1);
+ ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_BABEL);
rte e0 = {
.attrs = &a0,
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 6a91e6e7..11b1c728 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -404,7 +404,7 @@ bgp_total_aigp_metric_(const rte *e, u64 *metric, const struct adata **ad)
static inline int
bgp_init_aigp_metric(rte *e, u64 *metric, const struct adata **ad)
{
- if (e->attrs->source == RTS_BGP)
+ if (rt_get_source_attr(e) == RTS_BGP)
return 0;
*metric = rt_get_igp_metric(e);
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index b4d8b83f..24f3ec8f 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -43,7 +43,7 @@ CF_KEYWORDS(CEASE, PREFIX, LIMIT, HIT, ADMINISTRATIVE, SHUTDOWN, RESET, PEER,
CF_GRAMMAR
-toksym: BGP_MED | BGP_LOCAL_PREF ;
+toksym: BGP_MED | BGP_LOCAL_PREF | SOURCE ;
proto: bgp_proto '}' ;
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index c01dfeea..44a2f80a 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -2475,11 +2475,11 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
{
a = allocz(RTA_MAX_SIZE);
- a->source = RTS_BGP;
a->eattrs = ea;
ea_set_attr_data(&a->eattrs, &ea_gen_from, 0, &s->proto->remote_ip, sizeof(ip_addr));
ea_set_attr_u32(&a->eattrs, &ea_gen_preference, 0, c->c.preference);
+ ea_set_attr_u32(&a->eattrs, &ea_gen_source, 0, RTS_BGP);
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 121e8f9c..8fe64d95 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -392,15 +392,18 @@ ospf_rte_better(struct rte *new, struct rte *old)
if (new_metric1 == LSINFINITY)
return 0;
- if(new->attrs->source < old->attrs->source) return 1;
- if(new->attrs->source > old->attrs->source) return 0;
+ u32 ns = rt_get_source_attr(new);
+ u32 os = rt_get_source_attr(old);
- if(new->attrs->source == RTS_OSPF_EXT2)
+ if (ns < os) return 1;
+ if (ns > os) return 0;
+
+ if (ns == RTS_OSPF_EXT2)
{
u32 old_metric2 = ea_get_int(old->attrs->eattrs, &ea_ospf_metric2, LSINFINITY);
u32 new_metric2 = ea_get_int(new->attrs->eattrs, &ea_ospf_metric2, LSINFINITY);
- if(new_metric2 < old_metric2) return 1;
- if(new_metric2 > old_metric2) return 0;
+ if (new_metric2 < old_metric2) return 1;
+ if (new_metric2 > old_metric2) return 0;
}
u32 old_metric1 = ea_get_int(old->attrs->eattrs, &ea_ospf_metric1, LSINFINITY);
@@ -413,7 +416,7 @@ ospf_rte_better(struct rte *new, struct rte *old)
static u32
ospf_rte_igp_metric(const rte *rt)
{
- if (rt->attrs->source == RTS_OSPF_EXT2)
+ if (rt_get_source_attr(rt) == RTS_OSPF_EXT2)
return IGP_METRIC_UNKNOWN;
return ea_get_int(rt->attrs->eattrs, &ea_ospf_metric1, LSINFINITY);
@@ -571,7 +574,8 @@ ospf_get_route_info(rte * rte, byte * buf)
{
char *type = "<bug>";
- switch (rte->attrs->source)
+ uint source = rt_get_source_attr(rte);
+ switch (source)
{
case RTS_OSPF:
type = "I";
@@ -589,10 +593,10 @@ ospf_get_route_info(rte * rte, byte * buf)
buf += bsprintf(buf, " %s", type);
buf += bsprintf(buf, " (%d/%d", rt_get_preference(rte), ea_get_int(rte->attrs->eattrs, &ea_ospf_metric1, LSINFINITY));
- if (rte->attrs->source == RTS_OSPF_EXT2)
+ if (source == RTS_OSPF_EXT2)
buf += bsprintf(buf, "/%d", ea_get_int(rte->attrs->eattrs, &ea_ospf_metric2, LSINFINITY));
buf += bsprintf(buf, ")");
- if (rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2)
+ if (source == RTS_OSPF_EXT1 || source == RTS_OSPF_EXT2)
{
eattr *ea = ea_find(rte->attrs->eattrs, &ea_ospf_tag);
if (ea && (ea->u.data > 0))
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 0cfd3747..23b767bc 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -2004,11 +2004,19 @@ static inline int
ort_changed(ort *nf, rta *nr)
{
rta *or = nf->old_rta;
- return !or ||
+
+ if (!or ||
(nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) ||
(nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid) ||
- (nr->source != or->source) || (nr->dest != or->dest) ||
- !nexthop_same(&(nr->nh), &(or->nh));
+ (nr->dest != or->dest) ||
+ !nexthop_same(&(nr->nh), &(or->nh)))
+ return 1;
+
+ if ( ea_get_int(nr->eattrs, &ea_gen_source, 0)
+ != ea_get_int(or->eattrs, &ea_gen_source, 0))
+ return 1;
+
+ return 0;
}
static void
@@ -2053,7 +2061,6 @@ again1:
if (nf->n.type) /* Add the route */
{
rta a0 = {
- .source = nf->n.type,
.dest = RTD_UNICAST,
.nh = *(nf->n.nhs),
};
@@ -2067,7 +2074,7 @@ again1:
struct {
ea_list l;
- eattr a[5];
+ eattr a[6];
} eattrs;
eattrs.l = (ea_list) {};
@@ -2075,6 +2082,9 @@ again1:
eattrs.a[eattrs.l.count++] =
EA_LITERAL_EMBEDDED(&ea_gen_preference, 0, p->p.main_channel->preference);
+ eattrs.a[eattrs.l.count++] =
+ EA_LITERAL_EMBEDDED(&ea_gen_source, 0, nf->n.type);
+
eattrs.a[eattrs.l.count++] =
EA_LITERAL_EMBEDDED(&ea_ospf_metric1, 0, nf->n.metric1);
@@ -2089,6 +2099,7 @@ again1:
eattrs.a[eattrs.l.count++] =
EA_LITERAL_EMBEDDED(&ea_ospf_router_id, 0, nf->n.rid);
+ ASSERT_DIE(ARRAY_SIZE(eattrs.a) >= eattrs.l.count);
a0.eattrs = &eattrs.l;
rta_free(nf->old_rta);
diff --git a/proto/perf/perf.c b/proto/perf/perf.c
index 7c509eb0..2cb60e3e 100644
--- a/proto/perf/perf.c
+++ b/proto/perf/perf.c
@@ -143,7 +143,6 @@ perf_loop(void *data)
if (!p->attrs_per_rte || !(i % p->attrs_per_rte)) {
struct rta a0 = {
- .source = RTS_PERF,
.dest = RTD_UNICAST,
.nh.iface = p->ifa->iface,
.nh.gw = gw,
@@ -151,6 +150,7 @@ perf_loop(void *data)
};
ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, p->p.main_channel->preference);
+ ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_PERF);
p->data[i].a = rta_lookup(&a0);
}
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 1c7d1f1f..fbf91b94 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -152,17 +152,17 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
{
/* Update */
rta a0 = {
- .source = RTS_RIP,
.dest = RTD_UNICAST,
};
struct {
ea_list l;
- eattr a[2];
+ eattr a[3];
} ea_block = {
.l.count = ARRAY_SIZE(ea_block.a),
.a = {
EA_LITERAL_EMBEDDED(&ea_gen_preference, 0, p->p.main_channel->preference),
+ EA_LITERAL_EMBEDDED(&ea_gen_source, 0, RTS_RIP),
EA_LITERAL_EMBEDDED(&ea_rip_metric, 0, rt->metric),
},
};
diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c
index 8e2dbf49..96a794fa 100644
--- a/proto/rpki/rpki.c
+++ b/proto/rpki/rpki.c
@@ -121,11 +121,11 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_
struct rpki_proto *p = cache->p;
rta a0 = {
- .source = RTS_RPKI,
.dest = RTD_NONE,
};
ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, channel->preference);
+ ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_RPKI);
rte e0 = { .attrs = &a0, .src = p->p.main_source, };
diff --git a/proto/static/static.c b/proto/static/static.c
index 425cab1b..f7eddedb 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -55,9 +55,9 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
{
rta *a = allocz(RTA_MAX_SIZE);
struct rte_src *src = static_get_source(p, r->index);
- a->source = RTS_STATIC;
a->dest = r->dest;
ea_set_attr_u32(&a->eattrs, &ea_gen_preference, 0, p->p.main_channel->preference);
+ ea_set_attr_u32(&a->eattrs, &ea_gen_source, 0, RTS_STATIC);
if (r->dest == RTD_UNICAST)
{
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index 19ef2394..1c1bd50c 100644
--- a/sysdep/bsd/krt-sock.c
+++ b/sysdep/bsd/krt-sock.c
@@ -518,9 +518,10 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
net = net_get(p->p.main_channel->table, &ndst);
rta a = {
- .source = RTS_INHERIT,
};
+ ea_set_attr_u32(&a->eattrs, &ea_gen_source, 0, RTS_INHERIT);
+
/* reject/blackhole routes have also set RTF_GATEWAY,
we wil check them first. */
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 2dbe59e9..9c78ca48 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -1853,7 +1853,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
nl_announce_route(s);
rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE);
- ra->source = RTS_INHERIT;
+ ea_set_attr_u32(&ra->eattrs, &ea_gen_source, 0, RTS_INHERIT);
if (a[RTA_FLOW])
s->rta_flow = rta_get_u32(a[RTA_FLOW]);