一、概念

Intel® DPDK全称Intel Data Plane Development Kit,是intel提供的数据平面开发工具集,为Intel architecture(IA)处理器架构下用户空间高效的数据包处理提供库函数和驱动的支持,它不同于Linux系统以通用性设计为目的,而是专注于网络应用中数据包的高性能处理。目前已经验证可以运行在大多数Linux操作系统上。DPDK使用了BSDLicense,极大的方便了企业在其基础上来实现自己的协议栈或者应用。目前出现了很多基于 dpdk 的高性能网络框架,OVS 和 VPP 是常用的数据面框架,mTCP 和 f-stack 是常用的用户态协议栈。
    需要强调的是,DPDK应用程序是运行在用户空间上利用自身提供的数据平面库来收发数据包,绕过了Linux内核协议栈对数据包处理过程。Linux内核将DPDK应用程序看作是一个普通的用户态进程,包括它的编译、连接和加载方式和普通程序没有什么两样。如下图2所示DPDK包处理流程绕过了内核直接到用户层进行处理,区别于传统的数据包先到内核最后再到用户层。

图1 传统网络包处理路径                                                                                                                                            图2 DPDK数据包处理路径

Kni(Kernel NIC Interface)内核网卡接口,是DPDK允许用户态和内核态交换报文的解决方案,例如DPDK的协议栈是专门处理DNS报文,其余的报文通过KNI接口返回给内核来处理。KNI模拟了一个虚拟的网口,提供dpdk的应用程序和linux内核之间通讯。用于DPDK和内核的交互,kni接口允许报文从用户态接收后转发到内核协议栈去。DPDK的包全部在用户空间使用内存池管理,内核空间与用户空间的内存交互不用进行拷贝,只做控制权转移。DPDK的主要对外函数接口都以rte_作为前缀,抽象化函数接口是典型软件设计思路,rte是指runtime environment,eal是指environmentabstraction layer. 下图3是kni的mbuf使用流程图,可以看出报文的流向,因为报文在代码中其实就是一个个内存指针。其中rx_q右边是用户态,左边是内核态。最后通过调用netif_rx()将报文送入linux协议栈,这其中需要将dpdk的mbuf转换成skb_buf。当linux向kni端口发送报文时,调用回调函数kni_net_tx(),然后报文经过转换之后发送到端口上。rte_pktmbut_free()把内存重新释放到mbuf内存池中。

图3    数据包通过KNI的流程

二、DPDK的Helloworld代码示例

HelloWorld是最基础的入门程序,代码简短,功能也不复杂。它建立了一个多核(线程)运行的基础环境,每个线程会打印“hello from core #”,core # 是由操作系统管理的。

int  main(int    argc, char **argv)
{
   int ret;
   unsigned lcore_id; 
   ret = rte_eal_init(argc, argv);

   )
          rte_panic("Cannot init    EAL\n");

   /* call lcore_hello() on every slave    lcore */
   RTE_LCORE_FOREACH_SLAVE(lcore_id)    {
          rte_eal_remote_launch(lcore_hello,    NULL, lcore_id);
   } 

   /* call it on master lcore too */
   lcore_hello(NULL); 
   rte_eal_mp_wait_lcore(); 
   ;
}

对于HelloWorld这个实例,最需要的参数是“-c <core mask>”,线程掩码(coremask)指定了需要参与运行的线程(核)集合。rte_eal_init本身所完成的工作是复杂的,它读取入口参数,解析并保存作为DPDK运行的系统信息,依赖这些信息,构建一个针对包处理设计的运行环境。主要动作分解为:配置初始化-->内存初始化-->内存池初始化-->队列初始化-->告警初始化-->中断初始化-->PCI初始化-->定时器初始化-->检测内存本地化(NUMA)-->插件初始化-->主线程初始化-->轮询设备初始化-->建立主从线程通道-->将从线程设置在等待模式-->PCI设备的探测与初始化...对于DPDK库的使用者,这些操作已经被EAL封装起来,接口清晰。如果需要对DPDK进行深度定制,二次开发,需要仔细研究内部操作,详见官方网站https://doc.dpdk.org/guides/prog_guide/。

DPDK面向多核设计,程序会试图独占运行在逻辑核(lcore)上。Main函数里重要部分是启动多核运行环境,RTE_LCORE_FOREACH_SLAVE(lcore_id)如名所示,遍历所有EAL指定可以使用的lcore,然后通过rte_eal_remote_launch在每个lcore上,启动被指定的线程。

int rte_eal_remote_launch(int (*f)(void *),

void *arg, unsignedslave_id);
第一个参数是从线程,是被征召的线程,第二个参数是传给从线程的参数,第三个参数是指定的逻辑核,从线程会执行在这个core上。具体来说,int rte_eal_remote_launch(lcore_hello,NULL, lcore_id);参数lcore_id指定了从线程ID,运行入口函数lcore_hello.
运行函数lcore_hello,它读取自己的逻辑核编号(lcore_id), 打印出“hellofrom core #”

