草庐IT

iperf使用与交叉编译

参考demo 2023-04-04 原文

文章目录

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来代替的,如下

#define bool int

所以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会遇到以下问题

$ make
cd . && aclocal-1.9 
/bin/sh: aclocal-1.9: command not found
make: *** [Makefile:225: aclocal.m4] Error 127
$ make
 cd . && 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 <tromey@redhat.com>
       and Alexandre Duret-Lutz <adl@gnu.org>.

$ 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 <tromey@redhat.com>
       and Alexandre Duret-Lutz <adl@gnu.org>.

可以看到两个的版本才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了才有,才能修改代码。

有关iperf使用与交叉编译的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