为J6+Linux交叉编译iperf
$ tar xf iperf-2.0.5-source.tar.gz
$ cd iperf-2.0.5/
$ ./configure --host=arm-linux-gnueabihf
$ make
$ file src/iperf
src/iperf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=a2333230f5d705001c88e718e376de1b7b6cc694, not stripped
修改:在configure步骤自动生成的config.h会用rpl_malloc代替malloc,这会导致编译失败,注释掉即可。原文如下:
/* Define to rpl_malloc if the replacement function should be used. */
#define malloc rpl_malloc
为高通820+Android交叉编译iperf
上述过程编译出的iperf在高通820+Android平台上跑不起来,报No such file
;猜测原因应该是字长不同,820是64位,而编译出的iperf是32位的。
下面是直接把iperf源码解压到Android源码树的external
目录下编译。
首先需要写Android.mk,如下:
$ cd external/iperf-2.0.5/
$ cat Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -DHAVE_CONFIG_H
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := iperf
LOCAL_SRC_FILES := \
src/Client.cpp \
src/Extractor.c \
src/gnu_getopt.c \
src/gnu_getopt_long.c \
src/Launch.cpp \
src/List.cpp \
src/Listener.cpp \
src/Locale.c \
src/main.cpp \
src/PerfSocket.cpp \
src/ReportCSV.c \
src/ReportDefault.c \
src/Reporter.c \
src/Server.cpp \
src/service.c \
src/Settings.cpp \
src/SocketAddr.c \
src/sockets.c \
src/stdio.c \
src/tcp_window_size.c \
compat/delay.cpp \
compat/error.c \
compat/gettimeofday.c \
compat/inet_ntop.c \
compat/inet_pton.c \
compat/signal.c \
compat/snprintf.c \
compat/string.c \
compat/Thread.c
include $(BUILD_EXECUTABLE)
编译过程如下:
$ mmm external/iperf-2.0.5/
$ $ file out/target/product/XX/system/bin/iperf
out/target/product/XX/system/bin/iperf: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /system/bin/linker64, BuildID[md5/uuid]=90a6586fc1e850c20a6521e0e0011886, stripped
在编译过程中遇到多个问题:
1. fatal error: 'config.h' file not found
2. fatal error: 'iperf-int.h' file not found
把上一步生成的config.h和iperf-int.h拷贝到这里即可
3. error: format string is not a string literal (potentially insecure) [-Werror,-Wformat-security]
这是因为printf或fprintf等函数的传参不严格,没有加format(如%s)参数
4. error: redefinition of '__libcpp_is_integral<int>'
external/libcxx/include/type_traits:694:29: error: redefinition of '__libcpp_is_integral<int>'
template <> struct __libcpp_is_integral<int> : public true_type {};
^~~~~~~~~~~~~~~~~~~~~~~~~
external/libcxx/include/type_traits:683:29: note: previous definition is here
template <> struct __libcpp_is_integral<bool> : public true_type {};
这是因为在config.h里面有#define bool int
,即用int代替bool。
由于C99标准已经支持bool类型,只需include <stdbool.h>
即可,同时注释掉config.h里的那句话。
同样也遇到rpl_malloc的问题,也是注释掉即可。
注:移植到Android平台的iperf源码已上传到Github,二进制可执行文件已上传到CSDN,欢迎下载。
测试情况
J6侧:
root@dra7xx-g5-r1:/# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 192.168.85.2 port 5001 connected with 192.168.85.1 port 44160
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 215 MBytes 180 Mbits/sec
820侧:
# iperf -c 192.168.85.2
------------------------------------------------------------
Client connecting to 192.168.85.2, TCP port 5001
TCP window size: 1.00 MByte (default)
------------------------------------------------------------
[ 3] local 192.168.85.1 port 44160 connected with 192.168.85.2 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 215 MBytes 181 Mbits/sec
注意:iperf可进行多线程的并发测试,默认的情况下它只执行一个线程。在带宽很大的情况下,单线程无法达到带宽的最大上限,这样导致iperf测出的带宽值偏小。这种情况下,需要跑多线程进行压力测试,才能测到真正的上限。
多线程情况下的速度:
# iperf -c 192.168.85.2 -P 10
------------------------------------------------------------
Client connecting to 192.168.85.2, TCP port 5001
TCP window size: 1.00 MByte (default)
------------------------------------------------------------
[ 11] local 192.168.85.1 port 44180 connected with 192.168.85.2 port 5001
[ 13] local 192.168.85.1 port 44178 connected with 192.168.85.2 port 5001
[ 3] local 192.168.85.1 port 44163 connected with 192.168.85.2 port 5001
[ 5] local 192.168.85.1 port 44162 connected with 192.168.85.2 port 5001
[ 4] local 192.168.85.1 port 44166 connected with 192.168.85.2 port 5001
[ 6] local 192.168.85.1 port 44168 connected with 192.168.85.2 port 5001
[ 7] local 192.168.85.1 port 44170 connected with 192.168.85.2 port 5001
[ 9] local 192.168.85.1 port 44172 connected with 192.168.85.2 port 5001
[ 10] local 192.168.85.1 port 44176 connected with 192.168.85.2 port 5001
[ 8] local 192.168.85.1 port 44174 connected with 192.168.85.2 port 5001
[ ID] Interval Transfer Bandwidth
[ 5] 0.0-10.1 sec 30.1 MBytes 25.1 Mbits/sec
[ 11] 0.0-10.1 sec 29.8 MBytes 24.8 Mbits/sec
[ 13] 0.0-10.1 sec 17.8 MBytes 14.8 Mbits/sec
[ 10] 0.0-10.1 sec 26.2 MBytes 21.9 Mbits/sec
[ 3] 0.0-10.1 sec 21.4 MBytes 17.8 Mbits/sec
[ 6] 0.0-10.1 sec 28.6 MBytes 23.7 Mbits/sec
[ 9] 0.0-10.1 sec 25.6 MBytes 21.2 Mbits/sec
[ 8] 0.0-10.1 sec 29.0 MBytes 24.0 Mbits/sec
[ 4] 0.0-10.1 sec 29.0 MBytes 24.0 Mbits/sec
[ 7] 0.0-10.1 sec 23.2 MBytes 19.2 Mbits/sec
[SUM] 0.0-10.1 sec 261 MBytes 216 Mbits/sec
后记
上面是比较粗糙的测试,还可以通过调整包长、TCP窗口大小、MTU大小等参数来测得更精确的值。