深度剖析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
英文地址,請注明出處:http://en.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 提高組] 跳石頭 判斷條件該怎么寫

小麥矩陣系統:一鍵批量發,多賬號同步不掉鏈

隨著互聯網的發展和社交平臺的普及,企業和個人用戶越來越依賴社交媒體平臺來進行信息傳播、品牌宣傳以及市場推廣。在這個信息高速流動的時代,如何更高效地管理多個社交平臺的賬號,并保持信息的同步與流暢傳播,成為了許多企業面臨…