summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in11
-rw-r--r--filter/config.Y6
-rw-r--r--filter/f-util.c16
-rw-r--r--filter/filter.c311
-rw-r--r--filter/filter.h23
-rw-r--r--lib/macro.h98
-rw-r--r--nest/proto.c9
-rw-r--r--nest/protocol.h45
-rw-r--r--nest/route.h29
-rw-r--r--nest/rt-attr.c65
-rw-r--r--nest/rt-dev.c1
-rw-r--r--nest/rt-show.c34
-rw-r--r--nest/rt-table.c97
-rw-r--r--proto/babel/babel.c19
-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.c64
-rw-r--r--proto/bgp/bgp.c2
-rw-r--r--proto/bgp/bgp.h8
-rw-r--r--proto/bgp/config.Y24
-rw-r--r--proto/ospf/config.Y8
-rw-r--r--proto/ospf/ospf.c20
-rw-r--r--proto/ospf/ospf.h8
-rw-r--r--proto/ospf/topology.c3
-rw-r--r--proto/ospf/topology.h2
-rw-r--r--proto/pipe/pipe.c6
-rw-r--r--proto/radv/radv.c10
-rw-r--r--proto/radv/radv.h4
-rw-r--r--proto/rip/config.Y4
-rw-r--r--proto/rip/rip.c17
-rw-r--r--proto/rip/rip.h4
-rw-r--r--proto/rpki/rpki.c1
-rw-r--r--proto/static/static.c1
-rw-r--r--sysdep/bsd/krt-sock.c3
-rw-r--r--sysdep/linux/krt-sys.h38
-rw-r--r--sysdep/linux/netlink.c23
-rw-r--r--sysdep/unix/krt.Y4
-rw-r--r--sysdep/unix/krt.c40
-rw-r--r--sysdep/unix/krt.h6
-rw-r--r--test/bt-utils.c4
41 files changed, 567 insertions, 508 deletions
diff --git a/Makefile.in b/Makefile.in
index eb6cc5c9..8f6c0c8b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -95,7 +95,7 @@ clean = $(eval $(call clean_in,$(1)))
include $(addsuffix /Makefile,$(addprefix $(srcdir)/,$(dirs)))
# Generic rules
-
+# Object file rules
$(objdir)/%.o: $(srcdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h
$(E)echo CC -o $@ -c $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -c $<
@@ -104,7 +104,16 @@ $(objdir)/%.o: $(objdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h
$(E)echo CC -o $@ -c $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -c $<
+# Debug: Preprocessed source rules
+$(objdir)/%.E: $(srcdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h
+ $(E)echo CC -o $@ -E $<
+ $(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -E $<
+
+$(objdir)/%.E: $(objdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h
+ $(E)echo CC -o $@ -E $<
+ $(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -E $<
+# Debug: Assembler object rules
$(objdir)/%.S: $(srcdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h
$(E)echo CC -o $@ -S $<
$(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -S $<
diff --git a/filter/config.Y b/filter/config.Y
index e01e02ef..cf499b66 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -304,12 +304,10 @@ f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3)
}
else
{
- rv = cfg_allocz(sizeof(struct f_inst3));
- rv->lineno = ifs->lino;
- rv->fi_code = FI_LC_CONSTRUCT;
+ rv = f_new_inst(FI_LC_CONSTRUCT);
rv->a1.p = t1;
rv->a2.p = t2;
- INST3(rv).p = t3;
+ rv->a3.p = t3;
}
return rv;
diff --git a/filter/f-util.c b/filter/f-util.c
index 68aecd73..6170760b 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -77,6 +77,22 @@ f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct
return &ret->i;
}
+static const char * const f_instruction_name_str[] = {
+#define F(c,a,b) \
+ [c] = #c,
+FI__LIST
+#undef F
+};
+
+const char *
+f_instruction_name(enum f_instruction_code fi)
+{
+ if (fi < FI__MAX)
+ return f_instruction_name_str[fi];
+ else
+ bug("Got unknown instruction code: %d", fi);
+}
+
char *
filter_name(struct filter *filter)
{
diff --git a/filter/filter.c b/filter/filter.c
index 3d7b5c9f..6290e74a 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -538,14 +538,23 @@ val_format(struct f_val v, buffer *buf)
static struct rte **f_rte;
static struct rta *f_old_rta;
-static struct ea_list **f_tmp_attrs;
+static struct ea_list **f_eattrs;
static struct linpool *f_pool;
static struct buffer f_buf;
static int f_flags;
+static inline void f_cache_eattrs(void)
+{
+ f_eattrs = &((*f_rte)->attrs->eattrs);
+}
+
static inline void f_rte_cow(void)
{
- *f_rte = rte_cow(*f_rte);
+ if (!((*f_rte)->flags & REF_COW))
+ return;
+
+ *f_rte = rte_do_cow(*f_rte);
+ f_eattrs = NULL;
}
/*
@@ -570,6 +579,9 @@ f_rta_cow(void)
* suppose hostentry is not changed by filters).
*/
(*f_rte)->attrs = rta_do_cow((*f_rte)->attrs, f_pool);
+
+ /* Re-cache the ea_list */
+ f_cache_eattrs();
}
static char *
@@ -590,19 +602,23 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
return res; \
} while(0)
-#define ARG(x,y) \
- x = interpret(what->y); \
- if (x.type & T_RETURN) \
- return x;
-
-#define ONEARG ARG(v1, a1.p)
-#define TWOARGS ARG(v1, a1.p) \
- ARG(v2, a2.p)
-#define TWOARGS_C TWOARGS \
- if (v1.type != v2.type) \
- runtime( "Can't operate with values of incompatible types" );
+#define ARG_ANY(n) INTERPRET(v##n, what->a##n.p)
+
+#define ARG(n,t) ARG_ANY(n) \
+ if (v##n.type != t) \
+ runtime("Argument %d of instruction %s must be of type %02x, got %02x", \
+ n, f_instruction_name(what->fi_code), t, v##n.type);
+
+#define INTERPRET(val, what_) \
+ val = interpret(what_); \
+ if (val.type & T_RETURN) \
+ return val;
+
#define ACCESS_RTE \
- do { if (!f_rte) runtime("No route to access"); } while (0)
+ do { if (!f_rte) runtime("No route to access"); else f_cache_eattrs(); } while (0)
+
+#define ACCESS_EATTRS \
+ do { if (!f_eattrs) f_cache_eattrs(); } while (0)
#define BITFIELD_MASK(what) \
(1u << (what->a2.i >> 24))
@@ -628,7 +644,7 @@ static struct f_val
interpret(struct f_inst *what)
{
struct symbol *sym;
- struct f_val v1, v2, res = { .type = T_VOID }, *vp;
+ struct f_val v1, v2, v3, res = { .type = T_VOID }, *vp;
unsigned u1, u2;
int i;
u32 as;
@@ -638,61 +654,44 @@ interpret(struct f_inst *what)
switch(what->fi_code) {
/* Binary operators */
case FI_ADD:
- TWOARGS_C;
- switch (res.type = v1.type) {
- case T_VOID: runtime( "Can't operate with values of type void" );
- case T_INT: res.val.i = v1.val.i + v2.val.i; break;
- default: runtime( "Usage of unknown type" );
- }
+ ARG(1,T_INT);
+ ARG(2,T_INT);
+ res.type = T_INT;
+ res.val.i = v1.val.i + v2.val.i;
break;
case FI_SUBTRACT:
- TWOARGS_C;
- switch (res.type = v1.type) {
- case T_VOID: runtime( "Can't operate with values of type void" );
- case T_INT: res.val.i = v1.val.i - v2.val.i; break;
- default: runtime( "Usage of unknown type" );
- }
+ ARG(1,T_INT);
+ ARG(2,T_INT);
+ res.type = T_INT;
+ res.val.i = v1.val.i - v2.val.i;
break;
case FI_MULTIPLY:
- TWOARGS_C;
- switch (res.type = v1.type) {
- case T_VOID: runtime( "Can't operate with values of type void" );
- case T_INT: res.val.i = v1.val.i * v2.val.i; break;
- default: runtime( "Usage of unknown type" );
- }
+ ARG(1,T_INT);
+ ARG(2,T_INT);
+ res.type = T_INT;
+ res.val.i = v1.val.i * v2.val.i;
break;
case FI_DIVIDE:
- TWOARGS_C;
- switch (res.type = v1.type) {
- case T_VOID: runtime( "Can't operate with values of type void" );
- case T_INT: if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" );
- res.val.i = v1.val.i / v2.val.i; break;
- default: runtime( "Usage of unknown type" );
- }
+ ARG(1,T_INT);
+ ARG(2,T_INT);
+ res.type = T_INT;
+ if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" );
+ res.val.i = v1.val.i / v2.val.i;
break;
-
case FI_AND:
case FI_OR:
- ARG(v1, a1.p);
- if (v1.type != T_BOOL)
- runtime( "Can't do boolean operation on non-booleans" );
+ ARG(1,T_BOOL);
if (v1.val.i == (what->fi_code == FI_OR)) {
res.type = T_BOOL;
res.val.i = v1.val.i;
- break;
+ } else {
+ ARG(2,T_BOOL);
+ res = v2;
}
-
- ARG(v2, a2.p);
- if (v2.type != T_BOOL)
- runtime( "Can't do boolean operation on non-booleans" );
- res.type = T_BOOL;
- res.val.i = v2.val.i;
break;
-
case FI_PAIR_CONSTRUCT:
- TWOARGS;
- if ((v1.type != T_INT) || (v2.type != T_INT))
- runtime( "Can't operate with value of non-integer type in pair constructor" );
+ ARG(1,T_INT);
+ ARG(2,T_INT);
u1 = v1.val.i;
u2 = v2.val.i;
if ((u1 > 0xFFFF) || (u2 > 0xFFFF))
@@ -703,7 +702,8 @@ interpret(struct f_inst *what)
case FI_EC_CONSTRUCT:
{
- TWOARGS;
+ ARG_ANY(1);
+ ARG(2, T_INT);
int check, ipv4_used;
u32 key, val;
@@ -721,8 +721,6 @@ interpret(struct f_inst *what)
else
runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
- if (v2.type != T_INT)
- runtime("Can't operate with value of non-integer type in EC constructor");
val = v2.val.i;
/* XXXX */
@@ -749,15 +747,9 @@ interpret(struct f_inst *what)
case FI_LC_CONSTRUCT:
{
- TWOARGS;
-
- /* Third argument hack */
- struct f_val v3 = interpret(INST3(what).p);
- if (v3.type & T_RETURN)
- return v3;
-
- if ((v1.type != T_INT) || (v2.type != T_INT) || (v3.type != T_INT))
- runtime( "Can't operate with value of non-integer type in LC constructor" );
+ ARG(1, T_INT);
+ ARG(2, T_INT);
+ ARG(3, T_INT);
res.type = T_LC;
res.val.lc = (lcomm) { v1.val.i, v2.val.i, v3.val.i };
@@ -772,7 +764,8 @@ interpret(struct f_inst *what)
while (tt) {
*vv = lp_alloc(f_pool, sizeof(struct f_path_mask));
if (tt->kind == PM_ASN_EXPR) {
- struct f_val res = interpret((struct f_inst *) tt->val);
+ struct f_val res;
+ INTERPRET(res, (struct f_inst *) tt->val);
(*vv)->kind = PM_ASN;
if (res.type != T_INT) {
runtime( "Error resolving path mask template: value not an integer" );
@@ -794,7 +787,8 @@ interpret(struct f_inst *what)
/* Relational operators */
#define COMPARE(x) \
- TWOARGS; \
+ ARG_ANY(1); \
+ ARG_ANY(2); \
i = val_compare(v1, v2); \
if (i==CMP_ERROR) \
runtime( "Can't compare values of incompatible types" ); \
@@ -803,7 +797,8 @@ interpret(struct f_inst *what)
break;
#define SAME(x) \
- TWOARGS; \
+ ARG_ANY(1); \
+ ARG_ANY(2); \
i = val_same(v1, v2); \
res.type = T_BOOL; \
res.val.i = (x); \
@@ -815,15 +810,14 @@ interpret(struct f_inst *what)
case FI_LTE: COMPARE(i!=1);
case FI_NOT:
- ONEARG;
- if (v1.type != T_BOOL)
- runtime( "Not applied to non-boolean" );
+ ARG(1,T_BOOL);
res = v1;
res.val.i = !res.val.i;
break;
case FI_MATCH:
- TWOARGS;
+ ARG_ANY(1);
+ ARG_ANY(2);
res.type = T_BOOL;
res.val.i = val_in_range(v1, v2);
if (res.val.i == CMP_ERROR)
@@ -832,7 +826,8 @@ interpret(struct f_inst *what)
break;
case FI_NOT_MATCH:
- TWOARGS;
+ ARG_ANY(1);
+ ARG_ANY(2);
res.type = T_BOOL;
res.val.i = val_in_range(v1, v2);
if (res.val.i == CMP_ERROR)
@@ -841,12 +836,12 @@ interpret(struct f_inst *what)
break;
case FI_DEFINED:
- ONEARG;
+ ARG_ANY(1);
res.type = T_BOOL;
res.val.i = (v1.type != T_VOID) && !undef_value(v1);
break;
case FI_TYPE:
- ONEARG;
+ ARG_ANY(1); /* There may be more types supporting this operation */
switch (v1.type)
{
case T_NET:
@@ -858,16 +853,14 @@ interpret(struct f_inst *what)
}
break;
case FI_IS_V4:
- ONEARG;
- if (v1.type != T_IP)
- runtime( "IP version check needs an IP address" );
+ ARG(1, T_IP);
res.type = T_BOOL;
res.val.i = ipa_is_ip4(v1.val.ip);
break;
/* Set to indirect value, a1 = variable, a2 = value */
case FI_SET:
- ARG(v2, a2.p);
+ ARG_ANY(2);
sym = what->a1.p;
vp = sym->def;
if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID))
@@ -902,24 +895,23 @@ interpret(struct f_inst *what)
res = * ((struct f_val *) what->a1.p);
break;
case FI_PRINT:
- ONEARG;
+ ARG_ANY(1);
val_format(v1, &f_buf);
break;
case FI_CONDITION: /* ? has really strange error value, so we can implement if ... else nicely :-) */
- ONEARG;
- if (v1.type != T_BOOL)
- runtime( "If requires boolean expression" );
+ ARG(1, T_BOOL);
if (v1.val.i) {
- ARG(res,a2.p);
+ ARG_ANY(2);
res.val.i = 0;
- } else res.val.i = 1;
+ } else
+ res.val.i = 1;
res.type = T_BOOL;
break;
case FI_NOP:
debug( "No operation\n" );
break;
case FI_PRINT_AND_DIE:
- ONEARG;
+ ARG_ANY(1);
if ((what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p)) &&
!(f_flags & FF_SILENT))
log_commit(*L_INFO, &f_buf);
@@ -966,7 +958,7 @@ interpret(struct f_inst *what)
break;
case FI_RTA_SET:
ACCESS_RTE;
- ONEARG;
+ ARG_ANY(1);
if (what->aux != v1.type)
runtime( "Attempt to set static attribute to incompatible type" );
@@ -1018,17 +1010,11 @@ interpret(struct f_inst *what)
break;
case FI_EA_GET: /* Access to extended attributes */
ACCESS_RTE;
+ ACCESS_EATTRS;
{
- eattr *e = NULL;
u16 code = what->a2.i;
int f_type = what->aux >> 8;
-
- if (!(f_flags & FF_FORCE_TMPATTR))
- e = ea_find((*f_rte)->attrs->eattrs, code);
- if (!e)
- e = ea_find((*f_tmp_attrs), code);
- if ((!e) && (f_flags & FF_FORCE_TMPATTR))
- e = ea_find((*f_rte)->attrs->eattrs, code);
+ eattr *e = ea_find(*f_eattrs, code);
if (!e) {
/* A special case: undefined as_path looks like empty as_path */
@@ -1112,7 +1098,8 @@ interpret(struct f_inst *what)
break;
case FI_EA_SET:
ACCESS_RTE;
- ONEARG;
+ ACCESS_EATTRS;
+ ARG_ANY(1);
{
struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
u16 code = what->a2.i;
@@ -1166,13 +1153,7 @@ interpret(struct f_inst *what)
runtime( "Setting bit in bitfield attribute to non-bool value" );
{
/* First, we have to find the old value */
- eattr *e = NULL;
- if (!(f_flags & FF_FORCE_TMPATTR))
- e = ea_find((*f_rte)->attrs->eattrs, code);
- if (!e)
- e = ea_find((*f_tmp_attrs), code);
- if ((!e) && (f_flags & FF_FORCE_TMPATTR))
- e = ea_find((*f_rte)->attrs->eattrs, code);
+ eattr *e = ea_find(*f_eattrs, code);
u32 data = e ? e->u.data : 0;
if (v1.val.i)
@@ -1204,14 +1185,9 @@ interpret(struct f_inst *what)
default: bug("Unknown type in e,S");
}
- if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
- f_rta_cow();
- l->next = (*f_rte)->attrs->eattrs;
- (*f_rte)->attrs->eattrs = l;
- } else {
- l->next = (*f_tmp_attrs);
- (*f_tmp_attrs) = l;
- }
+ f_rta_cow();
+ l->next = *f_eattrs;
+ *f_eattrs = l;
}
break;
case FI_PREF_GET:
@@ -1221,16 +1197,14 @@ interpret(struct f_inst *what)
break;
case FI_PREF_SET:
ACCESS_RTE;
- ONEARG;
- if (v1.type != T_INT)
- runtime( "Can't set preference to non-integer" );
+ ARG(1,T_INT);
if (v1.val.i > 0xFFFF)
runtime( "Setting preference value out of bounds" );
f_rte_cow();
(*f_rte)->pref = v1.val.i;
break;
case FI_LENGTH: /* Get length of */
- ONEARG;
+ ARG_ANY(1);
res.type = T_INT;
switch(v1.type) {
case T_NET: res.val.i = net_pxlen(v1.val.net); break;
@@ -1242,8 +1216,8 @@ interpret(struct f_inst *what)
}
break;
case FI_SADR_SRC: /* Get SADR src prefix */
- ONEARG;
- if (v1.type != T_NET || !net_is_sadr(v1.val.net))
+ ARG(1, T_NET);
+ if (!net_is_sadr(v1.val.net))
runtime( "SADR expected" );
{
@@ -1256,8 +1230,8 @@ interpret(struct f_inst *what)
}
break;
case FI_ROA_MAXLEN: /* Get ROA max prefix length */
- ONEARG;
- if (v1.type != T_NET || !net_is_roa(v1.val.net))
+ ARG(1, T_NET);
+ if (!net_is_roa(v1.val.net))
runtime( "ROA expected" );
res.type = T_INT;
@@ -1266,8 +1240,8 @@ interpret(struct f_inst *what)
((net_addr_roa6 *) v1.val.net)->max_pxlen;
break;
case FI_ROA_ASN: /* Get ROA ASN */
- ONEARG;
- if (v1.type != T_NET || !net_is_roa(v1.val.net))
+ ARG(1, T_NET);
+ if (!net_is_roa(v1.val.net))
runtime( "ROA expected" );
res.type = T_INT;
@@ -1276,25 +1250,20 @@ interpret(struct f_inst *what)
((net_addr_roa6 *) v1.val.net)->asn;
break;
case FI_IP: /* Convert prefix to ... */
- ONEARG;
- if (v1.type != T_NET)
- runtime( "Prefix expected" );
+ ARG(1, T_NET);
res.type = T_IP;
res.val.ip = net_prefix(v1.val.net);
break;
case FI_ROUTE_DISTINGUISHER:
- ONEARG;
- if (v1.type != T_NET)
- runtime( "Prefix expected" );
+ ARG(1, T_NET);
+ res.type = T_IP;
if (!net_is_vpn(v1.val.net))
runtime( "VPN address expected" );
res.type = T_RD;
res.val.ec = net_rd(v1.val.net);
break;
case FI_AS_PATH_FIRST: /* Get first ASN from AS PATH */
- ONEARG;
- if (v1.type != T_PATH)
- runtime( "AS path expected" );
+ ARG(1, T_PATH);
as = 0;
as_path_get_first(v1.val.ad, &as);
@@ -1302,9 +1271,7 @@ interpret(struct f_inst *what)
res.val.i = as;
break;
case FI_AS_PATH_LAST: /* Get last ASN from AS PATH */
- ONEARG;
- if (v1.type != T_PATH)
- runtime( "AS path expected" );
+ ARG(1, T_PATH);
as = 0;
as_path_get_last(v1.val.ad, &as);
@@ -1312,20 +1279,18 @@ interpret(struct f_inst *what)
res.val.i = as;
break;
case FI_AS_PATH_LAST_NAG: /* Get last ASN from non-aggregated part of AS PATH */
- ONEARG;
- if (v1.type != T_PATH)
- runtime( "AS path expected" );
+ ARG(1, T_PATH);
res.type = T_INT;
res.val.i = as_path_get_last_nonaggregated(v1.val.ad);
break;
case FI_RETURN:
- ONEARG;
+ ARG_ANY(1);
res = v1;
res.type |= T_RETURN;
return res;
case FI_CALL: /* CALL: this is special: if T_RETURN and returning some value, mask it out */
- ONEARG;
+ ARG_ANY(1);
res = interpret(what->a2.p);
if (res.type == T_RETURN)
return res;
@@ -1336,7 +1301,7 @@ interpret(struct f_inst *what)
((struct f_val *) sym->def)->type = T_VOID;
break;
case FI_SWITCH:
- ONEARG;
+ ARG_ANY(1);
{
struct f_tree *t = find_tree(what->a2.p, v1);
if (!t) {
@@ -1349,17 +1314,12 @@ interpret(struct f_inst *what)
}
/* It is actually possible to have t->data NULL */
- res = interpret(t->data);
- if (res.type & T_RETURN)
- return res;
+ INTERPRET(res, t->data);
}
break;
case FI_IP_MASK: /* IP.MASK(val) */
- TWOARGS;
- if (v2.type != T_INT)
- runtime( "Integer expected");
- if (v1.type != T_IP)
- runtime( "You can mask only IP addresses" );
+ ARG(1, T_IP);
+ ARG(2, T_INT);
res.type = T_IP;
res.val.ip = ipa_is_ip4(v1.val.ip) ?
@@ -1372,18 +1332,16 @@ interpret(struct f_inst *what)
res.val.ad = adata_empty(f_pool, 0);
break;
case FI_PATH_PREPEND: /* Path prepend */
- TWOARGS;
- if (v1.type != T_PATH)
- runtime("Can't prepend to non-path");
- if (v2.type != T_INT)
- runtime("Can't prepend non-integer");
+ ARG(1, T_PATH);
+ ARG(2, T_INT);
res.type = T_PATH;
res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
break;
case FI_CLIST_ADD_DEL: /* (Extended) Community list add or delete */
- TWOARGS;
+ ARG_ANY(1);
+ ARG_ANY(2);
if (v1.type == T_PATH)
{
struct f_tree *set = NULL;
@@ -1551,20 +1509,20 @@ interpret(struct f_inst *what)
case FI_ROA_CHECK: /* ROA Check */
if (what->arg1)
{
- TWOARGS;
- if ((v1.type != T_NET) || (v2.type != T_INT))
- runtime("Invalid argument to roa_check()");
+ ARG(1, T_NET);
+ ARG(2, T_INT);
as = v2.val.i;
}
else
{
ACCESS_RTE;
+ ACCESS_EATTRS;
v1.val.net = (*f_rte)->net->n.addr;
/* We ignore temporary attributes, probably not a problem here */
/* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
- eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(EAP_BGP, 0x02));
+ eattr *e = ea_find(*f_eattrs, EA_CODE(PROTOCOL_BGP, 0x02));
if (!e || e->type != EAF_TYPE_AS_PATH)
runtime("Missing AS_PATH attribute");
@@ -1589,17 +1547,14 @@ interpret(struct f_inst *what)
break;
case FI_FORMAT: /* Format */
- ONEARG;
+ ARG_ANY(1);
res.type = T_STRING;
res.val.s = val_format_str(v1);
break;
case FI_ASSERT: /* Birdtest Assert */
- ONEARG;
-
- if (v1.type != T_BOOL)
- runtime("Should be boolean value");
+ ARG(1, T_BOOL);
res.type = v1.type;
res.val = v1.val;
@@ -1614,13 +1569,15 @@ interpret(struct f_inst *what)
}
#undef ARG
-#define ARG(x,y) \
- if (!i_same(f1->y, f2->y)) \
+#undef ARG_ANY
+
+#define ARG(n) \
+ if (!i_same(f1->a##n.p, f2->a##n.p)) \
return 0;
-#define ONEARG ARG(v1, a1.p)
-#define TWOARGS ARG(v1, a1.p) \
- ARG(v2, a2.p)
+#define ONEARG ARG(1);
+#define TWOARGS ONEARG; ARG(2);
+#define THREEARGS TWOARGS; ARG(3);
#define A2_SAME if (f1->a2.i != f2->a2.i) return 0;
@@ -1664,13 +1621,11 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case FI_TYPE: ONEARG; break;
case FI_LC_CONSTRUCT:
- TWOARGS;
- if (!i_same(INST3(f1).p, INST3(f2).p))
- return 0;
+ THREEARGS;
break;
case FI_SET:
- ARG(v2, a2.p);
+ ARG(2);
{
struct symbol *s1, *s2;
s1 = f1->a1.p;
@@ -1765,7 +1720,6 @@ i_same(struct f_inst *f1, struct f_inst *f2)
* f_run - run a filter for a route
* @filter: filter to run
* @rte: route being filtered, may be modified
- * @tmp_attrs: temporary attributes, prepared by caller or generated by f_run()
* @tmp_pool: all filter allocations go from this pool
* @flags: flags
*
@@ -1787,7 +1741,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
* modified in place, old cached rta is possibly freed.
*/
int
-f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
+f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags)
{
if (filter == FILTER_ACCEPT)
return F_ACCEPT;
@@ -1800,7 +1754,6 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
f_rte = rte;
f_old_rta = NULL;
- f_tmp_attrs = tmp_attrs;
f_pool = tmp_pool;
f_flags = flags;
@@ -1842,11 +1795,9 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
struct f_val
f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
{
- struct ea_list *tmp_attrs = NULL;
f_rte = rte;
f_old_rta = NULL;
- f_tmp_attrs = &tmp_attrs;
f_pool = tmp_pool;
f_flags = 0;
@@ -1855,9 +1806,6 @@ f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
/* Note that in this function we assume that rte->attrs is private / uncached */
struct f_val res = interpret(expr);
- /* Hack to include EAF_TEMP attributes to the main list */
- (*rte)->attrs->eattrs = ea_append(tmp_attrs, (*rte)->attrs->eattrs);
-
return res;
}
@@ -1865,7 +1813,6 @@ struct f_val
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
{
f_flags = 0;
- f_tmp_attrs = NULL;
f_rte = NULL;
f_pool = tmp_pool;
diff --git a/filter/filter.h b/filter/filter.h
index 982276f0..febfdc65 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -75,11 +75,14 @@
enum f_instruction_code {
#define F(c,a,b) \
- c = FI__TWOCHAR(a,b),
+ c,
FI__LIST
#undef F
+ FI__MAX,
} PACKED;
+const char *f_instruction_name(enum f_instruction_code fi);
+
struct f_inst { /* Instruction */
struct f_inst *next; /* Structure is 16 bytes, anyway */
enum f_instruction_code fi_code;
@@ -92,6 +95,10 @@ struct f_inst { /* Instruction */
uint i;
void *p;
} a2; /* The second argument */
+ union {
+ int i;
+ void *p;
+ } a3; /* The third argument */
int lineno;
};
@@ -104,17 +111,6 @@ struct f_inst_roa_check {
struct rtable_config *rtc;
};
-struct f_inst3 {
- struct f_inst i;
- union {
- int i;
- void *p;
- } a3;
-};
-
-#define INST3(x) (((struct f_inst3 *) x)->a3)
-
-
struct f_prefix {
net_addr net;
u8 lo, hi;
@@ -179,7 +175,7 @@ void trie_format(struct f_trie *t, buffer *buf);
struct ea_list;
struct rte;
-int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
+int f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool);
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
uint f_eval_int(struct f_inst *expr);
@@ -289,7 +285,6 @@ struct f_trie
#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
-#define FF_FORCE_TMPATTR 1 /* Force all attributes to be temporary */
#define FF_SILENT 2 /* Silent filter execution */
/* Bird Tests */
diff --git a/lib/macro.h b/lib/macro.h
new file mode 100644
index 00000000..24fc3393
--- /dev/null
+++ b/lib/macro.h
@@ -0,0 +1,98 @@
+/*
+ * BIRD Macro Tricks
+ *
+ * (c) 2018 Jan Maria Matejka <mq@jmq.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ *
+ * Contains useful but dirty macro tricks:
+ * MACRO_CONCAT(a, b) -> concatenates a##b
+ * MACRO_BOOL(x) -> convert 0 to 0, anything else to 1
+ * MACRO_IFELSE(b)(true-branch)(false-branch)
+ * -> b shall be 0 or 1; expands to the appropriate branch
+ * MACRO_ISEMPTY(...) -> 1 for empty argument list, 0 otherwise
+ * MACRO_FOREACH(func, ...)
+ * -> calling FOREACH(func, a, b, c, d) expands to
+ * func(a) func(b) func(c) func(d)
+ * MACRO_RPACK(func, terminator, ...)
+ * -> packs the list into recursive calls:
+ * func(func(func(func(terminator, a), b), c), d)
+ */
+
+#ifndef _BIRD_MACRO_H_
+#define _BIRD_MACRO_H_
+
+/* What to do with args */
+#define MACRO_DROP(...)
+#define MACRO_UNPAREN(...) __VA_ARGS__
+#define MACRO_SEP(a, b, sep) a sep b
+
+/* Aliases for some special chars */
+#define MACRO_COMMA ,
+#define MACRO_LPAREN (
+#define MACRO_RPAREN )
+#define MACRO_LPAREN_() (
+#define MACRO_RPAREN_() )
+
+/* Multiple expansion trick */
+#define MACRO_EXPAND0(...) __VA_ARGS__
+#define MACRO_EXPAND1(...) MACRO_EXPAND0(MACRO_EXPAND0(__VA_ARGS__))
+#define MACRO_EXPAND2(...) MACRO_EXPAND1(MACRO_EXPAND1(__VA_ARGS__))
+#define MACRO_EXPAND3(...) MACRO_EXPAND2(MACRO_EXPAND2(__VA_ARGS__))
+#define MACRO_EXPAND(...) MACRO_EXPAND3(MACRO_EXPAND3(__VA_ARGS__))
+
+/* Deferring expansion in the expansion trick */
+#define MACRO_EMPTY()
+#define MACRO_DEFER(t) t MACRO_EMPTY()
+#define MACRO_DEFER2(t) t MACRO_EMPTY MACRO_EMPTY()()
+#define MACRO_DEFER3(t) t MACRO_EMPTY MACRO_EMPTY MACRO_EMPTY()()()
+
+/* Token concatenation */
+#define MACRO_CONCAT(prefix, ...) prefix##__VA_ARGS__
+#define MACRO_CONCAT_AFTER(...) MACRO_CONCAT(__VA_ARGS__)
+
+/* Get first or second argument only */
+#define MACRO_FIRST(a, ...) a
+#define MACRO_SECOND(a, b, ...) b
+#define MACRO_SECOND_OR_ZERO(...) MACRO_SECOND(__VA_ARGS__, 0,)
+
+/* Macro Boolean auxiliary macros */
+#define MACRO_BOOL_CHECK_0 ~, 1
+#define MACRO_BOOL_NEG(x) MACRO_SECOND_OR_ZERO(MACRO_CONCAT(MACRO_BOOL_CHECK_, x))
+
+#define MACRO_BOOL_NOT_0 1
+#define MACRO_BOOL_NOT_1 0
+
+/* Macro Boolean negation */
+#define MACRO_NOT(x) MACRO_CONCAT(MACRO_BOOL_NOT_, x)
+
+/* Convert anything to bool (anything -> 1, 0 -> 0) */
+#define MACRO_BOOL(x) MACRO_NOT(MACRO_BOOL_NEG(x))
+
+/*
+ * Macro If/Else condition
+ * Usage: MACRO_IFELSE(condition)(true-branch)(false-branch)
+ * Expands to true-branch if condition is true, otherwise to false-branch.
+ */
+#define MACRO_IFELSE(b) MACRO_CONCAT(MACRO_IFELSE_, b)
+#define MACRO_IFELSE_0(...) MACRO_UNPAREN
+#define MACRO_IFELSE_1(...) __VA_ARGS__ MACRO_DROP
+
+/* Auxiliary macros for MACRO_FOREACH */
+#define MACRO_ISLAST(...) MACRO_BOOL_NEG(MACRO_FIRST(MACRO_ISLAST_CHECK __VA_ARGS__)())
+#define MACRO_ISLAST_CHECK() 0
+
+#define MACRO_FOREACH_EXPAND(call, a, ...) MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))(call(a))(call(a) MACRO_DEFER2(MACRO_FOREACH_PAREN)()(call, __VA_ARGS__))
+#define MACRO_FOREACH_PAREN() MACRO_FOREACH_EXPAND
+
+#define MACRO_RPACK_EXPAND(call, terminator, a, ...) MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))(call(terminator, a))(call(MACRO_DEFER2(MACRO_RPACK_PAREN)()(call, terminator, __VA_ARGS__), a))
+#define MACRO_RPACK_PAREN() MACRO_RPACK_EXPAND
+/*
+ * Call the first argument for each following:
+ * MACRO_FOREACH(func, a, b, c, d) expands to func(a) func(b) func(c) func(d).
+ * It supports also macros as func.
+ */
+#define MACRO_FOREACH(call, ...) MACRO_EXPAND(MACRO_FOREACH_EXPAND(call, __VA_ARGS__))
+#define MACRO_RPACK(call, terminator, ...) MACRO_EXPAND(MACRO_RPACK_EXPAND(call, terminator, __VA_ARGS__))
+
+#endif
diff --git a/nest/proto.c b/nest/proto.c
index 15d6f4de..49f71304 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -25,6 +25,7 @@ pool *proto_pool;
list proto_list;
static list protocol_list;
+struct protocol *class_to_protocol[PROTOCOL__MAX];
#define PD(pr, msg, args...) do { if (pr->debug & D_STATES) { log(L_TRACE "%s: " msg, pr->name , ## args); } } while(0)
@@ -1256,11 +1257,9 @@ void
proto_build(struct protocol *p)
{
add_tail(&protocol_list, &p->n);
- if (p->attr_class)
- {
- ASSERT(!attr_class_to_protocol[p->attr_class]);
- attr_class_to_protocol[p->attr_class] = p;
- }
+ ASSERT(p->class);
+ ASSERT(!class_to_protocol[p->class]);
+ class_to_protocol[p->class] = p;
}
/* FIXME: convert this call to some protocol hook */
diff --git a/nest/protocol.h b/nest/protocol.h
index 8a22d76b..dd942c10 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -37,12 +37,31 @@ struct symbol;
* Routing Protocol
*/
+enum protocol_class {
+ PROTOCOL_NONE,
+ PROTOCOL_BABEL,
+ PROTOCOL_BFD,
+ PROTOCOL_BGP,
+ PROTOCOL_DEVICE,
+ PROTOCOL_DIRECT,
+ PROTOCOL_KERNEL,
+ PROTOCOL_OSPF,
+ PROTOCOL_PIPE,
+ PROTOCOL_RADV,
+ PROTOCOL_RIP,
+ PROTOCOL_RPKI,
+ PROTOCOL_STATIC,
+ PROTOCOL__MAX
+};
+
+extern struct protocol *class_to_protocol[PROTOCOL__MAX];
+
struct protocol {
node n;
char *name;
char *template; /* Template for automatic generation of names */
int name_counter; /* Counter for automatic name generation */
- int attr_class; /* Attribute class known to this protocol */
+ enum protocol_class class; /* Machine readable protocol class */
uint preference; /* Default protocol preference */
uint channel_mask; /* Mask of accepted channel types (NB_*) */
uint proto_size; /* Size of protocol data structure */
@@ -58,7 +77,7 @@ struct protocol {
int (*shutdown)(struct proto *); /* Stop the instance */
void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
- void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
+ void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */
@@ -172,7 +191,7 @@ struct proto {
* rt_notify Notify protocol about routing table updates.
* neigh_notify Notify protocol about neighbor cache events.
* make_tmp_attrs Construct ea_list from private attrs stored in rte.
- * store_tmp_attrs Store private attrs back to the rte.
+ * store_tmp_attrs Store private attrs back to rta. The route MUST NOT be cached.
* import_control Called as the first step of the route importing process.
* It can construct a new rte, add private attributes and
* decide whether the route shall be imported: 1=yes, -1=no,
@@ -186,11 +205,11 @@ struct proto {
void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a);
- void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old, struct ea_list *attrs);
+ void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old);
void (*neigh_notify)(struct neighbor *neigh);
struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
- void (*store_tmp_attrs)(struct rte *rt, struct ea_list *attrs);
- int (*import_control)(struct proto *, struct rte **rt, struct ea_list **attrs, struct linpool *pool);
+ void (*store_tmp_attrs)(struct rte *rt);
+ int (*import_control)(struct proto *, struct rte **rt, struct linpool *pool);
void (*reload_routes)(struct channel *);
void (*feed_begin)(struct channel *, int initial);
void (*feed_end)(struct channel *);
@@ -273,12 +292,16 @@ proto_get_router_id(struct proto_config *pc)
return pc->router_id ? pc->router_id : pc->global->router_id;
}
-static inline struct ea_list *
-rte_make_tmp_attrs(struct rte *rt, struct linpool *pool)
+static inline void
+rte_make_tmp_attrs(struct rte **rt, struct linpool *pool)
{
struct ea_list *(*mta)(struct rte *rt, struct linpool *pool);
- mta = rt->attrs->src->proto->make_tmp_attrs;
- return mta ? mta(rt, pool) : NULL;
+ mta = (*rt)->attrs->src->proto->make_tmp_attrs;
+ if (!mta) return;
+ *rt = rte_cow_rta(*rt, pool);
+ struct ea_list *ea = mta(*rt, pool);
+ ea->next = (*rt)->attrs->eattrs;
+ (*rt)->attrs->eattrs = ea;
}
/* Moved from route.h to avoid dependency conflicts */
@@ -447,7 +470,7 @@ struct channel_class {
void (*dump_attrs)(struct rte *); /* Dump protocol-dependent attributes */
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
- void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
+ void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
diff --git a/nest/route.h b/nest/route.h
index 79127519..cad15440 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -294,7 +294,7 @@ rte *rte_get_temp(struct rta *);
void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
/* rte_update() moved to protocol.h to avoid dependency conflicts */
int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
-rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, linpool *pool, int silent);
+rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
void rt_refresh_begin(rtable *t, struct channel *c);
void rt_refresh_end(rtable *t, struct channel *c);
void rt_schedule_prune(rtable *t);
@@ -457,7 +457,7 @@ static inline int rte_is_reachable(rte *r)
*/
typedef struct eattr {
- word id; /* EA_CODE(EAP_..., protocol-dependent ID) */
+ word id; /* EA_CODE(PROTOCOL_..., protocol-dependent ID) */
byte flags; /* Protocol-dependent flags */
byte type; /* Attribute type and several flags (EAF_...) */
union {
@@ -466,20 +466,11 @@ typedef struct eattr {
} u;
} eattr;
-#define EAP_GENERIC 0 /* Generic attributes */
-#define EAP_BGP 1 /* BGP attributes */
-#define EAP_RIP 2 /* RIP */
-#define EAP_OSPF 3 /* OSPF */
-#define EAP_KRT 4 /* Kernel route attributes */
-#define EAP_BABEL 5 /* Babel attributes */
-#define EAP_RADV 6 /* Router advertisment attributes */
-#define EAP_MAX 7
-
#define EA_CODE(proto,id) (((proto) << 8) | (id))
#define EA_PROTO(ea) ((ea) >> 8)
#define EA_ID(ea) ((ea) & 0xff)
-#define EA_GEN_IGP_METRIC EA_CODE(EAP_GENERIC, 0)
+#define EA_GEN_IGP_METRIC EA_CODE(PROTOCOL_NONE, 0)
#define EA_CODE_MASK 0xffff
#define EA_ALLOW_UNDEF 0x10000 /* ea_find: allow EAF_TYPE_UNDEF */
@@ -555,6 +546,15 @@ uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
ea_list *ea_append(ea_list *to, ea_list *what);
void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
+#define ea_normalize(ea) do { \
+ if (ea->next) { \
+ ea_list *t = alloca(ea_scan(ea)); \
+ ea_merge(ea, t); \
+ ea = t; \
+ } \
+ ea_sort(ea); \
+} while(0) \
+
static inline eattr *
ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val)
{
@@ -620,7 +620,7 @@ rta *rta_do_cow(rta *o, linpool *lp);
static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; }
void rta_dump(rta *);
void rta_dump_all(void);
-void rta_show(struct cli *, rta *, ea_list *);
+void rta_show(struct cli *, rta *);
struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep);
void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls);
@@ -656,9 +656,6 @@ rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr
static inline void rt_lock_hostentry(struct hostentry *he) { if (he) he->uc++; }
static inline void rt_unlock_hostentry(struct hostentry *he) { if (he) he->uc--; }
-
-extern struct protocol *attr_class_to_protocol[EAP_MAX];
-
/*
* Default protocol preferences
*/
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 881687de..73ca4748 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -88,9 +88,6 @@ static struct idm src_ids;
static HASH(struct rte_src) src_hash;
-struct protocol *attr_class_to_protocol[EAP_MAX];
-
-
static void
rte_src_init(void)
{
@@ -553,29 +550,47 @@ ea_do_sort(ea_list *e)
while (ss);
}
+/**
+ * In place discard duplicates, undefs and temporary attributes in sorted
+ * ea_list. We use stable sort for this reason.
+ **/
static inline void
ea_do_prune(ea_list *e)
{
eattr *s, *d, *l, *s0;
int i = 0;
- /* Discard duplicates and undefs. Do you remember sorting was stable? */
- s = d = e->attrs;
- l = e->attrs + e->count;
+ s = d = e->attrs; /* Beginning of the list. @s is source, @d is destination. */
+ l = e->attrs + e->count; /* End of the list */
+
+ /* Walk from begin to end. */
while (s < l)
{
s0 = s++;
+ /* Find a consecutive block of the same attribute */
while (s < l && s->id == s[-1].id)
s++;
- /* s0 is the most recent version, s[-1] the oldest one */
- if ((s0->type & EAF_TYPE_MASK) != EAF_TYPE_UNDEF)
- {
- *d = *s0;
- d->type = (d->type & ~(EAF_ORIGINATED|EAF_FRESH)) | (s[-1].type & EAF_ORIGINATED);
- d++;
- i++;
- }
+
+ /* Now s0 is the most recent version, s[-1] the oldest one */
+ /* Drop undefs */
+ if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
+ continue;
+
+ /* Drop temporary attributes */
+ if (s0->type & EAF_TEMP)
+ continue;
+
+ /* Copy the newest version to destination */
+ *d = *s0;
+
+ /* Preserve info whether it originated locally */
+ d->type = (d->type & ~(EAF_ORIGINATED|EAF_FRESH)) | (s[-1].type & EAF_ORIGINATED);
+
+ /* Next destination */
+ d++;
+ i++;
}
+
e->count = i;
}
@@ -851,7 +866,7 @@ ea_show(struct cli *c, eattr *e)
byte buf[CLI_MSG_SIZE];
byte *pos = buf, *end = buf + sizeof(buf);
- if (p = attr_class_to_protocol[EA_PROTO(e->id)])
+ if (p = class_to_protocol[EA_PROTO(e->id)])
{
pos += bsprintf(pos, "%s.", p->name);
if (p->get_attr)
@@ -1131,15 +1146,7 @@ rta_lookup(rta *o)
ASSERT(!(o->aflags & RTAF_CACHED));
if (o->eattrs)
- {
- if (o->eattrs->next) /* Multiple ea_list's, need to merge them */
- {
- ea_list *ml = alloca(ea_scan(o->eattrs));
- ea_merge(o->eattrs, ml);
- o->eattrs = ml;
- }
- ea_sort(o->eattrs);
- }
+ ea_normalize(o->eattrs);
h = rta_hash(o);
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next)
@@ -1253,17 +1260,15 @@ rta_dump_all(void)
}
void
-rta_show(struct cli *c, rta *a, ea_list *eal)
+rta_show(struct cli *c, rta *a)
{
static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect",
"RIP", "OSPF", "OSPF-IA", "OSPF-E1", "OSPF-E2", "BGP", "pipe" };
- int i;
cli_printf(c, -1008, "\tType: %s %s", src_names[a->source], ip_scope_text(a->scope));
- if (!eal)
- eal = a->eattrs;
- for(; eal; eal=eal->next)
- for(i=0; i<eal->count; i++)
+
+ for(ea_list *eal = a->eattrs; eal; eal=eal->next)
+ for(int i=0; i<eal->count; i++)
ea_show(c, &eal->attrs[i]);
}
diff --git a/nest/rt-dev.c b/nest/rt-dev.c
index 66f458e7..61f025ce 100644
--- a/nest/rt-dev.c
+++ b/nest/rt-dev.c
@@ -185,6 +185,7 @@ dev_copy_config(struct proto_config *dest, struct proto_config *src)
struct protocol proto_device = {
.name = "Direct",
.template = "direct%d",
+ .class = PROTOCOL_DIRECT,
.preference = DEF_PREF_DIRECT,
.channel_mask = NB_IP | NB_IP6_SADR,
.proto_size = sizeof(struct rt_dev_proto),
diff --git a/nest/rt-show.c b/nest/rt-show.c
index 1f1b73d2..90165c57 100644
--- a/nest/rt-show.c
+++ b/nest/rt-show.c
@@ -29,14 +29,14 @@ rt_show_table(struct cli *c, struct rt_show_data *d)
}
static void
-rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
+rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
{
byte from[IPA_MAX_TEXT_LENGTH+8];
byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
rta *a = e->attrs;
int primary = (e->net->routes == e);
int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
- void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs);
+ void (*get_route_info)(struct rte *, byte *buf);
struct nexthop *nh;
tm_format_time(tm, &config->tf_route, e->lastmod);
@@ -46,17 +46,11 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
from[0] = 0;
get_route_info = a->src->proto->proto->get_route_info;
- if (get_route_info || d->verbose)
- {
- /* Need to normalize the extended attributes */
- ea_list *t = tmpa;
- t = ea_append(t, a->eattrs);
- tmpa = alloca(ea_scan(t));
- ea_merge(t, tmpa);
- ea_sort(tmpa);
- }
+ /* Need to normalize the extended attributes */
+ if ((get_route_info || d->verbose) && !rta_is_cached(a))
+ ea_normalize(a->eattrs);
if (get_route_info)
- get_route_info(e, info, tmpa);
+ get_route_info(e, info);
else
bsprintf(info, " (%d)", e->pref);
@@ -93,7 +87,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
}
if (d->verbose)
- rta_show(c, a, tmpa);
+ rta_show(c, a);
}
static void
@@ -101,7 +95,6 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
rte *e, *ee;
byte ia[NET_MAX_TEXT_LENGTH+1];
- struct ea_list *tmpa;
struct channel *ec = d->tab->export_channel;
int first = 1;
int pass = 0;
@@ -121,7 +114,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
continue;
ee = e;
- tmpa = rte_make_tmp_attrs(e, c->show_pool);
+ rte_make_tmp_attrs(&e, c->show_pool);
/* Export channel is down, do not try to export routes to it */
if (ec && (ec->export_state == ES_DOWN))
@@ -131,7 +124,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED))
{
rte *rt_free;
- e = rt_export_merged(ec, n, &rt_free, &tmpa, c->show_pool, 1);
+ e = rt_export_merged(ec, n, &rt_free, c->show_pool, 1);
pass = 1;
if (!e)
@@ -140,7 +133,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
else if (d->export_mode)
{
struct proto *ep = ec->proto;
- int ic = ep->import_control ? ep->import_control(ep, &e, &tmpa, c->show_pool) : 0;
+ int ic = ep->import_control ? ep->import_control(ep, &e, c->show_pool) : 0;
if (ec->ra_mode == RA_OPTIMAL || ec->ra_mode == RA_MERGED)
pass = 1;
@@ -156,8 +149,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
* command may change the export filter and do not update routes.
*/
int do_export = (ic > 0) ||
- (f_run(ec->out_filter, &e, &tmpa, c->show_pool,
- FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT);
+ (f_run(ec->out_filter, &e, c->show_pool, FF_SILENT) <= F_ACCEPT);
if (do_export != (d->export_mode == RSEM_EXPORT))
goto skip;
@@ -170,11 +162,11 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
if (d->show_protocol && (d->show_protocol != e->attrs->src->proto))
goto skip;
- if (f_run(d->filter, &e, &tmpa, c->show_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
+ if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT)
goto skip;
if (d->stats < 2)
- rt_show_rte(c, ia, e, d, tmpa);
+ rt_show_rte(c, ia, e, d);
d->show_counter++;
ia[0] = 0;
diff --git a/nest/rt-table.c b/nest/rt-table.c
index b885c6e3..de7b05fc 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -317,11 +317,11 @@ rte_cow_rta(rte *r, linpool *lp)
if (!rta_is_cached(r->attrs))
return r;
- rte *e = rte_cow(r);
+ r = rte_cow(r);
rta *a = rta_do_cow(r->attrs, lp);
- rta_free(e->attrs);
- e->attrs = a;
- return e;
+ rta_free(r->attrs);
+ r->attrs = a;
+ return r;
}
static int /* Actually better or at least as good as */
@@ -393,24 +393,20 @@ rte_trace_out(uint flag, struct proto *p, rte *e, char *msg)
}
static rte *
-export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpool *pool, int silent)
+export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int silent)
{
struct proto *p = c->proto;
struct filter *filter = c->out_filter;
struct proto_stats *stats = &c->stats;
- ea_list *tmpb = NULL;
rte *rt;
int v;
rt = rt0;
*rt_free = NULL;
- if (!tmpa)
- tmpa = &tmpb;
+ rte_make_tmp_attrs(&rt, pool);
- *tmpa = rte_make_tmp_attrs(rt, pool);
-
- v = p->import_control ? p->import_control(p, &rt, tmpa, pool) : 0;
+ v = p->import_control ? p->import_control(p, &rt, pool) : 0;
if (v < 0)
{
if (silent)
@@ -429,8 +425,8 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpo
}
v = filter && ((filter == FILTER_REJECT) ||
- (f_run(filter, &rt, tmpa, pool,
- FF_FORCE_TMPATTR | (silent ? FF_SILENT : 0)) > F_ACCEPT));
+ (f_run(filter, &rt, pool,
+ (silent ? FF_SILENT : 0)) > F_ACCEPT));
if (v)
{
if (silent)
@@ -454,13 +450,13 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpo
}
static inline rte *
-export_filter(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, int silent)
+export_filter(struct channel *c, rte *rt0, rte **rt_free, int silent)
{
- return export_filter_(c, rt0, rt_free, tmpa, rte_update_pool, silent);
+ return export_filter_(c, rt0, rt_free, rte_update_pool, silent);
}
static void
-do_rt_notify(struct channel *c, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
+do_rt_notify(struct channel *c, net *net, rte *new, rte *old, int refeed)
{
struct proto *p = c->proto;
struct proto_stats *stats = &c->stats;
@@ -533,19 +529,7 @@ do_rt_notify(struct channel *c, net *net, rte *new, rte *old, ea_list *tmpa, int
else if (old)
rte_trace_out(D_ROUTES, p, old, "removed");
}
- if (!new)
- p->rt_notify(p, c, net, NULL, old, NULL);
- else if (tmpa)
- {
- ea_list *t = tmpa;
- while (t->next)
- t = t->next;
- t->next = new->attrs->eattrs;
- p->rt_notify(p, c, net, new, old, tmpa);
- t->next = NULL;
- }
- else
- p->rt_notify(p, c, net, new, old, new->attrs->eattrs);
+ p->rt_notify(p, c, net, new, old);
}
static void
@@ -557,7 +541,6 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
rte *old = old0;
rte *new_free = NULL;
rte *old_free = NULL;
- ea_list *tmpa = NULL;
if (new)
c->stats.exp_updates_received++;
@@ -585,10 +568,10 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
*/
if (new)
- new = export_filter(c, new, &new_free, &tmpa, 0);
+ new = export_filter(c, new, &new_free, 0);
if (old && !refeed)
- old = export_filter(c, old, &old_free, NULL, 1);
+ old = export_filter(c, old, &old_free, 1);
if (!new && !old)
{
@@ -605,13 +588,13 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
#ifdef CONFIG_PIPE
if ((p->proto == &proto_pipe) && !new0 && (p != old0->sender->proto))
- p->rt_notify(p, c, net, NULL, old0, NULL);
+ p->rt_notify(p, c, net, NULL, old0);
#endif
return;
}
- do_rt_notify(c, net, new, old, tmpa, refeed);
+ do_rt_notify(c, net, new, old, refeed);
/* Discard temporary rte's */
if (new_free)
@@ -630,7 +613,6 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
rte *old_best = NULL;
rte *new_free = NULL;
rte *old_free = NULL;
- ea_list *tmpa = NULL;
/* Used to track whether we met old_changed position. If before_old is NULL
old_changed was the first and we met it implicitly before current best route. */
@@ -648,7 +630,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
/* First, find the new_best route - first accepted by filters */
for (r=net->routes; rte_is_valid(r); r=r->next)
{
- if (new_best = export_filter(c, r, &new_free, &tmpa, 0))
+ if (new_best = export_filter(c, r, &new_free, 0))
break;
/* Note if we walked around the position of old_changed route */
@@ -699,7 +681,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
/* First case */
if (old_meet)
- if (old_best = export_filter(c, old_changed, &old_free, NULL, 1))
+ if (old_best = export_filter(c, old_changed, &old_free, 1))
goto found;
/* Second case */
@@ -717,18 +699,18 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
/* Fourth case */
for (r=r->next; rte_is_valid(r); r=r->next)
{
- if (old_best = export_filter(c, r, &old_free, NULL, 1))
+ if (old_best = export_filter(c, r, &old_free, 1))
goto found;
if (r == before_old)
- if (old_best = export_filter(c, old_changed, &old_free, NULL, 1))
+ if (old_best = export_filter(c, old_changed, &old_free, 1))
goto found;
}
/* Implicitly, old_best is NULL and new_best is non-NULL */
found:
- do_rt_notify(c, net, new_best, old_best, tmpa, (feed == 2));
+ do_rt_notify(c, net, new_best, old_best, (feed == 2));
/* Discard temporary rte's */
if (new_free)
@@ -745,7 +727,7 @@ nexthop_merge_rta(struct nexthop *nhs, rta *a, linpool *pool, int max)
}
rte *
-rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, linpool *pool, int silent)
+rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent)
{
// struct proto *p = c->proto;
struct nexthop *nhs = NULL;
@@ -757,7 +739,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, lin
if (!rte_is_valid(best0))
return NULL;
- best = export_filter_(c, best0, rt_free, tmpa, pool, silent);
+ best = export_filter_(c, best0, rt_free, pool, silent);
if (!best || !rte_is_reachable(best))
return best;
@@ -767,7 +749,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, lin
if (!rte_mergable(best0, rt0))
continue;
- rt = export_filter_(c, rt0, &tmp, NULL, pool, 1);
+ rt = export_filter_(c, rt0, &tmp, pool, 1);
if (!rt)
continue;
@@ -807,7 +789,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
rte *old_best_free = NULL;
rte *new_changed_free = NULL;
rte *old_changed_free = NULL;
- ea_list *tmpa = NULL;
/* We assume that all rte arguments are either NULL or rte_is_valid() */
@@ -819,10 +800,10 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
if ((new_best == old_best) && !refeed)
{
new_changed = rte_mergable(new_best, new_changed) ?
- export_filter(c, new_changed, &new_changed_free, NULL, 1) : NULL;
+ export_filter(c, new_changed, &new_changed_free, 1) : NULL;
old_changed = rte_mergable(old_best, old_changed) ?
- export_filter(c, old_changed, &old_changed_free, NULL, 1) : NULL;
+ export_filter(c, old_changed, &old_changed_free, 1) : NULL;
if (!new_changed && !old_changed)
return;
@@ -835,15 +816,15 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
/* Prepare new merged route */
if (new_best)
- new_best = rt_export_merged(c, net, &new_best_free, &tmpa, rte_update_pool, 0);
+ new_best = rt_export_merged(c, net, &new_best_free, rte_update_pool, 0);
/* Prepare old merged route (without proper merged next hops) */
/* There are some issues with running filter on old route - see rt_notify_basic() */
if (old_best && !refeed)
- old_best = export_filter(c, old_best, &old_best_free, NULL, 1);
+ old_best = export_filter(c, old_best, &old_best_free, 1);
if (new_best || old_best)
- do_rt_notify(c, net, new_best, old_best, tmpa, refeed);
+ do_rt_notify(c, net, new_best, old_best, refeed);
/* Discard temporary rte's */
if (new_best_free)
@@ -1341,7 +1322,6 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
struct proto *p = c->proto;
struct proto_stats *stats = &c->stats;
struct filter *filter = c->in_filter;
- ea_list *tmpa = NULL;
rte *dummy = NULL;
net *nn;
@@ -1379,11 +1359,11 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
}
else
{
- tmpa = rte_make_tmp_attrs(new, rte_update_pool);
+ rte_make_tmp_attrs(&new, rte_update_pool);
if (filter && (filter != FILTER_REJECT))
{
- ea_list *old_tmpa = tmpa;
- int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
+ ea_list *oldea = new->attrs->eattrs;
+ int fr = f_run(filter, &new, rte_update_pool, 0);
if (fr > F_ACCEPT)
{
stats->imp_updates_filtered++;
@@ -1394,8 +1374,8 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
new->flags |= REF_FILTERED;
}
- if (tmpa != old_tmpa && src->proto->store_tmp_attrs)
- src->proto->store_tmp_attrs(new, tmpa);
+ if (new->attrs->eattrs != oldea && src->proto->store_tmp_attrs)
+ src->proto->store_tmp_attrs(new);
}
}
if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
@@ -1459,11 +1439,10 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
rte_update_lock();
/* Rest is stripped down export_filter() */
- ea_list *tmpa = rte_make_tmp_attrs(rt, rte_update_pool);
- int v = p->import_control ? p->import_control(p, &rt, &tmpa, rte_update_pool) : 0;
+ rte_make_tmp_attrs(&rt, rte_update_pool);
+ int v = p->import_control ? p->import_control(p, &rt, rte_update_pool) : 0;
if (v == RIC_PROCESS)
- v = (f_run(filter, &rt, &tmpa, rte_update_pool,
- FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT);
+ v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
/* Discard temporary rte */
if (rt != n->routes)
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 20953044..b4404f45 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1833,7 +1833,7 @@ babel_dump(struct proto *P)
}
static void
-babel_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
+babel_get_route_info(rte *rte, byte *buf)
{
buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id);
}
@@ -2091,12 +2091,13 @@ babel_prepare_attrs(struct linpool *pool, ea_list *next, uint metric, u64 router
static int
-babel_import_control(struct proto *P, struct rte **new, struct ea_list **attrs UNUSED, struct linpool *pool UNUSED)
+babel_import_control(struct proto *P, struct rte **new, struct linpool *pool)
{
- rte *e = *new;
+ struct babel_proto *p = (void *) P;
+ struct rta *a = (*new)->attrs;
/* Reject our own unreachable routes */
- if ((e->attrs->dest == RTD_UNREACHABLE) && (e->attrs->src->proto == P))
+ if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == P))
return -1;
return 0;
@@ -2109,9 +2110,9 @@ babel_make_tmp_attrs(struct rte *rt, struct linpool *pool)
}
static void
-babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
+babel_store_tmp_attrs(struct rte *rt)
{
- rt->u.babel.metric = ea_get_int(attrs, EA_BABEL_METRIC, 0);
+ rt->u.babel.metric = ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, 0);
}
/*
@@ -2120,7 +2121,7 @@ babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
*/
static void
babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
- struct rte *new, struct rte *old UNUSED, struct ea_list *attrs UNUSED)
+ struct rte *new, struct rte *old UNUSED)
{
struct babel_proto *p = (void *) P;
struct babel_entry *e;
@@ -2130,7 +2131,7 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
/* Update */
uint internal = (new->attrs->src->proto == P);
uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno;
- uint rt_metric = ea_get_int(attrs, EA_BABEL_METRIC, 0);
+ uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id;
if (rt_metric > BABEL_INFINITY)
@@ -2316,7 +2317,7 @@ babel_reconfigure(struct proto *P, struct proto_config *CF)
struct protocol proto_babel = {
.name = "Babel",
.template = "babel%d",
- .attr_class = EAP_BABEL,
+ .class = PROTOCOL_BABEL,
.preference = DEF_PREF_BABEL,
.channel_mask = NB_IP | NB_IP6_SADR,
.proto_size = sizeof(struct babel_proto),
diff --git a/proto/babel/babel.h b/proto/babel/babel.h
index e5c9cd5b..14765c60 100644
--- a/proto/babel/babel.h
+++ b/proto/babel/babel.h
@@ -25,8 +25,8 @@
#include "lib/string.h"
#include "lib/timer.h"
-#define EA_BABEL_METRIC EA_CODE(EAP_BABEL, 0)
-#define EA_BABEL_ROUTER_ID EA_CODE(EAP_BABEL, 1)
+#define EA_BABEL_METRIC EA_CODE(PROTOCOL_BABEL, 0)
+#define EA_BABEL_ROUTER_ID EA_CODE(PROTOCOL_BABEL, 1)
#define BABEL_MAGIC 42
#define BABEL_VERSION 2
diff --git a/proto/babel/config.Y b/proto/babel/config.Y
index 205b4e4f..2b20c43f 100644
--- a/proto/babel/config.Y
+++ b/proto/babel/config.Y
@@ -125,7 +125,7 @@ babel_iface_opt_list:
babel_iface:
babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish;
-CF_ADDTO(dynamic_attr, BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_BABEL_METRIC); })
+CF_ADDTO(dynamic_attr, BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_BABEL_METRIC); })
CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]);
diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c
index 67ec2270..64d5007b 100644
--- a/proto/bfd/bfd.c
+++ b/proto/bfd/bfd.c
@@ -1116,6 +1116,7 @@ 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 d7a4e692..8ecfaaa2 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -92,7 +92,7 @@ bgp_set_attr(ea_list **attrs, struct linpool *pool, uint code, uint flags, uintp
a->next = *attrs;
*attrs = a;
- e->id = EA_CODE(EAP_BGP, code);
+ e->id = EA_CODE(PROTOCOL_BGP, code);
e->type = bgp_attr_table[code].type;
e->flags = flags;
@@ -702,7 +702,7 @@ static inline void
bgp_decode_unknown(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to)
{
/* Cannot use bgp_set_attr_data() as it works on known attributes only */
- ea_set_attr_data(to, s->pool, EA_CODE(EAP_BGP, code), flags, EAF_TYPE_OPAQUE, data, len);
+ ea_set_attr_data(to, s->pool, EA_CODE(PROTOCOL_BGP, code), flags, EAF_TYPE_OPAQUE, data, len);
}
@@ -857,7 +857,7 @@ 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) != EAP_BGP)
+ if (EA_PROTO(a->id) != PROTOCOL_BGP)
return;
uint code = EA_ID(a->id);
@@ -937,7 +937,7 @@ bgp_export_attrs(struct bgp_export_state *s, ea_list *attrs)
static inline int
bgp_encode_attr(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
{
- ASSERT(EA_PROTO(a->id) == EAP_BGP);
+ ASSERT(EA_PROTO(a->id) == PROTOCOL_BGP);
uint code = EA_ID(a->id);
@@ -1375,7 +1375,7 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px)
*/
int
-bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
+bgp_import_control(struct proto *P, rte **new, struct linpool *pool UNUSED)
{
rte *e = *new;
struct proto *SRC = e->attrs->src->proto;
@@ -1408,7 +1408,7 @@ bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li
/* Handle well-known communities, RFC 1997 */
struct eattr *c;
if (p->cf->interpret_communities &&
- (c = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_COMMUNITY))))
+ (c = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY))))
{
struct adata *d = c->u.ptr;
@@ -1539,7 +1539,7 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at
}
void
-bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea_list *attrs)
+bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old)
{
struct bgp_proto *p = (void *) P;
struct bgp_channel *c = (void *) C;
@@ -1549,7 +1549,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea
if (new)
{
- attrs = bgp_update_attrs(p, c, new, attrs, bgp_linpool2);
+ struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, bgp_linpool2);
/* If attributes are invalid, we fail back to withdraw */
buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
@@ -1573,7 +1573,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea
static inline u32
bgp_get_neighbor(rte *r)
{
- eattr *e = ea_find(r->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
+ eattr *e = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
u32 as;
if (e && as_path_get_first_regular(e->u.ptr, &as))
@@ -1615,8 +1615,8 @@ bgp_rte_better(rte *new, rte *old)
return 0;
/* Start with local preferences */
- x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF));
- y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF));
+ 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));
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)
@@ -1627,8 +1627,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(EAP_BGP, BA_AS_PATH));
- y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
+ 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));
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)
@@ -1638,8 +1638,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(EAP_BGP, BA_ORIGIN));
- y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGIN));
+ x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
+ y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
n = x ? x->u.data : ORIGIN_INCOMPLETE;
o = y ? y->u.data : ORIGIN_INCOMPLETE;
if (n < o)
@@ -1661,8 +1661,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(EAP_BGP, BA_MULTI_EXIT_DISC));
- y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
+ 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));
n = x ? x->u.data : new_bgp->cf->default_med;
o = y ? y->u.data : old_bgp->cf->default_med;
if (n < o)
@@ -1687,8 +1687,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(EAP_BGP, BA_ORIGINATOR_ID));
- y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGINATOR_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));
n = x ? x->u.data : new_bgp->remote_id;
o = y ? y->u.data : old_bgp->remote_id;
@@ -1705,8 +1705,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(EAP_BGP, BA_CLUSTER_LIST));
- y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_CLUSTER_LIST));
+ 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));
n = x ? int_set_get_size(x->u.ptr) : 0;
o = y ? int_set_get_size(y->u.ptr) : 0;
if (n < o)
@@ -1736,8 +1736,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
return 0;
/* Start with local preferences */
- x = ea_find(pri->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF));
- y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_LOCAL_PREF));
+ 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));
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)
@@ -1746,8 +1746,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(EAP_BGP, BA_AS_PATH));
- y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
+ 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));
p = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
s = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
@@ -1759,8 +1759,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(EAP_BGP, BA_ORIGIN));
- y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_ORIGIN));
+ x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
+ y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
p = x ? x->u.data : ORIGIN_INCOMPLETE;
s = y ? y->u.data : ORIGIN_INCOMPLETE;
if (p != s)
@@ -1770,8 +1770,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(EAP_BGP, BA_MULTI_EXIT_DISC));
- y = ea_find(sec->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
+ 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));
p = x ? x->u.data : pri_bgp->cf->default_med;
s = y ? y->u.data : sec_bgp->cf->default_med;
if (p != s)
@@ -2010,10 +2010,10 @@ bgp_get_attr(eattr *a, byte *buf, int buflen)
}
void
-bgp_get_route_info(rte *e, byte *buf, ea_list *attrs)
+bgp_get_route_info(rte *e, byte *buf)
{
- eattr *p = ea_find(attrs, EA_CODE(EAP_BGP, BA_AS_PATH));
- eattr *o = ea_find(attrs, EA_CODE(EAP_BGP, BA_ORIGIN));
+ 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));
u32 origas;
buf += bsprintf(buf, " (%d", e->pref);
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 9db26050..932ad9f3 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -2148,7 +2148,7 @@ struct channel_class channel_bgp = {
struct protocol proto_bgp = {
.name = "BGP",
.template = "bgp%d",
- .attr_class = EAP_BGP,
+ .class = PROTOCOL_BGP,
.preference = DEF_PREF_BGP,
.channel_mask = NB_IP | NB_VPN | NB_FLOW,
.proto_size = sizeof(struct bgp_proto),
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 30424abb..1235ee78 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -462,7 +462,7 @@ struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id);
static inline eattr *
bgp_find_attr(ea_list *attrs, uint code)
{
- return ea_find(attrs, EA_CODE(EAP_BGP, code));
+ return ea_find(attrs, EA_CODE(PROTOCOL_BGP, code));
}
eattr *
@@ -505,10 +505,10 @@ void bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *bp);
int bgp_rte_better(struct rte *, struct rte *);
int bgp_rte_mergable(rte *pri, rte *sec);
int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best);
-void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea_list *attrs);
-int bgp_import_control(struct proto *, struct rte **, struct ea_list **, struct linpool *);
+void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
+int bgp_import_control(struct proto *, struct rte **, struct linpool *);
int bgp_get_attr(struct eattr *e, byte *buf, int buflen);
-void bgp_get_route_info(struct rte *, byte *buf, struct ea_list *attrs);
+void bgp_get_route_info(struct rte *, byte *buf);
/* packets.c */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 41eaa729..c731c4c7 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -253,29 +253,29 @@ bgp_proto_channel: bgp_channel_start bgp_channel_opt_list bgp_channel_end;
CF_ADDTO(dynamic_attr, BGP_ORIGIN
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_ENUM_BGP_ORIGIN, EA_CODE(EAP_BGP, BA_ORIGIN)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_ENUM_BGP_ORIGIN, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); })
CF_ADDTO(dynamic_attr, BGP_PATH
- { $$ = f_new_dynamic_attr(EAF_TYPE_AS_PATH, T_PATH, EA_CODE(EAP_BGP, BA_AS_PATH)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_AS_PATH, T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); })
CF_ADDTO(dynamic_attr, BGP_NEXT_HOP
- { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_CODE(EAP_BGP, BA_NEXT_HOP)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_CODE(PROTOCOL_BGP, BA_NEXT_HOP)); })
CF_ADDTO(dynamic_attr, BGP_MED
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC)); })
CF_ADDTO(dynamic_attr, BGP_LOCAL_PREF
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(EAP_BGP, BA_LOCAL_PREF)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); })
CF_ADDTO(dynamic_attr, BGP_ATOMIC_AGGR
- { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, T_ENUM_EMPTY, EA_CODE(EAP_BGP, BA_ATOMIC_AGGR)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_OPAQUE, T_ENUM_EMPTY, EA_CODE(PROTOCOL_BGP, BA_ATOMIC_AGGR)); })
CF_ADDTO(dynamic_attr, BGP_AGGREGATOR
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(EAP_BGP, BA_AGGREGATOR)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_CODE(PROTOCOL_BGP, BA_AGGREGATOR)); })
CF_ADDTO(dynamic_attr, BGP_COMMUNITY
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_COMMUNITY)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY)); })
CF_ADDTO(dynamic_attr, BGP_ORIGINATOR_ID
- { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_CODE(EAP_BGP, BA_ORIGINATOR_ID)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID)); })
CF_ADDTO(dynamic_attr, BGP_CLUSTER_LIST
- { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_CLUSTER_LIST)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(PROTOCOL_BGP, BA_CLUSTER_LIST)); })
CF_ADDTO(dynamic_attr, BGP_EXT_COMMUNITY
- { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(EAP_BGP, BA_EXT_COMMUNITY)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(PROTOCOL_BGP, BA_EXT_COMMUNITY)); })
CF_ADDTO(dynamic_attr, BGP_LARGE_COMMUNITY
- { $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(EAP_BGP, BA_LARGE_COMMUNITY)); })
+ { $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(PROTOCOL_BGP, BA_LARGE_COMMUNITY)); })
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 0b09966d..c439a614 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -497,10 +497,10 @@ ospf_iface:
ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
;
-CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC1); })
-CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC2); })
-CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_TAG); })
-CF_ADDTO(dynamic_attr, OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID | EAF_TEMP, T_QUAD, EA_OSPF_ROUTER_ID); })
+CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_METRIC1); })
+CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_METRIC2); })
+CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_TAG); })
+CF_ADDTO(dynamic_attr, OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_OSPF_ROUTER_ID); })
CF_CLI_HELP(SHOW OSPF, ..., [[Show information about OSPF protocol]]);
CF_CLI(SHOW OSPF, optsym, [<name>], [[Show information about OSPF protocol]])
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index 0a9efd19..fa122f01 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -101,9 +101,9 @@
#include <stdlib.h>
#include "ospf.h"
-static int ospf_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool);
+static int ospf_import_control(struct proto *P, rte **new, struct linpool *pool);
static struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
-static void ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs);
+static void ospf_store_tmp_attrs(struct rte *rt);
static void ospf_reload_routes(struct channel *C);
static int ospf_rte_better(struct rte *new, struct rte *old);
static int ospf_rte_same(struct rte *new, struct rte *old);
@@ -446,7 +446,7 @@ ospf_disp(timer * timer)
* import to the filters.
*/
static int
-ospf_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
+ospf_import_control(struct proto *P, rte **new, struct linpool *pool)
{
struct ospf_proto *p = (struct ospf_proto *) P;
struct ospf_area *oa = ospf_main_area(p);
@@ -471,12 +471,12 @@ ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool)
}
static void
-ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
+ospf_store_tmp_attrs(struct rte *rt)
{
- rt->u.ospf.metric1 = ea_get_int(attrs, EA_OSPF_METRIC1, LSINFINITY);
- rt->u.ospf.metric2 = ea_get_int(attrs, EA_OSPF_METRIC2, 10000);
- rt->u.ospf.tag = ea_get_int(attrs, EA_OSPF_TAG, 0);
- rt->u.ospf.router_id = ea_get_int(attrs, EA_OSPF_ROUTER_ID, 0);
+ rt->u.ospf.metric1 = ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
+ rt->u.ospf.metric2 = ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC2, 10000);
+ rt->u.ospf.tag = ea_get_int(rt->attrs->eattrs, EA_OSPF_TAG, 0);
+ rt->u.ospf.router_id = ea_get_int(rt->attrs->eattrs, EA_OSPF_ROUTER_ID, 0);
}
/**
@@ -535,7 +535,7 @@ ospf_get_status(struct proto *P, byte * buf)
}
static void
-ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED)
+ospf_get_route_info(rte * rte, byte * buf)
{
char *type = "<bug>";
@@ -1463,7 +1463,7 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
struct protocol proto_ospf = {
.name = "OSPF",
.template = "ospf%d",
- .attr_class = EAP_OSPF,
+ .class = PROTOCOL_OSPF,
.preference = DEF_PREF_OSPF,
.channel_mask = NB_IP,
.proto_size = sizeof(struct ospf_proto),
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index f26ed99c..ff55621a 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -863,10 +863,10 @@ struct lsadb_show_data {
};
-#define EA_OSPF_METRIC1 EA_CODE(EAP_OSPF, 0)
-#define EA_OSPF_METRIC2 EA_CODE(EAP_OSPF, 1)
-#define EA_OSPF_TAG EA_CODE(EAP_OSPF, 2)
-#define EA_OSPF_ROUTER_ID EA_CODE(EAP_OSPF, 3)
+#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)
/* ospf.c */
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index e909bbe9..54b255c9 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -1243,11 +1243,12 @@ find_surrogate_fwaddr(struct ospf_proto *p, struct ospf_area *oa)
}
void
-ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *ea)
+ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED)
{
struct ospf_proto *p = (struct ospf_proto *) P;
struct ospf_area *oa = NULL; /* non-NULL for NSSA-LSA */
ort *nf;
+ struct ea_list *ea = new->attrs->eattrs;
/*
* There are several posibilities:
diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h
index ac87334b..54ec9ccf 100644
--- a/proto/ospf/topology.h
+++ b/proto/ospf/topology.h
@@ -188,7 +188,7 @@ void ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort
void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options);
void ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode, u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit);
-void ospf_rt_notify(struct proto *P, struct channel *ch, net *n, rte *new, rte *old, ea_list *attrs);
+void ospf_rt_notify(struct proto *P, struct channel *ch, net *n, rte *new, rte *old);
void ospf_update_topology(struct ospf_proto *p);
struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 49ff52e2..7aada37e 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -44,7 +44,7 @@
#include "pipe.h"
static void
-pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs)
+pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old)
{
struct pipe_proto *p = (void *) P;
struct channel *dst = (src_ch == p->pri) ? p->sec : p->pri;
@@ -69,7 +69,6 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
memcpy(a, new->attrs, rta_size(new->attrs));
a->aflags = 0;
- a->eattrs = attrs;
a->hostentry = NULL;
e = rte_get_temp(a);
e->pflags = 0;
@@ -93,7 +92,7 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
}
static int
-pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED)
+pipe_import_control(struct proto *P, rte **ee, struct linpool *p UNUSED)
{
struct proto *pp = (*ee)->sender->proto;
@@ -275,6 +274,7 @@ pipe_show_proto_info(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/radv.c b/proto/radv/radv.c
index 8a79dfaf..ce88c7cc 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -395,7 +395,7 @@ radv_net_match_trigger(struct radv_config *cf, net *n)
}
int
-radv_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
+radv_import_control(struct proto *P, rte **new, struct linpool *pool UNUSED)
{
// struct radv_proto *p = (struct radv_proto *) P;
struct radv_config *cf = (struct radv_config *) (P->cf);
@@ -410,7 +410,7 @@ radv_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct l
}
static void
-radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs)
+radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED)
{
struct radv_proto *p = (struct radv_proto *) P;
struct radv_config *cf = (struct radv_config *) (P->cf);
@@ -448,11 +448,11 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
{
/* Update */
- ea = ea_find(attrs, EA_RA_PREFERENCE);
+ ea = ea_find(new->attrs->eattrs, EA_RA_PREFERENCE);
uint preference = ea ? ea->u.data : RA_PREF_MEDIUM;
uint preference_set = !!ea;
- ea = ea_find(attrs, EA_RA_LIFETIME);
+ ea = ea_find(new->attrs->eattrs, EA_RA_LIFETIME);
uint lifetime = ea ? ea->u.data : 0;
uint lifetime_set = !!ea;
@@ -762,7 +762,7 @@ radv_get_attr(eattr *a, byte *buf, int buflen UNUSED)
struct protocol proto_radv = {
.name = "RAdv",
.template = "radv%d",
- .attr_class = EAP_RADV,
+ .class = PROTOCOL_RADV,
.channel_mask = NB_IP6,
.proto_size = sizeof(struct radv_proto),
.config_size = sizeof(struct radv_config),
diff --git a/proto/radv/radv.h b/proto/radv/radv.h
index 66f785a7..719948d5 100644
--- a/proto/radv/radv.h
+++ b/proto/radv/radv.h
@@ -192,8 +192,8 @@ struct radv_iface
#define RA_PREF_MASK 0x18
/* Attributes */
-#define EA_RA_PREFERENCE EA_CODE(EAP_RADV, 0)
-#define EA_RA_LIFETIME EA_CODE(EAP_RADV, 1)
+#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
diff --git a/proto/rip/config.Y b/proto/rip/config.Y
index aff63f03..c46cf00c 100644
--- a/proto/rip/config.Y
+++ b/proto/rip/config.Y
@@ -186,8 +186,8 @@ rip_iface:
rip_iface_start iface_patt_list_nopx rip_iface_opt_list rip_iface_finish;
-CF_ADDTO(dynamic_attr, RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_RIP_METRIC); })
-CF_ADDTO(dynamic_attr, RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_RIP_TAG); })
+CF_ADDTO(dynamic_attr, RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RIP_METRIC); })
+CF_ADDTO(dynamic_attr, RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RIP_TAG); })
CF_CLI_HELP(SHOW RIP, ..., [[Show information about RIP protocol]]);
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index baf98737..90bf8e5c 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -298,7 +298,7 @@ rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from)
*/
static void
rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, struct rte *new,
- struct rte *old UNUSED, struct ea_list *attrs)
+ struct rte *old UNUSED)
{
struct rip_proto *p = (struct rip_proto *) P;
struct rip_entry *en;
@@ -307,8 +307,8 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
if (new)
{
/* Update */
- u32 rt_metric = ea_get_int(attrs, EA_RIP_METRIC, 1);
- u32 rt_tag = ea_get_int(attrs, EA_RIP_TAG, 0);
+ u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1);
+ u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0);
if (rt_metric > p->infinity)
{
@@ -1040,10 +1040,10 @@ rip_make_tmp_attrs(struct rte *rt, struct linpool *pool)
}
static void
-rip_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
+rip_store_tmp_attrs(struct rte *rt)
{
- rt->u.rip.metric = ea_get_int(attrs, EA_RIP_METRIC, 1);
- rt->u.rip.tag = ea_get_int(attrs, EA_RIP_TAG, 0);
+ rt->u.rip.metric = ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, 1);
+ rt->u.rip.tag = ea_get_int(rt->attrs->eattrs, EA_RIP_TAG, 0);
}
static int
@@ -1081,7 +1081,6 @@ rip_init(struct proto_config *CF)
P->if_notify = rip_if_notify;
P->rt_notify = rip_rt_notify;
P->neigh_notify = rip_neigh_notify;
- // P->import_control = rip_import_control;
P->reload_routes = rip_reload_routes;
P->make_tmp_attrs = rip_make_tmp_attrs;
P->store_tmp_attrs = rip_store_tmp_attrs;
@@ -1145,7 +1144,7 @@ rip_reconfigure(struct proto *P, struct proto_config *CF)
}
static void
-rip_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
+rip_get_route_info(rte *rte, byte *buf)
{
buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric);
@@ -1274,7 +1273,7 @@ rip_dump(struct proto *P)
struct protocol proto_rip = {
.name = "RIP",
.template = "rip%d",
- .attr_class = EAP_RIP,
+ .class = PROTOCOL_RIP,
.preference = DEF_PREF_RIP,
.channel_mask = NB_IP,
.proto_size = sizeof(struct rip_proto),
diff --git a/proto/rip/rip.h b/proto/rip/rip.h
index 55696333..2dc34862 100644
--- a/proto/rip/rip.h
+++ b/proto/rip/rip.h
@@ -182,8 +182,8 @@ 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(EAP_RIP, 0)
-#define EA_RIP_TAG EA_CODE(EAP_RIP, 1)
+#define EA_RIP_METRIC EA_CODE(PROTOCOL_RIP, 0)
+#define EA_RIP_TAG EA_CODE(PROTOCOL_RIP, 1)
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 74860071..36097dc5 100644
--- a/proto/rpki/rpki.c
+++ b/proto/rpki/rpki.c
@@ -913,6 +913,7 @@ 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 ede4c734..8dfa6f35 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -656,6 +656,7 @@ 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),
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index e56dd616..8522e415 100644
--- a/sysdep/bsd/krt-sock.c
+++ b/sysdep/bsd/krt-sock.c
@@ -347,8 +347,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
}
void
-krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old,
- struct ea_list *eattrs UNUSED)
+krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
{
int err = 0;
diff --git a/sysdep/linux/krt-sys.h b/sysdep/linux/krt-sys.h
index 76ae29b7..2b8cdaa7 100644
--- a/sysdep/linux/krt-sys.h
+++ b/sysdep/linux/krt-sys.h
@@ -34,9 +34,9 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return N
#define KRT_ALLOW_MERGE_PATHS 1
-#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0x10)
-#define EA_KRT_REALM EA_CODE(EAP_KRT, 0x11)
-#define EA_KRT_SCOPE EA_CODE(EAP_KRT, 0x12)
+#define EA_KRT_PREFSRC EA_CODE(PROTOCOL_KERNEL, 0x10)
+#define EA_KRT_REALM EA_CODE(PROTOCOL_KERNEL, 0x11)
+#define EA_KRT_SCOPE EA_CODE(PROTOCOL_KERNEL, 0x12)
#define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */
@@ -48,22 +48,22 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return N
* Following attributes are parts of RTA_METRICS kernel route attribute, their
* ids must be consistent with their RTAX_* constants (+ KRT_METRICS_OFFSET)
*/
-#define EA_KRT_METRICS EA_CODE(EAP_KRT, 0x20) /* Dummy one */
-#define EA_KRT_LOCK EA_CODE(EAP_KRT, 0x21)
-#define EA_KRT_MTU EA_CODE(EAP_KRT, 0x22)
-#define EA_KRT_WINDOW EA_CODE(EAP_KRT, 0x23)
-#define EA_KRT_RTT EA_CODE(EAP_KRT, 0x24)
-#define EA_KRT_RTTVAR EA_CODE(EAP_KRT, 0x25)
-#define EA_KRT_SSTRESH EA_CODE(EAP_KRT, 0x26)
-#define EA_KRT_CWND EA_CODE(EAP_KRT, 0x27)
-#define EA_KRT_ADVMSS EA_CODE(EAP_KRT, 0x28)
-#define EA_KRT_REORDERING EA_CODE(EAP_KRT, 0x29)
-#define EA_KRT_HOPLIMIT EA_CODE(EAP_KRT, 0x2a)
-#define EA_KRT_INITCWND EA_CODE(EAP_KRT, 0x2b)
-#define EA_KRT_FEATURES EA_CODE(EAP_KRT, 0x2c)
-#define EA_KRT_RTO_MIN EA_CODE(EAP_KRT, 0x2d)
-#define EA_KRT_INITRWND EA_CODE(EAP_KRT, 0x2e)
-#define EA_KRT_QUICKACK EA_CODE(EAP_KRT, 0x2f)
+#define EA_KRT_METRICS EA_CODE(PROTOCOL_KERNEL, 0x20) /* Dummy one */
+#define EA_KRT_LOCK EA_CODE(PROTOCOL_KERNEL, 0x21)
+#define EA_KRT_MTU EA_CODE(PROTOCOL_KERNEL, 0x22)
+#define EA_KRT_WINDOW EA_CODE(PROTOCOL_KERNEL, 0x23)
+#define EA_KRT_RTT EA_CODE(PROTOCOL_KERNEL, 0x24)
+#define EA_KRT_RTTVAR EA_CODE(PROTOCOL_KERNEL, 0x25)
+#define EA_KRT_SSTRESH EA_CODE(PROTOCOL_KERNEL, 0x26)
+#define EA_KRT_CWND EA_CODE(PROTOCOL_KERNEL, 0x27)
+#define EA_KRT_ADVMSS EA_CODE(PROTOCOL_KERNEL, 0x28)
+#define EA_KRT_REORDERING EA_CODE(PROTOCOL_KERNEL, 0x29)
+#define EA_KRT_HOPLIMIT EA_CODE(PROTOCOL_KERNEL, 0x2a)
+#define EA_KRT_INITCWND EA_CODE(PROTOCOL_KERNEL, 0x2b)
+#define EA_KRT_FEATURES EA_CODE(PROTOCOL_KERNEL, 0x2c)
+#define EA_KRT_RTO_MIN EA_CODE(PROTOCOL_KERNEL, 0x2d)
+#define EA_KRT_INITRWND EA_CODE(PROTOCOL_KERNEL, 0x2e)
+#define EA_KRT_QUICKACK EA_CODE(PROTOCOL_KERNEL, 0x2f)
/* Bits of EA_KRT_LOCK, also based on RTAX_* constants */
#define EA_KRT_LOCK_MTU EA_KRT_LOCK | EA_BIT(0x2)
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 84591eb2..73f77147 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -1177,11 +1177,12 @@ nh_bufsize(struct nexthop *nh)
}
static int
-nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int dest, struct nexthop *nh)
+nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
{
eattr *ea;
net *net = e->net;
rta *a = e->attrs;
+ ea_list *eattrs = a->eattrs;
int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh));
u32 priority = 0;
@@ -1328,7 +1329,7 @@ dest:
}
static inline int
-nl_add_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs)
+nl_add_rte(struct krt_proto *p, rte *e)
{
rta *a = e->attrs;
int err = 0;
@@ -1337,34 +1338,34 @@ nl_add_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs)
{
struct nexthop *nh = &(a->nh);
- err = nl_send_route(p, e, eattrs, NL_OP_ADD, RTD_UNICAST, nh);
+ err = nl_send_route(p, e, NL_OP_ADD, RTD_UNICAST, nh);
if (err < 0)
return err;
for (nh = nh->next; nh; nh = nh->next)
- err += nl_send_route(p, e, eattrs, NL_OP_APPEND, RTD_UNICAST, nh);
+ err += nl_send_route(p, e, NL_OP_APPEND, RTD_UNICAST, nh);
return err;
}
- return nl_send_route(p, e, eattrs, NL_OP_ADD, a->dest, &(a->nh));
+ return nl_send_route(p, e, NL_OP_ADD, a->dest, &(a->nh));
}
static inline int
-nl_delete_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs)
+nl_delete_rte(struct krt_proto *p, rte *e)
{
int err = 0;
/* For IPv6, we just repeatedly request DELETE until we get error */
do
- err = nl_send_route(p, e, eattrs, NL_OP_DELETE, RTD_NONE, NULL);
+ err = nl_send_route(p, e, NL_OP_DELETE, RTD_NONE, NULL);
while (krt_ecmp6(p) && !err);
return err;
}
void
-krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs)
+krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
{
int err = 0;
@@ -1380,10 +1381,10 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list
*/
if (old)
- nl_delete_rte(p, old, eattrs);
+ nl_delete_rte(p, old);
if (new)
- err = nl_add_rte(p, new, eattrs);
+ err = nl_add_rte(p, new);
if (err < 0)
n->n.flags |= KRF_SYNC_ERROR;
@@ -1751,7 +1752,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
for (t = 1; t < KRT_METRICS_MAX; t++)
if (metrics[0] & (1 << t))
{
- ea->attrs[n].id = EA_CODE(EAP_KRT, KRT_METRICS_OFFSET + t);
+ ea->attrs[n].id = EA_CODE(PROTOCOL_KERNEL, KRT_METRICS_OFFSET + t);
ea->attrs[n].flags = 0;
ea->attrs[n].type = EAF_TYPE_INT; /* FIXME: Some are EAF_TYPE_BITFIELD */
ea->attrs[n].u.data = metrics[t];
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index 9aac8668..98740b70 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -122,8 +122,8 @@ kif_iface:
kif_iface_start iface_patt_list_nopx kif_iface_opt_list;
-CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_SOURCE); })
-CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_METRIC); })
+CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SOURCE); })
+CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_METRIC); })
CF_CODE
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index b4fb1967..a79df54e 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -232,6 +232,7 @@ kif_copy_config(struct proto_config *dest, struct proto_config *src)
struct protocol proto_unix_iface = {
.name = "Device",
.template = "device%d",
+ .class = PROTOCOL_DEVICE,
.proto_size = sizeof(struct kif_proto),
.config_size = sizeof(struct kif_config),
.preconfig = kif_preconfig,
@@ -550,7 +551,7 @@ krt_flush_routes(struct krt_proto *p)
if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED))
{
/* FIXME: this does not work if gw is changed in export filter */
- krt_replace_rte(p, e->net, NULL, e, NULL);
+ krt_replace_rte(p, e->net, NULL, e);
n->n.flags &= ~KRF_INSTALLED;
}
}
@@ -558,14 +559,14 @@ krt_flush_routes(struct krt_proto *p)
}
static struct rte *
-krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
+krt_export_net(struct krt_proto *p, net *net, rte **rt_free)
{
struct channel *c = p->p.main_channel;
struct filter *filter = c->out_filter;
rte *rt;
if (c->ra_mode == RA_MERGED)
- return rt_export_merged(c, net, rt_free, tmpa, krt_filter_lp, 1);
+ return rt_export_merged(c, net, rt_free, krt_filter_lp, 1);
rt = net->routes;
*rt_free = NULL;
@@ -576,15 +577,14 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
if (filter == FILTER_REJECT)
return NULL;
- struct proto *src = rt->attrs->src->proto;
- *tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(rt, krt_filter_lp) : NULL;
+ rte_make_tmp_attrs(&rt, krt_filter_lp);
/* We could run krt_import_control() here, but it is already handled by KRF_INSTALLED */
if (filter == FILTER_ACCEPT)
goto accept;
- if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR | FF_SILENT) > F_ACCEPT)
+ if (f_run(filter, &rt, krt_filter_lp, FF_SILENT) > F_ACCEPT)
goto reject;
@@ -666,9 +666,8 @@ krt_got_route(struct krt_proto *p, rte *e)
if (net->n.flags & KRF_INSTALLED)
{
rte *new, *rt_free;
- ea_list *tmpa;
- new = krt_export_net(p, net, &rt_free, &tmpa);
+ new = krt_export_net(p, net, &rt_free);
/* TODO: There also may be changes in route eattrs, we ignore that for now. */
@@ -713,7 +712,6 @@ krt_prune(struct krt_proto *p)
{
int verdict = n->n.flags & KRF_VERDICT_MASK;
rte *new, *old, *rt_free = NULL;
- ea_list *tmpa = NULL;
if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
{
@@ -727,12 +725,10 @@ krt_prune(struct krt_proto *p)
if (verdict == KRF_CREATE || verdict == KRF_UPDATE)
{
/* We have to run export filter to get proper 'new' route */
- new = krt_export_net(p, n, &rt_free, &tmpa);
+ new = krt_export_net(p, n, &rt_free);
if (!new)
verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE;
- else
- tmpa = ea_append(tmpa, new->attrs->eattrs);
}
else
new = NULL;
@@ -743,7 +739,7 @@ krt_prune(struct krt_proto *p)
if (new && (n->n.flags & KRF_INSTALLED))
{
krt_trace_in(p, new, "reinstalling");
- krt_replace_rte(p, n, new, NULL, tmpa);
+ krt_replace_rte(p, n, new, NULL);
}
break;
case KRF_SEEN:
@@ -752,11 +748,11 @@ krt_prune(struct krt_proto *p)
break;
case KRF_UPDATE:
krt_trace_in(p, new, "updating");
- krt_replace_rte(p, n, new, old, tmpa);
+ krt_replace_rte(p, n, new, old);
break;
case KRF_DELETE:
krt_trace_in(p, old, "deleting");
- krt_replace_rte(p, n, NULL, old, NULL);
+ krt_replace_rte(p, n, NULL, old);
break;
default:
bug("krt_prune: invalid route status");
@@ -794,7 +790,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new)
if (new)
{
krt_trace_in(p, e, "[redirect] deleting");
- krt_replace_rte(p, net, NULL, e, NULL);
+ krt_replace_rte(p, net, NULL, e);
}
/* If !new, it is probably echo of our deletion */
break;
@@ -936,14 +932,14 @@ krt_make_tmp_attrs(rte *rt, struct linpool *pool)
}
static void
-krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
+krt_store_tmp_attrs(rte *rt)
{
/* EA_KRT_SOURCE is read-only */
- rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0);
+ rt->u.krt.metric = ea_get_int(rt->attrs->eattrs, EA_KRT_METRIC, 0);
}
static int
-krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
+krt_import_control(struct proto *P, rte **new, struct linpool *pool UNUSED)
{
// struct krt_proto *p = (struct krt_proto *) P;
rte *e = *new;
@@ -974,7 +970,7 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li
static void
krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net,
- rte *new, rte *old, struct ea_list *eattrs)
+ rte *new, rte *old)
{
struct krt_proto *p = (struct krt_proto *) P;
@@ -987,7 +983,7 @@ krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net,
else
net->n.flags &= ~KRF_INSTALLED;
if (p->initialized) /* Before first scan we don't touch the routes */
- krt_replace_rte(p, net, new, old, eattrs);
+ krt_replace_rte(p, net, new, old);
}
static void
@@ -1235,7 +1231,7 @@ krt_get_attr(eattr *a, byte *buf, int buflen)
struct protocol proto_unix_kernel = {
.name = "Kernel",
.template = "kernel%d",
- .attr_class = EAP_KRT,
+ .class = PROTOCOL_KERNEL,
.preference = DEF_PREF_INHERITED,
.channel_mask = NB_IP | MAYBE_IP6_SADR | MAYBE_MPLS,
.proto_size = sizeof(struct krt_proto),
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index b627882d..6ace2a86 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -30,8 +30,8 @@ struct kif_proto;
#define KRT_DEFAULT_ECMP_LIMIT 16
-#define EA_KRT_SOURCE EA_CODE(EAP_KRT, 0)
-#define EA_KRT_METRIC EA_CODE(EAP_KRT, 1)
+#define EA_KRT_SOURCE EA_CODE(PROTOCOL_KERNEL, 0)
+#define EA_KRT_METRIC EA_CODE(PROTOCOL_KERNEL, 1)
/* Whenever we recognize our own routes, we allow learing of foreign routes */
@@ -139,7 +139,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *);
int krt_capable(rte *e);
void krt_do_scan(struct krt_proto *);
-void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs);
+void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old);
int krt_sys_get_attr(eattr *a, byte *buf, int buflen);
diff --git a/test/bt-utils.c b/test/bt-utils.c
index 571ef2fa..7653abf6 100644
--- a/test/bt-utils.c
+++ b/test/bt-utils.c
@@ -75,8 +75,8 @@ bt_bird_init(void)
void bt_bird_cleanup(void)
{
- for (int i = 0; i < EAP_MAX; i++)
- attr_class_to_protocol[i] = NULL;
+ for (int i = 0; i < PROTOCOL__MAX; i++)
+ class_to_protocol[i] = NULL;
config = new_config = NULL;
}