struct list_head expressions;
unsigned int size;
uint32_t set_flags;
+ uint8_t field_len[NFT_REG32_COUNT];
+ uint8_t field_count;
};
struct {
/* EXPR_SET_REF */
* @rg_cache: cached range element (left)
* @policy: set mechanism policy
* @automerge: merge adjacents and overlapping elements, if possible
- * @desc: set mechanism desc
+ * @desc.size: count of set elements
+ * @desc.field_len: length of single concatenated fields, bytes
+ * @desc.field_count: count of concatenated fields
*/
struct set {
struct list_head list;
bool key_typeof_valid;
struct {
uint32_t size;
+ uint8_t field_len[NFT_REG32_COUNT];
+ uint8_t field_count;
} desc;
};
struct expr *i, *next;
list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
+ unsigned dsize_bytes;
+
if (expr_is_constant(*expr) && dtype && off == 0)
return expr_binary_error(ctx->msgs, i, *expr,
"unexpected concat component, "
i->dtype->name);
ntype = concat_subtype_add(ntype, i->dtype->type);
+
+ dsize_bytes = div_round_up(i->dtype->size, BITS_PER_BYTE);
+ (*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
}
(*expr)->flags |= flags;
return set_key_data_error(ctx, set,
set->key->dtype, type);
}
- if (set->flags & NFT_SET_INTERVAL &&
- set->key->etype == EXPR_CONCAT)
- return set_error(ctx, set, "concatenated types not supported in interval sets");
+
+ if (set->flags & NFT_SET_INTERVAL && set->key->etype == EXPR_CONCAT) {
+ memcpy(&set->desc.field_len, &set->key->field_len,
+ sizeof(set->desc.field_len));
+ set->desc.field_count = set->key->field_count;
+ }
if (set_is_datamap(set->flags)) {
if (set->data == NULL)
if (set->data)
set_key_expression(ctx, set->data, set->flags, udbuf, NFTNL_UDATA_SET_DATA_TYPEOF);
+ if (set->desc.field_len[0]) {
+ nftnl_set_set_data(nls, NFTNL_SET_DESC_CONCAT,
+ set->desc.field_len,
+ set->desc.field_count *
+ sizeof(set->desc.field_len[0]));
+ }
+
nftnl_set_set_data(nls, NFTNL_SET_USERDATA, nftnl_udata_buf_data(udbuf),
nftnl_udata_buf_len(udbuf));
nftnl_udata_buf_free(udbuf);
if (nftnl_set_is_set(nls, NFTNL_SET_DESC_SIZE))
set->desc.size = nftnl_set_get_u32(nls, NFTNL_SET_DESC_SIZE);
+ if (nftnl_set_is_set(nls, NFTNL_SET_DESC_CONCAT)) {
+ uint32_t len = NFT_REG32_COUNT;
+ const uint8_t *data;
+
+ data = nftnl_set_get_data(nls, NFTNL_SET_DESC_CONCAT, &len);
+ if (data) {
+ memcpy(set->desc.field_len, data, len);
+ set->desc.field_count = len;
+ }
+ }
+
return set;
}
new_set->objtype = set->objtype;
new_set->policy = set->policy;
new_set->automerge = set->automerge;
- new_set->desc.size = set->desc.size;
+ new_set->desc = set->desc;
return new_set;
}