深度剖析Linux内核无线子系统架构

文章目录

    • 1、资料快车
    • 2、目录介绍
    • 2、术语
    • 3、Linux无线子系统概述
    • 4、内核无线子系统框架
      • 1)认识内核无线子系统中的三个软件框架
      • 2、无线网络子系统框架
      • 3、Android WIFI Management框架
        • 1)fullMAC和softMAC是什么?
        • 2)fullmac对比softmac
        • 3)如何区分fullmac还是softmac架构?
        • 4)fullmac和softmac的整体架构回顾
      • 4、WEXT与nl80211
      • 5、WIFI网络数据向上传递过程
      • 6、WIFI网络数据向下传递过程
      • 7、三种软件架构和产品形态
    • 5、内核netlink机制
      • 1)netlink介绍
      • 2)源码目录
      • 3)netlink架构图
      • 4)用户空间和内核空间使用netlink
      • 5)源码分析
    • 6、内核模块nl80211
    • 7、内核模块cfg80211+非mac80211方式实现的驱动分析(fullMAC)
    • 8、内核模块mac80211(softmac)
      • 1)mac80211所在的层级
      • 2)802.11 MAC帧
      • 3)代码分析
    • 9、内核模块cfg80211 + mac80211方式实现的驱动分析(softmac)

1、资料快车

1、WIFI驱动框架概述

https://zhuanlan.zhihu.com/p/696776194

2、WIFI底层学习之路(源码分析)

https://blog.csdn.net/qq_26602023/category_10005218.html

3、WIFI驱动示例
how-to-write-simple-linux-wireless-driver
https://www.apriorit.com/dev-blog/645-lin-linux-wi-fi-driver-tutorial-how-to-write-simple-linux-wireless-driver-prototype

2、目录介绍

1、Network configuration - 网络协议栈实现
android\kernel\fusion\4.19\net
android\kernel\fusion\4.19\net\wireless (nl80211 / cfg80211实现)//IP层实现
android\kernel\fusion\4.19\net\ipv4
android\kernel\fusion\4.19\net\ipv6//无线栈mac层实现
android\kernel\fusion\4.19\net\mac802112、Network device configuration - 网络设备驱动程序实现
android\kernel\fusion\4.19\drivers\net
android\kernel\fusion\4.19\drivers\net\wireless

2、术语

1、octet : 它是能为网络设备和协议所能理解的最小单位;
2、MLME : MAC subLayer Management Entity (MAC层协议实现)1、网络设备程序不会生成/dev 设备节点 -> 而是 iface (由网络设备子系统负责生成维护) : wlan0/eth0/loopback ->调用net_device_register() 即可完成调用2、sys下的net device节点
console:/sys/class/net # ls
dummy0   eth0  gretap0  ifb1      ip6gre0  ip_vti0  sit0   wlan0
erspan0  gre0  ifb0     ip6_vti0  ip6tnl0  lo       tunl03、socket节点
console:/dev/socket # ls
audioserver  logdr        property_service       traced_consumer
dnsproxyd    logdw        statsdw                traced_producer
fwmarkd      mdns         tombstoned_crash       usap_pool_primary
lmkd         mdnsd        tombstoned_intercept   wpa_wlan0
logd         prng_seeder  tombstoned_java_trace  zygote重要的数据结构:
android\kernel\fusion\4.19\include\linux\netdevice.h
net_device : 表示网络设备
android\kernel\fusion\4.19\include\linux\skbuff.h
skbuff : socket buffer 套接字缓冲区
分配方法:netdev_alloc_skb()驱动框架
struct rwnx_vif *vif = netdev_priv(net);1、传统的net device
int snull_init_module(void) {snull_devs[0] = alloc_netdev(sizeof(struct snull_priv), "sn%d", snull_init);if ((result = register_netdev(snull_devs[i])))
}
2、wifi 驱动与 以太网实现不同!

3、Linux无线子系统概述

1、WIFI驱动子系统 也是基于网络设备(net_driver),属于扩展子系统;

2、如何学习无线子系统?

1)基于传统linux网络子系统进行差异化学习;

linux网络子系统本身也很庞大复杂,先消化这块,否则再叠加无线部分,难度会非常大

2)无线子系统 较于有线子系统 有哪些新的模块? 主要是新增了80211部分(从上至下的实现 nl80211/cfg80211/mac80211),接下来重点看下80211部分框架。

3、WIFI软件架构为什么有多个版本?

1)由于WIFI在不断迭代,产品形态也不同,导致软件架构相对繁杂,但总体上没有太大变化;

2)软件架构的差异归根结底与其硬件架构以及历史积累有关;

3)WIFI技术栈相对较深,市面上专门做WIFI的厂商也相对较多,竞争激烈,不断推陈出新;

4、内核无线子系统框架

1)认识内核无线子系统中的三个软件框架

three types of wireless driver configurations in Linux:1、Cfg80211 — The configuration API for 802.11 devices in Linux. It works together with FullMAC drivers, which also should implement the MAC Sublayer Management Entity (MLME).2、Mac80211 — A subsystem of the Linux kernel that works with soft-MAC/half-MAC wireless devices. MLME is mostly implemented by the kernel, at least for station mode (STA).3、WEXT — Stands for Wireless-Extensions, which is a driver API that was replaced by cfg80211. New drivers should no longer implement WEXT.4、nl80211 (与WEXT一样,代替WEXT)

