summaryrefslogtreecommitdiff
path: root/conf
diff options
context:
space:
mode:
Diffstat (limited to 'conf')
-rw-r--r--conf/cf-lex.l114
-rw-r--r--conf/conf.c5
-rw-r--r--conf/conf.h21
-rw-r--r--conf/confbase.Y36
-rw-r--r--conf/gen_keywords.m43
-rw-r--r--conf/gen_parser.m42
6 files changed, 123 insertions, 58 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index d6f46223..04e0b3a5 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -42,7 +42,7 @@
#define PARSER 1
#include "nest/bird.h"
-#include "nest/route.h"
+#include "nest/rt.h"
#include "nest/protocol.h"
#include "filter/filter.h"
#include "filter/f-inst.h"
@@ -77,19 +77,22 @@ static uint cf_hash(const byte *c);
#define SYM_NEXT(n) n->next
#define SYM_EQ(a,s1,b,s2) !strcmp(a,b) && s1 == s2
#define SYM_FN(k,s) cf_hash(k)
-#define SYM_ORDER 6 /* Initial */
+#define SYM_ORDER 4 /* Initial */
#define SYM_REHASH sym_rehash
-#define SYM_PARAMS /8, *1, 2, 2, 6, 20
+#define SYM_PARAMS /8, *1, 2, 2, 4, 20
HASH_DEFINE_REHASH_FN(SYM, struct symbol)
HASH(struct keyword) kw_hash;
-
+HASH(struct ea_class) ea_name_hash;
struct sym_scope *conf_this_scope;
+static struct sym_scope global_root_scope__init = { .active = 1, };
+struct sym_scope *global_root_scope = &global_root_scope__init;
+
linpool *cfg_mem;
int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
@@ -347,7 +350,7 @@ else: {
return DDOT;
}
-[={}:;,.()+*/%<>~\[\]?!\|-] {
+[={}:;,.()+*/%<>~\[\]?!\|&-] {
return yytext[0];
}
@@ -591,41 +594,58 @@ cf_new_symbol(const byte *c)
*s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
strcpy(s->name, c);
- if (!new_config->sym_hash.data)
- HASH_INIT(new_config->sym_hash, new_config->pool, SYM_ORDER);
+ if (!conf_this_scope->hash.data)
+ HASH_INIT(conf_this_scope->hash, new_config->pool, SYM_ORDER);
+
+ HASH_INSERT2(conf_this_scope->hash, SYM, new_config->pool, s);
+
+ if (conf_this_scope == new_config->root_scope)
+ add_tail(&(new_config->symbols), &(s->n));
+
+ return s;
+}
+
+static struct symbol *
+cf_root_symbol(const byte *c)
+{
+ uint l = strlen(c);
+ if (l > SYM_MAX_LEN)
+ bug("Root symbol %s too long", c);
- HASH_INSERT2(new_config->sym_hash, SYM, new_config->pool, s);
+ struct symbol *s = mb_alloc(&root_pool, sizeof(struct symbol) + l + 1);
+ *s = (struct symbol) { .scope = global_root_scope, .class = SYM_VOID, };
+ memcpy(s->name, c, l+1);
- add_tail(&(new_config->symbols), &(s->n));
+ if (!global_root_scope->hash.data)
+ HASH_INIT(global_root_scope->hash, &root_pool, SYM_ORDER);
+ HASH_INSERT2(global_root_scope->hash, SYM, &root_pool, s);
return s;
}
+
/**
- * cf_find_symbol - find a symbol by name
- * @cfg: specificed config
+ * cf_find_symbol_scope - find a symbol by name
+ * @scope: config scope
* @c: symbol name
*
- * This functions searches the symbol table in the config @cfg for a symbol of
- * given name. First it examines the current scope, then the second recent one
+ * This functions searches the symbol table in the scope @scope for a symbol of
+ * given name. First it examines the current scope, then the underlying one
* and so on until it either finds the symbol and returns a pointer to its
* &symbol structure or reaches the end of the scope chain and returns %NULL to
* signify no match.
*/
struct symbol *
-cf_find_symbol(const struct config *cfg, const byte *c)
+cf_find_symbol_scope(const struct sym_scope *scope, const byte *c)
{
struct symbol *s;
- if (cfg->sym_hash.data &&
- (s = HASH_FIND(cfg->sym_hash, SYM, c, 1)))
- return s;
-
- /* In CLI command parsing, fallback points to the current config, otherwise it is NULL. */
- if (cfg->fallback &&
- cfg->fallback->sym_hash.data &&
- (s = HASH_FIND(cfg->fallback->sym_hash, SYM, c, 1)))
- return s;
+ /* Find the symbol here or anywhere below */
+ while (scope)
+ if (scope->hash.data && (s = HASH_FIND(scope->hash, SYM, c, 1)))
+ return s;
+ else
+ scope = scope->next;
return NULL;
}
@@ -642,7 +662,7 @@ cf_find_symbol(const struct config *cfg, const byte *c)
struct symbol *
cf_get_symbol(const byte *c)
{
- return cf_find_symbol(new_config, c) ?: cf_new_symbol(c);
+ return cf_find_symbol_scope(conf_this_scope, c) ?: cf_new_symbol(c);
}
/**
@@ -693,10 +713,7 @@ cf_lex_symbol(const char *data)
struct symbol *sym = cf_get_symbol(data);
cf_lval.s = sym;
- if (sym->class != SYM_VOID)
- return CF_SYM_KNOWN;
-
- /* Is it a keyword? */
+ /* Is it a keyword? Prefer the keyword. */
struct keyword *k = HASH_FIND(kw_hash, KW, data);
if (k)
{
@@ -709,9 +726,11 @@ cf_lex_symbol(const char *data)
}
}
- /* OK, undefined symbol */
- cf_lval.s = sym;
- return CF_SYM_UNDEFINED;
+ /* OK, only a symbol. */
+ if (sym->class == SYM_VOID)
+ return CF_SYM_UNDEFINED;
+ else
+ return CF_SYM_KNOWN;
}
static void
@@ -724,6 +743,34 @@ cf_lex_init_kh(void)
HASH_INSERT(kw_hash, KW, k);
}
+void
+ea_lex_register(struct ea_class *def)
+{
+ struct symbol *sym = cf_root_symbol(def->name);
+ sym->class = SYM_ATTRIBUTE;
+ sym->attribute = def;
+ def->sym = sym;
+}
+
+void
+ea_lex_unregister(struct ea_class *def)
+{
+ struct symbol *sym = def->sym;
+ HASH_REMOVE2(global_root_scope->hash, SYM, &root_pool, sym);
+ mb_free(sym);
+ def->sym = NULL;
+}
+
+struct ea_class *
+ea_class_find_by_name(const char *name)
+{
+ struct symbol *sym = cf_find_symbol(global_root_scope, name);
+ if (!sym || (sym->class != SYM_ATTRIBUTE))
+ return NULL;
+ else
+ return sym->attribute;
+}
+
/**
* cf_lex_init - initialize the lexer
* @is_cli: true if we're going to parse CLI command, false for configuration
@@ -757,6 +804,11 @@ cf_lex_init(int is_cli, struct config *c)
c->root_scope = cfg_allocz(sizeof(struct sym_scope));
conf_this_scope = c->root_scope;
conf_this_scope->active = 1;
+
+ if (is_cli)
+ conf_this_scope->next = config->root_scope;
+ else
+ conf_this_scope->next = global_root_scope;
}
/**
diff --git a/conf/conf.c b/conf/conf.c
index 025c040e..17424402 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -46,7 +46,7 @@
#undef LOCAL_DEBUG
#include "nest/bird.h"
-#include "nest/route.h"
+#include "nest/rt.h"
#include "nest/protocol.h"
#include "nest/iface.h"
#include "lib/resource.h"
@@ -169,7 +169,6 @@ int
cli_parse(struct config *c)
{
int done = 0;
- c->fallback = config;
new_config = c;
cfg_mem = c->mem;
if (setjmp(conf_jmpbuf))
@@ -180,7 +179,6 @@ cli_parse(struct config *c)
done = 1;
cleanup:
- c->fallback = NULL;
new_config = NULL;
cfg_mem = NULL;
return done;
@@ -523,7 +521,6 @@ order_shutdown(int gr)
init_list(&c->tables);
init_list(&c->symbols);
memset(c->def_tables, 0, sizeof(c->def_tables));
- HASH_INIT(c->sym_hash, c->pool, 4);
c->shutdown = 1;
c->gr_down = gr;
diff --git a/conf/conf.h b/conf/conf.h
index e0f94b63..8b2e2dea 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -16,7 +16,6 @@
#include "lib/timer.h"
/* Configuration structure */
-
struct config {
pool *pool; /* Pool the configuration is stored in */
linpool *mem; /* Linear pool containing configuration data */
@@ -45,6 +44,7 @@ struct config {
int cli_debug; /* Tracing of CLI connections and commands */
int latency_debug; /* I/O loop tracks duration of each event */
+ int pipe_debug; /* Track route propagation through pipes */
u32 latency_limit; /* Events with longer duration are logged (us) */
u32 watchdog_warning; /* I/O loop watchdog limit for warning (us) */
u32 watchdog_timeout; /* Watchdog timeout (in seconds, 0 = disabled) */
@@ -54,8 +54,7 @@ struct config {
char *err_file_name; /* File name containing error */
char *file_name; /* Name of main configuration file */
int file_fd; /* File descriptor of main configuration file */
- HASH(struct symbol) sym_hash; /* Lexer: symbol hash table */
- struct config *fallback; /* Link to regular config for CLI parsing */
+
struct sym_scope *root_scope; /* Scope for root symbols */
int obstacle_count; /* Number of items blocking freeing of this config */
int shutdown; /* This is a pseudo-config for daemon shutdown */
@@ -122,7 +121,7 @@ struct symbol {
const struct f_line *function; /* For SYM_FUNCTION */
const struct filter *filter; /* For SYM_FILTER */
struct rtable_config *table; /* For SYM_TABLE */
- struct f_dynamic_attr *attribute; /* For SYM_ATTRIBUTE */
+ struct ea_class *attribute; /* For SYM_ATTRIBUTE */
struct f_val *val; /* For SYM_CONSTANT */
uint offset; /* For SYM_VARIABLE */
};
@@ -133,11 +132,16 @@ struct symbol {
struct sym_scope {
struct sym_scope *next; /* Next on scope stack */
struct symbol *name; /* Name of this scope */
+
+ HASH(struct symbol) hash; /* Local symbol hash */
+
uint slots; /* Variable slots */
byte active; /* Currently entered */
byte soft_scopes; /* Number of soft scopes above */
};
+extern struct sym_scope *global_root_scope;
+
struct bytestring {
size_t length;
byte data[];
@@ -186,7 +190,14 @@ int cf_lex(void);
void cf_lex_init(int is_cli, struct config *c);
void cf_lex_unwind(void);
-struct symbol *cf_find_symbol(const struct config *cfg, const byte *c);
+struct symbol *cf_find_symbol_scope(const struct sym_scope *scope, const byte *c);
+static inline struct symbol *cf_find_symbol_cfg(const struct config *cfg, const byte *c)
+{ return cf_find_symbol_scope(cfg->root_scope, c); }
+
+#define cf_find_symbol(where, what) _Generic(*(where), \
+ struct config: cf_find_symbol_cfg, \
+ struct sym_scope: cf_find_symbol_scope \
+ )((where), (what))
struct symbol *cf_get_symbol(const byte *c);
struct symbol *cf_default_name(char *template, int *counter);
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 1d5738ff..241c332d 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -18,7 +18,7 @@ CF_HDR
#include "lib/string.h"
#include "nest/protocol.h"
#include "nest/iface.h"
-#include "nest/route.h"
+#include "nest/rt.h"
#include "nest/bfd.h"
#include "nest/cli.h"
#include "filter/filter.h"
@@ -71,8 +71,9 @@ CF_DECLS
} xp;
enum filter_return fret;
enum ec_subtype ecs;
- struct f_dynamic_attr fda;
+ struct ea_class *ea_class;
struct f_static_attr fsa;
+ struct f_attr_bit fab;
struct f_lval flv;
struct f_line *fl;
struct f_arg *fa;
@@ -92,7 +93,7 @@ CF_DECLS
struct proto_spec ps;
struct channel_limit cl;
struct timeformat *tf;
- mpls_label_stack *mls;
+ struct adata *ad;
struct bytestring *bs;
}
@@ -113,14 +114,15 @@ CF_DECLS
%type <a> ipa
%type <net> net_ip4_ net_ip4 net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
-%type <mls> label_stack_start label_stack
+%type <ad> label_stack_start label_stack
%type <t> text opttext
-%type <s> symbol
+%type <s> symbol symbol_known toksym
%nonassoc PREFIX_DUMMY
%left AND OR
%nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC
+%left '|' '&'
%left '+' '-'
%left '*' '/' '%'
%left '!'
@@ -152,16 +154,16 @@ conf: definition ;
definition:
DEFINE symbol '=' term ';' {
- struct f_val *val = cfg_allocz(sizeof(struct f_val));
- if (f_eval(f_linearize($4, 1), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
- cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
+ struct f_val val;
+ if (f_eval(f_linearize($4, 1), &val) > F_RETURN) cf_error("Runtime error");
+ cf_define_symbol($2, SYM_CONSTANT | val.type, val, lp_val_copy(cfg_mem, &val));
}
;
expr:
NUM
| '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); }
- | CF_SYM_KNOWN {
+ | symbol_known {
if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
$$ = SYM_VAL($1).i; }
;
@@ -172,7 +174,9 @@ expr_us:
| expr US { $$ = $1 US_; }
;
-symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN ;
+toksym: FROM | PREFERENCE ;
+symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN | toksym ;
+symbol_known: CF_SYM_KNOWN | toksym ;
/* Switches */
@@ -357,17 +361,19 @@ net_or_ipa:
label_stack_start: NUM
{
- $$ = cfg_allocz(sizeof(mpls_label_stack));
- $$->len = 1;
- $$->stack[0] = $1;
+ $$ = cfg_allocz(ADATA_SIZE(MPLS_MAX_LABEL_STACK * sizeof(u32)));
+ $$->length = sizeof(u32);
+ *((u32 *)$$->data) = $1;
};
label_stack:
label_stack_start
| label_stack '/' NUM {
- if ($1->len >= MPLS_MAX_LABEL_STACK)
+ if ($1->length >= MPLS_MAX_LABEL_STACK * sizeof(u32))
cf_error("Too many labels in stack");
- $1->stack[$1->len++] = $3;
+
+ *((u32 *)($$->data + $1->length)) = $3;
+ $1->length += sizeof(u32);
$$ = $1;
}
;
diff --git a/conf/gen_keywords.m4 b/conf/gen_keywords.m4
index 0c1dc545..53226e4d 100644
--- a/conf/gen_keywords.m4
+++ b/conf/gen_keywords.m4
@@ -26,8 +26,7 @@ m4_define(CF_DEFINES, `m4_divert(-1)')
m4_define(CF_handle_kw, `m4_divert(1){ "m4_translit($1,[[A-Z]],[[a-z]])", $1, NULL },
m4_divert(-1)')
m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)CF_handle_kw($1)]])')
-m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks
-)DNL')
+m4_define(CF_KEYWORDS, `CF_iterate([[CF_keywd]], [[$@]])DNL')
# CLI commands generate keywords as well
m4_define(CF_CLI, `CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
diff --git a/conf/gen_parser.m4 b/conf/gen_parser.m4
index 5b378a93..af4b1455 100644
--- a/conf/gen_parser.m4
+++ b/conf/gen_parser.m4
@@ -31,7 +31,7 @@ m4_define(CF_iterate, `m4_define([[CF_iter]], m4_defn([[$1]]))CF_itera($2)')
# Keywords act as untyped %token
m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)m4_define([[CF_toks]],CF_toks $1)]])')
-m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks
+m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token<s>[[]]CF_toks
)DNL')
# CLI commands