dpdk实现kni

KNI(Kernel NIC Interface,内核网卡接口)是 DPDK 提供的一套机制,用于让 DPDK 用户态应用程序与 Linux 内核网络协议栈之间交换数据包。


我们可以只用dpdk解析特定的协议,然后把其他的协议写回内核中,交由内核处理,实现把数据写回内核的就是kni,也可以通过kni从内核中读取到数据。

dpdk会虚拟化一个eth,称之为veth,这个veth在内核中也有一个相应的结构体net_device。

把数据写回到veth的net device这样内核就可以通过这个结构体来读取网卡中的数据了。


查看kni设备,这个是在./usertools/dpdk-setup.sh中45 Insert KNI module开启的

root@ubuntu:/home/king/share/dpdk/dpdk-stable-19.08.2# ls /dev/kni -l

这个设备就是往内核写数据所使用的设备。

dpdk也提供了一套api接口来操作kni。

这个虚拟化的veth与其他eth有区别,veth有两个功能,

  1. 像其他eth一样,在内核中有net device,可以供内核使用,内核协议栈可以像普通网卡一样用它收发。

  2. dpdk中有操作veth的kni,可以把数据读取到dpdk中。

    // 注册的回调函数
    // 当ifconfig up/down时,会触发
    static int fun_config_network_if(uint16_t port_id,uint8_t if_up){
    if(!rte_eth_dev_is_valid_port(port_id)){
    return -EINVAL;
    }

    复制代码
     int ret = 0;
     if(if_up){
         rte_eth_dev_stop(port_id);
         ret = rte_eth_dev_start(port_id);
     } else {
         rte_eth_dev_stop(port_id);
     }
    
     if( ret < 0){
         printf("kni dev port start fail. port=%d\n",port_id);
         return ret;
     }
    
     return 0;

    }

    // 初始化kni
    struct rte_kni *fun_alloc_kni(struct rte_mempool *mbuf_pool){

    复制代码
     struct rte_kni *kni_hanlder = NULL;
     struct rte_kni_conf conf;
     memset(&conf,0,sizeof(struct rte_kni_conf));
     // 网卡名字
     snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth2");
     // 绑定的dpdk端口
     conf.group_id = gDpdkPortId;
     // kni内存池单个包的大小
     conf.mbuf_size = MAX_PACKET_SIZE;
     // 绑定网口的mac地址
     rte_eth_macaddr_get(gDpdkPortId, (struct rte_ether_addr *)conf.mac_addr);
     // 配置mtu
     rte_eth_dev_get_mtu(gDpdkPortId, &conf.mtu);
    
     print_ethaddr("kni alloc init mac: ",(struct rte_ether_addr *)conf.mac_addr);
    
     struct rte_kni_ops ops;
     memset(&ops,0,sizeof(struct rte_kni_ops));
    
     ops.port_id = gDpdkPortId;
     // 注册启停回调
     ops.config_network_if = fun_config_network_if;
    
     kni_hanlder = rte_kni_alloc(mbuf_pool, &conf, &ops);
     if(kni_hanlder == NULL){
         rte_exit(EXIT_FAILURE,"kni hanlder malloc fail\n");
     }
    
     return kni_hanlder;

    }

开启混杂模式:

rte_eth_promiscuous_enable(gDpdkPortId);

接收所有经过网卡的数据包,而不是只接收目的mac是本机地址的数据包。


如果在

ifconfig vEth2 192.168.222.134 up

时提示超时,是因为没有执行这两个函数

rte_kni_tx_burst()

rte_kni_handle_request()


在插入arp table时候如果插入的是相同的结点,那么这个结点next和recv都会指向自己,查找时候就进入死锁。

所以添加len进行限制查找次数,再对添加时候进行加锁。


可以把数据的解析和打包都交给sever线程去实现,pktprocess只负责协议的分发。


查看kni设备,这个是在./usertools/dpdk-setup.sh中45 Insert KNI module开启的

root@ubuntu:/home/king/share/dpdk/dpdk-stable-19.08.2# ls /dev/kni -l

ifconfig vEth2 192.168.222.134 up


启动程序,udp process 可以正常收发。

但是tcp 连接不上。

ifconfig vEth2 192.168.222.134 up

tcp客户端可以连接222.134但是信息一直发送不出去。


启动程序,有时候udp process 可以正常收发。tcp process 可以正常收发。有时候都不能正常收发。

ifconfig vEth2 192.168.222.134 up

tcp客户端可以连接222.134但是信息一直发送不出去,提示发送失败。

udp 可以正常收发。


tcp process中处理了很多 222.128的数据,所以把tcp process的打印关掉了,用客户端连接222.134,没有反应,怀疑tcp process一直在处理222.128,处理不过来222.134的数据。

udp process可以正常收发。


只要

ifconfig vEth2 192.168.222.134 up

tcp客户端可以连接222.134,但是信息就发送不出去。

UDP客户端可以正常收发。



pkt process

rte_cpu_to_be_16

我写成了

if(ehdr->ether_type == rte_cpu_to_le_16(RTE_ETHER_TYPE_IPV4))

释放mbuf

rte_pktmbuf_free(tcpmbuf);

写成了

rte_free(tcpmbuf);


文章参考<零声教育>的C/C++linux服务期高级架构系统教程学习:0voice · GitHub

相关推荐
大叔学Linux18 小时前
FreeRTOS任务切换笔记
arm开发·笔记
Chery114019 小时前
DPE5500 SPI以太网协议栈芯片详解:10/100M以太网、硬件TCP/IP与国产替代方案
arm开发·网络协议·tcp/ip
a5986521 天前
原生ARM云手机实测|ARM服务器底座,主流手游兼容性、闪退、帧率专项测试
服务器·arm开发·智能手机·云手机
a5986521 天前
工作室批量多开云手机|ARM 服务器方案成本解析、架构选型与踩坑总结
服务器·arm开发·智能手机·云手机
a5986522 天前
无公网IP,ARM服务器搭建云手机远程访问方案
服务器·arm开发·tcp/ip·云手机
en.en..2 天前
volatile 完整深度教程(C 代码 + 带注释 ARM 汇编 + 硬件中断原理 + 分步运行时序)
c语言·汇编·arm开发
下辈子不要当码农2 天前
项目框架搭建(2)
arm开发
女神下凡3 天前
芯参谋(61):PMSM永磁同步电机驱动电路设计指南
arm开发·单片机·嵌入式硬件·硬件工程·设计规范
早八晚十啊3 天前
基于ARM Cortex-A53与LVGL 9.0的智能车载系统设计与实现
arm开发·车载系统