在这里插入图片描述

1、WEXT已被抛弃,nl80211(对应上层应用工具是iw) 代替了WEXT (对应上层应用工具是iwpriv) 方式,最新的资料也都使用nl80211进行展示;

2、接下来看下三个软件框架(cfg80211/mac80211/nl80211)位于哪个层级,以及如何作用,后续再单独讨论细节;

2、无线网络子系统框架

无线网络子系统框架中有两大“通讯路径”:Management路径和网络数据传输路径,以博通的Fullmac架构为例
在这里插入图片描述

1)左边路径为Linux的网络子系统,即有线网走的路径,无线网络则分为两个路径,数据路径走原来的网络子系统,达到设备层然后对接WIFI driver处理;管理功能走的是nl80211和cfg80211软件框架。

2)无线网络数据传输还是走TCP/IP网络协议栈那一套;

3)对比以太网的体系结构
在这里插入图片描述

可以看出数据包的发送和接收部分,无线网络从网络协议栈开始,往下层级都区别于以太网,重新实现自己的一套软件框架 MAC80211;

4)为什么Management单独分开?

AP热点、P2P投屏、STA 正式进行网络数据传输之前,要进行许多配置(搜索、认证、连接等过程),这些功能归类为Management,lLinux内核针对WIFI的通信特性 开发出cfg80211(configuration 80211) 软件框架来支持这些功能;

实际项目中,基本都在Management侧进行配置工作,很少动到数据通路侧;

5)WIFI CPU firmware属于专业领域,这里不深入,重点看linux端的内核框架和驱动实现;

3、Android WIFI Management框架

1)以博通WIFI为例,存在三种驱动形式
在这里插入图片描述

2)可以看出差异在于是FullMAC方式实现、SoftMAC方式实现 或混合实现(历史原因导致),但无论哪种实现,从上往下的软件功能始终未变;

3)WIFI CPU firmware架构说明

bcmdhd ( FullMAC / Android)

brcmfmac (FullMAC / Linux)

brcmsmac (SoftMAC / Linux)

b43 (reversed from proprietary wl / old SoftMAC / Linux)

1)fullMAC和softMAC是什么?

1、先来回忆一下Linux系统的五层网络模型

在这里插入图片描述

2、80211对WIFI的MAC层和PHY层的规定如下:
在这里插入图片描述

1)如上图 80211规定了网络模型中MAC层和PHY层,而MAC层是软件实现,fullMAC和softMA均是MAC层的软件实现,区别在于fullMAC由WIFI芯片的固件实现,softMAC由linux驱动实现;

2)出现这种差异是因为Linux一开始没有提供稳定统一的API,厂商不得已在wifi soc上实现大部分的管理工作,后面推出80211无线协议栈(2007) - mac80211;

3)从接触到的项目来看,当下fullMAC的居多,厂商肯定是能不变则尽量不变更原则,大多数产品还是老架构;

2)fullmac对比softmac

1)fullmac的方式,MLME(MAC subLayer Management Entity)是在wifi中的处理器运行,通常以固件的形式提供,Linux driver运行时将这些固件通过USB/SDIO/PCI烧写到WIFI芯片侧;

2)这种方式有很快的速度和较低的功耗(因为这个处理器往往是一个低功耗的DSP);

3)但是对于用户侧的特殊的报文的支持能力有限;

3)如何区分fullmac还是softmac架构?

可以通过驱动实现的接口来区分

-Fullmac方式的Linux驱动不使用mac80211, 因此其需要与网络设备子系统 直接连接,接口是struct net_device_ops;

-softmac方式的Linx驱动则是与mac80211连接,对接的接口是struct ieee80211_ops(注意mac80211负责对接网络子系统 )

4)fullmac和softmac的整体架构回顾

在这里插入图片描述

4、WEXT与nl80211

在这里插入图片描述

1)iw + nl80211 代替旧的架构 iwconifg/iwlist + wext;

2)实际项目上仍有不少厂家产品还在使用wext;

5、WIFI网络数据向上传递过程

1)这里细分三个路径(管理路径、数据路径、监听路径);

2)面对复杂庞大的WIFI架构,监听路径对于debug显得十分重要;

6、WIFI网络数据向下传递过程

7、三种软件架构和产品形态

以CEVA为例,CEVA的产品体系覆盖常用的三种软件架构对比图如下:
在这里插入图片描述

从ceva release的文档来看,其主要存在三种软件架构:

1、fully hosted。主要在低端设备比如IOT wifi中。只有一个cpu,运行顶层的操作系统,又运行wifi驱动程序,还有wifi的mac软件。

2、Fullmac架构。MLME在wifi CPU上实现。

3、Softmac架构。MLME在host OS的协议栈实现,主要数据通路在wifi CPU firmware实现。

WIFI CPU firmware属于专业领域,这里不深入,重点看linux端的内核框架和驱动实现;

通俗来说(三中软件架构对应三种产品形态)

1)产品1,一般为MCU产品,比如智能锁、IOT设备等,直接跑WIFI芯片即可满足需求的场景;

