ARMアーキテクチャのAndroid向けにiperf3をビルドする

ネットワークスループットを測定するためのツール「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が使えますね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*