From 27d01216cf05eb0b49b6456137e01a44d4547796 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 30 Jul 2020 11:54:36 +0200 Subject: nft: Eliminate table list from cache The full list of tables in kernel is not relevant, only those used by iptables-nft and for those, knowing if they exist or not is sufficient. For holding that information, the already existing 'table' array in nft_cache suits well. Consequently, nft_table_find() merely checks if the new 'exists' boolean is true or not and nft_for_each_table() iterates over the builtin_table array in nft_handle, additionally checking the boolean in cache for whether to skip the entry or not. Signed-off-by: Phil Sutter --- iptables/nft-cache.c | 73 +++++++++++++--------------------------------------- 1 file changed, 18 insertions(+), 55 deletions(-) (limited to 'iptables/nft-cache.c') diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c index bf1fb346..c6baf090 100644 --- a/iptables/nft-cache.c +++ b/iptables/nft-cache.c @@ -107,59 +107,30 @@ static void mnl_genid_get(struct nft_handle *h, uint32_t *genid) "Could not fetch rule set generation id: %s\n", nft_strerror(errno)); } -static struct nft_table *nft_table_alloc(void) -{ - struct nftnl_table *nftnl; - struct nft_table *table; - - table = malloc(sizeof(struct nft_table)); - if (!table) - return NULL; - - nftnl = nftnl_table_alloc(); - if (!nftnl) { - free(table); - return NULL; - } - table->nftnl = nftnl; - - return table; -} - -static void nft_table_free(struct nft_table *table) +static int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data) { - nftnl_table_free(table->nftnl); - free(table); -} + struct nftnl_table *nftnl = nftnl_table_alloc(); + const struct builtin_table *t; + struct nft_handle *h = data; + const char *name; -static void nft_table_list_free(struct list_head *table_list) -{ - struct nft_table *table, *next; + if (!nftnl) + return MNL_CB_OK; - list_for_each_entry_safe(table, next, table_list, list) { - list_del(&table->list); - nft_table_free(table); - } -} + if (nftnl_table_nlmsg_parse(nlh, nftnl) < 0) + goto out; -static int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data) -{ - struct list_head *list = data; - struct nft_table *t; + name = nftnl_table_get_str(nftnl, NFTNL_TABLE_NAME); + if (!name) + goto out; - t = nft_table_alloc(); + t = nft_table_builtin_find(h, name); if (!t) - goto err; - - if (nftnl_table_nlmsg_parse(nlh, t->nftnl) < 0) goto out; - list_add_tail(&t->list, list); - - return MNL_CB_OK; + h->cache->table[t->type].exists = true; out: - nft_table_free(t); -err: + nftnl_table_free(nftnl); return MNL_CB_OK; } @@ -169,13 +140,10 @@ static int fetch_table_cache(struct nft_handle *h) char buf[16536]; int i, ret; - if (!list_empty(&h->cache->tables)) - return 0; - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family, NLM_F_DUMP, h->seq); - ret = mnl_talk(h, nlh, nftnl_table_list_cb, &h->cache->tables); + ret = mnl_talk(h, nlh, nftnl_table_list_cb, h); if (ret < 0 && errno == EINTR) assert(nft_restart(h) >= 0); @@ -635,9 +603,9 @@ static int flush_cache(struct nft_handle *h, struct nft_cache *c, nftnl_set_list_free(c->table[i].sets); c->table[i].sets = NULL; } + + c->table[i].exists = false; } - if (!list_empty(&c->tables)) - nft_table_list_free(&c->tables); return 1; } @@ -710,11 +678,6 @@ void nft_release_cache(struct nft_handle *h) } } -struct list_head *nft_table_list_get(struct nft_handle *h) -{ - return &h->cache->tables; -} - struct nftnl_set_list * nft_set_list_get(struct nft_handle *h, const char *table, const char *set) { -- cgit v1.2.3