DPDK18.05中的日志系统

1、简介

在当前较新版本(以DPDK 18.05版本为例)的日志系统中,引入了动态类型日志系统 ,设计得非常巧妙,除了原来支持的全局日志输出,也支持针对单独某个模块的日志输出。

2、主要数据结构说明

3、日志函数的定义

这里先从平时使用的日志函数定义讨论,反推到日志模块的初始化。

3.1 RTE_LOG宏

日常主要使用封闭好的RTE_LOG宏:

这个宏包含两个必选参考,以及后面的可变参数。后面的可变参数用法与printf()函数一样,不再多说。
前两个参数中,第一个是日志等级,第二个是日志类型,或者说指定的当前打印的日志模块。

日志等级定义如下:

日志类型定义如下:

RTE_LOG的使用举例:

3.2 rte_log()函数

该函数定义如下:

函数很简单,直接调用了rte_vlog()函数。

3.3 rte_vlog()函数

rte_vlog()函数定义如下:

4、日志模块初始化

了解到了日志函数中使用的一些变量,那么就可以看一下日志模块的初始化了。

日志模块的初始化分为两部分,一部分是在整个DPDK模块一被加载就被执行的初始化,这部分初始化使日志模块在DPDK的其他模块初始化过程中就可以使用。
另一部分是在DPDK的整体初始化(rte_eal_init())时执行,用来设置日志模块的输出。

4.1 日志模块的前期初始化

(1)struct rte_logs数据结构

type表示启用的logs模块的位掩码。不过在18.05版本中,这个变量还没有用到。
level 表示全局日志级别设置,只输出不大于该级别的日志
file表示日志输出的地方,可以是终端,也可以是文件
dynamic_types_len 表示日志类型的数量,每添加一个类型,该变量增加1
dynamic_types 指向表示日志类型的结构体,保存的日志类型的名字的设置的等级,定义如下:

(2)定义全局日志变量

(3)第一阶段初始化

logtype_strings[]数组的定义如下:

(4)调用__rte_log_register()函数注册日志类型

该函数比较简单,是将表示日志类型的id与类型名保存到rte_logs.dynamic_types中,将返回该类型在rte_logs.dynamic_types中的索引:

因此这些日志类型,如RTE_LOGTYPE_EAL等,同时也成为了该类型在 rte_logs.dynamic_types中的索引。

(5)最后设置日志类型的数量

至此,rte_logs模块第一阶段的初始化就完成了,DPDK中已经可以使用,且默认会将日志信息打印到stderr。

4.2 日志模块的第二阶段初始化

日志模块的后期初始化通过在rte_eal_init()函数中调用rte_eal_log_init()函数完成,该函数定义如下:

(1)创建输入输出流

函数首先使用fopencook(函数创建一个标准输入输出流,定义如下:

其中:
__magic_cookie是一种自定义的数据结构,用于和后面的__io_funcs配合使用,可以为NULL。
__modes表示打开方式,和fopen相同,包括:r,w,a,r+,w+,a+。
__io_funcs是由四个函数指针(read, write, seek, close)组成的函数集,需要用户实现这四个函数指针。

网上有对fopencookie更多详细的说明,本文不再复述。

console_log_func的定义如下:

由于日志模块只需要输出字符串,因此变量只实现了write写函数console_log_write函数,定义如下:

(2)syslog日志初始化

(3)设置DPDK日志模块的输出对象

将刚刚创建并初始化的log_stream,赋值给default_log_stream。根据前文rte_vlog()函数的定义,在输出日志时会使用。

也就是说,默认情况下,DPDK的标准日志模块会向标准输出 stdout输出日志信息,同时会向syslog中输出日志信息。

5、注册新的日志类型

除了自身默认的这些日志类型,DPDK系统也支持注册新的日志类型,或者复用现有的日志类型。

5.1 添加新的日志类型

通过rte_log_register()函数,可以向系统中添加新的日志类型。该函数定义如下:

5.2 设置/获取日志的打印级别

日志系统包含了全局日志打印级别的获取与设置函数,以及指定模块的日志打印级别的获取与设置函数。
这几个函数比较简单,定义如下:

5.3 举例

在testpmd这个程序为例,在程序的main()函数一开始,就注册了一个新的日志类型:

返回值testpmd_logtype 同时也表示了该类型在rte_logs.dynamic_types中的索引。
之后设置该类型的打印级别为DEBUG,打印所有该类型的日志:

同时,在testpmd示例的头文件中,对日志函数进行了对应的封装:

之后,就可以在testpmd示例程序中使用TESTPMD_LOG宏进行日志打印了。

6、复用现有日志类型

除了添加新的日志类型,也可以复用现有的日志类型,用法非常简单,以exception_path这个示例程序为例。
在ip_fragmentation/main.c文件中,有如下定义:

而RTE_LOGTYPE_USER1到RTE_LOGTYPE_USER8这8个类型,就是为用户自定义准备的,所以可以直接使用。

而在使用时,调用RTE_LOG宏时直接使用IP_FRAG即可:

————————————————————

原创文章,转载请注明: 转载自孙希栋的博客

本文链接地址: 《DPDK18.05中的日志系统》

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Scroll Up