FON2405E カスタムファーム

実家に転がっていた FON Simple(FON2405E)を貰ってきたのだが、 SoftBank の携帯からでしか、 Linus にはなれないようで、 MyPlace しか使えないらしい。
自分は、 FON_FREE_INTERNET を使うことが出来ないのに第三者にサービスするほどお人よしではないので、「鳴かぬなら殺してしまえ杜鵑」ということで、いろいろ調べてみると、やはり、ファームウェアを書き換えている人はいるようで、真似をしてみた。(→Hot Tuna Labs

シリアルコンソールを繋いで、ブートメッセージを見るまでは簡単に到達できたのだが、その次のステップの TFTP でファームを送り込む作業が大変だった。
基本的には、書いてあるとおりに作業を進めればよいのだが、 U-Boot で、 "2: Load system code then write to Flash via TFTP." を選択することが出来ず、普通に立ち上がってしまう。何度かリトライしているうちに、なぜかうまくいった。 どうやらリセットボタンを離すタイミングと、キーボードから "2" を入力するタイミングとの問題のようなのだが、「なぜかうまくいった」と書いたとおり残念ながら、どうするとうまくいくのかを説明することは出来ない。
ちなみに、リセットボタンと称しているのは、後ろのコネクタの並びにある FONWDS ボタンのことである。

なんとか、 TFTP 経由でカスタムファームに書き換え、起動するところまでは行ったのだが、 Radiko を聞いていると、10分ほどで通信が途切れてしまうと言う問題があることがわかった。こうなってしまうと、有線側からログインして、再起動するか、パワーサイクルを行ってコールドブートするしかない。

そんなこともあって、本当にオリジナルのカスタムファームを作ることにした。

そもそも、 FON Simple の中で走っているファームウェアは、 OpenWRT という Linux ベースのシステムであり、 CPU / Chipset 毎に用意されている Software Development Kit を入手して、クロスコンパイル環境を構築してしまえば、容易にカスタムファームを作ることが出来る。
そこで、 RoyalWindows を参考に、 Ubuntu10.04LTS で組んだ自宅の仮想サーバー群の開発用環境に クロスコンパイル環境を構築し、カスタムファームウェアを作製した。

基本的には、 RoyalWindows のサイトのとおりであるが、生の Ubuntu なので、通常アカウントでの作業になり、 tar 展開から、 sudo で作業を行わなければならないので注意する。( SDK が使う ./dev 以下のノードを作製するところで、特権が必要になるため、通常アカウントでは tar がエラーとなる。)私の使用環境では、 AP Client Mode / PPP 接続 / Firewall 機能 / 802.1q TagVLAN は不要なので削除し、 nslookup や netstat などのネットワークツールを導入している。 多くの機能を削ったために、イメージサイズは、1.6MBとかなり小さくなった。
Image Name: Linux Kernel Image
Created: Sat Mar 3 09:46:32 2012
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 1683310 Bytes = 1643.86 kB = 1.61 MB

出来上がったファームウェアは、 Hot Tuna Labs のカスタムファームウェアが適用されていれば WebUI からの書き換えが可能なので、書き換え自体は容易である。

さて、自分でビルドしたファームウェアを導入したところ、 10 分ほどでアクセスポイントが使えなくなってしまう現象は、発生しなくなった。ただ、 WPA2 の鍵の更新で手間取るのか、鍵の更新タイミングで 10 秒ほど通信断が生じてしまう。
 とりあえずは、定期的に再起動しなければならなかった状況からは大幅の進展なので、よしとする。

残作業としては、
 ・鍵の交換タイミングでの通信断の解消
 ・本体の状態表示用の LED が電源ランプ以外は機能していない問題の解消
である。

出来上がったカーネルのブートメッセージ
タイマーが 17179569.184000 から始まるのはご愛嬌

# dmesg
[17179569.184000] Linux version 2.6.21ASROC_Custom_Image_NoPPP_NoIPFilter_NoAPClient (root@bt) (gcc version 3.4.2) #17 Sat Mar 3 09:46:26 EST 2012
[17179569.184000]
[17179569.184000] The CPU feqenuce set to 320 MHz
[17179569.184000] CPU revision is: 0001964c
[17179569.184000] Determined physical RAM map:
[17179569.184000] memory: 02000000 @ 00000000 (usable)
[17179569.184000] Initrd not found or empty - disabling initrd
[17179569.184000] On node 0 totalpages: 8192
[17179569.184000] DMA zone: 64 pages used for memmap
[17179569.184000] DMA zone: 0 pages reserved
[17179569.184000] DMA zone: 8128 pages, LIFO batch:0
[17179569.184000] Normal zone: 0 pages used for memmap
[17179569.184000] Built 1 zonelists. Total pages: 8128
[17179569.184000] Kernel command line: console=ttyS1,57600n8 root=/dev/ram0
[17179569.184000] Primary instruction cache 32kB, physically tagged, 4-way, linesize 32 bytes.
[17179569.184000] Primary data cache 16kB, 4-way, linesize 32 bytes.
[17179569.184000] Synthesized TLB refill handler (20 instructions).
[17179569.184000] Synthesized TLB load handler fastpath (32 instructions).
[17179569.184000] Synthesized TLB store handler fastpath (32 instructions).
[17179569.184000] Synthesized TLB modify handler fastpath (31 instructions).
[17179569.184000] Cache parity protection disabled
[17179569.184000] cause = 800008, status = 1100ff00
[17179569.184000] PID hash table entries: 128 (order: 7, 512 bytes)
[17179569.184000] calculating r4koff... 00138800(1280000)
[17179569.184000] CPU frequency 320.00 MHz
[17179569.184000] Using 160.000 MHz high precision timer.
[17179569.188000] Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
[17179569.192000] Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
[17179569.200000] Memory: 28828k/32768k available (2371k kernel code, 3940k reserved, 297k data, 896k init, 0k highmem)
[17179569.204000] Calibrating delay loop... 212.99 BogoMIPS (lpj=425984)
[17179569.292000] Mount-cache hash table entries: 512
[17179569.296000] NET: Registered protocol family 16
[17179569.300000] NET: Registered protocol family 2
[17179569.304000] Time: MIPS clocksource has been installed.
[17179569.344000] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[17179569.348000] TCP established hash table entries: 1024 (order: 1, 8192 bytes)
[17179569.352000] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[17179569.356000] TCP: Hash tables configured (established 1024 bind 1024)
[17179569.360000] TCP reno registered
[17179569.376000] detected lzma initramfs
[17179569.380000] detected lzma initramfs
[17179569.384000] initramfs: LZMA lc=3,lp=0,pb=2,dictSize=1048576,origSize=3719168
[17179569.388000] LZMA initramfs by Ming-Ching Tiew .........................................................<6>squashfs: version 3.2-r2 (2007/01/15) Phillip Lougher
[17179570.928000] squashfs: LZMA suppport for slax.org by jro
[17179570.932000] io scheduler noop registered (default)
[17179570.936000] Ralink gpio driver initialized
[17179570.944000] HDLC line discipline: version $Revision: 1.1.1.1 $, maxframe=4096
[17179570.948000] N_HDLC line discipline registered.
[17179570.952000] Serial: 8250/16550 driver $Revision: 1.3 $ 2 ports, IRQ sharing disabled
[17179570.956000] serial8250: ttyS0 at I/O 0xb0000500 (irq = 37) is a 16550A
[17179570.960000] serial8250: ttyS1 at I/O 0xb0000c00 (irq = 12) is a 16550A
[17179570.964000] RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize
[17179570.968000] loop: loaded (max 8 devices)
[17179570.972000] rdm_major = 254
[17179570.984000]
[17179570.984000]
[17179570.984000] === pAd = c0000000, size = 495296 ===
[17179570.984000]
[17179570.988000] <-- RTMPAllocAdapterBlock, Status=0
[17179570.992000] block2mtd: version $Revision: 1.1.1.1 $
[17179570.996000] deice id : c2 20 15 c2 20 (2015c220)
[17179571.000000] mx25l3205d(c2 20160000) (4096 Kbytes)
[17179571.004000] mtd .name = raspi, .size = 0x00400000 (4M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
[17179571.008000] Creating 5 MTD partitions on "raspi":
[17179571.012000] 0x00000000-0x00400000 : "ALL"
[17179571.016000] 0x00000000-0x00010000 : "Bootloader"
[17179571.020000] 0x001f0000-0x00200000 : "Config"
[17179571.024000] 0x00010000-0x00020000 : "Factory"
[17179571.028000] 0x00020000-0x001f0000 : "Kernel"
[17179571.032000] TCP cubic registered
[17179571.036000] NET: Registered protocol family 1
[17179571.040000] NET: Registered protocol family 17
[17179571.044000] GDMA1_MAC_ADRH -- : 0x00000000
[17179571.048000] GDMA1_MAC_ADRL -- : 0x00000000
[17179571.052000] Ralink APSoC Ethernet Driver Initilization. v2.00 256 rx/tx descriptors allocated, mtu = 1500!
[17179571.056000] GDMA1_MAC_ADRH -- : 0x00000018
[17179571.060000] GDMA1_MAC_ADRL -- : 0x84f2a572
[17179571.064000] PROC INIT OK!
[17179571.084000] Freeing unused kernel memory: 896k freed
[17179571.104000] Algorithmics/MIPS FPU Emulator v1.5
[17179571.120000] devpts: called with bogus options
[17179572.916000]
[17179572.916000] phy_tx_ring = 0x01eb5000, tx_ring = 0xa1eb5000
[17179572.916000]
[17179572.916000] phy_rx_ring = 0x00000000, rx_ring = 0x00000000
[17179572.920000] RT305x_ESW: Link Status Changed
[17179572.924000] CDMA_CSG_CFG = 81000007
[17179572.928000] GDMA1_FWD_CFG = 710000
[17179577.256000] RX DESC a1ebb000 size = 2048
[17179577.264000] <-- RTMPAllocTxRxRingMemory, Status=0
[17179578.016000] Key1Str is Invalid key length(0) or Type(0)
[17179578.020000] Key2Str is Invalid key length(0) or Type(0)
[17179578.024000] Key3Str is Invalid key length(0) or Type(0)
[17179578.028000] Key4Str is Invalid key length(0) or Type(0)
[17179578.048000] 1. Phy Mode = 9
[17179578.052000] 2. Phy Mode = 9
[17179578.056000] 3. Phy Mode = 9
[17179578.060000] RTMPSetPhyMode: channel is out of range, use first channel=0
[17179578.064000] MCS Set = ff 00 00 00 00
[17179578.072000] SYNC - BBP R4 to 20MHz.l
[17179580.888000] Main bssid = 00:18:84:f2:a5:70
[17179580.892000] <==== rt28xx_init, Status=0
[17179580.896000] 0x1300 = 00064380
[17179581.184000] device ra0 entered promiscuous mode
[17179581.352000] device eth2 entered promiscuous mode
[17179582.332000] br0: port 2(eth2) entering learning state
[17179582.336000] br0: port 1(ra0) entering learning state
[17179582.940000] br0: port 2(eth2) entering disabled state
[17179582.944000] br0: port 1(ra0) entering disabled state
[17179582.956000] br0: port 2(eth2) entering learning state
[17179582.960000] br0: port 1(ra0) entering learning state
[17179584.884000] AP SETKEYS DONE - WPA2, AuthMode(7)=WPA2PSK, WepStatus(6)=AES, GroupWepStatus(4)=TKIP
[17179584.884000]
[17179588.888000] AP SETKEYS DONE - WPA2, AuthMode(7)=WPA2PSK, WepStatus(6)=AES, GroupWepStatus(4)=TKIP
[17179588.888000]
[17179597.960000] br0: topology change detected, propagating
[17179597.964000] br0: port 2(eth2) entering forwarding state
[17179597.968000] br0: topology change detected, propagating
[17179597.972000] br0: port 1(ra0) entering forwarding state

Gluster Bug

一晩、昨日の午後から Gluster の性能評価を始めていたが、今朝来てみると、評価プログラムが止まっていた。

Write to /gfs/write-test/sp8testee: standard output: No space left on device
tee: write error

測定値の書出しに失敗している
なぜ?!

取りあえず、df を取ってみる
% df
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 20G 19G 0 100% /
udev 3.9G 4.0K 3.9G 1% /dev
tmpfs 1.6G 268K 1.6G 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 4.0G 239M 3.7G 6% /run/shm
/dev/sdb1 1.9T 13G 1.9T 1% /gluster-partial
node1:/gfs 3.7T 35G 3.7T 1% /gfs

きっとログが溢れてるなということで、 /var/log を見てみると、 gluster.log が 17GB と大爆発している。

ログを見てみると、同じエラーが繰り返されている。
[2012-02-22 06:25:05.67891] E [iobuf.c:526:iobuf_ref] (-->/usr/lib/glusterfs/3.2.1/rpc-transport/rdma.so(rdma_recv_reply+0xe2) [0x7f5d48636612] (-->/usr/lib/glusterfs/3.2.1/rpc-transport/rdma.so(rdma_pollin_notify+0x71) [0x7f5d48636341] (-->/usr/lib/libgfrpc.so.0(rpc_transport_pollin_alloc+0x83) [0x7f5d4cd51a73]))) 0-iobuf: invalid argument: iobuf

Google先生に聞いてみると、どうやら Gluster 3.2.0 で RDMA を使う時のバグらしい。

http://gluster.org/pipermail/gluster-users/2011-April/007416.html
でも、このスレッドには、 3.2.1 で修正されるとあるが、直ってないし。

ただ、iobuf_ref()関数がヌル値で呼び出されたことによるとあるので、致命的な問題ではないのかな…

データのベリファイをしてみるかな・・・

ディスク単体の性能評価

まずはじめに、リファレンスデータとしてディスク単体の性能測定の結果。


1MBのファイルを100回作成することを255サイクル繰り返した結果。ディスクコントローラー上のキャッシュが利いているためか、1GB/sec近辺にピークがシフトしている。



2MBのファイルを100回作成することを255サイクル繰り返した結果。まだディスクコントローラー上のキャッシュの影響が残っているせいか、1GB/sec近辺になだらかな山が残っている。



4MBのファイルを100回作成することを255サイクル繰り返した結果。



8MBのファイルを100回作成することを255サイクル繰り返した結果。


16MBのファイルを100回作成することを255サイクル繰り返した結果。


32MBのファイルを100回作成することを255サイクル繰り返した結果。


64MBのファイルを100回作成することを255サイクル繰り返した結果。


128MBのファイルを100回作成することを255サイクル繰り返した結果。


256MBのファイルを100回作成することを255サイクル繰り返した結果。


512MBのファイルを100回作成することを255サイクル繰り返した結果。


1GBのファイルを100回作成することを255サイクル繰り返した結果。

ディスク性能チェックスクリプト

ディスク性能試験は、1ファイルサイズあたり100ファイルの生成を255回繰り返す方法としている。

スクリプトは下記の通り。

スクリプトの概要は、/dev/urandom より乱数ファイルをメモリディスク上に生成し、それを読みだして書込みデータとしている。また、同じ内容のファイルとならないように、書込み毎に読出し開始位置をずらしている。

スクリプトの引数は、6つあり、順番に
・容量(MB)
・書出しファイル名
・書出しパス
・ログ識別名
・開始サイクル数
・データ識別
となっている。ログ識別名、データ識別名は何でもよい。


#!/bin/tcsh
echo "target:$6"
set x=$5
set n=1
mkdir -p ~/PerfomanceTest/$4/$6/$2

if ( ! -d ${3} ) then
mkdir -p ${3}
endif

if ( ! -d ${3}/${2} ) then
mkdir -p ${3}/${2}
endif

@ seedsz = $1 + 110
echo $seedsz
set suffix = `echo $3 | awk -F '/' '{print $(NF)}'`
dd if=/dev/urandom of=/dev/shm/seed.dat bs=1M count=$seedsz
echo "Make Seed data finished"

loop:
loop2:
set fn = `printf "%.3d" $n`
set period = `printf "%.3d" $x`
echo -n "Write to $3/$2/$fn.dat Size $2 ${x}th Period ( $n / 100 ) "
dd if=/dev/shm/seed.dat of=$3/$2/$fn.dat bs=1M count=$1 skip=$n |& grep copi | awk '{print $1,$6,$8}' | tee -a ~/PerfomanceTest/$4/$6/$2/$period.log

@ n ++
if ($n < 100) then
goto loop2
endif

set n=1
@ x ++
if ($x > 255) then
exit
else
goto loop
endif

Gluster の設定

前提条件
 PC:Dell PowerEdge R310 を4台使用
CPU:X3470
MEM:PC10400 RDIMM 8GB
HDD:SATA 7.2krpm 2TB × 2 (システム用とGluster用)
IBHCA:MHQH29B-XTR (Port1:Infiniband QDR Port2:10G Ethernet

・IB系と10G系と2つの閉じたネットワークを構築
  IB系 172.22.0.0/24
10G系 172.22.1.0/24
 このほかに管理用としてオンボード1G NICを生活線に接続

/etc/hosts には、
IB系 ibnode1 〜 ibnode4
10G系 node1 〜 node4
 をそれぞれ記載した。

 HDD2台のうち1台を XFS でフォーマットし、 /gluster-partial にマウントしている

1) Glusetr のバージョンチェック
同時期に apt でインストールしているので、バージョンの不一致はない筈であるが念のため確認しておく

% gluster -V
glusterfs 3.2.1 built on Jun 28 2011 07:43:58
Repository revision: v3.2.1
Copyright (c) 2006-2010 Gluster Inc. http://www.gluster.com
GlusterFS comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of GlusterFS under the terms of the GNU Affero General Public License.


2) GlusterFS に参加する、操作端末以外のノードを認識させる

% sudo gluster peer probe ibnode2
Probe successful
% sudo gluster peer probe ibnode3
Probe successful
% sudo gluster peer probe ibnode4
Probe successful


認識状況の確認

% sudo gluster peer status
Number of Peers: 3

Hostname: ibnode2
Uuid: ffa446a4-217e-4bc2-bb7e-07a989065fba
State: Peer in Cluster (Connected)

Hostname: ibnode3
Uuid: f42a65cf-cdae-4f38-91af-df2c3a7c3d2e
State: Peer in Cluster (Connected)

Hostname: ibnode4
Uuid: 30580991-0aaa-4c0a-ad1d-c2bf8de83cd8
State: Peer in Cluster (Connected)


★認識済みのノードを、削除する場合

% sudo gluster peer detach node#
Detach successful


3) GlusterFS の構築
ここでは、4台のノードを使用して x2 の冗長性を持った GlusterFS を作成する。ノード間の転送経路は RDMA を使用する。
注意点は、 "gluster peer status" で、 "Hostname: " に記載されているホスト名を記載する必要がある。

