1.结构框图
1.1网络协议层:
为上层协议提供接口,其中它用到的关键数据结构都是skbuff。
skbuff 定义再include/linux/skbuff.h比较关键的几个成员是
网络协议栈(TCP/IP)每层(传输层,网络层)都会再head与data之间添加协议头,在tail与end之间添加新的协议,所以sk_buff结构体在各层协议之间传输不是通过拷贝结构体,而是通过移动这四个指针,来增加/移除协议头。下面介绍的sk_buff的操作接口都是定义在include/linux/skbuff.h
1.1.1 分配sk_buff的接口
struct sk_buff *alloc_skb(unsigned int size, gfp_t priority);
struct sk_buff *dev_alloc_skb(unsigned int len);
1.1.2 释放sk_buff常用接口
void kfree_skb(struct sk_buff *skb);
void dev_kfree_skb(struct sk_buff *skb);
1.1.3 变更sk_buff
void skb_reserve(struct sk_buff *skb, int len): 对于一个空的缓冲区而言,可以调整缓冲的头部,会把data和 tail指针同时后移len。一般用在一个新sk_buff来腾出头部空间。
unsigned char *skb_put(struct sk_buff *skb, unsigned int len):在尾部增加数据 会把tail指针后移len。
unsigned char *skb_push(struct sk_buff *skb, unsigned int len);在头部增加数据 会把tail指针前移len。
unsigned char *skb_pull(struct sk_buff *skb, unsigned int len):从起始位置删除数据。
1.1.4 生成 sk_buff步骤:
(1).刚申请时候,head,data,tail指针重合。
(2).调用skb_reserve,后移data tail指针,预留出头部空间,因为在打包网络数据包的过程需要添加很多包头,所以头部空间尽量留大一点。
(3).存储数据。skb_put 后移tail 来添加数据段。
(4).调用push 前移动data指针,插入协议头
1.2 网络设备接口层:
为了统一标准,抽象出了net_device结构体,实现多种硬件在软件上的统一。
定义在include/linux/net_device.h
挑几个成员说说:
char name[IFNAMSIZ]:网络设备名称。
unsigned long base_addr:网络设备IO及地址。
unsigned char *dev_addr:存放设备硬件地址。
struct net_device_ops *netdev_ops:网络设备硬件操作函数。
const struct ethtool_ops *ethtool_ops:与用户空间ethtool工具各个命令对应。
const struct header_ops *header_ops:对应硬件的头部操作,主要是完成创建硬件头部和从给定的sk_buff分析出头部等操作。
1.3 设备驱动层。
1.3.1 rk端mac驱动
平台rk , 芯片 ksz-8563
先来看soc这端的mac驱动:
drivers\net\ethernet\stmicro\dwmac-rk.c
依然采用平台总线框架,设备树的mac节点的compatible成员匹配后调用rk_gmac_probe;
调用rk_gmac_probe后最主要会调用stmmac_dvr_probe来初始化硬件:
主要会做以下事情:
alloc_etherdev实例化net_device。
stmmac_set_ethtool_ops(ndev):设置ethool操作函数。
ndev->netdev_ops = &stmmac_netdev_ops:给到网络设备需要的一系列操作函。
获取所需要的时钟等。
netif_napi_add 添加napi机制。
判断是否支持dma,给与dma相关的操作函数mac->dma = &dwmac100_dma_ops。
stmmac_mdio_register 注册mdiobus。
register_netdev 注册网络设备。
1.3.2 stmmac_netdev_ops实现的函数:
1.3.3 NAPI
它的核心概念就是不采用中断的方式读取数据,而代之的是以首先采用中断唤醒数据接收的服务程序,然后利用POLL的方法来轮询数据。
此驱动中就采用了napi机制来接受数据包,流程如下。
1.3.1 ksz-8563
此芯片是一个交换机芯片 内部构造如下,可以看到出去有两个port,对应两个RJ45接口,并且每个接口都有个对应的phy,soc 与 8563之间是通过RMII 来实现mac to mac的通信,再由mac经过 swich engine来转到另外的mac 再传到phy。这种芯片跟单纯的phy有所不同。
代码 路径 /driver/net/ethernet/micrel
此芯片不是单纯的phy,是个交换机芯片,其中的驱动十分复杂,包含了mac phy phy port等等各种的驱动,这里不做过多赘述。