Linux5.10内核stmmac驱动框架深度解析
本篇整理了linux5.10版本内核网络驱动(stmmac)的整体框架,openharmony中网络管理的服务组件(netmanager)后续再更新。
主要思考脉络:根据原理图核对对应的设备树,由设备树分析出对应的驱动源码,将驱动源码与rk3568手册和做对比分析,进而梳理出整个网络的驱动脉络。
系统版本:openharmony5.0.0
开发板:dayu200
编译环境:ubuntu22
原理图
从硬件的角度来分析,以太网的结构组成一般由CPU、MAC(Media Access Control)控制器和物理层接口(physical Layer PHY)组成,如下图所示:
MAC:以太网服务质量控制器是一个处理器中提供的以太网接口,具体的可以参考RK3568 GMAC手册内容(中文)
PHY芯片:负责接收到CPU的MAC层发送过来的数字信号,然后转换成模拟信号,通过MDI接口通过网络变压器传输出去。反之将模拟信息转换为数字信号给mac。需要详细了解的可以找一个phy芯片的手册看一下。
网络变压器:纯电气构件,由主变压器、共模电感和自耦变压器组成,主要作用包括信号传输、电气隔离、阻抗匹配、波形修复、信号杂波抑制和共模干扰抑制等。
注:有一些cpu是包含phy的或cpu不包含phy使用MAC+PHY的方案,以上为本开发板的结构,也是当前最常用的方案。
phy原理图如下:
1. RGMII接口引脚
CPU与phy的数据交互总线。
发送器
- GTX_CLK——吉比特TX…信号的时钟信号(125MHz)
- TXD[3…0]——被发送数据
- TX_CTL——发送控制
接收器
- RX_CLK——接收时钟信号(从收到的数据中提取,因此与GTXCLK无关联)
- RXD[3…0]——接收数据
- RX_CTL——接收控制
2. MDIO/MDC的介绍
负责对phy的寄存器的配置。
- MDC——配置接口时钟
- MDIO——配置接口I/O
3. MDI总线
PHY芯片的逻辑数据(0/1)转换为适合传输的物理信号。
4. LED灯
5. 时钟
提供时钟信号,按手册要求是25M,开发板也确实提供的25M。
设备树
从rk3568手册中可见千兆GMAC0的寄存器起始地址为0xfe2a0000,如下:
从当前系统中也可进一步验证:
由生成的.dtb文件可知设备树的配置文件为rk3568-toybrick-x0-linux.dts。
此文件包含如下设备树文件
//arch/arm64/boot/dts/rockchip/rk3568-toybrick-x0-linux.dts
#include "rk3568.dtsi" //包含gmac0基本配置
#include "rk3568-linux.dtsi"
#include "rk3568-toybrick-x0.dtsi" //包含gmac0的定制化配置并使能
#include "rk3568-toybrick-mipi-tx0-beiqicloud.dtsi"
从硬件的角度来看主要组成包含gmac、mdio、phy以及对应的gpio(reset等)。
引脚定义说明
此部分主要是设置网络接口中都包含哪些引脚以及复用引脚的配置值。下图为gmac0的引脚说明
由上图可见rxd2引脚的复用功能选择值为2,而txd0为1,所以设备树中也包含对应的配置
进一步分析可以参考drivers/pinctrl/pinctrl-rockchip.c文件。
gmac和mdio
其中rk3568.dtsi中定义了gmac的模版
//kernel\linux\pathces\linux-5.10\rk3568_patch\kernel.patch
gmac0: ethernet@fe2a0000 {//定义一个名为`gmac0`的以太网节点,地址为0xfe2a0000compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a";//设备兼容的驱动程序,与代码匹配reg = <0x0 0xfe2a0000 0x0 0x10000>;interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,<GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;//中断号及其触发类型。`GIC_SPI`表示使用GIC的共享外设中断。这两个中断分别对应MAC中断和以太网唤醒中断。interrupt-names = "macirq", "eth_wake_irq";//为中断提供了可读的名字,方便驱动程序识别,从/proc/device-tree/ethernet@fe2a0000/interrupt-names可查到rockchip,grf = <&grf>;//指定了与GMAC0相关的通用寄存器文件clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>,<&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>,<&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>,<&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>,<&cru PCLK_XPCS>;//列出了设备所需的时钟源,包括MAC自身时钟、收发时钟、参考时钟等clock-names = "stmmaceth", "mac_clk_rx","mac_clk_tx", "clk_mac_refout","aclk_mac", "pclk_mac","clk_mac_speed", "ptp_ref","pclk_xpcs";//为时钟源提供了可读的名字,方便驱动程序识别,从/proc/device-tree/ethernet@fe2a0000/clock-names可查询resets = <&cru SRST_A_GMAC0>;//设备重置的相关配置信息,控制时钟的软重启寄存器cru_softrst_con13,当处于高电平时,重置相对逻辑reset-names = "stmmaceth";//重置配置提供的可读的名字,从proc/device-tree/ethernet@fe2a0000/reset-names可查询snps,mixed-burst;//告诉驱动程序该设备支持混合突发模式snps,tso;//表示该设备支持TCP分段卸载(TSO)功能snps,axi-config = <&gmac0_stmmac_axi_setup>;//提供了AXI总线的配置信息,这里包含了读写突发长度限制和缓冲长度snps,mtl-rx-config = <&gmac0_mtl_rx_setup>;//定义了接收队列的配置,包括使用的队列数量,详见下文snps,mtl-tx-config = <&gmac0_mtl_tx_setup>;//分别定义了发送队列的配置,包括使用的队列数量,详见下文status = "disabled";//默认是禁用的mdio0: mdio {//配置和管理以太网PHY的mdio总线compatible = "snps,dwmac-mdio";//设备兼容的驱动程序,与代码匹配#address-cells = <0x1>;#size-cells = <0x0>;};gmac0_stmmac_axi_setup: stmmac-axi-config {snps,wr_osr_lmt = <4>;//定义了写突发长度限制。值4表示该设备在写操作时可以有最多4个未完成的请求。这个限制有助于控制内存带宽的使用,避免过多的未完成请求导致系统性能下降。snps,rd_osr_lmt = <8>;//定义了读突发长度限制。值8表示该设备在读操作时可以有最多8个未完成的请求。类似地,这个限制有助于管理内存带宽,确保读操作的高效性snps,blen = <0 0 0 0 16 8 4>;//数组中的每个值表示不同类型的突发传输的支持情况};gmac0_mtl_rx_setup: rx-queues-config {snps,rx-queues-to-use = <1>;//可以使用的接收队列数量。值`1`表示只使用一个接收队列queue0 {};//子节点定义了第一个接收队列的具体配置。当前配置为空,表示没有进一步的特殊配置。如果有需要,可以在`queue0`节点中添加更多的配置属性。};gmac0_mtl_tx_setup: tx-queues-config {snps,tx-queues-to-use = <1>;//使用的发送队列数量。值`1`表示只使用一个发送队列queue0 {};//子节点定义了第一个发送队列的具体配置。当前配置为空,表示没有进一步的特殊配置。如果有需要,可以在`queue0`节点中添加更多的配置属性};
};
由以上可见status = "disabled";
设置为不使能,但rk3568-toybrick-x0-linux.dts包含的子设备树文件:/arch/arm64/boot/dts/rockchip/rk3568-toybrick-x0.dtsi会将其使能(status = “okay”)并配置一些个性参数,如下:
&gmac0 {phy-mode = "rgmii";//phy模式配置clock_in_out = "output";//定义了以太网接口的时钟方向。`output`表示MAC会向PHY输出时钟。在RGMII模式中,MAC通常会输出参考时钟给PHY,以便PHY能够同步数据传输。snps,reset-gpio = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>;//配置reset控制引脚,与原理图中的reset引脚一致(GMAC0_RSTn_GPIO2_D3)snps,reset-active-low;//低电平有效/* Reset time is 20ms, 100ms for rtl8211f */snps,reset-delays-us = <0 20000 100000>;assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>;//设备所需的时钟源assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>;//这些时钟源的父时钟assigned-clock-rates = <0>, <125000000>;//时钟源的时钟频率pinctrl-names = "default";//引脚控制配置的名字pinctrl-0 = <&gmac0_miim&gmac0_tx_bus2&gmac0_rx_bus2&gmac0_rgmii_clk&gmac0_rgmii_bus>;tx_delay = <0x2d>;//发送延迟设置,具体值取决于硬件和驱动程序的定义,一般根据厂家建议调整rx_delay = <0x13>;//接收延迟设置,具体值取决于硬件和驱动程序的定义,一般根据厂家建议调整phy-handle = <&rgmii_phy0>;//指定以太网PHY的Phandle,用于配置和管理以太网物理层设备status = "okay";//启用
};
phy
&mdio0 {
+ rgmii_phy0: phy@0 {//定义了一个名为`rgmii_phy0`的PHY节点,地址为`0x0`
+ compatible = "ethernet-phy-ieee802.3-c22";//定义了PHY设备的兼容字符串。`"ethernet-phy-ieee802.3-c22"`表示该PHY设备符合IEEE 802.3标准的 Clause 22 管理接口。Clause 22接口是用于管理以太网PHY的传统接口
+ reg = <0x0>;//定义了PHY设备在MDIO总线上的地址,即广播地址,一般来说只有一个phy芯片时配置成0即可。
+ };
+};
linux内核源码分析
网络驱动主要包含三部分,分别为GMAC、外设PHY驱动以及mdio总线。
根据设备树中的compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a";
查找与之匹配的驱动程序在device/soc/rockchip/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c中
驱动加载过程
在设备启动和使能网络(ifconfig xxx up)时会进行设备驱动加载,网卡驱动的启动函数(rk_gmac_probe)中可以看出与传统内核的网络驱动的流程基本相同,首先解析配置文件并初始化(rk_gmac_probe->stmmac_dvr_probe->stmmac_hw_init)gmac,然后注册mdio总线,此时会自动扫描出对应的phy设备(rk_gmac_probe->stmmac_dvr_probe->stmmac_mdio_register),最终会对phy芯片做对应的初始化(rk_gmac_probe->stmmac_dvr_probe->stmmac_phy_setup)并完成网络的注册(rk_gmac_probe->stmmac_dvr_probe->register_netdev)。
以前分析过一个类似的驱动(/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c)放在这里可以参考下整体流程,细节有差异。后文涉及到此过程时再详细说明。
设备初始化过程
MAC
在驱动加载过程中赋值了网络操作集,如下:
static const struct net_device_ops stmmac_netdev_ops = {.ndo_open = stmmac_open,//1.打开网络设备.ndo_start_xmit = stmmac_xmit,//2.发送数据.ndo_stop = stmmac_release,//关闭网络设备.ndo_change_mtu = stmmac_change_mtu,//更改 MTU 大小.ndo_set_rx_mode = stmmac_set_rx_mode,//此函数用于改变地址过滤列表,根据 net_device 的 flags成员变量来设置 SOC 的网络外设寄存器。比如 flags 可能为 IFF_PROMISC、IFF_ALLMULTI 或IFF_MULTICAST,分别表示混杂模式、单播模式或多播模式.ndo_tx_timeout = stmmac_tx_timeout,//当发送超时的时候函数会执行,一般都是网络出问题了导致发送超时。一般可能会重启 MAC 和 PHY,重新开始数据发送等.ndo_do_ioctl = stmmac_ioctl,//用户程序调用 ioctl 的时候此函数就会执行,比如 PHY 芯片关的命令操作.ndo_setup_tc = stmmac_setup_tc,//用于设置网络设备的流量控制(Traffic Control)策略.ndo_select_queue = stmmac_select_queue,//选择用于发送数据的队列
#ifdef CONFIG_NET_POLL_CONTROLLER.ndo_poll_controller = stmmac_poll_controller,//在轮询模式下,用于轮询网络控制器以获取接收的数据
#endif.ndo_fix_features = stmmac_fix_features,//用于修正网络设备的特性,确保设备在不同的配置和环境中能够正常工作.ndo_set_features = stmmac_set_features,//设置网络设备的特性.ndo_set_mac_address = stmmac_set_mac_address,//设置网络设备的 MAC 地址.ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid,//在接收 VLAN 数据包时,将 VLAN ID 添加到接收列表中.ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid,//从接收列表中删除指定的 VLAN ID
};
int stmmac_dvr_probe(struct device *device,struct plat_stmmacenet_data *plat_dat,struct stmmac_resources *res){.......ndev->netdev_ops = &stmmac_netdev_ops;......
}
在rk3568技术手册的20.6.10 Programming Guide章节中可以发现MAC的初始化过程可分为以下三个步骤:
- 初始化DMA
- 初始化MTL寄存器
- 初始化MAC寄存器
手册中对每个初始化过程又有较为详细的说明,可与源码中打开网络设备时(stmmac_open)的过程做比对。每次打开网络的时候会进行初始化操作。如下:
//kernel\linux\linux-5.10\drivers\net\ethernet\stmicro\stmmac\stmmac_main.c
static int stmmac_open(struct net_device *dev)
|-->ret = stmmac_init_phy(dev);//phy的初始化
|-->ret = stmmac_hw_setup(dev, true)|-->ret = stmmac_init_dma_engine(priv)//1.DMA初始化|-->stmmac_mtl_configuration(priv);//2.初始化MTL|-->stmmac_mmc_setup(priv)//3.后续开始配置mac......
- DMA初始化可以与rk3568手册中的20.6.10.1 Initializing DMA匹配分析
- 初始化MTL部分可与rk3568手册中的20.6.10.2 Initializing MTL匹配分析
- 配置MAC部分可与rk3568手册中的20.6.10.3 Initializing MAC 匹配分析
注:在stmmac_open函数中会stmmac_hw_setup->stmmac_init_dma_engine->stmmac_reset函数会执行dma的重启操作即调用初始化过程中赋值的reset操作,其中stmmac_reset为通过宏定义的,需要仔细看下。。。坑了半个小时才发现。。。。
#define stmmac_do_callback(__priv, __module, __cname, __arg0, __args...) \
({ \int __result = -EINVAL; \if ((__priv)->hw->__module && (__priv)->hw->__module->__cname) \__result = (__priv)->hw->__module->__cname((__arg0), ##__args); \__result; \
})
#define stmmac_reset(__priv, __args...) \stmmac_do_callback(__priv, dma, reset, __args)
MDIO/PHY
网络设备到mdio总线到phy驱动注册的主要流程如下:
//kernel\linux\linux-5.10\drivers\net\ethernet\stmicro\stmmac\stmmac_main.c
int stmmac_dvr_probe(struct device *device,struct plat_stmmacenet_data *plat_dat,struct stmmac_resources *res)
......
|-->ret = stmmac_mdio_register(ndev);//mdio总线注册|-->err = of_mdiobus_register(new_bus, mdio_node);|-->int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,struct module *owner)//kernel\linux\linux-5.10\drivers\net\mdio\of_mdio.c,解析设备树的配置文件后注册mdio总线|-->rc = __mdiobus_register(mdio, owner);//注册mdio总线|-->phydev = mdiobus_scan(bus, i);//根据phy的地址i扫描总线(bus)上phy设备|-->err = phy_device_register(phydev);//注册扫描到的phy设备
以上实现了mac和mido以及phy的关联。
PHY 是 IEEE 802.3 规定的一个标准模块,文档名称为《802.3协议英文原版_2018年》,文档按照SECTION进行分类,一共8个SECTION。选中“802.3-2018_SECTION2”,找到“22.2.4 Management functions”章节,此章节对 PHY 的前16 个寄存器功能进行了规定,一般phy都会满足这个要求的,所以通用 PHY 驱动是应该可以让PHY 芯片实现基本的网络通信。
收发流程
Linux网络设备驱动程序的体系结构如下图所示,从上到下可以划分为4层,依次为网络协议接口层、网络设备接口层、提供实际功能的设备驱动功能层以及网络设备与媒介层,这4层的作用如下所示。
- 网络协议接口层向网络层协议提供统一的数据包收发接口,不论上层协议是ARP,还是IP,都通过dev_queue_xmit()函数发送数据,并通过netif_rx()函数接收数据。这一层的存在使得上层协议独立于具体的设备。
- 网络设备接口层向协议接口层提供统一的用于描述具体网络设备属性和操作的结构体net_device,该结构体是设备驱动功能层中各函数的容器。实际上,网络设备接口层从宏观上规划了具体操作硬件的设备驱动功能层的结构。
- 设备驱动功能层的各函数是网络设备接口层net_device数据结构的具体成员,是驱使网络设备硬件完成相应动作的程序,它通过hard_start_xmit()函数启动发送操作,并通过网络设备上的中断触发接收操作。
- 网络设备与媒介层是完成数据包发送和接收的物理实体,包括网络适配器和具体的传输媒介,网络适配器被设备驱动功能层中的函数在物理上驱动。
在设计具体的网络设备驱动程序时,我们需要完成的主要工作是编写设备驱动功能层的相关函数以填充net_device数据结构的内容并将net_device注册入内核。
- 发送流程
网络发送时通过网络协议层后会调用到协议接口层即kernel\linux\linux-5.10\net\core\dev.c中dev_queue_xmit函数。此函数经过协议的解析和数据包的整理后会调用网络设备驱动,由上文的网络操作集中的赋值可知,在此开发板中采用的是stmmac_xmit,以下为stmmac_xmit
函数的调用过程
dev_queue_xmit —>__dev_queue_xmit—>dev_hard_start_xmit—>xmit_one—>netdev_start_xmit—>__netdev_start_xmit—>ndo_start_xmit(stmmac_xmit)
;
其中stmmac_xmit
的主要执行过程如下:
//kernel\linux\linux-5.10\drivers\net\ethernet\stmicro\stmmac\stmmac_main.c
int stmmac_xmit(struct sk_buff *skb)
|-->if (priv->tx_path_in_lpi_mode)stmmac_disable_eee_mode(priv);//如果当前处于EEE(节能以太网)模式,先禁用EEE模式
|-->if (skb_is_gso(skb) && priv->tso) {return stmmac_tso_xmit(skb, dev);//如果数据包是GSO且设备支持TSO则调用`stmmac_tso_xmit`处理TCP分段卸载
|-->has_vlan = stmmac_vlan_insert(priv, skb, tx_q);
|-->if (has_vlan)stmmac_set_desc_vlan(priv, first, STMMAC_VLAN_INSERT);//判断是否可以由硬件插入VLAN标签,并设置相应标志
|-->if (enh_desc)is_jumbo = stmmac_is_jumbo_frm(priv, skb->len, enh_desc);
|-->if (unlikely(is_jumbo)) {entry = stmmac_jumbo_frm(priv, tx_q, skb, csum_insertion);//如果数据包是巨帧,调用`stmmac_jumbo_frm`来处理,分配必要的传输描述符
|-->for (i = 0; i < nfrags; i++) {stmmac_set_desc_addr(priv, desc, des);//遍历数据包的所有分片,将每个分片的数据映射到DMA地址空间,并设置相应的传输描述符tx_q->tx_skbuff_dma[entry].last_segment = last_segment;//设置描述符的地址和长度,并标记是否为最后一个分片stmmac_prepare_tx_desc(priv, desc, 0, len, csum_insertion,priv->mode, 1, last_segment, skb->len);//准备每个传输描述符,设置必要的传输参数......
|-->stmmac_enable_dma_transmission(priv, priv->ioaddr);//启动DMA传输......
stmmac_xmit函数主要实现将数据包从网络设备(如以太网卡)发送到网络的功能,包括数据包的分片处理、硬件加速功能(如TSO和TBS)、VLAN标签插入以及DMA传输的启动和管理。
- 接收流程
接收的流程是采用的NAPI(首先采用中断唤醒数据接收的服务程序,然后 POLL 的方法来轮询数据)的机制。整体过程如下:
在打开网络(stmmac_open)时会进行中断设置如下:
//drivers\net\ethernet\stmicro\stmmac\stmmac_main.c
static int stmmac_open(struct net_device *dev)
|-->ret = request_irq(dev->irq, stmmac_interrupt,IRQF_SHARED, dev->name, dev);//为网络设备的主要中断`dev->irq`分配中断处理函数
|-->ret = request_irq(priv->wol_irq, stmmac_interrupt,IRQF_SHARED, dev->name, dev);//为网络设备的唤醒中断`dev->wol_irq`分配中断处理函数
|-->ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,dev->name, dev)//为网络设备的低功耗中断`dev->lpi_irq`分配中断处理函数
由以上可知分配的低功耗、唤醒以及主要中断函数皆为stmmac_interrupt
。
//drivers\net\ethernet\stmicro\stmmac\stmmac_main.c
static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
....//处理唤醒以及低功耗模式,并更新网络状态。
|-->stmmac_dma_interrupt(priv);|-->for (chan = 0; chan < channels_to_check; chan++)status[chan] = stmmac_napi_check(priv, chan);//检查DMA通道的中断状态|-->if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {//接受中断时|-->if (napi_schedule_prep(&ch->rx_napi)) {//检测napi可以被调度|-->__napi_schedule(&ch->rx_napi);|-->____napi_schedule(this_cpu_ptr(&softnet_data), n)|-> list_add_tail(&napi->poll_list, &sd->poll_list);//添加网络层的poll处理队列|-> __raise_softirq_irqoff(NET_RX_SOFTIRQ);//触发接收的网络接收一个软中断
由以上可知在接收到网络中断后会触发一个软中断,下面就开始分析软中断处理函数如何注册的。
在驱动加载过程中stmmac_dvr_probe函数中的stmmac_napi_add函数会添加
//drivers\net\ethernet\stmicro\stmmac\stmmac_main.c
int stmmac_dvr_probe(struct device *device,struct plat_stmmacenet_data *plat_dat,struct stmmac_resources *res)
|-->stmmac_napi_add(ndev);|-->netif_napi_add(dev, &ch->rx_napi, stmmac_napi_poll_rx,NAPI_POLL_WEIGHT);//初始化napi的上下文|-->napi->poll = poll;
触发软中断
在/net/core/dev.c中static int __init net_dev_init(void)函数内可以看到触发软中断
static int __init net_dev_init(void
|-->open_softirq(NET_RX_SOFTIRQ, net_rx_action);
而net_rx_action函数内会调用work = n->poll(n, weight)
;如下
static __latent_entropy void net_rx_action(struct softirq_action *h)
|-->budget -= napi_poll(n, &repoll);|-->work = n->poll(n, weight)//此处即调用的netif_napi_add函数添加的驱动接收函数stmmac_napi_poll_rx
而poll是由netif_napi_add
函数设置了设备接收的函数static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget)
//drivers\net\ethernet\stmicro\stmmac\stmmac_main.c
static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget)
|-->priv->xstats.napi_poll++;
|-->work_done = stmmac_rx(priv, budget, chan);//接收线程
|-->if (work_done < budget && napi_complete_done(napi, work_done))//用于处理NAPI接收完成的通知
鸿蒙服务组件(网络管理)
网络管理主要分为连接管理、策略管理、流量管理、网络共享、VPN管理以及以太网连接等模块,其中连接管理、策略管理、流量管理为基础服务,归档在netmanager_base仓,以太网连接、网络共享、VPN管理三个模块为可裁剪扩展模块,归档在netmanager_ext仓
foundation/communication/netmanager_base/
├─figures # 架构图
├─frameworks # 接口实现
│ ├─js # JS接口
│ └─native # native接口
├─interfaces # 接口定义
│ ├─innerkits # native接口
│ └─kits # JS接口
├─sa_profile # sa定义
├─services # IPC服务端实现
│ ├─common # 公用代码存放目录
│ ├─etc # 进程配置文件目录
│ ├─netconnmanager # 网络管理核心代码目录
│ ├─netmanagernative # 网络子系统服务端代码
│ ├─netpolicymanager # 策略管理核心代码目录
│ ├─netstatsmanager # 流量管理核心代码目录
│ ├─netsys_bpf_stats # bpfReader为service提供功能接口目录
│ └─netsyscontroller # netsys客户端代码目录
├─test # 测试代码
│ ├─fuzztest # FUZZ测试目录
│ ├─netconnmanager # 网络管理单元测试目录
│ ├─netmanagernative # 网络子系统服务端单元测试目录
│ ├─netpolicymanager # 策略管理单元测试目录
│ ├─netstatsmanager # 流量统计单元测试目录
│ └─netsys_bpf_stats # bpfReader单元测试目录
└─utils # 公共功能├─common_utils # 共同库目录├─log # 日志实现目录└─napi_utils # 公用NAPI代码目录
参考资料
《OpenHarmony如何为内核打patch》
《Rockchip RK3568 TRM Part2 V1.1-20210301》
《RK3568_LPDDR4_HARMONYOS_CARRIER_原理图》
《C5279059_以太网收发器_YT8531SC_规格书_WJ375052》
《802.3协议英文原版_2018年》
网络管理子系统
网络管理