summaryrefslogtreecommitdiff
path: root/conf
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-10-04 15:40:52 +0200
committerMaria Matejka <mq@ucw.cz>2022-10-04 15:40:52 +0200
commitbecca314e2546d6005a23398ce2d3012d4b396cb (patch)
treebdd2f55e81d42e6a1108593840c9273106676e09 /conf
parent61c127c021ac34eba25d3245ccf8f9eb9dd352f5 (diff)
parent0072d11f3431165240656edf6ade473554b8747e (diff)
Merge commit '0072d11f' into tmp-learn
Diffstat (limited to 'conf')
-rw-r--r--conf/cf-lex.l56
-rw-r--r--conf/conf.c1
-rw-r--r--conf/conf.h11
-rw-r--r--conf/confbase.Y16
-rw-r--r--conf/flowspec.Y2
5 files changed, 78 insertions, 8 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 11bcdb18..04e0b3a5 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -577,6 +577,8 @@ check_eof(void)
return 0;
}
+static inline void cf_swap_soft_scope(void);
+
static struct symbol *
cf_new_symbol(const byte *c)
{
@@ -586,6 +588,8 @@ cf_new_symbol(const byte *c)
if (l > SYM_MAX_LEN)
cf_error("Symbol too long");
+ cf_swap_soft_scope();
+
s = cfg_allocz(sizeof(struct symbol) + l + 1);
*s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
strcpy(s->name, c);
@@ -676,8 +680,8 @@ cf_localize_symbol(struct symbol *sym)
return sym;
/* If the scope is the current, it is already defined in this scope. */
- if (sym->scope == conf_this_scope)
- cf_error("Symbol already defined");
+ if (cf_symbol_is_local(sym))
+ cf_error("Symbol '%s' already defined", sym->name);
/* Not allocated here yet, doing it now. */
return cf_new_symbol(sym->name);
@@ -839,6 +843,8 @@ cf_push_scope(struct symbol *sym)
void
cf_pop_scope(void)
{
+ ASSERT(!conf_this_scope->soft_scopes);
+
conf_this_scope->active = 0;
conf_this_scope = conf_this_scope->next;
@@ -846,6 +852,52 @@ cf_pop_scope(void)
}
/**
+ * cf_push_soft_scope - enter new soft scope
+ *
+ * If we want to enter a new anonymous scope that most likely will not contain
+ * any symbols, we can use cf_push_soft_scope() insteas of cf_push_scope().
+ * Such scope will be converted to a regular scope on first use.
+ */
+void
+cf_push_soft_scope(void)
+{
+ if (conf_this_scope->soft_scopes < 0xfe)
+ conf_this_scope->soft_scopes++;
+ else
+ cf_push_scope(NULL);
+}
+
+/**
+ * cf_pop_soft_scope - leave a soft scope
+ *
+ * Leave a soft scope entered by cf_push_soft_scope().
+ */
+void
+cf_pop_soft_scope(void)
+{
+ if (conf_this_scope->soft_scopes)
+ conf_this_scope->soft_scopes--;
+ else
+ cf_pop_scope();
+}
+
+/**
+ * cf_swap_soft_scope - convert soft scope to regular scope
+ *
+ * Soft scopes cannot hold symbols, so they must be converted to regular scopes
+ * on first use. It is done automatically by cf_new_symbol().
+ */
+static inline void
+cf_swap_soft_scope(void)
+{
+ if (conf_this_scope->soft_scopes)
+ {
+ conf_this_scope->soft_scopes--;
+ cf_push_scope(NULL);
+ }
+}
+
+/**
* cf_symbol_class_name - get name of a symbol class
* @sym: symbol
*
diff --git a/conf/conf.c b/conf/conf.c
index 580a6472..17424402 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -140,6 +140,7 @@ config_parse(struct config *c)
protos_preconfig(c);
rt_preconfig(c);
cf_parse();
+ rt_postconfig(c);
if (EMPTY_LIST(c->protos))
cf_error("No protocol is specified in the config file");
diff --git a/conf/conf.h b/conf/conf.h
index 4ccaa54e..50e01bf5 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -44,7 +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 */
+ int table_debug; /* Track route propagation through tables */
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) */
@@ -136,7 +136,8 @@ struct sym_scope {
HASH(struct symbol) hash; /* Local symbol hash */
uint slots; /* Variable slots */
- int active; /* Currently entered */
+ byte active; /* Currently entered */
+ byte soft_scopes; /* Number of soft scopes above */
};
extern struct sym_scope *global_root_scope;
@@ -202,6 +203,9 @@ struct symbol *cf_get_symbol(const byte *c);
struct symbol *cf_default_name(char *template, int *counter);
struct symbol *cf_localize_symbol(struct symbol *sym);
+static inline int cf_symbol_is_local(struct symbol *sym)
+{ return (sym->scope == conf_this_scope) && !conf_this_scope->soft_scopes; }
+
/**
* cf_define_symbol - define meaning of a symbol
* @sym: symbol to be defined
@@ -225,6 +229,9 @@ struct symbol *cf_localize_symbol(struct symbol *sym);
void cf_push_scope(struct symbol *);
void cf_pop_scope(void);
+void cf_push_soft_scope(void);
+void cf_pop_soft_scope(void);
+
char *cf_symbol_class_name(struct symbol *sym);
/* Parser */
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 58890cd6..241c332d 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -76,6 +76,7 @@ CF_DECLS
struct f_attr_bit fab;
struct f_lval flv;
struct f_line *fl;
+ struct f_arg *fa;
const struct filter *f;
struct f_tree *e;
struct f_trie *trie;
@@ -111,7 +112,7 @@ CF_DECLS
%type <i> expr bool pxlen4
%type <time> expr_us time
%type <a> ipa
-%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_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 <ad> label_stack_start label_stack
@@ -154,14 +155,14 @@ conf: definition ;
definition:
DEFINE symbol '=' term ';' {
struct f_val val;
- if (f_eval(f_linearize($4), &val) > F_RETURN) cf_error("Runtime error");
+ 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)); }
+ | '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); }
| symbol_known {
if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
$$ = SYM_VAL($1).i; }
@@ -307,6 +308,15 @@ net_:
/* Networks - regular */
+net_ip4:
+ net_ip4_
+ | CF_SYM_KNOWN {
+ if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP4))
+ cf_error("IPv4 network constant expected");
+ $$ = * SYM_VAL($1).net;
+ }
+ ;
+
net_ip6:
net_ip6_
| CF_SYM_KNOWN {
diff --git a/conf/flowspec.Y b/conf/flowspec.Y
index 56a7c5dc..dbdbdda5 100644
--- a/conf/flowspec.Y
+++ b/conf/flowspec.Y
@@ -142,7 +142,7 @@ flow_frag_opts:
;
flow4_item:
- flow_srcdst net_ip {
+ flow_srcdst net_ip4 {
flow_builder_set_type(this_flow, $1);
flow_builder4_add_pfx(this_flow, (net_addr_ip4 *) &($2));
}