嵌入式 Linux WiFi 框架完整篇:从cfg80211、mac80211 到wpa_supplicant

板子上插一块 WiFi 模组,用户态敲 iw / wpa_supplicant,内核里却常常分不清:nl80211、cfg80211、mac80211、厂商驱动、固件各自干啥。排障时「扫不到 AP」「连上没 IP」「吞吐只有几 Mbps」,也说不清卡在哪一层。

本文按嵌入式常见路径,把 Linux WiFi 软件栈 从用户态到硬件串成一条完整链路,覆盖 FullMAC / SoftMAC、扫描关联、数据收发、rfkill、设备树与调试手段,读完应对照源码与 iw 自己验证。

源码锚点

路径 作用
include/net/cfg80211.h struct cfg80211_opswiphy_newcfg80211_connect_*
net/wireless/ cfg80211 核心、nl80211
include/net/mac80211.h SoftMAC:struct ieee80211_opsieee80211_register_hw
net/mac80211/ SoftMAC:MLME、聚合、速率控制协作
include/uapi/linux/nl80211.h 用户态 ↔ 内核 Netlink 属性
include/linux/ieee80211.h 802.11 帧头、能力位
include/linux/rfkill.h 射频开关统一框架
Documentation/networking/mac80211* / wireless 内核文档

注册 SoftMAC 网卡(概念):

c 复制代码
/* include/net/mac80211.h */
struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
					const struct ieee80211_ops *ops);
int ieee80211_register_hw(struct ieee80211_hw *hw);

FullMAC / cfg80211 直连(概念):

c 复制代码
/* include/net/cfg80211.h */
struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv);
int wiphy_register(struct wiphy *wiphy);

先建立分层:谁管配置,谁管收发包

#mermaid-svg-XS5kOwFsrhOU7tXo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XS5kOwFsrhOU7tXo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XS5kOwFsrhOU7tXo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XS5kOwFsrhOU7tXo .error-icon{fill:#552222;}#mermaid-svg-XS5kOwFsrhOU7tXo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XS5kOwFsrhOU7tXo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XS5kOwFsrhOU7tXo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XS5kOwFsrhOU7tXo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XS5kOwFsrhOU7tXo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XS5kOwFsrhOU7tXo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XS5kOwFsrhOU7tXo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XS5kOwFsrhOU7tXo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XS5kOwFsrhOU7tXo .marker.cross{stroke:#333333;}#mermaid-svg-XS5kOwFsrhOU7tXo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XS5kOwFsrhOU7tXo p{margin:0;}#mermaid-svg-XS5kOwFsrhOU7tXo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XS5kOwFsrhOU7tXo .cluster-label text{fill:#333;}#mermaid-svg-XS5kOwFsrhOU7tXo .cluster-label span{color:#333;}#mermaid-svg-XS5kOwFsrhOU7tXo .cluster-label span p{background-color:transparent;}#mermaid-svg-XS5kOwFsrhOU7tXo .label text,#mermaid-svg-XS5kOwFsrhOU7tXo span{fill:#333;color:#333;}#mermaid-svg-XS5kOwFsrhOU7tXo .node rect,#mermaid-svg-XS5kOwFsrhOU7tXo .node circle,#mermaid-svg-XS5kOwFsrhOU7tXo .node ellipse,#mermaid-svg-XS5kOwFsrhOU7tXo .node polygon,#mermaid-svg-XS5kOwFsrhOU7tXo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XS5kOwFsrhOU7tXo .rough-node .label text,#mermaid-svg-XS5kOwFsrhOU7tXo .node .label text,#mermaid-svg-XS5kOwFsrhOU7tXo .image-shape .label,#mermaid-svg-XS5kOwFsrhOU7tXo .icon-shape .label{text-anchor:middle;}#mermaid-svg-XS5kOwFsrhOU7tXo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XS5kOwFsrhOU7tXo .rough-node .label,#mermaid-svg-XS5kOwFsrhOU7tXo .node .label,#mermaid-svg-XS5kOwFsrhOU7tXo .image-shape .label,#mermaid-svg-XS5kOwFsrhOU7tXo .icon-shape .label{text-align:center;}#mermaid-svg-XS5kOwFsrhOU7tXo .node.clickable{cursor:pointer;}#mermaid-svg-XS5kOwFsrhOU7tXo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XS5kOwFsrhOU7tXo .arrowheadPath{fill:#333333;}#mermaid-svg-XS5kOwFsrhOU7tXo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XS5kOwFsrhOU7tXo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XS5kOwFsrhOU7tXo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XS5kOwFsrhOU7tXo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XS5kOwFsrhOU7tXo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XS5kOwFsrhOU7tXo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XS5kOwFsrhOU7tXo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XS5kOwFsrhOU7tXo .cluster text{fill:#333;}#mermaid-svg-XS5kOwFsrhOU7tXo .cluster span{color:#333;}#mermaid-svg-XS5kOwFsrhOU7tXo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XS5kOwFsrhOU7tXo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XS5kOwFsrhOU7tXo rect.text{fill:none;stroke-width:0;}#mermaid-svg-XS5kOwFsrhOU7tXo .icon-shape,#mermaid-svg-XS5kOwFsrhOU7tXo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XS5kOwFsrhOU7tXo .icon-shape p,#mermaid-svg-XS5kOwFsrhOU7tXo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XS5kOwFsrhOU7tXo .icon-shape .label rect,#mermaid-svg-XS5kOwFsrhOU7tXo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XS5kOwFsrhOU7tXo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XS5kOwFsrhOU7tXo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XS5kOwFsrhOU7tXo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 内核数据面与驱动
内核配置面
用户态
SoftMAC
FullMAC
netif 收发
netif 收发
wpa_supplicant / hostapd / NetworkManager
iw / iwconfig
DHCP / 路由 / nftables
nl80211 Netlink
cfg80211
驱动类型?
mac80211 SoftMAC
FullMAC 厂商驱动
固件 Firmware
WiFi 硬件 / SDIO/USB/PCIe

一句话

  • cfg80211 + nl80211:统一「配置面」------扫描、关联、密钥、AP 模式、监管域。
  • mac80211 :SoftMAC 芯片由内核做大部分 802.11 MAC;驱动实现 ieee80211_ops(收发、队列、密钥等)。
  • FullMAC :MAC 多在固件;驱动主要实现 cfg80211_ops,把配置下到固件,并把网卡挂到网络栈。

嵌入式模组(如多数 SDIO WiFi)FullMAC 居多 ;部分 USB/PCIe 芯片走 SoftMAC。看驱动是否调用 ieee80211_register_hw 还是只 wiphy_register 即可判断。

调用链:从「连热点」到硬件

配置面:关联 AP

#mermaid-svg-Mhk8QrnCjuYAk0D4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .error-icon{fill:#552222;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .marker.cross{stroke:#333333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Mhk8QrnCjuYAk0D4 p{margin:0;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .cluster-label text{fill:#333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .cluster-label span{color:#333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .cluster-label span p{background-color:transparent;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .label text,#mermaid-svg-Mhk8QrnCjuYAk0D4 span{fill:#333;color:#333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .node rect,#mermaid-svg-Mhk8QrnCjuYAk0D4 .node circle,#mermaid-svg-Mhk8QrnCjuYAk0D4 .node ellipse,#mermaid-svg-Mhk8QrnCjuYAk0D4 .node polygon,#mermaid-svg-Mhk8QrnCjuYAk0D4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .rough-node .label text,#mermaid-svg-Mhk8QrnCjuYAk0D4 .node .label text,#mermaid-svg-Mhk8QrnCjuYAk0D4 .image-shape .label,#mermaid-svg-Mhk8QrnCjuYAk0D4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .rough-node .label,#mermaid-svg-Mhk8QrnCjuYAk0D4 .node .label,#mermaid-svg-Mhk8QrnCjuYAk0D4 .image-shape .label,#mermaid-svg-Mhk8QrnCjuYAk0D4 .icon-shape .label{text-align:center;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .node.clickable{cursor:pointer;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .arrowheadPath{fill:#333333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Mhk8QrnCjuYAk0D4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Mhk8QrnCjuYAk0D4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Mhk8QrnCjuYAk0D4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .cluster text{fill:#333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .cluster span{color:#333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Mhk8QrnCjuYAk0D4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .icon-shape,#mermaid-svg-Mhk8QrnCjuYAk0D4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .icon-shape p,#mermaid-svg-Mhk8QrnCjuYAk0D4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .icon-shape .label rect,#mermaid-svg-Mhk8QrnCjuYAk0D4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Mhk8QrnCjuYAk0D4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Mhk8QrnCjuYAk0D4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Mhk8QrnCjuYAk0D4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} wpa_supplicant: ADD_NETWORK / ENABLE
nl80211 CONNECT
cfg80211
cfg80211_ops.connect 或 auth/assoc
驱动下发固件 / SoftMAC MLME
cfg80211_connect_result / connect_bss
用户态得知已关联
DHCP 拿 IP

