Revision 42a0c054 filter/config.Y
filter/config.Y | ||
---|---|---|
75 | 75 |
return lst; |
76 | 76 |
} |
77 | 77 |
|
78 |
#define EC_ALL 0xFFFFFFFF |
|
79 |
|
|
80 |
static struct f_tree * |
|
81 |
f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt) |
|
82 |
{ |
|
83 |
u64 fm, to; |
|
84 |
|
|
85 |
if (ipv4_used || (key >= 0x10000)) { |
|
86 |
check_u16(vf); |
|
87 |
if (vt == EC_ALL) |
|
88 |
vt = 0xFFFF; |
|
89 |
else |
|
90 |
check_u16(vt); |
|
91 |
} |
|
92 |
|
|
93 |
if (kind == EC_GENERIC) { |
|
94 |
fm = ec_generic(key, vf); |
|
95 |
to = ec_generic(key, vt); |
|
96 |
} |
|
97 |
else if (ipv4_used) { |
|
98 |
fm = ec_ip4(kind, key, vf); |
|
99 |
to = ec_ip4(kind, key, vt); |
|
100 |
} |
|
101 |
else if (key < 0x10000) { |
|
102 |
fm = ec_as2(kind, key, vf); |
|
103 |
to = ec_as2(kind, key, vt); |
|
104 |
} |
|
105 |
else { |
|
106 |
fm = ec_as4(kind, key, vf); |
|
107 |
to = ec_as4(kind, key, vt); |
|
108 |
} |
|
109 |
|
|
110 |
struct f_tree *t = f_new_tree(); |
|
111 |
t->right = t; |
|
112 |
t->from.type = t->to.type = T_EC; |
|
113 |
t->from.val.ec = fm; |
|
114 |
t->to.val.ec = to; |
|
115 |
return t; |
|
116 |
} |
|
117 |
|
|
118 |
static inline struct f_inst * |
|
119 |
f_generate_empty(struct f_inst *dyn) |
|
120 |
{ |
|
121 |
struct f_inst *e = f_new_inst(); |
|
122 |
e->code = 'E'; |
|
123 |
|
|
124 |
switch (dyn->aux & EAF_TYPE_MASK) { |
|
125 |
case EAF_TYPE_AS_PATH: |
|
126 |
e->aux = T_PATH; |
|
127 |
break; |
|
128 |
case EAF_TYPE_INT_SET: |
|
129 |
e->aux = T_CLIST; |
|
130 |
break; |
|
131 |
case EAF_TYPE_EC_SET: |
|
132 |
e->aux = T_ECLIST; |
|
133 |
break; |
|
134 |
default: |
|
135 |
cf_error("Can't empty that attribute"); |
|
136 |
} |
|
137 |
|
|
138 |
dyn->code = P('e','S'); |
|
139 |
dyn->a1.p = e; |
|
140 |
return dyn; |
|
141 |
} |
|
142 |
|
|
143 |
|
|
144 |
static inline struct f_inst * |
|
145 |
f_generate_dpair(struct f_inst *t1, struct f_inst *t2) |
|
146 |
{ |
|
147 |
struct f_inst *rv; |
|
148 |
|
|
149 |
if ((t1->code == 'c') && (t2->code == 'c')) { |
|
150 |
if ((t1->aux != T_INT) || (t2->aux != T_INT)) |
|
151 |
cf_error( "Can't operate with value of non-integer type in pair constructor"); |
|
152 |
|
|
153 |
check_u16(t1->a2.i); |
|
154 |
check_u16(t2->a2.i); |
|
155 |
|
|
156 |
rv = f_new_inst(); |
|
157 |
rv->code = 'c'; |
|
158 |
rv->aux = T_PAIR; |
|
159 |
rv->a2.i = pair(t1->a2.i, t2->a2.i); |
|
160 |
} |
|
161 |
else { |
|
162 |
rv = f_new_inst(); |
|
163 |
rv->code = P('m', 'p'); |
|
164 |
rv->a1.p = t1; |
|
165 |
rv->a2.p = t2; |
|
166 |
} |
|
167 |
|
|
168 |
return rv; |
|
169 |
} |
|
170 |
|
|
171 |
static inline struct f_inst * |
|
172 |
f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv) |
|
173 |
{ |
|
174 |
struct f_inst *rv; |
|
175 |
int c1 = 0, c2 = 0, ipv4_used = 0; |
|
176 |
u32 key = 0, val2 = 0; |
|
177 |
|
|
178 |
if (tk->code == 'c') { |
|
179 |
c1 = 1; |
|
180 |
|
|
181 |
if (tk->aux == T_INT) { |
|
182 |
ipv4_used = 0; key = tk->a2.i; |
|
183 |
} |
|
184 |
else if (tk->aux == T_QUAD) { |
|
185 |
ipv4_used = 1; key = tk->a2.i; |
|
186 |
} |
|
187 |
else |
|
188 |
cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor"); |
|
189 |
} |
|
190 |
|
|
191 |
#ifndef IPV6 |
|
192 |
/* IP->Quad implicit conversion */ |
|
193 |
else if (tk->code == 'C') { |
|
194 |
c1 = 1; |
|
195 |
struct f_val *val = tk->a1.p; |
|
196 |
if (val->type == T_IP) { |
|
197 |
ipv4_used = 1; key = ipa_to_u32(val->val.px.ip); |
|
198 |
} |
|
199 |
else |
|
200 |
cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor"); |
|
201 |
} |
|
202 |
#endif |
|
203 |
|
|
204 |
if (tv->code == 'c') { |
|
205 |
if (tv->aux != T_INT) |
|
206 |
cf_error("Can't operate with value of non-integer type in EC constructor"); |
|
207 |
c2 = 1; |
|
208 |
val2 = tv->a2.i; |
|
209 |
} |
|
210 |
|
|
211 |
if (c1 && c2) { |
|
212 |
u64 ec; |
|
213 |
|
|
214 |
if (kind == EC_GENERIC) { |
|
215 |
ec = ec_generic(key, val2); |
|
216 |
} |
|
217 |
else if (ipv4_used) { |
|
218 |
check_u16(val2); |
|
219 |
ec = ec_ip4(kind, key, val2); |
|
220 |
} |
|
221 |
else if (key < 0x10000) { |
|
222 |
ec = ec_as2(kind, key, val2); |
|
223 |
} |
|
224 |
else { |
|
225 |
check_u16(val2); |
|
226 |
ec = ec_as4(kind, key, val2); |
|
227 |
} |
|
228 |
|
|
229 |
NEW_F_VAL; |
|
230 |
rv = f_new_inst(); |
|
231 |
rv->code = 'C'; |
|
232 |
rv->a1.p = val; |
|
233 |
val->type = T_EC; |
|
234 |
val->val.ec = ec; |
|
235 |
} |
|
236 |
else { |
|
237 |
rv = f_new_inst(); |
|
238 |
rv->code = P('m','c'); |
|
239 |
rv->aux = kind; |
|
240 |
rv->a1.p = tk; |
|
241 |
rv->a2.p = tv; |
|
242 |
} |
|
243 |
|
|
244 |
return rv; |
|
245 |
}; |
|
246 |
|
|
247 |
|
|
248 |
|
|
78 | 249 |
CF_DECLS |
79 | 250 |
|
80 | 251 |
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, |
81 | 252 |
ACCEPT, REJECT, ERROR, QUITBIRD, |
82 |
INT, BOOL, IP, PREFIX, PAIR, QUAD, SET, STRING, BGPMASK, BGPPATH, CLIST, |
|
253 |
INT, BOOL, IP, PREFIX, PAIR, QUAD, EC, |
|
254 |
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, |
|
83 | 255 |
IF, THEN, ELSE, CASE, |
84 |
TRUE, FALSE, |
|
256 |
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
|
|
85 | 257 |
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, PREFERENCE, |
86 | 258 |
LEN, |
87 | 259 |
DEFINED, |
... | ... | |
93 | 265 |
%nonassoc THEN |
94 | 266 |
%nonassoc ELSE |
95 | 267 |
|
96 |
%type <x> term block cmds cmds_int cmd function_body constant print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol dpair bgp_path_expr
|
|
268 |
%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr
|
|
97 | 269 |
%type <f> filter filter_body where_filter |
98 |
%type <i> type break_command pair_expr |
|
99 |
%type <i32> pair_atom |
|
100 |
%type <e> pair_item set_item switch_item set_items switch_items switch_body |
|
270 |
%type <i> type break_command pair_expr ec_kind
|
|
271 |
%type <i32> pair_atom ec_expr
|
|
272 |
%type <e> pair_item ec_item set_item switch_item set_items switch_items switch_body
|
|
101 | 273 |
%type <trie> fprefix_set |
102 | 274 |
%type <v> set_atom switch_atom fprefix fprefix_s fipa |
103 | 275 |
%type <s> decls declsn one_decl function_params |
... | ... | |
128 | 300 |
| PREFIX { $$ = T_PREFIX; } |
129 | 301 |
| PAIR { $$ = T_PAIR; } |
130 | 302 |
| QUAD { $$ = T_QUAD; } |
303 |
| EC { $$ = T_EC; } |
|
131 | 304 |
| STRING { $$ = T_STRING; } |
132 | 305 |
| BGPMASK { $$ = T_PATH_MASK; } |
133 | 306 |
| BGPPATH { $$ = T_PATH; } |
134 | 307 |
| CLIST { $$ = T_CLIST; } |
308 |
| ECLIST { $$ = T_ECLIST; } |
|
135 | 309 |
| type SET { |
136 | 310 |
switch ($1) { |
137 | 311 |
case T_INT: |
138 | 312 |
case T_PAIR: |
139 | 313 |
case T_QUAD: |
314 |
case T_EC: |
|
140 | 315 |
case T_IP: |
141 | 316 |
$$ = T_SET; |
142 | 317 |
break; |
... | ... | |
324 | 499 |
} |
325 | 500 |
; |
326 | 501 |
|
502 |
ec_expr: |
|
503 |
term { $$ = f_eval_int($1); } |
|
504 |
|
|
505 |
ec_kind: |
|
506 |
RT { $$ = EC_RT; } |
|
507 |
| RO { $$ = EC_RO; } |
|
508 |
| UNKNOWN NUM { $$ = $2; } |
|
509 |
| GENERIC { $$ = EC_GENERIC; } |
|
510 |
; |
|
511 |
|
|
512 |
ec_item: |
|
513 |
'(' ec_kind ',' ec_expr ',' ec_expr ')' { $$ = f_new_ec_item($2, 0, $4, $6, $6); } |
|
514 |
| '(' ec_kind ',' ec_expr ',' ec_expr DDOT ec_expr ')' { $$ = f_new_ec_item($2, 0, $4, $6, $8); } |
|
515 |
| '(' ec_kind ',' ec_expr ',' '*' ')' { $$ = f_new_ec_item($2, 0, $4, 0, EC_ALL); } |
|
516 |
; |
|
517 |
|
|
327 | 518 |
set_item: |
328 | 519 |
pair_item |
520 |
| ec_item |
|
329 | 521 |
| set_atom { $$ = f_new_item($1, $1); } |
330 | 522 |
| set_atom DDOT set_atom { $$ = f_new_item($1, $3); } |
331 | 523 |
; |
332 | 524 |
|
333 | 525 |
switch_item: |
334 | 526 |
pair_item |
527 |
| ec_item |
|
335 | 528 |
| switch_atom { $$ = f_new_item($1, $1); } |
336 | 529 |
| switch_atom DDOT switch_atom { $$ = f_new_item($1, $3); } |
337 | 530 |
; |
... | ... | |
411 | 604 |
| { $$ = NULL; } |
412 | 605 |
; |
413 | 606 |
|
414 |
dpair: |
|
415 |
'(' term ',' term ')' { |
|
416 |
if (($2->code == 'c') && ($4->code == 'c')) |
|
417 |
{ |
|
418 |
if (($2->aux != T_INT) || ($4->aux != T_INT)) |
|
419 |
cf_error( "Can't operate with value of non-integer type in pair constructor" ); |
|
420 |
check_u16($2->a2.i); check_u16($4->a2.i); |
|
421 |
$$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR; $$->a2.i = pair($2->a2.i, $4->a2.i); |
|
422 |
} |
|
423 |
else |
|
424 |
{ $$ = f_new_inst(); $$->code = P('m', 'p'); $$->a1.p = $2; $$->a2.p = $4; } |
|
425 |
} |
|
426 |
; |
|
427 |
|
|
428 | 607 |
constant: |
429 | 608 |
NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; } |
430 | 609 |
| TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; } |
... | ... | |
439 | 618 |
| bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; } |
440 | 619 |
; |
441 | 620 |
|
621 |
constructor: |
|
622 |
'(' term ',' term ')' { $$ = f_generate_dpair($2, $4); }; |
|
623 |
| '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); }; |
|
624 |
; |
|
625 |
|
|
442 | 626 |
|
443 | 627 |
/* |
444 | 628 |
* Maybe there are no dynamic attributes defined by protocols. |
... | ... | |
490 | 674 |
case SYM_VARIABLE | T_INT: |
491 | 675 |
case SYM_VARIABLE | T_PAIR: |
492 | 676 |
case SYM_VARIABLE | T_QUAD: |
677 |
case SYM_VARIABLE | T_EC: |
|
493 | 678 |
case SYM_VARIABLE | T_STRING: |
494 | 679 |
case SYM_VARIABLE | T_IP: |
495 | 680 |
case SYM_VARIABLE | T_PREFIX: |
... | ... | |
498 | 683 |
case SYM_VARIABLE | T_PATH: |
499 | 684 |
case SYM_VARIABLE | T_PATH_MASK: |
500 | 685 |
case SYM_VARIABLE | T_CLIST: |
686 |
case SYM_VARIABLE | T_ECLIST: |
|
501 | 687 |
$$->code = 'V'; |
502 | 688 |
$$->a1.p = $1->def; |
503 | 689 |
$$->a2.p = $1->name; |
... | ... | |
539 | 725 |
|
540 | 726 |
| symbol { $$ = $1; } |
541 | 727 |
| constant { $$ = $1; } |
542 |
| dpair { $$ = $1; }
|
|
728 |
| constructor { $$ = $1; }
|
|
543 | 729 |
|
544 | 730 |
| PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; } |
545 | 731 |
|
... | ... | |
563 | 749 |
|
564 | 750 |
| '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; } |
565 | 751 |
| '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; } |
752 |
| '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; } |
|
566 | 753 |
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; } |
567 | 754 |
| ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } |
568 | 755 |
| DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; } |
... | ... | |
702 | 889 |
} |
703 | 890 |
|
704 | 891 |
|
705 |
| rtadot dynamic_attr '.' EMPTY ';' |
|
706 |
{ struct f_inst *i = f_new_inst(); i->code = 'E'; i->aux = T_CLIST; $$ = $2; $$->code = P('e','S'); $$->a1.p = i; } |
|
892 |
| rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); } |
|
707 | 893 |
| rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); } |
708 |
| rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); }
|
|
709 |
| rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); }
|
|
710 |
| rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); }
|
|
894 |
| rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); } |
|
895 |
| rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); } |
|
896 |
| rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); } |
|
711 | 897 |
; |
712 | 898 |
|
713 | 899 |
CF_END |
Also available in: Unified diff