文章目录
iperf
介绍
iperf是一个网络性能测试工具。
一些生产硬件的公司在产品出厂前会做厂测,对网络性能指标有合格标准的,就会用iperf来测试设备的吞吐量。
我工作遇到了问题,需要debug用iperf不同版本验证下,但iperf官网上没有提供对应系统上的版本,就需要自己编译下,顺便记录下来
源码下载
iperf官网https://iperf.fr/iperf-download.php#source已经提供了不同版本的源码,往下翻就可以看到,免费下载,我现在能看到的iperf2最新版本是2.0.9
使用方法
测试吞吐量,就需要有一个收发数据的过程,对应的需要有服务端和客户端,所幸iperf足够强大,服务端和客户端的功能都集成在一起
测试时,在不同机子上输入以下命令,先开启服务端,再开启客户端
$ iperf -s #服务端
$ iperf -c IP -i1 -t10 #客户端
例
服务端 Android 板子
console:/ # iperf-s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 171 KByte (default)
------------------------------------------------------------
[ 4] local 192.168.1.242 port 5001 connected with 192.168.1.110 port 50231
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.1 sec 19.9 MBytes 16.5 Mbits/sec
客户端 windows PC
C:\iperf> iperf -c 192.168.1.242 -i1 -t10
------------------------------------------------------------
Client connecting to 192.168.1.242, TCP port 5001
TCP window size: 64.0 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.1.110 port 50231 connected with 192.168.1.242 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0- 1.0 sec 1.88 MBytes 15.7 Mbits/sec
[ 3] 1.0- 2.0 sec 1.12 MBytes 9.44 Mbits/sec
[ 3] 2.0- 3.0 sec 2.25 MBytes 18.9 Mbits/sec
[ 3] 3.0- 4.0 sec 2.38 MBytes 19.9 Mbits/sec
[ 3] 4.0- 5.0 sec 1.00 MBytes 8.39 Mbits/sec
[ 3] 5.0- 6.0 sec 2.25 MBytes 18.9 Mbits/sec
[ 3] 6.0- 7.0 sec 2.62 MBytes 22.0 Mbits/sec
[ 3] 7.0- 8.0 sec 2.50 MBytes 21.0 Mbits/sec
[ 3] 8.0- 9.0 sec 1.88 MBytes 15.7 Mbits/sec
[ 3] 9.0-10.0 sec 1.88 MBytes 15.7 Mbits/sec
[ 3] 0.0-10.1 sec 19.9 MBytes 16.5 Mbits/sec
那么问题来了,怎么用iperf测试板子的上行速率?板子是作为客户端还是服务端?
一开始我以为是数据流应该是从服务端流向客户端,那这样板子测试上行就应该是作为服务端。但是,事实恰恰相反,iperf客户端才是作为发数据的一端,板子测试上行就需要作为客户端。
如何验证?抓包。
通过抓包,你就可以看到client端发送的数据包里data段有一大堆数据,而server端的应答包data段长度为0。
还不信就上官网,这是iperf2的用户文档https://iperf.fr/iperf-doc.php#doc ,可以看到关于client端的描述用了“send”一词,而server则没有。
貌似我公司上下行一直以来都测反了=.=
Clinet Specification
Command line optionEnvironment variable optionDescription-b, --bandwidth #[KM]$IPERF_BANDWIDTHThe UDP bandwidth to send at, in bits/sec. This implies the -u option. Default is 1 Mbit/sec.-n, --num #[KM]$IPERF_NUMThe number of buffers to transmit. Normally, iPerf sends for 10 seconds. The -n option overrides this and sends an array of len bytes num times, no matter how long that takes. See also the -l and -t options.-t, --time #$IPERF_TIMEThe time in seconds to transmit for. iPerf normally works by repeatedly sending an array of len bytes for time seconds. Default is 10 seconds. See also the -l and -n options.-r, --tradeoff$IPERF_TRADEOFFRun iPerf in tradeoff testing mode. This will cause the server to connect back to the client on the port specified in the -L option (or defaults to the port the client connected to the server on). This is done following the client connection termination, therefore running the tests alternating. If you want an simultaneous test try -d.
看下上面表格最后一行,-r参数
使用该参数会令服务端在客户端断开连接后连接客户端,也就是说进行了一次反转,客户端变成服务端,服务端变成客户端。这样,板子一开始作为客户端测试完上行,在反转后就能接着测试下行,完成吞吐量的测试。反转后连接的端口取决于-L参数指定的端口,如果没有指定该参数,则为一开始服务端的端口(默认5001)。而如果你想同时测试上下行,可以使用-d参数。
交叉编译
环境搭建
如果你只需要64位的就很简单,直接编译就行了。由于iperf官方没有提供linux 32位的版本,需要交叉编译,得下载交叉编译链,不同目标平台可能不同。
我用的是公司的服务器,已经搭建好环境了,部分配置如下:
- arm-linux-gnueabihf-gcc 6.3.1
- arm-linux-gnueabihf-g++ 6.3.1
- aclocal 1.16.1
- automake 1.16.1
这样不用自己去下载东西了,看起来方便,但这也有弊端,后面会讲。
iperf2.0.9
iperf2.0.9较为简单,先用iperf提供的脚本configure配置下
$ ./configure --host=arm CC=arm-linux-gnueabihf-gcc CFLAGS=-static CXX=arm-linux-gnueabihf-g++ CXXFLAGS=-static
这里 - - host 设置目标平台为arm,CC 和 CXX 设置交叉编译器,CFLAGS 和 CXXFLAGS设置静态编译。静态编译就只有一个文件,管理比较方便,默认是动态编译。我看了其他博文,有些设置静态编译的命令不一样,是
$ ./configure --host... --enable-static #省略了部分参数
配置好后输入make开始编译
编译结果可以在src目录里看到,使用file命令可以看到是32bit, static linked的
$ file src/iperf
src/iperf: ELF 32-bit LSB executable, ARM, EABI5 version 1(GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=0b62ec7b41ee3febfe5eaf835aed1a7ae0aa4bf2, with debug_info, not stripped
接下来用adb或者U盘推到板子里就行了,如果没有执行权限用chmod +x iperf
iperf2.0.8
自iperf2.0.8到2.0.6(其他的没试过)编译make就会出错,出错点还不同,2.0.8的错误是这样的
In file included from /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/6.3.1/cmath:42:0,
from /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/6.3.1/math.h:36,
from ../include/headers.h:85,
from ../include/Timestamp.hpp:63,
from delay.cpp:55:
/opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/6.3.1/bits/cpp_type_traits.h:205:12: error: redefinition of ‘struct std::__is_integer<int>’
struct __is_integer<int>
^~~~~~~~~~~~~~~~~
/opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/6.3.1/bits/cpp_type_traits.h:138:12: error: previous definition of ‘struct std::__is_integer<int>’
struct __is_integer<bool>
^~~~~~~~~~~~~~~~~~
make[2]: *** [Makefile:406: delay.o] Error 1
看了这篇博文https://blog.csdn.net/feitingfj/article/details/106923384尾部的链接提的issue看不太懂,好像是说编译器更新了,GCC6以上的就会出错???
放弃直接看log,这里大概是说重定义了个结构体,一个是bool类型一个是int,这是因为C早期没有bool类型,C11才有,而这之前开发者使用int来代替的,如下
#defineboolint
所以struct __is_integer<bool>其实就是struct __is_integer<int>,才会报这个错,而后面gcc更新了,我推测应该也有bool类型了,干脆上面这条宏注释掉试试,结果编译通过了。
至于为什么以前编译不会报错?这个就搞不懂了
具体步骤:
先make下,报错了,输入以下grep命令递归查找当前目录所有文件是否包含该宏
$ grep -r "#define bool int" ./
./config.log:|#define bool int
./config.log:|#define bool int
./config.log:|#define bool int
./config.log:|#define bool int
./config.log:|#define bool int
./config.log:|#define bool int
./config.log:#define bool int
./configure: $as_echo"#define bool int">>confdefs.h
./config.h:#define bool int
可以看到configure文件和config.h文件里有相关定义,将其注释掉即可,然后重新编译make
configure修改为
$as_echo"//#define bool int">>confdefs.h
config,h修改为
// #define bool int
iperf2.0.7
2.0.7出错如下
In file included from /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/6.3.1/stdlib.h:36:0,
from ../include/headers.h:78,
from ../include/Timestamp.hpp:63,
from delay.cpp:53:
/opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/6.3.1/cstdlib:146:11: error: ‘::malloc’ has not been declared
using ::malloc;
^~~~~~
In file included from ../include/headers.h:78:0,
from ../include/Timestamp.hpp:63,
from delay.cpp:53:
/opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/c++/6.3.1/stdlib.h:65:12: error: ‘std::malloc’ has not been declared
using std::malloc;
^~~~~~
make[2]: *** [Makefile:301: delay.o] Error 1
参考这篇博文https://www.cnblogs.com/gaowengang/p/12631924.html,需要修改./configure.ac文件,
AC_FUNC_MALLOC
注释掉,修改为
# AC_FUNC_MALLOC
这个AC_FUNC_MALLOC是一个测试,应该是检查环境是否有该功能,但是由于xx原因,总之,把它注释掉就可以了,继续make,会遇到2.0.8的问题,同样解决就行
iperf2.0.6
iperf2.0.6会遇到以下问题
$ makecd.&& aclocal-1.9
/bin/sh: aclocal-1.9: command not found
make: *** [Makefile:225: aclocal.m4] Error 127
$ makecd.&& automake-1.9 --foreign
/bin/sh: line 4: automake-1.9: command not found
make: *** [Makefile:196: Makefile.in] Error 1
这个是版本不一致导致的,aclocal和automake是两个工具,如果没有的话要安装。正如我前面所讲的,用的是公司的编译服务器,这工具已经下好了,但是版本太低
$ aclocal --version #查看aclocal版本
aclocal (GNU automake)1.16.1
Copyright (C)2018 Free Software Foundation, Inc.
License GPLv2+: GNU GPL version 2 or later <https://gnu.org/licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Tom Tromey <[email protected]>
and Alexandre Duret-Lutz <[email protected]>.
$ automake --version #查看automake版本
automake (GNU automake)1.16.1
Copyright (C)2018 Free Software Foundation, Inc.
License GPLv2+: GNU GPL version 2 or later <https://gnu.org/licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Tom Tromey <[email protected]>
and Alexandre Duret-Lutz <[email protected]>.
可以看到两个的版本才1.16,编译要用的是1.9。
那怎么办?这不是我的电脑,不能随便下载东西。弊端就体现出来了。
既然不能改环境,改代码总可以吧
打开./aclocal.m4,将这两行的版本1.9改成自己的版本1.16.1
#aclocal 版本
AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.16.1"])#automake 版本
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.1])])
改完重新执行配置命令./configure --host…,再make,会遇到2.0.7和2.0.8相同的问题,同样解决即可。
需要注意的是有些文件需要make后才会出现,像config.h就是这样,一开始找不到,make了才有,才能修改代码。
版权归原作者 参考demo 所有, 如有侵权,请联系我们删除。