% sudo gluster volume create gfs replica 2 transport rdma ibnode1:/gluster-partial ibnode2:/gluster-prtial ibnode3:/gluster-partial ibnode4:/gluster-partial
Creation of volume gfs has been successful. Please start the volume to access data.


作成されたボリュームの確認

% sudo /usr/sbin/gluster volume info all

Volume Name: gfs
Type: Distributed-Replicate
Status: Created
Number of Bricks: 2 x 2 = 4
Transport-type: rdma
Bricks:
Brick1: ibnode1:/gluster-partial
Brick2: ibnode2:/gluster-partial
Brick3: ibnode3:/gluster-partial
Brick4: ibnode4:/gluster-partial


作成されたボリュームを有効にする

% sudo gluster volume start gfs
Starting volume gfs has been successful


有効になったボリュームを、ローカルマウントする

% sudo mount -t glusterfs -o log-level=WARNING,log-file=/var/log/gluster.log node1:/gfs /gfs

この状態で、 "df" を取っても "df: `/gfs': Transport endpoint is not connected" と怒られてしまう。
一旦 "/gfs" に何らかのアクセスを実行するとエラーは出なくなる。

とりあえず、100MBのファイルを書き込んでみる

% cd /gfs
% dd if=/dev/zero of=100M bs=1M count=1
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.595028 s, 176 MB/s

