Adds support for dynamic pair and bgp mask expressions.
This commit is contained in:
parent
f429d43482
commit
92a72a4cbd
6 changed files with 149 additions and 48 deletions
|
@ -572,7 +572,8 @@ incompatible with each other (that is to prevent you from shooting in the foot).
|
||||||
to +2000000000. Overflows are not checked. You can use <cf/0x1234/ syntax to write hexadecimal values.
|
to +2000000000. Overflows are not checked. You can use <cf/0x1234/ syntax to write hexadecimal values.
|
||||||
|
|
||||||
<tag/pair/ This is a pair of two short integers. Each component can have values from 0 to
|
<tag/pair/ This is a pair of two short integers. Each component can have values from 0 to
|
||||||
65535. Literals of this type is written as <cf/(1234,5678)/.
|
65535. Literals of this type are written as <cf/(1234,5678)/. The same syntax can also be
|
||||||
|
used to construct a pair from two arbitrary integer expressions (for example <cf/(1+2,a)/).
|
||||||
|
|
||||||
<tag/string/ This is a string of characters. There are no ways to modify strings in
|
<tag/string/ This is a string of characters. There are no ways to modify strings in
|
||||||
filters. You can pass them between functions, assign them to variables of type <cf/string/, print
|
filters. You can pass them between functions, assign them to variables of type <cf/string/, print
|
||||||
|
@ -640,6 +641,8 @@ incompatible with each other (that is to prevent you from shooting in the foot).
|
||||||
For example, if <cf>bgp_path</cf> is 4 3 2 1, then:
|
For example, if <cf>bgp_path</cf> is 4 3 2 1, then:
|
||||||
<tt>bgp_path ˜ [= * 4 3 * =]</tt> is true, but
|
<tt>bgp_path ˜ [= * 4 3 * =]</tt> is true, but
|
||||||
<tt>bgp_path ˜ [= * 4 5 * =]</tt> is false.
|
<tt>bgp_path ˜ [= * 4 5 * =]</tt> is false.
|
||||||
|
BGP mask expressions can also contain integer expressions enclosed in parenthesis
|
||||||
|
and integer variables, for example <tt>[= * 4 (1+2) a =]</tt>.
|
||||||
There is also old syntax that uses / .. / instead of [= .. =] and ? instead of *.
|
There is also old syntax that uses / .. / instead of [= .. =] and ? instead of *.
|
||||||
<tag/clist/
|
<tag/clist/
|
||||||
Community list is similar to set of pairs,
|
Community list is similar to set of pairs,
|
||||||
|
|
106
filter/config.Y
106
filter/config.Y
|
@ -14,6 +14,17 @@ CF_DEFINES
|
||||||
|
|
||||||
#define P(a,b) ((a<<8) | b)
|
#define P(a,b) ((a<<8) | b)
|
||||||
|
|
||||||
|
static int make_pair(int i1, int i2)
|
||||||
|
{
|
||||||
|
unsigned u1 = i1;
|
||||||
|
unsigned u2 = i2;
|
||||||
|
|
||||||
|
if ((u1 > 0xFFFF) || (u2 > 0xFFFF))
|
||||||
|
cf_error( "Can't operate with value out of bounds in pair constructor");
|
||||||
|
|
||||||
|
return (u1 << 16) | u2;
|
||||||
|
}
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||||
|
@ -32,9 +43,9 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||||
%nonassoc THEN
|
%nonassoc THEN
|
||||||
%nonassoc ELSE
|
%nonassoc ELSE
|
||||||
|
|
||||||
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn dynamic_attr static_attr function_call
|
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol dpair bgp_path_expr
|
||||||
%type <f> filter filter_body where_filter
|
%type <f> filter filter_body where_filter
|
||||||
%type <i> type break_command pair
|
%type <i> type break_command cpair
|
||||||
%type <e> set_item set_items switch_body
|
%type <e> set_item set_items switch_body
|
||||||
%type <trie> fprefix_set
|
%type <trie> fprefix_set
|
||||||
%type <v> set_atom fprefix fprefix_s fipa
|
%type <v> set_atom fprefix fprefix_s fipa
|
||||||
|
@ -203,8 +214,8 @@ block:
|
||||||
/*
|
/*
|
||||||
* Simple types, their bison value is int
|
* Simple types, their bison value is int
|
||||||
*/
|
*/
|
||||||
pair:
|
cpair:
|
||||||
'(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; }
|
'(' NUM ',' NUM ')' { $$ = make_pair($2, $4); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -216,7 +227,7 @@ fipa:
|
||||||
|
|
||||||
set_atom:
|
set_atom:
|
||||||
NUM { $$.type = T_INT; $$.val.i = $1; }
|
NUM { $$.type = T_INT; $$.val.i = $1; }
|
||||||
| pair { $$.type = T_PAIR; $$.val.i = $1; }
|
| cpair { $$.type = T_PAIR; $$.val.i = $1; }
|
||||||
| fipa { $$ = $1; }
|
| fipa { $$ = $1; }
|
||||||
| ENUM { $$.type = $1 >> 16; $$.val.i = $1 & 0xffff; }
|
| ENUM { $$.type = $1 >> 16; $$.val.i = $1 & 0xffff; }
|
||||||
;
|
;
|
||||||
|
@ -277,6 +288,11 @@ switch_body: /* EMPTY */ { $$ = NULL; }
|
||||||
|
|
||||||
/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
|
/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
|
||||||
|
|
||||||
|
bgp_path_expr:
|
||||||
|
symbol { $$ = $1; }
|
||||||
|
| '(' term ')' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
bgp_path:
|
bgp_path:
|
||||||
PO bgp_path_tail1 PC { $$ = $2; }
|
PO bgp_path_tail1 PC { $$ = $2; }
|
||||||
| '/' bgp_path_tail2 '/' { $$ = $2; }
|
| '/' bgp_path_tail2 '/' { $$ = $2; }
|
||||||
|
@ -286,6 +302,7 @@ bgp_path_tail1:
|
||||||
NUM bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
|
NUM bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
|
||||||
| '*' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; $$->val = 0; }
|
| '*' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; $$->val = 0; }
|
||||||
| '?' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; $$->val = 0; }
|
| '?' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; $$->val = 0; }
|
||||||
|
| bgp_path_expr bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN_EXPR; $$->val = (uintptr_t) $1; }
|
||||||
| { $$ = NULL; }
|
| { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -295,12 +312,24 @@ bgp_path_tail2:
|
||||||
| { $$ = NULL; }
|
| { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
dpair:
|
||||||
|
'(' term ',' term ')' {
|
||||||
|
if (($2->code == 'c') && ($4->code == 'c'))
|
||||||
|
{
|
||||||
|
if (($2->aux != T_INT) || ($4->aux != T_INT))
|
||||||
|
cf_error( "Can't operate with value of non-integer type in pair constructor" );
|
||||||
|
$$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR; $$->a2.i = make_pair($2->a2.i, $4->a2.i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ $$ = f_new_inst(); $$->code = P('m', 'p'); $$->a1.p = $2; $$->a2.p = $4; }
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
constant:
|
constant:
|
||||||
NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; }
|
NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; }
|
||||||
| TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; }
|
| TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; }
|
||||||
| FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; }
|
| FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; }
|
||||||
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
|
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
|
||||||
| pair { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR; $$->a2.i = $1; }
|
|
||||||
| fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
| fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
||||||
| fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
| fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
||||||
| '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
|
| '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
|
||||||
|
@ -309,6 +338,7 @@ constant:
|
||||||
| bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; }
|
| bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maybe there are no dynamic attributes defined by protocols.
|
* Maybe there are no dynamic attributes defined by protocols.
|
||||||
* For such cases, we force the dynamic_attr list to contain
|
* For such cases, we force the dynamic_attr list to contain
|
||||||
|
@ -342,6 +372,38 @@ function_call:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
symbol:
|
||||||
|
SYM {
|
||||||
|
$$ = f_new_inst();
|
||||||
|
switch ($1->class) {
|
||||||
|
case SYM_NUMBER:
|
||||||
|
$$ = f_new_inst();
|
||||||
|
$$->code = 'c';
|
||||||
|
$$->aux = T_INT;
|
||||||
|
$$->a2.i = $1->aux;
|
||||||
|
break;
|
||||||
|
case SYM_IPA:
|
||||||
|
{ NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_IP; val->val.px.ip = * (ip_addr *) ($1->def); }
|
||||||
|
break;
|
||||||
|
case SYM_VARIABLE | T_BOOL:
|
||||||
|
case SYM_VARIABLE | T_INT:
|
||||||
|
case SYM_VARIABLE | T_PAIR:
|
||||||
|
case SYM_VARIABLE | T_STRING:
|
||||||
|
case SYM_VARIABLE | T_IP:
|
||||||
|
case SYM_VARIABLE | T_PREFIX:
|
||||||
|
case SYM_VARIABLE | T_PREFIX_SET:
|
||||||
|
case SYM_VARIABLE | T_SET:
|
||||||
|
case SYM_VARIABLE | T_PATH:
|
||||||
|
case SYM_VARIABLE | T_PATH_MASK:
|
||||||
|
case SYM_VARIABLE | T_CLIST:
|
||||||
|
$$->code = 'C';
|
||||||
|
$$->a1.p = $1->def;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cf_error("%s: variable expected.", $1->name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static_attr:
|
static_attr:
|
||||||
FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, from); $$->a1.i = 1; }
|
FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, from); $$->a1.i = 1; }
|
||||||
|
|
||||||
|
@ -372,37 +434,9 @@ term:
|
||||||
| '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
|
| '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
|
||||||
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
|
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
|
||||||
|
|
||||||
|
| symbol { $$ = $1; }
|
||||||
| constant { $$ = $1; }
|
| constant { $$ = $1; }
|
||||||
| SYM {
|
| dpair { $$ = $1; }
|
||||||
$$ = f_new_inst();
|
|
||||||
switch ($1->class) {
|
|
||||||
case SYM_NUMBER:
|
|
||||||
$$ = f_new_inst();
|
|
||||||
$$->code = 'c';
|
|
||||||
$$->aux = T_INT;
|
|
||||||
$$->a2.i = $1->aux;
|
|
||||||
break;
|
|
||||||
case SYM_IPA:
|
|
||||||
{ NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_IP; val->val.px.ip = * (ip_addr *) ($1->def); }
|
|
||||||
break;
|
|
||||||
case SYM_VARIABLE | T_BOOL:
|
|
||||||
case SYM_VARIABLE | T_INT:
|
|
||||||
case SYM_VARIABLE | T_PAIR:
|
|
||||||
case SYM_VARIABLE | T_STRING:
|
|
||||||
case SYM_VARIABLE | T_IP:
|
|
||||||
case SYM_VARIABLE | T_PREFIX:
|
|
||||||
case SYM_VARIABLE | T_PREFIX_SET:
|
|
||||||
case SYM_VARIABLE | T_SET:
|
|
||||||
case SYM_VARIABLE | T_PATH:
|
|
||||||
case SYM_VARIABLE | T_PATH_MASK:
|
|
||||||
case SYM_VARIABLE | T_CLIST:
|
|
||||||
$$->code = 'C';
|
|
||||||
$$->a1.p = $1->def;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cf_error("%s: variable expected.", $1->name );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
| PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; }
|
| PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; }
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 f_eval_asn(struct f_inst *expr);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
|
pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
|
||||||
{
|
{
|
||||||
|
@ -82,10 +84,24 @@ pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->kind == PM_ASN)
|
switch(p->kind)
|
||||||
|
{
|
||||||
|
case PM_ASN:
|
||||||
buf += bsprintf(buf, " %u", p->val);
|
buf += bsprintf(buf, " %u", p->val);
|
||||||
else
|
break;
|
||||||
buf += bsprintf(buf, (p->kind == PM_ASTERISK) ? " *" : " ?");
|
|
||||||
|
case PM_QUESTION:
|
||||||
|
buf += bsprintf(buf, " ?");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PM_ASTERISK:
|
||||||
|
buf += bsprintf(buf, " *");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PM_ASN_EXPR:
|
||||||
|
buf += bsprintf(buf, " %u", f_eval_asn((struct f_inst *) p->val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
@ -333,6 +349,7 @@ interpret(struct f_inst *what)
|
||||||
{
|
{
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
struct f_val v1, v2, res;
|
struct f_val v1, v2, res;
|
||||||
|
unsigned u1, u2;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
res.type = T_VOID;
|
res.type = T_VOID;
|
||||||
|
@ -395,6 +412,18 @@ interpret(struct f_inst *what)
|
||||||
res.val.i = v1.val.i || v2.val.i;
|
res.val.i = v1.val.i || v2.val.i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case P('m','p'):
|
||||||
|
TWOARGS_C;
|
||||||
|
if ((v1.type != T_INT) || (v2.type != T_INT))
|
||||||
|
runtime( "Can't operate with value of non-integer type in pair constructor" );
|
||||||
|
u1 = v1.val.i;
|
||||||
|
u2 = v2.val.i;
|
||||||
|
if ((u1 > 0xFFFF) || (u2 > 0xFFFF))
|
||||||
|
runtime( "Can't operate with value out of bounds in pair constructor" );
|
||||||
|
res.val.i = (u1 << 16) | u2;
|
||||||
|
res.type = T_PAIR;
|
||||||
|
break;
|
||||||
|
|
||||||
/* Relational operators */
|
/* Relational operators */
|
||||||
|
|
||||||
#define COMPARE(x) \
|
#define COMPARE(x) \
|
||||||
|
@ -810,6 +839,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
||||||
case '/':
|
case '/':
|
||||||
case '|':
|
case '|':
|
||||||
case '&':
|
case '&':
|
||||||
|
case P('m','p'):
|
||||||
case P('!','='):
|
case P('!','='):
|
||||||
case P('=','='):
|
case P('=','='):
|
||||||
case '<':
|
case '<':
|
||||||
|
@ -933,6 +963,16 @@ f_eval_int(struct f_inst *expr)
|
||||||
return res.val.i;
|
return res.val.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32
|
||||||
|
f_eval_asn(struct f_inst *expr)
|
||||||
|
{
|
||||||
|
struct f_val res = interpret(expr);
|
||||||
|
if (res.type != T_INT)
|
||||||
|
cf_error("Can't operate with value of non-integer type in AS path mask constructor");
|
||||||
|
|
||||||
|
return res.val.i;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* filter_same - compare two filters
|
* filter_same - compare two filters
|
||||||
* @new: first filter to be compared
|
* @new: first filter to be compared
|
||||||
|
|
|
@ -9,6 +9,17 @@ router id 62.168.0.1;
|
||||||
|
|
||||||
define xyzzy = (120+10);
|
define xyzzy = (120+10);
|
||||||
|
|
||||||
|
|
||||||
|
function mkpair(int a)
|
||||||
|
{
|
||||||
|
return (1, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkpath(int a; int b)
|
||||||
|
{
|
||||||
|
return [= a b 3 2 1 =];
|
||||||
|
}
|
||||||
|
|
||||||
function callme(int arg1; int arg2)
|
function callme(int arg1; int arg2)
|
||||||
int local1;
|
int local1;
|
||||||
int local2;
|
int local2;
|
||||||
|
@ -50,6 +61,7 @@ clist l;
|
||||||
print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2;
|
print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2;
|
||||||
print "Should be true: ", p2 ~ / ? 4 3 2 1 /, " ", p2, " ", / ? 4 3 2 1 /;
|
print "Should be true: ", p2 ~ / ? 4 3 2 1 /, " ", p2, " ", / ? 4 3 2 1 /;
|
||||||
print "Should be true: ", p2 ~ [= * 4 3 * 1 =], " ", p2, " ", [= * 4 3 * 1 =];
|
print "Should be true: ", p2 ~ [= * 4 3 * 1 =], " ", p2, " ", [= * 4 3 * 1 =];
|
||||||
|
print "Should be true: ", p2 ~ [= (3+2) (2*2) 3 2 1 =], " ", p2 ~ mkpath(5, 4);
|
||||||
print "5 = ", p2.len;
|
print "5 = ", p2.len;
|
||||||
|
|
||||||
pm1 = [= 1 2 * 3 4 5 =];
|
pm1 = [= 1 2 * 3 4 5 =];
|
||||||
|
@ -143,11 +155,15 @@ string s;
|
||||||
|
|
||||||
px = 1.2.0.0/18;
|
px = 1.2.0.0/18;
|
||||||
print "Testing prefixes: 1.2.0.0/18 = ", px;
|
print "Testing prefixes: 1.2.0.0/18 = ", px;
|
||||||
|
print " must be true: ", 192.168.0.0/16 ~ 192.168.0.0/16, " ", 192.168.0.0/17 ~ 192.168.0.0/16, " ", 192.168.254.0/24 ~ 192.168.0.0/16;
|
||||||
|
print " must be false: ", 192.168.0.0/15 ~ 192.168.0.0/16, " ", 192.160.0.0/17 ~ 192.168.0.0/16;
|
||||||
|
|
||||||
p = 127.1.2.3;
|
p = 127.1.2.3;
|
||||||
print "Testing mask : 127.0.0.0 = ", p.mask(8);
|
print "Testing mask : 127.0.0.0 = ", p.mask(8);
|
||||||
|
|
||||||
pp = (1, 2);
|
pp = (1, 2);
|
||||||
print "Testing pairs: (1,2) = ", (1,2), " = ", pp;
|
print "Testing pairs: (1,2) = ", (1,2), " = ", pp, " = ", (1,1+1), " = ", mkpair(2);
|
||||||
|
print " must be true: ", (1,2) = (1,1+1);
|
||||||
print "Testing enums: ", RTS_DUMMY, " ", RTS_STATIC;
|
print "Testing enums: ", RTS_DUMMY, " ", RTS_STATIC;
|
||||||
|
|
||||||
s = "Hello";
|
s = "Hello";
|
||||||
|
|
|
@ -401,6 +401,7 @@ as_path_match(struct adata *path, struct f_path_mask *mask)
|
||||||
struct pm_pos pos[2048 + 1];
|
struct pm_pos pos[2048 + 1];
|
||||||
int plen = parse_path(path, pos);
|
int plen = parse_path(path, pos);
|
||||||
int l, h, i, nh, nl;
|
int l, h, i, nh, nl;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
/* l and h are bound of interval of positions where
|
/* l and h are bound of interval of positions where
|
||||||
are marked states */
|
are marked states */
|
||||||
|
@ -424,14 +425,20 @@ as_path_match(struct adata *path, struct f_path_mask *mask)
|
||||||
h = plen;
|
h = plen;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_QUESTION:
|
|
||||||
case PM_ASN:
|
case PM_ASN:
|
||||||
|
val = mask->val;
|
||||||
|
goto step;
|
||||||
|
case PM_ASN_EXPR:
|
||||||
|
val = f_eval_asn((struct f_inst *) mask->val);
|
||||||
|
goto step;
|
||||||
|
case PM_QUESTION:
|
||||||
|
step:
|
||||||
nh = -1;
|
nh = -1;
|
||||||
for (i = h; i >= l; i--)
|
for (i = h; i >= l; i--)
|
||||||
if (pos[i].mark)
|
if (pos[i].mark)
|
||||||
{
|
{
|
||||||
pos[i].mark = 0;
|
pos[i].mark = 0;
|
||||||
if ((mask->kind == PM_QUESTION) || pm_match(pos + i, mask->val))
|
if ((mask->kind == PM_QUESTION) || pm_match(pos + i, val))
|
||||||
pm_mark(pos, i, plen, &nl, &nh);
|
pm_mark(pos, i, plen, &nl, &nh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,11 +35,12 @@ int as_path_is_member(struct adata *path, u32 as);
|
||||||
#define PM_ASN 0
|
#define PM_ASN 0
|
||||||
#define PM_QUESTION 1
|
#define PM_QUESTION 1
|
||||||
#define PM_ASTERISK 2
|
#define PM_ASTERISK 2
|
||||||
|
#define PM_ASN_EXPR 3
|
||||||
|
|
||||||
struct f_path_mask {
|
struct f_path_mask {
|
||||||
struct f_path_mask *next;
|
struct f_path_mask *next;
|
||||||
int kind;
|
int kind;
|
||||||
u32 val;
|
uintptr_t val;
|
||||||
};
|
};
|
||||||
|
|
||||||
int as_path_match(struct adata *path, struct f_path_mask *mask);
|
int as_path_match(struct adata *path, struct f_path_mask *mask);
|
||||||
|
|
Loading…
Reference in a new issue