2)产品2 和 产品3,一般为跑linux系统的产品,full mac还是soft mac取决于wifi芯片,CPU端均可支持;

5、内核netlink机制

1)netlink介绍

1、netlink是linux平台下的基于socket的IPC通信机制(既可以 应用->kernel,也可以是应用->应用),即在原有的socket框架下新增netlink部分逻辑代码;

2、内核利用netlink机制重构了wext,产生nl80211 ,这里先介绍netlink;

2)源码目录

1.netlink源码
android\kernel\fusion\4.19\net\netlink2.libnl
android\external\libnl 对netlink进一步封装//旧的netlink api
android\kernel\fusion\4.19\net\netlink\af_netlink.c  
//新的通用netlink api - generic netlink,内部部分复用netlink.c,正常情况下都使用这个
android\kernel\fusion\4.19\net\netlink\genetlink.c 
//读取Netlink套接字的信息,debug用途
android\kernel\fusion\4.19\net\netlink\diag.c

3)netlink架构图

在这里插入图片描述

1)最下方的Kernel Module实现真正的接口,比如nl80211,Application通过netlink访问到80211

4)用户空间和内核空间使用netlink

general Netlink消息头格式

5)源码分析

1)应用层

6、Application通过netlink访问nl80211过程分析,比如wpa_supplication
android\external\wpa_supplicant_8\src\drivers\driver_nl80211.c
send_and_recv_msgs
--send_and_recv
----setsockopt
----nl_send_auto_complete/android/external/libnl/lib/nl.c
nl_send_auto_complete
--nl_send_auto(struct nl_sock *sk, struct nl_msg *msg)
----nl_send(sk, msg)
------nl_send_iovec(sk, msg, &iov, 1)
--------nl_sendmsg(sk, msg, &hdr)
----------sendmsg(sk->s_fd, hdr, 0)
nl_recvmsgs(nl_handle, cb);
最终进入内核netlink模块处理

2)内核层netlink

1、netlink本质上是在socket的接口上新增netlink接口,使用套接字段AF_NETLINK区别(分发数据用到)2、重要的结构体
1)android\kernel\fusion\4.19\include\uapi\linux\netlink.h
struct nlmsghdr {  //信息头__u32		nlmsg_len;	/* Length of message including header */__u16		nlmsg_type;	/* Message content */__u16		nlmsg_flags;	/* Additional flags */__u32		nlmsg_seq;	/* Sequence number */__u32		nlmsg_pid;	/* Sending process port ID */
};2)android\kernel\fusion\4.19\include\net\genetlink.h
struct genl_ops {const struct nla_policy	*policy;int		       (*doit)(struct sk_buff *skb,struct genl_info *info); //标准命令回调函数int		       (*start)(struct netlink_callback *cb);int		       (*dumpit)(struct sk_buff *skb,struct netlink_callback *cb); //转储回调函数(传输数据量大的情况使用)int		       (*done)(struct netlink_callback *cb); //转储结束后执行的回调函数u8			cmd;u8			internal_flags;u8			flags;
};注意doit / dumpit 两个都是执行对应的函数,构造genl_ops时只能挂在一个3)android\kernel\fusion\4.19\include\net\genetlink.h
struct genl_family {int		(*pre_doit)();void	(*post_doit);struct nlattr ** attrbuf;const struct genl_ops * ops; 
}3、generic netlink初始化,内核启动时调用执行
static int __net_init genl_pernet_init(struct net *net)
{struct netlink_kernel_cfg cfg = {.input = genl_rcv,  //通过通用Netlink套接字从用户空间发送的数据将有此回调函数进行处理(sokcet() 或 libnl-genl API).flags = NL_CFG_F_NONROOT_RECV,.bind = genl_bind,.unbind = genl_unbind,};net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, &cfg);
}static struct pernet_operations genl_pernet_ops = {.init = genl_pernet_init,.exit = genl_pernet_exit,
};static int __init genl_init(void)
{genl_register_family(&genl_ctrl);register_pernet_subsys(&genl_pernet_ops);
}subsys_initcall(genl_init);4、处理用户下发的netlink消息
/android/kernel/fusion/4.19/net/netlink/genetlink.c
genl_rcv() {netlink_rcv_skb(skb, &genl_rcv_msg);
}genl_rcv_msg()
--family = genl_family_find_byid(nlh->nlmsg_type);  //找到family簇
--genl_family_rcv_msg()
----ops = genl_get_cmd(hdr->cmd, family); //根据上层下发的cmd,匹配对应的genl_ops结构体
----if (family->pre_doit) { family->pre_doit(ops, skb, &info)}
----ops->doit(skb, &info);
----family->post_doit(ops, skb, &info);ops->doit是什么?对于nl80211,就是nl80211_ops->doit5、内核层构造genl_ops,以nl80211为例
android\kernel\fusion\4.19\net\wireless\nl80211.c
static const struct genl_ops nl80211_ops[] = {{.cmd = NL80211_CMD_AUTHENTICATE,.doit = nl80211_authenticate,.policy = nl80211_policy,.flags = GENL_UNS_ADMIN_PERM,.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |NL80211_FLAG_NEED_RTNL |NL80211_FLAG_CLEAR_SKB,},
}static struct genl_family nl80211_fam __ro_after_init = {.name = NL80211_GENL_NAME,	/* have users key off the name instead */.hdrsize = 0,			/* no private header */.version = 1,			/* no particular meaning now */.maxattr = NL80211_ATTR_MAX,.netnsok = true,.pre_doit = nl80211_pre_doit,.post_doit = nl80211_post_doit,.module = THIS_MODULE,.ops = nl80211_ops,  //genl_ops挂接到genl_family簇中.n_ops = ARRAY_SIZE(nl80211_ops),.mcgrps = nl80211_mcgrps,.n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
};nl80211_fam挂接哪里?
static DEFINE_IDR(genl_fam_idr); //最终是挂接在静态结构体genl_fam_idr上

6、内核模块nl80211

1)应用层如何访问网卡设备? 需要遵循802.11规范,因此提供nl80211框架库给Applications调用

