本文分析说明Zephyr网络层offload的使用和运行调用机制。
在Zephyr网络传输Offloading–概览一文中提到了Zephyr网络传输offloading支持socket offloading API, 本文就如何将第三方TCP/IP协议栈以offloading的方式添加到zephyr中和Zephyr的调用机制进行说明。
使用
net offload的实现被放到drv中,然后在编译期进行初始化函数注册,静态的保留在net iface的init section中,运行时进行初始化注册iface API后,应用层使用时就可以调用到drv中实现的net offload.
1.配置
配置CONFIG_NET_OFFLOAD=y
,编译时会启用网络层offload
2.实现net offload API
按照net_offload.h中struct struct net_offload的定义使用第三方TCP/IP API实现zephyr的net_offload抽象
1 | struct net_offload { |
3.实现net offload 初始化函数
net offload初始化函数完成将vender_offload注册到iface内
1 | int vender_offload_init(struct net_if *iface) |
4.注册设备
使用宏NET_DEVICE_OFFLOAD_INIT进行offload设备注册
1 | struct net_if_api { |
之后上层调用net_offload.h中的net_offload_ API就对应的调用到了vender_offload内的vender_ API
实现
本小节分析net_offload_ API是如何调用到对应的vender_ API
编译时注册
Z_DEVICE_DEFINE注册了vender_init的初始化函数是驱动级的,我们不展开分析,只分析net offload一路。
NET_DEVICE_OFFLOAD_INIT->Z_NET_DEVICE_OFFLOAD_INIT被展开为两个宏Z_DEVICE_DEFINE,NET_IF_OFFLOAD_INIT,Z_DEVICE_DEFINE注册了vender_init的初始化函数是驱动级的,我们不展开分析,只分析net offload一路。
1 | #define Z_NET_DEVICE_OFFLOAD_INIT(node_id, dev_name, drv_name, init_fn, \ |
这里dev_name是CONFIG_NET_VENDER_NAME,假设我们配置为”vender”, sfx为0,_mtu是VENDER_MTU,假设配置为2048,对NET_IF_OFFLOAD_INIT进行展开为
1 | static struct net_if_dev __net_if_dev_vender_0 __attribute__((section(._net_if_dev.static.__net_if_dev_vender_0))={ |
Z_DEVICE_DEFINE在zephyr驱动模型一文中DEVICE_DEFINE已经说明过,这里不做详细展开,只要知道这里展开的形式如下即可:
1 | const struct device _device_vender = { |
总结上面的放置和指向关系如下图:
运行时初始化
运行时初始化调用关系如下:
Net_core.c (subsys\net\ip):net_init->init_rx_queues->Net_if.c (subsys\net\ip): net_if_init
1 | void net_if_init(void) |
net offload函数的调用流程
前面提到过上层调用net_offload.h中的net_offload_ API就对应的调用到了vender_offload内的vender_ API,这里以net_offload_send为例来看
1 | static inline int net_offload_send(struct net_if *iface, |
net offload与TCP/IP的对接
Zephyr的TCP/IP对上的接口都封装在net_context内,net_context_ API都有用net_offload_ API实现,在使用offload的情况下,net_offload的API会被编译到net_context内,以recv为例
1 | int net_context_recv(struct net_context *context, |
虽然不同的API有一定的差异,但都是和net_offload_ API是对应的,详细可以在net_context.c中搜索CONFIG_NET_OFFLOAD,看每个API不同的实现。
另外需要说明的是,net offload是在TCP/IP级别,没有对ICMP进行offload,因此无法支持icmp,也就没有办法实现ping. 在icmpv4.c中也可以看到offload下会直接返回错误
1 | int net_icmpv4_send_echo_request(struct net_if *iface, |