NETMGR_DESIGN.md 期1范围(→ M6.0)落地: - meow_netmgrd 守护:svcd 托管 trigger=boot/restart=on-fail,进程内 HibyOS 只读降级 (/tmp/meow_boot_mode != meow → 读可查/写拒+日志,热切换)。 - 接口统一层(§3):iface 枚举(/sys/class/net+/proc/net/dev,lo/wlan0/usb-eth 热插拔节拍检测); WiFi 状态/扫描/网络列表/连接/断开(wpa_cli popen 有界收割防挂死,257 教训);IP/路由/DNS 只读 (ip 优先 /proc/net/route+resolv.conf);BT 状态/开关/已配对(hciconfig/bluetoothctl);rfkill 读写;udhcpc 续租/释放(MeowOS)。 - IPC 0x00E0-0x00E7(STATUS/IFACE/WIFI_CTL/BT_CTL+各自 RESULT):读级任意、写级仅系统身份(SO_PEERCRED 同 svc_power),0xE8-0xEF 期2/3 预留(仅注释)。 - CLI 双形态 meow_net(status/iface/wifi/bt/rfkill/help):IPC 薄壳,help 本地必可用。 - 日志框架:TF MeowOS/logs/net_<bootts>.log(无卡降级 /tmp),接口状态变化/写操作必记。 - 单线程 poll、静态表、热路径禁 malloc;mipsel 静态(0 warning),宿主+qemu-mipsel 全过, 真机只读验证 status/wifi scan/bt status 正确。 meow_ipc.h 仅追加 0x00E0-0x00E7 段(不改既有行)。
165 lines
6.9 KiB
Bash
Executable File
165 lines
6.9 KiB
Bash
Executable File
#!/bin/bash
|
||
# test_netmgrd.sh — meow_netmgrd 宿主桩测试(假 sysfs/procfs 节点 + 桩后端命令,MEOW_* env 覆盖)。
|
||
# 用法:./test_netmgrd.sh [host二进制路径](默认 ./meow_netmgrd_host;可传 mipsel 二进制 + QEMU 前缀)
|
||
# QEMU="qemu-mipsel" ./test_netmgrd.sh ./meow_netmgrd # qemu 验证
|
||
set -u
|
||
cd "$(dirname "$0")"
|
||
BIN="${1:-./meow_netmgrd_host}"
|
||
Q="${QEMU:-}"
|
||
T=$(mktemp -d /tmp/netmgrdtest.XXXXXX)
|
||
trap 'kill $DPID 2>/dev/null; rm -rf "$T"' EXIT
|
||
PASS=0; FAIL=0
|
||
ck() { # ck <名> <期望子串> <实际>
|
||
if echo "$3" | grep -qF "$2"; then PASS=$((PASS+1)); echo "PASS $1";
|
||
else FAIL=$((FAIL+1)); echo "FAIL $1: 期望含 [$2] 实际=[$3]"; fi
|
||
}
|
||
|
||
# ---- 搭假节点 ----
|
||
NET="$T/net"; RF="$T/rfkill"; BT="$T/bt"
|
||
mkdir -p "$NET/lo" "$NET/wlan0" "$RF/rfkill0" "$RF/rfkill1" "$BT/hci0"
|
||
echo up > "$NET/lo/operstate"
|
||
echo up > "$NET/wlan0/operstate"
|
||
echo wlan > "$RF/rfkill0/type"; echo 0 > "$RF/rfkill0/soft"; echo 0 > "$RF/rfkill0/hard"
|
||
echo bluetooth > "$RF/rfkill1/type"; echo 1 > "$RF/rfkill1/soft"; echo 0 > "$RF/rfkill1/hard"
|
||
echo 00:1A:7D:DA:71:13 > "$BT/hci0/address"
|
||
echo on > "$BT/hci0/power"
|
||
cat > "$T/netdev" <<'EOF'
|
||
Inter-| Receive | Transmit
|
||
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
||
lo: 1000 10 0 0 0 0 0 0 1000 10 0 0 0 0 0 0
|
||
wlan0: 5000000 5000 0 0 0 0 0 0 1000000 1000 0 0 0 0 0 0
|
||
EOF
|
||
cat > "$T/route" <<'EOF'
|
||
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||
wlan0 005EC20A 6F3DC20A 0003 0 0 0 00FFFFFF 0 0 0
|
||
lo 0100007F 00000000 0001 0 0 0 000000FF 0 0 0
|
||
EOF
|
||
printf 'nameserver 223.5.5.5\nnameserver 10.78.193.1\n' > "$T/resolv"
|
||
echo meow > "$T/boot_mode"
|
||
|
||
# 桩后端命令(popen stubbing)
|
||
cat > "$T/wpa_cli" <<'EOF'
|
||
#!/bin/sh
|
||
case "$1" in
|
||
status) echo "wpa_state=COMPLETED"; echo "ssid=MyWiFi"; echo "ip_address=10.78.193.50"; echo "signal=-45";;
|
||
scan) echo OK;;
|
||
scan_results) printf 'bssid / frequency / signal level / flags / ssid\nxx:xx / 2412 / -50 / WPA2 / TestAP\n';;
|
||
list_networks) printf 'network id / ssid / bssid / flags\n0\tMyWiFi\tany\t[CURRENT]\n';;
|
||
add_network) echo 1;;
|
||
set_network) echo OK;;
|
||
enable_network) echo OK;;
|
||
select_network) echo OK;;
|
||
disconnect) echo OK;;
|
||
esac
|
||
exit 0
|
||
EOF
|
||
cat > "$T/hciconfig" <<'EOF'
|
||
#!/bin/sh
|
||
echo "hci0: Type: Primary Bus: USB"
|
||
echo " BD Address: 00:1A:7D:DA:71:13 ACL MTU: 1021:8 SCO MTU: 64:1"
|
||
echo " UP RUNNING PSCAN"
|
||
EOF
|
||
cat > "$T/bluetoothctl" <<'EOF'
|
||
#!/bin/sh
|
||
echo "Device 00:1A:7D:DA:71:13 My Headset"
|
||
echo "Device 11:22:33:44:55:66 Speaker"
|
||
EOF
|
||
cat > "$T/ip" <<'EOF'
|
||
#!/bin/sh
|
||
for a in "$@"; do
|
||
if [ "$a" = "wlan0" ]; then echo "2: wlan0 inet 10.78.193.50/24 brd 255.255.255.255 scope global wlan0"; fi
|
||
if [ "$a" = "lo" ]; then echo "1: lo inet 127.0.0.1/8 scope host lo"; fi
|
||
done
|
||
exit 0
|
||
EOF
|
||
for f in wpa_cli hciconfig bluetoothctl ip; do chmod +x "$T/$f"; done
|
||
|
||
mkdir -p "$T/logs" "$T/pid"
|
||
ENVS="MEOW_NET_DIR=$NET MEOW_NETDEV=$T/netdev MEOW_NET_ROUTE=$T/route MEOW_RESOLV=$T/resolv
|
||
MEOW_RFKILL_DIR=$RF MEOW_BT_DIR=$BT MEOW_BOOT_MODE=$T/boot_mode MEOW_BOOTTS_CACHE=$T/bootts
|
||
MEOW_IP=$T/ip MEOW_WPA_CLI=$T/wpa_cli MEOW_HCICONFIG=$T/hciconfig MEOW_BLUETOOTHCTL=$T/bluetoothctl
|
||
MEOW_NET_SOCK=$T/net.sock MEOW_NET_POLL_SEC=1 MEOW_LOG_DIR=$T/logs"
|
||
ln -sf "$(readlink -f "$BIN")" "$T/meow_net" # argv[0] 双形态 → CLI
|
||
|
||
# ---- T0: 守护起 ----
|
||
env $ENVS $Q "$BIN" --sock "$T/net.sock" >"$T/daemon.log" 2>&1 &
|
||
DPID=$!
|
||
for i in $(seq 1 30); do [ -S "$T/net.sock" ] && break; sleep 0.2; done
|
||
[ -S "$T/net.sock" ] || { echo "FAIL T0: daemon socket 未出现"; cat "$T/daemon.log"; exit 1; }
|
||
PASS=$((PASS+1)); echo "PASS T0 daemon up"
|
||
|
||
# ---- T1: status(读级,任意调用者)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T1a "mode=meow src=daemon" "$OUT"
|
||
ck T1b "iface:lo kind=lo up=true" "$OUT"
|
||
ck T1c "iface:wlan0 kind=wifi up=true" "$OUT"
|
||
ck T1d "ip=10.78.193.50" "$OUT" # 若 iface 行 ip 解析成功(ip 桩已修)——实际由 wlan gw 行给,见下
|
||
ck T1e "gw=10.194.61.111" "$OUT"
|
||
ck T1f "wifi connected=1 state=COMPLETED ssid=MyWiFi" "$OUT"
|
||
ck T1g "bt available=1 powered=1 address=00:1A:7D:DA:71:13 paired=2" "$OUT"
|
||
ck T1h "rfkill:wlan soft=0 hard=0" "$OUT"
|
||
ck T1i "rfkill:bluetooth soft=1 hard=0" "$OUT"
|
||
|
||
# ---- T2: iface 单/全 ----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" iface wlan0 2>&1)
|
||
ck T2a '"name":"wlan0"' "$OUT"
|
||
ck T2b '"kind":"wifi"' "$OUT"
|
||
ck T2c '"ip":"10.78.193.50"' "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" iface 2>&1)
|
||
ck T2d '"name":"lo"' "$OUT"
|
||
|
||
# ---- T3: wifi networks(读级)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" wifi networks 2>&1)
|
||
ck T3a "MyWiFi" "$OUT"
|
||
|
||
# ---- T4: wifi scan(写级;宿主 CLI=CALL_OTHER → 拒)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" wifi scan 2>&1)
|
||
ck T4a "permission denied" "$OUT"
|
||
|
||
# ---- T5: bt status / bt paired(读级)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" bt status 2>&1)
|
||
ck T5a "available=1 powered=1" "$OUT"
|
||
ck T5b "paired=2" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" bt paired 2>&1)
|
||
ck T5c "My Headset" "$OUT"
|
||
ck T5d "Speaker" "$OUT"
|
||
|
||
# ---- T6: HibyOS 只读降级(读可查,写拒)----
|
||
echo hiby > "$T/boot_mode"
|
||
sleep 2 # 等守护下一拍热切换
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T6a "mode=readonly" "$OUT"
|
||
ck T6b "iface:wlan0" "$OUT" # 读侧仍可查
|
||
OUT=$(env $ENVS $Q "$T/meow_net" wifi networks 2>&1)
|
||
ck T6c "MyWiFi" "$OUT" # 读级子命令仍可用
|
||
OUT=$(env $ENVS $Q "$T/meow_net" wifi on 2>&1); RC=$?
|
||
ck T6d "permission denied" "$OUT"
|
||
echo meow > "$T/boot_mode"
|
||
sleep 2
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T6e "mode=meow" "$OUT" # 热切换回全功能
|
||
|
||
# ---- T7: 守护日志(每次开机新文件;接口 add/写拒绝 必记)----
|
||
sleep 1
|
||
LOGS=$(ls "$T/logs"/net_*.log 2>/dev/null | head -1)
|
||
[ -n "$LOGS" ] && { PASS=$((PASS+1)); echo "PASS T7a log file: $(basename "$LOGS")"; } || { FAIL=$((FAIL+1)); echo "FAIL T7a 无日志文件"; }
|
||
[ -n "$LOGS" ] && { grep -q "iface add kind=wifi name=wlan0" "$LOGS" && { PASS=$((PASS+1)); echo "PASS T7b iface add 已记"; } || { FAIL=$((FAIL+1)); echo "FAIL T7b 未记 iface add"; }; }
|
||
|
||
# ---- T8: 守护停 → CLI help 本地可用;status 报守护不可达 ----
|
||
kill $DPID 2>/dev/null; wait $DPID 2>/dev/null; DPID=""
|
||
sleep 0.5
|
||
OUT=$(env $ENVS $Q "$T/meow_net" help 2>&1)
|
||
ck T8a "usage: meow_net" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T8b "守护不可达" "$OUT"
|
||
|
||
# ---- T9: 无参 → help;未知子命令 → usage ----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" 2>&1)
|
||
ck T9a "usage: meow_net" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" bogus 2>&1); RC=$?
|
||
ck T9b "usage: meow_net" "$OUT"
|
||
|
||
echo "=============================="
|
||
echo "PASS=$PASS FAIL=$FAIL"
|
||
[ $FAIL -eq 0 ]
|