From 8b38ab8ead7829569ab6a3c9fa7a193d568b707a Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:18 +0100
Subject: [PATCH] xtables: Optimize list command with given chain
Make use of nftnl_chain_list_lookup_byname() even if not listing a
specific rule. Introduce __nft_print_header() to consolidate chain value
extraction for printing with ops->print_header().
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 11cbd7291f37fbfd5ebe6ffa1730f7d198ed2ac0)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 78 +++++++++++++++++++++-----------------------------
1 file changed, 32 insertions(+), 46 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 162d91e82115b..e1c997836cb97 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2247,6 +2247,24 @@ static int nft_rule_count(struct nft_handle *h, struct nftnl_chain *c)
return rule_ctr;
}
+static void __nft_print_header(struct nft_handle *h,
+ const struct nft_family_ops *ops,
+ struct nftnl_chain *c, unsigned int format)
+{
+ const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+ uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
+ bool basechain = !!nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM);
+ uint32_t refs = nftnl_chain_get_u32(c, NFTNL_CHAIN_USE);
+ uint32_t entries = nft_rule_count(h, c);
+ struct xt_counters ctrs = {
+ .pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
+ .bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES),
+ };
+
+ ops->print_header(format, chain_name, policy_name[policy],
+ &ctrs, basechain, refs - entries, entries);
+}
+
int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
int rulenum, unsigned int format)
{
@@ -2275,75 +2293,43 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
return 0;
}
- if (chain && rulenum) {
- c = nft_chain_find(h, table, chain);
+ list = nft_chain_list_get(h, table);
+ if (!list)
+ return 0;
+
+ if (chain) {
+ c = nftnl_chain_list_lookup_byname(list, chain);
if (!c)
return 0;
+ if (!rulenum) {
+ if (ops->print_table_header)
+ ops->print_table_header(table);
+ __nft_print_header(h, ops, c, format);
+ }
__nft_rule_list(h, c, rulenum, format, ops->print_rule);
return 1;
}
- list = nft_chain_list_get(h, table);
- if (!list)
- return 0;
-
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
- goto err;
+ return 0;
- if (!chain && ops->print_table_header)
+ if (ops->print_table_header)
ops->print_table_header(table);
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *chain_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- uint32_t policy =
- nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
- uint32_t refs =
- nftnl_chain_get_u32(c, NFTNL_CHAIN_USE);
- struct xt_counters ctrs = {
- .pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
- .bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES),
- };
- bool basechain = false;
- uint32_t entries;
-
- if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM))
- basechain = true;
-
- if (chain) {
- if (strcmp(chain, chain_name) != 0)
- goto next;
- else if (ops->print_table_header)
- ops->print_table_header(table);
- }
-
if (found)
printf("\n");
- entries = nft_rule_count(h, c);
- ops->print_header(format, chain_name, policy_name[policy],
- &ctrs, basechain, refs - entries, entries);
-
+ __nft_print_header(h, ops, c, format);
__nft_rule_list(h, c, rulenum, format, ops->print_rule);
found = true;
-
- /* we printed the chain we wanted, stop processing. */
- if (chain)
- break;
-
-next:
c = nftnl_chain_list_iter_next(iter);
}
-
nftnl_chain_list_iter_destroy(iter);
-err:
- if (chain && !found)
- return 0;
-
return 1;
}
--
2.21.0