All of lore.kernel.org
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
@ 2016-03-17 16:45 Matthias Schiffer
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 1/5] batman-adv: add generic netlink query API to replace debugfs files Matthias Schiffer
                   ` (7 more replies)
  0 siblings, 8 replies; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-17 16:45 UTC (permalink / raw)
  To: b.a.t.m.a.n

Hi,
this is the second take of my netlink API patches. As mentioned before, the
netlink API is superior to the current debugfs API in many aspects:

* debugfs is broken (see PATCH 1 for details)
* Netlink is namespace-aware, and can be used in unprivileged containers
  without problems
* Netlink packets are more machine-readable than text files, and can be
  easily extended without potentially breaking userspace
* On older kernels, seq_file can't fall back to vmalloc if kmalloc fails,
  which often leads to OOM when reading "originators" in large meshes, as
  the whole file must fit into a single buffer

Of course, are also a few downsides; when the data is too big to fit into
a single netlink packet, the provided data may be inconsistent (entries may
be missing or duplicated.) This will happen in large meshes only, and be
improbable in any case.

The patches have been developed on top of the netns patchset, but should
be applicable independently (maybe with minor changes.)

All netlink queries returning lists of any kind can only be used with
NLM_F_DUMP queries, so that arbitrarity large responses are possible (split
across multiple packets if necessary.)

At the moment, the following debugfs files have corresponding netlink APIs:

* routing_algos
* neighbors
* originators
* transtable_global
* transtable_local
* (hardinterfaces for a softif can be queried)

The following files are still missing:

* gateways
* bla_claim_table
* bla_backbone_table
* dat_cache
* nc_nodes

Obviously, documentation is also a TODO. Comments about the API design are
very welcome...

Regards,
Matthias


Matthias Schiffer (5):
  batman-adv: add generic netlink query API to replace debugfs files
  batman-adv: netlink: add translation table query
  batman-adv: netlink: add originator and neighbor table queries
  batman-adv: add B.A.T.M.A.N. IV bat_{orig,neigh}_dump implementations
  batman-adv: add B.A.T.M.A.N. V bat_{orig,neigh}_dump implementations

 Makefile                           |   1 +
 include/uapi/linux/batman_adv.h    | 101 ++++++++++++
 net/batman-adv/Makefile            |   1 +
 net/batman-adv/bat_iv_ogm.c        | 268 ++++++++++++++++++++++++++++++++
 net/batman-adv/bat_v.c             | 250 ++++++++++++++++++++++++++++++
 net/batman-adv/main.c              |  48 ++++++
 net/batman-adv/main.h              |   1 +
 net/batman-adv/netlink.c           | 276 +++++++++++++++++++++++++++++++++
 net/batman-adv/netlink.h           |  36 +++++
 net/batman-adv/originator.c        | 142 +++++++++++++++++
 net/batman-adv/originator.h        |   2 +
 net/batman-adv/packet.h            |  36 -----
 net/batman-adv/translation-table.c | 305 +++++++++++++++++++++++++++++++++++++
 net/batman-adv/translation-table.h |   2 +
 net/batman-adv/types.h             |   7 +
 15 files changed, 1440 insertions(+), 36 deletions(-)
 create mode 100644 include/uapi/linux/batman_adv.h
 create mode 100644 net/batman-adv/netlink.c
 create mode 100644 net/batman-adv/netlink.h

-- 
2.7.3


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

* [B.A.T.M.A.N.] [RFC v2 1/5] batman-adv: add generic netlink query API to replace debugfs files
  2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
@ 2016-03-17 16:45 ` Matthias Schiffer
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 2/5] batman-adv: netlink: add translation table query Matthias Schiffer
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-17 16:45 UTC (permalink / raw)
  To: b.a.t.m.a.n

debugfs is currently severely broken virtually everywhere in the kernel
where files are dynamically added and removed (see
http://lkml.iu.edu/hypermail/linux/kernel/1506.1/02196.html for some
details). In addition to that, debugfs is not namespace-aware.

Also, the debugfs interface will try to fix the whole list of originators/
TT entries into a single buffer. The situation has improved in recent
kernels,as the seq_file infrastructure will fall back to vmalloc now when
kmalloc fails. Still, converting all information to text and potentially
retrying multiple times until the buffer is big enough is very inefficient.

This commit adds generic infrastructur for the netlink interface to
batman-adv and implements the following command:

* BATADV_CMD_GET_ROUTING_ALGOS: will return the list of supported routing
  algorithms
* BATADV_CMD_GET_MESH_INFO: will return basic information about a
  batman-adv softif (name, index and MAC address for both the softif and
  the primary hardif; routing algorithm; batman-adv version)
* BATADV_CMD_GET_HARDIFS: will return the list of hardifs (including
  index, name and MAC address) of all hardifs for a given softif

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
---
 Makefile                        |   1 +
 include/uapi/linux/batman_adv.h |  49 ++++++++
 net/batman-adv/Makefile         |   1 +
 net/batman-adv/main.c           |  48 ++++++++
 net/batman-adv/main.h           |   1 +
 net/batman-adv/netlink.c        | 251 ++++++++++++++++++++++++++++++++++++++++
 net/batman-adv/netlink.h        |  36 ++++++
 7 files changed, 387 insertions(+)
 create mode 100644 include/uapi/linux/batman_adv.h
 create mode 100644 net/batman-adv/netlink.c
 create mode 100644 net/batman-adv/netlink.h

diff --git a/Makefile b/Makefile
index dc45cc8..c6cabd4 100644
--- a/Makefile
+++ b/Makefile
@@ -54,6 +54,7 @@ REVISION= $(shell	if [ -d "$(PWD)/.git" ]; then \
 			fi)
 export NOSTDINC_FLAGS := \
 	-I$(PWD)/compat-include/ \
+	-I$(PWD)/include/ \
 	-include $(PWD)/compat.h \
 	$(CFLAGS)
 
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
new file mode 100644
index 0000000..b9b7dfd
--- /dev/null
+++ b/include/uapi/linux/batman_adv.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2016 B.A.T.M.A.N. contributors:
+ *
+ * Matthias Schiffer
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _UAPI_LINUX_BATMAN_ADV_H_
+#define _UAPI_LINUX_BATMAN_ADV_H_
+
+#define BATADV_NL_NAME "batadv"
+
+enum {
+	BATADV_ATTR_UNSPEC,
+	BATADV_ATTR_VERSION,
+	BATADV_ATTR_ALGO_NAME,
+	BATADV_ATTR_MESH_IFINDEX,
+	BATADV_ATTR_MESH_IFNAME,
+	BATADV_ATTR_MESH_ADDRESS,
+	BATADV_ATTR_HARD_IFINDEX,
+	BATADV_ATTR_HARD_IFNAME,
+	BATADV_ATTR_HARD_ADDRESS,
+	BATADV_ATTR_ACTIVE,
+	__BATADV_ATTR_MAX,
+};
+
+#define BATADV_ATTR_MAX (__BATADV_ATTR_MAX - 1)
+
+enum {
+	BATADV_CMD_UNSPEC,
+	BATADV_CMD_GET_ROUTING_ALGOS,
+	BATADV_CMD_GET_MESH_INFO,
+	BATADV_CMD_GET_HARDIFS,
+	__BATADV_CMD_MAX,
+};
+
+#define BATADV_CMD_MAX (__BATADV_CMD_MAX - 1)
+
+#endif /* _UAPI_LINUX_BATMAN_ADV_H_ */
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 797cf2f..4e5adba 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -33,6 +33,7 @@ batman-adv-y += hash.o
 batman-adv-y += icmp_socket.o
 batman-adv-y += main.o
 batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast.o
+batman-adv-y += netlink.o
 batman-adv-$(CONFIG_BATMAN_ADV_NC) += network-coding.o
 batman-adv-y += originator.o
 batman-adv-y += routing.o
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index d64ddb9..895b7b6 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -47,6 +47,7 @@
 #include <linux/workqueue.h>
 #include <net/dsfield.h>
 #include <net/rtnetlink.h>
+#include <uapi/linux/batman_adv.h>
 
 #include "bat_algo.h"
 #include "bridge_loop_avoidance.h"
@@ -57,6 +58,7 @@
 #include "hard-interface.h"
 #include "icmp_socket.h"
 #include "multicast.h"
+#include "netlink.h"
 #include "network-coding.h"
 #include "originator.h"
 #include "packet.h"
@@ -101,6 +103,7 @@ static int __init batadv_init(void)
 
 	register_netdevice_notifier(&batadv_hard_if_notifier);
 	rtnl_link_register(&batadv_link_ops);
+	batadv_netlink_register();
 
 	pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n",
 		BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION);
@@ -111,6 +114,7 @@ static int __init batadv_init(void)
 static void __exit batadv_exit(void)
 {
 	batadv_debugfs_destroy();
+	batadv_netlink_unregister();
 	rtnl_link_unregister(&batadv_link_ops);
 	unregister_netdevice_notifier(&batadv_hard_if_notifier);
 	batadv_hardif_remove_interfaces();
@@ -598,6 +602,50 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
 	return 0;
 }
 
+static int batadv_algo_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+				  struct batadv_algo_ops *bat_algo_ops)
+{
+	void *hdr;
+
+	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
+			  BATADV_CMD_GET_ROUTING_ALGOS);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	if (nla_put_string(msg, BATADV_ATTR_ALGO_NAME, bat_algo_ops->name))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+int batadv_algo_dump(struct sk_buff *msg, struct netlink_callback *cb)
+{
+	int portid = NETLINK_CB(cb->skb).portid;
+	struct batadv_algo_ops *bat_algo_ops;
+	int skip = cb->args[0];
+	int i = 0;
+
+	hlist_for_each_entry(bat_algo_ops, &batadv_algo_list, list) {
+		if (i++ < skip)
+			continue;
+
+		if (batadv_algo_dump_entry(msg, portid, cb->nlh->nlmsg_seq,
+					   bat_algo_ops)) {
+			i--;
+			break;
+		}
+	}
+
+	cb->args[0] = i;
+
+	return msg->len;
+}
+
 /**
  * batadv_skb_crc32 - calculate CRC32 of the whole packet and skip bytes in
  *  the header
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index e602408..3cae306 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -217,6 +217,7 @@ void batadv_recv_handler_unregister(u8 packet_type);
 int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
 int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
+int batadv_algo_dump(struct sk_buff *msg, struct netlink_callback *cb);
 __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);
 
 /**
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
new file mode 100644
index 0000000..6682f78
--- /dev/null
+++ b/net/batman-adv/netlink.c
@@ -0,0 +1,251 @@
+/* Copyright (C) 2016 B.A.T.M.A.N. contributors:
+ *
+ * Matthias Schiffer
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "main.h"
+#include "netlink.h"
+
+#include <linux/netdevice.h>
+#include <net/sock.h>
+#include <uapi/linux/batman_adv.h>
+
+#include "hard-interface.h"
+#include "originator.h"
+#include "soft-interface.h"
+#include "translation-table.h"
+
+struct genl_family batadv_netlink_family = {
+	.id = GENL_ID_GENERATE,
+	.hdrsize = 0,
+	.name = BATADV_NL_NAME,
+	.version = 1,
+	.maxattr = BATADV_ATTR_MAX,
+};
+
+static int
+batadv_netlink_mesh_info_put(struct sk_buff *msg, struct net_device *soft_iface)
+{
+	int ret = -ENOBUFS;
+	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
+	struct batadv_hard_iface *primary_if = NULL;
+	struct net_device *hard_iface;
+
+	if (nla_put_string(msg, BATADV_ATTR_VERSION, BATADV_SOURCE_VERSION) ||
+	    nla_put_string(msg, BATADV_ATTR_ALGO_NAME,
+			   bat_priv->bat_algo_ops->name) ||
+	    nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, soft_iface->ifindex) ||
+	    nla_put_string(msg, BATADV_ATTR_MESH_IFNAME, soft_iface->name) ||
+	    nla_put(msg, BATADV_ATTR_MESH_ADDRESS, ETH_ALEN,
+		    soft_iface->dev_addr))
+		goto out;
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (primary_if && primary_if->if_status == BATADV_IF_ACTIVE) {
+		hard_iface = primary_if->net_dev;
+
+		if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
+				hard_iface->ifindex) ||
+		    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
+				   hard_iface->name) ||
+		    nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN,
+			    hard_iface->dev_addr))
+			goto out;
+	}
+
+	ret = 0;
+
+ out:
+	if (primary_if)
+		batadv_hardif_put(primary_if);
+
+	return ret;
+}
+
+static int
+batadv_netlink_get_mesh_info(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net *net = genl_info_net(info);
+	int ret;
+	struct sk_buff *msg = NULL;
+	void *msg_head;
+	int ifindex;
+	struct net_device *soft_iface;
+
+	if (!info->attrs[BATADV_ATTR_MESH_IFINDEX])
+		return -EINVAL;
+
+	ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]);
+	if (!ifindex)
+		return -EINVAL;
+
+	soft_iface = dev_get_by_index(net, ifindex);
+	if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+			       &batadv_netlink_family, 0,
+			       BATADV_CMD_GET_MESH_INFO);
+	if (!msg_head) {
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	ret = batadv_netlink_mesh_info_put(msg, soft_iface);
+
+ out:
+	if (soft_iface)
+		dev_put(soft_iface);
+
+	if (ret) {
+		if (msg)
+			nlmsg_free(msg);
+		return ret;
+	}
+
+	genlmsg_end(msg, msg_head);
+	return genlmsg_reply(msg, info);
+}
+
+static int
+batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, u32 seq,
+				 struct batadv_hard_iface *hard_iface)
+{
+	struct net_device *net_dev = hard_iface->net_dev;
+	void *hdr;
+
+	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
+			  BATADV_CMD_GET_HARDIFS);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
+			net_dev->ifindex) ||
+	    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
+			   net_dev->name) ||
+	    nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN,
+		    net_dev->dev_addr))
+		goto nla_put_failure;
+
+	if (hard_iface->if_status == BATADV_IF_ACTIVE) {
+		if (nla_put_flag(msg, BATADV_ATTR_ACTIVE))
+			goto nla_put_failure;
+	}
+
+	genlmsg_end(msg, hdr);
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int
+batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(cb->skb->sk);
+	struct net_device *soft_iface;
+	struct batadv_hard_iface *hard_iface;
+	int ifindex;
+	int portid = NETLINK_CB(cb->skb).portid;
+	int seq = cb->nlh->nlmsg_seq;
+	int skip = cb->args[0];
+	int i = 0;
+
+	ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
+	if (!ifindex)
+		return -EINVAL;
+
+	soft_iface = dev_get_by_index(net, ifindex);
+	if (!soft_iface)
+		return -ENODEV;
+
+	if (!batadv_softif_is_valid(soft_iface)) {
+		dev_put(soft_iface);
+		return -ENODEV;
+	}
+
+	rcu_read_lock();
+
+	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+		if (hard_iface->soft_iface != soft_iface)
+			continue;
+
+		if (i++ < skip)
+			continue;
+
+		if (batadv_netlink_dump_hardif_entry(msg, portid, seq,
+						     hard_iface)) {
+			i--;
+			break;
+		}
+	}
+
+	rcu_read_unlock();
+
+	dev_put(soft_iface);
+
+	cb->args[0] = i;
+
+	return msg->len;
+}
+
+static struct nla_policy batadv_netlink_policy[BATADV_ATTR_MAX + 1] = {
+	[BATADV_ATTR_MESH_IFINDEX]	= { .type = NLA_U32 },
+};
+
+static struct genl_ops batadv_netlink_ops[] = {
+	{
+		.cmd = BATADV_CMD_GET_ROUTING_ALGOS,
+		.flags = GENL_ADMIN_PERM,
+		.policy = batadv_netlink_policy,
+		.dumpit = batadv_algo_dump,
+	},
+	{
+		.cmd = BATADV_CMD_GET_MESH_INFO,
+		.flags = GENL_ADMIN_PERM,
+		.policy = batadv_netlink_policy,
+		.doit = batadv_netlink_get_mesh_info,
+	},
+	{
+		.cmd = BATADV_CMD_GET_HARDIFS,
+		.flags = GENL_ADMIN_PERM,
+		.policy = batadv_netlink_policy,
+		.dumpit = batadv_netlink_dump_hardifs,
+	},
+};
+
+void __init batadv_netlink_register(void)
+{
+	int ret;
+
+	ret = genl_register_family_with_ops(&batadv_netlink_family,
+					    batadv_netlink_ops);
+	if (ret)
+		pr_warn("unable to register netlink family");
+}
+
+void batadv_netlink_unregister(void)
+{
+	genl_unregister_family(&batadv_netlink_family);
+}
diff --git a/net/batman-adv/netlink.h b/net/batman-adv/netlink.h
new file mode 100644
index 0000000..31022d4
--- /dev/null
+++ b/net/batman-adv/netlink.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2016 B.A.T.M.A.N. contributors:
+ *
+ * Matthias Schiffer
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NET_BATMAN_ADV_NETLINK_H_
+#define _NET_BATMAN_ADV_NETLINK_H_
+
+#include <net/genetlink.h>
+
+void batadv_netlink_register(void);
+void batadv_netlink_unregister(void);
+
+static inline int
+batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype)
+{
+	struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype);
+
+	return attr ? nla_get_u32(attr) : 0;
+}
+
+extern struct genl_family batadv_netlink_family;
+
+#endif /* _NET_BATMAN_ADV_NETLINK_H_ */
-- 
2.7.3


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

