summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/netlink_delinearize.c46
-rwxr-xr-xtests/shell/testcases/sets/0045concat_ipv4_service16
-rw-r--r--tests/shell/testcases/sets/dumps/0045concat_ipv4_service.nft12
3 files changed, 73 insertions, 1 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index bd75ad5c..0c2b439e 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -134,6 +134,50 @@ err:
return NULL;
}
+static struct expr *netlink_parse_concat_key(struct netlink_parse_ctx *ctx,
+ const struct location *loc,
+ unsigned int reg,
+ const struct expr *key)
+{
+ uint32_t type = key->dtype->type;
+ unsigned int n, len = key->len;
+ struct expr *concat, *expr;
+ unsigned int consumed;
+
+ concat = concat_expr_alloc(loc);
+ n = div_round_up(fls(type), TYPE_BITS);
+
+ while (len > 0) {
+ const struct datatype *i;
+
+ expr = netlink_get_register(ctx, loc, reg);
+ if (expr == NULL) {
+ netlink_error(ctx, loc,
+ "Concat expression size mismatch");
+ goto err;
+ }
+
+ if (n > 0 && concat_subtype_id(type, --n)) {
+ i = concat_subtype_lookup(type, n);
+
+ expr_set_type(expr, i, i->byteorder);
+ }
+
+ compound_expr_add(concat, expr);
+
+ consumed = netlink_padded_len(expr->len);
+ assert(consumed > 0);
+ len -= consumed;
+ reg += netlink_register_space(expr->len);
+ }
+
+ return concat;
+
+err:
+ expr_free(concat);
+ return NULL;
+}
+
static struct expr *netlink_parse_concat_data(struct netlink_parse_ctx *ctx,
const struct location *loc,
unsigned int reg,
@@ -1572,7 +1616,7 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx,
if (expr->len < set->key->len) {
expr_free(expr);
- expr = netlink_parse_concat_expr(ctx, loc, sreg, set->key->len);
+ expr = netlink_parse_concat_key(ctx, loc, sreg, set->key);
if (expr == NULL)
return;
}
diff --git a/tests/shell/testcases/sets/0045concat_ipv4_service b/tests/shell/testcases/sets/0045concat_ipv4_service
new file mode 100755
index 00000000..5b40f973
--- /dev/null
+++ b/tests/shell/testcases/sets/0045concat_ipv4_service
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+$NFT -f - <<EOF
+table inet t {
+ set s {
+ type ipv4_addr . inet_service
+ size 65536
+ flags dynamic,timeout
+ elements = { 192.168.7.1 . 22 }
+ }
+
+ chain c {
+ tcp dport 21 add @s { ip saddr . 22 timeout 60s }
+ }
+}
+EOF
diff --git a/tests/shell/testcases/sets/dumps/0045concat_ipv4_service.nft b/tests/shell/testcases/sets/dumps/0045concat_ipv4_service.nft
new file mode 100644
index 00000000..e548a17a
--- /dev/null
+++ b/tests/shell/testcases/sets/dumps/0045concat_ipv4_service.nft
@@ -0,0 +1,12 @@
+table inet t {
+ set s {
+ type ipv4_addr . inet_service
+ size 65536
+ flags dynamic,timeout
+ elements = { 192.168.7.1 . 22 }
+ }
+
+ chain c {
+ tcp dport 21 add @s { ip saddr . 22 timeout 1m }
+ }
+}