From 52532335290457cc449564b7e011f73bef3a83e2 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 11 Apr 2015 17:02:13 +0100 Subject: expr: add set_elem_expr as container for set element attributes Add a new expression type "set_elem_expr" that is used as container for the key in order to attach different attributes, such as timeout values, to the key. The expression hierarchy is as follows: Sets: elem | key Maps: mapping / \ elem data | key Signed-off-by: Patrick McHardy --- src/netlink.c | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'src/netlink.c') diff --git a/src/netlink.c b/src/netlink.c index 343d8bea..0827034e 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -205,6 +205,7 @@ struct nft_set *alloc_nft_set(const struct handle *h) static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr) { + const struct expr *elem, *key, *data; struct nft_set_elem *nlse; struct nft_data_linearize nld; @@ -212,24 +213,28 @@ static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr) if (nlse == NULL) memory_allocation_error(); - if (expr->ops->type == EXPR_VALUE || - expr->flags & EXPR_F_INTERVAL_END) { - netlink_gen_data(expr, &nld); - nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY, - &nld.value, nld.len); + data = NULL; + if (expr->ops->type == EXPR_MAPPING) { + elem = expr->left; + if (!(expr->flags & EXPR_F_INTERVAL_END)) + data = expr->right; } else { - assert(expr->ops->type == EXPR_MAPPING); - netlink_gen_data(expr->left, &nld); - nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY, - &nld.value, nld.len); - netlink_gen_data(expr->right, &nld); - switch (expr->right->ops->type) { + elem = expr; + } + key = elem->key; + + netlink_gen_data(key, &nld); + nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY, &nld.value, nld.len); + + if (data != NULL) { + netlink_gen_data(data, &nld); + switch (data->ops->type) { case EXPR_VERDICT: nft_set_elem_attr_set_u32(nlse, NFT_SET_ELEM_ATTR_VERDICT, - expr->right->verdict); - if (expr->chain != NULL) + data->verdict); + if (data->chain != NULL) nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_CHAIN, - nld.chain, strlen(nld.chain)); + nld.chain, strlen(nld.chain)); break; case EXPR_VALUE: nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_DATA, @@ -1368,7 +1373,7 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse, struct set *set) { struct nft_data_delinearize nld; - struct expr *expr, *data; + struct expr *expr, *key, *data; uint32_t flags = 0; nld.value = @@ -1376,17 +1381,19 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse, if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_FLAGS)) flags = nft_set_elem_attr_get_u32(nlse, NFT_SET_ELEM_ATTR_FLAGS); - expr = netlink_alloc_value(&netlink_location, &nld); - expr->dtype = set->keytype; - expr->byteorder = set->keytype->byteorder; + key = netlink_alloc_value(&netlink_location, &nld); + key->dtype = set->keytype; + key->byteorder = set->keytype->byteorder; if (!(set->flags & SET_F_INTERVAL) && - expr->byteorder == BYTEORDER_HOST_ENDIAN) - mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE); + key->byteorder == BYTEORDER_HOST_ENDIAN) + mpz_switch_byteorder(key->value, key->len / BITS_PER_BYTE); + + if (key->dtype->basetype != NULL && + key->dtype->basetype->type == TYPE_BITMASK) + key = bitmask_expr_to_binops(key); - if (expr->dtype->basetype != NULL && - expr->dtype->basetype->type == TYPE_BITMASK) - expr = bitmask_expr_to_binops(expr); + expr = set_elem_expr_alloc(&netlink_location, key); if (flags & NFT_SET_ELEM_INTERVAL_END) { expr->flags |= EXPR_F_INTERVAL_END; -- cgit v1.2.3 From 38a077f7af8a2151b565e3cb324901b48afd299e Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 23 Mar 2015 21:34:57 +0000 Subject: set: add timeout support for sets Timeout support can be enabled in one of two ways: 1. Using a default timeout value: set test { type ipv4_addr; timeout 1h; } 2. Using the timeout flag without a default: set test { type ipv4_addr; flags timeout; } Optionally a garbage collection interval can be specified using gc-interval ; Signed-off-by: Patrick McHardy --- src/netlink.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/netlink.c') diff --git a/src/netlink.c b/src/netlink.c index 0827034e..e1d6421f 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1068,6 +1068,11 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx, set->datalen = data_len * BITS_PER_BYTE; } + if (nft_set_attr_is_set(nls, NFT_SET_ATTR_TIMEOUT)) + set->timeout = nft_set_attr_get_u64(nls, NFT_SET_ATTR_TIMEOUT); + if (nft_set_attr_is_set(nls, NFT_SET_ATTR_GC_INTERVAL)) + set->gc_int = nft_set_attr_get_u32(nls, NFT_SET_ATTR_GC_INTERVAL); + if (nft_set_attr_is_set(nls, NFT_SET_ATTR_POLICY)) set->policy = nft_set_attr_get_u32(nls, NFT_SET_ATTR_POLICY); @@ -1131,6 +1136,11 @@ static int netlink_add_set_batch(struct netlink_ctx *ctx, nft_set_attr_set_u32(nls, NFT_SET_ATTR_DATA_LEN, set->datalen / BITS_PER_BYTE); } + if (set->timeout) + nft_set_attr_set_u64(nls, NFT_SET_ATTR_TIMEOUT, set->timeout); + if (set->gc_int) + nft_set_attr_set_u32(nls, NFT_SET_ATTR_GC_INTERVAL, set->gc_int); + set->handle.set_id = ++set_id; nft_set_attr_set_u32(nls, NFT_SET_ATTR_ID, set->handle.set_id); -- cgit v1.2.3 From 7b5248972d9f2122c7b3683ca205d3165e7a9255 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 19 Mar 2015 13:34:18 +0000 Subject: setelem: add timeout support for set elements Support specifying per element timeout values and displaying the expiration time. If an element should not use the default timeout value of the set, an element specific value can be specified as follows: # nft add element filter test { 192.168.0.1, 192.168.0.2 timeout 10m} For listing of elements that use the default timeout value, just the expiration time is shown, otherwise the element specific timeout value is also displayed: set test { type ipv4_addr timeout 1h elements = { 192.168.0.2 timeout 10m expires 9m59s, 192.168.0.1 expires 59m59s} } Signed-off-by: Patrick McHardy --- src/netlink.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/netlink.c') diff --git a/src/netlink.c b/src/netlink.c index e1d6421f..7d675d7f 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -225,6 +225,9 @@ static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr) netlink_gen_data(key, &nld); nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY, &nld.value, nld.len); + if (elem->timeout) + nft_set_elem_attr_set_u64(nlse, NFT_SET_ELEM_ATTR_TIMEOUT, + elem->timeout); if (data != NULL) { netlink_gen_data(data, &nld); @@ -1404,6 +1407,10 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse, key = bitmask_expr_to_binops(key); expr = set_elem_expr_alloc(&netlink_location, key); + if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_TIMEOUT)) + expr->timeout = nft_set_elem_attr_get_u64(nlse, NFT_SET_ELEM_ATTR_TIMEOUT); + if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_EXPIRATION)) + expr->expiration = nft_set_elem_attr_get_u64(nlse, NFT_SET_ELEM_ATTR_EXPIRATION); if (flags & NFT_SET_ELEM_INTERVAL_END) { expr->flags |= EXPR_F_INTERVAL_END; -- cgit v1.2.3 From 35960e1e19bfe9135e33f13615d7d403d129192b Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 20 Mar 2015 06:30:29 +0000 Subject: setelem: add support for attaching comments to set elements Syntax: # nft add element filter test { 192.168.0.1 comment "some host" } Signed-off-by: Patrick McHardy --- src/netlink.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/netlink.c') diff --git a/src/netlink.c b/src/netlink.c index 7d675d7f..d31387f8 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -228,6 +228,9 @@ static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr) if (elem->timeout) nft_set_elem_attr_set_u64(nlse, NFT_SET_ELEM_ATTR_TIMEOUT, elem->timeout); + if (elem->comment) + nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_USERDATA, + elem->comment, strlen(elem->comment) + 1); if (data != NULL) { netlink_gen_data(data, &nld); @@ -1411,6 +1414,14 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse, expr->timeout = nft_set_elem_attr_get_u64(nlse, NFT_SET_ELEM_ATTR_TIMEOUT); if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_EXPIRATION)) expr->expiration = nft_set_elem_attr_get_u64(nlse, NFT_SET_ELEM_ATTR_EXPIRATION); + if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_USERDATA)) { + const void *data; + uint32_t len; + + data = nft_set_elem_attr_get(nlse, NFT_SET_ELEM_ATTR_USERDATA, &len); + expr->comment = xmalloc(len); + memcpy((char *)expr->comment, data, len); + } if (flags & NFT_SET_ELEM_INTERVAL_END) { expr->flags |= EXPR_F_INTERVAL_END; -- cgit v1.2.3