diff options
-rw-r--r-- | nest/route.h | 2 | ||||
-rw-r--r-- | proto/rip/rip.c | 54 |
2 files changed, 37 insertions, 19 deletions
diff --git a/nest/route.h b/nest/route.h index 61a5f623..d703d681 100644 --- a/nest/route.h +++ b/nest/route.h @@ -700,9 +700,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 eeca7834..5bf1b3e6 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; + rte e0 = { .attrs = &a0, .src = p->p.main_source, @@ -322,7 +339,8 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *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) { |