All of lore.kernel.org
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations
@ 2017-05-24 10:31 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
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Sven Eckelmann @ 2017-05-24 10:31 UTC (permalink / raw)
  To: b.a.t.m.a.n

[-- Attachment #1: Type: text/plain, Size: 2632 bytes --]

Hi,

alfred uses the TQ from batman-adv to find its best alfred neighbor. This best 
neighbor information is used by slave servers to request/publish data.

This is done for each server announcement packet by:

 * requesting the global translation table (netlink or debugfs) and then
   searching in it for the MAC address of the detected alfred server to find
   its originator address
 * requesting the originator table (netlink or debugfs) and then searching it
   it for the originator address of the detected alfred server to find its TQ
   value

This was previously done whenever a new announcement packet received by 
alfred. We've observed that this can be a problem on networks with a lot of 
master servers (~100) which can see each other, large translation tables and 
slow CPUs. alfred still worked but the CPU load by alfred was rather high
(~20% on an 560MHz AR9344).

The idea is now to avoid this lookup for master servers. And (for slave 
servers) to process all servers at once. This is done before the wants to push 
its local data to a master server in an sync interval.

The process which was described earlier was now changed to:

 * requesting the global translation table (netlink or debugfs) and then put
   MAC address and corresponding originator address in tg hash
 * requesting the originator table (netlink or debugfs) and then put
   originator address and corresponding TQ value orig hash
 * got through all servers:
   - search in tg hash for for the MAC address of the alfred server to find
   its originator address
   - search in orig hash for for the originator address of the alfred server
     to find its TQ value

These changes reduced the load on the previously mentioned devices 
significantly.

Kind regards,
	Sven


Sven Eckelmann (5):
  alfred: Move alfred specific netlink code in separate file
  alfred: Only query tq of remote master in slave mode
  alfred: Check the TQ of master servers before pushing data
  alfred: Cache the TQ values for each originator
  alfred: Cache the global translation table entries

 Makefile         |   1 +
 alfred.h         |   1 -
 batadv_query.c   | 227 +++++++++++++++++++++++++++++++++++++++++--------------
 batadv_query.h   |  25 +++++-
 batadv_querynl.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 batadv_querynl.h |  34 +++++++++
 netlink.c        | 195 -----------------------------------------------
 netlink.h        |   7 --
 recv.c           |  15 +---
 server.c         |  56 +++++++++++++-
 10 files changed, 501 insertions(+), 276 deletions(-)
 create mode 100644 batadv_querynl.c
 create mode 100644 batadv_querynl.h

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [B.A.T.M.A.N.] [PATCH 1/5] alfred: Move alfred specific netlink code in separate file
  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 ` 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
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Sven Eckelmann @ 2017-05-24 10:32 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

The vis daemon doesn't require the same set of netlink functions as alfred
daemon. But the netlink.c file is shared between both. Split the file to
avoid a lot of dead code in vis.

Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
---
 Makefile         |   1 +
 batadv_query.c   |   2 +-
 batadv_querynl.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 batadv_querynl.h |  35 +++++++++
 netlink.c        | 195 ---------------------------------------------
 netlink.h        |   7 --
 6 files changed, 273 insertions(+), 203 deletions(-)
 create mode 100644 batadv_querynl.c
 create mode 100644 batadv_querynl.h

diff --git a/Makefile b/Makefile
index 3c88e96..4c1c6b5 100755
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,7 @@
 # alfred build
 BINARY_NAME = alfred
 OBJ += batadv_query.o
+OBJ += batadv_querynl.o
 OBJ += client.o
 OBJ += debugfs.o
 OBJ += hash.o
diff --git a/batadv_query.c b/batadv_query.c
index 6ec086b..e68052b 100644
--- a/batadv_query.c
+++ b/batadv_query.c
@@ -34,7 +34,7 @@
 #endif
 #include <sys/types.h>
 
-#include "netlink.h"
+#include "batadv_querynl.h"
 #include "debugfs.h"
 
 #define DEBUG_BATIF_PATH_FMT "%s/batman_adv/%s"
diff --git a/batadv_querynl.c b/batadv_querynl.c
new file mode 100644
index 0000000..8dab96e
--- /dev/null
+++ b/batadv_querynl.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2009-2017  B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner <mareklindner@neomailbox.ch>, Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "batadv_querynl.h"
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <net/ethernet.h>
+
+#include "batman_adv.h"
+#include "netlink.h"
+
+#ifndef __unused
+#define __unused __attribute__((unused))
+#endif
+
+static const int translate_mac_netlink_mandatory[] = {
+	BATADV_ATTR_TT_ADDRESS,
+	BATADV_ATTR_ORIG_ADDRESS,
+};
+
+struct translate_mac_netlink_opts {
+	struct ether_addr mac;
+	bool found;
+	struct nlquery_opts query_opts;
+};
+
+static int translate_mac_netlink_cb(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *attrs[BATADV_ATTR_MAX + 1];
+	struct nlmsghdr *nlh = nlmsg_hdr(msg);
+	struct nlquery_opts *query_opts = arg;
+	struct translate_mac_netlink_opts *opts;
+	struct genlmsghdr *ghdr;
+	uint8_t *addr;
+	uint8_t *orig;
+
+	opts = container_of(query_opts, struct translate_mac_netlink_opts,
+			    query_opts);
+
+	if (!genlmsg_valid_hdr(nlh, 0))
+		return NL_OK;
+
+	ghdr = nlmsg_data(nlh);
+
+	if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_GLOBAL)
+		return NL_OK;
+
+	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
+		      genlmsg_len(ghdr), batadv_netlink_policy)) {
+		return NL_OK;
+	}
+
+	if (missing_mandatory_attrs(attrs, translate_mac_netlink_mandatory,
+				    ARRAY_SIZE(translate_mac_netlink_mandatory)))
+		return NL_OK;
+
+	addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]);
+	orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
+
+	if (!attrs[BATADV_ATTR_FLAG_BEST])
+		return NL_OK;
+
+	if (memcmp(&opts->mac, addr, ETH_ALEN) != 0)
+		return NL_OK;
+
+	memcpy(&opts->mac, orig, ETH_ALEN);
+	opts->found = true;
+	opts->query_opts.err = 0;
+
+	return NL_STOP;
+}
+
+int translate_mac_netlink(const char *mesh_iface, const struct ether_addr *mac,
+			  struct ether_addr *mac_out)
+{
+	struct translate_mac_netlink_opts opts = {
+		.found = false,
+		.query_opts = {
+			.err = 0,
+		},
+	};
+	int ret;
+
+	memcpy(&opts.mac, mac, ETH_ALEN);
+
+	ret = netlink_query_common(mesh_iface,
+				   BATADV_CMD_GET_TRANSTABLE_GLOBAL,
+				   translate_mac_netlink_cb, &opts.query_opts);
+	if (ret < 0)
+		return ret;
+
+	if (!opts.found)
+		return -ENOENT;
+
+	memcpy(mac_out, &opts.mac, ETH_ALEN);
+
+	return 0;
+}
+
+static const int get_tq_netlink_mandatory[] = {
+	BATADV_ATTR_ORIG_ADDRESS,
+	BATADV_ATTR_TQ,
+};
+
+struct get_tq_netlink_opts {
+	struct ether_addr mac;
+	uint8_t tq;
+	bool found;
+	struct nlquery_opts query_opts;
+};
+
+static int get_tq_netlink_cb(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *attrs[BATADV_ATTR_MAX + 1];
+	struct nlmsghdr *nlh = nlmsg_hdr(msg);
+	struct nlquery_opts *query_opts = arg;
+	struct get_tq_netlink_opts *opts;
+	struct genlmsghdr *ghdr;
+	uint8_t *orig;
+	uint8_t tq;
+
+	opts = container_of(query_opts, struct get_tq_netlink_opts,
+			    query_opts);
+
+	if (!genlmsg_valid_hdr(nlh, 0))
+		return NL_OK;
+
+	ghdr = nlmsg_data(nlh);
+
+	if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS)
+		return NL_OK;
+
+	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
+		      genlmsg_len(ghdr), batadv_netlink_policy)) {
+		return NL_OK;
+	}
+
+	if (missing_mandatory_attrs(attrs, get_tq_netlink_mandatory,
+				    ARRAY_SIZE(get_tq_netlink_mandatory)))
+		return NL_OK;
+
+	orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
+	tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);
+
+	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;
+	opts->query_opts.err = 0;
+
+	return NL_STOP;
+}
+
+int get_tq_netlink(const char *mesh_iface, const struct ether_addr *mac,
+		   uint8_t *tq)
+{
+	struct get_tq_netlink_opts opts = {
+		.tq = 0,
+		.found = false,
+		.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;
+}
+
+static int check_nlcmd_cb(struct nl_msg *msg __unused, void *arg __unused)
+{
+	return NL_STOP;
+}
+
+int batadv_interface_check_netlink(const char *mesh_iface)
+{
+	struct nlquery_opts opts = {
+		.err = 0,
+	};
+	int ret;
+
+	ret = netlink_query_common(mesh_iface,  BATADV_CMD_GET_ORIGINATORS,
+				   check_nlcmd_cb, &opts);
+	if (ret < 0)
+		return ret;
+
+	ret = netlink_query_common(mesh_iface, BATADV_CMD_GET_TRANSTABLE_GLOBAL,
+				   check_nlcmd_cb, &opts);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
diff --git a/batadv_querynl.h b/batadv_querynl.h
new file mode 100644
index 0000000..9b93a47
--- /dev/null
+++ b/batadv_querynl.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009-2017  B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner <mareklindner@neomailbox.ch>, Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#ifndef _BATADV_QUERYNL_H
+#define _BATADV_QUERYNL_H
+
+#include <stdint.h>
+
+struct ether_addr;
+
+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 batadv_interface_check_netlink(const char *mesh_iface);
+
+#endif /* _BATADV_QUERYNL_H */
diff --git a/netlink.c b/netlink.c
index 1964ab8..7ef4308 100644
--- a/netlink.c
+++ b/netlink.c
@@ -27,7 +27,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
-#include <net/ethernet.h>
 #include <net/if.h>
 #include <netlink/netlink.h>
 #include <netlink/genl/genl.h>
@@ -196,197 +195,3 @@ err_free_sock:
 
 	return query_opts->err;
 }
-
-static const int translate_mac_netlink_mandatory[] = {
-	BATADV_ATTR_TT_ADDRESS,
-	BATADV_ATTR_ORIG_ADDRESS,
-};
-
-struct translate_mac_netlink_opts {
-	struct ether_addr mac;
-	bool found;
-	struct nlquery_opts query_opts;
-};
-
-static int translate_mac_netlink_cb(struct nl_msg *msg, void *arg)
-{
-	struct nlattr *attrs[BATADV_ATTR_MAX+1];
-	struct nlmsghdr *nlh = nlmsg_hdr(msg);
-	struct nlquery_opts *query_opts = arg;
-	struct translate_mac_netlink_opts *opts;
-	struct genlmsghdr *ghdr;
-	uint8_t *addr;
-	uint8_t *orig;
-
-	opts = container_of(query_opts, struct translate_mac_netlink_opts,
-			    query_opts);
-
-	if (!genlmsg_valid_hdr(nlh, 0))
-		return NL_OK;
-
-	ghdr = nlmsg_data(nlh);
-
-	if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_GLOBAL)
-		return NL_OK;
-
-	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
-		      genlmsg_len(ghdr), batadv_netlink_policy)) {
-		return NL_OK;
-	}
-
-	if (missing_mandatory_attrs(attrs, translate_mac_netlink_mandatory,
-				    ARRAY_SIZE(translate_mac_netlink_mandatory)))
-		return NL_OK;
-
-	addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]);
-	orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
-
-	if (!attrs[BATADV_ATTR_FLAG_BEST])
-		return NL_OK;
-
-	if (memcmp(&opts->mac, addr, ETH_ALEN) != 0)
-		return NL_OK;
-
-	memcpy(&opts->mac, orig, ETH_ALEN);
-	opts->found = true;
-	opts->query_opts.err = 0;
-
-	return NL_STOP;
-}
-
-int translate_mac_netlink(const char *mesh_iface, const struct ether_addr *mac,
-			  struct ether_addr *mac_out)
-{
-	struct translate_mac_netlink_opts opts = {
-		.found = false,
-		.query_opts = {
-			.err = 0,
-		},
-	};
-	int ret;
-
-	memcpy(&opts.mac, mac, ETH_ALEN);
-
-	ret = netlink_query_common(mesh_iface,
-				   BATADV_CMD_GET_TRANSTABLE_GLOBAL,
-			           translate_mac_netlink_cb, &opts.query_opts);
-	if (ret < 0)
-		return ret;
-
-	if (!opts.found)
-		return -ENOENT;
-
-	memcpy(mac_out, &opts.mac, ETH_ALEN);
-
-	return 0;
-}
-
-static const int get_tq_netlink_mandatory[] = {
-	BATADV_ATTR_ORIG_ADDRESS,
-	BATADV_ATTR_TQ,
-};
-
-struct get_tq_netlink_opts {
-	struct ether_addr mac;
-	uint8_t tq;
-	bool found;
-	struct nlquery_opts query_opts;
-};
-
-static int get_tq_netlink_cb(struct nl_msg *msg, void *arg)
-{
-	struct nlattr *attrs[BATADV_ATTR_MAX+1];
-	struct nlmsghdr *nlh = nlmsg_hdr(msg);
-	struct nlquery_opts *query_opts = arg;
-	struct get_tq_netlink_opts *opts;
-	struct genlmsghdr *ghdr;
-	uint8_t *orig;
-	uint8_t tq;
-
-	opts = container_of(query_opts, struct get_tq_netlink_opts,
-			    query_opts);
-
-	if (!genlmsg_valid_hdr(nlh, 0))
-		return NL_OK;
-
-	ghdr = nlmsg_data(nlh);
-
-	if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS)
-		return NL_OK;
-
-	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
-		      genlmsg_len(ghdr), batadv_netlink_policy)) {
-		return NL_OK;
-	}
-
-	if (missing_mandatory_attrs(attrs, get_tq_netlink_mandatory,
-				    ARRAY_SIZE(get_tq_netlink_mandatory)))
-		return NL_OK;
-
-	orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
-	tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);
-
-	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;
-	opts->query_opts.err = 0;
-
-	return NL_STOP;
-}
-
-int get_tq_netlink(const char *mesh_iface, const struct ether_addr *mac,
-		   uint8_t *tq)
-{
-	struct get_tq_netlink_opts opts = {
-		.tq = 0,
-		.found = false,
-		.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;
-}
-
-static int check_nlcmd_cb(struct nl_msg *msg __unused, void *arg __unused)
-{
-	return NL_STOP;
-}
-
-int batadv_interface_check_netlink(const char *mesh_iface)
-{
-	struct nlquery_opts opts = {
-		.err = 0,
-	};
-	int ret;
-
-	ret = netlink_query_common(mesh_iface,  BATADV_CMD_GET_ORIGINATORS,
-				   check_nlcmd_cb, &opts);
-	if (ret < 0)
-		return ret;
-
-	ret = netlink_query_common(mesh_iface, BATADV_CMD_GET_TRANSTABLE_GLOBAL,
-				   check_nlcmd_cb, &opts);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
diff --git a/netlink.h b/netlink.h
index 1c87695..a4471a1 100644
--- a/netlink.h
+++ b/netlink.h
@@ -26,8 +26,6 @@
 #include <netlink/genl/ctrl.h>
 #include <stddef.h>
 
-struct ether_addr;
-
 struct nlquery_opts {
 	int err;
 };
@@ -45,11 +43,6 @@ int netlink_query_common(const char *mesh_iface, uint8_t nl_cmd,
 			 struct nlquery_opts *query_opts);
 int missing_mandatory_attrs(struct nlattr *attrs[],  const int mandatory[],
 			    size_t num);
-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 batadv_interface_check_netlink(const char *mesh_iface);
 
 extern struct nla_policy batadv_netlink_policy[];
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [B.A.T.M.A.N.] [PATCH 2/5] alfred: Only query tq of remote master in slave mode
  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 ` 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
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Sven Eckelmann @ 2017-05-24 10:32 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

The querying of the originator mac address and tq values of the orignator
address takes significant amount of time. It is therefore better to avoid
the TQ retrieval code when possible.

The TQ will not be used in master mode and it can therefore be skipped
together with the code which tries to find the new best server.

Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
---
 recv.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/recv.c b/recv.c
index 3fd964d..8aa512d 100644
--- a/recv.c
+++ b/recv.c
@@ -304,6 +304,13 @@ process_alfred_announce_master(struct globals *globals,
 	}
 
 	clock_gettime(CLOCK_MONOTONIC, &server->last_seen);
+
+	/* TQ is not used for master sync mode */
+	if (globals->opmode == OPMODE_MASTER) {
+		server->tq = 0;
+		return 0;
+	}
+
 	if (strcmp(globals->mesh_iface, "none") != 0) {
 		macaddr = translate_mac(globals->mesh_iface,
 					(struct ether_addr *)&server->hwaddr);
@@ -315,8 +322,7 @@ process_alfred_announce_master(struct globals *globals,
 		server->tq = 255;
 	}
 
-	if (globals->opmode == OPMODE_SLAVE)
-		set_best_server(globals);
+	set_best_server(globals);
 
 	return 0;
 }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [B.A.T.M.A.N.] [PATCH 3/5] alfred: Check the TQ of master servers before pushing data
  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 ` Sven Eckelmann
  2017-05-24 10:32 ` [B.A.T.M.A.N.] [PATCH 4/5] alfred: Cache the TQ values for each originator Sven Eckelmann
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Sven Eckelmann @ 2017-05-24 10:32 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

The TQ value of the server might have changed dramatically since we
received the last announcement of a master server. This can especially
happen when node (which was previously the best server) moves a lot and its
announcements are lost for a while.

Instead of querying the TQ values of each node when receiving an
announcement, just query the TQ value before new data should be pushed to a
master server.

Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
---
 alfred.h |  1 -
 recv.c   | 21 +--------------------
 server.c | 36 +++++++++++++++++++++++++++++++++++-
 3 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/alfred.h b/alfred.h
index 5f7a98c..429953f 100644
--- a/alfred.h
+++ b/alfred.h
@@ -153,7 +153,6 @@ extern alfred_addr alfred_mcast;
 
 /* server.c */
 int alfred_server(struct globals *globals);
-int set_best_server(struct globals *globals);
 void changed_data_type(struct globals *globals, uint8_t arg);
 
 /* client.c */
diff --git a/recv.c b/recv.c
index 8aa512d..12bb3f1 100644
--- a/recv.c
+++ b/recv.c
@@ -268,7 +268,6 @@ process_alfred_announce_master(struct globals *globals,
 			       struct alfred_announce_master_v0 *announce)
 {
 	struct server *server;
-	struct ether_addr *macaddr;
 	struct ether_addr mac;
 	int ret;
 	int len;
@@ -296,6 +295,7 @@ process_alfred_announce_master(struct globals *globals,
 
 		memcpy(&server->hwaddr, &mac, ETH_ALEN);
 		memcpy(&server->address, source, sizeof(*source));
+		server->tq = 0;
 
 		if (hash_add(interface->server_hash, server)) {
 			free(server);
@@ -305,25 +305,6 @@ process_alfred_announce_master(struct globals *globals,
 
 	clock_gettime(CLOCK_MONOTONIC, &server->last_seen);
 
-	/* TQ is not used for master sync mode */
-	if (globals->opmode == OPMODE_MASTER) {
-		server->tq = 0;
-		return 0;
-	}
-
-	if (strcmp(globals->mesh_iface, "none") != 0) {
-		macaddr = translate_mac(globals->mesh_iface,
-					(struct ether_addr *)&server->hwaddr);
-		if (macaddr)
-			server->tq = get_tq(globals->mesh_iface, macaddr);
-		else
-			server->tq = 0;
-	} else {
-		server->tq = 255;
-	}
-
-	set_best_server(globals);
-
 	return 0;
 }
 
diff --git a/server.c b/server.c
index 2c4042a..09acb80 100644
--- a/server.c
+++ b/server.c
@@ -113,7 +113,7 @@ static int create_hashes(struct globals *globals)
 	return 0;
 }
 
-int set_best_server(struct globals *globals)
+static int set_best_server(struct globals *globals)
 {
 	struct hash_it_t *hashit = NULL;
 	struct server *best_server = NULL;
@@ -218,6 +218,39 @@ static int purge_data(struct globals *globals)
 	return 0;
 }
 
+static void update_server_info(struct globals *globals)
+{
+	struct hash_it_t *hashit = NULL;
+	struct interface *interface;
+	struct ether_addr *macaddr;
+
+	/* TQ is not used for master sync mode */
+	if (globals->opmode == OPMODE_MASTER)
+		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) {
+				server->tq = 255;
+				continue;
+			}
+
+			macaddr = translate_mac(globals->mesh_iface,
+						&server->hwaddr);
+			if (macaddr)
+				server->tq = get_tq(globals->mesh_iface,
+						    macaddr);
+			else
+				server->tq = 0;
+		}
+	}
+
+	set_best_server(globals);
+}
+
 static void check_if_socket(struct interface *interface, struct globals *globals)
 {
 	int sock;
@@ -422,6 +455,7 @@ int alfred_server(struct globals *globals)
 			sync_data(globals);
 		} else {
 			/* send local data to server */
+			update_server_info(globals);
 			push_local_data(globals);
 		}
 		purge_data(globals);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [B.A.T.M.A.N.] [PATCH 4/5] alfred: Cache the TQ values for each originator
  2017-05-24 10:31 [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations Sven Eckelmann
                   ` (2 preceding siblings ...)
  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
  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
  5 siblings, 0 replies; 8+ messages in thread
From: Sven Eckelmann @ 2017-05-24 10:32 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

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


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [B.A.T.M.A.N.] [PATCH 5/5] alfred: Cache the global translation table entries
  2017-05-24 10:31 [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations Sven Eckelmann
                   ` (3 preceding siblings ...)
  2017-05-24 10:32 ` [B.A.T.M.A.N.] [PATCH 4/5] alfred: Cache the TQ values for each originator Sven Eckelmann
@ 2017-05-24 10:32 ` Sven Eckelmann
  2017-05-31 15:24 ` [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations Simon Wunderlich
  5 siblings, 0 replies; 8+ messages in thread
From: Sven Eckelmann @ 2017-05-24 10:32 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

There is a single loop which goes over all servers to find the originator
for each server. The originator usually doesn't change often because alfred
is usually started on the nodes which is already running batman-adv. It is
therefore not necessary to re-request the complete global translation table
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   | 117 +++++++++++++++++++++++++++++++++++++++++--------------
 batadv_query.h   |  11 +++++-
 batadv_querynl.c |  25 ++++--------
 batadv_querynl.h |   3 +-
 server.c         |  15 +++++--
 5 files changed, 118 insertions(+), 53 deletions(-)

diff --git a/batadv_query.c b/batadv_query.c
index 1123cf5..8580f1b 100644
--- a/batadv_query.c
+++ b/batadv_query.c
@@ -193,8 +193,7 @@ int batadv_interface_check(const char *mesh_iface)
 }
 
 static int translate_mac_debugfs(const char *mesh_iface,
-				 const struct ether_addr *mac,
-				 struct ether_addr *mac_out)
+				 struct hashtable_t *tg_hash)
 {
 	enum {
 		tg_start,
@@ -204,12 +203,12 @@ static int translate_mac_debugfs(const char *mesh_iface,
 	} pos;
 	char full_path[MAX_PATH+1];
 	struct ether_addr *mac_tmp;
+	struct ether_addr mac;
 	FILE *f = NULL;
 	size_t len = 0;
 	char *line = NULL;
 	char *input, *saveptr, *token;
 	int line_invalid;
-	bool found = false;
 
 	debugfs_make_path(DEBUG_BATIF_PATH_FMT "/" DEBUG_TRANSTABLE_GLOBAL,
 			  mesh_iface, full_path, sizeof(full_path));
@@ -235,11 +234,12 @@ static int translate_mac_debugfs(const char *mesh_iface,
 				break;
 			case tg_mac:
 				mac_tmp = ether_aton(token);
-				if (!mac_tmp || memcmp(mac_tmp, mac,
-						       ETH_ALEN) != 0)
+				if (!mac_tmp) {
 					line_invalid = 1;
-				else
+				} else {
+					memcpy(&mac, mac_tmp, sizeof(mac));
 					pos = tg_via;
+				}
 				break;
 			case tg_via:
 				if (strcmp(token, "via") == 0)
@@ -247,13 +247,10 @@ static int translate_mac_debugfs(const char *mesh_iface,
 				break;
 			case tg_originator:
 				mac_tmp = ether_aton(token);
-				if (!mac_tmp) {
+				if (!mac_tmp)
 					line_invalid = 1;
-				} else {
-					memcpy(mac_out, mac_tmp, ETH_ALEN);
-					found = true;
-					goto out;
-				}
+				else
+					tg_hash_add(tg_hash, &mac, mac_tmp);
 				break;
 			}
 
@@ -262,40 +259,100 @@ static int translate_mac_debugfs(const char *mesh_iface,
 		}
 	}
 
-out:
 	if (f)
 		fclose(f);
 	free(line);
 
-	if (found)
-		return 0;
+	return 0;
+}
+
+static int tg_compare(void *d1, void *d2)
+{
+	struct tg_entry *s1 = d1, *s2 = d2;
+
+	if (memcmp(&s1->mac, &s2->mac, sizeof(s1->mac)) == 0)
+		return 1;
 	else
-		return -ENOENT;
+		return 0;
 }
 
-struct ether_addr *translate_mac(const char *mesh_iface,
-				 const struct ether_addr *mac)
+static int tg_choose(void *d1, int size)
 {
-	struct ether_addr in_mac;
-	static struct ether_addr out_mac;
-	struct ether_addr *mac_result;
+	struct tg_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 *tg_hash_new(const char *mesh_iface)
+{
+	struct hashtable_t *tg_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));
-	memcpy(&out_mac, mac, sizeof(out_mac));
-	mac_result = &out_mac;
+	tg_hash = hash_new(64, tg_compare, tg_choose);
+	if (!tg_hash)
+		return NULL;
 
 	enable_net_admin_capability(1);
-	ret = translate_mac_netlink(mesh_iface, &in_mac, mac_result);
+	ret = translate_mac_netlink(mesh_iface, tg_hash);
 	enable_net_admin_capability(0);
 
+	ret = -EOPNOTSUPP;
 	if (ret == -EOPNOTSUPP)
-		translate_mac_debugfs(mesh_iface, &in_mac, mac_result);
+		translate_mac_debugfs(mesh_iface, tg_hash);
+
+	return tg_hash;
+}
+
+void tg_hash_free(struct hashtable_t *tg_hash)
+{
+	hash_delete(tg_hash, free);
+}
+
+int tg_hash_add(struct hashtable_t *tg_hash, struct ether_addr *mac,
+		struct ether_addr *originator)
+{
+	struct tg_entry *n;
+
+	n = malloc(sizeof(*n));
+	if (!n)
+		return -ENOMEM;
+
+	n->mac = *mac;
+	n->originator = *originator;
+
+	if (hash_add(tg_hash, n)) {
+		free(n);
+		return -EEXIST;
+	}
+
+	return 0;
+}
+
+struct ether_addr *translate_mac(struct hashtable_t *tg_hash,
+				 const struct ether_addr *mac)
+{
+	struct tg_entry search = {
+		.mac = *mac,
+	};
+	struct tg_entry *found;
+
+	found = hash_find(tg_hash, &search);
+	if (!found)
+		return 0;
 
-	return mac_result;
+	return &found->originator;
 }
 
 static int get_tq_debugfs(const char *mesh_iface, struct hashtable_t *orig_hash)
diff --git a/batadv_query.h b/batadv_query.h
index aa4d3f8..dc2b135 100644
--- a/batadv_query.h
+++ b/batadv_query.h
@@ -31,7 +31,16 @@ struct orig_entry {
 	uint8_t tq;
 };
 
-struct ether_addr *translate_mac(const char *mesh_iface,
+struct tg_entry {
+	struct ether_addr mac;
+	struct ether_addr originator;
+};
+
+struct hashtable_t *tg_hash_new(const char *mesh_iface);
+void tg_hash_free(struct hashtable_t *tg_hash);
+int tg_hash_add(struct hashtable_t *tg_hash, struct ether_addr *mac,
+		struct ether_addr *originator);
+struct ether_addr *translate_mac(struct hashtable_t *tg_hash,
 				 const struct ether_addr *mac);
 
 struct hashtable_t *orig_hash_new(const char *mesh_iface);
diff --git a/batadv_querynl.c b/batadv_querynl.c
index ba678ae..ca9ee2c 100644
--- a/batadv_querynl.c
+++ b/batadv_querynl.c
@@ -49,8 +49,7 @@ static const int translate_mac_netlink_mandatory[] = {
 };
 
 struct translate_mac_netlink_opts {
-	struct ether_addr mac;
-	bool found;
+	struct hashtable_t *tg_hash;
 	struct nlquery_opts query_opts;
 };
 
@@ -61,6 +60,8 @@ static int translate_mac_netlink_cb(struct nl_msg *msg, void *arg)
 	struct nlquery_opts *query_opts = arg;
 	struct translate_mac_netlink_opts *opts;
 	struct genlmsghdr *ghdr;
+	struct ether_addr mac_addr;
+	struct ether_addr mac_orig;
 	uint8_t *addr;
 	uint8_t *orig;
 
@@ -90,40 +91,30 @@ static int translate_mac_netlink_cb(struct nl_msg *msg, void *arg)
 	if (!attrs[BATADV_ATTR_FLAG_BEST])
 		return NL_OK;
 
-	if (memcmp(&opts->mac, addr, ETH_ALEN) != 0)
-		return NL_OK;
-
-	memcpy(&opts->mac, orig, ETH_ALEN);
-	opts->found = true;
+	memcpy(&mac_addr, addr, sizeof(mac_addr));
+	memcpy(&mac_orig, orig, sizeof(mac_orig));
+	tg_hash_add(opts->tg_hash, &mac_addr, &mac_orig);
 	opts->query_opts.err = 0;
 
 	return NL_STOP;
 }
 
-int translate_mac_netlink(const char *mesh_iface, const struct ether_addr *mac,
-			  struct ether_addr *mac_out)
+int translate_mac_netlink(const char *mesh_iface, struct hashtable_t *tg_hash)
 {
 	struct translate_mac_netlink_opts opts = {
-		.found = false,
+		.tg_hash = tg_hash,
 		.query_opts = {
 			.err = 0,
 		},
 	};
 	int ret;
 
-	memcpy(&opts.mac, mac, ETH_ALEN);
-
 	ret = netlink_query_common(mesh_iface,
 				   BATADV_CMD_GET_TRANSTABLE_GLOBAL,
 				   translate_mac_netlink_cb, &opts.query_opts);
 	if (ret < 0)
 		return ret;
 
-	if (!opts.found)
-		return -ENOENT;
-
-	memcpy(mac_out, &opts.mac, ETH_ALEN);
-
 	return 0;
 }
 
diff --git a/batadv_querynl.h b/batadv_querynl.h
index f5c7e38..4b42ed5 100644
--- a/batadv_querynl.h
+++ b/batadv_querynl.h
@@ -27,8 +27,7 @@
 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 translate_mac_netlink(const char *mesh_iface, struct hashtable_t *tg_hash);
 int get_tq_netlink(const char *mesh_iface, struct hashtable_t *orig_hash);
 int batadv_interface_check_netlink(const char *mesh_iface);
 
diff --git a/server.c b/server.c
index 91aa729..f28c89a 100644
--- a/server.c
+++ b/server.c
@@ -223,6 +223,7 @@ static void update_server_info(struct globals *globals)
 	struct hash_it_t *hashit = NULL;
 	struct interface *interface;
 	struct ether_addr *macaddr;
+	struct hashtable_t *tg_hash;
 	struct hashtable_t *orig_hash;
 
 	/* TQ is not used for master sync mode */
@@ -230,10 +231,16 @@ static void update_server_info(struct globals *globals)
 		return;
 
 	if (strcmp(globals->mesh_iface, "none") != 0) {
+		tg_hash = tg_hash_new(globals->mesh_iface);
+		if (!globals->data_hash) {
+			fprintf(stderr, "Failed to translation hash\n");
+			return;
+		}
+
 		orig_hash = orig_hash_new(globals->mesh_iface);
 		if (!globals->data_hash) {
 			fprintf(stderr, "Failed to originator hash\n");
-			return;
+			goto free_tg_hash;
 		}
 	}
 
@@ -247,8 +254,7 @@ static void update_server_info(struct globals *globals)
 				continue;
 			}
 
-			macaddr = translate_mac(globals->mesh_iface,
-						&server->hwaddr);
+			macaddr = translate_mac(tg_hash, &server->hwaddr);
 			if (macaddr)
 				server->tq = get_tq(orig_hash, macaddr);
 			else
@@ -260,6 +266,9 @@ static void update_server_info(struct globals *globals)
 
 	if (orig_hash)
 		orig_hash_free(orig_hash);
+free_tg_hash:
+	if (tg_hash)
+		tg_hash_free(tg_hash);
 }
 
 static void check_if_socket(struct interface *interface, struct globals *globals)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations
  2017-05-24 10:31 [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations Sven Eckelmann
                   ` (4 preceding siblings ...)
  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 ` Simon Wunderlich
  2017-06-01  6:15   ` Sven Eckelmann
  5 siblings, 1 reply; 8+ messages in thread
From: Simon Wunderlich @ 2017-05-31 15:24 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

[-- Attachment #1: Type: text/plain, Size: 1980 bytes --]

On Wednesday, May 24, 2017 12:31:28 PM CEST Sven Eckelmann wrote:
> Hi,
> 
> alfred uses the TQ from batman-adv to find its best alfred neighbor. This
> best neighbor information is used by slave servers to request/publish data.
> 
> This is done for each server announcement packet by:
> 
>  * requesting the global translation table (netlink or debugfs) and then
>    searching in it for the MAC address of the detected alfred server to find
> its originator address
>  * requesting the originator table (netlink or debugfs) and then searching
> it it for the originator address of the detected alfred server to find its
> TQ value
> 
> This was previously done whenever a new announcement packet received by
> alfred. We've observed that this can be a problem on networks with a lot of
> master servers (~100) which can see each other, large translation tables and
> slow CPUs. alfred still worked but the CPU load by alfred was rather high
> (~20% on an 560MHz AR9344).
> 
> The idea is now to avoid this lookup for master servers. And (for slave
> servers) to process all servers at once. This is done before the wants to
> push its local data to a master server in an sync interval.
> 
> The process which was described earlier was now changed to:
> 
>  * requesting the global translation table (netlink or debugfs) and then put
> MAC address and corresponding originator address in tg hash
>  * requesting the originator table (netlink or debugfs) and then put
>    originator address and corresponding TQ value orig hash
>  * got through all servers:
>    - search in tg hash for for the MAC address of the alfred server to find
>    its originator address
>    - search in orig hash for for the originator address of the alfred server
> to find its TQ value
> 
> These changes reduced the load on the previously mentioned devices
> significantly.

I've applied this patch series with some fixes in patch 4 and 5 regarding the 
hash initialization.

Thank you,
     Simon

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [B.A.T.M.A.N.] [PATCH 0/5] alfred: TQ query optimizations
  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
  0 siblings, 0 replies; 8+ messages in thread
From: Sven Eckelmann @ 2017-06-01  6:15 UTC (permalink / raw)
  To: b.a.t.m.a.n

[-- Attachment #1: Type: text/plain, Size: 298 bytes --]

On Mittwoch, 31. Mai 2017 17:24:45 CEST Simon Wunderlich wrote:
[....]
> I've applied this patch series with some fixes in patch 4 and 5 regarding the 
> hash initialization.
> 
> Thank you,
>      Simon

It looks like you haven't actually changed it. I will post fixes for it.

Kind regards,
	Sven

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-06-01  6:15 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [B.A.T.M.A.N.] [PATCH 4/5] alfred: Cache the TQ values for each originator Sven Eckelmann
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

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.