0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Filter: Add enum types to filter grammar

Enum types existed on semantic level, but not on syntactic level,
so they could not be used in filter code.

Generate filter grammar for enum types based on CF_ENUM() declarations.

Thanks to lbz for the bugreport.
This commit is contained in:
Ondrej Zajicek 2024-10-18 16:39:42 +02:00
parent 072821e55e
commit 80ca0ed279
8 changed files with 37 additions and 11 deletions

View File

@ -680,7 +680,7 @@ cf_lex_symbol(const char *data)
int val = sym->keyword->value;
if (val > 0) return val;
cf_lval.i = -val;
return ENUM;
return ENUM_TOKEN;
}
case SYM_METHOD:
return (sym->method->arg_num > 1) ? CF_SYM_METHOD_ARGS : CF_SYM_METHOD_BARE;

View File

@ -105,7 +105,7 @@ CF_DECLS
%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
%token GEQ LEQ NEQ AND OR IMP
%token PO PC
%token <i> NUM ENUM
%token <i> NUM ENUM_TOKEN
%token <ip4> IP4
%token <ip6> IP6
%token <i64> VPN_RD

View File

@ -35,10 +35,11 @@ m4_define(CF_CLI, `CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
# Enums are translated to C initializers: use CF_ENUM(typename, prefix, values)
# For different prefix: CF_ENUM_PX(typename, external prefix, C prefix, values)
# The typename is converted to a keyword by removing T_ENUM_ prefix
m4_define(CF_enum, `m4_divert(1){ "CF_enum_prefix_ext[[]]$1", -((CF_enum_type<<16) | CF_enum_prefix_int[[]]$1) },
m4_divert(-1)')
m4_define(CF_ENUM, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$2)CF_iterate([[CF_enum]], [[m4_shift(m4_shift($@))]])DNL')
m4_define(CF_ENUM_PX, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$3)CF_iterate([[CF_enum]], [[m4_shift(m4_shift(m4_shift($@)))]])DNL')
m4_define(CF_ENUM, `CF_keywd(m4_substr($1, 7))m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$2)CF_iterate([[CF_enum]], [[m4_shift(m4_shift($@))]])DNL')
m4_define(CF_ENUM_PX, `CF_keywd(m4_substr($1, 7))m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$3)CF_iterate([[CF_enum]], [[m4_shift(m4_shift(m4_shift($@)))]])DNL')
# After all configuration templates end, we generate the
m4_m4wrap(`

View File

@ -52,8 +52,10 @@ m4_define(CF_CLI_OPT, `')
m4_define(CF_CLI_HELP, `')
# ENUM declarations are ignored
m4_define(CF_ENUM, `')
m4_define(CF_ENUM_PX, `')
m4_define(CF_token, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)%token<s> $1]])')
m4_define(CF_enum, `CF_append([[CF_enum_type]],[[$1 { $$ = $2; }]],[[ | ]])CF_token($1)')
m4_define(CF_ENUM, `CF_enum(m4_substr($1, 7), $1)')
m4_define(CF_ENUM_PX, `CF_enum(m4_substr($1, 7), $1)')
# After all configuration templates end, we finally generate the grammar file.
m4_m4wrap(`
@ -65,9 +67,11 @@ m4_undivert(1)DNL
m4_undivert(2)DNL
%type <s> KEYWORD
%type <i> enum_type
%%
KEYWORD: CF_kw_rule;
enum_type: CF_enum_type;
m4_undivert(3)DNL

View File

@ -357,7 +357,7 @@ CF_DECLS
CF_KEYWORDS_EXCLUSIVE(IN)
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ACCEPT, REJECT, ERROR,
INT, BOOL, IP, PREFIX, RD, PAIR, QUAD, EC, LC,
INT, BOOL, IP, PREFIX, RD, PAIR, QUAD, EC, LC, ENUM,
SET, STRING, BYTESTRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
IF, THEN, ELSE, CASE,
FOR, DO,
@ -473,6 +473,7 @@ type:
case T_INT:
case T_PAIR:
case T_QUAD:
case T_ENUM:
case T_EC:
case T_LC:
case T_RD:
@ -488,6 +489,7 @@ type:
cf_error( "You can't create sets of this type." );
}
}
| ENUM enum_type { $$ = $2; };
;
function_argsn:
@ -640,7 +642,7 @@ set_atom0:
NUM { $$.type = T_INT; $$.val.i = $1; }
| fipa { $$ = $1; }
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
| ENUM_TOKEN { $$.type = pair_a($1); $$.val.i = pair_b($1); }
| '(' term ')' {
$$ = cf_eval($2, T_VOID);
if (!f_valid_set_type($$.type))
@ -808,7 +810,7 @@ constant:
DBG( "ook\n" );
}
| '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PREFIX_SET, .val.ti = $2, }); }
| ENUM { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = $1 >> 16, .val.i = $1 & 0xffff, }); }
| ENUM_TOKEN { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = $1 >> 16, .val.i = $1 & 0xffff, }); }
;
constructor:

View File

@ -44,6 +44,7 @@ static const char * const f_type_str[] = {
[T_ENUM_NETTYPE] = "enum nettype",
[T_ENUM_RA_PREFERENCE] = "enum ra_preference",
[T_ENUM_AF] = "enum af",
[T_ENUM_MPLS_POLICY] = "enum mpls_policy",
[T_IP] = "ip",
[T_NET] = "prefix",

View File

@ -471,12 +471,31 @@ bt_test_suite(t_ip_set, "Testing sets of ip address");
function t_enum()
{
enum rts ev0 = RTS_STATIC;
enum rtd ev1 = RTD_UNICAST;
enum scope ev2 = SCOPE_UNIVERSE;
enum roa ev3 = ROA_VALID;
enum aspa ev4 = ASPA_VALID;
enum af ev5 = AF_IPV6;
enum nettype ev6 = NET_IP6;
enum bgp_origin ev7 = ORIGIN_IGP;
enum ra_preference ev8 = RA_PREF_LOW;
enum mpls_policy ev9 = MPLS_POLICY_STATIC;
enum nettype set es = [NET_IP6, NET_VPN6];
bt_assert(format(RTS_STATIC) = "(enum 30)1");
bt_assert(format(NET_IP4) = "(enum 36)1");
bt_assert(format(NET_VPN6) = "(enum 36)4");
bt_assert(format(ev6) = "(enum 36)2");
bt_assert(ev0 = RTS_STATIC);
bt_assert(ev6 = NET_IP6);
bt_assert(RTS_STATIC ~ [RTS_STATIC, RTS_DEVICE]);
bt_assert(RTS_BGP !~ [RTS_STATIC, RTS_DEVICE]);
bt_assert(NET_IP6 ~ es);
bt_assert(NET_IP4 !~ es);
}
bt_test_suite(t_enum, "Testing enums");

View File

@ -132,6 +132,7 @@ CF_KEYWORDS(ASPA_PROVIDERS)
/* For r_args_channel */
CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC, ASPA)
CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, IP6_SADR, MPLS, ASPA)
CF_ENUM(T_ENUM_RTS, RTS_, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL, RPKI, L3VPN,
AGGREGATED)
@ -211,8 +212,6 @@ net_type:
| MPLS { $$ = NET_MPLS; }
;
CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, IP6_SADR, MPLS, ASPA)
/* Creation of routing tables */