基于DPDK的高效包处理系统
一、概念
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的高效包处理系统的更多相关文章
- 基于DPDK的高效数据包捕获技术分析与应用
被NFV的论文折磨了两天,今天上午看了两篇DPDK的综述. 传统的包捕获机制 1. BPF 两个组成部分:转发部分和过滤部分. 转发部分负责从链路层提取数据包并转发给过滤部分. 过滤部分根据过滤规则, ...
- TRex,一个基于DPDK的数据包发生器,测试仪
1. introduction TRex是cisco基于Intel dpdk开发的软件程序.推荐在CentOS/RHEL 7.6, 64bits中运行,否则connectx-4网卡不可使用. 笔者在U ...
- 26种基于PHP的开源博客系统
26种基于PHP的开源博客系统 来源:本站原创 PHP学习笔记 以下列举的PHP开源Blog系统中,除了我们熟知的WordPress之外,大多都没有使用过,其中一些已经被淘汰,或者有人还在使用.除了做 ...
- 代码片段:基于 JDK 8 time包的时间工具类 TimeUtil
摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “知识的工作者必须成为自己时间的首席执行官.” 前言 这次泥瓦匠带来的是一个好玩的基于 JDK ...
- 基于Flume的美团日志收集系统(二)改进和优化
在<基于Flume的美团日志收集系统(一)架构和设计>中,我们详述了基于Flume的美团日志收集系统的架构设计,以及为什么做这样的设计.在本节中,我们将会讲述在实际部署和使用过程中遇到的问 ...
- Factom(公证通)--基于区块链的存证系统
Factom这个Solution在2014年的时候就已经推出了,现在已经2018年了,我才来写这一篇分析文章可能有些迟了,但是它是十分具有参考价值的.因为现阶段来开区块链虽然炒得火热--养猫.养狗.草 ...
- 数据分析:基于Python的自定义文件格式转换系统
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- 深度学习与计算机视觉(11)_基于deep learning的快速图像检索系统
深度学习与计算机视觉(11)_基于deep learning的快速图像检索系统 作者:寒小阳 时间:2016年3月. 出处:http://blog.csdn.net/han_xiaoyang/arti ...
- 面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统
面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统 原型模式和基于原型继承的JavaScript对象系统 在 Brendan Eich 为 JavaScrip ...
随机推荐
- 记一个在移动端调试 web 页面的方法
1. 工具:Weinre 2. 安装:npm -g install weinre | npm install weinre -g --registry=https://registry.npm.tao ...
- JSP和Struts2、Hibernate、Spring3基础内容和原理
一.JSP工作原理 1.首先是利用客户端浏览器,然后由客户端浏览器请求JSP页面,向JSP服务器发出请求. 2.JSP服务器内部原理 JSP服务器首先在收到客户端传送过来的请求后,将JSP页面编译成S ...
- VS2015Git 源代码工具使用
1. 首先到源代码托管平台申请个账户:https://git.oschina.net/ 2.创建流程图: 2.1 开始创建项目: 2.2 3. 4. 作者:江宁织造 qq空间:苦心孤诣博客:http: ...
- 批处理for中字符串截取必须先把循环变量代替出来才行!!!
@echo off & setlocal enabledelayedexpansion set ifo=abc,def,ghi,jkl,mnopqrstuvwxyz0123456789 ech ...
- [UE4]Skeletal Mesh的碰撞体
一.骨骼模型和骨骼碰撞体肯定不是完全吻合的,因为骨骼模型太复杂了. 二.骨骼碰撞体编辑在Physics Asset资源中 三.Constraints:只显示碰撞体 四.对于射击游戏来说,这样的碰撞体完 ...
- "Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs
最近在部署MySQL主从复制架构的时候,碰到了"Last_IO_Error: Fatal error: The slave I/O thread stops because master a ...
- centos7搭建GitLab
1.安装依赖 yum -y install policycoreutils openssh-server openssh-clients postfix policycoreutils-python ...
- 数据帧、MTU、MSS、IP分片
1.以太网帧 在以太网链路上的数据包称作以太帧,在802.3标准里,规定了一个以太帧的数据部分(Payload)的最大长度是1500个字节(MTU),再加上14字节链路头和4字节的FCS,所以以太网帧 ...
- Idea项目上传git(与git结合使用)
Prerequisite(前提): 1.拥有github账号 2.本地电脑安装git 3.拥有一个guthub的新仓库 一.本地git与github安全连接(若已经将本地git与github建立连接, ...
- numpy学习笔记(四)
(1)NumPy - 矩阵库 NumPy 包包含一个 Matrix库numpy.matlib.此模块的函数返回矩阵而不是返回ndarray对象. matlib.empty()返回一个新矩阵,而不初始化 ...