diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2022-05-01 17:40:01 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2022-05-04 11:58:01 +0200 |
commit | b9e00458b9f357f6c9b301f95b276fd019da0692 (patch) | |
tree | 7bda5c1f1b684da25e864b42feb28d2f76a86a78 /src/expr/meta.c | |
parent | e2514c0eff4da7e8e0aabd410f7b7d0b7564c880 (diff) |
src: add dynamic register allocation infrastructure
Starting Linux kernel 5.18-rc, operations on registers that already
contain the expected data are turned into noop.
Track operation on registers to use the same register through
nftnl_reg_get(). This patch introduces an LRU eviction strategy when all
the registers are in used.
nftnl_reg_get_scratch() is used to allocate a register as scratchpad
area: no tracking is performed in this case, although register eviction
might occur.
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/expr/meta.c')
-rw-r--r-- | src/expr/meta.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/expr/meta.c b/src/expr/meta.c index 34fbb9b..601248f 100644 --- a/src/expr/meta.c +++ b/src/expr/meta.c @@ -14,6 +14,7 @@ #include <string.h> #include <arpa/inet.h> #include <errno.h> +#include <net/if.h> #include <linux/netfilter/nf_tables.h> #include "internal.h" @@ -132,6 +133,44 @@ nftnl_expr_meta_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } +static int nftnl_meta_reg_len(const struct nftnl_expr *e) +{ + const struct nftnl_expr_meta *meta = nftnl_expr_data(e); + + switch (meta->key) { + case NFT_META_IIFNAME: + case NFT_META_OIFNAME: + case NFT_META_IIFKIND: + case NFT_META_OIFKIND: + case NFT_META_SDIFNAME: + case NFT_META_BRI_IIFNAME: + case NFT_META_BRI_OIFNAME: + return IFNAMSIZ; + case NFT_META_TIME_NS: + return sizeof(uint64_t); + default: + break; + } + + return sizeof(uint32_t); +} + +static bool nftnl_meta_reg_cmp(const struct nftnl_reg *reg, + const struct nftnl_expr *e) +{ + const struct nftnl_expr_meta *meta = nftnl_expr_data(e); + + return reg->meta.key == meta->key; +} + +static void nftnl_meta_reg_update(struct nftnl_reg *reg, + const struct nftnl_expr *e) +{ + const struct nftnl_expr_meta *meta = nftnl_expr_data(e); + + reg->meta.key = meta->key; +} + static const char *meta_key2str_array[NFT_META_MAX] = { [NFT_META_LEN] = "len", [NFT_META_PROTOCOL] = "protocol", @@ -217,4 +256,9 @@ struct expr_ops expr_ops_meta = { .parse = nftnl_expr_meta_parse, .build = nftnl_expr_meta_build, .snprintf = nftnl_expr_meta_snprintf, + .reg = { + .len = nftnl_meta_reg_len, + .cmp = nftnl_meta_reg_cmp, + .update = nftnl_meta_reg_update, + }, }; |