mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Trie optimizer
This patch optimizes prefix sets like [ 10.0.0.0/24, 10.0.1.0/24, 10.0.2.0/24, 10.0.3.0/24 ] into [ 10.0.0.0/22{24,24} ] This should improve config loading speed with large config files. Works only in config-check mode; the appropriate flag is -O. Beware. The output is written directly on stdout. This patch is not intended to be ever merged with mainline in this form. Instead, we should fix bad lexer performance and also merge the merge-able prefixes on-the-fly during trie creation. Ultimately, we should have better possibility to feed database-like structures into BIRD instead of config file.
This commit is contained in:
parent
abec20083a
commit
dae0ea9b0e
@ -727,7 +727,13 @@ constant:
|
||||
| fprefix_s {NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); $$->a1.p = val; *val = $1; }
|
||||
| RTRID { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_QUAD; $$->a2.i = $1; }
|
||||
| '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(FI_CONSTANT); $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
|
||||
| '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_PREFIX_SET; $$->a2.p = $2; }
|
||||
| '[' fprefix_set ']' {
|
||||
$$ = f_new_inst(FI_CONSTANT);
|
||||
$$->aux = T_PREFIX_SET;
|
||||
$$->a2.p = $2;
|
||||
if (trie_optimize_flag)
|
||||
trie_optimize($$);
|
||||
}
|
||||
| ENUM { $$ = f_new_inst(FI_CONSTANT); $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
|
||||
;
|
||||
|
||||
|
@ -298,6 +298,8 @@ struct f_trie
|
||||
struct f_trie_node root[0]; /* Root trie node follows */
|
||||
};
|
||||
|
||||
void trie_optimize(struct f_inst *);
|
||||
|
||||
#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 */
|
||||
|
@ -70,10 +70,14 @@
|
||||
*/
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "lib/resource.h"
|
||||
#include "lib/string.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* f_new_trie - allocates and returns a new empty trie
|
||||
* @lp: linear pool to allocate items from
|
||||
@ -181,6 +185,10 @@ trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h)
|
||||
return n;
|
||||
}
|
||||
|
||||
/* All additional prefixes are already covered by this node. */
|
||||
if (ipa_equal(ipa_and(n->accept, amask), amask))
|
||||
return n;
|
||||
|
||||
/* Update accept mask part M2 and go deeper */
|
||||
n->accept = ipa_or(n->accept, ipa_and(amask, n->mask));
|
||||
|
||||
@ -258,6 +266,77 @@ trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2)
|
||||
return trie_node_same(t1->c[0], t2->c[0]) && trie_node_same(t1->c[1], t2->c[1]);
|
||||
}
|
||||
|
||||
static int
|
||||
trie_node_optimize(struct f_trie_node *t)
|
||||
{
|
||||
int ret = 0;
|
||||
if (t->c[0]) ret |= trie_node_optimize(t->c[0]);
|
||||
if (t->c[1]) ret |= trie_node_optimize(t->c[1]);
|
||||
|
||||
if ((!t->c[0]) || (!t->c[1])) return ret;
|
||||
|
||||
if (t->c[0]->plen != t->plen + 1) return ret;
|
||||
if (t->c[1]->plen != t->plen + 1) return ret;
|
||||
|
||||
ip_addr cmask = ipa_and(t->c[0]->accept, t->c[1]->accept);
|
||||
if (ipa_zero(cmask)) return ret;
|
||||
|
||||
ip_addr lmask = ipa_xor(t->c[0]->accept, cmask);
|
||||
ip_addr rmask = ipa_xor(t->c[1]->accept, cmask);
|
||||
|
||||
if (!ipa_zero(lmask) && !ipa_zero(rmask))
|
||||
return ret;
|
||||
|
||||
t->c[0]->accept = lmask;
|
||||
t->c[1]->accept = rmask;
|
||||
|
||||
t->accept = ipa_or(t->accept, cmask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
trie_node_count(struct f_trie_node *t)
|
||||
{
|
||||
int ret = 0;
|
||||
if (t->c[0]) ret += trie_node_count(t->c[0]);
|
||||
if (t->c[1]) ret += trie_node_count(t->c[1]);
|
||||
|
||||
for (
|
||||
ip_addr amask = t->accept;
|
||||
ipa_nonzero(amask);
|
||||
ret++,
|
||||
amask = ipa_xor(amask, ipa_bitrange(amask, NULL, NULL))
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
trie_optimize(struct f_inst *what)
|
||||
{
|
||||
struct f_trie *t = what->a2.p;
|
||||
if (!t || !t->root)
|
||||
return;
|
||||
|
||||
if (!trie_node_optimize(t->root))
|
||||
return;
|
||||
|
||||
int size = trie_node_count(t->root) * (STD_ADDRESS_P_LENGTH + 11);
|
||||
char *buf = xmalloc(size);
|
||||
buffer b = {
|
||||
.start = buf,
|
||||
.pos = buf,
|
||||
.end = buf + size
|
||||
};
|
||||
|
||||
printf("Prefix set in file %s at line %d: ", ifs->file_name, ifs->lino);
|
||||
|
||||
trie_format(t, &b);
|
||||
buffer_puts(&b, "\n");
|
||||
fputs(b.start, stdout);
|
||||
xfree(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* trie_same
|
||||
* @t1: first trie to be compared
|
||||
|
@ -619,12 +619,13 @@ signal_init(void)
|
||||
* Parsing of command-line arguments
|
||||
*/
|
||||
|
||||
static char *opt_list = "c:dD:ps:P:u:g:flRh";
|
||||
static char *opt_list = "c:dD:pOs:P:u:g:flRh";
|
||||
static int parse_and_exit;
|
||||
char *bird_name;
|
||||
static char *use_user;
|
||||
static char *use_group;
|
||||
static int run_in_foreground = 0;
|
||||
int trie_optimize_flag = 0;
|
||||
|
||||
static void
|
||||
display_usage(void)
|
||||
@ -649,6 +650,7 @@ display_help(void)
|
||||
" -h, --help Display this information\n"
|
||||
" -l Look for a configuration file and a communication socket\n"
|
||||
" file in the current working directory\n"
|
||||
" -O Optimize prefix sets; implies -p\n"
|
||||
" -p Test configuration file and exit without start\n"
|
||||
" -P <pid-file> Create a PID file with given filename\n"
|
||||
" -R Apply graceful restart recovery after start\n"
|
||||
@ -758,6 +760,10 @@ parse_args(int argc, char **argv)
|
||||
case 'p':
|
||||
parse_and_exit = 1;
|
||||
break;
|
||||
case 'O':
|
||||
parse_and_exit = 1;
|
||||
trie_optimize_flag = 1;
|
||||
break;
|
||||
case 's':
|
||||
path_control_socket = optarg;
|
||||
socket_changed = 1;
|
||||
|
@ -18,6 +18,7 @@ struct birdsock;
|
||||
/* main.c */
|
||||
|
||||
extern char *bird_name;
|
||||
extern int trie_optimize_flag;
|
||||
void async_config(void);
|
||||
void async_dump(void);
|
||||
void async_shutdown(void);
|
||||
|
Loading…
Reference in New Issue
Block a user