基于XDMA的简易FPGA网卡实现(一)
开发环境
FPGA开发板 | XC7K325T |
---|---|
CPU | RK3399 |
开发主机 | Win11 and ubuntu20.04 |
IDE版本 | Xilinx Vitis IDE v2021.1.0 (64-bit) Vivado v2021.1 (64-bit) |
实现原理
FPGA侧
-
top
模块:顶层模块,其中例化了xmda和axil_rw模块 -
xdma
ip:pcie dma,提供axi-lite接口读写fpga寄存器,提供axi-stream接口收发数据流 -
axil_rw
模块:将xdma的axi-lite信号用于读写mac模块寄存器 -
clk_wiz_125m_90phase
:提供90°相位125M时钟,供mac使用 -
gpio_dri
模块:gpio控制器,用于模拟mdio时序读写phy -
axis_dwidth_converter
ip:提供axis数据位宽转换功能,将xdma 128bit axi-stream转为8bit供fifo使用,使用了两个此模块实现双向转换 -
axis_data_fifo
:两个fifo,缓存mac接收和需要发送的数据 -
eth_mac_1g_rgmii
模块:源自verilog-eth开源项目,具有rgmii接口和速率自适应逻辑的三模式以太网MAC,axi-stream接口 -
ila
ip:抓信号调试
CPU侧
编写linux标准网卡驱动,使用零拷贝方式收发数据
发送流程
- 在ndo_start_xmit函数中进行发送
- 将sk_buff的head和fragmentation dma_map_single得到物理地址,将物理地址和长度写入描述符
- 发送前netif_stop_queue,在发送完成中断唤醒。如果直接继续发送,则新的sk_buff会在上一次的完成中断中被free
- 开启dma使能,进行发送
- 在发送完成中断中关闭发送dma使能,dma_unmap_single sk_buff的物理地址,free sk_buff。判断发送fifo是否超出发送阈值。超出则运行wait_work工作队列,在work中等待fifo低于启动阈值后netif_wake_queue唤醒发送队列,未超出阈值则netif_wake_queue唤醒发送队列
接收流程
-
在网卡驱动的probe函数中进行第一次接收,在接收完成中断或tasklet中配置后续接收
-
收到接收完成中断后关闭接收dma使能
-
dma会将接收结果写回到result内存,读取result内存获取包长度
-
skb_put修改sk_buff的tail和len,dma_unmap_single sk_buff的物理地址,执行netif_rx提交到协议栈
-
接收完成后开始准备新一轮的接收,在中断或tasklet中dev_alloc_skb一个1514字节的skb
-
将sk_buff的head和fragmentation dma_map_single得到物理地址,将物理地址和长度写入描述符
-
开启dma使能,进行接收
测试
feth0为fpga网卡,设置ip为192.168.1.208;电脑网卡配置成百兆全双工,ip设置为192.168.1.108。
root@NanoPC-T4:/home/pi# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.31.131 netmask 255.255.255.0 broadcast 192.168.31.255
inet6 fe80::2c2b:6887:1120:373c prefixlen 64 scopeid 0x20<link>
ether fa:f1:04:39:02:9a txqueuelen 1000 (Ethernet)
RX packets 739 bytes 60003 (58.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 600 bytes 150153 (146.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 60
feth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.208 netmask 255.255.255.0 broadcast 192.168.1.255
ether 00:00:00:00:00:00 txqueuelen 1000 (Ethernet)
RX packets 35382 bytes 2069214 (1.9 MiB)
RX errors 0 dropped 7 overruns 0 frame 0
TX packets 65186 bytes 98674228 (94.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 24 bytes 1944 (1.8 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 24 bytes 1944 (1.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ping测试
- ping 20000包长时,ICMP包分成了13个包发送,且延迟很长4ms,抓包正常
root@NanoPC-T4:/home/pi# ping 192.168.1.108
PING 192.168.1.108 (192.168.1.108) 56(84) bytes of data.
64 bytes from 192.168.1.108: icmp_seq=1 ttl=128 time=1.05 ms
64 bytes from 192.168.1.108: icmp_seq=2 ttl=128 time=0.992 ms
64 bytes from 192.168.1.108: icmp_seq=3 ttl=128 time=0.876 ms
64 bytes from 192.168.1.108: icmp_seq=4 ttl=128 time=1.01 ms
64 bytes from 192.168.1.108: icmp_seq=5 ttl=128 time=0.901 ms
64 bytes from 192.168.1.108: icmp_seq=6 ttl=128 time=1.02 ms
64 bytes from 192.168.1.108: icmp_seq=7 ttl=128 time=0.930 ms
^C
--- 192.168.1.108 ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 6011ms
rtt min/avg/max/mdev = 0.876/0.968/1.051/0.061 ms
root@NanoPC-T4:/home/pi# ping -s 20000 192.168.1.108
PING 192.168.1.108 (192.168.1.108) 20000(20028) bytes of data.
20008 bytes from 192.168.1.108: icmp_seq=1 ttl=128 time=4.23 ms
20008 bytes from 192.168.1.108: icmp_seq=2 ttl=128 time=3.93 ms
20008 bytes from 192.168.1.108: icmp_seq=3 ttl=128 time=4.32 ms
20008 bytes from 192.168.1.108: icmp_seq=4 ttl=128 time=3.95 ms
20008 bytes from 192.168.1.108: icmp_seq=5 ttl=128 time=4.21 ms
20008 bytes from 192.168.1.108: icmp_seq=6 ttl=128 time=4.01 ms
^C
--- 192.168.1.108 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5010ms
rtt min/avg/max/mdev = 3.930/4.107/4.324/0.152 ms
iperf测试
板子做客户端
- 抓包正常,速度只有33.5M
板子做服务器
- 抓包正常,速度正常94.9M
tftp下载文件
wireshark无警告和错误,下载后md5校验一致
结论
-
百兆网卡发送33.5M,接收95M。XDMA虽然是sgdma,但驱动一次只能发送一个包(可能有多个分片),等完成中断才能唤醒下一次发送,所以发送速度不理想。
-
修改xdma发送机制还可以优化发送速度,后续研究corundum开源项目,使用循环缓冲区实现高性能网卡文章来源:https://www.toymoban.com/news/detail-853464.html
关注博主公众号,优质文章不断更新
文章来源地址https://www.toymoban.com/news/detail-853464.html
到了这里,关于基于XDMA的简易FPGA网卡实现(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!