* [B.A.T.M.A.N.] [RFC v2 2/5] batman-adv: netlink: add translation table query
  2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 1/5] batman-adv: add generic netlink query API to replace debugfs files Matthias Schiffer
@ 2016-03-17 16:45 ` Matthias Schiffer
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 3/5] batman-adv: netlink: add originator and neighbor table queries Matthias Schiffer
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-17 16:45 UTC (permalink / raw)
  To: b.a.t.m.a.n

This adds the commands BATADV_CMD_GET_TRANSTABLE_LOCAL and
BATADV_CMD_GET_TRANSTABLE_GLOBAL, which correspond to the transtable_local
and transtable_global debugfs files.

The batadv_tt_client_flags enum is moved to the UAPI to expose it as part
of the netlink API.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
---
 include/uapi/linux/batman_adv.h    |  47 ++++++
 net/batman-adv/netlink.c           |  12 ++
 net/batman-adv/packet.h            |  36 -----
 net/batman-adv/translation-table.c | 305 +++++++++++++++++++++++++++++++++++++
 net/batman-adv/translation-table.h |   2 +
 5 files changed, 366 insertions(+), 36 deletions(-)

diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index b9b7dfd..25dee3c 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -20,6 +20,42 @@
 
 #define BATADV_NL_NAME "batadv"
 
+/**
+ * enum batadv_tt_client_flags - TT client specific flags
+ * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table
+ * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and the new
+ *  update telling its new real location has not been received/sent yet
+ * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi interface.
+ *  This information is used by the "AP Isolation" feature
+ * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This
+ *  information is used by the Extended Isolation feature
+ * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from the table
+ * @BATADV_TT_CLIENT_NEW: this client has been added to the local table but has
+ *  not been announced yet
+ * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it is kept
+ *  in the table for one more originator interval for consistency purposes
+ * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be part of
+ *  the network but no nnode has already announced it
+ *
+ * Bits from 0 to 7 are called _remote flags_ because they are sent on the wire.
+ * Bits from 8 to 15 are called _local flags_ because they are used for local
+ * computations only.
+ *
+ * Bits from 4 to 7 - a subset of remote flags - are ensured to be in sync with
+ * the other nodes in the network. To achieve this goal these flags are included
+ * in the TT CRC computation.
+ */
+enum batadv_tt_client_flags {
+	BATADV_TT_CLIENT_DEL     = (1 << 0),
+	BATADV_TT_CLIENT_ROAM    = (1 << 1),
+	BATADV_TT_CLIENT_WIFI    = (1 << 4),
+	BATADV_TT_CLIENT_ISOLA	 = (1 << 5),
+	BATADV_TT_CLIENT_NOPURGE = (1 << 8),
+	BATADV_TT_CLIENT_NEW     = (1 << 9),
+	BATADV_TT_CLIENT_PENDING = (1 << 10),
+	BATADV_TT_CLIENT_TEMP	 = (1 << 11),
+};
+
 enum {
 	BATADV_ATTR_UNSPEC,
 	BATADV_ATTR_VERSION,
@@ -31,6 +67,15 @@ enum {
 	BATADV_ATTR_HARD_IFNAME,
 	BATADV_ATTR_HARD_ADDRESS,
 	BATADV_ATTR_ACTIVE,
+	BATADV_ATTR_ORIG_ADDRESS,
+	BATADV_ATTR_TT_ADDRESS,
+	BATADV_ATTR_TT_TTVN,
+	BATADV_ATTR_TT_LAST_TTVN,
+	BATADV_ATTR_TT_CRC32,
+	BATADV_ATTR_TT_VID,
+	BATADV_ATTR_TT_FLAGS,
+	BATADV_ATTR_FLAG_BEST,
+	BATADV_ATTR_LAST_SEEN_MSECS,
 	__BATADV_ATTR_MAX,
 };
 
@@ -41,6 +86,8 @@ enum {
 	BATADV_CMD_GET_ROUTING_ALGOS,
 	BATADV_CMD_GET_MESH_INFO,
 	BATADV_CMD_GET_HARDIFS,
+	BATADV_CMD_GET_TRANSTABLE_LOCAL,
+	BATADV_CMD_GET_TRANSTABLE_GLOBAL,
 	__BATADV_CMD_MAX,
 };
 
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 6682f78..50047d4 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -233,6 +233,18 @@ static struct genl_ops batadv_netlink_ops[] = {
 		.policy = batadv_netlink_policy,
 		.dumpit = batadv_netlink_dump_hardifs,
 	},
+	{
+		.cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL,
+		.flags = GENL_ADMIN_PERM,
+		.policy = batadv_netlink_policy,
+		.dumpit = batadv_tt_local_dump,
+	},
+	{
+		.cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL,
+		.flags = GENL_ADMIN_PERM,
+		.policy = batadv_netlink_policy,
+		.dumpit = batadv_tt_global_dump,
+	},
 };
 
 void __init batadv_netlink_register(void)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 8a8d7ca..e7eb5eb 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -126,42 +126,6 @@ enum batadv_tt_data_flags {
 };
 
 /**
- * enum batadv_tt_client_flags - TT client specific flags
- * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table
- * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and the new
- *  update telling its new real location has not been received/sent yet
- * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi interface.
- *  This information is used by the "AP Isolation" feature
- * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This
- *  information is used by the Extended Isolation feature
- * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from the table
- * @BATADV_TT_CLIENT_NEW: this client has been added to the local table but has
- *  not been announced yet
- * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it is kept
- *  in the table for one more originator interval for consistency purposes
- * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be part of
- *  the network but no nnode has already announced it
- *
- * Bits from 0 to 7 are called _remote flags_ because they are sent on the wire.
- * Bits from 8 to 15 are called _local flags_ because they are used for local
- * computations only.
- *
- * Bits from 4 to 7 - a subset of remote flags - are ensured to be in sync with
- * the other nodes in the network. To achieve this goal these flags are included
- * in the TT CRC computation.
- */
-enum batadv_tt_client_flags {
-	BATADV_TT_CLIENT_DEL     = BIT(0),
-	BATADV_TT_CLIENT_ROAM    = BIT(1),
-	BATADV_TT_CLIENT_WIFI    = BIT(4),
-	BATADV_TT_CLIENT_ISOLA	 = BIT(5),
-	BATADV_TT_CLIENT_NOPURGE = BIT(8),
-	BATADV_TT_CLIENT_NEW     = BIT(9),
-	BATADV_TT_CLIENT_PENDING = BIT(10),
-	BATADV_TT_CLIENT_TEMP	 = BIT(11),
-};
-
-/**
  * enum batadv_vlan_flags - flags for the four MSB of any vlan ID field
  * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not
  */
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index ce63a51..1e1f2a1 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -43,11 +43,15 @@
 #include <linux/stddef.h>
 #include <linux/string.h>
 #include <linux/workqueue.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
+#include <uapi/linux/batman_adv.h>
 
 #include "bridge_loop_avoidance.h"
 #include "hard-interface.h"
 #include "hash.h"
 #include "multicast.h"
+#include "netlink.h"
 #include "originator.h"
 #include "packet.h"
 #include "soft-interface.h"
@@ -1064,6 +1068,138 @@ out:
 	return 0;
 }
 
+static int
+batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+			   struct batadv_priv *bat_priv,
+			   struct batadv_tt_common_entry *common)
+{
+	void *hdr;
+	struct batadv_softif_vlan *vlan;
+	struct batadv_tt_local_entry *local;
+	unsigned int last_seen_msecs;
+	u32 crc;
+
+	local = container_of(common, struct batadv_tt_local_entry, common);
+	last_seen_msecs = jiffies_to_msecs(jiffies - local->last_seen);
+
+	vlan = batadv_softif_vlan_get(bat_priv, common->vid);
+	if (!vlan)
+		return 0;
+
+	crc = vlan->tt.crc;
+
+	batadv_softif_vlan_put(vlan);
+
+	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
+			  BATADV_CMD_GET_TRANSTABLE_LOCAL);
+	if (!hdr)
+		return -ENOBUFS;
+
+	if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
+	    nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
+	    nla_put_u16(msg, BATADV_ATTR_TT_VID,
+			BATADV_PRINT_VID(common->vid)) ||
+	    nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
+		goto nla_put_failure;
+
+	if (!(common->flags & BATADV_TT_CLIENT_NOPURGE)) {
+		if (nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
+				last_seen_msecs))
+			goto nla_put_failure;
+	}
+
+	genlmsg_end(msg, hdr);
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int
+batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
+			    struct batadv_priv *bat_priv,
+			    struct hlist_head *head, int *idx_s)
+{
+	struct batadv_tt_common_entry *common;
+	int idx = 0;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(common, head, hash_entry) {
+		if (idx++ < *idx_s)
+			continue;
+
+		if (batadv_tt_local_dump_entry(msg, portid, seq, bat_priv,
+					       common)) {
+			rcu_read_unlock();
+			*idx_s = idx - 1;
+			return -EMSGSIZE;
+		}
+	}
+	rcu_read_unlock();
+
+	*idx_s = 0;
+	return 0;
+}
+
+int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(cb->skb->sk);
+	struct net_device *soft_iface = NULL;
+	struct batadv_priv *bat_priv;
+	struct batadv_hard_iface *primary_if = NULL;
+	struct batadv_hashtable *hash;
+	struct hlist_head *head;
+	int ret;
+	int ifindex;
+	int bucket = cb->args[0];
+	int idx = cb->args[1];
+	int portid = NETLINK_CB(cb->skb).portid;
+
+	ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
+	if (!ifindex)
+		return -EINVAL;
+
+	soft_iface = dev_get_by_index(net, ifindex);
+	if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	bat_priv = netdev_priv(soft_iface);
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	hash = bat_priv->tt.local_hash;
+
+	while (bucket < hash->size) {
+		head = &hash->table[bucket];
+
+		if (batadv_tt_local_dump_bucket(msg, portid, cb->nlh->nlmsg_seq,
+						bat_priv, head, &idx))
+			break;
+
+		bucket++;
+	}
+
+	ret = msg->len;
+
+ out:
+	if (primary_if)
+		batadv_hardif_put(primary_if);
+	if (soft_iface)
+		dev_put(soft_iface);
+
+	cb->args[0] = bucket;
+	cb->args[1] = idx;
+
+	return ret;
+}
+
 static void
 batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
 			    struct batadv_tt_local_entry *tt_local_entry,
@@ -1729,6 +1865,175 @@ out:
 	return 0;
 }
 
+static int
+batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
+			       struct batadv_tt_common_entry *common,
+			       struct batadv_tt_orig_list_entry *orig,
+			       bool best)
+{
+	void *hdr;
+	struct batadv_orig_node_vlan *vlan;
+	u8 last_ttvn;
+	u32 crc;
+
+	vlan = batadv_orig_node_vlan_get(orig->orig_node,
+					 common->vid);
+	if (!vlan)
+		return 0;
+
+	crc = vlan->tt.crc;
+
+	batadv_orig_node_vlan_put(vlan);
+
+	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
+			  BATADV_CMD_GET_TRANSTABLE_GLOBAL);
+	if (!hdr)
+		return -ENOBUFS;
+
+	last_ttvn = atomic_read(&orig->orig_node->last_ttvn);
+
+	if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
+	    nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
+		    orig->orig_node->orig) ||
+	    nla_put_u8(msg, BATADV_ATTR_TT_TTVN, orig->ttvn) ||
+	    nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) ||
+	    nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
+	    nla_put_u16(msg, BATADV_ATTR_TT_VID,
+			BATADV_PRINT_VID(common->vid)) ||
+	    nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
+		goto nla_put_failure;
+
+	if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int
+batadv_tt_global_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+			    struct batadv_priv *bat_priv,
+			    struct batadv_tt_common_entry *common, int *sub_s)
+{
+	struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
+	struct batadv_tt_global_entry *global;
+	struct hlist_head *head;
+	int sub = 0;
+	bool best;
+
+	global = container_of(common, struct batadv_tt_global_entry, common);
+	best_entry = batadv_transtable_best_orig(bat_priv, global);
+	head = &global->orig_list;
+
+	hlist_for_each_entry_rcu(orig_entry, head, list) {
+		if (sub++ < *sub_s)
+			continue;
+
+		best = (orig_entry == best_entry);
+
+		if (batadv_tt_global_dump_subentry(msg, portid, seq, common,
+						   orig_entry, best)) {
+			*sub_s = sub - 1;
+			return -EMSGSIZE;
+		}
+	}
+
+	*sub_s = 0;
+	return 0;
+}
+
+static int
+batadv_tt_global_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
+			     struct batadv_priv *bat_priv,
+			     struct hlist_head *head, int *idx_s, int *sub)
+{
+	struct batadv_tt_common_entry *common;
+	int idx = 0;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(common, head, hash_entry) {
+		if (idx++ < *idx_s)
+			continue;
+
+		if (batadv_tt_global_dump_entry(msg, portid, seq, bat_priv,
+						common, sub)) {
+			rcu_read_unlock();
+			*idx_s = idx - 1;
+			return -EMSGSIZE;
+		}
+	}
+	rcu_read_unlock();
+
+	*idx_s = 0;
+	*sub = 0;
+	return 0;
+}
+
+int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(cb->skb->sk);
+	struct net_device *soft_iface = NULL;
+	struct batadv_priv *bat_priv;
+	struct batadv_hard_iface *primary_if = NULL;
+	struct batadv_hashtable *hash;
+	struct hlist_head *head;
+	int ret;
+	int ifindex;
+	int bucket = cb->args[0];
+	int idx = cb->args[1];
+	int sub = cb->args[2];
+	int portid = NETLINK_CB(cb->skb).portid;
+
+	ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
+	if (!ifindex)
+		return -EINVAL;
+
+	soft_iface = dev_get_by_index(net, ifindex);
+	if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	bat_priv = netdev_priv(soft_iface);
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	hash = bat_priv->tt.global_hash;
+
+	while (bucket < hash->size) {
+		head = &hash->table[bucket];
+
+		if (batadv_tt_global_dump_bucket(msg, portid,
+						 cb->nlh->nlmsg_seq, bat_priv,
+						 head, &idx, &sub))
+			break;
+
+		bucket++;
+	}
+
+	ret = msg->len;
+
+ out:
+	if (primary_if)
+		batadv_hardif_put(primary_if);
+	if (soft_iface)
+		dev_put(soft_iface);
+
+	cb->args[0] = bucket;
+	cb->args[1] = idx;
+	cb->args[2] = sub;
+
+	return ret;
+}
+
 /**
  * _batadv_tt_global_del_orig_entry - remove and free an orig_entry
  * @tt_global_entry: the global entry to remove the orig_entry from
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 7c7e2c0..6d8b5b2 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -33,6 +33,8 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv,
 			   const char *message, bool roaming);
 int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
 int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
+int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb);
+int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb);
 void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
 			       struct batadv_orig_node *orig_node,
 			       s32 match_vid, const char *message);
-- 
2.7.3


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

* [B.A.T.M.A.N.] [RFC v2 3/5] batman-adv: netlink: add originator and neighbor table queries
  2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 1/5] batman-adv: add generic netlink query API to replace debugfs files Matthias Schiffer
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 2/5] batman-adv: netlink: add translation table query Matthias Schiffer
@ 2016-03-17 16:45 ` Matthias Schiffer
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 4/5] batman-adv: add B.A.T.M.A.N. IV bat_{orig, neigh}_dump implementations Matthias Schiffer
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-17 16:45 UTC (permalink / raw)
  To: b.a.t.m.a.n

