Blame SOURCES/0068-libxtables-Implement-notargets-hash-table.patch

aca4c4
From 3e8e2f0a6590a3b1eeb989e364fe4b5638be108f Mon Sep 17 00:00:00 2001
aca4c4
From: Phil Sutter <phil@nwl.cc>
aca4c4
Date: Tue, 15 Dec 2020 15:40:56 +0100
aca4c4
Subject: [PATCH] libxtables: Implement notargets hash table
aca4c4
aca4c4
Target lookup is relatively costly due to the filesystem access. Avoid
aca4c4
this overhead in huge rulesets which contain many chain jumps by caching
aca4c4
the failed lookups into a hashtable for later.
aca4c4
aca4c4
Signed-off-by: Phil Sutter <phil@nwl.cc>
aca4c4
Acked-by: Florian Westphal <fw@strlen.de>
aca4c4
(cherry picked from commit f58b0d7406451afbb4b9b6c7888990c964fa7c79)
aca4c4
aca4c4
Conflicts:
aca4c4
	libxtables/xtables.c
aca4c4
-> Context changes and missing xtables_fini() due to missing commit
aca4c4
   7db4333dc0b6c ("libxtables: Introduce xtables_fini()")
aca4c4
---
aca4c4
 libxtables/xtables.c | 79 ++++++++++++++++++++++++++++++++++++++++++++
aca4c4
 1 file changed, 79 insertions(+)
aca4c4
aca4c4
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
aca4c4
index 58dd69440253d..1e1c218df7441 100644
aca4c4
--- a/libxtables/xtables.c
aca4c4
+++ b/libxtables/xtables.c
aca4c4
@@ -48,6 +48,7 @@
aca4c4
 #include <linux/netfilter_ipv4/ip_tables.h>
aca4c4
 #include <linux/netfilter_ipv6/ip6_tables.h>
aca4c4
 #include <libiptc/libxtc.h>
aca4c4
+#include <libiptc/linux_list.h>
aca4c4
 
aca4c4
 #ifndef NO_SHARED_LIBS
aca4c4
 #include <dlfcn.h>
aca4c4
@@ -208,6 +209,71 @@ static bool xtables_fully_register_pending_match(struct xtables_match *me,
aca4c4
 static bool xtables_fully_register_pending_target(struct xtables_target *me,
aca4c4
 						  struct xtables_target *prev);
aca4c4
 
aca4c4
+struct notarget {
aca4c4
+	struct hlist_node node;
aca4c4
+	char name[];
aca4c4
+};
aca4c4
+
aca4c4
+#define NOTARGET_HSIZE	512
aca4c4
+static struct hlist_head notargets[NOTARGET_HSIZE];
aca4c4
+
aca4c4
+static void notargets_hlist_init(void)
aca4c4
+{
aca4c4
+	int i;
aca4c4
+
aca4c4
+	for (i = 0; i < NOTARGET_HSIZE; i++)
aca4c4
+		INIT_HLIST_HEAD(&notargets[i]);
aca4c4
+}
aca4c4
+
aca4c4
+static void notargets_hlist_free(void)
aca4c4
+{
aca4c4
+	struct hlist_node *pos, *n;
aca4c4
+	struct notarget *cur;
aca4c4
+	int i;
aca4c4
+
aca4c4
+	for (i = 0; i < NOTARGET_HSIZE; i++) {
aca4c4
+		hlist_for_each_entry_safe(cur, pos, n, &notargets[i], node) {
aca4c4
+			hlist_del(&cur->node);
aca4c4
+			free(cur);
aca4c4
+		}
aca4c4
+	}
aca4c4
+}
aca4c4
+
aca4c4
+static uint32_t djb_hash(const char *key)
aca4c4
+{
aca4c4
+	uint32_t i, hash = 5381;
aca4c4
+
aca4c4
+	for (i = 0; i < strlen(key); i++)
aca4c4
+		hash = ((hash << 5) + hash) + key[i];
aca4c4
+
aca4c4
+	return hash;
aca4c4
+}
aca4c4
+
aca4c4
+static struct notarget *notargets_hlist_lookup(const char *name)
aca4c4
+{
aca4c4
+	uint32_t key = djb_hash(name) % NOTARGET_HSIZE;
aca4c4
+	struct hlist_node *node;
aca4c4
+	struct notarget *cur;
aca4c4
+
aca4c4
+	hlist_for_each_entry(cur, node, &notargets[key], node) {
aca4c4
+		if (!strcmp(name, cur->name))
aca4c4
+			return cur;
aca4c4
+	}
aca4c4
+	return NULL;
aca4c4
+}
aca4c4
+
aca4c4
+static void notargets_hlist_insert(const char *name)
aca4c4
+{
aca4c4
+	struct notarget *cur;
aca4c4
+
aca4c4
+	if (!name)
aca4c4
+		return;
aca4c4
+
aca4c4
+	cur = xtables_malloc(sizeof(*cur) + strlen(name) + 1);
aca4c4
+	strcpy(cur->name, name);
aca4c4
+	hlist_add_head(&cur->node, &notargets[djb_hash(name) % NOTARGET_HSIZE]);
aca4c4
+}
aca4c4
+
aca4c4
 void xtables_init(void)
aca4c4
 {
aca4c4
 	xtables_libdir = getenv("XTABLES_LIBDIR");
aca4c4
@@ -233,6 +299,13 @@ void xtables_init(void)
aca4c4
 		return;
aca4c4
 	}
aca4c4
 	xtables_libdir = XTABLES_LIBDIR;
aca4c4
+
aca4c4
+	notargets_hlist_init();
aca4c4
+}
aca4c4
+
aca4c4
+void xtables_fini(void)
aca4c4
+{
aca4c4
+	notargets_hlist_free();
aca4c4
 }
aca4c4
 
aca4c4
 void xtables_set_nfproto(uint8_t nfproto)
aca4c4
@@ -750,6 +823,10 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
aca4c4
 	    || strcmp(name, XTC_LABEL_QUEUE) == 0
aca4c4
 	    || strcmp(name, XTC_LABEL_RETURN) == 0)
aca4c4
 		name = "standard";
aca4c4
+	/* known non-target? */
aca4c4
+	else if (notargets_hlist_lookup(name) &&
aca4c4
+		 tryload != XTF_LOAD_MUST_SUCCEED)
aca4c4
+		return NULL;
aca4c4
 
aca4c4
 	/* Trigger delayed initialization */
aca4c4
 	for (dptr = &xtables_pending_targets; *dptr; ) {
aca4c4
@@ -813,6 +890,8 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
aca4c4
 
aca4c4
 	if (ptr)
aca4c4
 		ptr->used = 1;
aca4c4
+	else
aca4c4
+		notargets_hlist_insert(name);
aca4c4
 
aca4c4
 	return ptr;
aca4c4
 }
aca4c4
-- 
aca4c4
2.34.1
aca4c4