Skip to contentSkip to conversation

Add throughput meter support

PATCH In review Sven Eckelmann 2 participants 6 messages May 3, 2016

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v3 1/1 Add throughput meter support

Hi,

here is the third version of the throughput meter support. It is just a rebased version of the patchset with two little bugfixes. Both problems were detected and reported by Antonio:

* batctl didn't check if the test_time is > 0 before doing a division
* batman-adv wasn't returning an error to batctl when dst was not reachable

I am currently unsure how we should proceed regarding the ICMP packet type used to communicate to the userspace ([PATCH 2/3]). Andrew+Matthias already prepared a netlink patchset which looks quite good and which should be tested+applied. The consequence for this patchset would be that patch 2 should be completely dropped and instead the tp_meter should become its own command in the netlink interface of batman-adv. Any opinions about that (order in which patches should be applied/netlink interface should be handled) by the Simon, Antonio, Marek, Matthias or Andrew?

Antonio Quartulli (4):
batman-adv: return netdev status in the TX path
batman-adv: use another ICMP packet when sending command from userspace
batman-adv: throughput meter implementation
batctl: introduce throughput meter support

 net/batman-adv/Makefile         |    1 +
 net/batman-adv/fragmentation.c  |   41 +-
 net/batman-adv/fragmentation.h  |    6 +-
 net/batman-adv/icmp_socket.c    |  225 +++---
 net/batman-adv/icmp_socket.h    |    5 +-
 net/batman-adv/main.c           |    6 +-
 net/batman-adv/main.h           |   24 +-
 net/batman-adv/packet.h         |  120 ++++
 net/batman-adv/routing.c        |   33 +-
 net/batman-adv/send.c           |   25 +-
 net/batman-adv/soft-interface.c |    2 +
 net/batman-adv/tp_meter.c       | 1453 +++++++++++++++++++++++++++++++++++++++
 net/batman-adv/tp_meter.h       |   34 +
 net/batman-adv/types.h          |  113 +++
 14 files changed, 1944 insertions(+), 144 deletions(-)
 Makefile     |   2 +-
 main.c       |   6 ++
 main.h       |   1 +
 man/batctl.8 |  24 +++++-
 packet.h     | 120 ++++++++++++++++++++++++++++++
 tcpdump.c    |  14 +++-
 tp_meter.c   | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tp_meter.h   |  22 ++++++
 8 files changed, 421 insertions(+), 4 deletions(-)

Kind regards,
Sven

#1 lore raw

PATCH v3 2/3 batman-adv: use another ICMP packet when sending command from userspace

From: Antonio Quartulli <[email protected]>

In the current code a real batadv ICMP packet is used to communicate from userspace to the module which ICMP operation should be start (the operation to start depends on the size of the received packet). This worked good so far because the same packet was used to perform the only two available ICMP operations and the very same packet received from userspace was also sent over the wire to perform the operation itself.

As soon as we add new and different ICMP operations this model will not work well anymore. To improve this feature make the userspace use a proper packet type to tell the kernel module which operation to start.

The module will then arrange the rest by itself.

---
v3:
- Rebase on current master version
- inform batctl about problems finding the remote originator
v2:
- Rebase on current master version

---
 net/batman-adv/icmp_socket.c | 212 +++++++++++++++++++++++++------------------
 net/batman-adv/icmp_socket.h |   5 +-
 net/batman-adv/packet.h      |  15 +++
 net/batman-adv/types.h       |   2 +
 4 files changed, 140 insertions(+), 94 deletions(-)