Add BATADV_CMD_GET_ORIGINATORS and BATADV_CMD_GET_NEIGHBORS commands,
using handlers bat_orig_dump and bat_neigh_dump in batadv_algo_ops. Will
always return -EOPNOTSUPP for now, as no implementations exist yet.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
---
 include/uapi/linux/batman_adv.h |   2 +
 net/batman-adv/netlink.c        |  13 ++++
 net/batman-adv/originator.c     | 142 ++++++++++++++++++++++++++++++++++++++++
 net/batman-adv/originator.h     |   2 +
 net/batman-adv/types.h          |   7 ++
 5 files changed, 166 insertions(+)

diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index 25dee3c..35d8e8c 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -88,6 +88,8 @@ enum {
 	BATADV_CMD_GET_HARDIFS,
 	BATADV_CMD_GET_TRANSTABLE_LOCAL,
 	BATADV_CMD_GET_TRANSTABLE_GLOBAL,
+	BATADV_CMD_GET_ORIGINATORS,
+	BATADV_CMD_GET_NEIGHBORS,
 	__BATADV_CMD_MAX,
 };
 
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 50047d4..3b40eb5 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -212,6 +212,7 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb)
 
 static struct nla_policy batadv_netlink_policy[BATADV_ATTR_MAX + 1] = {
 	[BATADV_ATTR_MESH_IFINDEX]	= { .type = NLA_U32 },
+	[BATADV_ATTR_HARD_IFINDEX]	= { .type = NLA_U32 },
 };
 
 static struct genl_ops batadv_netlink_ops[] = {
@@ -245,6 +246,18 @@ static struct genl_ops batadv_netlink_ops[] = {
 		.policy = batadv_netlink_policy,
 		.dumpit = batadv_tt_global_dump,
 	},
+	{
+		.cmd = BATADV_CMD_GET_ORIGINATORS,
+		.flags = GENL_ADMIN_PERM,
+		.policy = batadv_netlink_policy,
+		.dumpit = batadv_orig_dump,
+	},
+	{
+		.cmd = BATADV_CMD_GET_NEIGHBORS,
+		.flags = GENL_ADMIN_PERM,
+		.policy = batadv_netlink_policy,
+		.dumpit = batadv_hardif_neigh_dump,
+	},
 };
 
 void __init batadv_netlink_register(void)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index e63d6a5..d1b16e7 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -33,6 +33,8 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
+#include <net/sock.h>
+#include <uapi/linux/batman_adv.h>
 
 #include "distributed-arp-table.h"
 #include "fragmentation.h"
@@ -40,8 +42,10 @@
 #include "hard-interface.h"
 #include "hash.h"
 #include "multicast.h"
+#include "netlink.h"
 #include "network-coding.h"
 #include "routing.h"
+#include "soft-interface.h"
 #include "translation-table.h"
 
 /* hash class keys */
@@ -719,6 +723,75 @@ int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset)
 	return 0;
 }
 
+int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(cb->skb->sk);
+	struct net_device *soft_iface = NULL;
+	struct net_device *hard_iface = NULL;
+	struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT;
+	struct batadv_priv *bat_priv;
+	struct batadv_hard_iface *primary_if = NULL;
+	int ret;
+	int ifindex, hard_ifindex;
+
+	ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
+	if (!ifindex)
+		return -EINVAL;
+
+	soft_iface = dev_get_by_index(net, ifindex);
+	if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	bat_priv = netdev_priv(soft_iface);
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	hard_ifindex = batadv_netlink_get_ifindex(cb->nlh,
+						  BATADV_ATTR_HARD_IFINDEX);
+	if (hard_ifindex) {
+		hard_iface = dev_get_by_index(net, hard_ifindex);
+		if (hard_iface)
+			hardif = batadv_hardif_get_by_netdev(hard_iface);
+
+		if (!hardif) {
+			ret = -ENODEV;
+			goto out;
+		}
+
+		if (hardif->soft_iface != soft_iface) {
+			ret = -ENOENT;
+			goto out;
+		}
+	}
+
+	if (!bat_priv->bat_algo_ops->bat_neigh_dump) {
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	bat_priv->bat_algo_ops->bat_neigh_dump(msg, cb, bat_priv, hardif);
+
+	ret = msg->len;
+
+ out:
+	if (hardif)
+		batadv_hardif_put(hardif);
+	if (hard_iface)
+		dev_put(hard_iface);
+	if (primary_if)
+		batadv_hardif_put(primary_if);
+	if (soft_iface)
+		dev_put(soft_iface);
+
+	return ret;
+}
+
 /**
  * batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for
  *  free after rcu grace period
@@ -1310,6 +1383,75 @@ out:
 	return 0;
 }
 
+int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(cb->skb->sk);
+	struct net_device *soft_iface = NULL;
+	struct net_device *hard_iface = NULL;
+	struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT;
+	struct batadv_priv *bat_priv;
+	struct batadv_hard_iface *primary_if = NULL;
+	int ret;
+	int ifindex, hard_ifindex;
+
+	ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
+	if (!ifindex)
+		return -EINVAL;
+
+	soft_iface = dev_get_by_index(net, ifindex);
+	if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	bat_priv = netdev_priv(soft_iface);
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	hard_ifindex = batadv_netlink_get_ifindex(cb->nlh,
+						  BATADV_ATTR_HARD_IFINDEX);
+	if (hard_ifindex) {
+		hard_iface = dev_get_by_index(net, hard_ifindex);
+		if (hard_iface)
+			hardif = batadv_hardif_get_by_netdev(hard_iface);
+
+		if (!hardif) {
+			ret = -ENODEV;
+			goto out;
+		}
+
+		if (hardif->soft_iface != soft_iface) {
+			ret = -ENOENT;
+			goto out;
+		}
+	}
+
+	if (!bat_priv->bat_algo_ops->bat_orig_dump) {
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	bat_priv->bat_algo_ops->bat_orig_dump(msg, cb, bat_priv, hardif);
+
+	ret = msg->len;
+
+ out:
+	if (hardif)
+		batadv_hardif_put(hardif);
+	if (hard_iface)
+		dev_put(hard_iface);
+	if (primary_if)
+		batadv_hardif_put(primary_if);
+	if (soft_iface)
+		dev_put(soft_iface);
+
+	return ret;
+}
+
 int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
 			    int max_if_num)
 {
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 64a8951..a8eb520 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -61,6 +61,7 @@ batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
 			struct batadv_hard_iface *if_outgoing);
 void batadv_neigh_ifinfo_put(struct batadv_neigh_ifinfo *neigh_ifinfo);
 
+int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb);
 int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset);
 
 struct batadv_orig_ifinfo *
@@ -72,6 +73,7 @@ batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
 void batadv_orig_ifinfo_put(struct batadv_orig_ifinfo *orig_ifinfo);
 
 int batadv_orig_seq_print_text(struct seq_file *seq, void *offset);
+int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb);
 int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset);
 int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
 			    int max_if_num);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 9abfb3e..befed63 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -28,6 +28,7 @@
 #include <linux/if_ether.h>
 #include <linux/kref.h>
 #include <linux/netdevice.h>
+#include <linux/netlink.h>
 #include <linux/sched.h> /* for linux/wait.h */
 #include <linux/spinlock.h>
 #include <linux/types.h>
@@ -1296,9 +1297,15 @@ struct batadv_algo_ops {
 		 struct batadv_hard_iface *if_outgoing2);
 	void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq);
 	void (*bat_neigh_free)(struct batadv_neigh_node *neigh);
+	void (*bat_neigh_dump)(struct sk_buff *msg, struct netlink_callback *cb,
+			       struct batadv_priv *priv,
+			       struct batadv_hard_iface *hard_iface);
 	/* orig_node handling API */
 	void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq,
 			       struct batadv_hard_iface *hard_iface);
+	void (*bat_orig_dump)(struct sk_buff *msg, struct netlink_callback *cb,
+			      struct batadv_priv *priv,
+			      struct batadv_hard_iface *hard_iface);
 	void (*bat_orig_free)(struct batadv_orig_node *orig_node);
 	int (*bat_orig_add_if)(struct batadv_orig_node *orig_node,
 			       int max_if_num);
-- 
2.7.3


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

* [B.A.T.M.A.N.] [RFC v2 4/5] batman-adv: add B.A.T.M.A.N. IV bat_{orig, neigh}_dump implementations
  2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
                   ` (2 preceding siblings ...)
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 3/5] batman-adv: netlink: add originator and neighbor table queries Matthias Schiffer
@ 2016-03-17 16:45 ` Matthias Schiffer
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 5/5] batman-adv: add B.A.T.M.A.N. V " Matthias Schiffer
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-17 16:45 UTC (permalink / raw)
  To: b.a.t.m.a.n

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
---
 include/uapi/linux/batman_adv.h |   2 +
 net/batman-adv/bat_iv_ogm.c     | 268 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 270 insertions(+)

diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index 35d8e8c..baf4ac8 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -76,6 +76,8 @@ enum {
 	BATADV_ATTR_TT_FLAGS,
 	BATADV_ATTR_FLAG_BEST,
 	BATADV_ATTR_LAST_SEEN_MSECS,
+	BATADV_ATTR_NEIGH_ADDRESS,
+	BATADV_ATTR_TQ,
 	__BATADV_ATTR_MAX,
 };
 
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 2c65668..5aa413e 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -47,10 +47,12 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
+#include <uapi/linux/batman_adv.h>
 
 #include "bitarray.h"
 #include "hard-interface.h"
 #include "hash.h"
+#include "netlink.h"
 #include "network-coding.h"
 #include "originator.h"
 #include "packet.h"
@@ -1916,6 +1918,171 @@ next:
 		seq_puts(seq, "No batman nodes in range ...\n");
 }
 
