追記:5GHz+6GHz EasyMesh backhaul MLOの永続化、再起動後の自動復帰、Ethernet端末間iperf3で約0.94Gbpsの実測結果を追記しました。
LANケーブルを抜いた。
すぐさま、無線EasyMeshに切り替わり、SSHは途切れない。
backhaul connection status 1
backhaul connection Type 4
そして、
apcli0 carrier=0
apclii0 carrier=0
apclix0 carrier=1
よし、つながった。
SoftBank Air ターミナル6を2台使い、片方をEasyMesh Controller、もう片方をAgentとして動かし、Ethernetを外したあとも6GHz帯をバックホールとしてEasyMeshが維持されるところまで確認できた。
carrier=1を見て喜ぶ人生になるとは思わなかった。
この記事では、そこまでに何を確認し、どこでハマり、何を成功条件にしたのかをまとめる。特に、同じような実機を持っている人がこの記事をそのままAIに読ませて、作業時間を多少でも省略できることを狙っている。
最初に重要なこと:SSHへ入るまでの方法は書きません
今回使用している端末では、私は自分の所有する実機にroot権限でSSH接続できる状態を作っている。
ただし、そこへ至るまでに調査したRCE、初期侵入経路、権限取得に関係する情報はこの記事では意図的に公開しない。
具体的には以下を掲載しない。
- 脆弱性を利用した初期アクセスの具体的手順
- RCEを成立させるリクエストやペイロード
- 認証回避、権限昇格に関係する具体的な経路
- 攻撃可能なAPIや内部呼び出し経路
- 秘密鍵、Wi-Fi PSK、DPP private key
- 個体固有の認証情報、シリアル等
この記事のスタート地点は、
自分が管理権限を持つターミナル6に、rootでSSH接続できている
である。
そこから先は、OpenWrt上で既存のEasyMesh構成を調査し、OEMが用意している仕組みを使ってController / Agentを構成する話になる。EasyMesh部分を再現するうえで、RCEの情報は必要ない。
今回できたこと
結果から先に書く。
2台を仮に以下とする。
| 名前 | 役割 | 実験用管理IP |
|---|---|---|
| T6A | EasyMesh Controller | 192.168.3.2 |
| T6B | EasyMesh Agent | 192.168.3.223 |
最終的にはこうなった。
6 GHz wireless backhaul
┌────────────────────────────────────┐
│ │
┌───▼───┐ ┌───▼───┐
│ T6A │ │ T6B │
│ role1 │ │ role2 │
│ Ctrl │ │ Agent │
└───────┘ └───────┘
T6B側では、
dev_role 2
backhaul connection status 1
backhaul connection Type 4
となった。
さらに実インターフェースでは、
apcli0 : DOWN / NO-CARRIER
apclii0 : DOWN / NO-CARRIER
apclix0 : UP / LOWER_UP
になり、6GHz側のapclix0だけがリンクアップしてRX/TXカウンタも増加した。
Controller側のtopologyにもAgentが、
Device role: 02
Distance from controller: 1
Backhaul Medium Type: 6G
として現れる。
ここまで揃って、私は「6GHz EasyMeshバックホール成功」と判定した。
なお、これは後で詳しく書くが、MLO成功ではない。今回は6GHz単独のwireless backhaulまでを確認している。
実験環境
確認した実機環境は以下。
OpenWrt 21.02.7
r16847-f8282da11e
Linux 5.4.238
aarch64
BusyBox 1.33.2
Target:
gem6xxx/evb6990_cpe_mt7990_emmc
純粋なOpenWrt公式イメージではなく、ベンダー独自の構成がかなり入っている。
EasyMesh関連では、少なくとも以下が重要だった。
mapd
wapp
p1905_managerd
kn_meshd
mapd_cli
EasyMesh_openwrt.sh
mapd_cliにはかなり便利な診断機能が残っている。
mapd_cliで今回よく使ったもの
mapd_cli /tmp/mapd_ctrl getrole
mapd_cli /tmp/mapd_ctrl agent_list
mapd_cli /tmp/mapd_ctrl dump_topology
mapd_cli /tmp/mapd_ctrl dump_topology_v1
mapd_cli /tmp/mapd_ctrl bh_info
mapd_cli /tmp/mapd_ctrl bh_conn_status
mapd_cli /tmp/mapd_ctrl bh_conn_type
mapd_cli /tmp/mapd_ctrl get_bh_ap
mapd_cli /tmp/mapd_ctrl get_fh_ap
また、このFWのmapd_cliには、
onboarding
Do ethernet(0) or wifi(1) onboarding
config_renew
Issue Config Renew command from controller on all bands
も実装されている。
つまり少なくとも設計上は、
mapd_cli /tmp/mapd_ctrl onboarding 0
でEthernet onboardingを行う経路が存在する。
FWや初期状態によっては有線接続だけで自動的にAgentが認識されることもある。今回もまずtopologyとログを確認し、必要な場合だけCLI操作を加える形にした。
Controller / Agentを決めるDeviceRole
このFWではController / Agentの中心になる値がDeviceRoleである。
0 = Auto
1 = Controller
2 = Agent
OEMのEasyMesh_openwrt.sh自身がこの値を読み、ControllerかAgentかで起動方法を変えている。
Controllerでは概ね、
map_agent=0
map_root=1
p1905_managerd -r0 ...
Agentでは、
map_agent=1
map_root=0
p1905_managerd -r1 ...
という構成になる。
また、/etc/map/1905d.cfgはEasyMesh初期化時に生成・更新される。実行中の状態確認には使えるが、永続設定を考える場合には、その値の生成元まで追う必要がある。
設定ファイルの生成関係
EasyMeshの設定は一か所ではなかった。
今回確認した範囲では、概ね、
/etc/map/mapd_default.cfg
↓
/etc/map/mapd_user.cfg ← ユーザー側override
↓
uci2map / OEM script
↓
/etc/map/mapd_cfg ← 実行時に使われる生成設定
↓
mapd / p1905 / wapp
という流れになっている。
mapd_user.cfgの内容はmapd_cfgへmergeされる。
そのため、永続的にAgentへ設定する場合は、生成済みmapd_cfgだけではなくuser override側も確認することがポイントだった。
OEM自身のAgent設定コードにも、
wificonf -f /etc/map/mapd_user.cfg set DeviceRole 2
wificonf -f /etc/map/mapd_cfg set DeviceRole 2
という処理がある。
この生成関係を把握してから、設定変更と再起動後の状態を追いやすくなった。
変更する前にバックアップ
まずバックアップする。
mkdir -p /root/easymesh-backup
cp -a /etc/config/mapd \
/etc/map/mapd_default.cfg \
/etc/map/mapd_user.cfg \
/etc/map/mapd_cfg \
/etc/map/1905d.cfg \
/root/easymesh-backup/
無線設定は秘密情報を含む可能性があるため、公開用ログとは分けて保存した。
最初に現在値を確認する
Controller候補、Agent候補の両方で現在値を見る。
uci -q show mapd | grep -E \
'MapMode|DeviceRole|BhPriority|AutoBH|Mld'
echo
cat /etc/map/mapd_user.cfg
echo
grep -E \
'^(mode|MapMode|DeviceRole|BhPriority|AutoBH|NtwrkOptMld)' \
/etc/map/mapd_cfg
私のControllerで成功時に確認した主な値は、
MapMode=1
DeviceRole=1
BhPriority2G=3
BhPriority5GL=2
BhPriority5GH=2
BhPriority6G=1
AutoBHSwitching=1
NtwrkOptMldBhPriority=1
だった。
BhPriorityについては、少なくともこのFW、この構成で、
6GHz = 1
5GHz = 2
2.4GHz = 3
という組み合わせで6GHzバックホールが選ばれたことを確認した。
別FWでも同じ値の意味になるかは未確認なので、他バージョンで試す場合にはOEMスクリプト内での参照方法も確認したほうがよい。
Agent側をrole 2へする
T6B側ではDeviceRole=2にする。
OEM自身が使っている方法に寄せると、
wificonf -f /etc/map/mapd_user.cfg set DeviceRole 2
となる。
設定後に確認する。
cat /etc/map/mapd_user.cfg
今回のAgent側では、
DeviceRole=2
MapMode=1
となる状態を作った。
Controller側は、
DeviceRole=1
MapMode=1
であることを確認した。
EasyMeshを有効にする
今回の実機では、
uci -q get knos.network.easymesh
uci -q get knos.flags.mesh
で、
1
1
になっていた。
少なくとも今回の成功状態では、
knos.network.easymesh='1'
knos.flags.mesh='1'
だった。
FWが異なる場合は、実際の起動スクリプトと合わせて確認する必要がある。
OEMの起動シーケンスを使う
EasyMesh関連の主要プロセスは、
mapd
p1905_managerd
wapp
だが、EasyMesh_openwrt.shを見ると、その前後で多くの処理を行っている。
- Wi-Fi profile生成
- role判定
- APCLI準備
- bridge設定
- DHCP処理
- IEEE1905設定
- forwarding関連処理
mapfilter- WAPP
p1905_managerdmapd
などである。
そのため今回は、永続設定を整えたあと、
reboot
してOEMの通常起動シーケンスを通した。
個別daemonだけを起動するよりも、再起動後の状態を基準に比較するほうが再現しやすかった。
最初はEthernetでControllerとAgentを接続する
最初から無線だけで接続を成立させるのではなく、まず2台をEthernetで接続した。
これによって、
Controller / Agentのrole設定
IEEE1905 discovery
EasyMesh onboarding
wireless backhaulへの切り替え
を段階ごとに確認できる。
Controller側では、
mapd_cli /tmp/mapd_ctrl agent_list
mapd_cli /tmp/mapd_ctrl dump_topology_v1
を確認する。
途中の成功状態では、
T6A:
Device role: 01
Distance from controller: 0
T6B:
Device role: 02
Distance from controller: 1
となる。
ここまで確認できれば、ControllerからAgentがEasyMesh nodeとして認識されている。
Agent化すると管理IPの挙動も変わる
ここはかなり時間を使った。
Agent化したあと、T6Bへpingが通らなくなったり、管理IPが変わったりすることがあった。
OEMスクリプトを確認すると、MapMode=1ではDHCP周辺も自動変更している。
概ね、
network.wan.proto=none
dhcp.lan.ignore=1
udhcpc -i br-lan
という処理が入る。
つまりAgent化によって、
DHCP serverとして動く構成から、br-lan側でDHCP clientとしてアドレスを取得する構成へ移る
場合がある。
そのため、
以前のIPへpingが通らない
ことと、
EasyMesh Agentとして認識されていない
ことは分けて判断する必要があった。
Controller側からL2を見る。
bridge fdb show br br-lan
古い環境なら、
brctl showmacs br-lan
でも確認できる。
AgentのAL MACがbridge側に見え、topologyにもrole 02 / distance 1として現れていれば、EasyMesh自体は成立していて、管理IPv4だけ変化している可能性がある。
raspi2を作業・観測点にした
今回の作業は、最終的にこういう構成になった。
┌──────────────┐
│ Codex CLI │
│ VM │
└──────┬───────┘
│ SSH
▼
┌──────────────┐
│ raspi2 │
│ 作業・観測点 │
└──────┬───────┘
│
┌────────┴────────┐
│ │
▼ ▼
┌─────┐ ┌─────┐
│ T6A │ │ T6B │
└─────┘ └─────┘
Codex CLIから両方の状態を同時に取得できる。
片方を再起動している間に、もう片方のtopologyやinterface counterを監視する。Ethernetを外した直後も、数秒間隔で状態変化を記録できた。
2台を比較しながら実験するには、この構成がかなり便利だった。
LANケーブルを抜いて状態を観測する
有線状態でAgentが認識されたら、Ethernetを外す。
T6B側では以下のように状態を監視した。
for i in $(seq 1 60); do
echo "===== $(date) ====="
mapd_cli /tmp/mapd_ctrl getrole 2>&1
mapd_cli /tmp/mapd_ctrl bh_conn_status 2>&1
mapd_cli /tmp/mapd_ctrl bh_conn_type 2>&1
for d in apcli0 apclii0 apclix0; do
printf "%s carrier=" "$d"
cat /sys/class/net/$d/carrier 2>/dev/null
printf "%s rx=" "$d"
cat /sys/class/net/$d/statistics/rx_bytes 2>/dev/null
printf "%s tx=" "$d"
cat /sys/class/net/$d/statistics/tx_bytes 2>/dev/null
done
sleep 3
done
今回、最終的にこうなった。
dev_role 2
backhaul connection status 1
backhaul connection Type 4
apcli0:
carrier=0
apclii0:
carrier=0
apclix0:
carrier=1
apclix0のRX/TX byteだけが継続的に増える。
ここで、
どのradioのSTA interfaceが実際にバックホールを運んでいるのか
まで確認できた。
このFWでのAPCLI対応
今回確認した範囲では、STA / backhaul側は以下の対応だった。
| Interface | 帯域 |
|---|---|
apcli0 |
2.4GHz |
apclii0 |
5GHz |
apclix0 |
6GHz |
6GHz側apclix0では、今回、
channel 21
6055 MHz
width: 160 MHz
type managed
4addr: on
を確認した。
したがって、
apclix0 LOWER_UP
carrier=1
は6GHz側STA interfaceが接続していることを示す材料になる。
成功判定は複数の情報を組み合わせる
私は最終的に、以下の4系統が全部成立したところを成功とした。
1. EasyMesh論理topology
Controllerから、
Controller:
role 01
distance 0
Agent:
role 02
distance 1
として見える。
さらにAgent側に、
Backhaul Medium Type: 6G
が出る。
2. mapdのbackhaul状態
Agent側で、
backhaul connection status 1
backhaul connection Type 4
になる。
3. Linuxの実インターフェース
apcli0 carrier 0
apclii0 carrier 0
apclix0 carrier 1
となり、apclix0だけRX/TXが増加する。
4. 実際にIPトラフィックが流れる
T6Bの管理IPへ到達でき、iperf3を通せる。
この4つを組み合わせることで、topology表示だけではなく、実際のデータ経路まで確認した。
iperf3で実際に流してみる
このFWにはiperf3が入っていた。
実験ではT6Bをserverにした。
# T6B
iperf3 -s -B 192.168.3.223
T6Aから1 stream。
iperf3 \
-c 192.168.3.223 \
-B 192.168.3.2 \
-t 20
4 stream。
iperf3 \
-c 192.168.3.223 \
-B 192.168.3.2 \
-P 4 \
-t 20
逆方向。
iperf3 \
-c 192.168.3.223 \
-B 192.168.3.2 \
-P 4 \
-R \
-t 20
今回の実測は、おおむね、
A -> B
4 streams:
約350 Mbps
B -> A
4 streams:
約330 Mbps
だった。
1 streamでは約300Mbps前後になった回もあった。
これは「6GHzならこの速度が出る」というベンチマークではない。距離、配置、FW、アンテナ、radio schedulingなどの条件を含む今回の実験値である。
重要なのは速度そのものより、
Ethernetを抜いた状態で、6GHzのapclix0カウンタを増やしながら実IPトラフィックが数百Mbps流れた
ことである。
ハマった点1:生成設定と永続設定
この箱では、
mapd_default.cfg
mapd_user.cfg
mapd_cfg
/etc/config/mapd
1905d.cfg
など、似た名前の設定ファイルが並んでいる。
特に、
/etc/map/mapd_cfg
は実行時に参照される重要なファイルだが、生成される側でもある。
そのため今回の調査では、
現在どの値になっているか
だけでなく、
その値を誰が書くのか
次回起動時にはどこから生成されるのか
まで確認した。
最終的には、
persistentな入力側を変更し、生成側は結果確認に使う
という整理になった。
AIにも、
この値のsource of truthを追って。生成ファイルと入力ファイルを分けて整理して。
と依頼すると、この部分をかなり効率よく調べられた。
ハマった点2:OEMの起動スクリプト
mapd、p1905_managerd、wappだけを見ると個別に起動できそうに見えるが、実際にはOEMスクリプトがその前後でAPCLI、bridge、MAP filter、role、DHCPなどをまとめて処理していた。
そこで私は、
- persistent configを整える
- backupする
- rebootする
- OEMの通常起動後を観測する
という流れにした。
AIを使う場合にも、
このdaemonを本来起動しているスクリプトを先に追って
と依頼すると、単体プロセスだけを見るより全体像を把握しやすかった。
ハマった点3:診断CLIとEasyMesh本体
このFWでは一部の1905ctrl診断を実行すると、
Segmentation fault (core dumped)
することがあった。
ただし、その状態でもEasyMeshそのものは正常に動作した。
そのため今回は、
mapd_cli
実interface
bridge FDB
mapd / p1905 log
実通信
を中心に状態を確認した。
診断CLIが正常終了すること自体は成功条件に含めていない。
ハマった点4:ログ時刻
実機ログの時刻が、外側から見た実験時刻とずれることがあった。
複数台を比較するときには時系列が重要になるため、raspi2側でも、
echo "===== $(date) ====="
ssh ...
のように採取側のtimestampを付けた。
AIへ複数ログを渡す場合にも、共通の観測点でtimestampを付けておくと状態変化を追いやすい。
firewallについて
ここではファームウェアとの混同を避けるため、firewallと表記する。
今回の実験では、主な問題はIP firewallではなかった。
EasyMeshの初期発見やIEEE1905ではL2の状態も重要になる。
そのため、
ping
TCP port
だけではなく、
brctl show
bridge fdb show
ip maddr show br-lan
も確認した。
必要に応じてfirewall設定も確認する。
fw4 print
今回の純正に近い構成では、firewallを大きく変更する必要はなかった。
独自にbridge netfilter、ebtables、nftablesのbridge familyなどを追加している環境では、IEEE1905関連のL2通信が通る状態かどうかも確認対象になる。
今回は、
IP layer
L2 bridge
EasyMesh topology
を分けて見ることで整理できた。
「AgentになったがIPv4がない」という中間状態
今回かなり重要だった観察がこれ。
ControllerのL2側にはT6BのMACが見えている。
topologyにも、
Device role 02
Distance 1
で見えている。
一方で、
ping <以前のT6B-IP>
が通らないことがある。
この場合には、
EasyMeshとしてAgent化できていない
のか、
Agent化した結果、管理IPv4が変わった
のかを分けて考える必要がある。
AIに状態を判断させるときにも、私は以下の順番で見てもらうようにした。
1. IEEE1905 topology
2. DeviceRole
3. bridge FDB
4. bh_conn_status / bh_conn_type
5. APCLI carrier
6. 管理IPv4
この順番にすると、L2では成功しているがIPv4だけ追えていない状態を判別しやすかった。
今回の成功条件
今回成功した状態をまとめる。
[Controller]
DeviceRole = 1
MapMode = 1
EasyMesh enabled
[Agent]
DeviceRole = 2
MapMode = 1
EasyMesh enabled
[Backhaul policy]
BhPriority6G = 1
BhPriority5G = 2
BhPriority2G = 3
AutoBHSwitching = 1
[Ethernet onboarding]
Controller topologyにAgent role02 / distance1
[Ethernet切断後]
Agent role02を維持
bh_conn_status = 1
bh_conn_type = Type 4
[radio]
apcli0 carrier=0
apclii0 carrier=0
apclix0 carrier=1
[topology]
Backhaul Medium Type = 6G
[data plane]
Agent IPへ通信可能
iperf3等で実トラフィック通過
特に、
topologyが6G
apclix0だけcarrier=1
実データが流れる
の3点を合わせて、6GHzバックホール成立と判断した。
これはMLOではない
Wi-Fi 7なので、次に確認したくなるのがMLOである。
現在のAgentでは、
apcli0 DOWN
apclii0 DOWN
apclix0 UP
となっている。
さらに無線profile側には、
ApcliMloDisable=1
が残っているものも確認できた。
一方で、FWの中にはMLO関連のdebugfs nodeや、Enable_Apcli_MLO()などのOEMコードも存在する。
つまりMLO関連の実装は入っているが、現在確認できている通信は6GHz側apclix0単独である。
現状の成果を正確に書くなら、
EasyMesh R3で6GHz単独のwireless backhaulに成功
である。
MLOは次の確認項目として残っている。
AIに渡すための診断セット
この記事を残す目的の一つが、次に同じことを試す人が、現在状態の確認にかかる時間を減らせるようにすることである。
以下のような診断セットを最初に採取すると、AIにも状況を伝えやすい。
秘密情報を含めないEasyMesh診断セット
OUT="/tmp/t6-easymesh-diag-$(date +%Y%m%d-%H%M%S).txt"
{
echo "=================================================="
echo "T6 EASYMESH DIAGNOSTIC"
date
echo "=================================================="
echo
echo "===== SYSTEM ====="
uname -a
cat /etc/openwrt_release 2>/dev/null
echo
echo "===== MAPD CONFIG ====="
uci -q show mapd |
grep -E \
'MapMode|DeviceRole|BhPriority|AutoBH|NtwrkOptMld'
echo
echo "===== MAPD USER OVERRIDE ====="
grep -E \
'^(MapMode|DeviceRole|BhPriority|AutoBH|NtwrkOptMld)' \
/etc/map/mapd_user.cfg 2>/dev/null
echo
echo "===== KNOS ====="
uci -q show knos |
grep -E 'easymesh|mesh'
echo
echo "===== PROCESSES ====="
ps w |
grep -E '[m]apd|[w]app|[p]1905|[k]n_mesh'
echo
echo "===== BRIDGE ====="
brctl show 2>/dev/null
bridge fdb show br br-lan 2>/dev/null
echo
echo "===== BACKHAUL INTERFACES ====="
for d in apcli0 apclii0 apclix0; do
echo
echo "--- $d ---"
ip -s link show "$d" 2>/dev/null
printf "carrier="
cat "/sys/class/net/$d/carrier" 2>/dev/null
done
echo
echo "===== MAP ROLE ====="
mapd_cli /tmp/mapd_ctrl getrole 2>&1
echo
echo "===== BH STATUS ====="
mapd_cli /tmp/mapd_ctrl bh_conn_status 2>&1
mapd_cli /tmp/mapd_ctrl bh_conn_type 2>&1
mapd_cli /tmp/mapd_ctrl bh_info 2>&1
echo
echo "===== AGENTS ====="
mapd_cli /tmp/mapd_ctrl agent_list 2>&1
echo
echo "===== TOPOLOGY ====="
mapd_cli /tmp/mapd_ctrl dump_topology_v1 2>&1
echo
echo "===== RECENT MESH LOG ====="
logread 2>/dev/null |
grep -Ei \
'mapd|1905|easymesh|agent|controller|backhaul' |
tail -n 200
} > "$OUT" 2>&1
echo "$OUT"
このスクリプトでは、意図的に以下はdumpしていない。
Wi-Fi PSK
key
password
DPP private key
private SSH key
cloud credential
個体固有の秘密情報
AIへの指示文
AIへ渡す前提条件も、ある程度まとめておくと調査を始めやすい。
AIに渡すプロンプト例
SoftBank Air ターミナル6を2台使っています。
前提:
- 両方とも自分の所有機
- root SSH接続済み
- 初期アクセス/RCEの調査は不要
- OEM firmwareのまま
- OpenWrt 21.02.7系
- MediaTek系EasyMesh実装
- ControllerをT6A、AgentをT6Bとする
目的:
T6A/T6BをEasyMeshで構成し、
Ethernet onboarding後にケーブルを外して、
6GHz wireless backhaulへ自動移行させたい。
既知の成功条件:
- T6A DeviceRole=1
- T6B DeviceRole=2
- MapMode=1
- EasyMesh enabled
- BhPriority6G=1
- 5G=2
- 2G=3
- AutoBHSwitching=1
- Agentがdistance=1でtopologyに出る
- ケーブル切断後 bh_conn_status=1
- bh_conn_type=Type 4
- apclix0のみcarrier=1
- topologyにBackhaul Medium Type=6G
- 実IP trafficが通る
調査方針:
1. 最初はread-only調査だけする
2. 生成ファイルと永続設定ファイルを区別する
3. /etc/map/mapd_cfgの生成元を確認する
4. OEMの起動スクリプトを調べて通常の起動経路を使う
5. PSK/key/password/private keyを表示しない
6. factory resetは行わない
7. firmwareは書き換えない
8. 一度に複数の変更をしない
9. 各変更前にbackupする
10. 管理IPv4消失とEasyMesh失敗を区別する
まず診断ログから、
現在どの層まで成功しているかを判定してください。
前提条件と成功条件をここまで渡しておくと、一般的なEasyMeshの説明を省いて、実機状態の診断から始めやすい。
AIを使って特に短縮できたところ
今回、AIとの相性が特によかったのは、設定値そのものより、その設定値がどこから来て、誰に読まれ、誰に書き換えられるのかを追う作業だった。
たとえばDeviceRoleだけでも、
/etc/config/mapd
/etc/mapd.uci
/etc/map/mapd_default.cfg
/etc/map/mapd_user.cfg
/etc/map/mapd_cfg
/usr/bin/EasyMesh_openwrt.sh
/lib/wifi/wifi_services.lua
/usr/bin/config_agent.lua
などに現れる。
従来なら、
grep -R DeviceRole ...
して、一つずつ読むところである。
今回はAIに、
この値のwriterとreaderを全部追って。
boot後にどれがsource of truthになるか整理して。
変更候補を出す前に根拠となるコードを示して。
と依頼した。
さらに、片方を再起動している間にもう片方を3秒間隔で監視し、状態変化をまとめて比較するところまで任せられる。
ここまで来ると、AIは検索代行というより実験助手に近い。
人間は、
今は何を確かめたいのか
どこまで変更してよいのか
何を成功とするのか
を決める。
AIには、
コードを探す
設定の流れを追う
両機の差分を取る
ログを時系列で整理する
ところを任せる。
今回、この分担でかなり作業時間を短縮できた。
まとめ
SoftBank Air ターミナル6を2台使い、OEM FWを維持したままEasyMesh内部構成を調べた。
その結果、
- T6AをController
DeviceRole=1 - T6BをAgent
DeviceRole=2 - 最初はEthernetでEasyMesh topologyを形成
- Agentがrole02 / distance1で認識されることを確認
- 6GHz優先の既存バックホール設定を確認
AutoBHSwitching=1- Ethernetを切断
- Agent roleを維持
bh_conn_status=1bh_conn_type=Type 4-
apclix0だけがcarrier=1 - topology上も
Backhaul Medium Type=6G -
iperf3で双方向数百Mbpsの実通信を確認
まで到達した。
一番大きなポイントは、単なるWi-Fi設定として見るのではなく、
OEMが持っているEasyMeshの設定生成、role選択、起動シーケンスを追う
ことだった。
また、
管理IPv4
IEEE1905 topology
L2 bridge
backhaul state
実interface
data plane
を分けて確認することで、途中状態もかなり判別しやすくなった。
AIにも同じ順序で情報を渡すと、調査範囲をかなり絞ることができる。
現在、2台はLANケーブルなしで6GHzバックホールを維持している。
次はMLO。
FW内部にはEnable_Apcli_MLO()、ApcliMloDisable、mld_sta、mld_bssなど、調査対象になりそうな実装がすでに見えている。
追記:5GHz+6GHz EasyMesh backhaul MLOまで到達した
この記事を書いた時点では、
6GHz単独のwireless backhaulには成功したが、MLOではない
という状態だった。
その後も調査を続け、最終的に5GHz+6GHzの2-link EasyMesh backhaul MLOまで動作させることができた。
さらに、
- 設定を永続化
- Agentを通常の
rebootだけで再起動 - 手動介入なしでEasyMeshへ再参加
- 5GHz+6GHzの2-link MLOへ自動復帰
- Ethernet端末間の
iperf3で約0.94Gbps - 転送中に5GHz、6GHz双方のdriver byte counterが増加
まで確認した。
最初の記事を書いたときには「次はMLO」と書いていたが、本当にそこまで来た。
MLOで最初にハマったところ
MLOそのものは、一時的にはかなり早い段階で立ち上がった。
Agent側では、
mld_sta257
ref_cnt = 2
primary = 1
secondary = 2
となり、
band_idx = 1
band_idx = 2
の2リンクが見える。
構成としては概ね、
T6A Controller
5GHz rai2 ─┐
├─ AP MLD
6GHz rax2 ─┘
⇅
5GHz apclii0 ─┐
├─ STA MLD
6GHz apclix0 ─┘
T6B Agent
という状態まで到達した。
ところが、MLO link setup直後に接続が落ちる。
当初はwappやEasyMesh側の状態遷移を疑ったが、ログを時系列で追うと、実際の切断原因は別だった。
原因は5GHz側と6GHz側のRSNE不一致だった
T6B側のwpa_supplicantログでは、MLO setup後の4-way handshake中に、
RX message 3/4
M3 IE does not match Beacon/ProbeResp IE (RSNE)
Request to deauthenticate reason=1
という流れになっていた。
調べると、5GHz側と6GHz側でセキュリティ条件が揃っていなかった。
5GHz側は実行時に、
WPA2-PSK系
PMF optional相当
へ戻されていた。
一方、6GHz側は、
SAE
PMF required
だった。
MLOとして束ねる2リンクなのにRSNE条件が一致していない。
そこで5GHz側も、
SAE
PMF required
へ揃えた。
ただし、UCIだけ変更してもEasyMeshのruntime provisioningで元へ戻る。
最終的には、EasyMesh側のBSS profile生成元も合わせて変更し、5GHz側が実際のhostapd上でも、
wpa=2
key_mgmt=SAE
pairwise=CCMP
になることを確認した。
変更後は、
RX message 1/4
RX message 3/4
Sending EAPOL-Key 4/4
WPA: Key negotiation completed
CTRL-EVENT-CONNECTED
まで正常に進み、それまで出ていたRSNE mismatchとreason=1 deauthが消えた。
5GHz+6GHzの2-link MLOを確認
成功後のT6Bでは、debugfsから、
mld_sta257
ref_cnt : 2
primary : 1
secondary : 2
を確認できた。
さらに、
band_idx : 1
band_idx : 2
となる。
今回の対応では、
band_idx 1 = 5GHz
band_idx 2 = 6GHz
だった。
対応するSTA interfaceは、
5GHz = apclii0
6GHz = apclix0
である。
以前の6GHz単独backhaulではapclix0だけが実質的に仕事をしていたが、MLO成功後は2リンクをまとめたSTA MLDとして動作する。
なお、secondary link側のLinux netdevだけを見るとcarrier=0など、直感に反する表示になる場合があった。
そのためMLO判定では、
netdevのcarrier表示だけ
ではなく、
mld_sta
ref_cnt
band_idx
driver counter
実トラフィック
を組み合わせて判断した。
再起動後も自動復帰した
一時的にMLOが成立するだけでは、実用上はまだ不十分である。
そこでT6Bに対して、設定変更やWi-Fi再起動などを一切行わず、
sync
reboot
だけを実行した。
その結果、
約170秒後 DHCP address再取得
約173秒後 EasyMesh topologyへ再参加
した。
SSHも通常起動の中で自動復帰した。
さらにSSH復帰直後には、
mld_sta257
ref_cnt=2
band_idx=1
band_idx=2
となり、5GHz+6GHzの2-link MLOへ手動介入なしで自動復帰した。
最初のMLO確認から少なくとも342秒以上、その状態を維持した。
また、再起動試験前後で主要な設定ファイルのhashを比較し、一致することも確認した。
つまり、
偶然runtime上に残ったMLO状態
ではなく、
通常boot sequenceから再現されるpersistentな構成
になったと判断している。
この端末は通常起動自体に約170秒かかるようで、LEDの挙動から見た普段の起動時間とも概ね一致する。
ルータ自身でiperf3すると約330~360Mbpsだった
MLO成功後、最初はT6A/T6B自身をiperf3 endpointとして測定した。
4 streamでは概ね、
A -> B
約330~350 Mbps
B -> A
約350~380 Mbps
程度だった。
MLOにしても、6GHz単独backhaul時と大きく変わらない。
一瞬、
MLOにしても速くないのでは?
と思った。
ただし、Controller側が報告するlink rateはもっと高い。
そこで、ルータ自身をiperf3 endpointにする測定がボトルネックになっている可能性を疑った。
PC同士をEthernetでつないで測り直した
そこで、T6A/T6Bの両側へPCをEthernet接続した。
測定用には本宅LANと重ならないよう、
192.168.25.0/24
を使用した。
構成は以下。
CF-FV1
192.168.25.100
│
│ 1GbE
│
T6B
))
)) 5GHz + 6GHz
)) EasyMesh backhaul MLO
((
((
T6A
│
│ 1GbE
│
Pavilion
192.168.25.101
この状態でPC間pingは、
10 packets transmitted
10 received
0% loss
RTT:
min 3ms
max 6ms
avg 4ms
となった。
そしてiperf3を実行した。
Ethernet端末間では約0.94Gbps出た
まず1 stream。
iperf3.exe -c 192.168.25.101
結果は、
sender 937 Mbits/sec
receiver 936 Mbits/sec
だった。
逆方向。
iperf3.exe -c 192.168.25.101 -t 20 -R
では、
sender 910 Mbits/sec
receiver 909 Mbits/sec
だった。
さらに10 stream。
iperf3.exe -c 192.168.25.101 -t 20 -P 10
では、
sender 945 Mbits/sec
receiver 941 Mbits/sec
逆方向、
iperf3.exe -c 192.168.25.101 -t 20 -P 10 -R
では、
sender 915 Mbits/sec
receiver 908 Mbits/sec
となった。
まとめると、
| 測定 | 実測 |
|---|---|
| 1 stream 正方向 | 936 Mbps |
| 1 stream 逆方向 | 909 Mbps |
| 10 stream 正方向 | 941 Mbps |
| 10 stream 逆方向 | 908 Mbps |
となる。
つまり、1GbEの実効上限近くまで到達した。
この結果から、T6A/T6B自身でiperf3を動かしたときの約330~360Mbpsは、無線backhaulそのものの上限ではなく、端末自身のCPU、TCP stack、offloadを含むlocal endpoint側の制約だった可能性が高い。
少なくとも今回の構成では、無線backhaulの限界より先に1GbE側が頭打ちになった。
したがって、
このMLO backhaulの最大性能は、今回の1GbE構成ではまだ測定できていない
というのが正確な結論になる。
本当に5GHzと6GHzの両方へ流れているか確認した
最後に、
0.94Gbps出ても、実は片方のradioだけで流れているのでは?
を確認した。
T6B側では、
apclii0 = 5GHz
apclix0 = 6GHz
である。
iperf3実行前後に、
/sys/class/net/apclii0/statistics/rx_bytes
/sys/class/net/apclii0/statistics/tx_bytes
/sys/class/net/apclix0/statistics/rx_bytes
/sys/class/net/apclix0/statistics/tx_bytes
を採取した。
FV1からPavilionへ約20秒のiperf3を流した結果、T6B側TX counterは、
5GHz apclii0:
+1,584,971,776 bytes
6GHz apclix0:
+867,787,328 bytes
増加した。
合計すると、
約2.45GB
になる。
20秒換算ではdriver counter上で約981Mbps相当となり、iperf3の実効値約0.94Gbpsに各種overheadを加えた値として不自然ではない。
また、今回のcounter差分では概ね、
5GHz 約65%
6GHz 約35%
に分散していた。
比率は固定値とは限らず、radio conditionやschedulerによって変動すると考えられる。
重要なのは、約0.94Gbpsの実データ転送中に5GHzと6GHz双方のbyte counterが大きく増加したことである。
つまり、
2-link MLOとして接続表示されている
だけではなく、
実際のEthernet転送が5GHz、6GHz双方へ分散して流れている
ところまで確認できた。
追記後の成功条件
最初の記事では、
6GHz単独backhaul
を成功地点としていた。
その後、成功条件はここまで伸びた。
[Controller]
DeviceRole = 1
MapMode = 1
[Agent]
DeviceRole = 2
MapMode = 1
[MLO]
mld_sta257
ref_cnt = 2
5GHz:
band_idx = 1
apclii0
6GHz:
band_idx = 2
apclix0
[persistence]
T6Bを通常reboot
手動介入なし
EasyMesh topologyへ自動再参加
2-link MLOへ自動復帰
[data plane]
Ethernet端末間ping成功
iperf3 約0.91~0.94Gbps
[driver counter]
5GHzと6GHz双方へ実traffic
ここまで揃って、現在は、
SoftBank Air ターミナル6を2台使った、5GHz+6GHz EasyMesh backhaul MLOの永続動作を確認
と書いてよい状態になった。
追記まとめ
最初は、
6GHz単独EasyMesh backhaul
までだった。
その後、
5GHz+6GHz 2-link MLO
へ進み、
RSNE不一致の原因特定
↓
5GHz/6GHzのsecurity条件統一
↓
MLO安定化
↓
persistent化
↓
通常reboot後の自動復帰
↓
Ethernet端末間iperf3 約0.94Gbps
↓
5GHz/6GHz双方への実traffic確認
まで到達した。
個人的に一番面白かったのは、MLOそのものを有効にすることより、
一瞬成立したMLOがなぜ約100ms後に落ちるのか
をログから追ったところだった。
結果として、EasyMesh daemonの大きな仕組みではなく、4-way handshake中のRSNE不一致という、かなり具体的な一点に原因を絞ることができた。
そして最後のiperf3では、無線側より先に1GbEが限界になった。
この箱、まだ先があるらしい。
ただし物理Ethernetが1GbEなので、次に無線backhaulそのものの上限を測ろうとすると、今度は測定方法から考える必要がある。
ひとまず、
6GHz単独backhaul成功
から始まったこの記事の続きとしては、ここをフィナーレにしたい。