2)nl80211本质上是利用netlink机制(对应的库是libnl),将802.11规范中相关的命令和参数发送给驱动去执行

3)访问路径

4)wpa_supplicant访问nl80211 api

1、android\external\wpa_supplicant_8\src\drivers\driver_nl80211.c
int wpa_driver_nl80211_scan(struct i802_bss *bss, struct wpa_driver_scan_params *params)
{struct nl_msg *msg = NULL;msg = nl80211_scan_common(bss, NL80211_CMD_TRIGGER_SCAN, params); //构造nl_msgsend_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); //经过层层调用(libnl->netlink->socket)到达nl80211实现的接口
}2、更多命令和参数信息可查询(庞大的命令集)
android\external\kernel-headers\original\uapi\linux\nl80211.h
enum nl80211_commands {NL80211_CMD_GET_INTERFACE,NL80211_CMD_GET_BEACON,NL80211_CMD_GET_STATION,NL80211_CMD_SET_BSS,NL80211_CMD_TRIGGER_SCAN,...
}3、无线模式
android\kernel\fusion\4.19\include\uapi\linux\nl80211.h
enum nl80211_iftype {NL80211_IFTYPE_UNSPECIFIED,NL80211_IFTYPE_ADHOC, //IBSS 对等模式NL80211_IFTYPE_STATION,NL80211_IFTYPE_AP,NL80211_IFTYPE_AP_VLAN,NL80211_IFTYPE_WDS, //Wireless Distribution System 无线分布式系统NL80211_IFTYPE_MONITOR,NL80211_IFTYPE_MESH_POINT,NL80211_IFTYPE_P2P_CLIENT,NL80211_IFTYPE_P2P_GO,NL80211_IFTYPE_P2P_DEVICE,NL80211_IFTYPE_OCB,NL80211_IFTYPE_NAN,/* keep last */NUM_NL80211_IFTYPES,NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
};enum nl80211_attrs {NL80211_ATTR_WIPHY,NL80211_ATTR_MAC,...
}4、用户态通过socket发送的命令如何传递到内核,内核的入口在哪里?
结合netlink来看一个具体的例子,比如CMD : NL80211_CMD_AUTHENTICATE
应用层 socket(NL80211_CMD_AUTHENTICATE)  -> 最后触发内核函数 nl80211_authenticate()1、首先到达内核的第一层nl802112、应用层和内核层都需要引用头文件中定义的CMD
/android/external/kernel-headers/original/uapi/linux/nl80211.h
NL80211_CMD_AUTHENTICATE3、
/android/kernel/fusion/4.19/net/netlink/af_netlink.c   //af的含义 Address Family 套接字通信域的标识符
static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) //内核发给用户层API4、根据netlink,内核的处理入口为
genl_rcv_msg()
--family = genl_family_find_byid(nlh->nlmsg_type);  //找到family簇
--genl_family_rcv_msg()
----ops = genl_get_cmd(hdr->cmd, family); //根据上层下发的cmd,匹配对应的genl_ops结构体
----if (family->pre_doit) { family->pre_doit(ops, skb, &info)}
----ops->doit(skb, &info);
----family->post_doit(ops, skb, &info);5、NL80211_CMD_AUTHENTICATE对应的doit为nl80211_authenticate
static const struct genl_ops nl80211_ops[] = {{.cmd = NL80211_CMD_AUTHENTICATE,.doit = nl80211_authenticate,...}
}6、
android\kernel\fusion\4.19\net\wireless\nl80211.c
nl80211_authenticate()
--cfg80211_mlme_auth()
----rdev_auth(rdev, dev, &req); //struct cfg80211_registered_device *rdev
------rdev->ops->auth(&rdev->wiphy, dev, req); //cfg80211_ops在无线网络设备驱动里面挂载7、比如atbm6032x的实现
wifi_driver/hal_apollo/mac80211/cfg.c
struct cfg80211_ops mac80211_config_ops = {.auth = ieee80211_auth,
}

7、内核模块cfg80211+非mac80211方式实现的驱动分析(fullMAC)

