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

相关推荐
蜀黍@猿3 小时前
ARM 汇编入门(十):标量浮点与 VFP 指令全解析
汇编·arm开发·stm32·mcu
Good白10192 天前
嵌入式:1.嵌入式入门|初识嵌入式、处理器、ARM与STM32
arm开发·stm32·嵌入式硬件
물の韜3 天前
ZYNQ/FMQL系列Linux之I2C开发实战
linux·arm开发·嵌入式硬件·设备树·iic·zynq
女神下凡4 天前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
女神下凡8 天前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
NamoAmitabha1288 天前
ARM Cortex-A9 核心架构(演化后的“缝合怪”)--deepseek
arm开发·zynq--ps
AllData公司负责人8 天前
AllData 可定义数据中台完成信创适配|银河麒麟 + 海光X86 CPU / 华为鲲鹏ARM CPU+ OceanBase / 人大金仓国产化环境部署落地
大数据·arm开发·数据库·人工智能·oceanbase·kingbase
a5986529 天前
ARM服务器搭建云手机靠谱吗?个人自建方案优缺点总结
服务器·arm开发·智能手机·云手机
jiecy9 天前
在 ARM 的 UOS 系统里布署 WebDav
arm开发·docker·debian