> 技术文档 > Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架


基础框架

Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

基础概念

  • nl80211
    作用:用户空间与内核空间无线配置的接口(Netlink API)
    功能:提供基于 netlink 的通信机制,允许用户空间工具配置和管理无线设备
    代码位置:net/wireless/nl80211.c
  • cfg80211
    作用:无线配置框架,管理所有无线设备和驱动
    功能
    1)提供统一的无线配置接口(如设置频段、信道、功率等)
    2)管理 mac80211 和直接支持 FullMAC 的硬件
    3)处理 MLME(MAC Layer Management Entity)逻辑(如认证、关联)
    代码位置:net/wireless/
  • mac80211
    作用:driver开发者可用于为SoftMAC无线设备写驱动的框架,处理大部分 802.11 MAC 层功能
    功能
    1)实现 Beacon 处理、ACK 管理、速率控制、加密(WPA/WPA2) 等
    2)依赖硬件驱动实现 PHY 层操作(如发送/接收数据包)
    3)支持 AP、STA、Monitor、Mesh 等多种模式
    代码位置:net/mac80211/

理解

  • nl80211是介于用户空间与内核空间之间的 API ,可以算是 cfg80211 的前端
  • cfg80211 是设备和用户空间之间的桥梁,工作则是跟踪 WLAN 设备所处的实际状态
  • mac80211 的工作是给出硬件的所有功能和与硬件进行交互
  • 如果某些功能无法由设备硬件实现,那么就可以以纯软的方式实现,其也被称为 “Soft MAC” 模块,与 “Hard MAC” (由设备固件完成所有工作)相对。实际项目中通常是这两种方案混合使用的
那我们怎么去代码理解这几个组件呢,下面我将用一个管理路径的方式,去分析理解

iw dev wlan1 scan命令是如何调用到wifi驱动的

基本调用框架图
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
逻辑图
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

  1. 首先是iw工具
    iw 源码获取:git clone https://git.kernel.org/pub/scm/linux/kernel/git/jberg/iw.git
    编译完成后进行源码跟踪,将iw工具编译后命名为iw-debug.

  2. 添加打印
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    从如下调用就可看到iw最后调用的是libnl库函数 ---------> 理解iw到libnl的框架图
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    执行命令查看调用路径:
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

  3. 使用strace命令跟踪iw调用
    sudo strace -e socket,sendmsg,recvmsg iw dev wlan1 scan
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    消息的构造发生在iw工具,从下面的棘突也能看出,并且对应的是scan指令
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    libnl我们就不跟踪了,我们知道是一个非常好用的库就行了

  4. nl80211接收来自应用层的netlink消息
    内核源码中,genl_init 是 Linux 内核中 Generic Netlink(通用 Netlink)框架的初始化函数,负责在系统启动时注册 Generic Netlink 的核心组件
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    nl80211通过genl_family_rcv_msg接收netlink信息,通过回调函数nl80211_pre_doit, 查找cfg80211注册时的设备信息dev
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

  5. nl80211初始化
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

  6. nl80211消息传递给cfg80211
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    rdev_scan 函数已经属于 cfg80211 组件的范畴
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

  7. ops直接调用到mac80211
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

  8. 调用到驱动函数
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    驱动扫描函数实现
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    有管理路径针对管理帧,数据路径针对数据帧,所以还有数据路径,数据和管理路径在 mac80211 里面是分开实现的。

数据路径发送

  1. 内核协议栈 → mac80211
    调用逻辑
neigh_resolve_output()dev_queue_xmit()__dev_xmit_skb()sch_direct_xmit()dev_hard_start_xmit()netdev_start_xmit() 

Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
2. mac80211 → 驱动(ath9k/ath9k_htc)
调用路径:

ieee80211_subif_start_xmit()//mac802111入口函数 -->__ieee80211_subif_start_xmit() -->ieee80211_xmit() -->ieee80211_tx() -->__ieee80211_tx() -->ieee80211_tx_frags() -->drv_tx() -->[local->ops->tx()]

Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
调用drv_tx(),把帧传递给驱动
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

  1. 驱动(ath9k/ath9k_htc)
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架

  2. 驱动 → 硬件
    USB 设备(ath9k_htc):
    通过 USB Bulk 传输发送 HTC 协议封装的数据包。

数据路径接收

  1. 硬件中断 → 驱动
    中断处理:网卡收到数据后触发中断。
    USB 设备:USB 回调函数
  2. 驱动 → mac80211
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    如下是ieee80211_rx的源码解释:
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
  3. mac80211 → 内核协议栈
    解密和校验:处理 WPA/WPA2 解密、校验帧完整性。
    协议栈上传:通过 netif_receive_skb() 将数据包传递给 TCP/IP 协议栈
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    如果收到的帧是数据,它将被转换成 802.3 数据帧(通过 __ieee80211_data_to_8023 实现),然后该数据帧将通过 netif_receive_skb 交付到网络协议栈。在协议栈中,各层网络协议将会对数据进行解析,识别协议首部。
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
    Linux 无线网络驱动开发 之 子系统源码框架(nl80211、cfg80211、mac80211)_linux wifi驱动框架
  4. 协议栈 → 用户空间
    Socket 接收:用户程序通过 recv() 或 read() 读取数据。

什么是MLME

即MAC(Media Access Control ) Layer Management Entity,它管理物理层MAC状态机,负责 认证、关联、扫描、省电模式 等

如何理解MLME

  • MLME 功能(扫描、认证、关联、省电模式等)由 mac80211 在软件中实现
  • mac80211 不参与管理,仅通过 cfg80211 去操作MLME功能
  • 简单点理解可以为 cfg80211负责管理,mac80211负责实现MLME功能

疑问?

  1. 既然iw工具可以创建socket并连接netlink,为什么要需要调用libnl去发送消息给nl80211?
    若直接使用原生 Socket,代码量可能增加 3-5 倍,且难以维护,安全性、稳定性也难以保证
  2. MLME跟wifi状态机有什么关系?
    mlme是管理wifi 状态机的,wifi状态机是 MLME 的具体实现方式

这里是简单的框架梳理,希望能够抛砖引玉,谢谢
在这里插入图片描述