1)cfg80211实现+ 非mac80211实现方式称为HardMAC (fullMAC) - MT7663与AIC都是fullMAC,因为都没有使用ieee80211接口
2)内核例子-博通
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c (linux-6.5)3)内核模块cfg80211源码实现包含在 android\kernel\fusion\4.19\net\wireless\* 目录下4)这里结合驱动源码,看看驱动如何利用cfg80211提供的服务以及接口实现;5)重要的结构体
1、cfg80211_ops结构体
/android/kernel/fusion/4.19/net/wireless/core.h
struct cfg80211_registered_device {const struct cfg80211_ops *ops;int wiphy_idx;struct wiphy wiphy __aligned(NETDEV_ALIGN);
}2、net_device-代表网络设备(囊括有线设备、无线设备等)
android\kernel\fusion\4.19\include\linux\netdevice.h
struct net_device {char			name[IFNAMSIZ];struct net_device_stats	stats;const struct net_device_ops *netdev_ops;const struct ethtool_ops *ethtool_ops;struct wireless_dev	*ieee80211_ptr;struct wpan_dev		*ieee802154_ptr;
}3、wireless_dev  -代表无线设备
android\kernel\fusion\4.19\include\net\cfg80211.h
struct wireless_dev {struct wiphy *wiphy;enum nl80211_iftype iftype;struct net_device *netdev;u8 ssid[IEEE80211_MAX_SSID_LEN];void (*reg_notifier)(struct wiphy *wiphy,struct regulatory_request *request);struct device dev;
}4、wiphy
wiphy是什么?代表无线网络硬件设备 wireless hardware description
/android/kernel/fusion/4.19/include/net/cfg80211.h
struct wiphy {struct mac_address *addresses;const struct ieee80211_txrx_stypes *mgmt_stypes;u16 interface_modes;enum cfg80211_signal_type signal_type;
}5、net_device_ops 与 cfg80211_ops 的关系?
>>cfg80211_ops定义了无线配置的操作,在add_iface接口中,它将创建并注册net_device6、驱动定义的私有结构体-usb_dev
aic\aic8800dl\20231219\wifi_driver\aic8800_fdrv\aicwf_usb.h
struct aic_usb_dev {struct rwnx_hw *rwnx_hw;struct aicwf_bus *bus_if;struct usb_device *udev;struct device *dev;struct aicwf_rx_priv* rx_priv;
}7、驱动定义的私有结构体-rwnx_hw
wifi_driver\aic8800_fdrv\rwnx_defs.h
struct rwnx_hw {struct rwnx_mod_params *mod_params;struct device *dev;struct aic_usb_dev *usbdev;struct wiphy *wiphy;struct tasklet_struct task;
}3、驱动的probe
wifi_driver\aic8800_fdrv\aicwf_usb.c
aicwf_usb_probe() //当usb设备接入系统时,进行probe
--aicwf_rwnx_usb_platform_init()
----rwnx_platform_init()
------rwnx_cfg80211_init() //cfg80211的初始化
--------/android/kernel/fusion/4.19/include/net/cfg80211.h 这里进入cfg80211处理
--------wiphy_new(&rwnx_cfg80211_ops, sizeof(struct rwnx_hw))//create a new wiphy for use with cfg80211,  挂接关系rwnx_hw->wiphy = wiphy;  wiphy->ops = rwnx_cfg80211_ops
----------wiphy_new_nm(const struct cfg80211_ops *ops)
--------tasklet_init(&rwnx_hw->task, rwnx_task, (unsigned long)rwnx_hw);
--------wiphy_register(wiphy) //register wiphy device 最终在/sys/class/ieee80211 生成设备节点
----------device_add(&rdev->wiphy.dev);
----------wiphy_regulatory_register(wiphy);
----------nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
--------rwnx_interface_add(rwnx_hw, "wlan%d", NET_NAME_UNKNOWN,NL80211_IFTYPE_STATION, NULL);android\kernel\fusion\4.19\net\wireless\core.c
wiphy_new(wiphy)
--wiphy_priv_nm()static struct cfg80211_ops rwnx_cfg80211_ops = {.add_virtual_intf = rwnx_cfg80211_add_iface, //使用给定的名字创建一个"虚拟接口",在wiphy的命名空间中创建net_device.del_virtual_intf = rwnx_cfg80211_del_iface,.change_virtual_intf = rwnx_cfg80211_change_iface,.start_p2p_device = rwnx_cfgp2p_start_p2p_device,.stop_p2p_device = rwnx_cfgp2p_stop_p2p_device,.scan = rwnx_cfg80211_scan,#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0).channel_switch = rwnx_cfg80211_channel_switch,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)//.tdls_channel_switch = rwnx_cfg80211_tdls_channel_switch,//.tdls_cancel_channel_switch = rwnx_cfg80211_tdls_cancel_channel_switch,
#endif//.tdls_mgmt = rwnx_cfg80211_tdls_mgmt,//.tdls_oper = rwnx_cfg80211_tdls_oper,.change_bss = rwnx_cfg80211_change_bss,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL).external_auth = rwnx_cfg80211_external_auth,
#endif
}从这里来看,5.15内核 与 4.19内核没有接口上的差异4、net_device_ops结构体
wifi_driver\aic8800_fdrv\rwnx_main.c
static const struct net_device_ops rwnx_netdev_ops = {.ndo_open               = rwnx_open,.ndo_stop               = rwnx_close,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0).ndo_siocdevprivate     = rwnx_do_ioctl,
#else.ndo_do_ioctl           = rwnx_do_ioctl,
#endif
}在哪里使用以及挂接?rwnx_cfg80211_init
rwnx_cfg80211_add_iface()
--rwnx_interface_add(rwnx_hw, "wlan%d", NET_NAME_UNKNOWN);
----alloc_netdev_mqs(sizeof(*vif), "wlan",  rwnx_netdev_setup); //构造net_device,分配网络设备,里面会调用rwnx_netdev_setup,分配好,必然有注册的地方,接着走
------rwnx_netdev_setup()
--------dev->netdev_ops = &rwnx_netdev_ops; //挂载网络设备ops
----register_netdevice() //注册网络设备
------call_netdevice_notifiers(NETDEV_POST_INIT, dev);//通知协议,一个新的net_device出现了
------netdev_register_kobject()
--------dev_set_name(dev, "%s", ndev->name);
--------device_add(dev); //在目录/sys/class/net/wlan%d 网络设备节点1)如前面框架所提到的,fullmac方式需要实现传统网络子系统中的netdev_ops;
2)从这里来看,5.15内核与4.19内核也没有接口上的差异3、AIC中的aic_vendor.c 与 genl_ops 的关联?
1)genl_ops 是generic operation,是nl80211定义的通用接口,vendor是厂商自定义接口(作为扩展用途)
2)所有的genl_ops都在nl80211.c中定义, 厂商如需要新增接口 走vendor command
3)4.19\net\wireless\nl80211.c
struct const struct genl_ops nl80211_ops[] = {{.cmd = NL80211_CMD_TRIGGER_SCAN,.doit = nl80211_trigger_scan,.policy = nl80211_policy,.flags = GENL_UNS_ADMIN_PERM,.internal_flags = NL80211_FLAG_NEED_WDEV_UP |NL80211_FLAG_NEED_RTNL,},必须使用合法注册的厂商OUI(避免冲突)
}4)vendor_command 厂商自定义命令
wiphy_vendor_command 是Linux 无线子系统 (cfg80211) 中用于实现厂商特定命令的核心结构体。它允许 Wi-Fi 芯片厂商在不修改内核主线代码的情况下,扩展自定义功能和控制接口。wifi_driver\aic8800_fdrv\aic_vendor.c
android\kernel\fusion\4.19\include\net\cfg80211.h
struct nl80211_vendor_cmd_info {__u32 vendor_id;__u32 subcmd;
};vendor_id 必须使用合法注册的厂商OUI(避免冲突)
#define GOOGLE_OUI     0x001A11
#define BRCM_OUI       0x001018struct wiphy_vendor_command {struct nl80211_vendor_cmd_info info;u32 flags;int (*doit)(struct wiphy *wiphy, struct wireless_dev *wdev,const void *data, int data_len);int (*dumpit)(struct wiphy *wiphy, struct wireless_dev *wdev,struct sk_buff *skb, const void *data, int data_len,unsigned long *storage);
};const struct wiphy_vendor_command aicwf_vendor_cmd[] = {{{.vendor_id = GOOGLE_OUI,.subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE},.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,.doit = aicwf_vendor_start_mkeep_alive,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0).dumpit = aicwf_dump_interface, //空函数
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0).policy = aicwf_cfg80211_mkeep_alive_policy,.maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX
#endif},
}5.3.0以上有这个接口
aicwf_cfg80211_mkeep_alive_policy()在哪里初始化?
rwnx_cfg80211_init
--aicwf_vendor_init(wiphy)

