diff options
author | Maria Matejka <mq@ucw.cz> | 2019-06-19 14:09:57 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2019-06-19 14:09:57 +0200 |
commit | a84b8b6ebb2b6825b7059e34cfaafe405ab0117e (patch) | |
tree | 470357dba1529386a105ab3af32c2e5b754459dd /filter/f-inst.c | |
parent | 5c864e2cfaf5ff5e8e3db3ccd746162fbc7aac5b (diff) |
Revert "Filter: Dropped the setter instructions in favor of direct result storage."
This reverts commit bd91338246c1ba40358243f1bdf5a6dbd3a29f35.
Diffstat (limited to 'filter/f-inst.c')
-rw-r--r-- | filter/f-inst.c | 232 |
1 files changed, 218 insertions, 14 deletions
diff --git a/filter/f-inst.c b/filter/f-inst.c index 3be76d11..749e072c 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -36,7 +36,7 @@ * m4_dnl ACCESS_RTE; this instruction needs route * m4_dnl ACCESS_EATTRS; this instruction needs extended attributes * m4_dnl RESULT(type, union-field, value); putting this on value stack - * m4_dnl RESULT_PTR(vptr); put what is pointed-to on the value stack + * m4_dnl RESULT_OK; legalize what already is on the value stack * m4_dnl } * * Other code is just copied into the interpreter part. @@ -50,37 +50,41 @@ INST(FI_ADD, 2, 1) { ARG(1,T_INT); ARG(2,T_INT); - RESULT(T_INT, i, v1.val.i + v2.val.i); + res.val.i += v2.val.i; + RESULT_OK; } INST(FI_SUBTRACT, 2, 1) { ARG(1,T_INT); ARG(2,T_INT); - RESULT(T_INT, i, v1.val.i - v2.val.i); + res.val.i -= v2.val.i; + RESULT_OK; } INST(FI_MULTIPLY, 2, 1) { ARG(1,T_INT); ARG(2,T_INT); - RESULT(T_INT, i, v1.val.i * v2.val.i); + res.val.i *= v2.val.i; + RESULT_OK; } INST(FI_DIVIDE, 2, 1) { ARG(1,T_INT); ARG(2,T_INT); if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" ); - RESULT(T_INT, i, v1.val.i / v2.val.i); + res.val.i /= v2.val.i; + RESULT_OK; } INST(FI_AND, 1, 1) { ARG(1,T_BOOL); - if (v1.val.i) + if (res.val.i) LINE(2,0); else - RESULT_PTR(&(v1)); + RESULT_OK; } INST(FI_OR, 1, 1) { ARG(1,T_BOOL); - if (!v1.val.i) + if (!res.val.i) LINE(2,0); else - RESULT_PTR(&(v1)); + RESULT_OK; } INST(FI_PAIR_CONSTRUCT, 2, 1) { ARG(1,T_INT); @@ -277,7 +281,8 @@ INST(FI_VAR_GET, 0, 1) { SYMBOL(1); - RESULT_PTR(&(fstk->vstk[curline.vbase + sym->offset])); + res = fstk->vstk[curline.vbase + sym->offset]; + RESULT_OK; } /* some constants have value in a[1], some in *a[0].p, strange. */ @@ -298,7 +303,8 @@ debug("%svalue %s\n", INDENT, val_dump(&item->val)); FID_ALL - RESULT_PTR(&(whati->val)); + res = whati->val; + RESULT_OK; } INST(FI_CONSTANT_DEFINED, 0, 1) { FID_STRUCT_IN @@ -318,7 +324,8 @@ debug("%sconstant %s with value %s\n", INDENT, item->sym->name, val_dump(item->valp)); FID_ALL - RESULT_PTR(whati->valp); + res = *whati->valp; + RESULT_OK; } INST(FI_PRINT, 1, 0) { ARG_ANY(1); @@ -391,6 +398,76 @@ } } + INST(FI_RTA_SET, 1, 0) { + ACCESS_RTE; + ARG_ANY(1); + STATIC_ATTR; + if (sa.f_type != v1.type) + runtime( "Attempt to set static attribute to incompatible type" ); + + f_rta_cow(fs); + { + struct rta *rta = (*fs->rte)->attrs; + + switch (sa.sa_code) + { + case SA_FROM: + rta->from = v1.val.ip; + break; + + case SA_GW: + { + ip_addr ip = v1.val.ip; + neighbor *n = neigh_find(rta->src->proto, ip, NULL, 0); + if (!n || (n->scope == SCOPE_HOST)) + runtime( "Invalid gw address" ); + + rta->dest = RTD_UNICAST; + rta->nh.gw = ip; + rta->nh.iface = n->iface; + rta->nh.next = NULL; + rta->hostentry = NULL; + } + break; + + case SA_SCOPE: + rta->scope = v1.val.i; + break; + + case SA_DEST: + { + int i = v1.val.i; + if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT)) + runtime( "Destination can be changed only to blackhole, unreachable or prohibit" ); + + rta->dest = i; + rta->nh.gw = IPA_NONE; + rta->nh.iface = NULL; + rta->nh.next = NULL; + rta->hostentry = NULL; + } + break; + + case SA_IFNAME: + { + struct iface *ifa = if_find_by_name(v1.val.s); + if (!ifa) + runtime( "Invalid iface name" ); + + rta->dest = RTD_UNICAST; + rta->nh.gw = IPA_NONE; + rta->nh.iface = ifa; + rta->nh.next = NULL; + rta->hostentry = NULL; + } + break; + + default: + bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code); + } + } + } + INST(FI_EA_GET, 0, 1) { /* Access to extended attributes */ DYNAMIC_ATTR; ACCESS_RTE; @@ -424,7 +501,8 @@ } /* Undefined value */ - RESULT_VOID; + res.type = T_VOID; + RESULT_OK; break; } @@ -457,7 +535,8 @@ RESULT(T_LCLIST, ad, e->u.ptr); break; case EAF_TYPE_UNDEF: - RESULT_VOID; + res.type = T_VOID; + RESULT_OK; break; default: bug("Unknown dynamic attribute type"); @@ -465,6 +544,95 @@ } } + INST(FI_EA_SET, 1, 0) { + ACCESS_RTE; + ACCESS_EATTRS; + ARG_ANY(1); + DYNAMIC_ATTR; + { + struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr)); + + l->next = NULL; + l->flags = EALF_SORTED; + l->count = 1; + l->attrs[0].id = da.ea_code; + l->attrs[0].flags = 0; + l->attrs[0].type = da.type | EAF_ORIGINATED | EAF_FRESH; + + switch (da.type) { + case EAF_TYPE_INT: + if (v1.type != da.f_type) + runtime( "Setting int attribute to non-int value" ); + l->attrs[0].u.data = v1.val.i; + break; + + case EAF_TYPE_ROUTER_ID: + /* IP->Quad implicit conversion */ + if (val_is_ip4(&v1)) { + l->attrs[0].u.data = ipa_to_u32(v1.val.ip); + break; + } + /* T_INT for backward compatibility */ + if ((v1.type != T_QUAD) && (v1.type != T_INT)) + runtime( "Setting quad attribute to non-quad value" ); + l->attrs[0].u.data = v1.val.i; + break; + + case EAF_TYPE_OPAQUE: + runtime( "Setting opaque attribute is not allowed" ); + break; + case EAF_TYPE_IP_ADDRESS: + if (v1.type != T_IP) + runtime( "Setting ip attribute to non-ip value" ); + int len = sizeof(ip_addr); + struct adata *ad = lp_alloc(fs->pool, sizeof(struct adata) + len); + ad->length = len; + (* (ip_addr *) ad->data) = v1.val.ip; + l->attrs[0].u.ptr = ad; + 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_BITFIELD: + if (v1.type != T_BOOL) + runtime( "Setting bit in bitfield attribute to non-bool value" ); + { + /* First, we have to find the old value */ + eattr *e = ea_find(*fs->eattrs, da.ea_code); + u32 data = e ? e->u.data : 0; + + if (v1.val.i) + l->attrs[0].u.data = data | (1u << da.bit); + else + l->attrs[0].u.data = data & ~(1u << da.bit); + } + break; + case EAF_TYPE_INT_SET: + if (v1.type != T_CLIST) + runtime( "Setting clist attribute to non-clist value" ); + l->attrs[0].u.ptr = v1.val.ad; + break; + case EAF_TYPE_EC_SET: + if (v1.type != T_ECLIST) + runtime( "Setting eclist attribute to non-eclist value" ); + l->attrs[0].u.ptr = v1.val.ad; + break; + case EAF_TYPE_LC_SET: + if (v1.type != T_LCLIST) + runtime( "Setting lclist attribute to non-lclist value" ); + l->attrs[0].u.ptr = v1.val.ad; + break; + default: bug("Unknown type in e,S"); + } + + f_rta_cow(fs); + l->next = *fs->eattrs; + *fs->eattrs = l; + } + } + INST(FI_EA_UNSET, 0, 0) { DYNAMIC_ATTR; ACCESS_RTE; @@ -492,6 +660,15 @@ RESULT(T_INT, i, (*fs->rte)->pref); } + INST(FI_PREF_SET, 1, 0) { + ACCESS_RTE; + ARG(1,T_INT); + if (v1.val.i > 0xFFFF) + runtime( "Setting preference value out of bounds" ); + f_rte_cow(fs); + (*fs->rte)->pref = v1.val.i; + } + INST(FI_LENGTH, 1, 1) { /* Get length of */ ARG_ANY(1); switch(v1.type) { @@ -567,6 +744,33 @@ RESULT(T_INT, i, as_path_get_last_nonaggregated(v1.val.ad)); } + INST(FI_RETURN, 1, 1) { + /* Acquire the return value */ + ARG_ANY(1); + uint retpos = fstk->vcnt; + + /* Drop every sub-block including ourselves */ + while ((fstk->ecnt-- > 0) && !(fstk->estk[fstk->ecnt].emask & FE_RETURN)) + ; + + /* Now we are at the caller frame; if no such, try to convert to accept/reject. */ + if (!fstk->ecnt) + if (fstk->vstk[retpos].type == T_BOOL) + if (fstk->vstk[retpos].val.i) + + return F_ACCEPT; + else + return F_REJECT; + else + runtime("Can't return non-bool from non-function"); + + /* Set the value stack position, overwriting the former implicit void */ + fstk->vcnt = fstk->estk[fstk->ecnt].ventry - 1; + + /* Copy the return value */ + RESULT_VAL(fstk->vstk[retpos]); + } + INST(FI_CALL, 0, 1) { SYMBOL; |