From patchwork Tue Apr 12 08:50:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 15957 X-Patchwork-Delegate: a@unstable.cc Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 9298B824D7; Tue, 12 Apr 2016 10:50:59 +0200 (CEST) Authentication-Results: open-mesh.org; dmarc=none header.from=open-mesh.com Authentication-Results: open-mesh.org; dkim=fail reason="verification failed; unprotected key" header.d=open-mesh-com.20150623.gappssmtp.com header.i=@open-mesh-com.20150623.gappssmtp.com header.b=ckTC+niw; dkim-adsp=none (unprotected policy); dkim-atps=neutral Received-SPF: Neutral (access neither permitted nor denied) identity=mailfrom; client-ip=2a00:1450:400c:c09::22c; helo=mail-wm0-x22c.google.com; envelope-from=sven.eckelmann@open-mesh.com; receiver=b.a.t.m.a.n@lists.open-mesh.org Authentication-Results: open-mesh.org; dmarc=none header.from=open-mesh.com Received: from mail-wm0-x22c.google.com (mail-wm0-x22c.google.com [IPv6:2a00:1450:400c:c09::22c]) by open-mesh.org (Postfix) with ESMTPS id 3366D824B7 for ; Tue, 12 Apr 2016 10:50:55 +0200 (CEST) Received: by mail-wm0-x22c.google.com with SMTP id v188so117684496wme.1 for ; Tue, 12 Apr 2016 01:50:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=open-mesh-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=9u5C2YQQee7m/vnspMEARiSh0svtJSxb0iN4uhCrieE=; b=ckTC+niwiAIExpucXGsYKDfTGnAB2jBfiEV4Njh8Vm/rgn7UxTO2pYh5pILBoK0uh0 4qeSWesvfsgCez9Ge6PiK8ZSPwlyOkwTb7dwAuYf0sxAiLufr7Ds2ERqep4PSceFcqlP OTT0fw2ov3bv+5vCxtm3pRmFHHi2477uhaC8whXJA498XQb4+mMRr4BYM/WpPwejL9f7 7MqOUzfNAeE4g41l73DylDIfg6UGdzXPCqGIfImB0pOpeHqSWyJ8xp+Epv2Pi6Tpa3zj um8HhODCI9X4R2JWIvySkUkx2LnJBYkoK9GAIQe4eb2kB2Mi6+6+ny0vzeBJEBf0SbBc 634A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=9u5C2YQQee7m/vnspMEARiSh0svtJSxb0iN4uhCrieE=; b=Yw/7fZ7g8zEvAi9dKqLEuZVSeW0WwqBuyUTRrffpoprp8lkfsHr1645/kC4O151op9 +HQe0tfrqKj4G7vWoO/kZxCJrzzQiWzl8NRWSTk1urrUop4jT04nuE41U6M5DRfxomxV 8RiDluCLrLxR95o5tU7tbto+UdedORzStYoDjfUe9c1diJmVC708QiwwalS51JTOtViw CW6e7AspaoTPZneSyTJN4ela3zfghSlZzvOuMI2sjRRs01wENB50XUuY7ELbFWMHVRtT bA7Qx0r6kqIMTFJueqNKYV5Goc7KoFy9rf5pr8nz4dhsA9KiDIP0ylKXa5SlB8J6noCC ga3g== X-Gm-Message-State: AOPr4FXW4kXT/uSEBXJh71812+CzoMhwsAG+BO1C9owmiTYI0FLQjKebWKhzOy1pb6hPVcqI X-Received: by 10.28.173.137 with SMTP id w131mr7214466wme.72.1460451055157; Tue, 12 Apr 2016 01:50:55 -0700 (PDT) Received: from sven-desktop.home.narfation.org (x4d0d5022.dyn.telefonica.de. [77.13.80.34]) by smtp.gmail.com with ESMTPSA id lh1sm32153653wjb.20.2016.04.12.01.50.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 12 Apr 2016 01:50:54 -0700 (PDT) From: Sven Eckelmann X-Google-Original-From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Tue, 12 Apr 2016 10:50:47 +0200 Message-Id: <1460451047-18375-1-git-send-email-sven@open-mesh.com> X-Mailer: git-send-email 2.8.0.rc3 Cc: Sven Eckelmann , Antonio Quartulli Subject: [B.A.T.M.A.N.] [PATCH] batctl: introduce throughput meter support X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" From: Antonio Quartulli Add command to launch the throughput meter test. The throughput meter is a batman kernelspace tool for throughput measurements. The syntax is: batctl tp 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 Signed-off-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- Makefile | 2 +- main.c | 6 ++ main.h | 1 + man/batctl.8 | 24 ++++++- packet.h | 120 +++++++++++++++++++++++++++++++ tcpdump.c | 14 +++- tp_meter.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tp_meter.h | 22 ++++++ 8 files changed, 412 insertions(+), 4 deletions(-) create mode 100644 tp_meter.c create mode 100644 tp_meter.h diff --git a/Makefile b/Makefile index b82c0c6..7cfe851 100755 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/main.c b/main.c index a2cda5b..5e1ecc7 100644 --- a/main.c +++ b/main.c @@ -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 \tping another batman adv host via layer 2\n"); fprintf(stderr, " \ttraceroute|tr \ttraceroute another batman adv host via layer 2\n"); fprintf(stderr, " \ttcpdump|td \ttcpdump layer 2 traffic on the given interface\n"); + printf(" \tthroughputmeter|tp \tstart a throughput measurement\n"); fprintf(stderr, " \ttranslate|t \ttranslate a destination to the originator responsible for it\n"); #ifdef BATCTL_BISECT fprintf(stderr, " \tbisect_iv .. \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); diff --git a/main.h b/main.h index 81f223c..f75d103 100644 --- a/main.h +++ b/main.h @@ -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[]; diff --git a/man/batctl.8 b/man/batctl.8 index e804a08..69a2537 100644 --- a/man/batctl.8 +++ b/man/batctl.8 @@ -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 diff --git a/packet.h b/packet.h index 372128d..ed3224c 100644 --- a/packet.h +++ b/packet.h @@ -21,6 +21,8 @@ #include #include +#define batadv_tp_is_error(n) ((u8)n > 127 ? 1 : 0) + /** * enum batadv_packettype - types for batman-adv encapsulated packets * @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV @@ -93,6 +95,7 @@ enum batadv_icmp_packettype { BATADV_ECHO_REQUEST = 8, BATADV_TTL_EXCEEDED = 11, BATADV_PARAMETER_PROBLEM = 12, + BATADV_TP = 15, }; /** @@ -285,6 +288,31 @@ 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; +}; + +/** + * enum batadv_icmp_user_cmd_type - types for batman-adv icmp cmd modes + * @BATADV_TP_START: start a throughput meter run + * @BATADV_TP_STOP: stop a throughput meter run + */ +enum batadv_icmp_user_cmd_type { + BATADV_TP_START = 0, + BATADV_TP_STOP = 2, +}; + +/** * 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 @@ -334,6 +362,98 @@ struct batadv_icmp_packet { __be16 seqno; }; +/** + * struct batadv_icmp_tp_packet - ICMP TP Meter packet + * @packet_type: batman-adv packet type, part of the general header + * @version: batman-adv protocol version, part of the genereal header + * @ttl: time to live for this packet, part of the genereal header + * @msg_type: ICMP packet type + * @dst: address of the destination node + * @orig: address of the source node + * @uid: local ICMP socket identifier + * @subtype: TP packet subtype (see batadv_icmp_tp_subtype) + * @session: TP session identifier + * @seqno: the TP sequence number + * @timestamp: time when the packet has been sent. This value is filled in a + * TP_MSG and echoed back in the next TP_ACK so that the sender can compute the + * RTT. Since it is read only by the host which wrote it, there is no need to + * store it using network order + */ +struct batadv_icmp_tp_packet { + u8 packet_type; + u8 version; + u8 ttl; + u8 msg_type; /* see ICMP message types above */ + u8 dst[ETH_ALEN]; + u8 orig[ETH_ALEN]; + u8 uid; + u8 subtype; + u8 session[2]; + __be32 seqno; + __be32 timestamp; +}; + +/** + * enum batadv_icmp_tp_subtype - ICMP TP Meter packet subtypes + * @BATADV_TP_MSG: Msg from sender to receiver + * @BATADV_TP_ACK: acknowledgment from receiver to sender + */ +enum batadv_icmp_tp_subtype { + BATADV_TP_MSG = 0, + BATADV_TP_ACK, +}; + +/** + * struct batadv_icmp_tp_result_packet - tp response returned to batctl + * @packet_type: batman-adv packet type, part of the general header + * @version: batman-adv protocol version, part of the genereal header + * @ttl: time to live for this packet, part of the genereal header + * @msg_type: ICMP packet type + * @dst: address of the destination node + * @orig: address of the source node + * @uid: local ICMP socket identifier + * @reserved: not used - useful for alignment + * @return_value: result of run (see batadv_tp_meter_status) + * @test_time: time (msec) the run took + * @total_bytes: amount of acked bytes during run + */ +struct batadv_icmp_tp_result_packet { + u8 packet_type; + u8 version; + u8 ttl; + u8 msg_type; /* see ICMP message types above */ + u8 dst[ETH_ALEN]; + u8 orig[ETH_ALEN]; + u8 uid; + u8 reserved[2]; + u8 return_value; + u32 test_time; + u32 total_bytes; +}; + +/** + * enum batadv_tp_meter_reason - reason of a a tp meter test run stop + * @BATADV_TP_COMPLETE: sender finished tp run + * @BATADV_TP_SIGINT: sender was stopped during run + * @BATADV_TP_DST_UNREACHABLE: receiver could not be reached or didn't answer + * @BATADV_TP_RESEND_LIMIT: (unused) sender retry reached limit + * @BATADV_TP_ALREADY_ONGOING: test to or from the same node already ongoing + * @BATADV_TP_MEMORY_ERROR: test was stopped due to low memory + * @BATADV_TP_CANT_SEND: failed to send via outgoing interface + * @BATADV_TP_TOO_MANY: too many ongoing sessions + */ +enum batadv_tp_meter_reason { + BATADV_TP_COMPLETE = 3, + BATADV_TP_SIGINT = 4, + /* error status >= 128 */ + BATADV_TP_DST_UNREACHABLE = 128, + BATADV_TP_RESEND_LIMIT = 129, + BATADV_TP_ALREADY_ONGOING = 130, + BATADV_TP_MEMORY_ERROR = 131, + BATADV_TP_CANT_SEND = 132, + BATADV_TP_TOO_MANY = 133, +}; + #define BATADV_RR_LEN 16 /** diff --git a/tcpdump.c b/tcpdump.c index e969d7d..bca140c 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -807,11 +807,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(); @@ -819,7 +822,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: @@ -840,6 +844,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, diff --git a/tp_meter.c b/tp_meter.c new file mode 100644 index 0000000..e935564 --- /dev/null +++ b/tp_meter.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2013-2016 B.A.T.M.A.N. contributors: + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "functions.h" +#include "packet.h" +#include "bat-hosts.h" +#include "debugfs.h" + +struct ether_addr *dst_mac; +int tp_fd = -1; + +void tp_sig_handler(int sig) +{ + int write_bytes; + struct batadv_icmp_user_packet icmp; + + switch (sig) { + case SIGINT: + case SIGTERM: + fflush(stdout); + memcpy(&icmp.dst, dst_mac, ETH_ALEN); + icmp.version = BATADV_COMPAT_VERSION; + icmp.cmd_type = BATADV_TP_STOP; + + write_bytes = write(tp_fd, &icmp, sizeof(icmp)); + if (write_bytes < 0) { + printf("sig_handler can't write to fd for %d, %s\n", + write_bytes, strerror(write_bytes)); + } + break; + default: + break; + } +} + +static void tp_meter_usage(void) +{ + fprintf(stderr, "Usage: batctl tp [parameters] \n"); + fprintf(stderr, "Parameters:\n"); + fprintf(stderr, "\t -t