KNI全称为Kernel NIC Interface,是DPDK框架下实现的DPDK与内核的高性能通信方案。
主要解决物理网卡被DPDK接管后,仍然需要使用内核协议栈的问题;
此外,相对于TUN/TAP方式,减少一次拷贝,性能更高。
KNI是DPDK引入的技术,早期实现上为了高性能有不少问题,以下逐个分析(注:部分问题在最新版本中已经解决)
KNI实现中,DPDK程序与内核间,一般都是两个线程在处理,通信方式是FIFO,收发方向都有单独的FIFO;
早期实现仅考虑了strongly-ordered systems,典型的x86,因为未触发乱序问题(buffer与read/write指针的乱序行为)。
后续版本中,ARM环境的引入暴露了此问题,导致mbuf被复用等问题发生。
解决方式是引入合适的memory barrier。
之前提到KNI相对于TUN/TAP方式,减少了一次拷贝。
从上面的对比可以看出,KNI核心是共享大页内存,FIFO传递物理地址,内核收到后转换为内核地址进行处理。
但是在网络中,存在一种mbuf chain情况(典型的,mbuf本身2k,收包9k,会串成5个mbuf构成的chain),在用户态这些mbuf都是通过虚拟地址方式连结,往KNI传递时会遇到地址转换问题。
分两种情况:
KNI早期实现未考虑KNI释放时,FIFO中mbuf的释放问题,反复创建/释放KNI口的情况下可能会导致mbuf泄露。
修复方式:KNI释放时转换未处理的mbuf
https://git.dpdk.org/dpdk/commit/?id=e77fec694936ce067153c5a6596c6bc818baaa5c
当前KNI内核部分,是通过启动一个内核线程轮询收包实现,为了避免占用CPU过多,又加入了sleep机制,导致KNI的CPU/时延/吞吐等都不是很理想。更合理的方式是通过eventfd机制,用户态发包后唤醒kernel处理,采用NAPI类似方式,使得CPU/时延/吞吐达到理想状态。
当前KNI不支持多队列,极限性能受限(single线程模式不超过1GBps,mutiple线程模式又占用过多资源)。
在实现eventfd基础上,再实现多队列机制,可以让性能更加,同时在闲时不占用额外资源。
https://doc.dpdk.org/guides/prog_guide/kernel_nic_interface.html
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。