DPDK KNI 官方文档

概览


KNI(Kernel NIC Interface)是指被DPDK绑定端口之后,希望(一部分)报文走kernel的网络协议栈而开发的。
优势:

  • 比 Linux TUN/TAP interfaces的操作快(通过取消系统调用copy_to_user()/copy_from_user())。
  • 允许使用Linux标准网络工具ethtool, ifconfig和tcpdump管理DPDK端口。
  • 允许端口使用内核网络协议栈。

KNI 启动


dpdk 2.2 example/kni/main.cmain-->main_loop,它是dpdk启动kni应用时的应用。

  • 获取配置,lcore是负责rx还是tx。
  • 如果当前的lcore是负责rx,则死循环调用接口kni_ingress进行报文的收取。
  • 如果当前的lcore是负责tx,则死循环调用接口kni_egress进行报文的发送。
  • 因为一个lcore只能负责一个死循环,所以rx和tx必须至少每个安排一个lcore去操作,不然容易出问题。
  • 以上的两个死循环中有原子操作的标志读取,为了判定循环是否退出。退出表示靠signal_handler信号触发。

报文的接收


应用层

kni_ingress

  • rte_eth_rx_burst直接从接口读取数据。
  • rte_kni_tx_burst将报文放在kni->rx_q fifo的buffer区域。
  • rte_kni_handle_requestkni->req_q拿到request,然后根据修改mtu或者设置接口的命令做相应的操作,最后将response放回kni->resp_q

内核

应用层调用内核的open(main-->init_kni-->rte_kni_init-->open-->kni_open)创建线程kni_thread_single

  • 线程包含三个循环,第一层循环是判定线程是否要结束,第二层循环是接收循环,默认1000次,第三层循环是所有的kni设备。
  • 如果是kni host则调用kni_chk_vhost_rx
  • 其他情况调用kni_net_rx-->kni_net_rx_func-->kni_net_rx_normal

kni_net_rx_normal

  • 调用kni_fifo_getkni-->rx_q fifo的buffer区域获取报文。
  • 根据上面拿到的报文数,进行循环。
  • 申请skb,申请失败则drop,申请成功,将rte_mbuf的报文填充到skb,调用netif_rx
  • 将buffer放入kni->free_q,以备后期释放。

报文的发送


内核

kni设备的ndo_start_xmitkni_net_tx

  • 如果是RTE_KNI_VHOST,则丢掉。
  • kni->alloc_q fifo拿到buffer。
  • 将skb填充到rte_mbuf
  • 放入kni->tx_q

应用层

  • 循环从不同的kni收取报文。
  • rte_kni_rx_burstkni->tx_q fifo拿取报文。
  • 调用rte_eth_tx_burst发送报文。

流程

请输入图片描述

最后修改:2021 年 08 月 20 日
如果觉得我的文章对你有用,请随意赞赏