All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sven Eckelmann <sven.eckelmann@openmesh.com>
To: b.a.t.m.a.n@lists.open-mesh.org
Cc: Sven Eckelmann <sven.eckelmann@openmesh.com>
Subject: [B.A.T.M.A.N.] [PATCH 4/5] alfred: Cache the TQ values for each originator
Date: Wed, 24 May 2017 12:32:10 +0200	[thread overview]
Message-ID: <20170524103211.810-4-sven.eckelmann@openmesh.com> (raw)
In-Reply-To: <4690435.IOLn72U8Ez@bentobox>

There is a single loop which goes over all servers to find the TQs for each
server. The TQ value doesn't change often and it is relative unlikely that
it is different after some milliseconds. It is therefore not necessary to
re-request the TQ values from the kernel for each server in the server
hash. Instead, the values can be retrieved ones from the kernel during each
sync interval, cached and then retrieved from the cache again.

Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
---
 batadv_query.c   | 108 ++++++++++++++++++++++++++++++++++++++++++-------------
 batadv_query.h   |  14 +++++++-
 batadv_querynl.c |  29 +++++----------
 batadv_querynl.h |   4 +--
 server.c         |  17 +++++++--
 5 files changed, 121 insertions(+), 51 deletions(-)

diff --git a/batadv_query.c b/batadv_query.c
index e68052b..1123cf5 100644
--- a/batadv_query.c
+++ b/batadv_query.c
@@ -298,8 +298,7 @@ struct ether_addr *translate_mac(const char *mesh_iface,
 	return mac_result;
 }
 
