IEEE802.11sメッシュのはなし(2)
今回は実際にLinuxを使ってIEEE802.11sメッシュを動かしてみます。弊社製品BR-400ANについても少し言及します。
必要な機材
Linuxでは2.6.26(2008/7/13)からIEEE802.11sメッシュ機能がサポートされていますが、古い実装はバグだらけなので、少なくとも4.14以降を使うことをお勧めします。通信実験ですからLinuxマシンを少なくとも2台、マルチホップを試すなら3台以上が必要になります。カーネルバージョンやWi-Fiモジュールの品種は揃えた方が変なトラブルに悩まずに済みます。
はじめに確認
まず、カーネルのMAC80211モジュールがCONFIG_MAC80211_MESH=yとしてビルドされている必要があります。とはいえ、ディストリビューション毎にカーネルconfigの在処が違うので厄介です。/proc/config.gzがあれば(CONFIG_IKCONFIG_PROC=yに設定されていた場合)そこから検索し、無い場合はmodprobe configsで出てくるかも知れません(Raspberry Piの場合)。configsモジュールが無い場合も、/boot/conigや/boot/config-(カーネルバージョン)にあるかも知れません(Ubuntuの場合)。どうしてもconfigが見つからない場合は「とりあえず試してみて、エラーが出たら多分対応していない」ということになりそうです。
メッシュ制御のフロントエンドはiwコマンドになります。これも余程古いバージョンでなければメッシュ対応しているはずですが、とりあえず
iw | grep mesh
とやってみて、mesh joinとかmesh leaveとかのコマンドが出てくれば大丈夫でしょう。
Wi-Fiモジュールとドライバがメッシュに対応しているかどうかは、iw phy <phy name>で表示される大量の情報のなかの"Supported interface modes:"のリストに"mesh point"が含まれているかどうかで判断できます。
iw phy <phy name> info | grep -i "Supported interface modes" -A 10
とやればわかるでしょう(※註1) 。
(※註1) 残念ながら、Raspberry Pi3オンボードWi-Fiのbrcmfmacドライバは"mesh point"に対応していないようです。
メッシュネットワークの設定(基本編)
まずはroot権限を得る必要があります。今時のLinuxなら"sudo su"でrootになれるでしょう。パスワードはシステムの管理者に尋ねてください。
次に、今時のLinuxではGUIのネットワークマネージャーが動いていることが多いので、これを停止します。これもディストリビューションによって方法がバラバラなのですが、"service"がフロントエンドになっているものが多いはずです。
Ubuntuの場合
service network-manager stop
Raspberry Piの場合
service networking stop
念のため、"ps -A | grep wpa_supplicant"でwpa_supplicantが動いていないかどうか確認し、動いているものがあれば悪さをしないようにkillしてください。
そしてメッシュインターフェースを作ります。ifconfigで出てくるWi-Fiのデバイス(例えば"wlan0")に対し、
ifconfig wlan0 down
iw dev wlan0 interface add mesh0 type mp
とやればできるはずです。Operation not supported -95とかのエラーが出る場合は、カーネルのCONFIG_MAC80211_MESH=yに設定されていないのかも知れませんし、モジュール・ドライバがメッシュ対応していないのかも知れません。ものよってはiw devの代わりに
iw phy phy0 interface add mesh0 type mp
でインターフェースが作れるかも知れません。
インターフェースができたら、ifconfig -aで見てみてください。ものによっては指定したmesh0の名前が付かず、wlx0024a54f9c73とかの名前が付いているかも知れません。MACアドレスは元になったwlan0と同じ値かも知れないし、+1されているかも知れないし、ぜんぜん違う値が付いているかも知れません(※註2)。
(※註2) 何だか「場合によっては」とか「かも知れません」をやたら多用していますが、この辺の動作はカーネルやドライバのバージョンによって本当にバラバラなのです。Linuxの持病というか持って生まれた性格なので、諦めてください。
オープンセキュリティ(暗号なし)でのメッシュ接続
暗号なしのメッシュなら、サプリカントを使わなくとも設定できます。まずはチャンネルを設定しなければなりません。
ifconfig mesh0 down
iw dev mesh0 set channel 6
とやれば設定できるはずです。この時点で"iw dev mesh0 info"を見れば、こんな風になっているはずです。
Interface mesh0
ifindex 7
wdev 0x200000002
addr 00:24:a5:4f:9c:73
type mesh point
wiphy 2
txpower 20.00 dBm
次に
ifconfig mesh0 up
iw dev mesh0 mesh join <mesh-ID>
でメッシュに参加できるはずです。ifconfig mesh0 upの段階でまたDevice or resource busy (-16)とかのエラーが出て蹴られるかも知れません。ものによりますが、元になるインターフェースのwlan0と派生インターフェースのmesh0を同時にupできないドライバもあります(upできるけど異常動作を起こす場合もあります)。ifconfig wlan0 downしてから再度試してみてください。
wlan0とmesh0が同じMACアドレスを持っていることがトラブルの原因かもしれません。MACアドレスが同じでもwlan0がdown状態であればmesh0をupできるはずですが、それでもダメな場合はmesh0のアドレス変更を試してみてください。
ifconfig mesh0 hw ether aa:bb:cc:xx:yy:zz
aa:bb:cc:xx:yy:zzの値はMACアドレスの規則を満たしていれば何でも良いのですが、wlan0のMACアドレスに+1することが多いです。念のため先頭オクテットのbit1を上げて(0x02をORして)ローカルMACアドレスにすると良いかも知れません。
ifconfig upできるけれどiw joinでOperation not supported -95とかのエラーが出る場合は、インターフェースmesh0がメッシュモードに設定されていないかも知れません(※註3)。iw dev mesh0 infoで"type mesh point"が出ていることを確認してください。これがmanagedとかになっていた場合は
iw dev mesh0 set type mp
でメッシュモードに設定できるはずです。その上でもう一度mesh joinを試してください。
(※註3) wpa_supplicantは終了時にインターフェースタイプを"managed"に設定するので、一度wpa_supplicantを試してからmesh joinやauthsaeを試そうとするとこの罠に陥ります。
メッシュに参加できれば、iw dev mesh0 infoは次のようになっているはずです。
Interface mesh0
ifindex 7
wdev 0x200000002
addr 00:24:a5:4f:9c:73
type mesh point
wiphy 2
channel 6 (2437 MHz), width: 20 MHz (no HT), center1: 2437 MHz
txpower 20.00 dBm
2台以上のメッシュノードが同じチャネルとMesh IDで動作すれば、ビーコンによって互いの存在を認識しているはずです。
iw dev mesh0 station dump
で近隣ノードの一覧が出るはずです。
root@raspberrypi:/home/pi# iw dev mesh0 station dump
Station 54:27:1e:a4:dd:89 (on mesh0)
inactive time: 260 ms
rx bytes: 8146
rx packets: 110
tx bytes: 252
tx packets: 4
tx retries: 0
tx failed: 1
rx drop misc: 32
signal: -27 dBm
signal avg: -26 dBm
Toffset: 4275655393 us
tx bitrate: 54.0 MBit/s
rx bitrate: 6.0 MBit/s
expected throughput: 13.366Mbps
mesh llid: 9694
mesh plid: 22504
mesh plink: ESTAB
mesh local PS mode: ACTIVE
mesh peer PS mode: ACTIVE
mesh non-peer PS mode: ACTIVE
authorized: yes
authenticated: yes
associated: yes
preamble: long
WMM/WME: yes
MFP: no
TDLS peer: no
DTIM period: 2
beacon interval:1000
short slot time:yes
connected time: 42 seconds
Station e4:f4:c6:4c:57:f2 (on mesh0)
inactive time: 14840 ms
rx bytes: 72
rx packets: 2
tx bytes: 826
tx packets: 12
tx retries: 40
tx failed: 12
rx drop misc: 0
signal: -41 dBm
signal avg: -41 dBm
tx bitrate: 1.0 MBit/s
mesh llid: 0
mesh plid: 0
mesh plink: LISTEN
mesh local PS mode: UNKNOWN
mesh peer PS mode: UNKNOWN
mesh non-peer PS mode: ACTIVE
authorized: yes
authenticated: yes
associated: yes
preamble: long
WMM/WME: yes
MFP: no
TDLS peer: no
DTIM period: 2
beacon interval:1000
short slot time:yes
connected time: 40 seconds
ここまで動けば、あとはifconfigでIPアドレスを付けてpingを打てば普通に通信できるはずです。HWMPによる経路制御の様子は、"iw dev mesh0 mpath dump"で見ることができます。この例ではDEST ADDRとNEXT HOPが同じ(直結パス)になっていますが、3台以上のノードを使って中継パスを組んだ場合、DEST ADDRとNEXT HOPは違う値になります。
root@raspberrypi:/home/pi# iw dev mesh0 mpath dump
DEST ADDR NEXT HOP IFACE SN METRIC QLEN EXPTIMEDTIM DRET FLAGS
54:27:1e:a4:dd:89 54:27:1e:a4:dd:89 mesh0 3 598 0 2340 100 0 0x
メッシュネットワークの設定(応用編)
Linuxのiwで作られるメッシュはデフォルトでReactive Modeになります。Proactive Modeに設定したい場合は、まずroot nodeとなるべきマシンを決め、そのマシンで
iw dev mesh0 set mesh_param mesh_hwmp_rootmode=<モード>
を実行します。<モード>は2~4が設定でき、次のように定義されています。
0: Reactive mode
1: Undefined
2: Periodic Broadcast PREQ w/o PREP
3: Periodic Broadcast PREQ with PREP
4: Periodic RAAN (Root Announcement)
これだけでは何のことだかわからないので補足すると、
モード2:ルートからPREQをフラッディングするけれど、各ノードからのPREP返送はしない。片道だけで経路表が更新される。
モード3:ルートからPREQをフラッディングし、各ノードからPREPを返送させる。1往復で経路表が更新される。
モード4:ルートからRAANをフラッディングし、各ノードからルートに向けてのPREQをフラッディングさせ、ルートがPREPを返送する。1.5往復で経路表が更新される。
となっています。それぞれの利害得失・どういう場合にどのモードを使うのが適切なのかは、正直いってよくわかりません。
メッシュと有線LAN(MPP)や無線LAN(MAP)と中継する場合は「ブリッジ」機能を使います。brctlコマンドがブリッジのフロントエンドになります。brctlがインストールされていない場合は"apt-get install bridge-utils"でインストールできるかも知れません。この辺もディストリビューションによって使われているパッケージマネージャーが違うので一概には言えません。
有線LANのインターフェース名が"eth0"だとすると、下記のコマンドでブリッジ機能を有効化できるはずです。
ifconfig eth0 0.0.0.0
ifconfig mesh0 0.0.0.0
brctl addbr br0
brctl addif eth0
brctl addif mesh0
ifconfig br0 <IPアドレス>
ブリッジは複数のインターフェース間で1つのIPアドレスを共有するので、ブリッジ配下の個々のインターフェースのIPアドレスはリセット(0.0.0.0設定)しておく必要があることに注意してください。IPアドレスが残っていると変な動作になります。冒頭でネットワークマネージャーを止めたのも、ネットワークマネージャーが新規インターフェースを検出して勝手にDHCPを発動したり169.254.x.xのAutoIPアドレスを付けたりするのを止めるためです。
セキュリティあり(暗号化)のメッシュ接続
セキュリティを伴うメッシュを構築する場合はサプリカントが必要になります。通常のWi-Fi(インフラストラクチャモード)で多用されているwpa_supplicantもメッシュに対応していますが、ビルド時にCONFIG_MESH=yが設定されている必要があります。これまた、ビルド済みのバイナリからメッシュ対応の有無を判断するのは困難です。とりあえずオープンセキュリティのメッシュ用設定、mesh-open.confを作って
ctrl_interface=/var/run/wpa_supplicant
country=JP
user_mpm=1
network={
ssid="(Mesh-ID)"
mode=5
frequency=2437
key_mgmt=NONE
}
p2p_disabled=1
これでwpa_supplicant -i mesh0 -c mesh-open.confを実行して、mode=5を受け付けるか否かで判断してみてください。
システム標準添付のwpa_supplicantがメッシュ対応していない場合は"too large mode (value=5 max_value=4)"と表示されて蹴られるはずです。その場合はwpa_supplicantのソースをダウンロードして、.configのCONFIG_MESH=yに設定したwpa_supplicantをリビルドしなければなりません。wpa_supplicantの公式プロジェクトサイト(https://w1.fi/wpa_supplicant/)の"Download"から当たってください。Google検索の"wpa_supplicant github"でトップに出てくるGithubのレポジトリ(https://github.com/digsrc/wpa_supplicant)は相当古いバージョン(Version 2.5, 2016)で、メッシュに対応していません。
wpa_supplicantで暗号化メッシュを動かす設定ファイルmesh-secure.confは次のようになります。
ctrl_interface=/var/run/wpa_supplicant
country=JP
user_mpm=1
network={
ssid="(Mesh-ID)"
mode=5
frequency=2437
key_mgmt=SAE
psk="(パスワード)"
ieee80211w=2
}
p2p_disabled=1
これでWPA3-Personal相当のセキュリティになります。なお、メッシュではWPA2相当のセキュリティを使うことはできません("key_mgmt for mesh network should be open or SAE"と蹴られます)。
IEEE802.11sメッシュサプリカントにはもうひとつ、authsae(https://github.com/cozybit/authsae)というのもありますが、バージョンアップは2019年に止まっているようです。参考までに、authsaeを使ったオープンセキュリティの設定ファイルmeshd-secure.confは次のようになります。
authsae:
{
sae:
{
password="(パスワード)";
group=[19,26,21,25,20];
lifetime=3600;
};
meshd:
{
meshid="(Mesh-ID)";
band="11g";
channel=6;
pmf=1
};
};
authsaeの実行ファイル名は"meshd-nl80211"です。authsaeはwpa_supplicantと違ってインターフェースup/downやモードの設定機能は持たず、しかしインターフェース状態が期待と異なってもエラーも表示しないので注意してください。念のためmeshd-nl80211の起動前に
ifconfig mesh0 down
ifconfig mesh0 set type mp
ifconfig mesh0 up
とやってから
meshd-nl80211 -i mesh0 -c meshd-secure.conf -B
とすれば動くはずです。うまく動かないときは、confファイルに
sae:
{
debug = 480;
を追加して、-Bを付けずに起動してメッセージを見ればヒントが掴めるかも知れません。
Linuxメッシュ機能のトラブル
Linuxにおけるメッシュの設定手順について書いてきましたが、「場合によっては」とか「かも知れません」とかをやたら多用しました。実際、この記事を書くための実験では妙なトラブルをさんざん体験しました。
まずメッシュはあくまでオプション機能であり、世間に出回っているLinuxのカーネルやwpa_supplicantの多くはメッシュ非対応でビルドされています。メッシュ対応するためにはソースを入手してconfigを変更しリビルドしなければなりませんが、前述したようにconfigの確認方法すら一筋縄では行かず、ましてリビルドの手順はそれこそシステム毎にバラバラです。(※註4)
(※註4) クロスコンパイルが必要になる組み込みプラットホームでは特にめんどくさく、セルフビルドできるPCベースやRaspberry Piのほうが幾らかマシです。
ビルドが出来たとしても、Wi-Fiモジュールやドライバがメッシュに対応しているかどうかは「やってみないとわかりません」。同じドライバ/モジュールでも、メッシュ対応についてはバージョンによって異なります。古いドライバだと実装が中途半端なのか、iw phyで見ると対応していることになっている筈なのに、iw dev interface addとかiw dev mesh joinをするとOperation not supported (-95)で拒否するものもあったりします。
暗号化のないオープンセキュリティの設定でも、iw join meshで作ったノードとwpa_supplicant(オープン)で作ったノードでは通信できませんでした。ビーコンすら認識しておらず、iw station dumpでも出てきません。パケットをキャプチャして見てみましたが、iw join meshのビーコンにはIEEE802.11nのHT Capabilities / HT Informationが入らず、wpa_supplicantのビーコンには入っているくらいしか違いません。11n特有の機能を使わなければ11a/g互換モードで接続できそうな気がしますが、ダメなようです。
更に極端な場合では、iw join同士あるいはwpa_supplicant同士でも無線ドライバ/モジュールの機種が違うと、ビーコンを発信しているけれど他機からのビーコンを受信できないらしく、station dumpに何も出てこない場合もありました。
セキュリティが絡むと更に厄介で、複数のドライバ/モジュール(主にUSBドングル)で「オープンなら接続できるけれどセキュリティでは接続できない」という現象が起きました。これもパケット解析してみると、ビーコンは認識してstation dumpは見えるのだけど、そこから先のPREQ/PREP交換で暗号を解読できていないように見えます。送信側・受信側どちらが悪いのかよくわかりません。機種A,B,CがあってA-Bがダメ、B-Cもダメ、A-Cもダメとなるともう、一体誰が悪いのやらわかりません。wpa_supplicant.confのpmf=2(制御フレームの暗号化必須)をpmf=0(暗号化なし)に設定すると通信できた場合もありましたが、パケットを見てみるとpmf=0でも2でもPREQ/PREPは暗号化されて発信されており、これまた一体何が悪いのか原因不明です。
一方、暗号メッシュで相互通信できる機種同士ならば、wpa_supplicantの暗号メッシュとauthsaeの暗号メッシュでは相互通信できました。
BR-400ANについて
長々と書いてきたように、素のLinuxによるメッシュ構築と稼働は実際にやってみるといろいろ落とし穴があります。弊社製品BR-400ANはメッシュ対応のブリッジ(MP/MPP)/アクセスポイント(MAP)で、上に書いてきたような互換性問題に煩わされることなくメッシュ機能を利用できるようになっています。
BR-400ANのメッシュ機能は基本的にはLinux HWMPの応用で、動作モードはReactiveとProactiveを設定で選択できます。設定項目名は
・経路リフレッシュ機能: Disable=Reactiveモード / Enable=Proactieモード(デフォルト)
となっており、またProactiveモードの設定項目として
・経路リフレッシュ方式: ライト=PREQ送信PREPなし:デフォルト) / フル=PREQ送信PREPあり
・経路リフレッシュ間隔: 1~86400(秒, デフォルト3600秒=30分)
が用意されています。更にメッシュを安定させるため、
・経路モード: 即応型/安定型(デフォルト: 安定型)
・送信制御機能: ENABLE/DISABLE(デフォルト: ENABLE)
・通信ループ回避: DISABLE/ENABLE(デフォルト: DISABLE)
という設定も用意されていますが、これらの機能は弊社が独自に実装したもので、Linux標準のiwには対応する設定項目がありません。
一般的に「メッシュは多点接続で動的な経路選択を行うため障害に強い」とされますが、裏を返せば「些細な原因で経路がコロコロ変わって安定しない」という落とし穴があります。上記のデフォルト値や追加された設定項目は弊社がそれなりにトラブル対応や実験を経て、「通常時は極力安定した経路を維持して通信する」「異常時は早く経路を切り替える」ことを目的として実装したものです。
また、必ずしも接続状態を把握しやすくはないLinux標準のiw station dump / iw mpath dumpに代えて、グラフィカルにメッシュ接続情報を表示するAMCマネージャーMesh Monitorプラグインも提供しています。
まとめ
Linuxへのメッシュ機能の実装はかなり早くから着手されており、上記のようにカーネルバージョンとしては2.6.26(2008/7)が最初のリリースになりますが、ソースコード上のコミットはもう少し早く2008/2になっています。しかし、それから10年以上の時間が経った現状は上記の通りです。「適性のあるコンポーネント(カーネル・モジュール・ドライバ)を選んで正しく設定すれば動く」けれども落とし穴が多く、適性のない(対応していない・あるいは中途半端にしか動かない)モジュール・ドライバも少なくありません。これはすなわち、Linuxのメッシュ機能がほとんど活用されておらず、オープンソースへのフィードバックやコミットが少ないことを意味しています。
Linux以外の商用プラットホーム(Windows, MacOS, iOS)ではIEEE802.11sメッシュ規格じたいガン無視されている現状もありますが、Linuxという「一応標準で対応していることになっている」世界のなかでも「使われないから改善されない、改善されないから使ってみると問題だらけ、問題だらけだからますます使われない」という悪循環に陥っている気がします。
余談(Looking Back)
IEEE802.11s標準の提案は2003年でしたが、仕様制定作業は一進一退を繰り返して時間を空費し、仕様制定は9年後の2012年に遅れました。一体何でこんなことになったのか、どうも2000~2010年頃は無線メッシュが熱い話題だった時期で、あまりに多くの参加者が自分の意図を標準仕様に取り入れようとして衝突していたのかも知れません。「船頭多くして船山に登る」は標準規格の世界ではよくあることです。UWBのIEEE802.15.3a騒動では私も身をもって体験しました。
2000年代初めの「メッシュブーム」の火付け役になったのは、1999年1月に発表されたRFC2501 Mobile Ad hoc Networking(MANET)という提案でした。MANETの冒頭には「安価かつ堅牢な、携帯電話ネットワークの代替あるいは補完」という可能性が挙げられており、まだデジタル携帯網が発展途上だった時代に「月額料金を払わなくても世界中どこからでも無線通信できる!もう携帯キャリアに支配される時代は終わった!」という夢物語としてメッシュが盛り上がってゆくことになります。同じころには地域自治体が町全体をカバーする公共Wi-Fiを整備する「アーバン・ネットワーク」やら、自家用Wi-Fiを無断借用する「ロード・ウォリアー」あるいは「ウォー・チョーキング」、それを商業化したFON(2005~)なんてのも話題になっていました。
Linuxのメッシュ機能も多分にメッシュブームの一環として実装が進められたものですが、何だか浦島太郎の雰囲気です。携帯キャリアは衰退どころかますます強く大きくなり、「世界中どこからでも無線通信」の話題は次世代携帯の5Gサービスに収斂しており、CubeSatのような低軌道の安価な超小型衛星を5G網に統合して地球全域でのサービスを目論む企画も複数動いています。Wi-Fi規格は802.11n以後、電波状況の把握や帯域・アンテナ指向性制御の管制をアクセスポイントで集中管理する方向で高速・高効率を目指す方向で機能拡張されており、中枢を持たないメッシュは置いてけ堀にされている格好です。
ならば「メッシュは終わったのか?」と言われると難しいところで、「終わった」のは「誰もが無料で使える、携帯電話網を置き換える新たな通信インフラという幻想」だと思います。メッシュにはメッシュならでわの特長があり、適性のあるコンポーネントを選定し、運用環境に適したルーティングアルゴリズムを選択しパラメータをチューニングすれば、古典的なAP-STA接続では実現できない価値を実現できる可能性はあります。弊社製品のBR-400AN / MNS-300EMも産業用無線メッシュというユースケースを想定してチューニングしたもので、具体的に何をどう変えたかの一端については本記事でも解説しました。
新技術が世に出ると、まだ海のものとも山のものともつかないうちから過剰な期待ばかりが先行し、世の中の問題を何でも解決できる魔法のように語られることが多いです。メッシュもUWBもそれを通ってきましたし、最近では5G携帯網、人工知能(AI)、量子コンピュータにその傾向があります。「できる可能性がある」ということと「それができる製品をパッケージングして販売する」の間には大きなギャップがあるのですが、ニュースでは往々にして「可能性さえあればもう出来たも同然」みたいに語られることが多いように感じます。
本ブログでは「無線屋さんのおしごと」以来、延々と泥臭い製品開発現場の話をやってきましたが、今後もこのスタイルで続けてゆくつもりです。