static    int
lcore_hello(__attribute__((unused))    void *arg)
{

   unsigned lcore_id;

   lcore_id = rte_lcore_id();

   printf("hello from core    %u\n", lcore_id);

   ;

}

以上仅是个简单示例,在真实的DPDK处理场景中,该处理函数会是一个循环运行的处理过程。

DPDK也有自身的劣势,对于低负荷的场景不建议使用DPDK:

  • 内核栈转移至用户层增加了开发成本.
  • 低负荷服务器不实用,会造成内核空转.

基于DPDK的高效包处理系统的更多相关文章

  1. 基于DPDK的高效数据包捕获技术分析与应用

    被NFV的论文折磨了两天,今天上午看了两篇DPDK的综述. 传统的包捕获机制 1. BPF 两个组成部分:转发部分和过滤部分. 转发部分负责从链路层提取数据包并转发给过滤部分. 过滤部分根据过滤规则, ...

  2. TRex,一个基于DPDK的数据包发生器,测试仪

    1. introduction TRex是cisco基于Intel dpdk开发的软件程序.推荐在CentOS/RHEL 7.6, 64bits中运行,否则connectx-4网卡不可使用. 笔者在U ...

  3. 26种基于PHP的开源博客系统

    26种基于PHP的开源博客系统 来源:本站原创 PHP学习笔记 以下列举的PHP开源Blog系统中,除了我们熟知的WordPress之外,大多都没有使用过,其中一些已经被淘汰,或者有人还在使用.除了做 ...

  4. 代码片段:基于 JDK 8 time包的时间工具类 TimeUtil

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “知识的工作者必须成为自己时间的首席执行官.” 前言 这次泥瓦匠带来的是一个好玩的基于 JDK ...

  5. 基于Flume的美团日志收集系统(二)改进和优化

    在<基于Flume的美团日志收集系统(一)架构和设计>中,我们详述了基于Flume的美团日志收集系统的架构设计,以及为什么做这样的设计.在本节中,我们将会讲述在实际部署和使用过程中遇到的问 ...

  6. Factom(公证通)--基于区块链的存证系统

    Factom这个Solution在2014年的时候就已经推出了,现在已经2018年了,我才来写这一篇分析文章可能有些迟了,但是它是十分具有参考价值的.因为现阶段来开区块链虽然炒得火热--养猫.养狗.草 ...

  7. 数据分析:基于Python的自定义文件格式转换系统

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  8. 深度学习与计算机视觉(11)_基于deep learning的快速图像检索系统

    深度学习与计算机视觉(11)_基于deep learning的快速图像检索系统 作者:寒小阳 时间:2016年3月. 出处:http://blog.csdn.net/han_xiaoyang/arti ...

  9. 面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统

    面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统 原型模式和基于原型继承的JavaScript对象系统 在 Brendan Eich 为 JavaScrip ...

随机推荐

  1. pandas第一课

    pandas第一课 首先是数据的准备 movies.dat user.dat ratings.dat 注意,这些数据都是通过::来隔开每一列的,每一列有各自的含义 现在通过pandas来读入数据 首先 ...

  2. 关于FIFO异步复位的问题

    关于FIFO异步复位的问题 FIFO异步复位的宽度,需要保证至少3个较慢时钟的时钟周期长度. 怎样对一个脉冲加宽呢? `timescale 1ns / 1ps //////////////////// ...

  3. mongodb 导入文件

    linux命令:mongorestore -d db_name 文件夹目录 windows命令:mongorestore.exe -d db_name 文件夹目录

  4. 【环境部署】centos7安装mysql-5.7.19 group-replication

    --mysql高可用官方文档: https://dev.mysql.com/doc/refman/5.7/en/group-replication.html mysql下载地址: https://ww ...

  5. 【C++】反斜杠“\”的作用

    转自 https://blog.csdn.net/ismallboy/article/details/8082514 转义字符:如:\n表示回车+换行等. 续行符:这个需要注意一下,在一般的语句中,这 ...

  6. 如何重置Gitlab root用户密码

    一.切换到root用户 sudo su 二.进入gitlab控制台 gitlab-rails console production 三.查找用户对象 user = User.).first 四.重置密 ...

  7. javascript多语言设定方式

    1.控件文字语言设定 1.1 设定两个结构变量,定义好每一个控件需要用到的值,称它字典对象 var languagecn = { 1089: "夹柄不到位", 1090: &quo ...

  8. 【算法习题】正整数数组中和为sum的任意个数的组合数

    1.递归实现(参考:https://blog.csdn.net/hit_lk/article/details/53967627) public class Test { @org.junit.Test ...

  9. Redis深入学习笔记(六)Redis内存分配

    Redis的高效可以说是轻量级的epoll模型和基于内存的读写共同组成的,关于epoll对于以前的select或者poll的性能优势这里不做介绍,本篇主要介绍领一个重点,Redis的内存分配原理. 获 ...

  10. Tesseract训练

    最近在用Tesseract做一个图片识别的小应用,目标图像只有数字和英文字母,在实际使用过程中发现个别数识别错误,因此不得不研究学习Tesseract的训练. http://www.cnblogs.c ...