-static int get_tq_debugfs(const char *mesh_iface, struct ether_addr *mac,
-			  uint8_t *tq)
+static int get_tq_debugfs(const char *mesh_iface, struct hashtable_t *orig_hash)
 {
 	enum {
 		orig_mac,
@@ -308,16 +307,13 @@ static int get_tq_debugfs(const char *mesh_iface, struct ether_addr *mac,
 		orig_tqvalue,
 	} pos;
 	char full_path[MAX_PATH + 1];
-	static struct ether_addr in_mac;
 	struct ether_addr *mac_tmp;
 	FILE *f = NULL;
 	size_t len = 0;
 	char *line = NULL;
 	char *input, *saveptr, *token;
 	int line_invalid;
-	bool found = false;
-
-	memcpy(&in_mac, mac, sizeof(in_mac));
+	uint8_t tq;
 
 	debugfs_make_path(DEBUG_BATIF_PATH_FMT "/" DEBUG_ORIGINATORS,
 			  mesh_iface, full_path, sizeof(full_path));
@@ -337,8 +333,7 @@ static int get_tq_debugfs(const char *mesh_iface, struct ether_addr *mac,
 			switch (pos) {
 			case orig_mac:
 				mac_tmp = ether_aton(token);
-				if (!mac_tmp || memcmp(mac_tmp, &in_mac,
-						       sizeof(in_mac)) != 0)
+				if (!mac_tmp)
 					line_invalid = 1;
 				else
 					pos = orig_lastseen;
@@ -365,9 +360,8 @@ static int get_tq_debugfs(const char *mesh_iface, struct ether_addr *mac,
 					line_invalid = 1;
 				} else {
 					token[strlen(token) - 1] = '\0';
-					*tq = strtol(token, NULL, 10);
-					found = true;
-					goto out;
+					tq = strtol(token, NULL, 10);
+					orig_hash_add(orig_hash, mac_tmp, tq);
 				}
 				break;
 			}
@@ -377,34 +371,98 @@ static int get_tq_debugfs(const char *mesh_iface, struct ether_addr *mac,
 		}
 	}
 
-out:
 	if (f)
 		fclose(f);
 	free(line);
 
-	if (found)
-		return 0;
+	return 0;
+}
+
+static int orig_compare(void *d1, void *d2)
+{
+	struct orig_entry *s1 = d1, *s2 = d2;
+
+	if (memcmp(&s1->mac, &s2->mac, sizeof(s1->mac)) == 0)
+		return 1;
 	else
-		return -ENOENT;
+		return 0;
 }
 
-uint8_t get_tq(const char *mesh_iface, struct ether_addr *mac)
+static int orig_choose(void *d1, int size)
 {
-	struct ether_addr in_mac;
-	uint8_t tq = 0;
+	struct orig_entry *s1 = d1;
+	uint32_t hash = 0;
+	size_t i;
+
+	for (i = 0; i < sizeof(s1->mac); i++) {
+		hash += s1->mac.ether_addr_octet[i];
+		hash += (hash << 10);
+		hash ^= (hash >> 6);
+	}
+
+	hash += (hash << 3);
+	hash ^= (hash >> 11);
+	hash += (hash << 15);
+
+	return hash % size;
+}
+
+struct hashtable_t *orig_hash_new(const char *mesh_iface)
+{
+	struct hashtable_t *orig_hash;
 	int ret;
 
-	/* input mac has to be copied because it could be in the shared
-	 * ether_aton buffer
-	 */
-	memcpy(&in_mac, mac, sizeof(in_mac));
+	orig_hash = hash_new(64, orig_compare, orig_choose);
+	if (!orig_hash)
+		return NULL;
 
 	enable_net_admin_capability(1);
-	ret = get_tq_netlink(mesh_iface, &in_mac, &tq);
+	ret = get_tq_netlink(mesh_iface, orig_hash);
 	enable_net_admin_capability(0);
 
+	ret = -EOPNOTSUPP;
 	if (ret == -EOPNOTSUPP)
-		get_tq_debugfs(mesh_iface, &in_mac, &tq);
+		get_tq_debugfs(mesh_iface, orig_hash);
+
+	return orig_hash;
+}
+
+void orig_hash_free(struct hashtable_t *orig_hash)
+{
+	hash_delete(orig_hash, free);
+}
+
+int orig_hash_add(struct hashtable_t *orig_hash, struct ether_addr *mac,
+		  uint8_t tq)
+{
+	struct orig_entry *n;
+
+	n = malloc(sizeof(*n));
+	if (!n)
+		return -ENOMEM;
+
+	n->mac = *mac;
+	n->tq = tq;
+
+	if (hash_add(orig_hash, n)) {
+		free(n);
+		return -EEXIST;
+	}
+
+	return 0;
+}
+
+uint8_t get_tq(struct hashtable_t *orig_hash, struct ether_addr *mac)
+{
+	struct orig_entry search = {
+		.mac = *mac,
+		.tq = 0,
+	};
+	struct orig_entry *found;
+
+	found = hash_find(orig_hash, &search);
+	if (!found)
+		return 0;
 
-	return tq;
+	return found->tq;
 }
diff --git a/batadv_query.h b/batadv_query.h
index 9aa4f0e..aa4d3f8 100644
--- a/batadv_query.h
+++ b/batadv_query.h
@@ -24,9 +24,21 @@
 #include <stdint.h>
 #include <netinet/in.h>
 
+#include "hash.h"
+
+struct orig_entry {
+	struct ether_addr mac;
+	uint8_t tq;
+};
+
 struct ether_addr *translate_mac(const char *mesh_iface,
 				 const struct ether_addr *mac);
-uint8_t get_tq(const char *mesh_iface, struct ether_addr *mac);
+
+struct hashtable_t *orig_hash_new(const char *mesh_iface);
+void orig_hash_free(struct hashtable_t *orig_hash);
+int orig_hash_add(struct hashtable_t *orig_hash, struct ether_addr *mac,
+		  uint8_t tq);
+uint8_t get_tq(struct hashtable_t *orig_hash, struct ether_addr *mac);
 int batadv_interface_check(const char *mesh_iface);
 int mac_to_ipv6(const struct ether_addr *mac, alfred_addr *addr);
 int ipv6_to_mac(const alfred_addr *addr, struct ether_addr *mac);
diff --git a/batadv_querynl.c b/batadv_querynl.c
index 8dab96e..ba678ae 100644
--- a/batadv_querynl.c
+++ b/batadv_querynl.c
@@ -34,7 +34,9 @@
 #include <netlink/genl/ctrl.h>
 #include <net/ethernet.h>
 
+#include "alfred.h"
 #include "batman_adv.h"
+#include "batadv_query.h"
 #include "netlink.h"
 
 #ifndef __unused
@@ -131,9 +133,7 @@ static const int get_tq_netlink_mandatory[] = {
 };
 
 struct get_tq_netlink_opts {
-	struct ether_addr mac;
-	uint8_t tq;
-	bool found;
+	struct hashtable_t *orig_hash;
 	struct nlquery_opts query_opts;
 };
 
@@ -145,6 +145,7 @@ static int get_tq_netlink_cb(struct nl_msg *msg, void *arg)
 	struct get_tq_netlink_opts *opts;
 	struct genlmsghdr *ghdr;
 	uint8_t *orig;
+	struct ether_addr mac;
 	uint8_t tq;
 
 	opts = container_of(query_opts, struct get_tq_netlink_opts,
@@ -173,40 +174,28 @@ static int get_tq_netlink_cb(struct nl_msg *msg, void *arg)
 	if (!attrs[BATADV_ATTR_FLAG_BEST])
 		return NL_OK;
 
-	if (memcmp(&opts->mac, orig, ETH_ALEN) != 0)
-		return NL_OK;
-
-	opts->tq = tq;
-	opts->found = true;
+	memcpy(&mac, orig, sizeof(mac));
+	orig_hash_add(opts->orig_hash, &mac, tq);
 	opts->query_opts.err = 0;
 
-	return NL_STOP;
+	return NL_OK;
 }
 
-int get_tq_netlink(const char *mesh_iface, const struct ether_addr *mac,
-		   uint8_t *tq)
+int get_tq_netlink(const char *mesh_iface, struct hashtable_t *orig_hash)
 {
 	struct get_tq_netlink_opts opts = {
-		.tq = 0,
-		.found = false,
+		.orig_hash = orig_hash,
 		.query_opts = {
 			.err = 0,
 		},
 	};
 	int ret;
 
-	memcpy(&opts.mac, mac, ETH_ALEN);
-
 	ret = netlink_query_common(mesh_iface,  BATADV_CMD_GET_ORIGINATORS,
 				   get_tq_netlink_cb, &opts.query_opts);
 	if (ret < 0)
 		return ret;
 
-	if (!opts.found)
-		return -ENOENT;
-
-	*tq = opts.tq;
-
 	return 0;
 }
 
diff --git a/batadv_querynl.h b/batadv_querynl.h
index 9b93a47..f5c7e38 100644
--- a/batadv_querynl.h
+++ b/batadv_querynl.h
@@ -25,11 +25,11 @@
 #include <stdint.h>
 
 struct ether_addr;
+struct hashtable_t;
 
 int translate_mac_netlink(const char *mesh_iface, const struct ether_addr *mac,
 			  struct ether_addr *mac_out);
-int get_tq_netlink(const char *mesh_iface, const struct ether_addr *mac,
-		   uint8_t *tq);
+int get_tq_netlink(const char *mesh_iface, struct hashtable_t *orig_hash);
 int batadv_interface_check_netlink(const char *mesh_iface);
 
 #endif /* _BATADV_QUERYNL_H */
diff --git a/server.c b/server.c
index 09acb80..91aa729 100644
--- a/server.c
+++ b/server.c
@@ -223,17 +223,26 @@ static void update_server_info(struct globals *globals)
 	struct hash_it_t *hashit = NULL;
 	struct interface *interface;
 	struct ether_addr *macaddr;
+	struct hashtable_t *orig_hash;
 
 	/* TQ is not used for master sync mode */
 	if (globals->opmode == OPMODE_MASTER)
 		return;
 
+	if (strcmp(globals->mesh_iface, "none") != 0) {
+		orig_hash = orig_hash_new(globals->mesh_iface);
+		if (!globals->data_hash) {
+			fprintf(stderr, "Failed to originator hash\n");
+			return;
+		}
+	}
+
 	list_for_each_entry(interface, &globals->interfaces, list) {
 		while (NULL != (hashit = hash_iterate(interface->server_hash,
 						      hashit))) {
 			struct server *server = hashit->bucket->data;
 
-			if (strcmp(globals->mesh_iface, "none") == 0) {
+			if (!orig_hash) {
 				server->tq = 255;
 				continue;
 			}
@@ -241,14 +250,16 @@ static void update_server_info(struct globals *globals)
 			macaddr = translate_mac(globals->mesh_iface,
 						&server->hwaddr);
 			if (macaddr)
-				server->tq = get_tq(globals->mesh_iface,
-						    macaddr);
+				server->tq = get_tq(orig_hash, macaddr);
 			else
 				server->tq = 0;
 		}
 	}
 
 	set_best_server(globals);
+
+	if (orig_hash)
+		orig_hash_free(orig_hash);
 }
 
 static void check_if_socket(struct interface *interface, struct globals *globals)
-- 
2.11.0


  parent reply	other threads:[~2017-05-24 10:32 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-24 10:31 [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations Sven Eckelmann
2017-05-24 10:32 ` [B.A.T.M.A.N.] [PATCH 1/5] alfred: Move alfred specific netlink code in separate file Sven Eckelmann
2017-05-24 10:32 ` [B.A.T.M.A.N.] [PATCH 2/5] alfred: Only query tq of remote master in slave mode Sven Eckelmann
2017-05-24 10:32 ` [B.A.T.M.A.N.] [PATCH 3/5] alfred: Check the TQ of master servers before pushing data Sven Eckelmann
2017-05-24 10:32 ` Sven Eckelmann [this message]
2017-05-24 10:32 ` [B.A.T.M.A.N.] [PATCH 5/5] alfred: Cache the global translation table entries Sven Eckelmann
2017-05-31 15:24 ` [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations Simon Wunderlich
2017-06-01  6:15   ` Sven Eckelmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170524103211.810-4-sven.eckelmann@openmesh.com \
    --to=sven.eckelmann@openmesh.com \
    --cc=b.a.t.m.a.n@lists.open-mesh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.