Commit 4c553c5a authored by Maria Matejka's avatar Maria Matejka

Filter refactoring: dropped the recursion from the interpreter

This is a major change of how the filters are interpreted. If everything
works how it should, it should not affect you unless you are hacking the
filters themselves.

Anyway, this change should make a huge improvement in the filter performance
as previous benchmarks showed that our major problem lies in the
recursion itself.

There are also some changes in nest and protocols, related mostly to
spreading const declarations throughout the whole BIRD and also to
refactored dynamic attribute definitions. The need of these came up
during the whole work and it is too difficult to split out these
not-so-related changes.
parent 967b88d9
......@@ -55,7 +55,6 @@ CF_DECLS
struct f_tree *e;
struct f_trie *trie;
struct f_val v;
struct f_path_mask *h;
struct password_item *p;
struct rt_show_data *ra;
struct sym_show_data *sd;
......@@ -124,14 +123,14 @@ conf: definition ;
definition:
DEFINE SYM '=' term ';' {
struct f_val *val = cfg_alloc(sizeof(struct f_val));
if (f_eval($4, cfg_mem, val) > F_RETURN) cf_error("Runtime error");
if (f_eval(f_postfixify($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
cf_define_symbol($2, SYM_CONSTANT | val->type, val);
}
;
expr:
NUM
| '(' term ')' { $$ = f_eval_int($2); }
| '(' term ')' { $$ = f_eval_int(f_postfixify($2)); }
| SYM {
if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number expected");
$$ = SYM_VAL($1).i; }
......
......@@ -3982,7 +3982,7 @@ definitions, prefix definitions and DNS definitions:
RAdv protocol could be configured to change its behavior based on
availability of routes. When this option is used, the protocol waits in
suppressed state until a <it/trigger route/ (for the specified network)
is exported to the protocol, the protocol also returnsd to suppressed
is exported to the protocol, the protocol also returns to suppressed
state if the <it/trigger route/ disappears. Note that route export
depends on specified export filter, as usual. This option could be used,
e.g., for handling failover in multihoming scenarios.
......
......@@ -5,10 +5,22 @@ $(cf-local)
M4FLAGS_FILTERS=$(filter-out -s,$(M4FLAGS))
$(o)f-inst-interpret.c: $(s)interpret.m4 $(s)f-inst.c
$(o)f-inst-line-size.c: $(s)line-size.m4 $(s)f-inst.c $(objdir)/.dir-stamp
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
$(o)filter.o: $(o)f-inst-interpret.c
$(o)f-inst-postfixify.c: $(s)postfixify.m4 $(s)f-inst.c $(objdir)/.dir-stamp
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
$(o)f-inst-interpret.c: $(s)interpret.m4 $(s)f-inst.c $(objdir)/.dir-stamp
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
$(o)f-inst-same.c: $(s)same.m4 $(s)f-inst.c $(objdir)/.dir-stamp
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
$(o)f-inst-dump.c: $(s)dump.m4 $(s)f-inst.c $(objdir)/.dir-stamp
$(M4) $(M4FLAGS_FILTERS) -P $^ >$@
$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-line-size.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c
tests_src := tree_test.c filter_test.c trie_test.c
tests_targets := $(tests_targets) $(tests-target-files)
......
This diff is collapsed.
m4_divert(-1)m4_dnl
#
# BIRD -- Dumping instruction lines
#
# (c) 2018 Maria Matejka <mq@jmq.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
# Common aliases
m4_define(DNL, `m4_dnl')
m4_define(INST, `m4_divert(1)break; case $1:
m4_divert(-1)'))
m4_define(LINE, `m4_divert(1)f_dump_line(item->lines[$2], indent + 1);
m4_divert(-1)')
m4_define(LINEP, `LINE($@)')
m4_define(SYMBOL, `m4_divert(1)debug("%ssymbol %s\n", INDENT, item->sym->name);
m4_divert(-1)')
m4_define(VALI, `m4_divert(1)debug("%svalue %s\n", INDENT, val_dump(item->vp));
m4_divert(-1)')
m4_define(VALI, `m4_divert(1)debug("%svalue %s\n", INDENT, val_dump(item->vp));
m4_divert(-1)')
m4_define(FRET, `m4_divert(1)debug("%sfilter return value %d\n", INDENT, item->fret);
m4_divert(-1)')
m4_define(ECS, `m4_divert(1)debug("%sec subtype %d\n", INDENT, item->ecs);
m4_divert(-1)')
m4_define(RTC, `m4_divert(1)debug("%sroute table %s\n", INDENT, item->rtc->name);
m4_divert(-1)')
m4_define(STATIC_ATTR, `m4_divert(1)debug("%sstatic attribute %u/%u/%u\n", INDENT, item->sa.f_type, item->sa.sa_code, item->sa.readonly);
m4_divert(-1)')
m4_define(DYNAMIC_ATTR, `m4_divert(1)debug("%sdynamic attribute %u/%u/%u/%u\n", INDENT, item->da.type, item->da.bit, item->da.f_type, item->da.ea_code);
m4_divert(-1)')
m4_define(DUMP, `m4_divert(1)$1m4_divert(-1)')
m4_m4wrap(`
m4_divert(0)DNL
case FI_NOP: bug("This shall not happen");
m4_undivert(1)
break; default: bug( "Unknown instruction %d (%c)", item->fi_code, item->fi_code & 0xff);
')
m4_changequote([[,]])
This diff is collapsed.
......@@ -30,8 +30,7 @@ struct f_inst *
f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da)
{
struct f_inst *ret = f_new_inst(fi_code);
ret->aux = (da.f_type << 8) | da.type;
ret->a[1].i = da.ea_code;
ret->da = da;
return ret;
}
......@@ -39,9 +38,7 @@ struct f_inst *
f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa)
{
struct f_inst *ret = f_new_inst(fi_code);
ret->aux = sa.f_type;
ret->a[1].i = sa.sa_code;
ret->a[0].i = sa.readonly;
ret->sa = sa;
return ret;
}
......@@ -49,13 +46,12 @@ f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa)
* Generate set_dynamic( operation( get_dynamic(), argument ) )
*/
struct f_inst *
f_generate_complex(int operation, int operation_aux, struct f_dynamic_attr da, struct f_inst *argument)
f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument)
{
struct f_inst *set_dyn = f_new_inst_da(FI_EA_SET, da),
*oper = f_new_inst(operation),
*oper = f_new_inst(fi_code),
*get_dyn = f_new_inst_da(FI_EA_GET, da);
oper->aux = operation_aux;
oper->a[0].p = get_dyn;
oper->a[1].p = argument;
......@@ -63,21 +59,6 @@ f_generate_complex(int operation, int operation_aux, struct f_dynamic_attr da, s
return set_dyn;
}
struct f_inst *
f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn)
{
struct f_inst *ret = f_new_inst(FI_ROA_CHECK);
ret->arg1 = prefix;
ret->arg2 = asn;
/* prefix == NULL <-> asn == NULL */
if (table->addr_type != NET_ROA4 && table->addr_type != NET_ROA6)
cf_error("%s is not a ROA table", table->name);
ret->arg3 = table;
return ret;
}
static const char * const f_instruction_name_str[] = {
#define F(c,a,b) \
[c] = #c,
......@@ -219,7 +200,7 @@ ca_lookup(pool *p, const char *name, int f_type)
}
cas = mb_allocz(&root_pool, sizeof(struct ca_storage) + strlen(name) + 1);
cas->fda = f_new_dynamic_attr(ea_type, f_type, EA_CUSTOM(id));
cas->fda = f_new_dynamic_attr(ea_type, 0, f_type, EA_CUSTOM(id));
cas->uc = 1;
strcpy(cas->name, name);
......
This diff is collapsed.
This diff is collapsed.
......@@ -40,8 +40,7 @@ parse_config_file(const void *filename_void)
static int
run_function(const void *parsed_fn_def)
{
/* XXX: const -> non-const */
struct f_inst *f = (struct f_inst *) parsed_fn_def;
const struct f_line *f = (const struct f_line *) parsed_fn_def;
linpool *tmp = lp_new_default(&root_pool);
struct f_val res;
......@@ -52,7 +51,7 @@ run_function(const void *parsed_fn_def)
}
static void
bt_assert_filter(int result, struct f_inst *assert)
bt_assert_filter(int result, const struct f_line_item *assert)
{
int bt_suit_case_result = 1;
if (!result)
......@@ -62,7 +61,7 @@ bt_assert_filter(int result, struct f_inst *assert)
bt_suit_case_result = 0;
}
bt_log_suite_case_result(bt_suit_case_result, "Assertion at line %d (%s)", assert->lineno, (char *) assert->a[1].p);
bt_log_suite_case_result(bt_suit_case_result, "Assertion at line %d (%s)", assert->lineno, assert->s);
}
int
......
......@@ -10,7 +10,60 @@ m4_divert(-1)m4_dnl
# Common aliases
m4_define(DNL, `m4_dnl')
m4_define(INST, `break; case $1:')
m4_define(INST, `break; case $1:
m4_ifelse(eval($2 > 0), `if (vstk.cnt < $2) runtime("Stack underflow");', `')
vstk.cnt -= $2;
')
m4_define(ARG, `if (v$1.type != $2) runtime("Argument $1 of instruction %s must be of type $2, got 0x%02x", f_instruction_name(what->fi_code), v$1.type)')
m4_define(RESULT_OK, `vstk.cnt++')
m4_define(RESULT, `RESULT_VAL([[ (struct f_val) { .type = $1, .val.$2 = $3 } ]])')
m4_define(RESULT_VAL, `do { res = $1; RESULT_OK; } while (0)')
m4_define(LINEX, `do {
estk.item[estk.cnt].pos = 0;
estk.item[estk.cnt].line = $1;
estk.item[estk.cnt].ventry = vstk.cnt;
estk.item[estk.cnt].emask = 0;
estk.cnt++;
} while (0)')
m4_define(LINE, `do {
if (what->lines[$2]) {
estk.item[estk.cnt].pos = 0;
estk.item[estk.cnt].line = what->lines[$2];
estk.item[estk.cnt].ventry = vstk.cnt;
estk.item[estk.cnt].emask = 0;
estk.cnt++;
}
} while (0)')
m4_define(LINEP, LINE($1, $2))
m4_define(ARG_ANY, `')
m4_define(SYMBOL, `const struct symbol *sym = what->sym')
m4_define(VALI, `res = *what->vp')
m4_define(VALP, `res = *what->vp')
m4_define(FRET, `enum filter_return fret = what->fret')
m4_define(ECS, `enum ec_subtype ecs = what->ecs')
m4_define(RTC, `struct rtable *table = what->rtc->table')
m4_define(STATIC_ATTR, `struct f_static_attr sa = what->sa')
m4_define(DYNAMIC_ATTR, `struct f_dynamic_attr da = what->da')
m4_define(POSTFIXIFY, `')
m4_define(LINE_SIZE, `')
m4_define(SAME, `')
m4_define(COUNT, `')
m4_m4wrap(`
m4_divert(0)DNL
case FI_NOP: bug("This shall not happen");
m4_undivert(1)
break; default: bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff);
')
m4_divert(1)
m4_changequote([[,]])
m4_divert(0)
m4_divert(-1)m4_dnl
#
# BIRD -- Line size counting
#
# (c) 2018 Maria Matejka <mq@jmq.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
# Common aliases
m4_define(DNL, `m4_dnl')
m4_define(INST, `m4_divert(1)break; case $1: cnt += 1;
m4_divert(-1)')
m4_define(ARG, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p);
m4_divert(-1)')
m4_define(ARG_T, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p);
m4_divert(-1)')
m4_define(ARG_ANY, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p);
m4_divert(-1)')
m4_define(LINE_SIZE, `m4_divert(1)$1m4_divert(-1)')
m4_m4wrap(`
m4_divert(0)DNL
case FI_NOP: bug("This shall not happen");
m4_undivert(1)
break; default: bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff);
')
m4_changequote([[,]])
m4_divert(-1)m4_dnl
#
# BIRD -- Converting instructions trees to instruction lines
#
# (c) 2018 Maria Matejka <mq@jmq.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
# Common aliases
m4_define(DNL, `m4_dnl')
m4_define(POSTFIXIFY_TRAILER, `dest->items[pos].fi_code = what->fi_code;
dest->items[pos].lineno = what->lineno;')
m4_define(INST, `m4_divert(1)POSTFIXIFY_TRAILER
break; case $1:
m4_divert(-1)'))
m4_define(ARG, `m4_divert(1)pos = postfixify(dest, what->a[$1-1].p, pos);
m4_divert(-1)')
m4_define(ARG_ANY, `m4_divert(1)pos = postfixify(dest, what->a[$1-1].p, pos);
m4_divert(-1)')
m4_define(LINE, `m4_divert(1)dest->items[pos].lines[$2] = f_postfixify(what->a[$1-1].p);
m4_divert(-1)')
m4_define(LINEP, `m4_divert(1)dest->items[pos].lines[$2] = what->a[$1-1].p;
m4_divert(-1)')
m4_define(SYMBOL, `m4_divert(1)dest->items[pos].sym = what->a[$1-1].p;
m4_divert(-1)')
m4_define(VALI, `m4_divert(1)dest->items[pos].vp = &(what->val);
m4_divert(-1)')
m4_define(VALP, `m4_divert(1)dest->items[pos].vp = (dest->items[pos].sym = what->a[$1-1].p)->def;
m4_divert(-1)')
m4_define(FRET, `m4_divert(1)dest->items[pos].fret = what->a[$1-1].i;
m4_divert(-1)')
m4_define(ECS, `m4_divert(1)dest->items[pos].ecs = what->aux;
m4_divert(-1)')
m4_define(RTC, `m4_divert(1)dest->items[pos].rtc = what->a[$1-1].rtc;
m4_divert(-1)')
m4_define(STATIC_ATTR, `m4_divert(1)dest->items[pos].sa = what->sa;
m4_divert(-1)')
m4_define(DYNAMIC_ATTR, `m4_divert(1)dest->items[pos].da = what->da;
m4_divert(-1)')
m4_define(COUNT, `m4_divert(1)dest->items[pos].count = what->a[$1-1].i;
m4_divert(-1)')
m4_define(POSTFIXIFY, `m4_divert(1)$1m4_divert(-1)')
m4_m4wrap(`
m4_divert(0)DNL
case FI_NOP: bug("This shall not happen");
m4_undivert(1)
POSTFIXIFY_TRAILER
break; default: bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff);
')
m4_changequote([[,]])
m4_divert(-1)m4_dnl
#
# BIRD -- Filter Comparator Generator
#
# (c) 2018 Maria Matejka <mq@jmq.cz>
#
# Can be freely distributed and used under the terms of the GNU GPL.
#
# Common aliases
m4_define(DNL, `m4_dnl')
m4_define(INST, `m4_divert(1)break; case $1:
m4_divert(-1)')
m4_define(ARG, `')
m4_define(ARG_ANY, `')
m4_define(LINE, `m4_divert(1)if (!f_same(f1->lines[$2], f2->lines[$2])) return 0;
m4_divert(-1)')
m4_define(LINEP, LINE)
m4_define(SYMBOL, `m4_divert(1){
const struct symbol *s1 = f1->sym, *s2 = f2->sym;
if (strcmp(s1->name, s2->name)) return 0;
if (s1->class != s2->class) return 0;
}
m4_divert(-1)')
m4_define(VALI, `m4_divert(1)if (!val_same(f1->vp, f2->vp)) return 0;
m4_divert(-1)')
m4_define(VALP, `')
m4_define(FRET, `m4_divert(1)if (f1->fret != f2->fret) return 0;
m4_divert(-1)')
m4_define(ECS, `m4_divert(1)if (f1->ecs != f2->ecs) return 0;
m4_divert(-1)')
m4_define(RTC, `m4_divert(1)if (strcmp(f1->rtc->name, f2->rtc->name)) return 0;
m4_divert(-1)')
m4_define(STATIC_ATTR, `m4_divert(1)if (f1->sa.sa_code != f2->sa.sa_code) return 0;
m4_divert(-1)')
m4_define(DYNAMIC_ATTR, `m4_divert(1)if (f1->da.ea_code != f2->da.ea_code) return 0;
m4_divert(-1)')
m4_define(SAME, `m4_divert(1)$1m4_divert(-1)')
m4_m4wrap(`
m4_divert(0)DNL
case FI_NOP: bug("This shall not happen");
m4_undivert(1)
break; default: bug( "Unknown instruction %d (%c)", f1->fi_code, f1->fi_code & 0xff);
')
m4_divert(1)
m4_changequote([[,]])
......@@ -23,15 +23,15 @@
* Both set matching and |switch() { }| construction is implemented using this function,
* thus both are as fast as they can be.
*/
struct f_tree *
find_tree(struct f_tree *t, struct f_val val)
const struct f_tree *
find_tree(const struct f_tree *t, const struct f_val *val)
{
if (!t)
return NULL;
if ((val_compare(t->from, val) != 1) &&
(val_compare(t->to, val) != -1))
if ((val_compare(&(t->from), val) != 1) &&
(val_compare(&(t->to), val) != -1))
return t;
if (val_compare(t->from, val) == -1)
if (val_compare(&(t->from), val) == -1)
return find_tree(t->right, val);
else
return find_tree(t->left, val);
......@@ -56,7 +56,7 @@ build_tree_rec(struct f_tree **buf, int l, int h)
static int
tree_compare(const void *p1, const void *p2)
{
return val_compare((* (struct f_tree **) p1)->from, (* (struct f_tree **) p2)->from);
return val_compare(&((* (struct f_tree **) p1)->from), &((* (struct f_tree **) p2)->from));
}
/**
......@@ -119,39 +119,39 @@ f_new_tree(void)
* Compares two trees and returns 1 if they are same
*/
int
same_tree(struct f_tree *t1, struct f_tree *t2)
same_tree(const struct f_tree *t1, const struct f_tree *t2)
{
if ((!!t1) != (!!t2))
return 0;
if (!t1)
return 1;
if (val_compare(t1->from, t2->from))
if (val_compare(&(t1->from), &(t2->from)))
return 0;
if (val_compare(t1->to, t2->to))
if (val_compare(&(t1->to), &(t2->to)))
return 0;
if (!same_tree(t1->left, t2->left))
return 0;
if (!same_tree(t1->right, t2->right))
return 0;
if (!i_same(t1->data, t2->data))
if (!f_same(t1->data, t2->data))
return 0;
return 1;
}
static void
tree_node_format(struct f_tree *t, buffer *buf)
tree_node_format(const struct f_tree *t, buffer *buf)
{
if (t == NULL)
return;
tree_node_format(t->left, buf);
val_format(t->from, buf);
if (val_compare(t->from, t->to) != 0)
val_format(&(t->from), buf);
if (val_compare(&(t->from), &(t->to)) != 0)
{
buffer_puts(buf, "..");
val_format(t->to, buf);
val_format(&(t->to), buf);
}
buffer_puts(buf, ", ");
......@@ -159,7 +159,7 @@ tree_node_format(struct f_tree *t, buffer *buf)
}
void
tree_format(struct f_tree *t, buffer *buf)
tree_format(const struct f_tree *t, buffer *buf)
{
buffer_puts(buf, "[");
......
......@@ -226,8 +226,8 @@ t_find(void)
};
for(looking_up_value.val.i = 0; looking_up_value.val.i < nodes_count; looking_up_value.val.i++)
{
struct f_tree *found_tree = find_tree(tree, looking_up_value);
bt_assert((val_compare(looking_up_value, found_tree->from) == 0) && (val_compare(looking_up_value, found_tree->to) == 0));
const struct f_tree *found_tree = find_tree(tree, &looking_up_value);
bt_assert((val_compare(&looking_up_value, &(found_tree->from)) == 0) && (val_compare(&looking_up_value, &(found_tree->to)) == 0));
}
}
......@@ -278,11 +278,11 @@ t_find_ranges(void)
for(*i = 0; *i <= max_value; *i += (uint)bt_random()/nodes_count)
{
struct f_tree *found_tree = find_tree(tree, needle);
const struct f_tree *found_tree = find_tree(tree, &needle);
bt_debug("searching: %u \n", *i);
bt_assert(
(val_compare(needle, found_tree->from) == 0) || (val_compare(needle, found_tree->to) == 0) ||
((val_compare(needle, found_tree->from) == 1) && (val_compare(needle, found_tree->to) == -1))
(val_compare(&needle, &(found_tree->from)) == 0) || (val_compare(&needle, &(found_tree->to)) == 0) ||
((val_compare(&needle, &(found_tree->from)) == 1) && (val_compare(&needle, &(found_tree->to)) == -1))
);
}
}
......
......@@ -220,7 +220,7 @@ trie_add_prefix(struct f_trie *t, const net_addr *net, uint l, uint h)
}
static int
trie_match_prefix(struct f_trie *t, ip_addr px, uint plen)
trie_match_prefix(const struct f_trie *t, ip_addr px, uint plen)
{
ip_addr pmask = ipa_mkmask(plen);
ip_addr paddr = ipa_and(px, pmask);
......@@ -229,7 +229,7 @@ trie_match_prefix(struct f_trie *t, ip_addr px, uint plen)
return t->zero;
int plentest = plen - 1;
struct f_trie_node *n = t->root;
const struct f_trie_node *n = t->root;
while(n)
{
......@@ -264,7 +264,7 @@ trie_match_prefix(struct f_trie *t, ip_addr px, uint plen)
* is such prefix pattern in the trie.
*/
int
trie_match_net(struct f_trie *t, const net_addr *n)
trie_match_net(const struct f_trie *t, const net_addr *n)
{
uint add = 0;
......@@ -279,7 +279,7 @@ trie_match_net(struct f_trie *t, const net_addr *n)
}
static int
trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2)
trie_node_same(const struct f_trie_node *t1, const struct f_trie_node *t2)
{
if ((t1 == NULL) && (t2 == NULL))
return 1;
......@@ -303,13 +303,13 @@ trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2)
* Compares two tries and returns 1 if they are same
*/
int
trie_same(struct f_trie *t1, struct f_trie *t2)
trie_same(const struct f_trie *t1, const struct f_trie *t2)
{
return (t1->zero == t2->zero) && trie_node_same(t1->root, t2->root);
}
static void
trie_node_format(struct f_trie_node *t, buffer *buf)
trie_node_format(const struct f_trie_node *t, buffer *buf)
{
if (t == NULL)
return;
......@@ -329,7 +329,7 @@ trie_node_format(struct f_trie_node *t, buffer *buf)
* Prints the trie to the supplied buffer.
*/
void
trie_format(struct f_trie *t, buffer *buf)
trie_format(const struct f_trie *t, buffer *buf)
{
buffer_puts(buf, "[");
......
......@@ -354,12 +354,12 @@ mpls_put(char *buf, int len, u32 *stack)
* Unaligned data access (in network order)
*/
static inline ip4_addr get_ip4(void *buf)
static inline ip4_addr get_ip4(const void *buf)
{
return _MI4(get_u32(buf));
}
static inline ip6_addr get_ip6(void *buf)
static inline ip6_addr get_ip6(const void *buf)
{
ip6_addr a;
memcpy(&a, buf, 16);
......
......@@ -77,10 +77,10 @@ bad:
}
int
as_path_16to32(byte *dst, byte *src, uint len)
as_path_16to32(byte *dst, const byte *src, uint len)
{
byte *dst0 = dst;
byte *end = src + len;
const byte *end = src + len;
uint i, n;
while (src < end)
......@@ -101,10 +101,10 @@ as_path_16to32(byte *dst, byte *src, uint len)
}
int
as_path_32to16(byte *dst, byte *src, uint len)
as_path_32to16(byte *dst, const byte *src, uint len)
{
byte *dst0 = dst;
byte *end = src + len;
const byte *end = src + len;
uint i, n;
while (src < end)
......@@ -273,11 +273,11 @@ as_path_to_old(struct linpool *pool, const struct adata *path)
* AS_CONFED_* segments have zero length and must be added if they are on edge.
* In contrast to other as_path_* functions, @path is modified in place.
*/
void
as_path_cut(struct adata *path, uint num)
struct adata *
as_path_cut(struct linpool *pool, const struct adata *path, uint num)
{
byte *pos = path->data;
byte *end = pos + path->length;
const byte *pos = path->data;
const byte *end = pos + path->length;
while (pos < end)
{
......@@ -297,28 +297,39 @@ as_path_cut(struct adata *path, uint num)
/* Cannot add whole segment, so try partial one and finish */
if (num < n)
{
const byte *nend = pos;
if (num)
nend += 2 + BS * num;
struct adata *res = lp_alloc_adata(pool, path->length);
res->length = nend - (const byte *) path->data;
memcpy(res->data, path->data, res->length);
if (num)
{
pos[1] = num;
pos += 2 + BS * num;
byte *dpos = ((byte *) res->data) + (pos - (const byte *) path->data);
dpos[1] = num;
}
break;
return res;
}
num -= n;
pos += 2 + BS * l;
}
path->length = pos - path->data;
struct adata *res = lp_alloc_adata(pool, path->length);
res->length = path->length;
memcpy(res->data, path->data, res->length);
return res;
}
/*
* Merge (concatenate) paths @p1 and @p2 and return the result.
* In contrast to other as_path_* functions, @p1 and @p2 may be reused.
*/
struct adata *
as_path_merge(struct linpool *pool, struct adata *p1, struct adata *p2)
const struct adata *
as_path_merge(struct linpool *pool, const struct adata *p1, const struct adata *p2)
{
if (p1->length == 0)
return p2;
......@@ -561,7 +572,7 @@ as_path_contains(const struct adata *path, u32 as, int min)
}
int
as_path_match_set(const struct adata *path, struct f_tree *set)
as_path_match_set(const struct adata *path, const struct f_tree *set)
{
const u8 *p = path->data;
const u8 *q = p+path->length;
......@@ -574,7 +585,7 @@ as_path_match_set(const struct adata *path, struct f_tree *set)
for (i=0; i<n; i++)
{
struct f_val v = {T_INT, .val.i = get_as(p)};
if (find_tree(set, v))
if (find_tree(set, &v))
return 1;
p += BS;
}
......@@ -583,8 +594,8 @@ as_path_match_set(const struct adata *path, struct f_tree *set)
return 0;
}
struct adata *
as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos)
const struct adata *
as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int pos)
{
if (!path)
return NULL;
......@@ -612,7 +623,10 @@ as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32
int match;
if (set)
match = !!find_tree(set, (struct f_val){T_INT, .val.i = as});
{
struct f_val v = {T_INT, .val.i = as};
match = !!find_tree(set, &v);
}
else
match = (as == key);
......@@ -771,7 +785,7 @@ pm_mark(struct pm_pos *pos, int i, int plen, int *nl, int *nh)
* is marked.
*/
int
as_path_match(const struct adata *path, struct f_path_mask *mask)
as_path_match(const struct adata *path, const struct f_path_mask *mask)
{
struct pm_pos pos[2048 + 1];