Blame SOURCES/0004-chain-Hash-chain-list-by-name.patch

ef9e95
From a3af0aff50cd3e899cb5205d4d5330a96aeffaa5 Mon Sep 17 00:00:00 2001
ef9e95
From: Phil Sutter <psutter@redhat.com>
ef9e95
Date: Mon, 17 Dec 2018 17:30:06 +0100
ef9e95
Subject: [PATCH] chain: Hash chain list by name
ef9e95
ef9e95
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1658533
ef9e95
Upstream Status: libnftnl commit 7170f0929ef50
ef9e95
ef9e95
commit 7170f0929ef50a1a45d9fd5d058ea6178c8e56ef
ef9e95
Author: Phil Sutter <phil@nwl.cc>
ef9e95
Date:   Tue Dec 11 18:44:00 2018 +0100
ef9e95
ef9e95
    chain: Hash chain list by name
ef9e95
ef9e95
    Introduce a hash table to speedup nftnl_chain_list_lookup_byname(). In
ef9e95
    theory this could replace the linked list completely but has been left
ef9e95
    in place so that nftnl_chain_list_add_tail() still does what it's
ef9e95
    supposed to and iterators return chains in original order.
ef9e95
ef9e95
    Speed was tested using a simple script which creates a dump file
ef9e95
    containing a number of custom chains and for each of them two rules in
ef9e95
    INPUT chain jumping to it. The following table compares run-time of
ef9e95
    iptables-legacy-restore with iptables-nft-restore before and after this
ef9e95
    patch:
ef9e95
ef9e95
    count      legacy       nft-old        nft-new
ef9e95
    ----------------------------------------------
ef9e95
    10000         26s           38s            31s
ef9e95
    50000        137s          339s           149s
ef9e95
ef9e95
    So while it is still not as quick, it now scales nicely (at least in
ef9e95
    this very primitive test).
ef9e95
ef9e95
    Signed-off-by: Phil Sutter <phil@nwl.cc>
ef9e95
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
ef9e95
---
ef9e95
 src/chain.c | 30 +++++++++++++++++++++++++++++-
ef9e95
 1 file changed, 29 insertions(+), 1 deletion(-)
ef9e95
ef9e95
diff --git a/src/chain.c b/src/chain.c
ef9e95
index 22bb45c..ae074fd 100644
ef9e95
--- a/src/chain.c
ef9e95
+++ b/src/chain.c
ef9e95
@@ -32,6 +32,7 @@
ef9e95
 
ef9e95
 struct nftnl_chain {
ef9e95
 	struct list_head head;
ef9e95
+	struct hlist_node hnode;
ef9e95
 
ef9e95
 	const char	*name;
ef9e95
 	const char	*type;
ef9e95
@@ -991,20 +992,27 @@ void nftnl_rule_iter_destroy(struct nftnl_rule_iter *iter)
ef9e95
 	xfree(iter);
ef9e95
 }
ef9e95
 
ef9e95
+#define CHAIN_NAME_HSIZE	512
ef9e95
+
ef9e95
 struct nftnl_chain_list {
ef9e95
+
ef9e95
 	struct list_head list;
ef9e95
+	struct hlist_head name_hash[CHAIN_NAME_HSIZE];
ef9e95
 };
ef9e95
 
ef9e95
 EXPORT_SYMBOL(nftnl_chain_list_alloc);
ef9e95
 struct nftnl_chain_list *nftnl_chain_list_alloc(void)
ef9e95
 {
ef9e95
 	struct nftnl_chain_list *list;
ef9e95
+	int i;
ef9e95
 
ef9e95
 	list = calloc(1, sizeof(struct nftnl_chain_list));
ef9e95
 	if (list == NULL)
ef9e95
 		return NULL;
ef9e95
 
ef9e95
 	INIT_LIST_HEAD(&list->list);
ef9e95
+	for (i = 0; i < CHAIN_NAME_HSIZE; i++)
ef9e95
+		INIT_HLIST_HEAD(&list->name_hash[i]);
ef9e95
 
ef9e95
 	return list;
ef9e95
 }
ef9e95
@@ -1016,6 +1024,7 @@ void nftnl_chain_list_free(struct nftnl_chain_list *list)
ef9e95
 
ef9e95
 	list_for_each_entry_safe(r, tmp, &list->list, head) {
ef9e95
 		list_del(&r->head);
ef9e95
+		hlist_del(&r->hnode);
ef9e95
 		nftnl_chain_free(r);
ef9e95
 	}
ef9e95
 	xfree(list);
ef9e95
@@ -1027,15 +1036,31 @@ int nftnl_chain_list_is_empty(const struct nftnl_chain_list *list)
ef9e95
 	return list_empty(&list->list);
ef9e95
 }
ef9e95
 
ef9e95
+static uint32_t djb_hash(const char *key)
ef9e95
+{
ef9e95
+	uint32_t i, hash = 5381;
ef9e95
+
ef9e95
+	for (i = 0; i < strlen(key); i++)
ef9e95
+		hash = ((hash << 5) + hash) + key[i];
ef9e95
+
ef9e95
+	return hash;
ef9e95
+}
ef9e95
+
ef9e95
 EXPORT_SYMBOL(nftnl_chain_list_add);
ef9e95
 void nftnl_chain_list_add(struct nftnl_chain *r, struct nftnl_chain_list *list)
ef9e95
 {
ef9e95
+	int key = djb_hash(r->name) % CHAIN_NAME_HSIZE;
ef9e95
+
ef9e95
+	hlist_add_head(&r->hnode, &list->name_hash[key]);
ef9e95
 	list_add(&r->head, &list->list);
ef9e95
 }
ef9e95
 
ef9e95
 EXPORT_SYMBOL(nftnl_chain_list_add_tail);
ef9e95
 void nftnl_chain_list_add_tail(struct nftnl_chain *r, struct nftnl_chain_list *list)
ef9e95
 {
ef9e95
+	int key = djb_hash(r->name) % CHAIN_NAME_HSIZE;
ef9e95
+
ef9e95
+	hlist_add_head(&r->hnode, &list->name_hash[key]);
ef9e95
 	list_add_tail(&r->head, &list->list);
ef9e95
 }
ef9e95
 
ef9e95
@@ -1043,6 +1068,7 @@ EXPORT_SYMBOL(nftnl_chain_list_del);
ef9e95
 void nftnl_chain_list_del(struct nftnl_chain *r)
ef9e95
 {
ef9e95
 	list_del(&r->head);
ef9e95
+	hlist_del(&r->hnode);
ef9e95
 }
ef9e95
 
ef9e95
 EXPORT_SYMBOL(nftnl_chain_list_foreach);
ef9e95
@@ -1066,9 +1092,11 @@ struct nftnl_chain *
ef9e95
 nftnl_chain_list_lookup_byname(struct nftnl_chain_list *chain_list,
ef9e95
 			       const char *chain)
ef9e95
 {
ef9e95
+	int key = djb_hash(chain) % CHAIN_NAME_HSIZE;
ef9e95
 	struct nftnl_chain *c;
ef9e95
+	struct hlist_node *n;
ef9e95
 
ef9e95
-	list_for_each_entry(c, &chain_list->list, head) {
ef9e95
+	hlist_for_each_entry(c, n, &chain_list->name_hash[key], hnode) {
ef9e95
 		if (!strcmp(chain, c->name))
ef9e95
 			return c;
ef9e95
 	}
ef9e95
-- 
ef9e95
1.8.3.1
ef9e95