1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

Explicit definition structures of route attributes

Changes in internal API:

* Every route attribute must be defined as struct ea_class somewhere.
* Registration of route attributes known at startup must be done by
  ea_register_init() from protocol build functions.
* Every attribute has now its symbol registered in a global symbol table
  defined as SYM_ATTRIBUTE
* All attribute ID's are dynamically allocated.
* Attribute value custom formatting hook is defined in the ea_class.
* Attribute names are the same for display and filters, always prefixed
  by protocol name.

Also added some unit testing code for filters with route attributes.
This commit is contained in:
Maria Matejka
2022-03-19 16:23:42 +01:00
parent 165156beeb
commit 17f91f9e6e
54 changed files with 1056 additions and 878 deletions

View File

@@ -78,6 +78,7 @@
#include <stdlib.h>
#include "rip.h"
#include "lib/macro.h"
static inline void rip_lock_neighbor(struct rip_neighbor *n);
@@ -88,6 +89,7 @@ static inline void rip_iface_kick_timer(struct rip_iface *ifa);
static void rip_iface_timer(timer *timer);
static void rip_trigger_update(struct rip_proto *p);
static struct ea_class ea_rip_metric, ea_rip_tag, ea_rip_from;
/*
* RIP routes
@@ -200,9 +202,9 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
} ea_block = {
.l.count = 3,
.a = {
EA_LITERAL_EMBEDDED(EA_RIP_METRIC, T_INT, 0, rt_metric),
EA_LITERAL_EMBEDDED(EA_RIP_TAG, T_INT, 0, rt_tag),
EA_LITERAL_DIRECT_ADATA(EA_RIP_FROM, T_IFACE, 0, &ea_block.riad.ad),
EA_LITERAL_EMBEDDED(&ea_rip_metric, 0, rt_metric),
EA_LITERAL_EMBEDDED(&ea_rip_tag, 0, rt_tag),
EA_LITERAL_DIRECT_ADATA(&ea_rip_from, 0, &ea_block.riad.ad),
},
.riad = {
.ad = { .length = sizeof(struct rip_iface_adata) - sizeof(struct adata) },
@@ -326,9 +328,9 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
if (new)
{
/* 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);
const eattr *rie = ea_find(new->attrs->eattrs, EA_RIP_FROM);
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);
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)
@@ -1095,8 +1097,8 @@ rip_rte_better(struct rte *new, struct rte *old)
ASSERT_DIE(new->src == old->src);
struct rip_proto *p = (struct rip_proto *) new->src->proto;
u32 new_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, p->infinity);
u32 old_metric = ea_get_int(old->attrs->eattrs, EA_RIP_METRIC, p->infinity);
u32 new_metric = ea_get_int(new->attrs->eattrs, &ea_rip_metric, p->infinity);
u32 old_metric = ea_get_int(old->attrs->eattrs, &ea_rip_metric, p->infinity);
return new_metric < old_metric;
}
@@ -1104,7 +1106,7 @@ rip_rte_better(struct rte *new, struct rte *old)
static u32
rip_rte_igp_metric(struct rte *rt)
{
return ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, IGP_METRIC_UNKNOWN);
return ea_get_int(rt->attrs->eattrs, &ea_rip_metric, IGP_METRIC_UNKNOWN);
}
static void
@@ -1205,8 +1207,8 @@ static void
rip_get_route_info(rte *rte, byte *buf)
{
struct rip_proto *p = (struct rip_proto *) rte->src->proto;
u32 rt_metric = ea_get_int(rte->attrs->eattrs, EA_RIP_METRIC, p->infinity);
u32 rt_tag = ea_get_int(rte->attrs->eattrs, EA_RIP_TAG, 0);
u32 rt_metric = ea_get_int(rte->attrs->eattrs, &ea_rip_metric, p->infinity);
u32 rt_tag = ea_get_int(rte->attrs->eattrs, &ea_rip_tag, 0);
buf += bsprintf(buf, " (%d/%d)", rte->attrs->pref, rt_metric);
@@ -1214,24 +1216,29 @@ rip_get_route_info(rte *rte, byte *buf)
bsprintf(buf, " [%04x]", rt_tag);
}
static int
rip_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
static void
rip_tag_format(const eattr *a, byte *buf, uint buflen)
{
switch (a->id)
{
case EA_RIP_METRIC:
bsprintf(buf, "metric: %d", a->u.data);
return GA_FULL;
case EA_RIP_TAG:
bsprintf(buf, "tag: %04x", a->u.data);
return GA_FULL;
default:
return GA_UNKNOWN;
}
bsnprintf(buf, buflen, "tag: %04x", a->u.data);
}
static struct ea_class ea_rip_metric = {
.name = "rip_metric",
.type = T_INT,
};
static struct ea_class ea_rip_tag = {
.name = "rip_tag",
.type = T_INT,
.format = rip_tag_format,
};
static struct ea_class ea_rip_from = {
.name = "rip_from",
.type = T_IFACE,
.readonly = 1,
};
void
rip_show_interfaces(struct proto *P, const char *iff)
{
@@ -1334,7 +1341,6 @@ rip_dump(struct proto *P)
struct protocol proto_rip = {
.name = "RIP",
.template = "rip%d",
.class = PROTOCOL_RIP,
.preference = DEF_PREF_RIP,
.channel_mask = NB_IP,
.proto_size = sizeof(struct rip_proto),
@@ -1346,11 +1352,16 @@ struct protocol proto_rip = {
.shutdown = rip_shutdown,
.reconfigure = rip_reconfigure,
.get_route_info = rip_get_route_info,
.get_attr = rip_get_attr
};
void
rip_build(void)
{
proto_build(&proto_rip);
EA_REGISTER_ALL(
&ea_rip_metric,
&ea_rip_tag,
&ea_rip_from
);
}