Skip to content

feat: runtime Wi-Fi AP/STA mode switch for AIC8800 on SG2002 (LicheeRV Nano)#1266

Merged
ZR233 merged 2 commits into
rcore-os:devfrom
BattiestStone4:feat/wifi-mode-switch
Jun 16, 2026
Merged

feat: runtime Wi-Fi AP/STA mode switch for AIC8800 on SG2002 (LicheeRV Nano)#1266
ZR233 merged 2 commits into
rcore-os:devfrom
BattiestStone4:feat/wifi-mode-switch

Conversation

@BattiestStone4

Copy link
Copy Markdown
Contributor

背景

本 PR 在 #1185(SG2002 AIC8800 Wi-Fi SoftAP)的基础上,为 wlan0 增加运行时
AP↔STA 模式切换
能力:无需重启,即可在 SoftAP 与 Station 之间切换。切换通过标准
Linux wireless-extensions ioctl 路径驱动,网络栈保持 link-agnostic——所有无线
相关细节仍收敛在 WifiControl trait 之后,延续 #1185 的分层设计。

一次切换的完整控制面链路:

wifi_switch (SIOCSIW* + COMMIT)
  → StarryOS socket ioctl       (kernel/src/file/wext.rs)
  → ax_net::reconfigure_wifi
      → rd_net::WifiControlHandle → aic8800 WifiControl   (VIF 拆除 + 切换)
      → Service::reconfigure_as_{ap,sta}                  (IPv4 / DHCP 角色)

变更内容

驱动层(aic8800 / rd-net)

  • aic8800:在重建 VIF 前执行 MM_REMOVE_IF 拆除 + teardown_vif(),使反复
    STA/AP 切换能干净复用同一个 vif_idx
  • rd-net:WifiControlHandleNet 被数据面驱动接管之前克隆设备的
    Arc<NetInner>,使控制面在独立的 task/syscall 上下文中仍可达。

网络栈集成(ax-net)

  • 新增按接口名索引的 WIFI_CONTROLS 注册表与 reconfigure_wifi() 入口。
  • Service::reconfigure_as_{ap,sta} 仅切换 IPv4/DHCP 角色,不触碰链路细节。

系统调用(StarryOS)

  • wext.rs 处理 SIOCSIW{MODE,ESSID,ENCODEEXT,FREQ}(暂存)+ SIOCSIWCOMMIT
    (经 ax_net::reconfigure_wifi 原子应用)。

演示工具

  • wifi_switch.c 用户态工具 + WIFI_SWITCH_DEMO.md

实现逻辑

模式切换被建模为"先暂存、后提交"的两阶段操作:SIOCSIWMODE/ESSID/ENCODEEXT/FREQ
只把目标参数暂存在内核侧,直到 SIOCSIWCOMMIT 才真正下发。提交时 reconfigure_wifi
先经 WifiControl 让 aic8800 拆除当前 VIF 并按新模式重建(STA 走真实 WPA2-PSK
四次握手,AP 则 APM_START),再由 Service 切换网络栈的 IPv4/DHCP 角色(STA 转
DHCP client,AP 恢复 192.168.50.1/24 + 单客户端 DHCP server)。整个过程网络栈
不感知具体芯片,延续 #1185 的 link-agnostic 边界。

构建与验证

cargo xtask starry build -c os/StarryOS/configs/board/licheerv-nano-sg2002-wifi.toml

已在 SG2002 / LicheeRV Nano 实板验证(默认启动态为 SoftAP PicoClaw-Car,
192.168.50.1/24,单客户端 DHCP server 分配 .2):

  • AP→STA→AP 往返:反复切换后 SoftAP 仍正常工作,VIF 拆除/重建干净,
    vif_idx 泄漏。
  • STA 连接 WPA2 网络:完成真实 WPA2-PSK 四次握手并关联成功,经 DHCP
    client 获取地址,可 ping 通网关。
  • STA 连接开放网络:无密码网络关联成功并获取 DHCP 地址。
  • AP 模式:外部手机/笔记本可搜索到 PicoClaw-Car,经 DHCP 获得 .2,
    可 ping 通 192.168.50.1

已知限制

  • STA 关联走真实 WPA2-PSK 四次握手;WPA3/SAE 尚未实现
  • AP 与 STA 互斥,暂不支持并行 AP+STA。