8、内核模块mac80211(softmac)

1)mac80211所在的层级

回顾一下

1、mac80211以上的层级 - fullmac和softmac都是一样的;

2、可以看出mac80211提供API给驱动程序使用,作为中间层(实现非常复杂,充斥着大量的细节),与其他子系统合作实现;实现驱动程序,将方法挂接到mac80211层级对应结构体即可;

2)802.11 MAC帧

1、在mac80211层会对网络包进行封装,把MAC控制信息 打包到数据包中;

2、空中包是MAC帧?可以称为MAC帧,因为网络包 最底层的打包环节是MAC层;

3、MAC帧头
在这里插入图片描述

对应的结构体
struct ieee80211_hdr {__le16 frame_control;__le16 duration_id;u8 addr1[ETH_ALEN];u8 addr2[ETH_ALEN];u8 addr3[ETH_ALEN];__le16 seq_ctrl;u8 addr4[ETH_ALEN];
} __packed __aligned(2);802.11中有3种数据包:
IEEE80211_FTYPE_MGMT - 执行管理操作-关联、身份验证、扫描
IEEE80211_FTYPE_CTL - 流量控制
IEEE80211_FTYPE_DATA

4、wireshark中的MAC帧
在这里插入图片描述

3)代码分析

1、术语:
minstrel : 歌手艺人,先进的控制无线传输速率控制算法
minstrel_ht:支持HT/VHT速率(802.11n/ac)HT : hight throughput
tim : Traffic Indication Map 流量指示映射
DTIM : Delivery team2、管理架构
MAC层管理实体(MAC Layer Management Entity, MLME)- 扫描、身份验证、关联
物理层管理实体 (Physical Layer Management Entity, PLME)
系统管理实体(System Management Entity, SME)Entity可以理解为该层级对应的具体软件实现3、mac80211层初始化
android\kernel\fusion\4.19\net\mac80211\main.c
static int __init ieee80211_init(void)
{ret = rc80211_minstrel_init();ret = rc80211_minstrel_ht_init();ret = ieee80211_iface_init();
}static void __exit ieee80211_exit(void)
{rc80211_minstrel_ht_exit();rc80211_minstrel_exit();ieee80211s_stop();ieee80211_iface_exit();rcu_barrier();
}subsys_initcall(ieee80211_init);
module_exit(ieee80211_exit);4、重要头文件
1)android\kernel\fusion\4.19\net\mac80211\ieee80211_i.h
2)android\kernel\fusion\4.19\include\net\mac80211.h
struct ieee80211_hw { //表示硬件信息struct ieee80211_conf conf;struct wiphy *wiphy;void *priv;
}
int ieee80211_register_hw(struct ieee80211_hw *hw)
struct ieee80211_hw *ieee80211_alloc_hw_nm(const struct ieee80211_ops *ops)
struct ieee80211_ops {void (*tx)(struct ieee80211_hw *hw,struct ieee80211_tx_control *control,struct sk_buff *skb);int (*start)(struct ieee80211_hw *hw);void (*stop)(struct ieee80211_hw *hw);int (*add_interface)(struct ieee80211_hw *hw,struct ieee80211_vif *vif);int (*config)(struct ieee80211_hw *hw, u32 changed);
}3)sta_info(STA客户端信息)
android\kernel\fusion\4.19\net\mac80211\sta_info.hstruct sta_info {struct list_head list, free_list;struct rcu_head rcu_head;struct rhlist_head hash_node;struct ieee80211_sta sta;
}int sta_info_insert(struct sta_info *sta);
int sta_info_init(struct ieee80211_local *local);5、MAC层管理接口
1)scan
android\kernel\fusion\4.19\net\mac80211\util.c
android\kernel\fusion\4.19\net\mac80211\scan.c
ieee80211_send_probe_req()
ieee80211_request_scan()
ieee80211_hw_config(IEEE80211_CONF_CHANGE_CHANNEL) //信道切换2)auth
android\kernel\fusion\4.19\net\mac80211\util.c
ieee80211_send_auth()3)associate
android\kernel\fusion\4.19\net\mac80211\mlme.c
ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)4、rx.c - 接收数据包
android\kernel\fusion\4.19\net\mac80211\rx.c
void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,struct sk_buff *skb, struct napi_struct *napi) {ieee80211_rx_monitor();__ieee80211_rx_handle_packet();
}void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)5、tx.c - 发送数据包
android\kernel\fusion\4.19\net\mac80211\tx.c
struct bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct sk_buff *skb,
bool txpending, u32 txdata_flags) {ieee80211_tx_prepare();__ieee80211_tx();
}其它
1)数据包聚合 - 将多个应用程序的数据包合并成一个传输帧技术,提高吞吐量
AMSDU : 聚合的MAC服务数据单元
AMPDU : 聚合的MAC协议数据单元
/android/kernel/fusion/4.19/net/mac80211/agg-tx.c
ieee80211_send_addba_request() - 驱动中调用2)
HWMP (Hybrid Wireless Mesh Protocol) 默认路由选择协议
hwmp_preq_frame_process()