成功/失败必须回调:cfg80211_connect_result() / cfg80211_connect_bss() / cfg80211_connect_timeout()(见 cfg80211.h 注释约定)。驱动只「发出去不回报」会导致用户态一直卡住。

SoftMAC 数据面(示意)

text 复制代码
上层 IP 包 → netdev → mac80211 封装 802.11
  → ieee80211_ops.tx → 驱动 DMA/总线 → 射频

接收:硬件中断/NAPI → 驱动上报 → ieee80211_rx*
  → mac80211 解密/重组 → netif_receive_skb

FullMAC 数据面(示意)

text 复制代码
netdev.ndo_start_xmit → 驱动封装厂商协议 → SDIO/USB 写固件队列
固件完成 802.11;RX 路径反向,驱动把以太网帧交给协议栈

重点知识

1. cfg80211_ops:配置面契约

struct cfg80211_opsinclude/net/cfg80211.h)是驱动向 cfg80211 注册的后端。嵌入式最常碰到:

回调(概念) 作用
scan 扫描;完成后 cfg80211_scan_done
connect / disconnect SME 连接(FullMAC 常见)
auth / assoc 拆分认证关联(部分驱动)
add_key / del_key / set_default_key WPA/WPA2/WPA3 密钥
start_ap / stop_ap AP / SoftAP
set_wiphy_params RTS、分片等
set_power_mgmt 省电

驱动必须先 wiphy_new → 填能力(频段、cipher、interface modes)→ wiphy_register,再创建 wireless_dev / netdev。

2. mac80211 与 ieee80211_ops

SoftMAC 驱动实现 ieee80211_opsstart/stoptxadd_interfaceconfigbss_info_changedset_keyampdu_action 等。

mac80211 负责:beacon 处理、关联状态机、聚合、速率控制协作、与 cfg80211 对接。

注册:ieee80211_alloc_hw → 填 hw->wiphy 能力 → ieee80211_register_hw

3. nl80211 与用户态工具

工具 角色
iw 直接 nl80211:scan、link、reg、info
wpa_supplicant STA:扫描、WPA、漫游、与 DHCP 协作
hostapd AP
NetworkManager / connman 桌面/发行版集成

调试先确认内核侧:iw deviw phy,再查用户态配置,避免「驱动没起来却调 wpa」。

4. Interface 模式与并发

NL80211_IFTYPE_STATION / AP / MONITOR / P2P_* 等。嵌入式常要 STA+AP 并发 (手机热点同理),取决于固件/驱动是否声明组合能力(interface_combinations)。能力不够会出现「开 SoftAP 后 STA 掉线」。

