作者简介
陆文卓,DPDK软件开发工程师,专注于PMD相关开发。
如前一篇testpmd基础介绍所述,testpmd所使用的UI是命令行,显得比较古朴。作为一个轻量级的测试工具,testpmd的人机交互功能比较弱而有限,不需要复杂的图形界面就可以完成。因此使用CLI的好处也是比较明显的,可以控制项目的大小,防止在非核心的功能上花费过多的精力。
一般情况下,基于DPDK进行应用程序开发的使用者不需要对CLI有太多的了解,只需调用合适的API即可实现所需的功能。但是testpmd作为一个简单的应用程序,对实验性质的开发会有很大的帮助。在正式开发之前,通过简单修改CLI代码,可以方便的和testpmd程序交互,进行一些新功能的验证调试。
CLI使用说明
CLI的使用包含在testpmd的使用指南中。Testpmd的使用指南可以在dpdk官方网站上下载:http://core.dpdk.org/doc/。
CLI的说明在这个文件中,doc\guides\testpmd_app_ug\testpmd_funcs.rst,开发者在testpmd中增加、修改、删除CLI命令时,应该更新此文件。文档生成工具可以根据此文件自动生成pdf文档。
CLI举例
CLI都是比较类似的,简单的说,实现的就是解析字符串并将其和某个API关联起来,然后执行API的过程。API可能会实现很复杂的功能,但是这些功能都是由其它的lib提供的,(由于testpmd是针对PMD的测试程序,这个lib一般是ethdev这个lib。当然,使用者可以随意的扩展CLI,调用任意的API,以达到不同的测试目的。)所以,CLI的代码看起来都会有一些相似。下面的一个例子基本上就可以了解CLI的代码实现。
▌端口信息显示
以一个简单的CLI为例,我们可以了解CLI相关的代码实现。下面是一个直观的“showport info”的例子。
testpmd> show port info 0
********************* Infos for port 0 *********************
MAC address: 3C:FD:FE:9D:25:8C
Device name: 0000:07:00.0
Driver name: net_i40e
Connect to socket: 0
memory allocation on the socket: 0
Link status: up
Link speed: 10000 Mbps
Link duplex: full-duplex
MTU: 1500
Promiscuous mode: enabled
Allmulticast mode: disabled
Maximum number of MAC addresses: 64
Maximum number of MAC addresses of hash filtering: 0
VLAN offload:
strip off
filter off
qinq(extend) off
Hash key size in bytes: 52
Redirection table size: 512
Supported flow types:
ipv4-frag
ipv4-tcp
ipv4-udp
ipv4-sctp
ipv4-other
ipv6-frag
ipv6-tcp
ipv6-udp
ipv6-sctp
ipv6-other
l2_payload
Minimum size of RX buffer: 1024
Maximum configurable length of RX packet: 9728
Maximum number of VMDq pools: 64
Current number of RX queues: 1
Max possible RX queues: 320
Max possible number of RXDs per queue: 4096
Min possible number of RXDs per queue: 64
RXDs number alignment: 32
Current number of TX queues: 1
Max possible TX queues: 320
Max possible number of TXDs per queue: 4096
Min possible number of TXDs per queue: 64
TXDs number alignment: 32
▌数据结构介绍
在上一篇testpmd基础介绍中提到,当启动testpmd时,加入“-i”参数,testpmd将进入交互模式,此时用户可以使用CLI功能。
当用户在提示符后输入字符后,testpmd是如何处理字符串并执行相应的API的呢?
每个CLI都对应一个数据结构变量,这存在cmdline.c文件中。“show port info”的数据结构变量是:
cmdline_parse_inst_t cmd_showport = {
.f =cmd_showport_parsed,
.data =NULL,
.help_str= "show|clear port "
"info|stats|xstats|fdir|stat_qmap|dcb_tc|cap"
"<port_id>",
.tokens= {
(void*)&cmd_showport_show,
(void*)&cmd_showport_port,
(void*)&cmd_showport_what,
(void*)&cmd_showport_portnum,
NULL,
},
};
我们可以看到“cmd_showport”包含四个部分:
f。应该是指function,即CLI所执行的函数。
data。除了CLI之外,可以传递给执行函数的参数。因为它不是通过CLI传递的,可以看做不是属于UI的一部分,一般也不使用,置为空。
help_str。帮助信息。从帮助信息看,此CLI承担的功能不仅仅是显示端口的信息,它还可以显示统计信息等,并且也能够清空统计信息等。当然,这只是帮助信息声称的功能,是不是真正是这些功能呢?下面的详细分析会进一步说明。
tokens。描述了构成CLI的各个字符串。我们可以看到,这个CLI由4个字符串构成。
cmd_showport_show有两种可能,“show”或者“clear”。
cmd_showport_port只能是“port”。
cmd_showport_what可以是以下任意一个,“info”、“stats”、“xstats”、“fdir”、“stat_qmap”、“dcb_tc”、“cap”
cmd_showport_portnum则必须是无符号整数。
▌CLI解析介绍
简单的说,当一串字符可以和上述的四个小字符串的组合即tokens匹配时,就执行f所指定的函数。但是,当用户输入一串字符后,testpmd是怎么知道它能够匹配某一个CLI的呢?
上述的变量cmd_showport被放在了数组main_ctx中。当用户输入一串字符后,程序将会遍历main_ctx数组中所有的变量,判断此字符串是否和数组中的某个变量匹配。这部分的工作实际上是由librte_cmdline完成的。大致的流程如下:
1.将获取的一串字符分拆成若干子字符串。在分拆时,一串字符中的一个或若干个连续的空格被视为子字符串的间隔。显然字符串的结束符‘\0’被视为结束。
2.将这些子字符串和main_ctx数组中的变量逐个匹配。实际上是将子字符串和变量的tokens域进行匹配。例如如下字符串都可能和cmd_showport匹配。
a. show port info 0
b. show port stats 1
c. clear port xstats 4
d. clear port fdir 5
e. …
3.当发现某个变量可以和输入的字符串匹配时,并不会停止,而是继续匹配剩下的变量。当发现还有另外一个变量可以和输入的字符串匹配时,将会报错——含义模糊的命令。
这就要求testpmd的代码实现者在设计CLI时要保证不要和已有的CLI雷同。
4.匹配工作完成后,如果只有一个变量和输入的字符串匹配,则通过变量的f域执行处理函数。对于“showport info”是函数cmd_showport_parsed。
如果没有任何变量匹配,则报错。
▌函数执行
如前所述,当用户输入适当的token组合后,testpmd就会进入到显示端口信息的处理。端口信息显示函数port_infos_display是testpmd实现的,通过调用rte_eth的API获取需要的信息,然后打印。
文章小结
CLI在testpmd中是一个庞大的部分,但原理并不复杂,实现一些功能也很简单快捷。Dpdk的使用者可以对其进行初步的了解,模仿现有的代码实现一些简单的调试命令,有助于快速调试功能,提升开发效率。