+static bool
+batadv_iv_ogm_neigh_get_tq_avg(struct batadv_neigh_node *neigh_node,
+			       struct batadv_hard_iface *if_outgoing,
+			       u8 *tq_avg)
+{
+	struct batadv_neigh_ifinfo *n_ifinfo;
+
+	n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
+	if (!n_ifinfo)
+		return false;
+
+	*tq_avg = n_ifinfo->bat_iv.tq_avg;
+	batadv_neigh_ifinfo_put(n_ifinfo);
+
+	return true;
+}
+
+static int
+batadv_iv_ogm_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
+				 struct batadv_priv *bat_priv,
+				 struct batadv_hard_iface *if_outgoing,
+				 struct batadv_orig_node *orig_node,
+				 struct batadv_neigh_node *neigh_node,
+				 bool best)
+{
+	void *hdr;
+	u8 tq_avg;
+	unsigned int last_seen_msecs;
+
+	last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_seen);
+
+	if (!batadv_iv_ogm_neigh_get_tq_avg(neigh_node, if_outgoing, &tq_avg))
+		return 0;
+
+	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
+			  BATADV_CMD_GET_ORIGINATORS);
+	if (!hdr)
+		return -ENOBUFS;
+
+	if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) ||
+	    nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
+		    neigh_node->addr) ||
+	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
+			neigh_node->if_incoming->net_dev->ifindex) ||
+	    nla_put_u8(msg, BATADV_ATTR_TQ, tq_avg) ||
+	    nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
+			last_seen_msecs))
+		goto nla_put_failure;
+
+	if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int
+batadv_iv_ogm_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+			      struct batadv_priv *bat_priv,
+			      struct batadv_hard_iface *if_outgoing,
+			      struct batadv_orig_node *orig_node, int *sub_s)
+{
+	struct batadv_neigh_node *neigh_node_best;
+	struct batadv_neigh_node *neigh_node;
+	int sub = 0;
+	bool best;
+	u8 tq_avg_best;
+
+	neigh_node_best = batadv_orig_router_get(orig_node, if_outgoing);
+	if (!neigh_node_best)
+		goto out;
+
+	if (!batadv_iv_ogm_neigh_get_tq_avg(neigh_node_best, if_outgoing,
+					    &tq_avg_best))
+		goto out;
+
+	if (tq_avg_best == 0)
+		goto out;
+
+	hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
+		if (sub++ < *sub_s)
+			continue;
+
+		best = (neigh_node == neigh_node_best);
+
+		if (batadv_iv_ogm_orig_dump_subentry(msg, portid, seq, bat_priv,
+						     if_outgoing, orig_node,
+						     neigh_node, best)) {
+			batadv_neigh_node_put(neigh_node_best);
+
+			*sub_s = sub - 1;
+			return -EMSGSIZE;
+		}
+	}
+
+ out:
+	if (neigh_node_best)
+		batadv_neigh_node_put(neigh_node_best);
+
+	*sub_s = 0;
+	return 0;
+}
+
+static int
+batadv_iv_ogm_orig_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
+			       struct batadv_priv *bat_priv,
+			       struct batadv_hard_iface *if_outgoing,
+			       struct hlist_head *head, int *idx_s, int *sub)
+{
+	struct batadv_orig_node *orig_node;
+	int idx = 0;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
+		if (idx++ < *idx_s)
+			continue;
+
+		if (batadv_iv_ogm_orig_dump_entry(msg, portid, seq, bat_priv,
+						  if_outgoing, orig_node,
+						  sub)) {
+			rcu_read_unlock();
+			*idx_s = idx - 1;
+			return -EMSGSIZE;
+		}
+	}
+	rcu_read_unlock();
+
+	*idx_s = 0;
+	*sub = 0;
+	return 0;
+}
+
+static void
+batadv_iv_ogm_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
+			struct batadv_priv *bat_priv,
+			struct batadv_hard_iface *if_outgoing)
+{
+	struct batadv_hashtable *hash = bat_priv->orig_hash;
+	struct hlist_head *head;
+	int bucket = cb->args[0];
+	int idx = cb->args[1];
+	int sub = cb->args[2];
+	int portid = NETLINK_CB(cb->skb).portid;
+
+	while (bucket < hash->size) {
+		head = &hash->table[bucket];
+
+		if (batadv_iv_ogm_orig_dump_bucket(msg, portid,
+						   cb->nlh->nlmsg_seq,
+						   bat_priv, if_outgoing, head,
+						   &idx, &sub))
+			break;
+
+		bucket++;
+	}
+
+	cb->args[0] = bucket;
+	cb->args[1] = idx;
+	cb->args[2] = sub;
+}
+
 /**
  * batadv_iv_hardif_neigh_print - print a single hop neighbour node
  * @seq: neighbour table seq_file struct
@@ -1968,6 +2135,105 @@ static void batadv_iv_neigh_print(struct batadv_priv *bat_priv,
 		seq_puts(seq, "No batman nodes in range ...\n");
 }
 
+static int
+batadv_iv_ogm_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
+			       struct batadv_hardif_neigh_node *hardif_neigh)
+{
+	void *hdr;
+	unsigned int last_seen_msecs;
+
+	last_seen_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen);
+
+	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
+			  BATADV_CMD_GET_NEIGHBORS);
+	if (!hdr)
+		return -ENOBUFS;
+
+	if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
+		    hardif_neigh->addr) ||
+	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
+			hardif_neigh->if_incoming->net_dev->ifindex) ||
+	    nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
+			last_seen_msecs))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int
+batadv_iv_ogm_neigh_dump_hardif(struct sk_buff *msg, u32 portid, u32 seq,
+				struct batadv_priv *bat_priv,
+				struct batadv_hard_iface *hard_iface,
+				int *idx_s)
+{
+	struct batadv_hardif_neigh_node *hardif_neigh;
+	int idx = 0;
+
+	hlist_for_each_entry_rcu(hardif_neigh,
+				 &hard_iface->neigh_list, list) {
+		if (idx++ < *idx_s)
+			continue;
+
+		if (batadv_iv_ogm_neigh_dump_neigh(msg, portid, seq,
+						   hardif_neigh)) {
+			*idx_s = idx - 1;
+			return -EMSGSIZE;
+		}
+	}
+
+	*idx_s = 0;
+	return 0;
+}
+
+static void
+batadv_iv_ogm_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
+			 struct batadv_priv *bat_priv,
+			 struct batadv_hard_iface *single_hardif)
+{
+	struct batadv_hard_iface *hard_iface;
+	int i_hardif = 0;
+	int i_hardif_s = cb->args[0];
+	int idx = cb->args[1];
+	int portid = NETLINK_CB(cb->skb).portid;
+
+	rcu_read_lock();
+	if (single_hardif) {
+		if (i_hardif_s == 0) {
+			if (batadv_iv_ogm_neigh_dump_hardif(msg, portid,
+							    cb->nlh->nlmsg_seq,
+							    bat_priv,
+							    single_hardif,
+							    &idx) == 0)
+				i_hardif++;
+		}
+	} else {
+		list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+			if (hard_iface->soft_iface != bat_priv->soft_iface)
+				continue;
+
+			if (i_hardif++ < i_hardif_s)
+				continue;
+
+			if (batadv_iv_ogm_neigh_dump_hardif(msg, portid,
+							    cb->nlh->nlmsg_seq,
+							    bat_priv,
+							    hard_iface, &idx)) {
+				i_hardif--;
+				break;
+			}
+		}
+	}
+	rcu_read_unlock();
+
+	cb->args[0] = i_hardif;
+	cb->args[1] = idx;
+}
+
 /**
  * batadv_iv_ogm_neigh_cmp - compare the metrics of two neighbors
  * @neigh1: the first neighbor object of the comparison
@@ -2062,7 +2328,9 @@ static struct batadv_algo_ops batadv_batman_iv __read_mostly = {
 	.bat_neigh_cmp = batadv_iv_ogm_neigh_cmp,
 	.bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob,
 	.bat_neigh_print = batadv_iv_neigh_print,
+	.bat_neigh_dump = batadv_iv_ogm_neigh_dump,
 	.bat_orig_print = batadv_iv_ogm_orig_print,
+	.bat_orig_dump = batadv_iv_ogm_orig_dump,
 	.bat_orig_free = batadv_iv_ogm_orig_free,
 	.bat_orig_add_if = batadv_iv_ogm_orig_add_if,
 	.bat_orig_del_if = batadv_iv_ogm_orig_del_if,
-- 
2.7.3


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

* [B.A.T.M.A.N.] [RFC v2 5/5] batman-adv: add B.A.T.M.A.N. V bat_{orig, neigh}_dump implementations
  2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
                   ` (3 preceding siblings ...)
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 4/5] batman-adv: add B.A.T.M.A.N. IV bat_{orig, neigh}_dump implementations Matthias Schiffer
@ 2016-03-17 16:45 ` Matthias Schiffer
  2016-03-17 17:04 ` [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-17 16:45 UTC (permalink / raw)
  To: b.a.t.m.a.n

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
---
 include/uapi/linux/batman_adv.h |   1 +
 net/batman-adv/bat_v.c          | 250 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 251 insertions(+)

diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index baf4ac8..27f277f 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -78,6 +78,7 @@ enum {
 	BATADV_ATTR_LAST_SEEN_MSECS,
 	BATADV_ATTR_NEIGH_ADDRESS,
 	BATADV_ATTR_TQ,
+	BATADV_ATTR_THROUGHPUT,
 	__BATADV_ATTR_MAX,
 };
 
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
index 3315b9a..203c9cd 100644
--- a/net/batman-adv/bat_v.c
+++ b/net/batman-adv/bat_v.c
@@ -29,10 +29,12 @@
 #include <linux/seq_file.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
+#include <uapi/linux/batman_adv.h>
 
 #include "bat_v_elp.h"
 #include "bat_v_ogm.h"
 #include "hash.h"
+#include "netlink.h"
 #include "originator.h"
 #include "packet.h"
 
@@ -171,6 +173,107 @@ static void batadv_v_neigh_print(struct batadv_priv *bat_priv,
 		seq_puts(seq, "No batman nodes in range ...\n");
 }
 
+static int
+batadv_v_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
+			  struct batadv_hardif_neigh_node *hardif_neigh)
+{
+	void *hdr;
+	unsigned int last_seen_msecs;
+	u32 throughput;
+
+	last_seen_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen);
+	throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
+	throughput = throughput * 100;
+
+	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
+			  BATADV_CMD_GET_NEIGHBORS);
+	if (!hdr)
+		return -ENOBUFS;
+
+	if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
+		    hardif_neigh->addr) ||
+	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
+			hardif_neigh->if_incoming->net_dev->ifindex) ||
+	    nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
+			last_seen_msecs) ||
+	    nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int
+batadv_v_neigh_dump_hardif(struct sk_buff *msg, u32 portid, u32 seq,
+			   struct batadv_priv *bat_priv,
+			   struct batadv_hard_iface *hard_iface,
+			   int *idx_s)
+{
+	struct batadv_hardif_neigh_node *hardif_neigh;
+	int idx = 0;
+
+	hlist_for_each_entry_rcu(hardif_neigh,
+				 &hard_iface->neigh_list, list) {
+		if (idx++ < *idx_s)
+			continue;
+
+		if (batadv_v_neigh_dump_neigh(msg, portid, seq, hardif_neigh)) {
+			*idx_s = idx - 1;
+			return -EMSGSIZE;
+		}
+	}
+
+	*idx_s = 0;
+	return 0;
+}
+
+static void
+batadv_v_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
+		    struct batadv_priv *bat_priv,
+		    struct batadv_hard_iface *single_hardif)
+{
+	struct batadv_hard_iface *hard_iface;
+	int i_hardif = 0;
+	int i_hardif_s = cb->args[0];
+	int idx = cb->args[1];
+	int portid = NETLINK_CB(cb->skb).portid;
+
+	rcu_read_lock();
+	if (single_hardif) {
+		if (i_hardif_s == 0) {
+			if (batadv_v_neigh_dump_hardif(msg, portid,
+						       cb->nlh->nlmsg_seq,
+						       bat_priv, single_hardif,
+						       &idx) == 0)
+				i_hardif++;
+		}
+	} else {
+		list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
+			if (hard_iface->soft_iface != bat_priv->soft_iface)
+				continue;
+
+			if (i_hardif++ < i_hardif_s)
+				continue;
+
+			if (batadv_v_neigh_dump_hardif(msg, portid,
+						       cb->nlh->nlmsg_seq,
+						       bat_priv, hard_iface,
+						       &idx)) {
+				i_hardif--;
+				break;
+			}
+		}
+	}
+	rcu_read_unlock();
+
+	cb->args[0] = i_hardif;
+	cb->args[1] = idx;
+}
+
 /**
  * batadv_v_orig_print - print the originator table
  * @bat_priv: the bat priv with all the soft interface information
@@ -239,6 +342,151 @@ next:
 		seq_puts(seq, "No batman nodes in range ...\n");
 }
 
+static int
+batadv_v_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
+			    struct batadv_priv *bat_priv,
+			    struct batadv_hard_iface *if_outgoing,
+			    struct batadv_orig_node *orig_node,
+			    struct batadv_neigh_node *neigh_node,
+			    bool best)
+{
+	struct batadv_neigh_ifinfo *n_ifinfo;
+	unsigned int last_seen_msecs;
+	u32 throughput;
+	void *hdr;
+
+	n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
+	if (!n_ifinfo)
+		return 0;
+
+	throughput = n_ifinfo->bat_v.throughput * 100;
+
+	batadv_neigh_ifinfo_put(n_ifinfo);
+
+	last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_seen);
+
+	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
+			  BATADV_CMD_GET_ORIGINATORS);
+	if (!hdr)
+		return -ENOBUFS;
+
+	if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) ||
+	    nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
+		    neigh_node->addr) ||
+	    nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
+			neigh_node->if_incoming->net_dev->ifindex) ||
+	    nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput) ||
+	    nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
+			last_seen_msecs))
+		goto nla_put_failure;
+
+	if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int
+batadv_v_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+			 struct batadv_priv *bat_priv,
+			 struct batadv_hard_iface *if_outgoing,
+			 struct batadv_orig_node *orig_node, int *sub_s)
+{
+	struct batadv_neigh_node *neigh_node_best;
+	struct batadv_neigh_node *neigh_node;
+	int sub = 0;
+	bool best;
+
+	neigh_node_best = batadv_orig_router_get(orig_node, if_outgoing);
+	if (!neigh_node_best)
+		goto out;
+
+	hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
+		if (sub++ < *sub_s)
+			continue;
+
+		best = (neigh_node == neigh_node_best);
+
+		if (batadv_v_orig_dump_subentry(msg, portid, seq, bat_priv,
+						if_outgoing, orig_node,
+						neigh_node, best)) {
+			batadv_neigh_node_put(neigh_node_best);
+
+			*sub_s = sub - 1;
+			return -EMSGSIZE;
+		}
+	}
+
+ out:
+	if (neigh_node_best)
+		batadv_neigh_node_put(neigh_node_best);
+
+	*sub_s = 0;
+	return 0;
+}
+
+static int
+batadv_v_orig_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
+			  struct batadv_priv *bat_priv,
+			  struct batadv_hard_iface *if_outgoing,
+			  struct hlist_head *head, int *idx_s, int *sub)
+{
+	struct batadv_orig_node *orig_node;
+	int idx = 0;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
+		if (idx++ < *idx_s)
+			continue;
+
+		if (batadv_v_orig_dump_entry(msg, portid, seq, bat_priv,
+					     if_outgoing, orig_node, sub)) {
+			rcu_read_unlock();
+			*idx_s = idx - 1;
+			return -EMSGSIZE;
+		}
+	}
+	rcu_read_unlock();
+
+	*idx_s = 0;
+	*sub = 0;
+	return 0;
+}
+
+static void
+batadv_v_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
+		   struct batadv_priv *bat_priv,
+		   struct batadv_hard_iface *if_outgoing)
+{
+	struct batadv_hashtable *hash = bat_priv->orig_hash;
+	struct hlist_head *head;
+	int bucket = cb->args[0];
+	int idx = cb->args[1];
+	int sub = cb->args[2];
+	int portid = NETLINK_CB(cb->skb).portid;
+
+	while (bucket < hash->size) {
+		head = &hash->table[bucket];
+
+		if (batadv_v_orig_dump_bucket(msg, portid,
+					      cb->nlh->nlmsg_seq,
+					      bat_priv, if_outgoing, head, &idx,
+					      &sub))
+			break;
+
+		bucket++;
+	}
+
+	cb->args[0] = bucket;
+	cb->args[1] = idx;
+	cb->args[2] = sub;
+}
+
 static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
 			      struct batadv_hard_iface *if_outgoing1,
 			      struct batadv_neigh_node *neigh2,
@@ -282,9 +530,11 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = {
 	.bat_ogm_emit = batadv_v_ogm_emit,
 	.bat_ogm_schedule = batadv_v_ogm_schedule,
 	.bat_orig_print = batadv_v_orig_print,
+	.bat_orig_dump = batadv_v_orig_dump,
 	.bat_neigh_cmp = batadv_v_neigh_cmp,
 	.bat_neigh_is_similar_or_better = batadv_v_neigh_is_sob,
 	.bat_neigh_print = batadv_v_neigh_print,
+	.bat_neigh_dump = batadv_v_neigh_dump,
 };
 
 /**
-- 
2.7.3


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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
                   ` (4 preceding siblings ...)
  2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 5/5] batman-adv: add B.A.T.M.A.N. V " Matthias Schiffer
@ 2016-03-17 17:04 ` Matthias Schiffer
  2016-03-18  7:09   ` Sven Eckelmann
  2016-03-18 11:23 ` Sven Eckelmann
  2016-04-18 14:50 ` Simon Wunderlich
  7 siblings, 1 reply; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-17 17:04 UTC (permalink / raw)
  To: b.a.t.m.a.n


[-- Attachment #1.1.1: Type: text/plain, Size: 1947 bytes --]

On 03/17/2016 05:45 PM, Matthias Schiffer wrote:
> Hi,
> this is the second take of my netlink API patches. As mentioned before, the
> netlink API is superior to the current debugfs API in many aspects:
> 
> * debugfs is broken (see PATCH 1 for details)
> * Netlink is namespace-aware, and can be used in unprivileged containers
>   without problems
> * Netlink packets are more machine-readable than text files, and can be
>   easily extended without potentially breaking userspace
> * On older kernels, seq_file can't fall back to vmalloc if kmalloc fails,
>   which often leads to OOM when reading "originators" in large meshes, as
>   the whole file must fit into a single buffer
> 
> Of course, are also a few downsides; when the data is too big to fit into
> a single netlink packet, the provided data may be inconsistent (entries may
> be missing or duplicated.) This will happen in large meshes only, and be
> improbable in any case.
> 
> The patches have been developed on top of the netns patchset, but should
> be applicable independently (maybe with minor changes.)
> 
> All netlink queries returning lists of any kind can only be used with
> NLM_F_DUMP queries, so that arbitrarity large responses are possible (split
> across multiple packets if necessary.)
> 
> At the moment, the following debugfs files have corresponding netlink APIs:
> 
> * routing_algos
> * neighbors
> * originators
> * transtable_global
> * transtable_local
> * (hardinterfaces for a softif can be queried)
> 
> The following files are still missing:
> 
> * gateways
> * bla_claim_table
> * bla_backbone_table
> * dat_cache
> * nc_nodes
> 
> Obviously, documentation is also a TODO. Comments about the API design are
> very welcome...
> 
> Regards,
> Matthias
> 
> 

And here is the new version of the PoC userspace tool.
Build with:

gcc -o batnl batnl.c $$(pkg-config --cflags --libs libnl-1) -Wall


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.1.2: batnl.c --]
[-- Type: text/x-csrc; name="batnl.c", Size: 16521 bytes --]

#include <stdio.h>
#include <string.h>

#include <net/if.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "batman_adv.h"


static void usage()
{
	fprintf(stderr, "Usage:\n\n");
	fprintf(stderr, "  batnl routing_algos\n");
	fprintf(stderr, "  batnl info <mesh>\n");
	fprintf(stderr, "  batnl interface <mesh>\n");
	fprintf(stderr, "  batnl translocal <mesh>\n");
	fprintf(stderr, "  batnl transglobal <mesh>\n");
	fprintf(stderr, "  batnl neighbors <mesh> [<hardif>]\n");
	fprintf(stderr, "  batnl originators <mesh> [<hardif>]\n");
	exit(2);
}

static int print_error(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
{
	fprintf(stderr, "Error received: %s\n", strerror(-nlerr->error));
	exit(1);
}

static int stop_callback(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	int *error = nlmsg_data(nlh);

	if (*error)
		fprintf(stderr, "Error received: %s\n", strerror(-*error));

	return NL_STOP;
}

static int routing_algos_callback(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct genlmsghdr *ghdr;
	struct nlattr *attrs[BATADV_ATTR_MAX+1];

	if (!genlmsg_valid_hdr(nlh, 0)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	ghdr = nlmsg_data(nlh);

	if (ghdr->cmd != BATADV_CMD_GET_ROUTING_ALGOS)
		return NL_OK;

	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	const char *algo_name = nla_get_string(attrs[BATADV_ATTR_ALGO_NAME]);

	printf(" * %s\n", algo_name);

	return NL_OK;
}

static void routing_algos(struct nl_handle *sock, int family)
{
	struct nl_msg *msg;
	struct nl_cb *cb;

	msg = nlmsg_alloc();
	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_ROUTING_ALGOS, 1);

	nl_send_auto_complete(sock, msg);

	nlmsg_free(msg);

	cb = nl_cb_alloc(NL_CB_DEFAULT);
	nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, routing_algos_callback, NULL);
	nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);

	nl_recvmsgs(sock, cb);
}

static int info_callback(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct genlmsghdr *ghdr;
	struct nlattr *attrs[BATADV_ATTR_MAX+1];

	if (!genlmsg_valid_hdr(nlh, 0)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	ghdr = nlmsg_data(nlh);

	if (ghdr->cmd != BATADV_CMD_GET_MESH_INFO)
		return NL_OK;

	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	const char *mesh_name = nla_get_string(attrs[BATADV_ATTR_MESH_IFNAME]);

	if (attrs[BATADV_ATTR_HARD_IFNAME]) {
		const char *version = nla_get_string(attrs[BATADV_ATTR_VERSION]);
		const char *algo_name = nla_get_string(attrs[BATADV_ATTR_ALGO_NAME]);
		const char *primary_if = nla_get_string(attrs[BATADV_ATTR_HARD_IFNAME]);
		const uint8_t *primary_mac = nla_data(attrs[BATADV_ATTR_HARD_ADDRESS]);

		printf("[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%02x:%02x:%02x:%02x:%02x:%02x (%s %s)]\n",
		       version, primary_if,
		       primary_mac[0], primary_mac[1], primary_mac[2],
		       primary_mac[3], primary_mac[4], primary_mac[5],
		       mesh_name, algo_name);

	}
	else {
		printf("BATMAN mesh %s disabled\n", mesh_name);
	}

	return NL_STOP;
}

static void info(struct nl_handle *sock, int family, int ifindex)
{
	struct nl_msg *msg;
	struct nl_cb *cb;

	msg = nlmsg_alloc();
	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, 0, BATADV_CMD_GET_MESH_INFO, 1);

	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);

	nl_send_auto_complete(sock, msg);

	nlmsg_free(msg);

	cb = nl_cb_alloc(NL_CB_DEFAULT);
	nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, info_callback, NULL);
	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);

	nl_recvmsgs(sock, cb);
}

static int interface_callback(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct genlmsghdr *ghdr;
	struct nlattr *attrs[BATADV_ATTR_MAX+1];

	if (!genlmsg_valid_hdr(nlh, 0)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	ghdr = nlmsg_data(nlh);

	if (ghdr->cmd != BATADV_CMD_GET_HARDIFS)
		return NL_OK;

	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	const char *ifname = nla_get_string(attrs[BATADV_ATTR_HARD_IFNAME]);

	printf("%s: %sactive\n", ifname, attrs[BATADV_ATTR_ACTIVE] ? "" : "in");

	return NL_OK;
}

static void interface(struct nl_handle *sock, int family, int ifindex)
{
	struct nl_msg *msg;
	struct nl_cb *cb;

	msg = nlmsg_alloc();
	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_HARDIFS, 1);

	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);

	nl_send_auto_complete(sock, msg);

	nlmsg_free(msg);

	cb = nl_cb_alloc(NL_CB_DEFAULT);
	nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, interface_callback, NULL);
	nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);

	nl_recvmsgs(sock, cb);
}

static int translocal_callback(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct genlmsghdr *ghdr;
	struct nlattr *attrs[BATADV_ATTR_MAX+1];

	if (!genlmsg_valid_hdr(nlh, 0)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	ghdr = nlmsg_data(nlh);

	if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_LOCAL)
		return NL_OK;

	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	uint8_t *addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]);
	int16_t vid = nla_get_u16(attrs[BATADV_ATTR_TT_VID]);
	uint32_t crc32 = nla_get_u32(attrs[BATADV_ATTR_TT_CRC32]);
	uint32_t flags = nla_get_u32(attrs[BATADV_ATTR_TT_FLAGS]);
	int last_seen_msecs = 0, last_seen_secs = 0;

	char r = '.', p = '.', n = '.', x = '.', w = '.', i = '.';
	if (flags & BATADV_TT_CLIENT_ROAM)
		r = 'R';
	if (flags & BATADV_TT_CLIENT_NEW)
		n = 'N';
	if (flags & BATADV_TT_CLIENT_PENDING)
		x = 'X';
	if (flags & BATADV_TT_CLIENT_WIFI)
		w = 'W';
	if (flags & BATADV_TT_CLIENT_ISOLA)
		i = 'I';

	if (flags & BATADV_TT_CLIENT_NOPURGE)  {
		p = 'P';
	}
	else {
		last_seen_msecs = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
		last_seen_secs = last_seen_msecs / 1000;
		last_seen_msecs = last_seen_msecs % 1000;
	}


	printf(" * %02x:%02x:%02x:%02x:%02x:%02x %4i [%c%c%c%c%c%c] %3u.%03u   (0x%.8x)\n",
	       addr[0], addr[1], addr[2],
	       addr[3], addr[4], addr[5],
	       vid, r, p, n, x, w, i,
	       last_seen_secs, last_seen_msecs,
	       crc32);

	return NL_OK;
}

static void translocal(struct nl_handle *sock, int family, int ifindex)
{
	struct nl_msg *msg;
	struct nl_cb *cb;

	msg = nlmsg_alloc();
	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_TRANSTABLE_LOCAL, 1);

	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);

	nl_send_auto_complete(sock, msg);

	nlmsg_free(msg);

	cb = nl_cb_alloc(NL_CB_DEFAULT);
	nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, translocal_callback, NULL);
	nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);

	nl_recvmsgs(sock, cb);
}

static int transglobal_callback(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct genlmsghdr *ghdr;
	struct nlattr *attrs[BATADV_ATTR_MAX+1];

	if (!genlmsg_valid_hdr(nlh, 0)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	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), NULL)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	uint8_t *addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]);
	uint8_t *orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
	int16_t vid = nla_get_u16(attrs[BATADV_ATTR_TT_VID]);
	uint8_t ttvn = nla_get_u8(attrs[BATADV_ATTR_TT_TTVN]);
	uint8_t last_ttvn = nla_get_u8(attrs[BATADV_ATTR_TT_LAST_TTVN]);
	uint32_t crc32 = nla_get_u32(attrs[BATADV_ATTR_TT_CRC32]);
	uint32_t flags = nla_get_u32(attrs[BATADV_ATTR_TT_FLAGS]);

	char c = '+', r = '.', w = '.', i = '.', t = '.';
	if (attrs[BATADV_ATTR_FLAG_BEST])
		c = '*';
	if (flags & BATADV_TT_CLIENT_ROAM)
		r = 'R';
	if (flags & BATADV_TT_CLIENT_WIFI)
		w = 'W';
	if (flags & BATADV_TT_CLIENT_ISOLA)
		i = 'I';
	if (flags & BATADV_TT_CLIENT_TEMP)
		t = 'T';


	printf(" %c %02x:%02x:%02x:%02x:%02x:%02x %4i   (%3u) via %02x:%02x:%02x:%02x:%02x:%02x     (%3u)   (0x%.8x) [%c%c%c%c]\n",
	       c,
	       addr[0], addr[1], addr[2],
	       addr[3], addr[4], addr[5],
	       vid, ttvn,
	       orig[0], orig[1], orig[2],
	       orig[3], orig[4], orig[5],
	       last_ttvn, crc32, r, w, i, t);

	return NL_OK;
}

static void transglobal(struct nl_handle *sock, int family, int ifindex)
{
	struct nl_msg *msg;
	struct nl_cb *cb;

	msg = nlmsg_alloc();
	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_TRANSTABLE_GLOBAL, 1);

	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);

	nl_send_auto_complete(sock, msg);

	nlmsg_free(msg);

	cb = nl_cb_alloc(NL_CB_DEFAULT);
	nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, transglobal_callback, NULL);
	nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);

	nl_recvmsgs(sock, cb);
}

static int originators_callback(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct genlmsghdr *ghdr;
	struct nlattr *attrs[BATADV_ATTR_MAX+1];

	if (!genlmsg_valid_hdr(nlh, 0)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	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), NULL)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	uint8_t *orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
	uint8_t *neigh = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]);

	char ifname[IF_NAMESIZE];
	if (!if_indextoname(nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]), ifname))
		ifname[0] = '\0';

	char c = '+';
	if (attrs[BATADV_ATTR_FLAG_BEST])
		c = '*';

	int last_seen_msecs, last_seen_secs;
	last_seen_msecs = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
	last_seen_secs = last_seen_msecs / 1000;
	last_seen_msecs = last_seen_msecs % 1000;

	if (attrs[BATADV_ATTR_THROUGHPUT]) {
		unsigned throughput_mbits, throughput_kbits;
		throughput_kbits = nla_get_u32(attrs[BATADV_ATTR_THROUGHPUT]);
		throughput_mbits = throughput_kbits / 1000;
		throughput_kbits = throughput_kbits % 1000;

		printf(" %c %02x:%02x:%02x:%02x:%02x:%02x %4i.%03is (%9u.%1u) %02x:%02x:%02x:%02x:%02x:%02x [%10s]\n",
		       c,
		       orig[0], orig[1], orig[2],
		       orig[3], orig[4], orig[5],
		       last_seen_secs, last_seen_msecs,
		       throughput_mbits, throughput_kbits / 100,
		       neigh[0], neigh[1], neigh[2],
		       neigh[3], neigh[4], neigh[5],
		       ifname);
	}
	else {
		uint8_t tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);

		printf(" %c %02x:%02x:%02x:%02x:%02x:%02x %4i.%03is   (%3i) %02x:%02x:%02x:%02x:%02x:%02x [%10s]\n",
		       c,
		       orig[0], orig[1], orig[2],
		       orig[3], orig[4], orig[5],
		       last_seen_secs, last_seen_msecs, tq,
		       neigh[0], neigh[1], neigh[2],
		       neigh[3], neigh[4], neigh[5],
		       ifname);
	}

	return NL_OK;
}

static void originators(struct nl_handle *sock, int family, int ifindex, int hard_ifindex)
{
	struct nl_msg *msg;
	struct nl_cb *cb;

	msg = nlmsg_alloc();
	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_ORIGINATORS, 1);

	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);

	if (hard_ifindex)
		nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, hard_ifindex);

	nl_send_auto_complete(sock, msg);

	nlmsg_free(msg);

	cb = nl_cb_alloc(NL_CB_DEFAULT);
	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, originators_callback, NULL);
	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);

	nl_recvmsgs(sock, cb);
}

static int neighbors_callback(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct genlmsghdr *ghdr;
	struct nlattr *attrs[BATADV_ATTR_MAX+1];

	if (!genlmsg_valid_hdr(nlh, 0)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	ghdr = nlmsg_data(nlh);

	if (ghdr->cmd != BATADV_CMD_GET_NEIGHBORS)
		return NL_OK;

	if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), NULL)) {
		fputs("Received invalid data from kernel.", stderr);
		exit(1);
	}

	uint8_t *neigh = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]);

	char ifname[IF_NAMESIZE];
	if (!if_indextoname(nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]), ifname))
		ifname[0] = '\0';

	int last_seen_msecs, last_seen_secs;
	last_seen_msecs = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
	last_seen_secs = last_seen_msecs / 1000;
	last_seen_msecs = last_seen_msecs % 1000;

	if (attrs[BATADV_ATTR_THROUGHPUT]) {
		unsigned throughput_mbits, throughput_kbits;
		throughput_kbits = nla_get_u32(attrs[BATADV_ATTR_THROUGHPUT]);
		throughput_mbits = throughput_kbits / 1000;
		throughput_kbits = throughput_kbits % 1000;

		printf("%02x:%02x:%02x:%02x:%02x:%02x %4i.%03is (%9u.%1u) [%10s]\n",
		       neigh[0], neigh[1], neigh[2],
		       neigh[3], neigh[4], neigh[5],
		       last_seen_secs, last_seen_msecs,
		       throughput_mbits, throughput_kbits / 100,
		       ifname);
	}
	else {
		printf("   %10s   %02x:%02x:%02x:%02x:%02x:%02x %4i.%03is\n",
		       ifname,
		       neigh[0], neigh[1], neigh[2],
		       neigh[3], neigh[4], neigh[5],
		       last_seen_secs, last_seen_msecs);
	}

	return NL_OK;
}

static void neighbors(struct nl_handle *sock, int family, int ifindex, int hard_ifindex)
{
	struct nl_msg *msg;
	struct nl_cb *cb;

	msg = nlmsg_alloc();
	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_DUMP, BATADV_CMD_GET_NEIGHBORS, 1);

	nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);

	if (hard_ifindex)
		nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, hard_ifindex);

	nl_send_auto_complete(sock, msg);

	nlmsg_free(msg);

	cb = nl_cb_alloc(NL_CB_DEFAULT);
	nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, neighbors_callback, NULL);
	nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
	nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);

	nl_recvmsgs(sock, cb);
}

int main(int argc, char *argv[])
{
	struct nl_handle *sock;
	int family;

	sock = nl_handle_alloc();
	genl_connect(sock);

	family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
	if (family < 0) {
		fputs("Your kernel doesn't support the batman-adv netlink interface.\n", stderr);
		exit(1);
	}

	if (argc < 2 || argc > 4)
		usage();

	int ifindex = 0;
	if (argc > 2) {
		ifindex = if_nametoindex(argv[2]);
		if (!ifindex)
			usage();
	}

	int hard_ifindex = 0;
	if (argc > 3) {
		hard_ifindex = if_nametoindex(argv[3]);
		if (!hard_ifindex)
			usage();
	}

	if (!strcmp(argv[1], "routing_algos"))
		routing_algos(sock, family);
	else if (!strcmp(argv[1], "info"))
		info(sock, family, ifindex);
	else if (!strcmp(argv[1], "interface"))
		interface(sock, family, ifindex);
	else if (!strcmp(argv[1], "translocal"))
		translocal(sock, family, ifindex);
	else if (!strcmp(argv[1], "transglobal"))
		transglobal(sock, family, ifindex);
	else if (!strcmp(argv[1], "originators"))
		originators(sock, family, ifindex, hard_ifindex);
	else if (!strcmp(argv[1], "neighbors"))
		neighbors(sock, family, ifindex, hard_ifindex);
	else
		usage();

	return 0;
}

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-17 17:04 ` [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
@ 2016-03-18  7:09   ` Sven Eckelmann
  2016-03-18 11:53     ` Matthias Schiffer
  0 siblings, 1 reply; 23+ messages in thread
From: Sven Eckelmann @ 2016-03-18  7:09 UTC (permalink / raw)
  To: b.a.t.m.a.n


[-- Attachment #1.1: Type: text/plain, Size: 21323 bytes --]

=2D-nextPart3524408.fhnBrciRUx
Content-Transfer-Encoding: 7Bit
Content-Type: text/plain; charset="us-ascii"

On Thursday 17 March 2016 18:04:56 Matthias Schiffer wrote:
> And here is the new version of the PoC userspace tool.
> Build with:
> 
> gcc -o batnl batnl.c $$(pkg-config --cflags --libs libnl-1) -Wall

Thanks for the patches.

I've only looked at the test querier for a second and I am a little bit 
confused that you access things like attrs[BATADV_ATTR_ALGO_NAME] without 
checking if this is available or that the received message is valid (according 
to the nla_parse policy).

I know that this is only a PoC but wanted to mention it in case somebody wants 
to use it as reference for a batctl/alfred implementation.

I like that the netlink interface doesn't introduce complex structs at the 
moment (but I have to think a little bit about it). The unnamed enums freak me 
out a little bit (names would be nice so it is easier to write kernel-doc for 
it).

I just ran the build_test stuff through your branch so you get an early 
feedback about some common problems. See the attached mail (the unused symbols 
seem to be only symptoms of the build failures with old kernels < 3.12).

Kind regards,
	Sven
=2D-nextPart3524408.fhnBrciRUx
Content-Disposition: attachment; filename="Build check errors found_2016-03-17.mbox"
Content-Transfer-Encoding: 7Bit
Content-Type: application/mbox; name="Build check errors found_2016-03-17.mbox"

MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Build check errors found: 2016-03-17
From: postmaster@open-mesh.org
To: sven
Date: Thu, 17 Mar 2016 22:31:34 +0100 (CET)

Name of failed tests
====================

 * checkpatch master ./net/batman-adv/fragmentation.c
 * headers master
 * kerneldoc master ./net/batman-adv/types.h
 * smatch master linux-4.5 CONFIG_BATMAN_ADV_BLA=n CONFIG_BATMAN_ADV_DAT=n CONFIG_BATMAN_ADV_DEBUG=n CONFIG_BATMAN_ADV_NC=y CONFIG_BATMAN_ADV_MCAST=n CONFIG_BATMAN_ADV_BATMAN_V=y
 * smatch master linux-4.5 CONFIG_BATMAN_ADV_BLA=y CONFIG_BATMAN_ADV_DAT=n CONFIG_BATMAN_ADV_DEBUG=y CONFIG_BATMAN_ADV_NC=n CONFIG_BATMAN_ADV_MCAST=y CONFIG_BATMAN_ADV_BATMAN_V=n
 * smatch master linux-4.5 CONFIG_BATMAN_ADV_BLA=y CONFIG_BATMAN_ADV_DAT=n CONFIG_BATMAN_ADV_DEBUG=y CONFIG_BATMAN_ADV_NC=n CONFIG_BATMAN_ADV_MCAST=y CONFIG_BATMAN_ADV_BATMAN_V=y
 * smatch master linux-4.5 CONFIG_BATMAN_ADV_BLA=y CONFIG_BATMAN_ADV_DAT=y CONFIG_BATMAN_ADV_DEBUG=y CONFIG_BATMAN_ADV_NC=y CONFIG_BATMAN_ADV_MCAST=y CONFIG_BATMAN_ADV_BATMAN_V=n
 * sparse master linux-3.10 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.10 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.11 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.11 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.12 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.12 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.2 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.2 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.3 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.3 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.4 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.4 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.5 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.5 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.6 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.6 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.7 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.7 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.8 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.8 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * sparse master linux-3.9 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * sparse master linux-3.9 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.10 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.10 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.11 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.11 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.12 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.12 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.7 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.7 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.8 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.8 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.9 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * unused_symbols master linux-3.9 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.2 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.2 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.3 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.3 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.4 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.4 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.5 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.5 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.6 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
 * wrong namespace symbols master linux-3.6 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n

Output of different failed tests
================================

checkpatch master ./net/batman-adv/fragmentation.c
=2D-------------------------------------------------

    WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
    #455: FILE: ./net/batman-adv/fragmentation.c:455:
    +	mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE);
    
    total: 0 errors, 1 warnings, 0 checks, 516 lines checked


headers master
=2D-------------

    diff --git a/build/net/batman-adv/bat_iv_ogm.c b/build/net/batman-adv/bat_iv_ogm.c
    index 3952e3c..9f85ee3 100644
    --- a/build/net/batman-adv/bat_iv_ogm.c
    +++ b/build/net/batman-adv/bat_iv_ogm.c
    @@ -16,7 +16,10 @@
      */
     
     #include "bat_algo.h" // IWYU pragma: keep
    +#include "linux/netlink.h"
     #include "main.h" // IWYU pragma: keep
    +#include "net/genetlink.h"
    +#include "net/netlink.h"
     
     #include <linux/atomic.h>
     #include <linux/bitmap.h>
    @@ -48,7 +51,6 @@
     #include <linux/types.h>
     #include <linux/workqueue.h>
     #include <uapi/linux/batman_adv.h>
    -
     #include "bitarray.h"
     #include "hard-interface.h"
     #include "hash.h"
    diff --git a/build/net/batman-adv/bat_v.c b/build/net/batman-adv/bat_v.c
    index 2ff7e69..49928f9 100644
    --- a/build/net/batman-adv/bat_v.c
    +++ b/build/net/batman-adv/bat_v.c
    @@ -16,9 +16,14 @@
      */
     
     #include "bat_algo.h" // IWYU pragma: keep
    +#include "linux/netlink.h"
     #include "main.h" // IWYU pragma: keep
    +#include "net/genetlink.h"
    +#include "net/netlink.h"
     
     #include <linux/atomic.h>
    +#include <linux/errno.h>
    +#include <linux/if_ether.h>
     #include <linux/bug.h>
     #include <linux/cache.h>
     #include <linux/init.h>
    @@ -30,7 +35,6 @@
     #include <linux/types.h>
     #include <linux/workqueue.h>
     #include <uapi/linux/batman_adv.h>
    -
     #include "bat_v_elp.h"
     #include "bat_v_ogm.h"
     #include "hash.h"
    @@ -38,6 +42,8 @@
     #include "originator.h"
     #include "packet.h"
     
    +struct sk_buff;
    +
     static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
     {
     	int ret;
    diff --git a/build/net/batman-adv/main.c b/build/net/batman-adv/main.c
    index 4702f67..1194cbd 100644
    --- a/build/net/batman-adv/main.c
    +++ b/build/net/batman-adv/main.c
    @@ -48,7 +48,6 @@
     #include <net/dsfield.h>
     #include <net/rtnetlink.h>
     #include <uapi/linux/batman_adv.h>
    -
     #include "bat_algo.h" // IWYU pragma: keep
     #include "bridge_loop_avoidance.h"
     #include "debugfs.h"
    @@ -57,7 +56,10 @@
     #include "gateway_common.h"
     #include "hard-interface.h"
     #include "icmp_socket.h"
    +#include "linux/netlink.h"
     #include "multicast.h"
    +#include "net/genetlink.h"
    +#include "net/netlink.h"
     #include "netlink.h"
     #include "network-coding.h"
     #include "originator.h"
    diff --git a/build/net/batman-adv/main.h b/build/net/batman-adv/main.h
    index 946f09a..5f0be03 100644
    --- a/build/net/batman-adv/main.h
    +++ b/build/net/batman-adv/main.h
    @@ -187,6 +187,7 @@ enum batadv_uev_type {
     #include "types.h"
     
     struct batadv_ogm_packet;
    +struct netlink_callback;
     struct seq_file;
     struct sk_buff;
     
    diff --git a/build/net/batman-adv/netlink.c b/build/net/batman-adv/netlink.c
    index 55cc224..dd1347c 100644
    --- a/build/net/batman-adv/netlink.c
    +++ b/build/net/batman-adv/netlink.c
    @@ -15,13 +15,24 @@
      * along with this program; if not, see <http://www.gnu.org/licenses/>.
      */
     
    +#include "linux/netlink.h"
     #include "main.h" // IWYU pragma: keep
    +#include "net/genetlink.h"
     #include "netlink.h"
     
    +#include <linux/errno.h>
    +#include <linux/fs.h>
    +#include <linux/if_ether.h>
    +#include <linux/init.h>
     #include <linux/netdevice.h>
    +#include <linux/printk.h>
    +#include <linux/rculist.h>
    +#include <linux/rcupdate.h>
    +#include <linux/skbuff.h>
    +#include <linux/stddef.h>
    +#include <linux/types.h>
     #include <net/sock.h>
     #include <uapi/linux/batman_adv.h>
    -
     #include "hard-interface.h"
     #include "originator.h"
     #include "soft-interface.h"
    diff --git a/build/net/batman-adv/netlink.h b/build/net/batman-adv/netlink.h
    index 31022d4..2f53795 100644
    --- a/build/net/batman-adv/netlink.h
    +++ b/build/net/batman-adv/netlink.h
    @@ -18,7 +18,12 @@
     #ifndef _NET_BATMAN_ADV_NETLINK_H_
     #define _NET_BATMAN_ADV_NETLINK_H_
     
    +#include <linux/compiler.h>
     #include <net/genetlink.h>
    +#include "linux/genetlink.h"
    +#include "net/netlink.h"
    +
    +struct nlmsghdr;
     
     void batadv_netlink_register(void);
     void batadv_netlink_unregister(void);
    diff --git a/build/net/batman-adv/originator.c b/build/net/batman-adv/originator.c
    index 9cefcce..f5355c6 100644
    --- a/build/net/batman-adv/originator.c
    +++ b/build/net/batman-adv/originator.c
    @@ -16,9 +16,11 @@
      */
     
     #include "originator.h"
    +#include "linux/netlink.h"
     #include "main.h" // IWYU pragma: keep
     
     #include <linux/atomic.h>
    +#include <linux/skbuff.h>
     #include <linux/errno.h>
     #include <linux/etherdevice.h>
     #include <linux/fs.h>
    @@ -35,7 +37,6 @@
     #include <linux/workqueue.h>
     #include <net/sock.h>
     #include <uapi/linux/batman_adv.h>
    -
     #include "distributed-arp-table.h"
     #include "fragmentation.h"
     #include "gateway_client.h"
    diff --git a/build/net/batman-adv/originator.h b/build/net/batman-adv/originator.h
    index cdef186..6e33c6a 100644
    --- a/build/net/batman-adv/originator.h
    +++ b/build/net/batman-adv/originator.h
    @@ -31,7 +31,9 @@
     
     #include "hash.h"
     
    +struct netlink_callback;
     struct seq_file;
    +struct sk_buff;
     
     bool batadv_compare_orig(const struct hlist_node *node, const void *data2);
     int batadv_originator_init(struct batadv_priv *bat_priv);
    diff --git a/build/net/batman-adv/translation-table.c b/build/net/batman-adv/translation-table.c
    index 055d543..c0b6c4c 100644
    --- a/build/net/batman-adv/translation-table.c
    +++ b/build/net/batman-adv/translation-table.c
    @@ -16,9 +16,13 @@
      */
     
     #include "translation-table.h"
    +#include "linux/netlink.h"
     #include "main.h" // IWYU pragma: keep
    +#include "net/genetlink.h"
    +#include "net/netlink.h"
     
     #include <linux/atomic.h>
    +#include <linux/skbuff.h>
     #include <linux/bitops.h>
     #include <linux/bug.h>
     #include <linux/byteorder/generic.h>
    @@ -43,10 +47,8 @@
     #include <linux/stddef.h>
     #include <linux/string.h>
     #include <linux/workqueue.h>
    -#include <net/net_namespace.h>
     #include <net/sock.h>
     #include <uapi/linux/batman_adv.h>
    -
     #include "bridge_loop_avoidance.h"
     #include "hard-interface.h"
     #include "hash.h"
    diff --git a/build/net/batman-adv/translation-table.h b/build/net/batman-adv/translation-table.h
    index 889a071..e1a12a9 100644
    --- a/build/net/batman-adv/translation-table.h
    +++ b/build/net/batman-adv/translation-table.h
    @@ -20,6 +20,9 @@
     
     #include "main.h" // IWYU pragma: keep
     
    +struct netlink_callback;
    +struct sk_buff;
    +
     #include <linux/types.h>
     
     struct net_device;


kerneldoc master ./net/batman-adv/types.h
=2D----------------------------------------

    ./net/batman-adv/types.h:1314: warning: No description found for parameter 'bat_neigh_dump'
    ./net/batman-adv/types.h:1314: warning: No description found for parameter 'bat_orig_dump'


smatch master linux-4.5 CONFIG_BATMAN_ADV_BLA=y CONFIG_BATMAN_ADV_DAT=n CONFIG_BATMAN_ADV_DEBUG=y CONFIG_BATMAN_ADV_NC=n CONFIG_BATMAN_ADV_MCAST=y CONFIG_BATMAN_ADV_BATMAN_V=y
=2D--------------------------------------------------------------------------

    /tmp/build/net/batman-adv/routing.c:593 batadv_route_unicast_packet warn: unused return: ethhdr = eth_hdr()


sparse master linux-3.10 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
=2D------------------------------------------------------------------------

    /tmp/build/net/batman-adv/netlink.c:267:44: error: not enough arguments for function genl_register_family_with_ops
    /tmp/build/net/batman-adv/netlink.c: In function 'batadv_netlink_register':
    /tmp/build/net/batman-adv/netlink.c:267:8: error: too few arguments to function 'genl_register_family_with_ops'
      ret = genl_register_family_with_ops(&batadv_netlink_family,
            ^
    In file included from /tmp/build/net/batman-adv/netlink.h:21:0,
                     from /tmp/build/net/batman-adv/netlink.c:19:
    include/net/genetlink.h:125:12: note: declared here
     extern int genl_register_family_with_ops(struct genl_family *family,
                ^
    make[2]: *** [/tmp/build/net/batman-adv/netlink.o] Error 1
    make[1]: *** [_module_/tmp/build/net/batman-adv] Error 2
    make: *** [all] Error 2


sparse master linux-3.12 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
=2D------------------------------------------------------------------------

    /tmp/build/net/batman-adv/netlink.c:267:44: error: not enough arguments for function genl_register_family_with_ops
    /tmp/build/net/batman-adv/netlink.c: In function 'batadv_netlink_register':
    /tmp/build/net/batman-adv/netlink.c:267:8: error: too few arguments to function 'genl_register_family_with_ops'
      ret = genl_register_family_with_ops(&batadv_netlink_family,
            ^
    In file included from /tmp/build/net/batman-adv/netlink.h:21:0,
                     from /tmp/build/net/batman-adv/netlink.c:19:
    include/net/genetlink.h:136:19: note: declared here
     static inline int genl_register_family_with_ops(struct genl_family *family,
                       ^
    make[2]: *** [/tmp/build/net/batman-adv/netlink.o] Error 1
    make[1]: *** [_module_/tmp/build/net/batman-adv] Error 2
    make: *** [all] Error 2


sparse master linux-3.6 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
=2D-----------------------------------------------------------------------

    /tmp/build/net/batman-adv/bat_iv_ogm.c:2067:41: error: no member 'portid' in struct netlink_skb_parms
    /tmp/build/net/batman-adv/bat_iv_ogm.c:2202:41: error: no member 'portid' in struct netlink_skb_parms
    /tmp/build/net/batman-adv/bat_iv_ogm.c: In function 'batadv_iv_ogm_orig_dump':
    /tmp/build/net/batman-adv/bat_iv_ogm.c:2067:34: error: 'struct netlink_skb_parms' has no member named 'portid'
      int portid = NETLINK_CB(cb->skb).portid;
                                      ^
    /tmp/build/net/batman-adv/bat_iv_ogm.c: In function 'batadv_iv_ogm_neigh_dump':
    /tmp/build/net/batman-adv/bat_iv_ogm.c:2202:34: error: 'struct netlink_skb_parms' has no member named 'portid'
      int portid = NETLINK_CB(cb->skb).portid;
                                      ^
    make[2]: *** [/tmp/build/net/batman-adv/bat_iv_ogm.o] Error 1
    make[1]: *** [_module_/tmp/build/net/batman-adv] Error 2
    make: *** [all] Error 2


sparse master linux-3.9 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
=2D-----------------------------------------------------------------------

    /tmp/build/net/batman-adv/netlink.c:267:44: error: not enough arguments for function genl_register_family_with_ops
    /tmp/build/net/batman-adv/netlink.c: In function 'batadv_netlink_register':
    /tmp/build/net/batman-adv/netlink.c:267:8: error: too few arguments to function 'genl_register_family_with_ops'
      ret = genl_register_family_with_ops(&batadv_netlink_family,
            ^
    In file included from /tmp/build/net/batman-adv/netlink.h:21:0,
                     from /tmp/build/net/batman-adv/netlink.c:19:
    include/net/genetlink.h:124:12: note: declared here
     extern int genl_register_family_with_ops(struct genl_family *family,
                ^
    make[2]: *** [/tmp/build/net/batman-adv/netlink.o] Error 1
    make[1]: *** [_module_/tmp/build/net/batman-adv] Error 2
    make: *** [all] Error 2


unused_symbols master linux-3.12 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
=2D--------------------------------------------------------------------------

    batadv_algo_dump
    batadv_algo_select
    batadv_bla_check_bcast_duplist
    batadv_bla_is_backbone_gw
    batadv_bla_is_backbone_gw_orig
    batadv_bla_rx
    batadv_bla_status_update
    batadv_bla_tx
    batadv_broadcast_addr
    batadv_debugfs_add_meshif
    batadv_debugfs_del_meshif
    batadv_frag_purge_orig
    batadv_frag_send_packet
    batadv_frag_skb_buffer
    batadv_frag_skb_fwd
    batadv_gw_bandwidth_set
    batadv_gw_dhcp_recipient_get
    batadv_gw_election
    batadv_gw_get_selected_orig
    batadv_gw_node_delete
    batadv_gw_out_of_range
    batadv_gw_tvlv_container_update
    batadv_hardif_disable_interface
    batadv_hardif_enable_interface
    batadv_hardif_get_by_netdev
    batadv_hardif_min_mtu
    batadv_is_my_mac
    batadv_mcast_forw_mode
    batadv_mcast_mla_update
    batadv_mcast_purge_orig
    batadv_mesh_free
    batadv_mesh_init
    batadv_routing_algo
    batadv_skb_set_priority
    batadv_socket_receive_packet
    batadv_tvlv_containers_process
    batadv_tvlv_unicast_send
    batadv_update_min_mtu
    batadv_vlan_ap_isola_get
    init_module


unused_symbols master linux-3.12 cfg: BLA=y DAT=y DEBUG=y NC=y MCAST=y BATMAN_V=n
=2D--------------------------------------------------------------------------

    batadv_algo_dump
    batadv_algo_select
    batadv_bla_check_bcast_duplist
    batadv_bla_is_backbone_gw
    batadv_bla_is_backbone_gw_orig
    batadv_bla_rx
    batadv_bla_status_update
    batadv_bla_tx
    batadv_broadcast_addr
    batadv_dat_drop_broadcast_packet
    batadv_dat_snoop_incoming_arp_reply
    batadv_dat_snoop_incoming_arp_request
    batadv_dat_snoop_outgoing_arp_reply
    batadv_dat_snoop_outgoing_arp_request
    batadv_dat_status_update
    batadv_debugfs_add_meshif
    batadv_debugfs_del_meshif
    batadv_frag_purge_orig
    batadv_frag_send_packet
    batadv_frag_skb_buffer
    batadv_frag_skb_fwd
    batadv_gw_bandwidth_set
    batadv_gw_dhcp_recipient_get
    batadv_gw_election
    batadv_gw_get_selected_orig
    batadv_gw_node_delete
    batadv_gw_out_of_range
    batadv_gw_tvlv_container_update
    batadv_hardif_disable_interface
    batadv_hardif_enable_interface
    batadv_hardif_get_by_netdev
    batadv_hardif_min_mtu
    batadv_is_my_mac
    batadv_mcast_forw_mode
    batadv_mcast_mla_update
    batadv_mcast_purge_orig
    batadv_mesh_free
    batadv_mesh_init
    batadv_routing_algo
    batadv_skb_set_priority
    batadv_socket_receive_packet
    batadv_tvlv_containers_process
    batadv_tvlv_unicast_send
    batadv_update_min_mtu
    batadv_vlan_ap_isola_get
    init_module


wrong namespace symbols master linux-3.6 cfg: BLA=y DAT=n DEBUG=y NC=n MCAST=y BATMAN_V=n
=2D--------------------------------------------------------------------------

    nm: './build/net/batman-adv/*.o': No such file


=2D-nextPart3524408.fhnBrciRUx--
This is a multi-part message in MIME format.

[-- Attachment #1.2: Type: text/plain, Size: 1110 bytes --]

On Thursday 17 March 2016 18:04:56 Matthias Schiffer wrote:
> And here is the new version of the PoC userspace tool.
> Build with:
> 
> gcc -o batnl batnl.c $$(pkg-config --cflags --libs libnl-1) -Wall

Thanks for the patches.

I've only looked at the test querier for a second and I am a little bit 
confused that you access things like attrs[BATADV_ATTR_ALGO_NAME] without 
checking if this is available or that the received message is valid (according 
to the nla_parse policy).

I know that this is only a PoC but wanted to mention it in case somebody wants 
to use it as reference for a batctl/alfred implementation.

I like that the netlink interface doesn't introduce complex structs at the 
moment (but I have to think a little bit about it). The unnamed enums freak me 
out a little bit (names would be nice so it is easier to write kernel-doc for 
it).

I just ran the build_test stuff through your branch so you get an early 
feedback about some common problems. See the attached mail (the unused symbols 
seem to be only symptoms of the build failures with old kernels < 3.12).

Kind regards,
	Sven

[-- Attachment #1.3: Build check errors found_2016-03-17.mbox --]
[-- Type: application/mbox, Size: 19773 bytes --]

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
                   ` (5 preceding siblings ...)
  2016-03-17 17:04 ` [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
@ 2016-03-18 11:23 ` Sven Eckelmann
  2016-03-18 12:00   ` Matthias Schiffer
  2016-04-18 14:50 ` Simon Wunderlich
  7 siblings, 1 reply; 23+ messages in thread
From: Sven Eckelmann @ 2016-03-18 11:23 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: b.a.t.m.a.n

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

On Thursday 17 March 2016 17:45:30 Matthias Schiffer wrote:
[...]
> At the moment, the following debugfs files have corresponding netlink APIs:
> 
> * routing_algos
> * neighbors
> * originators
> * transtable_global
> * transtable_local
> * (hardinterfaces for a softif can be queried)
> 
> The following files are still missing:
> 
> * gateways
> * bla_claim_table
> * bla_backbone_table
> * dat_cache
> * nc_nodes

What about the "socket" file?

Kind regards,
	Sven

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-18  7:09   ` Sven Eckelmann
@ 2016-03-18 11:53     ` Matthias Schiffer
  2016-04-18 10:59       ` Sven Eckelmann
  0 siblings, 1 reply; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-18 11:53 UTC (permalink / raw)
  To: Sven Eckelmann; +Cc: b.a.t.m.a.n


[-- Attachment #1.1: Type: text/plain, Size: 1973 bytes --]

On 03/18/2016 08:09 AM, Sven Eckelmann wrote:
> On Thursday 17 March 2016 18:04:56 Matthias Schiffer wrote:
>> And here is the new version of the PoC userspace tool.
>> Build with:
>>
>> gcc -o batnl batnl.c $$(pkg-config --cflags --libs libnl-1) -Wall
> 
> Thanks for the patches.
> 
> I've only looked at the test querier for a second and I am a little bit 
> confused that you access things like attrs[BATADV_ATTR_ALGO_NAME] without 
> checking if this is available or that the received message is valid (according 
> to the nla_parse policy).
> 
> I know that this is only a PoC but wanted to mention it in case somebody wants 
> to use it as reference for a batctl/alfred implementation.
> 
> I like that the netlink interface doesn't introduce complex structs at the 
> moment (but I have to think a little bit about it). The unnamed enums freak me 
> out a little bit (names would be nice so it is easier to write kernel-doc for 
> it).
> 
> I just ran the build_test stuff through your branch so you get an early 
> feedback about some common problems. See the attached mail (the unused symbols 
> seem to be only symptoms of the build failures with old kernels < 3.12).
> 
> Kind regards,
> 	Sven
> 

Hi,
regarding the first issue: I guess I should just add validation, as doing
so is simple and can only improve robustness. One line of thought that
seems to be common when dealing with such ABIs is that the kernel would
break its ABI contract by sending invalid messages, and that userspace
behaviour would be unspecified anyways if the kernel misbehaves.

I guess we can just give the enums names. Looking through the other UAPI
files, some enums have names, others don't.

Thanks for the build testing, I haven't put too much thought into the
compat issues yet. The genl_register_family_with_ops error should be easy
to fix, the struct netlink_skb_parms differences might be more problematic.

Regards,
Matthias


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-18 11:23 ` Sven Eckelmann
@ 2016-03-18 12:00   ` Matthias Schiffer
  2016-03-18 12:04     ` Sven Eckelmann
  0 siblings, 1 reply; 23+ messages in thread
From: Matthias Schiffer @ 2016-03-18 12:00 UTC (permalink / raw)
  To: Sven Eckelmann; +Cc: b.a.t.m.a.n


[-- Attachment #1.1: Type: text/plain, Size: 913 bytes --]

On 03/18/2016 12:23 PM, Sven Eckelmann wrote:
> On Thursday 17 March 2016 17:45:30 Matthias Schiffer wrote:
> [...]
>> At the moment, the following debugfs files have corresponding netlink APIs:
>>
>> * routing_algos
>> * neighbors
>> * originators
>> * transtable_global
>> * transtable_local
>> * (hardinterfaces for a softif can be queried)
>>
>> The following files are still missing:
>>
>> * gateways
>> * bla_claim_table
>> * bla_backbone_table
>> * dat_cache
>> * nc_nodes
> 
> What about the "socket" file?
> 
> Kind regards,
> 	Sven
> 

Ah, I forgot about that one because it is very different from the others.

I think it should be possible to convert "socket" as well by wrapping the
BATADV_ICMP packets in netlink packets. Or maybe it would be possible to
drop that altogether and just do ping/traceroute in userspace with
AF_PACKET or similar?

Regards,
Matthias


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-18 12:00   ` Matthias Schiffer
@ 2016-03-18 12:04     ` Sven Eckelmann
  2016-03-19  8:49       ` Antonio Quartulli
  0 siblings, 1 reply; 23+ messages in thread
From: Sven Eckelmann @ 2016-03-18 12:04 UTC (permalink / raw)
  To: Matthias Schiffer; +Cc: b.a.t.m.a.n, Antonio Quartulli

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

On Friday 18 March 2016 13:00:54 Matthias Schiffer wrote:
[...]
> > What about the "socket" file?
[...]
> 
> Ah, I forgot about that one because it is very different from the others.
> 
> I think it should be possible to convert "socket" as well by wrapping the
> BATADV_ICMP packets in netlink packets. Or maybe it would be possible to
> drop that altogether and just do ping/traceroute in userspace with
> AF_PACKET or similar?

The latter could be problematic for TP meter implementation [1,2,3,4,5].
Antonio, do you have an opinion about that?

Kind regards,
	Sven

[1] https://patchwork.open-mesh.org/patch/15807/
[2] https://patchwork.open-mesh.org/patch/15808/
[3] https://patchwork.open-mesh.org/patch/15809/
[4] https://patchwork.open-mesh.org/patch/15810/
[5] https://patchwork.open-mesh.org/patch/15811/

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-18 12:04     ` Sven Eckelmann
@ 2016-03-19  8:49       ` Antonio Quartulli
  2016-03-19  9:19         ` Sven Eckelmann
  0 siblings, 1 reply; 23+ messages in thread
From: Antonio Quartulli @ 2016-03-19  8:49 UTC (permalink / raw)
  To: Sven Eckelmann; +Cc: b.a.t.m.a.n

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

On Fri, Mar 18, 2016 at 01:04:50PM +0100, Sven Eckelmann wrote:
> On Friday 18 March 2016 13:00:54 Matthias Schiffer wrote:
> [...]
> > > What about the "socket" file?
> [...]
> > 
> > Ah, I forgot about that one because it is very different from the others.
> > 
> > I think it should be possible to convert "socket" as well by wrapping the
> > BATADV_ICMP packets in netlink packets. Or maybe it would be possible to
> > drop that altogether and just do ping/traceroute in userspace with
> > AF_PACKET or similar?
> 
> The latter could be problematic for TP meter implementation [1,2,3,4,5].
> Antonio, do you have an opinion about that?

Personally I wouldn't mind doing ping/traceroute 100% in userspace.

The TP meter itself does not require to exchange real packets between user and
kernel space, but only requires the availability of a command to start and stop
a measurement session. I believe these could be implemented as yet another
netlink command/message type.

Cheers,

-- 
Antonio Quartulli

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-19  8:49       ` Antonio Quartulli
@ 2016-03-19  9:19         ` Sven Eckelmann
  2016-04-18 11:10           ` Sven Eckelmann
  0 siblings, 1 reply; 23+ messages in thread
From: Sven Eckelmann @ 2016-03-19  9:19 UTC (permalink / raw)
  To: Antonio Quartulli; +Cc: b.a.t.m.a.n

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

On Saturday 19 March 2016 16:49:34 Antonio Quartulli wrote:
> On Fri, Mar 18, 2016 at 01:04:50PM +0100, Sven Eckelmann wrote:
> > On Friday 18 March 2016 13:00:54 Matthias Schiffer wrote:
> > [...]
> > 
> > > > What about the "socket" file?
> > 
> > [...]
> > 
> > > Ah, I forgot about that one because it is very different from the
> > > others.
> > > 
> > > I think it should be possible to convert "socket" as well by wrapping
> > > the
> > > BATADV_ICMP packets in netlink packets. Or maybe it would be possible to
> > > drop that altogether and just do ping/traceroute in userspace with
> > > AF_PACKET or similar?
> > 
> > The latter could be problematic for TP meter implementation [1,2,3,4,5].
> > Antonio, do you have an opinion about that?
> 
> Personally I wouldn't mind doing ping/traceroute 100% in userspace.


How can this be implemented 100% in userspace? Lets ignore the 
reply/forwarding part for a second and just concentrate on the initiator of 
the ping/traceroute. It can use AF_PACKET in userspace to send batadv packets 
directly on the hardif. But here comes the first problem... which is the 
correct hardif? There can be multiple and the userspace does not really know 
which one is the one the kernel would use at a particular time. So you have to 
implement the same algorithms in userspace the emulate the kernel part (or you 
may do something completely different). And still then you would have problems 
when the kernel is tweaked and the userspace didn't receive this tweak.

Maybe it is necessary to ask the kernel before sending the ping by asking him 
"hey, what interface would use use right now and what other parameters are now 
required". Similar to what "ip route get 8.8.8.8" would do.

Or am I just overcomplicated things now?

Kind regards,
	Sven

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-18 11:53     ` Matthias Schiffer
@ 2016-04-18 10:59       ` Sven Eckelmann
  0 siblings, 0 replies; 23+ messages in thread
From: Sven Eckelmann @ 2016-04-18 10:59 UTC (permalink / raw)
  To: Matthias Schiffer; +Cc: b.a.t.m.a.n

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

On Friday 18 March 2016 12:53:37 Matthias Schiffer wrote:
[...]
> Thanks for the build testing, I haven't put too much thought into the
> compat issues yet. The genl_register_family_with_ops error should be easy
> to fix, the struct netlink_skb_parms differences might be more problematic.

The genl_register_family_with_ops error can most likely be solved by

https://git.kernel.org/cgit/linux/kernel/git/backports/backports.git/tree/backport/backport-include/net/genetlink.h?id=a91a3e6e3a6ed6cdbbe942bafe05ae5fcdf41ce9

The netlink_skb_parms most likely can be fixed by redefining NETLINK_CB to
something which casts to a structure with the name portid for the field
pid for Linux < 3.7.

    struct netlink_skb_parms_compat {
            struct scm_creds        creds;
             __u32                   portid;  /* was renamed in 3.7 from "pid" */
             __u32                   dst_group;    
             __u32                   flags;
             struct sock             *sk;
    };

Kind regards,
	Sven

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-19  9:19         ` Sven Eckelmann
@ 2016-04-18 11:10           ` Sven Eckelmann
  0 siblings, 0 replies; 23+ messages in thread
From: Sven Eckelmann @ 2016-04-18 11:10 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Antonio Quartulli

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

On Saturday 19 March 2016 10:19:39 Sven Eckelmann wrote:
> > > > > What about the "socket" file?
[...]
> How can this be implemented 100% in userspace? Lets ignore the 
> reply/forwarding part for a second and just concentrate on the initiator of 
> the ping/traceroute. It can use AF_PACKET in userspace to send batadv packets 
> directly on the hardif. But here comes the first problem... which is the 
> correct hardif? There can be multiple and the userspace does not really know 
> which one is the one the kernel would use at a particular time. So you have to 
> implement the same algorithms in userspace the emulate the kernel part (or you 
> may do something completely different). And still then you would have problems 
> when the kernel is tweaked and the userspace didn't receive this tweak.
> 
> Maybe it is necessary to ask the kernel before sending the ping by asking him 
> "hey, what interface would use use right now and what other parameters are now 
> required". Similar to what "ip route get 8.8.8.8" would do.
> 
> Or am I just overcomplicated things now?

It can also be postponed to later. No need to have this in netns from the
start.

But RTM_GETROUTE-like NLM_F_REQUEST requests sound feasible for a userspace
based ICMP-like request initiation. But most likely with generic messages
instead of structs.

Kind regards,
	Sven

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
                   ` (6 preceding siblings ...)
  2016-03-18 11:23 ` Sven Eckelmann
@ 2016-04-18 14:50 ` Simon Wunderlich
  2016-04-20  2:31   ` Andrew Lunn
  2016-04-20  7:32   ` Matthias Schiffer
  7 siblings, 2 replies; 23+ messages in thread
From: Simon Wunderlich @ 2016-04-18 14:50 UTC (permalink / raw)
  To: b.a.t.m.a.n

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

On Thursday 17 March 2016 17:45:30 Matthias Schiffer wrote:
> Hi,
> this is the second take of my netlink API patches. As mentioned before, the
> netlink API is superior to the current debugfs API in many aspects:
> 
> * debugfs is broken (see PATCH 1 for details)
> * Netlink is namespace-aware, and can be used in unprivileged containers
>   without problems
> * Netlink packets are more machine-readable than text files, and can be
>   easily extended without potentially breaking userspace
> * On older kernels, seq_file can't fall back to vmalloc if kmalloc fails,
>   which often leads to OOM when reading "originators" in large meshes, as
>   the whole file must fit into a single buffer
> 
> Of course, are also a few downsides; when the data is too big to fit into
> a single netlink packet, the provided data may be inconsistent (entries may
> be missing or duplicated.) This will happen in large meshes only, and be
> improbable in any case.
> 
> The patches have been developed on top of the netns patchset, but should
> be applicable independently (maybe with minor changes.)
> 
> All netlink queries returning lists of any kind can only be used with
> NLM_F_DUMP queries, so that arbitrarity large responses are possible (split
> across multiple packets if necessary.)
> 
> At the moment, the following debugfs files have corresponding netlink APIs:
> 
> * routing_algos
> * neighbors
> * originators
> * transtable_global
> * transtable_local
> * (hardinterfaces for a softif can be queried)
> 
> The following files are still missing:
> 
> * gateways
> * bla_claim_table
> * bla_backbone_table
> * dat_cache
> * nc_nodes
> 
> Obviously, documentation is also a TODO. Comments about the API design are
> very welcome...
> 
> Regards,
> Matthias

Hi Matthias,

thanks for reposting this and sorry for the long silence. Since we have the 
namespace work from Andrew now which would require netlink support, I think 
its a good time to integrate this. :)

I'll try to look into your patchset this week into more detail and give 
feedback. In the meantime, just a few question:

 * Would you like to add netlink support for the missing files as well? 
(gateways, bla, dat, nc) 
 * Would you also like to do the batctl support? I guess we can have batctl 
behave "compatible" by trying netlink first and fall back to debugfs for the 
next few years
 * Also open is the icmp socket stuff, which we could postpone and implement 
later.

Just wanted to check with your availability first, but we would like to 
support the netlink adoption. :)

Thanks!
     Simon

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-04-18 14:50 ` Simon Wunderlich
@ 2016-04-20  2:31   ` Andrew Lunn
  2016-04-20 11:39     ` Simon Wunderlich
  2016-04-20  7:32   ` Matthias Schiffer
  1 sibling, 1 reply; 23+ messages in thread
From: Andrew Lunn @ 2016-04-20  2:31 UTC (permalink / raw)
  To: The list for a Better Approach To Mobile Ad-hoc Networking

> > The following files are still missing:
> > 
> > * gateways
> > * bla_claim_table
> > * bla_backbone_table
> > * dat_cache
> > * nc_nodes
> > 
> > Obviously, documentation is also a TODO. Comments about the API design are
> > very welcome...
> > 
> > Regards,
> > Matthias
> 
> Hi Matthias,
> 
> thanks for reposting this and sorry for the long silence. Since we have the 
> namespace work from Andrew now which would require netlink support, I think 
> its a good time to integrate this. :)

Hi Simon, Matthias

I picked up your patches and played with them when combined with my
netns patches. All works well.

I also started on integrating the user space code with batctl. I've
got as far as integrating netlink user space code for what you had,
and i added gateways, and started on bla_claim_table.

I'm on vacation this week, and i'm not likely to be reading emails
again this week. 

I should be able to post code next week.

  Andrew

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-04-18 14:50 ` Simon Wunderlich
  2016-04-20  2:31   ` Andrew Lunn
@ 2016-04-20  7:32   ` Matthias Schiffer
  2016-04-20  7:39     ` Sven Eckelmann
  1 sibling, 1 reply; 23+ messages in thread
From: Matthias Schiffer @ 2016-04-20  7:32 UTC (permalink / raw)
  To: Simon Wunderlich; +Cc: b.a.t.m.a.n


[-- Attachment #1.1: Type: text/plain, Size: 3302 bytes --]

On 04/18/2016 04:50 PM, Simon Wunderlich wrote:
> On Thursday 17 March 2016 17:45:30 Matthias Schiffer wrote:
>> Hi,
>> this is the second take of my netlink API patches. As mentioned before, the
>> netlink API is superior to the current debugfs API in many aspects:
>>
>> * debugfs is broken (see PATCH 1 for details)
>> * Netlink is namespace-aware, and can be used in unprivileged containers
>>   without problems
>> * Netlink packets are more machine-readable than text files, and can be
>>   easily extended without potentially breaking userspace
>> * On older kernels, seq_file can't fall back to vmalloc if kmalloc fails,
>>   which often leads to OOM when reading "originators" in large meshes, as
>>   the whole file must fit into a single buffer
>>
>> Of course, are also a few downsides; when the data is too big to fit into
>> a single netlink packet, the provided data may be inconsistent (entries may
>> be missing or duplicated.) This will happen in large meshes only, and be
>> improbable in any case.
>>
>> The patches have been developed on top of the netns patchset, but should
>> be applicable independently (maybe with minor changes.)
>>
>> All netlink queries returning lists of any kind can only be used with
>> NLM_F_DUMP queries, so that arbitrarity large responses are possible (split
>> across multiple packets if necessary.)
>>
>> At the moment, the following debugfs files have corresponding netlink APIs:
>>
>> * routing_algos
>> * neighbors
>> * originators
>> * transtable_global
>> * transtable_local
>> * (hardinterfaces for a softif can be queried)
>>
>> The following files are still missing:
>>
>> * gateways
>> * bla_claim_table
>> * bla_backbone_table
>> * dat_cache
>> * nc_nodes
>>
>> Obviously, documentation is also a TODO. Comments about the API design are
>> very welcome...
>>
>> Regards,
>> Matthias
> 
> Hi Matthias,
> 
> thanks for reposting this and sorry for the long silence. Since we have the 
> namespace work from Andrew now which would require netlink support, I think 
> its a good time to integrate this. :)
> 
> I'll try to look into your patchset this week into more detail and give 
> feedback. In the meantime, just a few question:
> 
>  * Would you like to add netlink support for the missing files as well? 
> (gateways, bla, dat, nc) 
>  * Would you also like to do the batctl support? I guess we can have batctl 
> behave "compatible" by trying netlink first and fall back to debugfs for the 
> next few years
>  * Also open is the icmp socket stuff, which we could postpone and implement 
> later.
> 
> Just wanted to check with your availability first, but we would like to 
> support the netlink adoption. :)
> 
> Thanks!
>      Simon
> 


As Andrew has already started to integrate and extend my patchset, I'll
happily leave further development to him - I'm quite busy with other
projects at the moment, so it would probably take a lot longer if I were to
work on this myself.

As I've mentioned before, regarding the batctl support, I'd love to see a
little library ("libbatadv"?) on top of libnl that could be used by batctl,
alfred and other monitoring tools (like the ones we are using in the Gluon
Freifunk firmwares).

Regards,
Matthias


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-04-20  7:32   ` Matthias Schiffer
@ 2016-04-20  7:39     ` Sven Eckelmann
  2016-04-20  7:49       ` Matthias Schiffer
  0 siblings, 1 reply; 23+ messages in thread
From: Sven Eckelmann @ 2016-04-20  7:39 UTC (permalink / raw)
  To: b.a.t.m.a.n

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

On Wednesday 20 April 2016 09:32:19 Matthias Schiffer wrote:
[...]
> As I've mentioned before, regarding the batctl support, I'd love to see a
> little library ("libbatadv"?) on top of libnl that could be used by batctl,
> alfred and other monitoring tools (like the ones we are using in the Gluon
> Freifunk firmwares).

Hm, then we would have to make everything ABI stable. So we would loose the 
flexibility of netlink (adding more fields) again just to keep the library 
stable.

Or what kind of functionality should this library expose that can be easily be 
kept stable?

Kind regards,
	Sven

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-04-20  7:39     ` Sven Eckelmann
@ 2016-04-20  7:49       ` Matthias Schiffer
  2016-04-20  7:53         ` Sven Eckelmann
  0 siblings, 1 reply; 23+ messages in thread
From: Matthias Schiffer @ 2016-04-20  7:49 UTC (permalink / raw)
  To: Sven Eckelmann; +Cc: b.a.t.m.a.n


[-- Attachment #1.1: Type: text/plain, Size: 1230 bytes --]

On 04/20/2016 09:39 AM, Sven Eckelmann wrote:
> On Wednesday 20 April 2016 09:32:19 Matthias Schiffer wrote:
> [...]
>> As I've mentioned before, regarding the batctl support, I'd love to see a
>> little library ("libbatadv"?) on top of libnl that could be used by batctl,
>> alfred and other monitoring tools (like the ones we are using in the Gluon
>> Freifunk firmwares).
> 
> Hm, then we would have to make everything ABI stable. So we would loose the 
> flexibility of netlink (adding more fields) again just to keep the library 
> stable.
> 
> Or what kind of functionality should this library expose that can be easily be 
> kept stable?
> 
> Kind regards,
> 	Sven
> 

I don't understand. The same code that would we added to batctl and alfred
could just be made a library with a nicer API, so other projects can easily
reuse it. Of course, the library API/ABI would need to be designed in a way
that keeps it extensible without breaking ABI.

I'm thinking of functions like "iterate over all originators", which would
query the netlink API, and then just call a callback with the netlink
attribute set for each originator. Just a thin wrapper making things more
usable.

Regards,
Matthias


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-04-20  7:49       ` Matthias Schiffer
@ 2016-04-20  7:53         ` Sven Eckelmann
  0 siblings, 0 replies; 23+ messages in thread
From: Sven Eckelmann @ 2016-04-20  7:53 UTC (permalink / raw)
  To: Matthias Schiffer; +Cc: b.a.t.m.a.n

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

On Wednesday 20 April 2016 09:49:25 Matthias Schiffer wrote:
> On 04/20/2016 09:39 AM, Sven Eckelmann wrote:
> > On Wednesday 20 April 2016 09:32:19 Matthias Schiffer wrote:
> > [...]
> >> As I've mentioned before, regarding the batctl support, I'd love to see a
> >> little library ("libbatadv"?) on top of libnl that could be used by batctl,
> >> alfred and other monitoring tools (like the ones we are using in the Gluon
> >> Freifunk firmwares).
> > 
> > Hm, then we would have to make everything ABI stable. So we would loose the 
> > flexibility of netlink (adding more fields) again just to keep the library 
> > stable.
[...]
> I don't understand. The same code that would we added to batctl and alfred
> could just be made a library with a nicer API, so other projects can easily
> reuse it. Of course, the library API/ABI would need to be designed in a way
> that keeps it extensible without breaking ABI.
> 
> I'm thinking of functions like "iterate over all originators", which would
> query the netlink API, and then just call a callback with the netlink
> attribute set for each originator. Just a thin wrapper making things more
> usable.

Ok, I thought that you want to have complete abstraction of the netlink
interface. But this now just sounds like you want to have some helper
functions to make the initial request to the kernel. The callback with
the netlink data is already part of libnl.

Kind regards,
	Sven

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

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

* Re: [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API
  2016-04-20  2:31   ` Andrew Lunn
@ 2016-04-20 11:39     ` Simon Wunderlich
  0 siblings, 0 replies; 23+ messages in thread
From: Simon Wunderlich @ 2016-04-20 11:39 UTC (permalink / raw)
  To: b.a.t.m.a.n

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

Hey Andrew,

On Wednesday 20 April 2016 04:31:36 Andrew Lunn wrote:
> > > The following files are still missing:
> > > 
> > > * gateways
> > > * bla_claim_table
> > > * bla_backbone_table
> > > * dat_cache
> > > * nc_nodes
> > > 
> > > Obviously, documentation is also a TODO. Comments about the API design
> > > are
> > > very welcome...
> > > 
> > > Regards,
> > > Matthias
> > 
> > Hi Matthias,
> > 
> > thanks for reposting this and sorry for the long silence. Since we have
> > the
> > namespace work from Andrew now which would require netlink support, I
> > think
> > its a good time to integrate this. :)
> 
> Hi Simon, Matthias
> 
> I picked up your patches and played with them when combined with my
> netns patches. All works well.
> 
> I also started on integrating the user space code with batctl. I've
> got as far as integrating netlink user space code for what you had,
> and i added gateways, and started on bla_claim_table.
> 
> I'm on vacation this week, and i'm not likely to be reading emails
> again this week.
> 
> I should be able to post code next week.

Cool! Thanks a lot for picking it up, I'm looking forward to your patches and 
will make sure to review them. :)

Thanks again,
     Simon

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

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

end of thread, other threads:[~2016-04-20 11:39 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-17 16:45 [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 1/5] batman-adv: add generic netlink query API to replace debugfs files Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 2/5] batman-adv: netlink: add translation table query Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 3/5] batman-adv: netlink: add originator and neighbor table queries Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 4/5] batman-adv: add B.A.T.M.A.N. IV bat_{orig, neigh}_dump implementations Matthias Schiffer
2016-03-17 16:45 ` [B.A.T.M.A.N.] [RFC v2 5/5] batman-adv: add B.A.T.M.A.N. V " Matthias Schiffer
2016-03-17 17:04 ` [B.A.T.M.A.N.] [RFC v2 0/5] batman-adv netlink query API Matthias Schiffer
2016-03-18  7:09   ` Sven Eckelmann
2016-03-18 11:53     ` Matthias Schiffer
2016-04-18 10:59       ` Sven Eckelmann
2016-03-18 11:23 ` Sven Eckelmann
2016-03-18 12:00   ` Matthias Schiffer
2016-03-18 12:04     ` Sven Eckelmann
2016-03-19  8:49       ` Antonio Quartulli
2016-03-19  9:19         ` Sven Eckelmann
2016-04-18 11:10           ` Sven Eckelmann
2016-04-18 14:50 ` Simon Wunderlich
2016-04-20  2:31   ` Andrew Lunn
2016-04-20 11:39     ` Simon Wunderlich
2016-04-20  7:32   ` Matthias Schiffer
2016-04-20  7:39     ` Sven Eckelmann
2016-04-20  7:49       ` Matthias Schiffer
2016-04-20  7:53         ` 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.