5. 监管域 Regulatory

频段、功率受国家码约束。iw reg get / iw reg set CN;设备树或驱动也可带默认 regdomain。错误监管会导致「扫不到 5G」或非法信道。

6. rfkill

rfkill 统一软/硬射频开关。rfkill list;硬开关(机身拨码)会 block WiFi。现象:驱动加载了但 iw 扫描失败、日志有 rfkill。

7. 总线与固件(嵌入式痛点)

总线 关注点
SDIO 时钟、电源时序、MMC 控制器、mmc 报错
USB 电流、hub、固件加载超时
PCIe ASPM、BAR、MSI

固件路径通常 /lib/firmware/...;缺失则 probe 失败。看 dmesgDirect firmware load ... failed

设备树示例要素(概念):兼容字符串、interruptvmmc/vqmmc 电源、pinctrl、校准数据分区。

8. 安全与加密

WPA2-PSK / WPA3-SAE 密钥下发走 add_key;PMF、SAE 依赖驱动/固件能力位。嵌入式旧模组常「能连 WPA2、不能 WPA3」。

9. 性能与省电

  • 吞吐 :聚合 AMPDU、总线带宽、CPU 软中断、txqueue
  • 延迟:省电 PS / uAPSD 会换延迟;产线测吞吐时常关省电。
  • 天线 / 校准:校准数据错误 → RSSI 差、易掉线。

10. 排障路径

现象 先查
无 wlan0 probe、固件、设备树、rfkill
扫不到 AP 监管域、天线、区域、驱动 scan 回调
关联失败 密钥、超时回调、固件崩溃
有 link 无 IP 上层 DHCP/网络命名空间,非 WiFi MAC
吞吐差 总线、省电、干扰、信道宽

常用命令:

bash 复制代码
dmesg | grep -iE 'wlan|firmware|cfg80211|brcm|nl80211'
ip link; iw dev; iw phy
rfkill list
iw dev wlan0 scan | head
iw dev wlan0 link
cat /sys/kernel/debug/ieee80211/*/stations/*/rc_stats 2>/dev/null  # SoftMAC 示例

Checklist

  • 能画出:用户态 → nl80211 → cfg80211 → FullMAC/mac80211 → 固件 → 硬件
  • 能判断本板驱动是 FullMAC 还是 SoftMAC
  • 关联路径上知道必须有 cfg80211_connect_* 类结果回调
  • 会用 iw / rfkill / dmesg 区分「没模组」与「上层配置错」
  • 清楚 STA/AP 并发依赖 interface_combinations
  • 查过固件路径与设备树电源/中断
  • 吞吐问题先排除省电与总线,再查 802.11 层

成稿:articles/csdn-merged/嵌入式Linux-WiFi框架完整篇.md

相关推荐
吴声子夜歌1 小时前
Linux命令——打印
linux·运维·服务器
Jae den1 小时前
负载均衡到底解决什么问题?
运维·负载均衡
企鹅的蚂蚁1 小时前
Linux 开发板串口调试:picocom 从识别到退出的完整用法
linux·运维·服务器
山岚的运维笔记1 小时前
mysql 专业笔记 -- 第 17 章:连接:连接三个具有相同名称 ID 的表
运维·数据库·笔记·后端·学习·mysql·dba
bksczm2 小时前
从 “什么是 MySQL“ 到库与表的完整操作(MySQL基础篇)
linux·数据库·mysql
企鹅的蚂蚁2 小时前
LubanCat RK3588 实时内核移植第一步:先确认硬件与系统版本
linux·lubancat·嵌入式linux·freempt_rt
是个西兰花2 小时前
网络基础1
linux·网络·c++·智能路由器
2601_962299882 小时前
Python编写Linux命令指南
linux·python·开发·命令·指南
此冬歌咏2 小时前
自动化服务器运维监控系统(python+shell)
linux·运维·服务器·开发语言·python·自动化