mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-05 08:31:53 +00:00
Filters: First try (and first step) on simple method-like builtins
This commit is contained in:
parent
1267228568
commit
e830f3a6f3
@ -69,7 +69,7 @@ $(daemon): LIBS += $(DAEMON_LIBS)
|
|||||||
# Include directories
|
# Include directories
|
||||||
dirs := client conf doc filter lib nest test $(addprefix proto/,$(protocols)) @sysdep_dirs@
|
dirs := client conf doc filter lib nest test $(addprefix proto/,$(protocols)) @sysdep_dirs@
|
||||||
|
|
||||||
conf-y-targets := $(addprefix $(objdir)/conf/,cf-parse.y keywords.h commands.h)
|
conf-y-targets := $(addprefix $(objdir)/conf/,cf-parse.y keywords.h commands.h) $(objdir)/filter/methods.h
|
||||||
cf-local = $(conf-y-targets): $(s)config.Y
|
cf-local = $(conf-y-targets): $(s)config.Y
|
||||||
|
|
||||||
src-o-files = $(patsubst %.c,$(o)%.o,$(src))
|
src-o-files = $(patsubst %.c,$(o)%.o,$(src))
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
|
#include "filter/methods.h"
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
#include "conf/cf-parse.tab.h"
|
#include "conf/cf-parse.tab.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
@ -51,6 +51,7 @@ CF_DECLS
|
|||||||
struct f_inst *x;
|
struct f_inst *x;
|
||||||
struct f_dynamic_attr fda;
|
struct f_dynamic_attr fda;
|
||||||
struct f_static_attr fsa;
|
struct f_static_attr fsa;
|
||||||
|
enum f_method efm;
|
||||||
struct filter *f;
|
struct filter *f;
|
||||||
struct f_tree *e;
|
struct f_tree *e;
|
||||||
struct f_trie *trie;
|
struct f_trie *trie;
|
||||||
|
@ -39,6 +39,10 @@ m4_define(CF_dyn_rules,)
|
|||||||
m4_define(CF_ADDTO, `m4_define([[CF_rule_$1]],m4_ifdef([[CF_rule_$1]],CF_rule_$1 | ,[[m4_define([[CF_dyn_rules]],CF_dyn_rules[[CF_RULE($1)
|
m4_define(CF_ADDTO, `m4_define([[CF_rule_$1]],m4_ifdef([[CF_rule_$1]],CF_rule_$1 | ,[[m4_define([[CF_dyn_rules]],CF_dyn_rules[[CF_RULE($1)
|
||||||
]])]])$2)DNL')
|
]])]])$2)DNL')
|
||||||
|
|
||||||
|
# Simple filter object methods
|
||||||
|
m4_define(CF_OBJM, `m4_divert(2)CF_KEYWORDS($1)
|
||||||
|
m4_divert(3)f_object_method_simple: $1 { $$ = FM_$1; };')
|
||||||
|
|
||||||
# CLI commands
|
# CLI commands
|
||||||
m4_define(CF_CLI, `m4_define([[CF_cmd]], cmd_[[]]m4_translit($1, [[ ]], _))DNL
|
m4_define(CF_CLI, `m4_define([[CF_cmd]], cmd_[[]]m4_translit($1, [[ ]], _))DNL
|
||||||
m4_divert(2)CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
|
m4_divert(2)CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
|
||||||
|
@ -6,3 +6,11 @@ $(cf-local)
|
|||||||
tests_src := tree_test.c filter_test.c trie_test.c
|
tests_src := tree_test.c filter_test.c trie_test.c
|
||||||
tests_targets := $(tests_targets) $(tests-target-files)
|
tests_targets := $(tests_targets) $(tests-target-files)
|
||||||
tests_objs := $(tests_objs) $(src-o-files)
|
tests_objs := $(tests_objs) $(src-o-files)
|
||||||
|
|
||||||
|
$(conf-y-targets): $(s)methods.Y
|
||||||
|
|
||||||
|
$(o)methods.h: | $(s)gen_methods.m4
|
||||||
|
$(objdir)/conf/cf-parse.tab.o: $(o)methods.h
|
||||||
|
|
||||||
|
$(addprefix $(o), methods.h): $(objdir)/.dir-stamp
|
||||||
|
$(call clean, methods.h)
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
CF_HDR
|
CF_HDR
|
||||||
|
|
||||||
|
#include "filter/methods.h"
|
||||||
|
|
||||||
CF_DEFINES
|
CF_DEFINES
|
||||||
|
|
||||||
static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; }
|
static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; }
|
||||||
@ -413,7 +415,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
|||||||
IS_V4, IS_V6,
|
IS_V4, IS_V6,
|
||||||
LEN, MAXLEN,
|
LEN, MAXLEN,
|
||||||
DEFINED,
|
DEFINED,
|
||||||
ADD, DELETE, CONTAINS, RESET,
|
ADD, DELETE, CONTAINS,
|
||||||
PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
|
PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
|
||||||
EMPTY,
|
EMPTY,
|
||||||
FILTER, WHERE, EVAL,
|
FILTER, WHERE, EVAL,
|
||||||
@ -425,6 +427,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
|||||||
%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr
|
%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr
|
||||||
%type <fda> dynamic_attr
|
%type <fda> dynamic_attr
|
||||||
%type <fsa> static_attr
|
%type <fsa> static_attr
|
||||||
|
%type <efm> f_object_method_simple
|
||||||
%type <f> filter filter_body where_filter
|
%type <f> filter filter_body where_filter
|
||||||
%type <i> type break_command ec_kind
|
%type <i> type break_command ec_kind
|
||||||
%type <i32> cnum
|
%type <i32> cnum
|
||||||
@ -889,26 +892,9 @@ term:
|
|||||||
|
|
||||||
| rtadot dynamic_attr { $$ = f_new_inst_da(FI_EA_GET, $2); }
|
| rtadot dynamic_attr { $$ = f_new_inst_da(FI_EA_GET, $2); }
|
||||||
|
|
||||||
| term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4); $$->a1.p = $1; }
|
| term '.' f_object_method_simple { $$ = f_new_inst_method($1, $3); }
|
||||||
| term '.' TYPE { $$ = f_new_inst(FI_TYPE); $$->a1.p = $1; }
|
|
||||||
| term '.' IP { $$ = f_new_inst(FI_IP); $$->a1.p = $1; $$->aux = T_IP; }
|
|
||||||
| term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER); $$->a1.p = $1; $$->aux = T_RD; }
|
|
||||||
| term '.' LEN { $$ = f_new_inst(FI_LENGTH); $$->a1.p = $1; }
|
|
||||||
| term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN); $$->a1.p = $1; }
|
|
||||||
| term '.' ASN { $$ = f_new_inst(FI_ROA_ASN); $$->a1.p = $1; }
|
|
||||||
| term '.' SRC { $$ = f_new_inst(FI_SADR_SRC); $$->a1.p = $1; }
|
|
||||||
| term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK); $$->a1.p = $1; $$->a2.p = $5; }
|
|
||||||
| term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST); $$->a1.p = $1; }
|
|
||||||
| term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST); $$->a1.p = $1; }
|
|
||||||
| term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG); $$->a1.p = $1; }
|
|
||||||
|
|
||||||
/* Communities */
|
| term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK); $$->a1.p = $1; $$->a2.p = $5; }
|
||||||
/* This causes one shift/reduce conflict
|
|
||||||
| rtadot dynamic_attr '.' ADD '(' term ')' { }
|
|
||||||
| rtadot dynamic_attr '.' DELETE '(' term ')' { }
|
|
||||||
| rtadot dynamic_attr '.' CONTAINS '(' term ')' { }
|
|
||||||
| rtadot dynamic_attr '.' RESET{ }
|
|
||||||
*/
|
|
||||||
|
|
||||||
| '+' EMPTY '+' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_PATH; }
|
| '+' EMPTY '+' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_PATH; }
|
||||||
| '-' EMPTY '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_CLIST; }
|
| '-' EMPTY '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_CLIST; }
|
||||||
@ -924,8 +910,6 @@ term:
|
|||||||
|
|
||||||
| FORMAT '(' term ')' { $$ = f_new_inst(FI_FORMAT); $$->a1.p = $3; }
|
| FORMAT '(' term ')' { $$ = f_new_inst(FI_FORMAT); $$->a1.p = $3; }
|
||||||
|
|
||||||
/* | term '.' LEN { $$->code = P('P','l'); } */
|
|
||||||
|
|
||||||
/* function_call is inlined here */
|
/* function_call is inlined here */
|
||||||
| SYM '(' var_list ')' {
|
| SYM '(' var_list ')' {
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
@ -42,6 +42,16 @@ f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct f_inst *
|
||||||
|
f_new_inst_method(struct f_inst *target, enum f_method method)
|
||||||
|
{
|
||||||
|
struct f_inst *ret = f_new_inst(FI_METHOD);
|
||||||
|
ret->a1.p = target;
|
||||||
|
ret->a2.i = method;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate set_dynamic( operation( get_dynamic(), argument ) )
|
* Generate set_dynamic( operation( get_dynamic(), argument ) )
|
||||||
*/
|
*/
|
||||||
|
194
filter/filter.c
194
filter/filter.c
@ -840,23 +840,101 @@ interpret(struct f_inst *what)
|
|||||||
res.type = T_BOOL;
|
res.type = T_BOOL;
|
||||||
res.val.i = (v1.type != T_VOID) && !undef_value(v1);
|
res.val.i = (v1.type != T_VOID) && !undef_value(v1);
|
||||||
break;
|
break;
|
||||||
case FI_TYPE:
|
case FI_METHOD:
|
||||||
ARG_ANY(1); /* There may be more types supporting this operation */
|
switch (what->a2.i)
|
||||||
switch (v1.type)
|
|
||||||
{
|
{
|
||||||
case T_NET:
|
case FM_IS_V4:
|
||||||
|
ARG(1, T_IP);
|
||||||
|
res.type = T_BOOL;
|
||||||
|
res.val.i = ipa_is_ip4(v1.val.ip);
|
||||||
|
break;
|
||||||
|
case FM_TYPE:
|
||||||
|
ARG(1, T_NET);
|
||||||
res.type = T_ENUM_NETTYPE;
|
res.type = T_ENUM_NETTYPE;
|
||||||
res.val.i = v1.val.net->type;
|
res.val.i = v1.val.net->type;
|
||||||
break;
|
break;
|
||||||
default:
|
case FM_IP: /* Convert prefix to ... */
|
||||||
runtime( "Can't determine type of this item" );
|
ARG(1, T_NET);
|
||||||
|
res.type = T_IP;
|
||||||
|
res.val.ip = net_prefix(v1.val.net);
|
||||||
|
break;
|
||||||
|
case FM_RD:
|
||||||
|
ARG(1, T_NET);
|
||||||
|
if (!net_is_vpn(v1.val.net))
|
||||||
|
runtime( "VPN address expected" );
|
||||||
|
res.type = T_RD;
|
||||||
|
res.val.ec = net_rd(v1.val.net);
|
||||||
|
break;
|
||||||
|
case FM_LEN: /* Get length of */
|
||||||
|
ARG_ANY(1);
|
||||||
|
res.type = T_INT;
|
||||||
|
switch(v1.type) {
|
||||||
|
case T_NET: res.val.i = net_pxlen(v1.val.net); break;
|
||||||
|
case T_PATH: res.val.i = as_path_getlen(v1.val.ad); break;
|
||||||
|
case T_CLIST: res.val.i = int_set_get_size(v1.val.ad); break;
|
||||||
|
case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
|
||||||
|
case T_LCLIST: res.val.i = lc_set_get_size(v1.val.ad); break;
|
||||||
|
default: runtime( "Prefix, path, clist, eclist or lclist expected" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FM_MAXLEN: /* Get ROA max prefix length */
|
||||||
|
ARG(1, T_NET);
|
||||||
|
if (!net_is_roa(v1.val.net))
|
||||||
|
runtime( "ROA expected" );
|
||||||
|
|
||||||
|
res.type = T_INT;
|
||||||
|
res.val.i = (v1.val.net->type == NET_ROA4) ?
|
||||||
|
((net_addr_roa4 *) v1.val.net)->max_pxlen :
|
||||||
|
((net_addr_roa6 *) v1.val.net)->max_pxlen;
|
||||||
|
break;
|
||||||
|
case FM_ASN: /* Get ROA ASN */
|
||||||
|
ARG(1, T_NET);
|
||||||
|
if (!net_is_roa(v1.val.net))
|
||||||
|
runtime( "ROA expected" );
|
||||||
|
|
||||||
|
res.type = T_INT;
|
||||||
|
res.val.i = (v1.val.net->type == NET_ROA4) ?
|
||||||
|
((net_addr_roa4 *) v1.val.net)->asn :
|
||||||
|
((net_addr_roa6 *) v1.val.net)->asn;
|
||||||
|
break;
|
||||||
|
case FM_SRC: /* Get SADR src prefix */
|
||||||
|
ARG(1, T_NET);
|
||||||
|
if (!net_is_sadr(v1.val.net))
|
||||||
|
runtime( "SADR expected" );
|
||||||
|
|
||||||
|
{
|
||||||
|
net_addr_ip6_sadr *net = (void *) v1.val.net;
|
||||||
|
net_addr *src = lp_alloc(f_pool, sizeof(net_addr_ip6));
|
||||||
|
net_fill_ip6(src, net->src_prefix, net->src_pxlen);
|
||||||
|
|
||||||
|
res.type = T_NET;
|
||||||
|
res.val.net = src;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FM_FIRST: /* Get first ASN from AS PATH */
|
||||||
|
ARG(1, T_PATH);
|
||||||
|
|
||||||
|
as = 0;
|
||||||
|
as_path_get_first(v1.val.ad, &as);
|
||||||
|
res.type = T_INT;
|
||||||
|
res.val.i = as;
|
||||||
|
break;
|
||||||
|
case FM_LAST: /* Get last ASN from AS PATH */
|
||||||
|
ARG(1, T_PATH);
|
||||||
|
|
||||||
|
as = 0;
|
||||||
|
as_path_get_last(v1.val.ad, &as);
|
||||||
|
res.type = T_INT;
|
||||||
|
res.val.i = as;
|
||||||
|
break;
|
||||||
|
case FM_LAST_NONAGGREGATED: /* Get last ASN from non-aggregated part of AS PATH */
|
||||||
|
ARG(1, T_PATH);
|
||||||
|
|
||||||
|
res.type = T_INT;
|
||||||
|
res.val.i = as_path_get_last_nonaggregated(v1.val.ad);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FI_IS_V4:
|
|
||||||
ARG(1, T_IP);
|
|
||||||
res.type = T_BOOL;
|
|
||||||
res.val.i = ipa_is_ip4(v1.val.ip);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Set to indirect value, a1 = variable, a2 = value */
|
/* Set to indirect value, a1 = variable, a2 = value */
|
||||||
case FI_SET:
|
case FI_SET:
|
||||||
@ -1204,87 +1282,6 @@ interpret(struct f_inst *what)
|
|||||||
f_rte_cow();
|
f_rte_cow();
|
||||||
(*f_rte)->pref = v1.val.i;
|
(*f_rte)->pref = v1.val.i;
|
||||||
break;
|
break;
|
||||||
case FI_LENGTH: /* Get length of */
|
|
||||||
ARG_ANY(1);
|
|
||||||
res.type = T_INT;
|
|
||||||
switch(v1.type) {
|
|
||||||
case T_NET: res.val.i = net_pxlen(v1.val.net); break;
|
|
||||||
case T_PATH: res.val.i = as_path_getlen(v1.val.ad); break;
|
|
||||||
case T_CLIST: res.val.i = int_set_get_size(v1.val.ad); break;
|
|
||||||
case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
|
|
||||||
case T_LCLIST: res.val.i = lc_set_get_size(v1.val.ad); break;
|
|
||||||
default: runtime( "Prefix, path, clist or eclist expected" );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FI_SADR_SRC: /* Get SADR src prefix */
|
|
||||||
ARG(1, T_NET);
|
|
||||||
if (!net_is_sadr(v1.val.net))
|
|
||||||
runtime( "SADR expected" );
|
|
||||||
|
|
||||||
{
|
|
||||||
net_addr_ip6_sadr *net = (void *) v1.val.net;
|
|
||||||
net_addr *src = lp_alloc(f_pool, sizeof(net_addr_ip6));
|
|
||||||
net_fill_ip6(src, net->src_prefix, net->src_pxlen);
|
|
||||||
|
|
||||||
res.type = T_NET;
|
|
||||||
res.val.net = src;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FI_ROA_MAXLEN: /* Get ROA max prefix length */
|
|
||||||
ARG(1, T_NET);
|
|
||||||
if (!net_is_roa(v1.val.net))
|
|
||||||
runtime( "ROA expected" );
|
|
||||||
|
|
||||||
res.type = T_INT;
|
|
||||||
res.val.i = (v1.val.net->type == NET_ROA4) ?
|
|
||||||
((net_addr_roa4 *) v1.val.net)->max_pxlen :
|
|
||||||
((net_addr_roa6 *) v1.val.net)->max_pxlen;
|
|
||||||
break;
|
|
||||||
case FI_ROA_ASN: /* Get ROA ASN */
|
|
||||||
ARG(1, T_NET);
|
|
||||||
if (!net_is_roa(v1.val.net))
|
|
||||||
runtime( "ROA expected" );
|
|
||||||
|
|
||||||
res.type = T_INT;
|
|
||||||
res.val.i = (v1.val.net->type == NET_ROA4) ?
|
|
||||||
((net_addr_roa4 *) v1.val.net)->asn :
|
|
||||||
((net_addr_roa6 *) v1.val.net)->asn;
|
|
||||||
break;
|
|
||||||
case FI_IP: /* Convert prefix to ... */
|
|
||||||
ARG(1, T_NET);
|
|
||||||
res.type = T_IP;
|
|
||||||
res.val.ip = net_prefix(v1.val.net);
|
|
||||||
break;
|
|
||||||
case FI_ROUTE_DISTINGUISHER:
|
|
||||||
ARG(1, T_NET);
|
|
||||||
res.type = T_IP;
|
|
||||||
if (!net_is_vpn(v1.val.net))
|
|
||||||
runtime( "VPN address expected" );
|
|
||||||
res.type = T_RD;
|
|
||||||
res.val.ec = net_rd(v1.val.net);
|
|
||||||
break;
|
|
||||||
case FI_AS_PATH_FIRST: /* Get first ASN from AS PATH */
|
|
||||||
ARG(1, T_PATH);
|
|
||||||
|
|
||||||
as = 0;
|
|
||||||
as_path_get_first(v1.val.ad, &as);
|
|
||||||
res.type = T_INT;
|
|
||||||
res.val.i = as;
|
|
||||||
break;
|
|
||||||
case FI_AS_PATH_LAST: /* Get last ASN from AS PATH */
|
|
||||||
ARG(1, T_PATH);
|
|
||||||
|
|
||||||
as = 0;
|
|
||||||
as_path_get_last(v1.val.ad, &as);
|
|
||||||
res.type = T_INT;
|
|
||||||
res.val.i = as;
|
|
||||||
break;
|
|
||||||
case FI_AS_PATH_LAST_NAG: /* Get last ASN from non-aggregated part of AS PATH */
|
|
||||||
ARG(1, T_PATH);
|
|
||||||
|
|
||||||
res.type = T_INT;
|
|
||||||
res.val.i = as_path_get_last_nonaggregated(v1.val.ad);
|
|
||||||
break;
|
|
||||||
case FI_RETURN:
|
case FI_RETURN:
|
||||||
ARG_ANY(1);
|
ARG_ANY(1);
|
||||||
res = v1;
|
res = v1;
|
||||||
@ -1619,7 +1616,6 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
|||||||
case FI_NOT_MATCH:
|
case FI_NOT_MATCH:
|
||||||
case FI_MATCH: TWOARGS; break;
|
case FI_MATCH: TWOARGS; break;
|
||||||
case FI_DEFINED: ONEARG; break;
|
case FI_DEFINED: ONEARG; break;
|
||||||
case FI_TYPE: ONEARG; break;
|
|
||||||
|
|
||||||
case FI_LC_CONSTRUCT:
|
case FI_LC_CONSTRUCT:
|
||||||
THREEARGS;
|
THREEARGS;
|
||||||
@ -1670,7 +1666,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
|||||||
if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
|
if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case FI_PRINT: case FI_LENGTH: ONEARG; break;
|
case FI_PRINT: ONEARG; break;
|
||||||
case FI_CONDITION: THREEARGS; break;
|
case FI_CONDITION: THREEARGS; break;
|
||||||
case FI_NOP: case FI_EMPTY: break;
|
case FI_NOP: case FI_EMPTY: break;
|
||||||
case FI_PRINT_AND_DIE: ONEARG; A2_SAME; break;
|
case FI_PRINT_AND_DIE: ONEARG; A2_SAME; break;
|
||||||
@ -1682,12 +1678,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
|||||||
case FI_EA_SET: ONEARG; A2_SAME; break;
|
case FI_EA_SET: ONEARG; A2_SAME; break;
|
||||||
|
|
||||||
case FI_RETURN: ONEARG; break;
|
case FI_RETURN: ONEARG; break;
|
||||||
case FI_ROA_MAXLEN: ONEARG; break;
|
case FI_METHOD: ONEARG; A2_SAME; break;
|
||||||
case FI_ROA_ASN: ONEARG; break;
|
|
||||||
case FI_SADR_SRC: ONEARG; break;
|
|
||||||
case FI_IP: ONEARG; break;
|
|
||||||
case FI_IS_V4: ONEARG; break;
|
|
||||||
case FI_ROUTE_DISTINGUISHER: ONEARG; break;
|
|
||||||
case FI_CALL: /* Call rewriting trickery to avoid exponential behaviour */
|
case FI_CALL: /* Call rewriting trickery to avoid exponential behaviour */
|
||||||
ONEARG;
|
ONEARG;
|
||||||
if (!i_same(f1->a2.p, f2->a2.p))
|
if (!i_same(f1->a2.p, f2->a2.p))
|
||||||
@ -1699,9 +1690,6 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
|||||||
case FI_IP_MASK: TWOARGS; break;
|
case FI_IP_MASK: TWOARGS; break;
|
||||||
case FI_PATH_PREPEND: TWOARGS; break;
|
case FI_PATH_PREPEND: TWOARGS; break;
|
||||||
case FI_CLIST_ADD_DEL: TWOARGS; break;
|
case FI_CLIST_ADD_DEL: TWOARGS; break;
|
||||||
case FI_AS_PATH_FIRST:
|
|
||||||
case FI_AS_PATH_LAST:
|
|
||||||
case FI_AS_PATH_LAST_NAG: ONEARG; break;
|
|
||||||
case FI_ROA_CHECK:
|
case FI_ROA_CHECK:
|
||||||
TWOARGS;
|
TWOARGS;
|
||||||
/* Does not really make sense - ROA check results may change anyway */
|
/* Does not really make sense - ROA check results may change anyway */
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/attrs.h"
|
#include "nest/attrs.h"
|
||||||
|
|
||||||
|
#include "filter/methods.h"
|
||||||
|
|
||||||
/* Filter instruction types */
|
/* Filter instruction types */
|
||||||
|
|
||||||
#define FI__TWOCHAR(a,b) ((a<<8) | b)
|
#define FI__TWOCHAR(a,b) ((a<<8) | b)
|
||||||
@ -36,8 +38,6 @@
|
|||||||
F(FI_MATCH, 0, '~') \
|
F(FI_MATCH, 0, '~') \
|
||||||
F(FI_NOT_MATCH, '!', '~') \
|
F(FI_NOT_MATCH, '!', '~') \
|
||||||
F(FI_DEFINED, 'd', 'e') \
|
F(FI_DEFINED, 'd', 'e') \
|
||||||
F(FI_TYPE, 0, 'T') \
|
|
||||||
F(FI_IS_V4, 'I', 'i') \
|
|
||||||
F(FI_SET, 0, 's') \
|
F(FI_SET, 0, 's') \
|
||||||
F(FI_CONSTANT, 0, 'c') \
|
F(FI_CONSTANT, 0, 'c') \
|
||||||
F(FI_VARIABLE, 0, 'V') \
|
F(FI_VARIABLE, 0, 'V') \
|
||||||
@ -52,15 +52,7 @@
|
|||||||
F(FI_EA_SET, 'e', 'S') \
|
F(FI_EA_SET, 'e', 'S') \
|
||||||
F(FI_PREF_GET, 0, 'P') \
|
F(FI_PREF_GET, 0, 'P') \
|
||||||
F(FI_PREF_SET, 'P', 'S') \
|
F(FI_PREF_SET, 'P', 'S') \
|
||||||
F(FI_LENGTH, 0, 'L') \
|
F(FI_METHOD, 'o', 'M') \
|
||||||
F(FI_ROA_MAXLEN, 'R', 'M') \
|
|
||||||
F(FI_ROA_ASN, 'R', 'A') \
|
|
||||||
F(FI_SADR_SRC, 'n', 's') \
|
|
||||||
F(FI_IP, 'c', 'p') \
|
|
||||||
F(FI_ROUTE_DISTINGUISHER, 'R', 'D') \
|
|
||||||
F(FI_AS_PATH_FIRST, 'a', 'f') \
|
|
||||||
F(FI_AS_PATH_LAST, 'a', 'l') \
|
|
||||||
F(FI_AS_PATH_LAST_NAG, 'a', 'L') \
|
|
||||||
F(FI_RETURN, 0, 'r') \
|
F(FI_RETURN, 0, 'r') \
|
||||||
F(FI_CALL, 'c', 'a') \
|
F(FI_CALL, 'c', 'a') \
|
||||||
F(FI_CLEAR_LOCAL_VARS, 'c', 'V') \
|
F(FI_CLEAR_LOCAL_VARS, 'c', 'V') \
|
||||||
@ -152,6 +144,7 @@ struct filter {
|
|||||||
struct f_inst *f_new_inst(enum f_instruction_code fi_code);
|
struct f_inst *f_new_inst(enum f_instruction_code fi_code);
|
||||||
struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da);
|
struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da);
|
||||||
struct f_inst *f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa);
|
struct f_inst *f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa);
|
||||||
|
struct f_inst *f_new_inst_method(struct f_inst *target, enum f_method method);
|
||||||
static inline struct f_dynamic_attr f_new_dynamic_attr(int type, int f_type, int code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
|
static inline struct f_dynamic_attr f_new_dynamic_attr(int type, int f_type, int code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
|
||||||
{ return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
|
{ return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
|
||||||
static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly)
|
static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly)
|
||||||
|
33
filter/gen_methods.m4
Normal file
33
filter/gen_methods.m4
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
m4_divert(-1)m4_dnl
|
||||||
|
#
|
||||||
|
# BIRD -- Generator of Object Method List
|
||||||
|
#
|
||||||
|
# (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')
|
||||||
|
|
||||||
|
# Diversions used:
|
||||||
|
# 1 methods
|
||||||
|
|
||||||
|
# We don't need headers
|
||||||
|
m4_define(CF_HDR, `m4_divert(-1)')
|
||||||
|
|
||||||
|
m4_define(CF_OBJM, `m4_divert(1)FM_$1,
|
||||||
|
m4_divert(-1)')
|
||||||
|
|
||||||
|
m4_m4wrap(`
|
||||||
|
m4_divert(0)
|
||||||
|
#ifndef _BIRD_FILTER_METHOD_H_
|
||||||
|
#define _BIRD_FILTER_METHOD_H_
|
||||||
|
enum f_method {
|
||||||
|
m4_undivert(1)
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
')
|
||||||
|
|
||||||
|
# As we are processing C source, we must access all M4 primitives via
|
||||||
|
# m4_* and also set different quoting convention: `[[' and ']]'
|
||||||
|
m4_changequote([[,]])
|
13
filter/methods.Y
Normal file
13
filter/methods.Y
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
CF_OBJM(IS_V4)
|
||||||
|
CF_OBJM(TYPE)
|
||||||
|
CF_OBJM(IP)
|
||||||
|
CF_OBJM(RD)
|
||||||
|
CF_OBJM(LEN)
|
||||||
|
CF_OBJM(MAXLEN)
|
||||||
|
CF_OBJM(ASN)
|
||||||
|
CF_OBJM(SRC)
|
||||||
|
CF_OBJM(FIRST)
|
||||||
|
CF_OBJM(LAST)
|
||||||
|
CF_OBJM(LAST_NONAGGREGATED)
|
||||||
|
CF_OBJM(RESET)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user