}
static inline struct f_inst *
-f_const_empty(struct f_dynamic_attr dyn)
+f_generate_empty(const struct symbol *sym)
{
- struct f_val empty;
-
- switch (dyn.type) {
- case EAF_TYPE_AS_PATH:
- case EAF_TYPE_INT_SET:
- case EAF_TYPE_EC_SET:
- case EAF_TYPE_LC_SET:
- empty = (struct f_val) {
- .type = dyn.f_type,
- .val.ad = &null_adata,
- };
- break;
- default:
- cf_error("Can't empty that attribute");
- }
+ if (sym->class != SYM_ATTRIBUTE)
+ cf_error("Can't empty %s: not an attribute", sym->name);
- return f_new_inst(FI_CONSTANT, empty);
+ const struct ea_class *def = sym->attribute;
- const struct f_val *empty = f_get_empty(def->type);
- if (!empty)
++ const struct f_val empty = f_get_empty(def->type);
++ if (empty.type == T_VOID)
+ cf_error("Can't empty attribute %s", def->name);
+
- return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, *empty), def);
++ return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, empty), def);
}
-#define f_dummy_dynattr(_type, _f_type) ((struct f_dynamic_attr) { .type = _type, .f_type = _f_type, })
+static inline struct f_inst *
+f_implicit_roa_check(struct rtable_config *tab)
+{
+ const struct ea_class *def = ea_class_find("bgp_path");
+ if (!def)
+ cf_error("Fatal: Couldn't find BGP path attribute definition.");
+
+ struct f_static_attr fsa = f_new_static_attr(T_NET, SA_NET, 1);
-#define f_const_empty_path f_const_empty(f_dummy_dynattr(EAF_TYPE_AS_PATH, T_PATH))
-#define f_const_empty_clist f_const_empty(f_dummy_dynattr(EAF_TYPE_INT_SET, T_CLIST))
-#define f_const_empty_eclist f_const_empty(f_dummy_dynattr(EAF_TYPE_EC_SET, T_ECLIST))
-#define f_const_empty_lclist f_const_empty(f_dummy_dynattr(EAF_TYPE_LC_SET, T_LCLIST))
+ return f_new_inst(FI_ROA_CHECK,
+ f_new_inst(FI_RTA_GET, fsa),
+ f_new_inst(FI_AS_PATH_LAST, f_new_inst(FI_EA_GET, def)),
+ tab);
+}
/*
* Remove all new lines and doubled whitespaces
| dynamic_attr '.' RESET{ }
*/
- | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_path); }
- | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_clist); }
- | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_eclist); }
- | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_lclist); }
- | '+' EMPTY '+' { $$ = f_const_empty_path; }
- | '-' EMPTY '-' { $$ = f_const_empty_clist; }
- | '-' '-' EMPTY '-' '-' { $$ = f_const_empty_eclist; }
- | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_const_empty_lclist; }
++ | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_PATH)); }
++ | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_CLIST)); }
++ | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_ECLIST)); }
++ | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_LCLIST)); }
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, $3, $5); }
| ADD '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD, $3, $5); }
| DELETE '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_DEL, $3, $5); }
(v.val.ad == &null_adata);
}
- extern const struct f_val f_const_empty_path, f_const_empty_clist, f_const_empty_eclist, f_const_empty_lclist, f_const_empty_prefix_set;
- static inline const struct f_val *f_get_empty(btype t)
+ extern const struct f_val f_const_empty_prefix_set;
++static inline struct f_val f_get_empty(btype t)
+{
+ switch (t) {
- case T_PATH: return &f_const_empty_path;
- case T_CLIST: return &f_const_empty_clist;
- case T_ECLIST: return &f_const_empty_eclist;
- case T_LCLIST: return &f_const_empty_lclist;
- default: return NULL;
++ case T_PATH:
++ case T_CLIST:
++ case T_ECLIST:
++ case T_LCLIST:
++ return (struct f_val) {
++ .type = t,
++ .val.ad = &null_adata,
++ };
++ default:
++ return (struct f_val) { .type = T_VOID };
+ }
+}
-enum filter_return f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres);
+enum filter_return f_eval(const struct f_line *expr, struct f_val *pres);
#endif
INST(FI_EA_GET, 0, 1) { /* Access to extended attributes */
DYNAMIC_ATTR;
ACCESS_RTE;
- ACCESS_EATTRS;
- RESULT_TYPE(da.f_type);
+ RESULT_TYPE(da->type);
{
- const struct f_val *empty;
- eattr *e = ea_find(*fs->eattrs, da.ea_code);
++ struct f_val empty;
+ const eattr *e = ea_find(fs->rte->attrs, da->id);
- if (!e) {
- /* A special case: undefined as_path looks like empty as_path */
- if (da.type == EAF_TYPE_AS_PATH) {
- RESULT_(T_PATH, ad, &null_adata);
- break;
- }
-
- /* The same special case for int_set */
- if (da.type == EAF_TYPE_INT_SET) {
- RESULT_(T_CLIST, ad, &null_adata);
- break;
- }
-
- /* The same special case for ec_set */
- if (da.type == EAF_TYPE_EC_SET) {
- RESULT_(T_ECLIST, ad, &null_adata);
- break;
- }
+ if (e)
+ {
+ ASSERT_DIE(e->type == da->type);
- /* The same special case for lc_set */
- if (da.type == EAF_TYPE_LC_SET) {
- RESULT_(T_LCLIST, ad, &null_adata);
- break;
+ switch (e->type) {
+ case T_IP:
+ RESULT_(T_IP, ip, *((const ip_addr *) e->u.ptr->data));
+ break;
+ default:
+ RESULT_VAL([[(struct f_val) {
+ .type = e->type,
+ .val.bval = e->u,
+ }]]);
}
-
- /* Undefined value */
- RESULT_VOID;
- break;
- }
-
- switch (e->type & EAF_TYPE_MASK) {
- case EAF_TYPE_INT:
- RESULT_(da.f_type, i, e->u.data);
- break;
- case EAF_TYPE_ROUTER_ID:
- RESULT_(T_QUAD, i, e->u.data);
- break;
- case EAF_TYPE_OPAQUE:
- RESULT_(T_ENUM_EMPTY, i, 0);
- break;
- case EAF_TYPE_IP_ADDRESS:
- RESULT_(T_IP, ip, *((ip_addr *) e->u.ptr->data));
- break;
- case EAF_TYPE_AS_PATH:
- RESULT_(T_PATH, ad, e->u.ptr);
- break;
- case EAF_TYPE_BITFIELD:
- RESULT_(T_BOOL, i, !!(e->u.data & (1u << da.bit)));
- break;
- case EAF_TYPE_INT_SET:
- RESULT_(T_CLIST, ad, e->u.ptr);
- break;
- case EAF_TYPE_EC_SET:
- RESULT_(T_ECLIST, ad, e->u.ptr);
- break;
- case EAF_TYPE_LC_SET:
- RESULT_(T_LCLIST, ad, e->u.ptr);
- break;
- default:
- bug("Unknown dynamic attribute type");
}
- else if (empty = f_get_empty(da->type))
- RESULT_VAL(*empty);
++ else if ((empty = f_get_empty(da->type)).type != T_VOID)
++ RESULT_VAL(empty);
+ else
+ RESULT_VOID;
}
}