net/batman-adv/icmp_socket.c +122 -90
index 777aea1..7284510 100644
@@ -52,8 +52,7 @@
 static struct batadv_socket_client *batadv_socket_client_hash[256];
 
 static void batadv_socket_add_packet(struct batadv_socket_client *socket_client,
-				     struct batadv_icmp_header *icmph,
-				     size_t icmp_len);
+				     void *icmp_buffer, size_t icmp_len);
 
 void batadv_socket_init(void)
 {
@@ -157,7 +156,7 @@ static ssize_t batadv_socket_read(struct file *file, char __user *buf,
 	spin_unlock_bh(&socket_client->lock);
 
 	packet_len = min(count, socket_packet->icmp_len);
-	error = copy_to_user(buf, &socket_packet->icmp_packet, packet_len);
+	error = copy_to_user(buf, &socket_packet->packet, packet_len);
 
 	kfree(socket_packet);
 
@@ -167,73 +166,90 @@ static ssize_t batadv_socket_read(struct file *file, char __user *buf,
 	return packet_len;
 }
 
-static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
-				   size_t len, loff_t *off)
+/**
+ * batadv_socket_write_user - Parse batadv_icmp_user_packet
+ * @bat_priv: the bat priv with all the icmp socket information
+ * @socket_client: layer2 icmp socket client data
+ * @primary_if: the selected primary interface
+ * @buff: buffer of user data
+ * @len: length of the data in buff
+ *
+ * Return: Number of read bytes from buff or < 0 on errors
+ */
+static ssize_t
+batadv_socket_write_user(struct batadv_priv *bat_priv,
+			 struct batadv_socket_client *socket_client,
+			 struct batadv_hard_iface *primary_if,
+			 const char __user *buff, size_t len)
+{
+	struct batadv_icmp_user_packet icmp_user_packet;
+
+	if (copy_from_user(&icmp_user_packet, buff, len))
+		return -EFAULT;
+
+	/* no command supported yet! */
+	len = -EINVAL;
+
+	return len;
+}
+
+/**
+ * batadv_socket_write_raw - Parse batadv_icmp_packet/batadv_icmp_packet_rr
+ * @bat_priv: the bat priv with all the icmp socket information
+ * @socket_client: layer2 icmp socket client data
+ * @primary_if: the selected primary interface
+ * @buff: buffer of user data
+ * @len: length of the data in buff
+ *
+ * Return: Number of read bytes from buff or < 0 on errors
+ */
+static ssize_t
+batadv_socket_write_raw(struct batadv_priv *bat_priv,
+			struct batadv_socket_client *socket_client,
+			struct batadv_hard_iface *primary_if,
+			const char __user *buff, size_t len)
 {
-	struct batadv_socket_client *socket_client = file->private_data;
-	struct batadv_priv *bat_priv = socket_client->bat_priv;
-	struct batadv_hard_iface *primary_if = NULL;
 	struct sk_buff *skb;
-	struct batadv_icmp_packet_rr *icmp_packet_rr;
-	struct batadv_icmp_header *icmp_header;
+	struct batadv_icmp_packet_rr icmp_packet, *icmp_buff;
 	struct batadv_orig_node *orig_node = NULL;
 	struct batadv_neigh_node *neigh_node = NULL;
-	size_t packet_len = sizeof(struct batadv_icmp_packet);
+	size_t packet_len;
 	u8 *addr;
 
-	if (len < sizeof(struct batadv_icmp_header)) {
+	if (len != sizeof(struct batadv_icmp_packet_rr) &&
+	    len != sizeof(struct batadv_icmp_packet)) {
 		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 			   "Error - can't send packet from char device: invalid packet size\n");
 		return -EINVAL;
 	}
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-
-	if (!primary_if) {
-		len = -EFAULT;
-		goto out;
-	}
-
-	if (len >= BATADV_ICMP_MAX_PACKET_SIZE)
-		packet_len = BATADV_ICMP_MAX_PACKET_SIZE;
-	else
-		packet_len = len;
-
-	skb = netdev_alloc_skb_ip_align(NULL, packet_len + ETH_HLEN);
-	if (!skb) {
-		len = -ENOMEM;
-		goto out;
-	}
+	packet_len = len;
+	if (copy_from_user(&icmp_packet, buff, len))
+		return -EFAULT;
 
-	skb->priority = TC_PRIO_CONTROL;
-	skb_reserve(skb, ETH_HLEN);
-	icmp_header = (struct batadv_icmp_header *)skb_put(skb, packet_len);
+	icmp_packet.uid = socket_client->index;
 
-	if (copy_from_user(icmp_header, buff, packet_len)) {
-		len = -EFAULT;
-		goto free_skb;
+	/* if the compat version does not match, return an error now */
+	if (icmp_packet.version != BATADV_COMPAT_VERSION) {
+		icmp_packet.msg_type = BATADV_PARAMETER_PROBLEM;
+		icmp_packet.version = BATADV_COMPAT_VERSION;
+		batadv_socket_add_packet(socket_client, &icmp_packet,
+					 packet_len);
+		return len;
 	}
 
-	if (icmp_header->packet_type != BATADV_ICMP) {
+	if (icmp_packet.packet_type != BATADV_ICMP) {
 		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 			   "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
-		len = -EINVAL;
-		goto free_skb;
+		return -EINVAL;
 	}
 
-	switch (icmp_header->msg_type) {
+	switch (icmp_packet.msg_type) {
 	case BATADV_ECHO_REQUEST:
-		if (len < sizeof(struct batadv_icmp_packet)) {
-			batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-				   "Error - can't send packet from char device: invalid packet size\n");
-			len = -EINVAL;
-			goto free_skb;
-		}
-
 		if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
 			goto dst_unreach;
 
-		orig_node = batadv_orig_hash_find(bat_priv, icmp_header->dst);
+		orig_node = batadv_orig_hash_find(bat_priv, icmp_packet.dst);
 		if (!orig_node)
 			goto dst_unreach;
 
@@ -248,47 +264,68 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
 		if (neigh_node->if_incoming->if_status != BATADV_IF_ACTIVE)
 			goto dst_unreach;
 
-		icmp_packet_rr = (struct batadv_icmp_packet_rr *)icmp_header;
-		if (packet_len == sizeof(*icmp_packet_rr)) {
-			addr = neigh_node->if_incoming->net_dev->dev_addr;
-			ether_addr_copy(icmp_packet_rr->rr[0], addr);
-		}
-
 		break;
 	default:
 		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 			   "Error - can't send packet from char device: got unknown message type\n");
-		len = -EINVAL;
-		goto free_skb;
+		return -EINVAL;
 	}
 
-	icmp_header->uid = socket_client->index;
+	skb = netdev_alloc_skb_ip_align(NULL, packet_len + ETH_HLEN);
+	if (!skb)
+		return -ENOMEM;
 
-	if (icmp_header->version != BATADV_COMPAT_VERSION) {
-		icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
-		icmp_header->version = BATADV_COMPAT_VERSION;
-		batadv_socket_add_packet(socket_client, icmp_header,
-					 packet_len);
-		goto free_skb;
-	}
+	skb->priority = TC_PRIO_CONTROL;
+	skb_reserve(skb, ETH_HLEN);
+	icmp_buff = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len);
+	memcpy(icmp_buff, &icmp_packet, packet_len);
 
-	ether_addr_copy(icmp_header->orig, primary_if->net_dev->dev_addr);
+	ether_addr_copy(icmp_buff->orig, primary_if->net_dev->dev_addr);
+
+	switch (icmp_packet.msg_type) {
+	case BATADV_ECHO_REQUEST:
+		if (len == sizeof(struct batadv_icmp_packet_rr)) {
+			addr = neigh_node->if_incoming->net_dev->dev_addr;
+			ether_addr_copy(icmp_packet.rr[0], addr);
+		}
+		break;
+	}
 
 	batadv_send_unicast_skb(skb, neigh_node);
 	goto out;
 
 dst_unreach:
-	icmp_header->msg_type = BATADV_DESTINATION_UNREACHABLE;
-	batadv_socket_add_packet(socket_client, icmp_header, packet_len);
-free_skb:
-	kfree_skb(skb);
+	icmp_packet.msg_type = BATADV_DESTINATION_UNREACHABLE;
+	batadv_socket_add_packet(socket_client, &icmp_packet, packet_len);
 out:
-	if (primary_if)
-		batadv_hardif_put(primary_if);
 	if (neigh_node)
 		batadv_neigh_node_put(neigh_node);
 	if (orig_node)
 		batadv_orig_node_put(orig_node);
+
+	return len;
+}
+
+static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
+				   size_t len, loff_t *off)
+{
+	struct batadv_socket_client *socket_client = file->private_data;
+	struct batadv_priv *bat_priv = socket_client->bat_priv;
+	struct batadv_hard_iface *primary_if;
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		return -EFAULT;
+
+	if (len == sizeof(struct batadv_icmp_user_packet))
+		len = batadv_socket_write_user(bat_priv, socket_client,
+					       primary_if, buff, len);
+	else
+		len = batadv_socket_write_raw(bat_priv, socket_client,
+					      primary_if, buff, len);
+
+	batadv_hardif_put(primary_if);
+
 	return len;
 }
 