もう一度 "df" を取ってみると
% df
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 20G 2.6G 17G 14% /
udev 3.9G 4.0K 3.9G 1% /dev
tmpfs 1.6G 268K 1.6G 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 4.0G 115M 3.8G 3% /run/shm
/dev/sdb1 1.9T 478M 1.9T 1% /gluster-partial
node1:/gfs 3.7T 11G 3.7T 1% /gfs

めでたく /gfs が見えました。 容量は、1.9TB×4 で x2 の冗長性なので 3.7TBと出ている


とりあえず、これで一通りのパフォーマンス測定を行なうことにする。

Gluster のインストール

基本的には、apt でインストールするだけなので簡単

いつものおまじない
# sudo apt-get update

まず、RDMAを有効にするためにライブラリとツールのインストール
# sudo apt-get install librdmacm1 rdmacm-utils

グラスター本体のインストール
# sudo apt-get install glusterfs-server glusterfs-examples glusterfs-common glusterfs-client

Glusetrの基本ディスク領域をXFSでフォーマットしたかったので、XFS関係のインストール
# sudo apt-get install xfsprogs

ConnectX-2のPort2の動作モード変更(ib→eth)と衝突するので、スタートアップスクリプトからGluster-Serverの起動を外す
# sudo update-rc.d -f glusterfs-server remove

シャットダウン時には、Guluster-Server を落とさなければならないので
# sudo ln -s /etc/init.d/glusterfs-server /etc/rc0.d/K20glusterfs-server
# sudo ln -s /etc/init.d/glusterfs-server /etc/rc1.d/K20glusterfs-server
# sudo ln -s /etc/init.d/glusterfs-server /etc/rc6.d/K20glusterfs-server

起動スクリプトの一番最後でGluster-Serverを起動させるため、/etc/rc.localに
/etc/init.d/glusterfs-server start
を記述する。

あとは、Glusterで使用するファイルシステムを作成し、マウントすれば準備完了となる。

これで、基本的なセットアップはおしまい。