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

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