@@ -336,36 +373,29 @@ err:
  * batadv_socket_add_packet - schedule an icmp packet to be sent to
  *  userspace on an icmp socket.
  * @socket_client: the socket this packet belongs to
- * @icmph: pointer to the header of the icmp packet
+ * @icmp_buffer: pointer to the icmp packet
  * @icmp_len: total length of the icmp packet
  */
 static void batadv_socket_add_packet(struct batadv_socket_client *socket_client,
-				     struct batadv_icmp_header *icmph,
-				     size_t icmp_len)
+				     void *icmp_buffer, size_t icmp_len)
 {
 	struct batadv_socket_packet *socket_packet;
-	size_t len;
-
-	socket_packet = kmalloc(sizeof(*socket_packet), GFP_ATOMIC);
+	struct batadv_icmp_packet *icmp_packet;
 
+	icmp_packet = (struct batadv_icmp_packet *)icmp_buffer;
+	socket_packet = kmalloc(sizeof(*socket_packet) + icmp_len, GFP_ATOMIC);
 	if (!socket_packet)
 		return;
 
-	len = icmp_len;
-	/* check the maximum length before filling the buffer */
-	if (len > sizeof(socket_packet->icmp_packet))
-		len = sizeof(socket_packet->icmp_packet);
-
-	INIT_LIST_HEAD(&socket_packet->list);
-	memcpy(&socket_packet->icmp_packet, icmph, len);
-	socket_packet->icmp_len = len;
+	memcpy(socket_packet->packet, icmp_packet, icmp_len);
+	socket_packet->icmp_len = icmp_len;
 
 	spin_lock_bh(&socket_client->lock);
 
 	/* while waiting for the lock the socket_client could have been
 	 * deleted
 	 */
-	if (!batadv_socket_client_hash[icmph->uid]) {
+	if (!batadv_socket_client_hash[icmp_packet->uid]) {
 		spin_unlock_bh(&socket_client->lock);
 		kfree(socket_packet);
 		return;
@@ -392,15 +422,17 @@ static void batadv_socket_add_packet(struct batadv_socket_client *socket_client,
 /**
  * batadv_socket_receive_packet - schedule an icmp packet to be received
  *  locally and sent to userspace.
- * @icmph: pointer to the header of the icmp packet
+ * @icmp_buffer: pointer to the the icmp packet
  * @icmp_len: total length of the icmp packet
  */
-void batadv_socket_receive_packet(struct batadv_icmp_header *icmph,
-				  size_t icmp_len)
+void batadv_socket_receive_packet(void *icmp_buffer, size_t icmp_len)
 {
 	struct batadv_socket_client *hash;
+	struct batadv_icmp_packet *icmp;
+
+	icmp = (struct batadv_icmp_packet *)icmp_buffer;
 
-	hash = batadv_socket_client_hash[icmph->uid];
+	hash = batadv_socket_client_hash[icmp->uid];
 	if (hash)
-		batadv_socket_add_packet(hash, icmph, icmp_len);
+		batadv_socket_add_packet(hash, icmp_buffer, icmp_len);
 }
net/batman-adv/icmp_socket.h +1 -4
index 618d5de..0043b44 100644
@@ -22,13 +22,10 @@
 
 #include <linux/types.h>
 
-struct batadv_icmp_header;
-
 #define BATADV_ICMP_SOCKET "socket"
 
 void batadv_socket_init(void);
 int batadv_socket_setup(struct batadv_priv *bat_priv);
-void batadv_socket_receive_packet(struct batadv_icmp_header *icmph,
-				  size_t icmp_len);
+void batadv_socket_receive_packet(void *icmp_buffer, size_t icmp_len);
 
 #endif /* _NET_BATMAN_ADV_ICMP_SOCKET_H_ */
net/batman-adv/packet.h +15 -0
index 372128d..459836a 100644
@@ -285,6 +285,21 @@ struct batadv_elp_packet {
 #define BATADV_ELP_HLEN sizeof(struct batadv_elp_packet)
 
 /**
+ * struct batadv_icmp_user_packet - used to start an ICMP operation from
+ *  userspace
+ * @dst: destination node
+ * @version: compat version used by userspace
+ * @cmd_type: the command to start
+ * @arg1: possible argument for the command
+ */
+struct batadv_icmp_user_packet {
+	u8 dst[ETH_ALEN];
+	u8 version;
+	u8 cmd_type;
+	u32 arg1;
+};
+
+/**
  * struct batadv_icmp_header - common members among all the ICMP packets
  * @packet_type: batman-adv packet type, part of the general header
  * @version: batman-adv protocol version, part of the genereal header
net/batman-adv/types.h +2 -0
index 6a577f4..bc9bb9a 100644
@@ -995,11 +995,13 @@ struct batadv_socket_client {
  * @list: list node for batadv_socket_client::queue_list
  * @icmp_len: size of the layer2 icmp packet
  * @icmp_packet: layer2 icmp packet
+ * @packet: payload of layer2 icmp packet
  */
 struct batadv_socket_packet {
 	struct list_head list;
 	size_t icmp_len;
 	u8 icmp_packet[BATADV_ICMP_MAX_PACKET_SIZE];
+	u8 packet[0];
 };
 
 #ifdef CONFIG_BATMAN_ADV_BLA
Signature · 1 line
2.8.1
#2 lore raw

PATCH v3 3/3 batman-adv: throughput meter implementation

In reply to Sven Eckelmann

From: Antonio Quartulli <[email protected]>

The throughput meter module is a simple, kernel-space replacement for throughtput measurements tool like iperf and netperf. It is intended to approximate TCP behaviour.

It is invoked through batctl: the protocol is connection oriented, with cumulative acknowledgment and a dynamic-size sliding window.

The test *can* be interrupted by batctl. A receiver side timeout avoids unlimited waitings for sender packets: after one second of inactivity, the receiver abort the ongoing test.

Based on a prototype from Edo Monticelli <[email protected]>

---
v3:
- Rebase on current master version
- inform batctl about problems finding the remote originator
v2:
- Rebase on current master version

---
 net/batman-adv/Makefile         |    1 +
 net/batman-adv/icmp_socket.c    |   17 +-
 net/batman-adv/main.c           |    2 +
 net/batman-adv/main.h           |   24 +-
 net/batman-adv/packet.h         |  105 +++
 net/batman-adv/routing.c        |    9 +-
 net/batman-adv/soft-interface.c |    2 +
 net/batman-adv/tp_meter.c       | 1453 +++++++++++++++++++++++++++++++++++++++
 net/batman-adv/tp_meter.h       |   34 +
 net/batman-adv/types.h          |  111 +++
 10 files changed, 1748 insertions(+), 10 deletions(-)
 create mode 100644 net/batman-adv/tp_meter.c
 create mode 100644 net/batman-adv/tp_meter.h
net/batman-adv/Makefile +1 -0
index 797cf2f..a91c2f5 100644
@@ -39,4 +39,5 @@ batman-adv-y += routing.o
 batman-adv-y += send.o
 batman-adv-y += soft-interface.o
 batman-adv-y += sysfs.o
+batman-adv-y += tp_meter.o
 batman-adv-y += translation-table.o
net/batman-adv/icmp_socket.c +15 -2
index 7284510..9d5ff77 100644
@@ -48,6 +48,7 @@
 #include "originator.h"
 #include "packet.h"
 #include "send.h"
+#include "tp_meter.h"
 
 static struct batadv_socket_client *batadv_socket_client_hash[256];
 
@@ -57,6 +58,7 @@ static void batadv_socket_add_packet(struct batadv_socket_client *socket_client,
 void batadv_socket_init(void)
 {
 	memset(batadv_socket_client_hash, 0, sizeof(batadv_socket_client_hash));
+	batadv_tp_meter_init();
 }
 
 static int batadv_socket_open(struct inode *inode, struct file *file)
@@ -187,8 +189,19 @@ batadv_socket_write_user(struct batadv_priv *bat_priv,
 	if (copy_from_user(&icmp_user_packet, buff, len))
 		return -EFAULT;
 
-	/* no command supported yet! */
-	len = -EINVAL;
+	switch (icmp_user_packet.cmd_type) {
+	case BATADV_TP_START:
+		batadv_tp_start(socket_client, icmp_user_packet.dst,
+				icmp_user_packet.arg1);
+		break;
+	case BATADV_TP_STOP:
+		batadv_tp_stop(bat_priv, icmp_user_packet.dst,
+			       BATADV_TP_SIGINT);
+		break;
+	default:
+		len = -EINVAL;
+		break;
+	}
 
 	return len;
 }
net/batman-adv/main.c +2 -0
index 1d6984a..8157cd7 100644
@@ -141,6 +141,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
 	spin_lock_init(&bat_priv->tvlv.container_list_lock);
 	spin_lock_init(&bat_priv->tvlv.handler_list_lock);
 	spin_lock_init(&bat_priv->softif_vlan_list_lock);
+	spin_lock_init(&bat_priv->tp_list_lock);
 
 	INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
 	INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
@@ -159,6 +160,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
 	INIT_HLIST_HEAD(&bat_priv->tvlv.container_list);
 	INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list);
 	INIT_HLIST_HEAD(&bat_priv->softif_vlan_list);
+	INIT_HLIST_HEAD(&bat_priv->tp_list);
 
 	ret = batadv_v_mesh_init(bat_priv);
 	if (ret < 0)
net/batman-adv/main.h +17 -7
index 7692526..e28f698 100644
@@ -100,6 +100,9 @@
 #define BATADV_NUM_BCASTS_WIRELESS 3
 #define BATADV_NUM_BCASTS_MAX 3
 
+/* length of the single packet used by the TP meter */
+#define BATADV_TP_PACKET_LEN ETH_DATA_LEN
+
 /* msecs after which an ARP_REQUEST is sent in broadcast as fallback */
 #define ARP_REQ_DELAY 250
 /* numbers of originator to contact for any PUT/GET DHT operation */
@@ -131,6 +134,11 @@
 
 #define BATADV_NC_NODE_TIMEOUT 10000 /* Milliseconds */
 
+/**
+ * BATADV_TP_MAX_NUM - maximum number of simultaneously active tp sessions
+ */
+#define BATADV_TP_MAX_NUM 5
+
 enum batadv_mesh_state {
 	BATADV_MESH_INACTIVE,
 	BATADV_MESH_ACTIVE,
@@ -231,16 +239,18 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);
  * @BATADV_DBG_BLA: bridge loop avoidance messages
  * @BATADV_DBG_DAT: ARP snooping and DAT related messages
  * @BATADV_DBG_NC: network coding related messages
+ * @BATADV_DBG_TP_METER: throughput meter messages
  * @BATADV_DBG_ALL: the union of all the above log levels
  */
 enum batadv_dbg_level {
-	BATADV_DBG_BATMAN = BIT(0),
-	BATADV_DBG_ROUTES = BIT(1),
-	BATADV_DBG_TT	  = BIT(2),
-	BATADV_DBG_BLA    = BIT(3),
-	BATADV_DBG_DAT    = BIT(4),
-	BATADV_DBG_NC	  = BIT(5),
-	BATADV_DBG_ALL    = 63,
+	BATADV_DBG_BATMAN	= BIT(0),
+	BATADV_DBG_ROUTES	= BIT(1),
+	BATADV_DBG_TT		= BIT(2),
+	BATADV_DBG_BLA		= BIT(3),
+	BATADV_DBG_DAT		= BIT(4),
+	BATADV_DBG_NC		= BIT(5),
+	BATADV_DBG_TP_METER	= BIT(6),
+	BATADV_DBG_ALL		= 127,
 };
 
 #ifdef CONFIG_BATMAN_ADV_DEBUG
net/batman-adv/packet.h +105 -0

129 lines not on this page · raw message

net/batman-adv/routing.c +8 -1
index 1c3fea0..4e86290 100644
@@ -45,6 +45,7 @@
 #include "packet.h"
 #include "send.h"
 #include "soft-interface.h"
+#include "tp_meter.h"
 #include "translation-table.h"
 
 static int batadv_route_unicast_packet(struct sk_buff *skb,
@@ -242,7 +243,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
 		/* receive the packet */
 		if (skb_linearize(skb) < 0)
 			break;
-
 		batadv_socket_receive_packet(icmph, skb->len);
 		break;
 	case BATADV_ECHO_REQUEST:
@@ -275,6 +275,13 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
 			ret = NET_RX_SUCCESS;
 
 		break;
+	case BATADV_TP:
+		if (!pskb_may_pull(skb, sizeof(struct batadv_icmp_tp_packet)))
+			goto out;
+
+		batadv_tp_meter_recv(bat_priv, skb);
+		ret = NET_RX_SUCCESS;
+		goto out;
 	default:
 		/* drop unknown type */
 		goto out;
net/batman-adv/soft-interface.c +2 -0
index f37ce39..31d1df2 100644
@@ -837,6 +837,8 @@ static int batadv_softif_init_late(struct net_device *dev)
 #ifdef CONFIG_BATMAN_ADV_BLA
 	atomic_set(&bat_priv->bla.num_requests, 0);
 #endif
+	atomic_set(&bat_priv->tp_num, 0);
+
 	bat_priv->tt.last_changeset = NULL;
 	bat_priv->tt.last_changeset_len = 0;
 	bat_priv->isolation_mark = 0;
net/batman-adv/tp_meter.c new file +1453 -0

1,453 lines not on this page · raw message

net/batman-adv/tp_meter.h new file +34 -0
new file mode 100644
index 0000000..5e8b326
@@ -0,0 +1,34 @@
+/* Copyright (C) 2012-2016 B.A.T.M.A.N. contributors:
+ *
+ * Edo Monticelli, Antonio Quartulli
+ *
+ * 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_TP_METER_H_
+#define _NET_BATMAN_ADV_TP_METER_H_
+
+#include "main.h"
+
+struct sk_buff;
+
+#include <linux/types.h>
+
+void batadv_tp_meter_init(void);
+void batadv_tp_start(struct batadv_socket_client *socket_client, const u8 *dst,
+		     u32 test_length);
+void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst,
+		    u8 return_value);
+void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb);
+
+#endif /* _NET_BATMAN_ADV_TP_METER_H_ */
net/batman-adv/types.h +111 -0

135 lines not on this page · raw message

Signature · 1 line
2.8.1
#3 lore raw

PATCH v3 1/1 batctl: introduce throughput meter support

In reply to Sven Eckelmann

From: Antonio Quartulli <[email protected]>

Add command to launch the throughput meter test. The throughput meter is a batman kernelspace tool for throughput measurements. The syntax is:

batctl tp <MAC>

The test is interruptible with SIGINT or SIGTERM; if the test succeeds with no error the throughput and the elapsed time are printed to stdout, otherwise occurred an error message is displayed (on stdout) accordingly.

Based on a prototype from Edo Monticelli <[email protected]>

---
v3:
- Rebase on current master version
- check test_time for non-0 to avoid floating point exception during division
v2:
- Rebase on current master version

---
 Makefile     |   2 +-
 main.c       |   6 ++
 main.h       |   1 +
 man/batctl.8 |  24 +++++-
 packet.h     | 120 ++++++++++++++++++++++++++++++
 tcpdump.c    |  14 +++-
 tp_meter.c   | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tp_meter.h   |  22 ++++++
 8 files changed, 421 insertions(+), 4 deletions(-)
 create mode 100644 tp_meter.c
 create mode 100644 tp_meter.h
Makefile +1 -1
index b82c0c6..7cfe851 100755
@@ -24,7 +24,7 @@ export CONFIG_BATCTL_BISECT=n
 
 # batctl build
 BINARY_NAME = batctl
-OBJ = main.o bat-hosts.o functions.o sys.o debug.o ping.o traceroute.o tcpdump.o  hash.o debugfs.o ioctl.o list-batman.o translate.o
+OBJ = main.o bat-hosts.o functions.o sys.o debug.o ping.o traceroute.o tcpdump.o  hash.o debugfs.o ioctl.o list-batman.o translate.o tp_meter.o
 OBJ_BISECT = bisect_iv.o
 MANPAGE = man/batctl.8
 
main.c +6 -0
index a2cda5b..5e1ecc7 100644
@@ -33,6 +33,7 @@
 #include "translate.h"
 #include "traceroute.h"
 #include "tcpdump.h"
+#include "tp_meter.h"
 #include "bisect_iv.h"
 #include "ioctl.h"
 #include "functions.h"
@@ -82,6 +83,7 @@ static void print_usage(void)
 	fprintf(stderr, " \tping|p                     <destination>     \tping another batman adv host via layer 2\n");
 	fprintf(stderr, " \ttraceroute|tr              <destination>     \ttraceroute another batman adv host via layer 2\n");
 	fprintf(stderr, " \ttcpdump|td                 <interface>       \ttcpdump layer 2 traffic on the given interface\n");
+	printf(" \tthroughputmeter|tp         <destination>     \tstart a throughput measurement\n");
 	fprintf(stderr, " \ttranslate|t                <destination>     \ttranslate a destination to the originator responsible for it\n");
 #ifdef BATCTL_BISECT
 	fprintf(stderr, " \tbisect_iv                  <file1> .. <fileN>\tanalyze given batman iv log files for routing stability\n");
@@ -162,6 +164,10 @@ int main(int argc, char **argv)
 
 		ret = ping(mesh_iface, argc - 1, argv + 1);
 
+	} else if ((strcmp(argv[1], "throughputmeter") == 0) || (strcmp(argv[1], "tp") == 0)) {
+
+		ret = tp_meter (mesh_iface, argc -1, argv + 1);
+
 	} else if ((strcmp(argv[1], "traceroute") == 0) || (strcmp(argv[1], "tr") == 0)) {
 
 		ret = traceroute(mesh_iface, argc - 1, argv + 1);
main.h +1 -0
index e94fc33..36e28cd 100644
@@ -51,6 +51,7 @@
 
 typedef uint8_t u8; /* linux kernel compat */
 typedef uint16_t u16; /* linux kernel compat */
+typedef uint32_t u32; /* linux kernel compat */
 
 extern char module_ver_path[];
 
man/batctl.8 +22 -2
index e804a08..69a2537 100644
@@ -36,9 +36,11 @@ B.A.T.M.A.N. advanced operates on layer 2. Thus all hosts participating in the v
 connected together for all protocols above layer 2. Therefore the common diagnosis tools do not work as expected. To
 overcome these problems batctl contains the commands \fBping\fP, \fBtraceroute\fP, \fBtcpdump\fP which provide similar
 functionality to the normal \fBping\fP(1), \fBtraceroute\fP(1), \fBtcpdump\fP(1) commands, but modified to layer 2
-behaviour or using the B.A.T.M.A.N. advanced protocol.
-.PP
+behaviour or using the B.A.T.M.A.N. advanced protocol. For similar reasons, \fBthroughputmeter\fP, a command to test network
+performances, is also included.
+
 .PP
+.Pp
 .SH OPTIONS
 .TP
 .I \fBoptions:
@@ -319,6 +321,24 @@ for routing loops. Use "\-t" to trace OGMs of a host throughout the network. Use
 nodes. The option "\-s" can be used to limit the output to a range of sequence numbers, between min and max, or to one
 specific sequence number, min. Furthermore using "\-o" you can filter the output to a specified originator. If "\-n" is
 given batctl will not replace the MAC addresses with bat\-host names in the output.
+.RE
+.br
+.IP "\fBthroughputmeter\fP|\fBtp\fP \fBMAC\fP"
+This command starts a throughput test entirely controlled by batman module in
+kernel space: the computational resources needed to align memory and copy data
+between user and kernel space that are required by other user space tools may
+represent a bootleneck on some low profile device.
+
+The test consist of the transfer of 14 MB of data between the two nodes. The
+protocol used to transfer the data is somehow similar to TCP, but simpler: some
+TCP features are still missing, thus protocol performances could be worst. Since
+a fixed amount of data is transferred the experiment duration depends on the
+network conditions. The experiment can be interrupted with CTRL + C. At the end
+of a succesful experiment the throughput in KBytes per second is returned,
+togheter with the experiment duration in millisecond and the amount of bytes
+transferred. If too many packets are lost or the specified MAC address is not
+reachable, a message notifing the error is returned instead of the result.
+.RE
 .br
 .SH FILES
 .TP
packet.h +120 -0

144 lines not on this page · raw message

tcpdump.c +13 -1
index 363e9e4..be0c4f0 100644
@@ -808,11 +808,14 @@ static void dump_batman_elp(unsigned char *packet_buff, ssize_t buff_len,
 static void dump_batman_icmp(unsigned char *packet_buff, ssize_t buff_len, int read_opt, int time_printed)
 {
 	struct batadv_icmp_packet *icmp_packet;
+	struct batadv_icmp_tp_packet *tp;
+
 	char *name;
 
 	LEN_CHECK((size_t)buff_len - sizeof(struct ether_header), sizeof(struct batadv_icmp_packet), "BAT ICMP");
 
 	icmp_packet = (struct batadv_icmp_packet *)(packet_buff + sizeof(struct ether_header));
+	tp = (struct batadv_icmp_tp_packet *)icmp_packet;
 
 	if (!time_printed)
 		print_time();
@@ -820,7 +823,8 @@ static void dump_batman_icmp(unsigned char *packet_buff, ssize_t buff_len, int r
 	printf("BAT %s > ",
 	       get_name_by_macaddr((struct ether_addr *)icmp_packet->orig, read_opt));
 
-	name = get_name_by_macaddr((struct ether_addr *)icmp_packet->dst, read_opt);
+	name = get_name_by_macaddr((struct ether_addr *)icmp_packet->dst,
+				    read_opt);
 
 	switch (icmp_packet->msg_type) {
 	case BATADV_ECHO_REPLY:
@@ -841,6 +845,14 @@ static void dump_batman_icmp(unsigned char *packet_buff, ssize_t buff_len, int r
 			icmp_packet->ttl, icmp_packet->version,
 			(size_t)buff_len - sizeof(struct ether_header));
 		break;
+	case BATADV_TP:
+		printf("%s: ICMP TP type %s (%hhu), id %hhu, seq %u, ttl %2d, v %d, length %zu\n",
+		       name, tp->subtype == BATADV_TP_MSG ? "MSG" :
+			     tp->subtype == BATADV_TP_ACK ? "ACK" : "N/A",
+		       tp->subtype, tp->uid, ntohl(tp->seqno), tp->ttl,
+		       tp->version,
+		       (size_t)buff_len - sizeof(struct ether_header));
+		break;
 	default:
 		printf("%s: ICMP type %hhu, length %zu\n",
 			name, icmp_packet->msg_type,
tp_meter.c new file +236 -0

236 lines not on this page · raw message

tp_meter.h new file +22 -0
new file mode 100644
index 0000000..59bca07
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013-2016 B.A.T.M.A.N. contributors:
+ *
+ * Antonio Quartulli <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+int tp_meter(char *mesh_iface, int argc, char **argv);
Signature · 1 line
2.8.1
maintainer
#4 lore raw
In reply to Sven Eckelmann
Quoted 10 lines · On Tuesday 03 May 2016 10:59:07 Sven Eckelmann wrote:

Hi,

here is the third version of the throughput meter support. It is just a rebased version of the patchset with two little bugfixes. Both problems were detected and reported by Antonio:

* batctl didn't check if the test_time is > 0 before doing a division
* batman-adv wasn't returning an error to batctl when dst was not reachable

Quoted 8 lines

I am currently unsure how we should proceed regarding the ICMP packet type used to communicate to the userspace ([PATCH 2/3]). Andrew+Matthias already prepared a netlink patchset which looks quite good and which should be tested+applied. The consequence for this patchset would be that patch 2 should be completely dropped and instead the tp_meter should become its own command in the netlink interface of batman-adv. Any opinions about that (order in which patches should be applied/netlink interface should be handled) by the Simon, Antonio, Marek, Matthias or Andrew?

Thanks for preparing the patchset! Antonio, Marek and me discussed and agreed that we should adopt the patchset as it is, and have the netlink support additionally at a later point.

Thanks,
Simon

#5 lore raw
Quoted 20 lines · On Tuesday 03 May 2016 13:28:16 Simon Wunderlich wrote:
Quoted 10 lines · On Tuesday 03 May 2016 10:59:07 Sven Eckelmann wrote:

Hi,

here is the third version of the throughput meter support. It is just a rebased version of the patchset with two little bugfixes. Both problems were detected and reported by Antonio:

* batctl didn't check if the test_time is > 0 before doing a division
* batman-adv wasn't returning an error to batctl when dst was not reachable

Quoted 8 lines

I am currently unsure how we should proceed regarding the ICMP packet type used to communicate to the userspace ([PATCH 2/3]). Andrew+Matthias already prepared a netlink patchset which looks quite good and which should be tested+applied. The consequence for this patchset would be that patch 2 should be completely dropped and instead the tp_meter should become its own command in the netlink interface of batman-adv. Any opinions about that (order in which patches should be applied/netlink interface should be handled) by the Simon, Antonio, Marek, Matthias or Andrew?

Quoted 3 lines

Thanks for preparing the patchset! Antonio, Marek and me discussed and agreed that we should adopt the patchset as it is, and have the netlink support additionally at a later point.

Did read Antonio the comment in the internal ticket?

Kind regards,
Sven