summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-05-30 16:59:24 +0200
committerMaria Matejka <mq@ucw.cz>2022-05-30 16:59:24 +0200
commit5051e3c4afe04aeb59abeaa3370c9e660dfa37f1 (patch)
treeed70693701387b10d87710199b7770ae7153c23b /proto
parentc1645b9d5bef3d08ef91ac21197a4860a490bfd4 (diff)
parent17f91f9e6e70f7e3f29502e854823c0d48571eaa (diff)
Merge commit '17f91f9e6e70f7e3f29502e854823c0d48571eaa' into haugesund
Diffstat (limited to 'proto')
-rw-r--r--proto/babel/babel.c76
-rw-r--r--proto/babel/babel.h4
-rw-r--r--proto/babel/config.Y2
-rw-r--r--proto/bfd/bfd.c1
-rw-r--r--proto/bgp/attrs.c308
-rw-r--r--proto/bgp/bgp.c3
-rw-r--r--proto/bgp/bgp.h54
-rw-r--r--proto/bgp/config.Y30
-rw-r--r--proto/mrt/mrt.c1
-rw-r--r--proto/ospf/config.Y5
-rw-r--r--proto/ospf/ospf.c71
-rw-r--r--proto/ospf/ospf.h7
-rw-r--r--proto/ospf/rt.c8
-rw-r--r--proto/ospf/topology.c6
-rw-r--r--proto/perf/perf.c1
-rw-r--r--proto/pipe/pipe.c1
-rw-r--r--proto/radv/config.Y3
-rw-r--r--proto/radv/radv.c42
-rw-r--r--proto/radv/radv.h4
-rw-r--r--proto/rip/config.Y3
-rw-r--r--proto/rip/rip.c65
-rw-r--r--proto/rip/rip.h4
-rw-r--r--proto/rpki/rpki.c1
-rw-r--r--proto/static/static.c11
24 files changed, 342 insertions, 369 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index fcd7eafb..f19a2e0f 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -37,6 +37,7 @@
#include <stdlib.h>
#include "babel.h"
+#include "lib/macro.h"
#define LOG_PKT_AUTH(msg, args...) \
log_rl(&p->log_pkt_tbf, L_AUTH "%s: " msg, p->p.name, args)
@@ -58,6 +59,8 @@ static void babel_update_cost(struct babel_neighbor *n);
static inline void babel_kick_timer(struct babel_proto *p);
static inline void babel_iface_kick_timer(struct babel_iface *ifa);
+static struct ea_class ea_babel_metric, ea_babel_router_id, ea_babel_seqno;
+
/*
* Functions to maintain data structures
*/
@@ -646,9 +649,9 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
} eattrs = {
.l.count = 3,
.a = {
- EA_LITERAL_EMBEDDED(EA_BABEL_METRIC, T_INT, 0, r->metric),
- EA_LITERAL_STORE_ADATA(EA_BABEL_ROUTER_ID, T_OPAQUE, 0, &r->router_id, sizeof(r->router_id)),
- EA_LITERAL_EMBEDDED(EA_BABEL_SEQNO, T_INT, 0, r->seqno),
+ 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),
}
};
@@ -2021,38 +2024,40 @@ static void
babel_get_route_info(rte *rte, byte *buf)
{
u64 rid = 0;
- eattr *e = ea_find(rte->attrs->eattrs, EA_BABEL_ROUTER_ID);
+ eattr *e = ea_find(rte->attrs->eattrs, &ea_babel_router_id);
if (e)
memcpy(&rid, e->u.ptr->data, sizeof(u64));
buf += bsprintf(buf, " (%d/%d) [%lR]", rte->attrs->pref,
- ea_get_int(rte->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY), rid);
+ ea_get_int(rte->attrs->eattrs, &ea_babel_metric, BABEL_INFINITY), rid);
}
-static int
-babel_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
+static void
+babel_router_id_format(const eattr *a, byte *buf, uint len)
{
- switch (a->id)
- {
- case EA_BABEL_SEQNO:
- return GA_FULL;
+ u64 rid = 0;
+ memcpy(&rid, a->u.ptr->data, sizeof(u64));
+ bsnprintf(buf, len, "%lR", rid);
+}
- case EA_BABEL_METRIC:
- bsprintf(buf, "metric: %d", a->u.data);
- return GA_FULL;
+static struct ea_class ea_babel_metric = {
+ .name = "babel_metric",
+ .type = T_INT,
+};
- case EA_BABEL_ROUTER_ID:
- {
- u64 rid = 0;
- memcpy(&rid, a->u.ptr->data, sizeof(u64));
- bsprintf(buf, "router_id: %lR", rid);
- return GA_FULL;
- }
+static struct ea_class ea_babel_router_id = {
+ .name = "babel_router_id",
+ .type = T_OPAQUE,
+ .readonly = 1,
+ .format = babel_router_id_format,
+};
+
+static struct ea_class ea_babel_seqno = {
+ .name = "babel_seqno",
+ .type = T_INT,
+ .readonly = 1,
+};
- default:
- return GA_UNKNOWN;
- }
-}
void
babel_show_interfaces(struct proto *P, const char *iff)
@@ -2275,13 +2280,13 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net,
{
/* Update */
uint rt_seqno;
- uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
+ uint rt_metric = ea_get_int(new->attrs->eattrs, &ea_babel_metric, 0);
u64 rt_router_id = 0;
if (new->src->proto == P)
{
- rt_seqno = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
- eattr *e = ea_find(new->attrs->eattrs, EA_BABEL_ROUTER_ID);
+ rt_seqno = ea_get_int(new->attrs->eattrs, &ea_babel_seqno, 0);
+ eattr *e = ea_find(new->attrs->eattrs, &ea_babel_router_id);
if (e)
memcpy(&rt_router_id, e->u.ptr->data, sizeof(u64));
}
@@ -2332,8 +2337,8 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net,
static int
babel_rte_better(struct rte *new, struct rte *old)
{
- uint new_metric = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
- uint old_metric = ea_find(old->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
+ uint new_metric = ea_get_int(new->attrs->eattrs, &ea_babel_metric, BABEL_INFINITY);
+ uint old_metric = ea_get_int(old->attrs->eattrs, &ea_babel_metric, BABEL_INFINITY);
return new_metric < old_metric;
}
@@ -2341,7 +2346,7 @@ babel_rte_better(struct rte *new, struct rte *old)
static u32
babel_rte_igp_metric(struct rte *rt)
{
- return ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY);
+ return ea_get_int(rt->attrs->eattrs, &ea_babel_metric, BABEL_INFINITY);
}
@@ -2474,11 +2479,9 @@ babel_reconfigure(struct proto *P, struct proto_config *CF)
return 1;
}
-
struct protocol proto_babel = {
.name = "Babel",
.template = "babel%d",
- .class = PROTOCOL_BABEL,
.preference = DEF_PREF_BABEL,
.channel_mask = NB_IP | NB_IP6_SADR,
.proto_size = sizeof(struct babel_proto),
@@ -2490,11 +2493,16 @@ struct protocol proto_babel = {
.shutdown = babel_shutdown,
.reconfigure = babel_reconfigure,
.get_route_info = babel_get_route_info,
- .get_attr = babel_get_attr
};
void
babel_build(void)
{
proto_build(&proto_babel);
+
+ EA_REGISTER_ALL(
+ &ea_babel_metric,
+ &ea_babel_router_id,
+ &ea_babel_seqno
+ );
}
diff --git a/proto/babel/babel.h b/proto/babel/babel.h
index 00814641..a980d1da 100644
--- a/proto/babel/babel.h
+++ b/proto/babel/babel.h
@@ -26,10 +26,6 @@
#include "lib/string.h"
#include "lib/timer.h"
-#define EA_BABEL_METRIC EA_CODE(PROTOCOL_BABEL, 0)
-#define EA_BABEL_ROUTER_ID EA_CODE(PROTOCOL_BABEL, 1)
-#define EA_BABEL_SEQNO EA_CODE(PROTOCOL_BABEL, 2)
-
#define BABEL_MAGIC 42
#define BABEL_VERSION 2
#define BABEL_PORT 6696
diff --git a/proto/babel/config.Y b/proto/babel/config.Y
index fa745993..82419b20 100644
--- a/proto/babel/config.Y
+++ b/proto/babel/config.Y
@@ -163,8 +163,6 @@ babel_iface_opt_list:
babel_iface:
babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish;
-dynamic_attr: BABEL_METRIC { $$ = f_new_dynamic_attr(T_INT, EA_BABEL_METRIC); } ;
-
CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]);
CF_CLI(SHOW BABEL INTERFACES, optproto opttext, [<name>] [\"<interface>\"], [[Show information about Babel interfaces]])
diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c
index 873e2ed5..871ecf69 100644
--- a/proto/bfd/bfd.c
+++ b/proto/bfd/bfd.c
@@ -1183,7 +1183,6 @@ bfd_show_sessions(struct proto *P)
struct protocol proto_bfd = {
.name = "BFD",
.template = "bfd%d",
- .class = PROTOCOL_BFD,
.proto_size = sizeof(struct bfd_proto),
.config_size = sizeof(struct bfd_config),
.init = bfd_init,
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index e6f11a88..a713b7a2 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -21,6 +21,7 @@
#include "lib/resource.h"
#include "lib/string.h"
#include "lib/unaligned.h"
+#include "lib/macro.h"
#include "bgp.h"
@@ -64,28 +65,37 @@
* format - Optional hook that converts eattr to textual representation.
*/
-
-struct bgp_attr_desc {
- const char *name;
- uint type;
- uint flags;
- void (*export)(struct bgp_export_state *s, eattr *a);
- int (*encode)(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
- void (*decode)(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to);
- void (*format)(const eattr *ea, byte *buf, uint size);
+union bgp_attr_desc {
+ struct ea_class class;
+ struct {
+ EA_CLASS_INSIDE;
+ uint flags;
+ void (*export)(struct bgp_export_state *s, eattr *a);
+ int (*encode)(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
+ void (*decode)(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to);
+ };
};
-static const struct bgp_attr_desc bgp_attr_table[];
+static union bgp_attr_desc bgp_attr_table[];
+static inline const union bgp_attr_desc *bgp_find_attr_desc(eattr *a)
+{
+ const struct ea_class *class = ea_class_find(a->id);
+
+ if ((class < &bgp_attr_table[0].class) || (class >= &bgp_attr_table[BGP_ATTR_MAX].class))
+ return NULL;
+
+ return (const union bgp_attr_desc *) class;
+}
-static inline int bgp_attr_known(uint code);
+#define BGP_EA_ID(code) (bgp_attr_table[code].id)
+#define EA_BGP_ID(code) (((union bgp_attr_desc *) ea_class_find(code)) - bgp_attr_table)
void bgp_set_attr_u32(ea_list **to, uint code, uint flags, u32 val)
{
- ASSERT(bgp_attr_known(code));
+ const union bgp_attr_desc *desc = &bgp_attr_table[code];
ea_set_attr(to, EA_LITERAL_EMBEDDED(
- EA_CODE(PROTOCOL_BGP, code),
- bgp_attr_table[code].type,
+ &desc->class,
flags & ~BAF_EXT_LEN,
val
));
@@ -93,11 +103,10 @@ void bgp_set_attr_u32(ea_list **to, uint code, uint flags, u32 val)
void bgp_set_attr_ptr(ea_list **to, uint code, uint flags, const struct adata *ad)
{
- ASSERT(bgp_attr_known(code));
+ const union bgp_attr_desc *desc = &bgp_attr_table[code];
ea_set_attr(to, EA_LITERAL_DIRECT_ADATA(
- EA_CODE(PROTOCOL_BGP, code),
- bgp_attr_table[code].type,
+ &desc->class,
flags & ~BAF_EXT_LEN,
ad
));
@@ -106,17 +115,23 @@ void bgp_set_attr_ptr(ea_list **to, uint code, uint flags, const struct adata *a
void
bgp_set_attr_data(ea_list **to, uint code, uint flags, void *data, uint len)
{
- ASSERT(bgp_attr_known(code));
+ const union bgp_attr_desc *desc = &bgp_attr_table[code];
ea_set_attr(to, EA_LITERAL_STORE_ADATA(
- EA_CODE(PROTOCOL_BGP, code),
- bgp_attr_table[code].type,
+ &desc->class,
flags & ~BAF_EXT_LEN,
data,
len
));
}
+void
+bgp_unset_attr(ea_list **to, uint code)
+{
+ const union bgp_attr_desc *desc = &bgp_attr_table[code];
+ ea_unset_attr(to, 0, &desc->class);
+}
+
#define REPORT(msg, args...) \
({ log(L_REMOTE "%s: " msg, s->proto->p.name, ## args); })
@@ -172,7 +187,7 @@ bgp_encode_u8(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
if (size < (3+1))
return -1;
- bgp_put_attr_hdr3(buf, EA_ID(a->id), a->flags, 1);
+ bgp_put_attr_hdr3(buf, EA_BGP_ID(a->id), a->flags, 1);
buf[3] = a->u.data;
return 3+1;
@@ -184,7 +199,7 @@ bgp_encode_u32(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
if (size < (3+4))
return -1;
- bgp_put_attr_hdr3(buf, EA_ID(a->id), a->flags, 4);
+ bgp_put_attr_hdr3(buf, EA_BGP_ID(a->id), a->flags, 4);
put_u32(buf+3, a->u.data);
return 3+4;
@@ -198,7 +213,7 @@ bgp_encode_u32s(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size
if (size < (4+len))
return -1;
- uint hdr = bgp_put_attr_hdr(buf, EA_ID(a->id), a->flags, len);
+ uint hdr = bgp_put_attr_hdr(buf, EA_BGP_ID(a->id), a->flags, len);
put_u32s(buf + hdr, (u32 *) a->u.ptr->data, len / 4);
return hdr + len;
@@ -219,7 +234,7 @@ bgp_put_attr(byte *buf, uint size, uint code, uint flags, const byte *data, uint
static int
bgp_encode_raw(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
{
- return bgp_put_attr(buf, size, EA_ID(a->id), a->flags, a->u.ptr->data, a->u.ptr->length);
+ return bgp_put_attr(buf, size, EA_BGP_ID(a->id), a->flags, a->u.ptr->data, a->u.ptr->length);
}
@@ -359,7 +374,7 @@ bgp_aigp_set_metric(struct linpool *pool, const struct adata *ad, u64 metric)
int
bgp_total_aigp_metric_(struct rta *a, u64 *metric, const struct adata **ad)
{
- eattr *ea = ea_find(a->eattrs, EA_CODE(PROTOCOL_BGP, BA_AIGP));
+ eattr *ea = ea_find(a->eattrs, BGP_EA_ID(BA_AIGP));
if (!ea)
return 0;
@@ -994,10 +1009,29 @@ bgp_format_mpls_label_stack(const eattr *a, byte *buf, uint size)
}
static inline void
+bgp_export_unknown(struct bgp_export_state *s UNUSED, eattr *a)
+{
+ if (!(a->flags & BAF_TRANSITIVE))
+ UNSET(a);
+
+ a->flags |= BAF_PARTIAL;
+}
+
+static inline void
bgp_decode_unknown(struct bgp_parse_state *s UNUSED, uint code, uint flags, byte *data, uint len, ea_list **to)
{
+ if (!(flags & BAF_OPTIONAL))
+ WITHDRAW("Unknown attribute (code %u) - conflicting flags (%02x)", code, flags);
+
/* Cannot use bgp_set_attr_data() as it works on known attributes only */
- ea_set_attr_data(to, EA_CODE(PROTOCOL_BGP, code), flags, T_OPAQUE, data, len);
+ ea_set_attr_data(to, &bgp_attr_table[code].class, flags, data, len);
+}
+
+static inline void
+bgp_format_unknown(const eattr *a, byte *buf, uint size)
+{
+ if (a->flags & BAF_TRANSITIVE)
+ bsnprintf(buf, size, "(transitive)");
}
@@ -1005,9 +1039,9 @@ bgp_decode_unknown(struct bgp_parse_state *s UNUSED, uint code, uint flags, byte
* Attribute table
*/
-static const struct bgp_attr_desc bgp_attr_table[] = {
+static union bgp_attr_desc bgp_attr_table[BGP_ATTR_MAX] = {
[BA_ORIGIN] = {
- .name = "origin",
+ .name = "bgp_origin",
.type = T_ENUM_BGP_ORIGIN,
.flags = BAF_TRANSITIVE,
.export = bgp_export_origin,
@@ -1016,14 +1050,14 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.format = bgp_format_origin,
},
[BA_AS_PATH] = {
- .name = "as_path",
+ .name = "bgp_path",
.type = T_PATH,
.flags = BAF_TRANSITIVE,
.encode = bgp_encode_as_path,
.decode = bgp_decode_as_path,
},
[BA_NEXT_HOP] = {
- .name = "next_hop",
+ .name = "bgp_next_hop",
.type = T_IP,
.flags = BAF_TRANSITIVE,
.encode = bgp_encode_next_hop,
@@ -1031,14 +1065,14 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.format = bgp_format_next_hop,
},
[BA_MULTI_EXIT_DISC] = {
- .name = "med",
+ .name = "bgp_med",
.type = T_INT,
.flags = BAF_OPTIONAL,
.encode = bgp_encode_u32,
.decode = bgp_decode_med,
},
[BA_LOCAL_PREF] = {
- .name = "local_pref",
+ .name = "bgp_local_pref",
.type = T_INT,
.flags = BAF_TRANSITIVE,
.export = bgp_export_local_pref,
@@ -1046,14 +1080,14 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.decode = bgp_decode_local_pref,
},
[BA_ATOMIC_AGGR] = {
- .name = "atomic_aggr",
+ .name = "bgp_atomic_aggr",
.type = T_OPAQUE,
.flags = BAF_TRANSITIVE,
.encode = bgp_encode_raw,
.decode = bgp_decode_atomic_aggr,
},
[BA_AGGREGATOR] = {
- .name = "aggregator",
+ .name = "bgp_aggregator",
.type = T_OPAQUE,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.encode = bgp_encode_aggregator,
@@ -1061,7 +1095,7 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.format = bgp_format_aggregator,
},
[BA_COMMUNITY] = {
- .name = "community",
+ .name = "bgp_community",
.type = T_CLIST,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.export = bgp_export_community,
@@ -1069,7 +1103,7 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.decode = bgp_decode_community,
},
[BA_ORIGINATOR_ID] = {
- .name = "originator_id",
+ .name = "bgp_originator_id",
.type = T_QUAD,
.flags = BAF_OPTIONAL,
.export = bgp_export_originator_id,
@@ -1077,7 +1111,7 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.decode = bgp_decode_originator_id,
},
[BA_CLUSTER_LIST] = {
- .name = "cluster_list",
+ .name = "bgp_cluster_list",
.type = T_CLIST,
.flags = BAF_OPTIONAL,
.export = bgp_export_cluster_list,
@@ -1086,19 +1120,19 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.format = bgp_format_cluster_list,
},
[BA_MP_REACH_NLRI] = {
- .name = "mp_reach_nlri",
+ .name = "bgp_mp_reach_nlri",
.type = T_OPAQUE,
.flags = BAF_OPTIONAL,
.decode = bgp_decode_mp_reach_nlri,
},
[BA_MP_UNREACH_NLRI] = {
- .name = "mp_unreach_nlri",
+ .name = "bgp_mp_unreach_nlri",
.type = T_OPAQUE,
.flags = BAF_OPTIONAL,
.decode = bgp_decode_mp_unreach_nlri,
},
[BA_EXT_COMMUNITY] = {
- .name = "ext_community",
+ .name = "bgp_ext_community",
.type = T_ECLIST,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.export = bgp_export_ext_community,
@@ -1106,14 +1140,14 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.decode = bgp_decode_ext_community,
},
[BA_AS4_PATH] = {
- .name = "as4_path",
+ .name = "bgp_as4_path",
.type = T_PATH,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.encode = bgp_encode_raw,
.decode = bgp_decode_as4_path,
},
[BA_AS4_AGGREGATOR] = {
- .name = "as4_aggregator",
+ .name = "bgp_as4_aggregator",
.type = T_OPAQUE,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.encode = bgp_encode_raw,
@@ -1121,7 +1155,7 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.format = bgp_format_aggregator,
},
[BA_AIGP] = {
- .name = "aigp",
+ .name = "bgp_aigp",
.type = T_OPAQUE,
.flags = BAF_OPTIONAL | BAF_DECODE_FLAGS,
.export = bgp_export_aigp,
@@ -1130,7 +1164,7 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.format = bgp_format_aigp,
},
[BA_LARGE_COMMUNITY] = {
- .name = "large_community",
+ .name = "bgp_large_community",
.type = T_LCLIST,
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
.export = bgp_export_large_community,
@@ -1138,8 +1172,9 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
.decode = bgp_decode_large_community,
},
[BA_MPLS_LABEL_STACK] = {
- .name = "mpls_label_stack",
+ .name = "bgp_mpls_label_stack",
.type = T_CLIST,
+ .readonly = 1,
.export = bgp_export_mpls_label_stack,
.encode = bgp_encode_mpls_label_stack,
.decode = bgp_decode_mpls_label_stack,
@@ -1147,12 +1182,32 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
},
};
-static inline int
-bgp_attr_known(uint code)
+eattr *
+bgp_find_attr(ea_list *attrs, uint code)
{
- return (code < ARRAY_SIZE(bgp_attr_table)) && bgp_attr_table[code].name;
+ return ea_find(attrs, BGP_EA_ID(code));
}
+void
+bgp_register_attrs(void)
+{
+ for (uint i=0; i<ARRAY_SIZE(bgp_attr_table); i++)
+ {
+ if (!bgp_attr_table[i].name)
+ bgp_attr_table[i] = (union bgp_attr_desc) {
+ .name = mb_sprintf(&root_pool, "bgp_unknown_0x%02x", i),
+ .type = T_OPAQUE,
+ .flags = BAF_OPTIONAL,
+ .readonly = 1,
+ .export = bgp_export_unknown,
+ .encode = bgp_encode_raw,
+ .decode = bgp_decode_unknown,
+ .format = bgp_format_unknown,
+ };
+
+ ea_register_init(&bgp_attr_table[i].class);
+ }
+}
/*
* Attribute export
@@ -1161,38 +1216,24 @@ bgp_attr_known(uint code)
static inline void
bgp_export_attr(struct bgp_export_state *s, eattr *a, ea_list *to)
{
- if (EA_PROTO(a->id) != PROTOCOL_BGP)
+ const union bgp_attr_desc *desc = bgp_find_attr_desc(a);
+ if (!desc)
return;
- uint code = EA_ID(a->id);
-
- if (bgp_attr_known(code))
- {
- const struct bgp_attr_desc *desc = &bgp_attr_table[code];
-
- /* The flags might have been zero if the attr was added by filters */
- a->flags = (a->flags & BAF_PARTIAL) | desc->flags;
-
- /* Set partial bit if new opt-trans attribute is attached to non-local route */
- if ((s->src != NULL) && (a->originated) &&
- (a->flags & BAF_OPTIONAL) && (a->flags & BAF_TRANSITIVE))
- a->flags |= BAF_PARTIAL;
+ /* The flags might have been zero if the attr was added locally */
+ a->flags = (a->flags & BAF_PARTIAL) | desc->flags;
- /* Call specific hook */
- CALL(desc->export, s, a);
+ /* Set partial bit if new opt-trans attribute is attached to non-local route */
+ if ((s->src != NULL) && (a->originated) &&
+ (a->flags & BAF_OPTIONAL) && (a->flags & BAF_TRANSITIVE))
+ a->flags |= BAF_PARTIAL;
- /* Attribute might become undefined in hook */
- if (a->undef)
- return;
- }
- else
- {
- /* Don't re-export unknown non-transitive attributes */
- if (!(a->flags & BAF_TRANSITIVE))
- return;
+ /* Call specific hook */
+ CALL(desc->export, s, a);
- a->flags |= BAF_PARTIAL;
- }
+ /* Attribute might become undefined in hook */
+ if (a->undef)
+ return;
/* Append updated attribute */
to->attrs[to->count++] = *a;
@@ -1240,14 +1281,9 @@ bgp_export_attrs(struct bgp_export_state *s, const ea_list *a)
static inline int
bgp_encode_attr(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
{
- ASSERT(EA_PROTO(a->id) == PROTOCOL_BGP);
-
- uint code = EA_ID(a->id);
-
- if (bgp_attr_known(code))
- return bgp_attr_table[code].encode(s, a, buf, size);
- else
- return bgp_encode_raw(s, a, buf, size);
+ const union bgp_attr_desc *desc = bgp_find_attr_desc(a);
+ ASSERT_DIE(desc);
+ return desc->encode(s, a, buf, size);
}
/**
@@ -1312,7 +1348,7 @@ bgp_cluster_list_loopy(struct bgp_proto *p, ea_list *attrs)
}
static inline void
-bgp_decode_attr(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to)
+bgp_decode_attr(struct bgp_parse_state *s, byte code, byte flags, byte *data, uint len, ea_list **to)
{
/* Handle duplicate attributes; RFC 7606 3 (g) */
if (BIT32_TEST(s->attrs_seen, code))
@@ -1324,24 +1360,15 @@ bgp_decode_attr(struct bgp_parse_state *s, uint code, uint flags, byte *data, ui
}
BIT32_SET(s->attrs_seen, code);
- if (bgp_attr_known(code))
- {
- const struct bgp_attr_desc *desc = &bgp_attr_table[code];
+ ASSERT_DIE(bgp_attr_table[code].id);
+ const union bgp_attr_desc *desc = &bgp_attr_table[code];
- /* Handle conflicting flags; RFC 7606 3 (c) */
- if (((flags ^ desc->flags) & (BAF_OPTIONAL | BAF_TRANSITIVE)) &&
- !(desc->flags & BAF_DECODE_FLAGS))
- WITHDRAW("Malformed %s attribute - conflicting flags (%02x)", desc->name, flags);
+ /* Handle conflicting flags; RFC 7606 3 (c) */
+ if (((flags ^ desc->flags) & (BAF_OPTIONAL | BAF_TRANSITIVE)) &&
+ !(desc->flags & BAF_DECODE_FLAGS))
+ WITHDRAW("Malformed %s attribute - conflicting flags (%02x, expected %02x)", desc->name, flags, desc->flags);
- desc->decode(s, code, flags, data, len, to);
- }
- else /* Unknown attribute */
- {
- if (!(flags & BAF_OPTIONAL))
- WITHDRAW("Unknown attribute (code %u) - conflicting flags (%02x)", code, flags);
-
- bgp_decode_unknown(s, code, flags, data, len, to);
- }
+ desc->decode(s, code, flags, data, len, to);
}
/**
@@ -1359,7 +1386,8 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
{
struct bgp_proto *p = s->proto;
ea_list *attrs = NULL;
- uint code, flags, alen;
+ uint alen;
+ byte code, flags;
byte *pos = data;
/* Parse the attributes */
@@ -1704,7 +1732,7 @@ bgp_preexport(struct channel *c, rte *e)
/* Handle well-known communities, RFC 1997 */
struct eattr *com;
if (p->cf->interpret_communities &&
- (com = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY))))
+ (com = ea_find(e->attrs->eattrs, BGP_EA_ID(BA_COMMUNITY))))
{
const struct adata *d = com->u.ptr;
@@ -1881,7 +1909,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, c
static inline u32
bgp_get_neighbor(rte *r)
{
- eattr *e = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
+ eattr *e = ea_find(r->attrs->eattrs, BGP_EA_ID(BA_AS_PATH));
u32 as;
if (e && as_path_get_first_regular(e->u.ptr, &as))
@@ -1902,7 +1930,7 @@ rte_stale(rte *r)
return 0;
/* If staleness is unknown, compute and cache it */
- eattr *a = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY));
+ eattr *a = ea_find(r->attrs->eattrs, BGP_EA_ID(BA_COMMUNITY));
if (a && int_set_contains(a->u.ptr, BGP_COMM_LLGR_STALE))
{
r->pflags |= BGP_REF_STALE;
@@ -1948,8 +1976,8 @@ bgp_rte_better(rte *new, rte *old)
return 1;
/* Start with local preferences */
- x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
- y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
+ x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_LOCAL_PREF));
+ y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_LOCAL_PREF));
n = x ? x->u.data : new_bgp->cf->default_local_pref;
o = y ? y->u.data : old_bgp->cf->default_local_pref;
if (n > o)
@@ -1968,8 +1996,8 @@ bgp_rte_better(rte *new, rte *old)
/* RFC 4271 9.1.2.2. a) Use AS path lengths */
if (new_bgp->cf->compare_path_lengths || old_bgp->cf->compare_path_lengths)
{
- x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
- y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
+ x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_AS_PATH));
+ y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_AS_PATH));
n = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
o = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
if (n < o)
@@ -1979,8 +2007,8 @@ bgp_rte_better(rte *new, rte *old)
}
/* RFC 4271 9.1.2.2. b) Use origins */
- x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
- y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
+ x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_ORIGIN));
+ y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_ORIGIN));
n = x ? x->u.data : ORIGIN_INCOMPLETE;
o = y ? y->u.data : ORIGIN_INCOMPLETE;
if (n < o)
@@ -2002,8 +2030,8 @@ bgp_rte_better(rte *new, rte *old)
if (new_bgp->cf->med_metric || old_bgp->cf->med_metric ||
(bgp_get_neighbor(new) == bgp_get_neighbor(old)))
{
- x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC));
- y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC));
+ x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_MULTI_EXIT_DISC));
+ y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_MULTI_EXIT_DISC));
n = x ? x->u.data : new_bgp->cf->default_med;
o = y ? y->u.data : old_bgp->cf->default_med;
if (n < o)
@@ -2028,8 +2056,8 @@ bgp_rte_better(rte *new, rte *old)
/* RFC 4271 9.1.2.2. f) Compare BGP identifiers */
/* RFC 4456 9. a) Use ORIGINATOR_ID instead of local neighbor ID */
- x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID));
- y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID));
+ x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_ORIGINATOR_ID));
+ y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_ORIGINATOR_ID));
n = x ? x->u.data : new_bgp->remote_id;
o = y ? y->u.data : old_bgp->remote_id;
@@ -2046,8 +2074,8 @@ bgp_rte_better(rte *new, rte *old)
return 0;
/* RFC 4456 9. b) Compare cluster list lengths */
- x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_CLUSTER_LIST));
- y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_CLUSTER_LIST));
+ x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_CLUSTER_LIST));
+ y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_CLUSTER_LIST));
n = x ? int_set_get_size(x->u.ptr) : 0;
o = y ? int_set_get_size(y->u.ptr) : 0;
if (n < o)
@@ -2081,8 +2109,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
return 0;
/* Start with local preferences */
- x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
- y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
+ x = ea_find(pri->attrs->eattrs, BGP_EA_ID(BA_LOCAL_PREF));
+ y = ea_find(sec->attrs->eattrs, BGP_EA_ID(BA_LOCAL_PREF));
p = x ? x->u.data : pri_bgp->cf->default_local_pref;
s = y ? y->u.data : sec_bgp->cf->default_local_pref;
if (p != s)
@@ -2091,8 +2119,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
/* RFC 4271 9.1.2.2. a) Use AS path lengths */
if (pri_bgp->cf->compare_path_lengths || sec_bgp->cf->compare_path_lengths)
{
- x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
- y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
+ x = ea_find(pri->attrs->eattrs, BGP_EA_ID(BA_AS_PATH));
+ y = ea_find(sec->attrs->eattrs, BGP_EA_ID(BA_AS_PATH));
p = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
s = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
@@ -2104,8 +2132,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
}
/* RFC 4271 9.1.2.2. b) Use origins */
- x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
- y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
+ x = ea_find(pri->attrs->eattrs, BGP_EA_ID(BA_ORIGIN));
+ y = ea_find(sec->attrs->eattrs, BGP_EA_ID(BA_ORIGIN));
p = x ? x->u.data : ORIGIN_INCOMPLETE;
s = y ? y->u.data : ORIGIN_INCOMPLETE;
if (p != s)
@@ -2115,8 +2143,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
if (pri_bgp->cf->med_metric || sec_bgp->cf->med_metric ||
(bgp_get_neighbor(pri) == bgp_get_neighbor(sec)))
{
- x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC));
- y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC));
+ x = ea_find(pri->attrs->eattrs, BGP_EA_ID(BA_MULTI_EXIT_DISC));
+ y = ea_find(sec->attrs->eattrs, BGP_EA_ID(BA_MULTI_EXIT_DISC));
p = x ? x->u.data : pri_bgp->cf->default_med;
s = y ? y->u.data : sec_bgp->cf->default_med;
if (p != s)
@@ -2281,7 +2309,7 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
rte *
bgp_rte_modify_stale(struct rte *r, struct linpool *pool)
{
- eattr *ea = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY));
+ eattr *ea = ea_find(r->attrs->eattrs, BGP_EA_ID(BA_COMMUNITY));
const struct adata *ad = ea ? ea->u.ptr : NULL;
uint flags = ea ? ea->flags : BAF_PARTIAL;
@@ -2351,37 +2379,11 @@ bgp_process_as4_attrs(ea_list **attrs, struct linpool *pool)
}
}
-int
-bgp_get_attr(const eattr *a, byte *buf, int buflen)
-{
- uint i = EA_ID(a->id);
- const struct bgp_attr_desc *d;
- int len;
-
- if (bgp_attr_known(i))
- {
- d = &bgp_attr_table[i];
- len = bsprintf(buf, "%s", d->name);
- buf += len;
- if (d->format)
- {
- *buf++ = ':';
- *buf++ = ' ';
- d->format(a, buf, buflen - len - 2);
- return GA_FULL;
- }
- return GA_NAME;
- }
-
- bsprintf(buf, "%02x%s", i, (a->flags & BAF_TRANSITIVE) ? " [t]" : "");
- return GA_NAME;
-}
-
void
bgp_get_route_info(rte *e, byte *buf)
{
- eattr *p = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
- eattr *o = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
+ eattr *p = ea_find(e->attrs->eattrs, BGP_EA_ID(BA_AS_PATH));
+ eattr *o = ea_find(e->attrs->eattrs, BGP_EA_ID(BA_ORIGIN));
u32 origas;
buf += bsprintf(buf, " (%d", e->attrs->pref);
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 7c2ee642..84430287 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -2579,7 +2579,6 @@ struct channel_class channel_bgp = {
struct protocol proto_bgp = {
.name = "BGP",
.template = "bgp%d",
- .class = PROTOCOL_BGP,
.preference = DEF_PREF_BGP,
.channel_mask = NB_IP | NB_VPN | NB_FLOW,
.proto_size = sizeof(struct bgp_proto),
@@ -2591,7 +2590,6 @@ struct protocol proto_bgp = {
.reconfigure = bgp_reconfigure,
.copy_config = bgp_copy_config,
.get_status = bgp_get_status,
- .get_attr = bgp_get_attr,
.get_route_info = bgp_get_route_info,
.show_proto_info = bgp_show_proto_info
};
@@ -2599,4 +2597,5 @@ struct protocol proto_bgp = {
void bgp_build(void)
{
proto_build(&proto_bgp);
+ bgp_register_attrs();
}
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index cf6e2b6f..554681b4 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -538,17 +538,13 @@ rta_resolvable(rta *a)
/* attrs.c */
-static inline eattr *
-bgp_find_attr(ea_list *attrs, uint code)
-{
- return ea_find(attrs, EA_CODE(PROTOCOL_BGP, code));
-}
+eattr *
+bgp_find_attr(ea_list *attrs, uint code);
void bgp_set_attr_u32(ea_list **to, uint code, uint flags, u32 val);
void bgp_set_attr_ptr(ea_list **to, uint code, uint flags, const struct adata *ad);
void bgp_set_attr_data(ea_list **to, uint code, uint flags, void *data, uint len);
-
-#define bgp_unset_attr(to, code) ea_unset_attr(to, 0, code)
+void bgp_unset_attr(ea_list **to, uint code);
int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
@@ -573,7 +569,6 @@ struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool);
u32 bgp_rte_igp_metric(struct rte *);
void bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, const rte *old);
int bgp_preexport(struct channel *, struct rte *);
-int bgp_get_attr(const struct eattr *e, byte *buf, int buflen);
void bgp_get_route_info(struct rte *, byte *);
int bgp_total_aigp_metric_(rta *a, u64 *metric, const struct adata **ad);
@@ -590,6 +585,8 @@ bgp_total_aigp_metric(rta *a)
return metric;
}
+void bgp_register_attrs(void);
+
/* packets.c */
@@ -626,26 +623,31 @@ void bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to);
#define BAF_DECODE_FLAGS 0x0100 /* Private flag - attribute flags are handled by the decode hook */
-#define BA_ORIGIN 0x01 /* RFC 4271 */ /* WM */
-#define BA_AS_PATH 0x02 /* WM */
-#define BA_NEXT_HOP 0x03 /* WM */
-#define BA_MULTI_EXIT_DISC 0x04 /* ON */
-#define BA_LOCAL_PREF 0x05 /* WD */
-#define BA_ATOMIC_AGGR 0x06 /* WD */
-#define BA_AGGREGATOR 0x07 /* OT */
-#define BA_COMMUNITY 0x08 /* RFC 1997 */ /* OT */
-#define BA_ORIGINATOR_ID 0x09 /* RFC 4456 */ /* ON */
-#define BA_CLUSTER_LIST 0x0a /* RFC 4456 */ /* ON */
-#define BA_MP_REACH_NLRI 0x0e /* RFC 4760 */
-#define BA_MP_UNREACH_NLRI 0x0f /* RFC 4760 */
-#define BA_EXT_COMMUNITY 0x10 /* RFC 4360 */
-#define BA_AS4_PATH 0x11 /* RFC 6793 */
-#define BA_AS4_AGGREGATOR 0x12 /* RFC 6793 */
-#define BA_AIGP 0x1a /* RFC 7311 */
-#define BA_LARGE_COMMUNITY 0x20 /* RFC 8092 */
+enum bgp_attr_id {
+ BA_ORIGIN = 0x01, /* RFC 4271 */ /* WM */
+ BA_AS_PATH = 0x02, /* WM */
+ BA_NEXT_HOP = 0x03, /* WM */
+ BA_MULTI_EXIT_DISC = 0x04, /* ON */
+ BA_LOCAL_PREF = 0x05, /* WD */
+ BA_ATOMIC_AGGR = 0x06, /* WD */
+ BA_AGGREGATOR = 0x07, /* OT */
+ BA_COMMUNITY = 0x08, /* RFC 1997 */ /* OT */
+ BA_ORIGINATOR_ID = 0x09, /* RFC 4456 */ /* ON */
+ BA_CLUSTER_LIST = 0x0a, /* RFC 4456 */ /* ON */
+ BA_MP_REACH_NLRI = 0x0e, /* RFC 4760 */
+ BA_MP_UNREACH_NLRI = 0x0f, /* RFC 4760 */
+ BA_EXT_COMMUNITY = 0x10, /* RFC 4360 */
+ BA_AS4_PATH = 0x11, /* RFC 6793 */
+ BA_AS4_AGGREGATOR = 0x12, /* RFC 6793 */
+ BA_AIGP = 0x1a, /* RFC 7311 */
+ BA_LARGE_COMMUNITY = 0x20, /* RFC 8092 */
/* Bird's private internal BGP attributes */
-#define BA_MPLS_LABEL_STACK 0xfe /* MPLS label stack transfer attribute */
+ BA_MPLS_LABEL_STACK = 0x100, /* MPLS label stack transfer attribute */
+
+/* Maximum */
+ BGP_ATTR_MAX,
+};
/* BGP connection states */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 6a78f79b..db261bbb 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -316,36 +316,6 @@ bgp_channel_end:
bgp_proto_channel: bgp_channel_start bgp_channel_opt_list bgp_channel_end;
-
-dynamic_attr: BGP_ORIGIN
- { $$ = f_new_dynamic_attr(T_ENUM_BGP_ORIGIN, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); } ;
-dynamic_attr: BGP_PATH
- { $$ = f_new_dynamic_attr(T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); } ;
-dynamic_attr: BGP_NEXT_HOP
- { $$ = f_new_dynamic_attr(T_IP, EA_CODE(PROTOCOL_BGP, BA_NEXT_HOP)); } ;
-dynamic_attr: BGP_MED
- { $$ = f_new_dynamic_attr(T_INT, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); } ;
-dynamic_attr: BGP_LOCAL_PREF
- { $$ = f_new_dynamic_attr(T_INT, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); } ;
-dynamic_attr: BGP_ATOMIC_AGGR
- { $$ = f_new_dynamic_attr(T_OPAQUE, EA_CODE(PROTOCOL_BGP, BA_ATOMIC_AGGR)); } ;
-dynamic_attr: BGP_AGGREGATOR
- { $$ = f_new_dynamic_attr(T_OPAQUE, EA_CODE(PROTOCOL_BGP, BA_AGGREGATOR)); } ;
-dynamic_attr: BGP_COMMUNITY
- { $$ = f_new_dynamic_attr(T_CLIST, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY)); } ;
-dynamic_attr: BGP_ORIGINATOR_ID
- { $$ = f_new_dynamic_attr(T_QUAD, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID)); } ;
-dynamic_attr: BGP_CLUSTER_LIST
- { $$ = f_new_dynamic_attr(T_CLIST, EA_CODE(PROTOCOL_BGP, BA_CLUSTER_LIST)); } ;
-dynamic_attr: BGP_EXT_COMMUNITY
- { $$ = f_new_dynamic_attr(T_ECLIST, EA_CODE(PROTOCOL_BGP, BA_EXT_COMMUNITY)); } ;
-dynamic_attr: BGP_AIGP
- { $$ = f_new_dynamic_attr(T_OPAQUE, EA_CODE(PROTOCOL_BGP, BA_AIGP)); } ;
-dynamic_attr: BGP_LARGE_COMMUNITY
- { $$ = f_new_dynamic_attr(T_LCLIST, EA_CODE(PROTOCOL_BGP, BA_LARGE_COMMUNITY)); } ;
-
-
-
CF_ENUM(T_ENUM_BGP_ORIGIN, ORIGIN_, IGP, EGP, INCOMPLETE)
CF_CODE
diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c
index 6a186999..0f53dbe7 100644
--- a/proto/mrt/mrt.c
+++ b/proto/mrt/mrt.c
@@ -904,7 +904,6 @@ mrt_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUSE
struct protocol proto_mrt = {
.name = "MRT",
.template = "mrt%d",
- .class = PROTOCOL_MRT,
.proto_size = sizeof(struct mrt_proto),
.config_size = sizeof(struct mrt_config),
.init = mrt_init,
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index a8972d2c..136e1dcb 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -505,11 +505,6 @@ ospf_iface:
ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
;
-dynamic_attr: OSPF_METRIC1 { $$ = f_new_dynamic_attr(T_INT, EA_OSPF_METRIC1); } ;
-dynamic_attr: OSPF_METRIC2 { $$ = f_new_dynamic_attr(T_INT, EA_OSPF_METRIC2); } ;
-dynamic_attr: OSPF_TAG { $$ = f_new_dynamic_attr(T_INT, EA_OSPF_TAG); } ;
-dynamic_attr: OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(T_QUAD, EA_OSPF_ROUTER_ID); } ;
-
CF_CLI_HELP(SHOW OSPF, ..., [[Show information about OSPF protocol]]);
CF_CLI(SHOW OSPF, optproto, [<name>], [[Show information about OSPF protocol]])
{ PROTO_WALK_CMD($3, &proto_ospf, p) ospf_sh(p); };
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index ab77de02..e4522d41 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -106,6 +106,7 @@
#include <stdlib.h>
#include "ospf.h"
+#include "lib/macro.h"
static int ospf_preexport(struct channel *C, rte *new);
static void ospf_reload_routes(struct channel *C);
@@ -386,7 +387,7 @@ ospf_init(struct proto_config *CF)
static int
ospf_rte_better(struct rte *new, struct rte *old)
{
- u32 new_metric1 = ea_get_int(new->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
+ u32 new_metric1 = ea_get_int(new->attrs->eattrs, &ea_ospf_metric1, LSINFINITY);
if (new_metric1 == LSINFINITY)
return 0;
@@ -396,13 +397,13 @@ ospf_rte_better(struct rte *new, struct rte *old)
if(new->attrs->source == 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);
+ 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;
}
- u32 old_metric1 = ea_get_int(old->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
+ u32 old_metric1 = ea_get_int(old->attrs->eattrs, &ea_ospf_metric1, LSINFINITY);
if (new_metric1 < old_metric1)
return 1;
@@ -415,7 +416,7 @@ ospf_rte_igp_metric(struct rte *rt)
if (rt->attrs->source == RTS_OSPF_EXT2)
return IGP_METRIC_UNKNOWN;
- return ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
+ return ea_get_int(rt->attrs->eattrs, &ea_ospf_metric1, LSINFINITY);
}
void
@@ -587,42 +588,26 @@ ospf_get_route_info(rte * rte, byte * buf)
}
buf += bsprintf(buf, " %s", type);
- buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, ea_get_int(rte->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY));
+ buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, ea_get_int(rte->attrs->eattrs, &ea_ospf_metric1, LSINFINITY));
if (rte->attrs->source == RTS_OSPF_EXT2)
- buf += bsprintf(buf, "/%d", ea_get_int(rte->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY));
+ 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)
{
- eattr *ea = ea_find(rte->attrs->eattrs, EA_OSPF_TAG);
+ eattr *ea = ea_find(rte->attrs->eattrs, &ea_ospf_tag);
if (ea && (ea->u.data > 0))
buf += bsprintf(buf, " [%x]", ea->u.data);
}
- eattr *ea = ea_find(rte->attrs->eattrs, EA_OSPF_ROUTER_ID);
+ eattr *ea = ea_find(rte->attrs->eattrs, &ea_ospf_router_id);
if (ea)
buf += bsprintf(buf, " [%R]", ea->u.data);
}
-static int
-ospf_get_attr(const eattr * a, byte * buf, int buflen UNUSED)
+static void
+ospf_tag_format(const eattr * a, byte * buf, uint buflen)
{
- switch (a->id)
- {
- case EA_OSPF_METRIC1:
- bsprintf(buf, "metric1");
- return GA_NAME;
- case EA_OSPF_METRIC2:
- bsprintf(buf, "metric2");
- return GA_NAME;
- case EA_OSPF_TAG:
- bsprintf(buf, "tag: 0x%08x", a->u.data);
- return GA_FULL;
- case EA_OSPF_ROUTER_ID:
- bsprintf(buf, "router_id");
- return GA_NAME;
- default:
- return GA_UNKNOWN;
- }
+ bsnprintf(buf, buflen, "0x%08x", a->u.data);
}
static void
@@ -1520,7 +1505,6 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
struct protocol proto_ospf = {
.name = "OSPF",
.template = "ospf%d",
- .class = PROTOCOL_OSPF,
.preference = DEF_PREF_OSPF,
.channel_mask = NB_IP,
.proto_size = sizeof(struct ospf_proto),
@@ -1531,12 +1515,39 @@ struct protocol proto_ospf = {
.shutdown = ospf_shutdown,
.reconfigure = ospf_reconfigure,
.get_status = ospf_get_status,
- .get_attr = ospf_get_attr,
.get_route_info = ospf_get_route_info
};
+struct ea_class ea_ospf_metric1 = {
+ .name = "ospf_metric1",
+ .type = T_INT,
+};
+
+struct ea_class ea_ospf_metric2 = {
+ .name = "ospf_metric2",
+ .type = T_INT,
+};
+
+struct ea_class ea_ospf_tag = {
+ .name = "ospf_tag",
+ .type = T_INT,
+ .format = ospf_tag_format,
+};
+
+struct ea_class ea_ospf_router_id = {
+ .name = "ospf_router_id",
+ .type = T_QUAD,
+};
+
void
ospf_build(void)
{
proto_build(&proto_ospf);
+
+ EA_REGISTER_ALL(
+ &ea_ospf_metric1,
+ &ea_ospf_metric2,
+ &ea_ospf_tag,
+ &ea_ospf_router_id
+ );
}
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 3d0d57d9..7bed5c85 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -939,12 +939,7 @@ struct lsadb_show_data {
u32 router; /* Advertising router, 0 -> all */
};
-
-#define EA_OSPF_METRIC1 EA_CODE(PROTOCOL_OSPF, 0)
-#define EA_OSPF_METRIC2 EA_CODE(PROTOCOL_OSPF, 1)
-#define EA_OSPF_TAG EA_CODE(PROTOCOL_OSPF, 2)
-#define EA_OSPF_ROUTER_ID EA_CODE(PROTOCOL_OSPF, 3)
-
+extern struct ea_class ea_ospf_metric1, ea_ospf_metric2, ea_ospf_tag, ea_ospf_router_id;
/*
* For regular networks, neighbor address must match network prefix.
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 900fe82c..a6d39d7f 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -2075,18 +2075,18 @@ again1:
eattrs.l = (ea_list) {};
eattrs.a[eattrs.l.count++] =
- EA_LITERAL_EMBEDDED(EA_OSPF_METRIC1, T_INT, 0, nf->n.metric1);
+ EA_LITERAL_EMBEDDED(&ea_ospf_metric1, 0, nf->n.metric1);
if (nf->n.type == RTS_OSPF_EXT2)
eattrs.a[eattrs.l.count++] =
- EA_LITERAL_EMBEDDED(EA_OSPF_METRIC2, T_INT, 0, nf->n.metric2);
+ EA_LITERAL_EMBEDDED(&ea_ospf_metric2, 0, nf->n.metric2);
if ((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2))
eattrs.a[eattrs.l.count++] =
- EA_LITERAL_EMBEDDED(EA_OSPF_TAG, T_INT, 0, nf->n.tag);
+ EA_LITERAL_EMBEDDED(&ea_ospf_tag, 0, nf->n.tag);
eattrs.a[eattrs.l.count++] =
- EA_LITERAL_EMBEDDED(EA_OSPF_ROUTER_ID, T_QUAD, 0, nf->n.rid);
+ EA_LITERAL_EMBEDDED(&ea_ospf_router_id, 0, nf->n.rid);
a0.eattrs = &eattrs.l;
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 24fdcc54..81207e68 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -1338,8 +1338,8 @@ ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *n, rt
/* Get route attributes */
rta *a = new->attrs;
- eattr *m1a = ea_find(a->eattrs, EA_OSPF_METRIC1);
- eattr *m2a = ea_find(a->eattrs, EA_OSPF_METRIC2);
+ eattr *m1a = ea_find(a->eattrs, &ea_ospf_metric1);
+ eattr *m2a = ea_find(a->eattrs, &ea_ospf_metric2);
uint m1 = m1a ? m1a->u.data : 0;
uint m2 = m2a ? m2a->u.data : 10000;
@@ -1363,7 +1363,7 @@ ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *n, rt
uint ebit = m2a || !m1a;
uint metric = ebit ? m2 : m1;
- uint tag = ea_get_int(a->eattrs, EA_OSPF_TAG, 0);
+ uint tag = ea_get_int(a->eattrs, &ea_ospf_tag, 0);
ip_addr fwd = IPA_NONE;
if ((a->dest == RTD_UNICAST) && use_gw_for_fwaddr(p, a->nh.gw, a->nh.iface))
diff --git a/proto/perf/perf.c b/proto/perf/perf.c
index 6ebfe361..13ce656a 100644
--- a/proto/perf/perf.c
+++ b/proto/perf/perf.c
@@ -305,7 +305,6 @@ perf_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUS
struct protocol proto_perf = {
.name = "Perf",
.template = "perf%d",
- .class = PROTOCOL_PERF,
.channel_mask = NB_IP,
.proto_size = sizeof(struct perf_proto),
.config_size = sizeof(struct perf_config),
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index e8c69a0e..b99df434 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -299,7 +299,6 @@ pipe_update_debug(struct proto *P)
struct protocol proto_pipe = {
.name = "Pipe",
.template = "pipe%d",
- .class = PROTOCOL_PIPE,
.proto_size = sizeof(struct pipe_proto),
.config_size = sizeof(struct pipe_config),
.postconfig = pipe_postconfig,
diff --git a/proto/radv/config.Y b/proto/radv/config.Y
index 0a339cb4..f40fdcca 100644
--- a/proto/radv/config.Y
+++ b/proto/radv/config.Y
@@ -336,9 +336,6 @@ radv_sensitive:
| SENSITIVE bool { $$ = $2; }
;
-dynamic_attr: RA_PREFERENCE { $$ = f_new_dynamic_attr(T_ENUM_RA_PREFERENCE, EA_RA_PREFERENCE); } ;
-dynamic_attr: RA_LIFETIME { $$ = f_new_dynamic_attr(T_INT, EA_RA_LIFETIME); } ;
-
CF_CODE
CF_END
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index 24b1ce24..1f75b7c2 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -10,6 +10,7 @@
#include <stdlib.h>
#include "radv.h"
+#include "lib/macro.h"
/**
* DOC: Router Advertisements
@@ -42,6 +43,8 @@
* RFC 6106 - DNS extensions (RDDNS, DNSSL)
*/
+static struct ea_class ea_radv_preference, ea_radv_lifetime;
+
static void radv_prune_prefixes(struct radv_iface *ifa);
static void radv_prune_routes(struct radv_proto *p);
@@ -444,11 +447,11 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *n, rt
{
/* Update */
- ea = ea_find(new->attrs->eattrs, EA_RA_PREFERENCE);
+ ea = ea_find(new->attrs->eattrs, &ea_radv_preference);
uint preference = ea ? ea->u.data : RA_PREF_MEDIUM;
uint preference_set = !!ea;
- ea = ea_find(new->attrs->eattrs, EA_RA_LIFETIME);
+ ea = ea_find(new->attrs->eattrs, &ea_radv_lifetime);
uint lifetime = ea ? ea->u.data : 0;
uint lifetime_set = !!ea;
@@ -738,27 +741,26 @@ radv_pref_str(u32 pref)
}
}
-/* The buffer has some minimal size */
-static int
-radv_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
+static void
+radv_preference_format(const eattr *a, byte *buf, uint buflen)
{
- switch (a->id)
- {
- case EA_RA_PREFERENCE:
- bsprintf(buf, "preference: %s", radv_pref_str(a->u.data));
- return GA_FULL;
- case EA_RA_LIFETIME:
- bsprintf(buf, "lifetime");
- return GA_NAME;
- default:
- return GA_UNKNOWN;
- }
+ bsnprintf(buf, buflen, "%s", radv_pref_str(a->u.data));
}
+static struct ea_class ea_radv_preference = {
+ .name = "radv_preference",
+ .type = T_ENUM_RA_PREFERENCE,
+ .format = radv_preference_format,
+};
+
+static struct ea_class ea_radv_lifetime = {
+ .name = "radv_lifetime",
+ .type = T_INT,
+};
+
struct protocol proto_radv = {
.name = "RAdv",
.template = "radv%d",
- .class = PROTOCOL_RADV,
.channel_mask = NB_IP6,
.proto_size = sizeof(struct radv_proto),
.config_size = sizeof(struct radv_config),
@@ -769,11 +771,15 @@ struct protocol proto_radv = {
.reconfigure = radv_reconfigure,
.copy_config = radv_copy_config,
.get_status = radv_get_status,
- .get_attr = radv_get_attr
};
void
radv_build(void)
{
proto_build(&proto_radv);
+
+ EA_REGISTER_ALL(
+ &ea_radv_preference,
+ &ea_radv_lifetime
+ );
}
diff --git a/proto/radv/radv.h b/proto/radv/radv.h
index 5cca3aca..c9219bda 100644
--- a/proto/radv/radv.h
+++ b/proto/radv/radv.h
@@ -195,10 +195,6 @@ struct radv_iface
#define RA_PREF_HIGH 0x08
#define RA_PREF_MASK 0x18
-/* Attributes */
-#define EA_RA_PREFERENCE EA_CODE(PROTOCOL_RADV, 0)
-#define EA_RA_LIFETIME EA_CODE(PROTOCOL_RADV, 1)
-
#ifdef LOCAL_DEBUG
#define RADV_FORCE_DEBUG 1
#else
diff --git a/proto/rip/config.Y b/proto/rip/config.Y
index 3934d337..234e9029 100644
--- a/proto/rip/config.Y
+++ b/proto/rip/config.Y
@@ -190,9 +190,6 @@ rip_iface:
rip_iface_start iface_patt_list_nopx rip_iface_opt_list rip_iface_finish;
-dynamic_attr: RIP_METRIC { $$ = f_new_dynamic_attr(T_INT, EA_RIP_METRIC); } ;
-dynamic_attr: RIP_TAG { $$ = f_new_dynamic_attr(T_INT, EA_RIP_TAG); } ;
-
CF_CLI_HELP(SHOW RIP, ..., [[Show information about RIP protocol]]);
CF_CLI(SHOW RIP INTERFACES, optproto opttext, [<name>] [\"<interface>\"], [[Show information about RIP interfaces]])
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index b21a416b..03e0f4fb 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -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) },
@@ -325,9 +327,9 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *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)
@@ -1094,8 +1096,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;
}
@@ -1103,7 +1105,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
@@ -1204,8 +1206,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);
@@ -1213,23 +1215,28 @@ 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;
+ bsnprintf(buf, buflen, "tag: %04x", a->u.data);
+}
- case EA_RIP_TAG:
- bsprintf(buf, "tag: %04x", a->u.data);
- return GA_FULL;
+static struct ea_class ea_rip_metric = {
+ .name = "rip_metric",
+ .type = T_INT,
+};
- default:
- return GA_UNKNOWN;
- }
-}
+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)
@@ -1333,7 +1340,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),
@@ -1345,11 +1351,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
+ );
}
diff --git a/proto/rip/rip.h b/proto/rip/rip.h
index a6fa3326..a01f8d3b 100644
--- a/proto/rip/rip.h
+++ b/proto/rip/rip.h
@@ -195,10 +195,6 @@ struct rip_rte
#define RIP_ENTRY_VALID 1 /* Valid outgoing route */
#define RIP_ENTRY_STALE 2 /* Stale outgoing route, waiting for GC */
-#define EA_RIP_METRIC EA_CODE(PROTOCOL_RIP, 0)
-#define EA_RIP_TAG EA_CODE(PROTOCOL_RIP, 1)
-#define EA_RIP_FROM EA_CODE(PROTOCOL_RIP, 2)
-
static inline int rip_is_v2(struct rip_proto *p)
{ return p->rip2; }
diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c
index f1d32628..153e5293 100644
--- a/proto/rpki/rpki.c
+++ b/proto/rpki/rpki.c
@@ -952,7 +952,6 @@ rpki_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUS
struct protocol proto_rpki = {
.name = "RPKI",
.template = "rpki%d",
- .class = PROTOCOL_RPKI,
.preference = DEF_PREF_RPKI,
.proto_size = sizeof(struct rpki_proto),
.config_size = sizeof(struct rpki_config),
diff --git a/proto/static/static.c b/proto/static/static.c
index 87d795ee..2fc8e788 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -397,16 +397,16 @@ static_reload_routes(struct channel *C)
static int
static_rte_better(rte *new, rte *old)
{
- u32 n = ea_get_int(new->attrs->eattrs, EA_GEN_IGP_METRIC, IGP_METRIC_UNKNOWN);
- u32 o = ea_get_int(old->attrs->eattrs, EA_GEN_IGP_METRIC, IGP_METRIC_UNKNOWN);
+ u32 n = ea_get_int(new->attrs->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN);
+ u32 o = ea_get_int(old->attrs->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN);
return n < o;
}
static int
static_rte_mergable(rte *pri, rte *sec)
{
- u32 a = ea_get_int(pri->attrs->eattrs, EA_GEN_IGP_METRIC, IGP_METRIC_UNKNOWN);
- u32 b = ea_get_int(sec->attrs->eattrs, EA_GEN_IGP_METRIC, IGP_METRIC_UNKNOWN);
+ u32 a = ea_get_int(pri->attrs->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN);
+ u32 b = ea_get_int(sec->attrs->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN);
return a == b;
}
@@ -694,7 +694,7 @@ static_copy_config(struct proto_config *dest, struct proto_config *src)
static void
static_get_route_info(rte *rte, byte *buf)
{
- eattr *a = ea_find(rte->attrs->eattrs, EA_GEN_IGP_METRIC);
+ eattr *a = ea_find(rte->attrs->eattrs, &ea_gen_igp_metric);
if (a)
buf += bsprintf(buf, " (%d/%u)", rte->attrs->pref, a->u.data);
else
@@ -752,7 +752,6 @@ static_show(struct proto *P)
struct protocol proto_static = {
.name = "Static",
.template = "static%d",
- .class = PROTOCOL_STATIC,
.preference = DEF_PREF_STATIC,
.channel_mask = NB_ANY,
.proto_size = sizeof(struct static_proto),