ネットワークスループットを測定するためのツール「iperf」は有名なツールなのですが、GooglePlayで無料で公開されているAndroid向けのiperfは残念ながら最新のバージョン3系ではなくバージョン2系です。現在最新版であるバージョン3は有料版しかないので、自力でビルドしてみました。
なお、今回試したiperf3のバージョンは「3.0.11」になります。新しいバージョンの場合は手順が異なる可能性があるのでご注意下さい。
1.ビルド環境
- Ubuntu 14.04.01 LTS Server(x86_64)
- Android NDK Revision 10d
今回はUbuntu上にクロスコンパイルする環境を構築します。
Download Ubuntu Server
Android NDK
2.ビルド環境構築
OSインストール
今回はVirtualBOX上にインストールしました。iperf3だけのビルドなので、VMの設定はメモリ512MBのデフォルトで問題ありません。また、インストール中に選択可能なパッケージ時もSSHしか選択していません。
NDKインストール
NDKをダウンロードしインストールします。
$ pwd /home/osa $ wget http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin $ chmod +x android-ndk-r10d-linux-x86_64.bin $ ./android-ndk-r10d-linux-x86_64.bin $ ./android-ndk-r10d/build/tools/make-standalone-toolchain.sh --platform=android-19 --arch=arm --install-dir=./android-ndk $ ls -F android-ndk arm-linux-androideabi/ COPYING include/ lib64/ share/ sysroot/ bin/ COPYING.LIB lib/ libexec/ SOURCES $ sudo apt-get install build-essential git
ここではユーザのホームディレクトリ上に展開していますが特にどこでも問題ありません。なお、今回のターゲットは、Android 4.4のARMアーキテクチャになるのでそのような指定でツールチェインを生成します。
3.ビルド
iPerf3のソースはgithubで公開されています。
iperf3: A TCP, UDP, and SCTP network bandwidth measurement tool
なお、以下はiperf2という古いバージョンなので注意しましょう。
Iperf – The TCP/UDP Bandwidth Measurement Tool
リポジトリ取得
$ pwd /home/osa $ git clone https://github.com/esnet/iperf
任意の場所にiperf3のリポジトリをクローンします。
Makefile生成
$ cd iperf/ $ export PATH=/home/osa/android-ndk/bin:$PATH $ ./configure --host=arm-linux CC=arm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ CFLAGS=-static CXXFLAGS=-static
クロスコンパイル用のオプションを指定してMakefileを生成します。
ソース変更
このままだと、コンパイルが通らなかったり、実機での動作で問題がでるので一部ソースとMakefileを修正します。
$ vi src/net.c
ヘッダのパスが通常のLinuxと一部異なるので修正します。
--- net.c 2015-04-20 14:34:34.610766731 +0900 +++ net.c.org 2015-04-20 14:34:21.050766682 +0900 @@ -37,7 +37,7 @@ #include <assert.h> #include <netdb.h> #include <string.h> -#include <fcntl.h> +#include <sys/fcntl.h> #ifdef HAVE_SENDFILE #ifdef linux
$ vi src/iperf_api.c
一時ファイル作成場所がLinuxとAndroidで異なるので修正します。これを修正しなくてもコンパイルは通りますが実機で動作しないので修正しておきます。
--- iperf_api.c 2015-04-20 14:39:40.682767820 +0900 +++ iperf_api.c.org 2015-04-20 14:39:25.010767765 +0900 @@ -2570,7 +2570,7 @@ { int i; struct iperf_stream *sp; - char template[] = "/data/local/tmp/iperf3.XXXXXX"; + char template[] = "/tmp/iperf3.XXXXXX"; h_errno = 0;
$ vi src/Makefile
gprofのオプションが有効だとNDKではエラーになるようなので外しておきます。
--- Makefile 2015-04-20 14:45:35.246769083 +0900 +++ Makefile.org 2015-04-20 14:45:25.982769050 +0900 @@ -596,9 +596,9 @@ iperf3_profile_SOURCES = main.c \ $(libiperf_la_SOURCES) -iperf3_profile_CFLAGS = -g +iperf3_profile_CFLAGS = -pg -g iperf3_profile_LDADD = libiperf.la -iperf3_profile_LDFLAGS = -g +iperf3_profile_LDFLAGS = -pg -g # Specify the sources and various flags for the test cases t_timer_SOURCES = t_timer.c
4.ビルド
ようやくビルド実行です。
$ make Making all in src (snip) Making all in examples make[1]: Entering directory `/home/osa/iperf/examples' arm-linux-androideabi-gcc -DHAVE_CONFIG_H -I. -I../src -g -static -Wall -MT mic-mic.o -MD -MP -MF .deps/mic-mic.Tpo -c -o mic-mic.o `test -f 'mic.c' || echo './'`mic.c mic.c:7:22: fatal error: sysexits.h: No such file or directory #include <sysexits.h> ^ compilation terminated. make[1]: *** [mic-mic.o] Error 1 make[1]: Leaving directory `/home/osa/iperf/examples' make: *** [all-recursive] Error 1
iperf3は、別のプログラムから利用可能な形で設計されており、APIとして利用するサンプルのビルドで失敗します。が、以下のバイナリが生成されていればビルドは成功しているので無視します。
$ file src/iperf3 src/iperf3: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
5.インストール
転送
できあがったiperf3を実機に転送します。
$ adb push iperf3 //data/local/tmp/.
インストール
$ adb shell shell@SO-02G:/ $ chmod 755 /data/local/tmp/iperf3 shell@SO-02G:/ $ shell@SO-02G:/ $ /data/local/tmp/iperf3 -h /data/local/tmp/iperf3 -h Usage: iperf [-s|-c host] [options] iperf [-h|--help] [-v|--version] (snip) [KMG] indicates options that support a K/M/G suffix for kilo-, mega-, or giga- iperf3 homepage at: http://software.es.net/iperf/ Report bugs to: https://github.com/esnet/iperf
とりあえず/data/local/tmpに配置していますが、root権限なしでも実行できる場所であればどこでも問題ありません。
6.動作確認
いよいよ動作確認です。測定には対向側のサーバが必要になります。今回はUbuntu上でUbuntu用にビルドしたiperf3を起動します。Ubuntu用にビルドする場合は、ソース修正は不要なので別ディレクトリ名で以下の手順で行いましょう。
$ git clone https://github.com/esnet/iperf $ cd iperf/ $ ./configure $ make $ sudo make install $ sudo ldconfig
サーバ(192.168.1.xxx)
$ iperf3 -s ----------------------------------------------------------- Server listening on 5201 -----------------------------------------------------------
クライアント側を起動する前に実行しておきます。
クライアント(192.168.1.yy)
まずはクライアントからサーバへのアップリンクです。
shell@SO-02G:/ $ /data/local/tmp/iperf3 -c 192.168.1.xxx /data/local/tmp/iperf3 -c 192.168.1.xxx Connecting to host 192.168.1.xxx, port 5201 [ 4] local 192.168.1.yy port 38518 connected to 192.168.1.xxx port 5201 [ ID] Interval Transfer Bandwidth [ 4] 0.00-1.00 sec 9.33 MBytes 78.3 Mbits/sec [ 4] 1.00-2.00 sec 5.88 MBytes 49.3 Mbits/sec [ 4] 2.00-3.00 sec 3.97 MBytes 33.3 Mbits/sec [ 4] 3.00-4.00 sec 3.73 MBytes 31.3 Mbits/sec [ 4] 4.00-5.00 sec 4.64 MBytes 38.9 Mbits/sec [ 4] 5.00-6.00 sec 3.10 MBytes 26.0 Mbits/sec [ 4] 6.00-7.00 sec 3.57 MBytes 30.0 Mbits/sec [ 4] 7.00-8.00 sec 3.48 MBytes 29.2 Mbits/sec [ 4] 8.00-9.00 sec 3.33 MBytes 28.0 Mbits/sec [ 4] 9.00-10.02 sec 3.81 MBytes 31.4 Mbits/sec - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth [ 4] 0.00-10.02 sec 44.8 MBytes 37.5 Mbits/sec sender [ 4] 0.00-10.02 sec 44.8 MBytes 37.5 Mbits/sec receiver iperf Done.
続いてはサーバからクライアントへのダウンリンクです。実はこれがやりたかったのでiperf3をわざわざビルドしたのです。
shell@SO-02G:/ $ /data/local/tmp/iperf3 -c 192.168.1.xxx -R /data/local/tmp/iperf3 -c 192.168.1.xxx -R Connecting to host 192.168.1.xxx, port 5201 Reverse mode, remote host 192.168.1.xxx is sending [ 4] local 192.168.1.yy port 38520 connected to 192.168.1.xxx port 5201 [ ID] Interval Transfer Bandwidth [ 4] 0.00-1.00 sec 6.33 MBytes 53.1 Mbits/sec [ 4] 1.00-2.00 sec 8.07 MBytes 67.7 Mbits/sec [ 4] 2.00-3.00 sec 7.47 MBytes 62.7 Mbits/sec [ 4] 3.00-4.00 sec 7.80 MBytes 65.5 Mbits/sec [ 4] 4.00-5.00 sec 8.01 MBytes 67.2 Mbits/sec [ 4] 5.00-6.00 sec 7.77 MBytes 65.2 Mbits/sec [ 4] 6.00-7.00 sec 7.63 MBytes 64.1 Mbits/sec [ 4] 7.00-8.00 sec 7.82 MBytes 65.6 Mbits/sec [ 4] 8.00-9.00 sec 7.36 MBytes 61.7 Mbits/sec [ 4] 9.00-10.00 sec 7.59 MBytes 63.7 Mbits/sec - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 79.0 MBytes 66.3 Mbits/sec 38 sender [ 4] 0.00-10.00 sec 76.6 MBytes 64.3 Mbits/sec receiver iperf Done.
アップリンクとダウンリンクで測定したスループットが異なるのが確認できました。あとは誰かがGUIを作ってくれたらAndroidでも快適にiperf3が使えますね。