当前位置: 首页 > news >正文

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

基础框架

在这里插入图片描述

基础概念

  • 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驱动的

基本调用框架图
在这里插入图片描述
逻辑图
在这里插入图片描述

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

  2. 添加打印
    初始调用 在这里插入图片描述
    从如下调用就可看到iw最后调用的是libnl库函数 ---------> 理解iw到libnl的框架图
    在这里插入图片描述
    执行命令查看调用路径:
    在这里插入图片描述

  3. 使用strace命令跟踪iw调用
    sudo strace -e socket,sendmsg,recvmsg iw dev wlan1 scan
    在这里插入图片描述
    消息的构造发生在iw工具,从下面的棘突也能看出,并且对应的是scan指令
    在这里插入图片描述
    libnl我们就不跟踪了,我们知道是一个非常好用的库就行了

  4. nl80211接收来自应用层的netlink消息
    内核源码中,genl_init 是 Linux 内核中 Generic Netlink(通用 Netlink)框架的初始化函数,负责在系统启动时注册 Generic Netlink 的核心组件
    在这里插入图片描述
    nl80211通过genl_family_rcv_msg接收netlink信息,通过回调函数nl80211_pre_doit, 查找cfg80211注册时的设备信息dev
    在这里插入图片描述

  5. nl80211初始化
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  6. nl80211消息传递给cfg80211
    在这里插入图片描述
    rdev_scan 函数已经属于 cfg80211 组件的范畴
    在这里插入图片描述

  7. ops直接调用到mac80211
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  8. 调用到驱动函数
    在这里插入图片描述
    驱动扫描函数实现
    在这里插入图片描述
    有管理路径针对管理帧,数据路径针对数据帧,所以还有数据路径,数据和管理路径在 mac80211 里面是分开实现的。

数据路径发送

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
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()]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
调用drv_tx(),把帧传递给驱动
在这里插入图片描述
在这里插入图片描述

  1. 驱动(ath9k/ath9k_htc)
    在这里插入图片描述在这里插入图片描述

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

数据路径接收

  1. 硬件中断 → 驱动
    中断处理:网卡收到数据后触发中断。
    USB 设备:USB 回调函数
  2. 驱动 → mac80211
    在这里插入图片描述
    在这里插入图片描述
    如下是ieee80211_rx的源码解释:
    在这里插入图片描述
  3. mac80211 → 内核协议栈
    解密和校验:处理 WPA/WPA2 解密、校验帧完整性。
    协议栈上传:通过 netif_receive_skb() 将数据包传递给 TCP/IP 协议栈
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    如果收到的帧是数据,它将被转换成 802.3 数据帧(通过 __ieee80211_data_to_8023 实现),然后该数据帧将通过 netif_receive_skb 交付到网络协议栈。在协议栈中,各层网络协议将会对数据进行解析,识别协议首部。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  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 的具体实现方式

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

http://www.lryc.cn/news/573688.html

相关文章:

  • 【weaviate】分布式数据写入之LSM树深度解析:读写放大的权衡
  • 计算机网络通信技术与协议(九)————交换机技术
  • flink如何支持kafka容灾自动切换
  • C++,Qt事件处理机制编程开发练习全解析,23000字解析!!
  • 二、Generative adversarial network (GAN)
  • 深入理解Spring MVC:构建灵活Web应用的基石
  • Elasticsearch Kibana (一)
  • React纯函数和hooks原理
  • 开发语言本身只是提供了一种解决问题的工具
  • Qt应用中处理Linux信号:实现安全退出的技术指南
  • 对射式红外传感器计次旋转编码器计次
  • 消息队列:基本知识
  • day039-nginx配置补充
  • VSCode性能调优:从卡顿到丝滑的终极方案
  • React 核心原理与Fiber架构
  • java中关于异步转同步的一些解决方案的对比与思考。【spring mvc堵塞式】
  • 【前后前】导入Excel文件闭环模型:Vue3前端上传Excel文件,【Java后端接收、解析、返回数据】,Vue3前端接收展示数据
  • 华为云Flexus+DeepSeek征文|在Dify-LLM平台中开发童话故事精灵工作流AI Agent
  • 【DDD】——带你领略领域驱动设计的独特魅力
  • C4.5算法深度解析:决策树进化的里程碑
  • 《HTTP权威指南》 第7章 缓存
  • mysql join的原理及过程
  • C++法则10:引用本身是一个“别名”(alias),一旦绑定到一个对象后,就不能再重新绑定到其他对象。
  • 【递归,搜索与回溯算法】记忆化搜索(二)
  • 如何处理RocketMQ的各种线上问题
  • 【Python学习笔记】报错:Unindent amount does not match previous indent
  • Spring Boot 项目初始化
  • AWS 使用图形化界面创建 EKS 集群(零基础教程)
  • LabVIEW图像拼接原理与实现 链接附件有演示录像
  • 如何用AI开发完整的小程序<9>—UI自适应与游戏页优化