Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
labs
BIRD Internet Routing Daemon
Commits
92a72a4c
Commit
92a72a4c
authored
Jun 01, 2009
by
Ondřej Zajíček
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds support for dynamic pair and bgp mask expressions.
parent
f429d434
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
149 additions
and
48 deletions
+149
-48
doc/bird.sgml
doc/bird.sgml
+4
-1
filter/config.Y
filter/config.Y
+73
-39
filter/filter.c
filter/filter.c
+44
-4
filter/test.conf
filter/test.conf
+17
-1
nest/a-path.c
nest/a-path.c
+9
-2
nest/attrs.h
nest/attrs.h
+2
-1
No files found.
doc/bird.sgml
View file @
92a72a4c
...
...
@@ -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.
<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
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:
<tt>bgp_path ˜ [= * 4 3 * =]</tt> is true, but
<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 *.
<tag/clist/
Community list is similar to set of pairs,
...
...
filter/config.Y
View file @
92a72a4c
...
...
@@ -14,6 +14,17 @@ CF_DEFINES
#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_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
...
...
@@ -32,9 +43,9 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
%nonassoc THEN
%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 <i> type break_command pair
%type <i> type break_command
c
pair
%type <e> set_item set_items switch_body
%type <trie> fprefix_set
%type <v> set_atom fprefix fprefix_s fipa
...
...
@@ -203,8 +214,8 @@ block:
/*
* Simple types, their bison value is int
*/
pair:
'(' NUM ',' NUM ')' { $$ =
$2 << 16 |
$4; }
c
pair:
'(' NUM ',' NUM ')' { $$ =
make_pair($2,
$4
)
; }
;
/*
...
...
@@ -215,10 +226,10 @@ fipa:
;
set_atom:
NUM { $$.type = T_INT; $$.val.i = $1; }
| pair { $$.type = T_PAIR; $$.val.i = $1; }
| fipa { $$ = $1; }
| ENUM { $$.type = $1 >> 16; $$.val.i = $1 & 0xffff; }
NUM
{ $$.type = T_INT; $$.val.i = $1; }
|
c
pair { $$.type = T_PAIR; $$.val.i = $1; }
| fipa
{ $$ = $1; }
| ENUM
{ $$.type = $1 >> 16; $$.val.i = $1 & 0xffff; }
;
set_item:
...
...
@@ -277,6 +288,11 @@ switch_body: /* EMPTY */ { $$ = NULL; }
/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
bgp_path_expr:
symbol { $$ = $1; }
| '(' term ')' { $$ = $2; }
;
bgp_path:
PO bgp_path_tail1 PC { $$ = $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; }
| '*' 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_expr bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN_EXPR; $$->val = (uintptr_t) $1; }
| { $$ = NULL; }
;
...
...
@@ -295,12 +312,24 @@ bgp_path_tail2:
| { $$ = 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:
NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->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; }
| 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; }
| 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" ); }
...
...
@@ -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; }
;
/*
* Maybe there are no dynamic attributes defined by protocols.
* 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:
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; }
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
| symbol { $$ = $1; }
| constant { $$ = $1; }
| 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 );
}
}
| dpair { $$ = $1; }
| PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; }
...
...
filter/filter.c
View file @
92a72a4c
...
...
@@ -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
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
;
}
if
(
p
->
kind
==
PM_ASN
)
buf
+=
bsprintf
(
buf
,
" %u"
,
p
->
val
);
else
buf
+=
bsprintf
(
buf
,
(
p
->
kind
==
PM_ASTERISK
)
?
" *"
:
" ?"
);
switch
(
p
->
kind
)
{
case
PM_ASN
:
buf
+=
bsprintf
(
buf
,
" %u"
,
p
->
val
);
break
;
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
;
}
...
...
@@ -333,6 +349,7 @@ interpret(struct f_inst *what)
{
struct
symbol
*
sym
;
struct
f_val
v1
,
v2
,
res
;
unsigned
u1
,
u2
;
int
i
;
res
.
type
=
T_VOID
;
...
...
@@ -395,6 +412,18 @@ interpret(struct f_inst *what)
res
.
val
.
i
=
v1
.
val
.
i
||
v2
.
val
.
i
;
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 */
#define COMPARE(x) \
...
...
@@ -810,6 +839,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case
'/'
:
case
'|'
:
case
'&'
:
case
P
(
'm'
,
'p'
):
case
P
(
'!'
,
'='
):
case
P
(
'='
,
'='
):
case
'<'
:
...
...
@@ -933,6 +963,16 @@ f_eval_int(struct f_inst *expr)
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
* @new: first filter to be compared
...
...
filter/test.conf
View file @
92a72a4c
...
...
@@ -9,6 +9,17 @@ router id 62.168.0.1;
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
)
int
local1
;
int
local2
;
...
...
@@ -50,6 +61,7 @@ clist l;
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
*
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
;
pm1
= [=
1
2
*
3
4
5
=];
...
...
@@ -143,11 +155,15 @@ string s;
px
=
1
.
2
.
0
.
0
/
18
;
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
;
print
"Testing mask : 127.0.0.0 = "
,
p
.
mask
(
8
);
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
;
s
=
"Hello"
;
...
...
nest/a-path.c
View file @
92a72a4c
...
...
@@ -401,6 +401,7 @@ as_path_match(struct adata *path, struct f_path_mask *mask)
struct
pm_pos
pos
[
2048
+
1
];
int
plen
=
parse_path
(
path
,
pos
);
int
l
,
h
,
i
,
nh
,
nl
;
u32
val
;
/* l and h are bound of interval of positions where
are marked states */
...
...
@@ -424,14 +425,20 @@ as_path_match(struct adata *path, struct f_path_mask *mask)
h
=
plen
;
break
;
case
PM_QUESTION
:
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
;
for
(
i
=
h
;
i
>=
l
;
i
--
)
if
(
pos
[
i
].
mark
)
{
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
);
}
...
...
nest/attrs.h
View file @
92a72a4c
...
...
@@ -35,11 +35,12 @@ int as_path_is_member(struct adata *path, u32 as);
#define PM_ASN 0
#define PM_QUESTION 1
#define PM_ASTERISK 2
#define PM_ASN_EXPR 3
struct
f_path_mask
{
struct
f_path_mask
*
next
;
int
kind
;
u
32
val
;
u
intptr_t
val
;
};
int
as_path_match
(
struct
adata
*
path
,
struct
f_path_mask
*
mask
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment