diff options
-rw-r--r-- | src/expression.c | 17 | ||||
-rw-r--r-- | src/netlink.c | 10 | ||||
-rw-r--r-- | tests/py/bridge/vlan.t | 2 | ||||
-rw-r--r-- | tests/py/bridge/vlan.t.json | 41 | ||||
-rw-r--r-- | tests/py/bridge/vlan.t.payload | 12 | ||||
-rw-r--r-- | tests/py/bridge/vlan.t.payload.netdev | 14 |
6 files changed, 91 insertions, 5 deletions
diff --git a/src/expression.c b/src/expression.c index deb649e1..7390089c 100644 --- a/src/expression.c +++ b/src/expression.c @@ -879,17 +879,30 @@ static void concat_expr_print(const struct expr *expr, struct output_ctx *octx) #define NFTNL_UDATA_SET_KEY_CONCAT_SUB_DATA 1 #define NFTNL_UDATA_SET_KEY_CONCAT_SUB_MAX 2 +static struct expr *expr_build_udata_recurse(struct expr *e) +{ + switch (e->etype) { + case EXPR_BINOP: + return e->left; + default: + break; + } + + return e; +} + static int concat_expr_build_udata(struct nftnl_udata_buf *udbuf, const struct expr *concat_expr) { struct nftnl_udata *nest; + struct expr *expr, *tmp; unsigned int i = 0; - struct expr *expr; - list_for_each_entry(expr, &concat_expr->expressions, list) { + list_for_each_entry_safe(expr, tmp, &concat_expr->expressions, list) { struct nftnl_udata *nest_expr; int err; + expr = expr_build_udata_recurse(expr); if (!expr_ops(expr)->build_udata || i >= NFT_REG32_SIZE) return -1; diff --git a/src/netlink.c b/src/netlink.c index 89d864ed..799cf9b8 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1114,17 +1114,21 @@ static struct expr *concat_elem_expr(struct expr *key, struct expr *data, int *off) { const struct datatype *subtype; + unsigned int sub_length; struct expr *expr; if (key) { (*off)--; - expr = constant_expr_splice(data, key->len); + sub_length = round_up(key->len, BITS_PER_BYTE); + + expr = constant_expr_splice(data, sub_length); expr->dtype = datatype_get(key->dtype); expr->byteorder = key->byteorder; expr->len = key->len; } else { subtype = concat_subtype_lookup(dtype->type, --(*off)); - expr = constant_expr_splice(data, subtype->size); + sub_length = round_up(subtype->size, BITS_PER_BYTE); + expr = constant_expr_splice(data, sub_length); expr->dtype = subtype; expr->byteorder = subtype->byteorder; } @@ -1136,7 +1140,7 @@ static struct expr *concat_elem_expr(struct expr *key, expr->dtype->basetype->type == TYPE_BITMASK) expr = bitmask_expr_to_binops(expr); - data->len -= netlink_padding_len(expr->len); + data->len -= netlink_padding_len(sub_length); return expr; } diff --git a/tests/py/bridge/vlan.t b/tests/py/bridge/vlan.t index 49206017..95bdff4f 100644 --- a/tests/py/bridge/vlan.t +++ b/tests/py/bridge/vlan.t @@ -50,3 +50,5 @@ vlan id 1 vlan id set 2;ok ether saddr 00:01:02:03:04:05 vlan id 1;ok vlan id 2 ether saddr 0:1:2:3:4:6;ok;ether saddr 00:01:02:03:04:06 vlan id 2 + +ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 };ok diff --git a/tests/py/bridge/vlan.t.json b/tests/py/bridge/vlan.t.json index 58d4a40f..f77756f5 100644 --- a/tests/py/bridge/vlan.t.json +++ b/tests/py/bridge/vlan.t.json @@ -817,3 +817,44 @@ } } ] + +# ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 } +[ + { + "match": { + "left": { + "concat": [ + { + "payload": { + "field": "saddr", + "protocol": "ether" + } + }, + { + "payload": { + "field": "id", + "protocol": "vlan" + } + } + ] + }, + "op": "==", + "right": { + "set": [ + { + "concat": [ + "0a:0b:0c:0d:0e:0f", + 42 + ] + }, + { + "concat": [ + "0a:0b:0c:0d:0e:0f", + 4095 + ] + } + ] + } + } + } +] diff --git a/tests/py/bridge/vlan.t.payload b/tests/py/bridge/vlan.t.payload index 713670e9..62e4b89b 100644 --- a/tests/py/bridge/vlan.t.payload +++ b/tests/py/bridge/vlan.t.payload @@ -292,3 +292,15 @@ bridge test-bridge input [ payload load 2b @ link header + 14 => reg 1 ] [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ] [ cmp eq reg 1 0x00000200 ] + +# ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 } +__set%d test-bridge 3 size 2 +__set%d test-bridge 0 + element 0d0c0b0a 00000f0e 00002a00 : 0 [end] element 0d0c0b0a 00000f0e 0000ff0f : 0 [end] +bridge test-bridge input + [ payload load 2b @ link header + 12 => reg 1 ] + [ cmp eq reg 1 0x00000081 ] + [ payload load 6b @ link header + 6 => reg 1 ] + [ payload load 2b @ link header + 14 => reg 10 ] + [ bitwise reg 10 = ( reg 10 & 0x0000ff0f ) ^ 0x00000000 ] + [ lookup reg 1 set __set%d ] diff --git a/tests/py/bridge/vlan.t.payload.netdev b/tests/py/bridge/vlan.t.payload.netdev index 98a2a2b0..1018d4c6 100644 --- a/tests/py/bridge/vlan.t.payload.netdev +++ b/tests/py/bridge/vlan.t.payload.netdev @@ -342,3 +342,17 @@ netdev test-netdev ingress [ payload load 2b @ link header + 14 => reg 1 ] [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ] [ cmp eq reg 1 0x00000100 ] + +# ether saddr . vlan id { 0a:0b:0c:0d:0e:0f . 42, 0a:0b:0c:0d:0e:0f . 4095 } +__set%d test-netdev 3 size 2 +__set%d test-netdev 0 + element 0d0c0b0a 00000f0e 00002a00 : 0 [end] element 0d0c0b0a 00000f0e 0000ff0f : 0 [end] +netdev test-netdev ingress + [ meta load iiftype => reg 1 ] + [ cmp eq reg 1 0x00000001 ] + [ payload load 2b @ link header + 12 => reg 1 ] + [ cmp eq reg 1 0x00000081 ] + [ payload load 6b @ link header + 6 => reg 1 ] + [ payload load 2b @ link header + 14 => reg 10 ] + [ bitwise reg 10 = ( reg 10 & 0x0000ff0f ) ^ 0x00000000 ] + [ lookup reg 1 set __set%d ] |