没有合适的资源?快使用搜索试试~ 我知道了~
1、 使用大页缓存支持来提高内存访问效率 2、 利用 UIO 支持, 提供应用空间下驱动程序的支持, 3、 利用 LINUX亲和性支持, 把控制面线程及各个数据
资源详情
资源评论
资源推荐
DPDK关键技术
赵剑川 2014.11.26
概要
DPDK 是 INTEL提供的提升数据面报文快速处理速率的应用程序开发包,它主要利用以下几
个方面的支持特点来优化报文处理过程,从而加快报文处理速率:
1、 使用大页缓存支持来提高内存访问效率。
2、 利用 UIO 支持, 提供应用空间下驱动程序的支持, 也就是说网卡驱动是运行在用户空间
的,减下了报文在用户空间和应用空间的多次拷贝。
3、 利用 LINUX亲和性支持, 把控制面线程及各个数据面线程绑定到不同的 CPU核,节省了
线程在各个 CPU 核来回调度。
4、 提供内存池和无锁环形缓存管理,加快内存访问效率。
整个 DPDK系统由许多不同组件组成,各组件为应用程序和其它组件提供调用接口,其结构
图如下图所示:
Dpdk 各系统组件结构图
Pci驱动
Igb_uio Huge page KNI
Pci Uio device memseg
KNI lib Sched lib
Mem zone
Mem pool lib
Malloc lib
Pmd driver lib
Master core
Slave core
int log
pipe
Cpu feature
Pmd e1000 lib
Pmd pcap lib
Net prototol lib
arlarm
Per-care and Share variable
Dpdk application
blacklist
None pci
Timer
lib
Tail queue debug
Ring lib
mbuf lib
Pmd ixgbe lib Pmd virtio lib
Pmd ring lib
Hash/Lpm lib
None Dpdk application
timer
A B :表示模块 A 用到模块 B
meter/power
1、 环境抽象层: 为 DPDK其它组件和应用程序提供一个屏蔽具体平台特性的统一接口, EAL
提供的功能主要有: DPDK 加载和启动;支持多核或多线程执行类型; CPU 核亲和性处
理;原子操作和锁操作接口;时钟参考; PCI 总线访问接口;跟踪和调试接口; CPU 特
性采集接口;中断和告警接口等。
2、 堆内存管理组件( Malloc lib):堆内存管理组件为应用程序提供从大页内存分配堆内存
的接口。当需要分配大量内存小块时(如用于存储列表中每个表项指针的内存) ,使用
这些接口可以减少 TLB缺页。
3、 环缓冲区管理组件: 环缓冲区管理组件为应用程序和其它组件提供一个无锁的多生产者
多消费者 FIFO队列 API。
4、 内存池管理组件:为应用程序和其它组件提供分配内存池的接口,内存池是一个由固定
大小的多个内存块组成的内存容器,可用于存储相同对像实体,如报文缓存块等。内存
池由内存池的名称(一个字符串)来唯一标识,它由一个环缓中区和一组核本地缓存队
列组成,每个核从自已的缓存队列分配内存块,当本地缓存队列减少到一定程度时,从
内存环缓冲区中申请内存块来补充本地队列。
5、 网络报文缓存块管理组件:提供应用程序创建和释放用于存储报文信息的缓存块的接
口,这些 MBUF 存储在一内存池中。提供两种类型的 MBUF,一种用于存储一般信息,
一种用于存储报文数据。
6、 定时器组件:提供一些异步周期执行的接口(也可以只执行一次) ,可以指定某个函数
在规定的时间异步的执行,就像 LIBC中的 timer 定时器,但是这里的定时器需要应用程
序在主循环中周期调用 rte_timer_manage 来使定时器得到执行,使用起来没有那么方
便。定时器组件的时间参考来自 EAL层提供的时间接口。
除了以上六个核心组件外, DPDK还提供以下功能:
1、 以太网轮询模式驱动( PMD)架构:把以太网驱动从内核移到应用层,采用同步轮询机
制而不是内核态的异步中断机制来提高报文的接收和发送效率。
2、 报文转发算法支持: Hash 库和 LPM 库为报文转发算法提供支持。
3、 网络协议定义和相关宏定义: 基于
FreeBSD IP 协议栈的相关定义如: TCP 、UDP 、SCTP 等协
议头定义。
4、
报文 QOS 调度库:支持随机早检测、流量整形、严格优先级和加权随机循环优先级调度等相关 QOS
功能。
5、
内核网络接口库( KNI ):提供一种 DPDK 应用程序与内核协议栈的通信的方法,类似普通 LINUX
的 TUN/TAP 接口,但比 TUN/TAP 接口效率高。每个物理网口可以虚拟出多个 KNI 接口。
以下分章节对各个组件单元进行详细分析。
日志系统篇:
1、 全局日志变量 rte_logs
struct rte_logs rte_logs = {
.type = ~0,
.level = RTE_LOG_DEBUG,
.file = NULL,
};
该变量用于存储日志文件的的 FILE指针、日志打印级别、要记录的日志类型。
2、 日志类型:
/* 系统内部日志类型 */
#define RTE_LOGTYPE_EAL 0x00000001 /**< Log related to eal. */
#define RTE_LOGTYPE_MALLOC 0x00000002 /**< Log related to malloc. */
#define RTE_LOGTYPE_RING 0x00000004 /**< Log related to ring. */
#define RTE_LOGTYPE_MEMPOOL 0x00000008 /**< Log related to mempool. */
#define RTE_LOGTYPE_TIMER 0x00000010 /**< Log related to timers. */
#define RTE_LOGTYPE_PMD 0x00000020 /**< Log related to poll mode driver. */
#define RTE_LOGTYPE_HASH 0x00000040 /**< Log related to hash table. */
#define RTE_LOGTYPE_LPM 0x00000080 /**< Log related to LPM. */
#define RTE_LOGTYPE_KNI 0x00000100 /**< Log related to KNI. */
#define RTE_LOGTYPE_ACL 0x00000200 /**< Log related to ACL. */
#define RTE_LOGTYPE_POWER 0x00000400 /**< Log related to power. */
#define RTE_LOGTYPE_METER 0x00000800 /**< Log related to QoS meter. */
#define RTE_LOGTYPE_SCHED 0x00001000 /**< Log related to QoS port scheduler.
*/
/* 用户可自定义的日志类型 */
#define RTE_LOGTYPE_USER1 0x01000000 /**< User-defined log type 1. */
#define RTE_LOGTYPE_USER2 0x02000000 /**< User-defined log type 2. */
#define RTE_LOGTYPE_USER3 0x04000000 /**< User-defined log type 3. */
#define RTE_LOGTYPE_USER4 0x08000000 /**< User-defined log type 4. */
#define RTE_LOGTYPE_USER5 0x10000000 /**< User-defined log type 5. */
#define RTE_LOGTYPE_USER6 0x20000000 /**< User-defined log type 6. */
#define RTE_LOGTYPE_USER7 0x40000000 /**< User-defined log type 7. */
#define RTE_LOGTYPE_USER8 0x80000000 /**< User-defined log type 8. */
3、日志级别
/* :Can't use 0, as it gives compiler warnings */
#define RTE_LOG_EMERG 1U /**< System is unusable. */
#define RTE_LOG_ALERT 2U /**< Action must be taken immediately. */
#define RTE_LOG_CRIT 3U /**< Critical conditions. */
#define RTE_LOG_ERR 4U /**< Error conditions. */
#define RTE_LOG_WARNING 5U /**< Warning conditions. */
#define RTE_LOG_NOTICE 6U /**< Normal but significant condition. */
#define RTE_LOG_INFO 7U /**< Informational. */
#define RTE_LOG_DEBUG 8U /**< Debug-level messages. */
4、改写系统日志文件
/**
* @param f
* 文件流指针, 可以是 NULL,如果是 NULL,系统使用默认日志文件流, 如串口或 syslog.
rte_eal_log_init(const char *id, int facility) 初始化时,已经把默认日专文件流设置为 syslog
* @return
* - 0 on success.
* - Negative on error.
*/
int rte_openlog_stream(FILE *f);
5、设计日志打印级别
void rte_set_log_level(uint32_t level);
6、使能某个日志类型,使能之后,可以记录该类型的日志信息。
void rte_set_log_type(uint32_t type, int enable);
7、取得当前核中刚刚处理的日志消息类型和级别
每个核处理日志消息时,会记录本该消息的类型和级别到一个变量中。
int rte_log_cur_msg_loglevel(void);
int rte_log_cur_msg_logtype(void);
8、使能 LOG存储记录
void rte_log_set_history(int enable);
9、存储或显示历史记录,这个接口,日志是在标准输出中显示的
int rte_log_add_in_history(const char *buf, size_t size);
void rte_log_dump_history(void);
10、打印一条日志,这里会根据类型和级别,判断是否打印,如果打印,则打印到初始化时
所设定的文件中。
#define RTE_LOG(l, t, ...) \
(void)(((RTE_LOG_ ## l <= RTE_LOG_LEVEL) && \
(RTE_LOG_ ## l <= rte_logs.level) && \
(RTE_LOGTYPE_ ## t & rte_logs.type)) ? \
rte_log(RTE_LOG_ ## l, \
RTE_LOGTYPE_ ## t, # t ": " __VA_ARGS__) : \
0)
11、日志打印机制:
#define RTE_LOG(l, t, ...) \
(void)(((RTE_LOG_ ## l <= RTE_LOG_LEVEL) && \
(RTE_LOG_ ## l <= rte_logs.level) && \
(RTE_LOGTYPE_ ## t & rte_logs.type)) ? \
rte_log(RTE_LOG_ ## l, \
RTE_LOGTYPE_ ## t, # t ": " __VA_ARGS__) : \
0)
上面调用先判断类型和级别,看是否需要记录,如果不需要, 就什么都不做,如果需要就调
用:
rte_log(uint32_t level, uint32_t logtype, const char *format, ...)-----
rte_vlog(__attribute__((unused)) uint32_t level,__attribute__((unused)) uint32_t logtype,const
char *format, va_list ap)
{
int ret;
FILE *f = rte_logs.file;
unsigned lcore_id;
/* 记录正在打印的日志的类型和级别 */
lcore_id = rte_lcore_id();
log_cur_msg[lcore_id].loglevel = level;
log_cur_msg[lcore_id].logtype = logtype;
ret = vfprintf(f, format, ap);/* 把日志输出到初始化时定义的文件流中 */
fflush(f);
return ret;
}
初始化时定义的文件流设置如下(发) :
/*
* set the log to default function, called during eal init process,
* once memzones are available.
*/
int
rte_eal_log_init(const char *id, int facility)
{
FILE *log_stream;
log_stream = fopencookie(NULL, "w+", console_log_func);
if (log_stream == NULL)
return -1;
openlog(id, LOG_NDELAY | LOG_PID, facility);
/* 这里把默认的 LOG文件流定义为 fopencookie 所设置的文件流 */
if (rte_eal_common_log_init(log_stream) < 0)
return -1;
return 0;
}
Fopencookie 文件流的操作接口定义如下( lib\librte_eal\linuxapp\ealeal_log.c ):
static cookie_io_functions_t console_log_func = {
.read = console_log_read,
.write = console_log_write,/* 这就是 vfprintf 调用时,真正的写操作接口 */
.seek = console_log_seek,
.close = console_log_close
};
下面就是写日志时的真正操作了:
static ssize_t
console_log_write(__attribute__((unused)) void *c, const char *buf, size_t size)
{
char copybuf[BUFSIZ + 1];
ssize_t ret;
uint32_t loglevel;
/* 先把日志志信息记录在历史记录中 */
rte_log_add_in_history(buf, size);
/* 再把日志输出到标准输出 */
ret = fwrite(buf, 1, size, stdout);
fflush(stdout);
/* truncate message if too big (should not happen) */
if (size > BUFSIZ)
size = BUFSIZ;
/* Syslog error levels are from 0 to 7, so subtract 1 to convert */
loglevel = rte_log_cur_msg_loglevel() - 1;
memcpy(copybuf, buf, size);
copybuf[size] = '\0';
/* 最后,还把信息输出到系统日志中 */
syslog(loglevel, "%s", copybuf);
return ret;
}
HUGPAGE的使用:
为什么内存要分页?实践过程中,有这样的问题:程序需要使用 4G 内存空间,而物理内存
又小于 4G,导致程序不得不降低内存占用。为解决些问题,引入 MMU ,MMU 核心思想是
利用虚拟地址代替物理地址,即 CPU使用虚拟地址, MMU 负责把虚拟地址转成物理地址
内存分页是基于 MMU 的一种内存管理机制,这种机制,从结构上保证了访问内存的高效,
使 OS能支持非连续内存的分配。
为了访问更快,硬件上引入 TLB(页表寄存器缓冲) ,但 TLB有限,为了减少 MISS,引入大
页
大页的设置,
echo 128 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
mount -t hugetlbfs –o pagesize=2M nodev /mnt/hugepages-fs
剩余26页未读,继续阅读
小崔个人精进录
- 粉丝: 30
- 资源: 316
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- ASCII American Standard Code for Information Interchange
- 一个chm格式的 SQL 函数手册-SQL语言手册文档
- 计算当前月份的天数和剩余天数
- 基于ARM的指令调度和延迟分支
- 基于Vue和TypeScript的极简聊天应用设计源码 - HasChat
- 基于Vue2全家桶和Zcool数据的图片收集网站设计源码 - cool-picture
- 基于C和C++的二维绘制工具设计源码 - DrawPro
- Object.defineProperty 的 IE 补丁object-defineproperty-ie-master.zip
- 整卷预览.mhtml
- MySQL是一种广泛使用的开源关系型数据库管理系统,它提供了丰富的SQL语句用于数据库的创建、查询、更新和管理 以下是一些常见的
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0