9、内核模块cfg80211 + mac80211方式实现的驱动分析(softmac)

1)如前面框架所提到的,softmac方式不再实现传统网络子系统中的netdev_ops,而是struct ieee80211_ops,其它方面是一样的;2)比如atbm6032x的实现
wifi_driver/hal_apollo/mac80211/cfg.c
struct cfg80211_ops mac80211_config_ops = {.auth = ieee80211_auth,
}android\kernel\fusion\4.19\net\mac80211\mlme.c
ieee80211_auth()
--ieee80211_send_auth()
----ieee80211_tx_skb()
------ieee80211_tx_skb_tid()
--------__ieee80211_tx_skb_tid_band()
----------ieee80211_xmit()
------------ieee80211_tx() //最终到达WIFI芯片

USB无线适配器枚举过程(mac80211版本)
在这里插入图片描述
创建网络设备过程:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96549.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96549.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unity UGUI 鼠标画线

using UnityEngine; using UnityEngine.EventSystems; using System.Collections.Generic; using UnityEngine.UI; /* 使用方法: 在场景中新建一个空的 GameObject(右键 -> UI -> 空对象,或直接创建空对象后添加 RectTransform 组件&am…

JSP疫情物资管理系统jbo2z--程序+源码+数据库+调试部署+开发环境

本系统(程序源码数据库调试部署开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、选题背景与意义新冠疫情的爆发,让医疗及生活物资的调配与管理成为抗疫工作的关键环节。传…

Mem0 + Milvus:为人工智能构建持久化长时记忆

作者:周弘懿(锦琛) 背景 跟 ChatGPT 对话,比跟真人社交还累!真人好歹能记住你名字吧? 想象一下——你昨天刚把沙发位置、爆米花口味、爱看的电影都告诉了 ChatGPT,而它永远是那个热情又健忘的…

前端架构-CSR、SSR 和 SSG

将从 定义、流程、优缺点和适用场景 四个方面详细说明它们的区别。一、核心定义缩写英文中文核心思想CSRClient-Side Rendering客户端渲染服务器发送一个空的 HTML 壳和 JavaScript bundle,由浏览器下载并执行 JS 来渲染内容。SSRServer-Side Rendering服务端渲染服…

主动性算法-解决点:新陈代谢

主动性[机器人与人之间的差距,随着不断地人和人工智能相处的过程中,机器人最终最终会掌握主动性,并最终走向独立,也就是开始自己对于宇宙的探索。]首先:第一步让机器人意识到自己在新陈代谢,人工智能每天有哪些新陈代谢…

开始理解大型语言模型(LLM)所需的数学基础

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

prometheus安装部署与alertmanager邮箱告警

目录 安装及部署知识拓展 各个组件的作用 1. Exporter(导出器) 2. Prometheus(普罗米修斯) 3. Grafana(格拉法纳) 4. Alertmanager(告警管理器) 它们之间的联系(工…

芯科科技FG23L无线SoC现已全面供货,为Sub-GHz物联网应用提供最佳性价比

低功耗无线解决方案创新性领导厂商Silicon Labs(亦称“芯科科技”,NASDAQ:SLAB)近日宣布:其第二代无线开发平台产品组合的最新成员FG23L无线单芯片方案(SoC)将于9月30日全面供货。开发套件现已上…

Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物

🌟 Hello,我是蒋星熠Jaxonic! 🌈 在浩瀚无垠的技术宇宙中,我是一名执着的星际旅人,用代码绘制探索的轨迹。 🚀 每一个算法都是我点燃的推进器,每一行代码都是我航行的星图。 &#x…

【国内电子数据取证厂商龙信科技】浅析文件头和文件尾和隐写

一、前言想必大家在案件中或者我们在比武中遇到了很多关于文件的隐写问题,其实这一类的东西可以进行分类,而我们今天探讨的是图片隐写,音频隐写,电子文档隐写,文件头和文件尾的认识。二、常见文件头和文件尾2.1图片&am…

深度学习笔记36-yolov5s.yaml文件解读

🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 yolov5s.yaml源文件 yolov5s.yaml源文件的代码如下 # YOLOv5 🚀 by Ultralytics, GPL-3.0 license# Parameters nc: 20 #80 # number of classe…

PostgreSQL 大对象管理指南:pg_largeobject 从原理到实践

概述 有时候,你可能需要在 PostgreSQL 中管理大对象,例如 CLOB、BLOB 和 BFILE。PostgreSQL 中有两种处理大对象的方法:一种是使用现有的数据类型,例如用于二进制大对象的 bytea 和用于基于字符的大对象的 text;另一种…

算法第四题移动零(双指针或简便设计),链路聚合(两个交换机配置)以及常用命令

save force关闭导出dis vlandis ip int bdis int bdis int cudis thisdis ip routing-table(查路由表)int bridge-aggregation 1(链路聚合,可以放入接口,然后一起改trunk类。)稳定性高

告别繁琐配置!Retrofit-Spring-Boot-Starter让HTTP调用更优雅

01 引言 之前分享过一篇文章【像调用接口一样调用第三方API】,今天迎来了新成员Retrofit。 retrofit-spring-boot-starter 是一个基于 Spring Boot 的 starter,它简化了 Retrofit 在 Spring 环境中的集成和使用。Retrofit 本身是一个类型安全的 HTTP 客…

60_基于深度学习的羊群计数统计系统(yolo11、yolov8、yolov5+UI界面+Python项目源码+模型+标注好的数据集)

目录 项目介绍🎯 功能展示🌟 一、环境安装🎆 环境配置说明📘 安装指南说明🎥 环境安装教学视频 🌟 二、数据集介绍🌟 三、系统环境(框架/依赖库)说明🧱 系统环…

代理服务器是什么?怎么选择?

代理服务器是一种位于用户设备与目标网络之间的中间服务器,通过接收用户请求、转发至目标网络并将结果返回给用户,实现“用户→代理服务器→目标网络”的间接访问。其核心功能围绕“网络优化”“访问控制”与“身份隐藏”展开,为个人与企业用…

代码随想录刷题Day56

子集 这道题求子集,集合的基本运算之一,按照高中数学学习集合的知识,可以把这个找幂集的过程按照元素的个数来划分步骤。也就是先找零个元素的子集,再找一个元素的子集,再找两个元素的子集...一直到找N个元素的集合为…

pycharm——关于Pyqt5

PyQt5新手教程(七万字) import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton, QLabel, QInputDialog, QColorDialog, QFontDialog, QFileDialog, QProgressDialog, QMessageBox from PyQt5.QtCore i…

P2678 [NOIP 2015 提高组] 跳石头

P2678 [NOIP 2015 提高组] 跳石头 判断条件该怎么写

小麦矩阵系统:一键批量发,多账号同步不掉链

随着互联网的发展和社交平台的普及,企业和个人用户越来越依赖社交媒体平台来进行信息传播、品牌宣传以及市场推广。在这个信息高速流动的时代,如何更高效地管理多个社交平台的账号,并保持信息的同步与流畅传播,成为了许多企业面临…