SylixOS网络开发(五)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2020年12月26日19:58:01 评论 1,081

1. 发送零拷贝问题

某SOC是四核A9平台,网络控制器是dw,不使用发送零拷贝的tcp发送带宽是93M/s,使用发送零拷贝之后的发送带宽竟然降低到了20M/s。最后查出的原因是用发送零拷贝时需要cache flush,这个函数的执行时间在A9平台上贼慢,后来写了个测试程序,cache flush 2KB的数据需要约400us左右,而用memcpy拷贝2KB的数据只需要50us左右,接着在飞腾2000四核平台上测试cache flush 2KB的数据只需要800ns左右。。。。。。从这个案例中可以看出驱动中是否使用发送零拷贝需要分析cache flush和memcpy的速度才能下结论。

2. 接收零拷贝问题

还是某SOC dw网卡驱动==,接收零拷贝池使用不带cache属性时,一切工作正常,当使用带cache属性的零拷贝池时,用iperf测网速没啥问题,但是如果ping大包的话就会有丢包的现象,然后用tcpdump抓包会打印出ip包大小不正常,最后查出的问题是驱动中调用cache失效代码的位置有问题,放到正确的位置进行cache失效后,一切都正常了。下面请看具体的分析。

我们知道零拷贝池中的数据组织如下:

SylixOS网络开发(五)

我们重点来关注下payload部分,其实payload区域前面有一些字节是预留的,如下所示:

SylixOS网络开发(五)

  • PAD_SIZE是2字节大小。
  • VLAN_SIZE是4字节大小。
  • RESERVE大小是可以给程序员控制。
  • data区域就是真正存放帧数据的地方。

整个payload区域的起始地址是cacheline对齐的,A9的cacheline大小为32字节,在某SOC的dw网卡驱动中,RESERVE大小为32字节,所以data区域相对于payload起始地址的偏移是2+4+32=38字节。在原来的驱动中,接收处理在调用input方法上送数据之前调用了cache失效接口来失效data区域的cache,但是data区域的起始地址并不是cacheline对齐的,在sylixos中的cache失效接口实现中,如果起始地址不cacheline对齐的话,会先计算出cacheline对齐的地址,然后对这个cacheLine进行数据回写,从下一个cacheline开始才是真正的去失效cache。这样就会带来问题,由于我们在data区域中的数据是dma接收好的最新的数据,在调用cache失效接口时,由于data区域起始地址不是cacheline对齐,所以会将data起始地址所在的那个cacheline先数据回写,这样就会有64-38=26字节的数据被回写到data区域的前26字节,而这前26字节正好包含了以太网帧头部和部分IP头部的数据,从而导致接收到的真实数据被cache中的数据覆盖了,这就导致了网络的异常。

由于驱动中只在调用input方法之前失效cache,当协议栈处理完payload之后,可能会去写这个区域,从而导致cache中缓存了数据,当下一次需要失效的时候,就会把cache中的数据回写到data区,从而引起异常。

解决的方法有两种:

  • 第一种在失效前,手动通过data区域起始地址计算cacheline对齐的地址,然后再把这个地址传入API中进行cache失效。
  • 第二种方法需要调整调用cache失效的位置,我们需要在初始化的时候先将所有的data区域cache失效,然后在input方法调用成功之后,也就是协议栈处理完接收数据之后,再次对data区域cache失效,这样就能保证在pbuf上送协议栈之前,payload中的数据是最新的。
gewenbin
  • 本文由 发表于 2020年12月26日19:58:01
  • 转载请务必保留本文链接:http://www.databusworld.cn/9851.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: