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

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