Add runtime Wi-Fi mode switching for the aic8800 SoftAP/STA on sg2002,
driven through the standard Linux wireless-extensions ioctl path. The
network stack stays link-agnostic (PR rcore-os#1185 design): all wireless
specifics stay behind the WifiControl trait.

- aic8800: MM_REMOVE_IF teardown + teardown_vif() before re-creating the
  VIF, so repeated STA/AP switches reuse one vif_idx cleanly.
- rd-net: WifiControlHandle clones the device's Arc<NetInner> before the
  Net is consumed into the data-plane driver, keeping the control plane
  reachable from a separate task/syscall context.
- ax-net: name-indexed WIFI_CONTROLS registry + reconfigure_wifi() entry
  point; Service::reconfigure_as_{ap,sta} swap IPv4/DHCP role only.
- StarryOS: wext.rs handles SIOCSIW{MODE,ESSID,ENCODEEXT,FREQ} (staged)
  + SIOCSIWCOMMIT (atomic apply via ax_net::reconfigure_wifi).
- demo: wifi_switch.c userspace tool + WIFI_SWITCH_DEMO.md.

STA association performs a real WPA2-PSK 4-way handshake; WPA3/SAE is
not implemented yet.
CI 'Check formatting / run_host' failed on the mode-switch commit:
rustfmt reformats the WifiControlHandle .then() closure (rd-net) and the
reconfigure_wifi() call sites + byte-collect chain (wext.rs). No logic
change. sync-lint passed locally (182 packages); its CI failure was a
fail-fast cancellation triggered by the fmt failure, not a real lint.

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 审查总结

变更概述

本 PR 在 #1185(SG2002 AIC8800 Wi-Fi SoftAP)基础上,为 wlan0 增加运行时 AP↔STA 模式切换能力。通过标准 Linux wireless-extensions ioctl 路径驱动,采用「先暂存、后提交」两阶段操作模型:SIOCSIWMODE/ESSID/ENCODEEXT/FREQ 只暂存参数到内核侧 PENDING 表,SIOCSIWCOMMIT 原子应用全部变更。

变更涉及 13 个文件(+842/-6),涵盖四层:

  • 驱动层(aic8800 / rd-net):新增 MM_REMOVE_IF 拆除 + teardown_vif()WifiControlHandleNet 消费前克隆 Arc<NetInner>
  • 网络栈(ax-net):WIFI_CONTROLS 注册表 + reconfigure_wifi() 入口 + Service::reconfigure_as_{ap,sta}
  • 内核(StarryOS wext.rs):wireless-extensions ioctl 处理
  • 演示工具wifi_switch.c + WIFI_SWITCH_DEMO.md

实现逻辑评价

分层设计延续 #1185 的 link-agnostic 边界,网络栈不感知具体芯片。teardown_vif() 的 VIF 生命周期管理正确(先尽力 disconnect,再 REMOVE_IF,最后复位 vif_idx/sta_idx 到 0xFF)。WIFI_CONTROLSNet 消费前捕获控制面句柄的设计合理。Service 的 AP/STA 重配正确处理了 DHCP 客户端/服务器状态转换。

本地验证

  • cargo fmt --check ✅ 通过
  • cargo fmt --check ✅ 无格式问题
  • [patch.crates-io] 检查 ✅ 未引入 crates.io patch
  • git diff --stat origin/dev...HEAD ✅ 变更范围与 PR 描述一致

CI 状态

CI workflow run: 27527190735

实际运行的检查全部通过

  • Check formatting / run_host: ✅
  • Run sync-lint / run_container: ✅
  • Run clippy / run_host: ✅
  • Test with std / run_host: ✅
  • Test starry x86_64/aarch64/loongarch64 qemu: ✅
  • Test axvisor riscv64/aarch64/loongarch64 qemu: ✅
  • Test axvisor self-hosted x86_64: ✅
  • Test axvisor board roc-rk3568-pc-linux/orangepi-5-plus-linux: ✅

跳过的检查属于预期的 CI 矩阵路径过滤(run_host/run_container 互斥对、container publish 等),非 PR 引入的 CI 问题。workflow 级别显示 failure 是 GitHub Actions 对跳过矩阵条目的汇总行为,不影响实际通过状态。

重复/重叠分析

  • 前序 PR #1185(已合并):添加了 AIC8800 SoftAP 基础支持,本 PR 在其之上扩展运行时模式切换,不重复
  • 其他 open PR(#1265 串口 IRQ 重构等):与本 PR 改动范围无重叠
  • 本 PR 是 #1185 的自然延续,无冲突风险

无阻塞发现

  • 代码质量良好,分层清晰
  • 无 crates.io patch
  • 无合并冲突(mergeable: true
  • CI 全部实际检查通过
  • 无未解决的 review thread
  • 作者已在 SG2002 实板验证 AP→STA→AP 往返、WPA2 关联、开放网络关联、DHCP 等

Wi-Fi 硬件行为仅能在物理板上验证(SG2002/LicheeRV Nano),这是驱动代码的合理限制。共享的内核和网络栈代码已由 CI QEMU 测试覆盖。

Powered by mimo-v2.5-pro

@ZR233 ZR233 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

变更内容

本 PR 在 #1185(SG2002 AIC8800 SoftAP)的基础上,为 wlan0 增加运行时 AP↔STA 模式切换,走标准 Linux wireless-extensions ioctl 路径,网络栈保持 link-agnostic:

  • aic8800:新增 teardown_vif() + MM_REMOVE_IF_REQ,在重建 VIF 前拆除旧 VIF,使反复 STA/AP 切换能干净复用同一个 vif_idx(复位 vif_idx/sta_idx/缓存 MAC,避免固件侧 VIF 泄漏)。
  • rd-net:新增 WifiControlHandle,在 Net 被数据面消费前克隆同一份 Arc<NetInner>,使控制面在独立 task/syscall 上下文仍可达。
  • ax-net:新增按名索引的 WIFI_CONTROLS 注册表 + reconfigure_wifi() 入口;Service::reconfigure_as_{ap,sta} 仅切换 IPv4/DHCP 角色,不触碰链路细节。
  • StarryOS:wext.rs 处理 SIOCSIW{MODE,ESSID,ENCODEEXT,FREQ}(暂存)+ SIOCSIWCOMMIT(原子应用)。
  • demo:wifi_switch.c + WIFI_SWITCH_DEMO.md

实现逻辑评价

分层清晰,延续 #1185 的 link-agnostic 边界。几个并发/所有权点已确认合理:

  1. reconfigure_wifi 先释放注册表锁再做阻塞的 WifiControl 调用(lib.rs:380-396),不会在阻塞固件命令路径上同时持有 WIFI_CONTROLSSERVICE 两把锁。
  2. WifiControlHandle&mut 别名:wifi_control()&mut **interface.get() 拿到 &mut dyn WifiControl,与 IRQ handler / OOB poll task / 数据面 TX/RX 队列共享同一份 Arc<NetInner>::UnsafeCell<Interface>。这正是 base #1185 既有路径(irq_handlerreceiveprepare_send)的既有别名模型,本 PR 没有引入新的别名来源;模式切换由 syscall/task 上下文发起且与 poll_interfaces() 串行,符合 handle 注释所述约束。
  3. teardown_vif 状态机:先尽力 disconnect(失败不阻断),再 MM_REMOVE_IF_REQ,最后复位驱动侧 vif_idx=0xFF/sta_idx=0xFF/ap_mac=None;无有效 VIF 时为安全空操作。逻辑自洽。
  4. wext 暂存-提交两阶段:setter 只写 per-ifname 的 PENDING,只有 COMMIT 才下发;ifname 取自 iwreq.ifrn_name,与 register_wifi_control(name, ...)(devices.rs 用 &'static str)的命名一致。

验证

  • 构建/clippy:cargo xtask starry build -c os/StarryOS/configs/board/licheerv-nano-sg2002-wifi.toml 在本地通过(riscv64,产出 .uimg,含 starry-kernel + ax-net + aic8800)。cargo xtask clippy --package ax-net/rd-net/aic8800 全部通过,cargo fmt --check 通过。无 [patch.crates-io]
  • demo 工具:按文档 riscv64-linux-musl-gcc -static -O2 -o wifi_switch wifi_switch.c 编译通过(static-PIE riscv64 ELF);WIFI_SWITCH_DEMO.md 的准备工作/上板命令/成功判据完整可执行。
  • CI 状态(head c03c9a9):本次唯一真实失败是 Test starry riscv64 qemu / run_container,失败发生在 qemu-smp4/systembug-sched-affinity-pid(TEST START: sched affinity respects pid)挂起到 1800s 超时 —— 属调度器 affinity 测试,与本 PR 的 Wi-Fi/wext/ax-net/aic8800 改动面无关,且与既有 issue #1215(ci(starry): riscv64 qemu-smp4 system hangs in bug-sched-affinity-pid)描述完全一致。已在 #1215 追加本 PR 的复现证据(run/job 链接 + 失败模式)。其余 starry x86_64/aarch64/loongarch64 qemu、ax-net/aic8800 clippy、axvisor/board 各 job 均通过。Test starry self-hosted board licheerv-nano-sg2002 显示 fail 实为 step 5 cancelled(运行被取消),非真实失败。
  • 运行时行为:真实模式切换(WPA2-PSK 四次握手、AP↔STA 往返)依赖 AIC8800 芯片与真实 AP,只能在 SG2002 实板验证,QEMU 无 Wi-Fi 设备无法复现。PR 正文已提供板级证据(AP↔STA 往返、STA WPA2/开放网络关联+DHCP、AP 被 DHCP .2),作为 board-only 验证可接受。

重复/重叠

已用 WifiControlHandle/reconfigure_wifi/wext/aic8800 wext 多组关键词检索 base dev 与全部 open PR:base 无任何运行时模式切换/reconfigure_wifi/WifiControlHandle 实现,open PR 中也无重叠项,本 PR 是该能力的首次引入,与 #1185(SoftAP bring-up)互补而非重复。

非阻断建议(供后续)

  • 栈侧 Service::reconfigure_as_{ap,sta} 的 IPv4/DHCP 角色切换理论上可借助既有 test_support/LoopbackDevice 补一个 host 侧单测(不依赖芯片),目前 ax-net 无对应单测。非阻断,因该面由设备驱动触发且已在板级验证。
  • _write_iwreq_data#[allow(dead_code)] 是未来回写型 setter 的占位,可接受。

结论

分层合理、所有权/锁模型自洽、文档命令可复现、构建与 clippy 通过;唯一 CI 失败为既有 riscv64 bug-sched-affinity-pid 超时(issue #1215),与本 PR 无关。真实 Wi-Fi 切换为 board-only 能力,PR 已提供板级证据。准予合入。

@ZR233
ZR233 merged commit e03b5e3 into rcore-os:dev Jun 16, 2026
98 of 100 checks passed
fzg-23 pushed a commit to fzg-23/tgoskits that referenced this pull request Jun 16, 2026
…V Nano) (rcore-os#1266)

* feat(wifi): runtime AP<->STA mode switch via wireless-extensions ioctl

Add runtime Wi-Fi mode switching for the aic8800 SoftAP/STA on sg2002,
driven through the standard Linux wireless-extensions ioctl path. The
network stack stays link-agnostic (PR rcore-os#1185 design): all wireless
specifics stay behind the WifiControl trait.

- aic8800: MM_REMOVE_IF teardown + teardown_vif() before re-creating the
  VIF, so repeated STA/AP switches reuse one vif_idx cleanly.
- rd-net: WifiControlHandle clones the device's Arc<NetInner> before the
  Net is consumed into the data-plane driver, keeping the control plane
  reachable from a separate task/syscall context.
- ax-net: name-indexed WIFI_CONTROLS registry + reconfigure_wifi() entry
  point; Service::reconfigure_as_{ap,sta} swap IPv4/DHCP role only.
- StarryOS: wext.rs handles SIOCSIW{MODE,ESSID,ENCODEEXT,FREQ} (staged)
  + SIOCSIWCOMMIT (atomic apply via ax_net::reconfigure_wifi).
- demo: wifi_switch.c userspace tool + WIFI_SWITCH_DEMO.md.

STA association performs a real WPA2-PSK 4-way handshake; WPA3/SAE is
not implemented yet.

* style(wifi): apply rustfmt to mode-switch changes

CI 'Check formatting / run_host' failed on the mode-switch commit:
rustfmt reformats the WifiControlHandle .then() closure (rd-net) and the
reconfigure_wifi() call sites + byte-collect chain (wext.rs). No logic
change. sync-lint passed locally (182 packages); its CI failure was a
fail-fast cancellation triggered by the fmt failure, not a real lint.
This was referenced Jun 22, 2026
luodeb pushed a commit that referenced this pull request Jun 30, 2026
…V Nano) (#1266)

* feat(wifi): runtime AP<->STA mode switch via wireless-extensions ioctl

Add runtime Wi-Fi mode switching for the aic8800 SoftAP/STA on sg2002,
driven through the standard Linux wireless-extensions ioctl path. The
network stack stays link-agnostic (PR #1185 design): all wireless
specifics stay behind the WifiControl trait.

- aic8800: MM_REMOVE_IF teardown + teardown_vif() before re-creating the
  VIF, so repeated STA/AP switches reuse one vif_idx cleanly.
- rd-net: WifiControlHandle clones the device's Arc<NetInner> before the
  Net is consumed into the data-plane driver, keeping the control plane
  reachable from a separate task/syscall context.
- ax-net: name-indexed WIFI_CONTROLS registry + reconfigure_wifi() entry
  point; Service::reconfigure_as_{ap,sta} swap IPv4/DHCP role only.
- StarryOS: wext.rs handles SIOCSIW{MODE,ESSID,ENCODEEXT,FREQ} (staged)
  + SIOCSIWCOMMIT (atomic apply via ax_net::reconfigure_wifi).
- demo: wifi_switch.c userspace tool + WIFI_SWITCH_DEMO.md.

STA association performs a real WPA2-PSK 4-way handshake; WPA3/SAE is
not implemented yet.

* style(wifi): apply rustfmt to mode-switch changes

CI 'Check formatting / run_host' failed on the mode-switch commit:
rustfmt reformats the WifiControlHandle .then() closure (rd-net) and the
reconfigure_wifi() call sites + byte-collect chain (wext.rs). No logic
change. sync-lint passed locally (182 packages); its CI failure was a
fail-fast cancellation triggered by the fmt failure, not a real lint.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants