summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-04-13 17:05:12 +0200
committerMaria Matejka <mq@ucw.cz>2022-04-13 17:05:12 +0200
commit98fd158e28d89f10ee7a41b4f6a14fbd0021ef35 (patch)
tree577347901debd9bba7d2bfad5f85afc67375e6db
parentd39ef961d1dde230c55fcc931b53f44cb34a1e63 (diff)
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.
-rw-r--r--nest/route.h2
-rw-r--r--proto/rip/rip.c54
2 files changed, 37 insertions, 19 deletions
diff --git a/nest/route.h b/nest/route.h
index bf25dcf9..80c53ba6 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -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) */
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 9d8b9849..6ca7a6b5 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -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)
{