RIP: fixed the EA_RIP_FROM attribute

The interface pointer was improperly converted to u32 and back. Fixing
this by explicitly allocating an adata structure for it. It's not so
memory efficient, we'll optimize this later.
This commit is contained in:
Maria Matejka 2022-04-13 17:05:12 +02:00
parent d39ef961d1
commit 98fd158e28
2 changed files with 37 additions and 19 deletions

View file

@ -538,9 +538,9 @@ const char *ea_custom_name(uint ea);
#define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */
#define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */
#define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */
#define EAF_TYPE_PTR 0x0d /* Pointer to an object */
#define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */
#define EAF_TYPE_LC_SET 0x12 /* Set of triplets of u32's - large community list */
#define EAF_TYPE_IFACE 0x16 /* Interface pointer stored in adata */
#define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */
#define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */

View file

@ -124,6 +124,11 @@ static inline int rip_same_rte(struct rip_rte *a, struct rip_rte *b)
static inline int rip_valid_rte(struct rip_rte *rt)
{ return rt->from->ifa != NULL; }
struct rip_iface_adata {
struct adata ad;
struct iface *iface;
};
/**
* rip_announce_rte - announce route from RIP routing table to the core
* @p: RIP instance
@ -188,25 +193,37 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
a0.nh.iface = rt->from->ifa->iface;
}
a0.eattrs = alloca(sizeof(ea_list) + 3*sizeof(eattr));
memset(a0.eattrs, 0, sizeof(ea_list)); /* Zero-ing only the ea_list header */
a0.eattrs->count = 3;
a0.eattrs->attrs[0] = (eattr) {
.id = EA_RIP_METRIC,
.type = EAF_TYPE_INT,
.u.data = rt_metric,
};
a0.eattrs->attrs[1] = (eattr) {
.id = EA_RIP_TAG,
.type = EAF_TYPE_INT,
.u.data = rt_tag,
};
a0.eattrs->attrs[2] = (eattr) {
.id = EA_RIP_FROM,
.type = EAF_TYPE_PTR,
.u.data = (uintptr_t) a0.nh.iface,
struct {
ea_list l;
eattr e[3];
struct rip_iface_adata riad;
} ea_block = {
.l = { .count = 3, },
.e = {
{
.id = EA_RIP_METRIC,
.type = EAF_TYPE_INT,
.u.data = rt_metric,
},
{
.id = EA_RIP_TAG,
.type = EAF_TYPE_INT,
.u.data = rt_tag,
},
{
.id = EA_RIP_FROM,
.type = EAF_TYPE_IFACE,
.u.ptr = &ea_block.riad.ad,
}
},
.riad = {
.ad = { .length = sizeof(struct rip_iface_adata) - sizeof(struct adata) },
.iface = a0.nh.iface,
},
};
a0.eattrs = &ea_block.l;
rta *a = rta_lookup(&a0);
rte *e = rte_get_temp(a, p->p.main_source);
@ -323,7 +340,8 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
/* Update */
u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0);
u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1);
struct iface *rt_from = (struct iface *) ea_get_int(new->attrs->eattrs, EA_RIP_FROM, 0);
const eattr *rie = ea_find(new->attrs->eattrs, EA_RIP_FROM);
struct iface *rt_from = rie ? ((struct rip_iface_adata *) rie->u.ptr)->iface : NULL;
if (rt_metric > p->infinity)
{