return -1;
right = rel->right;
- if (rel->op == OP_IMPLICIT) {
- switch (right->ops->type) {
- case EXPR_RANGE:
- rel->op = OP_RANGE;
- break;
- case EXPR_SET:
- case EXPR_SET_REF:
- rel->op = OP_LOOKUP;
- break;
- case EXPR_LIST:
- rel->op = OP_FLAGCMP;
- break;
- default:
- if (right->dtype->basetype != NULL &&
- right->dtype->basetype->type == TYPE_BITMASK)
- rel->op = OP_FLAGCMP;
- else
- rel->op = OP_EQ;
- break;
- }
- }
-
if (!expr_is_constant(right))
return expr_binary_error(ctx->msgs, right, rel,
"Right hand side of relational "
"constant value",
expr_op_symbols[rel->op]);
+ if (!datatype_equal(left->dtype, right->dtype))
+ return expr_binary_error(ctx->msgs, right, left,
+ "datatype mismatch, expected %s, "
+ "expression has type %s",
+ left->dtype->desc,
+ right->dtype->desc);
+
switch (rel->op) {
- case OP_LOOKUP:
- /* A literal set expression implicitly declares the set */
- if (right->ops->type == EXPR_SET)
- right = rel->right =
- implicit_set_declaration(ctx, "__set%d",
- left, right);
- else if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "set has type %s",
- left->dtype->desc,
- right->dtype->desc);
-
- /* Data for range lookups needs to be in big endian order */
- if (right->set->flags & NFT_SET_INTERVAL &&
- byteorder_conversion(ctx, &rel->left,
- BYTEORDER_BIG_ENDIAN) < 0)
- return -1;
- left = rel->left;
- break;
case OP_EQ:
- if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "expression has type %s",
- left->dtype->desc,
- right->dtype->desc);
+ case OP_IMPLICIT:
/*
* Update protocol context for payload and meta iiftype
* equality expressions.
*/
- relational_expr_pctx_update(&ctx->pctx, rel);
-
- if (left->ops->type == EXPR_CONCAT)
- return 0;
+ if (expr_is_singleton(right))
+ relational_expr_pctx_update(&ctx->pctx, rel);
/* fall through */
case OP_NEQ:
- case OP_FLAGCMP:
- if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "expression has type %s",
- left->dtype->desc,
- right->dtype->desc);
-
switch (right->ops->type) {
case EXPR_RANGE:
- goto range;
+ if (byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
+ return -1;
+ if (byteorder_conversion(ctx, &right->left, BYTEORDER_BIG_ENDIAN) < 0)
+ return -1;
+ if (byteorder_conversion(ctx, &right->right, BYTEORDER_BIG_ENDIAN) < 0)
+ return -1;
+ break;
case EXPR_PREFIX:
if (byteorder_conversion(ctx, &right->prefix, left->byteorder) < 0)
return -1;
return -1;
break;
case EXPR_SET:
- assert(rel->op == OP_NEQ);
right = rel->right =
implicit_set_declaration(ctx, "__set%d", left, right);
/* fall through */
case EXPR_SET_REF:
- assert(rel->op == OP_NEQ);
/* Data for range lookups needs to be in big endian order */
if (right->set->flags & NFT_SET_INTERVAL &&
byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
case OP_GT:
case OP_LTE:
case OP_GTE:
- if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "expression has type %s",
- left->dtype->desc,
- right->dtype->desc);
-
switch (left->ops->type) {
case EXPR_CONCAT:
return expr_binary_error(ctx->msgs, left, rel,
if (byteorder_conversion(ctx, &rel->right, BYTEORDER_BIG_ENDIAN) < 0)
return -1;
break;
- case OP_RANGE:
- if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "expression has type %s",
- left->dtype->desc,
- right->dtype->desc);
-
-range:
- switch (left->ops->type) {
- case EXPR_CONCAT:
- return expr_binary_error(ctx->msgs, left, rel,
- "Relational expression (%s) is undefined"
- "for %s expressions",
- expr_op_symbols[rel->op],
- left->ops->name);
- default:
- break;
- }
-
- if (byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
- return -1;
- if (byteorder_conversion(ctx, &right->left, BYTEORDER_BIG_ENDIAN) < 0)
- return -1;
- if (byteorder_conversion(ctx, &right->right, BYTEORDER_BIG_ENDIAN) < 0)
- return -1;
- break;
default:
BUG("invalid relational operation %u\n", rel->op);
}
if (dreg != NFT_REG_VERDICT)
return netlink_set_register(ctx, dreg, expr);
} else {
- expr = relational_expr_alloc(loc, OP_LOOKUP, left, right);
+ expr = relational_expr_alloc(loc, OP_EQ, left, right);
}
if (nftnl_expr_is_set(nle, NFTNL_EXPR_LOOKUP_FLAGS)) {
const struct expr *left = expr->left;
struct expr *right = expr->right;
+ if (right->ops->type == EXPR_SET || right->ops->type == EXPR_SET_REF)
+ expr_set_type(right, left->dtype, left->byteorder);
+
switch (expr->op) {
case OP_EQ:
- if (expr->right->ops->type == EXPR_RANGE)
+ if (expr->right->ops->type == EXPR_RANGE ||
+ expr->right->ops->type == EXPR_SET ||
+ expr->right->ops->type == EXPR_SET_REF)
break;
relational_expr_pctx_update(&ctx->pctx, expr);
payload_dependency_store(&ctx->pdctx, ctx->stmt, base);
}
break;
- case OP_NEQ:
- if (right->ops->type != EXPR_SET && right->ops->type != EXPR_SET_REF)
- break;
- /* fall through */
- case OP_LOOKUP:
- expr_set_type(right, left->dtype, left->byteorder);
- break;
-
default:
break;
}
/* Flag comparison: data & flags != 0
*
* Split the flags into a list of flag values and convert the
- * op to OP_FLAGCMP.
+ * op to OP_EQ.
*/
expr_free(value);
expr->left = expr_get(binop->left);
expr->right = binop_tree_to_list(NULL, binop->right);
- expr->op = OP_FLAGCMP;
+ expr->op = OP_EQ;
expr_free(binop);
} else if (binop->left->dtype->flags & DTYPE_F_PREFIX &&
{
switch (op) {
case OP_EQ:
+ case OP_IMPLICIT:
return NFT_CMP_EQ;
case OP_NEQ:
return NFT_CMP_NEQ;
static void netlink_gen_range(struct netlink_linearize_ctx *ctx,
const struct expr *expr,
enum nft_registers dreg);
+static void netlink_gen_flagcmp(struct netlink_linearize_ctx *ctx,
+ const struct expr *expr,
+ enum nft_registers dreg);
static struct expr *netlink_gen_prefix(struct netlink_linearize_ctx *ctx,
const struct expr *expr,
case EXPR_SET:
case EXPR_SET_REF:
return netlink_gen_lookup(ctx, expr, dreg);
+ case EXPR_LIST:
+ return netlink_gen_flagcmp(ctx, expr, dreg);
case EXPR_PREFIX:
sreg = get_register(ctx, expr->left);
if (expr_basetype(expr->left)->type != TYPE_STRING) {
}
break;
default:
+ if (expr->op == OP_IMPLICIT &&
+ expr->right->dtype->basetype != NULL &&
+ expr->right->dtype->basetype->type == TYPE_BITMASK)
+ return netlink_gen_flagcmp(ctx, expr, dreg);
+
sreg = get_register(ctx, expr->left);
len = div_round_up(expr->right->len, BITS_PER_BYTE);
right = expr->right;
nld.value, nld.len);
nftnl_rule_add_expr(ctx->nlr, nle);
break;
- case OP_RANGE:
case OP_EQ:
+ case OP_IMPLICIT:
nle = alloc_nft_expr("cmp");
netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP,
enum nft_registers dreg)
{
switch (expr->op) {
+ case OP_IMPLICIT:
case OP_EQ:
case OP_NEQ:
case OP_LT:
case OP_LTE:
case OP_GTE:
return netlink_gen_cmp(ctx, expr, dreg);
- case OP_RANGE:
- return netlink_gen_range(ctx, expr, dreg);
- case OP_FLAGCMP:
- return netlink_gen_flagcmp(ctx, expr, dreg);
- case OP_LOOKUP:
- return netlink_gen_lookup(ctx, expr, dreg);
default:
BUG("invalid relational operation %u\n", expr->op);
}