Filters now know type path. It is possible to declare variable of type
path, but it is not possible to write constant of type path. It should be possible to print paths and match them.
This commit is contained in:
parent
7750634946
commit
10a5360886
4 changed files with 35 additions and 17 deletions
|
@ -65,7 +65,7 @@ CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||||
ACCEPT, REJECT, ERROR, QUITBIRD,
|
ACCEPT, REJECT, ERROR, QUITBIRD,
|
||||||
INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGP_PATH,
|
INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGPMASK, BGPPATH, CLIST,
|
||||||
IF, THEN, ELSE, CASE,
|
IF, THEN, ELSE, CASE,
|
||||||
TRUE, FALSE,
|
TRUE, FALSE,
|
||||||
FROM, GW, NET, MASK, SOURCE,
|
FROM, GW, NET, MASK, SOURCE,
|
||||||
|
@ -106,7 +106,9 @@ type:
|
||||||
| PREFIX { $$ = T_PREFIX; }
|
| PREFIX { $$ = T_PREFIX; }
|
||||||
| PAIR { $$ = T_PAIR; }
|
| PAIR { $$ = T_PAIR; }
|
||||||
| STRING { $$ = T_STRING; }
|
| STRING { $$ = T_STRING; }
|
||||||
| BGP_PATH { $$ = T_PATH_MASK; }
|
| BGPMASK { $$ = T_PATH_MASK; }
|
||||||
|
| BGPPATH { $$ = T_PATH; }
|
||||||
|
| CLIST { $$ = T_CLIST; }
|
||||||
| type SET {
|
| type SET {
|
||||||
switch ($1) {
|
switch ($1) {
|
||||||
default:
|
default:
|
||||||
|
@ -406,16 +408,16 @@ term:
|
||||||
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
|
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
|
||||||
|
|
||||||
/* Communities */
|
/* Communities */
|
||||||
|
/* This causes one shift/reduce conflict
|
||||||
| term '.' ADD '(' term ')' { }
|
| rtadot dynamic_attr '.' ADD '(' term ')' { }
|
||||||
| term '.' DELETE '(' term ')' { }
|
| rtadot dynamic_attr '.' DELETE '(' term ')' { }
|
||||||
| term '.' CONTAINS '(' term ')' { }
|
| rtadot dynamic_attr '.' CONTAINS '(' term ')' { }
|
||||||
| term '.' RESET { }
|
| rtadot dynamic_attr '.' RESET { }
|
||||||
|
*/
|
||||||
|
|
||||||
/* Paths */
|
/* Paths */
|
||||||
| rtadot PATH '~' term { }
|
| rtadot dynamic_attr '.' APPEND '(' term ')' { }
|
||||||
| rtadot PATH '.' APPEND '(' term ')' { }
|
| rtadot dynamic_attr '.' LEN { $$->code = P('P','l'); }
|
||||||
| rtadot PATH '.' LEN { $$->code = P('P','l'); }
|
|
||||||
|
|
||||||
/* function_call is inlined here */
|
/* function_call is inlined here */
|
||||||
| SYM '(' var_list ')' {
|
| SYM '(' var_list ')' {
|
||||||
|
|
|
@ -60,6 +60,9 @@ val_compare(struct f_val v1, struct f_val v2)
|
||||||
int
|
int
|
||||||
val_simple_in_range(struct f_val v1, struct f_val v2)
|
val_simple_in_range(struct f_val v1, struct f_val v2)
|
||||||
{
|
{
|
||||||
|
if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
|
||||||
|
return path_match(&v1.val.ad->data, v1.val.ad->length, v2.val.path_mask);
|
||||||
|
|
||||||
if ((v1.type == T_IP) && (v2.type == T_PREFIX))
|
if ((v1.type == T_IP) && (v2.type == T_PREFIX))
|
||||||
return !(ipa_compare(ipa_and(v2.val.px.ip, ipa_mkmask(v2.val.px.len)), ipa_and(v1.val.px.ip, ipa_mkmask(v2.val.px.len))));
|
return !(ipa_compare(ipa_and(v2.val.px.ip, ipa_mkmask(v2.val.px.len)), ipa_and(v1.val.px.ip, ipa_mkmask(v2.val.px.len))));
|
||||||
|
|
||||||
|
@ -133,6 +136,7 @@ val_print(struct f_val v)
|
||||||
case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
|
case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
|
||||||
case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
|
case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
|
||||||
case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
|
case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
|
||||||
|
case T_PATH: PRINTF( "%s", path_format(&v.val.ad->data, v.val.ad->length)); break;
|
||||||
case T_PATH_MASK: debug( "(path " ); { struct f_path_mask *p = v.val.s; while (p) { debug("%d ", p->val); p=p->next; } debug(")" ); } break;
|
case T_PATH_MASK: debug( "(path " ); { struct f_path_mask *p = v.val.s; while (p) { debug("%d ", p->val); p=p->next; } debug(")" ); } break;
|
||||||
default: PRINTF( "[unknown type %x]", v.type );
|
default: PRINTF( "[unknown type %x]", v.type );
|
||||||
#undef PRINTF
|
#undef PRINTF
|
||||||
|
@ -341,11 +345,14 @@ interpret(struct f_inst *what)
|
||||||
res.type = T_VOID;
|
res.type = T_VOID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
res.type = what->aux;
|
res.type = what->aux; /* FIXME: should check type? */
|
||||||
switch (what->a1.i) {
|
switch (what->a1.i) {
|
||||||
case T_INT:
|
case T_INT:
|
||||||
res.val.i = e->u.data;
|
res.val.i = e->u.data;
|
||||||
break;
|
break;
|
||||||
|
case T_PATH:
|
||||||
|
res.val.ad = e->u.ptr;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -369,6 +376,11 @@ interpret(struct f_inst *what)
|
||||||
runtime( "Setting int attribute to non-int value" );
|
runtime( "Setting int attribute to non-int value" );
|
||||||
l->attrs[0].u.data = v1.val.i;
|
l->attrs[0].u.data = v1.val.i;
|
||||||
break;
|
break;
|
||||||
|
case EAF_TYPE_AS_PATH:
|
||||||
|
if (v1.type != T_PATH)
|
||||||
|
runtime( "Setting path attribute to non-path value" );
|
||||||
|
l->attrs[0].u.ptr = v1.val.ad;
|
||||||
|
break;
|
||||||
case EAF_TYPE_UNDEF:
|
case EAF_TYPE_UNDEF:
|
||||||
if (v1.type != T_VOID)
|
if (v1.type != T_VOID)
|
||||||
runtime( "Setting void attribute to non-void value" );
|
runtime( "Setting void attribute to non-void value" );
|
||||||
|
|
|
@ -39,6 +39,11 @@ struct prefix {
|
||||||
/* If range then prefix must be in range (len >> 16 & 0xff, len >> 8 & 0xff) */
|
/* If range then prefix must be in range (len >> 16 & 0xff, len >> 8 & 0xff) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct f_path_mask {
|
||||||
|
struct f_path_mask *next;
|
||||||
|
int val;
|
||||||
|
};
|
||||||
|
|
||||||
struct f_val {
|
struct f_val {
|
||||||
int type;
|
int type;
|
||||||
union {
|
union {
|
||||||
|
@ -47,14 +52,11 @@ struct f_val {
|
||||||
struct prefix px;
|
struct prefix px;
|
||||||
char *s;
|
char *s;
|
||||||
struct f_tree *t;
|
struct f_tree *t;
|
||||||
|
struct adata *ad;
|
||||||
|
struct f_path_mask *path_mask;
|
||||||
} val;
|
} val;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct f_path_mask {
|
|
||||||
struct f_path_mask *next;
|
|
||||||
int val;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct filter {
|
struct filter {
|
||||||
char *name;
|
char *name;
|
||||||
struct f_inst *root;
|
struct f_inst *root;
|
||||||
|
@ -116,6 +118,8 @@ void val_print(struct f_val v);
|
||||||
#define T_PREFIX 0x21
|
#define T_PREFIX 0x21
|
||||||
#define T_STRING 0x22
|
#define T_STRING 0x22
|
||||||
#define T_PATH_MASK 0x23 /* mask for BGP path */
|
#define T_PATH_MASK 0x23 /* mask for BGP path */
|
||||||
|
#define T_PATH 0x24 /* BGP path */
|
||||||
|
#define T_CLIST 0x25 /* Community list */
|
||||||
|
|
||||||
#define T_RETURN 0x40
|
#define T_RETURN 0x40
|
||||||
#define T_SET 0x80
|
#define T_SET 0x80
|
||||||
|
|
|
@ -30,7 +30,7 @@ function fifteen()
|
||||||
}
|
}
|
||||||
|
|
||||||
function paths()
|
function paths()
|
||||||
bgp_path p;
|
bgpmask p;
|
||||||
{
|
{
|
||||||
print "Testing paths";
|
print "Testing paths";
|
||||||
p = / 1 2 3 4 /;
|
p = / 1 2 3 4 /;
|
||||||
|
|
Loading…
Reference in a new issue